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