LLVM API Documentation

Graph.h
Go to the documentation of this file.
00001 //===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // PBQP Graph class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 
00015 #ifndef LLVM_CODEGEN_PBQP_GRAPH_H
00016 #define LLVM_CODEGEN_PBQP_GRAPH_H
00017 
00018 #include "Math.h"
00019 #include "llvm/ADT/ilist.h"
00020 #include "llvm/ADT/ilist_node.h"
00021 #include <list>
00022 #include <map>
00023 
00024 namespace PBQP {
00025 
00026   /// PBQP Graph class.
00027   /// Instances of this class describe PBQP problems.
00028   class Graph {
00029   private:
00030 
00031     // ----- TYPEDEFS -----
00032     class NodeEntry;
00033     class EdgeEntry;
00034 
00035     typedef llvm::ilist<NodeEntry> NodeList;
00036     typedef llvm::ilist<EdgeEntry> EdgeList;
00037 
00038   public:
00039 
00040     typedef NodeList::iterator NodeItr;
00041     typedef NodeList::const_iterator ConstNodeItr;
00042 
00043     typedef EdgeList::iterator EdgeItr;
00044     typedef EdgeList::const_iterator ConstEdgeItr;
00045 
00046   private:
00047 
00048     typedef std::list<EdgeItr> AdjEdgeList;
00049   
00050   public:
00051 
00052     typedef AdjEdgeList::iterator AdjEdgeItr;
00053 
00054   private:
00055 
00056     class NodeEntry : public llvm::ilist_node<NodeEntry> {
00057       friend struct llvm::ilist_sentinel_traits<NodeEntry>;
00058     private:
00059       Vector costs;      
00060       AdjEdgeList adjEdges;
00061       unsigned degree;
00062       void *data;
00063       NodeEntry() : costs(0, 0) {}
00064     public:
00065       NodeEntry(const Vector &costs) : costs(costs), degree(0) {}
00066       Vector& getCosts() { return costs; }
00067       const Vector& getCosts() const { return costs; }
00068       unsigned getDegree() const { return degree; }
00069       AdjEdgeItr edgesBegin() { return adjEdges.begin(); }
00070       AdjEdgeItr edgesEnd() { return adjEdges.end(); }
00071       AdjEdgeItr addEdge(EdgeItr e) {
00072         ++degree;
00073         return adjEdges.insert(adjEdges.end(), e);
00074       }
00075       void removeEdge(AdjEdgeItr ae) {
00076         --degree;
00077         adjEdges.erase(ae);
00078       }
00079       void setData(void *data) { this->data = data; }
00080       void* getData() { return data; }
00081     };
00082 
00083     class EdgeEntry : public llvm::ilist_node<EdgeEntry> {
00084       friend struct llvm::ilist_sentinel_traits<EdgeEntry>;
00085     private:
00086       NodeItr node1, node2;
00087       Matrix costs;
00088       AdjEdgeItr node1AEItr, node2AEItr;
00089       void *data;
00090       EdgeEntry() : costs(0, 0, 0) {}
00091     public:
00092       EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs)
00093         : node1(node1), node2(node2), costs(costs) {}
00094       NodeItr getNode1() const { return node1; }
00095       NodeItr getNode2() const { return node2; }
00096       Matrix& getCosts() { return costs; }
00097       const Matrix& getCosts() const { return costs; }
00098       void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; }
00099       AdjEdgeItr getNode1AEItr() { return node1AEItr; }
00100       void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; }
00101       AdjEdgeItr getNode2AEItr() { return node2AEItr; }
00102       void setData(void *data) { this->data = data; }
00103       void *getData() { return data; }
00104     };
00105 
00106     // ----- MEMBERS -----
00107 
00108     NodeList nodes;
00109     unsigned numNodes;
00110 
00111     EdgeList edges;
00112     unsigned numEdges;
00113 
00114     // ----- INTERNAL METHODS -----
00115 
00116     NodeEntry& getNode(NodeItr nItr) { return *nItr; }
00117     const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; }
00118 
00119     EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; }
00120     const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; }
00121 
00122     NodeItr addConstructedNode(const NodeEntry &n) {
00123       ++numNodes;
00124       return nodes.insert(nodes.end(), n);
00125     }
00126 
00127     EdgeItr addConstructedEdge(const EdgeEntry &e) {
00128       assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() &&
00129              "Attempt to add duplicate edge.");
00130       ++numEdges;
00131       EdgeItr edgeItr = edges.insert(edges.end(), e);
00132       EdgeEntry &ne = getEdge(edgeItr);
00133       NodeEntry &n1 = getNode(ne.getNode1());
00134       NodeEntry &n2 = getNode(ne.getNode2());
00135       // Sanity check on matrix dimensions:
00136       assert((n1.getCosts().getLength() == ne.getCosts().getRows()) &&
00137              (n2.getCosts().getLength() == ne.getCosts().getCols()) &&
00138              "Edge cost dimensions do not match node costs dimensions.");
00139       ne.setNode1AEItr(n1.addEdge(edgeItr));
00140       ne.setNode2AEItr(n2.addEdge(edgeItr));
00141       return edgeItr;
00142     }
00143 
00144     inline void copyFrom(const Graph &other);
00145   public:
00146 
00147     /// \brief Construct an empty PBQP graph.
00148     Graph() : numNodes(0), numEdges(0) {}
00149 
00150     /// \brief Copy construct this graph from "other". Note: Does not copy node
00151     ///        and edge data, only graph structure and costs.
00152     /// @param other Source graph to copy from.
00153     Graph(const Graph &other) : numNodes(0), numEdges(0) {
00154       copyFrom(other);
00155     }
00156 
00157     /// \brief Make this graph a copy of "other". Note: Does not copy node and
00158     ///        edge data, only graph structure and costs.
00159     /// @param other The graph to copy from.
00160     /// @return A reference to this graph.
00161     ///
00162     /// This will clear the current graph, erasing any nodes and edges added,
00163     /// before copying from other.
00164     Graph& operator=(const Graph &other) {
00165       clear();      
00166       copyFrom(other);
00167       return *this;
00168     }
00169 
00170     /// \brief Add a node with the given costs.
00171     /// @param costs Cost vector for the new node.
00172     /// @return Node iterator for the added node.
00173     NodeItr addNode(const Vector &costs) {
00174       return addConstructedNode(NodeEntry(costs));
00175     }
00176 
00177     /// \brief Add an edge between the given nodes with the given costs.
00178     /// @param n1Itr First node.
00179     /// @param n2Itr Second node.
00180     /// @return Edge iterator for the added edge.
00181     EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr,
00182                     const Matrix &costs) {
00183       assert(getNodeCosts(n1Itr).getLength() == costs.getRows() &&
00184              getNodeCosts(n2Itr).getLength() == costs.getCols() &&
00185              "Matrix dimensions mismatch.");
00186       return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); 
00187     }
00188 
00189     /// \brief Get the number of nodes in the graph.
00190     /// @return Number of nodes in the graph.
00191     unsigned getNumNodes() const { return numNodes; }
00192 
00193     /// \brief Get the number of edges in the graph.
00194     /// @return Number of edges in the graph.
00195     unsigned getNumEdges() const { return numEdges; }
00196 
00197     /// \brief Get a node's cost vector.
00198     /// @param nItr Node iterator.
00199     /// @return Node cost vector.
00200     Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); }
00201 
00202     /// \brief Get a node's cost vector (const version).
00203     /// @param nItr Node iterator.
00204     /// @return Node cost vector.
00205     const Vector& getNodeCosts(ConstNodeItr nItr) const {
00206       return getNode(nItr).getCosts();
00207     }
00208 
00209     /// \brief Set a node's data pointer.
00210     /// @param nItr Node iterator.
00211     /// @param data Pointer to node data.
00212     ///
00213     /// Typically used by a PBQP solver to attach data to aid in solution.
00214     void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); }
00215 
00216     /// \brief Get the node's data pointer.
00217     /// @param nItr Node iterator.
00218     /// @return Pointer to node data.
00219     void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); }
00220     
00221     /// \brief Get an edge's cost matrix.
00222     /// @param eItr Edge iterator.
00223     /// @return Edge cost matrix.
00224     Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); }
00225 
00226     /// \brief Get an edge's cost matrix (const version).
00227     /// @param eItr Edge iterator.
00228     /// @return Edge cost matrix.
00229     const Matrix& getEdgeCosts(ConstEdgeItr eItr) const {
00230       return getEdge(eItr).getCosts();
00231     }
00232 
00233     /// \brief Set an edge's data pointer.
00234     /// @param eItr Edge iterator.
00235     /// @param data Pointer to edge data.
00236     ///
00237     /// Typically used by a PBQP solver to attach data to aid in solution.
00238     void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); }
00239 
00240     /// \brief Get an edge's data pointer.
00241     /// @param eItr Edge iterator.
00242     /// @return Pointer to edge data. 
00243     void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); }
00244 
00245     /// \brief Get a node's degree.
00246     /// @param nItr Node iterator.
00247     /// @return The degree of the node.
00248     unsigned getNodeDegree(NodeItr nItr) const {
00249       return getNode(nItr).getDegree();
00250     }
00251 
00252     /// \brief Begin iterator for node set.
00253     NodeItr nodesBegin() { return nodes.begin(); }
00254 
00255     /// \brief Begin const iterator for node set.
00256     ConstNodeItr nodesBegin() const { return nodes.begin(); }
00257 
00258     /// \brief End iterator for node set.
00259     NodeItr nodesEnd() { return nodes.end(); }
00260 
00261     /// \brief End const iterator for node set.
00262     ConstNodeItr nodesEnd() const { return nodes.end(); }
00263 
00264     /// \brief Begin iterator for edge set.
00265     EdgeItr edgesBegin() { return edges.begin(); }
00266 
00267     /// \brief End iterator for edge set.
00268     EdgeItr edgesEnd() { return edges.end(); }
00269 
00270     /// \brief Get begin iterator for adjacent edge set.
00271     /// @param nItr Node iterator.
00272     /// @return Begin iterator for the set of edges connected to the given node.
00273     AdjEdgeItr adjEdgesBegin(NodeItr nItr) {
00274       return getNode(nItr).edgesBegin();
00275     }
00276 
00277     /// \brief Get end iterator for adjacent edge set.
00278     /// @param nItr Node iterator.
00279     /// @return End iterator for the set of edges connected to the given node.
00280     AdjEdgeItr adjEdgesEnd(NodeItr nItr) {
00281       return getNode(nItr).edgesEnd();
00282     }
00283 
00284     /// \brief Get the first node connected to this edge.
00285     /// @param eItr Edge iterator.
00286     /// @return The first node connected to the given edge. 
00287     NodeItr getEdgeNode1(EdgeItr eItr) {
00288       return getEdge(eItr).getNode1();
00289     }
00290 
00291     /// \brief Get the second node connected to this edge.
00292     /// @param eItr Edge iterator.
00293     /// @return The second node connected to the given edge. 
00294     NodeItr getEdgeNode2(EdgeItr eItr) {
00295       return getEdge(eItr).getNode2();
00296     } 
00297 
00298     /// \brief Get the "other" node connected to this edge.
00299     /// @param eItr Edge iterator.
00300     /// @param nItr Node iterator for the "given" node.
00301     /// @return The iterator for the "other" node connected to this edge. 
00302     NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) {
00303       EdgeEntry &e = getEdge(eItr);
00304       if (e.getNode1() == nItr) {
00305         return e.getNode2();
00306       } // else
00307       return e.getNode1();
00308     }
00309 
00310     /// \brief Get the edge connecting two nodes.
00311     /// @param n1Itr First node iterator.
00312     /// @param n2Itr Second node iterator.
00313     /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists,
00314     ///         otherwise returns edgesEnd(). 
00315     EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) {
00316       for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr);
00317          aeItr != aeEnd; ++aeItr) {
00318         if ((getEdgeNode1(*aeItr) == n2Itr) ||
00319             (getEdgeNode2(*aeItr) == n2Itr)) {
00320           return *aeItr;
00321         }
00322       }
00323       return edges.end();
00324     }
00325 
00326     /// \brief Remove a node from the graph.
00327     /// @param nItr Node iterator.
00328     void removeNode(NodeItr nItr) {
00329       NodeEntry &n = getNode(nItr);
00330       for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) {
00331         EdgeItr eItr = *itr;
00332         ++itr;
00333         removeEdge(eItr); 
00334       }
00335       nodes.erase(nItr);
00336       --numNodes;
00337     }
00338 
00339     /// \brief Remove an edge from the graph.
00340     /// @param eItr Edge iterator.
00341     void removeEdge(EdgeItr eItr) {
00342       EdgeEntry &e = getEdge(eItr);
00343       NodeEntry &n1 = getNode(e.getNode1());
00344       NodeEntry &n2 = getNode(e.getNode2());
00345       n1.removeEdge(e.getNode1AEItr());
00346       n2.removeEdge(e.getNode2AEItr());
00347       edges.erase(eItr);
00348       --numEdges;
00349     }
00350 
00351     /// \brief Remove all nodes and edges from the graph.
00352     void clear() {
00353       nodes.clear();
00354       edges.clear();
00355       numNodes = numEdges = 0;
00356     }
00357 
00358     /// \brief Dump a graph to an output stream.
00359     template <typename OStream>
00360     void dump(OStream &os) {
00361       os << getNumNodes() << " " << getNumEdges() << "\n";
00362 
00363       for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
00364            nodeItr != nodeEnd; ++nodeItr) {
00365         const Vector& v = getNodeCosts(nodeItr);
00366         os << "\n" << v.getLength() << "\n";
00367         assert(v.getLength() != 0 && "Empty vector in graph.");
00368         os << v[0];
00369         for (unsigned i = 1; i < v.getLength(); ++i) {
00370           os << " " << v[i];
00371         }
00372         os << "\n";
00373       }
00374 
00375       for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
00376            edgeItr != edgeEnd; ++edgeItr) {
00377         unsigned n1 = std::distance(nodesBegin(), getEdgeNode1(edgeItr));
00378         unsigned n2 = std::distance(nodesBegin(), getEdgeNode2(edgeItr));
00379         assert(n1 != n2 && "PBQP graphs shound not have self-edges.");
00380         const Matrix& m = getEdgeCosts(edgeItr);
00381         os << "\n" << n1 << " " << n2 << "\n"
00382            << m.getRows() << " " << m.getCols() << "\n";
00383         assert(m.getRows() != 0 && "No rows in matrix.");
00384         assert(m.getCols() != 0 && "No cols in matrix.");
00385         for (unsigned i = 0; i < m.getRows(); ++i) {
00386           os << m[i][0];
00387           for (unsigned j = 1; j < m.getCols(); ++j) {
00388             os << " " << m[i][j];
00389           }
00390           os << "\n";
00391         }
00392       }
00393     }
00394 
00395     /// \brief Print a representation of this graph in DOT format.
00396     /// @param os Output stream to print on.
00397     template <typename OStream>
00398     void printDot(OStream &os) {
00399     
00400       os << "graph {\n";
00401 
00402       for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
00403            nodeItr != nodeEnd; ++nodeItr) {
00404 
00405         os << "  node" << nodeItr << " [ label=\""
00406            << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n";
00407       }
00408 
00409       os << "  edge [ len=" << getNumNodes() << " ]\n";
00410 
00411       for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
00412            edgeItr != edgeEnd; ++edgeItr) {
00413 
00414         os << "  node" << getEdgeNode1(edgeItr)
00415            << " -- node" << getEdgeNode2(edgeItr)
00416            << " [ label=\"";
00417 
00418         const Matrix &edgeCosts = getEdgeCosts(edgeItr);
00419 
00420         for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
00421           os << edgeCosts.getRowAsVector(i) << "\\n";
00422         }
00423         os << "\" ]\n";
00424       }
00425       os << "}\n";
00426     }
00427 
00428   };
00429 
00430   class NodeItrComparator {
00431   public:
00432     bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const {
00433       return &*n1 < &*n2;
00434     }
00435 
00436     bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const {
00437       return &*n1 < &*n2;
00438     }
00439   };
00440 
00441   class EdgeItrCompartor {
00442   public:
00443     bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const {
00444       return &*e1 < &*e2;
00445     }
00446 
00447     bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const {
00448       return &*e1 < &*e2;
00449     }
00450   };
00451 
00452   void Graph::copyFrom(const Graph &other) {
00453     std::map<Graph::ConstNodeItr, Graph::NodeItr,
00454              NodeItrComparator> nodeMap;
00455 
00456      for (Graph::ConstNodeItr nItr = other.nodesBegin(),
00457                              nEnd = other.nodesEnd();
00458          nItr != nEnd; ++nItr) {
00459       nodeMap[nItr] = addNode(other.getNodeCosts(nItr));
00460     }
00461       
00462   }
00463 
00464 }
00465 
00466 #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP