00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00064 #ifdef USE_PCH
00065 #include "lno_pch.h"
00066 #endif // USE_PCH
00067 #pragma hdrstop
00068
00069 #include "cxx_graph.h"
00070 #include "cxx_memory.h"
00071 #include "errors.h"
00072 #include "lno_scc.h"
00073
00074 extern MEM_POOL LNO_local_pool;
00075
00076 SCC_DIRECTED_GRAPH16::
00077 SCC_DIRECTED_GRAPH16(const VINDEX16 vsize, const EINDEX16 esize)
00078 :DIRECTED_GRAPH16<EDGE16,VERTEX16>(vsize, esize){
00079
00080
00081 _sccmpool = CXX_NEW(MEM_POOL,Malloc_Mem_Pool);
00082 MEM_POOL_Initialize(_sccmpool,"sccmpool",FALSE);
00083 MEM_POOL_Push(_sccmpool);
00084
00085 _scc_id.Set_Mem_Pool(_sccmpool);
00086 _scc_id.Alloc_array(vsize+1);
00087 _scc_id.Setidx( vsize );
00088 Invalidate_Scc();
00089 }
00090
00091
00092 VINDEX16
00093 SCC_DIRECTED_GRAPH16::Add_Vertex() {
00094
00095 Invalidate_Scc();
00096 return DIRECTED_GRAPH16<EDGE16,VERTEX16>::Add_Vertex();
00097
00098 }
00099
00100 EINDEX16
00101 SCC_DIRECTED_GRAPH16::Add_Edge(VINDEX16 from, VINDEX16 to) {
00102
00103
00104
00105 if (Scc_Is_Valid() && _scc_id[from] != _scc_id[to])
00106 Invalidate_Scc();
00107
00108 return DIRECTED_GRAPH16<EDGE16,VERTEX16>::Add_Edge(from,to);
00109 }
00110
00111 EINDEX16
00112 SCC_DIRECTED_GRAPH16::Add_Unique_Edge(VINDEX16 from, VINDEX16 to) {
00113 EINDEX16 new_edge;
00114
00115
00116
00117 if (Scc_Is_Valid() && _scc_id[from] != _scc_id[to])
00118 Invalidate_Scc();
00119
00120 return DIRECTED_GRAPH16<EDGE16,VERTEX16>::Add_Unique_Edge(from,to);
00121
00122 }
00123
00124 void
00125 SCC_DIRECTED_GRAPH16::Delete_Vertex(VINDEX16 v) {
00126
00127 Invalidate_Scc();
00128 DIRECTED_GRAPH16<EDGE16,VERTEX16>::Delete_Vertex(v);
00129
00130 }
00131
00132 void
00133 SCC_DIRECTED_GRAPH16::Delete_Edge(EINDEX16 e) {
00134
00135 VINDEX16 from, to;
00136
00137
00138 FmtAssert (Edge_Is_In_Graph(e), ("Edge not in graph\n"));
00139
00140 from = _e[e].Get_Source();
00141 to = _e[e].Get_Sink();
00142
00143
00144
00145 if (Scc_Is_Valid() && _scc_id[from] == _scc_id[to])
00146 Invalidate_Scc();
00147
00148 DIRECTED_GRAPH16<EDGE16,VERTEX16>::Delete_Edge(e);
00149
00150 }
00151
00152 SCC_DIRECTED_GRAPH16&
00153 SCC_DIRECTED_GRAPH16::operator=(const SCC_DIRECTED_GRAPH16& g) {
00154
00155
00156
00157 DIRECTED_GRAPH16<EDGE16,VERTEX16>::operator=(g);
00158
00159 _scc_cnt = g._scc_cnt;
00160 _scc_id = g._scc_id;
00161
00162 return *this;
00163 }
00164
00169 void
00170 SCC_DIRECTED_GRAPH16::Scc_Dfs(VINDEX16 n) {
00171
00172 EINDEX16 e=_v[n].Get_Out_Edge();
00173 VINDEX16 j;
00174
00175 _visited[n] = 1;
00176 _dfn[n] = _df_count;
00177 _link[n] = _df_count++;
00178 _dfs_stack->Push(n);
00179 _in_stack[n] = 1;
00180 while (e) {
00181 j = _e[e].Get_Sink();
00182 if (!_visited[j]) {
00183 Scc_Dfs(j);
00184 if (_link[j] < _link[n]) _link[n] = _link[j];
00185 } else if (_dfn[j] < _dfn[n] && _in_stack[j] )
00186 if (_dfn[j] < _link[n]) _link[n] = _dfn[j];
00187 e = _e[e].Get_Next_Out_Edge();
00188 }
00189 if (_link[n] == _dfn[n]) {
00190 do {
00191 j = _dfs_stack->Top();
00192 _dfs_stack->Pop();
00193 _in_stack[j] = 0;
00194 _scc_id[j] = _scc_cnt;
00195 } while (j != n);
00196 _scc_cnt++;
00197 }
00198 }
00199
00200
00201 void
00202 SCC_DIRECTED_GRAPH16::Find_Scc() {
00203
00204 VINDEX16 i;
00205 VINDEX16 vcnt = Get_Vertex_Count();
00206
00207 if (Scc_Is_Valid()) return;
00208
00209 MEM_POOL_Push(&LNO_local_pool);
00210
00211 _link = CXX_NEW_ARRAY(VINDEX16,vcnt+1,&LNO_local_pool);
00212 _dfn = CXX_NEW_ARRAY(VINDEX16,vcnt+1,&LNO_local_pool);
00213 _visited = CXX_NEW_ARRAY(BOOL,vcnt+1,&LNO_local_pool);
00214 _in_stack = CXX_NEW_ARRAY(BOOL,vcnt+1,&LNO_local_pool);
00215 _dfs_stack = CXX_NEW(STACK<VINDEX16>(&LNO_local_pool), &LNO_local_pool);
00216
00217 if (_scc_id.Sizeof() < vcnt+1) {
00218 _scc_id.Realloc_array(vcnt+1);
00219 }
00220 _scc_id.Setidx(vcnt) ;
00221
00222 _df_count=1;
00223 _scc_cnt=1;
00224 for (i=1; i<vcnt+1; i++) _visited[i]=_in_stack[i]=0;
00225 for (i=1; i<vcnt+1; i++) if (!_visited[i]) Scc_Dfs(i);
00226 _scc_cnt--;
00227
00228 MEM_POOL_Pop(&LNO_local_pool);
00229 }
00230
00231 VINDEX16
00232 SCC_DIRECTED_GRAPH16::Get_Scc_Size(VINDEX16 i) {
00233
00234 VINDEX16 count=0;
00235 VINDEX16 vcnt = Get_Vertex_Count();
00236
00237 if ( ! Scc_Is_Valid() ) Find_Scc();
00238
00239 for (VINDEX16 j=1; j<vcnt+1; j++) if ( _scc_id[j] == i ) count++;
00240 return count;
00241 }
00242
00243 mUINT16
00244 SCC_DIRECTED_GRAPH16::Get_Level(mUINT16 level[]) {
00245
00246 VINDEX16 *queue;
00247 VINDEX16 head,i;
00248 mUINT16 max_level;
00249 VINDEX16 vcnt = Get_Vertex_Count();
00250
00251 if ( ! Scc_Is_Valid() ) Find_Scc();
00252 FmtAssert( Get_Scc_Count() == Get_Vertex_Count(),
00253 ("Directed graph with cycle passed to Get_Level()\n"));
00254
00255 MEM_POOL_Push(&LNO_local_pool);
00256
00257
00258 DIRECTED_GRAPH16<EDGE16,VERTEX16> g(Get_Vertex_Count(), Get_Edge_Count());
00259 g = *this;
00260
00261 queue = CXX_NEW_ARRAY(VINDEX16,Get_Vertex_Count(),&LNO_local_pool);
00262 head = 0;
00263
00264 for (i = 1; i<vcnt+1; i++) {
00265
00266 if (!_v[i].Get_In_Edge()) {
00267 queue[head++] = i;
00268 level[i] = 0;
00269
00270 } else {
00271
00272 FmtAssert(!Get_Edge(i,i),
00273 ("Directed graph with self-cycle passed to Get_Level()\n"));
00274 }
00275 }
00276
00277 max_level = 0;
00278 for (i = 0; i <head; i++) {
00279 VINDEX16 j = queue[i];
00280 EINDEX16 e;
00281 e = g.Get_Out_Edge(j);
00282 while (e) {
00283 EINDEX16 e1;
00284 e1 = e;
00285 e = g.Get_Next_Out_Edge(e);
00286 VINDEX16 sink = g.Get_Sink(e1);
00287 g.Delete_Edge(e1);
00288 if (!g.Get_In_Edge(sink)) {
00289 queue[head++] = sink;
00290 level[sink] = level[j]+1;
00291
00292 if (level[sink]>max_level) max_level = level[sink];
00293
00294 }
00295 }
00296 }
00297
00298 MEM_POOL_Pop(&LNO_local_pool);
00299
00300 return max_level;
00301
00302 }
00303
00304 mUINT16
00305 SCC_DIRECTED_GRAPH16::Level_Sort(VINDEX16 queue[]) {
00306
00307 VINDEX16 head,i;
00308 mUINT16 max_level;
00309 VINDEX16 vcnt = Get_Vertex_Count();
00310
00311 if ( ! Scc_Is_Valid() ) Find_Scc();
00312 FmtAssert( Get_Scc_Count() == Get_Vertex_Count(),
00313 ("Directed graph with cycle passed to Level_Sort()\n"));
00314
00315 MEM_POOL_Push(&LNO_local_pool);
00316
00317
00318 DIRECTED_GRAPH16<EDGE16,VERTEX16> g(Get_Vertex_Count(), Get_Edge_Count());
00319 g = *this;
00320
00321 mUINT16* level = CXX_NEW_ARRAY(mUINT16,Get_Vertex_Count()+1,&LNO_local_pool);
00322 head = 0;
00323
00324 for (i = 1; i<vcnt+1; i++) {
00325
00326 if (!_v[i].Get_In_Edge()) {
00327 queue[head++] = i;
00328 level[i] = 0;
00329
00330 } else {
00331
00332 FmtAssert(!Get_Edge(i,i),
00333 ("Directed graph with self-cycle passed to Level_Sort()\n"));
00334 }
00335 }
00336
00337 max_level = 0;
00338 for (i = 0; i <head; i++) {
00339 VINDEX16 j = queue[i];
00340 EINDEX16 e;
00341 e = g.Get_Out_Edge(j);
00342 while (e) {
00343 EINDEX16 e1;
00344 e1 = e;
00345 e = g.Get_Next_Out_Edge(e);
00346 VINDEX16 sink = g.Get_Sink(e1);
00347 g.Delete_Edge(e1);
00348 if (!g.Get_In_Edge(sink)) {
00349 queue[head++] = sink;
00350 level[sink] = level[j]+1;
00351
00352 if (level[sink]>max_level) max_level = level[sink];
00353
00354 }
00355 }
00356 }
00357
00358 MEM_POOL_Pop(&LNO_local_pool);
00359
00360 return max_level;
00361
00362 }
00363
00364 SCC_DIRECTED_GRAPH16*
00365 SCC_DIRECTED_GRAPH16::Acyclic_Condensation(MEM_POOL *mpool) {
00366
00367 SCC_DIRECTED_GRAPH16 *g;
00368 VINDEX16 vcnt = Get_Vertex_Count();
00369 VINDEX16 i;
00370 VINDEX16 j;
00371 VINDEX16 k;
00372
00373 if ( ! Scc_Is_Valid() ) Find_Scc();
00374
00375
00376 g= CXX_NEW( SCC_DIRECTED_GRAPH16(Get_Scc_Count(), 0), mpool );
00377
00378 k=Get_Scc_Count();
00379 for (i=1; i<=k; i++) {
00380 j = g->Add_Vertex();
00381 FmtAssert(i == j,
00382 ("SCC id (%d) does not match VINDEX (%d)\n", i, j));
00383 }
00384
00385 EINDEX16 e = Get_Edge();
00386 while (e) {
00387
00388 if (_scc_id[Get_Source(e)]!=_scc_id[Get_Sink(e)])
00389 g->Add_Unique_Edge(_scc_id[Get_Source(e)],_scc_id[Get_Sink(e)]);
00390 e = Get_Next_Edge(e);
00391
00392 }
00393 return g;
00394 }
00395
00396