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