00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef HAVE_CONFIG_H
00019 #include "config.h"
00020 #endif
00021
00022 #include "neato.h"
00023 #include "stress.h"
00024 #include <time.h>
00025 #ifndef WIN32
00026 #include <unistd.h>
00027 #endif
00028
00029 static double Epsilon2;
00030 #ifndef HAVE_DRAND48
00031 double drand48(void)
00032 {
00033 double d;
00034 d = rand();
00035 d = d / RAND_MAX;
00036 return d;
00037 }
00038 #endif
00039
00040 double fpow32(double x)
00041 {
00042 x = sqrt(x);
00043 return x * x * x;
00044 }
00045
00046 double distvec(double *p0, double *p1, double *vec)
00047 {
00048 int k;
00049 double dist = 0.0;
00050
00051 for (k = 0; k < Ndim; k++) {
00052 vec[k] = p0[k] - p1[k];
00053 dist += (vec[k] * vec[k]);
00054 }
00055 dist = sqrt(dist);
00056 return dist;
00057 }
00058
00059 double **new_array(int m, int n, double ival)
00060 {
00061 double **rv;
00062 double *mem;
00063 int i, j;
00064
00065 rv = N_NEW(m, double *);
00066 mem = N_NEW(m * n, double);
00067 for (i = 0; i < m; i++) {
00068 rv[i] = mem;
00069 mem = mem + n;
00070 for (j = 0; j < n; j++)
00071 rv[i][j] = ival;
00072 }
00073 return rv;
00074 }
00075
00076 void free_array(double **rv)
00077 {
00078 if (rv) {
00079 free(rv[0]);
00080 free(rv);
00081 }
00082 }
00083
00084
00085 static double ***new_3array(int m, int n, int p, double ival)
00086 {
00087 double ***rv;
00088 int i, j, k;
00089
00090 rv = N_NEW(m + 1, double **);
00091 for (i = 0; i < m; i++) {
00092 rv[i] = N_NEW(n + 1, double *);
00093 for (j = 0; j < n; j++) {
00094 rv[i][j] = N_NEW(p, double);
00095 for (k = 0; k < p; k++)
00096 rv[i][j][k] = ival;
00097 }
00098 rv[i][j] = NULL;
00099 }
00100 rv[i] = NULL;
00101 return rv;
00102 }
00103
00104 static void free_3array(double ***rv)
00105 {
00106 int i, j;
00107
00108 if (rv) {
00109 for (i = 0; rv[i]; i++) {
00110 for (j = 0; rv[i][j]; j++)
00111 free(rv[i][j]);
00112 free(rv[i]);
00113 }
00114 free(rv);
00115 }
00116 }
00117
00118 double doubleattr(void *obj, int index, double defval)
00119 {
00120 double val;
00121 if (index < 0)
00122 return defval;
00123 if (sscanf(agxget(obj, index), "%lf", &val) < 1)
00124 return defval;
00125 return val;
00126 }
00127
00128
00129
00130
00131
00132
00133 static int degreeKind(graph_t * g, node_t * n, node_t ** op)
00134 {
00135 edge_t *ep;
00136 int deg = 0;
00137 node_t *other = NULL;
00138
00139 for (ep = agfstedge(g, n); ep; ep = agnxtedge(g, ep, n)) {
00140 if (ep->head == ep->tail)
00141 continue;
00142 if (deg == 1) {
00143 if (((ep->tail == n) && (ep->head == other)) ||
00144 ((ep->tail == other) && (ep->head == n)))
00145 continue;
00146 return 2;
00147 } else {
00148 if (ep->tail == n)
00149 other = ep->head;
00150 else
00151 other = ep->tail;
00152 *op = other;
00153 deg++;
00154 }
00155 }
00156 return deg;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static node_t *prune(graph_t * G, node_t * np, node_t * next)
00170 {
00171 node_t *other;
00172 int deg;
00173
00174 while (np) {
00175 deg = degreeKind(G, np, &other);
00176 if (deg == 0) {
00177 if (next == np)
00178 next = agnxtnode(G, np);
00179 agdelete(G->root, np);
00180 np = 0;
00181 } else if (deg == 1) {
00182 if (next == np)
00183 next = agnxtnode(G, np);
00184 agdelete(G->root, np);
00185 np = other;
00186 } else
00187 np = 0;
00188
00189 }
00190 return next;
00191 }
00192
00193 static double setEdgeLen(graph_t * G, node_t * np, int lenx)
00194 {
00195 edge_t *ep;
00196 double total_len = 0.0;
00197 double len;
00198 for (ep = agfstout(G, np); ep; ep = agnxtout(G, ep)) {
00199 len = doubleattr(ep, lenx, 1.0);
00200 if (len <= 0) {
00201 agerr(AGERR, "bad edge len %f in %s ignored\n", len, G->name);
00202 len = 1.0;
00203 }
00204 ED_dist(ep) = len;
00205 total_len += len;
00206 }
00207 return total_len;
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 int scan_graph_mode(graph_t * G, int mode)
00217 {
00218 int i, lenx, nV, nE, deg;
00219 char *str;
00220 node_t *np, *xp, *other;
00221 double total_len = 0.0;
00222
00223 if (Verbose)
00224 fprintf(stderr, "Scanning graph %s, %d nodes\n", G->name,
00225 agnnodes(G));
00226
00227
00228 if (Reduce) {
00229 for (np = agfstnode(G); np; np = xp) {
00230 xp = agnxtnode(G, np);
00231 deg = degreeKind(G, np, &other);
00232 if (deg == 0) {
00233 agdelete(G->root, np);
00234 } else if (deg == 1) {
00235 agdelete(G->root, np);
00236 xp = prune(G, other, xp);
00237 }
00238 }
00239 }
00240 nV = agnnodes(G);
00241 nE = agnedges(G);
00242
00243 lenx = agindex(G->root->proto->e, "len");
00244 if (mode == MODE_KK) {
00245 Epsilon = .0001 * nV;
00246 getdouble(G, "epsilon", &Epsilon);
00247 if ((str = agget(G->root, "Damping")))
00248 Damping = atof(str);
00249 else
00250 Damping = .99;
00251 GD_neato_nlist(G) = N_NEW(nV + 1, node_t *);
00252 for (i = 0, np = agfstnode(G); np; np = agnxtnode(G, np)) {
00253 GD_neato_nlist(G)[i] = np;
00254 ND_id(np) = i++;
00255 ND_heapindex(np) = -1;
00256 total_len += setEdgeLen(G, np, lenx);
00257 }
00258 } else {
00259 Epsilon = DFLT_TOLERANCE;
00260 getdouble(G, "epsilon", &Epsilon);
00261 for (i = 0, np = agfstnode(G); np; np = agnxtnode(G, np)) {
00262 ND_id(np) = i++;
00263 total_len += setEdgeLen(G, np, lenx);
00264 }
00265 }
00266
00267 str = agget(G, "defaultdist");
00268 if (str && str[0])
00269 Initial_dist = MAX(Epsilon, atof(str));
00270 else
00271 Initial_dist = total_len / (nE > 0 ? nE : 1) * sqrt(nV) + 1;
00272
00273 if (!Nop && (mode == MODE_KK)) {
00274 GD_dist(G) = new_array(nV, nV, Initial_dist);
00275 GD_spring(G) = new_array(nV, nV, 1.0);
00276 GD_sum_t(G) = new_array(nV, Ndim, 1.0);
00277 GD_t(G) = new_3array(nV, nV, Ndim, 0.0);
00278 }
00279
00280 return nV;
00281 }
00282
00283 int scan_graph(graph_t * g)
00284 {
00285 return scan_graph_mode(g, MODE_KK);
00286 }
00287
00288 void free_scan_graph(graph_t * g)
00289 {
00290
00291 free(GD_neato_nlist(g));
00292 if (!Nop) {
00293 free_array(GD_dist(g));
00294 free_array(GD_spring(g));
00295 free_array(GD_sum_t(g));
00296
00297 free_3array(GD_t(g));
00298 GD_t(g) = NULL;
00299 }
00300 }
00301
00302 void jitter_d(node_t * np, int nG, int n)
00303 {
00304 int k;
00305 for (k = n; k < Ndim; k++)
00306 ND_pos(np)[k] = nG * drand48();
00307 }
00308
00309 void jitter3d(node_t * np, int nG)
00310 {
00311 jitter_d(np, nG, 2);
00312 }
00313
00314 void randompos(node_t * np, int nG)
00315 {
00316 ND_pos(np)[0] = nG * drand48();
00317 ND_pos(np)[1] = nG * drand48();
00318 if (Ndim > 2)
00319 jitter3d(np, nG);
00320 }
00321
00322 void initial_positions(graph_t * G, int nG)
00323 {
00324 int init, i;
00325 node_t *np;
00326 static int once = 0;
00327
00328 if (Verbose)
00329 fprintf(stderr, "Setting initial positions\n");
00330
00331 init = checkStart(G, nG, INIT_RANDOM);
00332 if (init == INIT_REGULAR)
00333 return;
00334 if ((init == INIT_SELF) && (once == 0)) {
00335 agerr(AGWARN, "start=%s not supported with mode=self - ignored\n");
00336 once = 1;
00337 }
00338
00339 for (i = 0; (np = GD_neato_nlist(G)[i]); i++) {
00340 if (hasPos(np))
00341 continue;
00342 randompos(np, 1);
00343 }
00344 }
00345
00346 void diffeq_model(graph_t * G, int nG)
00347 {
00348 int i, j, k;
00349 double dist, **D, **K, del[MAXDIM], f;
00350 node_t *vi, *vj;
00351 edge_t *e;
00352
00353 if (Verbose) {
00354 fprintf(stderr, "Setting up spring model: ");
00355 start_timer();
00356 }
00357
00358 K = GD_spring(G);
00359 D = GD_dist(G);
00360 for (i = 0; i < nG; i++) {
00361 for (j = 0; j < i; j++) {
00362 f = Spring_coeff / (D[i][j] * D[i][j]);
00363 if ((e =
00364 agfindedge(G, GD_neato_nlist(G)[i],
00365 GD_neato_nlist(G)[j])))
00366 f = f * ED_factor(e);
00367 K[i][j] = K[j][i] = f;
00368 }
00369 }
00370
00371
00372 for (i = 0; i < nG; i++)
00373 for (k = 0; k < Ndim; k++)
00374 GD_sum_t(G)[i][k] = 0.0;
00375
00376 for (i = 0; (vi = GD_neato_nlist(G)[i]); i++) {
00377 for (j = 0; j < nG; j++) {
00378 if (i == j)
00379 continue;
00380 vj = GD_neato_nlist(G)[j];
00381 dist = distvec(ND_pos(vi), ND_pos(vj), del);
00382 for (k = 0; k < Ndim; k++) {
00383 GD_t(G)[i][j][k] =
00384 GD_spring(G)[i][j] * (del[k] -
00385 GD_dist(G)[i][j] * del[k] /
00386 dist);
00387 GD_sum_t(G)[i][k] += GD_t(G)[i][j][k];
00388 }
00389 }
00390 }
00391 if (Verbose) {
00392 fprintf(stderr, "%.2f sec\n", elapsed_sec());
00393 }
00394 }
00395
00396
00397
00398
00399 static double total_e(graph_t * G, int nG)
00400 {
00401 int i, j, d;
00402 double e = 0.0;
00403 double t0;
00404 double t1;
00405 node_t *ip, *jp;
00406
00407 for (i = 0; i < nG - 1; i++) {
00408 ip = GD_neato_nlist(G)[i];
00409 for (j = i + 1; j < nG; j++) {
00410 jp = GD_neato_nlist(G)[j];
00411 for (t0 = 0.0, d = 0; d < Ndim; d++) {
00412 t1 = (ND_pos(ip)[d] - ND_pos(jp)[d]);
00413 t0 += t1 * t1;
00414 }
00415 e = e + GD_spring(G)[i][j] *
00416 (t0 + GD_dist(G)[i][j] * GD_dist(G)[i][j]
00417 - 2.0 * GD_dist(G)[i][j] * sqrt(t0));
00418 }
00419 }
00420 return e;
00421 }
00422
00423 void solve_model(graph_t * G, int nG)
00424 {
00425 node_t *np;
00426
00427 Epsilon2 = Epsilon * Epsilon;
00428
00429 while ((np = choose_node(G, nG))) {
00430 move_node(G, nG, np);
00431 }
00432 if (Verbose) {
00433 fprintf(stderr, "\nfinal e = %f", total_e(G, nG));
00434 fprintf(stderr, " %d%s iterations %.2f sec\n",
00435 GD_move(G), (GD_move(G) == MaxIter ? "!" : ""),
00436 elapsed_sec());
00437 }
00438 if (GD_move(G) == MaxIter)
00439 agerr(AGWARN, "Max. iterations (%d) reached on graph %s\n",
00440 MaxIter, G->name);
00441 }
00442
00443 void update_arrays(graph_t * G, int nG, int i)
00444 {
00445 int j, k;
00446 double del[MAXDIM], dist, old;
00447 node_t *vi, *vj;
00448
00449 vi = GD_neato_nlist(G)[i];
00450 for (k = 0; k < Ndim; k++)
00451 GD_sum_t(G)[i][k] = 0.0;
00452 for (j = 0; j < nG; j++) {
00453 if (i == j)
00454 continue;
00455 vj = GD_neato_nlist(G)[j];
00456 dist = distvec(ND_pos(vi), ND_pos(vj), del);
00457 for (k = 0; k < Ndim; k++) {
00458 old = GD_t(G)[i][j][k];
00459 GD_t(G)[i][j][k] =
00460 GD_spring(G)[i][j] * (del[k] -
00461 GD_dist(G)[i][j] * del[k] / dist);
00462 GD_sum_t(G)[i][k] += GD_t(G)[i][j][k];
00463 old = GD_t(G)[j][i][k];
00464 GD_t(G)[j][i][k] = -GD_t(G)[i][j][k];
00465 GD_sum_t(G)[j][k] += (GD_t(G)[j][i][k] - old);
00466 }
00467 }
00468 }
00469
00470 #define Msub(i,j) M[(i)*Ndim+(j)]
00471 void D2E(graph_t * G, int nG, int n, double *M)
00472 {
00473 int i, l, k;
00474 node_t *vi, *vn;
00475 double scale, sq, t[MAXDIM];
00476 double **K = GD_spring(G);
00477 double **D = GD_dist(G);
00478
00479 vn = GD_neato_nlist(G)[n];
00480 for (l = 0; l < Ndim; l++)
00481 for (k = 0; k < Ndim; k++)
00482 Msub(l, k) = 0.0;
00483 for (i = 0; i < nG; i++) {
00484 if (n == i)
00485 continue;
00486 vi = GD_neato_nlist(G)[i];
00487 sq = 0.0;
00488 for (k = 0; k < Ndim; k++) {
00489 t[k] = ND_pos(vn)[k] - ND_pos(vi)[k];
00490 sq += (t[k] * t[k]);
00491 }
00492 scale = 1 / fpow32(sq);
00493 for (k = 0; k < Ndim; k++) {
00494 for (l = 0; l < k; l++)
00495 Msub(l, k) += K[n][i] * D[n][i] * t[k] * t[l] * scale;
00496 Msub(k, k) +=
00497 K[n][i] * (1.0 - D[n][i] * (sq - (t[k] * t[k])) * scale);
00498 }
00499 }
00500 for (k = 1; k < Ndim; k++)
00501 for (l = 0; l < k; l++)
00502 Msub(k, l) = Msub(l, k);
00503 }
00504
00505 void final_energy(graph_t * G, int nG)
00506 {
00507 fprintf(stderr, "iterations = %d final e = %f\n", GD_move(G),
00508 total_e(G, nG));
00509 }
00510
00511 node_t *choose_node(graph_t * G, int nG)
00512 {
00513 int i, k;
00514 double m, max;
00515 node_t *choice, *np;
00516 static int cnt = 0;
00517 #if 0
00518 double e;
00519 static double save_e = MAXDOUBLE;
00520 #endif
00521
00522 cnt++;
00523 if (GD_move(G) >= MaxIter)
00524 return NULL;
00525 #if 0
00526 if ((cnt % 100) == 0) {
00527 e = total_e(G, nG);
00528 if (e - save_e > 0)
00529 return NULL;
00530 save_e = e;
00531 }
00532 #endif
00533 max = 0.0;
00534 choice = NULL;
00535 for (i = 0; i < nG; i++) {
00536 np = GD_neato_nlist(G)[i];
00537 if (ND_pinned(np) > P_SET)
00538 continue;
00539 for (m = 0.0, k = 0; k < Ndim; k++)
00540 m += (GD_sum_t(G)[i][k] * GD_sum_t(G)[i][k]);
00541
00542 if (m > max) {
00543 choice = np;
00544 max = m;
00545 }
00546 }
00547 if (max < Epsilon2)
00548 choice = NULL;
00549 else {
00550 if (Verbose && (cnt % 100 == 0)) {
00551 fprintf(stderr, "%.3f ", sqrt(max));
00552 if (cnt % 1000 == 0)
00553 fprintf(stderr, "\n");
00554 }
00555 #if 0
00556 e = total_e(G, nG);
00557 if (fabs((e - save_e) / save_e) < 1e-5) {
00558 choice = NULL;
00559 }
00560 #endif
00561 }
00562 return choice;
00563 }
00564
00565 void move_node(graph_t * G, int nG, node_t * n)
00566 {
00567 int i, m;
00568 static double *a, b[MAXDIM], c[MAXDIM];
00569
00570 m = ND_id(n);
00571 a = ALLOC(Ndim * Ndim, a, double);
00572 D2E(G, nG, m, a);
00573 for (i = 0; i < Ndim; i++)
00574 c[i] = -GD_sum_t(G)[m][i];
00575 solve(a, b, c, Ndim);
00576 for (i = 0; i < Ndim; i++) {
00577 b[i] = (Damping + 2 * (1 - Damping) * drand48()) * b[i];
00578 ND_pos(n)[i] += b[i];
00579 }
00580 GD_move(G)++;
00581 update_arrays(G, nG, m);
00582 if (test_toggle()) {
00583 double sum = 0;
00584 for (i = 0; i < Ndim; i++) {
00585 sum += fabs(b[i]);
00586 }
00587 sum = sqrt(sum);
00588 fprintf(stderr, "%s %.3f\n", n->name, sum);
00589 }
00590 }
00591
00592 static node_t **Heap;
00593 static int Heapsize;
00594 static node_t *Src;
00595
00596 void heapup(node_t * v)
00597 {
00598 int i, par;
00599 node_t *u;
00600
00601 for (i = ND_heapindex(v); i > 0; i = par) {
00602 par = (i - 1) / 2;
00603 u = Heap[par];
00604 if (ND_dist(u) <= ND_dist(v))
00605 break;
00606 Heap[par] = v;
00607 ND_heapindex(v) = par;
00608 Heap[i] = u;
00609 ND_heapindex(u) = i;
00610 }
00611 }
00612
00613 void heapdown(node_t * v)
00614 {
00615 int i, left, right, c;
00616 node_t *u;
00617
00618 i = ND_heapindex(v);
00619 while ((left = 2 * i + 1) < Heapsize) {
00620 right = left + 1;
00621 if ((right < Heapsize)
00622 && (Heap[right]->u.dist < Heap[left]->u.dist))
00623 c = right;
00624 else
00625 c = left;
00626 u = Heap[c];
00627 if (ND_dist(v) <= ND_dist(u))
00628 break;
00629 Heap[c] = v;
00630 ND_heapindex(v) = c;
00631 Heap[i] = u;
00632 ND_heapindex(u) = i;
00633 i = c;
00634 }
00635 }
00636
00637 void neato_enqueue(node_t * v)
00638 {
00639 int i;
00640
00641 assert(ND_heapindex(v) < 0);
00642 i = Heapsize++;
00643 ND_heapindex(v) = i;
00644 Heap[i] = v;
00645 if (i > 0)
00646 heapup(v);
00647 }
00648
00649 node_t *neato_dequeue(void)
00650 {
00651 int i;
00652 node_t *rv, *v;
00653
00654 if (Heapsize == 0)
00655 return NULL;
00656 rv = Heap[0];
00657 i = --Heapsize;
00658 v = Heap[i];
00659 Heap[0] = v;
00660 ND_heapindex(v) = 0;
00661 if (i > 1)
00662 heapdown(v);
00663 ND_heapindex(rv) = -1;
00664 return rv;
00665 }
00666
00667 void shortest_path(graph_t * G, int nG)
00668 {
00669 node_t *v;
00670
00671 Heap = N_NEW(nG + 1, node_t *);
00672 if (Verbose) {
00673 fprintf(stderr, "Calculating shortest paths: ");
00674 start_timer();
00675 }
00676 for (v = agfstnode(G); v; v = agnxtnode(G, v))
00677 s1(G, v);
00678 if (Verbose) {
00679 fprintf(stderr, "%.2f sec\n", elapsed_sec());
00680 }
00681 free(Heap);
00682 }
00683
00684 void s1(graph_t * G, node_t * node)
00685 {
00686 node_t *v, *u;
00687 edge_t *e;
00688 int t;
00689 double f;
00690
00691 for (t = 0; (v = GD_neato_nlist(G)[t]); t++)
00692 ND_dist(v) = Initial_dist;
00693 Src = node;
00694 ND_dist(Src) = 0;
00695 ND_hops(Src) = 0;
00696 neato_enqueue(Src);
00697
00698 while ((v = neato_dequeue())) {
00699 if (v != Src)
00700 make_spring(G, Src, v, ND_dist(v));
00701 for (e = agfstedge(G, v); e; e = agnxtedge(G, e, v)) {
00702 if ((u = e->head) == v)
00703 u = e->tail;
00704 f = ND_dist(v) + ED_dist(e);
00705 if (ND_dist(u) > f) {
00706 ND_dist(u) = f;
00707 if (ND_heapindex(u) >= 0)
00708 heapup(u);
00709 else {
00710 ND_hops(u) = ND_hops(v) + 1;
00711 neato_enqueue(u);
00712 }
00713 }
00714 }
00715 }
00716 }
00717
00718 void make_spring(graph_t * G, node_t * u, node_t * v, double f)
00719 {
00720 int i, j;
00721
00722 i = ND_id(u);
00723 j = ND_id(v);
00724 GD_dist(G)[i][j] = GD_dist(G)[j][i] = f;
00725 }
00726
00727 int allow_edits(int nsec)
00728 {
00729 #ifdef INTERACTIVE
00730 static int onetime = TRUE;
00731 static FILE *fp;
00732 static fd_set fd;
00733 static struct timeval tv;
00734
00735 char buf[256], name[256];
00736 double x, y;
00737 node_t *np;
00738
00739 if (onetime) {
00740 fp = fopen("/dev/tty", "r");
00741 if (fp == NULL)
00742 exit(1);
00743 setbuf(fp, NULL);
00744 tv.tv_usec = 0;
00745 onetime = FALSE;
00746 }
00747 tv.tv_sec = nsec;
00748 FD_ZERO(&fd);
00749 FD_SET(fileno(fp), &fd);
00750 if (select(32, &fd, (fd_set *) 0, (fd_set *) 0, &tv) > 0) {
00751 fgets(buf, sizeof(buf), fp);
00752 switch (buf[0]) {
00753 case 'm':
00754 if (sscanf(buf + 1, "%s %lf%lf", name, &x, &y) == 3) {
00755 np = getnode(G, name);
00756 if (np) {
00757 NP_pos(np)[0] = x;
00758 NP_pos(np)[1] = y;
00759 diffeq_model();
00760 }
00761 }
00762 break;
00763 case 'q':
00764 return FALSE;
00765 default:
00766 agerr(AGERR, "unknown command '%s', ignored\n", buf);
00767 }
00768 return TRUE;
00769 }
00770 #endif
00771 return FALSE;
00772 }