LLVM API Documentation
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