llvm.org GIT mirror llvm / 6699fb2
New C++ PBQP solver. Currently about as fast (read _slow_) as the old C based solver, but I'll be working to improve that. The PBQP allocator has been updated to use the new solver. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78354 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 11 years ago
13 changed file(s) with 2855 addition(s) and 1790 deletion(s). Raw diff Collapse all Expand all
0 #ifndef LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H
1 #define LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H
2
3 #include "GraphBase.h"
4
5 namespace PBQP {
6
7
8 template class AnnotatedEdge;
9
10 template
11 class AnnotatedNode : public NodeBase,
12 AnnotatedEdge > {
13 private:
14
15 NodeData nodeData;
16
17 public:
18
19 AnnotatedNode(const Vector &costs, const NodeData &nodeData) :
20 NodeBase,
21 AnnotatedEdge >(costs),
22 nodeData(nodeData) {}
23
24 NodeData& getNodeData() { return nodeData; }
25 const NodeData& getNodeData() const { return nodeData; }
26
27 };
28
29 template
30 class AnnotatedEdge : public EdgeBase,
31 AnnotatedEdge > {
32 private:
33
34 typedef typename GraphBase,
35 AnnotatedEdge >::NodeIterator
36 NodeIterator;
37
38 EdgeData edgeData;
39
40 public:
41
42
43 AnnotatedEdge(const NodeIterator &node1Itr, const NodeIterator &node2Itr,
44 const Matrix &costs, const EdgeData &edgeData) :
45 EdgeBase,
46 AnnotatedEdge >(node1Itr, node2Itr, costs),
47 edgeData(edgeData) {}
48
49 EdgeData& getEdgeData() { return edgeData; }
50 const EdgeData& getEdgeData() const { return edgeData; }
51
52 };
53
54 template
55 class AnnotatedGraph : public GraphBase,
56 AnnotatedEdge > {
57 private:
58
59 typedef GraphBase,
60 AnnotatedEdge > PGraph;
61
62 typedef AnnotatedNode NodeEntry;
63 typedef AnnotatedEdge EdgeEntry;
64
65
66 void copyFrom(const AnnotatedGraph &other) {
67 if (!other.areNodeIDsValid()) {
68 other.assignNodeIDs();
69 }
70 std::vector newNodeItrs(other.getNumNodes());
71
72 for (ConstNodeIterator nItr = other.nodesBegin(), nEnd = other.nodesEnd();
73 nItr != nEnd; ++nItr) {
74 newNodeItrs[other.getNodeID(nItr)] = addNode(other.getNodeCosts(nItr));
75 }
76
77 for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd = other.edgesEnd();
78 eItr != eEnd; ++eItr) {
79
80 unsigned node1ID = other.getNodeID(other.getEdgeNode1(eItr)),
81 node2ID = other.getNodeID(other.getEdgeNode2(eItr));
82
83 addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID],
84 other.getEdgeCosts(eItr), other.getEdgeData(eItr));
85 }
86
87 }
88
89 public:
90
91 typedef typename PGraph::NodeIterator NodeIterator;
92 typedef typename PGraph::ConstNodeIterator ConstNodeIterator;
93 typedef typename PGraph::EdgeIterator EdgeIterator;
94 typedef typename PGraph::ConstEdgeIterator ConstEdgeIterator;
95
96 AnnotatedGraph() {}
97
98 AnnotatedGraph(const AnnotatedGraph &other) {
99 copyFrom(other);
100 }
101
102 AnnotatedGraph& operator=(const AnnotatedGraph &other) {
103 PGraph::clear();
104 copyFrom(other);
105 return *this;
106 }
107
108 NodeIterator addNode(const Vector &costs, const NodeData &data) {
109 return PGraph::addConstructedNode(NodeEntry(costs, data));
110 }
111
112 EdgeIterator addEdge(const NodeIterator &node1Itr,
113 const NodeIterator &node2Itr,
114 const Matrix &costs, const EdgeData &data) {
115 return PGraph::addConstructedEdge(EdgeEntry(node1Itr, node2Itr,
116 costs, data));
117 }
118
119 NodeData& getNodeData(const NodeIterator &nodeItr) {
120 return getNodeEntry(nodeItr).getNodeData();
121 }
122
123 const NodeData& getNodeData(const NodeIterator &nodeItr) const {
124 return getNodeEntry(nodeItr).getNodeData();
125 }
126
127 EdgeData& getEdgeData(const EdgeIterator &edgeItr) {
128 return getEdgeEntry(edgeItr).getEdgeData();
129 }
130
131 const EdgeEntry& getEdgeData(const EdgeIterator &edgeItr) const {
132 return getEdgeEntry(edgeItr).getEdgeData();
133 }
134
135 SimpleGraph toSimpleGraph() const {
136 SimpleGraph g;
137
138 if (!PGraph::areNodeIDsValid()) {
139 PGraph::assignNodeIDs();
140 }
141 std::vector newNodeItrs(PGraph::getNumNodes());
142
143 for (ConstNodeIterator nItr = PGraph::nodesBegin(),
144 nEnd = PGraph::nodesEnd();
145 nItr != nEnd; ++nItr) {
146
147 newNodeItrs[getNodeID(nItr)] = g.addNode(getNodeCosts(nItr));
148 }
149
150 for (ConstEdgeIterator
151 eItr = PGraph::edgesBegin(), eEnd = PGraph::edgesEnd();
152 eItr != eEnd; ++eItr) {
153
154 unsigned node1ID = getNodeID(getEdgeNode1(eItr)),
155 node2ID = getNodeID(getEdgeNode2(eItr));
156
157 g.addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID],
158 getEdgeCosts(eItr));
159 }
160
161 return g;
162 }
163
164 };
165
166
167 }
168
169 #endif // LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H
0 #ifndef LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H
1 #define LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H
2
3 #include "Solver.h"
4
5 namespace PBQP {
6
7 class ExhaustiveSolverImpl {
8 private:
9
10 const SimpleGraph &g;
11
12 PBQPNum getSolutionCost(const Solution &solution) const {
13 PBQPNum cost = 0.0;
14
15 for (SimpleGraph::ConstNodeIterator
16 nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd();
17 nodeItr != nodeEnd; ++nodeItr) {
18
19 unsigned nodeId = g.getNodeID(nodeItr);
20
21 cost += g.getNodeCosts(nodeItr)[solution.getSelection(nodeId)];
22 }
23
24 for (SimpleGraph::ConstEdgeIterator
25 edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd();
26 edgeItr != edgeEnd; ++edgeItr) {
27
28 SimpleGraph::ConstNodeIterator n1 = g.getEdgeNode1Itr(edgeItr),
29 n2 = g.getEdgeNode2Itr(edgeItr);
30 unsigned sol1 = solution.getSelection(g.getNodeID(n1)),
31 sol2 = solution.getSelection(g.getNodeID(n2));
32
33 cost += g.getEdgeCosts(edgeItr)[sol1][sol2];
34 }
35
36 return cost;
37 }
38
39 public:
40
41 ExhaustiveSolverImpl(const SimpleGraph &g) : g(g) {}
42
43 Solution solve() const {
44 Solution current(g.getNumNodes(), true), optimal(current);
45
46 PBQPNum bestCost = std::numeric_limits::infinity();
47 bool finished = false;
48
49 while (!finished) {
50 PBQPNum currentCost = getSolutionCost(current);
51
52 if (currentCost < bestCost) {
53 optimal = current;
54 bestCost = currentCost;
55 }
56
57 // assume we're done.
58 finished = true;
59
60 for (unsigned i = 0; i < g.getNumNodes(); ++i) {
61 if (current.getSelection(i) ==
62 (g.getNodeCosts(g.getNodeItr(i)).getLength() - 1)) {
63 current.setSelection(i, 0);
64 }
65 else {
66 current.setSelection(i, current.getSelection(i) + 1);
67 finished = false;
68 break;
69 }
70 }
71
72 }
73
74 optimal.setSolutionCost(bestCost);
75
76 return optimal;
77 }
78
79 };
80
81 class ExhaustiveSolver : public Solver {
82 public:
83 ~ExhaustiveSolver() {}
84 Solution solve(const SimpleGraph &g) const {
85 ExhaustiveSolverImpl solver(g);
86 return solver.solve();
87 }
88 };
89
90 }
91
92 #endif // LLVM_CODGEN_PBQP_EXHAUSTIVESOLVER_HPP
0 #ifndef LLVM_CODEGEN_PBQP_GRAPHBASE_H
1 #define LLVM_CODEGEN_PBQP_GRAPHBASE_H
2
3 #include "PBQPMath.h"
4
5 #include
6 #include
7
8 namespace PBQP {
9
10 // UGLY, but I'm not sure there's a good way around this: We need to be able to
11 // look up a Node's "adjacent edge list" structure type before the Node type is
12 // fully constructed. We can enable this by pushing the choice of data type
13 // out into this traits class.
14 template
15 class NodeBaseTraits {
16 public:
17 typedef std::list AdjEdgeList;
18 typedef typename AdjEdgeList::iterator AdjEdgeIterator;
19 typedef typename AdjEdgeList::const_iterator ConstAdjEdgeIterator;
20 };
21
22 /// \brief Base for concrete graph classes. Provides a basic set of graph
23 /// operations which are useful for PBQP solvers.
24 template
25 class GraphBase {
26 private:
27
28 typedef GraphBase ThisGraphT;
29
30 typedef std::list NodeList;
31 typedef std::list EdgeList;
32
33 NodeList nodeList;
34 unsigned nodeListSize;
35
36 EdgeList edgeList;
37 unsigned edgeListSize;
38
39 GraphBase(const ThisGraphT &other) { abort(); }
40 void operator=(const ThisGraphT &other) { abort(); }
41
42 public:
43
44 /// \brief Iterates over the nodes of a graph.
45 typedef typename NodeList::iterator NodeIterator;
46 /// \brief Iterates over the nodes of a const graph.
47 typedef typename NodeList::const_iterator ConstNodeIterator;
48 /// \brief Iterates over the edges of a graph.
49 typedef typename EdgeList::iterator EdgeIterator;
50 /// \brief Iterates over the edges of a const graph.
51 typedef typename EdgeList::const_iterator ConstEdgeIterator;
52
53 /// \brief Iterates over the edges attached to a node.
54 typedef typename NodeBaseTraits::AdjEdgeIterator
55 AdjEdgeIterator;
56
57 /// \brief Iterates over the edges attached to a node in a const graph.
58 typedef typename NodeBaseTraits::ConstAdjEdgeIterator
59 ConstAdjEdgeIterator;
60
61 private:
62
63 typedef std::vector IDToNodeMap;
64
65 IDToNodeMap idToNodeMap;
66 bool nodeIDsValid;
67
68 void invalidateNodeIDs() {
69 if (nodeIDsValid) {
70 idToNodeMap.clear();
71 nodeIDsValid = false;
72 }
73 }
74
75 template
76 bool iteratorInRange(ItrT itr, const ItrT &begin, const ItrT &end) {
77 for (ItrT t = begin; t != end; ++t) {
78 if (itr == t)
79 return true;
80 }
81
82 return false;
83 }
84
85 protected:
86
87 GraphBase() : nodeListSize(0), edgeListSize(0), nodeIDsValid(false) {}
88
89 NodeEntry& getNodeEntry(const NodeIterator &nodeItr) { return *nodeItr; }
90 const NodeEntry& getNodeEntry(const ConstNodeIterator &nodeItr) const {
91 return *nodeItr;
92 }
93
94 EdgeEntry& getEdgeEntry(const EdgeIterator &edgeItr) { return *edgeItr; }
95 const EdgeEntry& getEdgeEntry(const ConstEdgeIterator &edgeItr) const {
96 return *edgeItr;
97 }
98
99 NodeIterator addConstructedNode(const NodeEntry &nodeEntry) {
100 ++nodeListSize;
101
102 invalidateNodeIDs();
103
104 NodeIterator newNodeItr = nodeList.insert(nodeList.end(), nodeEntry);
105
106 return newNodeItr;
107 }
108
109 EdgeIterator addConstructedEdge(const EdgeEntry &edgeEntry) {
110
111 assert((findEdge(edgeEntry.getNode1Itr(), edgeEntry.getNode2Itr())
112 == edgeList.end()) && "Attempt to add duplicate edge.");
113
114 ++edgeListSize;
115
116 // Add the edge to the graph.
117 EdgeIterator edgeItr = edgeList.insert(edgeList.end(), edgeEntry);
118
119 // Get a reference to the version in the graph.
120 EdgeEntry &newEdgeEntry = getEdgeEntry(edgeItr);
121
122 // Node entries:
123 NodeEntry &node1Entry = getNodeEntry(newEdgeEntry.getNode1Itr()),
124 &node2Entry = getNodeEntry(newEdgeEntry.getNode2Itr());
125
126 unsigned n1Len = node1Entry.getCosts().getLength(),
127 n2Len = node2Entry.getCosts().getLength(),
128 mRows = newEdgeEntry.getCosts().getRows(),
129 mCols = newEdgeEntry.getCosts().getCols();
130
131 // Sanity check on matrix dimensions.
132 assert((n1Len == mRows) && (n2Len == mCols) &&
133 "Matrix dimensions do not match cost vector dimensions.");
134
135 // Create links between nodes and edges.
136 newEdgeEntry.setNode1ThisEdgeItr(
137 node1Entry.addAdjEdge(edgeItr));
138 newEdgeEntry.setNode2ThisEdgeItr(
139 node2Entry.addAdjEdge(edgeItr));
140
141 return edgeItr;
142 }
143
144 public:
145
146 /// \brief Returns the number of nodes in this graph.
147 unsigned getNumNodes() const { return nodeListSize; }
148
149 /// \brief Returns the number of edges in this graph.
150 unsigned getNumEdges() const { return edgeListSize; }
151
152 /// \brief Return the cost vector for the given node.
153 Vector& getNodeCosts(const NodeIterator &nodeItr) {
154 return getNodeEntry(nodeItr).getCosts();
155 }
156
157 /// \brief Return the cost vector for the give node.
158 const Vector& getNodeCosts(const ConstNodeIterator &nodeItr) const {
159 return getNodeEntry(nodeItr).getCosts();
160 }
161
162 /// \brief Return the degree of the given node.
163 unsigned getNodeDegree(const NodeIterator &nodeItr) const {
164 return getNodeEntry(nodeItr).getDegree();
165 }
166
167 /// \brief Assigns sequential IDs to the nodes, starting at 0, which
168 /// remain valid until the next addition or removal of a node.
169 void assignNodeIDs() {
170 unsigned curID = 0;
171 idToNodeMap.resize(getNumNodes());
172 for (NodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd();
173 nodeItr != nodeEnd; ++nodeItr, ++curID) {
174 getNodeEntry(nodeItr).setID(curID);
175 idToNodeMap[curID] = nodeItr;
176 }
177 nodeIDsValid = true;
178 }
179
180 /// \brief Assigns sequential IDs to the nodes using the ordering of the
181 /// given vector.
182 void assignNodeIDs(const std::vector &nodeOrdering) {
183 assert((getNumNodes() == nodeOrdering.size()) &&
184 "Wrong number of nodes in node ordering.");
185 idToNodeMap = nodeOrdering;
186 for (unsigned nodeID = 0; nodeID < idToNodeMap.size(); ++nodeID) {
187 getNodeEntry(idToNodeMap[nodeID]).setID(nodeID);
188 }
189 nodeIDsValid = true;
190 }
191
192 /// \brief Returns true if valid node IDs are assigned, false otherwise.
193 bool areNodeIDsValid() const { return nodeIDsValid; }
194
195 /// \brief Return the numeric ID of the given node.
196 ///
197 /// Calls to this method will result in an assertion failure if there have
198 /// been any node additions or removals since the last call to
199 /// assignNodeIDs().
200 unsigned getNodeID(const ConstNodeIterator &nodeItr) const {
201 assert(nodeIDsValid && "Attempt to retrieve invalid ID.");
202 return getNodeEntry(nodeItr).getID();
203 }
204
205 /// \brief Returns the iterator associated with the given node ID.
206 NodeIterator getNodeItr(unsigned nodeID) {
207 assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID.");
208 return idToNodeMap[nodeID];
209 }
210
211 /// \brief Returns the iterator associated with the given node ID.
212 ConstNodeIterator getNodeItr(unsigned nodeID) const {
213 assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID.");
214 return idToNodeMap[nodeID];
215 }
216
217 /// \brief Removes the given node (and all attached edges) from the graph.
218 void removeNode(const NodeIterator &nodeItr) {
219 assert(iteratorInRange(nodeItr, nodeList.begin(), nodeList.end()) &&
220 "Iterator does not belong to this graph!");
221
222 invalidateNodeIDs();
223
224 NodeEntry &nodeEntry = getNodeEntry(nodeItr);
225
226 // We need to copy this out because it will be destroyed as the edges are
227 // removed.
228 typedef std::vector AdjEdgeList;
229 typedef typename AdjEdgeList::iterator AdjEdgeListItr;
230
231 AdjEdgeList adjEdges;
232 adjEdges.reserve(nodeEntry.getDegree());
233 std::copy(nodeEntry.adjEdgesBegin(), nodeEntry.adjEdgesEnd(),
234 std::back_inserter(adjEdges));
235
236 // Iterate over the copied out edges and remove them from the graph.
237 for (AdjEdgeListItr itr = adjEdges.begin(), end = adjEdges.end();
238 itr != end; ++itr) {
239 removeEdge(*itr);
240 }
241
242 // Erase the node from the nodelist.
243 nodeList.erase(nodeItr);
244 --nodeListSize;
245 }
246
247 NodeIterator nodesBegin() { return nodeList.begin(); }
248 ConstNodeIterator nodesBegin() const { return nodeList.begin(); }
249 NodeIterator nodesEnd() { return nodeList.end(); }
250 ConstNodeIterator nodesEnd() const { return nodeList.end(); }
251
252 AdjEdgeIterator adjEdgesBegin(const NodeIterator &nodeItr) {
253 return getNodeEntry(nodeItr).adjEdgesBegin();
254 }
255
256 ConstAdjEdgeIterator adjEdgesBegin(const ConstNodeIterator &nodeItr) const {
257 return getNodeEntry(nodeItr).adjEdgesBegin();
258 }
259
260 AdjEdgeIterator adjEdgesEnd(const NodeIterator &nodeItr) {
261 return getNodeEntry(nodeItr).adjEdgesEnd();
262 }
263
264 ConstAdjEdgeIterator adjEdgesEnd(const ConstNodeIterator &nodeItr) const {
265 getNodeEntry(nodeItr).adjEdgesEnd();
266 }
267
268 EdgeIterator findEdge(const NodeIterator &node1Itr,
269 const NodeIterator &node2Itr) {
270
271 for (AdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr),
272 adjEdgeEnd = adjEdgesEnd(node1Itr);
273 adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) {
274 if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) ||
275 (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) {
276 return *adjEdgeItr;
277 }
278 }
279
280 return edgeList.end();
281 }
282
283 ConstEdgeIterator findEdge(const ConstNodeIterator &node1Itr,
284 const ConstNodeIterator &node2Itr) const {
285
286 for (ConstAdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr),
287 adjEdgeEnd = adjEdgesEnd(node1Itr);
288 adjEdgeItr != adjEdgesEnd; ++adjEdgeItr) {
289 if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) ||
290 (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) {
291 return *adjEdgeItr;
292 }
293 }
294
295 return edgeList.end();
296 }
297
298 Matrix& getEdgeCosts(const EdgeIterator &edgeItr) {
299 return getEdgeEntry(edgeItr).getCosts();
300 }
301
302 const Matrix& getEdgeCosts(const ConstEdgeIterator &edgeItr) const {
303 return getEdgeEntry(edgeItr).getCosts();
304 }
305
306 NodeIterator getEdgeNode1Itr(const EdgeIterator &edgeItr) {
307 return getEdgeEntry(edgeItr).getNode1Itr();
308 }
309
310 ConstNodeIterator getEdgeNode1Itr(const ConstEdgeIterator &edgeItr) const {
311 return getEdgeEntry(edgeItr).getNode1Itr();
312 }
313
314 NodeIterator getEdgeNode2Itr(const EdgeIterator &edgeItr) {
315 return getEdgeEntry(edgeItr).getNode2Itr();
316 }
317
318 ConstNodeIterator getEdgeNode2Itr(const ConstEdgeIterator &edgeItr) const {
319 return getEdgeEntry(edgeItr).getNode2Itr();
320 }
321
322 NodeIterator getEdgeOtherNode(const EdgeIterator &edgeItr,
323 const NodeIterator &nodeItr) {
324
325 EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
326 if (nodeItr == edgeEntry.getNode1Itr()) {
327 return edgeEntry.getNode2Itr();
328 }
329 //else
330 return edgeEntry.getNode1Itr();
331 }
332
333 ConstNodeIterator getEdgeOtherNode(const ConstEdgeIterator &edgeItr,
334 const ConstNodeIterator &nodeItr) const {
335
336 const EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
337 if (nodeItr == edgeEntry.getNode1Itr()) {
338 return edgeEntry.getNode2Itr();
339 }
340 //else
341 return edgeEntry.getNode1Itr();
342 }
343
344 void removeEdge(const EdgeIterator &edgeItr) {
345 assert(iteratorInRange(edgeItr, edgeList.begin(), edgeList.end()) &&
346 "Iterator does not belong to this graph!");
347
348 --edgeListSize;
349
350 // Get the edge entry.
351 EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
352
353 // Get the nodes entry.
354 NodeEntry &node1Entry(getNodeEntry(edgeEntry.getNode1Itr())),
355 &node2Entry(getNodeEntry(edgeEntry.getNode2Itr()));
356
357 // Disconnect the edge from the nodes.
358 node1Entry.removeAdjEdge(edgeEntry.getNode1ThisEdgeItr());
359 node2Entry.removeAdjEdge(edgeEntry.getNode2ThisEdgeItr());
360
361 // Remove the edge from the graph.
362 edgeList.erase(edgeItr);
363 }
364
365 EdgeIterator edgesBegin() { return edgeList.begin(); }
366 ConstEdgeIterator edgesBegin() const { return edgeList.begin(); }
367 EdgeIterator edgesEnd() { return edgeList.end(); }
368 ConstEdgeIterator edgesEnd() const { return edgeList.end(); }
369
370 void clear() {
371 nodeList.clear();
372 nodeListSize = 0;
373 edgeList.clear();
374 edgeListSize = 0;
375 idToNodeMap.clear();
376 }
377
378 template
379 void printDot(OStream &os) const {
380
381 assert(areNodeIDsValid() &&
382 "Cannot print a .dot of a graph unless IDs have been assigned.");
383
384 os << "graph {\n";
385
386 for (ConstNodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd();
387 nodeItr != nodeEnd; ++nodeItr) {
388
389 os << " node" << getNodeID(nodeItr) << " [ label=\""
390 << getNodeID(nodeItr) << ": " << getNodeCosts(nodeItr) << "\" ]\n";
391 }
392
393 os << " edge [ len=" << getNumNodes() << " ]\n";
394
395 for (ConstEdgeIterator edgeItr = edgesBegin(), edgeEnd = edgesEnd();
396 edgeItr != edgeEnd; ++edgeItr) {
397
398 os << " node" << getNodeID(getEdgeNode1Itr(edgeItr))
399 << " -- node" << getNodeID(getEdgeNode2Itr(edgeItr))
400 << " [ label=\"";
401
402 const Matrix &edgeCosts = getEdgeCosts(edgeItr);
403
404 for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
405 os << edgeCosts.getRowAsVector(i) << "\\n";
406 }
407
408 os << "\" ]\n";
409 }
410
411 os << "}\n";
412 }
413
414 template
415 void printDot(OStream &os) {
416 if (!areNodeIDsValid()) {
417 assignNodeIDs();
418 }
419
420 const_cast(this)->printDot(os);
421 }
422
423 template
424 void dumpTo(OStream &os) const {
425 typedef ConstNodeIterator ConstNodeID;
426
427 assert(areNodeIDsValid() &&
428 "Cannot dump a graph unless IDs have been assigned.");
429
430 for (ConstNodeIterator nItr = nodesBegin(), nEnd = nodesEnd();
431 nItr != nEnd; ++nItr) {
432 os << getNodeID(nItr) << "\n";
433 }
434
435 unsigned edgeNumber = 1;
436 for (ConstEdgeIterator eItr = edgesBegin(), eEnd = edgesEnd();
437 eItr != eEnd; ++eItr) {
438
439 os << edgeNumber++ << ": { "
440 << getNodeID(getEdgeNode1Itr(eItr)) << ", "
441 << getNodeID(getEdgeNode2Itr(eItr)) << " }\n";
442 }
443
444 }
445
446 template
447 void dumpTo(OStream &os) {
448 if (!areNodeIDsValid()) {
449 assignNodeIDs();
450 }
451
452 const_cast(this)->dumpTo(os);
453 }
454
455 };
456
457 /// \brief Provides a base from which to derive nodes for GraphBase.
458 template
459 class NodeBase {
460 private:
461
462 typedef GraphBase GraphBaseT;
463 typedef NodeBaseTraits ThisNodeBaseTraits;
464
465 public:
466 typedef typename GraphBaseT::EdgeIterator EdgeIterator;
467
468 private:
469 typedef typename ThisNodeBaseTraits::AdjEdgeList AdjEdgeList;
470
471 unsigned degree, id;
472 Vector costs;
473 AdjEdgeList adjEdges;
474
475 void operator=(const NodeBase& other) {
476 assert(false && "Can't assign NodeEntrys.");
477 }
478
479 public:
480
481 typedef typename ThisNodeBaseTraits::AdjEdgeIterator AdjEdgeIterator;
482 typedef typename ThisNodeBaseTraits::ConstAdjEdgeIterator
483 ConstAdjEdgeIterator;
484
485 NodeBase(const Vector &costs) : degree(0), costs(costs) {
486 assert((costs.getLength() > 0) && "Can't have zero-length cost vector.");
487 }
488
489 Vector& getCosts() { return costs; }
490 const Vector& getCosts() const { return costs; }
491
492 unsigned getDegree() const { return degree; }
493
494 void setID(unsigned id) { this->id = id; }
495 unsigned getID() const { return id; }
496
497 AdjEdgeIterator addAdjEdge(const EdgeIterator &edgeItr) {
498 ++degree;
499 return adjEdges.insert(adjEdges.end(), edgeItr);
500 }
501
502 void removeAdjEdge(const AdjEdgeIterator &adjEdgeItr) {
503 --degree;
504 adjEdges.erase(adjEdgeItr);
505 }
506
507 AdjEdgeIterator adjEdgesBegin() { return adjEdges.begin(); }
508 ConstAdjEdgeIterator adjEdgesBegin() const { return adjEdges.begin(); }
509 AdjEdgeIterator adjEdgesEnd() { return adjEdges.end(); }
510 ConstAdjEdgeIterator adjEdgesEnd() const { return adjEdges.end(); }
511
512 };
513
514 template
515 class EdgeBase {
516 public:
517 typedef typename GraphBase::NodeIterator NodeIterator;
518 typedef typename GraphBase::EdgeIterator EdgeIterator;
519
520 typedef typename NodeImpl::AdjEdgeIterator NodeAdjEdgeIterator;
521
522 private:
523
524 NodeIterator node1Itr, node2Itr;
525 NodeAdjEdgeIterator node1ThisEdgeItr, node2ThisEdgeItr;
526 Matrix costs;
527
528 void operator=(const EdgeBase &other) {
529 assert(false && "Can't assign EdgeEntrys.");
530 }
531
532 public:
533
534 EdgeBase(const NodeIterator &node1Itr, const NodeIterator &node2Itr,
535 const Matrix &costs) :
536 node1Itr(node1Itr), node2Itr(node2Itr), costs(costs) {
537
538 assert((costs.getRows() > 0) && (costs.getCols() > 0) &&
539 "Can't have zero-dimensioned cost matrices");
540 }
541
542 Matrix& getCosts() { return costs; }
543 const Matrix& getCosts() const { return costs; }
544
545 const NodeIterator& getNode1Itr() const { return node1Itr; }
546 const NodeIterator& getNode2Itr() const { return node2Itr; }
547
548 void setNode1ThisEdgeItr(const NodeAdjEdgeIterator &node1ThisEdgeItr) {
549 this->node1ThisEdgeItr = node1ThisEdgeItr;
550 }
551
552 const NodeAdjEdgeIterator& getNode1ThisEdgeItr() const {
553 return node1ThisEdgeItr;
554 }
555
556 void setNode2ThisEdgeItr(const NodeAdjEdgeIterator &node2ThisEdgeItr) {
557 this->node2ThisEdgeItr = node2ThisEdgeItr;
558 }
559
560 const NodeAdjEdgeIterator& getNode2ThisEdgeItr() const {
561 return node2ThisEdgeItr;
562 }
563
564 };
565
566
567 }
568
569 #endif // LLVM_CODEGEN_PBQP_GRAPHBASE_HPP
0 #ifndef LLVM_CODEGEN_PBQP_GRAPHGENERATOR_H
1 #define LLVM_CODEGEN_PBQP_GRAPHGENERATOR_H
2
3 #include "PBQPMath.h"
4
5 namespace PBQP {
6
7 unsigned randRange(unsigned min, unsigned max) {
8 return min + (rand() % (max - min + 1));
9 }
10
11 class BasicNodeCostsGenerator {
12 private:
13
14 unsigned maxDegree, minCost, maxCost;
15
16
17 public:
18
19 BasicNodeCostsGenerator(unsigned maxDegree, unsigned minCost,
20 unsigned maxCost) :
21 maxDegree(maxDegree), minCost(minCost), maxCost(maxCost) { }
22
23 Vector operator()() const {
24 Vector v(randRange(1, maxDegree));
25 for (unsigned i = 0; i < v.getLength(); ++i) {
26 v[i] = randRange(minCost, maxCost);
27 }
28 return v;
29 };
30
31 };
32
33 class FixedDegreeSpillCostGenerator {
34 private:
35
36 unsigned degree, spillCostMin, spillCostMax;
37
38 public:
39
40 FixedDegreeSpillCostGenerator(unsigned degree, unsigned spillCostMin,
41 unsigned spillCostMax) :
42 degree(degree), spillCostMin(spillCostMin), spillCostMax(spillCostMax) { }
43
44 Vector operator()() const {
45 Vector v(degree, 0);
46 v[0] = randRange(spillCostMin, spillCostMax);
47 return v;
48 }
49
50 };
51
52 class BasicEdgeCostsGenerator {
53 private:
54
55 unsigned minCost, maxCost;
56
57 public:
58
59 BasicEdgeCostsGenerator(unsigned minCost, unsigned maxCost) :
60 minCost(minCost), maxCost(maxCost) {}
61
62 Matrix operator()(const SimpleGraph &g,
63 const SimpleGraph::ConstNodeIterator &n1,
64 const SimpleGraph::ConstNodeIterator &n2) const {
65
66 Matrix m(g.getNodeCosts(n1).getLength(),
67 g.getNodeCosts(n2).getLength());
68
69 for (unsigned i = 0; i < m.getRows(); ++i) {
70 for (unsigned j = 0; j < m.getCols(); ++j) {
71 m[i][j] = randRange(minCost, maxCost);
72 }
73 }
74
75 return m;
76 }
77
78 };
79
80 class InterferenceCostsGenerator {
81 public:
82
83 Matrix operator()(const SimpleGraph &g,
84 const SimpleGraph::ConstNodeIterator &n1,
85 const SimpleGraph::ConstNodeIterator &n2) const {
86
87 unsigned len = g.getNodeCosts(n1).getLength();
88
89 assert(len == g.getNodeCosts(n2).getLength());
90
91 Matrix m(len, len);
92
93 m[0][0] = 0;
94 for (unsigned i = 1; i < len; ++i) {
95 m[i][i] = std::numeric_limits::infinity();
96 }
97
98 return m;
99 }
100 };
101
102 class RingEdgeGenerator {
103 public:
104
105 template
106 void operator()(SimpleGraph &g, EdgeCostsGenerator &edgeCostsGen) {
107
108 assert(g.areNodeIDsValid() && "Graph must have valid node IDs.");
109
110 if (g.getNumNodes() < 2)
111 return;
112
113 if (g.getNumNodes() == 2) {
114 SimpleGraph::NodeIterator n1 = g.getNodeItr(0),
115 n2 = g.getNodeItr(1);
116 g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
117 return;
118 }
119
120 // Else |V| > 2:
121 for (unsigned i = 0; i < g.getNumNodes(); ++i) {
122 SimpleGraph::NodeIterator
123 n1 = g.getNodeItr(i),
124 n2 = g.getNodeItr((i + 1) % g.getNumNodes());
125 g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
126 }
127 }
128
129 };
130
131 class FullyConnectedEdgeGenerator {
132 public:
133
134 template
135 void operator()(SimpleGraph &g, EdgeCostsGenerator &edgeCostsGen) {
136 assert(g.areNodeIDsValid() && "Graph must have valid node IDs.");
137
138 for (unsigned i = 0; i < g.getNumNodes(); ++i) {
139 for (unsigned j = i + 1; j < g.getNumNodes(); ++j) {
140 SimpleGraph::NodeIterator
141 n1 = g.getNodeItr(i),
142 n2 = g.getNodeItr(j);
143 g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
144 }
145 }
146 }
147
148 };
149
150 class RandomEdgeGenerator {
151 public:
152
153 template
154 void operator()(SimpleGraph &g, EdgeCostsGenerator &edgeCostsGen) {
155
156 assert(g.areNodeIDsValid() && "Graph must have valid node IDs.");
157
158 for (unsigned i = 0; i < g.getNumNodes(); ++i) {
159 for (unsigned j = i + 1; j < g.getNumNodes(); ++j) {
160 if (rand() % 2 == 0) {
161 SimpleGraph::NodeIterator
162 n1 = g.getNodeItr(i),
163 n2 = g.getNodeItr(j);
164 g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
165 }
166 }
167 }
168 }
169
170 };
171
172 template
173 typename EdgesGenerator,
174 typename EdgeCostsGenerator>
175 SimpleGraph createRandomGraph(unsigned numNodes,
176 NodeCostsGenerator nodeCostsGen,
177 EdgesGenerator edgeGen,
178 EdgeCostsGenerator edgeCostsGen) {
179
180 SimpleGraph g;
181 for (unsigned n = 0; n < numNodes; ++n) {
182 g.addNode(nodeCostsGen());
183 }
184
185 g.assignNodeIDs();
186
187 edgeGen(g, edgeCostsGen);
188
189 return g;
190 }
191
192 }
193
194 #endif // LLVM_CODEGEN_PBQP_GRAPHGENERATOR_H
0 #ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
1 #define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
2
3 #include "Solver.h"
4 #include "AnnotatedGraph.h"
5
6 #include
7 #include
8
9 namespace PBQP {
10
11 /// \brief Important types for the HeuristicSolverImpl.
12 ///
13 /// Declared seperately to allow access to heuristic classes before the solver
14 /// is fully constructed.
15 template
16 class HSITypes {
17 public:
18
19 class NodeData;
20 class EdgeData;
21
22 typedef AnnotatedGraph SolverGraph;
23 typedef typename SolverGraph::NodeIterator GraphNodeIterator;
24 typedef typename SolverGraph::EdgeIterator GraphEdgeIterator;
25 typedef typename SolverGraph::AdjEdgeIterator GraphAdjEdgeIterator;
26
27 typedef std::list NodeList;
28 typedef typename NodeList::iterator NodeListIterator;
29
30 typedef std::vector NodeStack;
31 typedef typename NodeStack::iterator NodeStackIterator;
32
33 class NodeData {
34 friend class EdgeData;
35
36 private:
37
38 typedef std::list LinksList;
39
40 unsigned numLinks;
41 LinksList links, solvedLinks;
42 NodeListIterator bucketItr;
43 HeuristicNodeData heuristicData;
44
45 public:
46
47 typedef typename LinksList::iterator AdjLinkIterator;
48
49 private:
50
51 AdjLinkIterator addLink(const GraphEdgeIterator &edgeItr) {
52 ++numLinks;
53 return links.insert(links.end(), edgeItr);
54 }
55
56 void delLink(const AdjLinkIterator &adjLinkItr) {
57 --numLinks;
58 links.erase(adjLinkItr);
59 }
60
61 public:
62
63 NodeData() : numLinks(0) {}
64
65 unsigned getLinkDegree() const { return numLinks; }
66
67 HeuristicNodeData& getHeuristicData() { return heuristicData; }
68 const HeuristicNodeData& getHeuristicData() const {
69 return heuristicData;
70 }
71
72 void setBucketItr(const NodeListIterator &bucketItr) {
73 this->bucketItr = bucketItr;
74 }
75
76 const NodeListIterator& getBucketItr() const {
77 return bucketItr;
78 }
79
80 AdjLinkIterator adjLinksBegin() {
81 return links.begin();
82 }
83
84 AdjLinkIterator adjLinksEnd() {
85 return links.end();
86 }
87
88 void addSolvedLink(const GraphEdgeIterator &solvedLinkItr) {
89 solvedLinks.push_back(solvedLinkItr);
90 }
91
92 AdjLinkIterator solvedLinksBegin() {
93 return solvedLinks.begin();
94 }
95
96 AdjLinkIterator solvedLinksEnd() {
97 return solvedLinks.end();
98 }
99
100 };
101
102 class EdgeData {
103 private:
104
105 SolverGraph &g;
106 GraphNodeIterator node1Itr, node2Itr;
107 HeuristicEdgeData heuristicData;
108 typename NodeData::AdjLinkIterator node1ThisEdgeItr, node2ThisEdgeItr;
109
110 public:
111
112 EdgeData(SolverGraph &g) : g(g) {}
113
114 HeuristicEdgeData& getHeuristicData() { return heuristicData; }
115 const HeuristicEdgeData& getHeuristicData() const {
116 return heuristicData;
117 }
118
119 void setup(const GraphEdgeIterator &thisEdgeItr) {
120 node1Itr = g.getEdgeNode1Itr(thisEdgeItr);
121 node2Itr = g.getEdgeNode2Itr(thisEdgeItr);
122
123 node1ThisEdgeItr = g.getNodeData(node1Itr).addLink(thisEdgeItr);
124 node2ThisEdgeItr = g.getNodeData(node2Itr).addLink(thisEdgeItr);
125 }
126
127 void unlink() {
128 g.getNodeData(node1Itr).delLink(node1ThisEdgeItr);
129 g.getNodeData(node2Itr).delLink(node2ThisEdgeItr);
130 }
131
132 };
133
134 };
135
136 template
137 class HeuristicSolverImpl {
138 public:
139 // Typedefs to make life easier:
140 typedef HSITypes
141 typename Heuristic::EdgeData> HSIT;
142 typedef typename HSIT::SolverGraph SolverGraph;
143 typedef typename HSIT::NodeData NodeData;
144 typedef typename HSIT::EdgeData EdgeData;
145 typedef typename HSIT::GraphNodeIterator GraphNodeIterator;
146 typedef typename HSIT::GraphEdgeIterator GraphEdgeIterator;
147 typedef typename HSIT::GraphAdjEdgeIterator GraphAdjEdgeIterator;
148
149 typedef typename HSIT::NodeList NodeList;
150 typedef typename HSIT::NodeListIterator NodeListIterator;
151
152 typedef std::vector NodeStack;
153 typedef typename NodeStack::iterator NodeStackIterator;
154
155 /*!
156 * \brief Constructor, which performs all the actual solver work.
157 */
158 HeuristicSolverImpl(const SimpleGraph &orig) :
159 solution(orig.getNumNodes(), true)
160 {
161 copyGraph(orig);
162 simplify();
163 setup();
164 computeSolution();
165 computeSolutionCost(orig);
166 }
167
168 /*!
169 * \brief Returns the graph for this solver.
170 */
171 SolverGraph& getGraph() { return g; }
172
173 /*!
174 * \brief Return the solution found by this solver.
175 */
176 const Solution& getSolution() const { return solution; }
177
178 private:
179
180 /*!
181 * \brief Add the given node to the appropriate bucket for its link
182 * degree.
183 */
184 void addToBucket(const GraphNodeIterator &nodeItr) {
185 NodeData &nodeData = g.getNodeData(nodeItr);
186
187 switch (nodeData.getLinkDegree()) {
188 case 0: nodeData.setBucketItr(
189 r0Bucket.insert(r0Bucket.end(), nodeItr));
190 break;
191 case 1: nodeData.setBucketItr(
192 r1Bucket.insert(r1Bucket.end(), nodeItr));
193 break;
194 case 2: nodeData.setBucketItr(
195 r2Bucket.insert(r2Bucket.end(), nodeItr));
196 break;
197 default: heuristic.addToRNBucket(nodeItr);
198 break;
199 }
200 }
201
202 /*!
203 * \brief Remove the given node from the appropriate bucket for its link
204 * degree.
205 */
206 void removeFromBucket(const GraphNodeIterator &nodeItr) {
207 NodeData &nodeData = g.getNodeData(nodeItr);
208
209 switch (nodeData.getLinkDegree()) {
210 case 0: r0Bucket.erase(nodeData.getBucketItr()); break;
211 case 1: r1Bucket.erase(nodeData.getBucketItr()); break;
212 case 2: r2Bucket.erase(nodeData.getBucketItr()); break;
213 default: heuristic.removeFromRNBucket(nodeItr); break;
214 }
215 }
216
217 public:
218
219 /*!
220 * \brief Add a link.
221 */
222 void addLink(const GraphEdgeIterator &edgeItr) {
223 g.getEdgeData(edgeItr).setup(edgeItr);
224
225 if ((g.getNodeData(g.getEdgeNode1Itr(edgeItr)).getLinkDegree() > 2) ||
226 (g.getNodeData(g.getEdgeNode2Itr(edgeItr)).getLinkDegree() > 2)) {
227 heuristic.handleAddLink(edgeItr);
228 }
229 }
230
231 /*!
232 * \brief Remove link, update info for node.
233 *
234 * Only updates information for the given node, since usually the other
235 * is about to be removed.
236 */
237 void removeLink(const GraphEdgeIterator &edgeItr,
238 const GraphNodeIterator &nodeItr) {
239
240 if (g.getNodeData(nodeItr).getLinkDegree() > 2) {
241 heuristic.handleRemoveLink(edgeItr, nodeItr);
242 }
243 g.getEdgeData(edgeItr).unlink();
244 }
245
246 /*!
247 * \brief Remove link, update info for both nodes. Useful for R2 only.
248 */
249 void removeLinkR2(const GraphEdgeIterator &edgeItr) {
250 GraphNodeIterator node1Itr = g.getEdgeNode1Itr(edgeItr);
251
252 if (g.getNodeData(node1Itr).getLinkDegree() > 2) {
253 heuristic.handleRemoveLink(edgeItr, node1Itr);
254 }
255 removeLink(edgeItr, g.getEdgeNode2Itr(edgeItr));
256 }
257
258 /*!
259 * \brief Removes all links connected to the given node.
260 */
261 void unlinkNode(const GraphNodeIterator &nodeItr) {
262 NodeData &nodeData = g.getNodeData(nodeItr);
263
264 typedef std::vector TempEdgeList;
265
266 TempEdgeList edgesToUnlink;
267 edgesToUnlink.reserve(nodeData.getLinkDegree());
268
269 // Copy adj edges into a temp vector. We want to destroy them during
270 // the unlink, and we can't do that while we're iterating over them.
271 std::copy(nodeData.adjLinksBegin(), nodeData.adjLinksEnd(),
272 std::back_inserter(edgesToUnlink));
273
274 for (typename TempEdgeList::iterator
275 edgeItr = edgesToUnlink.begin(), edgeEnd = edgesToUnlink.end();
276 edgeItr != edgeEnd; ++edgeItr) {
277
278 GraphNodeIterator otherNode = g.getEdgeOtherNode(*edgeItr, nodeItr);
279
280 removeFromBucket(otherNode);
281 removeLink(*edgeItr, otherNode);
282 addToBucket(otherNode);
283 }
284 }
285
286 /*!
287 * \brief Push the given node onto the stack to be solved with
288 * backpropagation.
289 */
290 void pushStack(const GraphNodeIterator &nodeItr) {
291 stack.push_back(nodeItr);
292 }
293
294 /*!
295 * \brief Set the solution of the given node.
296 */
297 void setSolution(const GraphNodeIterator &nodeItr, unsigned solIndex) {
298 solution.setSelection(g.getNodeID(nodeItr), solIndex);
299
300 for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin(nodeItr),
301 adjEdgeEnd = g.adjEdgesEnd(nodeItr);
302 adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) {
303 GraphEdgeIterator edgeItr(*adjEdgeItr);
304 GraphNodeIterator adjNodeItr(g.getEdgeOtherNode(edgeItr, nodeItr));
305 g.getNodeData(adjNodeItr).addSolvedLink(edgeItr);
306 }
307 }
308
309 private:
310
311 SolverGraph g;
312 Heuristic heuristic;
313 Solution solution;
314
315 NodeList r0Bucket,
316 r1Bucket,
317 r2Bucket;
318
319 NodeStack stack;
320
321 // Copy the SimpleGraph into an annotated graph which we can use for reduction.
322 void copyGraph(const SimpleGraph &orig) {
323
324 assert((g.getNumEdges() == 0) && (g.getNumNodes() == 0) &&
325 "Graph should be empty prior to solver setup.");
326
327 assert(orig.areNodeIDsValid() &&
328 "Cannot copy from a graph with invalid node IDs.");
329
330 std::vector newNodeItrs;
331
332 for (unsigned nodeID = 0; nodeID < orig.getNumNodes(); ++nodeID) {
333 newNodeItrs.push_back(
334 g.addNode(orig.getNodeCosts(orig.getNodeItr(nodeID)), NodeData()));
335 }
336
337 for (SimpleGraph::ConstEdgeIterator
338 origEdgeItr = orig.edgesBegin(), origEdgeEnd = orig.edgesEnd();
339 origEdgeItr != origEdgeEnd; ++origEdgeItr) {
340
341 unsigned id1 = orig.getNodeID(orig.getEdgeNode1Itr(origEdgeItr)),
342 id2 = orig.getNodeID(orig.getEdgeNode2Itr(origEdgeItr));
343
344 g.addEdge(newNodeItrs[id1], newNodeItrs[id2],
345 orig.getEdgeCosts(origEdgeItr), EdgeData(g));
346 }
347
348 // Assign IDs to the new nodes using the ordering from the old graph,
349 // this will lead to nodes in the new graph getting the same ID as the
350 // corresponding node in the old graph.
351 g.assignNodeIDs(newNodeItrs);
352 }
353
354 // Simplify the annotated graph by eliminating independent edges and trivial
355 // nodes.
356 void simplify() {
357 disconnectTrivialNodes();
358 eliminateIndependentEdges();
359 }
360
361 // Eliminate trivial nodes.
362 void disconnectTrivialNodes() {
363 for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd();
364 nodeItr != nodeEnd; ++nodeItr) {
365
366 if (g.getNodeCosts(nodeItr).getLength() == 1) {
367
368 std::vector edgesToRemove;
369
370 for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin(nodeItr),
371 adjEdgeEnd = g.adjEdgesEnd(nodeItr);
372 adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) {
373
374 GraphEdgeIterator edgeItr = *adjEdgeItr;
375
376 if (g.getEdgeNode1Itr(edgeItr) == nodeItr) {
377 GraphNodeIterator otherNodeItr = g.getEdgeNode2Itr(edgeItr);
378 g.getNodeCosts(otherNodeItr) +=
379 g.getEdgeCosts(edgeItr).getRowAsVector(0);
380 }
381 else {
382 GraphNodeIterator otherNodeItr = g.getEdgeNode1Itr(edgeItr);
383 g.getNodeCosts(otherNodeItr) +=
384 g.getEdgeCosts(edgeItr).getColAsVector(0);
385 }
386
387 edgesToRemove.push_back(edgeItr);
388 }
389
390 while (!edgesToRemove.empty()) {
391 g.removeEdge(edgesToRemove.back());
392 edgesToRemove.pop_back();
393 }
394 }
395 }
396 }
397
398 void eliminateIndependentEdges() {
399 std::vector edgesToProcess;
400
401 for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd();
402 edgeItr != edgeEnd; ++edgeItr) {
403 edgesToProcess.push_back(edgeItr);
404 }
405
406 while (!edgesToProcess.empty()) {
407 tryToEliminateEdge(edgesToProcess.back());
408 edgesToProcess.pop_back();
409 }
410 }
411
412 void tryToEliminateEdge(const GraphEdgeIterator &edgeItr) {
413 if (tryNormaliseEdgeMatrix(edgeItr)) {
414 g.removeEdge(edgeItr);
415 }
416 }
417
418 bool tryNormaliseEdgeMatrix(const GraphEdgeIterator &edgeItr) {
419
420 Matrix &edgeCosts = g.getEdgeCosts(edgeItr);
421 Vector &uCosts = g.getNodeCosts(g.getEdgeNode1Itr(edgeItr)),
422 &vCosts = g.getNodeCosts(g.getEdgeNode2Itr(edgeItr));
423
424 for (unsigned r = 0; r < edgeCosts.getRows(); ++r) {
425 PBQPNum rowMin = edgeCosts.getRowMin(r);
426 uCosts[r] += rowMin;
427 if (rowMin != std::numeric_limits::infinity()) {
428 edgeCosts.subFromRow(r, rowMin);
429 }
430 else {
431 edgeCosts.setRow(r, 0);
432 }
433 }
434
435 for (unsigned c = 0; c < edgeCosts.getCols(); ++c) {
436 PBQPNum colMin = edgeCosts.getColMin(c);
437 vCosts[c] += colMin;
438 if (colMin != std::numeric_limits::infinity()) {
439 edgeCosts.subFromCol(c, colMin);
440 }
441 else {
442 edgeCosts.setCol(c, 0);
443 }
444 }
445
446 return edgeCosts.isZero();
447 }
448
449 void setup() {
450 setupLinks();
451 heuristic.initialise(*this);
452 setupBuckets();
453 }
454
455 void setupLinks() {
456 for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd();
457 edgeItr != edgeEnd; ++edgeItr) {
458 g.getEdgeData(edgeItr).setup(edgeItr);
459 }
460 }
461
462 void setupBuckets() {
463 for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd();
464 nodeItr != nodeEnd; ++nodeItr) {
465 addToBucket(nodeItr);
466 }
467 }
468
469 void computeSolution() {
470 assert(g.areNodeIDsValid() &&
471 "Nodes cannot be added/removed during reduction.");
472
473 reduce();
474 computeTrivialSolutions();
475 backpropagate();
476 }
477
478 void printNode(const GraphNodeIterator &nodeItr) {
479
480 std::cerr << "Node " << g.getNodeID(nodeItr) << " (" << &*nodeItr << "):\n"
481 << " costs = " << g.getNodeCosts(nodeItr) << "\n"
482 << " link degree = " << g.getNodeData(nodeItr).getLinkDegree() << "\n"
483 << " links = [ ";
484
485 for (typename HSIT::NodeData::AdjLinkIterator
486 aeItr = g.getNodeData(nodeItr).adjLinksBegin(),
487 aeEnd = g.getNodeData(nodeItr).adjLinksEnd();
488 aeItr != aeEnd; ++aeItr) {
489 std::cerr << "(" << g.getNodeID(g.getEdgeNode1Itr(*aeItr))
490 << ", " << g.getNodeID(g.getEdgeNode2Itr(*aeItr))
491 << ") ";
492 }
493 std::cout << "]\n";
494 }
495
496 void dumpState() {
497
498 std::cerr << "\n";
499
500 for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd();
501 nodeItr != nodeEnd; ++nodeItr) {
502 printNode(nodeItr);
503 }
504
505 NodeList* buckets[] = { &r0Bucket, &r1Bucket, &r2Bucket };
506
507 for (unsigned b = 0; b < 3; ++b) {
508 NodeList &bucket = *buckets[b];
509
510 std::cerr << "Bucket " << b << ": [ ";
511
512 for (NodeListIterator nItr = bucket.begin(), nEnd = bucket.end();
513 nItr != nEnd; ++nItr) {
514 std::cerr << g.getNodeID(*nItr) << " ";
515 }
516
517 std::cerr << "]\n";
518 }
519
520 std::cerr << "Stack: [ ";
521 for (NodeStackIterator nsItr = stack.begin(), nsEnd = stack.end();
522 nsItr != nsEnd; ++nsItr) {
523 std::cerr << g.getNodeID(*nsItr) << " ";
524 }
525 std::cerr << "]\n";
526 }
527
528 void reduce() {
529 bool reductionFinished = r1Bucket.empty() && r2Bucket.empty() &&
530 heuristic.rNBucketEmpty();
531
532 while (!reductionFinished) {
533
534 if (!r1Bucket.empty()) {
535 processR1();
536 }
537 else if (!r2Bucket.empty()) {
538 processR2();
539 }
540 else if (!heuristic.rNBucketEmpty()) {
541 solution.setProvedOptimal(false);
542 solution.incRNReductions();
543 heuristic.processRN();
544 }
545 else reductionFinished = true;
546 }
547
548 };
549
550 void processR1() {
551
552 // Remove the first node in the R0 bucket:
553 GraphNodeIterator xNodeItr = r1Bucket.front();
554 r1Bucket.pop_front();
555
556 solution.incR1Reductions();
557
558 //std::cerr << "Applying R1 to " << g.getNodeID(xNodeItr) << "\n";
559
560 assert((g.getNodeData(xNodeItr).getLinkDegree() == 1) &&
561 "Node in R1 bucket has degree != 1");
562
563 GraphEdgeIterator edgeItr = *g.getNodeData(xNodeItr).adjLinksBegin();
564
565 const Matrix &edgeCosts = g.getEdgeCosts(edgeItr);
566
567 const Vector &xCosts = g.getNodeCosts(xNodeItr);
568 unsigned xLen = xCosts.getLength();
569
570 // Duplicate a little code to avoid transposing matrices:
571 if (xNodeItr == g.getEdgeNode1Itr(edgeItr)) {
572 GraphNodeIterator yNodeItr = g.getEdgeNode2Itr(edgeItr);
573 Vector &yCosts = g.getNodeCosts(yNodeItr);
574 unsigned yLen = yCosts.getLength();
575
576 for (unsigned j = 0; j < yLen; ++j) {
577 PBQPNum min = edgeCosts[0][j] + xCosts[0];
578 for (unsigned i = 1; i < xLen; ++i) {
579 PBQPNum c = edgeCosts[i][j] + xCosts[i];
580 if (c < min)
581 min = c;
582 }
583 yCosts[j] += min;
584 }
585 }
586 else {
587 GraphNodeIterator yNodeItr = g.getEdgeNode1Itr(edgeItr);
588 Vector &yCosts = g.getNodeCosts(yNodeItr);
589 unsigned yLen = yCosts.getLength();
590
591 for (unsigned i = 0; i < yLen; ++i) {
592 PBQPNum min = edgeCosts[i][0] + xCosts[0];
593
594 for (unsigned j = 1; j < xLen; ++j) {
595 PBQPNum c = edgeCosts[i][j] + xCosts[j];
596 if (c < min)
597 min = c;
598 }
599 yCosts[i] += min;
600 }
601 }
602
603 unlinkNode(xNodeItr);
604 pushStack(xNodeItr);
605 }
606
607 void processR2() {
608
609 GraphNodeIterator xNodeItr = r2Bucket.front();
610 r2Bucket.pop_front();
611
612 solution.incR2Reductions();
613
614 // Unlink is unsafe here. At some point it may optimistically more a node
615 // to a lower-degree list when its degree will later rise, or vice versa,
616 // violating the assumption that node degrees monotonically decrease
617 // during the reduction phase. Instead we'll bucket shuffle manually.
618 pushStack(xNodeItr);
619
620 assert((g.getNodeData(xNodeItr).getLinkDegree() == 2) &&
621 "Node in R2 bucket has degree != 2");
622
623 const Vector &xCosts = g.getNodeCosts(xNodeItr);
624
625 typename NodeData::AdjLinkIterator tempItr =
626 g.getNodeData(xNodeItr).adjLinksBegin();
627
628 GraphEdgeIterator yxEdgeItr = *tempItr,
629 zxEdgeItr = *(++tempItr);
630
631 GraphNodeIterator yNodeItr = g.getEdgeOtherNode(yxEdgeItr, xNodeItr),
632 zNodeItr = g.getEdgeOtherNode(zxEdgeItr, xNodeItr);
633
634 removeFromBucket(yNodeItr);
635 removeFromBucket(zNodeItr);
636
637 removeLink(yxEdgeItr, yNodeItr);
638 removeLink(zxEdgeItr, zNodeItr);
639
640 // Graph some of the costs:
641 bool flipEdge1 = (g.getEdgeNode1Itr(yxEdgeItr) == xNodeItr),
642 flipEdge2 = (g.getEdgeNode1Itr(zxEdgeItr) == xNodeItr);
643
644 const Matrix *yxCosts = flipEdge1 ?
645 new Matrix(g.getEdgeCosts(yxEdgeItr).transpose()) :
646 &g.getEdgeCosts(yxEdgeItr),
647 *zxCosts = flipEdge2 ?
648 new Matrix(g.getEdgeCosts(zxEdgeItr).transpose()) :
649 &g.getEdgeCosts(zxEdgeItr);
650
651 unsigned xLen = xCosts.getLength(),
652 yLen = yxCosts->getRows(),
653 zLen = zxCosts->getRows();
654
655 // Compute delta:
656 Matrix delta(yLen, zLen);
657
658 for (unsigned i = 0; i < yLen; ++i) {
659 for (unsigned j = 0; j < zLen; ++j) {
660 PBQPNum min = (*yxCosts)[i][0] + (*zxCosts)[j][0] + xCosts[0];
661 for (unsigned k = 1; k < xLen; ++k) {
662 PBQPNum c = (*yxCosts)[i][k] + (*zxCosts)[j][k] + xCosts[k];
663 if (c < min) {
664 min = c;
665 }
666 }
667 delta[i][j] = min;
668 }
669 }
670
671 if (flipEdge1)
672 delete yxCosts;
673
674 if (flipEdge2)
675 delete zxCosts;
676
677 // Deal with the potentially induced yz edge.
678 GraphEdgeIterator yzEdgeItr = g.findEdge(yNodeItr, zNodeItr);
679 if (yzEdgeItr == g.edgesEnd()) {
680 yzEdgeItr = g.addEdge(yNodeItr, zNodeItr, delta, EdgeData(g));
681 }
682 else {
683 // There was an edge, but we're going to screw with it. Delete the old
684 // link, update the costs. We'll re-link it later.
685 removeLinkR2(yzEdgeItr);
686 g.getEdgeCosts(yzEdgeItr) +=
687 (yNodeItr == g.getEdgeNode1Itr(yzEdgeItr)) ?
688 delta : delta.transpose();
689 }
690
691 bool nullCostEdge = tryNormaliseEdgeMatrix(yzEdgeItr);
692
693 // Nulled the edge, remove it entirely.
694 if (nullCostEdge) {
695 g.removeEdge(yzEdgeItr);
696 }
697 else {
698 // Edge remains - re-link it.
699 addLink(yzEdgeItr);
700 }
701
702 addToBucket(yNodeItr);
703 addToBucket(zNodeItr);
704 }
705
706 void computeTrivialSolutions() {
707
708 for (NodeListIterator r0Itr = r0Bucket.begin(), r0End = r0Bucket.end();
709 r0Itr != r0End; ++r0Itr) {
710 GraphNodeIterator nodeItr = *r0Itr;
711
712 solution.incR0Reductions();
713 setSolution(nodeItr, g.getNodeCosts(nodeItr).minIndex());
714 }
715
716 }
717
718 void backpropagate() {
719 while (!stack.empty()) {
720 computeSolution(stack.back());
721 stack.pop_back();
722 }
723 }
724
725 void computeSolution(const GraphNodeIterator &nodeItr) {
726
727 NodeData &nodeData = g.getNodeData(nodeItr);
728
729 Vector v(g.getNodeCosts(nodeItr));
730
731 // Solve based on existing links.
732 for (typename NodeData::AdjLinkIterator
733 solvedLinkItr = nodeData.solvedLinksBegin(),
734 solvedLinkEnd = nodeData.solvedLinksEnd();
735 solvedLinkItr != solvedLinkEnd; ++solvedLinkItr) {
736
737 GraphEdgeIterator solvedEdgeItr(*solvedLinkItr);
738 Matrix &edgeCosts = g.getEdgeCosts(solvedEdgeItr);
739
740 if (nodeItr == g.getEdgeNode1Itr(solvedEdgeItr)) {
741 GraphNodeIterator adjNode(g.getEdgeNode2Itr(solvedEdgeItr));
742 unsigned adjSolution =
743 solution.getSelection(g.getNodeID(adjNode));
744 v += edgeCosts.getColAsVector(adjSolution);
745 }
746 else {
747 GraphNodeIterator adjNode(g.getEdgeNode1Itr(solvedEdgeItr));
748 unsigned adjSolution =
749 solution.getSelection(g.getNodeID(adjNode));
750 v += edgeCosts.getRowAsVector(adjSolution);
751 }
752
753 }
754
755 setSolution(nodeItr, v.minIndex());
756 }
757
758 void computeSolutionCost(const SimpleGraph &orig) {
759 PBQPNum cost = 0.0;
760
761 for (SimpleGraph::ConstNodeIterator
762 nodeItr = orig.nodesBegin(), nodeEnd = orig.nodesEnd();
763 nodeItr != nodeEnd; ++nodeItr) {
764
765 unsigned nodeId = orig.getNodeID(nodeItr);
766
767 cost += orig.getNodeCosts(nodeItr)[solution.getSelection(nodeId)];
768 }
769
770 for (SimpleGraph::ConstEdgeIterator
771 edgeItr = orig.edgesBegin(), edgeEnd = orig.edgesEnd();
772 edgeItr != edgeEnd; ++edgeItr) {
773
774 SimpleGraph::ConstNodeIterator n1 = orig.getEdgeNode1Itr(edgeItr),
775 n2 = orig.getEdgeNode2Itr(edgeItr);
776 unsigned sol1 = solution.getSelection(orig.getNodeID(n1)),
777 sol2 = solution.getSelection(orig.getNodeID(n2));
778
779 cost += orig.getEdgeCosts(edgeItr)[sol1][sol2];
780 }
781
782 solution.setSolutionCost(cost);
783 }
784
785 };
786
787 template
788 class HeuristicSolver : public Solver {
789 public:
790 Solution solve(const SimpleGraph &g) const {
791 HeuristicSolverImpl solverImpl(g);
792 return solverImpl.getSolution();
793 }
794 };
795
796 }
797
798 #endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
0 #ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
1 #define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
2
3 #include "../HeuristicSolver.h"
4
5 #include
6
7 namespace PBQP {
8 namespace Heuristics {
9
10 class Briggs {
11 public:
12
13 class NodeData;
14 class EdgeData;
15
16 private:
17
18 typedef HeuristicSolverImpl Solver;
19 typedef HSITypes HSIT;
20 typedef HSIT::SolverGraph SolverGraph;
21 typedef HSIT::GraphNodeIterator GraphNodeIterator;
22 typedef HSIT::GraphEdgeIterator GraphEdgeIterator;
23
24 class LinkDegreeComparator {
25 public:
26 LinkDegreeComparator() : g(0) {}
27 LinkDegreeComparator(SolverGraph *g) : g(g) {}
28
29 bool operator()(const GraphNodeIterator &node1Itr,
30 const GraphNodeIterator &node2Itr) const {
31 assert((g != 0) && "Graph object not set, cannot access node data.");
32 unsigned n1Degree = g->getNodeData(node1Itr).getLinkDegree(),
33 n2Degree = g->getNodeData(node2Itr).getLinkDegree();
34 if (n1Degree > n2Degree) {
35 return true;
36 }
37 else if (n1Degree < n2Degree) {
38 return false;
39 }
40 // else they're "equal" by degree, differentiate based on ID.
41 return g->getNodeID(node1Itr) < g->getNodeID(node2Itr);
42 }
43
44 private:
45 SolverGraph *g;
46 };
47
48 class SpillPriorityComparator {
49 public:
50 SpillPriorityComparator() : g(0) {}
51 SpillPriorityComparator(SolverGraph *g) : g(g) {}
52
53 bool operator()(const GraphNodeIterator &node1Itr,
54 const GraphNodeIterator &node2Itr) const {
55 assert((g != 0) && "Graph object not set, cannot access node data.");
56 PBQPNum cost1 =
57 g->getNodeCosts(node1Itr)[0] /
58 g->getNodeData(node1Itr).getLinkDegree(),
59 cost2 =
60 g->getNodeCosts(node2Itr)[0] /
61 g->getNodeData(node2Itr).getLinkDegree();
62
63 if (cost1 < cost2) {
64 return true;
65 }
66 else if (cost1 > cost2) {
67 return false;
68 }
69 // else they'er "equal" again, differentiate based on address again.
70 return g->getNodeID(node1Itr) < g->getNodeID(node2Itr);
71 }
72
73 private:
74 SolverGraph *g;
75 };
76
77 typedef std::set
78 RNAllocableNodeList;
79 typedef RNAllocableNodeList::iterator RNAllocableNodeListIterator;
80
81 typedef std::set
82 RNUnallocableNodeList;
83 typedef RNUnallocableNodeList::iterator RNUnallocableNodeListIterator;
84
85 public:
86
87 class NodeData {
88 private:
89 RNAllocableNodeListIterator rNAllocableNodeListItr;
90 RNUnallocableNodeListIterator rNUnallocableNodeListItr;
91 unsigned numRegOptions, numDenied, numSafe;
92 std::vector unsafeDegrees;
93 bool allocable;
94
95 void addRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr,
96 const GraphEdgeIterator &edgeItr, bool add) {
97
98 //assume we're adding...
99 unsigned udTarget = 0, dir = 1;
100
101 if (!add) {
102 udTarget = 1;
103 dir = -1;
104 }
105
106 EdgeData &linkEdgeData = g.getEdgeData(edgeItr).getHeuristicData();
107
108 EdgeData::ConstUnsafeIterator edgeUnsafeBegin, edgeUnsafeEnd;
109
110 if (nodeItr == g.getEdgeNode1Itr(edgeItr)) {
111 numDenied += (dir * linkEdgeData.getWorstDegree());
112 edgeUnsafeBegin = linkEdgeData.unsafeBegin();
113 edgeUnsafeEnd = linkEdgeData.unsafeEnd();
114 }
115 else {
116 numDenied += (dir * linkEdgeData.getReverseWorstDegree());
117 edgeUnsafeBegin = linkEdgeData.reverseUnsafeBegin();
118 edgeUnsafeEnd = linkEdgeData.reverseUnsafeEnd();
119 }
120
121 assert((unsafeDegrees.size() ==
122 static_cast(
123 std::distance(edgeUnsafeBegin, edgeUnsafeEnd)))
124 && "Unsafe array size mismatch.");
125
126 std::vector::iterator unsafeDegreesItr =
127 unsafeDegrees.begin();
128
129 for (EdgeData::ConstUnsafeIterator edgeUnsafeItr = edgeUnsafeBegin;
130 edgeUnsafeItr != edgeUnsafeEnd;
131 ++edgeUnsafeItr, ++unsafeDegreesItr) {
132
133 if ((*edgeUnsafeItr == 1) && (*unsafeDegreesItr == udTarget)) {
134 numSafe -= dir;
135 }
136 *unsafeDegreesItr += (dir * (*edgeUnsafeItr));
137 }
138
139 allocable = (numDenied < numRegOptions) || (numSafe > 0);
140 }
141
142 public:
143
144 void setup(SolverGraph &g, const GraphNodeIterator &nodeItr) {
145
146 numRegOptions = g.getNodeCosts(nodeItr).getLength() - 1;
147
148 numSafe = numRegOptions; // Optimistic, correct below.
149 numDenied = 0; // Also optimistic.
150 unsafeDegrees.resize(numRegOptions, 0);
151
152 HSIT::NodeData &nodeData = g.getNodeData(nodeItr);
153
154 for (HSIT::NodeData::AdjLinkIterator
155 adjLinkItr = nodeData.adjLinksBegin(),
156 adjLinkEnd = nodeData.adjLinksEnd();
157 adjLinkItr != adjLinkEnd; ++adjLinkItr) {
158
159 addRemoveLink(g, nodeItr, *adjLinkItr, true);
160 }
161 }
162
163 bool isAllocable() const { return allocable; }
164
165 void handleAddLink(SolverGraph &g, const GraphNodeIterator &nodeItr,
166 const GraphEdgeIterator &adjEdge) {
167 addRemoveLink(g, nodeItr, adjEdge, true);
168 }
169
170 void handleRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr,
171 const GraphEdgeIterator &adjEdge) {
172 addRemoveLink(g, nodeItr, adjEdge, false);
173 }
174
175 void setRNAllocableNodeListItr(
176 const RNAllocableNodeListIterator &rNAllocableNodeListItr) {
177
178 this->rNAllocableNodeListItr = rNAllocableNodeListItr;
179 }
180
181 RNAllocableNodeListIterator getRNAllocableNodeListItr() const {
182 return rNAllocableNodeListItr;
183 }
184
185 void setRNUnallocableNodeListItr(
186 const RNUnallocableNodeListIterator &rNUnallocableNodeListItr) {
187
188 this->rNUnallocableNodeListItr = rNUnallocableNodeListItr;
189 }
190
191 RNUnallocableNodeListIterator getRNUnallocableNodeListItr() const {
192 return rNUnallocableNodeListItr;
193 }
194
195
196 };
197
198 class EdgeData {
199 private:
200
201 typedef std::vector UnsafeArray;
202
203 unsigned worstDegree,
204 reverseWorstDegree;
205 UnsafeArray unsafe, reverseUnsafe;
206
207 public:
208
209 EdgeData() : worstDegree(0), reverseWorstDegree(0) {}
210
211 typedef UnsafeArray::const_iterator ConstUnsafeIterator;
212
213 void setup(SolverGraph &g, const GraphEdgeIterator &edgeItr) {
214 const Matrix &edgeCosts = g.getEdgeCosts(edgeItr);
215 unsigned numRegs = edgeCosts.getRows() - 1,
216 numReverseRegs = edgeCosts.getCols() - 1;
217
218 unsafe.resize(numRegs, 0);
219 reverseUnsafe.resize(numReverseRegs, 0);
220
221 std::vector rowInfCounts(numRegs, 0),
222 colInfCounts(numReverseRegs, 0);
223
224 for (unsigned i = 0; i < numRegs; ++i) {
225 for (unsigned j = 0; j < numReverseRegs; ++j) {
226 if (edgeCosts[i + 1][j + 1] ==
227 std::numeric_limits::infinity()) {
228 unsafe[i] = 1;
229 reverseUnsafe[j] = 1;
230 ++rowInfCounts[i];
231 ++colInfCounts[j];
232
233 if (colInfCounts[j] > worstDegree) {
234 worstDegree = colInfCounts[j];
235 }
236
237 if (rowInfCounts[i] > reverseWorstDegree) {
238 reverseWorstDegree = rowInfCounts[i];
239 }
240 }
241 }
242 }
243 }
244
245 unsigned getWorstDegree() const { return worstDegree; }
246 unsigned getReverseWorstDegree() const { return reverseWorstDegree; }
247 ConstUnsafeIterator unsafeBegin() const { return unsafe.begin(); }
248 ConstUnsafeIterator unsafeEnd() const { return unsafe.end(); }
249 ConstUnsafeIterator reverseUnsafeBegin() const {
250 return reverseUnsafe.begin();
251 }
252 ConstUnsafeIterator reverseUnsafeEnd() const {
253 return reverseUnsafe.end();
254 }
255 };
256
257 void initialise(Solver &solver) {
258 this->s = &solver;
259 g = &s->getGraph();
260 rNAllocableBucket = RNAllocableNodeList(LinkDegreeComparator(g));
261 rNUnallocableBucket =
262 RNUnallocableNodeList(SpillPriorityComparator(g));
263
264 for (GraphEdgeIterator
265 edgeItr = g->edgesBegin(), edgeEnd = g->edgesEnd();
266 edgeItr != edgeEnd; ++edgeItr) {
267
268 g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr);
269 }
270
271 for (GraphNodeIterator
272 nodeItr = g->nodesBegin(), nodeEnd = g->nodesEnd();
273 nodeItr != nodeEnd; ++nodeItr) {
274
275 g->getNodeData(nodeItr).getHeuristicData().setup(*g, nodeItr);
276 }
277 }
278
279 void addToRNBucket(const GraphNodeIterator &nodeItr) {
280 NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
281
282 if (nodeData.isAllocable()) {
283 nodeData.setRNAllocableNodeListItr(
284 rNAllocableBucket.insert(rNAllocableBucket.begin(), nodeItr));
285 }
286 else {
287 nodeData.setRNUnallocableNodeListItr(
288 rNUnallocableBucket.insert(rNUnallocableBucket.begin(), nodeItr));
289 }
290 }
291
292 void removeFromRNBucket(const GraphNodeIterator &nodeItr) {
293 NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
294
295 if (nodeData.isAllocable()) {
296 rNAllocableBucket.erase(nodeData.getRNAllocableNodeListItr());
297 }
298 else {
299 rNUnallocableBucket.erase(nodeData.getRNUnallocableNodeListItr());
300 }
301 }
302
303 void handleAddLink(const GraphEdgeIterator &edgeItr) {
304 // We assume that if we got here this edge is attached to at least
305 // one high degree node.
306 g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr);
307
308 GraphNodeIterator n1Itr = g->getEdgeNode1Itr(edgeItr),
309 n2Itr = g->getEdgeNode2Itr(edgeItr);
310
311 HSIT::NodeData &n1Data = g->getNodeData(n1Itr),
312 &n2Data = g->getNodeData(n2Itr);
313
314 if (n1Data.getLinkDegree() > 2) {
315 n1Data.getHeuristicData().handleAddLink(*g, n1Itr, edgeItr);
316 }
317 if (n2Data.getLinkDegree() > 2) {
318 n2Data.getHeuristicData().handleAddLink(*g, n2Itr, edgeItr);
319 }
320 }
321
322 void handleRemoveLink(const GraphEdgeIterator &edgeItr,
323 const GraphNodeIterator &nodeItr) {
324 NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
325 nodeData.handleRemoveLink(*g, nodeItr, edgeItr);
326 }
327
328 void processRN() {
329
330 /*
331 std::cerr << "processRN():\n"
332 << " rNAllocable = [ ";
333 for (RNAllocableNodeListIterator nItr = rNAllocableBucket.begin(),
334 nEnd = rNAllocableBucket.end();
335 nItr != nEnd; ++nItr) {
336 std::cerr << g->getNodeID(*nItr) << " (" << g->getNodeData(*nItr).getLinkDegree() << ") ";
337 }
338 std::cerr << "]\n"
339 << " rNUnallocable = [ ";
340 for (RNUnallocableNodeListIterator nItr = rNUnallocableBucket.begin(),
341 nEnd = rNUnallocableBucket.end();
342 nItr != nEnd; ++nItr) {
343 float bCost = g->getNodeCosts(*nItr)[0] / g->getNodeData(*nItr).getLinkDegree();
344 std::cerr << g->getNodeID(*nItr) << " (" << bCost << ") ";
345 }
346 std::cerr << "]\n";
347 */
348
349 if (!rNAllocableBucket.empty()) {
350 GraphNodeIterator selectedNodeItr = *rNAllocableBucket.begin();
351 //std::cerr << "RN safely pushing " << g->getNodeID(selectedNodeItr) << "\n";
352 rNAllocableBucket.erase(rNAllocableBucket.begin());
353 s->pushStack(selectedNodeItr);
354 s->unlinkNode(selectedNodeItr);
355 }
356 else {
357 GraphNodeIterator selectedNodeItr = *rNUnallocableBucket.begin();
358 //std::cerr << "RN optimistically pushing " << g->getNodeID(selectedNodeItr) << "\n";
359 rNUnallocableBucket.erase(rNUnallocableBucket.begin());
360 s->pushStack(selectedNodeItr);
361 s->unlinkNode(selectedNodeItr);
362 }
363
364 }
365
366 bool rNBucketEmpty() const {
367 return (rNAllocableBucket.empty() && rNUnallocableBucket.empty());
368 }
369
370 private:
371
372 Solver *s;
373 SolverGraph *g;
374 RNAllocableNodeList rNAllocableBucket;
375 RNUnallocableNodeList rNUnallocableBucket;
376 };
377
378
379
380 }
381 }
382
383
384 #endif // LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
0 #ifndef LLVM_CODEGEN_PBQP_PBQPMATH_H
1 #define LLVM_CODEGEN_PBQP_PBQPMATH_H
2
3 #include
4 #include
5 #include
6
7 namespace PBQP {
8
9 typedef double PBQPNum;
10
11 /// \brief PBQP Vector class.
12 class Vector {
13 public:
14
15 /// \brief Construct a PBQP vector of the given size.
16 explicit Vector(unsigned length) :
17 length(length), data(new PBQPNum[length]) {
18 }
19
20 /// \brief Construct a PBQP vector with initializer.
21 Vector(unsigned length, PBQPNum initVal) :
22 length(length), data(new PBQPNum[length]) {
23 std::fill(data, data + length, initVal);
24 }
25
26 /// \brief Copy construct a PBQP vector.
27 Vector(const Vector &v) :
28 length(v.length), data(new PBQPNum[length]) {
29 std::copy(v.data, v.data + length, data);
30 }
31
32 /// \brief Destroy this vector, return its memory.
33 ~Vector() { delete[] data; }
34
35 /// \brief Assignment operator.
36 Vector& operator=(const Vector &v) {
37 delete[] data;
38 length = v.length;
39 data = new PBQPNum[length];
40 std::copy(v.data, v.data + length, data);
41 return *this;
42 }
43
44 /// \brief Return the length of the vector
45 unsigned getLength() const throw () {
46 return length;
47 }
48
49 /// \brief Element access.
50 PBQPNum& operator[](unsigned index) {
51 assert(index < length && "Vector element access out of bounds.");
52 return data[index];
53 }
54
55 /// \brief Const element access.
56 const PBQPNum& operator[](unsigned index) const {
57 assert(index < length && "Vector element access out of bounds.");
58 return data[index];
59 }
60
61 /// \brief Add another vector to this one.
62 Vector& operator+=(const Vector &v) {
63 assert(length == v.length && "Vector length mismatch.");
64 std::transform(data, data + length, v.data, data, std::plus());
65 return *this;
66 }
67
68 /// \brief Subtract another vector from this one.
69 Vector& operator-=(const Vector &v) {
70 assert(length == v.length && "Vector length mismatch.");
71 std::transform(data, data + length, v.data, data, std::minus());
72 return *this;
73 }
74
75 /// \brief Returns the index of the minimum value in this vector
76 unsigned minIndex() const {
77 return std::min_element(data, data + length) - data;
78 }
79
80 private:
81 unsigned length;
82 PBQPNum *data;
83 };
84
85 /// \brief Output a textual representation of the given vector on the given
86 /// output stream.
87 template
88 OStream& operator<<(OStream &os, const Vector &v) {
89 assert((v.getLength() != 0) && "Zero-length vector badness.");
90
91 os << "[ " << v[0];
92 for (unsigned i = 1; i < v.getLength(); ++i) {
93 os << ", " << v[i];
94 }
95 os << " ]";
96
97 return os;
98 }
99
100
101 /// \brief PBQP Matrix class
102 class Matrix {
103 public:
104
105 /// \brief Construct a PBQP Matrix with the given dimensions.
106 Matrix(unsigned rows, unsigned cols) :
107 rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
108 }
109
110 /// \brief Construct a PBQP Matrix with the given dimensions and initial
111 /// value.
112 Matrix(unsigned rows, unsigned cols, PBQPNum initVal) :
113 rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
114 std::fill(data, data + (rows * cols), initVal);
115 }
116
117 /// \brief Copy construct a PBQP matrix.
118 Matrix(const Matrix &m) :
119 rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) {
120 std::copy(m.data, m.data + (rows * cols), data);
121 }
122
123 /// \brief Destroy this matrix, return its memory.
124 ~Matrix() { delete[] data; }
125
126 /// \brief Assignment operator.
127 Matrix& operator=(const Matrix &m) {
128 delete[] data;
129 rows = m.rows; cols = m.cols;
130 data = new PBQPNum[rows * cols];
131 std::copy(m.data, m.data + (rows * cols), data);
132 return *this;
133 }
134
135 /// \brief Return the number of rows in this matrix.
136 unsigned getRows() const throw () { return rows; }
137
138 /// \brief Return the number of cols in this matrix.
139 unsigned getCols() const throw () { return cols; }
140
141 /// \brief Matrix element access.
142 PBQPNum* operator[](unsigned r) {
143 assert(r < rows && "Row out of bounds.");
144 return data + (r * cols);
145 }
146
147 /// \brief Matrix element access.
148 const PBQPNum* operator[](unsigned r) const {
149 assert(r < rows && "Row out of bounds.");
150 return data + (r * cols);
151 }
152
153 /// \brief Returns the given row as a vector.
154 Vector getRowAsVector(unsigned r) const {
155 Vector v(cols);
156 for (unsigned c = 0; c < cols; ++c)
157 v[c] = (*this)[r][c];
158 return v;
159 }
160
161 /// \brief Returns the given column as a vector.
162 Vector getColAsVector(unsigned c) const {
163 Vector v(rows);
164 for (unsigned r = 0; r < rows; ++r)
165 v[r] = (*this)[r][c];
166 return v;
167 }
168
169 /// \brief Reset the matrix to the given value.
170 Matrix& reset(PBQPNum val = 0) {
171 std::fill(data, data + (rows * cols), val);
172 return *this;
173 }
174
175 /// \brief Set a single row of this matrix to the given value.
176 Matrix& setRow(unsigned r, PBQPNum val) {
177 assert(r < rows && "Row out of bounds.");
178 std::fill(data + (r * cols), data + ((r + 1) * cols), val);
179 return *this;
180 }
181
182 /// \brief Set a single column of this matrix to the given value.
183 Matrix& setCol(unsigned c, PBQPNum val) {
184 assert(c < cols && "Column out of bounds.");
185 for (unsigned r = 0; r < rows; ++r)
186 (*this)[r][c] = val;
187 return *this;
188 }
189
190 /// \brief Matrix transpose.
191 Matrix transpose() const {
192 Matrix m(cols, rows);
193 for (unsigned r = 0; r < rows; ++r)
194 for (unsigned c = 0; c < cols; ++c)
195 m[c][r] = (*this)[r][c];
196 return m;
197 }
198
199 /// \brief Returns the diagonal of the matrix as a vector.
200 ///
201 /// Matrix must be square.
202 Vector diagonalize() const {
203 assert(rows == cols && "Attempt to diagonalize non-square matrix.");
204
205 Vector v(rows);
206 for (unsigned r = 0; r < rows; ++r)
207 v[r] = (*this)[r][r];
208 return v;
209 }
210
211 /// \brief Add the given matrix to this one.
212 Matrix& operator+=(const Matrix &m) {
213 assert(rows == m.rows && cols == m.cols &&
214 "Matrix dimensions mismatch.");
215 std::transform(data, data + (rows * cols), m.data, data,
216 std::plus());
217 return *this;
218 }
219
220 /// \brief Returns the minimum of the given row
221 PBQPNum getRowMin(unsigned r) const {
222 assert(r < rows && "Row out of bounds");
223 return *std::min_element(data + (r * cols), data + ((r + 1) * cols));
224 }
225
226 /// \brief Returns the minimum of the given column
227 PBQPNum getColMin(unsigned c) const {
228 PBQPNum minElem = (*this)[0][c];
229 for (unsigned r = 1; r < rows; ++r)
230 if ((*this)[r][c] < minElem) minElem = (*this)[r][c];
231 return minElem;
232 }
233
234 /// \brief Subtracts the given scalar from the elements of the given row.
235 Matrix& subFromRow(unsigned r, PBQPNum val) {
236 assert(r < rows && "Row out of bounds");
237 std::transform(data + (r * cols), data + ((r + 1) * cols),
238 data + (r * cols),
239 std::bind2nd(std::minus(), val));
240 return *this;
241 }
242
243 /// \brief Subtracts the given scalar from the elements of the given column.
244 Matrix& subFromCol(unsigned c, PBQPNum val) {
245 for (unsigned r = 0; r < rows; ++r)
246 (*this)[r][c] -= val;
247 return *this;
248 }
249
250 /// \brief Returns true if this is a zero matrix.
251 bool isZero() const {
252 return find_if(data, data + (rows * cols),
253 std::bind2nd(std::not_equal_to(), 0)) ==
254 data + (rows * cols);
255 }
256
257 private:
258 unsigned rows, cols;
259 PBQPNum *data;
260 };
261
262 /// \brief Output a textual representation of the given matrix on the given
263 /// output stream.
264 template
265 OStream& operator<<(OStream &os, const Matrix &m) {
266
267 assert((m.getRows() != 0) && "Zero-row matrix badness.");
268
269 for (unsigned i = 0; i < m.getRows(); ++i) {
270 os << m.getRowAsVector(i);
271 }
272
273 return os;
274 }
275
276 }
277
278 #endif // LLVM_CODEGEN_PBQP_PBQPMATH_HPP
0 #ifndef LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H
1 #define LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H
2
3 #include "GraphBase.h"
4
5 namespace PBQP {
6
7 class SimpleEdge;
8
9 class SimpleNode : public NodeBase {
10 public:
11 SimpleNode(const Vector &costs) :
12 NodeBase(costs) {}
13 };
14
15 class SimpleEdge : public EdgeBase {
16 public:
17 SimpleEdge(const NodeIterator &node1Itr, const NodeIterator &node2Itr,
18 const Matrix &costs) :
19 EdgeBase(node1Itr, node2Itr, costs) {}
20 };
21
22 class SimpleGraph : public GraphBase {
23 private:
24
25 typedef GraphBase PGraph;
26
27 void copyFrom(const SimpleGraph &other) {
28 assert(other.areNodeIDsValid() &&
29 "Cannot copy from another graph unless IDs have been assigned.");
30
31 std::vector newNodeItrs(other.getNumNodes());
32
33 for (ConstNodeIterator nItr = other.nodesBegin(), nEnd = other.nodesEnd();
34 nItr != nEnd; ++nItr) {
35 newNodeItrs[other.getNodeID(nItr)] = addNode(other.getNodeCosts(nItr));
36 }
37
38 for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd = other.edgesEnd();
39 eItr != eEnd; ++eItr) {
40
41 unsigned node1ID = other.getNodeID(other.getEdgeNode1Itr(eItr)),
42 node2ID = other.getNodeID(other.getEdgeNode2Itr(eItr));
43
44 addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID],
45 other.getEdgeCosts(eItr));
46 }
47 }
48
49 void copyFrom(SimpleGraph &other) {
50 if (!other.areNodeIDsValid()) {
51 other.assignNodeIDs();
52 }
53 copyFrom(const_cast(other));
54 }
55
56 public:
57
58 SimpleGraph() {}
59
60
61 SimpleGraph(const SimpleGraph &other) : PGraph() {
62 copyFrom(other);
63 }
64
65 SimpleGraph& operator=(const SimpleGraph &other) {
66 clear();
67 copyFrom(other);
68 return *this;
69 }
70
71 NodeIterator addNode(const Vector &costs) {
72 return PGraph::addConstructedNode(SimpleNode(costs));
73 }
74
75 EdgeIterator addEdge(const NodeIterator &node1Itr,
76 const NodeIterator &node2Itr,
77 const Matrix &costs) {
78 return PGraph::addConstructedEdge(SimpleEdge(node1Itr, node2Itr, costs));
79 }
80
81 };
82
83 }
84
85 #endif // LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H
0 #ifndef LLVM_CODEGEN_PBQP_SOLUTION_H
1 #define LLVM_CODEGEN_PBQP_SOLUTION_H
2
3 #include "PBQPMath.h"
4
5 namespace PBQP {
6
7 class Solution {
8
9 friend class SolverImplementation;
10
11 private:
12
13 std::vector selections;
14 PBQPNum solutionCost;
15 bool provedOptimal;
16 unsigned r0Reductions, r1Reductions,
17 r2Reductions, rNReductions;
18
19 public:
20
21 Solution() :
22 solutionCost(0.0), provedOptimal(false),
23 r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {}
24
25 Solution(unsigned length, bool assumeOptimal) :
26 selections(length), solutionCost(0.0), provedOptimal(assumeOptimal),
27 r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {}
28
29 void setProvedOptimal(bool provedOptimal) {
30 this->provedOptimal = provedOptimal;
31 }
32
33 void setSelection(unsigned nodeID, unsigned selection) {
34 selections[nodeID] = selection;
35 }
36
37 void setSolutionCost(PBQPNum solutionCost) {
38 this->solutionCost = solutionCost;
39 }
40
41 void incR0Reductions() { ++r0Reductions; }
42 void incR1Reductions() { ++r1Reductions; }
43 void incR2Reductions() { ++r2Reductions; }
44 void incRNReductions() { ++rNReductions; }
45
46 unsigned numNodes() const { return selections.size(); }
47
48 unsigned getSelection(unsigned nodeID) const {
49 return selections[nodeID];
50 }
51
52 PBQPNum getCost() const { return solutionCost; }
53
54 bool isProvedOptimal() const { return provedOptimal; }
55
56 unsigned getR0Reductions() const { return r0Reductions; }
57 unsigned getR1Reductions() const { return r1Reductions; }
58 unsigned getR2Reductions() const { return r2Reductions; }
59 unsigned getRNReductions() const { return rNReductions; }
60
61 bool operator==(const Solution &other) const {
62 return (selections == other.selections);
63 }
64
65 bool operator!=(const Solution &other) const {
66 return !(*this == other);
67 }
68
69 };
70
71 }
72
73 #endif // LLVM_CODEGEN_PBQP_SOLUTION_H
0 #ifndef LLVM_CODEGEN_PBQP_SOLVER_H
1 #define LLVM_CODEGEN_PBQP_SOLVER_H
2
3 #include "SimpleGraph.h"
4 #include "Solution.h"
5
6 namespace PBQP {
7
8 /// \brief Interface for solver classes.
9 class Solver {
10 public:
11
12 virtual ~Solver() = 0;
13 virtual Solution solve(const SimpleGraph &orig) const = 0;
14 };
15
16 Solver::~Solver() {}
17
18 }
19
20 #endif // LLVM_CODEGEN_PBQP_SOLVER_H
+0
-1395
lib/CodeGen/PBQP.cpp less more
None //===---------------- PBQP.cpp --------- PBQP Solver ------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Developed by: Bernhard Scholz
10 // The University of Sydney
11 // http://www.it.usyd.edu.au/~scholz
12 //===----------------------------------------------------------------------===//
13
14 #include "PBQP.h"
15 #include "llvm/Config/alloca.h"
16 #include
17 #include
18 #include
19
20 namespace llvm {
21
22 /**************************************************************************
23 * Data Structures
24 **************************************************************************/
25
26 /* edge of PBQP graph */
27 typedef struct adjnode {
28 struct adjnode *prev, /* doubly chained list */
29 *succ,
30 *reverse; /* reverse edge */
31 int adj; /* adj. node */
32 PBQPMatrix *costs; /* cost matrix of edge */
33
34 bool tc_valid; /* flag whether following fields are valid */
35 int *tc_safe_regs; /* safe registers */
36 int tc_impact; /* impact */
37 } adjnode;
38
39 /* bucket node */
40 typedef struct bucketnode {
41 struct bucketnode *prev; /* doubly chained list */
42 struct bucketnode *succ;
43 int u; /* node */
44 } bucketnode;
45
46 /* data structure of partitioned boolean quadratic problem */
47 struct pbqp {
48 int num_nodes; /* number of nodes */
49 int max_deg; /* maximal degree of a node */
50 bool solved; /* flag that indicates whether PBQP has been solved yet */
51 bool optimal; /* flag that indicates whether PBQP is optimal */
52 PBQPNum min;
53 bool changed; /* flag whether graph has changed in simplification */
54
55 /* node fields */
56 PBQPVector **node_costs; /* cost vectors of nodes */
57 int *node_deg; /* node degree of nodes */
58 int *solution; /* solution for node */
59 adjnode **adj_list; /* adj. list */
60 bucketnode **bucket_ptr; /* bucket pointer of a node */
61
62 /* node stack */
63 int *stack; /* stack of nodes */
64 int stack_ptr; /* stack pointer */
65
66 /* bucket fields */
67 bucketnode **bucket_list; /* bucket list */
68
69 int num_r0; /* counters for number statistics */
70 int num_ri;
71 int num_rii;
72 int num_rn;
73 int num_rn_special;
74 };
75
76 bool isInf(PBQPNum n) { return n == std::numeric_limits::infinity(); }
77
78 /*****************************************************************************
79 * allocation/de-allocation of pbqp problem
80 ****************************************************************************/
81
82 /* allocate new partitioned boolean quadratic program problem */
83 pbqp *alloc_pbqp(int num_nodes)
84 {
85 pbqp *this_;
86 int u;
87
88 assert(num_nodes > 0);
89
90 /* allocate memory for pbqp data structure */
91 this_ = (pbqp *)malloc(sizeof(pbqp));
92
93 /* Initialize pbqp fields */
94 this_->num_nodes = num_nodes;
95 this_->solved = false;
96 this_->optimal = true;
97 this_->min = 0.0;
98 this_->max_deg = 0;
99 this_->changed = false;
100 this_->num_r0 = 0;
101 this_->num_ri = 0;
102 this_->num_rii = 0;
103 this_->num_rn = 0;
104 this_->num_rn_special = 0;
105
106 /* initialize/allocate stack fields of pbqp */
107 this_->stack = (int *) malloc(sizeof(int)*num_nodes);
108 this_->stack_ptr = 0;
109
110 /* initialize/allocate node fields of pbqp */
111 this_->adj_list = (adjnode **) malloc(sizeof(adjnode *)*num_nodes);
112 this_->node_deg = (int *) malloc(sizeof(int)*num_nodes);
113 this_->solution = (int *) malloc(sizeof(int)*num_nodes);
114 this_->bucket_ptr = (bucketnode **) malloc(sizeof(bucketnode **)*num_nodes);
115 this_->node_costs = (PBQPVector**) malloc(sizeof(PBQPVector*) * num_nodes);
116 for(u=0;u
117 this_->solution[u]=-1;
118 this_->adj_list[u]=NULL;
119 this_->node_deg[u]=0;
120 this_->bucket_ptr[u]=NULL;
121 this_->node_costs[u]=NULL;
122 }
123
124 /* initialize bucket list */
125 this_->bucket_list = NULL;
126
127 return this_;
128 }
129
130 /* free pbqp problem */
131 void free_pbqp(pbqp *this_)
132 {
133 int u;
134 int deg;
135 adjnode *adj_ptr,*adj_next;
136 bucketnode *bucket,*bucket_next;
137
138 assert(this_ != NULL);
139
140 /* free node cost fields */
141 for(u=0;u < this_->num_nodes;u++) {
142 delete this_->node_costs[u];
143 }
144 free(this_->node_costs);
145
146 /* free bucket list */
147 for(deg=0;deg<=this_->max_deg;deg++) {
148 for(bucket=this_->bucket_list[deg];bucket!=NULL;bucket=bucket_next) {
149 this_->bucket_ptr[bucket->u] = NULL;
150 bucket_next = bucket-> succ;
151 free(bucket);
152 }
153 }
154 free(this_->bucket_list);
155
156 /* free adj. list */
157 assert(this_->adj_list != NULL);
158 for(u=0;u < this_->num_nodes; u++) {
159 for(adj_ptr = this_->adj_list[u]; adj_ptr != NULL; adj_ptr = adj_next) {
160 adj_next = adj_ptr -> succ;
161 if (u < adj_ptr->adj) {
162 assert(adj_ptr != NULL);
163 delete adj_ptr->costs;
164 }
165 if (adj_ptr -> tc_safe_regs != NULL) {
166 free(adj_ptr -> tc_safe_regs);
167 }
168 free(adj_ptr);
169 }
170 }
171 free(this_->adj_list);
172
173 /* free other node fields */
174 free(this_->node_deg);
175 free(this_->solution);
176 free(this_->bucket_ptr);
177
178 /* free stack */
179 free(this_->stack);
180
181 /* free pbqp data structure itself */
182 free(this_);
183 }
184
185
186 /****************************************************************************
187 * adj. node routines
188 ****************************************************************************/
189
190 /* find data structure of adj. node of a given node */
191 static
192 adjnode *find_adjnode(pbqp *this_,int u,int v)
193 {
194 adjnode *adj_ptr;
195
196 assert (this_ != NULL);
197 assert (u >= 0 && u < this_->num_nodes);
198 assert (v >= 0 && v < this_->num_nodes);
199 assert(this_->adj_list != NULL);
200
201 for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
202 if (adj_ptr->adj == v) {
203 return adj_ptr;
204 }
205 }
206 return NULL;
207 }
208
209 /* allocate a new data structure for adj. node */
210 static
211 adjnode *alloc_adjnode(pbqp *this_,int u, PBQPMatrix *costs)
212 {
213 adjnode *p;
214
215 assert(this_ != NULL);
216 assert(costs != NULL);
217 assert(u >= 0 && u < this_->num_nodes);
218
219 p = (adjnode *)malloc(sizeof(adjnode));
220 assert(p != NULL);
221
222 p->adj = u;
223 p->costs = costs;
224
225 p->tc_valid= false;
226 p->tc_safe_regs = NULL;
227 p->tc_impact = 0;
228
229 return p;
230 }
231
232 /* insert adjacence node to adj. list */
233 static
234 void insert_adjnode(pbqp *this_, int u, adjnode *adj_ptr)
235 {
236
237 assert(this_ != NULL);
238 assert(adj_ptr != NULL);
239 assert(u >= 0 && u < this_->num_nodes);
240
241 /* if adjacency list of node is not empty -> update
242 first node of the list */
243 if (this_ -> adj_list[u] != NULL) {
244 assert(this_->adj_list[u]->prev == NULL);
245 this_->adj_list[u] -> prev = adj_ptr;
246 }
247
248 /* update doubly chained list pointers of pointers */
249 adj_ptr -> succ = this_->adj_list[u];
250 adj_ptr -> prev = NULL;
251
252 /* update adjacency list pointer of node u */
253 this_->adj_list[u] = adj_ptr;
254 }
255
256 /* remove entry in an adj. list */
257 static
258 void remove_adjnode(pbqp *this_, int u, adjnode *adj_ptr)
259 {
260 assert(this_!= NULL);
261 assert(u >= 0 && u <= this_->num_nodes);
262 assert(this_->adj_list != NULL);
263 assert(adj_ptr != NULL);
264
265 if (adj_ptr -> prev == NULL) {
266 this_->adj_list[u] = adj_ptr -> succ;
267 } else {
268 adj_ptr -> prev -> succ = adj_ptr -> succ;
269 }
270
271 if (adj_ptr -> succ != NULL) {
272 adj_ptr -> succ -> prev = adj_ptr -> prev;
273 }
274
275 if(adj_ptr->reverse != NULL) {
276 adjnode *rev = adj_ptr->reverse;
277 rev->reverse = NULL;
278 }
279
280 if (adj_ptr -> tc_safe_regs != NULL) {
281 free(adj_ptr -> tc_safe_regs);
282 }
283
284 free(adj_ptr);
285 }
286
287 /*****************************************************************************
288 * node functions
289 ****************************************************************************/
290
291 /* get degree of a node */
292 static
293 int get_deg(pbqp *this_,int u)
294 {
295 adjnode *adj_ptr;
296 int deg = 0;
297
298 assert(this_ != NULL);
299 assert(u >= 0 && u < this_->num_nodes);
300 assert(this_->adj_list != NULL);
301
302 for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
303 deg ++;
304 }
305 return deg;
306 }
307
308 /* reinsert node */
309 static
310 void reinsert_node(pbqp *this_,int u)
311 {
312 adjnode *adj_u,
313 *adj_v;
314
315 assert(this_!= NULL);
316 assert(u >= 0 && u <= this_->num_nodes);
317 assert(this_->adj_list != NULL);
318
319 for(adj_u = this_ -> adj_list[u]; adj_u != NULL; adj_u = adj_u -> succ) {
320 int v = adj_u -> adj;
321 adj_v = alloc_adjnode(this_,u,adj_u->costs);
322 insert_adjnode(this_,v,adj_v);
323 }
324 }
325
326 /* remove node */
327 static
328 void remove_node(pbqp *this_,int u)
329 {
330 adjnode *adj_ptr;
331
332 assert(this_!= NULL);
333 assert(u >= 0 && u <= this_->num_nodes);
334 assert(this_->adj_list != NULL);
335
336 for(adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
337 remove_adjnode(this_,adj_ptr->adj,adj_ptr -> reverse);
338 }
339 }
340
341 /*****************************************************************************
342 * edge functions
343 ****************************************************************************/
344
345 /* insert edge to graph */
346 /* (does not check whether edge exists in graph */
347 static
348 void insert_edge(pbqp *this_, int u, int v, PBQPMatrix *costs)
349 {
350 adjnode *adj_u,
351 *adj_v;
352
353 /* create adjanceny entry for u */
354 adj_u = alloc_adjnode(this_,v,costs);
355 insert_adjnode(this_,u,adj_u);
356
357
358 /* create adjanceny entry for v */
359 adj_v = alloc_adjnode(this_,u,costs);
360 insert_adjnode(this_,v,adj_v);
361
362 /* create link for reverse edge */
363 adj_u -> reverse = adj_v;
364 adj_v -> reverse = adj_u;
365 }
366
367 /* delete edge */
368 static
369 void delete_edge(pbqp *this_,int u,int v)
370 {
371 adjnode *adj_ptr;
372 adjnode *rev;
373
374 assert(this_ != NULL);
375 assert( u >= 0 && u < this_->num_nodes);
376 assert( v >= 0 && v < this_->num_nodes);
377
378 adj_ptr=find_adjnode(this_,u,v);
379 assert(adj_ptr != NULL);
380 assert(adj_ptr->reverse != NULL);
381
382 delete adj_ptr -> costs;
383
384 rev = adj_ptr->reverse;
385 remove_adjnode(this_,u,adj_ptr);
386 remove_adjnode(this_,v,rev);
387 }
388
389 /*****************************************************************************
390 * cost functions
391 ****************************************************************************/
392
393 /* Note: Since cost(u,v) = transpose(cost(v,u)), it would be necessary to store
394 two matrices for both edges (u,v) and (v,u). However, we only store the
395 matrix for the case u < v. For the other case we transpose the stored matrix
396 if required.
397 */
398
399 /* add costs to cost vector of a node */
400 void add_pbqp_nodecosts(pbqp *this_,int u, PBQPVector *costs)
401 {
402 assert(this_ != NULL);
403 assert(costs != NULL);
404 assert(u >= 0 && u <= this_->num_nodes);
405
406 if (!this_->node_costs[u]) {
407 this_->node_costs[u] = new PBQPVector(*costs);
408 } else {
409 *this_->node_costs[u] += *costs;
410 }
411 }
412
413 /* get cost matrix ptr */
414 static
415 PBQPMatrix *get_costmatrix_ptr(pbqp *this_, int u, int v)
416 {
417 adjnode *adj_ptr;
418 PBQPMatrix *m = NULL;
419
420 assert (this_ != NULL);
421 assert (u >= 0 && u < this_->num_nodes);
422 assert (v >= 0 && v < this_->num_nodes);
423
424 adj_ptr = find_adjnode(this_,u,v);
425
426 if (adj_ptr != NULL) {
427 m = adj_ptr -> costs;
428 }
429
430 return m;
431 }
432
433 /* get cost matrix ptr */
434 /* Note: only the pointer is returned for
435 cost(u,v), if u < v.
436 */
437 static
438 PBQPMatrix *pbqp_get_costmatrix(pbqp *this_, int u, int v)
439 {
440 adjnode *adj_ptr = find_adjnode(this_,u,v);
441
442 if (adj_ptr != NULL) {
443 if ( u < v) {
444 return new PBQPMatrix(*adj_ptr->costs);
445 } else {
446 return new PBQPMatrix(adj_ptr->costs->transpose());
447 }
448 } else {
449 return NULL;
450 }
451 }
452
453 /* add costs to cost matrix of an edge */
454 void add_pbqp_edgecosts(pbqp *this_,int u,int v, PBQPMatrix *costs)
455 {
456 PBQPMatrix *adj_costs;
457
458 assert(this_!= NULL);
459 assert(costs != NULL);
460 assert(u >= 0 && u <= this_->num_nodes);
461 assert(v >= 0 && v <= this_->num_nodes);
462
463 /* does the edge u-v exists ? */
464 if (u == v) {
465 PBQPVector *diag = new PBQPVector(costs->diagonalize());
466 add_pbqp_nodecosts(this_,v,diag);
467 delete diag;
468 } else if ((adj_costs = get_costmatrix_ptr(this_,u,v))!=NULL) {
469 if ( u < v) {
470 *adj_costs += *costs;
471 } else {
472 *adj_costs += costs->transpose();
473 }
474 } else {
475 adj_costs = new PBQPMatrix((u < v) ? *costs : costs->transpose());
476 insert_edge(this_,u,v,adj_costs);
477 }
478 }
479
480 /* remove bucket from bucket list */
481 static
482 void pbqp_remove_bucket(pbqp *this_, bucketnode *bucket)
483 {
484 int u = bucket->u;
485
486 assert(this_ != NULL);
487 assert(u >= 0 && u < this_->num_nodes);
488 assert(this_->bucket_list != NULL);
489 assert(this_->bucket_ptr[u] != NULL);
490
491 /* update predecessor node in bucket list
492 (if no preceeding bucket exists, then
493 the bucket_list pointer needs to be
494 updated.)
495 */
496 if (bucket->prev != NULL) {
497 bucket->prev-> succ = bucket->succ;
498 } else {
499 this_->bucket_list[this_->node_deg[u]] = bucket -> succ;
500 }
501
502 /* update successor node in bucket list */
503 if (bucket->succ != NULL) {
504 bucket->succ-> prev = bucket->prev;
505 }
506 }
507
508 /**********************************************************************************
509 * pop functions
510 **********************************************************************************/
511
512 /* pop node of given degree */
513 static
514 int pop_node(pbqp *this_,int deg)
515 {
516 bucketnode *bucket;
517 int u;
518
519 assert(this_ != NULL);
520 assert(deg >= 0 && deg <= this_->max_deg);
521 assert(this_->bucket_list != NULL);
522
523 /* get first bucket of bucket list */
524 bucket = this_->bucket_list[deg];
525 assert(bucket != NULL);
526
527 /* remove bucket */
528 pbqp_remove_bucket(this_,bucket);
529 u = bucket->u;
530 free(bucket);
531 return u;
532 }
533
534 /**********************************************************************************
535 * reorder functions
536 **********************************************************************************/
537
538 /* add bucket to bucketlist */
539 static
540 void add_to_bucketlist(pbqp *this_,bucketnode *bucket, int deg)
541 {
542 bucketnode *old_head;
543
544 assert(bucket != NULL);
545 assert(this_ != NULL);
546 assert(deg >= 0 && deg <= this_->max_deg);
547 assert(this_->bucket_list != NULL);
548
549 /* store node degree (for re-ordering purposes)*/
550 this_->node_deg[bucket->u] = deg;
551
552 /* put bucket to front of doubly chained list */
553 old_head = this_->bucket_list[deg];
554 bucket -> prev = NULL;
555 bucket -> succ = old_head;
556 this_ -> bucket_list[deg] = bucket;
557 if (bucket -> succ != NULL ) {
558 assert ( old_head -> prev == NULL);
559 old_head -> prev = bucket;
560 }
561 }
562
563
564 /* reorder node in bucket list according to
565 current node degree */
566 static
567 void reorder_node(pbqp *this_, int u)
568 {
569 int deg;
570
571 assert(this_ != NULL);
572 assert(u>= 0 && u < this_->num_nodes);
573 assert(this_->bucket_list != NULL);
574 assert(this_->bucket_ptr[u] != NULL);
575
576 /* get current node degree */
577 deg = get_deg(this_,u);
578
579 /* remove bucket from old bucket list only
580 if degree of node has changed. */
581 if (deg != this_->node_deg[u]) {
582 pbqp_remove_bucket(this_,this_->bucket_ptr[u]);
583 add_to_bucketlist(this_,this_->bucket_ptr[u],deg);
584 }
585 }
586
587 /* reorder adj. nodes of a node */
588 static
589 void reorder_adjnodes(pbqp *this_,int u)
590 {
591 adjnode *adj_ptr;
592
593 assert(this_!= NULL);
594 assert(u >= 0 && u <= this_->num_nodes);
595 assert(this_->adj_list != NULL);
596
597 for(adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
598 reorder_node(this_,adj_ptr->adj);
599 }
600 }
601
602 /**********************************************************************************
603 * creation functions
604 **********************************************************************************/
605
606 /* create new bucket entry */
607 /* consistency of the bucket list is not checked! */
608 static
609 void create_bucket(pbqp *this_,int u,int deg)
610 {
611 bucketnode *bucket;
612
613 assert(this_ != NULL);
614 assert(u >= 0 && u < this_->num_nodes);
615 assert(this_->bucket_list != NULL);
616
617 bucket = (bucketnode *)malloc(sizeof(bucketnode));
618 assert(bucket != NULL);
619
620 bucket -> u = u;
621 this_->bucket_ptr[u] = bucket;
622
623 add_to_bucketlist(this_,bucket,deg);
624 }
625
626 /* create bucket list */
627 static
628 void create_bucketlist(pbqp *this_)
629 {
630 int u;
631 int max_deg;
632 int deg;
633
634 assert(this_ != NULL);
635 assert(this_->bucket_list == NULL);
636
637 /* determine max. degree of the nodes */
638 max_deg = 2; /* at least of degree two! */
639 for(u=0;unum_nodes;u++) {
640 deg = this_->node_deg[u] = get_deg(this_,u);
641 if (deg > max_deg) {
642 max_deg = deg;
643 }
644 }
645 this_->max_deg = max_deg;
646
647 /* allocate bucket list */
648 this_ -> bucket_list = (bucketnode **)malloc(sizeof(bucketnode *)*(max_deg + 1));
649 memset(this_->bucket_list,0,sizeof(bucketnode *)*(max_deg + 1));
650 assert(this_->bucket_list != NULL);
651
652 /* insert nodes to the list */
653 for(u=0;unum_nodes;u++) {
654 create_bucket(this_,u,this_->node_deg[u]);
655 }
656 }
657
658 /*****************************************************************************
659 * PBQP simplification for trivial nodes
660 ****************************************************************************/
661
662 /* remove trivial node with cost vector length of one */
663 static
664 void disconnect_trivialnode(pbqp *this_,int u)
665 {
666 int v;
667 adjnode *adj_ptr,
668 *next;
669 PBQPMatrix *c_uv;
670 PBQPVector *c_v;
671
672 assert(this_ != NULL);
673 assert(this_->node_costs != NULL);
674 assert(u >= 0 && u < this_ -> num_nodes);
675 assert(this_->node_costs[u]->getLength() == 1);
676
677 /* add edge costs to node costs of adj. nodes */
678 for(adj_ptr = this_->adj_list[u]; adj_ptr != NULL; adj_ptr = next){
679 next = adj_ptr -> succ;
680 v = adj_ptr -> adj;
681 assert(v >= 0 && v < this_ -> num_nodes);
682
683 /* convert matrix to cost vector offset for adj. node */
684 c_uv = pbqp_get_costmatrix(this_,u,v);
685 c_v = new PBQPVector(c_uv->getRowAsVector(0));
686 *this_->node_costs[v] += *c_v;
687
688 /* delete edge & free vec/mat */
689 delete c_v;
690 delete c_uv;
691 delete_edge(this_,u,v);
692 }
693 }
694
695 /* find all trivial nodes and disconnect them */
696 static
697 void eliminate_trivial_nodes(pbqp *this_)
698 {
699 int u;
700
701 assert(this_ != NULL);
702 assert(this_ -> node_costs != NULL);
703
704 for(u=0;u < this_ -> num_nodes; u++) {
705 if (this_->node_costs[u]->getLength() == 1) {
706 disconnect_trivialnode(this_,u);
707 }
708 }
709 }
710
711 /*****************************************************************************
712 * Normal form for PBQP
713 ****************************************************************************/
714
715 /* simplify a cost matrix. If the matrix
716 is independent, then simplify_matrix
717 returns true - otherwise false. In
718 vectors u and v the offset values of
719 the decomposition are stored.
720 */
721
722 static
723 bool normalize_matrix(PBQPMatrix *m, PBQPVector *u, PBQPVector *v)
724 {
725 assert( m != NULL);
726 assert( u != NULL);
727 assert( v != NULL);
728 assert( u->getLength() > 0);
729 assert( v->getLength() > 0);
730
731 assert(m->getRows() == u->getLength());
732 assert(m->getCols() == v->getLength());
733
734 /* determine u vector */
735 for(unsigned r = 0; r < m->getRows(); ++r) {
736 PBQPNum min = m->getRowMin(r);
737 (*u)[r] += min;
738 if (!isInf(min)) {
739 m->subFromRow(r, min);
740 } else {
741 m->setRow(r, 0);
742 }
743 }
744
745 /* determine v vector */
746 for(unsigned c = 0; c < m->getCols(); ++c) {
747 PBQPNum min = m->getColMin(c);
748 (*v)[c] += min;
749 if (!isInf(min)) {
750 m->subFromCol(c, min);
751 } else {
752 m->setCol(c, 0);
753 }
754 }
755
756 /* determine whether matrix is
757 independent or not.
758 */
759 return m->isZero();
760 }
761
762 /* simplify single edge */
763 static
764 void simplify_edge(pbqp *this_,int u,int v)
765 {
766 PBQPMatrix *costs;
767 bool is_zero;
768
769 assert (this_ != NULL);
770 assert (u >= 0 && u num_nodes);
771 assert (v >= 0 && v num_nodes);
772 assert (u != v);
773
774 /* swap u and v if u > v in order to avoid un-necessary
775 tranpositions of the cost matrix */
776
777 if (u > v) {
778 int swap = u;
779 u = v;
780 v = swap;
781 }
782
783 /* get cost matrix and simplify it */
784 costs = get_costmatrix_ptr(this_,u,v);
785 is_zero=normalize_matrix(costs,this_->node_costs[u],this_->node_costs[v]);
786
787 /* delete edge */
788 if(is_zero){
789 delete_edge(this_,u,v);
790 this_->changed = true;
791 }
792 }
793
794 /* normalize cost matrices and remove
795 edges in PBQP if they ary independent,
796 i.e. can be decomposed into two
797 cost vectors.
798 */
799 static
800 void eliminate_independent_edges(pbqp *this_)
801 {
802 int u,v;
803 adjnode *adj_ptr,*next;
804
805 assert(this_ != NULL);
806 assert(this_ -> adj_list != NULL);
807
808 this_->changed = false;
809 for(u=0;u < this_->num_nodes;u++) {
810 for (adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr = next) {
811 next = adj_ptr -> succ;
812 v = adj_ptr -> adj;
813 assert(v >= 0 && v < this_->num_nodes);
814 if (u < v) {
815 simplify_edge(this_,u,v);
816 }
817 }
818 }
819 }
820
821
822 /*****************************************************************************
823 * PBQP reduction rules
824 ****************************************************************************/
825
826 /* RI reduction
827 This reduction rule is applied for nodes
828 of degree one. */
829
830 static
831 void apply_RI(pbqp *this_,int x)
832 {
833 int y;
834 unsigned xlen,
835 ylen;
836 PBQPMatrix *c_yx;
837 PBQPVector *c_x, *delta;
838
839 assert(this_ != NULL);
840 assert(x >= 0 && x < this_->num_nodes);
841 assert(this_ -> adj_list[x] != NULL);
842 assert(this_ -> adj_list[x] -> succ == NULL);
843
844 /* get adjacence matrix */
845 y = this_ -> adj_list[x] -> adj;
846 assert(y >= 0 && y < this_->num_nodes);
847
848 /* determine length of cost vectors for node x and y */
849 xlen = this_ -> node_costs[x]->getLength();
850 ylen = this_ -> node_costs[y]->getLength();
851
852 /* get cost vector c_x and matrix c_yx */
853 c_x = this_ -> node_costs[x];
854 c_yx = pbqp_get_costmatrix(this_,y,x);
855 assert (c_yx != NULL);
856
857
858 /* allocate delta vector */
859 delta = new PBQPVector(ylen);
860
861 /* compute delta vector */
862 for(unsigned i = 0; i < ylen; ++i) {
863 PBQPNum min = (*c_yx)[i][0] + (*c_x)[0];
864 for(unsigned j = 1; j < xlen; ++j) {
865 PBQPNum c = (*c_yx)[i][j] + (*c_x)[j];
866 if ( c < min )
867 min = c;
868 }
869 (*delta)[i] = min;
870 }
871
872 /* add delta vector */
873 *this_ -> node_costs[y] += *delta;
874
875 /* delete node x */
876 remove_node(this_,x);
877
878 /* reorder adj. nodes of node x */
879 reorder_adjnodes(this_,x);
880
881 /* push node x on stack */
882 assert(this_ -> stack_ptr < this_ -> num_nodes);
883 this_->stack[this_ -> stack_ptr++] = x;
884
885 /* free vec/mat */
886 delete c_yx;
887 delete delta;
888
889 /* increment counter for number statistic */
890 this_->num_ri++;
891 }
892
893 /* RII reduction
894 This reduction rule is applied for nodes
895 of degree two. */
896
897 static
898 void apply_RII(pbqp *this_,int x)
899 {
900 int y,z;
901 unsigned xlen,ylen,zlen;
902 adjnode *adj_yz;
903
904 PBQPMatrix *c_yx, *c_zx;
905 PBQPVector *cx;
906 PBQPMatrix *delta;
907
908 assert(this_ != NULL);
909 assert(x >= 0 && x < this_->num_nodes);
910 assert(this_ -> adj_list[x] != NULL);
911 assert(this_ -> adj_list[x] -> succ != NULL);
912 assert(this_ -> adj_list[x] -> succ -> succ == NULL);
913
914 /* get adjacence matrix */
915 y = this_ -> adj_list[x] -> adj;
916 z = this_ -> adj_list[x] -> succ -> adj;
917 assert(y >= 0 && y < this_->num_nodes);
918 assert(z >= 0 && z < this_->num_nodes);
919
920 /* determine length of cost vectors for node x and y */
921 xlen = this_ -> node_costs[x]->getLength();
922 ylen = this_ -> node_costs[y]->getLength();
923 zlen = this_ -> node_costs[z]->getLength();
924
925 /* get cost vector c_x and matrix c_yx */
926 cx = this_ -> node_costs[x];
927 c_yx = pbqp_get_costmatrix(this_,y,x);
928 c_zx = pbqp_get_costmatrix(this_,z,x);
929 assert(c_yx != NULL);
930 assert(c_zx != NULL);
931
932 /* Colour Heuristic */
933 if ( (adj_yz = find_adjnode(this_,y,z)) != NULL) {
934 adj_yz->tc_valid = false;
935 adj_yz->reverse->tc_valid = false;
936 }
937
938 /* allocate delta matrix */
939 delta = new PBQPMatrix(ylen, zlen);
940
941 /* compute delta matrix */
942 for(unsigned i=0;i
943 for(unsigned j=0;j
944 PBQPNum min = (*c_yx)[i][0] + (*c_zx)[j][0] + (*cx)[0];
945 for(unsigned k=1;k
946 PBQPNum c = (*c_yx)[i][k] + (*c_zx)[j][k] + (*cx)[k];
947 if ( c < min ) {
948 min = c;
949 }
950 }
951 (*delta)[i][j] = min;
952 }
953 }
954
955 /* add delta matrix */
956 add_pbqp_edgecosts(this_,y,z,delta);
957
958 /* delete node x */
959 remove_node(this_,x);
960
961 /* simplify cost matrix c_yz */
962 simplify_edge(this_,y,z);
963
964 /* reorder adj. nodes */
965 reorder_adjnodes(this_,x);
966<