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