1 //===-- HeuristicSolver.h - Heuristic PBQP Solver --------------*- C++ --*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Heuristic PBQP solver. This solver is able to perform optimal reductions for
11 // nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is
12 // used to to select a node for reduction.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
17 #define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
20 #include "AnnotatedGraph.h"
21 #include "llvm/Support/raw_ostream.h"
26 /// \brief Important types for the HeuristicSolverImpl.
28 /// Declared seperately to allow access to heuristic classes before the solver
29 /// is fully constructed.
30 template <typename HeuristicNodeData
, typename HeuristicEdgeData
>
37 typedef AnnotatedGraph
<NodeData
, EdgeData
> SolverGraph
;
38 typedef typename
SolverGraph::NodeIterator GraphNodeIterator
;
39 typedef typename
SolverGraph::EdgeIterator GraphEdgeIterator
;
40 typedef typename
SolverGraph::AdjEdgeIterator GraphAdjEdgeIterator
;
42 typedef std::list
<GraphNodeIterator
> NodeList
;
43 typedef typename
NodeList::iterator NodeListIterator
;
45 typedef std::vector
<GraphNodeIterator
> NodeStack
;
46 typedef typename
NodeStack::iterator NodeStackIterator
;
49 friend class EdgeData
;
53 typedef std::list
<GraphEdgeIterator
> LinksList
;
56 LinksList links
, solvedLinks
;
57 NodeListIterator bucketItr
;
58 HeuristicNodeData heuristicData
;
62 typedef typename
LinksList::iterator AdjLinkIterator
;
66 AdjLinkIterator
addLink(const GraphEdgeIterator
&edgeItr
) {
68 return links
.insert(links
.end(), edgeItr
);
71 void delLink(const AdjLinkIterator
&adjLinkItr
) {
73 links
.erase(adjLinkItr
);
78 NodeData() : numLinks(0) {}
80 unsigned getLinkDegree() const { return numLinks
; }
82 HeuristicNodeData
& getHeuristicData() { return heuristicData
; }
83 const HeuristicNodeData
& getHeuristicData() const {
87 void setBucketItr(const NodeListIterator
&bucketItr
) {
88 this->bucketItr
= bucketItr
;
91 const NodeListIterator
& getBucketItr() const {
95 AdjLinkIterator
adjLinksBegin() {
99 AdjLinkIterator
adjLinksEnd() {
103 void addSolvedLink(const GraphEdgeIterator
&solvedLinkItr
) {
104 solvedLinks
.push_back(solvedLinkItr
);
107 AdjLinkIterator
solvedLinksBegin() {
108 return solvedLinks
.begin();
111 AdjLinkIterator
solvedLinksEnd() {
112 return solvedLinks
.end();
121 GraphNodeIterator node1Itr
, node2Itr
;
122 HeuristicEdgeData heuristicData
;
123 typename
NodeData::AdjLinkIterator node1ThisEdgeItr
, node2ThisEdgeItr
;
127 EdgeData(SolverGraph
&g
) : g(g
) {}
129 HeuristicEdgeData
& getHeuristicData() { return heuristicData
; }
130 const HeuristicEdgeData
& getHeuristicData() const {
131 return heuristicData
;
134 void setup(const GraphEdgeIterator
&thisEdgeItr
) {
135 node1Itr
= g
.getEdgeNode1Itr(thisEdgeItr
);
136 node2Itr
= g
.getEdgeNode2Itr(thisEdgeItr
);
138 node1ThisEdgeItr
= g
.getNodeData(node1Itr
).addLink(thisEdgeItr
);
139 node2ThisEdgeItr
= g
.getNodeData(node2Itr
).addLink(thisEdgeItr
);
143 g
.getNodeData(node1Itr
).delLink(node1ThisEdgeItr
);
144 g
.getNodeData(node2Itr
).delLink(node2ThisEdgeItr
);
151 template <typename Heuristic
>
152 class HeuristicSolverImpl
{
154 // Typedefs to make life easier:
155 typedef HSITypes
<typename
Heuristic::NodeData
,
156 typename
Heuristic::EdgeData
> HSIT
;
157 typedef typename
HSIT::SolverGraph SolverGraph
;
158 typedef typename
HSIT::NodeData NodeData
;
159 typedef typename
HSIT::EdgeData EdgeData
;
160 typedef typename
HSIT::GraphNodeIterator GraphNodeIterator
;
161 typedef typename
HSIT::GraphEdgeIterator GraphEdgeIterator
;
162 typedef typename
HSIT::GraphAdjEdgeIterator GraphAdjEdgeIterator
;
164 typedef typename
HSIT::NodeList NodeList
;
165 typedef typename
HSIT::NodeListIterator NodeListIterator
;
167 typedef std::vector
<GraphNodeIterator
> NodeStack
;
168 typedef typename
NodeStack::iterator NodeStackIterator
;
170 /// \brief Constructor, which performs all the actual solver work.
171 HeuristicSolverImpl(const SimpleGraph
&orig
) :
172 solution(orig
.getNumNodes(), true)
178 computeSolutionCost(orig
);
181 /// \brief Returns the graph for this solver.
182 SolverGraph
& getGraph() { return g
; }
184 /// \brief Return the solution found by this solver.
185 const Solution
& getSolution() const { return solution
; }
189 /// \brief Add the given node to the appropriate bucket for its link
191 void addToBucket(const GraphNodeIterator
&nodeItr
) {
192 NodeData
&nodeData
= g
.getNodeData(nodeItr
);
194 switch (nodeData
.getLinkDegree()) {
195 case 0: nodeData
.setBucketItr(
196 r0Bucket
.insert(r0Bucket
.end(), nodeItr
));
198 case 1: nodeData
.setBucketItr(
199 r1Bucket
.insert(r1Bucket
.end(), nodeItr
));
201 case 2: nodeData
.setBucketItr(
202 r2Bucket
.insert(r2Bucket
.end(), nodeItr
));
204 default: heuristic
.addToRNBucket(nodeItr
);
209 /// \brief Remove the given node from the appropriate bucket for its link
211 void removeFromBucket(const GraphNodeIterator
&nodeItr
) {
212 NodeData
&nodeData
= g
.getNodeData(nodeItr
);
214 switch (nodeData
.getLinkDegree()) {
215 case 0: r0Bucket
.erase(nodeData
.getBucketItr()); break;
216 case 1: r1Bucket
.erase(nodeData
.getBucketItr()); break;
217 case 2: r2Bucket
.erase(nodeData
.getBucketItr()); break;
218 default: heuristic
.removeFromRNBucket(nodeItr
); break;
224 /// \brief Add a link.
225 void addLink(const GraphEdgeIterator
&edgeItr
) {
226 g
.getEdgeData(edgeItr
).setup(edgeItr
);
228 if ((g
.getNodeData(g
.getEdgeNode1Itr(edgeItr
)).getLinkDegree() > 2) ||
229 (g
.getNodeData(g
.getEdgeNode2Itr(edgeItr
)).getLinkDegree() > 2)) {
230 heuristic
.handleAddLink(edgeItr
);
234 /// \brief Remove link, update info for node.
236 /// Only updates information for the given node, since usually the other
237 /// is about to be removed.
238 void removeLink(const GraphEdgeIterator
&edgeItr
,
239 const GraphNodeIterator
&nodeItr
) {
241 if (g
.getNodeData(nodeItr
).getLinkDegree() > 2) {
242 heuristic
.handleRemoveLink(edgeItr
, nodeItr
);
244 g
.getEdgeData(edgeItr
).unlink();
247 /// \brief Remove link, update info for both nodes. Useful for R2 only.
248 void removeLinkR2(const GraphEdgeIterator
&edgeItr
) {
249 GraphNodeIterator node1Itr
= g
.getEdgeNode1Itr(edgeItr
);
251 if (g
.getNodeData(node1Itr
).getLinkDegree() > 2) {
252 heuristic
.handleRemoveLink(edgeItr
, node1Itr
);
254 removeLink(edgeItr
, g
.getEdgeNode2Itr(edgeItr
));
257 /// \brief Removes all links connected to the given node.
258 void unlinkNode(const GraphNodeIterator
&nodeItr
) {
259 NodeData
&nodeData
= g
.getNodeData(nodeItr
);
261 typedef std::vector
<GraphEdgeIterator
> TempEdgeList
;
263 TempEdgeList edgesToUnlink
;
264 edgesToUnlink
.reserve(nodeData
.getLinkDegree());
266 // Copy adj edges into a temp vector. We want to destroy them during
267 // the unlink, and we can't do that while we're iterating over them.
268 std::copy(nodeData
.adjLinksBegin(), nodeData
.adjLinksEnd(),
269 std::back_inserter(edgesToUnlink
));
271 for (typename
TempEdgeList::iterator
272 edgeItr
= edgesToUnlink
.begin(), edgeEnd
= edgesToUnlink
.end();
273 edgeItr
!= edgeEnd
; ++edgeItr
) {
275 GraphNodeIterator otherNode
= g
.getEdgeOtherNode(*edgeItr
, nodeItr
);
277 removeFromBucket(otherNode
);
278 removeLink(*edgeItr
, otherNode
);
279 addToBucket(otherNode
);
283 /// \brief Push the given node onto the stack to be solved with
285 void pushStack(const GraphNodeIterator
&nodeItr
) {
286 stack
.push_back(nodeItr
);
289 /// \brief Set the solution of the given node.
290 void setSolution(const GraphNodeIterator
&nodeItr
, unsigned solIndex
) {
291 solution
.setSelection(g
.getNodeID(nodeItr
), solIndex
);
293 for (GraphAdjEdgeIterator adjEdgeItr
= g
.adjEdgesBegin(nodeItr
),
294 adjEdgeEnd
= g
.adjEdgesEnd(nodeItr
);
295 adjEdgeItr
!= adjEdgeEnd
; ++adjEdgeItr
) {
296 GraphEdgeIterator
edgeItr(*adjEdgeItr
);
297 GraphNodeIterator
adjNodeItr(g
.getEdgeOtherNode(edgeItr
, nodeItr
));
298 g
.getNodeData(adjNodeItr
).addSolvedLink(edgeItr
);
314 // Copy the SimpleGraph into an annotated graph which we can use for reduction.
315 void copyGraph(const SimpleGraph
&orig
) {
317 assert((g
.getNumEdges() == 0) && (g
.getNumNodes() == 0) &&
318 "Graph should be empty prior to solver setup.");
320 assert(orig
.areNodeIDsValid() &&
321 "Cannot copy from a graph with invalid node IDs.");
323 std::vector
<GraphNodeIterator
> newNodeItrs
;
325 for (unsigned nodeID
= 0; nodeID
< orig
.getNumNodes(); ++nodeID
) {
326 newNodeItrs
.push_back(
327 g
.addNode(orig
.getNodeCosts(orig
.getNodeItr(nodeID
)), NodeData()));
330 for (SimpleGraph::ConstEdgeIterator
331 origEdgeItr
= orig
.edgesBegin(), origEdgeEnd
= orig
.edgesEnd();
332 origEdgeItr
!= origEdgeEnd
; ++origEdgeItr
) {
334 unsigned id1
= orig
.getNodeID(orig
.getEdgeNode1Itr(origEdgeItr
)),
335 id2
= orig
.getNodeID(orig
.getEdgeNode2Itr(origEdgeItr
));
337 g
.addEdge(newNodeItrs
[id1
], newNodeItrs
[id2
],
338 orig
.getEdgeCosts(origEdgeItr
), EdgeData(g
));
341 // Assign IDs to the new nodes using the ordering from the old graph,
342 // this will lead to nodes in the new graph getting the same ID as the
343 // corresponding node in the old graph.
344 g
.assignNodeIDs(newNodeItrs
);
347 // Simplify the annotated graph by eliminating independent edges and trivial
350 disconnectTrivialNodes();
351 eliminateIndependentEdges();
354 // Eliminate trivial nodes.
355 void disconnectTrivialNodes() {
356 for (GraphNodeIterator nodeItr
= g
.nodesBegin(), nodeEnd
= g
.nodesEnd();
357 nodeItr
!= nodeEnd
; ++nodeItr
) {
359 if (g
.getNodeCosts(nodeItr
).getLength() == 1) {
361 std::vector
<GraphEdgeIterator
> edgesToRemove
;
363 for (GraphAdjEdgeIterator adjEdgeItr
= g
.adjEdgesBegin(nodeItr
),
364 adjEdgeEnd
= g
.adjEdgesEnd(nodeItr
);
365 adjEdgeItr
!= adjEdgeEnd
; ++adjEdgeItr
) {
367 GraphEdgeIterator edgeItr
= *adjEdgeItr
;
369 if (g
.getEdgeNode1Itr(edgeItr
) == nodeItr
) {
370 GraphNodeIterator otherNodeItr
= g
.getEdgeNode2Itr(edgeItr
);
371 g
.getNodeCosts(otherNodeItr
) +=
372 g
.getEdgeCosts(edgeItr
).getRowAsVector(0);
375 GraphNodeIterator otherNodeItr
= g
.getEdgeNode1Itr(edgeItr
);
376 g
.getNodeCosts(otherNodeItr
) +=
377 g
.getEdgeCosts(edgeItr
).getColAsVector(0);
380 edgesToRemove
.push_back(edgeItr
);
383 while (!edgesToRemove
.empty()) {
384 g
.removeEdge(edgesToRemove
.back());
385 edgesToRemove
.pop_back();
391 void eliminateIndependentEdges() {
392 std::vector
<GraphEdgeIterator
> edgesToProcess
;
394 for (GraphEdgeIterator edgeItr
= g
.edgesBegin(), edgeEnd
= g
.edgesEnd();
395 edgeItr
!= edgeEnd
; ++edgeItr
) {
396 edgesToProcess
.push_back(edgeItr
);
399 while (!edgesToProcess
.empty()) {
400 tryToEliminateEdge(edgesToProcess
.back());
401 edgesToProcess
.pop_back();
405 void tryToEliminateEdge(const GraphEdgeIterator
&edgeItr
) {
406 if (tryNormaliseEdgeMatrix(edgeItr
)) {
407 g
.removeEdge(edgeItr
);
411 bool tryNormaliseEdgeMatrix(const GraphEdgeIterator
&edgeItr
) {
413 Matrix
&edgeCosts
= g
.getEdgeCosts(edgeItr
);
414 Vector
&uCosts
= g
.getNodeCosts(g
.getEdgeNode1Itr(edgeItr
)),
415 &vCosts
= g
.getNodeCosts(g
.getEdgeNode2Itr(edgeItr
));
417 for (unsigned r
= 0; r
< edgeCosts
.getRows(); ++r
) {
418 PBQPNum rowMin
= edgeCosts
.getRowMin(r
);
420 if (rowMin
!= std::numeric_limits
<PBQPNum
>::infinity()) {
421 edgeCosts
.subFromRow(r
, rowMin
);
424 edgeCosts
.setRow(r
, 0);
428 for (unsigned c
= 0; c
< edgeCosts
.getCols(); ++c
) {
429 PBQPNum colMin
= edgeCosts
.getColMin(c
);
431 if (colMin
!= std::numeric_limits
<PBQPNum
>::infinity()) {
432 edgeCosts
.subFromCol(c
, colMin
);
435 edgeCosts
.setCol(c
, 0);
439 return edgeCosts
.isZero();
444 heuristic
.initialise(*this);
449 for (GraphEdgeIterator edgeItr
= g
.edgesBegin(), edgeEnd
= g
.edgesEnd();
450 edgeItr
!= edgeEnd
; ++edgeItr
) {
451 g
.getEdgeData(edgeItr
).setup(edgeItr
);
455 void setupBuckets() {
456 for (GraphNodeIterator nodeItr
= g
.nodesBegin(), nodeEnd
= g
.nodesEnd();
457 nodeItr
!= nodeEnd
; ++nodeItr
) {
458 addToBucket(nodeItr
);
462 void computeSolution() {
463 assert(g
.areNodeIDsValid() &&
464 "Nodes cannot be added/removed during reduction.");
467 computeTrivialSolutions();
471 void printNode(const GraphNodeIterator
&nodeItr
) {
472 llvm::errs() << "Node " << g
.getNodeID(nodeItr
) << " (" << &*nodeItr
<< "):\n"
473 << " costs = " << g
.getNodeCosts(nodeItr
) << "\n"
474 << " link degree = " << g
.getNodeData(nodeItr
).getLinkDegree() << "\n"
477 for (typename
HSIT::NodeData::AdjLinkIterator
478 aeItr
= g
.getNodeData(nodeItr
).adjLinksBegin(),
479 aeEnd
= g
.getNodeData(nodeItr
).adjLinksEnd();
480 aeItr
!= aeEnd
; ++aeItr
) {
481 llvm::errs() << "(" << g
.getNodeID(g
.getEdgeNode1Itr(*aeItr
))
482 << ", " << g
.getNodeID(g
.getEdgeNode2Itr(*aeItr
))
485 llvm::errs() << "]\n";
489 llvm::errs() << "\n";
491 for (GraphNodeIterator nodeItr
= g
.nodesBegin(), nodeEnd
= g
.nodesEnd();
492 nodeItr
!= nodeEnd
; ++nodeItr
) {
496 NodeList
* buckets
[] = { &r0Bucket
, &r1Bucket
, &r2Bucket
};
498 for (unsigned b
= 0; b
< 3; ++b
) {
499 NodeList
&bucket
= *buckets
[b
];
501 llvm::errs() << "Bucket " << b
<< ": [ ";
503 for (NodeListIterator nItr
= bucket
.begin(), nEnd
= bucket
.end();
504 nItr
!= nEnd
; ++nItr
) {
505 llvm::errs() << g
.getNodeID(*nItr
) << " ";
508 llvm::errs() << "]\n";
511 llvm::errs() << "Stack: [ ";
512 for (NodeStackIterator nsItr
= stack
.begin(), nsEnd
= stack
.end();
513 nsItr
!= nsEnd
; ++nsItr
) {
514 llvm::errs() << g
.getNodeID(*nsItr
) << " ";
516 llvm::errs() << "]\n";
520 bool reductionFinished
= r1Bucket
.empty() && r2Bucket
.empty() &&
521 heuristic
.rNBucketEmpty();
523 while (!reductionFinished
) {
525 if (!r1Bucket
.empty()) {
528 else if (!r2Bucket
.empty()) {
531 else if (!heuristic
.rNBucketEmpty()) {
532 solution
.setProvedOptimal(false);
533 solution
.incRNReductions();
534 heuristic
.processRN();
536 else reductionFinished
= true;
543 // Remove the first node in the R0 bucket:
544 GraphNodeIterator xNodeItr
= r1Bucket
.front();
545 r1Bucket
.pop_front();
547 solution
.incR1Reductions();
549 //llvm::errs() << "Applying R1 to " << g.getNodeID(xNodeItr) << "\n";
551 assert((g
.getNodeData(xNodeItr
).getLinkDegree() == 1) &&
552 "Node in R1 bucket has degree != 1");
554 GraphEdgeIterator edgeItr
= *g
.getNodeData(xNodeItr
).adjLinksBegin();
556 const Matrix
&edgeCosts
= g
.getEdgeCosts(edgeItr
);
558 const Vector
&xCosts
= g
.getNodeCosts(xNodeItr
);
559 unsigned xLen
= xCosts
.getLength();
561 // Duplicate a little code to avoid transposing matrices:
562 if (xNodeItr
== g
.getEdgeNode1Itr(edgeItr
)) {
563 GraphNodeIterator yNodeItr
= g
.getEdgeNode2Itr(edgeItr
);
564 Vector
&yCosts
= g
.getNodeCosts(yNodeItr
);
565 unsigned yLen
= yCosts
.getLength();
567 for (unsigned j
= 0; j
< yLen
; ++j
) {
568 PBQPNum min
= edgeCosts
[0][j
] + xCosts
[0];
569 for (unsigned i
= 1; i
< xLen
; ++i
) {
570 PBQPNum c
= edgeCosts
[i
][j
] + xCosts
[i
];
578 GraphNodeIterator yNodeItr
= g
.getEdgeNode1Itr(edgeItr
);
579 Vector
&yCosts
= g
.getNodeCosts(yNodeItr
);
580 unsigned yLen
= yCosts
.getLength();
582 for (unsigned i
= 0; i
< yLen
; ++i
) {
583 PBQPNum min
= edgeCosts
[i
][0] + xCosts
[0];
585 for (unsigned j
= 1; j
< xLen
; ++j
) {
586 PBQPNum c
= edgeCosts
[i
][j
] + xCosts
[j
];
594 unlinkNode(xNodeItr
);
600 GraphNodeIterator xNodeItr
= r2Bucket
.front();
601 r2Bucket
.pop_front();
603 solution
.incR2Reductions();
605 // Unlink is unsafe here. At some point it may optimistically more a node
606 // to a lower-degree list when its degree will later rise, or vice versa,
607 // violating the assumption that node degrees monotonically decrease
608 // during the reduction phase. Instead we'll bucket shuffle manually.
611 assert((g
.getNodeData(xNodeItr
).getLinkDegree() == 2) &&
612 "Node in R2 bucket has degree != 2");
614 const Vector
&xCosts
= g
.getNodeCosts(xNodeItr
);
616 typename
NodeData::AdjLinkIterator tempItr
=
617 g
.getNodeData(xNodeItr
).adjLinksBegin();
619 GraphEdgeIterator yxEdgeItr
= *tempItr
,
620 zxEdgeItr
= *(++tempItr
);
622 GraphNodeIterator yNodeItr
= g
.getEdgeOtherNode(yxEdgeItr
, xNodeItr
),
623 zNodeItr
= g
.getEdgeOtherNode(zxEdgeItr
, xNodeItr
);
625 removeFromBucket(yNodeItr
);
626 removeFromBucket(zNodeItr
);
628 removeLink(yxEdgeItr
, yNodeItr
);
629 removeLink(zxEdgeItr
, zNodeItr
);
631 // Graph some of the costs:
632 bool flipEdge1
= (g
.getEdgeNode1Itr(yxEdgeItr
) == xNodeItr
),
633 flipEdge2
= (g
.getEdgeNode1Itr(zxEdgeItr
) == xNodeItr
);
635 const Matrix
*yxCosts
= flipEdge1
?
636 new Matrix(g
.getEdgeCosts(yxEdgeItr
).transpose()) :
637 &g
.getEdgeCosts(yxEdgeItr
),
638 *zxCosts
= flipEdge2
?
639 new Matrix(g
.getEdgeCosts(zxEdgeItr
).transpose()) :
640 &g
.getEdgeCosts(zxEdgeItr
);
642 unsigned xLen
= xCosts
.getLength(),
643 yLen
= yxCosts
->getRows(),
644 zLen
= zxCosts
->getRows();
647 Matrix
delta(yLen
, zLen
);
649 for (unsigned i
= 0; i
< yLen
; ++i
) {
650 for (unsigned j
= 0; j
< zLen
; ++j
) {
651 PBQPNum min
= (*yxCosts
)[i
][0] + (*zxCosts
)[j
][0] + xCosts
[0];
652 for (unsigned k
= 1; k
< xLen
; ++k
) {
653 PBQPNum c
= (*yxCosts
)[i
][k
] + (*zxCosts
)[j
][k
] + xCosts
[k
];
668 // Deal with the potentially induced yz edge.
669 GraphEdgeIterator yzEdgeItr
= g
.findEdge(yNodeItr
, zNodeItr
);
670 if (yzEdgeItr
== g
.edgesEnd()) {
671 yzEdgeItr
= g
.addEdge(yNodeItr
, zNodeItr
, delta
, EdgeData(g
));
674 // There was an edge, but we're going to screw with it. Delete the old
675 // link, update the costs. We'll re-link it later.
676 removeLinkR2(yzEdgeItr
);
677 g
.getEdgeCosts(yzEdgeItr
) +=
678 (yNodeItr
== g
.getEdgeNode1Itr(yzEdgeItr
)) ?
679 delta
: delta
.transpose();
682 bool nullCostEdge
= tryNormaliseEdgeMatrix(yzEdgeItr
);
684 // Nulled the edge, remove it entirely.
686 g
.removeEdge(yzEdgeItr
);
689 // Edge remains - re-link it.
693 addToBucket(yNodeItr
);
694 addToBucket(zNodeItr
);
697 void computeTrivialSolutions() {
699 for (NodeListIterator r0Itr
= r0Bucket
.begin(), r0End
= r0Bucket
.end();
700 r0Itr
!= r0End
; ++r0Itr
) {
701 GraphNodeIterator nodeItr
= *r0Itr
;
703 solution
.incR0Reductions();
704 setSolution(nodeItr
, g
.getNodeCosts(nodeItr
).minIndex());
709 void backpropagate() {
710 while (!stack
.empty()) {
711 computeSolution(stack
.back());
716 void computeSolution(const GraphNodeIterator
&nodeItr
) {
718 NodeData
&nodeData
= g
.getNodeData(nodeItr
);
720 Vector
v(g
.getNodeCosts(nodeItr
));
722 // Solve based on existing links.
723 for (typename
NodeData::AdjLinkIterator
724 solvedLinkItr
= nodeData
.solvedLinksBegin(),
725 solvedLinkEnd
= nodeData
.solvedLinksEnd();
726 solvedLinkItr
!= solvedLinkEnd
; ++solvedLinkItr
) {
728 GraphEdgeIterator
solvedEdgeItr(*solvedLinkItr
);
729 Matrix
&edgeCosts
= g
.getEdgeCosts(solvedEdgeItr
);
731 if (nodeItr
== g
.getEdgeNode1Itr(solvedEdgeItr
)) {
732 GraphNodeIterator
adjNode(g
.getEdgeNode2Itr(solvedEdgeItr
));
733 unsigned adjSolution
=
734 solution
.getSelection(g
.getNodeID(adjNode
));
735 v
+= edgeCosts
.getColAsVector(adjSolution
);
738 GraphNodeIterator
adjNode(g
.getEdgeNode1Itr(solvedEdgeItr
));
739 unsigned adjSolution
=
740 solution
.getSelection(g
.getNodeID(adjNode
));
741 v
+= edgeCosts
.getRowAsVector(adjSolution
);
746 setSolution(nodeItr
, v
.minIndex());
749 void computeSolutionCost(const SimpleGraph
&orig
) {
752 for (SimpleGraph::ConstNodeIterator
753 nodeItr
= orig
.nodesBegin(), nodeEnd
= orig
.nodesEnd();
754 nodeItr
!= nodeEnd
; ++nodeItr
) {
756 unsigned nodeId
= orig
.getNodeID(nodeItr
);
758 cost
+= orig
.getNodeCosts(nodeItr
)[solution
.getSelection(nodeId
)];
761 for (SimpleGraph::ConstEdgeIterator
762 edgeItr
= orig
.edgesBegin(), edgeEnd
= orig
.edgesEnd();
763 edgeItr
!= edgeEnd
; ++edgeItr
) {
765 SimpleGraph::ConstNodeIterator n1
= orig
.getEdgeNode1Itr(edgeItr
),
766 n2
= orig
.getEdgeNode2Itr(edgeItr
);
767 unsigned sol1
= solution
.getSelection(orig
.getNodeID(n1
)),
768 sol2
= solution
.getSelection(orig
.getNodeID(n2
));
770 cost
+= orig
.getEdgeCosts(edgeItr
)[sol1
][sol2
];
773 solution
.setSolutionCost(cost
);
778 template <typename Heuristic
>
779 class HeuristicSolver
: public Solver
{
781 Solution
solve(const SimpleGraph
&g
) const {
782 HeuristicSolverImpl
<Heuristic
> solverImpl(g
);
783 return solverImpl
.getSolution();
789 #endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H