Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F27036897
dreadnaut.c
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Authored By
Unknown
Size
80 KB
Referenced Files
None
Subscribers
None
dreadnaut.c
View Options
/*****************************************************************************
* *
* This is the main file for dreadnaut() version 2.6, which is a test-bed *
* for nauty() version 2.6. *
* *
* Subject to the copyright notice in the file COPYRIGHT. *
* *
* CHANGE HISTORY *
* 10-Nov-87 : final changes for version 1.2 *
* 5-Dec-87 - replaced all uses of fscanf() by appropriate uses *
* of the new procedures readinteger() and readstring() *
* - changed the '<' command slightly. If a file of the *
* given name cannot be openned, an attempt is made to *
* open a file with the same name extended by DEFEXT. *
* - improved error processing for 'n' command. *
* 28-Sep-88 : changes for version 1.4 : *
* - replaced incorrect %d by %ld in fprintf for ? command *
* 23-Mar-89 : changes for version 1.5 : *
* - added optional startup message *
* - enabled use of refine1 in 'i' command *
* - implemented $$ command *
* - replaced ALLOCS test by DYNALLOC test *
* - modified @ command and added # command *
* - declared local procedures static *
* 25-Mar-89 - implemented k command *
* 27-Mar-89 - implemented * and I commands *
* 29-Mar-89 - implemented K command *
* 2-Apr-89 - added reporting of vertex-invariant statistics *
* 2-Apr-89 - added ## command *
* 4-Apr-89 - added triples(), quadruples(), adjtriang() *
* - updated error reporting for nauty() *
* 5-Apr-89 - removed flushline() from g and e commands *
* - added T command *
* 6-Apr-89 - added cellquads() and distances() *
* 26-Apr-89 - modified ? command, added & and && commands *
* - added indsets(), cliques(), cellquins() *
* 18-Aug-89 - made g, lab, canong dynamically allocated always *
* 2-Mar-90 - added celltrips(), cellcliq(), cellind() *
* 13-Mar-90 - changed canong and savedg in output to h and h' *
* 19-Mar-90 - revised help() a little *
* 19-Apr-90 : changes for version 1.6 *
* - rewrote "*" command to avoid bug in Pyramid C compiler *
* 20-Apr-90 - rewrote above rewrite to avoid bug in SUN3 gcc *
* 23-Apr-90 - undid above rewrite and fixed *my* bug <blush> by *
* making NUMINVARS have type int. Sorry, gcc. *
* 10-Nov-90 - added calls to null routines (see comment on code) *
* 27-Aug-92 : renamed to version 1.7, no changes to this file *
* 5-Jun-93 : renamed to version 1.7+, no changes to this file *
* 18-Aug-93 : renamed to version 1.8, no changes to this file *
* 17-Sep-93 : changes for version 1.9 : *
* - added invariant adjacencies() *
* 7-Jun-96 : changes for version 2.0 : *
* - added invariants cellfano() and cellfano2() *
* - made y=10 the default *
* 11-Jul-96 - added dynamic allocation *
* - rewrote h command and added H command *
* - implemented M and R commands *
* 15-Aug-96 - changed z command to use sethash() *
* 30-Aug-96 - no need to declare seed; already in naututil.h *
* 12-Sep-96 - let i and I commands use userrefproc *
* 9-Dec-96 - made y=infinity the default *
* 6-Sep-97 - allocated arrays before accepting commands *
* 7-Sep-97 - make g,canong,savedg 1-d arrays even statically *
* 22-Sep-97 - undid error introduced on 7-Sep (worksize) *
* 9-Jan-00 - used *_check() instead of *_null() *
* 12-Feb-00 - minor code formatting *
* 17-Aug-00 - now use tc_level from DEFAULTOPTIONS *
* 16-Nov-00 - made changes listed in nauty.h *
* 22-Apr-01 - include nautyinv.h *
* - improve worksize processing for MAXN=0 *
* 5-May-01 - k=0 1 automatic for *, also K=3 or K=0 *
* 2-Jun-01 - added __ command for digraph converse *
* 18-Oct-01 - moved WORKSIZE to here *
* 21-Nov-01 - use NAUTYREQUIRED in *_check() calls *
* 1-Sep-02 - Undid the previous change *
* 17-Nov-03 - Changed INFINITY to NAUTY_INFINITY *
* 15-Nov-04 - Completed all prototypes *
* 23-Nov-06 - no usertcellproc() any more in version 2.4 *
* 10-Nov-09 - removed types shortish and permutation *
* 17-Nov-09 - added sparsegraphs, schreier, A and G commands *
* 19-Nov-09 - added F command, stub for Traces *
* 1-Dec-09 - added traces refinement, M also applies to i *
* 16-Dec-09 - added sr# command for random regular graphs *
* 19-Dec-09 - added s# command for the sparse case *
* - w command is in units of 2*m now *
* 19-May-10 - Incorporate traces canonical labelling *
* 7-Jun-10 - implement %, _ and __ commands for sparse format *
* 8-Jun-10 - add O and P commands, and sparse && command *
* 11-Jun-10 - revise command-line parameters *
* 14-Jun-10 - digraphs and invariants (top level only) in Traces *
* 26-Oct-10 - fix u command for sparse graphs; default G=10 *
* 14-Mar-11 - store partition with savedg *
* 21-Jul-11 - extend M command *
* 24-Oct-11 - add S and OO commands *
* 15-Jan-12 - use putorbitsplus() if USE_ANSICONTROLS *
* 20-Sep-12 - the first argument of ungetc is int, not char *
* 18-Jan-13 - add code for ^C catching in nauty *
* - add usercanonproc sample *
* - ->> means flush output file *
* 14-Nov-14 - fix numcells calculation in 'OO' command *
* 16-Mar-15 - add B command *
* 16-Dec-15 - add r& command *
* 22-Jan-16 - commands with short arguments must be all on one line *
* - most errors cause rest of input line to be skipped *
* 19-Feb-16 - make R command induce a partition if one is defined *
* *
*****************************************************************************/
#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 INFILE fileptr[curfile]
#define SCHREIER_DEFAULT 10
static
long
seed
;
#if !MAXN
DYNALLSTAT
(
graph
,
g
,
g_sz
);
DYNALLSTAT
(
graph
,
canong
,
canong_sz
);
DYNALLSTAT
(
graph
,
savedg
,
savedg_sz
);
DYNALLSTAT
(
setword
,
workspace
,
workspace_sz
);
DYNALLSTAT
(
int
,
lab
,
lab_sz
);
DYNALLSTAT
(
int
,
ptn
,
ptn_sz
);
DYNALLSTAT
(
int
,
orbits
,
orbits_sz
);
DYNALLSTAT
(
int
,
templab
,
templab_sz
);
DYNALLSTAT
(
int
,
tempptn
,
tempptn_sz
);
DYNALLSTAT
(
int
,
perm
,
perm_sz
);
DYNALLSTAT
(
int
,
savedlab
,
savedlab_sz
);
DYNALLSTAT
(
int
,
savedptn
,
savedptn_sz
);
DYNALLSTAT
(
set
,
tempactive
,
tempactive_sz
);
DYNALLSTAT
(
set
,
active
,
active_sz
);
#else
static
graph
g
[
MAXM
*
1L
*
MAXN
];
static
graph
canong
[
MAXM
*
1L
*
MAXN
];
static
graph
savedg
[
MAXM
*
1L
*
MAXN
];
static
setword
workspace
[
MAXM
*
2L
*
WORKSIZE
];
static
int
lab
[
MAXN
];
static
int
ptn
[
MAXN
];
static
int
orbits
[
MAXN
];
static
int
savedlab
[
MAXN
],
savedptn
[
MAXN
];
static
int
perm
[
MAXN
];
static
int
templab
[
MAXN
];
static
int
tempptn
[
MAXN
];
static
int
tempactive
[
MAXM
];
static
set
active
[
MAXM
];
#endif
static
sparsegraph
g_sg
;
static
sparsegraph
canong_sg
;
static
sparsegraph
savedg_sg
;
static
DEFAULTOPTIONS_GRAPH
(
options
);
static
DEFAULTOPTIONS_SPARSEGRAPH
(
options_sg
);
static
statsblk
stats
;
static
int
curfile
;
static
FILE
*
fileptr
[
MAXIFILES
];
static
FILE
*
outfile
;
static
char
def_ext
[]
=
DEFEXT
;
static
boolean
firstpath
;
/* used in usernode() */
DEFAULTOPTIONS_TRACES
(
traces_opts
);
static
TracesStats
traces_stats
;
#define TMP
#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
#ifndef NODEPROC
#define NODEPROC usernode
#else
extern
void
NODEPROC
(
graph
*
,
int
*
,
int
*
,
int
,
int
,
int
,
int
,
int
,
int
);
#endif
#ifndef AUTOMPROC
#define AUTOMPROC userautom
#else
extern
void
AUTOMPROC
(
int
,
int
*
,
int
*
,
int
,
int
,
int
);
#endif
#ifndef LEVELPROC
#define LEVELPROC userlevel
#else
extern
void
LEVELPROC
(
int
*
,
int
*
,
int
,
int
*
,
statsblk
*
,
int
,
int
,
int
,
int
,
int
,
int
);
#endif
#ifndef REFPROC
#define REFPROC NULL
#else
extern
void
REFPROC
(
graph
*
,
int
*
,
int
*
,
int
,
int
*
,
int
*
,
set
*
,
int
*
,
int
,
int
);
#endif
#ifndef CANONPROC
#define CANONPROC usercanon
#else
extern
int
CANONPROC
(
graph
*
,
int
*
,
graph
*
,
int
,
int
,
int
,
int
);
#endif
#ifndef INVARPROC
#define INVARPROC NULL
#define INVARPROCNAME "none"
#else
extern
void
INVARPROC
(
graph
*
,
int
*
,
int
*
,
int
,
int
,
int
,
int
*
,
int
,
boolean
,
int
,
int
);
#define INVARPROCNAME "user-defined"
#endif
#ifndef INVARPROC_SG
#define INVARPROC_SG NULL
#define INVARPROCNAME_SG "none"
#else
extern
void
INVARPROC_SG
(
graph
*
,
int
*
,
int
*
,
int
,
int
,
int
,
int
*
,
int
,
boolean
,
int
,
int
);
#define INVARPROCNAME_SG "user-defined"
#endif
static
struct
invarrec
{
void
(
*
entrypoint
)(
graph
*
,
int
*
,
int
*
,
int
,
int
,
int
,
int
*
,
int
,
boolean
,
int
,
int
);
char
*
name
;
void
(
*
entrypoint_sg
)(
graph
*
,
int
*
,
int
*
,
int
,
int
,
int
,
int
*
,
int
,
boolean
,
int
,
int
);
char
*
name_sg
;
}
invarproc
[]
=
{{
INVARPROC
,
INVARPROCNAME
,
INVARPROC_SG
,
INVARPROCNAME_SG
},
{
NULL
,
"none"
,
NULL
,
"none"
},
{
twopaths
,
"twopaths"
,
NULL
,
"unavailable"
},
{
adjtriang
,
"adjtriang"
,
NULL
,
"unavailable"
},
{
triples
,
"triples"
,
NULL
,
"unavailable"
},
{
quadruples
,
"quadruples"
,
NULL
,
"unavailable"
},
{
celltrips
,
"celltrips"
,
NULL
,
"unavailable"
},
{
cellquads
,
"cellquads"
,
NULL
,
"unavailable"
},
{
cellquins
,
"cellquins"
,
NULL
,
"unavailable"
},
{
distances
,
"distances"
,
distances_sg
,
"distances_sg"
},
{
indsets
,
"indsets"
,
NULL
,
"unavailable"
},
{
cliques
,
"cliques"
,
NULL
,
"unavailable"
},
{
cellcliq
,
"cellcliq"
,
NULL
,
"unavailable"
},
{
cellind
,
"cellind"
,
NULL
,
"unavailable"
},
{
adjacencies
,
"adjacencies"
,
adjacencies_sg
,
"adjacencies_sg"
},
{
cellfano
,
"cellfano"
,
NULL
,
"unavailable"
},
{
cellfano2
,
"cellfano2"
,
NULL
,
"unavailable"
},
{
refinvar
,
"refinvar"
,
NULL
,
"unavailable"
}
};
#define NUMINVARS ((int)(sizeof(invarproc)/sizeof(struct invarrec)))
static
void
help
(
FILE
*
,
int
);
static
void
userautom
(
int
,
int
*
,
int
*
,
int
,
int
,
int
);
static
void
usernode
(
graph
*
,
int
*
,
int
*
,
int
,
int
,
int
,
int
,
int
,
int
);
static
void
userlevel
(
int
*
,
int
*
,
int
,
int
*
,
statsblk
*
,
int
,
int
,
int
,
int
,
int
,
int
);
static
int
usercanon
(
graph
*
,
int
*
,
graph
*
,
int
,
int
,
int
,
int
);
static
boolean
options_writeautoms
,
options_writemarkers
,
options_digraph
,
options_getcanon
,
options_linelength
;
static
int
options_invarproc
,
options_mininvarlevel
,
options_maxinvarlevel
,
options_invararg
,
options_tc_level
,
options_cartesian
;
static
int
options_schreier
,
options_keepgroup
,
options_verbosity
,
options_strategy
;
#if USE_ANSICONTROLS && !DREADTEST
#define PUTORBITS putorbitsplus
#else
#define PUTORBITS putorbits
#endif
#ifdef EXTRADECLS
EXTRADECLS
#endif
#if !HAVE_SIGACTION
#undef ALLOW_INTERRUPT
#define ALLOW_INTERRUPT 0
#endif
#if ALLOW_INTERRUPT
/*****************************************************************************
* *
* Routines for catching SIGINT *
* *
*****************************************************************************/
void
sigintcatcher
(
int
sig
)
/* This is the routine called on SIGINT receipt. */
{
struct
sigaction
ss
;
nauty_kill_request
=
1
;
ss
.
sa_handler
=
SIG_DFL
;
sigemptyset
(
&
ss
.
sa_mask
);
ss
.
sa_flags
=
0
;
sigaction
(
SIGINT
,
&
ss
,
0
);
}
static
void
setsigcatcher
(
void
)
{
struct
sigaction
ss
;
nauty_kill_request
=
0
;
ss
.
sa_handler
=
sigintcatcher
;
sigemptyset
(
&
ss
.
sa_mask
);
ss
.
sa_flags
=
0
;
sigaction
(
SIGINT
,
&
ss
,
0
);
}
static
void
unsetsigcatcher
(
void
)
{
struct
sigaction
ss
;
nauty_kill_request
=
0
;
ss
.
sa_handler
=
SIG_DFL
;
sigemptyset
(
&
ss
.
sa_mask
);
ss
.
sa_flags
=
0
;
sigaction
(
SIGINT
,
&
ss
,
0
);
}
#else
static
void
setsigcatcher
(
void
)
{
}
static
void
unsetsigcatcher
(
void
)
{
}
#endif
/*****************************************************************************
* *
* This is a program which illustrates the use of nauty. *
* Commands are read from stdin, and may be separated by white space, *
* commas or not separated. Output is written to stdout. *
* For a short description, see the nauty User's Guide. *
* *
*****************************************************************************/
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
;
HELP
;
PUTVERSION
;
if
(
argc
==
3
&&
strcmp
(
argv
[
1
],
"-o"
)
==
0
)
parameters
=
argv
[
2
];
else
if
(
argc
!=
1
)
{
fprintf
(
ERRFILE
,
USAGE
);
exit
(
1
);
}
else
parameters
=
""
;
mode
=
DENSE_MODE
;
curfile
=
0
;
fileptr
[
curfile
]
=
stdin
;
#ifdef DREADTEST
prompt
=
FALSE
;
#else
prompt
=
DOPROMPT
(
INFILE
);
#endif
outfile
=
stdout
;
options_writeautoms
=
options_writemarkers
=
TRUE
;
options_digraph
=
FALSE
;
options_getcanon
=
options
.
getcanon
;
options_mininvarlevel
=
options
.
mininvarlevel
;
options_maxinvarlevel
=
options
.
maxinvarlevel
;
options_invararg
=
options
.
invararg
;
options_invarproc
=
1
;
/* index into invarproc[] */
options_tc_level
=
options
.
tc_level
;
options_cartesian
=
options
.
cartesian
;
options_linelength
=
options
.
linelength
;
options_schreier
=
SCHREIER_DEFAULT
;
options_keepgroup
=
FALSE
;
generators
=
NULL
;
options_verbosity
=
1
;
options_strategy
=
0
;
n
=
m
=
1
;
worksize
=
WORKSIZE
;
#if !MAXN
n
=
WORDSIZE
;
DYNALLOC2
(
graph
,
g
,
g_sz
,
n
,
m
,
"dreadnaut"
);
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"
);
n
=
1
;
#endif
#ifdef DREADTEST
seed
=
1
;
ran_init
(
seed
);
#else
#ifdef INITSEED
INITSEED
;
ran_init
(
seed
);
#endif
#endif
umask
=
0
;
pvalid
=
FALSE
;
ovalid
=
FALSE
;
gvalid
=
gvalid_sg
=
FALSE
;
/* at most one valid */
cvalid
=
cvalid_sg
=
FALSE
;
/* at most one valid */
sgorg
=
labelorg
=
oldorg
=
0
;
sgn
=
0
;
multiplicity
=
1
;
mintime
=
0.0
;
flushing
=
FALSE
;
#ifdef INITIALIZE
INITIALIZE
;
#endif
if
(
prompt
)
{
fprintf
(
PROMPTFILE
,
"Dreadnaut version %s.
\n
"
,
NAUTYVERSION
);
fprintf
(
PROMPTFILE
,
"> "
);
}
nauty_check
(
WORDSIZE
,
1
,
1
,
NAUTYVERSIONID
);
nautinv_check
(
WORDSIZE
,
1
,
1
,
NAUTYVERSIONID
);
nautil_check
(
WORDSIZE
,
1
,
1
,
NAUTYVERSIONID
);
naututil_check
(
WORDSIZE
,
1
,
1
,
NAUTYVERSIONID
);
nausparse_check
(
WORDSIZE
,
1
,
1
,
NAUTYVERSIONID
);
SG_INIT
(
g_sg
);
SG_INIT
(
canong_sg
);
SG_INIT
(
savedg_sg
);
minus
=
FALSE
;
for
(
ap
=
parameters
;
*
ap
!=
'\0'
;
)
{
c
=
*
ap
++
;
switch
(
c
)
{
case
' '
:
case
'\t'
:
break
;
case
'-'
:
minus
=
TRUE
;
break
;
case
'+'
:
minus
=
FALSE
;
break
;
case
'a'
:
options_writeautoms
=
!
minus
;
minus
=
FALSE
;
break
;
case
'c'
:
options_getcanon
=
!
minus
;
minus
=
FALSE
;
break
;
case
'm'
:
options_writemarkers
=
!
minus
;
minus
=
FALSE
;
break
;
case
'p'
:
options_cartesian
=
!
minus
;
minus
=
FALSE
;
break
;
case
'B'
:
flushing
=
!
minus
;
minus
=
FALSE
;
break
;
case
'd'
:
options_digraph
=
!
minus
;
minus
=
FALSE
;
break
;
case
'P'
:
options_keepgroup
=
!
minus
;
minus
=
FALSE
;
break
;
case
'w'
:
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
worksize
,
"w"
);
#if MAXN
if
(
worksize
>
2
*
MAXM
*
WORKSIZE
)
{
fprintf
(
ERRFILE
,
"too big - setting worksize = %d
\n
"
,
WORKSIZE
);
worksize
=
WORKSIZE
;
}
#endif
minus
=
FALSE
;
break
;
case
'V'
:
if
(
minus
)
{
options_verbosity
=
0
;
minus
=
FALSE
;
}
else
{
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
i
,
"V"
);
if
(
i
<
0
)
fprintf
(
ERRFILE
,
"verbosity must be >= 0
\n
"
);
else
options_verbosity
=
i
;
}
break
;
case
'S'
:
if
(
minus
)
{
options_strategy
=
0
;
minus
=
FALSE
;
}
else
{
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
i
,
"S"
);
/*
if (i < 0) fprintf(ERRFILE,"strategy must be >= 0\n");
else options_strategy = i;
*/
if
(
i
!=
0
)
fprintf
(
ERRFILE
,
"Only strategy 0 is supported in this version
\n
"
);
}
break
;
case
'G'
:
if
(
minus
)
{
options_schreier
=
0
;
minus
=
FALSE
;
}
else
{
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
i
,
"G"
);
if
(
i
<
0
)
fprintf
(
ERRFILE
,
"schreierfails must be >= 0
\n
"
);
else
{
options_schreier
=
i
;
if
(
i
>
0
)
schreier_fails
(
i
);
}
}
break
;
case
'y'
:
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
options_tc_level
,
"y"
);
minus
=
FALSE
;
break
;
case
'$'
:
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
labelorg
,
"$"
);
minus
=
FALSE
;
break
;
case
'M'
:
if
(
minus
)
{
multiplicity
=
1
;
mintime
=
0.0
;
minus
=
FALSE
;
}
else
{
actmult
=
0
;
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
multiplicity
,
"M"
);
if
(
*
ap
==
'/'
)
{
++
ap
;
arg_int
(
&
ap
,
&
actmult
,
"M/"
);
}
if
(
multiplicity
<
0
)
multiplicity
=
0
;
if
(
actmult
<
0
)
actmult
=
0
;
if
(
multiplicity
==
0
&&
actmult
==
0
)
multiplicity
=
1
;
mintime
=
(
double
)
actmult
;
}
break
;
case
'l'
:
while
(
*
ap
==
'='
||
*
ap
==
' '
)
++
ap
;
arg_int
(
&
ap
,
&
options_linelength
,
"l"
);
minus
=
FALSE
;
break
;
case
'A'
:
d
=
*
ap
++
;
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'
));
break
;
}
minus
=
FALSE
;
break
;
default
:
fprintf
(
ERRFILE
,
"Illegal initialization command %c
\n
"
,
c
);
exit
(
1
);
}
}
minus
=
FALSE
;
while
(
curfile
>=
0
)
{
if
((
c
=
getc
(
INFILE
))
==
EOF
||
c
==
'\004'
)
{
fclose
(
INFILE
);
--
curfile
;
if
(
curfile
>=
0
)
prompt
=
DOPROMPT
(
INFILE
);
}
else
switch
(
c
)
{
case
'\n'
:
/* possibly issue prompt */
if
(
prompt
)
fprintf
(
PROMPTFILE
,
"> "
);
minus
=
FALSE
;
break
;
case
' '
:
/* do nothing */
case
'\t'
:
#ifndef NLMAP
case
'\r'
:
#endif
case
'\f'
:
break
;
case
'-'
:
/* remember this for next time */
minus
=
TRUE
;
break
;
case
'+'
:
/* forget - */
case
','
:
case
';'
:
minus
=
FALSE
;
break
;
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
'g'
:
/* read graph */
minus
=
FALSE
;
if
(
SPARSEREP
(
mode
))
{
readgraph_sg
(
INFILE
,
&
g_sg
,
options_digraph
,
prompt
,
options_linelength
,
n
);
gvalid_sg
=
TRUE
;
cvalid_sg
=
FALSE
;
}
else
{
#if !MAXN
DYNALLOC2
(
graph
,
g
,
g_sz
,
n
,
m
,
"dreadnaut"
);
#endif
readgraph
(
INFILE
,
g
,
options_digraph
,
prompt
,
FALSE
,
options_linelength
,
m
,
n
);
gvalid
=
TRUE
;
cvalid
=
FALSE
;
}
ovalid
=
FALSE
;
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
);
++
actmult
;
if
(
multiplicity
>
0
&&
actmult
>=
multiplicity
)
break
;
#ifdef CPUTIME
if
(
mintime
>
0.0
&&
(
actmult
<
20
||
!
(
actmult
&
7
))
&&
CPUTIME
>=
timebefore
+
mintime
)
break
;
#endif
}
#ifdef CPUTIME
timeafter
=
CPUTIME
;
#endif
if
(
numcells
>
1
)
pvalid
=
TRUE
;
fprintf
(
outfile
,
" %d cell%s; code = %x"
,
SS
(
numcells
,
""
,
"s"
),
refcode
);
#ifdef CPUTIME
fprintf
(
outfile
,
"; cpu time = %.7f seconds
\n
"
,
(
timeafter
-
timebefore
)
/
actmult
);
#else
fprintf
(
outfile
,
"
\n
"
);
#endif
break
;
case
'x'
:
/* execute nauty */
minus
=
FALSE
;
if
(
mode
==
TRACES_MODE
)
{
ovalid
=
FALSE
;
cvalid_sg
=
FALSE
;
if
(
!
gvalid_sg
)
{
fprintf
(
ERRFILE
,
"g is not defined
\n
"
);
FLUSHANDPROMPT
;
break
;
}
traces_opts
.
getcanon
=
options_getcanon
;
traces_opts
.
writeautoms
=
options_writeautoms
;
traces_opts
.
cartesian
=
options_cartesian
;
traces_opts
.
linelength
=
options_linelength
;
traces_opts
.
digraph
=
options_digraph
;
traces_opts
.
outfile
=
outfile
;
traces_opts
.
verbosity
=
options_verbosity
;
traces_opts
.
strategy
=
options_strategy
;
if
(
options_keepgroup
)
traces_opts
.
generators
=
&
generators
;
else
traces_opts
.
generators
=
NULL
;
#if !MAXN
DYNALLOC1
(
int
,
tempptn
,
tempptn_sz
,
n
,
"dreadnaut"
);
#endif
if
(
!
pvalid
)
unitptn
(
lab
,
ptn
,
&
numcells
,
n
);
memcpy
(
tempptn
,
ptn
,
n
*
sizeof
(
int
));
savednc
=
numcells
;
if
(
options_invarproc
!=
1
&&
options_maxinvarlevel
>
0
)
{
if
(
options_maxinvarlevel
>
1
)
fprintf
(
ERRFILE
,
"Warning: Traces only uses invariants at the top level
\n
"
);
if
(
invarproc
[
options_invarproc
].
entrypoint_sg
)
{
#ifdef CPUTIME
timebefore
=
CPUTIME
;
#endif
cellstarts
(
tempptn
,
0
,
active
,
m
,
n
);
doref
((
graph
*
)
&
g_sg
,
lab
,
tempptn
,
0
,
&
savednc
,
&
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
);
fprintf
(
outfile
,
"Invariant %s %s; %d cell%s"
,
invarproc
[
options_invarproc
].
name_sg
,
(
qinvar
==
2
?
"worked"
:
"failed"
),
SS
(
savednc
,
""
,
"s"
));
#ifdef CPUTIME
timeafter
=
CPUTIME
;
fprintf
(
outfile
,
"; cpu time = %.2f seconds
\n
"
,
timeafter
-
timebefore
);
#else
fprintf
(
outfile
,
"
\n
"
);
#endif
}
}
#ifdef CPUTIME
timebefore
=
CPUTIME
;
#endif
actmult
=
0
;
setsigcatcher
();
for
(;;)
{
traces_opts
.
defaultptn
=
!
pvalid
;
Traces
(
&
g_sg
,
lab
,
tempptn
,
orbits
,
&
traces_opts
,
&
traces_stats
,
&
canong_sg
);
if
(
traces_stats
.
errstatus
)
break
;
traces_opts
.
writeautoms
=
FALSE
;
traces_opts
.
verbosity
=
0
;
++
actmult
;
if
(
multiplicity
>
0
&&
actmult
>=
multiplicity
)
break
;
#ifdef CPUTIME
if
(
mintime
>
0.0
&&
(
actmult
<
20
||
!
(
actmult
&
7
))
&&
CPUTIME
>=
timebefore
+
mintime
)
break
;
#endif
}
unsetsigcatcher
();
#ifdef CPUTIME
timeafter
=
CPUTIME
;
#endif
if
(
traces_stats
.
errstatus
)
{
if
(
traces_stats
.
errstatus
==
NAUABORTED
)
fprintf
(
ERRFILE
,
"Traces aborted
\n
"
);
else
if
(
traces_stats
.
errstatus
==
NAUKILLED
)
fprintf
(
ERRFILE
,
"Traces interrupted
\n
"
);
else
fprintf
(
ERRFILE
,
"Traces returned error status %d [this can't happen]
\n
"
,
traces_stats
.
errstatus
);
cvalid
=
cvalid_sg
=
ovalid
=
FALSE
;
}
else
{
fprintf
(
outfile
,
"%d orbit%s"
,
SS
(
traces_stats
.
numorbits
,
""
,
"s"
));
fprintf
(
outfile
,
"; grpsize="
);
writegroupsize
(
outfile
,
traces_stats
.
grpsize1
,
traces_stats
.
grpsize2
);
fprintf
(
outfile
,
"; %d gen%s"
,
SS
(
traces_stats
.
numgenerators
,
""
,
"s"
));
fprintf
(
outfile
,
"; %lu node%s "
,
SS
(
traces_stats
.
numnodes
,
""
,
"s"
));
if
(
traces_stats
.
interrupted
)
fprintf
(
outfile
,
"(%lu interrupted, "
,
traces_stats
.
interrupted
);
else
fprintf
(
outfile
,
"("
);
fprintf
(
outfile
,
"%lu peak); maxlev=%d
\n
"
,
traces_stats
.
peaknodes
,
traces_stats
.
treedepth
);
if
(
options_getcanon
)
fprintf
(
outfile
,
"canupdates=%d; "
,
traces_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
(
options_getcanon
)
cvalid_sg
=
TRUE
;
ovalid
=
TRUE
;
}
}
else
{
ovalid
=
FALSE
;
cvalid
=
cvalid_sg
=
FALSE
;
if
(
!
gvalid
&&
!
gvalid_sg
)
{
fprintf
(
ERRFILE
,
"g is not defined
\n
"
);
FLUSHANDPROMPT
;
break
;
}
if
(
mode
==
DENSE_MODE
)
{
if
(
pvalid
)
{
fprintf
(
outfile
,
"[fixing partition]
\n
"
);
options
.
defaultptn
=
FALSE
;
}
else
options
.
defaultptn
=
TRUE
;
options
.
outfile
=
outfile
;
options
.
digraph
=
options_digraph
;
options
.
cartesian
=
options_cartesian
;
options
.
schreier
=
(
options_schreier
>
0
);
options
.
getcanon
=
options_getcanon
;
options
.
tc_level
=
options_tc_level
;
options
.
linelength
=
options_linelength
;
options
.
invarproc
=
invarproc
[
options_invarproc
].
entrypoint
;
options
.
mininvarlevel
=
options_mininvarlevel
;
if
(
options
.
invarproc
)
options
.
maxinvarlevel
=
options_maxinvarlevel
;
else
options
.
maxinvarlevel
=
0
;
options
.
invararg
=
options_invararg
;
if
(
options_schreier
>
0
)
schreier_fails
(
options_schreier
);
if
(
umask
&
U_NODE
)
options
.
usernodeproc
=
NODEPROC
;
else
options
.
usernodeproc
=
NULL
;
if
(
umask
&
U_AUTOM
)
options
.
userautomproc
=
AUTOMPROC
;
else
options
.
userautomproc
=
NULL
;
if
(
umask
&
U_LEVEL
)
options
.
userlevelproc
=
LEVELPROC
;
else
options
.
userlevelproc
=
NULL
;
if
(
umask
&
U_REF
)
options
.
userrefproc
=
REFPROC
;
else
options
.
userrefproc
=
NULL
;
if
(
umask
&
U_CANON
)
options
.
usercanonproc
=
CANONPROC
;
else
options
.
usercanonproc
=
NULL
;
#if !MAXN
if
(
options_getcanon
)
DYNALLOC2
(
graph
,
canong
,
canong_sz
,
n
,
m
,
"dreadnaut"
);
DYNALLOC1
(
setword
,
workspace
,
workspace_sz
,
2
*
m
*
worksize
,
"dreadnaut"
);
#endif
firstpath
=
TRUE
;
options
.
writeautoms
=
options_writeautoms
;
options
.
writemarkers
=
options_writemarkers
;
#ifdef CPUTIME
timebefore
=
CPUTIME
;
#endif
actmult
=
0
;
setsigcatcher
();
for
(;;)
{
nauty
(
g
,
lab
,
ptn
,
NULL
,
orbits
,
&
options
,
&
stats
,
workspace
,
2
*
m
*
worksize
,
m
,
n
,
canong
);
if
(
stats
.
errstatus
)
break
;
options
.
writeautoms
=
FALSE
;
options
.
writemarkers
=
FALSE
;
++
actmult
;
if
(
multiplicity
>
0
&&
actmult
>=
multiplicity
)
break
;
#ifdef CPUTIME
if
(
mintime
>
0.0
&&
(
actmult
<
20
||
!
(
actmult
&
7
))
&&
CPUTIME
>=
timebefore
+
mintime
)
break
;
#endif
}
unsetsigcatcher
();
#ifdef CPUTIME
timeafter
=
CPUTIME
;
#endif
}
if
(
mode
==
SPARSE_MODE
)
{
if
(
pvalid
)
{
fprintf
(
outfile
,
"[fixing partition]
\n
"
);
options_sg
.
defaultptn
=
FALSE
;
}
else
options_sg
.
defaultptn
=
TRUE
;
options_sg
.
outfile
=
outfile
;
options_sg
.
digraph
=
options_digraph
;
options_sg
.
cartesian
=
options_cartesian
;
options_sg
.
schreier
=
(
options_schreier
>
0
);
options_sg
.
getcanon
=
options_getcanon
;
options_sg
.
linelength
=
options_linelength
;
options_sg
.
invarproc
=
invarproc
[
options_invarproc
].
entrypoint_sg
;
options_sg
.
mininvarlevel
=
options_mininvarlevel
;
if
(
options_sg
.
invarproc
)
options_sg
.
maxinvarlevel
=
options_maxinvarlevel
;
else
options_sg
.
maxinvarlevel
=
0
;
options_sg
.
invararg
=
options_invararg
;
options_sg
.
tc_level
=
options_tc_level
;
if
(
options_schreier
>
0
)
schreier_fails
(
options_schreier
);
if
(
umask
&
U_NODE
)
options_sg
.
usernodeproc
=
NODEPROC
;
else
options_sg
.
usernodeproc
=
NULL
;
if
(
umask
&
U_AUTOM
)
options_sg
.
userautomproc
=
AUTOMPROC
;
else
options_sg
.
userautomproc
=
NULL
;
if
(
umask
&
U_LEVEL
)
options_sg
.
userlevelproc
=
LEVELPROC
;
else
options_sg
.
userlevelproc
=
NULL
;
if
(
umask
&
U_REF
)
options_sg
.
userrefproc
=
REFPROC
;
else
options_sg
.
userrefproc
=
NULL
;
if
(
umask
&
U_CANON
)
options_sg
.
usercanonproc
=
CANONPROC
;
else
options_sg
.
usercanonproc
=
NULL
;
#if !MAXN
DYNALLOC1
(
setword
,
workspace
,
workspace_sz
,
2
*
m
*
worksize
,
"dreadnaut"
);
#endif
firstpath
=
TRUE
;
options_sg
.
writeautoms
=
options_writeautoms
;
options_sg
.
writemarkers
=
options_writemarkers
;
#ifdef CPUTIME
timebefore
=
CPUTIME
;
#endif
actmult
=
0
;
setsigcatcher
();
for
(;;)
{
nauty
((
graph
*
)
&
g_sg
,
lab
,
ptn
,
NULL
,
orbits
,
&
options_sg
,
&
stats
,
workspace
,
2
*
m
*
worksize
,
m
,
n
,(
graph
*
)
&
canong_sg
);
if
(
stats
.
errstatus
)
break
;
options_sg
.
writeautoms
=
FALSE
;
options_sg
.
writemarkers
=
FALSE
;
++
actmult
;
if
(
multiplicity
>
0
&&
actmult
>=
multiplicity
)
break
;
#ifdef CPUTIME
if
(
mintime
>
0.0
&&
(
actmult
<
20
||
!
(
actmult
&
7
))
&&
CPUTIME
>=
timebefore
+
mintime
)
break
;
#endif
}
unsetsigcatcher
();
#ifdef CPUTIME
timeafter
=
CPUTIME
;
#endif
}
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
;
}
}
}
if
(
ptn
[
i
]
>
0
)
{
ptn
[
i
]
=
0
;
++
numcells
;
}
pvalid
=
TRUE
;
}
freeschreier
(
NULL
,
&
generators
);
break
;
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
);
zseed
=
hashgraph
(
canong
,
m
,
n
,
19883109L
);
fprintf
(
outfile
,
" %07lx"
,
zseed
);
zseed
=
hashgraph
(
canong
,
m
,
n
,
489317L
);
fprintf
(
outfile
,
" %07lx]
\n
"
,
zseed
);
}
else
if
(
cvalid_sg
)
{
zseed
=
hashgraph_sg
(
&
canong_sg
,
2922320L
);
fprintf
(
outfile
,
"[%c%07lx"
,
mode
==
SPARSE_MODE
?
'S'
:
'T'
,
zseed
);
zseed
=
hashgraph_sg
(
&
canong_sg
,
19883109L
);
fprintf
(
outfile
,
" %07lx"
,
zseed
);
zseed
=
hashgraph_sg
(
&
canong_sg
,
489317L
);
fprintf
(
outfile
,
" %07lx]
\n
"
,
zseed
);
}
else
{
fprintf
(
ERRFILE
,
"h is not defined
\n
"
);
FLUSHANDPROMPT
;
}
break
;
case
'c'
:
/* set getcanon option */
options_getcanon
=
!
minus
;
minus
=
FALSE
;
break
;
case
'w'
:
/* read size of workspace */
minus
=
FALSE
;
worksize
=
getint_sl
(
INFILE
);
#if MAXN
if
(
worksize
>
2
*
MAXM
*
WORKSIZE
)
{
fprintf
(
ERRFILE
,
"too big - setting worksize = %d
\n
"
,
WORKSIZE
);
worksize
=
WORKSIZE
;
}
#endif
break
;
case
'l'
:
/* read linelength for output */
options_linelength
=
getint_sl
(
INFILE
);
minus
=
FALSE
;
break
;
case
'y'
:
/* set tc_level field of options */
options_tc_level
=
getint_sl
(
INFILE
);
minus
=
FALSE
;
break
;
case
'M'
:
/* set multiplicity */
if
(
minus
)
{
multiplicity
=
1
;
mintime
=
0.0
;
minus
=
FALSE
;
}
else
{
multiplicity
=
getint_sl
(
INFILE
);
if
(
multiplicity
<
0
)
multiplicity
=
0
;
if
((
d
=
getc
(
INFILE
))
==
'/'
)
{
actmult
=
getint_sl
(
INFILE
);
if
(
actmult
<
0
)
actmult
=
0
;
}
else
{
ungetc
(
d
,
INFILE
);
actmult
=
0
;
}
if
(
multiplicity
==
0
&&
actmult
==
0
)
multiplicity
=
1
;
mintime
=
(
double
)
actmult
;
}
break
;
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,"strategy must be >= 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
;
}
/* end of switch */
if
(
flushing
)
fflush
(
outfile
);
}
exit
(
0
);
}
/*****************************************************************************
* *
* help(f,i) writes help information to file f (i = 0,1). *
* *
*****************************************************************************/
static
void
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."
)
}
}
/*****************************************************************************
* *
* usernode(g,lab,ptn,level,numcells,tc,code,m,n) is a simple version of the *
* procedure named by options.usernodeproc. *
* *
*****************************************************************************/
static
void
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
;
}
/*****************************************************************************
* *
* userautom(count,perm,orbits,numorbits,stabvertex,n) is a simple *
* version of the procedure named by options.userautomproc. *
* *
*****************************************************************************/
static
void
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
);
}
/*****************************************************************************
* *
* userlevel(lab,ptn,level,orbits,stats,tv,index,tcellsize,numcells,cc,n) *
* is a simple version of the procedure named by options.userlevelproc. *
* *
*****************************************************************************/
static
void
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
);
}
/*****************************************************************************
* *
* usercanon(g,lab,canong,count,code,m,n) *
* is a simple version of the procedure named by options.userlevelproc. *
* *
*****************************************************************************/
static
int
usercanon
(
graph
*
g
,
int
*
lab
,
graph
*
canong
,
int
count
,
int
code
,
int
m
,
int
n
)
{
fprintf
(
outfile
,
"**usercanonproc: count=%d code=%d
\n
"
,
count
,
code
);
return
0
;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Oct 27, 8:17 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
407864
Default Alt Text
dreadnaut.c (80 KB)
Attached To
Mode
R272 SoC_NEM_Synthesis
Attached
Detach File
Event Timeline