Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 1 | //===--Graph.cpp--- implements Graph class ---------------- ------*- C++ -*--=// |
| 2 | // |
| 3 | // This implements Graph for helping in trace generation |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame] | 4 | // This graph gets used by "ProfilePaths" class |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 5 | // |
| 6 | //===----------------------------------------------------------------------===// |
| 7 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 8 | #include "llvm/Transforms/Instrumentation/Graph.h" |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 9 | #include "llvm/iTerminators.h" |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 10 | #include "llvm/BasicBlock.h" |
Chris Lattner | 3cf3782 | 2002-10-01 22:38:37 +0000 | [diff] [blame] | 11 | #include "Support/Statistic.h" |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 12 | #include <algorithm> |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame] | 13 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 14 | //using std::list; |
| 15 | //using std::set; |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame] | 16 | using std::map; |
| 17 | using std::vector; |
| 18 | using std::cerr; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 19 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 20 | const graphListElement *findNodeInList(const Graph::nodeList &NL, |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 21 | Node *N) { |
| 22 | for(Graph::nodeList::const_iterator NI = NL.begin(), NE=NL.end(); NI != NE; |
| 23 | ++NI) |
| 24 | if (*NI->element== *N) |
| 25 | return &*NI; |
| 26 | return 0; |
| 27 | } |
| 28 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 29 | graphListElement *findNodeInList(Graph::nodeList &NL, Node *N) { |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 30 | for(Graph::nodeList::iterator NI = NL.begin(), NE=NL.end(); NI != NE; ++NI) |
| 31 | if (*NI->element== *N) |
| 32 | return &*NI; |
| 33 | return 0; |
| 34 | } |
| 35 | |
| 36 | //graph constructor with root and exit specified |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 37 | Graph::Graph(std::vector<Node*> n, std::vector<Edge> e, |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 38 | Node *rt, Node *lt){ |
| 39 | strt=rt; |
| 40 | ext=lt; |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 41 | for(vector<Node* >::iterator x=n.begin(), en=n.end(); x!=en; ++x) |
| 42 | //nodes[*x] = list<graphListElement>(); |
| 43 | nodes[*x] = vector<graphListElement>(); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 44 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 45 | for(vector<Edge >::iterator x=e.begin(), en=e.end(); x!=en; ++x){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 46 | Edge ee=*x; |
| 47 | int w=ee.getWeight(); |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 48 | //nodes[ee.getFirst()].push_front(graphListElement(ee.getSecond(),w, ee.getRandId())); |
| 49 | nodes[ee.getFirst()].push_back(graphListElement(ee.getSecond(),w, ee.getRandId())); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | } |
| 53 | |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 54 | //sorting edgelist, called by backEdgeVist ONLY!!! |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 55 | Graph::nodeList &Graph::sortNodeList(Node *par, nodeList &nl, vector<Edge> &be){ |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 56 | assert(par && "null node pointer"); |
| 57 | BasicBlock *bbPar = par->getElement(); |
| 58 | |
| 59 | if(nl.size()<=1) return nl; |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 60 | if(getExit() == par) return nl; |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 61 | |
| 62 | for(nodeList::iterator NLI = nl.begin(), NLE = nl.end()-1; NLI != NLE; ++NLI){ |
| 63 | nodeList::iterator min = NLI; |
| 64 | for(nodeList::iterator LI = NLI+1, LE = nl.end(); LI!=LE; ++LI){ |
| 65 | //if LI < min, min = LI |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 66 | if(min->element->getElement() == LI->element->getElement() && |
| 67 | min->element == getExit()){ |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 68 | |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 69 | //same successors: so might be exit??? |
| 70 | //if it is exit, then see which is backedge |
| 71 | //check if LI is a left back edge! |
| 72 | |
| 73 | TerminatorInst *tti = par->getElement()->getTerminator(); |
| 74 | BranchInst *ti = cast<BranchInst>(tti); |
| 75 | |
| 76 | assert(ti && "not a branch"); |
| 77 | assert(ti->getNumSuccessors()==2 && "less successors!"); |
| 78 | |
| 79 | BasicBlock *tB = ti->getSuccessor(0); |
| 80 | BasicBlock *fB = ti->getSuccessor(1); |
| 81 | //so one of LI or min must be back edge! |
| 82 | //Algo: if succ(0)!=LI (and so !=min) then succ(0) is backedge |
| 83 | //and then see which of min or LI is backedge |
| 84 | //THEN if LI is in be, then min=LI |
| 85 | if(LI->element->getElement() != tB){//so backedge must be made min! |
| 86 | for(vector<Edge>::iterator VBEI = be.begin(), VBEE = be.end(); |
| 87 | VBEI != VBEE; ++VBEI){ |
| 88 | if(VBEI->getRandId() == LI->randId){ |
| 89 | min = LI; |
| 90 | break; |
| 91 | } |
| 92 | else if(VBEI->getRandId() == min->randId) |
| 93 | break; |
| 94 | } |
| 95 | } |
| 96 | else{// if(LI->element->getElement() != fB) |
| 97 | for(vector<Edge>::iterator VBEI = be.begin(), VBEE = be.end(); |
| 98 | VBEI != VBEE; ++VBEI){ |
| 99 | if(VBEI->getRandId() == min->randId){ |
| 100 | min = LI; |
| 101 | break; |
| 102 | } |
| 103 | else if(VBEI->getRandId() == LI->randId) |
| 104 | break; |
| 105 | } |
| 106 | } |
| 107 | } |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 108 | |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 109 | else if (min->element->getElement() != LI->element->getElement()){ |
| 110 | TerminatorInst *tti = par->getElement()->getTerminator(); |
| 111 | BranchInst *ti = cast<BranchInst>(tti); |
| 112 | assert(ti && "not a branch"); |
| 113 | |
| 114 | if(ti->getNumSuccessors()<=1) continue; |
| 115 | |
| 116 | assert(ti->getNumSuccessors()==2 && "less successors!"); |
| 117 | |
| 118 | BasicBlock *tB = ti->getSuccessor(0); |
| 119 | BasicBlock *fB = ti->getSuccessor(1); |
| 120 | |
| 121 | if(tB == LI->element->getElement() || fB == min->element->getElement()) |
| 122 | min = LI; |
| 123 | } |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | graphListElement tmpElmnt = *min; |
| 127 | *min = *NLI; |
| 128 | *NLI = tmpElmnt; |
| 129 | } |
| 130 | return nl; |
| 131 | } |
| 132 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 133 | //check whether graph has an edge |
| 134 | //having an edge simply means that there is an edge in the graph |
| 135 | //which has same endpoints as the given edge |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 136 | bool Graph::hasEdge(Edge ed){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 137 | if(ed.isNull()) |
| 138 | return false; |
| 139 | |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 140 | nodeList &nli= nodes[ed.getFirst()]; //getNodeList(ed.getFirst()); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 141 | Node *nd2=ed.getSecond(); |
| 142 | |
| 143 | return (findNodeInList(nli,nd2)!=NULL); |
| 144 | |
| 145 | } |
| 146 | |
| 147 | |
| 148 | //check whether graph has an edge, with a given wt |
| 149 | //having an edge simply means that there is an edge in the graph |
| 150 | //which has same endpoints as the given edge |
| 151 | //This function checks, moreover, that the wt of edge matches too |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 152 | bool Graph::hasEdgeAndWt(Edge ed){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 153 | if(ed.isNull()) |
| 154 | return false; |
| 155 | |
| 156 | Node *nd2=ed.getSecond(); |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 157 | nodeList nli = nodes[ed.getFirst()];//getNodeList(ed.getFirst()); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 158 | |
| 159 | for(nodeList::iterator NI=nli.begin(), NE=nli.end(); NI!=NE; ++NI) |
| 160 | if(*NI->element == *nd2 && ed.getWeight()==NI->weight) |
| 161 | return true; |
| 162 | |
| 163 | return false; |
| 164 | } |
| 165 | |
| 166 | //add a node |
| 167 | void Graph::addNode(Node *nd){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 168 | vector<Node *> lt=getAllNodes(); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 169 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 170 | for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE;++LI){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 171 | if(**LI==*nd) |
| 172 | return; |
| 173 | } |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 174 | //chng |
| 175 | nodes[nd] =vector<graphListElement>(); //list<graphListElement>(); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | //add an edge |
| 179 | //this adds an edge ONLY when |
| 180 | //the edge to be added doesn not already exist |
| 181 | //we "equate" two edges here only with their |
| 182 | //end points |
| 183 | void Graph::addEdge(Edge ed, int w){ |
| 184 | nodeList &ndList = nodes[ed.getFirst()]; |
| 185 | Node *nd2=ed.getSecond(); |
| 186 | |
| 187 | if(findNodeInList(nodes[ed.getFirst()], nd2)) |
| 188 | return; |
| 189 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 190 | //ndList.push_front(graphListElement(nd2,w, ed.getRandId())); |
| 191 | ndList.push_back(graphListElement(nd2,w, ed.getRandId()));//chng |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 192 | //sortNodeList(ed.getFirst(), ndList); |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 193 | |
| 194 | //sort(ndList.begin(), ndList.end(), NodeListSort()); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | //add an edge EVEN IF such an edge already exists |
| 198 | //this may make a multi-graph |
| 199 | //which does happen when we add dummy edges |
| 200 | //to the graph, for compensating for back-edges |
| 201 | void Graph::addEdgeForce(Edge ed){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 202 | //nodes[ed.getFirst()].push_front(graphListElement(ed.getSecond(), |
| 203 | //ed.getWeight(), ed.getRandId())); |
| 204 | nodes[ed.getFirst()].push_back |
| 205 | (graphListElement(ed.getSecond(), ed.getWeight(), ed.getRandId())); |
| 206 | |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 207 | //sortNodeList(ed.getFirst(), nodes[ed.getFirst()]); |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 208 | //sort(nodes[ed.getFirst()].begin(), nodes[ed.getFirst()].end(), NodeListSort()); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 209 | } |
| 210 | |
| 211 | //remove an edge |
| 212 | //Note that it removes just one edge, |
| 213 | //the first edge that is encountered |
| 214 | void Graph::removeEdge(Edge ed){ |
| 215 | nodeList &ndList = nodes[ed.getFirst()]; |
| 216 | Node &nd2 = *ed.getSecond(); |
| 217 | |
| 218 | for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) { |
| 219 | if(*NI->element == nd2) { |
| 220 | ndList.erase(NI); |
| 221 | break; |
| 222 | } |
| 223 | } |
| 224 | } |
| 225 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 226 | //remove an edge with a given wt |
| 227 | //Note that it removes just one edge, |
| 228 | //the first edge that is encountered |
| 229 | void Graph::removeEdgeWithWt(Edge ed){ |
| 230 | nodeList &ndList = nodes[ed.getFirst()]; |
| 231 | Node &nd2 = *ed.getSecond(); |
| 232 | |
| 233 | for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) { |
| 234 | if(*NI->element == nd2 && NI->weight==ed.getWeight()) { |
| 235 | ndList.erase(NI); |
| 236 | break; |
| 237 | } |
| 238 | } |
| 239 | } |
| 240 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 241 | //set the weight of an edge |
| 242 | void Graph::setWeight(Edge ed){ |
| 243 | graphListElement *El = findNodeInList(nodes[ed.getFirst()], ed.getSecond()); |
| 244 | if (El) |
| 245 | El->weight=ed.getWeight(); |
| 246 | } |
| 247 | |
| 248 | |
| 249 | |
| 250 | //get the list of successor nodes |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 251 | vector<Node *> Graph::getSuccNodes(Node *nd){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 252 | nodeMapTy::const_iterator nli = nodes.find(nd); |
| 253 | assert(nli != nodes.end() && "Node must be in nodes map"); |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 254 | const nodeList &nl = getNodeList(nd);//getSortedNodeList(nd); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 255 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 256 | vector<Node *> lt; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 257 | for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI) |
| 258 | lt.push_back(NI->element); |
| 259 | |
| 260 | return lt; |
| 261 | } |
| 262 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 263 | //get the number of outgoing edges |
| 264 | int Graph::getNumberOfOutgoingEdges(Node *nd) const { |
| 265 | nodeMapTy::const_iterator nli = nodes.find(nd); |
| 266 | assert(nli != nodes.end() && "Node must be in nodes map"); |
| 267 | const nodeList &nl = nli->second; |
| 268 | |
| 269 | int count=0; |
| 270 | for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI) |
| 271 | count++; |
| 272 | |
| 273 | return count; |
| 274 | } |
| 275 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 276 | //get the list of predecessor nodes |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 277 | vector<Node *> Graph::getPredNodes(Node *nd){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 278 | vector<Node *> lt; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 279 | for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){ |
| 280 | Node *lnode=EI->first; |
| 281 | const nodeList &nl = getNodeList(lnode); |
| 282 | |
| 283 | const graphListElement *N = findNodeInList(nl, nd); |
| 284 | if (N) lt.push_back(lnode); |
| 285 | } |
| 286 | return lt; |
| 287 | } |
| 288 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 289 | //get the number of predecessor nodes |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 290 | int Graph::getNumberOfIncomingEdges(Node *nd){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 291 | int count=0; |
| 292 | for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){ |
| 293 | Node *lnode=EI->first; |
| 294 | const nodeList &nl = getNodeList(lnode); |
| 295 | for(Graph::nodeList::const_iterator NI = nl.begin(), NE=nl.end(); NI != NE; |
| 296 | ++NI) |
| 297 | if (*NI->element== *nd) |
| 298 | count++; |
| 299 | } |
| 300 | return count; |
| 301 | } |
| 302 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 303 | //get the list of all the vertices in graph |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 304 | vector<Node *> Graph::getAllNodes() const{ |
| 305 | vector<Node *> lt; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 306 | for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x) |
| 307 | lt.push_back(x->first); |
| 308 | |
| 309 | return lt; |
| 310 | } |
| 311 | |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 312 | //get the list of all the vertices in graph |
| 313 | vector<Node *> Graph::getAllNodes(){ |
| 314 | vector<Node *> lt; |
| 315 | for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x) |
| 316 | lt.push_back(x->first); |
| 317 | |
| 318 | return lt; |
| 319 | } |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 320 | |
| 321 | //class to compare two nodes in graph |
| 322 | //based on their wt: this is used in |
| 323 | //finding the maximal spanning tree |
| 324 | struct compare_nodes { |
| 325 | bool operator()(Node *n1, Node *n2){ |
| 326 | return n1->getWeight() < n2->getWeight(); |
| 327 | } |
| 328 | }; |
| 329 | |
| 330 | |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame] | 331 | static void printNode(Node *nd){ |
| 332 | cerr<<"Node:"<<nd->getElement()->getName()<<"\n"; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 333 | } |
| 334 | |
| 335 | //Get the Maximal spanning tree (also a graph) |
| 336 | //of the graph |
| 337 | Graph* Graph::getMaxSpanningTree(){ |
| 338 | //assume connected graph |
| 339 | |
| 340 | Graph *st=new Graph();//max spanning tree, undirected edges |
| 341 | int inf=9999999;//largest key |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 342 | vector<Node *> lt = getAllNodes(); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 343 | |
| 344 | //initially put all vertices in vector vt |
| 345 | //assign wt(root)=0 |
| 346 | //wt(others)=infinity |
| 347 | // |
| 348 | //now: |
| 349 | //pull out u: a vertex frm vt of min wt |
| 350 | //for all vertices w in vt, |
| 351 | //if wt(w) greater than |
| 352 | //the wt(u->w), then assign |
| 353 | //wt(w) to be wt(u->w). |
| 354 | // |
| 355 | //make parent(u)=w in the spanning tree |
| 356 | //keep pulling out vertices from vt till it is empty |
| 357 | |
| 358 | vector<Node *> vt; |
| 359 | |
| 360 | map<Node*, Node* > parent; |
| 361 | map<Node*, int > ed_weight; |
| 362 | |
| 363 | //initialize: wt(root)=0, wt(others)=infinity |
| 364 | //parent(root)=NULL, parent(others) not defined (but not null) |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 365 | for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 366 | Node *thisNode=*LI; |
| 367 | if(*thisNode == *getRoot()){ |
| 368 | thisNode->setWeight(0); |
| 369 | parent[thisNode]=NULL; |
| 370 | ed_weight[thisNode]=0; |
| 371 | } |
| 372 | else{ |
| 373 | thisNode->setWeight(inf); |
| 374 | } |
| 375 | st->addNode(thisNode);//add all nodes to spanning tree |
| 376 | //we later need to assign edges in the tree |
| 377 | vt.push_back(thisNode); //pushed all nodes in vt |
| 378 | } |
| 379 | |
| 380 | //keep pulling out vertex of min wt from vt |
| 381 | while(!vt.empty()){ |
| 382 | Node *u=*(min_element(vt.begin(), vt.end(), compare_nodes())); |
Chris Lattner | e1fc2d9 | 2002-05-22 21:56:32 +0000 | [diff] [blame] | 383 | DEBUG(cerr<<"popped wt"<<(u)->getWeight()<<"\n"; |
| 384 | printNode(u)); |
| 385 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 386 | if(parent[u]!=NULL){ //so not root |
| 387 | Edge edge(parent[u],u, ed_weight[u]); //assign edge in spanning tree |
| 388 | st->addEdge(edge,ed_weight[u]); |
Chris Lattner | e1fc2d9 | 2002-05-22 21:56:32 +0000 | [diff] [blame] | 389 | |
| 390 | DEBUG(cerr<<"added:\n"; |
| 391 | printEdge(edge)); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 392 | } |
| 393 | |
| 394 | //vt.erase(u); |
| 395 | |
| 396 | //remove u frm vt |
| 397 | for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){ |
| 398 | if(**VI==*u){ |
| 399 | vt.erase(VI); |
| 400 | break; |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | //assign wt(v) to all adjacent vertices v of u |
| 405 | //only if v is in vt |
| 406 | Graph::nodeList nl=getNodeList(u); |
| 407 | for(nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){ |
| 408 | Node *v=NI->element; |
| 409 | int weight=-NI->weight; |
| 410 | //check if v is in vt |
| 411 | bool contains=false; |
| 412 | for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){ |
| 413 | if(**VI==*v){ |
| 414 | contains=true; |
| 415 | break; |
| 416 | } |
| 417 | } |
Chris Lattner | e1fc2d9 | 2002-05-22 21:56:32 +0000 | [diff] [blame] | 418 | DEBUG(cerr<<"wt:v->wt"<<weight<<":"<<v->getWeight()<<"\n"; |
| 419 | printNode(v);cerr<<"node wt:"<<(*v).weight<<"\n"); |
| 420 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 421 | //so if v in in vt, change wt(v) to wt(u->v) |
| 422 | //only if wt(u->v)<wt(v) |
| 423 | if(contains && weight<v->getWeight()){ |
| 424 | parent[v]=u; |
| 425 | ed_weight[v]=weight; |
| 426 | v->setWeight(weight); |
Chris Lattner | e1fc2d9 | 2002-05-22 21:56:32 +0000 | [diff] [blame] | 427 | |
| 428 | DEBUG(cerr<<v->getWeight()<<":Set weight------\n"; |
| 429 | printGraph(); |
| 430 | printEdge(Edge(u,v,weight))); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 431 | } |
| 432 | } |
| 433 | } |
| 434 | return st; |
| 435 | } |
| 436 | |
| 437 | //print the graph (for debugging) |
| 438 | void Graph::printGraph(){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 439 | vector<Node *> lt=getAllNodes(); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 440 | cerr<<"Graph---------------------\n"; |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 441 | for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 442 | cerr<<((*LI)->getElement())->getName()<<"->"; |
| 443 | Graph::nodeList nl=getNodeList(*LI); |
| 444 | for(Graph::nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){ |
| 445 | cerr<<":"<<"("<<(NI->element->getElement()) |
| 446 | ->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<")"; |
| 447 | } |
| 448 | cerr<<"--------\n"; |
| 449 | } |
| 450 | } |
| 451 | |
| 452 | |
| 453 | //get a list of nodes in the graph |
| 454 | //in r-topological sorted order |
| 455 | //note that we assumed graph to be connected |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 456 | vector<Node *> Graph::reverseTopologicalSort(){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 457 | vector <Node *> toReturn; |
| 458 | vector<Node *> lt=getAllNodes(); |
| 459 | for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 460 | if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK) |
| 461 | DFS_Visit(*LI, toReturn); |
| 462 | } |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 463 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 464 | return toReturn; |
| 465 | } |
| 466 | |
| 467 | //a private method for doing DFS traversal of graph |
| 468 | //this is used in determining the reverse topological sort |
| 469 | //of the graph |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 470 | void Graph::DFS_Visit(Node *nd, vector<Node *> &toReturn){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 471 | nd->setWeight(GREY); |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 472 | vector<Node *> lt=getSuccNodes(nd); |
| 473 | for(vector<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 474 | if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK) |
| 475 | DFS_Visit(*LI, toReturn); |
| 476 | } |
| 477 | toReturn.push_back(nd); |
| 478 | } |
| 479 | |
| 480 | //Ordinarily, the graph is directional |
| 481 | //this converts the graph into an |
| 482 | //undirectional graph |
| 483 | //This is done by adding an edge |
| 484 | //v->u for all existing edges u->v |
| 485 | void Graph::makeUnDirectional(){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 486 | vector<Node* > allNodes=getAllNodes(); |
| 487 | for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 488 | ++NI) { |
| 489 | nodeList nl=getNodeList(*NI); |
| 490 | for(nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE; ++NLI){ |
| 491 | Edge ed(NLI->element, *NI, NLI->weight); |
| 492 | if(!hasEdgeAndWt(ed)){ |
Chris Lattner | e1fc2d9 | 2002-05-22 21:56:32 +0000 | [diff] [blame] | 493 | DEBUG(cerr<<"######doesn't hv\n"; |
| 494 | printEdge(ed)); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 495 | addEdgeForce(ed); |
| 496 | } |
| 497 | } |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | //reverse the sign of weights on edges |
| 502 | //this way, max-spanning tree could be obtained |
| 503 | //usin min-spanning tree, and vice versa |
| 504 | void Graph::reverseWts(){ |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 505 | vector<Node *> allNodes=getAllNodes(); |
| 506 | for(vector<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 507 | ++NI) { |
| 508 | nodeList node_list=getNodeList(*NI); |
| 509 | for(nodeList::iterator NLI=nodes[*NI].begin(), NLE=nodes[*NI].end(); |
| 510 | NLI!=NLE; ++NLI) |
| 511 | NLI->weight=-NLI->weight; |
| 512 | } |
| 513 | } |
| 514 | |
| 515 | |
| 516 | //getting the backedges in a graph |
| 517 | //Its a variation of DFS to get the backedges in the graph |
| 518 | //We get back edges by associating a time |
| 519 | //and a color with each vertex. |
| 520 | //The time of a vertex is the time when it was first visited |
| 521 | //The color of a vertex is initially WHITE, |
| 522 | //Changes to GREY when it is first visited, |
| 523 | //and changes to BLACK when ALL its neighbors |
| 524 | //have been visited |
| 525 | //So we have a back edge when we meet a successor of |
| 526 | //a node with smaller time, and GREY color |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 527 | void Graph::getBackEdges(vector<Edge > &be, map<Node *, int> &d){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 528 | map<Node *, Color > color; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 529 | int time=0; |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 530 | |
| 531 | getBackEdgesVisit(getRoot(), be, color, d, time); |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 532 | } |
| 533 | |
| 534 | //helper function to get back edges: it is called by |
| 535 | //the "getBackEdges" function above |
| 536 | void Graph::getBackEdgesVisit(Node *u, vector<Edge > &be, |
| 537 | map<Node *, Color > &color, |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 538 | map<Node *, int > &d, int &time) { |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 539 | color[u]=GREY; |
| 540 | time++; |
| 541 | d[u]=time; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 542 | |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 543 | vector<graphListElement> &succ_list = getNodeList(u); |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 544 | |
| 545 | for(vector<graphListElement>::iterator vl=succ_list.begin(), |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 546 | ve=succ_list.end(); vl!=ve; ++vl){ |
| 547 | Node *v=vl->element; |
Anand Shukla | f94ad68 | 2002-09-16 05:26:51 +0000 | [diff] [blame] | 548 | if(color[v]!=GREY && color[v]!=BLACK){ |
| 549 | getBackEdgesVisit(v, be, color, d, time); |
| 550 | } |
Anand Shukla | fd61c60 | 2002-07-18 20:56:47 +0000 | [diff] [blame] | 551 | |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 552 | //now checking for d and f vals |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 553 | if(color[v]==GREY){ |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 554 | //so v is ancestor of u if time of u > time of v |
Anand Shukla | 2190689 | 2002-06-25 21:14:58 +0000 | [diff] [blame] | 555 | if(d[u] >= d[v]){ |
| 556 | Edge *ed=new Edge(u, v,vl->weight, vl->randId); |
| 557 | if (!(*u == *getExit() && *v == *getRoot())) |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 558 | be.push_back(*ed); // choose the forward edges |
| 559 | } |
| 560 | } |
| 561 | } |
| 562 | color[u]=BLACK;//done with visiting the node and its neighbors |
| 563 | } |
| 564 | |
| 565 | |