00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "blocktree.h"
00019
00020 static int min_value(int x, int y)
00021 {
00022 if (x < y)
00023 return x;
00024 return y;
00025 }
00026
00027 static void addNode(block_t * bp, Agnode_t * n)
00028 {
00029 aginsert(bp->sub_graph, n);
00030 SET_BCDONE(n);
00031 BLOCK(n) = bp;
00032 }
00033
00034 static Agraph_t *makeBlockGraph(Agraph_t * g, circ_state * state)
00035 {
00036 char name[SMALLBUF];
00037 Agraph_t *subg;
00038
00039 sprintf(name, "_block_%d", state->blockCount++);
00040 subg = agsubg(g, name);
00041 return subg;
00042 }
00043
00044 static block_t *makeBlock(Agraph_t * g, circ_state * state)
00045 {
00046 Agraph_t *subg = makeBlockGraph(g, state);
00047 block_t *bp = mkBlock(subg);
00048
00049 return bp;
00050 }
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 static void dfs(Agraph_t * g, Agnode_t * n, circ_state * state, int isRoot)
00067 {
00068 Agedge_t *e;
00069 Agnode_t *curtop;
00070
00071 LOWVAL(n) = VAL(n) = state->orderCount++;
00072
00073 stackPush(state->bcstack, n);
00074
00075 for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
00076 Agnode_t *neighbor = e->head;
00077 if (neighbor == n)
00078 neighbor = e->tail;
00079
00080 if (neighbor == PARENT(n))
00081 continue;
00082
00083 if (VAL(neighbor)) {
00084 LOWVAL(n) = min_value(LOWVAL(n), VAL(neighbor));
00085 continue;
00086 }
00087 if (!stackCheck(state->bcstack, n)) {
00088 stackPush(state->bcstack, n);
00089 }
00090
00091 PARENT(neighbor) = n;
00092 curtop = top(state->bcstack);
00093 dfs(g, neighbor, state, 0);
00094
00095 LOWVAL(n) = min_value(LOWVAL(n), LOWVAL(neighbor));
00096 if (LOWVAL(neighbor) >= VAL(n)) {
00097 block_t *block = NULL;
00098 Agnode_t *np;
00099 if (top(state->bcstack) != curtop)
00100 do {
00101 np = stackPop(state->bcstack);
00102 if (!BCDONE(np)) {
00103 if (!block)
00104 block = makeBlock(g, state);
00105 addNode(block, np);
00106 }
00107 } while (np != n);
00108 if (block) {
00109 if (isRoot && (BLOCK(n) == block))
00110 insertBlock(&state->bl, block);
00111 else
00112 appendBlock(&state->bl, block);
00113 }
00114 if ((LOWVAL(n) < VAL(n)) && (!stackCheck(state->bcstack, n))) {
00115 stackPush(state->bcstack, n);
00116 }
00117 }
00118 }
00119 if ((LOWVAL(n) == VAL(n)) && !BCDONE(n)) {
00120 block_t *block = makeBlock(g, state);
00121 stackPop(state->bcstack);
00122 addNode(block, n);
00123 if (isRoot)
00124 insertBlock(&state->bl, block);
00125 else
00126 appendBlock(&state->bl, block);
00127 }
00128 }
00129
00130 #ifdef USER_BLOCKS
00131
00132
00133
00134
00135
00136
00137
00138
00139 static Agnode_t *findUnvisited(blocklist_t * blp)
00140 {
00141 Agnode_t *retn = NULL;
00142 FIX:finish Agnode_t * n;
00143 Agnode_t *newn;
00144 graph_t *clust_subg;
00145 edge_t *e;
00146 block_t *bp;
00147 block_t *prev = NULL;
00148
00149 for (bp = blp->first; prev != blp->last; bp = bp->next) {
00150 prev = bp;
00151 clust = bp->sub_graph;
00152
00153 if (DONE(bp))
00154 continue;
00155 if (PARTIAL(bp)) {
00156 for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
00157 if (!VISITED(n)) {
00158 for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
00159 newn = e->head;
00160 if (newn == n)
00161 newn = e->tail;
00162 if ((BLOCK(newn) != bp)) {
00163 retn = newn;
00164 return;
00165 }
00166 }
00167
00168 }
00169 }
00170
00171 } else {
00172 }
00173 }
00174 return retn;
00175 }
00176 #endif
00177
00178
00179
00180 static void find_blocks(Agraph_t * g, circ_state * state)
00181 {
00182 Agnode_t *n;
00183 Agnode_t *root = NULL;
00184 block_t *rootBlock = NULL;
00185 blocklist_t ublks;
00186 #ifdef USER_BLOCKS
00187 graph_t *clust_subg;
00188 graph_t *mg;
00189 edge_t *me;
00190 node_t *mm;
00191 int isRoot;
00192 #endif
00193
00194 initBlocklist(&ublks);
00195
00196
00197
00198 if (state->rootname) {
00199 root = agfindnode(g, state->rootname);
00200 }
00201 if (!root && state->N_root) {
00202 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00203 if (late_bool(ORIGN(n), state->N_root, 0)) {
00204 root = n;
00205 break;
00206 }
00207 }
00208 }
00209 #ifdef USER_BLOCKS
00210
00211
00212 mm = g->meta_node;
00213 mg = mm->graph;
00214 for (me = agfstout(mg, mm); me; me = agnxtout(mg, me)) {
00215 block_t *block;
00216
00217 clust_subg = agusergraph(me->head);
00218
00219 isRoot = 0;
00220 block = mkBlock(clust_subg);
00221
00222 for (n = agfstnode(clust_subg); n; n = agnxtnode(clust_subg, n)) {
00223 if (!BCDONE(n)) {
00224 SET_BCDONE(n);
00225 BLOCK(n) = block;
00226 if (n == root)
00227 isRoot = 1;
00228 }
00229 }
00230 if (isRoot) {
00231
00232
00233
00234 rootBlock = block;
00235 insertBlock(&state->bl, block);
00236 } else {
00237 appendBlock(&state->bl, block);
00238 }
00239 }
00240 ublks.first = state->bl.first;
00241 ublks.last = state->bl.last;
00242 #endif
00243
00244 if (!root)
00245 root = agfstnode(g);
00246 dfs(g, root, state, !rootBlock);
00247
00248 #ifdef USER_BLOCKS
00249
00250
00251
00252
00253
00254 if (ublks.first) {
00255 while (n = findUnvisited(&ublks)) {
00256 dfs(g, n, state, 0);
00257 }
00258 }
00259 #endif
00260 }
00261
00262
00263
00264
00265
00266
00267 block_t *createBlocktree(Agraph_t * g, circ_state * state)
00268 {
00269 block_t *bp;
00270 block_t *next;
00271 block_t *root;
00272 int min;
00273
00274
00275 find_blocks(g, state);
00276
00277 bp = state->bl.first;
00278
00279 root = bp;
00280
00281
00282
00283
00284 for (bp = bp->next; bp; bp = next) {
00285 Agnode_t *n;
00286 Agnode_t *parent;
00287 Agnode_t *child;
00288 Agraph_t *subg = bp->sub_graph;
00289
00290 child = n = agfstnode(subg);
00291 min = VAL(n);
00292 parent = PARENT(n);
00293 for (n = agnxtnode(subg, n); n; n = agnxtnode(subg, n)) {
00294 if (VAL(n) < min) {
00295 child = n;
00296 min = VAL(n);
00297 parent = PARENT(n);
00298 }
00299 }
00300 SET_PARENT(parent);
00301 CHILD(bp) = child;
00302 next = bp->next;
00303 appendBlock(&(BLOCK(parent)->children), bp);
00304 }
00305 initBlocklist(&state->bl);
00306 return root;
00307 }
00308
00309 void freeBlocktree(block_t * bp)
00310 {
00311 block_t *child;
00312 block_t *next;
00313
00314 for (child = bp->children.first; child; child = next) {
00315 next = child->next;
00316 freeBlocktree(child);
00317 }
00318
00319 freeBlock(bp);
00320 }
00321
00322 #ifdef DEBUG
00323 static void indent(int i)
00324 {
00325 while (i--)
00326 fputs(" ", stderr);
00327 }
00328
00329 void print_blocktree(block_t * sn, int depth)
00330 {
00331 block_t *child;
00332 Agnode_t *n;
00333 Agraph_t *g;
00334
00335 indent(depth);
00336 g = sn->sub_graph;
00337 fprintf(stderr, "%s:", g->name);
00338 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00339 fprintf(stderr, " %s", n->name);
00340 }
00341 fputs("\n", stderr);
00342
00343 depth++;
00344 for (child = sn->children.first; child; child = child->next) {
00345 print_blocktree(child, depth);
00346 }
00347 }
00348
00349 #endif