std::vector< std::vector<int> > datastructures::TarjansAlgorithm::getSCCs(std::vector<varset> &parents) { initChildMatrix(parents); for (int i = 0; i < indices.size(); i++) { indices[i] = -1; } stronglyConnectedComponents.clear(); /** * index := 0 S := empty for each v in V do if (v.index is undefined) * then strongconnect(v) end if repeat */ index = 0; while (S.size() > 0) { S.pop(); } for (int v = 0; v < size; v++) { if (indices[v] == -1) { strongconnect(v); } } return stronglyConnectedComponents; }
void datastructures::TarjansAlgorithm::strongconnect(int v) { /** * Set the depth index for v to the smallest unused index * * v.index := index v.lowlink := index index := index + 1 S.push(v) * */ indices[v] = index; lowlink[v] = index; index++; S.push(v); VARSET_SET(sContents, v); /** * Consider successors of v * * for each (v, w) in E do if (w.index is undefined) then // Successor w * has not yet been visited; recurse on it strongconnect(w) v.lowlink := * min(v.lowlink, w.lowlink) else if (w is in S) then // Successor w is * in stack S and hence in the current SCC v.lowlink := min(v.lowlink, * w.index) end if repeat * */ for (int w = 0; w < size; w++) { if (! VARSET_GET(childMatrix[v], w)) continue; if (indices[w] == -1) { strongconnect(w); int mi = std::min(lowlink[v], lowlink[w]); lowlink[v] = mi; } else if (VARSET_GET(sContents, w)) { int mi = std::min(lowlink[v], indices[w]); lowlink[v] = mi; } } /** * If v is a root node, pop the stack and generate an SCC * * if (v.lowlink = v.index) then start a new strongly connected * component repeat w := S.pop() add w to current strongly connected * component until (w = v) output the current strongly connected * component end if * */ if (lowlink[v] == indices[v]) { std::vector<int> scc; int w = -1; do { w = S.top(); S.pop(); VARSET_CLEAR(sContents, w); scc.push_back(w); } while (w != v); stronglyConnectedComponents.push_back(scc); } }
// Node v is the i-the node // Graph is passed to use getOutgoingEdges void StronglyConnectedComponentsVisitor::strongconnect(Graph* g, Node *v, int i) { // Set the depth index for v to the smallest unused index _indexTable[i] = _index; _lowlinkTable[i] = _index; _index = _index +1; S.push_front(v); list<Edge*> outgoing = g->getOutgoingEdges(v); // Consider successors of v // For each (v, w) in E for (list<Edge*>::iterator it = outgoing.begin() ; it != outgoing.end(); ++it) { // current w Node* w = (*it)->getTarget(); // if w's index is undefined if ( _indexTable[g->nodeToIndex(w)] == -1) { // Successor w has not yet been visited; recurse on it strongconnect(g, w, g->nodeToIndex(w)); // v.lowlink := min(v.lowlink, w.lowlink) _lowlinkTable[g->nodeToIndex(v)] = min( _lowlinkTable[g->nodeToIndex(v)], _lowlinkTable[g->nodeToIndex(w)] ); } // else if ( w is in S ) else if ( isInStack(w) ) { // Successor w is in stack S and hence in the current SCC // v.lowlink := min(v.lowlink, w.index) _lowlinkTable[g->nodeToIndex(v)] = min(_lowlinkTable[g->nodeToIndex(v)], _indexTable[g->nodeToIndex(w)] ); } } // If v is a root node, pop the stack and generate a SCC if (_lowlinkTable[g->nodeToIndex(v)] == _indexTable[g->nodeToIndex(v)]) { Node * w; // start a new strongly connected component vector<Node*> scc; do { w = S.front(); S.pop_front(); // add w to current strongly connected component scc.push_back(w); } while (!(w==v)); // add the current strongly connected component to the vector of strongly connected component _SCC.push_back(scc); } }
static void scc(CallGraphWrapperPass &cg, RecursiveGuardSpecPolicy::SCC& scc) { std::map<const Function*, std::pair<int, int> > indicies; std::list<Function*> stack; std::set<Function*> stack_contents; int index = 0; for (CallGraphWrapperPass::iterator i = cg.begin(), e = cg.end(); i != e; ++i) { if (indicies.find(i->first) == indicies.end()) { strongconnect(i->second, cg, stack, stack_contents, indicies, index, scc); } } }
static void strongconnect(CallGraphNode* from, CallGraphWrapperPass& cg, std::list<Function*>& stack, std::set<Function*>& stack_contents, std::map<const Function*, std::pair<int, int> >& indicies, int& next_idx, RecursiveGuardSpecPolicy::SCC& result) { int base_idx = next_idx; Function* f = from->getFunction(); indicies[f] = std::pair<int, int>(next_idx, next_idx); next_idx++; stack.push_back(f); bool self = false; for (CallGraphNode::iterator i = from->begin(), e = from->end(); i != e; ++i) { Function* fi = i->second->getFunction(); if (fi == NULL) continue; if (fi == f) self = true; if (indicies.find(fi) == indicies.end()) { strongconnect(i->second, cg, stack, stack_contents, indicies, next_idx, result); std::pair<int,int>& wi = indicies[fi]; std::pair<int,int>& vi = indicies[f]; vi.second = std::min(vi.second, wi.second); } else if (stack_contents.find(fi) != stack_contents.end()) { std::pair<int,int>& wi = indicies[fi]; std::pair<int,int>& vi = indicies[f]; vi.second = std::min(vi.second, wi.first); } } std::pair<int,int>& vi = indicies[f]; if (vi.first == vi.second) { if (stack.back() == f && !self) { stack.pop_back(); return; } Function* w = NULL; do { w = stack.back(); stack.pop_back(); result[w] = base_idx; } while (w != f); } }
void StronglyConnectedComponentsVisitor::computeComponents(Graph & graph, bool color) { // reset _SCC _SCC.clear(); vector<Node*> nodes = graph.getNodes(); int size = nodes.size(); initTables(size); for ( int i = 0; i < size; ++i ) { // if nodes[i] has no index if ( _indexTable[i] == -1 ) strongconnect( &graph, nodes[i], i ); } if ( color ) // color the different strongly connected components to distinguish them colorComponents(); }