1 /* amtog.c version 2.0; B D McKay, Jun 2015. */
2
3 #define USAGE "amtog [-n#sgzhq] [-o#] [infile [outfile]]"
4
5 #define HELPTEXT \
6 " Read graphs in matrix format.\n\
7 \n\
8 -n# Set the initial graph order to # (no default).\n\
9 This can be overridden in the input.\n\
10 -g Write the output in graph6 format (default).\n\
11 -s Write the output in sparse6 format.\n\
12 -z Write the output in digraph6 format.\n\
13 -h Write a header (according to -g or -s).\n\
14 -w Don't warn about loops (which are suppressed for -g)\n\
15 -q Suppress auxiliary information.\n\
16 -o# Treat digit # as 1 and other digits as 0.\n\
17 \n\
18 Input consists of a sequence of commands restricted to:\n\
19 \n\
20 n=# set number of vertices (no default)\n\
21 The = is optional.\n\
22 m Matrix to follow\n\
23 An 'm' is also assumed if a digit is encountered.\n\
24 M Complement of matrix to follow (as m)\n\
25 t Upper triangle of matrix to follow, row by row\n\
26 excluding the diagonal.\n\
27 T Complement of upper trangle to follow (as t)\n\
28 s Upper triangle of matrix to follow, row by row\n\
29 excluding the diagonal; lower triangle is complement.\n\
30 q exit (optional)\n"
31
32 /*************************************************************************/
33
34 #include "gtools.h" /* which includes nauty.h and stdio.h */
35 #include <ctype.h>
36
37 /**************************************************************************/
38 /**************************************************************************/
39
40 int
main(int argc,char * argv[])41 main(int argc, char *argv[])
42 {
43 int m,n,outdigit;
44 int argnum,i,j,outcode,val;
45 int unsym0,unsym1,loop0;
46 char *arg,sw,ochar;
47 boolean badargs;
48 boolean nswitch,sswitch,gswitch,hswitch,qswitch;
49 boolean warn,loop,unsymm,compl,triangle,tournament;
50 boolean zswitch,oswitch,nowarn;
51 char *infilename,*outfilename;
52 FILE *infile,*outfile;
53 nauty_counter nin;
54 char s[10];
55 #if MAXN
56 graph g[MAXN*MAXM];
57 #else
58 DYNALLSTAT(graph,g,g_sz);
59 #endif
60
61 HELP; PUTVERSION;
62
63 sswitch = gswitch = zswitch = oswitch = FALSE;
64 nowarn = qswitch = nswitch = hswitch = FALSE;
65 infilename = outfilename = NULL;
66 n = -1;
67
68 argnum = 0;
69 badargs = FALSE;
70 for (j = 1; !badargs && j < argc; ++j)
71 {
72 arg = argv[j];
73 if (arg[0] == '-' && arg[1] != '\0')
74 {
75 ++arg;
76 while (*arg != '\0')
77 {
78 sw = *arg++;
79 SWBOOLEAN('s',sswitch)
80 else SWBOOLEAN('g',gswitch)
81 else SWBOOLEAN('z',zswitch)
82 else SWBOOLEAN('h',hswitch)
83 else SWBOOLEAN('w',nowarn)
84 else SWBOOLEAN('q',qswitch)
85 else SWINT('n',nswitch,n,">E amtog -n")
86 else SWINT('o',oswitch,outdigit,">E amtog -o")
87 else badargs = TRUE;
88 }
89 }
90 else
91 {
92 ++argnum;
93 if (argnum == 1) infilename = arg;
94 else if (argnum == 2) outfilename = arg;
95 else badargs = TRUE;
96 }
97 }
98
99 if ((sswitch!=0) + (gswitch!=0) + (zswitch!=0) > 1)
100 gt_abort(">E amtog: -sgz are incompatible\n");
101
102 if (oswitch && (outdigit < 0 || outdigit > 9))
103 gt_abort(">E amtog: only digits are allowed for -o\n");
104
105 if (badargs || argnum > 2)
106 {
107 fprintf(stderr,">E Usage: %s\n",USAGE);
108 GETHELP;
109 exit(1);
110 }
111
112 if (oswitch) ochar = outdigit + '0';
113 else ochar = '1';
114
115 if (!infilename || infilename[0] == '-')
116 {
117 infilename = "stdin";
118 infile = stdin;
119 }
120 else if ((infile = fopen(infilename,"r")) == NULL)
121 {
122 fprintf(stderr,"Can't open input file %s\n",infilename);
123 gt_abort(NULL);
124 }
125
126 if (!outfilename || outfilename[0] == '-')
127 {
128 outfilename = "stdout";
129 outfile = stdout;
130 }
131 else if ((outfile = fopen(outfilename,"w")) == NULL)
132 {
133 fprintf(stderr,"Can't open output file %s\n",outfilename);
134 gt_abort(NULL);
135 }
136
137 if (sswitch) outcode = SPARSE6;
138 else if (zswitch) outcode = DIGRAPH6;
139 else outcode = GRAPH6;
140
141 if (hswitch)
142 {
143 if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER);
144 else if (outcode == DIGRAPH6) writeline(outfile,DIGRAPH6_HEADER);
145 else writeline(outfile,GRAPH6_HEADER);
146 }
147
148 #if MAXN
149 if (nswitch && n > MAXN)
150 {
151 gt_abort(">E amtog: value of -n too large\n");
152 exit(2);
153 }
154 #else
155 if (nswitch)
156 {
157 m = (n + WORDSIZE - 1) / WORDSIZE;
158 DYNALLOC2(graph,g,g_sz,n,m,"amtog");
159 }
160 #endif
161
162 /* perform scanning required */
163
164 warn = FALSE;
165 nin = 0;
166 while (fscanf(infile,"%1s",s) == 1)
167 {
168 if (s[0] == 'n')
169 {
170 if (fscanf(infile,"=%d",&n) != 1)
171 {
172 gt_abort(">E amtog: invalid n=# command\n");
173 exit(2);
174 }
175 m = (n + WORDSIZE - 1) / WORDSIZE;
176 #if MAXN
177 if (n < 1 || n > MAXN || m > MAXM)
178 gt_abort(">E amtog: n<0 or n,m too big\n");
179 #else
180 DYNALLOC2(graph,g,g_sz,n,m,"amtog");
181 #endif
182 }
183 else if (s[0] == 'm' || s[0] == 'M' || s[0] == 't' ||
184 s[0] == 'T' || s[0] == 's' || s[0] == '0' ||
185 s[0] == '1' || (oswitch && isdigit(s[0])))
186 {
187 if (n < 0)
188 {
189 fprintf(stderr,
190 ">E amtog: matrix found before n is defined\n");
191 exit(2);
192 }
193 if (isdigit(s[0])) ungetc(s[0],infile);
194 m = (n + WORDSIZE - 1) / WORDSIZE;
195
196 EMPTYSET(g,m*(size_t)n);
197
198 loop = unsymm = tournament = FALSE;
199 triangle = (s[0] == 't') || (s[0] == 'T') || (s[0] == 's');
200 tournament = s[0] == 's';
201 compl = (s[0] == 'M') || (s[0] == 'T');
202
203 ++nin;
204 for (i = 0; i < n; ++i)
205 for (j = (triangle ? i+1 : 0); j < n; ++j)
206 {
207 if (fscanf(infile,"%1s",s) != 1)
208 {
209 fprintf(stderr,">E amtog: incomplete matrix\n");
210 ABORT(">E amtog");
211 }
212 if (s[0] == '0' || s[0] == '1'
213 || (oswitch && isdigit(s[0])))
214 {
215 val = ((i != j) & compl) ^ (s[0] == ochar);
216 if (val == 1)
217 {
218 if (tournament)
219 ADDELEMENT(GRAPHROW(g,i,m),j);
220 else if (triangle)
221 {
222 ADDELEMENT(GRAPHROW(g,i,m),j);
223 ADDELEMENT(GRAPHROW(g,j,m),i);
224 }
225 else
226 {
227 if (j < i && !ISELEMENT(GRAPHROW(g,j,m),i))
228 {
229 unsymm = TRUE;
230 unsym0 = i; unsym1 = j;
231 }
232 ADDELEMENT(GRAPHROW(g,i,m),j);
233 }
234 if (i == j)
235 {
236 loop = TRUE;
237 loop0 = i;
238 }
239 }
240 else if (tournament)
241 ADDELEMENT(GRAPHROW(g,j,m),i);
242 else if (j < i && ISELEMENT(GRAPHROW(g,j,m),i))
243 {
244 unsymm = TRUE;
245 unsym0 = i; unsym1 = j;
246 }
247 }
248 else
249 {
250 fprintf(stderr,
251 ">E amtog: illegal character in matrix: \"%c\"\n",
252 s[0]);
253 gt_abort(NULL);
254 }
255 }
256
257 if ((tournament || unsymm) && outcode != DIGRAPH6)
258 fprintf(stderr,">W amtog: warning, graph "
259 COUNTER_FMT " is unsymmetric (%d,%d)\n",nin,unsym0,unsym1);
260
261 if (outcode == DIGRAPH6) writed6(outfile,g,m,n);
262 else if (outcode == SPARSE6) writes6(outfile,g,m,n);
263 else writeg6(outfile,g,m,n);
264 if (loop && outcode == GRAPH6) ++warn;
265 }
266 else if (s[0] == 'q')
267 {
268 exit(0);
269 }
270 else
271 {
272 fprintf(stderr,">E amtog: invalid command \"%c\"\n",s[0]);
273 gt_abort(NULL);
274 }
275 }
276
277 if (warn && !nowarn) fprintf(stderr,">Z amtog: loops were lost (%d)\n",loop0);
278
279 if (!qswitch)
280 fprintf(stderr,">Z " COUNTER_FMT " graphs converted from %s to %s.\n",
281 nin,infilename,outfilename);
282
283 exit(0);
284 }
285