blob: bda5952e22a90b88d6ae474c4fca70ed05451d17 [file] [log] [blame]
Lang Hames3ca9a5b2009-08-06 23:32:48 +00001#ifndef LLVM_CODEGEN_PBQP_GRAPHBASE_H
2#define LLVM_CODEGEN_PBQP_GRAPHBASE_H
3
4#include "PBQPMath.h"
5
6#include <list>
7#include <vector>
8
9namespace PBQP {
10
11// UGLY, but I'm not sure there's a good way around this: We need to be able to
12// look up a Node's "adjacent edge list" structure type before the Node type is
13// fully constructed. We can enable this by pushing the choice of data type
14// out into this traits class.
15template <typename Graph>
16class NodeBaseTraits {
17 public:
18 typedef std::list<typename Graph::EdgeIterator> AdjEdgeList;
19 typedef typename AdjEdgeList::iterator AdjEdgeIterator;
20 typedef typename AdjEdgeList::const_iterator ConstAdjEdgeIterator;
21};
22
23/// \brief Base for concrete graph classes. Provides a basic set of graph
24/// operations which are useful for PBQP solvers.
25template <typename NodeEntry, typename EdgeEntry>
26class GraphBase {
27private:
28
29 typedef GraphBase<NodeEntry, EdgeEntry> ThisGraphT;
30
31 typedef std::list<NodeEntry> NodeList;
32 typedef std::list<EdgeEntry> EdgeList;
33
34 NodeList nodeList;
35 unsigned nodeListSize;
36
37 EdgeList edgeList;
38 unsigned edgeListSize;
39
40 GraphBase(const ThisGraphT &other) { abort(); }
41 void operator=(const ThisGraphT &other) { abort(); }
42
43public:
44
45 /// \brief Iterates over the nodes of a graph.
46 typedef typename NodeList::iterator NodeIterator;
47 /// \brief Iterates over the nodes of a const graph.
48 typedef typename NodeList::const_iterator ConstNodeIterator;
49 /// \brief Iterates over the edges of a graph.
50 typedef typename EdgeList::iterator EdgeIterator;
51 /// \brief Iterates over the edges of a const graph.
52 typedef typename EdgeList::const_iterator ConstEdgeIterator;
53
54 /// \brief Iterates over the edges attached to a node.
55 typedef typename NodeBaseTraits<ThisGraphT>::AdjEdgeIterator
56 AdjEdgeIterator;
57
58 /// \brief Iterates over the edges attached to a node in a const graph.
59 typedef typename NodeBaseTraits<ThisGraphT>::ConstAdjEdgeIterator
60 ConstAdjEdgeIterator;
61
62private:
63
64 typedef std::vector<NodeIterator> IDToNodeMap;
65
66 IDToNodeMap idToNodeMap;
67 bool nodeIDsValid;
68
69 void invalidateNodeIDs() {
70 if (nodeIDsValid) {
71 idToNodeMap.clear();
72 nodeIDsValid = false;
73 }
74 }
75
76 template <typename ItrT>
77 bool iteratorInRange(ItrT itr, const ItrT &begin, const ItrT &end) {
78 for (ItrT t = begin; t != end; ++t) {
79 if (itr == t)
80 return true;
81 }
82
83 return false;
84 }
85
86protected:
87
88 GraphBase() : nodeListSize(0), edgeListSize(0), nodeIDsValid(false) {}
89
90 NodeEntry& getNodeEntry(const NodeIterator &nodeItr) { return *nodeItr; }
91 const NodeEntry& getNodeEntry(const ConstNodeIterator &nodeItr) const {
92 return *nodeItr;
93 }
94
95 EdgeEntry& getEdgeEntry(const EdgeIterator &edgeItr) { return *edgeItr; }
96 const EdgeEntry& getEdgeEntry(const ConstEdgeIterator &edgeItr) const {
97 return *edgeItr;
98 }
99
100 NodeIterator addConstructedNode(const NodeEntry &nodeEntry) {
101 ++nodeListSize;
102
103 invalidateNodeIDs();
104
105 NodeIterator newNodeItr = nodeList.insert(nodeList.end(), nodeEntry);
106
107 return newNodeItr;
108 }
109
110 EdgeIterator addConstructedEdge(const EdgeEntry &edgeEntry) {
111
112 assert((findEdge(edgeEntry.getNode1Itr(), edgeEntry.getNode2Itr())
113 == edgeList.end()) && "Attempt to add duplicate edge.");
114
115 ++edgeListSize;
116
117 // Add the edge to the graph.
118 EdgeIterator edgeItr = edgeList.insert(edgeList.end(), edgeEntry);
119
120 // Get a reference to the version in the graph.
121 EdgeEntry &newEdgeEntry = getEdgeEntry(edgeItr);
122
123 // Node entries:
124 NodeEntry &node1Entry = getNodeEntry(newEdgeEntry.getNode1Itr()),
125 &node2Entry = getNodeEntry(newEdgeEntry.getNode2Itr());
126
127 unsigned n1Len = node1Entry.getCosts().getLength(),
128 n2Len = node2Entry.getCosts().getLength(),
129 mRows = newEdgeEntry.getCosts().getRows(),
130 mCols = newEdgeEntry.getCosts().getCols();
131
132 // Sanity check on matrix dimensions.
133 assert((n1Len == mRows) && (n2Len == mCols) &&
134 "Matrix dimensions do not match cost vector dimensions.");
135
136 // Create links between nodes and edges.
137 newEdgeEntry.setNode1ThisEdgeItr(
138 node1Entry.addAdjEdge(edgeItr));
139 newEdgeEntry.setNode2ThisEdgeItr(
140 node2Entry.addAdjEdge(edgeItr));
141
142 return edgeItr;
143 }
144
145public:
146
147 /// \brief Returns the number of nodes in this graph.
148 unsigned getNumNodes() const { return nodeListSize; }
149
150 /// \brief Returns the number of edges in this graph.
151 unsigned getNumEdges() const { return edgeListSize; }
152
153 /// \brief Return the cost vector for the given node.
154 Vector& getNodeCosts(const NodeIterator &nodeItr) {
155 return getNodeEntry(nodeItr).getCosts();
156 }
157
158 /// \brief Return the cost vector for the give node.
159 const Vector& getNodeCosts(const ConstNodeIterator &nodeItr) const {
160 return getNodeEntry(nodeItr).getCosts();
161 }
162
163 /// \brief Return the degree of the given node.
164 unsigned getNodeDegree(const NodeIterator &nodeItr) const {
165 return getNodeEntry(nodeItr).getDegree();
166 }
167
168 /// \brief Assigns sequential IDs to the nodes, starting at 0, which
169 /// remain valid until the next addition or removal of a node.
170 void assignNodeIDs() {
171 unsigned curID = 0;
172 idToNodeMap.resize(getNumNodes());
173 for (NodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd();
174 nodeItr != nodeEnd; ++nodeItr, ++curID) {
175 getNodeEntry(nodeItr).setID(curID);
176 idToNodeMap[curID] = nodeItr;
177 }
178 nodeIDsValid = true;
179 }
180
181 /// \brief Assigns sequential IDs to the nodes using the ordering of the
182 /// given vector.
183 void assignNodeIDs(const std::vector<NodeIterator> &nodeOrdering) {
184 assert((getNumNodes() == nodeOrdering.size()) &&
185 "Wrong number of nodes in node ordering.");
186 idToNodeMap = nodeOrdering;
187 for (unsigned nodeID = 0; nodeID < idToNodeMap.size(); ++nodeID) {
188 getNodeEntry(idToNodeMap[nodeID]).setID(nodeID);
189 }
190 nodeIDsValid = true;
191 }
192
193 /// \brief Returns true if valid node IDs are assigned, false otherwise.
194 bool areNodeIDsValid() const { return nodeIDsValid; }
195
196 /// \brief Return the numeric ID of the given node.
197 ///
198 /// Calls to this method will result in an assertion failure if there have
199 /// been any node additions or removals since the last call to
200 /// assignNodeIDs().
201 unsigned getNodeID(const ConstNodeIterator &nodeItr) const {
202 assert(nodeIDsValid && "Attempt to retrieve invalid ID.");
203 return getNodeEntry(nodeItr).getID();
204 }
205
206 /// \brief Returns the iterator associated with the given node ID.
207 NodeIterator getNodeItr(unsigned nodeID) {
208 assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID.");
209 return idToNodeMap[nodeID];
210 }
211
212 /// \brief Returns the iterator associated with the given node ID.
213 ConstNodeIterator getNodeItr(unsigned nodeID) const {
214 assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID.");
215 return idToNodeMap[nodeID];
216 }
217
218 /// \brief Removes the given node (and all attached edges) from the graph.
219 void removeNode(const NodeIterator &nodeItr) {
220 assert(iteratorInRange(nodeItr, nodeList.begin(), nodeList.end()) &&
221 "Iterator does not belong to this graph!");
222
223 invalidateNodeIDs();
224
225 NodeEntry &nodeEntry = getNodeEntry(nodeItr);
226
227 // We need to copy this out because it will be destroyed as the edges are
228 // removed.
229 typedef std::vector<EdgeIterator> AdjEdgeList;
230 typedef typename AdjEdgeList::iterator AdjEdgeListItr;
231
232 AdjEdgeList adjEdges;
233 adjEdges.reserve(nodeEntry.getDegree());
234 std::copy(nodeEntry.adjEdgesBegin(), nodeEntry.adjEdgesEnd(),
235 std::back_inserter(adjEdges));
236
237 // Iterate over the copied out edges and remove them from the graph.
238 for (AdjEdgeListItr itr = adjEdges.begin(), end = adjEdges.end();
239 itr != end; ++itr) {
240 removeEdge(*itr);
241 }
242
243 // Erase the node from the nodelist.
244 nodeList.erase(nodeItr);
245 --nodeListSize;
246 }
247
248 NodeIterator nodesBegin() { return nodeList.begin(); }
249 ConstNodeIterator nodesBegin() const { return nodeList.begin(); }
250 NodeIterator nodesEnd() { return nodeList.end(); }
251 ConstNodeIterator nodesEnd() const { return nodeList.end(); }
252
253 AdjEdgeIterator adjEdgesBegin(const NodeIterator &nodeItr) {
254 return getNodeEntry(nodeItr).adjEdgesBegin();
255 }
256
257 ConstAdjEdgeIterator adjEdgesBegin(const ConstNodeIterator &nodeItr) const {
258 return getNodeEntry(nodeItr).adjEdgesBegin();
259 }
260
261 AdjEdgeIterator adjEdgesEnd(const NodeIterator &nodeItr) {
262 return getNodeEntry(nodeItr).adjEdgesEnd();
263 }
264
265 ConstAdjEdgeIterator adjEdgesEnd(const ConstNodeIterator &nodeItr) const {
266 getNodeEntry(nodeItr).adjEdgesEnd();
267 }
268
269 EdgeIterator findEdge(const NodeIterator &node1Itr,
270 const NodeIterator &node2Itr) {
271
272 for (AdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr),
273 adjEdgeEnd = adjEdgesEnd(node1Itr);
274 adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) {
275 if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) ||
276 (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) {
277 return *adjEdgeItr;
278 }
279 }
280
281 return edgeList.end();
282 }
283
284 ConstEdgeIterator findEdge(const ConstNodeIterator &node1Itr,
285 const ConstNodeIterator &node2Itr) const {
286
287 for (ConstAdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr),
288 adjEdgeEnd = adjEdgesEnd(node1Itr);
289 adjEdgeItr != adjEdgesEnd; ++adjEdgeItr) {
290 if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) ||
291 (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) {
292 return *adjEdgeItr;
293 }
294 }
295
296 return edgeList.end();
297 }
298
299 Matrix& getEdgeCosts(const EdgeIterator &edgeItr) {
300 return getEdgeEntry(edgeItr).getCosts();
301 }
302
303 const Matrix& getEdgeCosts(const ConstEdgeIterator &edgeItr) const {
304 return getEdgeEntry(edgeItr).getCosts();
305 }
306
307 NodeIterator getEdgeNode1Itr(const EdgeIterator &edgeItr) {
308 return getEdgeEntry(edgeItr).getNode1Itr();
309 }
310
311 ConstNodeIterator getEdgeNode1Itr(const ConstEdgeIterator &edgeItr) const {
312 return getEdgeEntry(edgeItr).getNode1Itr();
313 }
314
315 NodeIterator getEdgeNode2Itr(const EdgeIterator &edgeItr) {
316 return getEdgeEntry(edgeItr).getNode2Itr();
317 }
318
319 ConstNodeIterator getEdgeNode2Itr(const ConstEdgeIterator &edgeItr) const {
320 return getEdgeEntry(edgeItr).getNode2Itr();
321 }
322
323 NodeIterator getEdgeOtherNode(const EdgeIterator &edgeItr,
324 const NodeIterator &nodeItr) {
325
326 EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
327 if (nodeItr == edgeEntry.getNode1Itr()) {
328 return edgeEntry.getNode2Itr();
329 }
330 //else
331 return edgeEntry.getNode1Itr();
332 }
333
334 ConstNodeIterator getEdgeOtherNode(const ConstEdgeIterator &edgeItr,
335 const ConstNodeIterator &nodeItr) const {
336
337 const EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
338 if (nodeItr == edgeEntry.getNode1Itr()) {
339 return edgeEntry.getNode2Itr();
340 }
341 //else
342 return edgeEntry.getNode1Itr();
343 }
344
345 void removeEdge(const EdgeIterator &edgeItr) {
346 assert(iteratorInRange(edgeItr, edgeList.begin(), edgeList.end()) &&
347 "Iterator does not belong to this graph!");
348
349 --edgeListSize;
350
351 // Get the edge entry.
352 EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
353
354 // Get the nodes entry.
355 NodeEntry &node1Entry(getNodeEntry(edgeEntry.getNode1Itr())),
356 &node2Entry(getNodeEntry(edgeEntry.getNode2Itr()));
357
358 // Disconnect the edge from the nodes.
359 node1Entry.removeAdjEdge(edgeEntry.getNode1ThisEdgeItr());
360 node2Entry.removeAdjEdge(edgeEntry.getNode2ThisEdgeItr());
361
362 // Remove the edge from the graph.
363 edgeList.erase(edgeItr);
364 }
365
366 EdgeIterator edgesBegin() { return edgeList.begin(); }
367 ConstEdgeIterator edgesBegin() const { return edgeList.begin(); }
368 EdgeIterator edgesEnd() { return edgeList.end(); }
369 ConstEdgeIterator edgesEnd() const { return edgeList.end(); }
370
371 void clear() {
372 nodeList.clear();
373 nodeListSize = 0;
374 edgeList.clear();
375 edgeListSize = 0;
376 idToNodeMap.clear();
377 }
378
379 template <typename OStream>
380 void printDot(OStream &os) const {
381
382 assert(areNodeIDsValid() &&
383 "Cannot print a .dot of a graph unless IDs have been assigned.");
384
385 os << "graph {\n";
386
387 for (ConstNodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd();
388 nodeItr != nodeEnd; ++nodeItr) {
389
390 os << " node" << getNodeID(nodeItr) << " [ label=\""
391 << getNodeID(nodeItr) << ": " << getNodeCosts(nodeItr) << "\" ]\n";
392 }
393
394 os << " edge [ len=" << getNumNodes() << " ]\n";
395
396 for (ConstEdgeIterator edgeItr = edgesBegin(), edgeEnd = edgesEnd();
397 edgeItr != edgeEnd; ++edgeItr) {
398
399 os << " node" << getNodeID(getEdgeNode1Itr(edgeItr))
400 << " -- node" << getNodeID(getEdgeNode2Itr(edgeItr))
401 << " [ label=\"";
402
403 const Matrix &edgeCosts = getEdgeCosts(edgeItr);
404
405 for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
406 os << edgeCosts.getRowAsVector(i) << "\\n";
407 }
408
409 os << "\" ]\n";
410 }
411
412 os << "}\n";
413 }
414
415 template <typename OStream>
416 void printDot(OStream &os) {
417 if (!areNodeIDsValid()) {
418 assignNodeIDs();
419 }
420
421 const_cast<const ThisGraphT*>(this)->printDot(os);
422 }
423
424 template <typename OStream>
425 void dumpTo(OStream &os) const {
426 typedef ConstNodeIterator ConstNodeID;
427
428 assert(areNodeIDsValid() &&
429 "Cannot dump a graph unless IDs have been assigned.");
430
431 for (ConstNodeIterator nItr = nodesBegin(), nEnd = nodesEnd();
432 nItr != nEnd; ++nItr) {
433 os << getNodeID(nItr) << "\n";
434 }
435
436 unsigned edgeNumber = 1;
437 for (ConstEdgeIterator eItr = edgesBegin(), eEnd = edgesEnd();
438 eItr != eEnd; ++eItr) {
439
440 os << edgeNumber++ << ": { "
441 << getNodeID(getEdgeNode1Itr(eItr)) << ", "
442 << getNodeID(getEdgeNode2Itr(eItr)) << " }\n";
443 }
444
445 }
446
447 template <typename OStream>
448 void dumpTo(OStream &os) {
449 if (!areNodeIDsValid()) {
450 assignNodeIDs();
451 }
452
453 const_cast<const ThisGraphT*>(this)->dumpTo(os);
454 }
455
456};
457
458/// \brief Provides a base from which to derive nodes for GraphBase.
459template <typename NodeImpl, typename EdgeImpl>
460class NodeBase {
461private:
462
463 typedef GraphBase<NodeImpl, EdgeImpl> GraphBaseT;
464 typedef NodeBaseTraits<GraphBaseT> ThisNodeBaseTraits;
465
466public:
467 typedef typename GraphBaseT::EdgeIterator EdgeIterator;
468
469private:
470 typedef typename ThisNodeBaseTraits::AdjEdgeList AdjEdgeList;
471
472 unsigned degree, id;
473 Vector costs;
474 AdjEdgeList adjEdges;
475
476 void operator=(const NodeBase& other) {
477 assert(false && "Can't assign NodeEntrys.");
478 }
479
480public:
481
482 typedef typename ThisNodeBaseTraits::AdjEdgeIterator AdjEdgeIterator;
483 typedef typename ThisNodeBaseTraits::ConstAdjEdgeIterator
484 ConstAdjEdgeIterator;
485
486 NodeBase(const Vector &costs) : degree(0), costs(costs) {
487 assert((costs.getLength() > 0) && "Can't have zero-length cost vector.");
488 }
489
490 Vector& getCosts() { return costs; }
491 const Vector& getCosts() const { return costs; }
492
493 unsigned getDegree() const { return degree; }
494
495 void setID(unsigned id) { this->id = id; }
496 unsigned getID() const { return id; }
497
498 AdjEdgeIterator addAdjEdge(const EdgeIterator &edgeItr) {
499 ++degree;
500 return adjEdges.insert(adjEdges.end(), edgeItr);
501 }
502
503 void removeAdjEdge(const AdjEdgeIterator &adjEdgeItr) {
504 --degree;
505 adjEdges.erase(adjEdgeItr);
506 }
507
508 AdjEdgeIterator adjEdgesBegin() { return adjEdges.begin(); }
509 ConstAdjEdgeIterator adjEdgesBegin() const { return adjEdges.begin(); }
510 AdjEdgeIterator adjEdgesEnd() { return adjEdges.end(); }
511 ConstAdjEdgeIterator adjEdgesEnd() const { return adjEdges.end(); }
512
513};
514
515template <typename NodeImpl, typename EdgeImpl>
516class EdgeBase {
517public:
518 typedef typename GraphBase<NodeImpl, EdgeImpl>::NodeIterator NodeIterator;
519 typedef typename GraphBase<NodeImpl, EdgeImpl>::EdgeIterator EdgeIterator;
520
521 typedef typename NodeImpl::AdjEdgeIterator NodeAdjEdgeIterator;
522
523private:
524
525 NodeIterator node1Itr, node2Itr;
526 NodeAdjEdgeIterator node1ThisEdgeItr, node2ThisEdgeItr;
527 Matrix costs;
528
529 void operator=(const EdgeBase &other) {
530 assert(false && "Can't assign EdgeEntrys.");
531 }
532
533public:
534
535 EdgeBase(const NodeIterator &node1Itr, const NodeIterator &node2Itr,
536 const Matrix &costs) :
537 node1Itr(node1Itr), node2Itr(node2Itr), costs(costs) {
538
539 assert((costs.getRows() > 0) && (costs.getCols() > 0) &&
540 "Can't have zero-dimensioned cost matrices");
541 }
542
543 Matrix& getCosts() { return costs; }
544 const Matrix& getCosts() const { return costs; }
545
546 const NodeIterator& getNode1Itr() const { return node1Itr; }
547 const NodeIterator& getNode2Itr() const { return node2Itr; }
548
549 void setNode1ThisEdgeItr(const NodeAdjEdgeIterator &node1ThisEdgeItr) {
550 this->node1ThisEdgeItr = node1ThisEdgeItr;
551 }
552
553 const NodeAdjEdgeIterator& getNode1ThisEdgeItr() const {
554 return node1ThisEdgeItr;
555 }
556
557 void setNode2ThisEdgeItr(const NodeAdjEdgeIterator &node2ThisEdgeItr) {
558 this->node2ThisEdgeItr = node2ThisEdgeItr;
559 }
560
561 const NodeAdjEdgeIterator& getNode2ThisEdgeItr() const {
562 return node2ThisEdgeItr;
563 }
564
565};
566
567
568}
569
570#endif // LLVM_CODEGEN_PBQP_GRAPHBASE_HPP