00001
00024
00025
00026 #include <cassert>
00027
00028 #include <map>
00029 #include <set>
00030 #include <stack>
00031
00032
00033
00034 #include <OpenAnalysis/Utils/SCC.hpp>
00035 #include <OpenAnalysis/Utils/Util.hpp>
00036
00037
00038
00039
00040
00041
00042
00043
00044 namespace OA {
00045
00046 class LowLinkState {
00047 public:
00048 LowLinkState(OA::OA_ptr<OA::RIFG> rifg_) : rifg(rifg_), mCount(1) {
00049 unsigned int sz = rifg->getHighWaterMarkNodeId() + 1;
00050 mNodeStatus = new SCCNodeStatus[sz];
00051 }
00052
00053 ~LowLinkState() {
00054 delete[] mNodeStatus;
00055 }
00056
00057
00058 void Mark(OA::RIFG::NodeId nid)
00059 { mOld.insert(nid); }
00060 unsigned int IsMarked(OA::RIFG::NodeId nid) {
00061 MyNodeIdSet::const_iterator it = mOld.find(nid);
00062 return (it != mOld.end());
00063 }
00064
00065
00066 unsigned int& LOWLINK(OA::RIFG::NodeId nid)
00067 { return mNodeStatus[nid].lowlink; }
00068
00069 unsigned int& DFNUMBER(OA::RIFG::NodeId nid)
00070 { return mNodeStatus[nid].dfnumber; }
00071
00072 unsigned int& Count()
00073 { return mCount; }
00074
00075
00076 void Push(OA_ptr<DGraph::Interface::Node> node, OA::RIFG::NodeId nid) {
00077 mNodeStatus[nid].inStack = true;
00078 mNodeStack.push(node);
00079 }
00080
00081 OA_ptr<DGraph::Interface::Node> Top()
00082 { return mNodeStack.top(); }
00083
00084 OA_ptr<DGraph::Interface::Node> Pop() {
00085 OA_ptr<DGraph::Interface::Node> node = mNodeStack.top();
00086 OA::RIFG::NodeId nid = rifg->getNodeId(node);
00087 mNodeStack.pop();
00088 mNodeStatus[nid].inStack = false;
00089 return node;
00090 }
00091
00092 bool IsOnStack(OA::RIFG::NodeId nid)
00093 { return mNodeStatus[nid].inStack; }
00094
00095 private:
00096
00097
00098
00099 class SCCNodeStatus {
00100 public:
00101 SCCNodeStatus(unsigned int l=0, unsigned int d=0, bool i=false)
00102 : lowlink(l), dfnumber(d), inStack(i) { }
00103
00104 unsigned int lowlink;
00105 unsigned int dfnumber;
00106 bool inStack;
00107 };
00108
00109 typedef std::set<OA::RIFG::NodeId> MyNodeIdSet;
00110
00111 typedef std::stack<OA_ptr<DGraph::Interface::Node> > MyNodeStack;
00112
00113 private:
00114 OA::OA_ptr<OA::RIFG> rifg;
00115
00116 unsigned int mCount;
00117 SCCNodeStatus* mNodeStatus;
00118 MyNodeIdSet mOld;
00119 MyNodeStack mNodeStack;
00120 };
00121
00122 }
00123
00124
00125
00126
00127 static void
00128 CreateHelper(OA::SCCSet* sccSet,
00129 OA::OA_ptr<OA::RIFG> rifg,
00130 OA::OA_ptr<OA::DGraph::Interface::Node> v,
00131 OA::RIFG::NodeId vid,
00132 OA::LowLinkState* state);
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 namespace OA {
00143
00144 SCCSet::SCCSet()
00145 {
00146 }
00147
00148
00149 SCCSet::SCCSet(OA_ptr<DGraph::Interface> graph,
00150 OA_ptr<RIFG> rifg)
00151 {
00152 if (rifg.ptrEqual(0)) {
00153 rifg = new OA::RIFG(graph, RIFG::getSourceNode(graph),
00154 RIFG::getSinkNode(graph));
00155 }
00156
00157 Create(graph, rifg);
00158 }
00159
00160
00161 void
00162 SCCSet::Create(OA_ptr<DGraph::Interface> graph,
00163 OA_ptr<RIFG> rifg)
00164 {
00165
00166 LowLinkState *state = new LowLinkState(rifg);
00167
00168
00169
00170 OA_ptr<DGraph::Interface::NodesIterator> it = graph->getNodesIterator();
00171 for (; it->isValid(); ++(*it)) {
00172 OA_ptr<DGraph::Interface::Node> node = it->current();
00173 OA::RIFG::NodeId nid = rifg->getNodeId(node);
00174 if ( !state->IsMarked(nid) ) {
00175 CreateHelper(this, rifg, node, nid, state);
00176 }
00177 }
00178 }
00179
00180
00181 SCCSet::~SCCSet()
00182 {
00183 Destroy();
00184 }
00185
00186
00187 void
00188 SCCSet::Destroy()
00189 {
00190 this->clear();
00191 }
00192
00193
00194 OA_ptr<SCCNodeSet>
00195 SCCSet::NodeToSCC(const OA_ptr<DGraph::Interface::Node> node)
00196 {
00197
00198
00199
00200 for (self_t::const_iterator it = this->begin(); it != this->end(); ++it) {
00201 OA_ptr<SCCNodeSet> scc = *it;
00202 if (scc->find(node) != scc->end()) {
00203 return scc;
00204 }
00205 }
00206 assert(false);
00207 return OA_ptr<SCCNodeSet>();
00208 }
00209
00210
00211 void
00212 SCCSet::dump(std::ostream& os)
00213 {
00214 using std::endl;
00215
00216 os << "{ SCCSet: num SCC sets: " << this->size() << endl;
00217 for (self_t::iterator it = this->begin(); it != this->end(); ++it) {
00218 OA_ptr<SCCNodeSet> scc = *it;
00219
00220 os << " { SCC: ";
00221 SCCNodeSet::iterator sccIt = scc->begin();
00222 for ( ; sccIt != scc->end(); ++sccIt) {
00223 OA_ptr<DGraph::Interface::Node> node = *sccIt;
00224 os << node->getId() << " ";
00225 }
00226 os << "}" << endl;
00227 }
00228 }
00229
00230
00231 }
00232
00233
00234
00235
00236
00237
00238 static void
00239 CreateHelper(OA::SCCSet* sccSet,
00240 OA::OA_ptr<OA::RIFG> rifg,
00241 OA::OA_ptr<OA::DGraph::Interface::Node> v,
00242 OA::RIFG::NodeId vid,
00243 OA::LowLinkState* state)
00244 {
00245 using namespace OA;
00246
00247 state->Mark(vid);
00248 state->DFNUMBER(vid) = state->Count();
00249 state->Count()++;
00250 state->LOWLINK(vid) = state->DFNUMBER(vid);
00251 state->Push(v, vid);
00252
00253
00254 OA::OA_ptr<OA::DGraph::Interface::NodesIterator> it =
00255 v->getSinkNodesIterator();
00256 for (; it->isValid(); ++(*it)) {
00257 OA_ptr<DGraph::Interface::Node> w = it->current();
00258 OA::RIFG::NodeId wid = rifg->getNodeId(w);
00259
00260
00261 if (!state->IsMarked(wid)) {
00262 CreateHelper(sccSet, rifg, w, wid, state);
00263 state->LOWLINK(vid) = OA_MIN(state->LOWLINK(vid), state->LOWLINK(wid));
00264 }
00265
00266 else {
00267 if ( state->DFNUMBER(wid) < state->DFNUMBER(vid) &&
00268 state->IsOnStack(wid) ) {
00269 state->LOWLINK(vid) = OA_MIN(state->DFNUMBER(wid),
00270 state->LOWLINK(vid));
00271 }
00272 }
00273 }
00274
00275
00276
00277 if ( state->LOWLINK(vid) == state->DFNUMBER(vid) ) {
00278 OA_ptr<SCCNodeSet> scc; scc = new SCCNodeSet;
00279
00280
00281 OA_ptr<DGraph::Interface::Node> x;
00282 do {
00283 x = state->Pop();
00284 scc->insert(x);
00285 } while (x != v);
00286
00287
00288 sccSet->insert(scc);
00289 }
00290 }
00291