blob: 5066685a19d90e6a3daa291b683760f552cf51be [file] [log] [blame]
Lang Hames030c4bf2010-01-26 04:49:58 +00001//===-- HeuristicSolver.h - Heuristic PBQP Solver --------------*- C++ -*-===//
Lang Hamescaaf1202009-08-07 00:25:12 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
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.
13//
14//===----------------------------------------------------------------------===//
15
Lang Hames6699fb22009-08-06 23:32:48 +000016#ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
17#define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
18
Lang Hames030c4bf2010-01-26 04:49:58 +000019#include "Graph.h"
20#include "Solution.h"
Bill Wendlingeb753642009-08-15 22:28:08 +000021#include "llvm/Support/raw_ostream.h"
Lang Hames030c4bf2010-01-26 04:49:58 +000022#include <vector>
Lang Hames6699fb22009-08-06 23:32:48 +000023#include <limits>
Lang Hames6699fb22009-08-06 23:32:48 +000024
25namespace PBQP {
26
Lang Hames030c4bf2010-01-26 04:49:58 +000027 /// \brief Heuristic PBQP solver implementation.
Lang Hamescaaf1202009-08-07 00:25:12 +000028 ///
Lang Hames030c4bf2010-01-26 04:49:58 +000029 /// This class should usually be created (and destroyed) indirectly via a call
30 /// to HeuristicSolver<HImpl>::solve(Graph&).
31 /// See the comments for HeuristicSolver.
32 ///
33 /// HeuristicSolverImpl provides the R0, R1 and R2 reduction rules,
34 /// backpropagation phase, and maintains the internal copy of the graph on
35 /// which the reduction is carried out (the original being kept to facilitate
36 /// backpropagation).
37 template <typename HImpl>
38 class HeuristicSolverImpl {
39 private:
Lang Hames6699fb22009-08-06 23:32:48 +000040
Lang Hames030c4bf2010-01-26 04:49:58 +000041 typedef typename HImpl::NodeData HeuristicNodeData;
42 typedef typename HImpl::EdgeData HeuristicEdgeData;
Lang Hames6699fb22009-08-06 23:32:48 +000043
Lang Hames030c4bf2010-01-26 04:49:58 +000044 typedef std::list<Graph::EdgeItr> SolverEdges;
Lang Hames6699fb22009-08-06 23:32:48 +000045
Lang Hames030c4bf2010-01-26 04:49:58 +000046 public:
47
48 /// \brief Iterator type for edges in the solver graph.
49 typedef SolverEdges::iterator SolverEdgeItr;
Lang Hames6699fb22009-08-06 23:32:48 +000050
Lang Hames030c4bf2010-01-26 04:49:58 +000051 private:
Lang Hames6699fb22009-08-06 23:32:48 +000052
Lang Hames030c4bf2010-01-26 04:49:58 +000053 class NodeData {
54 public:
55 NodeData() : solverDegree(0) {}
Lang Hames6699fb22009-08-06 23:32:48 +000056
Lang Hames030c4bf2010-01-26 04:49:58 +000057 HeuristicNodeData& getHeuristicData() { return hData; }
Lang Hames6699fb22009-08-06 23:32:48 +000058
Lang Hames030c4bf2010-01-26 04:49:58 +000059 SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) {
60 ++solverDegree;
61 return solverEdges.insert(solverEdges.end(), eItr);
Lang Hames6699fb22009-08-06 23:32:48 +000062 }
63
Lang Hames030c4bf2010-01-26 04:49:58 +000064 void removeSolverEdge(SolverEdgeItr seItr) {
65 --solverDegree;
66 solverEdges.erase(seItr);
Lang Hames6699fb22009-08-06 23:32:48 +000067 }
Lang Hames030c4bf2010-01-26 04:49:58 +000068
69 SolverEdgeItr solverEdgesBegin() { return solverEdges.begin(); }
70 SolverEdgeItr solverEdgesEnd() { return solverEdges.end(); }
71 unsigned getSolverDegree() const { return solverDegree; }
72 void clearSolverEdges() {
73 solverDegree = 0;
74 solverEdges.clear();
Lang Hames6699fb22009-08-06 23:32:48 +000075 }
Lang Hames6699fb22009-08-06 23:32:48 +000076
Lang Hames030c4bf2010-01-26 04:49:58 +000077 private:
78 HeuristicNodeData hData;
79 unsigned solverDegree;
80 SolverEdges solverEdges;
81 };
82
83 class EdgeData {
84 public:
85 HeuristicEdgeData& getHeuristicData() { return hData; }
Lang Hames6699fb22009-08-06 23:32:48 +000086
Lang Hames030c4bf2010-01-26 04:49:58 +000087 void setN1SolverEdgeItr(SolverEdgeItr n1SolverEdgeItr) {
88 this->n1SolverEdgeItr = n1SolverEdgeItr;
89 }
Lang Hames6699fb22009-08-06 23:32:48 +000090
Lang Hames030c4bf2010-01-26 04:49:58 +000091 SolverEdgeItr getN1SolverEdgeItr() { return n1SolverEdgeItr; }
Lang Hames6699fb22009-08-06 23:32:48 +000092
Lang Hames030c4bf2010-01-26 04:49:58 +000093 void setN2SolverEdgeItr(SolverEdgeItr n2SolverEdgeItr){
94 this->n2SolverEdgeItr = n2SolverEdgeItr;
95 }
Lang Hames6699fb22009-08-06 23:32:48 +000096
Lang Hames030c4bf2010-01-26 04:49:58 +000097 SolverEdgeItr getN2SolverEdgeItr() { return n2SolverEdgeItr; }
Lang Hames6699fb22009-08-06 23:32:48 +000098
Lang Hames030c4bf2010-01-26 04:49:58 +000099 private:
Lang Hames6699fb22009-08-06 23:32:48 +0000100
Lang Hames030c4bf2010-01-26 04:49:58 +0000101 HeuristicEdgeData hData;
102 SolverEdgeItr n1SolverEdgeItr, n2SolverEdgeItr;
103 };
Lang Hames6699fb22009-08-06 23:32:48 +0000104
Lang Hames030c4bf2010-01-26 04:49:58 +0000105 Graph &g;
106 HImpl h;
107 Solution s;
108 std::vector<Graph::NodeItr> stack;
Lang Hames6699fb22009-08-06 23:32:48 +0000109
Lang Hames030c4bf2010-01-26 04:49:58 +0000110 std::vector<NodeData> nodeData;
111 std::vector<EdgeData> edgeData;
Lang Hames6699fb22009-08-06 23:32:48 +0000112
Lang Hames030c4bf2010-01-26 04:49:58 +0000113 public:
Lang Hames6699fb22009-08-06 23:32:48 +0000114
Lang Hames030c4bf2010-01-26 04:49:58 +0000115 /// \brief Construct a heuristic solver implementation to solve the given
116 /// graph.
117 /// @param g The graph representing the problem instance to be solved.
118 HeuristicSolverImpl(Graph &g) : g(g), h(*this) {}
119
120 /// \brief Get the graph being solved by this solver.
121 /// @return The graph representing the problem instance being solved by this
122 /// solver.
123 Graph& getGraph() { return g; }
124
125 /// \brief Get the heuristic data attached to the given node.
126 /// @param nItr Node iterator.
127 /// @return The heuristic data attached to the given node.
128 HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) {
129 return getSolverNodeData(nItr).getHeuristicData();
130 }
131
132 /// \brief Get the heuristic data attached to the given edge.
133 /// @param eItr Edge iterator.
134 /// @return The heuristic data attached to the given node.
135 HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) {
136 return getSolverEdgeData(eItr).getHeuristicData();
137 }
138
139 /// \brief Begin iterator for the set of edges adjacent to the given node in
140 /// the solver graph.
141 /// @param nItr Node iterator.
142 /// @return Begin iterator for the set of edges adjacent to the given node
143 /// in the solver graph.
144 SolverEdgeItr solverEdgesBegin(Graph::NodeItr nItr) {
145 return getSolverNodeData(nItr).solverEdgesBegin();
146 }
147
148 /// \brief End iterator for the set of edges adjacent to the given node in
149 /// the solver graph.
150 /// @param nItr Node iterator.
151 /// @return End iterator for the set of edges adjacent to the given node in
152 /// the solver graph.
153 SolverEdgeItr solverEdgesEnd(Graph::NodeItr nItr) {
154 return getSolverNodeData(nItr).solverEdgesEnd();
155 }
156
157 /// \brief Remove a node from the solver graph.
158 /// @param eItr Edge iterator for edge to be removed.
159 ///
160 /// Does <i>not</i> notify the heuristic of the removal. That should be
161 /// done manually if necessary.
162 void removeSolverEdge(Graph::EdgeItr eItr) {
163 EdgeData &eData = getSolverEdgeData(eItr);
164 NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)),
165 &n2Data = getSolverNodeData(g.getEdgeNode2(eItr));
166
167 n1Data.removeSolverEdge(eData.getN1SolverEdgeItr());
168 n2Data.removeSolverEdge(eData.getN2SolverEdgeItr());
169 }
170
171 /// \brief Compute a solution to the PBQP problem instance with which this
172 /// heuristic solver was constructed.
173 /// @return A solution to the PBQP problem.
174 ///
175 /// Performs the full PBQP heuristic solver algorithm, including setup,
176 /// calls to the heuristic (which will call back to the reduction rules in
177 /// this class), and cleanup.
178 Solution computeSolution() {
179 setup();
180 h.setup();
181 h.reduce();
182 backpropagate();
183 h.cleanup();
184 cleanup();
185 return s;
186 }
187
188 /// \brief Add to the end of the stack.
189 /// @param nItr Node iterator to add to the reduction stack.
190 void pushToStack(Graph::NodeItr nItr) {
191 getSolverNodeData(nItr).clearSolverEdges();
192 stack.push_back(nItr);
193 }
194
195 /// \brief Returns the solver degree of the given node.
196 /// @param nItr Node iterator for which degree is requested.
197 /// @return Node degree in the <i>solver</i> graph (not the original graph).
198 unsigned getSolverDegree(Graph::NodeItr nItr) {
199 return getSolverNodeData(nItr).getSolverDegree();
200 }
201
202 /// \brief Set the solution of the given node.
203 /// @param nItr Node iterator to set solution for.
204 /// @param selection Selection for node.
205 void setSolution(const Graph::NodeItr &nItr, unsigned selection) {
206 s.setSelection(nItr, selection);
207
208 for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr),
209 aeEnd = g.adjEdgesEnd(nItr);
210 aeItr != aeEnd; ++aeItr) {
211 Graph::EdgeItr eItr(*aeItr);
212 Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr));
213 getSolverNodeData(anItr).addSolverEdge(eItr);
Lang Hames6699fb22009-08-06 23:32:48 +0000214 }
215 }
Lang Hames030c4bf2010-01-26 04:49:58 +0000216
217 /// \brief Apply rule R0.
218 /// @param nItr Node iterator for node to apply R0 to.
219 ///
220 /// Node will be automatically pushed to the solver stack.
221 void applyR0(Graph::NodeItr nItr) {
222 assert(getSolverNodeData(nItr).getSolverDegree() == 0 &&
223 "R0 applied to node with degree != 0.");
224
225 // Nothing to do. Just push the node onto the reduction stack.
226 pushToStack(nItr);
227 }
228
229 /// \brief Apply rule R1.
230 /// @param nItr Node iterator for node to apply R1 to.
231 ///
232 /// Node will be automatically pushed to the solver stack.
233 void applyR1(Graph::NodeItr xnItr) {
234 NodeData &nd = getSolverNodeData(xnItr);
235 assert(nd.getSolverDegree() == 1 &&
236 "R1 applied to node with degree != 1.");
237
238 Graph::EdgeItr eItr = *nd.solverEdgesBegin();
239
240 const Matrix &eCosts = g.getEdgeCosts(eItr);
241 const Vector &xCosts = g.getNodeCosts(xnItr);
242
243 // Duplicate a little to avoid transposing matrices.
244 if (xnItr == g.getEdgeNode1(eItr)) {
245 Graph::NodeItr ynItr = g.getEdgeNode2(eItr);
246 Vector &yCosts = g.getNodeCosts(ynItr);
247 for (unsigned j = 0; j < yCosts.getLength(); ++j) {
248 PBQPNum min = eCosts[0][j] + xCosts[0];
249 for (unsigned i = 1; i < xCosts.getLength(); ++i) {
250 PBQPNum c = eCosts[i][j] + xCosts[i];
251 if (c < min)
252 min = c;
253 }
254 yCosts[j] += min;
255 }
256 h.handleRemoveEdge(eItr, ynItr);
257 } else {
258 Graph::NodeItr ynItr = g.getEdgeNode1(eItr);
259 Vector &yCosts = g.getNodeCosts(ynItr);
260 for (unsigned i = 0; i < yCosts.getLength(); ++i) {
261 PBQPNum min = eCosts[i][0] + xCosts[0];
262 for (unsigned j = 1; j < xCosts.getLength(); ++j) {
263 PBQPNum c = eCosts[i][j] + xCosts[j];
264 if (c < min)
265 min = c;
266 }
267 yCosts[i] += min;
268 }
269 h.handleRemoveEdge(eItr, ynItr);
270 }
271 removeSolverEdge(eItr);
272 assert(nd.getSolverDegree() == 0 &&
273 "Degree 1 with edge removed should be 0.");
274 pushToStack(xnItr);
275 }
276
277 /// \brief Apply rule R2.
278 /// @param nItr Node iterator for node to apply R2 to.
279 ///
280 /// Node will be automatically pushed to the solver stack.
281 void applyR2(Graph::NodeItr xnItr) {
282 assert(getSolverNodeData(xnItr).getSolverDegree() == 2 &&
283 "R2 applied to node with degree != 2.");
284
285 NodeData &nd = getSolverNodeData(xnItr);
286 const Vector &xCosts = g.getNodeCosts(xnItr);
287
288 SolverEdgeItr aeItr = nd.solverEdgesBegin();
289 Graph::EdgeItr yxeItr = *aeItr,
290 zxeItr = *(++aeItr);
291
292 Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr),
293 znItr = g.getEdgeOtherNode(zxeItr, xnItr);
294
295 bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr),
296 flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr);
297
298 const Matrix *yxeCosts = flipEdge1 ?
299 new Matrix(g.getEdgeCosts(yxeItr).transpose()) :
300 &g.getEdgeCosts(yxeItr);
301
302 const Matrix *zxeCosts = flipEdge2 ?
303 new Matrix(g.getEdgeCosts(zxeItr).transpose()) :
304 &g.getEdgeCosts(zxeItr);
305
306 unsigned xLen = xCosts.getLength(),
307 yLen = yxeCosts->getRows(),
308 zLen = zxeCosts->getRows();
309
310 Matrix delta(yLen, zLen);
Lang Hames6699fb22009-08-06 23:32:48 +0000311
312 for (unsigned i = 0; i < yLen; ++i) {
Lang Hames030c4bf2010-01-26 04:49:58 +0000313 for (unsigned j = 0; j < zLen; ++j) {
314 PBQPNum min = (*yxeCosts)[i][0] + (*zxeCosts)[j][0] + xCosts[0];
315 for (unsigned k = 1; k < xLen; ++k) {
316 PBQPNum c = (*yxeCosts)[i][k] + (*zxeCosts)[j][k] + xCosts[k];
317 if (c < min) {
318 min = c;
319 }
320 }
321 delta[i][j] = min;
Lang Hames6699fb22009-08-06 23:32:48 +0000322 }
Lang Hames030c4bf2010-01-26 04:49:58 +0000323 }
324
325 if (flipEdge1)
326 delete yxeCosts;
327
328 if (flipEdge2)
329 delete zxeCosts;
330
331 Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr);
332 bool addedEdge = false;
333
334 if (yzeItr == g.edgesEnd()) {
335 yzeItr = g.addEdge(ynItr, znItr, delta);
336 addedEdge = true;
337 } else {
338 Matrix &yzeCosts = g.getEdgeCosts(yzeItr);
339 h.preUpdateEdgeCosts(yzeItr);
340 if (ynItr == g.getEdgeNode1(yzeItr)) {
341 yzeCosts += delta;
342 } else {
343 yzeCosts += delta.transpose();
344 }
345 }
346
347 bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr);
348
349 if (!addedEdge) {
350 // If we modified the edge costs let the heuristic know.
351 h.postUpdateEdgeCosts(yzeItr);
352 }
353
354 if (nullCostEdge) {
355 // If this edge ended up null remove it.
356 if (!addedEdge) {
357 // We didn't just add it, so we need to notify the heuristic
358 // and remove it from the solver.
359 h.handleRemoveEdge(yzeItr, ynItr);
360 h.handleRemoveEdge(yzeItr, znItr);
361 removeSolverEdge(yzeItr);
362 }
363 g.removeEdge(yzeItr);
364 } else if (addedEdge) {
365 // If the edge was added, and non-null, finish setting it up, add it to
366 // the solver & notify heuristic.
367 edgeData.push_back(EdgeData());
368 g.setEdgeData(yzeItr, &edgeData.back());
369 addSolverEdge(yzeItr);
370 h.handleAddEdge(yzeItr);
371 }
372
373 h.handleRemoveEdge(yxeItr, ynItr);
374 removeSolverEdge(yxeItr);
375 h.handleRemoveEdge(zxeItr, znItr);
376 removeSolverEdge(zxeItr);
377
378 pushToStack(xnItr);
379 }
380
381 private:
382
383 NodeData& getSolverNodeData(Graph::NodeItr nItr) {
384 return *static_cast<NodeData*>(g.getNodeData(nItr));
385 }
386
387 EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) {
388 return *static_cast<EdgeData*>(g.getEdgeData(eItr));
389 }
390
391 void addSolverEdge(Graph::EdgeItr eItr) {
392 EdgeData &eData = getSolverEdgeData(eItr);
393 NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)),
394 &n2Data = getSolverNodeData(g.getEdgeNode2(eItr));
395
396 eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr));
397 eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr));
398 }
399
400 void setup() {
401 if (h.solverRunSimplify()) {
402 simplify();
403 }
404
405 // Reserve space for the node and edge data.
406 nodeData.resize(g.getNumNodes());
407 edgeData.resize(g.getNumEdges());
408
409 // Create node data objects.
410 unsigned ndIndex = 0;
411 for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
412 nItr != nEnd; ++nItr, ++ndIndex) {
413 g.setNodeData(nItr, &nodeData[ndIndex]);
414 }
415
416 // Create edge data objects.
417 unsigned edIndex = 0;
418 for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd();
419 eItr != eEnd; ++eItr, ++edIndex) {
420 g.setEdgeData(eItr, &edgeData[edIndex]);
421 addSolverEdge(eItr);
Lang Hames6699fb22009-08-06 23:32:48 +0000422 }
423 }
424
Lang Hames030c4bf2010-01-26 04:49:58 +0000425 void simplify() {
426 disconnectTrivialNodes();
427 eliminateIndependentEdges();
428 }
Lang Hames6699fb22009-08-06 23:32:48 +0000429
Lang Hames030c4bf2010-01-26 04:49:58 +0000430 // Eliminate trivial nodes.
431 void disconnectTrivialNodes() {
432 unsigned numDisconnected = 0;
Lang Hames6699fb22009-08-06 23:32:48 +0000433
Lang Hames030c4bf2010-01-26 04:49:58 +0000434 for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
435 nItr != nEnd; ++nItr) {
Lang Hames6699fb22009-08-06 23:32:48 +0000436
Lang Hames030c4bf2010-01-26 04:49:58 +0000437 if (g.getNodeCosts(nItr).getLength() == 1) {
Lang Hames6699fb22009-08-06 23:32:48 +0000438
Lang Hames030c4bf2010-01-26 04:49:58 +0000439 std::vector<Graph::EdgeItr> edgesToRemove;
Lang Hames6699fb22009-08-06 23:32:48 +0000440
Lang Hames030c4bf2010-01-26 04:49:58 +0000441 for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr),
442 aeEnd = g.adjEdgesEnd(nItr);
443 aeItr != aeEnd; ++aeItr) {
Lang Hames6699fb22009-08-06 23:32:48 +0000444
Lang Hames030c4bf2010-01-26 04:49:58 +0000445 Graph::EdgeItr eItr = *aeItr;
Lang Hames6699fb22009-08-06 23:32:48 +0000446
Lang Hames030c4bf2010-01-26 04:49:58 +0000447 if (g.getEdgeNode1(eItr) == nItr) {
448 Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr);
449 g.getNodeCosts(otherNodeItr) +=
450 g.getEdgeCosts(eItr).getRowAsVector(0);
451 }
452 else {
453 Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr);
454 g.getNodeCosts(otherNodeItr) +=
455 g.getEdgeCosts(eItr).getColAsVector(0);
456 }
Lang Hames6699fb22009-08-06 23:32:48 +0000457
Lang Hames030c4bf2010-01-26 04:49:58 +0000458 edgesToRemove.push_back(eItr);
459 }
Lang Hames6699fb22009-08-06 23:32:48 +0000460
Lang Hames030c4bf2010-01-26 04:49:58 +0000461 if (!edgesToRemove.empty())
462 ++numDisconnected;
Lang Hames6699fb22009-08-06 23:32:48 +0000463
Lang Hames030c4bf2010-01-26 04:49:58 +0000464 while (!edgesToRemove.empty()) {
465 g.removeEdge(edgesToRemove.back());
466 edgesToRemove.pop_back();
Lang Hames6699fb22009-08-06 23:32:48 +0000467 }
468 }
Lang Hames6699fb22009-08-06 23:32:48 +0000469 }
470 }
471
Lang Hames030c4bf2010-01-26 04:49:58 +0000472 void eliminateIndependentEdges() {
473 std::vector<Graph::EdgeItr> edgesToProcess;
474 unsigned numEliminated = 0;
Lang Hames6699fb22009-08-06 23:32:48 +0000475
Lang Hames030c4bf2010-01-26 04:49:58 +0000476 for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd();
477 eItr != eEnd; ++eItr) {
478 edgesToProcess.push_back(eItr);
Lang Hames6699fb22009-08-06 23:32:48 +0000479 }
480
Lang Hames030c4bf2010-01-26 04:49:58 +0000481 while (!edgesToProcess.empty()) {
482 if (tryToEliminateEdge(edgesToProcess.back()))
483 ++numEliminated;
484 edgesToProcess.pop_back();
485 }
Lang Hames6699fb22009-08-06 23:32:48 +0000486 }
487
Lang Hames030c4bf2010-01-26 04:49:58 +0000488 bool tryToEliminateEdge(Graph::EdgeItr eItr) {
489 if (tryNormaliseEdgeMatrix(eItr)) {
490 g.removeEdge(eItr);
491 return true;
492 }
493 return false;
Lang Hames6699fb22009-08-06 23:32:48 +0000494 }
495
Lang Hames030c4bf2010-01-26 04:49:58 +0000496 bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) {
Lang Hames6699fb22009-08-06 23:32:48 +0000497
Lang Hames030c4bf2010-01-26 04:49:58 +0000498 Matrix &edgeCosts = g.getEdgeCosts(eItr);
499 Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)),
500 &vCosts = g.getNodeCosts(g.getEdgeNode2(eItr));
Lang Hames6699fb22009-08-06 23:32:48 +0000501
Lang Hames030c4bf2010-01-26 04:49:58 +0000502 for (unsigned r = 0; r < edgeCosts.getRows(); ++r) {
503 PBQPNum rowMin = edgeCosts.getRowMin(r);
504 uCosts[r] += rowMin;
505 if (rowMin != std::numeric_limits<PBQPNum>::infinity()) {
506 edgeCosts.subFromRow(r, rowMin);
507 }
508 else {
509 edgeCosts.setRow(r, 0);
510 }
511 }
512
513 for (unsigned c = 0; c < edgeCosts.getCols(); ++c) {
514 PBQPNum colMin = edgeCosts.getColMin(c);
515 vCosts[c] += colMin;
516 if (colMin != std::numeric_limits<PBQPNum>::infinity()) {
517 edgeCosts.subFromCol(c, colMin);
518 }
519 else {
520 edgeCosts.setCol(c, 0);
521 }
522 }
523
524 return edgeCosts.isZero();
Lang Hames6699fb22009-08-06 23:32:48 +0000525 }
526
Lang Hames030c4bf2010-01-26 04:49:58 +0000527 void backpropagate() {
528 while (!stack.empty()) {
529 computeSolution(stack.back());
530 stack.pop_back();
531 }
532 }
Lang Hames6699fb22009-08-06 23:32:48 +0000533
Lang Hames030c4bf2010-01-26 04:49:58 +0000534 void computeSolution(Graph::NodeItr nItr) {
Lang Hames6699fb22009-08-06 23:32:48 +0000535
Lang Hames030c4bf2010-01-26 04:49:58 +0000536 NodeData &nodeData = getSolverNodeData(nItr);
537
538 Vector v(g.getNodeCosts(nItr));
539
540 // Solve based on existing solved edges.
541 for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(),
542 solvedEdgeEnd = nodeData.solverEdgesEnd();
543 solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) {
544
545 Graph::EdgeItr eItr(*solvedEdgeItr);
546 Matrix &edgeCosts = g.getEdgeCosts(eItr);
547
548 if (nItr == g.getEdgeNode1(eItr)) {
549 Graph::NodeItr adjNode(g.getEdgeNode2(eItr));
550 unsigned adjSolution = s.getSelection(adjNode);
551 v += edgeCosts.getColAsVector(adjSolution);
552 }
553 else {
554 Graph::NodeItr adjNode(g.getEdgeNode1(eItr));
555 unsigned adjSolution = s.getSelection(adjNode);
556 v += edgeCosts.getRowAsVector(adjSolution);
557 }
558
559 }
560
561 setSolution(nItr, v.minIndex());
562 }
563
564 void cleanup() {
565 h.cleanup();
566 nodeData.clear();
567 edgeData.clear();
568 }
569 };
570
571 /// \brief PBQP heuristic solver class.
572 ///
573 /// Given a PBQP Graph g representing a PBQP problem, you can find a solution
574 /// by calling
575 /// <tt>Solution s = HeuristicSolver<H>::solve(g);</tt>
576 ///
577 /// The choice of heuristic for the H parameter will affect both the solver
578 /// speed and solution quality. The heuristic should be chosen based on the
579 /// nature of the problem being solved.
580 /// Currently the only solver included with LLVM is the Briggs heuristic for
581 /// register allocation.
582 template <typename HImpl>
583 class HeuristicSolver {
584 public:
585 static Solution solve(Graph &g) {
586 HeuristicSolverImpl<HImpl> hs(g);
587 return hs.computeSolution();
588 }
589 };
Lang Hames6699fb22009-08-06 23:32:48 +0000590
591}
592
593#endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H