#include"gtools.h"/* which includes nauty.h, which includes stdio.h */ #include"nautinv.h" #include"schreier.h" #include"traces.h"
#define USAGE "dreadnaut [-o options]"
#define HELPTEXT \ " Enter nauty+traces test program.\n\
\n\
-o options - set initial options. The parameter value is a string of\n\
dreadnaut commands from the following set:\n\
a,c,d,m,p,l,G,P,w,y,$,A,V,M\n\
The effect is the same as if these commands are entered\n\
at the beginning of the standard input.\n\
For help within dreadnaut, use the h command.\n"
#define PM(x) ((x) ? '+' : '-') #define SS(n,sing,plur) (n),((n)==1?(sing):(plur)) #define WORKSIZE 60 #define FLUSHANDPROMPT do { flushline(INFILE); if (prompt) fprintf(PROMPTFILE,"> "); } while (0)
#define SORT_OF_SORT 2 #define SORT_NAME sort2ints #define SORT_TYPE1 int #define SORT_TYPE2 int #include"sorttemplates.c"/* define sort2ints(a,b,n) */
#define DENSE_MODE 0 #define SPARSE_MODE 1 #define TRACES_MODE 2 #define SPARSEREP(mode) ((mode)==1||(mode)==2) #define NOSPARSEYET(c) else if (SPARSEREP(mode)) { fprintf(ERRFILE,\ "command %s is not implemented in the sparse case\n",c); } #define NODENSEYET else if (!SPARSEREP(mode)) { fprintf(ERRFILE,\ "command %c is not implemented in the dense case\n",c); } #define NOTRACESYET if (mode==TRACES_MODE) { fprintf(ERRFILE,\ "command %c is not implemented for Traces\n",c); }
static int mode;
#define U_NODE 1/* masks for u values */ #define U_AUTOM 2 #define U_LEVEL 4 #define U_TCELL 8/* At version 2.4, usertcellproc() is gone */ #define U_REF 16 #define U_CANON 32
int
main(int argc, char *argv[])
{
int m,n,newm,newn;
boolean gvalid,ovalid,cvalid,pvalid,minus,prompt,doquot;
boolean gvalid_sg,cvalid_sg;
int i,j,k,worksize,numcells,savednc,refcode,umask,qinvar;
int oldorg,oldmode;
int maxsize,cell1,cell2;
boolean ranreg,same;
char *s1,*s2;
int c,d; unsigned long uli;
size_t sli;
set *gp; double timebefore,timeafter,mintime;
char filename[515];
int sgn,sgorg,nperm;
int multiplicity,actmult;
long zseed;
permnode *generators;
char *ap,*parameters;
boolean flushing;
case'<': /* new input file */
minus = FALSE;
if (curfile == MAXIFILES - 1)
{
fprintf(ERRFILE,"exceeded maximum input nesting of %d\n",
MAXIFILES);
FLUSHANDPROMPT; break;
}
if (!readstring(INFILE,filename,513))
{
fprintf(ERRFILE, "missing file name on '<' command : ignored\n"); break;
}
if ((fileptr[curfile+1] = fopen(filename,"r")) == NULL)
{
for (s1 = filename; *s1 != '\0'; ++s1) {}
for (s2 = def_ext; (*s1 = *s2) != '\0'; ++s1, ++s2) {}
fileptr[curfile+1] = fopen(filename,"r");
}
if (fileptr[curfile+1] != NULL)
{
++curfile;
prompt = DOPROMPT(INFILE);
if (prompt)
fprintf(PROMPTFILE,"> ");
} else
{
fprintf(ERRFILE,"can't open input file\n");
FLUSHANDPROMPT;
} break;
case'>': /* new output file, or flush output file */
if ((d = getc(INFILE)) != '>') ungetc(d,INFILE);
if (minus)
{
minus = FALSE;
if (d == '>')
fflush(outfile); else if (outfile != stdout)
{
fclose(outfile);
outfile = stdout;
}
} else
{
if (!readstring(INFILE,filename,513))
{
fprintf(ERRFILE, "improper file name, reverting to stdout\n");
outfile = stdout;
FLUSHANDPROMPT; break;
}
OPENOUT(outfile,filename,d=='>');
if (outfile == NULL)
{
fprintf(ERRFILE, "can't open output file, reverting to stdout\n");
outfile = stdout;
FLUSHANDPROMPT;
}
} break;
case'B':
flushing = !minus;
minus = FALSE; break;
case'!': /* ignore rest of line */ do
c = getc(INFILE); while (c != '\n' && c != EOF);
if (c == '\n') ungetc('\n',INFILE); break;
case'n': /* read n value */
minus = FALSE;
i = getint_sl(INFILE);
if (i <= 0 || (MAXN && i > MAXN)
|| (!MAXN && i > NAUTY_INFINITY-2))
{
fprintf(ERRFILE, " n can't be less than 1 or more than %d\n",
MAXN ? MAXN : NAUTY_INFINITY-2);
FLUSHANDPROMPT;
} else
{
gvalid = FALSE;
cvalid = FALSE;
gvalid_sg = FALSE;
cvalid_sg = FALSE;
pvalid = FALSE;
ovalid = FALSE;
n = i;
m = SETWORDSNEEDED(n);
freeschreier(NULL,&generators); #if !MAXN
DYNALLOC1(int,lab,lab_sz,n,"dreadnaut");
DYNALLOC1(int,ptn,ptn_sz,n,"dreadnaut");
DYNALLOC1(int,orbits,orbits_sz,n,"dreadnaut");
DYNALLOC1(int,perm,perm_sz,n,"dreadnaut");
DYNALLOC1(set,active,active_sz,m,"dreadnaut"); #endif
} break;
case'e': /* edit graph */
minus = FALSE;
if (SPARSEREP(mode))
{
fprintf(ERRFILE,"e command only works in dense mode\n");
FLUSHANDPROMPT;
} else
{
readgraph(INFILE,g,options_digraph,prompt,gvalid,
options_linelength,m,n);
gvalid = TRUE;
cvalid = FALSE;
ovalid = FALSE;
} break;
case'r': /* relabel graph and current partition */
minus = FALSE;
if ((d = getc(INFILE)) != '&') ungetc(d,INFILE);
if (gvalid_sg)
{
if (d == '&')
{
if (pvalid)
relabel_sg(&g_sg,lab,lab,&canong_sg);
} else
{
readvperm(INFILE,perm,prompt,n,&nperm);
relabel_sg(&g_sg,(pvalid ? lab : NULL),perm,&canong_sg);
}
cvalid_sg = FALSE;
ovalid = FALSE;
} else if (gvalid)
{
if (d == '&')
{
if (pvalid)
{ #if !MAXN
DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif
relabel(g,lab,lab,canong,m,n);
}
} else
{ #if !MAXN
DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif
readvperm(INFILE,perm,prompt,n,&nperm);
relabel(g,(pvalid ? lab : NULL),perm,canong,m,n);
}
cvalid = FALSE;
ovalid = FALSE;
} else
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
} break;
case'R': /* form subgraph */
if (gvalid)
{ #if !MAXN
DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif
readvperm(INFILE,perm,prompt,n,&nperm);
if ((minus && nperm == n) || (!minus && nperm == 0))
{
fprintf(ERRFILE,"can't form null graph\n");
FLUSHANDPROMPT;
} else if (minus)
{
sublabel(g,perm+nperm,n-nperm,canong,m,n);
if (pvalid) numcells = subpartition(lab,ptn,n,perm+nperm,n-nperm);
n = n - nperm;
} else
{
sublabel(g,perm,nperm,canong,m,n);
if (pvalid) numcells = subpartition(lab,ptn,n,perm,nperm);
n = nperm;
}
cvalid = FALSE;
ovalid = FALSE;
m = SETWORDSNEEDED(n);
} else if (gvalid_sg)
{
readvperm(INFILE,perm,prompt,n,&nperm);
if ((minus && nperm == n) || (!minus && nperm == 0))
{
fprintf(ERRFILE,"can't form null graph\n");
FLUSHANDPROMPT;
} else if (minus)
{
sublabel_sg(&g_sg,perm+nperm,n-nperm,&canong_sg);
if (pvalid) numcells = subpartition(lab,ptn,n,perm+nperm,n-nperm);
n = n - nperm;
} else
{
sublabel_sg(&g_sg,perm,nperm,&canong_sg);
if (pvalid) numcells = subpartition(lab,ptn,n,perm,nperm);
n = nperm;
}
cvalid_sg = FALSE;
ovalid = FALSE;
m = SETWORDSNEEDED(n);
} else
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
}
minus = FALSE; break;
case'_': /* complement graph or converse digraph */
minus = FALSE;
if ((d = getc(INFILE)) != '_') ungetc(d,INFILE);
if (!gvalid && !gvalid_sg)
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
} else if (gvalid)
{
if (d == '_') converse(g,m,n); else complement(g,m,n);
cvalid = FALSE;
} else
{
if (d == '_')
{
copy_sg(&g_sg,&canong_sg);
converse_sg(&canong_sg,&g_sg);
cvalid_sg = FALSE;
} else
{
copy_sg(&g_sg,&canong_sg);
complement_sg(&canong_sg,&g_sg);
cvalid_sg = FALSE;
}
} break;
case'@': /* copy canong into savedg */
minus = FALSE;
if (cvalid)
{ #if !MAXN
DYNALLOC2(graph,savedg,savedg_sz,n,m,"dreadnaut");
DYNALLOC1(int,savedlab,savedlab_sz,n,"dreadnaut");
DYNALLOC1(int,savedptn,savedptn_sz,n,"dreadnaut"); #endif
sgn = n;
memcpy(savedg,canong,m*(size_t)n*sizeof(setword));
for (i = n; --i >= 0;)
{
savedlab[i] = lab[i];
savedptn[i] = ptn[i];
}
sgorg = labelorg;
} else if (cvalid_sg)
{ #if !MAXN
DYNALLOC1(int,savedlab,savedlab_sz,n,"dreadnaut");
DYNALLOC1(int,savedptn,savedptn_sz,n,"dreadnaut"); #endif
sgn = n;
copy_sg(&canong_sg,&savedg_sg);
for (i = n; --i >= 0;)
{
savedlab[i] = lab[i];
savedptn[i] = ptn[i];
}
sgorg = labelorg;
} else
{
fprintf(ERRFILE,"h is not defined\n");
FLUSHANDPROMPT;
} break;
case'#': /* compare canong to savedg */
if ((d = getc(INFILE)) != '#') ungetc(d,INFILE);
if (cvalid || cvalid_sg)
{
if (sgn > 0)
{
if (sgn != n)
fprintf(outfile, "h and h' have different sizes.\n"); else
{
if (cvalid)
{
for (sli = 0; sli < m*(size_t)n; ++sli)
if (savedg[sli] != canong[sli]) break;
same = (sli == m*(size_t)n);
} else
same = aresame_sg(&canong_sg,&savedg_sg);
if (!same)
fprintf(outfile,"h and h' are different.\n"); else
{
for (i = 0; i < n; ++i)
if ((ptn[i] == 0) != (savedptn[i] == 0)) break;
if (i < n)
fprintf(outfile, "h and h' are identical but have incompatible colourings.\n"); else
fprintf(outfile, "h and h' are identical.\n");
if (d == '#')
putmapping(outfile,savedlab,sgorg,
lab,labelorg,options_linelength,n);
}
}
} else
{
fprintf(ERRFILE,"h' is not defined\n");
FLUSHANDPROMPT;
}
} else
{
fprintf(ERRFILE,"h is not defined\n");
FLUSHANDPROMPT;
} break;
case'j': /* relabel graph randomly */
minus = FALSE;
if (gvalid)
{
ranperm(perm,n); #if !MAXN
DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif
relabel(g,(pvalid?lab:NULL),perm,canong,m,n);
cvalid = FALSE;
ovalid = FALSE;
freeschreier(NULL,&generators);
} else if (gvalid_sg)
{
ranperm(perm,n);
relabel_sg(&g_sg,(pvalid?lab:NULL),perm,&canong_sg);
cvalid_sg = FALSE;
ovalid = FALSE;
freeschreier(NULL,&generators);
} else
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
} break;
case'v': /* write vertex degrees */
minus = FALSE;
if ((d = getc(INFILE)) != 'v') ungetc(d,INFILE);
if (gvalid)
{
if (d == 'v') putdegseq(outfile,g,options_linelength,m,n); else putdegs(outfile,g,options_linelength,m,n);
} else if (gvalid_sg)
{
if (d == 'v') putdegseq_sg(outfile,&g_sg,options_linelength); else putdegs_sg(outfile,&g_sg,options_linelength);
} else
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
} break;
case'%': /* do Mathon doubling operation */
minus = FALSE;
if (gvalid || gvalid_sg)
{ #if !MAXN
if (2L * ((long)n + 1L) > NAUTY_INFINITY-2)
{
fprintf(ERRFILE, "n can't be more than %d\n",NAUTY_INFINITY-2); break;
} #else
if (2L * ((long)n + 1L) > MAXN)
{
fprintf(ERRFILE,"n can't be more than %d\n",MAXN);
FLUSHANDPROMPT; break;
} #endif
newn = 2 * (n + 1);
newm = SETWORDSNEEDED(newn); #if !MAXN
DYNALLOC1(int,lab,lab_sz,newn,"dreadnaut");
DYNALLOC1(int,ptn,ptn_sz,newn,"dreadnaut");
DYNALLOC1(int,orbits,orbits_sz,newn,"dreadnaut");
DYNALLOC1(int,perm,perm_sz,newn,"dreadnaut");
DYNALLOC1(set,active,active_sz,newm,"dreadnaut"); #endif
ovalid = FALSE;
pvalid = FALSE;
freeschreier(NULL,&generators);
} else
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
}
if (gvalid)
{ #if !MAXN
DYNALLOC2(graph,canong,canong_sz,n,m,"dreadnaut"); #endif
memcpy(canong,g,m*(size_t)n*sizeof(setword));
#if !MAXN
DYNALLOC2(graph,g,g_sz,newn,newm,"dreadnaut"); #endif
mathon(canong,m,n,g,newm,newn);
m = newm;
n = newn;
cvalid = FALSE;
} else if (gvalid_sg)
{
copy_sg(&g_sg,&canong_sg);
mathon_sg(&canong_sg,&g_sg);
m = newm;
n = newn;
cvalid_sg = FALSE;
} break;
case's': /* generate random graph */
minus = FALSE;
d = getc(INFILE);
if (d == 'r')
ranreg = TRUE; else
{
ranreg = FALSE;
if (d != EOF) ungetc(d,INFILE);
}
i = getint_sl(INFILE);
if (ranreg)
{
if (i < 0) i = 3;
if (i > MAXREG)
{
fprintf(ERRFILE,"sr is limited to degree %d\n",MAXREG);
FLUSHANDPROMPT; break;
}
if (SPARSEREP(mode))
{
ranreg_sg(&g_sg,i,n);
gvalid_sg = TRUE;
cvalid = FALSE;
ovalid = FALSE;
freeschreier(NULL,&generators);
}
NODENSEYET
} else
{
if (i <= 0) i = 2;
if (!SPARSEREP(mode))
{ #if !MAXN
DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut"); #endif
rangraph(g,options_digraph,i,m,n);
gvalid = TRUE;
cvalid = FALSE;
ovalid = FALSE;
freeschreier(NULL,&generators);
} else
{
rangraph2_sg(&g_sg,options_digraph,1,i,n);
gvalid_sg = TRUE;
cvalid = FALSE;
ovalid = FALSE;
freeschreier(NULL,&generators);
}
} break;
case'q': /* quit */
EXIT; break;
case'"': /* copy comment to output */
minus = FALSE;
copycomment(INFILE,outfile,'"'); break;
case'I': /* do refinement and invariants procedure */
minus = FALSE;
if (!gvalid && !gvalid_sg)
{
fprintf(ERRFILE,"g is not valid\n");
FLUSHANDPROMPT; break;
}
if (!pvalid) unitptn(lab,ptn,&numcells,n);
cellstarts(ptn,0,active,m,n); #ifdef CPUTIME
timebefore = CPUTIME; #endif
if (gvalid)
{
doref(g,lab,ptn,0,&numcells,&qinvar,perm,active,&refcode,
options.userrefproc ? options.userrefproc :
(m == 1 ? refine1 : refine),
invarproc[options_invarproc].entrypoint,0,0,
options_invararg,options_digraph,m,n);
if (numcells > 1) pvalid = TRUE;
} else if (gvalid_sg)
{
doref((graph*)&g_sg,lab,ptn,0,&numcells,&qinvar,perm,
active,&refcode,
options_sg.userrefproc ? options_sg.userrefproc :
refine_sg,
invarproc[options_invarproc].entrypoint_sg,0,0,
options_invararg,options_digraph,m,n);
if (numcells > 1) pvalid = TRUE;
} else
{
fprintf(ERRFILE,"g is not valid\n");
FLUSHANDPROMPT; break;
} #ifdef CPUTIME
timeafter = CPUTIME; #endif
fprintf(outfile," %d cell%s; code = %x",
SS(numcells,"","s"),refcode);
if (mode == SPARSE_MODE)
{
if (invarproc[options_invarproc].entrypoint_sg)
fprintf(outfile, " (%s %s)",invarproc[options_invarproc].name_sg,
(qinvar == 2 ? "worked" : "failed"));
} else if (mode == DENSE_MODE)
{
if (invarproc[options_invarproc].entrypoint)
fprintf(outfile, " (%s %s)",invarproc[options_invarproc].name,
(qinvar == 2 ? "worked" : "failed"));
} #ifdef CPUTIME
fprintf(outfile,"; cpu time = %.2f seconds\n",
timeafter-timebefore); #else
fprintf(outfile,"\n"); #endif
if (numcells > 1) pvalid = TRUE; break;
case'i': /* do refinement */
minus = FALSE;
if (!gvalid && !gvalid_sg)
{
fprintf(ERRFILE,"g is not valid\n");
FLUSHANDPROMPT; break;
}
if (!pvalid) unitptn(lab,ptn,&numcells,n);
cellstarts(ptn,0,active,m,n);
if (multiplicity != 0 || mintime != 0.0)
{
savednc = numcells; #if !MAXN
DYNALLOC1(int,tempptn,tempptn_sz,n,"dreadnaut");
DYNALLOC1(int,templab,templab_sz,n,"dreadnaut");
DYNALLOC1(set,tempactive,tempactive_sz,m,"dreadnaut"); #endif
memcpy(templab,lab,n*sizeof(int));
memcpy(tempptn,ptn,n*sizeof(int));
for (i = 0; i < m; ++i) tempactive[i] = active[i];
}
#ifdef CPUTIME
timebefore = CPUTIME; #endif
actmult = 0;
for (;;)
{
if (actmult > 0)
{
memcpy(lab,templab,n*sizeof(int));
memcpy(ptn,tempptn,n*sizeof(int));
for (i = 0; i < m; ++i) active[i] = tempactive[i];
numcells = savednc;
}
if (options.userrefproc)
(*options.userrefproc)
(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); else if (gvalid)
{
if (m == 1)
refine1(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n); else
refine(g,lab,ptn,0,&numcells,perm,active,&refcode,m,n);
} else if (mode == SPARSE_MODE)
refine_sg((graph*)&g_sg,lab,ptn,0,&numcells,perm,active,
&refcode,m,n); else/* traces mode */
refine_tr(&g_sg,lab,ptn,&numcells,&refcode,&traces_opts);
if (stats.errstatus)
{
if (stats.errstatus == NAUABORTED)
fprintf(ERRFILE,"nauty aborted\n"); else if (stats.errstatus == NAUKILLED)
fprintf(ERRFILE,"nauty interrupted\n"); else
fprintf(ERRFILE, "nauty returned error status %d [this can't happen]\n",
stats.errstatus);
cvalid = cvalid_sg = ovalid = FALSE;
} else
{
if (options_getcanon)
{
if (mode == DENSE_MODE) cvalid = TRUE; else cvalid_sg = TRUE;
}
ovalid = TRUE;
fprintf(outfile,"%d orbit%s",SS(stats.numorbits,"","s"));
fprintf(outfile,"; grpsize=");
writegroupsize(outfile,stats.grpsize1,stats.grpsize2);
fprintf(outfile,"; %d gen%s",
SS(stats.numgenerators,"","s"));
fprintf(outfile,"; %lu node%s",SS(stats.numnodes,"","s"));
if (stats.numbadleaves)
fprintf(outfile," (%lu bad lea%s)",
SS(stats.numbadleaves,"f","ves"));
fprintf(outfile,"; maxlev=%d\n", stats.maxlevel); /* fprintf(outfile,"tctotal=%lu",stats.tctotal); */
if (options_getcanon)
fprintf(outfile,"canupdates=%lu; ",stats.canupdates); #ifdef CPUTIME
fprintf(outfile,actmult == 1 ? "cpu time = %.2f seconds\n" : "cpu time = %.7f seconds\n",
(timeafter-timebefore)/actmult); #else
fprintf(outfile,"\n"); #endif
if (mode == DENSE_MODE && options_maxinvarlevel != 0
&& invarproc[options_invarproc].entrypoint)
{
fprintf(outfile,"invarproc \"%s\" succeeded %lu/%lu",
invarproc[options_invarproc].name,
stats.invsuccesses,stats.invapplics);
if (stats.invarsuclevel > 0)
fprintf(outfile," beginning at level %d.\n",
stats.invarsuclevel); else
fprintf(outfile,".\n");
}
if (mode == SPARSE_MODE && options_maxinvarlevel != 0
&& invarproc[options_invarproc].entrypoint_sg)
{
fprintf(outfile,"invarproc \"%s\" succeeded %lu/%lu",
invarproc[options_invarproc].name_sg,
stats.invsuccesses,stats.invapplics);
if (stats.invarsuclevel > 0)
fprintf(outfile," beginning at level %d.\n",
stats.invarsuclevel); else
fprintf(outfile,".\n");
}
}
} break;
case'A': /* change mode, with possible conversion */
minus = FALSE;
oldmode = mode;
d = getc(INFILE);
if (d == 'n' || d == 'N' || d == 'd' || d == 'D') mode = DENSE_MODE; else if (d == 's' || d == 'S') mode = SPARSE_MODE; else if (d == 't' || d == 'T') mode = TRACES_MODE; else
{
fprintf(ERRFILE,"Mode %c is unknown\n",(d?d:'0'));
FLUSHANDPROMPT; break;
}
if ((d = getc(INFILE)) != '+')
{
ungetc(d,INFILE);
gvalid = gvalid_sg = FALSE;
pvalid = ovalid = FALSE;
} else
{
if (SPARSEREP(oldmode) && !SPARSEREP(mode) && gvalid_sg)
{ #if !MAXN
DYNALLOC2(graph,g,g_sz,n,m,"dreadnaut"); #endif
sg_to_nauty(&g_sg,g,m,&m);
gvalid_sg = FALSE;
gvalid = TRUE;
}
if (!SPARSEREP(oldmode) && SPARSEREP(mode) && gvalid)
{
nauty_to_sg(g,&g_sg,m,n);
gvalid = FALSE;
gvalid_sg = TRUE;
}
}
cvalid = cvalid_sg = FALSE;
sgn = 0; /* invalidate saved graph */ break;
case'f': /* read initial partition */
if (minus)
{
pvalid = FALSE;
minus = FALSE;
} else
{
readptn(INFILE,lab,ptn,&numcells,prompt,n);
pvalid = TRUE;
freeschreier(NULL,&generators);
} break;
case'F': /* individualise one more vertex */
if ((d = getc(INFILE)) != 'F') ungetc(d,INFILE);
minus = FALSE;
if (d != 'F')
{
i = getint_sl(INFILE);
i -= labelorg;
if (i < 0 || i >= n)
{
fprintf(ERRFILE,"F argument must be 0..n-1\n");
FLUSHANDPROMPT;
} else
{
if (!pvalid) unitptn(lab,ptn,&numcells,n);
individualise(lab,ptn,0,i,&d,&numcells,n);
pvalid = TRUE;
}
} else
{
if (!gvalid && !gvalid_sg)
{
fprintf(stderr,"g is not defined\n");
FLUSHANDPROMPT; break;
}
if (!pvalid) unitptn(lab,ptn,&numcells,n);
if (!SPARSEREP(mode))
i = targetcell(g,lab,ptn,0,1,options_digraph,-1,m,n); else if (mode == SPARSE_MODE)
i = targetcell_sg((graph*)&g_sg,lab,ptn,0,1,
options_digraph,-1,m,n); else/* Traces mode */
{
maxsize = 0;
for (cell1 = 0; cell1 < n; cell1 = cell2 + 1)
{
for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {}
if (cell2-cell1+1 > maxsize)
{
i = cell1;
maxsize = cell2 - cell1 + 1;
}
}
}
case't': /* type graph */
minus = FALSE;
if (gvalid)
putgraph(outfile,g,options_linelength,m,n); else if (gvalid_sg)
putgraph_sg(outfile,&g_sg,options_linelength); else
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
} break;
case'T': /* type graph preceded by n, $ and g commands */
minus = FALSE;
if (gvalid)
{
fprintf(outfile,"n=%d $=%d g\n",n,labelorg);
putgraph(outfile,g,options_linelength,m,n);
fprintf(outfile,"$$\n");
} else if (gvalid_sg)
{
fprintf(outfile,"n=%d $=%d g\n",n,labelorg);
putgraph_sg(outfile,&g_sg,options_linelength);
fprintf(outfile,"$$\n");
} else
{
fprintf(ERRFILE,"g is not defined\n");
FLUSHANDPROMPT;
} break;
case'u': /* call user procs */
if (minus)
{
umask = 0;
minus = FALSE;
} else
{
umask = getint_sl(INFILE);
if (umask < 0) umask = ~U_TCELL;
}
if (umask & U_TCELL)
{
fprintf(ERRFILE,"usertcellproc() is gone at version 2.4\n");
umask &= ~U_TCELL;
} break;
case'o': /* type orbits */
minus = FALSE;
if (ovalid)
PUTORBITS(outfile,orbits,options_linelength,n); else
{
fprintf(ERRFILE,"orbits are not defined\n");
FLUSHANDPROMPT;
} break;
case'O': /* make orbits into a partition*/
minus = FALSE;
if ((d = getc(INFILE)) != 'O') ungetc(d,INFILE);
if (ovalid && d != 'O')
{ #if !MAXN
DYNALLOC1(int,tempptn,tempptn_sz,n,"dreadnaut"); #endif
for (i = n; --i >= 0;) tempptn[i] = 0;
for (i = n; --i >= 0;)
if ((j = orbits[i]) < i)
{
tempptn[i] = tempptn[j];
tempptn[j] = i;
}
k = 0;
numcells = 0;
for (i = 0; i < n; ++i)
{
if (orbits[i] == i)
{
j = i; do
{
lab[k] = j;
ptn[k] = 1;
++k;
j = tempptn[j];
} while (j > 0);
ptn[k-1] = 0;
++numcells;
}
}
pvalid = TRUE;
} else if (ovalid && d == 'O')
{ #if !MAXN
DYNALLOC1(int,tempptn,tempptn_sz,n,"dreadnaut");
DYNALLOC1(int,templab,templab_sz,n,"dreadnaut"); #endif
for (i = 0; i < n; ++i) tempptn[i] = 0;
for (i = 0; i < n; ++i) ++tempptn[orbits[i]];
j = 0;
for (i = 0; i < n; ++i)
if (tempptn[i] > 0)
{
templab[j] = i;
tempptn[j] = tempptn[i];
++j;
}
sort2ints(tempptn,templab,j);
k = 0;
for (i = 0; i < j; ++i)
{
ptn[templab[i]] = k;
k += tempptn[i];
}
for (i = 0; i < n; ++i) lab[ptn[orbits[i]]++] = i;
for (i = 0; i < n; ++i) ptn[i] = 1;
k = 0;
numcells = 0;
for (i = 0; i < j; ++i)
{
k += tempptn[i];
if (i == j-1 || tempptn[i] != tempptn[i+1])
{
ptn[k-1] = 0;
++numcells;
}
}
pvalid = TRUE;
} else
{
fprintf(ERRFILE,"orbits are not defined\n");
FLUSHANDPROMPT;
} break;
case'b': /* type canonlab and canong */
minus = FALSE;
if (cvalid)
putcanon(outfile,lab,canong,options_linelength,m,n); else if (cvalid_sg)
{
sortlists_sg(&canong_sg);
putcanon_sg(outfile,lab,&canong_sg,options_linelength);
} else
{
fprintf(ERRFILE,"h is not defined\n");
FLUSHANDPROMPT;
} break;
case'z': /* type hashcode for canong */
minus = FALSE;
if (cvalid)
{
zseed = hashgraph(canong,m,n,2922320L);
fprintf(outfile,"[N%07lx",zseed);
case'k': /* set invarlev fields of options */
options_mininvarlevel = getint_sl(INFILE);
options_maxinvarlevel = getint_sl(INFILE);
minus = FALSE; break;
case'K': /* set invararg field of options */
options_invararg = getint_sl(INFILE);
minus = FALSE; break;
case'*': /* set invarproc field of options */
minus = FALSE;
d = getint_sl(INFILE);
if (d >= -1 && d <= NUMINVARS-2)
{
options_invarproc = d+1;
options_mininvarlevel = 0;
options_maxinvarlevel = 1;
if (options_invarproc >= 10 && options_invarproc <= 13)
options.invararg = 3; else
options.invararg = 0;
} else
{
fprintf(ERRFILE,"no such vertex-invariant\n");
FLUSHANDPROMPT;
} break;
case'a': /* set writeautoms option */
options_writeautoms = !minus;
minus = FALSE; break;
case'm': /* set writemarkers option */
options_writemarkers = !minus;
minus = FALSE; break;
case'V': /* set verbosity for Traces */
if (minus)
{
options_verbosity = 0;
minus = FALSE;
} else
{
i = getint_sl(INFILE);
if (i < 0)
{
fprintf(ERRFILE,"verbosity must be >= 0\n");
FLUSHANDPROMPT;
} else
options_verbosity = i;
} break;
case'S': /* set strategy for Traces */
if (minus)
{
options_strategy = 0;
minus = FALSE;
} else
{
i = getint_sl(INFILE);
if (i != 0) fprintf(ERRFILE, "Only strategy 0 is supported in this version\n"); /* if(i<0) { fprintf(ERRFILE,"strategymustbe>=0\n"); FLUSHANDPROMPT; } else options_strategy=i;
*/
} break;
case'G': /* set schreier option */
if (minus)
{
options_schreier = 0;
minus = FALSE;
} else
{
i = getint_sl(INFILE);
if (i < 0)
{
fprintf(ERRFILE,"schreierfails must be >= 0\n");
FLUSHANDPROMPT;
} else
{
options_schreier = i;
if (i > 0) schreier_fails(i);
}
} break;
case'p': /* set cartesian option */
options_cartesian = !minus;
minus = FALSE; break;
case'd': /* set digraph option */
if (options_digraph && minus) gvalid = gvalid_sg = FALSE;
options_digraph = !minus;
minus = FALSE; break;
case'P': /* set keep-group option */
if (minus && options_keepgroup)
{
options_keepgroup = FALSE;
freeschreier(NULL,&generators);
} else
{
if ((d = getc(INFILE)) != 'P') ungetc(d,INFILE);
options_keepgroup = TRUE;
if (d == 'P')
{
readvperm(INFILE,perm,prompt,n,&nperm);
if (nperm != n)
{
fprintf(ERRFILE,"Incomplete permutation\n");
FLUSHANDPROMPT;
} else
addpermutation(&generators,perm,n);
}
}
minus = FALSE; break;
case'$': /* set label origin */
if ((d = getc(INFILE)) == '$')
labelorg = oldorg; else
{
ungetc(d,INFILE);
oldorg = labelorg;
i = getint_sl(INFILE);
if (i < 0)
{
fprintf(ERRFILE,"labelorg must be >= 0\n");
FLUSHANDPROMPT;
} else
labelorg = i;
} break;
case'?': /* type options, etc. */
minus = FALSE;
fprintf(outfile,"Mode=%s ",
(mode==DENSE_MODE?"dense":
mode==SPARSE_MODE?"sparse":"Traces"));
fprintf(outfile,"m=%d n=%d labelorg=%d",m,n,labelorg);
if (!gvalid && !gvalid_sg)
fprintf(outfile," g=undef"); else if (gvalid)
{
uli = 0;
for (i = 0, gp = g; i < n; ++i, gp += m) uli += setsize(gp,m);
if (options_digraph) fprintf(outfile," arcs=%lu",uli); else fprintf(outfile," edges=%lu",uli/2);
} else
{
uli = g_sg.nde;
if (options_digraph) fprintf(outfile," arcs=%lu",uli); else fprintf(outfile," edges=%lu",uli/2);
}
fprintf(outfile," options=(%cc%ca%cm%cp%cd",
PM(options_getcanon),PM(options_writeautoms),
PM(options_writemarkers),PM(options_cartesian),
PM(options_digraph));
if (mode == TRACES_MODE)
fprintf(outfile,"%cP",PM(options_keepgroup));
if (umask & 31)
fprintf(outfile," u=%d",umask&31);
if (options_tc_level > 0)
fprintf(outfile," y=%d",options_tc_level);
if (options_mininvarlevel != 0 || options_maxinvarlevel != 0)
fprintf(outfile," k=(%d,%d)",
options_mininvarlevel,options_maxinvarlevel);
if (options_invararg > 0)
fprintf(outfile," K=%d",options_invararg);
if (multiplicity != 1 || mintime != 0.0)
fprintf(outfile," M=%d/%.0f",multiplicity,mintime);
fprintf(outfile,")\n");
fprintf(outfile,"linelen=%d worksize=%d input_depth=%d",
options_linelength,worksize,curfile);
if (options_schreier > 0)
fprintf(outfile," G=%d",options_schreier);
if (mode == TRACES_MODE)
{
if (options_verbosity != 1)
fprintf(outfile," V=%d",options_verbosity);
if (options_strategy != 0)
fprintf(outfile," S=%d",options_strategy);
}
if (options_invarproc != 1)
fprintf(outfile," invarproc=%s",
(mode == DENSE_MODE ?
invarproc[options_invarproc].name :
invarproc[options_invarproc].name_sg));
if (pvalid)
fprintf(outfile,"; %d cell%s",SS(numcells,"","s")); else
fprintf(outfile,"; 1 cell");
fprintf(outfile,"\n");
if (outfile != PROMPTFILE)
{
fprintf(outfile,"Mode=%s ",
(mode==DENSE_MODE?"dense":
mode==SPARSE_MODE?"sparse":"Traces"));
fprintf(PROMPTFILE,"n=%d depth=%d labelorg=%d\n",
n,curfile,labelorg);
} break;
case'&': /* list the partition and possibly the quotient */
if ((d = getc(INFILE)) == '&')
doquot = TRUE; else
{
ungetc(d,INFILE);
doquot = FALSE;
}
minus = FALSE;
if (pvalid)
putptn(outfile,lab,ptn,0,options_linelength,n); else
fprintf(outfile,"unit partition\n");
if (doquot)
{
if (!pvalid) unitptn(lab,ptn,&numcells,n);
if (SPARSEREP(mode))
putquotient_sg(outfile,&g_sg,lab,ptn,0,options_linelength); else
putquotient(outfile,g,lab,ptn,0,options_linelength,m,n);
} break;
case'h': /* type help information */ case'H':
minus = FALSE;
help(PROMPTFILE,c == 'H'); break;
default: /* illegal command */
fprintf(ERRFILE,"'%c' is illegal - type 'h' for help\n",c);
FLUSHANDPROMPT; break;
staticvoid
help(FILE *f, int i)
{ #define H(ss) fprintf(f," %s\n",ss);
if (i == 0)
{
H("Modes: An = dense, As = sparse, At = Traces; extra + to convert graph")
H("+- a : write automs v,vv : write degrees *=# : select invariant:")
H(" b : write canong w=# : set worksize (units of 2m)")
H("+- c : canonise x : run nauty -1 = user-defined")
H("+- d : digraph or loops y=# : set tc_level 0 = none")
H(" e : edit graph z : write hashcode 1 = twopaths")
H("-f, f=#, f=[...] : set colours 2 = adjtriang(K=0,1)")
H(" g : read graph $=# : set origin 3 = triples")
H(" h,H : help $$ : restore origin 4 = quadruples")
H(" i : refine ? : type options 5 = celltrips")
H(" I : refine using invar _ : compl __ : conv 6 = cellquads")
H(" j : relabel randomly % : Mathon doubling 7 = cellquins")
H("k=# # : set invar levels & : type colouring 8 = distances(K)")
H(" K=# : set invar param && : + quotient matrix 9 = indsets(K)")
H(" l=# : set line length >ff : write to file 10 = cliques(K)")
H("+- m : write markers >>ff : append to file 11 = cellcliq(K)")
H(" n=# : set order ->/->> : close/flush output 12 = cellind(K)")
H(" o : write orbits <ff : read from file 13 = adjacencies")
H("+- p : set autom format @ : save canong 14 = cellfano")
H(" q : quit # : canong = savedg? 15 = cellfano2")
H(" r,R : relabel/subgraph ## : + write mapping 16 = refinvar")
H(" s=# : random g (p=1/#) sr=# : random reg \"...\" : copy comment")
H("-G,G=# : schreier param F=# : fix extra vertex FF: fix target vertex")
H(" t,T : type graph ! : ignore line O : orbits->partition")
H("+- P : keep group PP : add automorphism Type H for more..")
}
if (i == 1)
{
H("Commands for g and e : ")
H(" There is always a \"current vertex\" v, initially first vertex.")
H(" # : add edge v-# ; : increment v (exit if over limit)")
H(" -# : delete edge v-# #: : set v := #")
H(" ? : list nbhs of v . : exit")
H("Mode change: An = dense nauty, As = sparse nauty, At = Traces")
H("Use An+, As+ or At+ to also convert graph between dense and sparse")
H("Command line argument -o options allows a,c,d,m,p,l,G,P,w,y,$,A,V,M")
H("Syntax for f : f=[2 3|4:9|10] (rest in extra cell at right)")
H(" -f same as f=[], f=# same as f=[#]")
H("Syntax for r : r 2:4 1 5; (rest appended in order)")
H("r& relabels the graph and partition in order of the partition")
H("Syntax for R : R 2:4 1 5; or -R 0 3 6:10;")
H("Syntax for PP : PP 2:4 1 5 0; (must be complete)")
H("Arguments for u : 1=node,2=autom,4=level,16=ref,32=canon (add them)")
H("Accurate times: M=#/# set number of runs and minimum total cpu.")
}
staticvoid
usernode(graph *g, int *lab, int *ptn, int level, int numcells,
int tc, int code, int m, int n)
{
int i;
for (i = 0; i < level; ++i) PUTC('.',outfile);
if (numcells == n)
fprintf(outfile,"(n/%d)\n",code); else if (tc < 0)
fprintf(outfile,"(%d/%d)\n",numcells,code); else
fprintf(outfile,"(%d/%d/%d)\n",numcells,code,tc);
if (firstpath) putptn(outfile,lab,ptn,level,options_linelength,n);
if (numcells == n) firstpath = FALSE;
}
staticvoid
userautom(int count, int *perm, int *orbits,
int numorbits, int stabvertex, int n)
{
fprintf(outfile, "**userautomproc: count=%d stabvertex=%d numorbits=%d\n",
count,stabvertex+labelorg,numorbits);
PUTORBITS(outfile,orbits,options_linelength,n);
}
staticvoid
userlevel(int *lab, int *ptn, int level, int *orbits, statsblk *stats,
int tv, int index, int tcellsize, int numcells, int cc, int n)
{
fprintf(outfile, "**userlevelproc: level=%d tv=%d index=%d tcellsize=%d cc=%d\n",
level,tv+labelorg,index,tcellsize,cc);
fprintf(outfile," nodes=%lu cells=%d orbits=%d generators=%d\n",
stats->numnodes,numcells,stats->numorbits,stats->numgenerators);
}
static int
usercanon(graph *g, int *lab, graph *canong, unsigned long count, int code,
int m, int n)
{
fprintf(outfile, "**usercanonproc: count=%lu code=%d\n",count,code); return0;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.60 Sekunden
(vorverarbeitet am 2026-09-04)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.