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 | |
| 8 | #include "Graph.h" |
| 9 | #include "llvm/BasicBlock.h" |
| 10 | #include <algorithm> |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame^] | 11 | #include <iostream> |
| 12 | |
| 13 | using std::list; |
| 14 | using std::set; |
| 15 | using std::map; |
| 16 | using std::vector; |
| 17 | using std::cerr; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 18 | |
| 19 | static const graphListElement *findNodeInList(const Graph::nodeList &NL, |
| 20 | Node *N) { |
| 21 | for(Graph::nodeList::const_iterator NI = NL.begin(), NE=NL.end(); NI != NE; |
| 22 | ++NI) |
| 23 | if (*NI->element== *N) |
| 24 | return &*NI; |
| 25 | return 0; |
| 26 | } |
| 27 | |
| 28 | static graphListElement *findNodeInList(Graph::nodeList &NL, Node *N) { |
| 29 | for(Graph::nodeList::iterator NI = NL.begin(), NE=NL.end(); NI != NE; ++NI) |
| 30 | if (*NI->element== *N) |
| 31 | return &*NI; |
| 32 | return 0; |
| 33 | } |
| 34 | |
| 35 | //graph constructor with root and exit specified |
| 36 | Graph::Graph(std::set<Node*> n, std::set<Edge> e, |
| 37 | Node *rt, Node *lt){ |
| 38 | strt=rt; |
| 39 | ext=lt; |
| 40 | for(set<Node* >::iterator x=n.begin(), en=n.end(); x!=en; ++x) |
| 41 | nodes[*x] = list<graphListElement>(); |
| 42 | |
| 43 | for(set<Edge >::iterator x=e.begin(), en=e.end(); x!=en; ++x){ |
| 44 | Edge ee=*x; |
| 45 | int w=ee.getWeight(); |
| 46 | nodes[ee.getFirst()].push_front(graphListElement(ee.getSecond(),w)); |
| 47 | } |
| 48 | |
| 49 | } |
| 50 | |
| 51 | //check whether graph has an edge |
| 52 | //having an edge simply means that there is an edge in the graph |
| 53 | //which has same endpoints as the given edge |
| 54 | bool Graph::hasEdge(Edge ed) const{ |
| 55 | if(ed.isNull()) |
| 56 | return false; |
| 57 | |
| 58 | nodeList nli=getNodeList(ed.getFirst()); |
| 59 | Node *nd2=ed.getSecond(); |
| 60 | |
| 61 | return (findNodeInList(nli,nd2)!=NULL); |
| 62 | |
| 63 | } |
| 64 | |
| 65 | |
| 66 | //check whether graph has an edge, with a given wt |
| 67 | //having an edge simply means that there is an edge in the graph |
| 68 | //which has same endpoints as the given edge |
| 69 | //This function checks, moreover, that the wt of edge matches too |
| 70 | bool Graph::hasEdgeAndWt(Edge ed) const{ |
| 71 | if(ed.isNull()) |
| 72 | return false; |
| 73 | |
| 74 | Node *nd2=ed.getSecond(); |
| 75 | nodeList nli=getNodeList(ed.getFirst()); |
| 76 | |
| 77 | for(nodeList::iterator NI=nli.begin(), NE=nli.end(); NI!=NE; ++NI) |
| 78 | if(*NI->element == *nd2 && ed.getWeight()==NI->weight) |
| 79 | return true; |
| 80 | |
| 81 | return false; |
| 82 | } |
| 83 | |
| 84 | //add a node |
| 85 | void Graph::addNode(Node *nd){ |
| 86 | list<Node *> lt=getAllNodes(); |
| 87 | |
| 88 | for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE;++LI){ |
| 89 | if(**LI==*nd) |
| 90 | return; |
| 91 | } |
| 92 | |
| 93 | nodes[nd] = list<graphListElement>(); |
| 94 | } |
| 95 | |
| 96 | //add an edge |
| 97 | //this adds an edge ONLY when |
| 98 | //the edge to be added doesn not already exist |
| 99 | //we "equate" two edges here only with their |
| 100 | //end points |
| 101 | void Graph::addEdge(Edge ed, int w){ |
| 102 | nodeList &ndList = nodes[ed.getFirst()]; |
| 103 | Node *nd2=ed.getSecond(); |
| 104 | |
| 105 | if(findNodeInList(nodes[ed.getFirst()], nd2)) |
| 106 | return; |
| 107 | |
| 108 | ndList.push_front(graphListElement(nd2,w)); |
| 109 | } |
| 110 | |
| 111 | //add an edge EVEN IF such an edge already exists |
| 112 | //this may make a multi-graph |
| 113 | //which does happen when we add dummy edges |
| 114 | //to the graph, for compensating for back-edges |
| 115 | void Graph::addEdgeForce(Edge ed){ |
| 116 | nodes[ed.getFirst()].push_front(graphListElement(ed.getSecond(), |
| 117 | ed.getWeight())); |
| 118 | } |
| 119 | |
| 120 | //remove an edge |
| 121 | //Note that it removes just one edge, |
| 122 | //the first edge that is encountered |
| 123 | void Graph::removeEdge(Edge ed){ |
| 124 | nodeList &ndList = nodes[ed.getFirst()]; |
| 125 | Node &nd2 = *ed.getSecond(); |
| 126 | |
| 127 | for(nodeList::iterator NI=ndList.begin(), NE=ndList.end(); NI!=NE ;++NI) { |
| 128 | if(*NI->element == nd2) { |
| 129 | ndList.erase(NI); |
| 130 | break; |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | //set the weight of an edge |
| 136 | void Graph::setWeight(Edge ed){ |
| 137 | graphListElement *El = findNodeInList(nodes[ed.getFirst()], ed.getSecond()); |
| 138 | if (El) |
| 139 | El->weight=ed.getWeight(); |
| 140 | } |
| 141 | |
| 142 | |
| 143 | |
| 144 | //get the list of successor nodes |
| 145 | list<Node *> Graph::getSuccNodes(Node *nd) const { |
| 146 | nodeMapTy::const_iterator nli = nodes.find(nd); |
| 147 | assert(nli != nodes.end() && "Node must be in nodes map"); |
| 148 | const nodeList &nl = nli->second; |
| 149 | |
| 150 | list<Node *> lt; |
| 151 | for(nodeList::const_iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI) |
| 152 | lt.push_back(NI->element); |
| 153 | |
| 154 | return lt; |
| 155 | } |
| 156 | |
| 157 | //get the list of predecessor nodes |
| 158 | list<Node *> Graph::getPredNodes(Node *nd) const{ |
| 159 | list<Node *> lt; |
| 160 | for(nodeMapTy::const_iterator EI=nodes.begin(), EE=nodes.end(); EI!=EE ;++EI){ |
| 161 | Node *lnode=EI->first; |
| 162 | const nodeList &nl = getNodeList(lnode); |
| 163 | |
| 164 | const graphListElement *N = findNodeInList(nl, nd); |
| 165 | if (N) lt.push_back(lnode); |
| 166 | } |
| 167 | return lt; |
| 168 | } |
| 169 | |
| 170 | //get the list of all the vertices in graph |
| 171 | list<Node *> Graph::getAllNodes() const{ |
| 172 | list<Node *> lt; |
| 173 | for(nodeMapTy::const_iterator x=nodes.begin(), en=nodes.end(); x != en; ++x) |
| 174 | lt.push_back(x->first); |
| 175 | |
| 176 | return lt; |
| 177 | } |
| 178 | |
| 179 | |
| 180 | //class to compare two nodes in graph |
| 181 | //based on their wt: this is used in |
| 182 | //finding the maximal spanning tree |
| 183 | struct compare_nodes { |
| 184 | bool operator()(Node *n1, Node *n2){ |
| 185 | return n1->getWeight() < n2->getWeight(); |
| 186 | } |
| 187 | }; |
| 188 | |
| 189 | |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame^] | 190 | static void printNode(Node *nd){ |
| 191 | cerr<<"Node:"<<nd->getElement()->getName()<<"\n"; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | //Get the Maximal spanning tree (also a graph) |
| 195 | //of the graph |
| 196 | Graph* Graph::getMaxSpanningTree(){ |
| 197 | //assume connected graph |
| 198 | |
| 199 | Graph *st=new Graph();//max spanning tree, undirected edges |
| 200 | int inf=9999999;//largest key |
| 201 | list<Node *> lt = getAllNodes(); |
| 202 | |
| 203 | //initially put all vertices in vector vt |
| 204 | //assign wt(root)=0 |
| 205 | //wt(others)=infinity |
| 206 | // |
| 207 | //now: |
| 208 | //pull out u: a vertex frm vt of min wt |
| 209 | //for all vertices w in vt, |
| 210 | //if wt(w) greater than |
| 211 | //the wt(u->w), then assign |
| 212 | //wt(w) to be wt(u->w). |
| 213 | // |
| 214 | //make parent(u)=w in the spanning tree |
| 215 | //keep pulling out vertices from vt till it is empty |
| 216 | |
| 217 | vector<Node *> vt; |
| 218 | |
| 219 | map<Node*, Node* > parent; |
| 220 | map<Node*, int > ed_weight; |
| 221 | |
| 222 | //initialize: wt(root)=0, wt(others)=infinity |
| 223 | //parent(root)=NULL, parent(others) not defined (but not null) |
| 224 | for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| 225 | Node *thisNode=*LI; |
| 226 | if(*thisNode == *getRoot()){ |
| 227 | thisNode->setWeight(0); |
| 228 | parent[thisNode]=NULL; |
| 229 | ed_weight[thisNode]=0; |
| 230 | } |
| 231 | else{ |
| 232 | thisNode->setWeight(inf); |
| 233 | } |
| 234 | st->addNode(thisNode);//add all nodes to spanning tree |
| 235 | //we later need to assign edges in the tree |
| 236 | vt.push_back(thisNode); //pushed all nodes in vt |
| 237 | } |
| 238 | |
| 239 | //keep pulling out vertex of min wt from vt |
| 240 | while(!vt.empty()){ |
| 241 | Node *u=*(min_element(vt.begin(), vt.end(), compare_nodes())); |
| 242 | #ifdef DEBUG_PATH_PROFILES |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame^] | 243 | cerr<<"popped wt"<<(u)->getWeight()<<"\n"; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 244 | printNode(u); |
| 245 | #endif |
| 246 | if(parent[u]!=NULL){ //so not root |
| 247 | Edge edge(parent[u],u, ed_weight[u]); //assign edge in spanning tree |
| 248 | st->addEdge(edge,ed_weight[u]); |
| 249 | #ifdef DEBUG_PATH_PROFILES |
| 250 | cerr<<"added:\n"; |
| 251 | printEdge(edge); |
| 252 | #endif |
| 253 | } |
| 254 | |
| 255 | //vt.erase(u); |
| 256 | |
| 257 | //remove u frm vt |
| 258 | for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){ |
| 259 | if(**VI==*u){ |
| 260 | vt.erase(VI); |
| 261 | break; |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | //assign wt(v) to all adjacent vertices v of u |
| 266 | //only if v is in vt |
| 267 | Graph::nodeList nl=getNodeList(u); |
| 268 | for(nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){ |
| 269 | Node *v=NI->element; |
| 270 | int weight=-NI->weight; |
| 271 | //check if v is in vt |
| 272 | bool contains=false; |
| 273 | for(vector<Node *>::iterator VI=vt.begin(), VE=vt.end(); VI!=VE; ++VI){ |
| 274 | if(**VI==*v){ |
| 275 | contains=true; |
| 276 | break; |
| 277 | } |
| 278 | } |
| 279 | #ifdef DEBUG_PATH_PROFILES |
Chris Lattner | 5328c6f | 2002-02-26 19:40:28 +0000 | [diff] [blame^] | 280 | cerr<<"wt:v->wt"<<weight<<":"<<v->getWeight()<<"\n"; |
| 281 | printNode(v);cerr<<"node wt:"<<(*v).weight<<"\n"; |
Anand Shukla | d3d1fcd | 2002-02-26 18:58:39 +0000 | [diff] [blame] | 282 | #endif |
| 283 | //so if v in in vt, change wt(v) to wt(u->v) |
| 284 | //only if wt(u->v)<wt(v) |
| 285 | if(contains && weight<v->getWeight()){ |
| 286 | parent[v]=u; |
| 287 | ed_weight[v]=weight; |
| 288 | v->setWeight(weight); |
| 289 | #ifdef DEBUG_PATH_PROFILES |
| 290 | cerr<<v->getWeight()<<":Set weight------\n"; |
| 291 | printGraph(); |
| 292 | printEdge(Edge(u,v,weight)); |
| 293 | #endif |
| 294 | } |
| 295 | } |
| 296 | } |
| 297 | return st; |
| 298 | } |
| 299 | |
| 300 | //print the graph (for debugging) |
| 301 | void Graph::printGraph(){ |
| 302 | list<Node *> lt=getAllNodes(); |
| 303 | cerr<<"Graph---------------------\n"; |
| 304 | for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| 305 | cerr<<((*LI)->getElement())->getName()<<"->"; |
| 306 | Graph::nodeList nl=getNodeList(*LI); |
| 307 | for(Graph::nodeList::iterator NI=nl.begin(), NE=nl.end(); NI!=NE; ++NI){ |
| 308 | cerr<<":"<<"("<<(NI->element->getElement()) |
| 309 | ->getName()<<":"<<NI->element->getWeight()<<","<<NI->weight<<")"; |
| 310 | } |
| 311 | cerr<<"--------\n"; |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | |
| 316 | //get a list of nodes in the graph |
| 317 | //in r-topological sorted order |
| 318 | //note that we assumed graph to be connected |
| 319 | list<Node *> Graph::reverseTopologicalSort() const{ |
| 320 | list <Node *> toReturn; |
| 321 | list<Node *> lt=getAllNodes(); |
| 322 | for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| 323 | if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK) |
| 324 | DFS_Visit(*LI, toReturn); |
| 325 | } |
| 326 | return toReturn; |
| 327 | } |
| 328 | |
| 329 | //a private method for doing DFS traversal of graph |
| 330 | //this is used in determining the reverse topological sort |
| 331 | //of the graph |
| 332 | void Graph::DFS_Visit(Node *nd, list<Node *> &toReturn) const { |
| 333 | nd->setWeight(GREY); |
| 334 | list<Node *> lt=getSuccNodes(nd); |
| 335 | for(list<Node *>::iterator LI=lt.begin(), LE=lt.end(); LI!=LE; ++LI){ |
| 336 | if((*LI)->getWeight()!=GREY && (*LI)->getWeight()!=BLACK) |
| 337 | DFS_Visit(*LI, toReturn); |
| 338 | } |
| 339 | toReturn.push_back(nd); |
| 340 | } |
| 341 | |
| 342 | //Ordinarily, the graph is directional |
| 343 | //this converts the graph into an |
| 344 | //undirectional graph |
| 345 | //This is done by adding an edge |
| 346 | //v->u for all existing edges u->v |
| 347 | void Graph::makeUnDirectional(){ |
| 348 | list<Node* > allNodes=getAllNodes(); |
| 349 | for(list<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE; |
| 350 | ++NI) { |
| 351 | nodeList nl=getNodeList(*NI); |
| 352 | for(nodeList::iterator NLI=nl.begin(), NLE=nl.end(); NLI!=NLE; ++NLI){ |
| 353 | Edge ed(NLI->element, *NI, NLI->weight); |
| 354 | if(!hasEdgeAndWt(ed)){ |
| 355 | #ifdef DEBUG_PATH_PROFILES |
| 356 | cerr<<"######doesn't hv\n"; |
| 357 | printEdge(ed); |
| 358 | #endif |
| 359 | addEdgeForce(ed); |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | } |
| 364 | |
| 365 | //reverse the sign of weights on edges |
| 366 | //this way, max-spanning tree could be obtained |
| 367 | //usin min-spanning tree, and vice versa |
| 368 | void Graph::reverseWts(){ |
| 369 | list<Node *> allNodes=getAllNodes(); |
| 370 | for(list<Node *>::iterator NI=allNodes.begin(), NE=allNodes.end(); NI!=NE; |
| 371 | ++NI) { |
| 372 | nodeList node_list=getNodeList(*NI); |
| 373 | for(nodeList::iterator NLI=nodes[*NI].begin(), NLE=nodes[*NI].end(); |
| 374 | NLI!=NLE; ++NLI) |
| 375 | NLI->weight=-NLI->weight; |
| 376 | } |
| 377 | } |
| 378 | |
| 379 | |
| 380 | //getting the backedges in a graph |
| 381 | //Its a variation of DFS to get the backedges in the graph |
| 382 | //We get back edges by associating a time |
| 383 | //and a color with each vertex. |
| 384 | //The time of a vertex is the time when it was first visited |
| 385 | //The color of a vertex is initially WHITE, |
| 386 | //Changes to GREY when it is first visited, |
| 387 | //and changes to BLACK when ALL its neighbors |
| 388 | //have been visited |
| 389 | //So we have a back edge when we meet a successor of |
| 390 | //a node with smaller time, and GREY color |
| 391 | void Graph::getBackEdges(vector<Edge > &be) const{ |
| 392 | map<Node *, Color > color; |
| 393 | map<Node *, int > d; |
| 394 | list<Node *> allNodes=getAllNodes(); |
| 395 | int time=0; |
| 396 | for(list<Node *>::const_iterator NI=allNodes.begin(), NE=allNodes.end(); |
| 397 | NI!=NE; ++NI){ |
| 398 | if(color[*NI]!=GREY && color[*NI]!=BLACK) |
| 399 | getBackEdgesVisit(*NI, be, color, d, time); |
| 400 | } |
| 401 | } |
| 402 | |
| 403 | //helper function to get back edges: it is called by |
| 404 | //the "getBackEdges" function above |
| 405 | void Graph::getBackEdgesVisit(Node *u, vector<Edge > &be, |
| 406 | map<Node *, Color > &color, |
| 407 | map<Node *, int > &d, int &time) const{ |
| 408 | color[u]=GREY; |
| 409 | time++; |
| 410 | d[u]=time; |
| 411 | list<Node *> succ_list=getSuccNodes(u); |
| 412 | |
| 413 | for(list<Node *>::const_iterator v=succ_list.begin(), ve=succ_list.end(); |
| 414 | v!=ve; ++v){ |
| 415 | if(color[*v]!=GREY && color[*v]!=BLACK){ |
| 416 | getBackEdgesVisit(*v, be, color, d, time); |
| 417 | } |
| 418 | |
| 419 | //now checking for d and f vals |
| 420 | if(color[*v]==GREY){ |
| 421 | //so v is ancestor of u if time of u > time of v |
| 422 | if(d[u] >= d[*v]){ |
| 423 | Edge *ed=new Edge(u, *v); |
| 424 | if (!(*u == *getExit() && **v == *getRoot())) |
| 425 | be.push_back(*ed); // choose the forward edges |
| 426 | } |
| 427 | } |
| 428 | } |
| 429 | color[u]=BLACK;//done with visiting the node and its neighbors |
| 430 | } |
| 431 | |
| 432 | |