LLVM API Documentation
00001 //===----------- ReductionRules.h - Reduction Rules -------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Reduction Rules. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CODEGEN_PBQP_REDUCTIONRULES_H 00015 #define LLVM_CODEGEN_PBQP_REDUCTIONRULES_H 00016 00017 #include "Graph.h" 00018 #include "Math.h" 00019 #include "Solution.h" 00020 00021 namespace PBQP { 00022 00023 /// \brief Reduce a node of degree one. 00024 /// 00025 /// Propagate costs from the given node, which must be of degree one, to its 00026 /// neighbor. Notify the problem domain. 00027 template <typename GraphT> 00028 void applyR1(GraphT &G, typename GraphT::NodeId NId) { 00029 typedef typename GraphT::NodeId NodeId; 00030 typedef typename GraphT::EdgeId EdgeId; 00031 typedef typename GraphT::Vector Vector; 00032 typedef typename GraphT::Matrix Matrix; 00033 typedef typename GraphT::RawVector RawVector; 00034 00035 assert(G.getNodeDegree(NId) == 1 && 00036 "R1 applied to node with degree != 1."); 00037 00038 EdgeId EId = *G.adjEdgeIds(NId).begin(); 00039 NodeId MId = G.getEdgeOtherNodeId(EId, NId); 00040 00041 const Matrix &ECosts = G.getEdgeCosts(EId); 00042 const Vector &XCosts = G.getNodeCosts(NId); 00043 RawVector YCosts = G.getNodeCosts(MId); 00044 00045 // Duplicate a little to avoid transposing matrices. 00046 if (NId == G.getEdgeNode1Id(EId)) { 00047 for (unsigned j = 0; j < YCosts.getLength(); ++j) { 00048 PBQPNum Min = ECosts[0][j] + XCosts[0]; 00049 for (unsigned i = 1; i < XCosts.getLength(); ++i) { 00050 PBQPNum C = ECosts[i][j] + XCosts[i]; 00051 if (C < Min) 00052 Min = C; 00053 } 00054 YCosts[j] += Min; 00055 } 00056 } else { 00057 for (unsigned i = 0; i < YCosts.getLength(); ++i) { 00058 PBQPNum Min = ECosts[i][0] + XCosts[0]; 00059 for (unsigned j = 1; j < XCosts.getLength(); ++j) { 00060 PBQPNum C = ECosts[i][j] + XCosts[j]; 00061 if (C < Min) 00062 Min = C; 00063 } 00064 YCosts[i] += Min; 00065 } 00066 } 00067 G.setNodeCosts(MId, YCosts); 00068 G.disconnectEdge(EId, MId); 00069 } 00070 00071 template <typename GraphT> 00072 void applyR2(GraphT &G, typename GraphT::NodeId NId) { 00073 typedef typename GraphT::NodeId NodeId; 00074 typedef typename GraphT::EdgeId EdgeId; 00075 typedef typename GraphT::Vector Vector; 00076 typedef typename GraphT::Matrix Matrix; 00077 typedef typename GraphT::RawMatrix RawMatrix; 00078 00079 assert(G.getNodeDegree(NId) == 2 && 00080 "R2 applied to node with degree != 2."); 00081 00082 const Vector &XCosts = G.getNodeCosts(NId); 00083 00084 typename GraphT::AdjEdgeItr AEItr = G.adjEdgeIds(NId).begin(); 00085 EdgeId YXEId = *AEItr, 00086 ZXEId = *(++AEItr); 00087 00088 NodeId YNId = G.getEdgeOtherNodeId(YXEId, NId), 00089 ZNId = G.getEdgeOtherNodeId(ZXEId, NId); 00090 00091 bool FlipEdge1 = (G.getEdgeNode1Id(YXEId) == NId), 00092 FlipEdge2 = (G.getEdgeNode1Id(ZXEId) == NId); 00093 00094 const Matrix *YXECosts = FlipEdge1 ? 00095 new Matrix(G.getEdgeCosts(YXEId).transpose()) : 00096 &G.getEdgeCosts(YXEId); 00097 00098 const Matrix *ZXECosts = FlipEdge2 ? 00099 new Matrix(G.getEdgeCosts(ZXEId).transpose()) : 00100 &G.getEdgeCosts(ZXEId); 00101 00102 unsigned XLen = XCosts.getLength(), 00103 YLen = YXECosts->getRows(), 00104 ZLen = ZXECosts->getRows(); 00105 00106 RawMatrix Delta(YLen, ZLen); 00107 00108 for (unsigned i = 0; i < YLen; ++i) { 00109 for (unsigned j = 0; j < ZLen; ++j) { 00110 PBQPNum Min = (*YXECosts)[i][0] + (*ZXECosts)[j][0] + XCosts[0]; 00111 for (unsigned k = 1; k < XLen; ++k) { 00112 PBQPNum C = (*YXECosts)[i][k] + (*ZXECosts)[j][k] + XCosts[k]; 00113 if (C < Min) { 00114 Min = C; 00115 } 00116 } 00117 Delta[i][j] = Min; 00118 } 00119 } 00120 00121 if (FlipEdge1) 00122 delete YXECosts; 00123 00124 if (FlipEdge2) 00125 delete ZXECosts; 00126 00127 EdgeId YZEId = G.findEdge(YNId, ZNId); 00128 00129 if (YZEId == G.invalidEdgeId()) { 00130 YZEId = G.addEdge(YNId, ZNId, Delta); 00131 } else { 00132 const Matrix &YZECosts = G.getEdgeCosts(YZEId); 00133 if (YNId == G.getEdgeNode1Id(YZEId)) { 00134 G.setEdgeCosts(YZEId, Delta + YZECosts); 00135 } else { 00136 G.setEdgeCosts(YZEId, Delta.transpose() + YZECosts); 00137 } 00138 } 00139 00140 G.disconnectEdge(YXEId, YNId); 00141 G.disconnectEdge(ZXEId, ZNId); 00142 00143 // TODO: Try to normalize newly added/modified edge. 00144 } 00145 00146 00147 // \brief Find a solution to a fully reduced graph by backpropagation. 00148 // 00149 // Given a graph and a reduction order, pop each node from the reduction 00150 // order and greedily compute a minimum solution based on the node costs, and 00151 // the dependent costs due to previously solved nodes. 00152 // 00153 // Note - This does not return the graph to its original (pre-reduction) 00154 // state: the existing solvers destructively alter the node and edge 00155 // costs. Given that, the backpropagate function doesn't attempt to 00156 // replace the edges either, but leaves the graph in its reduced 00157 // state. 00158 template <typename GraphT, typename StackT> 00159 Solution backpropagate(GraphT& G, StackT stack) { 00160 typedef GraphBase::NodeId NodeId; 00161 typedef typename GraphT::Matrix Matrix; 00162 typedef typename GraphT::RawVector RawVector; 00163 00164 Solution s; 00165 00166 while (!stack.empty()) { 00167 NodeId NId = stack.back(); 00168 stack.pop_back(); 00169 00170 RawVector v = G.getNodeCosts(NId); 00171 00172 for (auto EId : G.adjEdgeIds(NId)) { 00173 const Matrix& edgeCosts = G.getEdgeCosts(EId); 00174 if (NId == G.getEdgeNode1Id(EId)) { 00175 NodeId mId = G.getEdgeNode2Id(EId); 00176 v += edgeCosts.getColAsVector(s.getSelection(mId)); 00177 } else { 00178 NodeId mId = G.getEdgeNode1Id(EId); 00179 v += edgeCosts.getRowAsVector(s.getSelection(mId)); 00180 } 00181 } 00182 00183 s.setSelection(NId, v.minIndex()); 00184 } 00185 00186 return s; 00187 } 00188 00189 } 00190 00191 #endif