00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "render.h"
00023
00024 static int init_graph(graph_t *);
00025 static void dfs_cutval(node_t * v, edge_t * par);
00026 static int dfs_range(node_t * v, edge_t * par, int low);
00027 static int x_val(edge_t * e, node_t * v, int dir);
00028 #ifdef DEBUG
00029 static void check_cycles(graph_t * g);
00030 #endif
00031
00032 #define LENGTH(e) (ND_rank(e->head) - ND_rank(e->tail))
00033 #define SLACK(e) (LENGTH(e) - ED_minlen(e))
00034 #define SEQ(a,b,c) (((a) <= (b)) && ((b) <= (c)))
00035 #define TREE_EDGE(e) (ED_tree_index(e) >= 0)
00036
00037 static graph_t *G;
00038 static int N_nodes, N_edges;
00039 static int Minrank, Maxrank;
00040 static int S_i;
00041 static int Search_size;
00042 #define SEARCHSIZE 30
00043 static nlist_t Tree_node;
00044 static elist Tree_edge;
00045
00046 static void add_tree_edge(edge_t * e)
00047 {
00048 node_t *n;
00049 if (TREE_EDGE(e))
00050 abort();
00051 ED_tree_index(e) = Tree_edge.size;
00052 Tree_edge.list[Tree_edge.size++] = e;
00053 if (ND_mark(e->tail) == FALSE)
00054 Tree_node.list[Tree_node.size++] = e->tail;
00055 if (ND_mark(e->head) == FALSE)
00056 Tree_node.list[Tree_node.size++] = e->head;
00057 n = e->tail;
00058 ND_mark(n) = TRUE;
00059 ND_tree_out(n).list[ND_tree_out(n).size++] = e;
00060 ND_tree_out(n).list[ND_tree_out(n).size] = NULL;
00061 if (ND_out(n).list[ND_tree_out(n).size - 1] == 0)
00062 abort();
00063 n = e->head;
00064 ND_mark(n) = TRUE;
00065 ND_tree_in(n).list[ND_tree_in(n).size++] = e;
00066 ND_tree_in(n).list[ND_tree_in(n).size] = NULL;
00067 if (ND_in(n).list[ND_tree_in(n).size - 1] == 0)
00068 abort();
00069 }
00070
00071 static void exchange_tree_edges(edge_t * e, edge_t * f)
00072 {
00073 int i, j;
00074 node_t *n;
00075
00076 ED_tree_index(f) = ED_tree_index(e);
00077 Tree_edge.list[ED_tree_index(e)] = f;
00078 ED_tree_index(e) = -1;
00079
00080 n = e->tail;
00081 i = --(ND_tree_out(n).size);
00082 for (j = 0; j <= i; j++)
00083 if (ND_tree_out(n).list[j] == e)
00084 break;
00085 ND_tree_out(n).list[j] = ND_tree_out(n).list[i];
00086 ND_tree_out(n).list[i] = NULL;
00087 n = e->head;
00088 i = --(ND_tree_in(n).size);
00089 for (j = 0; j <= i; j++)
00090 if (ND_tree_in(n).list[j] == e)
00091 break;
00092 ND_tree_in(n).list[j] = ND_tree_in(n).list[i];
00093 ND_tree_in(n).list[i] = NULL;
00094
00095 n = f->tail;
00096 ND_tree_out(n).list[ND_tree_out(n).size++] = f;
00097 ND_tree_out(n).list[ND_tree_out(n).size] = NULL;
00098 n = f->head;
00099 ND_tree_in(n).list[ND_tree_in(n).size++] = f;
00100 ND_tree_in(n).list[ND_tree_in(n).size] = NULL;
00101 }
00102
00103 static
00104 void init_rank(void)
00105 {
00106 int i, ctr;
00107 nodequeue *Q;
00108 node_t *v;
00109 edge_t *e;
00110
00111 Q = new_queue(N_nodes);
00112 ctr = 0;
00113
00114 for (v = GD_nlist(G); v; v = ND_next(v)) {
00115 if (ND_priority(v) == 0)
00116 enqueue(Q, v);
00117 }
00118
00119 while ((v = dequeue(Q))) {
00120 ND_rank(v) = 0;
00121 ctr++;
00122 for (i = 0; (e = ND_in(v).list[i]); i++)
00123 ND_rank(v) = MAX(ND_rank(v), ND_rank(e->tail) + ED_minlen(e));
00124 for (i = 0; (e = ND_out(v).list[i]); i++) {
00125 if (--(ND_priority(e->head)) <= 0)
00126 enqueue(Q, e->head);
00127 }
00128 }
00129 if (ctr != N_nodes) {
00130 agerr(AGERR, "trouble in init_rank\n");
00131 for (v = GD_nlist(G); v; v = ND_next(v))
00132 if (ND_priority(v))
00133 agerr(AGPREV, "\t%s %d\n", v->name, ND_priority(v));
00134 }
00135 free_queue(Q);
00136 }
00137
00138 static node_t *incident(edge_t * e)
00139 {
00140 if (ND_mark(e->tail)) {
00141 if (ND_mark(e->head) == FALSE)
00142 return e->tail;
00143 } else {
00144 if (ND_mark(e->head))
00145 return e->head;
00146 }
00147 return NULL;
00148 }
00149
00150 static edge_t *leave_edge(void)
00151 {
00152 edge_t *f, *rv = NULL;
00153 int j, cnt = 0;
00154
00155 j = S_i;
00156 while (S_i < Tree_edge.size) {
00157 if ((f = Tree_edge.list[S_i])->u.cutvalue < 0) {
00158 if (rv) {
00159 if (ED_cutvalue(rv) > ED_cutvalue(f))
00160 rv = f;
00161 } else
00162 rv = Tree_edge.list[S_i];
00163 if (++cnt >= Search_size)
00164 return rv;
00165 }
00166 S_i++;
00167 }
00168 if (j > 0) {
00169 S_i = 0;
00170 while (S_i < j) {
00171 if ((f = Tree_edge.list[S_i])->u.cutvalue < 0) {
00172 if (rv) {
00173 if (ED_cutvalue(rv) > ED_cutvalue(f))
00174 rv = f;
00175 } else
00176 rv = Tree_edge.list[S_i];
00177 if (++cnt >= Search_size)
00178 return rv;
00179 }
00180 S_i++;
00181 }
00182 }
00183 return rv;
00184 }
00185
00186 static edge_t *Enter;
00187 static int Low, Lim, Slack;
00188
00189 static void dfs_enter_outedge(node_t * v)
00190 {
00191 int i, slack;
00192 edge_t *e;
00193
00194 for (i = 0; (e = ND_out(v).list[i]); i++) {
00195 if (TREE_EDGE(e) == FALSE) {
00196 if (!SEQ(Low, ND_lim(e->head), Lim)) {
00197 slack = SLACK(e);
00198 if ((slack < Slack) || (Enter == NULL)) {
00199 Enter = e;
00200 Slack = slack;
00201 }
00202 }
00203 } else if (ND_lim(e->head) < ND_lim(v))
00204 dfs_enter_outedge(e->head);
00205 }
00206 for (i = 0; (e = ND_tree_in(v).list[i]) && (Slack > 0); i++)
00207 if (ND_lim(e->tail) < ND_lim(v))
00208 dfs_enter_outedge(e->tail);
00209 }
00210
00211 static void dfs_enter_inedge(node_t * v)
00212 {
00213 int i, slack;
00214 edge_t *e;
00215
00216 for (i = 0; (e = ND_in(v).list[i]); i++) {
00217 if (TREE_EDGE(e) == FALSE) {
00218 if (!SEQ(Low, ND_lim(e->tail), Lim)) {
00219 slack = SLACK(e);
00220 if ((slack < Slack) || (Enter == NULL)) {
00221 Enter = e;
00222 Slack = slack;
00223 }
00224 }
00225 } else if (ND_lim(e->tail) < ND_lim(v))
00226 dfs_enter_inedge(e->tail);
00227 }
00228 for (i = 0; (e = ND_tree_out(v).list[i]) && (Slack > 0); i++)
00229 if (ND_lim(e->head) < ND_lim(v))
00230 dfs_enter_inedge(e->head);
00231 }
00232
00233 static edge_t *enter_edge(edge_t * e)
00234 {
00235 node_t *v;
00236 int outsearch;
00237
00238
00239 if (ND_lim(e->tail) < ND_lim(e->head)) {
00240 v = e->tail;
00241 outsearch = FALSE;
00242 } else {
00243 v = e->head;
00244 outsearch = TRUE;
00245 }
00246 Enter = NULL;
00247 Slack = INT_MAX;
00248 Low = ND_low(v);
00249 Lim = ND_lim(v);
00250 if (outsearch)
00251 dfs_enter_outedge(v);
00252 else
00253 dfs_enter_inedge(v);
00254 return Enter;
00255 }
00256
00257 static int treesearch(node_t * v)
00258 {
00259 int i;
00260 edge_t *e;
00261
00262 for (i = 0; (e = ND_out(v).list[i]); i++) {
00263 if ((ND_mark(e->head) == FALSE) && (SLACK(e) == 0)) {
00264 add_tree_edge(e);
00265 if ((Tree_edge.size == N_nodes - 1) || treesearch(e->head))
00266 return TRUE;
00267 }
00268 }
00269 for (i = 0; (e = ND_in(v).list[i]); i++) {
00270 if ((ND_mark(e->tail) == FALSE) && (SLACK(e) == 0)) {
00271 add_tree_edge(e);
00272 if ((Tree_edge.size == N_nodes - 1) || treesearch(e->tail))
00273 return TRUE;
00274 }
00275 }
00276 return FALSE;
00277 }
00278
00279 static int tight_tree(void)
00280 {
00281 int i;
00282 node_t *n;
00283
00284 for (n = GD_nlist(G); n; n = ND_next(n)) {
00285 ND_mark(n) = FALSE;
00286 ND_tree_in(n).list[0] = ND_tree_out(n).list[0] = NULL;
00287 ND_tree_in(n).size = ND_tree_out(n).size = 0;
00288 }
00289 for (i = 0; i < Tree_edge.size; i++)
00290 Tree_edge.list[i]->u.tree_index = -1;
00291
00292 Tree_node.size = Tree_edge.size = 0;
00293 for (n = GD_nlist(G); n && (Tree_edge.size == 0); n = ND_next(n))
00294 treesearch(n);
00295 return Tree_node.size;
00296 }
00297
00298 static void init_cutvalues(void)
00299 {
00300 dfs_range(GD_nlist(G), NULL, 1);
00301 dfs_cutval(GD_nlist(G), NULL);
00302 }
00303
00304 static int feasible_tree(void)
00305 {
00306 int i, delta;
00307 node_t *n;
00308 edge_t *e, *f;
00309
00310 if (N_nodes <= 1)
00311 return 0;
00312 while (tight_tree() < N_nodes) {
00313 e = NULL;
00314 for (n = GD_nlist(G); n; n = ND_next(n)) {
00315 for (i = 0; (f = ND_out(n).list[i]); i++) {
00316 if ((TREE_EDGE(f) == FALSE) && incident(f) && ((e == NULL)
00317 || (SLACK(f)
00318 <
00319 SLACK
00320 (e))))
00321 e = f;
00322 }
00323 }
00324 if (e) {
00325 delta = SLACK(e);
00326 if (delta) {
00327 if (incident(e) == e->head)
00328 delta = -delta;
00329 for (i = 0; i < Tree_node.size; i++)
00330 Tree_node.list[i]->u.rank += delta;
00331 }
00332 } else {
00333 #ifdef DEBUG
00334 fprintf(stderr, "not in tight tree:\n");
00335 for (n = GD_nlist(G); n; n = ND_next(n)) {
00336 for (i = 0; i < Tree_node.size; i++)
00337 if (Tree_node.list[i] == n)
00338 break;
00339 if (i >= Tree_node.size)
00340 fprintf(stderr, "\t%s\n", n->name);
00341 }
00342 #endif
00343 return 1;
00344 }
00345 }
00346 init_cutvalues();
00347 return 0;
00348 }
00349
00350
00351 static node_t *treeupdate(node_t * v, node_t * w, int cutvalue, int dir)
00352 {
00353 edge_t *e;
00354 int d;
00355
00356 while (!SEQ(ND_low(v), ND_lim(w), ND_lim(v))) {
00357 e = ND_par(v);
00358 if (v == e->tail)
00359 d = dir;
00360 else
00361 d = NOT(dir);
00362 if (d)
00363 ED_cutvalue(e) += cutvalue;
00364 else
00365 ED_cutvalue(e) -= cutvalue;
00366 if (ND_lim(e->tail) > ND_lim(e->head))
00367 v = e->tail;
00368 else
00369 v = e->head;
00370 }
00371 return v;
00372 }
00373
00374 static void rerank(node_t * v, int delta)
00375 {
00376 int i;
00377 edge_t *e;
00378
00379 ND_rank(v) -= delta;
00380 for (i = 0; (e = ND_tree_out(v).list[i]); i++)
00381 if (e != ND_par(v))
00382 rerank(e->head, delta);
00383 for (i = 0; (e = ND_tree_in(v).list[i]); i++)
00384 if (e != ND_par(v))
00385 rerank(e->tail, delta);
00386 }
00387
00388
00389
00390
00391 static void
00392 update(edge_t * e, edge_t * f)
00393 {
00394 int cutvalue, delta;
00395 node_t *lca;
00396
00397 delta = SLACK(f);
00398
00399 if (delta > 0) {
00400 int s;
00401 s = ND_tree_in(e->tail).size + ND_tree_out(e->tail).size;
00402 if (s == 1)
00403 rerank(e->tail, delta);
00404 else {
00405 s = ND_tree_in(e->head).size + ND_tree_out(e->head).size;
00406 if (s == 1)
00407 rerank(e->head, -delta);
00408 else {
00409 if (ND_lim(e->tail) < ND_lim(e->head))
00410 rerank(e->tail, delta);
00411 else
00412 rerank(e->head, -delta);
00413 }
00414 }
00415 }
00416
00417 cutvalue = ED_cutvalue(e);
00418 lca = treeupdate(f->tail, f->head, cutvalue, 1);
00419 if (treeupdate(f->head, f->tail, cutvalue, 0) != lca)
00420 abort();
00421 ED_cutvalue(f) = -cutvalue;
00422 ED_cutvalue(e) = 0;
00423 exchange_tree_edges(e, f);
00424 dfs_range(lca, ND_par(lca), ND_low(lca));
00425 }
00426
00427 static void scan_and_normalize(void)
00428 {
00429 node_t *n;
00430
00431 Minrank = INT_MAX;
00432 Maxrank = -INT_MAX;
00433 for (n = GD_nlist(G); n; n = ND_next(n)) {
00434 if (ND_node_type(n) == NORMAL) {
00435 Minrank = MIN(Minrank, ND_rank(n));
00436 Maxrank = MAX(Maxrank, ND_rank(n));
00437 }
00438 }
00439 if (Minrank != 0) {
00440 for (n = GD_nlist(G); n; n = ND_next(n))
00441 ND_rank(n) -= Minrank;
00442 Maxrank -= Minrank;
00443 Minrank = 0;
00444 }
00445 }
00446
00447 static void
00448 freeTreeList (graph_t* g)
00449 {
00450 node_t *n;
00451 for (n = GD_nlist(G); n; n = ND_next(n)) {
00452 free_list(ND_tree_in(n));
00453 free_list(ND_tree_out(n));
00454 ND_mark(n) = FALSE;
00455 }
00456 }
00457
00458 static void LR_balance(void)
00459 {
00460 int i, delta;
00461 edge_t *e, *f;
00462
00463 for (i = 0; i < Tree_edge.size; i++) {
00464 e = Tree_edge.list[i];
00465 if (ED_cutvalue(e) == 0) {
00466 f = enter_edge(e);
00467 if (f == NULL)
00468 continue;
00469 delta = SLACK(f);
00470 if (delta <= 1)
00471 continue;
00472 if (ND_lim(e->tail) < ND_lim(e->head))
00473 rerank(e->tail, delta / 2);
00474 else
00475 rerank(e->head, -delta / 2);
00476 }
00477 }
00478 freeTreeList (G);
00479 }
00480
00481 static void TB_balance(void)
00482 {
00483 node_t *n;
00484 edge_t *e;
00485 int i, low, high, choice, *nrank;
00486 int inweight, outweight;
00487
00488 scan_and_normalize();
00489
00490
00491 nrank = N_NEW(Maxrank + 1, int);
00492 for (i = 0; i <= Maxrank; i++)
00493 nrank[i] = 0;
00494 for (n = GD_nlist(G); n; n = ND_next(n))
00495 if (ND_node_type(n) == NORMAL)
00496 nrank[ND_rank(n)]++;
00497 for (n = GD_nlist(G); n; n = ND_next(n)) {
00498 if (ND_node_type(n) != NORMAL)
00499 continue;
00500 inweight = outweight = 0;
00501 low = 0;
00502 high = Maxrank;
00503 for (i = 0; (e = ND_in(n).list[i]); i++) {
00504 inweight += ED_weight(e);
00505 low = MAX(low, ND_rank(e->tail) + ED_minlen(e));
00506 }
00507 for (i = 0; (e = ND_out(n).list[i]); i++) {
00508 outweight += ED_weight(e);
00509 high = MIN(high, ND_rank(e->head) - ED_minlen(e));
00510 }
00511 if (low < 0)
00512 low = 0;
00513 if (inweight == outweight) {
00514 choice = low;
00515 for (i = low + 1; i <= high; i++)
00516 if (nrank[i] < nrank[choice])
00517 choice = i;
00518 nrank[ND_rank(n)]--;
00519 nrank[choice]++;
00520 ND_rank(n) = choice;
00521 }
00522 free_list(ND_tree_in(n));
00523 free_list(ND_tree_out(n));
00524 ND_mark(n) = FALSE;
00525 }
00526 free(nrank);
00527 }
00528
00529 static int init_graph(graph_t * g)
00530 {
00531 int i, feasible;
00532 node_t *n;
00533 edge_t *e;
00534
00535 G = g;
00536 N_nodes = N_edges = S_i = 0;
00537 for (n = GD_nlist(g); n; n = ND_next(n)) {
00538 ND_mark(n) = FALSE;
00539 N_nodes++;
00540 for (i = 0; (e = ND_out(n).list[i]); i++)
00541 N_edges++;
00542 }
00543
00544 Tree_node.list = ALLOC(N_nodes, Tree_node.list, node_t *);
00545 Tree_node.size = 0;
00546 Tree_edge.list = ALLOC(N_nodes, Tree_edge.list, edge_t *);
00547 Tree_edge.size = 0;
00548
00549 feasible = TRUE;
00550 for (n = GD_nlist(g); n; n = ND_next(n)) {
00551 ND_priority(n) = 0;
00552 for (i = 0; (e = ND_in(n).list[i]); i++) {
00553 ND_priority(n)++;
00554 ED_cutvalue(e) = 0;
00555 ED_tree_index(e) = -1;
00556 if (feasible
00557 && (ND_rank(e->head) - ND_rank(e->tail) < ED_minlen(e)))
00558 feasible = FALSE;
00559 }
00560 ND_tree_in(n).list = N_NEW(i + 1, edge_t *);
00561 ND_tree_in(n).size = 0;
00562 for (i = 0; (e = ND_out(n).list[i]); i++);
00563 ND_tree_out(n).list = N_NEW(i + 1, edge_t *);
00564 ND_tree_out(n).size = 0;
00565 }
00566 return feasible;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 int rank(graph_t * g, int balance, int maxiter)
00582 {
00583 int iter = 0, feasible;
00584 char *s, *ns = "network simplex: ";
00585 edge_t *e, *f;
00586
00587 #ifdef DEBUG
00588 check_cycles(g);
00589 #endif
00590 if (Verbose)
00591 start_timer();
00592 feasible = init_graph(g);
00593 if (!feasible)
00594 init_rank();
00595 if (maxiter <= 0) {
00596 freeTreeList (g);
00597 return 0;
00598 }
00599
00600 if ((s = agget(g, "searchsize")))
00601 Search_size = atoi(s);
00602 else
00603 Search_size = SEARCHSIZE;
00604
00605 if (feasible_tree()) {
00606 freeTreeList (g);
00607 return 1;
00608 }
00609 while ((e = leave_edge())) {
00610 f = enter_edge(e);
00611 update(e, f);
00612 iter++;
00613 if (Verbose && (iter % 100 == 0)) {
00614 if (iter % 1000 == 100)
00615 fputs(ns, stderr);
00616 fprintf(stderr, "%d ", iter);
00617 if (iter % 1000 == 0)
00618 fputc('\n', stderr);
00619 }
00620 if (iter >= maxiter)
00621 break;
00622 }
00623 switch (balance) {
00624 case 1:
00625 TB_balance();
00626 break;
00627 case 2:
00628 LR_balance();
00629 break;
00630 default:
00631 scan_and_normalize();
00632 break;
00633 }
00634 if (Verbose) {
00635 if (iter >= 100)
00636 fputc('\n', stderr);
00637 fprintf(stderr, "%s%d nodes %d edges %d iter %.2f sec\n",
00638 ns, N_nodes, N_edges, iter, elapsed_sec());
00639 }
00640 return 0;
00641 }
00642
00643
00644 static void x_cutval(edge_t * f)
00645 {
00646 node_t *v;
00647 edge_t *e;
00648 int i, sum, dir;
00649
00650
00651 if (ND_par(f->tail) == f) {
00652 v = f->tail;
00653 dir = 1;
00654 } else {
00655 v = f->head;
00656 dir = -1;
00657 }
00658
00659 sum = 0;
00660 for (i = 0; (e = ND_out(v).list[i]); i++)
00661 sum += x_val(e, v, dir);
00662 for (i = 0; (e = ND_in(v).list[i]); i++)
00663 sum += x_val(e, v, dir);
00664 ED_cutvalue(f) = sum;
00665 }
00666
00667 static int x_val(edge_t * e, node_t * v, int dir)
00668 {
00669 node_t *other;
00670 int d, rv, f;
00671
00672 if (e->tail == v)
00673 other = e->head;
00674 else
00675 other = e->tail;
00676 if (!(SEQ(ND_low(v), ND_lim(other), ND_lim(v)))) {
00677 f = 1;
00678 rv = ED_weight(e);
00679 } else {
00680 f = 0;
00681 if (TREE_EDGE(e))
00682 rv = ED_cutvalue(e);
00683 else
00684 rv = 0;
00685 rv -= ED_weight(e);
00686 }
00687 if (dir > 0) {
00688 if (e->head == v)
00689 d = 1;
00690 else
00691 d = -1;
00692 } else {
00693 if (e->tail == v)
00694 d = 1;
00695 else
00696 d = -1;
00697 }
00698 if (f)
00699 d = -d;
00700 if (d < 0)
00701 rv = -rv;
00702 return rv;
00703 }
00704
00705 static void dfs_cutval(node_t * v, edge_t * par)
00706 {
00707 int i;
00708 edge_t *e;
00709
00710 for (i = 0; (e = ND_tree_out(v).list[i]); i++)
00711 if (e != par)
00712 dfs_cutval(e->head, e);
00713 for (i = 0; (e = ND_tree_in(v).list[i]); i++)
00714 if (e != par)
00715 dfs_cutval(e->tail, e);
00716 if (par)
00717 x_cutval(par);
00718 }
00719
00720 static int dfs_range(node_t * v, edge_t * par, int low)
00721 {
00722 edge_t *e;
00723 int i, lim;
00724
00725 lim = low;
00726 ND_par(v) = par;
00727 ND_low(v) = low;
00728 for (i = 0; (e = ND_tree_out(v).list[i]); i++)
00729 if (e != par)
00730 lim = dfs_range(e->head, e, lim);
00731 for (i = 0; (e = ND_tree_in(v).list[i]); i++)
00732 if (e != par)
00733 lim = dfs_range(e->tail, e, lim);
00734 ND_lim(v) = lim;
00735 return lim + 1;
00736 }
00737
00738 #ifdef DEBUG
00739 void tchk(void)
00740 {
00741 int i, n_cnt, e_cnt;
00742 node_t *n;
00743 edge_t *e;
00744
00745 n_cnt = 0;
00746 e_cnt = 0;
00747 for (n = GD_nlist(G); n; n = ND_next(n)) {
00748 n_cnt++;
00749 for (i = 0; (e = ND_tree_out(n).list[i]); i++) {
00750 e_cnt++;
00751 if (SLACK(e) > 0)
00752 printf("not a tight tree %x", e);
00753 }
00754 }
00755 if ((n_cnt != Tree_node.size) || (e_cnt != Tree_edge.size))
00756 printf("something missing\n");
00757 }
00758
00759 void check_cutvalues(void)
00760 {
00761 node_t *v;
00762 edge_t *e;
00763 int i, save;
00764
00765 for (v = GD_nlist(G); v; v = ND_next(v)) {
00766 for (i = 0; (e = ND_tree_out(v).list[i]); i++) {
00767 save = ED_cutvalue(e);
00768 x_cutval(e);
00769 if (save != ED_cutvalue(e))
00770 abort();
00771 }
00772 }
00773 }
00774
00775 int check_ranks(void)
00776 {
00777 int i, cost = 0;
00778 node_t *n;
00779 edge_t *e;
00780
00781 for (n = GD_nlist(G); n; n = ND_next(n)) {
00782 for (i = 0; (e = ND_out(n).list[i]); i++) {
00783 cost += (ED_weight(e)) * abs(LENGTH(e));
00784 if (ND_rank(e->head) - ND_rank(e->tail) - ED_minlen(e) < 0)
00785 abort();
00786 }
00787 }
00788 fprintf(stderr, "rank cost %d\n", cost);
00789 return cost;
00790 }
00791
00792 void checktree(void)
00793 {
00794 int i, n = 0, m = 0;
00795 node_t *v;
00796 edge_t *e;
00797
00798 for (v = GD_nlist(G); v; v = ND_next(v)) {
00799 for (i = 0; (e = ND_tree_out(v).list[i]); i++)
00800 n++;
00801 if (i != ND_tree_out(v).size)
00802 abort();
00803 for (i = 0; (e = ND_tree_in(v).list[i]); i++)
00804 m++;
00805 if (i != ND_tree_in(v).size)
00806 abort();
00807 }
00808 printf("%d %d %d\n", Tree_edge.size, n, m);
00809 }
00810
00811 void check_fast_node(node_t * n)
00812 {
00813 node_t *nptr;
00814 nptr = GD_nlist(n->graph);
00815 while (nptr && nptr != n)
00816 nptr = ND_next(nptr);
00817 assert(nptr != NULL);
00818 }
00819
00820 static node_t *checkdfs(node_t * n)
00821 {
00822 int i;
00823 edge_t *e;
00824 node_t *w,*x;
00825
00826 if (ND_mark(n))
00827 return 0;
00828 ND_mark(n) = TRUE;
00829 ND_onstack(n) = TRUE;
00830 for (i = 0; (e = ND_out(n).list[i]); i++) {
00831 w = e->head;
00832 if (ND_onstack(w)) {
00833 fprintf(stderr, "cycle: last edge %x %s(%x) %s(%x)\n",
00834 e,n->name,n,w->name,w);
00835 return w;
00836 }
00837 else {
00838 if (ND_mark(w) == FALSE) {
00839 x = checkdfs(w);
00840 if (x) {
00841 fprintf(stderr,"unwind %x %s(%x)\n",e,n->name,n);
00842 if (x != n) return x;
00843 fprintf(stderr,"unwound to root\n");
00844 fflush(stderr);
00845 abort();
00846 return 0;
00847 }
00848 }
00849 }
00850 }
00851 ND_onstack(n) = FALSE;
00852 return 0;
00853 }
00854
00855 void check_cycles(graph_t * g)
00856 {
00857 node_t *n;
00858 for (n = GD_nlist(g); n; n = ND_next(n))
00859 ND_mark(n) = ND_onstack(n) = FALSE;
00860 for (n = GD_nlist(g); n; n = ND_next(n))
00861 checkdfs(n);
00862 }
00863 #endif