Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
mm2gv.c
Go to the documentation of this file.
1
6/*************************************************************************
7 * Copyright (c) 2011 AT&T Intellectual Property
8 * All rights reserved. This program and the accompanying materials
9 * are made available under the terms of the Eclipse Public License v1.0
10 * which accompanies this distribution, and is available at
11 * https://www.eclipse.org/legal/epl-v10.html
12 *
13 * Contributors: Details at https://graphviz.org
14 *************************************************************************/
15
16#include "config.h"
17#include <cgraph/alloc.h>
18#include <cgraph/unreachable.h>
19
20#define STANDALONE
21#include <cgraph/cgraph.h>
22#include <stdbool.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <math.h>
27#include <assert.h>
28#include "mmio.h"
29#include <cgraph/agxbuf.h>
30#include <sparse/SparseMatrix.h>
31#include "matrix_market.h"
32#include <getopt.h>
33
34typedef struct {
35 Agrec_t h;
36 int id;
38
39#define ND_id(n) (((Agnodeinfo_t*)(n->base.data))->id)
40
41static char *cmd;
42
43static double Hue2RGB(double v1, double v2, double H)
44{
45 if (H < 0.0)
46 H += 1.0;
47 if (H > 1.0)
48 H -= 1.0;
49 if (6.0 * H < 1.0)
50 return (v1 + (v2 - v1) * 6.0 * H);
51 if (2.0 * H < 1.0)
52 return v2;
53 if (3.0 * H < 2.0)
54 return v1 + (v2 - v1) * (2.0 / 3.0 - H) * 6.0;
55 return v1;
56}
57
58static char *hue2rgb(double hue, agxbuf *xb) {
59 double v1, v2, lightness = .5, saturation = 1;
60 int red, blue, green;
61
62 v2 = lightness + saturation - saturation * lightness;
63
64 v1 = 2.0 * lightness - v2;
65
66 red = (int) (255.0 * Hue2RGB(v1, v2, hue + 1.0 / 3.0) + 0.5);
67 green = (int) (255.0 * Hue2RGB(v1, v2, hue) + 0.5);
68 blue = (int) (255.0 * Hue2RGB(v1, v2, hue - 1.0 / 3.0) + 0.5);
69 agxbprint(xb, "#%02x%02x%02x", red, green, blue);
70 return agxbuse(xb);
71}
72
73static Agraph_t *makeDotGraph(SparseMatrix A, char *name, int dim,
74 double * x, int with_color, int with_label, int with_val)
75{
76 Agraph_t *g;
77 Agnode_t *n;
78 Agnode_t *h;
79 Agedge_t *e;
80 int i, j;
81 Agsym_t *sym = NULL, *sym2 = NULL, *sym3 = NULL;
82 int *ia = A->ia;
83 int *ja = A->ja;
84 double *val = A->a;
85 Agnode_t **arr = gv_calloc(A->m, sizeof(Agnode_t*));
86 double *color = NULL;
87
88 name = strip_dir(name);
89
90 if (with_color) {
91 if (A->type == MATRIX_TYPE_REAL && !val) {
92 fprintf (stderr, "Warning: input matrix has no values, -c flag ignored\n");
93 with_color = 0;
94 }
95 else if (A->type != MATRIX_TYPE_REAL && !x) {
96 fprintf (stderr, "Warning: input has no coordinates, -c flag ignored\n");
97 with_color = 0;
98 }
99 }
100
102 g = agopen("G", Agundirected, NULL);
103 } else {
104 g = agopen("G", Agdirected, NULL);
105 }
106
107 if (with_val) {
108 sym = agattr(g, AGEDGE, "len", "1");
109 }
110 agxbuf xb = {0};
111 if (with_label) {
112 agxbprint (&xb, "%s. %d nodes, %d edges.", name, A->m, A->nz);
113 agattr(g, AGRAPH, "label", agxbuse (&xb));
114 }
115
116 for (i = 0; i < A->m; i++) {
117 agxbprint(&xb, "%d", i);
118 n = agnode(g, agxbuse(&xb), 1);
119 agbindrec(n, "nodeinfo", sizeof(Agnodeinfo_t), true);
120 ND_id(n) = i;
121 arr[i] = n;
122 }
123
124 if (with_color) {
125 double maxdist = 0.;
126 double mindist = 0.;
127 bool first = true;
128
129 sym2 = agattr(g, AGEDGE, "color", "");
130 sym3 = agattr(g, AGEDGE, "wt", "");
131 agattr(g, AGRAPH, "bgcolor", "black");
132 color = gv_calloc(A->nz, sizeof(double));
133 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
134 i = ND_id(n);
135 if (A->type != MATRIX_TYPE_REAL) {
136 for (j = ia[i]; j < ia[i + 1]; j++) {
137 color[j] = distance(x, dim, i, ja[j]);
138 if (i != ja[j]) {
139 if (first) {
140 mindist = color[j];
141 first = false;
142 } else {
143 mindist = fmin(mindist, color[j]);
144 }
145 }
146 maxdist = fmax(color[j], maxdist);
147 }
148 } else {
149 for (j = ia[i]; j < ia[i + 1]; j++) {
150 if (val) color[j] = fabs(val[j]);
151 else color[j] = 1;
152 if (i != ja[j]) {
153 if (first) {
154 mindist = color[j];
155 first = false;
156 } else {
157 mindist = fmin(mindist, color[j]);
158 }
159 }
160 maxdist = fmax(color[j], maxdist);
161 }
162 }
163 }
164 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
165 i = ND_id(n);
166 for (j = ia[i]; j < ia[i + 1]; j++) {
167 color[j] = (color[j] - mindist) / fmax(maxdist - mindist, 0.000001);
168 }
169 }
170 }
171
172 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
173 i = ND_id(n);
174 for (j = ia[i]; j < ia[i + 1]; j++) {
175 h = arr[ja[j]];
176 e = agedge(g, n, h, NULL, 1);
177 if (sym && val) {
178 agxbprint(&xb, "%f", val[j]);
179 agxset(e, sym, agxbuse(&xb));
180 }
181 if (with_color) {
182 agxset(e, sym2, hue2rgb(.65 * color[j], &xb));
183 agxbprint(&xb, "%f", color[j]);
184 agxset(e, sym3, agxbuse(&xb));
185 }
186 }
187 }
188
189 agxbfree (&xb);
190 free(color);
191 free(arr);
192 return g;
193}
194
195static char* useString = "Usage: %s [-uvcl] [-o file] matrix_market_filename\n\
196 -u - make graph undirected\n\
197 -U i - treat non-square matrix as a bipartite graph\n\
198 i = 0 never\n\
199 i = 1 if pattern unsymmetric (default)\n\
200 i = 2 if matrix unsymmetric\n\
201 i = 3 always\n\
202 -v - assign len to edges\n\
203 -c - assign color and wt to edges\n\
204 -l - add label\n\
205 -o <file> - output file \n";
206
207static void usage(int eval)
208{
209 fprintf(stderr, useString, cmd);
211}
212
213static FILE *openF(char *fname, char *mode)
214{
215 FILE *f = fopen(fname, mode);
216 if (!f) {
217 fprintf(stderr, "Could not open %s for %s\n", fname,
218 *mode == 'r' ? "reading" : "writing");
219 graphviz_exit(1);
220 }
221 return f;
222}
223
224typedef struct {
225 FILE *inf;
226 FILE *outf;
227 char *infile;
233} parms_t;
234
235static void init(int argc, char **argv, parms_t * p)
236{
237 int c;
238
239 cmd = argv[0];
240 opterr = 0;
241 while ((c = getopt(argc, argv, ":o:uvclU:?")) != -1) {
242 switch (c) {
243 case 'o':
244 p->outf = openF(optarg, "w");
245 break;
246 case 'l':
247 p->with_label = 1;
248 break;
249 case 'u':
250 p->undirected = 1;
251 break;
252 case 'v':
253 p->with_val = 1;
254 break;
255 case 'c':
256 p->with_color = 1;
257 break;
258 case 'U':{
259 int u;
260 if (sscanf(optarg,"%d",&u) <= 0 || u < 0 || u > BIPARTITE_ALWAYS) {
261 usage(1);
262 } else {
263 p->bipartite = u;
264 }
265 break;
266 }
267 case ':':
268 fprintf(stderr, "%s: option -%c missing argument - ignored\n", cmd, optopt);
269 break;
270 case '?':
271 if (optopt == '\0' || optopt == '?')
272 usage(0);
273 else {
274 fprintf(stderr,
275 "%s: option -%c unrecognized\n", cmd,
276 optopt);
277 usage(1);
278 }
279 break;
280 default:
281 UNREACHABLE();
282 }
283 }
284 argv += optind;
285 argc -= optind;
286
287 if (argc > 0) {
288 p->infile = argv[0];
289 p->inf = openF(argv[0], "r");
290 }
291}
292
293int main(int argc, char *argv[])
294{
295 Agraph_t *g = 0;
297 int dim=0;
298 parms_t pv;
299
300 /* ======================= set parameters ==================== */
301 pv.inf = stdin;
302 pv.outf = stdout;
303 pv.infile = "stdin";
304 pv.undirected = 0;
305 pv.with_label = 0;
306 pv.with_color = 0;
307 pv.with_val = 0;
309 init(argc, argv, &pv);
310
311 /* ======================= read graph ==================== */
312
314 if (!A) {
315 fprintf (stderr, "Unable to read input file \"%s\"\n", pv.infile);
316 usage(1);
317 }
318
320
321 if (!A) {
322 fprintf(stderr, "cannot import from file %s\n", pv.infile);
323 graphviz_exit(1);
324 }
325
326 if (pv.undirected) {
330 A = B;
331 }
332 g = makeDotGraph(A, pv.infile, dim, NULL, pv.with_color, pv.with_label, pv.with_val);
333
334 agwrite(g, pv.outf);
335
336 graphviz_exit(0);
337}
338
SparseMatrix SparseMatrix_to_square_matrix(SparseMatrix A, int bipartite_options)
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix SparseMatrix_make_undirected(SparseMatrix A)
@ MATRIX_TYPE_REAL
#define SparseMatrix_known_undirected(A)
@ BIPARTITE_PATTERN_UNSYM
@ BIPARTITE_ALWAYS
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:77
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:213
static char * agxbuse(agxbuf *xb)
Definition agxbuf.h:286
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
abstract graph C library, Cgraph API
mode
Definition cvtgxl.c:33
static char * fname
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
#define A(n, t)
Definition expr.h:76
static int eval(Agraph_t *g, int root)
Definition gc.c:269
char * strip_dir(char *s)
Definition general.c:161
double distance(double *x, int dim, int i, int j)
Definition general.c:145
void free(void *)
node NULL
Definition grammar.y:149
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Definition attr.c:341
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:481
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:260
Agdesc_t Agundirected
undirected
Definition graph.c:275
Agraph_t * agopen(char *name, Agdesc_t desc, Agdisc_t *disc)
creates a new graph with the given name and kind
Definition graph.c:44
int agwrite(Agraph_t *g, void *chan)
Return 0 on success, EOF on failure.
Definition write.c:708
Agdesc_t Agdirected
directed
Definition graph.c:273
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Definition node.c:147
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
@ AGEDGE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
Definition rec.c:88
static void color(Agraph_t *g)
Definition gvcolor.c:128
static const char * usage
Definition gvpr.c:53
#define B
Definition hierarchy.c:117
SparseMatrix SparseMatrix_import_matrix_market(FILE *f)
import Matrix Market
#define ND_id(n)
Definition mm2gv.c:39
static char * hue2rgb(double hue, agxbuf *xb)
Definition mm2gv.c:58
static void init(int argc, char **argv, parms_t *p)
Definition mm2gv.c:235
static char * cmd
Definition mm2gv.c:41
static FILE * openF(char *fname, char *mode)
Definition mm2gv.c:213
static Agraph_t * makeDotGraph(SparseMatrix A, char *name, int dim, double *x, int with_color, int with_label, int with_val)
Definition mm2gv.c:73
static char * useString
Definition mm2gv.c:195
static double Hue2RGB(double v1, double v2, double H)
Definition mm2gv.c:43
Matrix Market I/O API
graph or subgraph
Definition cgraph.h:425
implementation of Agrec_t
Definition cgraph.h:172
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:639
int bipartite
Definition mm2gv.c:232
int with_val
Definition mm2gv.c:231
char * infile
Definition mm2gv.c:227
int with_label
Definition mm2gv.c:229
FILE * outf
Definition mm2gv.c:226
FILE * inf
Definition mm2gv.c:225
int with_color
Definition mm2gv.c:230
int undirected
Definition mm2gv.c:228
int main()
#define UNREACHABLE()
Definition unreachable.h:30