Graphviz 13.1.3~dev.20250813.1130
Loading...
Searching...
No Matches
stuff.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11
12#include "config.h"
13#include <math.h>
14#include <neatogen/neato.h>
15#include <neatogen/stress.h>
16#include <stdatomic.h>
17#include <stdlib.h>
18#include <time.h>
19#include <util/alloc.h>
20#ifndef _WIN32
21#include <unistd.h>
22#endif
23
24static double Epsilon2;
25static Agnode_t *choose_node(graph_t *, int);
26static void make_spring(graph_t *, Agnode_t *, Agnode_t *, double);
27static void move_node(graph_t *, int, Agnode_t *);
28
29static double distvec(double *p0, double *p1, double *vec)
30{
31 int k;
32 double dist = 0.0;
33
34 for (k = 0; k < Ndim; k++) {
35 vec[k] = p0[k] - p1[k];
36 dist += vec[k] * vec[k];
37 }
38 dist = sqrt(dist);
39 return dist;
40}
41
42double **new_array(int m, int n, double ival)
43{
44 int i, j;
45
46 double **rv = gv_calloc(m, sizeof(double*));
47 double *mem = gv_calloc(m * n, sizeof(double));
48 for (i = 0; i < m; i++) {
49 rv[i] = mem;
50 mem += n;
51 for (j = 0; j < n; j++)
52 rv[i][j] = ival;
53 }
54 return rv;
55}
56
57void free_array(double **rv)
58{
59 if (rv) {
60 free(rv[0]);
61 free(rv);
62 }
63}
64
65
66static double ***new_3array(int m, int n, int p, double ival)
67{
68 int i, j, k;
69
70 double ***rv = gv_calloc(m + 1, sizeof(double**));
71 for (i = 0; i < m; i++) {
72 rv[i] = gv_calloc(n + 1, sizeof(double*));
73 for (j = 0; j < n; j++) {
74 rv[i][j] = gv_calloc(p, sizeof(double));
75 for (k = 0; k < p; k++)
76 rv[i][j][k] = ival;
77 }
78 rv[i][j] = NULL; /* NULL terminate so we can clean up */
79 }
80 rv[i] = NULL;
81 return rv;
82}
83
84static void free_3array(double ***rv)
85{
86 int i, j;
87
88 if (rv) {
89 for (i = 0; rv[i]; i++) {
90 for (j = 0; rv[i][j]; j++)
91 free(rv[i][j]);
92 free(rv[i]);
93 }
94 free(rv);
95 }
96}
97
98
99/* lenattr:
100 * Return 1 if attribute not defined
101 * Return 2 if attribute string bad
102 */
103static int lenattr(edge_t* e, Agsym_t* index, double* val)
104{
105 char* s;
106
107 if (index == NULL)
108 return 1;
109
110 s = agxget(e, index);
111 if (*s == '\0') return 1;
112
113 if (sscanf(s, "%lf", val) < 1 || *val < 0 || (*val == 0 && !Nop)) {
114 agwarningf("bad edge len \"%s\"", s);
115 return 2;
116 }
117 else
118 return 0;
119}
120
121
122/* degreeKind;
123 * Returns degree of n ignoring loops and multiedges.
124 * Returns 0, 1 or many (2)
125 * For case of 1, returns other endpoint of edge.
126 */
127static int degreeKind(graph_t * g, node_t * n, node_t ** op)
128{
129 edge_t *ep;
130 int deg = 0;
131 node_t *other = NULL;
132
133 for (ep = agfstedge(g, n); ep; ep = agnxtedge(g, ep, n)) {
134 if (aghead(ep) == agtail(ep))
135 continue; /* ignore loops */
136 if (deg == 1) {
137 if ((agtail(ep) == n && aghead(ep) == other) || /* ignore multiedge */
138 (agtail(ep) == other && aghead(ep) == n))
139 continue;
140 return 2;
141 } else { /* deg == 0 */
142 if (agtail(ep) == n)
143 other = aghead(ep);
144 else
145 other = agtail(ep);
146 *op = other;
147 deg++;
148 }
149 }
150 return deg;
151}
152
153
154/* prune:
155 * np is at end of a chain. If its degree is 0, remove it.
156 * If its degree is 1, remove it and recurse.
157 * If its degree > 1, stop.
158 * The node next is the next node to be visited during iteration.
159 * If it is equal to a node being deleted, set it to next one.
160 * Delete from root graph, since G may be a connected component subgraph.
161 * Return next.
162 */
163static node_t *prune(graph_t * G, node_t * np, node_t * next)
164{
165 node_t *other;
166 int deg;
167
168 while (np) {
169 deg = degreeKind(G, np, &other);
170 if (deg == 0) {
171 if (next == np)
172 next = agnxtnode(G, np);
173 agdelete(G->root, np);
174 np = 0;
175 } else if (deg == 1) {
176 if (next == np)
177 next = agnxtnode(G, np);
178 agdelete(G->root, np);
179 np = other;
180 } else
181 np = 0;
182
183 }
184 return next;
185}
186
187static double setEdgeLen(graph_t * G, node_t * np, Agsym_t* lenx, double dfltlen)
188{
189 edge_t *ep;
190 double total_len = 0.0;
191 double len;
192 int err;
193
194 for (ep = agfstout(G, np); ep; ep = agnxtout(G, ep)) {
195 if ((err = lenattr(ep, lenx, &len))) {
196 if (err == 2) agerr(AGPREV, " in %s - setting to %.02f\n", agnameof(G), dfltlen);
197 len = dfltlen;
198 }
199 ED_dist(ep) = len;
200 total_len += len;
201 }
202 return total_len;
203}
204
205/* scan_graph_mode:
206 * Prepare the graph and data structures depending on the layout mode.
207 * If Reduce is true, eliminate singletons and trees. Since G may be a
208 * subgraph, we remove the nodes from the root graph.
209 * Return the number of nodes in the reduced graph.
210 */
212{
213 int i, nV, nE, deg;
214 char *str;
215 node_t *np, *xp, *other;
216 double total_len = 0.0;
217 double dfltlen = 1.0;
218 Agsym_t* lenx;
219
220 if (Verbose)
221 fprintf(stderr, "Scanning graph %s, %d nodes\n", agnameof(G),
222 agnnodes(G));
223
224
225 /* Eliminate singletons and trees */
226 if (Reduce) {
227 for (np = agfstnode(G); np; np = xp) {
228 xp = agnxtnode(G, np);
229 deg = degreeKind(G, np, &other);
230 if (deg == 0) { /* singleton node */
231 agdelete(G->root, np);
232 } else if (deg == 1) {
233 agdelete(G->root, np);
234 xp = prune(G, other, xp);
235 }
236 }
237 }
238
239 nV = agnnodes(G);
240 nE = agnedges(G);
241
242 lenx = agattr_text(G, AGEDGE, "len", 0);
243 if (mode == MODE_KK) {
244 Epsilon = .0001 * nV;
245 getdouble(G, "epsilon", &Epsilon);
246 if ((str = agget(G->root, "Damping")))
247 Damping = atof(str);
248 else
249 Damping = .99;
250 GD_neato_nlist(G) = gv_calloc(nV + 1, sizeof(node_t*));
251 for (i = 0, np = agfstnode(G); np; np = agnxtnode(G, np)) {
252 GD_neato_nlist(G)[i] = np;
253 ND_id(np) = i++;
254 ND_heapindex(np) = -1;
255 total_len += setEdgeLen(G, np, lenx, dfltlen);
256 }
257 } else if (mode == MODE_SGD) {
258 Epsilon = .01;
259 getdouble(G, "epsilon", &Epsilon);
260 GD_neato_nlist(G) = gv_calloc(nV + 1, sizeof(node_t *));
261 for (i = 0, np = agfstnode(G); np; np = agnxtnode(G, np)) {
262 GD_neato_nlist(G)[i] = np;
263 ND_id(np) = i++;
264 total_len += setEdgeLen(G, np, lenx, dfltlen);
265 }
266 } else {
268 getdouble(G, "epsilon", &Epsilon);
269 for (i = 0, np = agfstnode(G); np; np = agnxtnode(G, np)) {
270 ND_id(np) = i++;
271 total_len += setEdgeLen(G, np, lenx, dfltlen);
272 }
273 }
274
275 str = agget(G, "defaultdist");
276 if (str && str[0])
277 Initial_dist = fmax(Epsilon, atof(str));
278 else
279 Initial_dist = total_len / (nE > 0 ? nE : 1) * sqrt(nV) + 1;
280
281 if (!Nop && mode == MODE_KK) {
282 GD_dist(G) = new_array(nV, nV, Initial_dist);
283 GD_spring(G) = new_array(nV, nV, 1.0);
284 GD_sum_t(G) = new_array(nV, Ndim, 1.0);
285 GD_t(G) = new_3array(nV, nV, Ndim, 0.0);
286 }
287
288 return nV;
289}
290
292{
293 return scan_graph_mode(g, MODE_KK);
294}
295
297{
299 if (!Nop) {
303 free_3array(GD_t(g));
304 GD_t(g) = NULL;
305 }
306}
307
308void jitter_d(node_t * np, int nG, int n)
309{
310 int k;
311 for (k = n; k < Ndim; k++)
312 ND_pos(np)[k] = nG * drand48();
313}
314
315void jitter3d(node_t * np, int nG)
316{
317 jitter_d(np, nG, 2);
318}
319
320void randompos(node_t * np, int nG)
321{
322 ND_pos(np)[0] = nG * drand48();
323 ND_pos(np)[1] = nG * drand48();
324 if (Ndim > 2)
325 jitter3d(np, nG);
326}
327
329{
330 int init, i;
331 node_t *np;
332 static atomic_flag once;
333
334 if (Verbose)
335 fprintf(stderr, "Setting initial positions\n");
336
338 if (init == INIT_REGULAR)
339 return;
340 if (init == INIT_SELF && !atomic_flag_test_and_set(&once)) {
341 agwarningf("start=0 not supported with mode=self - ignored\n");
342 }
343
344 for (i = 0; (np = GD_neato_nlist(G)[i]); i++) {
345 if (hasPos(np))
346 continue;
347 randompos(np, 1);
348 }
349}
350
351void diffeq_model(graph_t * G, int nG)
352{
353 int i, j, k;
354 double dist, **D, **K, del[MAXDIM], f;
355 node_t *vi, *vj;
356 edge_t *e;
357
358 if (Verbose) {
359 fprintf(stderr, "Setting up spring model: ");
360 start_timer();
361 }
362 /* init springs */
363 K = GD_spring(G);
364 D = GD_dist(G);
365 for (i = 0; i < nG; i++) {
366 for (j = 0; j < i; j++) {
367 f = Spring_coeff / (D[i][j] * D[i][j]);
368 if ((e = agfindedge(G, GD_neato_nlist(G)[i], GD_neato_nlist(G)[j])))
369 f *= ED_factor(e);
370 K[i][j] = K[j][i] = f;
371 }
372 }
373
374 /* init differential equation solver */
375 for (i = 0; i < nG; i++)
376 for (k = 0; k < Ndim; k++)
377 GD_sum_t(G)[i][k] = 0.0;
378
379 for (i = 0; (vi = GD_neato_nlist(G)[i]); i++) {
380 for (j = 0; j < nG; j++) {
381 if (i == j)
382 continue;
383 vj = GD_neato_nlist(G)[j];
384 dist = distvec(ND_pos(vi), ND_pos(vj), del);
385 for (k = 0; k < Ndim; k++) {
386 GD_t(G)[i][j][k] =
387 GD_spring(G)[i][j] * (del[k] -
388 GD_dist(G)[i][j] * del[k] /
389 dist);
390 GD_sum_t(G)[i][k] += GD_t(G)[i][j][k];
391 }
392 }
393 }
394 if (Verbose) {
395 fprintf(stderr, "%.2f sec\n", elapsed_sec());
396 }
397}
398
399/* total_e:
400 * Return 2*energy of system.
401 */
402static double total_e(graph_t * G, int nG)
403{
404 int i, j, d;
405 double e = 0.0; /* 2*energy */
406 double t0; /* distance squared */
407 double t1;
408 node_t *ip, *jp;
409
410 for (i = 0; i < nG - 1; i++) {
411 ip = GD_neato_nlist(G)[i];
412 for (j = i + 1; j < nG; j++) {
413 jp = GD_neato_nlist(G)[j];
414 for (t0 = 0.0, d = 0; d < Ndim; d++) {
415 t1 = ND_pos(ip)[d] - ND_pos(jp)[d];
416 t0 += t1 * t1;
417 }
418 e = e + GD_spring(G)[i][j] *
419 (t0 + GD_dist(G)[i][j] * GD_dist(G)[i][j]
420 - 2.0 * GD_dist(G)[i][j] * sqrt(t0));
421 }
422 }
423 return e;
424}
425
426void solve_model(graph_t * G, int nG)
427{
428 node_t *np;
429
431
432 while ((np = choose_node(G, nG))) {
433 move_node(G, nG, np);
434 }
435 if (Verbose) {
436 fprintf(stderr, "\nfinal e = %f", total_e(G, nG));
437 fprintf(stderr, " %d%s iterations %.2f sec\n",
438 GD_move(G), GD_move(G) == MaxIter ? "!" : "",
439 elapsed_sec());
440 }
441 if (GD_move(G) == MaxIter)
442 agwarningf("Max. iterations (%d) reached on graph %s\n",
443 MaxIter, agnameof(G));
444}
445
446static void update_arrays(graph_t * G, int nG, int i)
447{
448 int j, k;
449 double del[MAXDIM], dist;
450 node_t *vi, *vj;
451
452 vi = GD_neato_nlist(G)[i];
453 for (k = 0; k < Ndim; k++)
454 GD_sum_t(G)[i][k] = 0.0;
455 for (j = 0; j < nG; j++) {
456 if (i == j)
457 continue;
458 vj = GD_neato_nlist(G)[j];
459 dist = distvec(ND_pos(vi), ND_pos(vj), del);
460 for (k = 0; k < Ndim; k++) {
461 GD_t(G)[i][j][k] =
462 GD_spring(G)[i][j] * (del[k] -
463 GD_dist(G)[i][j] * del[k] / dist);
464 GD_sum_t(G)[i][k] += GD_t(G)[i][j][k];
465 const double old = GD_t(G)[j][i][k];
466 GD_t(G)[j][i][k] = -GD_t(G)[i][j][k];
467 GD_sum_t(G)[j][k] += GD_t(G)[j][i][k] - old;
468 }
469 }
470}
471
472#define Msub(i,j) M[(i)*Ndim+(j)]
473static void D2E(graph_t * G, int nG, int n, double *M)
474{
475 int i, l, k;
476 node_t *vi, *vn;
477 double scale, sq, t[MAXDIM];
478 double **K = GD_spring(G);
479 double **D = GD_dist(G);
480
481 vn = GD_neato_nlist(G)[n];
482 for (l = 0; l < Ndim; l++)
483 for (k = 0; k < Ndim; k++)
484 Msub(l, k) = 0.0;
485 for (i = 0; i < nG; i++) {
486 if (n == i)
487 continue;
488 vi = GD_neato_nlist(G)[i];
489 sq = 0.0;
490 for (k = 0; k < Ndim; k++) {
491 t[k] = ND_pos(vn)[k] - ND_pos(vi)[k];
492 sq += t[k] * t[k];
493 }
494 scale = 1 / pow(sq, 1.5);
495 for (k = 0; k < Ndim; k++) {
496 for (l = 0; l < k; l++)
497 Msub(l, k) += K[n][i] * D[n][i] * t[k] * t[l] * scale;
498 Msub(k, k) +=
499 K[n][i] * (1.0 - D[n][i] * (sq - t[k] * t[k]) * scale);
500 }
501 }
502 for (k = 1; k < Ndim; k++)
503 for (l = 0; l < k; l++)
504 Msub(k, l) = Msub(l, k);
505}
506
508{
509 int i, k;
510 double m, max;
511 node_t *choice, *np;
512 static int cnt = 0;
513
514 cnt++;
515 if (GD_move(G) >= MaxIter)
516 return NULL;
517 max = 0.0;
518 choice = NULL;
519 for (i = 0; i < nG; i++) {
520 np = GD_neato_nlist(G)[i];
521 if (ND_pinned(np) > P_SET)
522 continue;
523 for (m = 0.0, k = 0; k < Ndim; k++)
524 m += GD_sum_t(G)[i][k] * GD_sum_t(G)[i][k];
525 /* could set the color=energy of the node here */
526 if (m > max) {
527 choice = np;
528 max = m;
529 }
530 }
531 if (max < Epsilon2)
532 choice = NULL;
533 else {
534 if (Verbose && cnt % 100 == 0) {
535 fprintf(stderr, "%.3f ", sqrt(max));
536 if (cnt % 1000 == 0)
537 fprintf(stderr, "\n");
538 }
539 }
540 return choice;
541}
542
543void move_node(graph_t * G, int nG, node_t * n)
544{
545 int i, m;
546 double b[MAXDIM] = {0};
547 double c[MAXDIM] = {0};
548
549 m = ND_id(n);
550 double *a = gv_calloc((size_t)Ndim * Ndim, sizeof(double));
551 D2E(G, nG, m, a);
552 for (i = 0; i < Ndim; i++)
553 c[i] = -GD_sum_t(G)[m][i];
554 solve(a, b, c, Ndim);
555 for (i = 0; i < Ndim; i++) {
556 b[i] = (Damping + 2 * (1 - Damping) * drand48()) * b[i];
557 ND_pos(n)[i] += b[i];
558 }
559 GD_move(G)++;
560 update_arrays(G, nG, m);
561 if (test_toggle()) {
562 double sum = 0;
563 for (i = 0; i < Ndim; i++) {
564 sum += fabs(b[i]);
565 } /* Why not squared? */
566 sum = sqrt(sum);
567 fprintf(stderr, "%s %.3f\n", agnameof(n), sum);
568 }
569 free(a);
570}
571
572static node_t **Heap;
573static int Heapsize;
574static node_t *Src;
575
576static void heapup(node_t * v)
577{
578 int i, par;
579 node_t *u;
580
581 for (i = ND_heapindex(v); i > 0; i = par) {
582 par = (i - 1) / 2;
583 u = Heap[par];
584 if (ND_dist(u) <= ND_dist(v))
585 break;
586 Heap[par] = v;
587 ND_heapindex(v) = par;
588 Heap[i] = u;
589 ND_heapindex(u) = i;
590 }
591}
592
593static void heapdown(node_t * v)
594{
595 int i, left, right, c;
596 node_t *u;
597
598 i = ND_heapindex(v);
599 while ((left = 2 * i + 1) < Heapsize) {
600 right = left + 1;
602 c = right;
603 else
604 c = left;
605 u = Heap[c];
606 if (ND_dist(v) <= ND_dist(u))
607 break;
608 Heap[c] = v;
609 ND_heapindex(v) = c;
610 Heap[i] = u;
611 ND_heapindex(u) = i;
612 i = c;
613 }
614}
615
617{
618 int i;
619
620 assert(ND_heapindex(v) < 0);
621 i = Heapsize++;
622 ND_heapindex(v) = i;
623 Heap[i] = v;
624 if (i > 0)
625 heapup(v);
626}
627
629{
630 int i;
631 node_t *rv, *v;
632
633 if (Heapsize == 0)
634 return NULL;
635 rv = Heap[0];
636 i = --Heapsize;
637 v = Heap[i];
638 Heap[0] = v;
639 ND_heapindex(v) = 0;
640 if (i > 1)
641 heapdown(v);
642 ND_heapindex(rv) = -1;
643 return rv;
644}
645
646void shortest_path(graph_t * G, int nG)
647{
648 node_t *v;
649
650 Heap = gv_calloc(nG + 1, sizeof(node_t*));
651 if (Verbose) {
652 fprintf(stderr, "Calculating shortest paths: ");
653 start_timer();
654 }
655 for (v = agfstnode(G); v; v = agnxtnode(G, v))
656 s1(G, v);
657 if (Verbose) {
658 fprintf(stderr, "%.2f sec\n", elapsed_sec());
659 }
660 free(Heap);
661}
662
664{
665 node_t *v, *u;
666 edge_t *e;
667 int t;
668 double f;
669
670 for (t = 0; (v = GD_neato_nlist(G)[t]); t++)
672 Src = node;
673 ND_dist(Src) = 0;
674 ND_hops(Src) = 0;
676
677 while ((v = neato_dequeue())) {
678 if (v != Src)
679 make_spring(G, Src, v, ND_dist(v));
680 for (e = agfstedge(G, v); e; e = agnxtedge(G, e, v)) {
681 if ((u = agtail(e)) == v)
682 u = aghead(e);
683 f = ND_dist(v) + ED_dist(e);
684 if (ND_dist(u) > f) {
685 ND_dist(u) = f;
686 if (ND_heapindex(u) >= 0)
687 heapup(u);
688 else {
689 ND_hops(u) = ND_hops(v) + 1;
690 neato_enqueue(u);
691 }
692 }
693 }
694 }
695}
696
697void make_spring(graph_t * G, node_t * u, node_t * v, double f)
698{
699 int i, j;
700
701 i = ND_id(u);
702 j = ND_id(v);
703 GD_dist(G)[i][j] = GD_dist(G)[j][i] = f;
704}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define Epsilon
Definition arcball.h:209
#define right(i)
Definition closest.c:80
int test_toggle(void)
Definition utils.c:414
double drand48(void)
Definition utils.c:1548
#define P_SET
Definition const.h:261
#define MAXDIM
Definition const.h:169
#define Spring_coeff
Definition const.h:167
mode
Definition cvtgxl.c:33
static char * err
Definition delaunay.c:546
#define left
Definition dthdr.h:12
static void del(Dict_t *d, Dtlink_t **set, Agedge_t *e)
Definition edge.c:156
static void init(int argc, char *argv[], double *angle, double *accuracy, int *check_edges_with_same_endpoint, int *seed, const char **color_scheme, int *lightness)
static double dist(int dim, double *x, double *y)
#define G
Definition gdefs.h:7
static pointf scale(double c, pointf p)
Definition geomprocs.h:155
double Initial_dist
Definition globals.h:65
int MaxIter
Definition globals.h:61
int Nop
Definition globals.h:55
bool Reduce
Definition globals.h:52
unsigned short Ndim
Definition globals.h:62
double Damping
Definition globals.h:66
static double len(glCompPoint p)
Definition glutils.c:136
static bool Verbose
Definition gml2gv.c:24
void free(void *)
node NULL
Definition grammar.y:181
static int cnt(Dict_t *d, Dtlink_t **set)
Definition graph.c:196
int agnedges(Agraph_t *g)
Definition graph.c:161
int agnnodes(Agraph_t *g)
Definition graph.c:155
Agsym_t * agattr_text(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up text attributes of a graph
Definition attr.c:334
char * agget(void *obj, char *name)
Definition attr.c:448
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:458
#define ED_dist(e)
Definition types.h:602
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:26
#define agtail(e)
Definition cgraph.h:988
#define agfindedge(g, t, h)
Definition types.h:609
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Definition edge.c:96
#define ED_factor(e)
Definition types.h:585
#define aghead(e)
Definition cgraph.h:989
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:41
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Definition edge.c:87
void agwarningf(const char *fmt,...)
Definition agerror.c:173
int agerr(agerrlevel_t level, const char *fmt,...)
Definition agerror.c:155
@ AGPREV
Definition cgraph.h:957
#define GD_sum_t(g)
Definition types.h:404
#define GD_move(g)
Definition types.h:388
#define GD_t(g)
Definition types.h:405
#define GD_dist(g)
Definition types.h:357
#define GD_spring(g)
Definition types.h:403
#define GD_neato_nlist(g)
Definition types.h:392
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:48
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:41
#define ND_pinned(n)
Definition types.h:519
#define ND_heapindex(n)
Definition types.h:497
#define ND_hops(n)
Definition types.h:499
#define ND_pos(n)
Definition types.h:520
#define ND_dist(n)
Definition types.h:491
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:143
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Definition obj.c:20
@ AGEDGE
Definition cgraph.h:207
#define D
Definition hierarchy.c:120
textitem scanner parser str
Definition htmlparse.y:224
void getdouble(graph_t *g, char *name, double *result)
Definition input.c:500
#define hasPos(n)
Definition macros.h:18
#define ND_id(n)
Definition mm2gv.c:40
#define INIT_SELF
Definition neato.h:27
#define MODE_SGD
Definition neato.h:24
#define MODE_KK
Definition neato.h:20
#define INIT_RANDOM
Definition neato.h:29
#define INIT_REGULAR
Definition neato.h:28
int checkStart(graph_t *G, int nG, int dflt)
Definition neatoinit.c:1013
NEATOPROCS_API void solve(double *, double *, double *, size_t)
Definition solve.c:21
#define M
Definition randomkit.c:90
#define DFLT_TOLERANCE
Definition stress.h:29
graph or subgraph
Definition cgraph.h:424
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:651
static void heapup(node_t *v)
Definition stuff.c:576
static void update_arrays(graph_t *G, int nG, int i)
Definition stuff.c:446
static void make_spring(graph_t *, Agnode_t *, Agnode_t *, double)
Definition stuff.c:697
static double Epsilon2
Definition stuff.c:24
void solve_model(graph_t *G, int nG)
Definition stuff.c:426
void randompos(node_t *np, int nG)
Definition stuff.c:320
int scan_graph(graph_t *g)
Definition stuff.c:291
void s1(graph_t *G, node_t *node)
Definition stuff.c:663
#define Msub(i, j)
Definition stuff.c:472
void jitter3d(node_t *np, int nG)
Definition stuff.c:315
void shortest_path(graph_t *G, int nG)
Definition stuff.c:646
static node_t * prune(graph_t *G, node_t *np, node_t *next)
Definition stuff.c:163
static void D2E(graph_t *G, int nG, int n, double *M)
Definition stuff.c:473
static double setEdgeLen(graph_t *G, node_t *np, Agsym_t *lenx, double dfltlen)
Definition stuff.c:187
node_t * neato_dequeue(void)
Definition stuff.c:628
void jitter_d(node_t *np, int nG, int n)
Definition stuff.c:308
static node_t ** Heap
Definition stuff.c:572
int scan_graph_mode(graph_t *G, int mode)
Definition stuff.c:211
void free_array(double **rv)
Definition stuff.c:57
void free_scan_graph(graph_t *g)
Definition stuff.c:296
void diffeq_model(graph_t *G, int nG)
Definition stuff.c:351
static void move_node(graph_t *, int, Agnode_t *)
Definition stuff.c:543
void initial_positions(graph_t *G, int nG)
Definition stuff.c:328
static Agnode_t * choose_node(graph_t *, int)
Definition stuff.c:507
static int degreeKind(graph_t *g, node_t *n, node_t **op)
Definition stuff.c:127
static void heapdown(node_t *v)
Definition stuff.c:593
static void free_3array(double ***rv)
Definition stuff.c:84
static double total_e(graph_t *G, int nG)
Definition stuff.c:402
void neato_enqueue(node_t *v)
Definition stuff.c:616
static double distvec(double *p0, double *p1, double *vec)
Definition stuff.c:29
static double *** new_3array(int m, int n, int p, double ival)
Definition stuff.c:66
static node_t * Src
Definition stuff.c:574
static int Heapsize
Definition stuff.c:573
static int lenattr(edge_t *e, Agsym_t *index, double *val)
Definition stuff.c:103
double ** new_array(int m, int n, double ival)
Definition stuff.c:42
double elapsed_sec(void)
Definition timing.c:48
void start_timer(void)
Definition timing.c:43
Definition grammar.c:90