Home | History | Annotate | Download | only in PBQP
      1 //===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // PBQP Graph class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 
     15 #ifndef LLVM_CODEGEN_PBQP_GRAPH_H
     16 #define LLVM_CODEGEN_PBQP_GRAPH_H
     17 
     18 #include "Math.h"
     19 #include "llvm/ADT/ilist.h"
     20 #include "llvm/ADT/ilist_node.h"
     21 #include <list>
     22 #include <map>
     23 
     24 namespace PBQP {
     25 
     26   /// PBQP Graph class.
     27   /// Instances of this class describe PBQP problems.
     28   class Graph {
     29   private:
     30 
     31     // ----- TYPEDEFS -----
     32     class NodeEntry;
     33     class EdgeEntry;
     34 
     35     typedef llvm::ilist<NodeEntry> NodeList;
     36     typedef llvm::ilist<EdgeEntry> EdgeList;
     37 
     38   public:
     39 
     40     typedef NodeList::iterator NodeItr;
     41     typedef NodeList::const_iterator ConstNodeItr;
     42 
     43     typedef EdgeList::iterator EdgeItr;
     44     typedef EdgeList::const_iterator ConstEdgeItr;
     45 
     46   private:
     47 
     48     typedef std::list<EdgeItr> AdjEdgeList;
     49 
     50   public:
     51 
     52     typedef AdjEdgeList::iterator AdjEdgeItr;
     53 
     54   private:
     55 
     56     class NodeEntry : public llvm::ilist_node<NodeEntry> {
     57       friend struct llvm::ilist_sentinel_traits<NodeEntry>;
     58     private:
     59       Vector costs;
     60       AdjEdgeList adjEdges;
     61       unsigned degree;
     62       void *data;
     63       NodeEntry() : costs(0, 0) {}
     64     public:
     65       NodeEntry(const Vector &costs) : costs(costs), degree(0) {}
     66       Vector& getCosts() { return costs; }
     67       const Vector& getCosts() const { return costs; }
     68       unsigned getDegree() const { return degree; }
     69       AdjEdgeItr edgesBegin() { return adjEdges.begin(); }
     70       AdjEdgeItr edgesEnd() { return adjEdges.end(); }
     71       AdjEdgeItr addEdge(EdgeItr e) {
     72         ++degree;
     73         return adjEdges.insert(adjEdges.end(), e);
     74       }
     75       void removeEdge(AdjEdgeItr ae) {
     76         --degree;
     77         adjEdges.erase(ae);
     78       }
     79       void setData(void *data) { this->data = data; }
     80       void* getData() { return data; }
     81     };
     82 
     83     class EdgeEntry : public llvm::ilist_node<EdgeEntry> {
     84       friend struct llvm::ilist_sentinel_traits<EdgeEntry>;
     85     private:
     86       NodeItr node1, node2;
     87       Matrix costs;
     88       AdjEdgeItr node1AEItr, node2AEItr;
     89       void *data;
     90       EdgeEntry() : costs(0, 0, 0) {}
     91     public:
     92       EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs)
     93         : node1(node1), node2(node2), costs(costs) {}
     94       NodeItr getNode1() const { return node1; }
     95       NodeItr getNode2() const { return node2; }
     96       Matrix& getCosts() { return costs; }
     97       const Matrix& getCosts() const { return costs; }
     98       void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; }
     99       AdjEdgeItr getNode1AEItr() { return node1AEItr; }
    100       void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; }
    101       AdjEdgeItr getNode2AEItr() { return node2AEItr; }
    102       void setData(void *data) { this->data = data; }
    103       void *getData() { return data; }
    104     };
    105 
    106     // ----- MEMBERS -----
    107 
    108     NodeList nodes;
    109     unsigned numNodes;
    110 
    111     EdgeList edges;
    112     unsigned numEdges;
    113 
    114     // ----- INTERNAL METHODS -----
    115 
    116     NodeEntry& getNode(NodeItr nItr) { return *nItr; }
    117     const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; }
    118 
    119     EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; }
    120     const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; }
    121 
    122     NodeItr addConstructedNode(const NodeEntry &n) {
    123       ++numNodes;
    124       return nodes.insert(nodes.end(), n);
    125     }
    126 
    127     EdgeItr addConstructedEdge(const EdgeEntry &e) {
    128       assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() &&
    129              "Attempt to add duplicate edge.");
    130       ++numEdges;
    131       EdgeItr edgeItr = edges.insert(edges.end(), e);
    132       EdgeEntry &ne = getEdge(edgeItr);
    133       NodeEntry &n1 = getNode(ne.getNode1());
    134       NodeEntry &n2 = getNode(ne.getNode2());
    135       // Sanity check on matrix dimensions:
    136       assert((n1.getCosts().getLength() == ne.getCosts().getRows()) &&
    137              (n2.getCosts().getLength() == ne.getCosts().getCols()) &&
    138              "Edge cost dimensions do not match node costs dimensions.");
    139       ne.setNode1AEItr(n1.addEdge(edgeItr));
    140       ne.setNode2AEItr(n2.addEdge(edgeItr));
    141       return edgeItr;
    142     }
    143 
    144     inline void copyFrom(const Graph &other);
    145   public:
    146 
    147     /// \brief Construct an empty PBQP graph.
    148     Graph() : numNodes(0), numEdges(0) {}
    149 
    150     /// \brief Copy construct this graph from "other". Note: Does not copy node
    151     ///        and edge data, only graph structure and costs.
    152     /// @param other Source graph to copy from.
    153     Graph(const Graph &other) : numNodes(0), numEdges(0) {
    154       copyFrom(other);
    155     }
    156 
    157     /// \brief Make this graph a copy of "other". Note: Does not copy node and
    158     ///        edge data, only graph structure and costs.
    159     /// @param other The graph to copy from.
    160     /// @return A reference to this graph.
    161     ///
    162     /// This will clear the current graph, erasing any nodes and edges added,
    163     /// before copying from other.
    164     Graph& operator=(const Graph &other) {
    165       clear();
    166       copyFrom(other);
    167       return *this;
    168     }
    169 
    170     /// \brief Add a node with the given costs.
    171     /// @param costs Cost vector for the new node.
    172     /// @return Node iterator for the added node.
    173     NodeItr addNode(const Vector &costs) {
    174       return addConstructedNode(NodeEntry(costs));
    175     }
    176 
    177     /// \brief Add an edge between the given nodes with the given costs.
    178     /// @param n1Itr First node.
    179     /// @param n2Itr Second node.
    180     /// @return Edge iterator for the added edge.
    181     EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr,
    182                     const Matrix &costs) {
    183       assert(getNodeCosts(n1Itr).getLength() == costs.getRows() &&
    184              getNodeCosts(n2Itr).getLength() == costs.getCols() &&
    185              "Matrix dimensions mismatch.");
    186       return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs));
    187     }
    188 
    189     /// \brief Get the number of nodes in the graph.
    190     /// @return Number of nodes in the graph.
    191     unsigned getNumNodes() const { return numNodes; }
    192 
    193     /// \brief Get the number of edges in the graph.
    194     /// @return Number of edges in the graph.
    195     unsigned getNumEdges() const { return numEdges; }
    196 
    197     /// \brief Get a node's cost vector.
    198     /// @param nItr Node iterator.
    199     /// @return Node cost vector.
    200     Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); }
    201 
    202     /// \brief Get a node's cost vector (const version).
    203     /// @param nItr Node iterator.
    204     /// @return Node cost vector.
    205     const Vector& getNodeCosts(ConstNodeItr nItr) const {
    206       return getNode(nItr).getCosts();
    207     }
    208 
    209     /// \brief Set a node's data pointer.
    210     /// @param nItr Node iterator.
    211     /// @param data Pointer to node data.
    212     ///
    213     /// Typically used by a PBQP solver to attach data to aid in solution.
    214     void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); }
    215 
    216     /// \brief Get the node's data pointer.
    217     /// @param nItr Node iterator.
    218     /// @return Pointer to node data.
    219     void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); }
    220 
    221     /// \brief Get an edge's cost matrix.
    222     /// @param eItr Edge iterator.
    223     /// @return Edge cost matrix.
    224     Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); }
    225 
    226     /// \brief Get an edge's cost matrix (const version).
    227     /// @param eItr Edge iterator.
    228     /// @return Edge cost matrix.
    229     const Matrix& getEdgeCosts(ConstEdgeItr eItr) const {
    230       return getEdge(eItr).getCosts();
    231     }
    232 
    233     /// \brief Set an edge's data pointer.
    234     /// @param eItr Edge iterator.
    235     /// @param data Pointer to edge data.
    236     ///
    237     /// Typically used by a PBQP solver to attach data to aid in solution.
    238     void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); }
    239 
    240     /// \brief Get an edge's data pointer.
    241     /// @param eItr Edge iterator.
    242     /// @return Pointer to edge data.
    243     void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); }
    244 
    245     /// \brief Get a node's degree.
    246     /// @param nItr Node iterator.
    247     /// @return The degree of the node.
    248     unsigned getNodeDegree(NodeItr nItr) const {
    249       return getNode(nItr).getDegree();
    250     }
    251 
    252     /// \brief Begin iterator for node set.
    253     NodeItr nodesBegin() { return nodes.begin(); }
    254 
    255     /// \brief Begin const iterator for node set.
    256     ConstNodeItr nodesBegin() const { return nodes.begin(); }
    257 
    258     /// \brief End iterator for node set.
    259     NodeItr nodesEnd() { return nodes.end(); }
    260 
    261     /// \brief End const iterator for node set.
    262     ConstNodeItr nodesEnd() const { return nodes.end(); }
    263 
    264     /// \brief Begin iterator for edge set.
    265     EdgeItr edgesBegin() { return edges.begin(); }
    266 
    267     /// \brief End iterator for edge set.
    268     EdgeItr edgesEnd() { return edges.end(); }
    269 
    270     /// \brief Get begin iterator for adjacent edge set.
    271     /// @param nItr Node iterator.
    272     /// @return Begin iterator for the set of edges connected to the given node.
    273     AdjEdgeItr adjEdgesBegin(NodeItr nItr) {
    274       return getNode(nItr).edgesBegin();
    275     }
    276 
    277     /// \brief Get end iterator for adjacent edge set.
    278     /// @param nItr Node iterator.
    279     /// @return End iterator for the set of edges connected to the given node.
    280     AdjEdgeItr adjEdgesEnd(NodeItr nItr) {
    281       return getNode(nItr).edgesEnd();
    282     }
    283 
    284     /// \brief Get the first node connected to this edge.
    285     /// @param eItr Edge iterator.
    286     /// @return The first node connected to the given edge.
    287     NodeItr getEdgeNode1(EdgeItr eItr) {
    288       return getEdge(eItr).getNode1();
    289     }
    290 
    291     /// \brief Get the second node connected to this edge.
    292     /// @param eItr Edge iterator.
    293     /// @return The second node connected to the given edge.
    294     NodeItr getEdgeNode2(EdgeItr eItr) {
    295       return getEdge(eItr).getNode2();
    296     }
    297 
    298     /// \brief Get the "other" node connected to this edge.
    299     /// @param eItr Edge iterator.
    300     /// @param nItr Node iterator for the "given" node.
    301     /// @return The iterator for the "other" node connected to this edge.
    302     NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) {
    303       EdgeEntry &e = getEdge(eItr);
    304       if (e.getNode1() == nItr) {
    305         return e.getNode2();
    306       } // else
    307       return e.getNode1();
    308     }
    309 
    310     /// \brief Get the edge connecting two nodes.
    311     /// @param n1Itr First node iterator.
    312     /// @param n2Itr Second node iterator.
    313     /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists,
    314     ///         otherwise returns edgesEnd().
    315     EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) {
    316       for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr);
    317          aeItr != aeEnd; ++aeItr) {
    318         if ((getEdgeNode1(*aeItr) == n2Itr) ||
    319             (getEdgeNode2(*aeItr) == n2Itr)) {
    320           return *aeItr;
    321         }
    322       }
    323       return edges.end();
    324     }
    325 
    326     /// \brief Remove a node from the graph.
    327     /// @param nItr Node iterator.
    328     void removeNode(NodeItr nItr) {
    329       NodeEntry &n = getNode(nItr);
    330       for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) {
    331         EdgeItr eItr = *itr;
    332         ++itr;
    333         removeEdge(eItr);
    334       }
    335       nodes.erase(nItr);
    336       --numNodes;
    337     }
    338 
    339     /// \brief Remove an edge from the graph.
    340     /// @param eItr Edge iterator.
    341     void removeEdge(EdgeItr eItr) {
    342       EdgeEntry &e = getEdge(eItr);
    343       NodeEntry &n1 = getNode(e.getNode1());
    344       NodeEntry &n2 = getNode(e.getNode2());
    345       n1.removeEdge(e.getNode1AEItr());
    346       n2.removeEdge(e.getNode2AEItr());
    347       edges.erase(eItr);
    348       --numEdges;
    349     }
    350 
    351     /// \brief Remove all nodes and edges from the graph.
    352     void clear() {
    353       nodes.clear();
    354       edges.clear();
    355       numNodes = numEdges = 0;
    356     }
    357 
    358     /// \brief Dump a graph to an output stream.
    359     template <typename OStream>
    360     void dump(OStream &os) {
    361       os << getNumNodes() << " " << getNumEdges() << "\n";
    362 
    363       for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
    364            nodeItr != nodeEnd; ++nodeItr) {
    365         const Vector& v = getNodeCosts(nodeItr);
    366         os << "\n" << v.getLength() << "\n";
    367         assert(v.getLength() != 0 && "Empty vector in graph.");
    368         os << v[0];
    369         for (unsigned i = 1; i < v.getLength(); ++i) {
    370           os << " " << v[i];
    371         }
    372         os << "\n";
    373       }
    374 
    375       for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
    376            edgeItr != edgeEnd; ++edgeItr) {
    377         unsigned n1 = std::distance(nodesBegin(), getEdgeNode1(edgeItr));
    378         unsigned n2 = std::distance(nodesBegin(), getEdgeNode2(edgeItr));
    379         assert(n1 != n2 && "PBQP graphs shound not have self-edges.");
    380         const Matrix& m = getEdgeCosts(edgeItr);
    381         os << "\n" << n1 << " " << n2 << "\n"
    382            << m.getRows() << " " << m.getCols() << "\n";
    383         assert(m.getRows() != 0 && "No rows in matrix.");
    384         assert(m.getCols() != 0 && "No cols in matrix.");
    385         for (unsigned i = 0; i < m.getRows(); ++i) {
    386           os << m[i][0];
    387           for (unsigned j = 1; j < m.getCols(); ++j) {
    388             os << " " << m[i][j];
    389           }
    390           os << "\n";
    391         }
    392       }
    393     }
    394 
    395     /// \brief Print a representation of this graph in DOT format.
    396     /// @param os Output stream to print on.
    397     template <typename OStream>
    398     void printDot(OStream &os) {
    399 
    400       os << "graph {\n";
    401 
    402       for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
    403            nodeItr != nodeEnd; ++nodeItr) {
    404 
    405         os << "  node" << nodeItr << " [ label=\""
    406            << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n";
    407       }
    408 
    409       os << "  edge [ len=" << getNumNodes() << " ]\n";
    410 
    411       for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
    412            edgeItr != edgeEnd; ++edgeItr) {
    413 
    414         os << "  node" << getEdgeNode1(edgeItr)
    415            << " -- node" << getEdgeNode2(edgeItr)
    416            << " [ label=\"";
    417 
    418         const Matrix &edgeCosts = getEdgeCosts(edgeItr);
    419 
    420         for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
    421           os << edgeCosts.getRowAsVector(i) << "\\n";
    422         }
    423         os << "\" ]\n";
    424       }
    425       os << "}\n";
    426     }
    427 
    428   };
    429 
    430   class NodeItrComparator {
    431   public:
    432     bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const {
    433       return &*n1 < &*n2;
    434     }
    435 
    436     bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const {
    437       return &*n1 < &*n2;
    438     }
    439   };
    440 
    441   class EdgeItrCompartor {
    442   public:
    443     bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const {
    444       return &*e1 < &*e2;
    445     }
    446 
    447     bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const {
    448       return &*e1 < &*e2;
    449     }
    450   };
    451 
    452   void Graph::copyFrom(const Graph &other) {
    453     std::map<Graph::ConstNodeItr, Graph::NodeItr,
    454              NodeItrComparator> nodeMap;
    455 
    456      for (Graph::ConstNodeItr nItr = other.nodesBegin(),
    457                              nEnd = other.nodesEnd();
    458          nItr != nEnd; ++nItr) {
    459       nodeMap[nItr] = addNode(other.getNodeCosts(nItr));
    460     }
    461 
    462   }
    463 
    464 }
    465 
    466 #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP
    467