00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "dot.h"
00019
00020
00021
00022
00023
00024
00025 static edge_t *ffe(node_t * u, elist uL, node_t * v, elist vL)
00026 {
00027 int i;
00028 edge_t *e;
00029
00030 if ((uL.size > 0) && (vL.size > 0)) {
00031 if (uL.size < vL.size) {
00032 for (i = 0; (e = uL.list[i]); i++)
00033 if (e->head == v)
00034 break;
00035 } else {
00036 for (i = 0; (e = vL.list[i]); i++)
00037 if (e->tail == u)
00038 break;
00039 }
00040 } else
00041 e = 0;
00042 return e;
00043 }
00044
00045 edge_t *find_fast_edge(node_t * u, node_t * v)
00046 {
00047 return ffe(u, ND_out(u), v, ND_in(v));
00048 }
00049
00050 static node_t*
00051 find_fast_node(graph_t * g, node_t * n)
00052 {
00053 node_t *v;
00054 for (v = GD_nlist(g); v; v = ND_next(v))
00055 if (v == n)
00056 break;
00057 return v;
00058 }
00059
00060 edge_t *find_flat_edge(node_t * u, node_t * v)
00061 {
00062 return ffe(u, ND_flat_out(u), v, ND_flat_in(v));
00063 }
00064
00065
00066 static void
00067 safe_list_append(edge_t * e, elist * L)
00068 {
00069 int i;
00070
00071 for (i = 0; i < L->size; i++)
00072 if (e == L->list[i])
00073 return;
00074 elist_append(e, (*L));
00075 }
00076
00077 edge_t *fast_edge(edge_t * e)
00078 {
00079 #ifdef DEBUG
00080 int i;
00081 edge_t *f;
00082 for (i = 0; (f = ND_out(e->tail).list[i]); i++) {
00083 if (e == f) {
00084 fprintf(stderr, "duplicate fast edge\n");
00085 return;
00086 }
00087 assert(e->head != f->head);
00088 }
00089 for (i = 0; (f = ND_in(e->head).list[i]); i++) {
00090 if (e == f) {
00091 fprintf(stderr, "duplicate fast edge\n");
00092 return;
00093 }
00094 assert(e->tail != f->tail);
00095 }
00096 #endif
00097 elist_append(e, ND_out(e->tail));
00098 elist_append(e, ND_in(e->head));
00099 return e;
00100 }
00101
00102
00103 void zapinlist(elist * L, edge_t * e)
00104 {
00105 int i;
00106
00107 for (i = 0; i < L->size; i++) {
00108 if (L->list[i] == e) {
00109 L->size--;
00110 L->list[i] = L->list[L->size];
00111 L->list[L->size] = NULL;
00112 break;
00113 }
00114 }
00115 }
00116
00117
00118 void delete_fast_edge(edge_t * e)
00119 {
00120 assert(e != NULL);
00121 zapinlist(&(ND_out(e->tail)), e);
00122 zapinlist(&(ND_in(e->head)), e);
00123 }
00124
00125 static void
00126 safe_delete_fast_edge(edge_t * e)
00127 {
00128 int i;
00129 edge_t *f;
00130
00131 assert(e != NULL);
00132 for (i = 0; (f = ND_out(e->tail).list[i]); i++)
00133 if (f == e)
00134 zapinlist(&(ND_out(e->tail)), e);
00135 for (i = 0; (f = ND_in(e->head).list[i]); i++)
00136 if (f == e)
00137 zapinlist(&(ND_in(e->head)), e);
00138 }
00139
00140 void other_edge(edge_t * e)
00141 {
00142 elist_append(e, ND_other(e->tail));
00143 }
00144
00145 void safe_other_edge(edge_t * e)
00146 {
00147 safe_list_append(e, &(ND_other(e->tail)));
00148 }
00149
00150 #ifdef OBSOLETE
00151 void
00152 delete_other_edge(edge_t * e)
00153 {
00154 assert(e != NULL);
00155 zapinlist(&(ND_other(e->tail)), e);
00156 }
00157 #endif
00158
00159
00160
00161
00162
00163
00164
00165 edge_t *new_virtual_edge(node_t * u, node_t * v, edge_t * orig)
00166 {
00167 edge_t *e;
00168
00169 e = NEW(edge_t);
00170 e->tail = u;
00171 e->head = v;
00172 ED_edge_type(e) = VIRTUAL;
00173
00174 if (orig) {
00175 e->id = orig->id;
00176 ED_count(e) = ED_count(orig);
00177 ED_xpenalty(e) = ED_xpenalty(orig);
00178 ED_weight(e) = ED_weight(orig);
00179 ED_minlen(e) = ED_minlen(orig);
00180 if (e->tail == orig->tail)
00181 ED_tail_port(e) = ED_tail_port(orig);
00182 else if (e->tail == orig->head)
00183 ED_tail_port(e) = ED_head_port(orig);
00184 if (e->head == orig->head)
00185 ED_head_port(e) = ED_head_port(orig);
00186 else if (e->head == orig->tail)
00187 ED_head_port(e) = ED_tail_port(orig);
00188
00189 if (ED_to_virt(orig) == NULL)
00190 ED_to_virt(orig) = e;
00191 ED_to_orig(e) = orig;
00192 } else
00193 ED_minlen(e) = ED_count(e) = ED_xpenalty(e) = ED_weight(e) = 1;
00194 return e;
00195 }
00196
00197 edge_t *virtual_edge(node_t * u, node_t * v, edge_t * orig)
00198 {
00199 return fast_edge(new_virtual_edge(u, v, orig));
00200 }
00201
00202 void fast_node(graph_t * g, Agnode_t * n)
00203 {
00204
00205 #ifdef DEBUG
00206 assert(find_fast_node(g, n) == NULL);
00207 #endif
00208 ND_next(n) = GD_nlist(g);
00209 if (ND_next(n))
00210 ND_next(n)->u.prev = n;
00211 GD_nlist(g) = n;
00212 ND_prev(n) = NULL;
00213 assert(n != ND_next(n));
00214 }
00215
00216 void fast_nodeapp(node_t * u, node_t * v)
00217 {
00218 assert(u != v);
00219 assert(ND_next(v) == NULL);
00220 ND_next(v) = ND_next(u);
00221 if (ND_next(u))
00222 ND_next(u)->u.prev = v;
00223 ND_prev(v) = u;
00224 ND_next(u) = v;
00225 }
00226
00227 void delete_fast_node(graph_t * g, node_t * n)
00228 {
00229 assert(find_fast_node(g, n));
00230 if (ND_next(n))
00231 ND_next(n)->u.prev = ND_prev(n);
00232 if (ND_prev(n))
00233 ND_prev(n)->u.next = ND_next(n);
00234 else
00235 GD_nlist(g) = ND_next(n);
00236 }
00237
00238 node_t *virtual_node(graph_t * g)
00239 {
00240 node_t *n;
00241
00242 n = NEW(node_t);
00243 n->name = "virtual";
00244 n->graph = g;
00245 ND_node_type(n) = VIRTUAL;
00246 ND_lw_i(n) = ND_rw_i(n) = 1;
00247 ND_ht_i(n) = 1;
00248 ND_UF_size(n) = 1;
00249 alloc_elist(4, ND_in(n));
00250 alloc_elist(4, ND_out(n));
00251 fast_node(g, n);
00252 GD_n_nodes(g)++;
00253 return n;
00254 }
00255
00256 void flat_edge(graph_t * g, edge_t * e)
00257 {
00258 elist_append(e, ND_flat_out(e->tail));
00259 elist_append(e, ND_flat_in(e->head));
00260 GD_has_flat_edges(g->root) = GD_has_flat_edges(g) = TRUE;
00261 }
00262
00263 void delete_flat_edge(edge_t * e)
00264 {
00265 assert(e != NULL);
00266 if (ED_to_orig(e) && ED_to_virt(ED_to_orig(e)) == e)
00267 ED_to_virt(ED_to_orig(e)) = NULL;
00268 zapinlist(&(ND_flat_out(e->tail)), e);
00269 zapinlist(&(ND_flat_in(e->head)), e);
00270 }
00271
00272 #ifdef DEBUG
00273 static char *NAME(node_t * n)
00274 {
00275 static char buf[20];
00276 if (ND_node_type(n) == NORMAL)
00277 return n->name;
00278 sprintf(buf, "V%x", n);
00279 return buf;
00280 }
00281
00282 void fastgr(graph_t * g)
00283 {
00284 int i, j;
00285 node_t *n, *w;
00286 edge_t *e, *f;
00287
00288 for (n = GD_nlist(g); n; n = ND_next(n)) {
00289 fprintf(stderr, "%s %d: (", NAME(n), ND_rank(n));
00290 for (i = 0; e = ND_out(n).list[i]; i++) {
00291 fprintf(stderr, " %s:%d", NAME(e->head), ED_count(e));
00292 w = e->head;
00293 if (g == g->root) {
00294 for (j = 0; f = ND_in(w).list[j]; j++)
00295 if (e == f)
00296 break;
00297 assert(f != NULL);
00298 }
00299 }
00300 fprintf(stderr, " ) (");
00301 for (i = 0; e = ND_in(n).list[i]; i++) {
00302 fprintf(stderr, " %s:%d", NAME(e->tail), ED_count(e));
00303 w = e->tail;
00304 if (g == g->root) {
00305 for (j = 0; f = ND_out(w).list[j]; j++)
00306 if (e == f)
00307 break;
00308 assert(f != NULL);
00309 }
00310 }
00311 fprintf(stderr, " )\n");
00312 }
00313 }
00314 #endif
00315
00316 static void
00317 basic_merge(edge_t * e, edge_t * rep)
00318 {
00319 if (ED_minlen(rep) < ED_minlen(e))
00320 ED_minlen(rep) = ED_minlen(e);
00321 while (rep) {
00322 ED_count(rep) += ED_count(e);
00323 ED_xpenalty(rep) += ED_xpenalty(e);
00324 ED_weight(rep) += ED_weight(e);
00325 rep = ED_to_virt(rep);
00326 }
00327 }
00328
00329 void
00330 merge_oneway(edge_t * e, edge_t * rep)
00331 {
00332 if (rep == ED_to_virt(e)) {
00333 agerr(AGWARN, "merge_oneway glitch\n");
00334 return;
00335 }
00336 assert(ED_to_virt(e) == NULL);
00337 ED_to_virt(e) = rep;
00338 basic_merge(e, rep);
00339 }
00340
00341 static void
00342 unrep(edge_t * rep, edge_t * e)
00343 {
00344 ED_count(rep) -= ED_count(e);
00345 ED_xpenalty(rep) -= ED_xpenalty(e);
00346 ED_weight(rep) -= ED_weight(e);
00347 }
00348
00349 void unmerge_oneway(edge_t * e)
00350 {
00351 edge_t *rep, *nextrep;
00352 for (rep = ED_to_virt(e); rep; rep = nextrep) {
00353 unrep(rep, e);
00354 nextrep = ED_to_virt(rep);
00355 if (ED_count(rep) == 0)
00356 safe_delete_fast_edge(rep);
00357
00358
00359 while ((ED_edge_type(rep) == VIRTUAL)
00360 && (ND_node_type(rep->head) == VIRTUAL)
00361 && (ND_out(rep->head).size == 1)) {
00362 rep = ND_out(rep->head).list[0];
00363 unrep(rep, e);
00364 }
00365 }
00366 ED_to_virt(e) = NULL;
00367 }
00368
00369 #ifdef OBSOLETET
00370 static int
00371 is_fast_node(graph_t * g, node_t * v)
00372 {
00373 node_t *n;
00374
00375 for (n = GD_nlist(g); n; n = ND_next(n))
00376 if (v == n)
00377 return TRUE;
00378 return FALSE;
00379 }
00380 #endif