Graphviz 14.1.2~dev.20251218.0900
Loading...
Searching...
No Matches
DotIO.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#define STANDALONE
12#include <sparse/general.h>
13#include <sparse/DotIO.h>
14#include <sparse/clustering.h>
15#include <math.h>
16#include <sparse/mq.h>
18#include <sparse/colorutil.h>
19#include <stdbool.h>
20#include <stddef.h>
21#include <string.h>
22#include <util/agxbuf.h>
23#include <util/alloc.h>
24#include <util/itos.h>
25#include <util/startswith.h>
26#include <util/unreachable.h>
27
28typedef struct {
29 Agrec_t h;
30 unsigned int id;
32
33#define ND_id(n) (((Agnodeinfo_t*)((n)->base.data))->id)
34
35static void color_string(agxbuf *buf, int dim, double *color){
36 if (dim > 3 || dim < 1){
37 fprintf(stderr,"can only 1, 2 or 3 dimensional color space. with color value between 0 to 1\n");
38 assert(0);
39 }
40 if (dim == 3){
41 agxbprint(buf, "#%02x%02x%02x", MIN((unsigned int)(color[0] *255), 255),
42 MIN((unsigned int) (color[1]*255), 255), MIN((unsigned int)(color[2]*255), 255));
43 } else if (dim == 1){
44 agxbprint(buf, "#%02x%02x%02x", MIN((unsigned int)(color[0] * 255), 255),
45 MIN((unsigned int) (color[0]*255), 255), MIN((unsigned int)(color[0]*255), 255));
46 } else if (dim == 2){
47 agxbprint(buf, "#%02x%02x%02x", MIN((unsigned int)(color[0] * 255), 255),
48 0, MIN((unsigned int)(color[1]*255), 255));
49 }
50}
51
52void attach_edge_colors(Agraph_t* g, int dim, double *colors){
53 /* colors is array of dim*nedges, with color for edge i at colors[dim*i, dim(i+1))
54 */
55 Agsym_t* sym = agattr_text(g, AGEDGE, "color", 0);
56 Agedge_t* e;
57 Agnode_t* n;
58 agxbuf buf = {0};
59 unsigned row, col;
60 int ie = 0;
61
62 if (!sym)
63 sym = agattr_text (g, AGEDGE, "color", "");
64
65 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
66 row = ND_id(n);
67 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
68 col = ND_id(aghead(e));
69 if (row == col) continue;
70 color_string(&buf, dim, colors + ie*dim);
71 agxset(e, sym, agxbuse(&buf));
72 ie++;
73 }
74 }
75 agxbfree(&buf);
76}
77
78/* SparseMatrix_import_dot:
79 * Assumes g is connected and simple, i.e., we can have a->b and b->a
80 * but not a->b and a->b
81 */
83 double **x, int format) {
84 SparseMatrix A = 0;
85 Agnode_t* n;
86 Agedge_t* e;
87 Agsym_t *sym;
88 Agsym_t *psym;
89 int nnodes;
90 int nedges;
91 int i, row;
92 int* I;
93 int* J;
94 double *val;
95 double v;
97
98 if (!g) return NULL;
99 nnodes = agnnodes (g);
100 nedges = agnedges (g);
101 if (format != FORMAT_CSR && format != FORMAT_COORD) {
102 fprintf (stderr, "Format %d not supported\n", format);
103 graphviz_exit(1);
104 }
105
106 /* Assign node ids */
107 i = 0;
108 for (n = agfstnode (g); n; n = agnxtnode (g, n))
109 ND_id(n) = i++;
110
111 if (format == FORMAT_COORD){
113 A->nz = (size_t)nedges;
114 I = A->ia;
115 J = A->ja;
116 val = A->a;
117 } else {
118 I = gv_calloc(nedges, sizeof(int));
119 J = gv_calloc(nedges, sizeof(int));
120 val = gv_calloc(nedges, sizeof(double));
121 }
122
123 sym = agattr_text(g, AGEDGE, "weight", NULL);
124 i = 0;
125 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
126 row = ND_id(n);
127 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
128 I[i] = row;
129 J[i] = ND_id(aghead(e));
130
131 /* edge weight */
132 if (sym) {
133 if (sscanf (agxget(e,sym), "%lf", &v) != 1) v = 1;
134 } else {
135 v = 1;
136 }
137 val[i] = v;
138
139 i++;
140 }
141 }
142
143 if (x && (psym = agattr_text(g, AGNODE, "pos", NULL))) {
144 bool has_positions = true;
145 char* pval;
146 if (!(*x)) {
147 *x = gv_calloc(dim * nnodes, sizeof(double));
148 }
149 for (n = agfstnode (g); n && has_positions; n = agnxtnode (g, n)) {
150 double xx,yy, zz,ww;
151 int nitems;
152 i = ND_id(n);
153 if ((pval = agxget(n, psym)) && *pval) {
154 if (dim == 2){
155 nitems = sscanf(pval, "%lf,%lf", &xx, &yy);
156 if (nitems != 2) {
157 has_positions = false;
158 agerrorf("Node \"%s\" pos has %d < 2 values", agnameof(n), nitems);
159 }
160 (*x)[i*dim] = xx;
161 (*x)[i*dim+1] = yy;
162 } else if (dim == 3){
163 nitems = sscanf(pval, "%lf,%lf,%lf", &xx, &yy, &zz);
164 if (nitems != 3) {
165 has_positions = false;
166 agerrorf("Node \"%s\" pos has %d < 3 values", agnameof(n), nitems);
167 }
168 (*x)[i*dim] = xx;
169 (*x)[i*dim+1] = yy;
170 (*x)[i*dim+2] = zz;
171 } else if (dim == 4){
172 nitems = sscanf(pval, "%lf,%lf,%lf,%lf", &xx, &yy, &zz,&ww);
173 if (nitems != 4) {
174 has_positions = false;
175 agerrorf("Node \"%s\" pos has %d < 4 values", agnameof(n), nitems);
176 }
177 (*x)[i*dim] = xx;
178 (*x)[i*dim+1] = yy;
179 (*x)[i*dim+2] = zz;
180 (*x)[i*dim+3] = ww;
181 } else if (dim == 1){
182 nitems = sscanf(pval, "%lf", &xx);
183 if (nitems != 1){
185 A = NULL;
186 goto done;
187 }
188 (*x)[i*dim] = xx;
189 } else {
190 assert(0);
191 }
192 } else {
193 has_positions = false;
194 agerrorf("Node \"%s\" lacks position info", agnameof(n));
195 }
196 }
197 if (!has_positions) {
198 free(*x);
199 *x = NULL;
200 }
201 }
202 else if (x)
203 agerrorf("Error: graph %s has missing \"pos\" information", agnameof(g));
204
205 size_t sz = sizeof(double);
206 if (format == FORMAT_CSR) {
207 A = SparseMatrix_from_coordinate_arrays((size_t)nedges, nnodes, nnodes, I,
208 J, val, type, sz);
209 }
210
211done:
212 if (format != FORMAT_COORD){
213 free(I);
214 free(J);
215 free(val);
216 }
217
218 return A;
219}
220
221/* get spline info */
222int Import_dot_splines(Agraph_t* g, int *ne, char ***xsplines){
223 /* get the list of splines for the edges in the order they appear, and store as a list of strings in xspline.
224 If *xsplines = NULL, it will be allocated. On exit (*xsplines)[i] is the control point string for the i-th edge. This string
225 is of the form "x1,y1 x2,y2...", the two end points of the edge is not included per Dot format
226 Return 1 if success. 0 if not.
227 */
228 Agnode_t* n;
229 Agedge_t* e;
230 Agsym_t *sym;
231 int nedges;
232 unsigned i;
233
234 if (!g){
235 return 0;
236 }
237
238 *ne = nedges = agnedges (g);
239
240 /* Assign node ids */
241 i = 0;
242 for (n = agfstnode (g); n; n = agnxtnode (g, n))
243 ND_id(n) = i++;
244
245 sym = agattr_text(g, AGEDGE, "pos", 0);
246 if (!sym) return 0;
247
248 *xsplines = gv_calloc(nedges, sizeof(char*));
249
250 i = 0;
251 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
252 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
253 /* edge weight */
254 char *pos = agxget (e, sym);
255 (*xsplines)[i] = strdup(pos);
256 i++;
257 }
258 }
259 return 1;
260}
261
262static int hex2int(char h){
263 if (h >= '0' && h <= '9') return h - '0';
264 if (h >= 'a' && h <= 'f') return 10 + h - 'a';
265 if (h >= 'A' && h <= 'F') return 10 + h - 'A';
266 return 0;
267}
268
269static float hexcol2rgb(const char *h) {
270 return (hex2int(h[0])*16 + hex2int(h[1]))/255.;
271}
272
273void Dot_SetClusterColor(Agraph_t* g, float *rgb_r, float *rgb_g, float *rgb_b, int *clusters){
274
275 Agnode_t* n;
276 agxbuf scluster = {0};
277 unsigned i;
278 Agsym_t* clust_clr_sym = agattr_text(g, AGNODE, "clustercolor", NULL);
279
280 if (!clust_clr_sym) clust_clr_sym = agattr_text(g, AGNODE, "clustercolor", "-1");
281 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
282 i = ND_id(n);
283 if (rgb_r && rgb_g && rgb_b) {
284 rgb2hex(rgb_r[clusters[i]], rgb_g[clusters[i]], rgb_b[clusters[i]],
285 &scluster, NULL);
286 }
287 agxset(n, clust_clr_sym, agxbuse(&scluster));
288 }
289 agxbfree(&scluster);
290}
291
292SparseMatrix Import_coord_clusters_from_dot(Agraph_t* g, int maxcluster, int dim, int *nn, double **label_sizes, double **x, int **clusters, float **rgb_r, float **rgb_g, float **rgb_b, float **fsz, char ***labels, int default_color_scheme, int clustering_scheme, int useClusters){
293 SparseMatrix A = 0;
294 Agnode_t* n;
295 Agedge_t* e;
296 Agsym_t* sym;
297 Agsym_t* clust_sym;
298 Agsym_t* clust_clr_sym;
299 int nnodes;
300 int nedges;
301 int i, row, ic,nc, j;
302 double v;
304 float ff;
305
306 int MAX_GRPS, MIN_GRPS;
307 bool noclusterinfo = false;
308 bool first = true;
309 const float *pal;
310 int max_color = MAX_COLOR;
311
312 switch (default_color_scheme){
314 pal = &(palette_blue_to_yellow[0][0]);
315 break;
317 pal = &(palette_white_to_red[0][0]);
318 break;
320 pal = &(palette_grey_to_red[0][0]);
321 break;
323 pal = &(palette_grey[0][0]);
324 break;
326 pal = &(palette_pastel[0][0]);
327 break;
330 break;
333 break;
335 pal = &(palette_primary[0][0]);
336 break;
338 pal = &(palette_adam_blend[0][0]);
339 break;
341 pal = &(palette_adam[0][0]);
342 max_color = 11;
343 break;
345 pal = NULL;
346 break;
347 default:
348 pal = &(palette_pastel[0][0]);
349 break;
350 }
351
352 if (!g) return NULL;
353 nnodes = agnnodes (g);
354 nedges = agnedges (g);
355 *nn = nnodes;
356
357 /* Assign node ids */
358 i = 0;
359 for (n = agfstnode (g); n; n = agnxtnode (g, n))
360 ND_id(n) = i++;
361
362 /* form matrix */
363 int* I = gv_calloc(nedges, sizeof(int));
364 int* J = gv_calloc(nedges, sizeof(int));
365 double* val = gv_calloc(nedges, sizeof(double));
366
367 sym = agattr_text(g, AGEDGE, "weight", NULL);
368 clust_sym = agattr_text(g, AGNODE, "cluster", NULL);
369 clust_clr_sym = agattr_text(g, AGNODE, "clustercolor", NULL);
370 i = 0;
371 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
372 row = ND_id(n);
373 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
374 I[i] = row;
375 J[i] = ND_id(aghead(e));
376 if (sym) {
377 if (sscanf (agxget(e,sym), "%lf", &v) != 1)
378 v = 1;
379 }
380 else
381 v = 1;
382 val[i] = v;
383 i++;
384 }
385 }
386 A = SparseMatrix_from_coordinate_arrays((size_t)nedges, nnodes, nnodes, I, J,
387 val, type, sizeof(double));
388
389 /* get clustering info */
390 *clusters = gv_calloc(nnodes, sizeof(int));
391 nc = 1;
392 MIN_GRPS = 0;
393 /* if useClusters, the nodes in each top-level cluster subgraph are assigned to
394 * clusters 2, 3, .... Any nodes not in a cluster subgraph are tossed into cluster 1.
395 */
396 if (useClusters) {
397 Agraph_t* sg;
398 int gid = 1;
399 memset (*clusters, 0, sizeof(int)*nnodes);
400 for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) {
401 if (!startswith(agnameof(sg), "cluster")) continue;
402 gid++;
403 for (n = agfstnode(sg); n; n = agnxtnode (sg, n)) {
404 i = ND_id(n);
405 if ((*clusters)[i])
406 fprintf (stderr, "Warning: node %s appears in multiple clusters.\n", agnameof(n));
407 else
408 (*clusters)[i] = gid;
409 }
410 }
411 for (n = agfstnode(g); n; n = agnxtnode (g, n)) {
412 i = ND_id(n);
413 if ((*clusters)[i] == 0)
414 (*clusters)[i] = 1;
415 }
416 MIN_GRPS = 1;
417 nc = gid;
418 }
419 else if (clust_sym) {
420 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
421 i = ND_id(n);
422 if ((sscanf(agxget(n,clust_sym), "%d", &ic)>0)) {
423 (*clusters)[i] = ic;
424 nc = MAX(nc, ic);
425 if (first){
426 MIN_GRPS = ic;
427 first = false;
428 } else {
429 MIN_GRPS = MIN(MIN_GRPS, ic);
430 }
431 } else {
432 noclusterinfo = true;
433 break;
434 }
435 }
436 }
437 else
438 noclusterinfo = true;
439 MAX_GRPS = nc;
440
441 if (noclusterinfo) {
442 double modularity;
443 if (!clust_sym) clust_sym = agattr_text(g,AGNODE,"cluster","-1");
444
445 if (clustering_scheme == CLUSTERING_MQ){
446 mq_clustering(A, maxcluster,
447 &nc, clusters, &modularity);
448 } else if (clustering_scheme == CLUSTERING_MODULARITY){
449 modularity_clustering(A, false, maxcluster,
450 &nc, clusters, &modularity);
451 } else {
452 UNREACHABLE();
453 }
454 for (i = 0; i < nnodes; i++) (*clusters)[i]++;/* make into 1 based */
455 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
456 i = ND_id(n);
457 agxset(n, clust_sym, ITOS((*clusters)[i]));
458 }
459 MIN_GRPS = 1;
460 MAX_GRPS = nc;
461 if (Verbose){
462 fprintf(stderr," no complement clustering info in dot file, using modularity clustering. Modularity = %f, ncluster=%d\n",modularity, nc);
463 }
464 }
465
466 *label_sizes = gv_calloc(dim * nnodes, sizeof(double));
467 if (pal || (!noclusterinfo && clust_clr_sym)){
468 *rgb_r = gv_calloc(1 + MAX_GRPS, sizeof(float));
469 *rgb_g = gv_calloc(1 + MAX_GRPS, sizeof(float));
470 *rgb_b = gv_calloc(1 + MAX_GRPS, sizeof(float));
471 } else {
472 *rgb_r = NULL;
473 *rgb_g = NULL;
474 *rgb_b = NULL;
475 }
476 *fsz = gv_calloc(nnodes, sizeof(float));
477 *labels = gv_calloc(nnodes, sizeof(char*));
478
479 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
481 double sz;
482 i = ND_id(n);
483 if (agget(n, "width") && agget(n, "height")){
484 sscanf(agget(n, "width"), "%lf", &sz);
485 (*label_sizes)[i*2] = POINTS(sz*0.5);
486 sscanf(agget(n, "height"), "%lf", &sz);
487 (*label_sizes)[i*2+1] = POINTS(sz*0.5);
488 } else {
489 (*label_sizes)[i*2] = POINTS(0.75/2);
490 (*label_sizes)[i*2+1] = POINTS(0.5*2);
491 }
492
493 if (agget(n, "fontsize")){
494 sscanf(agget(n, "fontsize"), "%f", &ff);
495 (*fsz)[i] = ff;
496 } else {
497 (*fsz)[i] = 14;
498 }
499
500 if (agget(n, "label") && strcmp(agget(n, "label"), "") != 0 && strcmp(agget(n, "label"), "\\N") != 0){
501 char *lbs = agget(n, "label");
502 (*labels)[i] = strdup(lbs);
503 } else {
504 (*labels)[i] = strdup(agnameof(n));
505 }
506
507
508
509 j = (*clusters)[i];
510 if (MAX_GRPS-MIN_GRPS < max_color) {
511 j = (j-MIN_GRPS)*((int)((max_color-1)/MAX((MAX_GRPS-MIN_GRPS),1)));
512 } else {
513 j = (j-MIN_GRPS)%max_color;
514 }
515
516 if (pal){
517 (*rgb_r)[(*clusters)[i]] = pal[3*j+0];
518 (*rgb_g)[(*clusters)[i]] = pal[3*j+1];
519 (*rgb_b)[(*clusters)[i]] = pal[3*j+2];
520 }
521
522 if (!noclusterinfo && clust_clr_sym && (colorxlate(agxget(n,clust_clr_sym),&color,RGBA_DOUBLE) == COLOR_OK)) {
523 (*rgb_r)[(*clusters)[i]] = color.u.RGBA[0];
524 (*rgb_g)[(*clusters)[i]] = color.u.RGBA[1];
525 (*rgb_b)[(*clusters)[i]] = color.u.RGBA[2];
526 }
527
528 const char *cc = agget(n, "clustercolor");
529 if (!noclusterinfo && agget(n, "cluster") && cc && strlen(cc) >= 7 && pal) {
530 (*rgb_r)[(*clusters)[i]] = hexcol2rgb(cc+1);
531 (*rgb_g)[(*clusters)[i]] = hexcol2rgb(cc+3);
532 (*rgb_b)[(*clusters)[i]] = hexcol2rgb(cc+5);
533 }
534
535 }
536
537
538 if (x){
539 bool has_position = false;
540 *x = gv_calloc(dim * nnodes, sizeof(double));
541 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
542 double xx,yy;
543 i = ND_id(n);
544 if (agget(n, "pos")){
545 has_position = true;
546 sscanf(agget(n, "pos"), "%lf,%lf", &xx, &yy);
547 (*x)[i*dim] = xx;
548 (*x)[i*dim+1] = yy;
549 } else {
550 fprintf(stderr,"WARNING: pos field missing for node %d, set to origin\n",i);
551 (*x)[i*dim] = 0;
552 (*x)[i*dim+1] = 0;
553 }
554 }
555 if (!has_position){
556 free(*x);
557 *x = NULL;
558 }
559 }
560
561
562 free(I);
563 free(J);
564 free(val);
565
566 return A;
567}
568
569void attached_clustering(Agraph_t* g, int maxcluster, int clustering_scheme){
570 SparseMatrix A = 0;
571 Agnode_t* n;
572 Agedge_t* e;
573 Agsym_t *sym, *clust_sym;
574 int nnodes;
575 int nedges;
576 int i, row,nc;
577 double v;
579 size_t sz = sizeof(double);
580
581 if (!g) return;
582 nnodes = agnnodes (g);
583 nedges = agnedges (g);
584
585 /* Assign node ids */
586 i = 0;
587 for (n = agfstnode (g); n; n = agnxtnode (g, n))
588 ND_id(n) = i++;
589
590 /* form matrix */
591 int* I = gv_calloc(nedges, sizeof(int));
592 int* J = gv_calloc(nedges, sizeof(int));
593 double* val = gv_calloc(nedges, sizeof(double));
594
595 sym = agattr_text(g, AGEDGE, "weight", NULL);
596 clust_sym = agattr_text(g, AGNODE, "cluster", NULL);
597
598 i = 0;
599 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
600 row = ND_id(n);
601 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
602 I[i] = row;
603 J[i] = ND_id(aghead(e));
604 if (sym) {
605 if (sscanf (agxget(e,sym), "%lf", &v) != 1)
606 v = 1;
607 }
608 else
609 v = 1;
610 val[i] = v;
611 i++;
612 }
613 }
614 A = SparseMatrix_from_coordinate_arrays((size_t)nedges, nnodes, nnodes, I, J,
615 val, type, sz);
616
617 int *clusters = gv_calloc(nnodes, sizeof(int));
618
619 {
620 double modularity;
621 if (!clust_sym) clust_sym = agattr_text(g,AGNODE,"cluster","-1");
622
623 if (clustering_scheme == CLUSTERING_MQ){
624 mq_clustering(A, maxcluster,
625 &nc, &clusters, &modularity);
626 } else if (clustering_scheme == CLUSTERING_MODULARITY){
627 modularity_clustering(A, false, maxcluster,
628 &nc, &clusters, &modularity);
629 } else {
630 UNREACHABLE();
631 }
632 for (i = 0; i < nnodes; i++) (clusters)[i]++;/* make into 1 based */
633 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
634 i = ND_id(n);
635 agxset(n, clust_sym, ITOS(clusters[i]));
636 }
637 if (Verbose){
638 fprintf(stderr," no complement clustering info in dot file, using modularity clustering. Modularity = %f, ncluster=%d\n",modularity, nc);
639 }
640 }
641
642 free(I);
643 free(J);
644 free(val);
645 free(clusters);
646
648
649}
650
651
652
654{
655 aginit(g, AGNODE, "info", sizeof(Agnodeinfo_t), true);
656}
657
658void setDotNodeID (Agnode_t* n, int v)
659{
660 ND_id(n) = v;
661}
662
664{
665 return ND_id(n);
666}
667
#define ND_id(n)
Definition DotIO.c:33
void Dot_SetClusterColor(Agraph_t *g, float *rgb_r, float *rgb_g, float *rgb_b, int *clusters)
Definition DotIO.c:273
SparseMatrix SparseMatrix_import_dot(Agraph_t *g, int dim, double **x, int format)
Definition DotIO.c:82
int getDotNodeID(Agnode_t *n)
Definition DotIO.c:663
void initDotIO(Agraph_t *g)
Definition DotIO.c:653
SparseMatrix Import_coord_clusters_from_dot(Agraph_t *g, int maxcluster, int dim, int *nn, double **label_sizes, double **x, int **clusters, float **rgb_r, float **rgb_g, float **rgb_b, float **fsz, char ***labels, int default_color_scheme, int clustering_scheme, int useClusters)
Definition DotIO.c:292
static float hexcol2rgb(const char *h)
Definition DotIO.c:269
void attach_edge_colors(Agraph_t *g, int dim, double *colors)
Definition DotIO.c:52
static void color_string(agxbuf *buf, int dim, double *color)
Definition DotIO.c:35
void setDotNodeID(Agnode_t *n, int v)
Definition DotIO.c:658
static int hex2int(char h)
Definition DotIO.c:262
void attached_clustering(Agraph_t *g, int maxcluster, int clustering_scheme)
Definition DotIO.c:569
int Import_dot_splines(Agraph_t *g, int *ne, char ***xsplines)
Definition DotIO.c:222
@ COLOR_SCHEME_ADAM_BLEND
Definition DotIO.h:20
@ COLOR_SCHEME_PASTEL
Definition DotIO.h:20
@ COLOR_SCHEME_ADAM
Definition DotIO.h:20
@ COLOR_SCHEME_GREY_RED
Definition DotIO.h:20
@ COLOR_SCHEME_SEQUENTIAL_SINGLEHUE_RED
Definition DotIO.h:20
@ COLOR_SCHEME_NONE
Definition DotIO.h:20
@ COLOR_SCHEME_SEQUENTIAL_SINGLEHUE_RED_LIGHTER
Definition DotIO.h:20
@ COLOR_SCHEME_GREY
Definition DotIO.h:20
@ COLOR_SCHEME_WHITE_RED
Definition DotIO.h:20
@ COLOR_SCHEME_PRIMARY
Definition DotIO.h:20
@ COLOR_SCHEME_BLUE_YELLOW
Definition DotIO.h:20
SparseMatrix SparseMatrix_from_coordinate_arrays(size_t nz, int m, int n, int *irn, int *jcn, const void *val, int type, size_t sz)
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix SparseMatrix_new(int m, int n, size_t nz, int type, int format)
@ MATRIX_TYPE_REAL
@ FORMAT_COORD
@ FORMAT_CSR
Dynamically expanding string buffers.
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:97
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:252
static WUR char * agxbuse(agxbuf *xb)
Definition agxbuf.h:325
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define MIN(a, b)
Definition arith.h:28
#define MAX(a, b)
Definition arith.h:33
void modularity_clustering(SparseMatrix A, bool inplace, int ncluster_target, int *nclusters, int **assignment, double *modularity)
Definition clustering.c:341
@ CLUSTERING_MODULARITY
Definition clustering.h:39
@ CLUSTERING_MQ
Definition clustering.h:39
static bool useClusters
Definition ccomps.c:65
@ RGBA_DOUBLE
Definition color.h:27
#define COLOR_OK
Definition color.h:44
const float palette_sequential_singlehue_red[1001][3]
const float palette_grey[1001][3]
const float palette_sequential_singlehue_red_lighter[1001][3]
const float palette_blue_to_yellow[1001][3]
const float palette_grey_to_red[1001][3]
const float palette_adam[11][3]
const float palette_white_to_red[1001][3]
const float palette_adam_blend[1001][3]
const float palette_pastel[1001][3]
const float palette_primary[1001][3]
@ MAX_COLOR
void rgb2hex(float r, float g, float b, agxbuf *cstring, const char *opacity)
Definition colorutil.c:21
void colorxlate(char *str, agxbuf *buf)
Definition colxlate.c:46
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
expr procedure type
Definition exparse.y:208
#define A(n, t)
Definition expr.h:76
#define I
Definition expr.h:71
#define POINTS(a_inches)
Definition geom.h:62
static bool Verbose
Definition gml2gv.c:24
void free(void *)
node NULL
Definition grammar.y:181
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
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:522
char * agget(void *obj, char *name)
Definition attr.c:448
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:458
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:26
#define aghead(e)
Definition cgraph.h:978
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:41
void agerrorf(const char *fmt,...)
Definition agerror.c:165
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:48
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:41
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:143
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
void aginit(Agraph_t *g, int kind, const char *rec_name, int rec_size, int move_to_front)
attach new records to objects of specified kind
Definition rec.c:170
Agraph_t * agfstsubg(Agraph_t *g)
Definition subg.c:73
Agraph_t * agnxtsubg(Agraph_t *subg)
Definition subg.c:78
static void color(Agraph_t *g)
Definition gvcolor.c:129
GVIO_API const char * format
Definition gvio.h:51
rows row
Definition htmlparse.y:320
#define ITOS(i)
Definition itos.h:43
void mq_clustering(SparseMatrix A, int maxcluster, int *nclusters, int **assignment, double *mq)
Definition mq.c:581
static const int dim
static int nedges
total no. of edges used in routing
Definition routespl.c:32
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
Definition startswith.h:11
unsigned int id
Definition DotIO.c:30
graph or subgraph
Definition cgraph.h:424
implementation of Agrec_t
Definition cgraph.h:172
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:640
#define UNREACHABLE()
Definition unreachable.h:30