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