39 #pragma GCC diagnostic ignored "-Wunused-variable" 40 #pragma GCC diagnostic ignored "-Wredundant-decls" 41 #pragma GCC diagnostic ignored "-Wpedantic" 44 #include "nauty/nauty.h" 45 #include "nauty/nausparse.h" 47 #include "nauty/traces.h" 50 #pragma GCC diagnostic warning "-Wunused-variable" 51 #pragma GCC diagnostic warning "-Wredundant-decls" 52 #pragma GCC diagnostic warning "-Wpedantic" 105 nauty_kill_request = 1;
121 for (
int j = 0; j < permlen; ++j)
123 if ( (
int) p[j] != j )
182 nauty_kill_request = 1;
198 for (j = 0; j < permlen; ++j)
200 if ( (
int) p[j] != j )
251 assert(symgraph !=
NULL);
261 if ( first < 0 && second < 0 )
267 if ( first < 0 || second < 0 )
273 if ( first >= 0 && second >= 0 )
281 else if ( first >= 0 )
328 assert( SG !=
NULL || determinesize );
329 assert( internodeid !=
NULL );
330 assert( *internodeid >= 0 );
331 assert( degrees !=
NULL );
332 assert( maxdegrees !=
NULL );
333 assert( *maxdegrees > 0 );
334 assert( nnodes !=
NULL );
335 assert( nedges !=
NULL );
336 assert( neighbors !=
NULL );
337 assert( colors !=
NULL );
338 assert( naddednodes !=
NULL );
339 assert( naddededges !=
NULL );
340 assert( commonnodeidx <= *internodeid );
349 curcolor = colors[0];
351 for (e = 1; e < nneighbors; ++e)
354 if ( colors[e] != curcolor )
360 (*degrees)[*internodeid] = 1;
361 ++(*degrees)[commonnodeidx];
362 (*colorstostore)[*internodeid] = curcolor;
364 for (f = curstart; f < e; ++f)
366 assert( neighbors[f] <= *internodeid );
367 ++(*degrees)[*internodeid];
368 ++(*degrees)[neighbors[f]];
373 SG->e[edgestartpos[commonnodeidx]++] = *internodeid;
374 SG->e[edgestartpos[*internodeid]++] = commonnodeidx;
376 for (f = curstart; f < e; ++f)
378 SG->e[edgestartpos[neighbors[f]]++] = *internodeid;
379 SG->e[edgestartpos[*internodeid]++] = neighbors[f];
383 *naddededges += e - curstart + 1;
386 curcolor = colors[e];
397 (*degrees)[*internodeid] = 1;
398 ++(*degrees)[commonnodeidx];
399 (*colorstostore)[*internodeid] = curcolor;
401 for (f = curstart; f < nneighbors; ++f)
403 assert( neighbors[f] <= *internodeid );
404 ++(*degrees)[*internodeid];
405 ++(*degrees)[neighbors[f]];
410 SG->e[edgestartpos[commonnodeidx]++] = *internodeid;
411 SG->e[edgestartpos[*internodeid]++] = commonnodeidx;
413 for (f = curstart; f < nneighbors; ++f)
415 SG->e[edgestartpos[*internodeid]++] = neighbors[f];
416 SG->e[edgestartpos[neighbors[f]]++] = *internodeid;
420 *naddededges += nneighbors - curstart + 1;
445 int* groupfirsts =
NULL;
446 int* groupseconds =
NULL;
447 int* groupcolors =
NULL;
449 int edgebegincnt = 0;
460 assert( scip !=
NULL );
461 assert( symgraph !=
NULL );
462 assert( SG !=
NULL || determinesize );
463 assert( nnodes !=
NULL );
464 assert( nedges !=
NULL );
465 assert( degrees !=
NULL );
466 assert( maxdegrees !=
NULL );
467 assert( colors !=
NULL );
468 assert( ncolors !=
NULL );
469 assert( success !=
NULL );
479 nvarnodestoadd = nsymvars;
483 nvarnodestoadd = 2 * nsymvars;
499 for (j = 0; j < *
nnodes; ++j)
506 for (j = 0; j < nvarnodestoadd; ++j)
516 for (j = 0; j < *
nnodes; ++j)
518 SG->d[j] = (*degrees)[j];
519 SG->v[j] = (size_t) (
unsigned) edgebegincnt;
520 pos[j] = edgebegincnt;
521 edgebegincnt += (*degrees)[j];
545 first += nvarnodestoadd;
547 second = -second - 1;
549 second += nvarnodestoadd;
561 groupfirsts[ngroupedges] = first;
562 groupseconds[ngroupedges] = second;
566 groupfirsts[ngroupedges] = second;
567 groupseconds[ngroupedges] = first;
574 assert(0 <= first && first < *nnodes);
575 assert(0 <= second && second < *nnodes);
585 ++(*degrees)[second];
586 (*degrees)[internodeid] = 2;
594 assert( internodeid < *nnodes );
597 SG->e[pos[first]++] = internodeid;
598 SG->e[pos[internodeid]++] = first;
599 SG->e[pos[second]++] = internodeid;
600 SG->e[pos[internodeid]++] = second;
602 assert( first == *nnodes - 1 || pos[first] <= (
int) SG->v[first+1] );
603 assert( second == *nnodes - 1 || pos[second] <= (
int) SG->v[second+1] );
604 assert( internodeid == *nnodes - 1 || pos[internodeid] <= (
int) SG->v[internodeid+1] );
614 ++(*degrees)[second];
620 SG->e[pos[first]++] = second;
621 SG->e[pos[second]++] = first;
623 assert( first == *nnodes - 1 || pos[first] <= (
int) SG->v[first+1] );
624 assert( second == *nnodes - 1 || pos[second] <= (
int) SG->v[second+1] );
631 if ( ngroupedges > 0 )
640 firstnodeidx = groupfirsts[0];
642 for (j = 1; j < ngroupedges; ++j)
645 if ( groupfirsts[j] != firstnodeidx )
648 degrees, maxdegrees, colors, ncolors, nnodes, nedges, firstnodeidx, &groupseconds[firstidx],
649 &groupcolors[firstidx], j - firstidx, &naddednodes, &naddededges) );
652 firstnodeidx = groupfirsts[j];
656 *nnodes += naddednodes;
657 *nedges += naddededges;
664 degrees, maxdegrees, colors, ncolors, nnodes, nedges, firstnodeidx, &groupseconds[firstidx],
665 &groupcolors[firstidx], ngroupedges - firstidx, &naddednodes, &naddededges) );
669 *nnodes += naddednodes;
670 *nedges += naddededges;
684 for (j = 0; j < nvarnodestoadd; ++j)
690 for (j = 0; j < nsymvars; ++j)
692 SG->e[pos[j]++] = j + nsymvars;
693 SG->e[pos[j + nsymvars]++] = j;
695 assert( pos[j] <= (
int) SG->v[j+1] );
696 assert( j + nsymvars == *nnodes - 1 || pos[j+nsymvars] <= (
int) SG->v[j+nsymvars+1] );
707 SCIPdebugMsg(scip,
"#nodes for variables: %d\n", nvarnodestoadd);
740 int* nnodesfromgraph1,
748 int* nvarused1 =
NULL;
749 int* nvarused2 =
NULL;
750 int* varlabel =
NULL;
751 int* groupfirsts =
NULL;
752 int* groupseconds =
NULL;
753 int* groupcolors =
NULL;
756 int edgebegincnt = 0;
771 assert( scip !=
NULL );
772 assert( graph1 !=
NULL );
773 assert( graph2 !=
NULL );
774 assert( SG !=
NULL || determinesize );
775 assert( nnodes !=
NULL );
776 assert( nedges !=
NULL );
777 assert( degrees !=
NULL );
778 assert( maxdegrees !=
NULL );
779 assert( colors !=
NULL );
780 assert( ncolors !=
NULL );
781 assert( nusedvars !=
NULL );
782 assert( ! determinesize || nnodesfromgraph1 !=
NULL );
783 assert( success !=
NULL );
806 nvarnodestoadd = nsymvars;
810 nvarnodestoadd = 2 * nsymvars;
818 for (e = 0; e < nsymedges; ++e)
823 nvarused1[-first - 1] += 1;
825 nvarused1[-second - 1] += 1;
830 nvarused2[-first - 1] += 1;
832 nvarused2[-second - 1] += 1;
835 for (j = 0; j < nvarnodestoadd; ++j)
838 if ( nvarused1[j] != nvarused2[j] )
849 varlabel[j] = nusdvars++;
870 for (j = 0; j < *
nnodes; ++j)
872 SG->d[j] = (*degrees)[j];
873 SG->v[j] = (size_t) (
unsigned) edgebegincnt;
874 pos[j] = edgebegincnt;
875 edgebegincnt += (*degrees)[j];
889 for (i = 0; i < 2; ++i)
892 symgraph = i == 0 ? graph1 : graph2;
899 for (j = 0; j < nvarnodestoadd; ++j)
901 if ( varlabel[j] >= 0 )
904 (*degrees)[nodeshift + varlabel[j]] = 0;
915 (*degrees)[nodeshift + nusdvars + j] = 0;
924 for (j = 0; j < nvarnodestoadd; ++j)
926 if ( varlabel[j] >= 0 )
933 internodeid = nodeshift + curnnodes;
934 for (e = 0; e < nsymedges; ++e)
941 first = varlabel[-first - 1];
943 first = nusdvars + first;
945 second = varlabel[-second - 1];
947 second = nusdvars + second;
957 groupfirsts[ngroupedges] = nodeshift + first;
958 groupseconds[ngroupedges] = nodeshift + second;
962 groupfirsts[ngroupedges] = nodeshift + second;
963 groupseconds[ngroupedges] = nodeshift + first;
970 assert(0 <= first && first < *nnodes);
971 assert(0 <= second && second < *nnodes);
981 ++(*degrees)[nodeshift + first];
982 ++(*degrees)[nodeshift + second];
983 (*degrees)[internodeid] = 2;
986 (*colors)[internodeid] = nusdvars + color;
993 assert( internodeid < *nnodes );
995 SG->e[pos[internodeid]++] = nodeshift + first;
996 SG->e[pos[internodeid]++] = nodeshift + second;
997 SG->e[pos[nodeshift + first]++] = internodeid;
998 SG->e[pos[nodeshift + second]++] = internodeid;
1000 assert( internodeid == *nnodes - 1
1001 || pos[internodeid] <= (
int) SG->v[internodeid+1] );
1002 assert( nodeshift + first == *nnodes - 1
1003 || pos[nodeshift + first] <= (
int) SG->v[nodeshift+first+1] );
1004 assert( nodeshift + second == *nnodes - 1 ||
1005 pos[nodeshift + second] <= (
int) SG->v[nodeshift+second+1] );
1012 if ( determinesize )
1014 ++(*degrees)[nodeshift + first];
1015 ++(*degrees)[nodeshift + second];
1020 SG->e[pos[nodeshift + first]++] = nodeshift + second;
1021 SG->e[pos[nodeshift + second]++] = nodeshift + first;
1023 assert( nodeshift+first == *nnodes - 1 || pos[nodeshift+first] <= (
int) SG->v[nodeshift+first+1] );
1024 assert( nodeshift+second == *nnodes - 1 || pos[nodeshift+second] <= (
int) SG->v[nodeshift+second+1] );
1031 if ( ngroupedges > 0 )
1040 firstnodeidx = groupfirsts[0];
1042 for (j = 1; j < ngroupedges; ++j)
1045 if ( groupfirsts[j] != firstnodeidx )
1048 degrees, maxdegrees, colors, ncolors, nnodes, nedges, firstnodeidx,
1049 &groupseconds[firstidx], &groupcolors[firstidx], j - firstidx, &naddednodes, &naddededges) );
1052 firstnodeidx = groupfirsts[j];
1054 if ( determinesize )
1056 *nnodes += naddednodes;
1057 *nedges += naddededges;
1059 curnnodes += naddednodes;
1065 degrees, maxdegrees, colors, ncolors, nnodes, nedges, firstnodeidx,
1066 &groupseconds[firstidx], &groupcolors[firstidx], ngroupedges - firstidx, &naddednodes, &naddededges) );
1068 if ( determinesize )
1070 *nnodes += naddednodes;
1071 *nedges += naddededges;
1073 curnnodes += naddednodes;
1079 if ( determinesize )
1081 for (j = 0; j < nusdvars; ++j)
1082 ++(*degrees)[nodeshift + j];
1083 (*nedges) += nusdvars / 2;
1087 for (j = 0; j < nusdvars/2; ++j)
1089 SG->e[pos[nodeshift+j]++] = nodeshift + j + nusdvars/2;
1090 SG->e[pos[nodeshift + j + nusdvars/2]++] = nodeshift + j;
1092 assert( pos[nodeshift+j] <= (
int) SG->v[nodeshift+j+1] );
1093 assert( nodeshift+j+nusdvars/2 == *nnodes - 1
1094 || pos[nodeshift+j+nusdvars/2] <= (
int) SG->v[nodeshift+j+nusdvars/2+1] );
1098 nodeshift = curnnodes;
1101 if ( determinesize && i == 0 )
1102 *nnodesfromgraph1 = *
nnodes;
1106 if ( determinesize )
1112 for (j = 0; j < *nnodes - 1; ++j)
1114 (*degrees)[*nnodes - 1] = *nnodes - 1;
1115 (*nedges) += *nnodes - 1;
1116 (*colors)[*nnodes - 1] = 8;
1120 for (j = 0; j < *nnodes - 1; ++j)
1122 SG->e[pos[j]++] = *nnodes - 1;
1123 SG->e[pos[*nnodes-1]++] = j;
1137 if ( determinesize )
1138 *nusedvars = nusdvars;
1153 static const char nautyname[] =
"Traces "NAUTYVERSION;
1166 return "Computing Graph Automorphism Groups by Brendan D. McKay (https://users.cecs.anu.edu.au/~bdm/nauty/)";
1168 return "Computing Graph Automorphism Groups by Adolfo Piperno (https://pallini.di.uniroma1.it/)";
1213 DEFAULTOPTIONS_SPARSEGRAPH(options);
1216 static DEFAULTOPTIONS_TRACES(options);
1224 *log10groupsize = 0;
1230 options.writeautoms =
FALSE;
1232 options.defaultptn =
FALSE;
1235 options.writeautoms =
FALSE;
1236 options.userautomproc = traceshook;
1237 options.defaultptn =
FALSE;
1244 °rees, &maxdegrees, &colors, &ncolors, &success) );
1249 "Stopped symmetry computation: Symmetry graph would become too large.\n");
1256 SG_ALLOC(SG, (
size_t) nnodes, 2 * (
size_t)(
unsigned) nedges,
"malloc");
1259 SG.nde = (size_t) (
unsigned) (2 * nedges);
1263 °rees, &maxdegrees, &colors, &ncolors, &success) );
1273 for (v = 0; v <
nnodes; ++v)
1280 for (v = 0; v <
nnodes; ++v)
1282 if ( v < nnodes-1 && colors[v] == colors[v+1] )
1288 SCIPdebugMsg(scip,
"Symmetry detection graph has %d nodes.\n", nnodes);
1301 sparsenauty(&SG, lab, ptn, orbits, &options, &stats,
NULL);
1303 Traces(&SG, lab, ptn, orbits, &options, &stats,
NULL);
1333 *log10groupsize = (
SCIP_Real) stats.grpsize2;
1357 assert( scip !=
NULL );
1358 assert( G1 !=
NULL );
1359 assert( G2 !=
NULL );
1367 &colors, &ncolors, &nusedvars, &nnodesfromG1, &success) );
1384 DEFAULTOPTIONS_SPARSEGRAPH(options);
1387 static DEFAULTOPTIONS_TRACES(options);
1394 options.writeautoms =
FALSE;
1396 options.defaultptn =
FALSE;
1399 options.writeautoms =
FALSE;
1400 options.userautomproc = traceshook;
1401 options.defaultptn =
FALSE;
1407 SG_ALLOC(SG, (
size_t) nnodes, 2 * (
size_t)(
unsigned) nedges,
"malloc");
1410 SG.nde = (size_t) (
unsigned) (2 * nedges);
1414 &colors, &ncolors, &nusedvars,
NULL, &success) );
1419 #ifdef SCIP_DISABLED_CODE 1424 for (v = 0; v < SG.nv; ++v)
1429 for (v = 0; v < SG.nv; ++v)
1434 for (v = 0; v < SG.nv; ++v)
1436 for (
int w = 0;
w < SG.d[v]; ++
w)
1449 for (v = 0; v <
nnodes; ++v)
1456 for (v = 0; v <
nnodes; ++v)
1458 if ( v < nnodes-1 && colors[v] == colors[v+1] )
1464 #ifdef SCIP_DISABLED_CODE 1467 for (v = 0; v < SG.nv; ++v)
1485 sparsenauty(&SG, lab, ptn, orbits, &options, &stats,
NULL);
1487 Traces(&SG, lab, ptn, orbits, &options, &stats,
NULL);
1505 for (
int i = 0; i < nnodesfromG1; ++i)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
static SCIP_RETCODE addOrDetermineEffectOfGroupedEdges(SCIP *scip, sparsegraph *SG, int *edgestartpos, SCIP_Bool determinesize, int *internodeid, int **degrees, int *maxdegrees, int **colorstostore, int *ncolorstostore, int *nnodes, int *nedges, int commonnodeidx, int *neighbors, int *colors, int nneighbors, int *naddednodes, int *naddededges)
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
#define SCIPallocBlockMemoryArray(scip, ptr, num)
SCIP_Bool SYMcanComputeSymmetry(void)
public methods for memory management
#define SCIPallocClearBufferArray(scip, ptr, num)
int SCIPgetSymgraphNodeColor(SYM_GRAPH *graph, int nodeidx)
int SCIPcalcMemGrowSize(SCIP *scip, int num)
void SCIPsortIntIntInt(int *intarray1, int *intarray2, int *intarray3, int len)
private functions to work with algebraic expressions
int SCIPgetSymgraphNEdges(SYM_GRAPH *graph)
enum SCIP_Retcode SCIP_RETCODE
SCIP_Bool SCIPhasGraphUniqueEdgetype(SYM_GRAPH *graph)
const char * SYMsymmetryGetAddName(void)
static struct NAUTY_Data data_
#define SCIPfreeBufferArray(scip, ptr)
static void nautyhook(int count, int *p, int *orbits, int numorbits, int stabvertex, int n)
variable expression handler
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
interface for symmetry computations
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
methods for dealing with symmetry detection graphs
int SCIPgetSymgraphEdgeFirst(SYM_GRAPH *graph, int edgeidx)
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
static SCIP_Bool isEdgeGroupable(SYM_GRAPH *symgraph, int edgeidx, SCIP_Bool groupbycons)
const char * SYMsymmetryGetAddDesc(void)
SCIP_Bool SCIPisSymgraphEdgeColored(SYM_GRAPH *graph, int edgeidx)
power and signed power expression handlers
static SCIP_RETCODE createOrDetermineSizeGraph(SCIP *scip, SYM_GRAPH *symgraph, SCIP_Bool determinesize, sparsegraph *SG, int *nnodes, int *nedges, int **degrees, int *maxdegrees, int **colors, int *ncolors, SCIP_Bool *success)
SYM_SYMTYPE SCIPgetSymgraphSymtype(SYM_GRAPH *graph)
#define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
static const char nautyname[]
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
static SCIP_RETCODE createOrDetermineSizeGraphCheck(SCIP *scip, SYM_GRAPH *graph1, SYM_GRAPH *graph2, SCIP_Bool determinesize, sparsegraph *SG, int *nnodes, int *nedges, int **degrees, int *maxdegrees, int **colors, int *ncolors, int *nusedvars, int *nnodesfromgraph1, SCIP_Bool *success)
const char * SYMsymmetryGetName(void)
#define SCIPallocBufferArray(scip, ptr, num)
const char * SYMsymmetryGetDesc(void)
constraint handler for nonlinear constraints specified by algebraic expressions
enum SYM_Symtype SYM_SYMTYPE
Constraint handler for linear constraints in their most general form, .
int SCIPgetSymgraphEdgeColor(SYM_GRAPH *graph, int edgeidx)
int SCIPgetSymgraphNConsnodes(SYM_GRAPH *graph)
SYM_NODETYPE SCIPgetSymgraphNodeType(SYM_GRAPH *graph, int nodeidx)
int SCIPgetSymgraphNVars(SYM_GRAPH *graph)
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
#define SCIP_CALL_ABORT(x)
SCIP_Bool SYMcheckGraphsAreIdentical(SCIP *scip, SYM_SYMTYPE symtype, SYM_GRAPH *G1, SYM_GRAPH *G2)
enum SYM_Nodetype SYM_NODETYPE
int SCIPgetSymgraphVarnodeColor(SYM_GRAPH *graph, int nodeidx)
int SCIPgetSymgraphNNodes(SYM_GRAPH *graph)
int SCIPgetSymgraphEdgeSecond(SYM_GRAPH *graph, int edgeidx)
SCIP_RETCODE SYMcomputeSymmetryGenerators(SCIP *scip, int maxgenerators, SYM_GRAPH *symgraph, int *nperms, int *nmaxperms, int ***perms, SCIP_Real *log10groupsize, SCIP_Real *symcodetime)