1 //===-- GraphBase.h - Abstract Base PBQP Graph -----------------*- C++ --*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Base class for PBQP Graphs.
12 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CODEGEN_PBQP_GRAPHBASE_H
16 #define LLVM_CODEGEN_PBQP_GRAPHBASE_H
25 // UGLY, but I'm not sure there's a good way around this: We need to be able to
26 // look up a Node's "adjacent edge list" structure type before the Node type is
27 // fully constructed. We can enable this by pushing the choice of data type
28 // out into this traits class.
29 template <typename Graph
>
30 class NodeBaseTraits
{
32 typedef std::list
<typename
Graph::EdgeIterator
> AdjEdgeList
;
33 typedef typename
AdjEdgeList::iterator AdjEdgeIterator
;
34 typedef typename
AdjEdgeList::const_iterator ConstAdjEdgeIterator
;
37 /// \brief Base for concrete graph classes. Provides a basic set of graph
38 /// operations which are useful for PBQP solvers.
39 template <typename NodeEntry
, typename EdgeEntry
>
43 typedef GraphBase
<NodeEntry
, EdgeEntry
> ThisGraphT
;
45 typedef std::list
<NodeEntry
> NodeList
;
46 typedef std::list
<EdgeEntry
> EdgeList
;
49 unsigned nodeListSize
;
52 unsigned edgeListSize
;
54 GraphBase(const ThisGraphT
&other
) { abort(); }
55 void operator=(const ThisGraphT
&other
) { abort(); }
59 /// \brief Iterates over the nodes of a graph.
60 typedef typename
NodeList::iterator NodeIterator
;
61 /// \brief Iterates over the nodes of a const graph.
62 typedef typename
NodeList::const_iterator ConstNodeIterator
;
63 /// \brief Iterates over the edges of a graph.
64 typedef typename
EdgeList::iterator EdgeIterator
;
65 /// \brief Iterates over the edges of a const graph.
66 typedef typename
EdgeList::const_iterator ConstEdgeIterator
;
68 /// \brief Iterates over the edges attached to a node.
69 typedef typename NodeBaseTraits
<ThisGraphT
>::AdjEdgeIterator
72 /// \brief Iterates over the edges attached to a node in a const graph.
73 typedef typename NodeBaseTraits
<ThisGraphT
>::ConstAdjEdgeIterator
78 typedef std::vector
<NodeIterator
> IDToNodeMap
;
80 IDToNodeMap idToNodeMap
;
83 void invalidateNodeIDs() {
90 template <typename ItrT
>
91 bool iteratorInRange(ItrT itr
, const ItrT
&begin
, const ItrT
&end
) {
92 for (ItrT t
= begin
; t
!= end
; ++t
) {
102 GraphBase() : nodeListSize(0), edgeListSize(0), nodeIDsValid(false) {}
104 NodeEntry
& getNodeEntry(const NodeIterator
&nodeItr
) { return *nodeItr
; }
105 const NodeEntry
& getNodeEntry(const ConstNodeIterator
&nodeItr
) const {
109 EdgeEntry
& getEdgeEntry(const EdgeIterator
&edgeItr
) { return *edgeItr
; }
110 const EdgeEntry
& getEdgeEntry(const ConstEdgeIterator
&edgeItr
) const {
114 NodeIterator
addConstructedNode(const NodeEntry
&nodeEntry
) {
119 NodeIterator newNodeItr
= nodeList
.insert(nodeList
.end(), nodeEntry
);
124 EdgeIterator
addConstructedEdge(const EdgeEntry
&edgeEntry
) {
126 assert((findEdge(edgeEntry
.getNode1Itr(), edgeEntry
.getNode2Itr())
127 == edgeList
.end()) && "Attempt to add duplicate edge.");
131 // Add the edge to the graph.
132 EdgeIterator edgeItr
= edgeList
.insert(edgeList
.end(), edgeEntry
);
134 // Get a reference to the version in the graph.
135 EdgeEntry
&newEdgeEntry
= getEdgeEntry(edgeItr
);
138 NodeEntry
&node1Entry
= getNodeEntry(newEdgeEntry
.getNode1Itr()),
139 &node2Entry
= getNodeEntry(newEdgeEntry
.getNode2Itr());
141 // Sanity check on matrix dimensions.
142 assert((node1Entry
.getCosts().getLength() ==
143 newEdgeEntry
.getCosts().getRows()) &&
144 (node2Entry
.getCosts().getLength() ==
145 newEdgeEntry
.getCosts().getCols()) &&
146 "Matrix dimensions do not match cost vector dimensions.");
148 // Create links between nodes and edges.
149 newEdgeEntry
.setNode1ThisEdgeItr(
150 node1Entry
.addAdjEdge(edgeItr
));
151 newEdgeEntry
.setNode2ThisEdgeItr(
152 node2Entry
.addAdjEdge(edgeItr
));
159 /// \brief Returns the number of nodes in this graph.
160 unsigned getNumNodes() const { return nodeListSize
; }
162 /// \brief Returns the number of edges in this graph.
163 unsigned getNumEdges() const { return edgeListSize
; }
165 /// \brief Return the cost vector for the given node.
166 Vector
& getNodeCosts(const NodeIterator
&nodeItr
) {
167 return getNodeEntry(nodeItr
).getCosts();
170 /// \brief Return the cost vector for the give node.
171 const Vector
& getNodeCosts(const ConstNodeIterator
&nodeItr
) const {
172 return getNodeEntry(nodeItr
).getCosts();
175 /// \brief Return the degree of the given node.
176 unsigned getNodeDegree(const NodeIterator
&nodeItr
) const {
177 return getNodeEntry(nodeItr
).getDegree();
180 /// \brief Assigns sequential IDs to the nodes, starting at 0, which
181 /// remain valid until the next addition or removal of a node.
182 void assignNodeIDs() {
184 idToNodeMap
.resize(getNumNodes());
185 for (NodeIterator nodeItr
= nodesBegin(), nodeEnd
= nodesEnd();
186 nodeItr
!= nodeEnd
; ++nodeItr
, ++curID
) {
187 getNodeEntry(nodeItr
).setID(curID
);
188 idToNodeMap
[curID
] = nodeItr
;
193 /// \brief Assigns sequential IDs to the nodes using the ordering of the
195 void assignNodeIDs(const std::vector
<NodeIterator
> &nodeOrdering
) {
196 assert((getNumNodes() == nodeOrdering
.size()) &&
197 "Wrong number of nodes in node ordering.");
198 idToNodeMap
= nodeOrdering
;
199 for (unsigned nodeID
= 0; nodeID
< idToNodeMap
.size(); ++nodeID
) {
200 getNodeEntry(idToNodeMap
[nodeID
]).setID(nodeID
);
205 /// \brief Returns true if valid node IDs are assigned, false otherwise.
206 bool areNodeIDsValid() const { return nodeIDsValid
; }
208 /// \brief Return the numeric ID of the given node.
210 /// Calls to this method will result in an assertion failure if there have
211 /// been any node additions or removals since the last call to
213 unsigned getNodeID(const ConstNodeIterator
&nodeItr
) const {
214 assert(nodeIDsValid
&& "Attempt to retrieve invalid ID.");
215 return getNodeEntry(nodeItr
).getID();
218 /// \brief Returns the iterator associated with the given node ID.
219 NodeIterator
getNodeItr(unsigned nodeID
) {
220 assert(nodeIDsValid
&& "Attempt to retrieve iterator with invalid ID.");
221 return idToNodeMap
[nodeID
];
224 /// \brief Returns the iterator associated with the given node ID.
225 ConstNodeIterator
getNodeItr(unsigned nodeID
) const {
226 assert(nodeIDsValid
&& "Attempt to retrieve iterator with invalid ID.");
227 return idToNodeMap
[nodeID
];
230 /// \brief Removes the given node (and all attached edges) from the graph.
231 void removeNode(const NodeIterator
&nodeItr
) {
232 assert(iteratorInRange(nodeItr
, nodeList
.begin(), nodeList
.end()) &&
233 "Iterator does not belong to this graph!");
237 NodeEntry
&nodeEntry
= getNodeEntry(nodeItr
);
239 // We need to copy this out because it will be destroyed as the edges are
241 typedef std::vector
<EdgeIterator
> AdjEdgeList
;
242 typedef typename
AdjEdgeList::iterator AdjEdgeListItr
;
244 AdjEdgeList adjEdges
;
245 adjEdges
.reserve(nodeEntry
.getDegree());
246 std::copy(nodeEntry
.adjEdgesBegin(), nodeEntry
.adjEdgesEnd(),
247 std::back_inserter(adjEdges
));
249 // Iterate over the copied out edges and remove them from the graph.
250 for (AdjEdgeListItr itr
= adjEdges
.begin(), end
= adjEdges
.end();
255 // Erase the node from the nodelist.
256 nodeList
.erase(nodeItr
);
260 NodeIterator
nodesBegin() { return nodeList
.begin(); }
261 ConstNodeIterator
nodesBegin() const { return nodeList
.begin(); }
262 NodeIterator
nodesEnd() { return nodeList
.end(); }
263 ConstNodeIterator
nodesEnd() const { return nodeList
.end(); }
265 AdjEdgeIterator
adjEdgesBegin(const NodeIterator
&nodeItr
) {
266 return getNodeEntry(nodeItr
).adjEdgesBegin();
269 ConstAdjEdgeIterator
adjEdgesBegin(const ConstNodeIterator
&nodeItr
) const {
270 return getNodeEntry(nodeItr
).adjEdgesBegin();
273 AdjEdgeIterator
adjEdgesEnd(const NodeIterator
&nodeItr
) {
274 return getNodeEntry(nodeItr
).adjEdgesEnd();
277 ConstAdjEdgeIterator
adjEdgesEnd(const ConstNodeIterator
&nodeItr
) const {
278 getNodeEntry(nodeItr
).adjEdgesEnd();
281 EdgeIterator
findEdge(const NodeIterator
&node1Itr
,
282 const NodeIterator
&node2Itr
) {
284 for (AdjEdgeIterator adjEdgeItr
= adjEdgesBegin(node1Itr
),
285 adjEdgeEnd
= adjEdgesEnd(node1Itr
);
286 adjEdgeItr
!= adjEdgeEnd
; ++adjEdgeItr
) {
287 if ((getEdgeNode1Itr(*adjEdgeItr
) == node2Itr
) ||
288 (getEdgeNode2Itr(*adjEdgeItr
) == node2Itr
)) {
293 return edgeList
.end();
296 ConstEdgeIterator
findEdge(const ConstNodeIterator
&node1Itr
,
297 const ConstNodeIterator
&node2Itr
) const {
299 for (ConstAdjEdgeIterator adjEdgeItr
= adjEdgesBegin(node1Itr
),
300 adjEdgeEnd
= adjEdgesEnd(node1Itr
);
301 adjEdgeItr
!= adjEdgesEnd
; ++adjEdgeItr
) {
302 if ((getEdgeNode1Itr(*adjEdgeItr
) == node2Itr
) ||
303 (getEdgeNode2Itr(*adjEdgeItr
) == node2Itr
)) {
308 return edgeList
.end();
311 Matrix
& getEdgeCosts(const EdgeIterator
&edgeItr
) {
312 return getEdgeEntry(edgeItr
).getCosts();
315 const Matrix
& getEdgeCosts(const ConstEdgeIterator
&edgeItr
) const {
316 return getEdgeEntry(edgeItr
).getCosts();
319 NodeIterator
getEdgeNode1Itr(const EdgeIterator
&edgeItr
) {
320 return getEdgeEntry(edgeItr
).getNode1Itr();
323 ConstNodeIterator
getEdgeNode1Itr(const ConstEdgeIterator
&edgeItr
) const {
324 return getEdgeEntry(edgeItr
).getNode1Itr();
327 NodeIterator
getEdgeNode2Itr(const EdgeIterator
&edgeItr
) {
328 return getEdgeEntry(edgeItr
).getNode2Itr();
331 ConstNodeIterator
getEdgeNode2Itr(const ConstEdgeIterator
&edgeItr
) const {
332 return getEdgeEntry(edgeItr
).getNode2Itr();
335 NodeIterator
getEdgeOtherNode(const EdgeIterator
&edgeItr
,
336 const NodeIterator
&nodeItr
) {
338 EdgeEntry
&edgeEntry
= getEdgeEntry(edgeItr
);
339 if (nodeItr
== edgeEntry
.getNode1Itr()) {
340 return edgeEntry
.getNode2Itr();
343 return edgeEntry
.getNode1Itr();
346 ConstNodeIterator
getEdgeOtherNode(const ConstEdgeIterator
&edgeItr
,
347 const ConstNodeIterator
&nodeItr
) const {
349 const EdgeEntry
&edgeEntry
= getEdgeEntry(edgeItr
);
350 if (nodeItr
== edgeEntry
.getNode1Itr()) {
351 return edgeEntry
.getNode2Itr();
354 return edgeEntry
.getNode1Itr();
357 void removeEdge(const EdgeIterator
&edgeItr
) {
358 assert(iteratorInRange(edgeItr
, edgeList
.begin(), edgeList
.end()) &&
359 "Iterator does not belong to this graph!");
363 // Get the edge entry.
364 EdgeEntry
&edgeEntry
= getEdgeEntry(edgeItr
);
366 // Get the nodes entry.
367 NodeEntry
&node1Entry(getNodeEntry(edgeEntry
.getNode1Itr())),
368 &node2Entry(getNodeEntry(edgeEntry
.getNode2Itr()));
370 // Disconnect the edge from the nodes.
371 node1Entry
.removeAdjEdge(edgeEntry
.getNode1ThisEdgeItr());
372 node2Entry
.removeAdjEdge(edgeEntry
.getNode2ThisEdgeItr());
374 // Remove the edge from the graph.
375 edgeList
.erase(edgeItr
);
378 EdgeIterator
edgesBegin() { return edgeList
.begin(); }
379 ConstEdgeIterator
edgesBegin() const { return edgeList
.begin(); }
380 EdgeIterator
edgesEnd() { return edgeList
.end(); }
381 ConstEdgeIterator
edgesEnd() const { return edgeList
.end(); }
391 template <typename OStream
>
392 void printDot(OStream
&os
) const {
394 assert(areNodeIDsValid() &&
395 "Cannot print a .dot of a graph unless IDs have been assigned.");
399 for (ConstNodeIterator nodeItr
= nodesBegin(), nodeEnd
= nodesEnd();
400 nodeItr
!= nodeEnd
; ++nodeItr
) {
402 os
<< " node" << getNodeID(nodeItr
) << " [ label=\""
403 << getNodeID(nodeItr
) << ": " << getNodeCosts(nodeItr
) << "\" ]\n";
406 os
<< " edge [ len=" << getNumNodes() << " ]\n";
408 for (ConstEdgeIterator edgeItr
= edgesBegin(), edgeEnd
= edgesEnd();
409 edgeItr
!= edgeEnd
; ++edgeItr
) {
411 os
<< " node" << getNodeID(getEdgeNode1Itr(edgeItr
))
412 << " -- node" << getNodeID(getEdgeNode2Itr(edgeItr
))
415 const Matrix
&edgeCosts
= getEdgeCosts(edgeItr
);
417 for (unsigned i
= 0; i
< edgeCosts
.getRows(); ++i
) {
418 os
<< edgeCosts
.getRowAsVector(i
) << "\\n";
427 template <typename OStream
>
428 void printDot(OStream
&os
) {
429 if (!areNodeIDsValid()) {
433 const_cast<const ThisGraphT
*>(this)->printDot(os
);
436 template <typename OStream
>
437 void dumpTo(OStream
&os
) const {
438 typedef ConstNodeIterator ConstNodeID
;
440 assert(areNodeIDsValid() &&
441 "Cannot dump a graph unless IDs have been assigned.");
443 for (ConstNodeIterator nItr
= nodesBegin(), nEnd
= nodesEnd();
444 nItr
!= nEnd
; ++nItr
) {
445 os
<< getNodeID(nItr
) << "\n";
448 unsigned edgeNumber
= 1;
449 for (ConstEdgeIterator eItr
= edgesBegin(), eEnd
= edgesEnd();
450 eItr
!= eEnd
; ++eItr
) {
452 os
<< edgeNumber
++ << ": { "
453 << getNodeID(getEdgeNode1Itr(eItr
)) << ", "
454 << getNodeID(getEdgeNode2Itr(eItr
)) << " }\n";
459 template <typename OStream
>
460 void dumpTo(OStream
&os
) {
461 if (!areNodeIDsValid()) {
465 const_cast<const ThisGraphT
*>(this)->dumpTo(os
);
470 /// \brief Provides a base from which to derive nodes for GraphBase.
471 template <typename NodeImpl
, typename EdgeImpl
>
475 typedef GraphBase
<NodeImpl
, EdgeImpl
> GraphBaseT
;
476 typedef NodeBaseTraits
<GraphBaseT
> ThisNodeBaseTraits
;
479 typedef typename
GraphBaseT::EdgeIterator EdgeIterator
;
482 typedef typename
ThisNodeBaseTraits::AdjEdgeList AdjEdgeList
;
486 AdjEdgeList adjEdges
;
488 void operator=(const NodeBase
& other
) {
489 assert(false && "Can't assign NodeEntrys.");
494 typedef typename
ThisNodeBaseTraits::AdjEdgeIterator AdjEdgeIterator
;
495 typedef typename
ThisNodeBaseTraits::ConstAdjEdgeIterator
496 ConstAdjEdgeIterator
;
498 NodeBase(const Vector
&costs
) : degree(0), costs(costs
) {
499 assert((costs
.getLength() > 0) && "Can't have zero-length cost vector.");
502 Vector
& getCosts() { return costs
; }
503 const Vector
& getCosts() const { return costs
; }
505 unsigned getDegree() const { return degree
; }
507 void setID(unsigned id
) { this->id
= id
; }
508 unsigned getID() const { return id
; }
510 AdjEdgeIterator
addAdjEdge(const EdgeIterator
&edgeItr
) {
512 return adjEdges
.insert(adjEdges
.end(), edgeItr
);
515 void removeAdjEdge(const AdjEdgeIterator
&adjEdgeItr
) {
517 adjEdges
.erase(adjEdgeItr
);
520 AdjEdgeIterator
adjEdgesBegin() { return adjEdges
.begin(); }
521 ConstAdjEdgeIterator
adjEdgesBegin() const { return adjEdges
.begin(); }
522 AdjEdgeIterator
adjEdgesEnd() { return adjEdges
.end(); }
523 ConstAdjEdgeIterator
adjEdgesEnd() const { return adjEdges
.end(); }
527 template <typename NodeImpl
, typename EdgeImpl
>
530 typedef typename GraphBase
<NodeImpl
, EdgeImpl
>::NodeIterator NodeIterator
;
531 typedef typename GraphBase
<NodeImpl
, EdgeImpl
>::EdgeIterator EdgeIterator
;
533 typedef typename
NodeImpl::AdjEdgeIterator NodeAdjEdgeIterator
;
537 NodeIterator node1Itr
, node2Itr
;
538 NodeAdjEdgeIterator node1ThisEdgeItr
, node2ThisEdgeItr
;
541 void operator=(const EdgeBase
&other
) {
542 assert(false && "Can't assign EdgeEntrys.");
547 EdgeBase(const NodeIterator
&node1Itr
, const NodeIterator
&node2Itr
,
548 const Matrix
&costs
) :
549 node1Itr(node1Itr
), node2Itr(node2Itr
), costs(costs
) {
551 assert((costs
.getRows() > 0) && (costs
.getCols() > 0) &&
552 "Can't have zero-dimensioned cost matrices");
555 Matrix
& getCosts() { return costs
; }
556 const Matrix
& getCosts() const { return costs
; }
558 const NodeIterator
& getNode1Itr() const { return node1Itr
; }
559 const NodeIterator
& getNode2Itr() const { return node2Itr
; }
561 void setNode1ThisEdgeItr(const NodeAdjEdgeIterator
&node1ThisEdgeItr
) {
562 this->node1ThisEdgeItr
= node1ThisEdgeItr
;
565 const NodeAdjEdgeIterator
& getNode1ThisEdgeItr() const {
566 return node1ThisEdgeItr
;
569 void setNode2ThisEdgeItr(const NodeAdjEdgeIterator
&node2ThisEdgeItr
) {
570 this->node2ThisEdgeItr
= node2ThisEdgeItr
;
573 const NodeAdjEdgeIterator
& getNode2ThisEdgeItr() const {
574 return node2ThisEdgeItr
;
582 #endif // LLVM_CODEGEN_PBQP_GRAPHBASE_HPP