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