summaryrefslogtreecommitdiff
path: root/nauty/traces.c
diff options
context:
space:
mode:
authorAndrew Guschin <guschin.drew@gmail.com>2023-08-13 01:27:00 +0400
committerAndrew Guschin <guschin.drew@gmail.com>2023-08-13 06:00:02 -0500
commit58acff54b1cd64cb23b9d0b1a304eb9db768e3eb (patch)
tree87281f776e0015f218aadb5cbfdad43c66406342 /nauty/traces.c
Initial commit
Diffstat (limited to 'nauty/traces.c')
-rw-r--r--nauty/traces.c10490
1 files changed, 10490 insertions, 0 deletions
diff --git a/nauty/traces.c b/nauty/traces.c
new file mode 100644
index 0000000..78b397d
--- /dev/null
+++ b/nauty/traces.c
@@ -0,0 +1,10490 @@
+/******************************************************************************
+ * *
+ * This is the main file for traces() version 2.2, which is included into *
+ * nauty() version 2.8.6. *
+ * *
+ * nauty is Copyright (1984-2018) Brendan McKay. All rights reserved. *
+ * Traces is Copyright Adolfo Piperno, 2008-2018. All rights reserved. *
+ * See the file COPYRIGHT for the details of the software license. *
+ * *
+ * CHANGE HISTORY *
+ * 28-Dec-12 : final changes for version 2.0 *
+ * 20-Jan-13 : add code for ^C catching in Traces *
+ * 29-Mar-13 : bug correction in automorphism mode *
+ * 02-Apr-13 : add preprocessing *
+ * 21-May-13 : bug correction (coloured lists) *
+ * 29-Jun-13 : bug correction (coloured lists and cycles) *
+ * 07-Dec-13 : bug correction in automorphism mode (wrong group size *
+ * due to randomness in Schreier-Sims orbit computation) *
+ * bug correction (discrete initial partition) *
+ * 15-Feb-14 : CPUDEFS removed (already declared in gtools.h) *
+ * 01-Sep-15 : add weighted edges (not active) *
+ * 28-Jan-16 : version ready for nauty and Traces v.2.6 distribution *
+ * 12-Jul-16 : bug correction (reaching degree 2 vertices) *
+ * 07-Jun-18 : bug correction (finalnumcells, thanks R.Kralovic) *
+ * 07-Jun-18 : bug correction (index computation when findperm) *
+ * 10-Nov-22 : bug correction (cycles in degree 2 subgraphs) *
+ *****************************************************************************/
+
+#include "traces.h"
+
+#ifdef NAUTY_IN_MAGMA
+#include "cleanup.e"
+#endif
+
+#define SORT_OF_SORT 2
+#define SORT_NAME sort2ints
+#define SORT_TYPE1 int
+#define SORT_TYPE2 int
+#include "sorttemplates.c"
+
+typedef struct weightwhere {
+ int weight;
+ int *ref;
+} weightwhere;
+
+#define SORT_OF_SORT 2
+#define SORT_NAME sortweights
+#undef SORT_TYPE2
+#define SORT_TYPE1 int
+#define SORT_TYPE2 weightwhere
+#include "sorttemplates.c"
+
+#define NAUTY_ABORTED (-11)
+#define NAUTY_KILLED (-12)
+
+typedef struct Candidate {
+ boolean sortedlab;
+ int *invlab;
+ int *lab;
+ int code;
+ int do_it;
+ int indnum;
+ int name;
+ int vertex;
+ struct Candidate *next;
+ struct searchtrie *stnode;
+ unsigned int firstsingcode;
+ unsigned int pathsingcode;
+ unsigned int singcode;
+} Candidate;
+
+typedef struct Partition {
+ int *cls;
+ int *inv;
+ int active;
+ int cells;
+ int code;
+} Partition;
+
+typedef struct trielist {
+ struct searchtrie *triearray;
+ struct trielist *prev;
+ struct trielist *next;
+} trielist;
+
+typedef struct TracesVars {
+ char digstring[25];
+ double autchk;
+ double expaths;
+ double schreier1;
+ double schreier2;
+ double schreier3;
+ int augmented_cells;
+ int build_autom;
+ int *currorbit;
+ int *orbits;
+ int answ;
+ int brkstpcount;
+ int compstage;
+ int cand_level;
+ int canlist;
+ int digits;
+ int expathlength;
+ int firstpathlength;
+ int fromlevel;
+ int group_level;
+ int indivend;
+ int indivstart;
+ int indiv_vtx;
+ int lastcell;
+ int lastlev;
+ int lev_of_lastauto;
+ int levelfromCS0;
+ int linelgth;
+ int mark;
+ int treemark;
+ int autmark;
+ int markcell1;
+ int markcell2;
+ int maxdeg;
+ int maxtreelevel;
+ int maxspineorblevel;
+ int mindeg;
+ int name;
+ struct searchtrie *gotonode;
+ struct searchtrie *newgotonode;
+ struct searchtrie *newst_stage1;
+ int newindex;
+ int nextlevel;
+ int nfix;
+ int finalnumcells;
+ int permInd;
+ int preprocessed;
+ int samepref;
+ int specialgens;
+ int stackmark;
+ int steps;
+ int strategy;
+ trielist *strielist;
+ int strienext;
+ int tcell_sz;
+ int tcell;
+ int tcellevel;
+ int tcellexpath_sz;
+ int tcellexpath;
+ int tolevel_tl;
+ int tolevel;
+ int treedepth;
+ int trienext;
+ int triepos;
+ TracesOptions *options;
+ TracesStats *stats;
+ unsigned int singlongcode;
+ sparsegraph *graph;
+ sparsegraph *cangraph;
+ sparsegraph *input_graph;
+ int conta0;
+ int conta1;
+ int conta2;
+ int conta3;
+ int conta4;
+ int conta5;
+ int conta6;
+ int conta7;
+ int contatc;
+} TracesVars;
+
+typedef struct TracesInfo {
+ boolean autofound;
+ boolean deg_one;
+ boolean first_matching;
+ boolean regular;
+ boolean exitfromref;
+ boolean identitygroup;
+ boolean minimalinorbits;
+ boolean thegraphisparse;
+ boolean thegrouphaschanged;
+ boolean thereisnextlevel;
+ boolean useTempOrbits1;
+ boolean useTempOrbits2;
+} TracesInfo;
+
+typedef struct TracesSpine {
+ boolean thetracexists;
+ Candidate *listend;
+ Candidate *liststart;
+ int ccend;
+ int ccstart;
+ int listcounter;
+ int stpend;
+ int stpstart;
+ int tgtcell;
+ int tgtend;
+ int tgtfrom;
+ int tgtpos;
+ int tgtsize;
+ int trcend;
+ int trcstart;
+ int singend;
+ int singstart;
+ int updates;
+ unsigned long keptcounter;
+ unsigned long levelcounter;
+ Partition *part;
+ unsigned int singcode;
+} TracesSpine;
+
+typedef struct trie {
+ int value;
+ struct trie *first_child;
+ struct trie *next_sibling;
+} trie;
+
+typedef struct searchtrie {
+ int index;
+ int name;
+ int vtx;
+ int level;
+ struct searchtrie *father;
+ struct searchtrie *first_child;
+ struct searchtrie *last_child;
+ struct searchtrie *next_sibling;
+ struct searchtrie *goes_to;
+} searchtrie;
+
+typedef struct pair {
+ int arg;
+ int val;
+} pair;
+
+typedef struct grph_strct {
+ int *e;
+ int *w;
+ int d;
+ boolean one;
+} grph_strct;
+
+typedef struct ExpPathInfo {
+ int code;
+ int cell;
+ int info;
+} ExpPathInfo;
+
+static boolean traces_degree_refine(sparsegraph*, Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*, int, int*);
+static int traces_vertexclass_refine (int, int*, int*, Candidate*, Partition*, int*);
+static int traces_refine(Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*, int, boolean);
+static void traces_refine_notrace(Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*);
+static void traces_refine_maketrie(Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*);
+static int traces_refine_comptrie(Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*);
+static int traces_refine_sametrace(Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*);
+static int traces_refine_refine(sparsegraph*, Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*);
+static void refine_tr_refine(Candidate*, int, Partition*,
+ struct TracesVars*, struct TracesInfo*);
+static int given_gens(sparsegraph*, permnode*, int*, boolean);
+static void quickSort(int*, int);
+static struct Partition* NewPartition(int);
+static struct Candidate* NewCandidate(int, Candidate**, int);
+static void NewPartSpine(int, int);
+static int FreeList(Candidate*, int);
+static int FixBase(int*, struct TracesVars*, Candidate*, int, int);
+static boolean FixedBase(int*, struct TracesVars*, Candidate*, int, int);
+static void factorial(double*, int*, int);
+static void factorial2(double*, int*, int);
+static int CheckForAutomorphisms(Candidate*, Candidate*, struct TracesVars*, struct TracesInfo*, int, int, Partition*);
+static int CheckForSingAutomorphisms(Candidate*, Partition*, Candidate*, struct TracesVars*, struct TracesInfo*, int, int);
+static int CheckForMatching(Candidate*, Candidate*, Partition*, struct TracesVars*, struct TracesInfo*, int, int);
+static void Individualize(Partition*, Candidate*, int, int, int, int);
+static boolean TreeFyTwo(int, Candidate*, Candidate*, Partition*, int, struct TracesVars*, struct TracesInfo*);
+static void ExperimentalStep(Partition*, Candidate*, struct TracesVars*, struct TracesInfo*, int, int);
+static boolean TargetCell(Candidate*, Partition*, int, struct TracesVars*, int);
+static boolean TargetCellFirstPath(Candidate*, Partition*, struct TracesVars*);
+static int TargetCellExpPath(Candidate*, Partition*, struct TracesVars*);
+static boolean TargetCellSmall(Candidate*, Partition*, int, struct TracesVars*, int);
+static boolean TargetCellFirstPathSmall(Candidate*, Partition*, struct TracesVars*);
+static int TargetCellExpPathSmall(Candidate*, Partition*, struct TracesVars*);
+static boolean SelectNextLevel(int, struct TracesVars*, struct TracesInfo*);
+static void CopyCand(Candidate*, Candidate*, int, int*, int*);
+static struct trie* trie_new(int, struct TracesVars*);
+static struct trie* trie_make(trie*, int, int, struct TracesVars*);
+static struct trie* trie_comp(trie*, int);
+static void trie_dump(trie*);
+static void trie_class(trie*, int*);
+static void RemoveFromLevel(int, int, int, boolean);
+static int CompStage0(Partition*, Partition*, Candidate*, Candidate*, int, int, struct TracesVars*, struct TracesInfo*);
+static int CompStage1(Partition*, Partition*, Candidate*, Candidate*, int, int, struct TracesVars*, struct TracesInfo*);
+static int CompStage2(Partition*, Partition*, Candidate*, Candidate*, int, int, struct TracesVars*, struct TracesInfo*);
+static void grouporderplus(sparsegraph*, Candidate*, Partition*, permnode**, double*, int*, int, struct TracesVars*, struct TracesInfo*);
+static boolean Prefix(Candidate*, Candidate*, int);
+static boolean findperm(permnode*, int*, int);
+static int spinelementorbsize(int*, int*, int, int);
+static trielist* searchtrie_new(int, struct TracesVars*);
+static searchtrie* searchtrie_make(Candidate*, Candidate*, int, struct TracesVars*);
+static boolean lookup(searchtrie*);
+static int* findcurrorbits(schreier*, int);
+static int Preprocess(sparsegraph*, permnode**, Candidate*, int, Partition*, struct TracesVars*);
+static void MakeTree(int, int, sparsegraph*, int, struct TracesVars*, boolean);
+static void MakeCanTree(int, sparsegraph*, int, Candidate*, Partition*, struct TracesVars*);
+static int maxint(int, int);
+static int minint(int, int);
+static void orbjoin_sp_perm(int*, int*, int*, int, int*);
+static void orbjoin_sp_pair(int*, int*, int, int, int, int*);
+static boolean isautom_sg_pair(graph*, int*, boolean, int, int, struct TracesVars*);
+static void SetAutom(int, int, struct TracesVars*);
+static void ResetAutom(int, int, struct TracesVars*);
+static void PrintVect(int*, int, int, int);
+static void putgraphplus_sg(FILE*, sparsegraph*, int);
+static boolean VerifyId(int *p, int n);
+static void PrintPartition(int*, int*, int, int, int);
+static void Place(int, Candidate*, Partition*);
+static int NonSingDeg(int, Candidate*, Partition*);
+static int NonSingDegPlus1(Candidate*, Partition*, int, TracesVars*);
+static void NonSingDegPlus2(Candidate*, Partition*, int, TracesVars*);
+static void Edge_Delete(int, int, Candidate*, TracesVars*);
+static boolean VerifyPart(Partition*, int, int);
+static int VerifyPerm(int*, int,int);
+static boolean VerifyCand(Candidate*, int, int);
+static int FirstNeighbour(int, Candidate*, Partition*, int*, int, int*, int);
+static int NextNeighbour(int, Candidate*, Partition*, int*, int, int*, int);
+static sparsegraph* copy_sg_structure(sparsegraph*, sparsegraph*);
+static void WeightCodes (int);
+static void PrintWeightedGraph1(sparsegraph*, int, char[30]);
+static void PrintWeightedGraph2(int n, char msg[30]);
+static void MakeDiscrete(Partition*, int);
+static void Complete(sparsegraph*, Candidate*, Partition*, int, TracesVars*, double*, int*,permnode**, int);
+static void Allocate_Traces_Structures(int);
+static void Allocate_refine_Structures(int);
+static void Initialize_Traces_Variables(TracesVars*, TracesOptions*, TracesStats*, int*, sparsegraph*, sparsegraph*, int);
+static void Initialize_Traces_Statistics (TracesStats*, int);
+static void Initialize_Traces_Time_Variables (TracesVars*);
+static int trie_classify(int, TracesVars*);
+static int Check_degree_one(sparsegraph*, Candidate*, Partition*, int);
+static void sort_Split_Array(int*, int);
+static const unsigned int fuzz1[] = {037541, 061532, 005257, 026416};
+static const unsigned int fuzz2[] = {006532, 070236, 035523, 062437};
+static int Select_from_CStack(int*, int);
+static void PrintBlissGraph(int);
+static void CodeClassify(int, int, int);
+static void Adjust_Cycles(Candidate*, Partition*, int, TracesVars*);
+
+#define FUZZ1(x) ((x) ^ fuzz1[(x)&3])
+#define FUZZ2(x) ((x) ^ fuzz2[(x)&3])
+
+#define MASHCOMM(l, i) ((l) + FUZZ1(i))
+#define MASHNONCOMM(l, i) (FUZZ2(l) + (i))
+#define MASH(l, i) ((((l) ^ 065435) + (i)) & 077777)
+#define MASH1(l, i) ((l + (i*i)) & 077777)
+#define CLEANUP(l) ((int)((l) % 0x7FFF))
+#define SS(n, sing, plur) (n), ((n) == 1?(sing):(plur))
+
+#define SETMARK(Arr, Mrk) if (Mrk > (NAUTY_INFINITY-2)) { memset(Arr, 0, n*sizeof(int)); Mrk = 0; } Mrk++;
+
+#define COPYNODE(W, V) { \
+memcpy(W->lab, V->lab, n*sizeof(int)); \
+memcpy(W->invlab, V->invlab, n*sizeof(int)); \
+W->code = V->code; \
+W->singcode = V->singcode; \
+W->do_it = V->do_it; }
+
+#define NEXTLINE fprintf(outfile, "\n");
+
+#define PRINTCHAR(c) fprintf(outfile, "%s", c);
+
+#define PRINTCAND(V, Lev) PRINTCHAR(" ") for (tmp=1; tmp<=Lev; tmp++) {fprintf(outfile, tv->digstring, V->lab[Spine[tmp].tgtpos]+labelorg);}
+
+#define PRINTCANDF(V, Lev) { NEXTLINE for (tmp=1; tmp<=Lev; tmp++) {fprintf(outfile, "F%di", V->lab[Spine[tmp].tgtpos]+labelorg);} NEXTLINE }
+
+#define PRINTCANDBIG(V, Lev) { PRINTCHAR(" ") \
+for (tmp=1; tmp<=5; tmp++) {fprintf(outfile, tv->digstring, V->lab[Spine[tmp].tgtpos]+labelorg);} \
+fprintf(outfile, "... "); \
+for (tmp=Lev-4; tmp<=Lev; tmp++) {fprintf(outfile, tv->digstring, V->lab[Spine[tmp].tgtpos]+labelorg);} }
+
+#define LINE(K, c) { PRINTCHAR(c) for (tmp=1; tmp<=K; tmp++) {fprintf(outfile, c);} }
+
+#define TRACE_CHECK(Tr, Ind, Arg, End) { TracePos = Tr+Ind; \
+if (newtrace) { \
+*TracePos = Arg; \
+} \
+else { \
+if (Ind < *End) { \
+if (*TracePos != Arg) { \
+if (*TracePos > Arg) { \
+return FALSE; \
+} \
+else { \
+*TracePos = Arg; \
+newtrace = TRUE; \
+} \
+} \
+} \
+else { \
+*TracePos = Arg; \
+newtrace = TRUE; \
+} \
+} \
+Ind++; }
+
+#define SAMETRACE_CHECK(Tr, Ind, Arg, End) { TracePos = Tr+Ind; \
+if (Ind < *End) { \
+if (*TracePos != Arg) { \
+return FALSE; \
+} \
+} \
+else { \
+return FALSE; \
+} \
+Ind++; }
+
+#define NEWPARTSPINE(Lev) { if (Lev > 3) { \
+Spine[Lev].part = malloc(sizeof(*(Spine[Lev].part))); \
+if (Spine[Lev].part == NULL) { \
+fprintf(ERRFILE, "\nError, memory not allocated.\n"); \
+exit(1); \
+} \
+Spine[Lev].part->cls = Spine[Lev-3].part->cls; \
+Spine[Lev].part->inv = Spine[Lev-3].part->inv; \
+Spine[Lev-3].part->cls = Spine[Lev-3].part->inv = NULL; \
+Spine[Lev].part->code = -1; \
+Spine[Lev].part->cells = 0; \
+} \
+else { \
+Spine[Lev].part = NewPartition(n); \
+} }
+
+#define FIND_SPLIT_CELLS SplInd = 0; \
+for (j = 0; j < HitClsInd; j++) { \
+ind1 = HitCls[j]; \
+ElmHitCll[ind1] -= ind1; \
+if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) { \
+SplCls[SplInd++] = ind1; \
+} \
+}
+
+#define FREEPART(Part) { if (Part) { \
+if (Part->cls) free(Part->cls); \
+if (Part->inv) free(Part->inv); \
+free(Part); } \
+}
+
+#define FREECAND(Cand) { if (Cand) { \
+if (Cand->lab) free(Cand->lab); \
+if (Cand->invlab) free(Cand->invlab); \
+free(Cand); \
+} }
+
+#define COPYPART(P, Q) { memcpy(P->cls, Q->cls, n*sizeof(int)); \
+memcpy(P->inv, Q->inv, n*sizeof(int)); \
+P->cells = Q->cells; \
+P->code = Q->code; } \
+
+#define ADDTONEXTLEVEL { if (SpineTL->listend) { \
+(SpineTL->listend)->next = NewCandidate(n, &GarbList, TRUE); \
+if ((tv->compstage < 2) && (SpineTL->listcounter <= (NAUTY_INFINITY-2))) SpineTL->listcounter++; \
+SpineTL->listend = (SpineTL->listend)->next; \
+CopyCand(SpineTL->listend, NextCand, n, NULL, NULL); \
+} \
+else { \
+SpineTL->liststart = NewCandidate(n, &GarbList, TRUE); \
+if (tv->compstage < 2) SpineTL->listcounter = 1; \
+SpineTL->listend = SpineTL->liststart; \
+CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL); \
+} }
+
+#define ORBITSIZES { memset(OrbSize, 0, n*sizeof(int)); \
+for (i=0; i<n; i++) { \
+OrbSize[tv->orbits[i]]++; \
+} }
+
+#define CURRORBITSIZES { memset(CurrOrbSize, 0, n*sizeof(int)); \
+for (i=SpineTL->tgtcell; i<SpineTL->tgtend; i++) { \
+CurrOrbSize[tv->currorbit[CurrCand->lab[i]]]++; \
+} }
+
+#define EXITFROMSTAGE0REFINE { PRINT_LINE_PLUS(tv->tolevel) \
+if (tv->options->verbosity >= 2) fprintf(outfile, "-=="); \
+CurrCand->indnum--; \
+RemoveFromLevel(tv->tolevel, tv->treedepth, tv->strategy, FALSE); \
+tv->compstage = 1; \
+TempOrbits = NULL; \
+trieroot = trie_new(n, tv); \
+trieref = trieroot; \
+tv->nextlevel = tv->maxtreelevel = tv->fromlevel; \
+ti->thereisnextlevel = TRUE; \
+ti->exitfromref = TRUE; \
+return 0; }
+
+#define EXITFROMSTAGE0EXPATH2 { PRINT_LINE_PLUS(tv->tolevel) \
+if (tv->options->verbosity >= 2) fprintf(outfile, "=-="); \
+tv->compstage = 1; \
+TempOrbits = NULL; \
+trieroot = trie_new(n, tv); \
+trieref = trieroot; \
+tv->nextlevel = tv->maxtreelevel = tv->tolevel; \
+ti->thereisnextlevel = TRUE; \
+ti->exitfromref = FALSE; \
+return 0; }
+
+#define EXITFROMSTAGE0EXPATH1 { PRINT_RETURN PRINT_LINE_PLUS(tv->tolevel) \
+if (tv->options->verbosity >= 2) fprintf(outfile, "==-"); \
+if (SpineTL->liststart) { \
+AuxCand = SpineTL->liststart; \
+SpineTL->liststart = NewCandidate(n, &GarbList, TRUE); \
+CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL); \
+SpineTL->liststart->next = AuxCand; \
+} \
+else { \
+SpineTL->liststart = NewCandidate(n, &GarbList, TRUE); \
+SpineTL->listend = SpineTL->liststart; \
+SpineTL->liststart->next = NULL; \
+CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL); \
+} \
+tv->compstage = 1; \
+TempOrbits = NULL; \
+trieroot = trie_new(n, tv); \
+trieref = trieroot; \
+tv->nextlevel = tv->maxtreelevel = tv->tolevel; \
+ti->thereisnextlevel = TRUE; \
+ti->exitfromref = FALSE; \
+return 0; }
+
+#define UPDATE_LINELGTH { if (tv->options->verbosity >= 2) { \
+if (tv->tolevel < 12) { \
+tv->linelgth = (tv->digits+1)*tv->tolevel+16; \
+} \
+else { \
+tv->linelgth = (tv->digits+1)*10+20; \
+} \
+} }
+
+#define PRINT_LINE { if ((tv->options->verbosity >= 1) && (tv->strategy == 0)) { \
+if (tv->options->verbosity >= 2) { LINE(tv->linelgth, "-"); \
+NEXTLINE} \
+} \
+}
+
+#define PRINT_LINE_PLUS(Lev) { if ((tv->options->verbosity >= 1) && (tv->strategy == 0)) { \
+if (tv->options->verbosity >= 2) { LINE(16+tv->digits+1, "-");} \
+fprintf(outfile, " Level %d: %d cell%s; %d singleton%s; target cell: %d; %d orbit%s; %lu node%s (%lu kept); %d update%s;", \
+Lev, SS(Spine[Lev].part->cells, "", "s"), SS((Spine[Lev].part->cells == n) ? n : Spine[Lev].singend, "", "s"), Spine[Lev].tgtsize, SS(tv->stats->numorbits, "", "s"), \
+SS(Spine[Lev].levelcounter, "", "s"), Spine[Lev].keptcounter, SS(Spine[Lev].updates, "", "s")); \
+if (Lev <= tv->group_level) fprintf(outfile, " group_level: %d", tv->group_level); \
+NEXTLINE \
+} \
+}
+
+#define PRINT_CANDIDATE(Cand, Lev) { \
+for (tmp = Cand->name, cu = 0; tmp > 0; tmp /= 10, ++cu) {} \
+for (tmp = Lev, cu1 = 0; tmp > 0; tmp /= 10, ++cu1) {} \
+cu = 14-cu-cu1; \
+LINE(cu, "-") \
+fprintf(outfile, " %d, %d) ", Lev % 10000, Cand->name % 10000000); \
+if (Lev < 12) { \
+PRINTCAND(Cand, Lev) \
+} \
+else { \
+PRINTCANDBIG(Cand, Lev) \
+} \
+PRINTCHAR("| ") \
+fprintf(outfile, "{%x, %x} ", Cand->code, Cand->singcode); \
+}
+
+#define PRINT_CANDIDATEPLUS(PrevCand, Cand, Lev) { \
+for (tmp = Cand->name, cu = 0; tmp > 0; tmp /= 10, ++cu) {} \
+for (tmp = Lev, cu1 = 0; tmp > 0; tmp /= 10, ++cu1) {} \
+cu = 14-cu-cu1; \
+LINE(cu, "-") \
+fprintf(outfile, " %d, %d, %d) ", Lev % 10000, Cand->name % 10000000, PrevCand->name); \
+if (Lev < 12) { \
+PRINTCAND(Cand, Lev) \
+} \
+else { \
+PRINTCANDBIG(Cand, Lev) \
+} \
+PRINTCHAR("| ") \
+fprintf(outfile, "{%x, %x} ", Cand->code, Cand->singcode); \
+}
+
+#define PRINT_EXPPATHSTEP(Cand, Boo) { \
+if (tv->options->verbosity >= 2) { \
+if ((tv->tolevel_tl-tv->tolevel < 6) || !has_nexttcell) { \
+fprintf(outfile, "%d ", tv->indiv_vtx+labelorg); \
+if (Boo) { \
+if (tv->options->verbosity >= 2) fprintf(outfile, "{%d:%x} ", tv->tcellexpath, Cand->code); \
+} \
+else fprintf(outfile, "{interr.(%d)} ", NextPart->cells); \
+if ((!has_nexttcell) && (tv->compstage == 0)) { \
+fprintf(outfile, "(%d) ", tv->tolevel_tl); \
+} \
+} \
+else { \
+if (tv->tolevel_tl-tv->tolevel == 6) { \
+fprintf(outfile, "... "); \
+} \
+} \
+} \
+}
+
+#define PRINT_RETURN { if (tv->options->verbosity >= 2) { \
+fprintf(outfile, "\n"); \
+} }
+
+#define PRINT_FROM_VERB(Verb,Lev) { if (tv->options->verbosity >= Verb) { \
+fprintf(outfile, "FROM: "); \
+if (Lev < 12) { \
+PRINTCAND(CurrCand, tv->fromlevel) \
+} \
+else { \
+PRINTCANDBIG(CurrCand, tv->fromlevel) \
+} \
+fprintf(outfile, " do_it: %d, indnum: %d, stnode->index: %d tcell @ %d: %d", CurrCand->do_it, CurrCand->indnum, CurrCand->stnode->index,tv->tcellevel,Spine[tv->tcellevel].tgtcell); \
+PRINT_RETURN \
+} }
+
+#define PRINT_NOTMIN_VERB(Verb) { if (tv->options->verbosity >= Verb) { \
+fprintf(outfile, " is NOT minimal in orbits (1, %d) [%d]; ", gom_level, CurrCand->lab[Spine[gom_level+1].tgtpos]+labelorg); \
+fprintf(outfile, "at lev %d, orb[%d] = %d.\n", gom_level+1, CurrCand->lab[Spine[gom_level+1].tgtpos]+labelorg, tv->currorbit[CurrCand->lab[Spine[gom_level+1].tgtpos]]+labelorg); } }
+
+#define PRINT_SKIPPED_VERB(Verb) { if (tv->options->verbosity >= Verb) \
+fprintf(outfile, " skipped (0) (orbit[%d] = %d)\n", \
+NextCand->vertex+labelorg, tv->currorbit[NextCand->vertex]+labelorg); }
+
+#define PRINT_REFINE_VERB(Verb,where) { if (tv->options->verbosity >= Verb) \
+fprintf(outfile, " REFINE(%c) (orbit[%d] = %d)\n",where, NextCand->vertex+labelorg, tv->currorbit[NextCand->vertex]+labelorg); }
+
+#define PRINT_INDIV_VERB(Verb,Lev) { if (tv->options->verbosity >= Verb) { \
+if (Lev < 12) { \
+PRINTCAND(CurrCand, tv->fromlevel) \
+} \
+else { \
+PRINTCANDBIG(CurrCand, tv->fromlevel) \
+} \
+fprintf(outfile, "| "); \
+fprintf(outfile, tv->digstring, NextCand->vertex+labelorg); \
+} }
+
+#define PRINT_INDEX(V,Verb,where) if (tv->options->verbosity >= Verb) \
+fprintf(outfile,"Set index @ %d: Name %d, index %d\n",where,V->name,V->index);
+
+#define SPECIALGENERATORS { if (tv->options->generators) addpermutation(ring, AUTPERM, n); \
+tv->stats->numgenerators++; \
+tv->specialgens++; \
+if (tv->options->writeautoms) { \
+fprintf(outfile, "Gen #%d: ", tv->stats->numgenerators); \
+writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n); \
+} \
+if (tv->options->userautomproc) { \
+(*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n); \
+} }
+
+#define UPDATEMIN(A, B) if (B < A) A = B;
+
+#define PAIRORBJOIN(A, V) { if (A != V) { \
+PrmPairs[tv->permInd].arg = A; \
+PrmPairs[tv->permInd].val = V; \
+tv->permInd++; \
+orbjoin_sp_pair(tv->orbits, OrbList, n, A, V, &tv->stats->numorbits); \
+MakeTree(A, V, sg, n, tv, FALSE); \
+} }
+
+#define SETPAIRS(A, V) { if (A != V) { \
+PrmPairs[tv->permInd].arg = A; \
+PrmPairs[tv->permInd].val = V; \
+tv->permInd++; \
+} }
+
+#define SETPAIRSAUT(A, V) { if ((A != V) && (AUTPERM[A] != V)) { \
+AUTPERM[A] = V; \
+PrmPairs[tv->permInd].arg = A; \
+PrmPairs[tv->permInd].val = V; \
+tv->permInd++; \
+} }
+
+#define SETPAIRSAUTANDTREE(arg, val) { if (tv->build_autom) { SETPAIRSAUT(arg, val) } \
+if (arg != val) orbjoin_sp_pair(tv->orbits, OrbList, n, arg, val, &tv->stats->numorbits); \
+MakeTree(arg, val, sg_orig, n, tv, FALSE); }
+
+#define PRINTF2(A, B) if (tv->options->verbosity > 3) printf(A, B)
+#define PRINTF2_2(A, B, C) if (tv->options->verbosity > 3) printf(A, B, C)
+#define PRINTF2_3(A, B, C, D) if (tv->options->verbosity > 3) printf(A, B, C, D)
+#define PRINTF2_4(A, B, C, D, E) if (tv->options->verbosity > 3) printf(A, B, C, D, E)
+
+#define VERB_PRINT(V,Verb,R) if (tv->options->verbosity >= Verb) { \
+fprintf(outfile,"\033[0;32m%s\033[0m ",V); \
+if (R) fprintf(outfile,"\n"); }
+
+/* data decls. for CPUTIME */
+#ifdef CPUDEFS
+CPUDEFS
+#endif
+
+#if !MAXN
+DYNALLSTAT(int, AUTPERM, AUTPERM_sz);
+DYNALLSTAT(int, BreakSteps, BreakSteps_sz);
+DYNALLSTAT(int, CStack, CStack_sz);
+DYNALLSTAT(int, CurrOrbSize, CurrOrbSize_sz);
+DYNALLSTAT(int, CurrRefCells, CurrRefCells_sz);
+DYNALLSTAT(boolean, Diff, Diff_sz);
+DYNALLSTAT(boolean, Factorials, Factorials_sz);
+DYNALLSTAT(int, fix, fix_sz);
+DYNALLSTAT(int, IDENTITY_PERM, IDENTITY_PERM_sz);
+DYNALLSTAT(int, Markers, Markers_sz);
+DYNALLSTAT(int, TreeMarkers, TreeMarkers_sz);
+DYNALLSTAT(int, AutMarkers, AutMarkers_sz);
+DYNALLSTAT(int, MarkHitVtx, MarkHitVtx_sz);
+DYNALLSTAT(int, MultRefCells, MultRefCells_sz);
+DYNALLSTAT(int, NghCounts, NghCounts_sz);
+DYNALLSTAT(int, OrbSize, OrbSize_sz);
+DYNALLSTAT(int, OrbList, OrbList_sz);
+DYNALLSTAT(pair, PrmPairs, PrmPairs_sz);
+DYNALLSTAT(int, TempOrbList, TempOrbList_sz);
+DYNALLSTAT(int, RefCells, RefCells_sz);
+DYNALLSTAT(searchtrie*, RefPath, RefPath_sz);
+DYNALLSTAT(int, Singletons, Singletons_sz);
+DYNALLSTAT(int, SplCls, SplCls_sz);
+DYNALLSTAT(int, SplCnt, SplCnt_sz);
+DYNALLSTAT(int, SplPos, SplPos_sz);
+DYNALLSTAT(int, StackMarkers, StackMarkers_sz);
+DYNALLSTAT(int, TheTrace, TheTrace_sz);
+DYNALLSTAT(int, TheTraceCC, TheTraceCC_sz);
+DYNALLSTAT(int, TheTraceSplNum, TheTraceSplNum_sz);
+DYNALLSTAT(int, TheTraceSteps, TheTraceSteps_sz);
+DYNALLSTAT(int, TEMPLAB, TEMPLAB_sz);
+DYNALLSTAT(int, TEMPINVLAB, TEMPINVLAB_sz);
+DYNALLSTAT(int, WeightsSeq, WeightsSeq_sz);
+DYNALLSTAT(int, WorkArray, WorkArray_sz);
+DYNALLSTAT(int, WorkArray0, WorkArray0_sz);
+DYNALLSTAT(int, WorkArray1, WorkArray1_sz);
+DYNALLSTAT(int, WorkArray2, WorkArray2_sz);
+DYNALLSTAT(int, WorkArray3, WorkArray3_sz);
+DYNALLSTAT(int, WorkArray4, WorkArray4_sz);
+DYNALLSTAT(int, WorkArray5, WorkArray5_sz);
+DYNALLSTAT(int, WorkArray6, WorkArray6_sz);
+DYNALLSTAT(int, WorkArray7, WorkArray7_sz);
+DYNALLSTAT(int, Neighbs1, Neighbs1_sz);
+DYNALLSTAT(int, Neighbs2, Neighbs2_sz);
+DYNALLSTAT(int, TreeStack, TreeStack_sz);
+DYNALLSTAT(TracesSpine, Spine, Spine_sz);
+DYNALLSTAT(trie*, TrieArray, TrieArray_sz);
+DYNALLSTAT(grph_strct, TheGraph, TheGraph_sz);
+DYNALLSTAT(ExpPathInfo, EPCodes, EPCodes_sz);
+DYNALLSTAT(int, CyclesPart, CyclesPart_sz);
+DYNALLSTAT(int, CyclesLength, CyclesLength_sz);
+#else
+static TLS_ATTR int CStack[MAXN];
+static TLS_ATTR int AUTPERM[MAXN];
+static TLS_ATTR int BreakSteps[MAXN];
+static TLS_ATTR int CurrOrbSize[MAXN];
+static TLS_ATTR int CurrRefCells[MAXN];
+static TLS_ATTR boolean Diff[MAXN];
+static TLS_ATTR boolean Factorials[MAXN];
+static TLS_ATTR int fix[MAXN];
+static TLS_ATTR int IDENTITY_PERM[MAXN];
+static TLS_ATTR int Markers[MAXN];
+static TLS_ATTR int TreeMarkers[MAXN];
+static TLS_ATTR int AutMarkers[MAXN];
+static TLS_ATTR int MarkHitVtx[MAXN];
+static TLS_ATTR int MultRefCells[MAXN];
+static TLS_ATTR int NghCounts[MAXN];
+static TLS_ATTR int OrbSize[MAXN];
+static TLS_ATTR int OrbList[MAXN];
+static TLS_ATTR pair PrmPairs[MAXN];
+static TLS_ATTR int TempOrbList[MAXN];
+static TLS_ATTR int RefCells[MAXN];
+static TLS_ATTR searchtrie* RefPath[MAXN];
+static TLS_ATTR int Singletons[MAXN];
+static TLS_ATTR int SplCls[MAXN];
+static TLS_ATTR int SplCnt[MAXN];
+static TLS_ATTR int SplPos[MAXN];
+static TLS_ATTR int StackMarkers[MAXN];
+static TLS_ATTR int TheTrace[MAXN];
+static TLS_ATTR int TheTraceCC[MAXN];
+static TLS_ATTR int TheTraceSplNum[MAXN];
+static TLS_ATTR int TheTraceSteps[MAXN];
+static TLS_ATTR int TEMPLAB[MAXN];
+static TLS_ATTR int TEMPINVLAB[MAXN];
+static TLS_ATTR int WeightsSeq[MAXN];
+static TLS_ATTR int WorkArray[MAXN];
+static TLS_ATTR int WorkArray0[MAXN];
+static TLS_ATTR int WorkArray1[MAXN];
+static TLS_ATTR int WorkArray2[MAXN];
+static TLS_ATTR int WorkArray3[MAXN];
+static TLS_ATTR int WorkArray4[MAXN];
+static TLS_ATTR int WorkArray5[MAXN];
+static TLS_ATTR int WorkArray6[MAXN];
+static TLS_ATTR int WorkArray7[MAXN];
+static TLS_ATTR int TreeStack[MAXN];
+static TLS_ATTR TracesSpine Spine[MAXN];
+static TLS_ATTR trie* TrieArray[MAXN];
+static TLS_ATTR grph_strct TheGraph[MAXN];
+static TLS_ATTR int Neighbs1[MAXN];
+static TLS_ATTR int Neighbs2[MAXN];
+static TLS_ATTR ExpPathInfo EPCodes[MAXN];
+static TLS_ATTR int CyclesPart[MAXN];
+static TLS_ATTR int CyclesLength[MAXN];
+#endif
+
+#define PERMSTACK WorkArray1
+#define CYCLES WorkArray1
+#define HitCls WorkArray2
+#define CYCOLR WorkArray2
+#define HitVtx WorkArray3
+#define CYLGTH WorkArray3
+#define CYMULT WorkArray4
+#define HitCount WorkArray5
+#define ElmHitCll WorkArray5
+#define CYCPOS WorkArray5
+#define CYCHIT TempOrbList
+#define LGHATTR RefCells
+#define CYCREP MultRefCells
+#define TempOrbSize TEMPLAB
+#define AutomCount TEMPINVLAB
+#define CanonIndices MarkHitVtx
+#define NSFCells NghCounts
+#define TreeNodes AutMarkers
+#define CellMarkers1 WorkArray6
+#define CellMarkers2 WorkArray7
+#define SingNonSing Singletons
+
+static TLS_ATTR FILE *outfile;
+
+/* Brendan's SCHREIER */
+static TLS_ATTR schreier *gpB; /* This will point to the Schreier structure */
+static TLS_ATTR permnode *gensB; /* This will point to the stored generators */
+
+static TLS_ATTR Candidate *GarbList, *SpOrd, *SpCyc, *SpSwp;
+static TLS_ATTR Partition *SpPart1, *SpPart2;
+static TLS_ATTR TracesSpine *SpineTL, *SpineFL, *SpineTL_tl;
+static TLS_ATTR trie *trieroot, *trieref;
+static TLS_ATTR int *TempOrbits = NULL;
+static TLS_ATTR sparsegraph redgraph;
+
+
+void
+Traces(sparsegraph *g_arg, int *lab, int *ptn,
+ int *orbits_arg, TracesOptions *options_arg, TracesStats *stats_arg,
+ sparsegraph *canong_arg) {
+ int i, j;
+ int tmp;
+ int deg, vtx1, vtx2, *ngh1, *ngh2, *wgh1, *wgh2, ord;
+ size_t j1;
+
+ trielist *STStart, *STAux;
+ searchtrie *TrieNode;
+ int retval;
+ Partition *CurrPart, *NextPart;
+ Candidate *CurrCand, *NextCand, *BestCand, *AuxCand;
+
+ const int n = g_arg->nv;
+ const int m = SETWORDSNEEDED(n);
+
+ if (g_arg->nv > (NAUTY_INFINITY-2))
+ {
+ fprintf(ERRFILE, "Traces: need n <= %d, but n=%d\n\n",
+ NAUTY_INFINITY-2, g_arg->nv);
+ return;
+ }
+
+ Allocate_Traces_Structures(n);
+
+ struct TracesVars *tv = malloc(sizeof(struct TracesVars));
+ if (tv == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ struct TracesInfo *ti = malloc(sizeof(struct TracesInfo));
+ if (ti == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+
+ trieroot = NULL;
+ NextCand = GarbList = NULL;
+ DYNFREE(g_arg->w,g_arg->wlen); /* to be removed in presence of weightd edges */
+
+ Initialize_Traces_Variables(tv, options_arg, stats_arg, orbits_arg, g_arg, canong_arg, n);
+
+ outfile = (tv->options->outfile == NULL ? stdout : tv->options->outfile);
+
+ SpOrd = SpCyc = SpSwp = NULL;
+ SpPart1 = SpPart2 = NULL;
+
+ if (tv->options->verbosity >= 2) {
+ for (i = n, tv->digits = 0; i > 0; i /= 10, ++tv->digits) {}
+ snprintf(tv->digstring, 25, "%s%dd ", "%", tv->digits);
+ }
+
+ /* Initialize group and statistics */
+ Initialize_Traces_Statistics(stats_arg,n);
+
+ if (tv->options->verbosity >= 2) {
+ Initialize_Traces_Time_Variables(tv);
+ }
+
+ /* Initialize lab and ptn when in the unit partition case */
+ if (tv->options->defaultptn) {
+ for (i = 0; i < n; i++) {
+ IDENTITY_PERM[i] = i;
+ ptn[i] = NAUTY_INFINITY;
+ }
+ ptn[n-1] = 0;
+ memcpy(lab, IDENTITY_PERM, n*sizeof(int));
+ } else {
+ for (i = 0; i < n; i++) {
+ IDENTITY_PERM[i] = i;
+ }
+ }
+
+ memcpy(orbits_arg, IDENTITY_PERM, n*sizeof(int));
+
+ if (tv->options->generators) {
+ tv->stats->numorbits = given_gens(g_arg, *tv->options->generators,
+ orbits_arg, tv->options->digraph);
+ newgroup(&gpB, NULL, n);
+ gensB = *tv->options->generators;
+ expandschreier(gpB, &gensB, n);
+ ti->thegrouphaschanged = TRUE;
+ ti->identitygroup = FALSE;
+ memcpy(OrbList, gpB->orbits, n*sizeof(int));
+ }
+ else {
+ newgroup(&gpB, &gensB, n);
+ memcpy(OrbList, IDENTITY_PERM, n*sizeof(int));
+ tv->stats->numorbits = n;
+ ti->thegrouphaschanged = FALSE;
+ ti->identitygroup = TRUE;
+ }
+
+ copy_sg_structure(&redgraph, g_arg);
+
+ tv->graph = &redgraph;
+ if (g_arg->w) memcpy(tv->graph->w, g_arg->w, tv->graph->wlen*sizeof(int));
+ if (g_arg->e) memcpy(tv->graph->e, g_arg->e, tv->graph->elen*sizeof(int));
+
+ for (i=0; i<n; i++) {
+ EPCodes[i].info = 0;
+ TheGraph[i].d = g_arg->d[i];
+ if (TheGraph[i].d > tv->maxdeg) {
+ tv->maxdeg = TheGraph[i].d;
+ }
+ if (TheGraph[i].d < tv->mindeg) {
+ tv->mindeg = TheGraph[i].d;
+ }
+ if (g_arg->e) {
+ TheGraph[i].e = tv->graph->e + g_arg->v[i];
+ }
+ else {
+ TheGraph[i].e = NULL;
+ }
+ if (g_arg->w) {
+ TheGraph[i].w = tv->graph->w + g_arg->v[i];
+ }
+ else {
+ TheGraph[i].w = NULL;
+ }
+ TheGraph[i].one = FALSE;
+ }
+
+ ord = 0;
+
+ /*----------- WEIGHTS --------------*/
+ if (tv->options->weighted) {
+ WeightCodes(n);
+ ord = trie_classify(n,tv);
+ }
+ /*----------------------------------*/
+
+ if ((tv->maxdeg == tv->mindeg) && (ord == 0)) ti->regular = TRUE; else ti->regular = FALSE;
+
+ tv->currorbit = gpB->orbits;
+
+ memcpy(AUTPERM, IDENTITY_PERM, n*sizeof(int));
+ tv->permInd = 0;
+
+ memset(fix, 0, n*sizeof(int));
+ memset(TheTraceCC, 0, n*sizeof(int));
+ memset(Factorials, 0, n*sizeof(int));
+ /* ran_init(1234); any long int as an argument */
+
+ /* The graph is sparse? */
+ if (g_arg->nde < n || g_arg->nde / n < n / (g_arg->nde / n)) {
+ ti->thegraphisparse = TRUE;
+ }
+ else {
+ ti->thegraphisparse = FALSE;
+ }
+
+ tv->preprocessed = 0;
+ ti->deg_one = FALSE;
+ ti->first_matching = FALSE;
+ retval = 0;
+
+ /* Initialize candidate, partition, cells, orbits */
+ Spine[0].part = NewPartition(n);
+ CurrPart = Spine[0].part;
+ memset(CurrPart->inv, 0, n*sizeof(int));
+
+ NextPart = NewPartition(n);
+ CurrCand = NewCandidate(n, &GarbList, TRUE);
+
+ CurrCand->singcode = 0;
+ TempOrbits = NULL;
+ STStart = NULL;
+
+ if (ti->regular) {
+ if (tv->options->defaultptn) {
+ memcpy(CurrCand->lab, IDENTITY_PERM, n*sizeof(int));
+ memcpy(CurrCand->invlab, IDENTITY_PERM, n*sizeof(int));
+ CurrPart->cells = 1;
+ CurrPart->cls[0] = n;
+ TheTrace[0] = 0;
+ }
+ else {
+ memcpy(CurrCand->lab, lab, n*sizeof(int));
+ CurrPart->cells = 0;
+ j = 0;
+ for (i = 0; i < n; i++) {
+ if (j) CurrPart->inv[i] = j;
+ CurrCand->invlab[CurrCand->lab[i]] = i;
+ if (!ptn[i]) {
+ CurrPart->cls[j] = i-j+1;
+ if (CurrPart->cls[j] == 1) {
+ CurrCand->singcode = MASHCOMM(CurrCand->singcode, CurrCand->lab[j]);
+ }
+ TheTrace[CurrPart->cells++] = j;
+ j = i+1;
+ }
+ }
+ }
+ } else {
+ if (tv->options->weighted) {
+ CurrPart->cells = traces_vertexclass_refine(n, lab, ptn,
+ CurrCand, CurrPart, WeightsSeq);
+ }
+ else {
+ CurrPart->cells = traces_vertexclass_refine (n, lab, ptn,
+ CurrCand, CurrPart, g_arg->d);
+ }
+ }
+
+ memset(NghCounts,0,n*sizeof(int));
+ if (tv->options->verbosity == 7) PrintPartition(CurrCand->lab,CurrPart->cls,n,labelorg,1323);
+
+ /* Check for deg 1 vertices */
+ ti->deg_one = Check_degree_one(g_arg, CurrCand, CurrPart, n);
+
+#if !MAXN
+ DYNALLOC1(int, Neighbs1, Neighbs1_sz, tv->maxdeg, "Traces");
+ DYNALLOC1(int, Neighbs2, Neighbs2_sz, tv->maxdeg, "Traces");
+#endif
+
+ if (ti->deg_one) {
+ tv->preprocessed = Preprocess(g_arg, &gensB, CurrCand, n, CurrPart, tv);
+ }
+
+ if (tv->preprocessed) {
+ memset(Diff,0,n*sizeof(boolean));
+ for (i=0; i<n; i++) {
+ if ((TheGraph[i].d > 1) && (tv->input_graph->d[i] != TheGraph[i].d))
+ Diff[i] = TRUE;
+ }
+ }
+
+ /* Initialization of Spine structure */
+ SpineFL = Spine;
+ SpineFL->tgtcell = SpineFL->tgtpos = 0;
+ SpineFL->tgtend = n;
+ SpineFL->tgtfrom = -1;
+ SpineFL->trcstart = 0;
+ SpineFL->trcend = CurrPart->active = CurrPart->cells;
+ SpineFL->ccstart = SpineFL->ccend = 0;
+ SpineFL->stpstart = SpineFL->stpend = 0;
+ SpineFL->singstart = SpineFL->singend = 0;
+ SpineFL->thetracexists = FALSE;
+ SpineFL->liststart = SpineFL->listend = CurrCand;
+ SpineFL->levelcounter = 1;
+ SpineFL->keptcounter = 1;
+ SpineFL->updates = 1;
+
+ /* Further initializations */
+ tv->maxtreelevel = 0;
+ tv->tolevel = 0;
+ tv->tcell = 0;
+ UPDATE_LINELGTH
+
+ /* First refinement */
+ if (tv->preprocessed < 2)
+ traces_refine(CurrCand, n, CurrPart, tv, ti, 0, FALSE);
+
+ CurrCand->name = 0;
+
+ if (CurrPart->cells == n) {
+ tv->stats->canupdates++;
+
+ /* CANONICAL FORM ? */
+ if (tv->options->getcanon) {
+ memcpy(lab, CurrCand->lab, n*sizeof(int));
+ if (canong_arg) memcpy(CurrPart->inv, CurrCand->invlab, n*sizeof(int));
+ if (tv->options->usercanonproc != NULL)
+ {
+ (*tv->options->usercanonproc)((graph*)g_arg, lab, (graph*)canong_arg, tv->stats->canupdates, CurrCand->code, m, n);
+ }
+ }
+ }
+ else {
+ STStart = searchtrie_new(n, tv);
+ CurrCand->stnode = tv->strielist->triearray;
+ NextCand = NewCandidate(n, &GarbList, TRUE);
+ SpineFL->listcounter = 1;
+ tv->tcellevel = 0;
+ ti->exitfromref = FALSE;
+ Spine[1].levelcounter = 0;
+ Spine[1].updates = 0;
+ Spine[1].tgtfrom = 0;
+
+ memset(WorkArray, 0, n*sizeof(int));
+
+ do {
+ tv->fromlevel = tv->tolevel;
+ SpineFL = Spine+tv->fromlevel;
+
+ if (CurrCand) {
+ switch (tv->compstage) {
+ case 0: retval = CompStage0(CurrPart, NextPart, CurrCand, NextCand, m, n, tv, ti);
+ break;
+ case 1:
+ if (!TempOrbits) {
+ memcpy(WorkArray1, tv->currorbit, n*sizeof(int));
+ TempOrbits = WorkArray1;
+ }
+ memset(TempOrbSize, 0, n*sizeof(int));
+ for (i=SpineTL->tgtcell; i<SpineTL->tgtend; i++) {
+ TempOrbSize[TempOrbits[CurrCand->lab[i]]]++;
+ }
+ retval = CompStage1(CurrPart, NextPart, CurrCand, NextCand, m, n, tv, ti);
+ break;
+ case 2:
+ retval = CompStage2(CurrPart, NextPart, CurrCand, NextCand, m, n, tv, ti);
+ break;
+ default:
+ break;
+ }
+ if (retval == NAUTY_ABORTED)
+ tv->stats->errstatus = NAUABORTED;
+ else if (retval == NAUTY_KILLED) {
+ tv->stats->errstatus = NAUKILLED;
+ return;
+ }
+ }
+ /* NEXT CANDIDATE */
+ if (ti->thereisnextlevel) {
+ if (tv->nextlevel != tv->fromlevel) {
+ UPDATE_LINELGTH
+ }
+ tv->tolevel = tv->nextlevel;
+ CurrCand = Spine[tv->nextlevel].liststart;
+ CurrPart = Spine[tv->nextlevel].part;
+ }
+ }
+ while (ti->thereisnextlevel);
+
+ if (!retval) {
+ if (tv->compstage) {
+ memset(CurrOrbSize, 0, n*sizeof(int));
+ for (i=0; i<n; i++) {
+ CurrOrbSize[TempOrbits[i]]++;
+ }
+ }
+
+ if (!tv->options->getcanon) {
+ if (tv->compstage) {
+ tv->maxtreelevel++;
+ TrieNode = Spine[tv->maxtreelevel].liststart->stnode;
+ if (TrieNode->father) {
+ TrieNode = TrieNode->father;
+ }
+ if (!ti->exitfromref) {
+ TrieNode->index = 0;
+ for (i=1; i<AutomCount[0]; i++) {
+ TrieNode->index += CurrOrbSize[AutomCount[i]];
+ PRINT_INDEX(TrieNode,4,30)
+ }
+ }
+ }
+ }
+
+ if (tv->maxtreelevel) PRINT_LINE_PLUS(tv->maxtreelevel);
+
+ AuxCand = Spine[tv->maxtreelevel].liststart;
+ while (!AuxCand->do_it) {
+ AuxCand = AuxCand->next;
+ }
+
+ /* CANONICAL FORM ? */
+ if (tv->options->getcanon) {
+ BestCand = AuxCand;
+ AuxCand = AuxCand->next;
+ while (AuxCand) {
+ if (AuxCand->do_it) {
+ if (comparelab_tr(g_arg, BestCand->lab, BestCand->invlab, AuxCand->lab, AuxCand->invlab, Spine[tv->maxtreelevel].part->cls, Spine[tv->maxtreelevel].part->inv) == 1) {
+ BestCand = AuxCand;
+ tv->stats->canupdates++;
+ if (tv->options->usercanonproc != NULL)
+ {
+ (*tv->options->usercanonproc)((graph*)g_arg, lab, (graph*)canong_arg, tv->stats->canupdates, CurrCand->code, m, n);
+ }
+ }
+ }
+ AuxCand = AuxCand->next;
+ }
+
+ grouporderplus(g_arg, BestCand, Spine[tv->maxtreelevel].part, &gensB, &(tv->stats->grpsize1), &(tv->stats->grpsize2), n, tv, ti);
+
+ if (tv->options->verbosity >= 2) {
+ LINE(32, "-")
+ NEXTLINE
+ fprintf(outfile, "Canonical:");
+ PRINTCAND(BestCand, tv->maxtreelevel)
+ PRINT_RETURN
+ }
+ memcpy(lab, BestCand->lab, n*sizeof(int));
+ if (canong_arg) memcpy(CurrPart->inv, BestCand->invlab, n*sizeof(int));
+ }
+ else {
+ grouporderplus(g_arg, AuxCand, Spine[tv->maxtreelevel].part, &gensB, &(tv->stats->grpsize1), &(tv->stats->grpsize2), n, tv, ti);
+ }
+
+ if (tv->options->verbosity >= 2) {
+ if (tv->linelgth < 40) {
+ tv->linelgth = 40;
+ }
+ LINE(32, "-")
+ NEXTLINE
+ }
+
+ }
+ }
+ tv->stats->treedepth = tv->treedepth;
+ if (Spine[tv->treedepth].part->code == -1) {
+ tv->stats->treedepth--;
+ }
+
+ if (tv->options->verbosity >= 2) {
+ fprintf(outfile, "group time: %.2f, %.2f, %.2f; total: %.2f; exp_paths time: %.2f; aut_check time: %.2f\n%lu refinement%s interrupted by trace comparison (%s); special cells: %d\n------", tv->schreier1, tv->schreier2, tv->schreier3, tv->schreier1+tv->schreier2+tv->schreier3,
+ tv->expaths, tv->autchk, SS(tv->stats->interrupted, "", "s"), (tv->options->strategy == 0 ? "breadth-first" : "depth-first"), tv->specialgens);
+ PRINT_RETURN
+ }
+ if (tv->options->verbosity >= 3) fprintf(outfile, "CPYCAND(0): %d, ID<-TMPORB(1): %d, LAB(2): %d, PART(3): %d, TEMP(4)->: %d, TEMP(5)<-: %d, CHKFORAUT(6): %d, ISAUT(7): %d, ContaTC: %d\n", tv->conta0, tv->conta1, tv->conta2, tv->conta3, tv->conta4, tv->conta5, tv->conta6, tv->conta7, tv->contatc);
+
+ if (tv->options->getcanon && canong_arg) {
+ canong_arg->nv = g_arg->nv;
+ canong_arg->nde = g_arg->nde;
+ SG_ALLOC(*canong_arg, g_arg->nv, g_arg->nde, "traces canong");
+ updatecan_tr(g_arg, canong_arg, lab, CurrPart->inv, 0);
+ }
+
+ if (tv->options->generators) {
+ deleteunmarked(&gensB);
+ *tv->options->generators = gensB;
+ freeschreier(&gpB, NULL);
+ }
+ else {
+ freeschreier(&gpB, &gensB);
+ schreier_freedyn();
+ }
+
+ while (STStart) {
+ STAux = STStart;
+ free(STAux->triearray);
+ STStart = STStart->next;
+ free(STAux);
+ }
+
+ tv->canlist = 0;
+ for (i=0; i<=tv->treedepth; i++) {
+ if (Spine[i].liststart) {
+ tv->canlist += FreeList(Spine[i].liststart, TRUE);
+ Spine[i].liststart = Spine[i].listend = NULL;
+ }
+ }
+
+ if (GarbList) {
+ tv->stats->peaknodes = FreeList(GarbList, FALSE);
+ }
+
+ FREECAND(NextCand)
+ FREECAND(SpOrd)
+ FREECAND(SpCyc)
+ FREECAND(SpSwp)
+ FREEPART(NextPart)
+ FREEPART(SpPart1)
+ FREEPART(SpPart2)
+
+ if (!tv->options->getcanon && trieroot) {
+ for (i=0; i<=tv->triepos; i++) {
+ free(TrieArray[i]);
+ }
+ }
+
+ for (i=0; i <= tv->treedepth; i++) {
+ FREEPART(Spine[i].part)
+ }
+
+ CurrCand = GarbList = NULL;
+ tv->stats->peaknodes += tv->canlist;
+
+ if (tv->graph != g_arg) {
+ SG_FREE(redgraph);
+ }
+ free(tv);
+ free(ti);
+ traces_freedyn();
+
+ return;
+}
+
+int traces_vertexclass_refine (int n, int *lab, int *ptn, Candidate *Cand, Partition *Part, int *RefArray) {
+
+ int i, j, k, aux, cells, end;
+
+ memcpy(Cand->lab, lab, n*sizeof(int));
+
+ cells = 0;
+ j = 0;
+
+ for (i = 0; i < n; i++) {
+ WorkArray1[i] = RefArray[Cand->lab[i]];
+ if (!ptn[i]) {
+ TheTrace[cells++] = j;
+
+ sort2ints(WorkArray1+j,Cand->lab+j,i-j+1);
+
+ aux = WorkArray1[j];
+ Part->cls[j] = 1;
+ Part->inv[j] = j;
+ Cand->invlab[Cand->lab[j]] = j;
+
+ if (i == j) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[j]);
+ j++;
+ } else {
+ end = i+1;
+ for (k=j+1; k<end; k++) {
+ if (WorkArray1[k] == aux) {
+ (Part->cls[j])++;
+ Part->inv[k] = j;
+ Cand->invlab[Cand->lab[k]] = k;
+ } else {
+ if (Part->cls[j] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[j]);
+ }
+
+ TheTrace[cells++] = k;
+ j = k;
+ aux = WorkArray1[j];
+ Part->cls[j] = 1;
+ Part->inv[j] = j;
+ Cand->invlab[Cand->lab[j]] = j;
+ }
+ }
+ j = end;
+ }
+ }
+ }
+ return cells;
+}
+
+int traces_refine(Candidate *Cand,
+ int n,
+ Partition *Part,
+ struct TracesVars* tv,
+ struct TracesInfo *ti,
+ int num_indv,
+ boolean make_code) {
+
+ int i, j, k, jk, sc, ind0, ind1, ind2, ind3, ind4, tlp1, labi;
+ int value, iend, newcell;
+ int HitClsInd, SplInd, SplCntInd, CStackInd, TraceInd, TraceCCInd, TraceStepsInd, SingInd;
+ int j1int, iend1int;
+ unsigned int longcode;
+ int newtrace = FALSE;
+ int Sparse = TRUE;
+ int *lab, *cls, *InvLab, *TracePos, *SplitCell, *LabCell, *TraceEnd, Traceccend, *Tracestpend;
+ int BigCell, BigCellPos, BigCellSize;
+ boolean TraceCell = FALSE;
+ int *nghb;
+ int conta;
+ const int variation = 0;
+ int currentweight, weightstart, weightend, currentcell, currentsize;
+
+ VERB_PRINT("RFLT",3,FALSE)
+
+ HitClsInd = 0;
+ if (tv->stackmark > (NAUTY_INFINITY-2)) {
+ memset(StackMarkers, 0, n*sizeof(int));
+ tv->stackmark = 0;
+ }
+ tv->stackmark++;
+ tv->augmented_cells = Part->cells;
+
+ SpineTL = Spine+tv->tolevel;
+ TraceEnd = &(SpineTL->trcend);
+ Traceccend = SpineTL->ccend;
+ Tracestpend = &(SpineTL->stpend);
+ TraceCCInd = SpineTL->ccstart;
+ TraceStepsInd = SpineTL->stpstart;
+
+ SingInd = SpineTL->singstart + num_indv;
+
+ lab = Cand->lab;
+ InvLab = Cand->invlab;
+ cls = Part->cls;
+
+ UPDATEMIN(Part->active, n-1);
+ memcpy(CStack+1, TheTrace+SpineTL->trcstart, (Part->active)*sizeof(int));
+ CStackInd = Part->active;
+ for (i = 1; i <= CStackInd; i++) {
+ StackMarkers[CStack[i]] = tv->stackmark;
+ }
+
+ longcode = Part->cells;
+ TraceInd = SpineTL->trcstart+Part->active;
+ if (!SpineTL->thetracexists) {
+ newtrace = TRUE;
+ }
+ conta=0;
+
+ while (CStackInd > 0) {
+
+ weightend = 0;
+
+ if (tv->mark > (NAUTY_INFINITY-2)) {
+ memset(Markers, 0, n*sizeof(int));
+ memset(MarkHitVtx, 0, n*sizeof(int));
+ tv->mark = 0;
+ }
+ tv->mark++;
+
+ if (Part->cells == n) break;
+
+ k = Select_from_CStack(cls, CStackInd);
+
+ currentcell = CStack[k];
+ currentsize = currentcell+cls[currentcell];
+ CStack[k] = CStack[CStackInd--];
+ StackMarkers[currentcell] = 0;
+
+ labi = lab[currentcell];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+
+ do {
+ ind0 = currentcell;
+ ind2 = currentsize;
+ weightstart = weightend;
+
+ if (tv->options->weighted) {
+ currentweight = (TheGraph[labi].w)[weightstart];
+ while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
+ weightend++;
+ }
+ } else {
+ weightend = TheGraph[labi].d;
+ }
+
+ if (!newtrace) {
+ TraceCell = ((ind0 == TheTraceCC[TraceCCInd]) && (TraceCCInd < Traceccend));
+ }
+
+ /* Analysis of occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is built */
+ if (cls[ind0] == 1) { /* SINGLETON CURRENT CELL CASE */
+
+ /* NEIGHCOUNT_SING_MULT */
+ HitClsInd = 0;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ ElmHitCll[value] = value;
+ }
+ HitVtx[ElmHitCll[value]++] = k;
+ } else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* end NEIGHCOUNT_SING_MULT */
+
+ tv->mark++;
+ FIND_SPLIT_CELLS;
+
+ /* SINGLETON CC CASE */
+ if (SplInd) {
+ if (newtrace) {
+ TheTraceCC[TraceCCInd] = ind0;
+ }
+ if (!TraceCell) {
+ TheTraceCC[TraceCCInd] = ind0;
+ newtrace = TRUE;
+ }
+
+ TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd, &Traceccend)
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) {
+ ind1 = SplCls[j];
+ i = ind1+cls[ind1]-ElmHitCll[ind1];
+ TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+
+ for (j = 0; j < SplInd; j++) {
+ /* REARRANGE_CELLS */
+ ind1 = SplCls[j];
+ cls[ind1] = cls[ind1]-ElmHitCll[ind1];
+ newcell = ind1+cls[ind1];
+ cls[newcell] = ElmHitCll[ind1];
+ Part->cells++;
+ if (StackMarkers[ind1] != tv->stackmark) {
+ if (cls[newcell] < cls[ind1]) {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ else {
+ CStack[++CStackInd] = ind1;
+ StackMarkers[ind1] = tv->stackmark;
+ }
+ }
+ else {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ SplitCell = HitVtx+ind1;
+ ind3 = cls[newcell];
+ LabCell = lab+newcell;
+ for (jk = 0; jk < ind3; jk++) {
+ k = SplitCell[jk];
+ i = LabCell[jk];
+ Part->inv[newcell+jk] = newcell;
+ lab[InvLab[k]] = i;
+ InvLab[i] = InvLab[k];
+ LabCell[jk] = k;
+ InvLab[k] = newcell+jk;
+ }
+ /* END REARRANGE_CELLS */
+
+ if (cls[ind1] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[ind1]);
+ if (newtrace) Singletons[SingInd] = ind1;
+ SingInd++;
+ }
+ if (cls[newcell] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[newcell]);
+ if (newtrace) Singletons[SingInd] = newcell;
+ SingInd++;
+ }
+ }
+ }
+ else {
+ if ((!newtrace) && TraceCell) {
+ if (!tv->options->weighted) return 0;
+ }
+ }
+ }
+ else {
+ if (ti->thegraphisparse) {
+
+ /* NEIGHCOUNT_SPARSE_MULT */
+ HitClsInd = 0;
+ if (cls[ind0] != n) {
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j = weightstart; j < weightend; j++) {
+ k = nghb[j];
+ if (MarkHitVtx[k] == tv->mark) {
+ NghCounts[k]++;
+ }
+ else {
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ MarkHitVtx[k] = tv->mark;
+ NghCounts[k] = 1;
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ HitVtx[value] = k;
+ ElmHitCll[value] = 1;
+ }
+ else {
+ HitVtx[value+ElmHitCll[value]++] = k;
+ }
+ }
+ else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* End NEIGHCOUNT_SPARSE_MULT */
+
+ tv->mark++;
+
+ SplInd = 0;
+ SplCls[0] = n;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
+ SplCls[SplInd++] = ind1;
+ }
+ else {
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+ }
+
+ /* SPARSE CASE */
+ if (SplInd) {
+ if (newtrace) {
+ TheTraceCC[TraceCCInd] = ind0;
+ }
+ if (!TraceCell) {
+ TheTraceCC[TraceCCInd] = ind0;
+ newtrace = TRUE;
+ }
+ TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+n, &Traceccend)
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (sc = 0; sc < SplInd; sc++) { /* For each cell C to be split */
+ ind0 = SplCls[sc];
+ ind1 = ind0 + cls[ind0];
+ SplCntInd = 0;
+ if (ElmHitCll[ind0] < cls[ind0]) {
+ SplCnt[SplCntInd++] = 0;
+ SplPos[0] = cls[ind0] - ElmHitCll[ind0];
+ }
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = NghCounts[HitVtx[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ if (SplCntInd) {
+ TRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+n, Tracestpend)
+ }
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt,SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+ /* Permute elements of the cell C */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = HitVtx[i];
+ j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
+ k = InvLab[value]; /* where HitVtx[i] is in lab */
+ lab[k] = lab[j];
+ lab[j] = value;
+ InvLab[value] = j;
+ InvLab[lab[k]] = k;
+ NghCounts[value] = 0;
+ }
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind1 - ElmHitCll[ind0];
+ i = newcell;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
+ if (cls[i] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
+ if (newtrace) Singletons[SingInd] = i;
+ SingInd++;
+ }
+ }
+
+ }
+ }
+ else {
+ if ((!newtrace) && TraceCell) {
+ return 0;
+ }
+ }
+
+ }
+ else {
+ if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
+ Sparse = FALSE;
+ }
+ else {
+ Sparse = TRUE;
+ }
+ Sparse = TRUE;
+ if (Sparse) {
+ /* Counting occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is also built */
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ HitCls[0] = 0;
+ HitClsInd = 1;
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_SPARSE_MULT */
+ HitClsInd = 0;
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ value = Part->inv[InvLab[k]];
+ if (Markers[value] != tv->mark) {
+ if (cls[value] > 1) HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ }
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
+
+ }
+
+ tv->mark++;
+
+
+ SplInd = 0;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+
+ /* DENSE-SPARSE CASE */
+ if (SplInd) {
+ if (newtrace) {
+ TheTraceCC[TraceCCInd] = ind0;
+ }
+ if (!TraceCell) {
+ TheTraceCC[TraceCCInd] = ind0;
+ newtrace = TRUE;
+ }
+ TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+2*n, &Traceccend)
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) { /* For each cell C to be split */
+ ind0 = SplCls[j];
+ ind1 = ind0+cls[ind0];
+ SplCntInd = 0;
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ for (i = ind0; i < ind1; i++) {
+ value = NghCounts[lab[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ if (SplCntInd) {
+ TRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+2*n, Tracestpend)
+ }
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
+ if (cls[i] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
+ if (newtrace) Singletons[SingInd] = i;
+ SingInd++;
+ }
+ }
+
+ }
+ }
+ else {
+ if ((!newtrace) && TraceCell) {
+ return 0;
+ }
+ }
+
+ }
+ else {
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_DENSE_MULT */
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_DENSE_MULT */
+
+ }
+ SplInd = 0;
+ ind4 = 0;
+ while (ind4 < n) { /* For each cell C with size(C) > 1 */
+ ind1 = ind4+cls[ind4];
+ if (cls[ind4] > 1) {
+
+
+ /* Determine whether C must be split */
+ SplCntInd = 0;
+ value = NghCounts[lab[ind4]];
+ for (i = ind4+1; i < ind1; i++) {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplInd++;
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = i-ind4;
+ do {
+ value = NghCounts[lab[i++]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ while(i != ind1);
+ break;
+ }
+ }
+ tv->mark++;
+
+ if (SplInd && !TraceCell) newtrace = TRUE;
+
+ if (SplCntInd) {
+ TRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+3*n, Tracestpend)
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind4;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+
+ if ((StackMarkers[ind4] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+ }
+ if ((StackMarkers[ind4] != tv->stackmark) && (BigCell != ind4)) {
+ CStack[BigCellPos] = ind4;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind4] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind4;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind4;
+ i = ind4;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind4; i < ind1; i+=cls[i]) {
+ if (cls[i] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
+ if (newtrace) Singletons[SingInd] = i;
+ SingInd++;
+ }
+ }
+ }
+ }
+ ind4 = ind1;
+ }
+
+ /* DENSE-DENSE CASE */
+ if (SplInd) {
+ if (!TraceCell) {
+ newtrace = TRUE;
+ }
+ TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+3*n, &Traceccend)
+ if (newtrace) {
+ TheTraceCC[TraceCCInd-1] = ind0;
+ }
+ }
+ else {
+ if ((!newtrace) && TraceCell) {
+ return 0;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ while (weightend < iend1int);
+ } /* end while (CStackInd > 0) */
+
+ tv->augmented_cells = Part->cells - tv->augmented_cells;
+
+ if (make_code) {
+ for (i=SpineTL->trcstart; i < TraceInd; i++) {
+ ind0 = TheTrace[i];
+ longcode = MASHNONCOMM(longcode, Part->inv[ind0]);
+ labi = lab[ind0];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+ for (j1int = 0; j1int < iend1int; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ longcode = MASHCOMM(longcode, value);
+ }
+ }
+ }
+ Part->code = Cand->code = CLEANUP(longcode);
+ tlp1 = tv->tolevel+1;
+ if (newtrace) {
+ if ((tlp1 < n) && (tlp1 > tv->treedepth)) {
+ tv->treedepth = tlp1;
+ if (tv->strategy) {
+ Spine[tlp1].part = NewPartition(n);
+ }
+ else {
+ NewPartSpine(tlp1,n);
+ }
+ Spine[tlp1].liststart = Spine[tlp1].listend = NULL;
+ Spine[tlp1].listcounter = 0;
+ }
+ *TraceEnd = TraceInd;
+ SpineTL->ccend = TraceCCInd;
+ SpineTL->singend = SingInd;
+ *Tracestpend = TraceStepsInd;
+
+ SpineTL->thetracexists = TRUE;
+ if (tlp1 < n) {
+ Spine[tlp1].ccstart = TraceCCInd;
+ Spine[tlp1].singstart = Spine[tlp1].singend = SingInd;
+ Spine[tlp1].stpstart = TraceStepsInd;
+ Spine[tlp1].thetracexists = FALSE;
+ Spine[tlp1].part->code = -1;
+ }
+ return 2;
+ }
+ else {
+ if (TraceInd < *TraceEnd) {
+ return 0;
+ }
+ if (Cand->code > SpineTL->part->code) {
+ return 2;
+ }
+ else {
+ if (Cand->code < SpineTL->part->code) {
+ return 0;
+ }
+ }
+ return 1;
+ }
+}
+
+void traces_refine_notrace(Candidate *Cand,
+ int n,
+ Partition *Part,
+ struct TracesVars* tv,
+ struct TracesInfo *ti) {
+ int i, j, k, jk, sc, ind0, ind1, ind2, ind3, labi, auxcells;
+ int value, iend, newcell;
+ int HitClsInd, SplInd, SplCntInd, CStackInd;
+ int iend1int, j1int;
+ unsigned int longcode;
+ int Split = 0;
+ int Sparse = TRUE;
+ int *lab, *cls, *InvLab, *SplitCell, *LabCell;
+ int BigCell, BigCellPos, BigCellSize;
+ int *nghb;
+ const int variation = 1;
+ int currentweight, weightstart, weightend, currentcell, currentsize;
+
+ if (tv->stackmark > (NAUTY_INFINITY-2)) {
+ memset(StackMarkers, 0, n*sizeof(int));
+ tv->stackmark = 0;
+ }
+ tv->stackmark++;
+
+ tv->augmented_cells = Part->cells;
+
+ lab = Cand->lab;
+ InvLab = Cand->invlab;
+ cls = Part->cls;
+
+ CStackInd = 1;
+ CStack[1] = tv->tcellexpath+cls[tv->tcellexpath];
+
+ for (i = 1; i <= CStackInd; i++) {
+ StackMarkers[CStack[i]] = tv->stackmark;
+ }
+
+ longcode = Part->cells;
+
+ while (CStackInd > 0) {
+
+ weightend = 0;
+
+ if (tv->mark > (NAUTY_INFINITY-2)) {
+ memset(Markers, 0, n*sizeof(int));
+ memset(MarkHitVtx, 0, n*sizeof(int));
+ tv->mark = 0;
+ }
+ tv->mark++;
+
+ k = Select_from_CStack(cls, CStackInd);
+
+ currentcell = CStack[k];
+ currentsize = currentcell+cls[currentcell];
+ CStack[k] = CStack[CStackInd--]; /* Current Cell */
+ longcode = MASHNONCOMM(longcode, currentcell);
+ StackMarkers[currentcell] = 0;
+
+ labi = lab[currentcell];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+
+ do {
+ ind0 = currentcell;
+ ind2 = currentsize;
+ weightstart = weightend;
+
+ if (tv->options->weighted) {
+ currentweight = (TheGraph[labi].w)[weightstart];
+ while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
+ weightend++;
+ }
+ } else {
+ weightend = TheGraph[labi].d;
+ }
+
+ /* Analysis of occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is built */
+
+ if (cls[ind0] == 1) { /* SINGLETON CURRENT CELL CASE */
+
+ /* NEIGHCOUNT_SING_MULT */
+ HitClsInd = 0;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ ElmHitCll[value] = value;
+ }
+ HitVtx[ElmHitCll[value]++] = k;
+ } else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* end NEIGHCOUNT_SING_MULT */
+
+ tv->mark++;
+ FIND_SPLIT_CELLS;
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ /* REARRANGE THE CELLS */
+ for (j = 0; j < SplInd; j++) {
+ /* REARRANGE_CELLS */
+ ind1 = SplCls[j];
+ cls[ind1] = cls[ind1]-ElmHitCll[ind1];
+ newcell = ind1+cls[ind1];
+ cls[newcell] = ElmHitCll[ind1];
+ Part->cells++;
+ if (StackMarkers[ind1] != tv->stackmark) {
+ if (cls[newcell] < cls[ind1]) {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ else {
+ CStack[++CStackInd] = ind1;
+ StackMarkers[ind1] = tv->stackmark;
+ }
+ }
+ else {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ SplitCell = HitVtx+ind1;
+ ind3 = cls[newcell];
+ LabCell = lab+newcell;
+ for (jk = 0; jk < ind3; jk++) {
+ k = SplitCell[jk];
+ i = LabCell[jk];
+ Part->inv[newcell+jk] = newcell;
+ lab[InvLab[k]] = i;
+ InvLab[i] = InvLab[k];
+ LabCell[jk] = k;
+ InvLab[k] = newcell+jk;
+ }
+ /* END REARRANGE_CELLS */
+
+ if (cls[ind1] == 1) {
+ Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[ind1]);
+ }
+ if (cls[newcell] == 1) {
+ Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[newcell]);
+ }
+ }
+ }
+ else {
+ if (ti->thegraphisparse) {
+
+ /* NEIGHCOUNT_SPARSE_MULT */
+ HitClsInd = 0;
+ if (cls[ind0] != n) {
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j = weightstart; j < weightend; j++) {
+ k = nghb[j];
+ if (MarkHitVtx[k] == tv->mark) {
+ NghCounts[k]++;
+ }
+ else {
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ MarkHitVtx[k] = tv->mark;
+ NghCounts[k] = 1;
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ HitVtx[value] = k;
+ ElmHitCll[value] = 1;
+ }
+ else {
+ HitVtx[value+ElmHitCll[value]++] = k;
+ }
+ }
+ else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* End NEIGHCOUNT_SPARSE_MULT */
+
+ tv->mark++;
+
+ SplInd = 0;
+ SplCls[0] = n;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
+ SplCls[SplInd++] = ind1;
+ }
+ else {
+ ind2 = ind1+cls[ind1];
+ Split = FALSE;
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ Split = TRUE;
+ break;
+ }
+ }
+ if (!Split) {
+ longcode = MASHCOMM(longcode, ind1);
+ }
+ }
+ }
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (sc = 0; sc < SplInd; sc++) { /* For each cell C to be split */
+ ind0 = SplCls[sc];
+ ind1 = ind0 + cls[ind0];
+ SplCntInd = 0;
+ if (ElmHitCll[ind0] < cls[ind0]) {
+ SplCnt[SplCntInd++] = 0;
+ SplPos[0] = cls[ind0] - ElmHitCll[ind0];
+ }
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = NghCounts[HitVtx[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = HitVtx[i];
+ j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
+ k = InvLab[value]; /* where HitVtx[i] is in lab */
+ lab[k] = lab[j];
+ lab[j] = value;
+ InvLab[value] = j;
+ InvLab[lab[k]] = k;
+ NghCounts[value] = 0;
+ }
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind1 - ElmHitCll[ind0];
+ i = newcell;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
+ if (cls[i] == 1) {
+ Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[i]);
+ }
+ }
+
+ }
+ }
+ else {
+ if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
+ Sparse = FALSE;
+ }
+ else {
+ Sparse = TRUE;
+ }
+ Sparse = TRUE;
+ if (Sparse) {
+ /* Counting occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is also built */
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ HitCls[0] = 0;
+ HitClsInd = 1;
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_SPARSE_MULT */
+ HitClsInd = 0;
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ value = Part->inv[InvLab[k]];
+ if (Markers[value] != tv->mark) {
+ if (cls[value] > 1) HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ }
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
+
+ }
+
+ tv->mark++;
+
+ SplInd = 0;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) { /* For each cell C to be split */
+ ind0 = SplCls[j];
+ ind1 = ind0+cls[ind0];
+ SplCntInd = 0;
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ for (i = ind0; i < ind1; i++) {
+ value = NghCounts[lab[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
+ if (cls[i] == 1) {
+ Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[i]);
+ }
+ }
+
+ }
+ }
+ else {
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_DENSE_MULT */
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_DENSE_MULT */
+
+ }
+
+ ind0 = 0;
+ while (ind0 < n) { /* For each cell C with size(C) > 1 */
+ ind1 = ind0+cls[ind0];
+ if (cls[ind0] > 1) {
+
+ /* Determine whether C must be split */
+ SplCntInd = 0;
+ value = NghCounts[lab[ind0]];
+ for (i = ind0+1; i < ind1; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = i-ind0;
+ do {
+ value = NghCounts[lab[i++]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ while(i != ind1);
+ break;
+ }
+ }
+
+ if (SplCntInd) {
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0; i < ind1; i+=cls[i]) {
+ if (cls[i] == 1) {
+ Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[i]);
+ }
+ }
+
+ }
+ }
+ ind0 = ind1;
+ }
+ }
+ }
+ }
+ }
+ while (weightend < iend1int);
+ } /* end while (CStackInd > 0) */
+
+ tv->augmented_cells = Part->cells - tv->augmented_cells;
+ Cand->code = CLEANUP(longcode);
+ return;
+}
+
+void traces_refine_maketrie(Candidate *Cand,
+ int n,
+ Partition *Part,
+ struct TracesVars* tv,
+ struct TracesInfo *ti) {
+ int i, j, k, jk, sc, ind0, ind1, ind2, ind3, labi;
+ int value, iend, newcell;
+ int HitClsInd, SplInd, SplCntInd, CStackInd;
+ int j1int, iend1int;
+ unsigned int longcode;
+ int Split = 0;
+ int Sparse = TRUE;
+ int *lab, *cls, *InvLab, *SplitCell, *LabCell;
+ int BigCell, BigCellPos, BigCellSize;
+ int *nghb;
+ const int variation = 1;
+ int currentweight, weightstart, weightend, currentcell, currentsize;
+
+ if (tv->stackmark > (NAUTY_INFINITY-2)) {
+ memset(StackMarkers, 0, n*sizeof(int));
+ tv->stackmark = 0;
+ }
+ tv->stackmark++;
+
+ tv->augmented_cells = Part->cells;
+
+ lab = Cand->lab;
+ InvLab = Cand->invlab;
+ cls = Part->cls;
+
+ CStack[1] = Spine[tv->tolevel_tl].tgtpos;
+ CStackInd = 1;
+ for (i = 1; i <= CStackInd; i++) {
+ StackMarkers[CStack[i]] = tv->stackmark;
+ }
+
+ longcode = Part->cells;
+
+ while (CStackInd > 0)
+ {
+ weightend = 0;
+
+ if (tv->mark > (NAUTY_INFINITY-2)) {
+ memset(Markers, 0, n*sizeof(int));
+ memset(MarkHitVtx, 0, n*sizeof(int));
+ tv->mark = 0;
+ }
+ tv->mark++;
+
+ if (Part->cells == n) break;
+
+ k = Select_from_CStack(cls, CStackInd);
+
+ currentcell = CStack[k];
+ currentsize = currentcell+cls[currentcell];
+ CStack[k] = CStack[CStackInd--];
+ longcode = MASHNONCOMM(longcode, currentcell);
+ StackMarkers[currentcell] = 0;
+
+ labi = lab[currentcell];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+
+ do {
+ ind0 = currentcell;
+ ind2 = currentsize;
+ weightstart = weightend;
+
+ if (tv->options->weighted) {
+ currentweight = (TheGraph[labi].w)[weightstart];
+ while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
+ weightend++;
+ }
+ } else {
+ weightend = TheGraph[labi].d;
+ }
+
+ /* Analysis of occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is built */
+ if (cls[ind0] == 1) { /* SINGLETON CURRENT CELL CASE */
+
+ /* NEIGHCOUNT_SING_MULT */
+ HitClsInd = 0;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ ElmHitCll[value] = value;
+ }
+ HitVtx[ElmHitCll[value]++] = k;
+ } else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* end NEIGHCOUNT_SING_MULT */
+
+ tv->mark++;
+ FIND_SPLIT_CELLS;
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) {
+ ind1 = SplCls[j];
+ i = ind1+cls[ind1]-ElmHitCll[ind1];
+ trieref = trie_make(trieref, i, n, tv);
+ }
+
+ /* REARRANGE THE CELLS */
+ for (j = 0; j < SplInd; j++) {
+ /* REARRANGE_CELLS */
+ ind1 = SplCls[j];
+ cls[ind1] = cls[ind1]-ElmHitCll[ind1];
+ newcell = ind1+cls[ind1];
+ cls[newcell] = ElmHitCll[ind1];
+ Part->cells++;
+ if (StackMarkers[ind1] != tv->stackmark) {
+ if (cls[newcell] < cls[ind1]) {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ else {
+ CStack[++CStackInd] = ind1;
+ StackMarkers[ind1] = tv->stackmark;
+ }
+ }
+ else {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ SplitCell = HitVtx+ind1;
+ ind3 = cls[newcell];
+ LabCell = lab+newcell;
+ for (jk = 0; jk < ind3; jk++) {
+ k = SplitCell[jk];
+ i = LabCell[jk];
+ Part->inv[newcell+jk] = newcell;
+ lab[InvLab[k]] = i;
+ InvLab[i] = InvLab[k];
+ LabCell[jk] = k;
+ InvLab[k] = newcell+jk;
+ }
+ /* END REARRANGE_CELLS */
+ }
+ }
+ else {
+ if (ti->thegraphisparse) {
+
+ /* NEIGHCOUNT_SPARSE_MULT */
+ HitClsInd = 0;
+ if (cls[ind0] != n) {
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j = weightstart; j < weightend; j++) {
+ k = nghb[j];
+ if (MarkHitVtx[k] == tv->mark) {
+ NghCounts[k]++;
+ }
+ else {
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ MarkHitVtx[k] = tv->mark;
+ NghCounts[k] = 1;
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ HitVtx[value] = k;
+ ElmHitCll[value] = 1;
+ }
+ else {
+ HitVtx[value+ElmHitCll[value]++] = k;
+ }
+ }
+ else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* End NEIGHCOUNT_SPARSE_MULT */
+
+ tv->mark++;
+
+ SplInd = 0;
+ SplCls[0] = n;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
+ SplCls[SplInd++] = ind1;
+ }
+ else {
+ ind2 = ind1+cls[ind1];
+ Split = FALSE;
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ Split = TRUE;
+ break;
+ }
+ }
+ if (!Split) {
+ longcode = MASHCOMM(longcode, ind1);
+ }
+ }
+ }
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (sc = 0; sc < SplInd; sc++) { /* For each cell C to be split */
+ ind0 = SplCls[sc];
+ ind1 = ind0 + cls[ind0];
+ SplCntInd = 0;
+ if (ElmHitCll[ind0] < cls[ind0]) {
+ SplCnt[SplCntInd++] = 0;
+ SplPos[0] = cls[ind0] - ElmHitCll[ind0];
+ }
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = NghCounts[HitVtx[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ trieref = trie_make(trieref, i, n, tv);
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+ /* Permute elements of the cell C */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = HitVtx[i];
+ j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
+ k = InvLab[value]; /* where HitVtx[i] is in lab */
+ lab[k] = lab[j];
+ lab[j] = value;
+ InvLab[value] = j;
+ InvLab[lab[k]] = k;
+ NghCounts[value] = 0;
+ }
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind1 - ElmHitCll[ind0];
+ i = newcell;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ else {
+ if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
+ Sparse = FALSE;
+ }
+ else {
+ Sparse = TRUE;
+ }
+ Sparse = TRUE;
+ if (Sparse) {
+ /* Counting occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is also built */
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ HitCls[0] = 0;
+ HitClsInd = 1;
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_SPARSE_MULT */
+ HitClsInd = 0;
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ value = Part->inv[InvLab[k]];
+ if (Markers[value] != tv->mark) {
+ if (cls[value] > 1) HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ }
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
+
+ }
+
+ tv->mark++;
+
+ SplInd = 0;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) { /* For each cell C to be split */
+ ind0 = SplCls[j];
+ ind1 = ind0+cls[ind0];
+ SplCntInd = 0;
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ for (i = ind0; i < ind1; i++) {
+ value = NghCounts[lab[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ trieref = trie_make(trieref, i, n, tv);
+ }
+ }
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ else {
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_DENSE_MULT */
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_DENSE_MULT */
+
+ }
+
+ ind0 = 0;
+ while (ind0 < n) { /* For each cell C with size(C) > 1 */
+ ind1 = ind0+cls[ind0];
+ if (cls[ind0] > 1) {
+
+ /* Determine whether C must be split */
+ SplCntInd = 0;
+ value = NghCounts[lab[ind0]];
+ for (i = ind0+1; i < ind1; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = i-ind0;
+ do {
+ value = NghCounts[lab[i++]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ while(i != ind1);
+ break;
+ }
+ }
+
+ if (SplCntInd) {
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ trieref = trie_make(trieref, i, n, tv);
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ ind0 = ind1;
+ }
+ }
+ }
+ }
+ }
+ while (weightend < iend1int);
+ } /* end while (CStackInd > 0) */
+
+ tv->augmented_cells = Part->cells - tv->augmented_cells;
+
+ Cand->code = CLEANUP(longcode);
+ return;
+}
+
+int traces_refine_comptrie(Candidate *Cand,
+ int n,
+ Partition *Part,
+ struct TracesVars* tv,
+ struct TracesInfo *ti) {
+ int i, j, k, jk, sc, ind0, ind1, ind2, ind3, labi;
+ int value, iend, newcell;
+ int HitClsInd, SplInd, SplCntInd, CStackInd;
+ int j1int, iend1int;
+ unsigned int longcode;
+ int Split = 0;
+ int Sparse = TRUE;
+ int *lab, *cls, *InvLab, *SplitCell, *LabCell;
+ int BigCell, BigCellPos, BigCellSize;
+ int *nghb;
+ const int variation = 1;
+ int currentweight, weightstart, weightend, currentcell, currentsize;
+
+ if (tv->stackmark > (NAUTY_INFINITY-2)) {
+ memset(StackMarkers, 0, n*sizeof(int));
+ tv->stackmark = 0;
+ }
+ tv->stackmark++;
+
+ tv->augmented_cells = Part->cells;
+
+ lab = Cand->lab;
+ InvLab = Cand->invlab;
+ cls = Part->cls;
+
+ CStack[1] = Spine[tv->tolevel_tl].tgtpos;
+ CStackInd = 1;
+ for (i = 1; i <= CStackInd; i++) {
+ StackMarkers[CStack[i]] = tv->stackmark;
+ }
+
+ longcode = Part->cells;
+ while (CStackInd > 0)
+ {
+
+ weightend = 0;
+
+ if (tv->mark > (NAUTY_INFINITY-2)) {
+ memset(Markers, 0, n*sizeof(int));
+ memset(MarkHitVtx, 0, n*sizeof(int));
+ tv->mark = 0;
+ }
+ tv->mark++;
+
+ if (Part->cells == n) break;
+
+ k = Select_from_CStack(cls, CStackInd);
+
+ currentcell = CStack[k];
+ currentsize = currentcell+cls[currentcell];
+ CStack[k] = CStack[CStackInd--]; /* Current Cell */
+ longcode = MASHNONCOMM(longcode, currentcell);
+ StackMarkers[currentcell] = 0;
+
+ labi = lab[currentcell];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+
+ do {
+ ind0 = currentcell;
+ ind2 = currentsize;
+ weightstart = weightend;
+
+ if (tv->options->weighted) {
+ currentweight = (TheGraph[labi].w)[weightstart];
+ while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
+ weightend++;
+ }
+ } else {
+ weightend = TheGraph[labi].d;
+ }
+
+ /* Analysis of occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is built */
+ if (cls[ind0] == 1) { /* SINGLETON CURRENT CELL CASE */
+
+ /* NEIGHCOUNT_SING_MULT */
+ HitClsInd = 0;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ ElmHitCll[value] = value;
+ }
+ HitVtx[ElmHitCll[value]++] = k;
+ } else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* end NEIGHCOUNT_SING_MULT */
+
+ tv->mark++;
+ FIND_SPLIT_CELLS;
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) {
+ ind1 = SplCls[j];
+ i = ind1+cls[ind1]-ElmHitCll[ind1];
+ trieref = trie_comp(trieref, i);
+ if (trieref == NULL) return 0;
+ }
+
+ /* REARRANGE THE CELLS */
+ for (j = 0; j < SplInd; j++) {
+ /* REARRANGE_CELLS */
+ ind1 = SplCls[j];
+ cls[ind1] = cls[ind1]-ElmHitCll[ind1];
+ newcell = ind1+cls[ind1];
+ cls[newcell] = ElmHitCll[ind1];
+ Part->cells++;
+ if (StackMarkers[ind1] != tv->stackmark) {
+ if (cls[newcell] < cls[ind1]) {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ else {
+ CStack[++CStackInd] = ind1;
+ StackMarkers[ind1] = tv->stackmark;
+ }
+ }
+ else {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ SplitCell = HitVtx+ind1;
+ ind3 = cls[newcell];
+ LabCell = lab+newcell;
+ for (jk = 0; jk < ind3; jk++) {
+ k = SplitCell[jk];
+ i = LabCell[jk];
+ Part->inv[newcell+jk] = newcell;
+ lab[InvLab[k]] = i;
+ InvLab[i] = InvLab[k];
+ LabCell[jk] = k;
+ InvLab[k] = newcell+jk;
+ }
+ /* END REARRANGE_CELLS */
+ }
+ }
+ else {
+ if (ti->thegraphisparse) {
+
+ /* NEIGHCOUNT_SPARSE_MULT */
+ HitClsInd = 0;
+ if (cls[ind0] != n) {
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j = weightstart; j < weightend; j++) {
+ k = nghb[j];
+ if (MarkHitVtx[k] == tv->mark) {
+ NghCounts[k]++;
+ }
+ else {
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ MarkHitVtx[k] = tv->mark;
+ NghCounts[k] = 1;
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ HitVtx[value] = k;
+ ElmHitCll[value] = 1;
+ }
+ else {
+ HitVtx[value+ElmHitCll[value]++] = k;
+ }
+ }
+ else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* End NEIGHCOUNT_SPARSE_MULT */
+
+ tv->mark++;
+
+ SplInd = 0;
+ SplCls[0] = n;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
+ SplCls[SplInd++] = ind1;
+ }
+ else {
+ ind2 = ind1+cls[ind1];
+ Split = FALSE;
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ Split = TRUE;
+ break;
+ }
+ }
+ if (!Split) {
+ longcode = MASHCOMM(longcode, ind1);
+ }
+ }
+ }
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (sc = 0; sc < SplInd; sc++) { /* For each cell C to be split */
+ ind0 = SplCls[sc];
+ ind1 = ind0 + cls[ind0];
+ SplCntInd = 0;
+ if (ElmHitCll[ind0] < cls[ind0]) {
+ SplCnt[SplCntInd++] = 0;
+ SplPos[0] = cls[ind0] - ElmHitCll[ind0];
+ }
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = NghCounts[HitVtx[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ trieref = trie_comp(trieref, i);
+ if (trieref == NULL) return 0;
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+ /* Permute elements of the cell C */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = HitVtx[i];
+ j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
+ k = InvLab[value]; /* where HitVtx[i] is in lab */
+ lab[k] = lab[j];
+ lab[j] = value;
+ InvLab[value] = j;
+ InvLab[lab[k]] = k;
+ NghCounts[value] = 0;
+ }
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind1 - ElmHitCll[ind0];
+ i = newcell;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ else {
+ if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
+ Sparse = FALSE;
+ }
+ else {
+ Sparse = TRUE;
+ }
+ Sparse = TRUE;
+ if (Sparse) {
+ /* Counting occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is also built */
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ HitCls[0] = 0;
+ HitClsInd = 1;
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_SPARSE_MULT */
+ HitClsInd = 0;
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ value = Part->inv[InvLab[k]];
+ if (Markers[value] != tv->mark) {
+ if (cls[value] > 1) HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ }
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
+ ;
+ }
+
+ tv->mark++;
+
+ SplInd = 0;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) { /* For each cell C to be split */
+ ind0 = SplCls[j];
+ ind1 = ind0+cls[ind0];
+ SplCntInd = 0;
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ for (i = ind0; i < ind1; i++) {
+ value = NghCounts[lab[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ trieref = trie_comp(trieref, i);
+ if (trieref == NULL) return 0;
+ }
+ }
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ else {
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_DENSE_MULT */
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_DENSE_MULT */
+
+ }
+
+ ind0 = 0;
+ while (ind0 < n) { /* For each cell C with size(C) > 1 */
+ ind1 = ind0+cls[ind0];
+ if (cls[ind0] > 1) {
+
+ /* Determine whether C must be split */
+ SplCntInd = 0;
+ value = NghCounts[lab[ind0]];
+ for (i = ind0+1; i < ind1; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = i-ind0;
+ do {
+ value = NghCounts[lab[i++]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ while(i != ind1);
+ break;
+ }
+ }
+
+ if (SplCntInd) {
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ trieref = trie_comp(trieref, i);
+ if (trieref == NULL) return 0;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ ind0 = ind1;
+ }
+ }
+ }
+ }
+ }
+ while (weightend < iend1int);
+ } /* end while (CStackInd > 0) */
+
+ tv->augmented_cells = Part->cells - tv->augmented_cells;
+
+ Cand->code = CLEANUP(longcode);
+ return 1;
+}
+
+int traces_refine_sametrace(Candidate *Cand,
+ int n,
+ Partition *Part,
+ struct TracesVars* tv,
+ struct TracesInfo *ti) {
+ int i, j, k, jk, sc, ind0, ind1, ind2, ind3, ind4, labi;
+ int value, iend, newcell;
+ int HitClsInd, SplInd, SplCntInd, CStackInd, TraceInd, TraceCCInd, TraceStepsInd;
+ int j1int, iend1int;
+ unsigned int longcode;
+ int Sparse = TRUE;
+ int *lab, *cls, *InvLab, *TracePos, *SplitCell, *LabCell, *TraceEnd, Traceccend, *Tracestpend;
+ int BigCell, BigCellPos, BigCellSize;
+ boolean TraceCell = FALSE;
+ int *nghb;
+ const int variation = 0;
+ int currentweight, weightstart, weightend, currentcell, currentsize;
+
+ if (tv->stackmark > (NAUTY_INFINITY-2)) {
+ memset(StackMarkers, 0, n*sizeof(int));
+ tv->stackmark = 0;
+ }
+ tv->stackmark++;
+
+ tv->augmented_cells = Part->cells;
+
+ SpineTL = Spine+tv->tolevel;
+ TraceEnd = &(SpineTL->trcend);
+ Traceccend = SpineTL->ccend;
+ Tracestpend = &(SpineTL->stpend);
+ TraceCCInd = SpineTL->ccstart;
+ TraceStepsInd = SpineTL->stpstart;
+
+ lab = Cand->lab;
+ InvLab = Cand->invlab;
+ cls = Part->cls;
+
+ UPDATEMIN(Part->active, n-1);
+ memcpy(CStack+1, TheTrace+SpineTL->trcstart, (Part->active)*sizeof(int));
+ CStackInd = Part->active;
+ for (i = 1; i <= CStackInd; i++) {
+ StackMarkers[CStack[i]] = tv->stackmark;
+ }
+
+ longcode = Part->cells;
+ TraceInd = SpineTL->trcstart+Part->active;
+
+ while (CStackInd > 0)
+ {
+
+ weightend = 0;
+
+ if (tv->mark > (NAUTY_INFINITY-2)) {
+ memset(Markers, 0, n*sizeof(int));
+ memset(MarkHitVtx, 0, n*sizeof(int));
+ tv->mark = 0;
+ }
+ tv->mark++;
+
+ if (Part->cells == n) break;
+
+ k = Select_from_CStack(cls, CStackInd);
+
+ currentcell = CStack[k];
+ currentsize = currentcell+cls[currentcell];
+ CStack[k] = CStack[CStackInd--]; /* Current Cell */
+ StackMarkers[currentcell] = 0;
+
+ labi = lab[currentcell];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+
+ do {
+ ind0 = currentcell;
+ ind2 = currentsize;
+ weightstart = weightend;
+
+ if (tv->options->weighted) {
+ currentweight = (TheGraph[labi].w)[weightstart];
+ while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
+ weightend++;
+ }
+ } else {
+ weightend = TheGraph[labi].d;
+ }
+
+ TraceCell = ((ind0 == TheTraceCC[TraceCCInd]) && (TraceCCInd < Traceccend));
+
+ /* Analysis of occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is built */
+ if (cls[ind0] == 1) { /* SINGLETON CURRENT CELL CASE */
+
+ /* NEIGHCOUNT_SING_MULT */
+ HitClsInd = 0;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ ElmHitCll[value] = value;
+ }
+ HitVtx[ElmHitCll[value]++] = k;
+ } else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* end NEIGHCOUNT_SING_MULT */
+
+ tv->mark++;
+ FIND_SPLIT_CELLS;
+
+ /* SINGLETON CC CASE */
+ if (SplInd) {
+ SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd, &Traceccend)
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) {
+ ind1 = SplCls[j];
+ i = ind1+cls[ind1]-ElmHitCll[ind1];
+ SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+
+ /* REARRANGE THE CELLS */
+ for (j = 0; j < SplInd; j++) {
+ /* REARRANGE_CELLS */
+ ind1 = SplCls[j];
+ cls[ind1] = cls[ind1]-ElmHitCll[ind1];
+ newcell = ind1+cls[ind1];
+ cls[newcell] = ElmHitCll[ind1];
+ Part->cells++;
+ if (StackMarkers[ind1] != tv->stackmark) {
+ if (cls[newcell] < cls[ind1]) {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ else {
+ CStack[++CStackInd] = ind1;
+ StackMarkers[ind1] = tv->stackmark;
+ }
+ }
+ else {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ SplitCell = HitVtx+ind1;
+ ind3 = cls[newcell];
+ LabCell = lab+newcell;
+ for (jk = 0; jk < ind3; jk++) {
+ k = SplitCell[jk];
+ i = LabCell[jk];
+ Part->inv[newcell+jk] = newcell;
+ lab[InvLab[k]] = i;
+ InvLab[i] = InvLab[k];
+ LabCell[jk] = k;
+ InvLab[k] = newcell+jk;
+ }
+ /* END REARRANGE_CELLS */
+
+ if (cls[ind1] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[ind1]);
+ }
+ if (cls[newcell] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[newcell]);
+ }
+ }
+ }
+ else {
+ if (TraceCell) {
+ return 0;
+ }
+ }
+
+ }
+ else {
+ if (ti->thegraphisparse) {
+
+ /* NEIGHCOUNT_SPARSE_MULT */
+ HitClsInd = 0;
+ if (cls[ind0] != n) {
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j = weightstart; j < weightend; j++) {
+ k = nghb[j];
+ if (MarkHitVtx[k] == tv->mark) {
+ NghCounts[k]++;
+ }
+ else {
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ MarkHitVtx[k] = tv->mark;
+ NghCounts[k] = 1;
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ HitVtx[value] = k;
+ ElmHitCll[value] = 1;
+ }
+ else {
+ HitVtx[value+ElmHitCll[value]++] = k;
+ }
+ }
+ else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* End NEIGHCOUNT_SPARSE_MULT */
+
+ tv->mark++;
+
+ SplInd = 0;
+ SplCls[0] = n;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
+ SplCls[SplInd++] = ind1;
+ }
+ else {
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+ }
+
+ /* SPARSE CASE */
+ if (SplInd) {
+ SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+n, &Traceccend)
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (sc = 0; sc < SplInd; sc++) { /* For each cell C to be split */
+ ind0 = SplCls[sc];
+ ind1 = ind0 + cls[ind0];
+ SplCntInd = 0;
+ if (ElmHitCll[ind0] < cls[ind0]) {
+ SplCnt[SplCntInd++] = 0;
+ SplPos[0] = cls[ind0] - ElmHitCll[ind0];
+ }
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = NghCounts[HitVtx[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ if (SplCntInd) {
+ SAMETRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+n, Tracestpend)
+ }
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+ /* Permute elements of the cell C */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = HitVtx[i];
+ j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
+ k = InvLab[value]; /* where HitVtx[i] is in lab */
+ lab[k] = lab[j];
+ lab[j] = value;
+ InvLab[value] = j;
+ InvLab[lab[k]] = k;
+ NghCounts[value] = 0;
+ }
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind1 - ElmHitCll[ind0];
+ i = newcell;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
+ if (cls[i] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
+ }
+ }
+
+ }
+ }
+ else {
+ if (TraceCell) {
+ return 0;
+ }
+ }
+
+ }
+ else {
+ if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
+ Sparse = FALSE;
+ }
+ else {
+ Sparse = TRUE;
+ }
+ Sparse = TRUE;
+ if (Sparse) {
+ /* Counting occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is also built */
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ HitCls[0] = 0;
+ HitClsInd = 1;
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_SPARSE_MULT */
+ HitClsInd = 0;
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ value = Part->inv[InvLab[k]];
+ if (Markers[value] != tv->mark) {
+ if (cls[value] > 1) HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ }
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
+
+ }
+
+ tv->mark++;
+
+ SplInd = 0;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+
+ /* DENSE-SPARSE CASE */
+ if (SplInd) {
+ SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+2*n, &Traceccend)
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) { /* For each cell C to be split */
+ ind0 = SplCls[j];
+ ind1 = ind0+cls[ind0];
+ SplCntInd = 0;
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ for (i = ind0; i < ind1; i++) {
+ value = NghCounts[lab[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ if (SplCntInd) {
+ SAMETRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+2*n, Tracestpend)
+ }
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
+ if (cls[i] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
+ }
+ }
+
+ }
+ }
+ else {
+ if (TraceCell) {
+ return 0;
+ }
+ }
+
+ }
+ else {
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_DENSE_MULT */
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_DENSE_MULT */
+
+ }
+ SplInd = 0;
+ ind4 = 0;
+ while (ind4 < n) { /* For each cell C with size(C) > 1 */
+ ind1 = ind4+cls[ind4];
+ if (cls[ind4] > 1) {
+
+ /* Determine whether C must be split */
+ SplCntInd = 0;
+ value = NghCounts[lab[ind4]];
+ for (i = ind4+1; i < ind1; i++) {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplInd++;
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = i-ind4;
+ do {
+ value = NghCounts[lab[i++]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ while(i != ind1);
+ break;
+ }
+ }
+ tv->mark++;
+
+ if (SplCntInd) {
+ SAMETRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+3*n, Tracestpend)
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind4;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind4] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
+ }
+ }
+ if ((StackMarkers[ind4] != tv->stackmark) && (BigCell != ind4)) {
+ CStack[BigCellPos] = ind4;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind4] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind4;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind4;
+ i = ind4;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind4, k = 0; k < SplCntInd; i+=cls[i], k++) {
+ if (cls[i] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
+ }
+ }
+
+ }
+ }
+ ind4 = ind1;
+ }
+
+ /* DENSE-DENSE CASE */
+ if (SplInd) {
+ SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+3*n, &Traceccend)
+ }
+ else {
+ if (TraceCell) {
+ return 0;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ while (weightend < iend1int);
+ } /* end while (CStackInd > 0) */
+
+ for (i=SpineTL->trcstart; i < TraceInd; i++) {
+ ind0 = TheTrace[i];
+ longcode = MASHNONCOMM(longcode, Part->inv[ind0]);
+ labi = lab[ind0];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+ for (j1int = 0; j1int < iend1int; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ longcode = MASHCOMM(longcode, value);
+ }
+ }
+
+ tv->augmented_cells = Part->cells - tv->augmented_cells;
+
+ Part->code = Cand->code = CLEANUP(longcode);
+ if ((Cand->code != SpineTL->part->code) || (TraceInd != *TraceEnd)) return FALSE;
+ return TRUE;
+}
+
+void refine_tr(sparsegraph *sg, int *lab, int *ptn, int *numcells, int *code, TracesOptions *options_arg) {
+
+ const int n = sg->nv;
+ const int m = SETWORDSNEEDED(n);
+
+ int i, j, ord;
+ Partition *CurrPart;
+ Candidate *CurrCand;
+ struct TracesVars tvar, *tv;
+ struct TracesInfo tinf, *ti;
+
+ if (n > (NAUTY_INFINITY-2))
+ {
+ fprintf(ERRFILE, "Traces: need n <= %d, but n=%d\n\n",
+ NAUTY_INFINITY-2, n);
+ return;
+ }
+
+ Allocate_refine_Structures(n);
+
+ tv = &tvar;
+ ti = &tinf;
+
+ tv->options = options_arg;
+ tv->mark = tv->stackmark = NAUTY_INFINITY-1;
+ tv->maxdeg = 0;
+ tv->mindeg = n;
+
+ outfile = (tv->options->outfile == NULL ? stdout : tv->options->outfile);
+
+ for (i = 0; i < n; i++) {
+ IDENTITY_PERM[i] = i;
+ }
+
+ copy_sg_structure(&redgraph, sg);
+
+ tv->graph = &redgraph;
+ if (tv->options->weighted) {
+ tv->graph->w = malloc(tv->graph->wlen*sizeof(int));
+ if (tv->graph->w == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ memcpy(tv->graph->w, sg->w, tv->graph->wlen*sizeof(int));
+ }
+ memcpy(tv->graph->e, sg->e, tv->graph->elen*sizeof(int));
+
+ for (i=0; i<n; i++) {
+ TheGraph[i].d = sg->d[i];
+ if (TheGraph[i].d > tv->maxdeg) {
+ tv->maxdeg = TheGraph[i].d;
+ }
+ if (TheGraph[i].d < tv->mindeg) {
+ tv->mindeg = TheGraph[i].d;
+ }
+ TheGraph[i].e = tv->graph->e + sg->v[i];
+ if (sg->w)
+ TheGraph[i].w = tv->graph->w + sg->v[i];
+ else
+ TheGraph[i].w = NULL;
+ TheGraph[i].one = FALSE;
+ }
+
+ ord = 0;
+
+ /*----------- WEIGHTS --------------*/
+ if (tv->options->weighted) {
+ WeightCodes(n);
+ ord = trie_classify(n,tv);
+ }
+ /*----------------------------------*/
+
+ if ((tv->maxdeg == tv->mindeg) && (ord == 0)) ti->regular = TRUE; else ti->regular = FALSE;
+
+ /* The graph is sparse? */
+ if (sg->nde < n || sg->nde / n < n / (sg->nde / n)) {
+ ti->thegraphisparse = TRUE;
+ }
+ else {
+ ti->thegraphisparse = FALSE;
+ }
+
+ /* Initialize candidate, partition, cells, orbits */
+ CurrCand = NewCandidate(n, &GarbList, TRUE);
+ CurrPart = NewPartition(n);
+ memset(CurrPart->inv, 0, n*sizeof(int));
+
+ CurrCand->singcode = 0;
+
+ if (ti->regular) {
+ memcpy(CurrCand->lab, lab, n*sizeof(int));
+ CurrPart->cells = 0;
+ j = 0;
+ for (i = 0; i < n; i++) {
+ if (j) CurrPart->inv[i] = j;
+ CurrCand->invlab[CurrCand->lab[i]] = i;
+ if (!ptn[i]) {
+ CurrPart->cls[j] = i-j+1;
+ if (CurrPart->cls[j] == 1) {
+ CurrCand->singcode = MASHCOMM(CurrCand->singcode, CurrCand->lab[j]);
+ }
+ TheTrace[CurrPart->cells++] = j;
+ j = i+1;
+ }
+ }
+ } else {
+ if (tv->options->weighted) {
+ CurrPart->cells = traces_vertexclass_refine (n, lab, ptn, CurrCand, CurrPart, WeightsSeq);
+ }
+ else {
+ CurrPart->cells = traces_vertexclass_refine (n, lab, ptn, CurrCand, CurrPart, sg->d);
+ }
+ }
+
+ /* First refinement */
+ refine_tr_refine(CurrCand, n, CurrPart, tv, ti);
+
+ for (i = CurrPart->cls[0]; i < n; i+=CurrPart->cls[i]) {
+ ptn[i-1] = 0;
+ }
+ ptn[n-1] = 0;
+
+ memcpy(lab, CurrCand->lab, n*sizeof(int));
+ *code = CurrCand->code;
+ *numcells = CurrPart->cells;
+
+ FREECAND(CurrCand)
+ FREEPART(CurrPart)
+
+ if (tv->graph != sg) {
+ SG_FREE(redgraph);
+ }
+
+#if !MAXN
+ DYNFREE(CStack, CStack_sz);
+ DYNFREE(IDENTITY_PERM, IDENTITY_PERM_sz);
+ DYNFREE(Markers, Markers_sz);
+ DYNFREE(MarkHitVtx, MarkHitVtx_sz);
+ DYNFREE(TreeMarkers, TreeMarkers_sz);
+ DYNFREE(NghCounts, NghCounts_sz);
+ DYNFREE(Singletons, Singletons_sz);
+ DYNFREE(SplPos, SplPos_sz);
+ DYNFREE(SplCls, SplCls_sz);
+ DYNFREE(SplCnt, SplCnt_sz);
+ DYNFREE(StackMarkers, StackMarkers_sz);
+ DYNFREE(TheTrace, TheTrace_sz);
+ DYNFREE(TheTraceSteps, TheTraceSteps_sz);
+ DYNFREE(TheTraceCC, TheTraceCC_sz);
+ DYNFREE(TheTraceSplNum, TheTraceSplNum_sz);
+ DYNFREE(WeightsSeq, WeightsSeq_sz);
+ DYNFREE(WorkArray1, WorkArray1_sz);
+ DYNFREE(WorkArray2, WorkArray2_sz);
+ DYNFREE(WorkArray3, WorkArray3_sz);
+ DYNFREE(WorkArray4, WorkArray4_sz);
+ DYNFREE(WorkArray5, WorkArray5_sz);
+ DYNFREE(TreeStack, TreeStack_sz);
+ DYNFREE(Spine, Spine_sz);
+ DYNFREE(TrieArray, TrieArray_sz);
+ DYNFREE(TheGraph, TheGraph_sz);
+#endif
+}
+
+void refine_tr_refine(Candidate *Cand,
+ int n,
+ Partition *Part,
+ struct TracesVars* tv,
+ struct TracesInfo *ti) {
+
+ int i, j, k, jk, sc, ind0, ind1, ind2, ind3, ind4, labi;
+ int value, iend, newcell;
+ int HitClsInd, SplInd, SplCntInd, CStackInd, TraceInd, TraceCCInd, TraceStepsInd;
+ int j1int, iend1int;
+ unsigned int longcode;
+ int newtrace = FALSE;
+ int Sparse = TRUE;
+ int *lab, *cls, *InvLab, *TracePos, *SplitCell, *LabCell, TraceEnd, Traceccend, Tracestpend;
+ int BigCell, BigCellPos, BigCellSize;
+ boolean TraceCell = FALSE;
+ int *nghb;
+ const int variation = 0;
+ int currentweight, weightstart, weightend, currentcell, currentsize;
+
+ HitClsInd = 0;
+ if (tv->stackmark > (NAUTY_INFINITY-2)) {
+ memset(StackMarkers, 0, n*sizeof(int));
+ tv->stackmark = 0;
+ }
+ tv->stackmark++;
+
+ lab = Cand->lab;
+ InvLab = Cand->invlab;
+ cls = Part->cls;
+
+ UPDATEMIN(Part->active, n-1);
+ memcpy(CStack+1, TheTrace, (Part->cells)*sizeof(int));
+ CStackInd = Part->cells;
+
+ for (i = 1; i <= CStackInd; i++) {
+ StackMarkers[CStack[i]] = tv->stackmark;
+ }
+
+ longcode = Part->cells;
+ newtrace = TRUE;
+ while (CStackInd > 0) {
+
+ weightend = 0;
+
+ if (tv->mark > (NAUTY_INFINITY-2)) {
+ memset(Markers, 0, n*sizeof(int));
+ memset(MarkHitVtx, 0, n*sizeof(int));
+ tv->mark = 0;
+ }
+ tv->mark++;
+
+ if (Part->cells == n) break;
+
+ k = Select_from_CStack(cls, CStackInd);
+
+ currentcell = CStack[k];
+ currentsize = currentcell+cls[currentcell];
+ CStack[k] = CStack[CStackInd--];
+ StackMarkers[currentcell] = 0;
+
+ labi = lab[currentcell];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+
+ do {
+
+ ind0 = currentcell;
+ ind2 = currentsize;
+ weightstart = weightend;
+
+ if (tv->options->weighted) {
+ currentweight = (TheGraph[labi].w)[weightstart];
+ while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
+ weightend++;
+ }
+ } else {
+ weightend = TheGraph[labi].d;
+ }
+
+ /* Analysis of occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is built */
+ if (cls[ind0] == 1) { /* SINGLETON CURRENT CELL CASE */
+
+ /* NEIGHCOUNT_SING_MULT */
+ HitClsInd = 0;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ ElmHitCll[value] = value;
+ }
+ HitVtx[ElmHitCll[value]++] = k;
+ } else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* end NEIGHCOUNT_SING_MULT */
+
+ tv->mark++;
+ FIND_SPLIT_CELLS;
+
+ /* SINGLETON CC CASE */
+ if (SplInd) {
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) {
+ ind1 = SplCls[j];
+ i = ind1+cls[ind1]-ElmHitCll[ind1];
+ }
+
+ /* REARRANGE THE CELLS */
+ for (j = 0; j < SplInd; j++) {
+ /* REARRANGE_CELLS */
+ ind1 = SplCls[j];
+ cls[ind1] = cls[ind1]-ElmHitCll[ind1];
+ newcell = ind1+cls[ind1];
+ cls[newcell] = ElmHitCll[ind1];
+ Part->cells++;
+ if (StackMarkers[ind1] != tv->stackmark) {
+ if (cls[newcell] < cls[ind1]) {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ else {
+ CStack[++CStackInd] = ind1;
+ StackMarkers[ind1] = tv->stackmark;
+ }
+ }
+ else {
+ CStack[++CStackInd] = newcell;
+ StackMarkers[newcell] = tv->stackmark;
+ }
+ SplitCell = HitVtx+ind1;
+ ind3 = cls[newcell];
+ LabCell = lab+newcell;
+ for (jk = 0; jk < ind3; jk++) {
+ k = SplitCell[jk];
+ i = LabCell[jk];
+ Part->inv[newcell+jk] = newcell;
+ lab[InvLab[k]] = i;
+ InvLab[i] = InvLab[k];
+ LabCell[jk] = k;
+ InvLab[k] = newcell+jk;
+ }
+ /* END REARRANGE_CELLS */
+
+ }
+ }
+ else {
+ }
+ }
+ else {
+ if (ti->thegraphisparse) {
+
+ /* NEIGHCOUNT_SPARSE_MULT */
+ HitClsInd = 0;
+ if (cls[ind0] != n) {
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j = weightstart; j < weightend; j++) {
+ k = nghb[j];
+ if (MarkHitVtx[k] == tv->mark) {
+ NghCounts[k]++;
+ }
+ else {
+ value = Part->inv[InvLab[k]];
+ if (cls[value] > 1) {
+ MarkHitVtx[k] = tv->mark;
+ NghCounts[k] = 1;
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ HitVtx[value] = k;
+ ElmHitCll[value] = 1;
+ }
+ else {
+ HitVtx[value+ElmHitCll[value]++] = k;
+ }
+ }
+ else {
+ switch (variation) {
+ case 1:
+ longcode = MASHCOMM(longcode, value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* End NEIGHCOUNT_SPARSE_MULT */
+
+ tv->mark++;
+
+ SplInd = 0;
+ SplCls[0] = n;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
+ SplCls[SplInd++] = ind1;
+ }
+ else {
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+ }
+
+ /* SPARSE CASE */
+ if (SplInd) {
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (sc = 0; sc < SplInd; sc++) { /* For each cell C to be split */
+ ind0 = SplCls[sc];
+ ind1 = ind0 + cls[ind0];
+ SplCntInd = 0;
+ if (ElmHitCll[ind0] < cls[ind0]) {
+ SplCnt[SplCntInd++] = 0;
+ SplPos[0] = cls[ind0] - ElmHitCll[ind0];
+ }
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = NghCounts[HitVtx[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ sort_Split_Array(SplCnt,SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+ /* Permute elements of the cell C */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = HitVtx[i];
+ j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
+ k = InvLab[value]; /* where HitVtx[i] is in lab */
+ lab[k] = lab[j];
+ lab[j] = value;
+ InvLab[value] = j;
+ InvLab[lab[k]] = k;
+ NghCounts[value] = 0;
+ }
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind1 - ElmHitCll[ind0];
+ i = newcell;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ }
+ else {
+ if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
+ Sparse = FALSE;
+ }
+ else {
+ Sparse = TRUE;
+ }
+ Sparse = TRUE;
+ if (Sparse) {
+ /* Counting occurrences of neighbors of the current cell */
+ /* The list of cells with neighbors in the current cell is also built */
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ HitCls[0] = 0;
+ HitClsInd = 1;
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_SPARSE_MULT */
+ HitClsInd = 0;
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ value = Part->inv[InvLab[k]];
+ if (Markers[value] != tv->mark) {
+ if (cls[value] > 1) HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ }
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
+
+ }
+
+ tv->mark++;
+
+
+ SplInd = 0;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ ind2 = ind1+cls[ind1];
+ value = NghCounts[lab[ind1++]];
+ for (i = ind1; i < ind2; i++)
+ {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ }
+
+ /* DENSE-SPARSE CASE */
+ if (SplInd) {
+
+ /* Sorting the cells to be split */
+ sort_Split_Array(SplCls, SplInd);
+
+ for (j = 0; j < SplInd; j++) { /* For each cell C to be split */
+ ind0 = SplCls[j];
+ ind1 = ind0+cls[ind0];
+ SplCntInd = 0;
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ for (i = ind0; i < ind1; i++) {
+ value = NghCounts[lab[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+
+ if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
+ CStack[BigCellPos] = ind0;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind0] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind0;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind0;
+ i = ind0;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ }
+ else {
+ if (cls[ind0] == n) {
+ for (i = 0; i < n; i++) {
+ NghCounts[i] = TheGraph[i].d;
+ }
+ }
+ else {
+ memset(NghCounts, 0, n*sizeof(int));
+
+ /* NEIGHCOUNT_DENSE_DENSE_MULT */
+ for (i = ind0; i < ind2; i++) {
+ labi = lab[i];
+ nghb = TheGraph[labi].e;
+ for (j1int = weightstart; j1int < weightend; ++j1int) {
+ k = nghb[j1int];
+ (NghCounts[k])++;
+ }
+ }
+ /* End NEIGHCOUNT_DENSE_DENSE_MULT */
+
+ }
+ SplInd = 0;
+ ind4 = 0;
+ while (ind4 < n) { /* For each cell C with size(C) > 1 */
+ ind1 = ind4+cls[ind4];
+ if (cls[ind4] > 1) {
+
+
+ /* Determine whether C must be split */
+ SplCntInd = 0;
+ value = NghCounts[lab[ind4]];
+ for (i = ind4+1; i < ind1; i++) {
+ if (NghCounts[lab[i]] != value)
+ {
+ SplInd++;
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = i-ind4;
+ do {
+ value = NghCounts[lab[i++]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ while(i != ind1);
+ break;
+ }
+ }
+ tv->mark++;
+
+ if (SplCntInd) {
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind4;
+ if (StackMarkers[i] != tv->stackmark) {
+ BigCellSize = 0;
+ }
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ cls[i] = value;
+
+ if ((StackMarkers[ind4] != tv->stackmark) && (value > BigCellSize)) {
+ BigCell = i;
+ BigCellPos = CStackInd;
+ BigCellSize = cls[i];
+ }
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ CStack[++CStackInd] = i;
+ StackMarkers[i] = tv->stackmark;
+ }
+ }
+ if ((StackMarkers[ind4] != tv->stackmark) && (BigCell != ind4)) {
+ CStack[BigCellPos] = ind4;
+ StackMarkers[BigCell] = 0;
+ StackMarkers[ind4] = tv->stackmark;
+ }
+
+ /* Permute elements of the cell C */
+ i = ind4;
+ do {
+ SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
+ }
+ while(++i < ind1);
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind4;
+ i = ind4;
+ ind2 = newcell+cls[newcell]-1;
+ do {
+ lab[i] = SplCnt[i];
+ InvLab[lab[i]] = i;
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+ }
+ }
+ ind4 = ind1;
+ }
+
+ /* DENSE-DENSE CASE */
+ }
+ }
+ }
+ }
+ while (weightend < iend1int);
+ } /* end while (CStackInd > 0) */
+
+ Cand->code = CLEANUP(longcode);
+ for (ind0=Part->cls[0]; ind0 < n; ind0+=Part->cls[ind0]) {
+ longcode = MASHNONCOMM(longcode, Part->inv[ind0]);
+ labi = lab[ind0];
+ iend1int = TheGraph[labi].d;
+ nghb = TheGraph[labi].e;
+ for (j1int = 0; j1int < iend1int; ++j1int) {
+ k = nghb[j1int];
+ value = Part->inv[InvLab[k]];
+ longcode = MASHCOMM(longcode, value);
+ }
+ }
+ Part->code = Cand->code = CLEANUP(longcode);
+ return;
+}
+
+void Adjust_Cycles(Candidate *Cand, Partition *Part, int n, struct TracesVars *tv) {
+ int i, j, i1, j1, k;
+ int tmp, arg, cyclength;
+
+ if (Part->cells < n) {
+ memset(CyclesLength,0,n*sizeof(int));
+ SETMARK(CellMarkers1, tv->markcell1)
+ SETMARK(CellMarkers2, tv->markcell2)
+ i1 = j1 = 0;
+ for (i=0; i<n; i+=Part->cls[i]) {
+ if (Part->cls[i] > 1) {
+ for (j=i; j<i+Part->cls[i]; j++) {
+ arg = Cand->lab[j];
+ if (CellMarkers1[arg] != tv->markcell1) {
+ CellMarkers1[arg] = tv->markcell1;
+ cyclength = 1;
+ CyclesPart[i1++] = Cand->invlab[arg];
+ do {
+ tmp = NextNeighbour(arg, Cand, Part, CellMarkers1, tv->markcell1, &arg, n);
+ if (tmp) {
+ CellMarkers1[arg] = tv->markcell1;
+ cyclength++;
+ CyclesPart[i1++] = Cand->invlab[arg];
+ }
+ } while (tmp);
+ for (k=j1; k<i1; k++) {
+ CyclesLength[CyclesPart[k]] = cyclength;
+ }
+ j1 = i1;
+ }
+ }
+ }
+ }
+ }
+ for (i=0; i<n; i+=Part->cls[i]) {
+ if (Part->cls[i] > 1) {
+ sort2ints(CyclesLength+i, Cand->lab+i, Part->cls[i]);
+ }
+ for (j=i; j<i+Part->cls[i]; j++) {
+ Cand->invlab[Cand->lab[j]] = j;
+ }
+ }
+}
+
+void Allocate_Traces_Structures(int n) {
+#if !MAXN
+ DYNALLOC1(int, AUTPERM, AUTPERM_sz, n, "Traces");
+ DYNALLOC1(int, BreakSteps, BreakSteps_sz, n, "Traces");
+ DYNALLOC1(int, CurrOrbSize, CurrOrbSize_sz, n, "Traces");
+ DYNALLOC1(int, CurrRefCells, CurrRefCells_sz, n, "Traces");
+ DYNALLOC1(boolean, Diff, Diff_sz, n, "Traces");
+ DYNALLOC1(int, CStack, CStack_sz, n, "Traces");
+ DYNALLOC1(boolean, Factorials, Factorials_sz, n, "Traces");
+ DYNALLOC1(int, fix, fix_sz, n, "Traces");
+ DYNALLOC1(int, IDENTITY_PERM, IDENTITY_PERM_sz, n, "Traces");
+ DYNALLOC1(int, Markers, Markers_sz, n, "Traces");
+ DYNALLOC1(int, TreeMarkers, TreeMarkers_sz, n, "Traces");
+ DYNALLOC1(int, AutMarkers, AutMarkers_sz, n, "Traces");
+ DYNALLOC1(int, MarkHitVtx, MarkHitVtx_sz, n, "Traces");
+ DYNALLOC1(int, MultRefCells, MultRefCells_sz, n, "Traces");
+ DYNALLOC1(int, NghCounts, NghCounts_sz, n, "Traces");
+ DYNALLOC1(int, OrbSize, OrbSize_sz, n, "Traces");
+ DYNALLOC1(int, OrbList, OrbList_sz, n, "Traces");
+ DYNALLOC1(pair, PrmPairs, PrmPairs_sz, n, "Traces");
+ DYNALLOC1(int, TempOrbList, TempOrbList_sz, n, "Traces");
+ DYNALLOC1(int, RefCells, RefCells_sz, n, "Traces");
+ DYNALLOC1(int, Singletons, Singletons_sz, n, "Traces");
+ DYNALLOC1(int, SplCls, SplCls_sz, n, "Traces");
+ DYNALLOC1(int, SplCnt, SplCnt_sz, n, "Traces");
+ DYNALLOC1(int, SplPos, SplPos_sz, n, "Traces");
+ DYNALLOC1(int, StackMarkers, StackMarkers_sz, n, "Traces");
+ DYNALLOC1(int, TheTrace, TheTrace_sz, n+10, "Traces");
+ DYNALLOC1(int, TheTraceCC, TheTraceCC_sz, n, "Traces");
+ DYNALLOC1(int, TheTraceSplNum, TheTraceSplNum_sz, n, "Traces");
+ DYNALLOC1(int, TheTraceSteps, TheTraceSteps_sz, n+10, "Traces");
+ DYNALLOC1(int, TEMPLAB, TEMPLAB_sz, n, "Traces");
+ DYNALLOC1(int, TEMPINVLAB, TEMPINVLAB_sz, n, "Traces");
+ DYNALLOC1(int, WeightsSeq, WeightsSeq_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray, WorkArray_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray0, WorkArray0_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray1, WorkArray1_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray2, WorkArray2_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray3, WorkArray3_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray4, WorkArray4_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray5, WorkArray5_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray6, WorkArray6_sz, n, "Traces");
+ DYNALLOC1(int, WorkArray7, WorkArray7_sz, n, "Traces");
+ DYNALLOC1(int, TreeStack, TreeStack_sz, n, "Traces");
+ DYNALLOC1(TracesSpine, Spine, Spine_sz, n, "Traces");
+ DYNALLOC1(trie*, TrieArray, TrieArray_sz, n, "Traces");
+ DYNALLOC1(grph_strct, TheGraph, TheGraph_sz, n, "Traces");
+ DYNALLOC1(ExpPathInfo, EPCodes, EPCodes_sz, n, "Traces");
+ DYNALLOC1(int, CyclesPart, CyclesPart_sz, n, "Traces");
+ DYNALLOC1(int, CyclesLength, CyclesLength_sz, n, "Traces");
+#endif
+ return;
+}
+
+void Allocate_refine_Structures(int n) {
+#if !MAXN
+ DYNALLOC1(int, CStack, CStack_sz, n, "refine_tr");
+ DYNALLOC1(int, IDENTITY_PERM, IDENTITY_PERM_sz, n, "refine_tr");
+ DYNALLOC1(int, Markers, Markers_sz, n, "refine_tr");
+ DYNALLOC1(int, MarkHitVtx, MarkHitVtx_sz, n, "refine_tr");
+ DYNALLOC1(int, TreeMarkers, TreeMarkers_sz, n, "refine_tr");
+ DYNALLOC1(int, NghCounts, NghCounts_sz, n, "refine_tr");
+ DYNALLOC1(int, Singletons, Singletons_sz, n, "refine_tr");
+ DYNALLOC1(int, SplPos, SplPos_sz, n, "refine_tr");
+ DYNALLOC1(int, SplCls, SplCls_sz, n, "refine_tr");
+ DYNALLOC1(int, SplCnt, SplCnt_sz, n, "refine_tr");
+ DYNALLOC1(int, StackMarkers, StackMarkers_sz, n, "refine_tr");
+ DYNALLOC1(int, TheTrace, TheTrace_sz, n+10, "refine_tr");
+ DYNALLOC1(int, TheTraceSteps, TheTraceSteps_sz, n+10, "refine_tr");
+ DYNALLOC1(int, TheTraceCC, TheTraceCC_sz, n, "refine_tr");
+ DYNALLOC1(int, TheTraceSplNum, TheTraceSplNum_sz, n, "refine_tr");
+ DYNALLOC1(int, WeightsSeq, WeightsSeq_sz, n, "refine_tr");
+ DYNALLOC1(int, WorkArray1, WorkArray1_sz, n, "refine_tr");
+ DYNALLOC1(int, WorkArray2, WorkArray2_sz, n, "refine_tr");
+ DYNALLOC1(int, WorkArray3, WorkArray3_sz, n, "refine_tr");
+ DYNALLOC1(int, WorkArray4, WorkArray4_sz, n, "refine_tr");
+ DYNALLOC1(int, WorkArray5, WorkArray5_sz, n, "refine_tr");
+ DYNALLOC1(int, TreeStack, TreeStack_sz, n, "refine_tr");
+ DYNALLOC1(TracesSpine, Spine, Spine_sz, n, "refine_tr");
+ DYNALLOC1(trie*, TrieArray, TrieArray_sz, n, "refine_tr");
+ DYNALLOC1(grph_strct, TheGraph, TheGraph_sz, n, "refine_tr");
+#endif
+
+#define HitCls WorkArray2
+#define HitVtx WorkArray3
+#define ElmHitCll WorkArray5
+ return;
+}
+
+struct Candidate *NewCandidate(int n, Candidate **GarbList, int Mrk) {
+ struct Candidate *Cand;
+
+ if (*GarbList) {
+ Cand = *GarbList;
+ *GarbList = (*GarbList)->next;
+ }
+ else {
+ Cand = malloc(sizeof(*Cand));
+ if (Cand == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ Cand->lab = malloc(n*sizeof(*Cand->lab));
+ if (Cand->lab == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ Cand->invlab = malloc(n*sizeof(*Cand->invlab));
+ if (Cand->invlab == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ }
+ Cand->do_it = Mrk;
+ Cand->indnum = 0;
+ Cand->code = 0;
+ Cand->next = NULL;
+ Cand->stnode = NULL;
+ Cand->sortedlab = FALSE;
+ return Cand;
+}
+
+int Check_degree_one(sparsegraph *sg, Candidate *Cand, Partition *Part, int n) {
+
+ int i;
+
+ for (i=0; i<n; i += Part->cls[i]) {
+ if (sg->d[Cand->lab[i]] == 1) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+int CheckForAutomorphisms(Candidate *CurrCand, Candidate *NextCand,
+ struct TracesVars* tv, struct TracesInfo* ti,
+ int m, int n, Partition* Part) {
+ Candidate *CheckAutList;
+ int i, j, k, tgt_level, numtemporbits;
+ int CheckLevel, CheckLevelEnd;
+ int temp, tmp, tmp1, arg, arg1, val, val1;
+ searchtrie *TrieCandFrom, *TrieCheckFrom;
+
+ VERB_PRINT("CFA",3,FALSE)
+
+ CheckLevel = 0;
+ CheckLevelEnd = 0;
+ temp = 0;
+ tv->gotonode = NULL;
+ tv->conta6++;
+
+ switch (tv->compstage) {
+ case 0:
+ if (tv->strategy) {
+ CheckLevel = CheckLevelEnd = tv->maxtreelevel;
+ }
+ else {
+ if ((Spine[tv->tolevel].part)->cells == tv->finalnumcells) {
+ CheckLevel = CheckLevelEnd = tv->maxtreelevel;
+ }
+ else {
+ CheckLevel = 1;
+ if ((Spine[tv->maxtreelevel].part)->cells == tv->finalnumcells) {
+ CheckLevelEnd = tv->maxtreelevel - 1;
+ }
+ else {
+ CheckLevelEnd = tv->maxtreelevel;
+ }
+ }
+ }
+ break;
+ case 1:
+ CheckLevel = CheckLevelEnd = tv->tolevel;
+ break;
+ case 2:
+ if (m || (tv->tolevel == tv->maxtreelevel+1)) {
+ CheckLevel = CheckLevelEnd = tv->maxtreelevel+1;
+ }
+ else {
+ CheckLevel = 1;
+ if ((Spine[tv->maxtreelevel].part)->cells == tv->finalnumcells) {
+ CheckLevelEnd = tv->maxtreelevel - 1;
+ }
+ else {
+ CheckLevelEnd = tv->maxtreelevel;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ Adjust_Cycles(NextCand, Part, n, tv);
+
+ while (CheckLevel <= CheckLevelEnd) {
+ CheckAutList = Spine[CheckLevel].liststart;
+ while (CheckAutList) {
+ if (CheckAutList->do_it && lookup(CheckAutList->stnode) && (CheckAutList != NextCand) && (CheckAutList != CurrCand)) {
+ if (CheckAutList->code == NextCand->code) {
+ SETMARK(Markers, tv->mark)
+ if (Part->cells == n) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (i = 0; i < n; i++) {
+ arg = NextCand->lab[i];
+ val = CheckAutList->lab[i];
+ SETPAIRSAUT(arg, val)
+ }
+ }
+ else {
+ Adjust_Cycles(CheckAutList, Part, n, tv);
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ SETMARK(CellMarkers1, tv->markcell1)
+ SETMARK(CellMarkers2, tv->markcell2)
+ for (i=0; i<n; i+=Part->cls[i]) {
+ if (Part->cls[i] == 1) {
+ arg = NextCand->lab[i];
+ val = CheckAutList->lab[i];
+ SETPAIRSAUT(arg, val)
+ if (tv->preprocessed && Diff[arg])
+ MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
+ }
+ else {
+ k = i;
+ for (j=i; j<i+Part->cls[i]; j++) {
+ arg = arg1 = NextCand->lab[j];
+ if (CellMarkers1[arg] != tv->markcell1) {
+ CellMarkers1[arg] = tv->markcell1;
+ while ((CellMarkers2[CheckAutList->lab[k]] == tv->markcell2) && (k < i+Part->cls[i])) {
+ k++;
+ }
+ if (k < i+Part->cls[i]) {
+ val = val1 = CheckAutList->lab[k];
+ CellMarkers2[val] = tv->markcell2;
+ SETPAIRSAUT(arg, val)
+ if (tv->preprocessed && Diff[arg])
+ MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
+ tmp = FirstNeighbour(arg, NextCand, Part, CellMarkers1, tv->markcell1, &arg, n);
+ if (tmp) {
+ CellMarkers1[arg] = tv->markcell1;
+ tmp = FirstNeighbour(val, CheckAutList, Part, CellMarkers2, tv->markcell2, &val, n);
+ CellMarkers2[val] = tv->markcell2;
+ SETPAIRSAUT(arg, val)
+ if (tv->preprocessed && Diff[arg])
+ MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
+ while (tmp) {
+ tmp = NextNeighbour(arg, NextCand, Part, CellMarkers1, tv->markcell1, &arg, n);
+ if (tmp) {
+ CellMarkers1[arg] = tv->markcell1;
+ tmp = NextNeighbour(val, CheckAutList, Part, CellMarkers2, tv->markcell2, &val, n);
+ if (tmp) {
+ CellMarkers2[val] = tv->markcell2;
+ SETPAIRSAUT(arg, val)
+ if (tv->preprocessed && Diff[arg])
+ MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
+ }
+ }
+ }
+ arg = arg1;
+ val = val1;
+ do {
+ tmp = NextNeighbour(arg, NextCand, Part, CellMarkers1, tv->markcell1, &arg, n);
+ if (tmp) {
+ CellMarkers1[arg] = tv->markcell1;
+ tmp = NextNeighbour(val, CheckAutList, Part, CellMarkers2, tv->markcell2, &val, n);
+ if (tmp) {
+ CellMarkers2[val] = tv->markcell2;
+ SETPAIRSAUT(arg, val)
+ if (tv->preprocessed && Diff[arg])
+ MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
+ }
+ }
+ } while (tmp);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (isautom_sg_pair((graph*)tv->input_graph, AUTPERM, tv->options->digraph, m, n, tv)) {
+ if (!findperm(gensB, AUTPERM, n)) {
+ if (tv->options->verbosity >= 2) tv->schreier3 -= CPUTIME;
+ addgenerator(&gpB, &gensB, AUTPERM, n);
+ if (tv->options->verbosity >= 2) tv->schreier3 += CPUTIME;
+ if (tv->options->verbosity >= 2) {
+ fprintf(outfile, "[A(%d,%d)] ", CheckLevel, CheckAutList->name);
+ }
+ tv->lev_of_lastauto = tv->tolevel;
+ tv->stats->numgenerators++;
+ orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
+ ti->thegrouphaschanged = TRUE;
+ ti->identitygroup = FALSE;
+ if (tv->options->verbosity >= 2 && tv->options->writeautoms) {
+ PRINT_RETURN
+ }
+ if (tv->options->writeautoms) {
+ fprintf(outfile, "Gen(A) #%d: ", tv->stats->numgenerators);
+ writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n);
+ }
+ if (tv->options->userautomproc) {
+ (*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n);
+ }
+ }
+ else {
+ orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
+ if (tv->options->verbosity >= 2) {
+ fprintf(outfile, "[A*(%d,%d)] ", CheckLevel, CheckAutList->name);
+ }
+ }
+ TrieCandFrom = NULL;
+ TrieCheckFrom = CheckAutList->stnode;
+ if (CurrCand->stnode->level <= 1) {
+ tgt_level = CurrCand->stnode->level + 1;
+ while (TrieCheckFrom->level > tgt_level) {
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ if (tv->tolevel <= TrieCheckFrom->level) {
+ tgt_level = tv->tolevel;
+ while (TrieCheckFrom->level != tgt_level) {
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ TrieCandFrom = CurrCand->stnode;
+ tgt_level = TrieCheckFrom->level;
+ while (TrieCandFrom->level != tgt_level) {
+ TrieCandFrom = TrieCandFrom->father;
+ }
+ }
+ }
+ if (TrieCandFrom) {
+ while (TrieCandFrom->father != TrieCheckFrom->father) {
+ TrieCandFrom = TrieCandFrom->father;
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ if ((TrieCheckFrom->level > 1) && (TrieCheckFrom->father != CurrCand->stnode)) {
+ TrieCandFrom = CurrCand->stnode;
+ TrieCheckFrom = TrieCheckFrom->father;
+ while (TrieCandFrom->father != TrieCheckFrom->father) {
+ TrieCandFrom = TrieCandFrom->father;
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ }
+
+ while (TrieCheckFrom->goes_to) {
+ TrieCheckFrom = TrieCheckFrom->goes_to;
+ }
+
+ for (temp=1; temp<=tv->tolevel; temp++) {
+ if (CheckAutList->lab[Spine[temp].tgtpos] != NextCand->lab[Spine[temp].tgtpos]) {
+ break;
+ }
+ }
+
+ if (temp == tv->tolevel) {
+ if (TempOrbits) {
+ if (tv->compstage == 0) {
+ for (j=0; j<tv->permInd; j++) {
+ orbjoin_sp_pair(TempOrbits, TempOrbList, n,
+ PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
+ }
+ }
+ else {
+ orbjoin(TempOrbits, AUTPERM, n);
+ }
+ } else {
+ orbjoin(tv->currorbit, AUTPERM, n);
+ }
+ }
+
+ switch (tv->compstage) {
+ case 0:
+ if (tv->strategy && (tv->steps == 1)) {
+ RemoveFromLevel(temp, tv->maxtreelevel-1, tv->strategy, FALSE);
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,1)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,2)
+ }
+ NextCand->do_it = FALSE;
+ }
+ else {
+ if (CheckAutList->lab[Spine[temp].tgtpos] >= NextCand->lab[Spine[temp].tgtpos]) {
+ CheckAutList->do_it = FALSE;
+ if (TrieCandFrom) {
+ TrieCandFrom->index += TrieCheckFrom->index;
+ tv->newindex = 0;
+ TrieCheckFrom->goes_to = TrieCandFrom;
+ PRINT_INDEX(TrieCandFrom,4,3)
+ }
+ else {
+ if (CurrCand->stnode->level > 1) {
+ tv->newgotonode = TrieCheckFrom;
+ tv->newindex = TrieCheckFrom->index;
+ }
+ else {
+ tv->newgotonode = NULL;
+ tv->newindex = 0;
+ }
+ }
+ }
+ else {
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,4)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,5)
+ }
+ NextCand->do_it = FALSE;
+ }
+ }
+ break;
+ case 1:
+ TrieCheckFrom->index ++;
+ PRINT_INDEX(TrieCheckFrom,4,6)
+ tv->gotonode = TrieCheckFrom;
+ break;
+ case 2:
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,7)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,8)
+ }
+ if (temp == tv->maxtreelevel) {
+ tmp1 = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
+
+ if (CheckAutList->lab[Spine[temp].tgtpos] == AutomCount[1]) {
+ for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == tmp1) break;
+ if (i == AutomCount[0]) {
+ AutomCount[AutomCount[0]++] = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
+ }
+ }
+
+ }
+ break;
+ default:
+ break;
+ }
+ return temp;
+ }
+ }
+ }
+ CheckAutList = CheckAutList->next;
+ }
+ CheckLevel++;
+ }
+ return FALSE;
+}
+
+
+int CheckForSingAutomorphisms(Candidate *CurrCand, Partition *NextPart, Candidate *NextCand,
+ struct TracesVars* tv, struct TracesInfo* ti,
+ int m, int n) {
+ int i, j, temp, tmp, tmp1, result, tgt_level, numtemporbits;
+ TracesSpine *SpineTL;
+ Candidate *CheckAutList;
+ searchtrie *TrieCandFrom, *TrieCheckFrom;
+
+ SpineTL = Spine+tv->tolevel;
+ CheckAutList = SpineTL->liststart;
+ tv->gotonode = NULL;
+
+ VERB_PRINT("CFSA",3,FALSE)
+
+ result = 0;
+ while (CheckAutList != NULL) {
+ if (CheckAutList->do_it && (CheckAutList->stnode->father == CurrCand->stnode)) {
+ if (CheckAutList->firstsingcode == NextCand->firstsingcode) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ if ((tv->tolevel == 1) && (Spine[0].part->cells == 1)) tmp = 2; else tmp = tv->tolevel;
+ if (TreeFyTwo(tmp, CheckAutList, NextCand, NextPart, n, tv, ti)) {
+ if (isautom_sg((graph*)tv->input_graph, AUTPERM, tv->options->digraph, m, n)) {
+ if (!findperm(gensB, AUTPERM, n)) {
+ if (tv->options->verbosity >= 2) tv->schreier3 -= CPUTIME;
+ addgenerator(&gpB, &gensB, AUTPERM, n);
+ if (tv->options->verbosity >= 2) tv->schreier3 += CPUTIME;
+ result = CheckAutList->name;
+ if (TempOrbits) {
+ if (tv->compstage == 0) {
+ for (j=0; j<tv->permInd; j++) {
+ orbjoin_sp_pair(TempOrbits, TempOrbList, n,
+ PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
+ }
+ }
+ else {
+ orbjoin(TempOrbits, AUTPERM, n);
+ }
+ }
+ tv->stats->numgenerators++;
+ orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
+
+ ti->thegrouphaschanged = TRUE;
+ ti->identitygroup = FALSE;
+ tv->lev_of_lastauto = tv->tolevel;
+ if (tv->options->verbosity >= 2) fprintf(outfile, "[a(%d)] ", CheckAutList->name);
+ if (tv->options->verbosity >= 2 && tv->options->writeautoms) {
+ PRINT_RETURN
+ }
+ if (tv->options->writeautoms) {
+ fprintf(outfile, "Gen(a) #%d: ", tv->stats->numgenerators);
+ writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n);
+ }
+ if (tv->options->userautomproc) {
+ (*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n);
+ }
+ }
+ else {
+ if (tv->options->verbosity >= 2) {
+ fprintf(outfile, "[a*]");
+ }
+ if (TempOrbits) {
+ if (tv->compstage == 0) {
+ for (j=0; j<tv->permInd; j++) {
+ orbjoin_sp_pair(TempOrbits, TempOrbList, n,
+ PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
+ }
+ }
+ else {
+ orbjoin(TempOrbits, AUTPERM, n);
+ }
+ }
+ else {
+ orbjoin(tv->currorbit, AUTPERM, n);
+ }
+ orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
+
+ result = -CheckAutList->name;
+ }
+
+ TrieCandFrom = NULL;
+ TrieCheckFrom = CheckAutList->stnode;
+ if (CurrCand->stnode->level <= 1) {
+ tgt_level = CurrCand->stnode->level + 1;
+ while (TrieCheckFrom->level > tgt_level) {
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ if (tv->tolevel <= TrieCheckFrom->level) {
+ tgt_level = tv->tolevel;
+ while (TrieCheckFrom->level != tgt_level) {
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ TrieCandFrom = CurrCand->stnode;
+ tgt_level = TrieCheckFrom->level;
+ while (TrieCandFrom->level != tgt_level) {
+ TrieCandFrom = TrieCandFrom->father;
+ }
+ }
+ }
+ if (TrieCandFrom) {
+ while (TrieCandFrom->father != TrieCheckFrom->father) {
+ TrieCandFrom = TrieCandFrom->father;
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ if ((TrieCheckFrom->level > 1) && (TrieCheckFrom->father != CurrCand->stnode)) {
+ TrieCandFrom = CurrCand->stnode;
+ TrieCheckFrom = TrieCheckFrom->father;
+ while (TrieCandFrom->father != TrieCheckFrom->father) {
+ TrieCandFrom = TrieCandFrom->father;
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ }
+
+ while (TrieCheckFrom->goes_to) {
+ TrieCheckFrom = TrieCheckFrom->goes_to;
+ }
+
+ for (temp=1; temp<=tv->tolevel; temp++) {
+ if (CheckAutList->lab[Spine[temp].tgtpos] != NextCand->lab[Spine[temp].tgtpos]) {
+ break;
+ }
+ }
+
+ switch (tv->compstage) {
+ case 0:
+ if (tv->strategy && (tv->steps == 1)) {
+ RemoveFromLevel(temp, tv->maxtreelevel-1, tv->strategy, FALSE);
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,9)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,10)
+ }
+ NextCand->do_it = FALSE;
+ }
+ else {
+ if (CheckAutList->lab[Spine[temp].tgtpos] >= NextCand->lab[Spine[temp].tgtpos]) {
+ CheckAutList->do_it = FALSE;
+ if (TrieCandFrom) {
+ TrieCandFrom->index += TrieCheckFrom->index;
+ tv->newindex = 0;
+ TrieCheckFrom->goes_to = TrieCandFrom;
+ PRINT_INDEX(TrieCandFrom,4,11)
+ }
+ else {
+ if (CurrCand->stnode->level > 1) {
+ tv->newgotonode = TrieCheckFrom;
+ tv->newindex = TrieCheckFrom->index;
+ }
+ else {
+ tv->newgotonode = NULL;
+ tv->newindex = 0;
+ }
+ }
+ }
+ else {
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,12)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,13)
+ }
+ NextCand->do_it = FALSE;
+ }
+ }
+ break;
+ case 1:
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,14)
+ tv->gotonode = TrieCheckFrom;
+ break;
+ case 2:
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,15)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,16)
+ }
+ if ((temp == tv->maxtreelevel) && (CheckAutList->lab[Spine[temp].tgtpos] == AutomCount[1])) {
+ tmp1 = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
+ for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == tmp1) break;
+ if (i == AutomCount[0]) {
+ AutomCount[AutomCount[0]++] = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return result;
+ }
+ }
+ }
+ }
+ CheckAutList = CheckAutList->next;
+ }
+ return result;
+}
+
+int CheckForMatching(Candidate *CurrCand, Candidate *NextCand, Partition *Part, struct TracesVars* tv, struct TracesInfo* ti, int m, int n) {
+ int i, j, vtx, vtx1, temp, tmp1, tgt_level, numtemporbits, pos;
+ TracesSpine *SpineTL;
+ Candidate *CheckAutList;
+ int *cls;
+ searchtrie *TrieCandFrom, *TrieCheckFrom;
+ boolean CodeVerify;
+
+ VERB_PRINT("CFM",3,FALSE)
+
+ SpineTL = Spine+tv->tolevel;
+ CheckAutList = SpineTL->liststart;
+ cls = Part->cls;
+ numtemporbits = 0;
+ tv->gotonode = NULL;
+
+ while (CheckAutList != NULL) {
+ if (CheckAutList->do_it && (CheckAutList->singcode == NextCand->singcode)) {
+ TrieCheckFrom = CheckAutList->stnode->father;
+ TrieCandFrom = CurrCand->stnode;
+ while (TrieCandFrom != TrieCheckFrom) {
+ TrieCandFrom = TrieCandFrom->father;
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+
+ CodeVerify = TRUE;
+ for (i=Spine[TrieCheckFrom->level+1].singstart; i<SpineTL->singend; i++) {
+ Markers[NextCand->lab[Singletons[i]]] = tv->mark;
+ }
+ for (i=Spine[TrieCheckFrom->level+1].singstart; i<SpineTL->singend; i++) {
+ pos = Singletons[i];
+ vtx1 = CheckAutList->lab[pos];
+ if (Markers[vtx1] != tv->mark) {
+ CodeVerify = FALSE;
+ break;
+ }
+ vtx = NextCand->lab[pos];
+ SETPAIRSAUT(vtx, vtx1)
+
+ if (tv->preprocessed && Diff[vtx1]) {
+ MakeTree(vtx, vtx1, tv->input_graph, n, tv, TRUE);
+ }
+ }
+ tv->conta7++;
+
+ if (CodeVerify) {
+ if (isautom_sg_pair((graph*)tv->input_graph, AUTPERM, tv->options->digraph, m, n, tv)) {
+
+ if (!findperm(gensB, AUTPERM, n)) {
+ if (tv->options->verbosity >= 2) tv->schreier3 -= CPUTIME;
+ if (tv->options->generators) addpermutation(&gensB, AUTPERM, n);
+
+ if (tv->options->verbosity >= 2) tv->schreier3 += CPUTIME;
+
+ if (CheckAutList->stnode->father == CurrCand->stnode) {
+ if (TempOrbits) {
+ if (tv->compstage == 0) {
+ for (j=0; j<tv->permInd; j++) {
+ orbjoin_sp_pair(TempOrbits, TempOrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
+ }
+ }
+ else {
+ orbjoin(TempOrbits, AUTPERM, n);
+ }
+ } else {
+ orbjoin(tv->currorbit, AUTPERM, n);
+ }
+ }
+
+ tv->stats->numgenerators++;
+
+ for (j=0; j<tv->permInd; j++) {
+ orbjoin_sp_pair(tv->orbits, OrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &tv->stats->numorbits);
+ }
+
+ ti->thegrouphaschanged = TRUE;
+ ti->first_matching = TRUE;
+ tv->lev_of_lastauto = tv->tolevel;
+ if (tv->options->verbosity >= 2) fprintf(outfile, "[M(%d)] ", CheckAutList->name);
+ if (tv->options->verbosity >= 2 && tv->options->writeautoms) {
+ PRINT_RETURN
+ }
+ if (tv->options->writeautoms) {
+ fprintf(outfile, "Gen(M) #%d: ", tv->stats->numgenerators);
+ writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n);
+ }
+ if (tv->options->userautomproc) {
+ (*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n);
+ }
+
+ }
+ else {
+ if (tv->options->verbosity >= 2) {
+ fprintf(outfile, "[M*]");
+ }
+ if (CheckAutList->stnode->father == CurrCand->stnode) {
+ if (TempOrbits) {
+ if (tv->compstage == 0) {
+ for (j=0; j<tv->permInd; j++) {
+ orbjoin_sp_pair(TempOrbits, TempOrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
+ }
+ }
+ else {
+ orbjoin(TempOrbits, AUTPERM, n);
+ }
+ } else {
+ orbjoin(tv->currorbit, AUTPERM, n);
+ }
+ }
+
+ for (j=0; j<tv->permInd; j++) {
+ orbjoin_sp_pair(tv->orbits, OrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &tv->stats->numorbits);
+ }
+ }
+
+ TrieCandFrom = NULL;
+ TrieCheckFrom = CheckAutList->stnode;
+ if (CurrCand->stnode->level <= 1) {
+ tgt_level = CurrCand->stnode->level + 1;
+ while (TrieCheckFrom->level > tgt_level) {
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ if (tv->tolevel <= TrieCheckFrom->level) {
+ tgt_level = tv->tolevel;
+ while (TrieCheckFrom->level != tgt_level) {
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ TrieCandFrom = CurrCand->stnode;
+ tgt_level = TrieCheckFrom->level;
+ while (TrieCandFrom->level != tgt_level) {
+ TrieCandFrom = TrieCandFrom->father;
+ }
+ }
+ }
+ if (TrieCandFrom) {
+ while (TrieCandFrom->father != TrieCheckFrom->father) {
+ TrieCandFrom = TrieCandFrom->father;
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ else {
+ if ((TrieCheckFrom->level > 1) && (TrieCheckFrom->father != CurrCand->stnode)) {
+ TrieCandFrom = CurrCand->stnode;
+ TrieCheckFrom = TrieCheckFrom->father;
+ while (TrieCandFrom->father != TrieCheckFrom->father) {
+ TrieCandFrom = TrieCandFrom->father;
+ TrieCheckFrom = TrieCheckFrom->father;
+ }
+ }
+ }
+
+ while (TrieCheckFrom->goes_to) {
+ TrieCheckFrom = TrieCheckFrom->goes_to;
+ }
+
+ for (temp=1; temp<=tv->tolevel; temp++) {
+ if (CheckAutList->lab[Spine[temp].tgtpos] != NextCand->lab[Spine[temp].tgtpos]) {
+ break;
+ }
+ }
+ switch (tv->compstage) {
+ case 0:
+ if (tv->strategy && (tv->steps == 1)) {
+ RemoveFromLevel(temp, tv->maxtreelevel-1, tv->strategy, FALSE);
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,17)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,18)
+ }
+ NextCand->do_it = FALSE;
+ }
+ else {
+ if (CheckAutList->lab[Spine[temp].tgtpos] >= NextCand->lab[Spine[temp].tgtpos]) {
+ CheckAutList->do_it = FALSE;
+ if (TrieCandFrom) {
+ TrieCandFrom->index += TrieCheckFrom->index;
+ tv->newindex = 0;
+ TrieCheckFrom->goes_to = TrieCandFrom;
+ PRINT_INDEX(TrieCandFrom,4,19)
+ }
+ else {
+ if (CurrCand->stnode->level > 1) {
+ tv->newgotonode = TrieCheckFrom;
+ tv->newindex = TrieCheckFrom->index;
+ }
+ else {
+ tv->newgotonode = NULL;
+ tv->newindex = 0;
+ }
+ }
+ }
+ else {
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,20)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,21)
+ }
+ NextCand->do_it = FALSE;
+ }
+ }
+ break;
+ case 1:
+ TrieCheckFrom->index ++;
+ tv->gotonode = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,22)
+ break;
+ case 2:
+ if (TrieCandFrom) {
+ TrieCheckFrom->index += TrieCandFrom->index;
+ TrieCandFrom->goes_to = TrieCheckFrom;
+ PRINT_INDEX(TrieCheckFrom,4,23)
+ }
+ else {
+ TrieCheckFrom->index++;
+ PRINT_INDEX(TrieCheckFrom,4,24)
+ }
+ if ((temp == tv->maxtreelevel) && (CheckAutList->lab[Spine[temp].tgtpos] == AutomCount[1])) {
+ tmp1 = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
+ for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == tmp1) break;
+ if (i == AutomCount[0]) {
+ AutomCount[AutomCount[0]++] = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return temp;
+ }
+ }
+ }
+ CheckAutList = CheckAutList->next;
+ }
+ return FALSE;
+}
+
+void CodeClassify(int Level, int code, int cell) {
+ switch (EPCodes[Level].info) {
+ case 0:
+ EPCodes[Level].code = code;
+ EPCodes[Level].cell = cell;
+ EPCodes[Level].info = 1;
+ break;
+ case 1:
+ if (EPCodes[Level].cell != cell) {
+ EPCodes[Level].info = 3;
+ } else {
+ if (EPCodes[Level].code != code) {
+ EPCodes[Level].info = 2;
+ }
+ }
+ break;
+ case 2:
+ if (EPCodes[Level].cell != cell) {
+ EPCodes[Level].info = 3;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void Complete(sparsegraph *sg_orig, Candidate *Cand, Partition *Part, int cell, TracesVars *tv,
+ double *grpsize1, int *grpsize2, permnode **ring, int n) {
+ int i, j, k;
+ int arg, val;
+ int numtemporbits;
+ k = cell + Part->cls[cell];
+
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (i = cell; i < k; i++) {
+ tv->currorbit[Cand->lab[i]] = Cand->lab[k];
+ arg = Cand->lab[i];
+ val = Cand->lab[i+1];
+ SETPAIRSAUTANDTREE(arg, val)
+ }
+ arg = Cand->lab[i];
+ val = Cand->lab[cell];
+ SETPAIRSAUTANDTREE(arg, val)
+ SPECIALGENERATORS
+
+ if (Part->cls[cell] > 1) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ arg = Cand->lab[cell];
+ val = Cand->lab[cell+1];
+ SETPAIRSAUTANDTREE(arg, val)
+ arg = Cand->lab[cell+1];
+ val = Cand->lab[cell];
+ SETPAIRSAUTANDTREE(arg, val)
+ SPECIALGENERATORS
+ }
+}
+
+int CompStage0(Partition *CurrPart, Partition *NextPart, Candidate *CurrCand, Candidate *NextCand,
+ int m, int n, struct TracesVars* tv, struct TracesInfo *ti) {
+ int i, j, i1, j2, k, cu, cu1, num_indv;
+ int temp, tmp, auxcode, search_vtx, gom_level;
+ boolean closeloop, firstsing, has_nexttcell;
+ Candidate *SpTLliststart, *AuxCand;
+ searchtrie *TreeNode, *TreeNode1, *TreeNode2;
+
+#ifdef NAUTY_IN_MAGMA
+ if (main_seen_interrupt) return NAUTY_KILLED;
+#else
+ if (nauty_kill_request) return NAUTY_KILLED;
+#endif
+
+ PRINT_FROM_VERB(4,tv->tolevel)
+ if (TargetCell(CurrCand, CurrPart, n, tv, tv->tolevel)) {
+ ++tv->tolevel;
+ SpineTL = Spine+tv->tolevel;
+ SpineTL->tgtcell = tv->tcell;
+ SpineTL->tgtsize = CurrPart->cls[tv->tcell];
+ SpineTL->tgtend = tv->tcell+SpineTL->tgtsize;
+ SpineTL->tgtpos = SpineTL->tgtend - 1;
+ }
+ else {
+ tv->finalnumcells = CurrPart->cells;
+ ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
+ return 0;
+ }
+
+ tv->newgotonode = NULL;
+
+ /* CANDIDATE */
+ temp = CurrCand->lab[Spine[1].tgtpos];
+ k = SpineTL->tgtend;
+
+ TreeNode = CurrCand->stnode;
+ while (TreeNode) {
+ if (TreeNode->goes_to) {
+ CurrCand->do_it = FALSE;
+ break;
+ }
+ TreeNode = TreeNode->father;
+ }
+
+ if (CurrCand->do_it) {
+ if ((tv->orbits[temp] == temp) || tv->tolevel == 1) {
+ ti->minimalinorbits = TRUE;
+
+ if ((tv->group_level >= tv->tolevel) && (FixedBase(fix, tv, CurrCand, 0, tv->fromlevel))) {
+ tv->nfix = tv->fromlevel;
+ tv->currorbit = findcurrorbits(gpB, tv->nfix);
+ } else {
+ if ((!ti->identitygroup) &&
+ (((Spine[tv->fromlevel].liststart != Spine[tv->fromlevel].listend)
+ && (CurrPart->cls[tv->tcell] > 10))
+ || tv->strategy
+ || (tv->expathlength <=10)
+ )) {
+
+ TempOrbits = NULL;
+ tv->samepref = FixBase(fix, tv, CurrCand, 0, tv->fromlevel);
+ if ((tv->samepref != tv->nfix) || ti->thegrouphaschanged) {
+ if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
+ gom_level = getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit, CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell], n, TRUE);
+ if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
+ ti->thegrouphaschanged = FALSE;
+
+ if (gom_level < tv->nfix) {
+ PRINT_NOTMIN_VERB(4)
+
+ TreeNode = CurrCand->stnode;
+ j2 = CurrCand->lab[Spine[gom_level+1].tgtpos];
+ i1 = tv->currorbit[j2];
+ for (j=0; j < tv->nfix - gom_level; j++) {
+ TreeNode = TreeNode->father;
+ }
+ TreeNode1 = TreeNode->first_child;
+ while (TreeNode1) {
+ if (TreeNode1->vtx == i1) {
+ break;
+ }
+ TreeNode1 = TreeNode1->next_sibling;
+ }
+ if (TreeNode1) {
+ while (TreeNode1->goes_to) {
+ TreeNode1 = TreeNode1->goes_to;
+ }
+ TreeNode2 = TreeNode1->next_sibling;
+ while (TreeNode2->vtx != j2) {
+ TreeNode2 = TreeNode2->next_sibling;
+ }
+ TreeNode1->index += TreeNode2->index;
+ TreeNode2->goes_to = TreeNode1;
+ PRINT_INDEX(TreeNode1,4,25)
+
+ ti->minimalinorbits = FALSE;
+ }
+ else {
+ tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
+ }
+ }
+ }
+ else {
+ tv->currorbit = findcurrorbits(gpB, tv->nfix);
+ }
+ }
+ else {
+ TempOrbits = WorkArray1;
+ memcpy(TempOrbits, IDENTITY_PERM, n*sizeof(int));
+ memcpy(TempOrbList, IDENTITY_PERM, n*sizeof(int));
+
+ tv->conta1++;
+ tv->currorbit = TempOrbits;
+ }
+ }
+ if (ti->minimalinorbits) {
+ memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
+ memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
+ tv->conta2++;
+ auxcode = CurrCand->code;
+ SpineTL->trcstart = CurrPart->cells;
+ TheTrace[SpineTL->trcstart] = SpineTL->tgtpos;
+ if (!CurrCand->sortedlab) {
+ quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
+ for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
+ CurrCand->invlab[CurrCand->lab[i]] = i;
+ }
+ CurrCand->sortedlab = TRUE;
+ }
+
+ tv->indivstart = tv->tcell+CurrCand->indnum;
+ tv->indivend = tv->indivstart+tv->steps;
+ if (tv->indivend > SpineTL->tgtend) {
+ tv->indivend = SpineTL->tgtend;
+ }
+
+ temp = CurrCand->lab[tv->indivstart];
+ for (k = tv->indivstart; k < tv->indivend; k++) {
+ CurrCand->indnum++;
+ NextCand->singcode = CurrCand->singcode;
+ NextCand->vertex = CurrCand->lab[k];
+ NextCand->name = ++tv->name;
+ if (NextCand->name == (NAUTY_INFINITY-2)) {
+ NextCand->name = tv->name = 1;
+ }
+
+ PRINT_INDIV_VERB(4,tv->tolevel)
+ if (tv->currorbit[NextCand->vertex] != NextCand->vertex) {
+ PRINT_SKIPPED_VERB(4)
+
+ search_vtx = tv->currorbit[NextCand->vertex];
+ TreeNode = CurrCand->stnode;
+ if (TreeNode->first_child) {
+ TreeNode = TreeNode->first_child;
+ while (TreeNode) {
+ if (TreeNode->vtx == search_vtx) {
+ break;
+ }
+ TreeNode = TreeNode->next_sibling;
+ }
+ if (TreeNode) {
+ while (TreeNode->goes_to) {
+ TreeNode = TreeNode->goes_to;
+ }
+ TreeNode->index++;
+ PRINT_INDEX(TreeNode,4,26)
+ continue;
+ }
+ }
+ }
+ else {
+ PRINT_REFINE_VERB(4,'a')
+
+ memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
+ memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
+
+ tv->conta3++;
+
+ if (NextPart->cls[tv->tcell] == 2) {
+ num_indv = 2;
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell]);
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell+1]);
+ if (SpineTL->singstart == SpineTL->singend) {
+ Singletons[SpineTL->singend++] = tv->tcell;
+ Singletons[SpineTL->singend++] = tv->tcell+1;
+ }
+ }
+ else {
+ num_indv = 1;
+ NextCand->singcode = MASHCOMM(NextCand->singcode, NextCand->vertex);
+ if (SpineTL->singstart == SpineTL->singend) {
+ Singletons[SpineTL->singend++] = tv->tcell + NextPart->cls[tv->tcell] - 1;
+ }
+ }
+
+ Individualize(NextPart, NextCand, NextCand->vertex, tv->tcell, CurrPart->cells, SpineTL->tgtpos);
+ tv->stats->numnodes++;
+ tv->answ = traces_refine(NextCand,
+ n,
+ NextPart, tv, ti, num_indv, TRUE);
+ switch (tv->answ) {
+ case 0: /* Interrupted refinement: do not add to the list */
+ tv->stats->interrupted++;
+ SpineTL->levelcounter++;
+ break;
+ case 1 : /* The same trace has been found once more : add to the list */
+ SpineTL->levelcounter++;
+
+ NextCand->do_it = TRUE;
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel);
+
+ tv->tolevel_tl = tv->tolevel;
+ NextCand->pathsingcode = NextCand->singcode;
+ NextCand->firstsingcode = 0;
+
+ if (tv->steps > 1) {
+ if (tv->fromlevel <= tv->lev_of_lastauto) {
+ closeloop = CheckForMatching(CurrCand, NextCand, NextPart, tv, ti, m, n);
+ }
+ if (NextCand->do_it) {
+ firstsing = TRUE;
+
+ /* EXPERIMENTAL PATH */
+ if (NextPart->cells != tv->finalnumcells) { /* 160712 */
+ if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
+ while (NextPart->cells < n) {
+ if (firstsing && BreakSteps[tv->tolevel]) {
+ firstsing = FALSE;
+ NextCand->firstsingcode = NextCand->pathsingcode;
+ if (CheckForSingAutomorphisms(CurrCand, NextPart, NextCand, tv, ti, m, n))
+ if (!NextCand->do_it) {
+ break;
+ }
+ }
+
+ has_nexttcell = TargetCellExpPath(NextCand, NextPart, tv);
+
+ if (!has_nexttcell) {
+ NextCand->firstsingcode = NextCand->pathsingcode;
+ if (tv->options->verbosity >= 2) {
+ if (tv->tolevel_tl-tv->tolevel >= 6) {
+ PRINT_EXPPATHSTEP(NextCand, TRUE)
+ }
+ else {
+ fprintf(outfile, "(%d) ", tv->tolevel_tl);
+ }
+ }
+ break;
+ }
+ ExperimentalStep(NextPart, NextCand, tv, ti, m, n);
+ if (NextPart->cells == n) {
+ has_nexttcell = FALSE;
+ }
+ PRINT_EXPPATHSTEP(NextCand, TRUE)
+ }
+ if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
+ }
+ }
+ else {
+ if (closeloop < tv->tolevel) k = SpineTL->tgtend;
+ PRINT_RETURN
+ break;
+ }
+
+ if (!tv->strategy && !tv->options->getcanon && (tv->tolevel_tl == tv->tolevel + 1) && ((NextPart->cells > tv->finalnumcells) || (NextPart->cells == n))) { /* 160717 */
+ tv->levelfromCS0 = tv->tolevel;
+ tv->maxtreelevel = tv->tolevel_tl;
+ tv->finalnumcells = NextPart->cells;
+ if (tv->tolevel == 1) {
+ tv->newst_stage1 = searchtrie_make(CurrCand, NextCand, n, tv);
+ EXITFROMSTAGE0EXPATH1
+ }
+ else {
+ temp = 0;
+ for (i=0; i<tv->tolevel; i++) {
+ temp += Spine[i].listcounter;
+ }
+ if (temp > 5) {
+ tv->newst_stage1 = searchtrie_make(CurrCand, NextCand, n, tv);
+ EXITFROMSTAGE0EXPATH1
+ }
+ }
+ }
+
+ /* ANY AUTOMORPHISM? */
+ if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
+ tv->newindex = 0;
+ if (NextCand->do_it) {
+ closeloop = CheckForAutomorphisms(CurrCand, NextCand, tv, ti, m, n, NextPart);
+ if (!NextCand->do_it && closeloop < tv->tolevel) k = SpineTL->tgtend;
+ }
+ if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
+
+ if (NextCand->do_it) {
+ ADDTONEXTLEVEL;
+ SpineTL->keptcounter++;
+ searchtrie_make(CurrCand, SpineTL->listend, n, tv);
+ }
+ }
+ else {
+ if (BreakSteps[tv->tolevel]) {
+ NextCand->firstsingcode = NextCand->pathsingcode;
+ if (CheckForSingAutomorphisms(CurrCand, NextPart, NextCand, tv, ti, m, n))
+ if (!NextCand->do_it) {
+ PRINT_RETURN
+ break;
+ }
+ }
+
+ /* ANY AUTOMORPHISM? */
+ if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
+ tv->newindex = 0;
+ if (NextCand->do_it) {
+ closeloop = CheckForAutomorphisms(CurrCand, NextCand, tv, ti, m, n, NextPart);
+ if (!NextCand->do_it && closeloop < tv->tolevel) k = SpineTL->tgtend;
+ }
+ if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
+
+ if (NextCand->do_it) {
+ ADDTONEXTLEVEL;
+ SpineTL->keptcounter++;
+ searchtrie_make(CurrCand, SpineTL->listend, n, tv);
+ }
+ }
+ PRINT_RETURN
+ break;
+ case 2 : /* Delete the old list and start a new one: a better trace has been found */
+
+ if (NextPart->cells > tv->finalnumcells) {
+ tv->finalnumcells = NextPart->cells;
+ }
+ tv->tolevel_tl = tv->tolevel;
+ has_nexttcell = FALSE;
+ if (NextPart->cells == n) {
+ tv->stats->canupdates++;
+ if (tv->options->usercanonproc != NULL)
+ {
+ (*tv->options->usercanonproc)((graph*)tv->input_graph, NextCand->lab, (graph*)tv->cangraph, tv->stats->canupdates, NextCand->code, m, n);
+ }
+ }
+
+ if (tv->tolevel > tv->treedepth) {
+ tv->treedepth = tv->tolevel;
+ if (tv->strategy) {
+ SpineTL->part = NewPartition(n);
+ }
+ else {
+ NewPartSpine(tv->tolevel,n);
+ }
+ }
+
+ if (!tv->strategy && (tv->tolevel > 1) && !SpineTL->liststart) {
+ /* First Candidate at current level */
+ tv->maxtreelevel = tv->tolevel;
+
+ SpineTL->liststart = NewCandidate(n, &GarbList, TRUE);
+ SpineTL->listend = SpineTL->liststart;
+
+ tv->conta0++;
+ CopyCand(SpineTL->liststart, NextCand, n, TEMPLAB, TEMPINVLAB);
+ if (NextPart->cells < tv->finalnumcells) SpineTL->liststart->code = auxcode;
+ COPYPART(SpineTL->part, NextPart);
+ tv->newindex = 0;
+ tv->newst_stage1 = searchtrie_make(CurrCand, SpineTL->listend, n, tv);
+
+ SpineTL->listcounter = 1;
+ SpTLliststart = SpineTL->liststart;
+
+ i = tv->tolevel;
+ if (tv->brkstpcount) {
+ while ((i<n) && !BreakSteps[i]) {
+ i++;
+ }
+ if (i<n) SpineTL->liststart->firstsingcode = Spine[i].singcode;
+ }
+
+ SpineTL->updates = 1;
+ SpineTL->levelcounter = 1;
+ SpineTL->keptcounter = 1;
+
+ PRINT_LINE_PLUS(tv->fromlevel)
+
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(SpineTL->liststart, tv->tolevel);
+ PRINT_RETURN;
+
+ if (!tv->strategy && !tv->options->getcanon && (tv->tolevel+1 == tv->firstpathlength) && ((NextPart->cells > tv->finalnumcells) || (NextPart->cells == n))) {
+ tv->finalnumcells = NextPart->cells;
+ if ((tv->tolevel == 1) && (CurrPart->cls[tv->tcell] > 5)) {
+ EXITFROMSTAGE0EXPATH2;
+ }
+ else {
+ temp = 0;
+ for (i=0; i<tv->tolevel; i++) {
+ temp += Spine[i].listcounter;
+ }
+ if (temp > 5) {
+ EXITFROMSTAGE0EXPATH2;
+ }
+ }
+ }
+ }
+ else {
+ memset(WorkArray, 0, n*sizeof(int));
+
+ tv->lastcell = tv->lastlev = -1;
+ has_nexttcell = TargetCellFirstPath(NextCand, NextPart, tv);
+
+ if (!has_nexttcell) {
+ tv->stats->canupdates++;
+ if (tv->options->usercanonproc != NULL) {
+ (*tv->options->usercanonproc)((graph*)tv->input_graph, NextCand->lab, (graph*)tv->cangraph, tv->stats->canupdates, NextCand->code, m, n);
+ }
+ }
+
+ tv->tcellevel = tv->maxtreelevel = tv->tolevel;
+ SpineTL->levelcounter++;
+ SpineTL->updates++;
+ SpineTL->keptcounter = 1;
+
+ RemoveFromLevel(tv->tolevel, tv->treedepth, tv->strategy, TRUE);
+ SpineTL->liststart = NewCandidate(n, &GarbList, TRUE);
+ SpineTL->listend = SpineTL->liststart;
+
+ tv->conta0++;
+ CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL);
+ COPYPART(SpineTL->part, NextPart);
+
+ tv->newindex = 0;
+
+ tv->newst_stage1 = searchtrie_make(CurrCand, SpineTL->listend, n, tv);
+
+ SpineTL->listcounter = 1;
+ SpTLliststart = SpineTL->liststart;
+
+ SpTLliststart->pathsingcode = SpineTL->singcode = SpTLliststart->singcode;
+ SpTLliststart->firstsingcode = 0;
+
+ PRINT_LINE
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(SpTLliststart, tv->tolevel);
+
+ memset(BreakSteps, 0, n*sizeof(int));
+ tv->brkstpcount = 0;
+
+ if (tv->steps > 1) {
+
+ /* EXPERIMENTAL PATH */
+ if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
+ PRINTF2("CStage0 2: %d\n", tv->finalnumcells);
+ tv->finalnumcells = n;
+
+ while (has_nexttcell) {
+ ExperimentalStep(NextPart, SpTLliststart, tv, ti, m, n);
+
+ Spine[tv->tolevel_tl].singcode = SpTLliststart->pathsingcode;
+ has_nexttcell = TargetCellFirstPath(SpTLliststart, NextPart, tv);
+ PRINT_EXPPATHSTEP(SpTLliststart, TRUE)
+ }
+ if (NextPart->cells < n) {
+ PRINTF2("CStage0 3: %d\n", tv->finalnumcells);
+ tv->finalnumcells = minint(NextPart->cells,tv->finalnumcells); /* 160712 */
+ tv->finalnumcells = NextPart->cells;
+
+ PRINTF2("CStage0 3<: %d\n", tv->finalnumcells);
+ }
+
+ PRINTF2("CS0 2?: finalnumcells: %d\n", tv->finalnumcells);
+ if (NextPart->cells == tv->finalnumcells) {
+ UPDATEMIN(tv->expathlength, tv->tolevel_tl);
+ }
+
+ if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
+
+ tv->firstpathlength = tv->tolevel_tl;
+ PRINT_RETURN
+ if (!tv->strategy && !tv->options->getcanon && (NextPart->cells == tv->finalnumcells) && (tv->tolevel_tl == tv->tolevel + 1) && ((NextPart->cells > tv->finalnumcells) || (NextPart->cells == n))) {
+ tv->maxtreelevel = tv->tolevel_tl;
+ tv->finalnumcells = NextPart->cells;
+ if ((tv->tolevel == 1) && (CurrPart->cls[tv->tcell] > 5)) {
+ EXITFROMSTAGE0EXPATH2
+ }
+ else {
+ temp = 0;
+ for (i=0; i<tv->tolevel; i++) {
+ temp += Spine[i].listcounter;
+ }
+ if (temp > 5) {
+ EXITFROMSTAGE0EXPATH2
+ }
+ }
+ }
+ memcpy(TEMPLAB, SpTLliststart->lab, n*sizeof(int));
+ memcpy(TEMPINVLAB, SpTLliststart->invlab, n*sizeof(int));
+ tv->conta5++;
+ }
+ else {
+ PRINT_RETURN
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ } /* end for */
+ }
+ }
+ }
+
+ /* REMOVE CURRENT CANDIDATE */
+ if (SpineFL->liststart && (k >= SpineTL->tgtend)) {
+ SpineFL->liststart = CurrCand->next;
+ if (CurrCand->next == NULL) {
+ SpineFL->listend = NULL;
+ }
+ SpineFL->listcounter--;
+ CurrCand->next = GarbList;
+ GarbList = CurrCand;
+ }
+ ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
+ return 0;
+}
+
+int CompStage1(Partition *CurrPart, Partition *NextPart, Candidate *CurrCand, Candidate *NextCand,
+ int m, int n,
+ struct TracesVars* tv, struct TracesInfo *ti) {
+ int i, k, cu, cu1, tmp, gom_level, search_vtx, temp;
+ searchtrie *TreeNode, *TrieNode;
+
+#ifdef NAUTY_IN_MAGMA
+ if (main_seen_interrupt) return NAUTY_KILLED;
+#else
+ if (nauty_kill_request) return NAUTY_KILLED;
+#endif
+
+ CurrCand->stnode = tv->newst_stage1;
+
+ tv->tolevel++;
+ SpineTL = Spine+tv->tolevel;
+ tv->tcell = SpineTL->tgtcell;
+ SpineTL->levelcounter = 0;
+ SpineTL->keptcounter = 0;
+ SpineTL->updates = 1;
+
+
+ if (tv->options->verbosity >= 2) {
+ LINE(32, "=")
+ NEXTLINE
+ }
+
+ memset(RefCells, 0, n*sizeof(int));
+ memset(MultRefCells, 0, n*sizeof(int));
+ ti->thegrouphaschanged = TRUE;
+
+ /* CANDIDATE */
+ memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
+ memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
+ NextCand->do_it = TRUE;
+ SpineTL->trcstart = CurrPart->cells;
+
+ tv->indivstart = tv->tcell;
+ tv->indivend = SpineTL->tgtend;
+ if (TheGraph[CurrCand->lab[tv->indivstart]].d == 1) {
+ tv->indivstart = SpineTL->tgtend-1;
+ }
+
+ FixBase(fix, tv, NextCand, 0, tv->fromlevel);
+
+ if (!ti->identitygroup) {
+ if (tv->options->verbosity >= 2) tv->schreier2 -= CPUTIME;
+ tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
+ if (tv->options->verbosity >= 2) tv->schreier2 += CPUTIME;
+ }
+ else {
+ memcpy(tv->currorbit, IDENTITY_PERM, n*sizeof(int));
+ }
+
+ if (!CurrCand->sortedlab) {
+ quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
+ for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
+ CurrCand->invlab[CurrCand->lab[i]] = i;
+ }
+ CurrCand->sortedlab = TRUE;
+ }
+ for (k = tv->indivstart; k < tv->indivend; k++) {
+ NextCand->vertex = CurrCand->lab[k];
+ NextCand->name = ++tv->name;
+ if (NextCand->name == (NAUTY_INFINITY-2)) {
+ NextCand->name = tv->name = 1;
+ }
+ if (tv->currorbit[CurrCand->lab[k]] != CurrCand->lab[k]) {
+ search_vtx = tv->currorbit[NextCand->vertex];
+ TreeNode = CurrCand->stnode;
+ if (TreeNode->first_child) {
+ TreeNode = TreeNode->first_child;
+ while (TreeNode) {
+ if (TreeNode->vtx == search_vtx) {
+ break;
+ }
+ TreeNode = TreeNode->next_sibling;
+ }
+ if (TreeNode) {
+ while (TreeNode->goes_to) {
+ TreeNode = TreeNode->goes_to;
+ }
+ TreeNode->index++;
+ PRINT_INDEX(TreeNode,4,27)
+ }
+ }
+ continue;
+ }
+ PRINT_REFINE_VERB(4,'b')
+ memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
+ memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
+
+ Individualize(NextPart, NextCand, CurrCand->lab[k], tv->tcell, CurrPart->cells, SpineTL->tgtpos);
+
+ tv->stats->numnodes++;
+ SpineTL->levelcounter++;
+ tv->tolevel_tl = tv->tolevel;
+ trieref = trieroot;
+ SpineTL->levelcounter++;
+
+ traces_refine_maketrie(NextCand,
+ n,
+ NextPart, tv, ti);
+
+ RefCells[CurrCand->lab[k]] = NextPart->cells;
+ PRINTF2("CS1 1?: finalnumcells: %d\n", tv->finalnumcells);
+ if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel);
+
+ /* ANY AUTOMORPHISM? */
+ if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
+
+ PRINTF2("CS1 2?: finalnumcells: %d\n", tv->finalnumcells);
+ CheckForAutomorphisms(CurrCand, NextCand, tv, ti, m, n, NextPart);
+ if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
+
+ PRINT_RETURN
+
+ /* ADD TO NEXT LEVEL */
+ SpineTL->keptcounter++;
+ if (!Spine[tv->tolevel].listend) COPYPART(Spine[tv->tolevel].part, NextPart);
+ ADDTONEXTLEVEL;
+ searchtrie_make(CurrCand, SpineTL->listend, n, tv);
+ }
+ } /* end for */
+ PRINTF2("CS1 3: finalnumcells: %d\n", tv->finalnumcells);
+ for (k = tv->indivstart; k < tv->indivend; k++) {
+ MultRefCells[RefCells[tv->currorbit[CurrCand->lab[k]]] % n]++;
+ }
+
+ if (tv->options->verbosity >= 2) {
+ if (MultRefCells[0]) {
+ fprintf(outfile, tv->digstring, n);
+ fprintf(outfile, "cells: %d; ", MultRefCells[0]);
+ }
+ for (k=1; k<n; k++) {
+ if (MultRefCells[k]) {
+ fprintf(outfile, tv->digstring, k);
+ fprintf(outfile, "cells: %d; ", MultRefCells[k]);
+ }
+ }
+ NEXTLINE
+
+ }
+
+#if !MAXN
+ DYNALLOC1(searchtrie*, RefPath, RefPath_sz, tv->tolevel, "Traces-CS1");
+#endif
+
+ TreeNode = CurrCand->stnode;
+ while (TreeNode) {
+ RefPath[TreeNode->level] = TreeNode;
+ TreeNode = TreeNode->father;
+ }
+
+ /* REMOVE CURRENT CANDIDATE */
+ SpineFL->liststart = CurrCand->next;
+ if (CurrCand->next == NULL) {
+ SpineFL->listend = NULL;
+ SpineFL->listcounter = 1;
+ }
+ SpineFL->listcounter--;
+ CurrCand->next = GarbList;
+ GarbList = CurrCand;
+
+ if (tv->options->verbosity >= 2) {
+ LINE(32, "=")
+ NEXTLINE
+ }
+ tv->compstage = 2;
+ tv->steps = n;
+
+ if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
+
+ gom_level = getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit,
+ CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell], n, TRUE);
+ if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
+ ORBITSIZES
+ ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
+ PRINTF2("CS1 4: finalnumcells: %d\n", tv->finalnumcells);
+ SpineTL->part->cells = tv->finalnumcells;
+
+ AutomCount[0] = 2;
+ AutomCount[1] = CurrCand->vertex;
+
+ return 0;
+}
+
+int CompStage2(Partition *CurrPart, Partition *NextPart, Candidate *CurrCand, Candidate *NextCand,
+ int m, int n,
+ struct TracesVars* tv, struct TracesInfo *ti) {
+ int i, j, i1, j2, k, cu, cu1, vertex, gom_level;
+ int temp, tmp, autom;
+ Candidate *AuxCand;
+ searchtrie *TreeNode, *TreeNode1, *TreeNode2;
+ int *CuOrb,*AuxOrb;
+ boolean has_nexttcell = FALSE;
+ searchtrie *TrieNode;
+ boolean schreierwrong;
+
+#ifdef NAUTY_IN_MAGMA
+ if (main_seen_interrupt) return NAUTY_KILLED;
+#else
+ if (nauty_kill_request) return NAUTY_KILLED;
+#endif
+
+ autom = 0;
+ schreierwrong = FALSE;
+
+ TreeNode = CurrCand->stnode;
+ tv->cand_level = 0;
+
+ while (TreeNode) {
+ if (TreeNode->goes_to) {
+ CurrCand->do_it = FALSE;
+ }
+ if (!tv->cand_level && TreeNode == RefPath[TreeNode->level]) {
+ tv->cand_level = TreeNode->level;
+ }
+ TreeNode = TreeNode->father;
+ }
+ if (tv->cand_level+1 == tv->maxtreelevel) {
+ ti->useTempOrbits1 = TRUE;
+ }
+ else {
+ ti->useTempOrbits1 = FALSE;
+ }
+ if (tv->cand_level == tv->fromlevel) {
+ ti->useTempOrbits2 = TRUE;
+ }
+ else {
+ ti->useTempOrbits2 = FALSE;
+ }
+
+ PRINT_FROM_VERB(4,tv->tolevel)
+
+ if (CurrCand->do_it) {
+ if (tv->tolevel == 0) {
+ vertex = Spine[tv->maxtreelevel+1].liststart->lab[Spine[1].tgtpos];
+ k = n;
+
+ tv->fromlevel = tv->tolevel++;
+ SpineFL = Spine+tv->fromlevel;
+ SpineTL = Spine+tv->tolevel;
+ tv->tcell = Spine[tv->tolevel].tgtcell;
+
+ memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
+ memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
+ SpineTL->trcstart = CurrPart->cells;
+ TheTrace[SpineTL->trcstart] = SpineTL->tgtpos;
+
+ tv->indivstart = tv->tcell+CurrCand->indnum;
+ tv->indivend = tv->indivstart+tv->steps;
+ if (tv->indivend > SpineTL->tgtend) {
+ tv->indivend = SpineTL->tgtend;
+ }
+ memset(CurrRefCells, 0, n*sizeof(int));
+ ti->thegrouphaschanged = TRUE;
+
+ if (!CurrCand->sortedlab) {
+ quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
+ for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
+ CurrCand->invlab[CurrCand->lab[i]] = i;
+ }
+ CurrCand->sortedlab = TRUE;
+ }
+
+ for (k = tv->indivstart; k < tv->indivend; k++) {
+ if ((tv->orbits[CurrCand->lab[k]] == CurrCand->lab[k]) && ((tv->finalnumcells < n) || (OrbSize[tv->orbits[CurrCand->lab[k]]] >= OrbSize[tv->orbits[vertex]]))) {
+
+ CurrCand->indnum++;
+ NextCand->singcode = CurrCand->singcode;
+ NextCand->vertex = CurrCand->lab[k];
+ NextCand->name = ++tv->name;
+ if (NextCand->name == (NAUTY_INFINITY-2)) {
+ NextCand->name = tv->name = 1;
+ }
+
+ if (ti->thegrouphaschanged) {
+ if (tv->fromlevel == tv->maxtreelevel) {
+ CURRORBITSIZES
+ }
+ ti->thegrouphaschanged = FALSE;
+ }
+
+ if (tv->currorbit[CurrCand->lab[k]] != CurrCand->lab[k]) {
+ continue;
+ }
+
+ memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
+ memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
+ if (NextPart->cls[tv->tcell] == 2) {
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell]);
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell+1]);
+ }
+ else {
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[k]+labelorg);
+ }
+
+ Individualize(NextPart, NextCand, CurrCand->lab[k], tv->tcell, CurrPart->cells, SpineTL->tgtpos);
+
+ tv->stats->numnodes++;
+ Spine[tv->tolevel+1].levelcounter++;
+ if (tv->fromlevel == tv->maxtreelevel) {
+ tv->tolevel_tl = tv->tolevel;
+ trieref = trieroot;
+
+ tv->answ = traces_refine_comptrie(NextCand,
+ n,
+ NextPart, tv, ti);
+ if (tv->answ) {
+ if (NextPart->cells != tv->finalnumcells) {
+ CurrRefCells[NextPart->cells % n] += CurrOrbSize[CurrCand->lab[k]];
+ if (CurrRefCells[NextPart->cells % n] > MultRefCells[NextPart->cells % n]) {
+ k = n;
+ break;
+ }
+ continue;
+ }
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel)
+ }
+ }
+ else {
+ tv->answ = traces_refine_sametrace(NextCand,
+ n,
+ NextPart, tv, ti);
+
+ if (tv->answ) {
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel)
+ if (tv->tolevel == tv->maxtreelevel) {
+ tv->tolevel_tl = tv->tolevel;
+ if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
+ TargetCellExpPath(NextCand, NextPart, tv);
+ ExperimentalStep(NextPart, NextCand, tv, ti, m, n);
+ PRINT_EXPPATHSTEP(NextCand, tv->answ)
+ PRINTF2("CS2 1?: finalnumcells: %d\n", tv->finalnumcells);
+ if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
+ UPDATEMIN(tv->expathlength, tv->tolevel_tl);
+ }
+
+ if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
+ if (!tv->answ) {
+ PRINT_RETURN
+ }
+ }
+ }
+ }
+ if (tv->answ) {
+ PRINTF2("CS2 2?: finalnumcells: %d\n", tv->finalnumcells);
+ if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
+ if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
+ temp = (tv->tolevel_tl == tv->tolevel+1);
+ autom = CheckForAutomorphisms(CurrCand, NextCand,
+ tv, ti, temp, n, NextPart);
+ if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
+
+ if (ti->thegrouphaschanged) {
+ ORBITSIZES
+ }
+ }
+ PRINT_RETURN
+
+ /* ADD TO NEXT LEVEL */
+ PRINTF2_2("CS2 3?: cells: %d, finalnumcells: %d\n", NextPart->cells, tv->finalnumcells);
+ if ((NextPart->cells != tv->finalnumcells) || (tv->tolevel != tv->maxtreelevel) || (tv->tolevel_tl != tv->tolevel+1)) {
+ ADDTONEXTLEVEL;
+ searchtrie_make(CurrCand, SpineTL->listend, n, tv);
+ }
+ }
+ else {
+ tv->stats->interrupted++;
+ }
+ if (tv->fromlevel == tv->maxtreelevel) {
+ k = n;
+ break;
+ }
+ }
+ } /* end for */
+ }
+ else {
+
+ temp = CurrCand->lab[Spine[1].tgtpos];
+ vertex = Spine[tv->maxtreelevel+1].liststart->lab[Spine[1].tgtpos];
+ k = n;
+
+ if (tv->cand_level ||
+ ((tv->orbits[temp] == temp) && ((tv->finalnumcells < n) || (OrbSize[tv->orbits[temp]] >= OrbSize[tv->orbits[vertex]])))) {
+ tv->fromlevel = tv->tolevel++;
+ SpineFL = Spine+tv->fromlevel;
+ SpineTL = Spine+tv->tolevel;
+ tv->tcell = Spine[tv->tolevel].tgtcell;
+
+ ti->minimalinorbits = TRUE;
+
+ if (!ti->identitygroup) {
+
+ if (ti->useTempOrbits1 && ti->useTempOrbits2) {
+ CuOrb = TempOrbits;
+ }
+ else {
+ FixBase(fix, tv, CurrCand, 0, tv->fromlevel);
+ if (ti->useTempOrbits1 && tv->fromlevel == tv->maxtreelevel) {
+ tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
+ CuOrb = tv->currorbit;
+ }
+ else {
+ if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
+
+ gom_level = getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit,
+ CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell], n, TRUE);
+ if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
+
+ CuOrb = tv->currorbit;
+ if (gom_level < tv->nfix) {
+ PRINT_NOTMIN_VERB(4)
+ if (ti->useTempOrbits1) {
+ for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == CuOrb[tv->currorbit[CurrCand->vertex]]) break;
+ if (i < AutomCount[0]) {
+ AutomCount[AutomCount[0]++] = CurrCand->vertex;
+ }
+ ti->minimalinorbits = FALSE;
+ }
+ else {
+ TreeNode = CurrCand->stnode;
+ j2 = CurrCand->lab[Spine[gom_level+1].tgtpos];
+ i1 = tv->currorbit[j2];
+ for (j=0; j < tv->nfix - gom_level; j++) {
+ TreeNode = TreeNode->father;
+ }
+ TreeNode1 = TreeNode->first_child;
+ while (TreeNode1) {
+ if (TreeNode1->vtx == i1) {
+ break;
+ }
+ TreeNode1 = TreeNode1->next_sibling;
+ }
+ schreierwrong = FALSE;
+ if (TreeNode1) {
+ while (TreeNode1->goes_to) {
+ TreeNode1 = TreeNode1->goes_to;
+ }
+ TreeNode2 = TreeNode->first_child;
+ while (TreeNode2->vtx != j2) {
+ TreeNode2 = TreeNode2->next_sibling;
+ }
+
+ TreeNode1->index += TreeNode2->index;
+ TreeNode2->goes_to = TreeNode1;
+ PRINT_INDEX(TreeNode1,4,28)
+ PRINT_INDEX(TreeNode2,4,29)
+ ti->minimalinorbits = FALSE;
+ }
+ else {
+ tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
+ schreierwrong = TRUE;
+ }
+ }
+ }
+ }
+ }
+ ti->thegrouphaschanged = FALSE;
+ }
+ else {
+ CuOrb = IDENTITY_PERM;
+ }
+
+ if (ti->minimalinorbits) {
+ memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
+ memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
+ SpineTL->trcstart = CurrPart->cells;
+ TheTrace[SpineTL->trcstart] = SpineTL->tgtpos;
+
+ tv->indivstart = tv->tcell+CurrCand->indnum;
+ tv->indivend = tv->indivstart+tv->steps;
+ if (tv->indivend > SpineTL->tgtend) {
+ tv->indivend = SpineTL->tgtend;
+ }
+ memset(CurrRefCells, 0, n*sizeof(int));
+ ti->thegrouphaschanged = TRUE;
+
+ if (!CurrCand->sortedlab) {
+ quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
+ for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
+ CurrCand->invlab[CurrCand->lab[i]] = i;
+ }
+ CurrCand->sortedlab = TRUE;
+ }
+
+ for (k = tv->indivstart; k < tv->indivend; k++) {
+ CurrCand->indnum++;
+ NextCand->singcode = CurrCand->singcode;
+ NextCand->vertex = CurrCand->lab[k];
+ NextCand->name = ++tv->name;
+ if (NextCand->name == (NAUTY_INFINITY-2)) {
+ NextCand->name = tv->name = 1;
+ }
+
+ if (ti->thegrouphaschanged) {
+ if (tv->fromlevel == tv->maxtreelevel) {
+ CURRORBITSIZES
+ }
+ ti->thegrouphaschanged = FALSE;
+ }
+
+ if (!schreierwrong) {
+ if (CuOrb[CurrCand->lab[k]] != CurrCand->lab[k]) {
+ continue;
+ }
+ }
+
+ memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
+ memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
+ if (NextPart->cls[tv->tcell] == 2) {
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell]);
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell+1]);
+ }
+ else {
+ NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[k]);
+ }
+
+ Individualize(NextPart, NextCand, CurrCand->lab[k], tv->tcell, CurrPart->cells, SpineTL->tgtpos);
+
+ tv->stats->numnodes++;
+ Spine[tv->tolevel+1].levelcounter++;
+ if (tv->fromlevel == tv->maxtreelevel) {
+ tv->tolevel_tl = tv->tolevel;
+ trieref = trieroot;
+
+ tv->answ = traces_refine_comptrie(NextCand,
+ n,
+ NextPart, tv, ti);
+
+ if (tv->answ) {
+ PRINTF2("CS2 4?: finalnumcells: %d\n", tv->finalnumcells);
+ if (NextPart->cells != tv->finalnumcells) {
+ CurrRefCells[NextPart->cells % n] += CurrOrbSize[CurrCand->lab[k]];
+ if (CurrRefCells[NextPart->cells % n] > MultRefCells[NextPart->cells % n]) {
+ k = n;
+ break;
+ }
+ continue;
+ }
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel);
+ }
+ }
+ else
+ {
+ tv->answ = traces_refine_sametrace(NextCand,
+ n,
+ NextPart, tv, ti);
+
+ if (tv->answ) {
+ if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel)
+ if (tv->tolevel == tv->maxtreelevel) {
+ tv->tolevel_tl = tv->tolevel;
+ if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
+ if (TargetCellExpPath(NextCand, NextPart, tv)) {
+ ExperimentalStep(NextPart, NextCand, tv, ti, m, n);
+ PRINT_EXPPATHSTEP(NextCand, tv->answ)
+ PRINTF2("CS2 5?: finalnumcells: %d\n", tv->finalnumcells);
+ if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
+ UPDATEMIN(tv->expathlength, tv->tolevel_tl);
+ }
+
+ }
+ if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
+ if (!tv->answ) {
+ PRINT_RETURN
+ }
+ }
+ }
+ }
+ if (tv->answ) {
+ PRINTF2("CS2 6?: finalnumcells: %d\n", tv->finalnumcells);
+ if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
+ if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
+ temp = (tv->tolevel_tl == tv->tolevel+1);
+ autom = CheckForAutomorphisms(CurrCand, NextCand,
+ tv, ti, temp, n, NextPart);
+ if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
+ if (autom) {
+ for (i=autom; i<=tv->maxtreelevel; i++) {
+ AuxCand = Spine[i].liststart;
+ while (AuxCand && Prefix(AuxCand, NextCand, autom)) {
+ AuxCand->do_it = FALSE;
+ AuxCand = AuxCand->next;
+ }
+ }
+ if (autom == tv->tolevel) {
+ autom = 0;
+ }
+ }
+
+ if (ti->thegrouphaschanged) {
+ ORBITSIZES
+ }
+ }
+ PRINT_RETURN
+
+ /* ADD TO NEXT LEVEL */
+ PRINTF2("CS2 7?: finalnumcells: %d\n", tv->finalnumcells);
+ if ((NextPart->cells != tv->finalnumcells) || (tv->tolevel != tv->maxtreelevel) || (tv->tolevel_tl != tv->tolevel+1)) {
+ ADDTONEXTLEVEL;
+ searchtrie_make(CurrCand, SpineTL->listend, n, tv);
+ }
+ }
+ else {
+ tv->stats->interrupted++;
+ }
+ if (autom) {
+ k = n;
+ autom = 0;
+ break;
+ }
+ if (tv->fromlevel == tv->maxtreelevel) {
+ k = n;
+ break;
+ }
+ } /* end for */
+ TreeNode = RefPath[tv->maxtreelevel];
+ }
+ }
+ else SpineTL = &Spine[tv->tolevel+1];
+ }
+
+ }
+
+ /* REMOVE CURRENT CANDIDATE */
+ if (!CurrCand->do_it || k >= SpineTL->tgtend) {
+ SpineFL->liststart = CurrCand->next;
+ if (CurrCand->next == NULL) {
+ SpineFL->listend = NULL;
+ }
+ CurrCand->next = GarbList;
+ GarbList = CurrCand;
+ }
+ ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
+ return 0;
+}
+
+void CopyCand(Candidate *W, Candidate *V,int n, int *lab, int *invlab) {
+
+ if (lab) {
+ memcpy(W->lab, lab, n*sizeof(int));
+ memcpy(W->invlab, invlab, n*sizeof(int));
+ }
+ else {
+ memcpy(W->lab, V->lab, n*sizeof(int));
+ memcpy(W->invlab, V->invlab, n*sizeof(int));
+ }
+ W->name = V->name;
+ W->vertex = V->vertex;
+ W->code = V->code;
+ W->singcode = V->singcode;
+ W->firstsingcode = V->firstsingcode;
+ W->do_it = V->do_it;
+ W->sortedlab = FALSE;
+}
+
+sparsegraph* copy_sg_structure(sparsegraph *sg2, sparsegraph *sg1) {
+ int *d1, *e1, *d2, *e2;
+ int i, n;
+ size_t *v1, *v2, k;
+
+ if (!sg2)
+ {
+ if ((sg2 = (sparsegraph*)ALLOCS(1, sizeof(sparsegraph))) == NULL)
+ {
+ fprintf(ERRFILE, "copy_sg: malloc failed\n");
+ exit(1);
+ }
+ SG_INIT(*sg2);
+ }
+
+ SG_VDE(sg1, v1, d1, e1);
+
+ n = sg1->nv;
+
+ k = 0;
+ for (i = 0; i < n; ++i)
+ if (v1[i]+d1[i]>k) k = v1[i] + d1[i];
+ SG_ALLOC(*sg2, n, k, "copy_sg malloc");
+
+ sg2->nv = n;
+ sg2->nde = sg1->nde;
+ sg2->elen = k;
+ /* sg2->wlen = k; */
+ return sg2;
+}
+
+void Edge_Delete(int vertex, int sons, Candidate *Cand, TracesVars *tv) {
+ int d_vtx, j1, temp;
+ int *sge, *sgw;
+
+ if (TheGraph[vertex].d <= 1) {
+ return;
+ }
+
+ d_vtx = TheGraph[vertex].d = TheGraph[vertex].d - sons;
+ sge = TheGraph[vertex].e;
+ sgw = TheGraph[vertex].w;
+
+ for (j1=0; j1<d_vtx; j1++) {
+ if (TheGraph[sge[j1]].one) {
+ while (TheGraph[sge[TheGraph[vertex].d]].d == -1) {
+ (TheGraph[vertex].d)++;
+ }
+ temp = sge[j1];
+ sge[j1] = sge[TheGraph[vertex].d];
+ sge[TheGraph[vertex].d] = temp;
+ if (sgw) {
+ temp = sgw[j1];
+ sgw[j1] = sgw[TheGraph[vertex].d];
+ sgw[TheGraph[vertex].d] = temp;
+ }
+ }
+ }
+ TheGraph[vertex].d = d_vtx;
+}
+
+void ExperimentalStep(Partition *NextPart, Candidate *NextCand,
+ TracesVars *tv, TracesInfo *ti, int m, int n) {
+ int i, iend, min, tmp;
+
+ SpineTL_tl = Spine+tv->tolevel_tl;
+ NextPart->active = 1;
+ VERB_PRINT("EXSTP ",3,FALSE)
+ if (SpineTL_tl) {
+ }
+
+ /* EXPERIMENTAL PATH INDIVIDUALIZATION AND REFINEMENT */
+ if (tv->answ == 2) {
+ min = NextCand->lab[tv->tcellexpath];
+ tmp = tv->tcellexpath;
+ iend = tv->tcellexpath + NextPart->cls[tv->tcellexpath];
+ for (i=tv->tcellexpath + 1; i<iend ; i++) {
+ if (NextCand->lab[i] < min) {
+ min = NextCand->lab[i];
+ tmp = i;
+ }
+ }
+ }
+ else {
+ tmp = tv->tcellexpath+KRAN(NextPart->cls[tv->tcellexpath]);
+ }
+ if (NextPart->cls[tv->tcellexpath] == 2) {
+ NextCand->pathsingcode = MASHCOMM(NextCand->pathsingcode, NextCand->lab[tv->tcellexpath]);
+ NextCand->pathsingcode = MASHCOMM(NextCand->pathsingcode, NextCand->lab[tv->tcellexpath+1]);
+ }
+ else {
+ NextCand->pathsingcode = MASHCOMM(NextCand->pathsingcode, NextCand->lab[tmp]);
+ }
+
+ tv->indiv_vtx = NextCand->lab[tmp];
+ Individualize(NextPart, NextCand, NextCand->lab[tmp], tv->tcellexpath, NextPart->cells, tv->tcellexpath + NextPart->cls[tv->tcellexpath]-1);
+
+ tv->stats->numnodes++;
+ if (tv->compstage == 0) {
+ traces_refine_notrace(NextCand,
+ n,
+ NextPart, tv, ti);
+ }
+ else {
+ if (tv->tolevel_tl == tv->maxtreelevel+1) {
+ trieref = trieroot;
+ tv->answ = traces_refine_comptrie(NextCand,
+ n,
+ NextPart, tv, ti);
+ if (tv->answ == 0 ) {
+ tv->stats->interrupted++;
+ }
+ }
+ else {
+ traces_refine_notrace(NextCand,
+ n,
+ NextPart, tv, ti);
+ }
+ }
+
+ CodeClassify(tv->tolevel_tl, NextCand->code, tv->tcellexpath);
+
+}
+
+void factorial(double *size1, int *size2, int k) {
+ int i;
+
+ for(i = k; i; i--) {
+ MULTIPLY(*size1, *size2, i);
+ }
+}
+
+void factorial2(double *size1, int *size2, int k) {
+ int i;
+
+ for(i = k; i > 0; i -= 2) {
+ MULTIPLY(*size1, *size2, i);
+ }
+}
+
+boolean findperm(permnode *pn, int *p, int n) {
+ permnode *rn;
+
+ if (!pn) {
+ return FALSE;
+ }
+ rn = pn;
+ do {
+ if (!memcmp(rn->p, p, n*sizeof(int))) {
+ return TRUE;
+ }
+ rn = rn->next;
+ } while (rn != pn);
+ return FALSE;
+}
+
+int *findcurrorbits(schreier *gp, int k) {
+ int i;
+ schreier *sh;
+
+ sh = gp;
+ for (i = 0; i < k; i++) {
+ sh = sh->next;
+ }
+ return sh->orbits;
+}
+
+int FirstNeighbour(int vtx, Candidate *Cand, Partition *Part, int* Markers, int mark, int *ngh, int n) {
+ int *e_vtx;
+ int i, k, deg;
+ int ngh1, ngh2, cell1, cell2;
+
+ k = 0;
+
+ deg = TheGraph[vtx].d;
+ e_vtx = TheGraph[vtx].e;
+
+ if (deg == n-1) {
+ return 0;
+ }
+
+ for (i=0; i<deg; i++) {
+ if (Markers[e_vtx[i]] != mark) {
+ cell1 = Part->inv[Cand->invlab[e_vtx[i]]];
+ if (Part->cls[cell1] > 1) {
+ ngh1 = e_vtx[i++];
+ k++;
+ break;
+ }
+ }
+ }
+ for (; i<deg; i++) {
+ if (Markers[e_vtx[i]] != mark) {
+ cell2 = Part->inv[Cand->invlab[e_vtx[i]]];
+ if (Part->cls[cell2] > 1) {
+ ngh2 = e_vtx[i];
+ k++;
+ break;
+ }
+ }
+ }
+ switch (k) {
+ case 0:
+ break;
+
+ case 1:
+ *ngh = ngh1;
+ break;
+
+ case 2:
+ if (cell1 < cell2) {
+ *ngh = ngh1;
+ }
+ else {
+ *ngh = ngh2;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return k;
+}
+
+int FixBase(int *fix, struct TracesVars *tv, Candidate *Cand, int from, int to) {
+ int i, j, k, go, nfix;
+
+ nfix = j = 0;
+ go = TRUE;
+ for (i = from; i < to; i++) {
+ k = Cand->lab[Spine[i+1].tgtpos];
+ if (go && (nfix < tv->nfix) && (fix[nfix] == k)) {
+ j++;
+ }
+ else {
+ fix[nfix] = k;
+ if (go) go = FALSE;
+ }
+ nfix++;
+ }
+ tv->nfix = nfix;
+ return j;
+}
+
+boolean FixedBase(int *fix, struct TracesVars *tv, Candidate *Cand, int from, int to) {
+ int i, k, nfix;
+
+ nfix = 0;
+ for (i = from; i < to; i++) {
+ k = Cand->lab[Spine[i+1].tgtpos];
+ if (fix[nfix] != k) {
+ return FALSE;
+ }
+ nfix++;
+ }
+ return TRUE;
+}
+
+int FreeList(Candidate *List, int cond) {
+ Candidate *Temp;
+ int conta = 0;
+ int conta1 = 0;
+
+ while (List) {
+ if (List->do_it == cond) {
+ conta1++;
+ }
+ conta++;
+ Temp = List;
+ if (List->lab) free(List->lab);
+ if (List->invlab) free(List->invlab);
+ List = List->next;
+ free(Temp);
+ }
+
+ if (cond) {
+ return conta1;
+ }
+ else {
+ return conta;
+ }
+}
+
+/* Check if the permutations in the list gens are automorphisms,
+ * also set mark and refcount fields and initialise orbits. */
+int given_gens(sparsegraph *g, permnode *gens, int *orbits, boolean digraph) {
+ int i, m, n, norbs;
+ permnode *pn;
+
+ n = g->nv;
+ for (i = 0; i < n; ++i) orbits[i] = i;
+ memcpy(IDENTITY_PERM, orbits, n*sizeof(int));
+ norbs = n;
+
+ if (!gens) return norbs;
+
+ m = SETWORDSNEEDED(n);
+ pn = gens;
+ do {
+ if (!isautom_sg((graph*)g, pn->p, digraph, m, n)) {
+ fprintf(ERRFILE, "Input permutation is not an automorphism\n");
+ exit(1);
+ }
+ norbs = orbjoin(orbits, pn->p, n);
+ pn->mark = 1;
+ pn->refcount = 0;
+ pn = pn->next;
+ } while (pn != gens);
+
+ return norbs;
+}
+
+void grouporderplus(sparsegraph *sg_orig, Candidate *Cand, Partition *Part, permnode **ring,
+ double *grpsize1, int *grpsize2, int n, TracesVars *tv, TracesInfo *ti) {
+
+ int i, i1, j, j0, j2, k, k1, k2, w, w1, w2, c, c1, c2, n1, n2;
+ int prev, step, start, counts, StInd, CyInd, cycnum;
+ int tmp, temp, halfsize, nghcell, numvertices;
+ int arg, val;
+
+ searchtrie *TrieNode;
+ int NSFCInd, ind;
+ boolean do_ngh = FALSE;
+
+ numvertices = n;
+ memcpy(CanonIndices, IDENTITY_PERM, n*sizeof(int));
+ memset(TreeNodes, 0, n*sizeof(int));
+
+ TrieNode = Spine[tv->maxtreelevel].liststart->stnode;
+ if (TrieNode->father) {
+ if (tv->options->verbosity >= 2) {
+ LINE(32, "-")
+ NEXTLINE
+ fprintf(outfile, "group structure: ");
+ while (TrieNode->father) {
+ if (Factorials[TrieNode->level]) {
+ fprintf(outfile, "%d (%d!), ", TrieNode->name, TrieNode->index);
+ factorial(grpsize1, grpsize2, TrieNode->index);
+ } else {
+ if (TrieNode->father->name) {
+ fprintf(outfile, "%d (%d), ", TrieNode->name, TrieNode->index);
+ MULTIPLY(tv->stats->grpsize1, tv->stats->grpsize2, TrieNode->index);
+ }
+ else {
+ temp = spinelementorbsize(tv->orbits, Spine[tv->maxtreelevel].liststart->lab+Spine[1].tgtcell, Spine[1].tgtsize, TrieNode->vtx);
+ MULTIPLY(*grpsize1, *grpsize2, temp);
+ fprintf(outfile, "%d (%d)\n",
+ TrieNode->name, temp);
+ }
+ }
+ TrieNode = TrieNode->father;
+ }
+ }
+ else {
+ while (TrieNode->father) {
+ if (Factorials[TrieNode->level]) {
+ factorial(grpsize1, grpsize2, TrieNode->index);
+ } else {
+ if (TrieNode->father->name) {
+ MULTIPLY(tv->stats->grpsize1, tv->stats->grpsize2, TrieNode->index);
+ }
+ else {
+ temp = spinelementorbsize(tv->orbits, Spine[tv->maxtreelevel].liststart->lab+Spine[1].tgtcell, Spine[1].tgtsize, TrieNode->vtx);
+ MULTIPLY(*grpsize1, *grpsize2, temp);
+ }
+ }
+ TrieNode = TrieNode->father;
+ }
+ }
+ }
+
+ if (Part->cells < n) {
+ if (!ti->deg_one) {
+ if (sg_orig->e) {
+ memcpy(tv->graph->e, sg_orig->e, tv->graph->elen*sizeof(int));
+ for (i=0; i<n; i++) {
+ TheGraph[i].e = tv->graph->e + sg_orig->v[i];
+ }
+ }
+ }
+ NSFCInd = 0;
+
+ /* Trees */
+ if (tv->options->getcanon && tv->preprocessed) {
+ for (i = 0; i < n; i += Part->cls[i]) {
+ if (Part->cls[i] == 1) {
+ tmp = Cand->lab[i];
+ if ((TheGraph[tmp].d >= 0) && (TheGraph[tmp].d < sg_orig->d[tmp])) {
+ for (j=i; j<i+Part->cls[i]; j++) {
+ MakeCanTree(Cand->lab[j], sg_orig, n, Cand, Part, tv);
+ }
+ }
+ }
+ }
+ }
+
+ memset(SingNonSing, 0, n*sizeof(int));
+
+ for (i = 0; i < n; i += Part->cls[i]) {
+ if (Part->cls[i] > 1) {
+ if (TheGraph[Cand->lab[i]].d > 2) {
+ for (j=i; j<i+Part->cls[i]; j++) {
+ SingNonSing[Cand->lab[j]] = 2;
+ }
+ }
+ }
+ else {
+ SingNonSing[Cand->lab[i]] = 1;
+ }
+ }
+
+ for (i = 0; i < n; i += Part->cls[i]) {
+ if (Part->cls[i] > 1) {
+ if (TheGraph[Cand->lab[i]].d > 2) NonSingDegPlus1(Cand, Part, i, tv);
+ NSFCells[NSFCInd++] = i;
+ }
+ else {
+ NonSingDegPlus2(Cand, Part, i, tv);
+ numvertices--;
+ }
+ }
+
+ /* Degree 2 and at least one nghb with deg > 2 */
+ SETMARK(StackMarkers, tv->stackmark)
+ for (ind = 0; ind < NSFCInd; ind++) {
+ i = NSFCells[ind];
+ SETMARK(Markers, tv->mark)
+ if (Part->cls[i] > 1) {
+ tmp = Cand->lab[i];
+ if ((TheGraph[tmp].d == 2) && ((TheGraph[TheGraph[tmp].e[0]].d > 2) || ((TheGraph[TheGraph[tmp].e[1]].d > 2)))) {
+ n1 = TheGraph[tmp].e[0];
+ n2 = TheGraph[tmp].e[1];
+ if (TheGraph[n1].d > 2) {
+ if (TheGraph[n2].d > 2) {
+ if (Cand->invlab[n1] < Cand->invlab[n2]) {
+ start = n1;
+ }
+ else {
+ start = n2;
+ }
+ }
+ else {
+ start = n1;
+ }
+ }
+ else {
+ start = n2;
+ }
+ counts = 0;
+ StInd = 0;
+ for (j=i; j<i+Part->cls[i]; j++) {
+ step = Cand->lab[j];
+ if (Markers[step] != tv->mark) {
+ prev = start;
+ counts++;
+ do {
+ Markers[step] = tv->mark;
+ PERMSTACK[StInd++] = step;
+ if (TheGraph[step].e[0] != prev) {
+ prev = step;
+ step = TheGraph[step].e[0];
+ }
+ else {
+ prev = step;
+ step = TheGraph[step].e[1];
+ }
+ } while (TheGraph[step].d == 2);
+
+ if (TheGraph[step].d == 1) {
+ PERMSTACK[StInd++] = step;
+ }
+ }
+ }
+
+ if (counts == Part->cls[i]) {
+ factorial(grpsize1, grpsize2, Part->cls[i]);
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<counts-1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ if (counts > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ }
+ }
+ else {
+ factorial2(grpsize1, grpsize2, Part->cls[i]);
+ for (j=0; j<counts; j++) {
+ j0 = j*(StInd/counts);
+ k1 = (j+1)*(StInd/counts);
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=j0, i1=k1-1; k<k1; k++, i1--) {
+ SETPAIRSAUTANDTREE(PERMSTACK[k], PERMSTACK[i1])
+ }
+ SPECIALGENERATORS
+ }
+ if (counts > 1) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<counts-1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ }
+ if (counts > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ }
+ }
+ for (j=0; j<StInd; j++) {
+ Place(PERMSTACK[j], Cand, Part);
+ if ((TheGraph[PERMSTACK[j]].d >= 0) && (TheGraph[PERMSTACK[j]].d < sg_orig->d[PERMSTACK[j]])) {
+ MakeCanTree(PERMSTACK[j], sg_orig, n, Cand, Part, tv);
+ }
+ }
+ }
+ }
+ }
+
+ /* Degree 2 and at least one nghb with == 1 */
+ for (ind = 0; ind < NSFCInd; ind++) {
+ SETMARK(Markers, tv->mark)
+ i = NSFCells[ind];
+ if (Part->cls[i] > 1) {
+ tmp = Cand->lab[i];
+ if ((TheGraph[tmp].d == 2) && ((TheGraph[TheGraph[tmp].e[0]].d == 1) || ((TheGraph[TheGraph[tmp].e[1]].d == 1)))) {
+ counts = 0;
+ StInd = 0;
+ for (j=i; j<i+Part->cls[i]; j++) {
+ step = Cand->lab[j];
+ if (Markers[step] != tv->mark) {
+ n1 = TheGraph[step].e[0];
+ n2 = TheGraph[step].e[1];
+ if (TheGraph[n1].d == 1) {
+ if (TheGraph[n2].d == 1) {
+ if (Cand->invlab[n1] < Cand->invlab[n2]) {
+ start = n1;
+ }
+ else {
+ start = n2;
+ }
+ }
+ else {
+ start = n1;
+ }
+ }
+ else {
+ start = n2;
+ }
+ PERMSTACK[StInd++] = start;
+ prev = start;
+ counts++;
+
+ do {
+ Markers[step] = tv->mark;
+ PERMSTACK[StInd++] = step;
+ if (TheGraph[step].e[0] != prev) {
+ prev = step;
+ step = TheGraph[step].e[0];
+ } else {
+ prev = step;
+ step = TheGraph[step].e[1];
+ }
+ } while (TheGraph[step].d == 2);
+ PERMSTACK[StInd++] = step;
+ }
+ }
+
+ if (counts == Part->cls[i]) {
+ if (Part->inv[Cand->invlab[PERMSTACK[0]]] != Part->inv[Cand->invlab[PERMSTACK[StInd/counts-1]]]) {
+ factorial(grpsize1, grpsize2, Part->cls[i]);
+ }
+ else {
+ factorial2(grpsize1, grpsize2, 2*Part->cls[i]);
+ for (j=0; j<counts; j++) {
+ j0 = j*(StInd/counts);
+ k1 = (j+1)*(StInd/counts);
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=j0, i1=k1-1; k<k1; k++, i1--) {
+ SETPAIRSAUTANDTREE(PERMSTACK[k], PERMSTACK[i1])
+ }
+ SPECIALGENERATORS
+ }
+ }
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<counts-1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ if (counts > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ }
+ }
+ else {
+ factorial2(grpsize1, grpsize2, Part->cls[i]);
+ for (j=0; j<counts; j++) {
+ j0 = j*(StInd/counts);
+ k1 = (j+1)*(StInd/counts);
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=j0, i1=k1-1; k<k1; k++, i1--) {
+ SETPAIRSAUTANDTREE(PERMSTACK[k], PERMSTACK[i1])
+ }
+ SPECIALGENERATORS
+ }
+ if (counts > 1) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<counts-1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ }
+ if (counts > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (k=0; k<StInd/counts; k++) {
+ i1 = PERMSTACK[k];
+ for (j0=0; j0<1; j0++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
+ }
+ SPECIALGENERATORS
+ }
+ }
+ for (j=0; j<StInd; j++) {
+ Place(PERMSTACK[j], Cand, Part);
+ if ((TheGraph[PERMSTACK[j]].d >= 0) && (TheGraph[PERMSTACK[j]].d < sg_orig->d[PERMSTACK[j]])) {
+ MakeCanTree(PERMSTACK[j], sg_orig, n, Cand, Part, tv);
+ }
+ }
+ }
+ }
+ }
+
+ /* Cycles */
+ for (ind = 0; ind < NSFCInd; ind++) {
+ i = NSFCells[ind];
+ SETMARK(Markers, tv->mark)
+ if (Part->cls[i] > 1) {
+ tmp = Cand->lab[i];
+ if (TheGraph[tmp].d == 2) {
+ CyInd = StInd = cycnum = 0;
+ for (j=i; j<i+Part->cls[i]; j++) {
+ start = Cand->lab[j];
+ if (Markers[start] != tv->mark) {
+ counts = 1;
+ CYCLES[StInd] = start;
+ CYCOLR[StInd++] = Part->inv[Cand->invlab[start]];
+ Markers[start] = tv->mark;
+ k = Cand->invlab[TheGraph[start].e[0]];
+ k1 = Cand->invlab[TheGraph[start].e[1]];
+ if (Part->inv[k] < Part->inv[k1]) {
+ step = TheGraph[start].e[0];
+ }
+ else {
+ step = TheGraph[start].e[1];
+ }
+ prev = start;
+ do {
+ counts++;
+ Markers[step] = tv->mark;
+ CYCLES[StInd] = step;
+ CYCOLR[StInd++] = Part->inv[Cand->invlab[step]];
+
+ if (TheGraph[step].e[0] != prev) {
+ prev = step;
+ step = TheGraph[step].e[0];
+ }
+ else {
+ prev = step;
+ step = TheGraph[step].e[1];
+ }
+ } while (step != start);
+ CYLGTH[CyInd++] = counts;
+ cycnum++;
+ }
+ }
+
+ CYCPOS[0] = 0;
+ for (j=1; j<CyInd; j++) {
+ CYCPOS[j] = CYCPOS[j-1]+CYLGTH[j-1];
+ }
+ memcpy(WorkArray, CYLGTH, CyInd*sizeof(int));
+ sort2ints(WorkArray, CYCPOS, CyInd);
+
+ k = 0;
+ for (i1=0; i1<CyInd; i1++) {
+ k1 = CYCOLR[k];
+ k2 = CYCOLR[k+1];
+ for (j=1; j<=CYLGTH[i1]/2; j++) {
+ w1 = CYCOLR[j+k];
+ w2 = CYCOLR[j+1+k];
+ if ((w1 == k1) && (w2 == k2)) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (w=0; w<CYLGTH[i1]; w++) {
+ if (CYCOLR[w+k] == CYCOLR[((w+j) % CYLGTH[i1]) + k]) {
+ SETPAIRSAUTANDTREE(CYCLES[w+k], CYCLES[((w+j) % CYLGTH[i1]) + k])
+ }
+ else {
+ break;
+ }
+ }
+ if (w == CYLGTH[i1]) { SPECIALGENERATORS }
+ if (w == CYLGTH[i1]) {
+ MULTIPLY(*grpsize1, *grpsize2, CYLGTH[i1]/j);
+ break;
+ }
+ }
+ }
+
+ if (Part->cls[k1] >= Part->cls[k2]) {
+ for (j=CYLGTH[i1]-1; j>0; j--) {
+ w1 = CYCOLR[j % CYLGTH[i1] + k];
+ w2 = CYCOLR[(j-1) % CYLGTH[i1] + k];
+ if ((w1 == k1) && (w2 == k2)) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (w=0; w<CYLGTH[i1]; w++) {
+ SETPAIRSAUTANDTREE(CYCLES[w+k], CYCLES[((j-w+(w>j)*CYLGTH[i1]) % CYLGTH[i1]) + k])
+ }
+ SPECIALGENERATORS
+ MULTIPLY(*grpsize1, *grpsize2, 2);
+ break;
+ }
+ }
+ }
+ else {
+ j=CYLGTH[i1]-1;
+ w2 = CYCOLR[j % CYLGTH[i1] + k];
+ if (w2 == k2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (w=1; w<CYLGTH[i1]; w++) {
+ SETPAIRSAUTANDTREE(CYCLES[w+k], CYCLES[CYLGTH[i1]-w+k])
+ }
+ SPECIALGENERATORS
+ MULTIPLY(*grpsize1, *grpsize2, 2);
+ }
+ }
+ k += CYLGTH[i1];
+ }
+ k = 0;
+ for (i1=0; i1<CyInd; i1++) {
+ if (CYLGTH[i1] > 0) {
+ CYMULT[0] = k;
+ k1 = k;
+ counts = 1;
+ for (j0=i1+1; j0<CyInd; j0++) {
+ k1 += abs(CYLGTH[j0]);
+ if (CYLGTH[j0] == CYLGTH[i1]) {
+ CYMULT[counts++] = k1;
+ CYLGTH[j0] = -CYLGTH[j0];
+ }
+ }
+ if (counts > 1) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (j0=0; j0<CYLGTH[i1]; j0++) {
+ for (j2 = 0; j2<counts-1; j2++) {
+ SETPAIRSAUTANDTREE(CYCLES[CYMULT[j2]+j0], CYCLES[CYMULT[j2+1]+j0])
+ }
+ SETPAIRSAUTANDTREE(CYCLES[CYMULT[j2]+j0], CYCLES[CYMULT[0]+j0])
+ }
+ SPECIALGENERATORS
+ if (counts > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (j0=0; j0<CYLGTH[i1]; j0++) {
+ SETPAIRSAUTANDTREE(CYCLES[CYMULT[1]+j0], CYCLES[CYMULT[0]+j0])
+ if (tv->build_autom) {
+ SETPAIRSAUT(CYCLES[CYMULT[0]+j0], CYCLES[CYMULT[1]+j0])
+ }
+ MakeTree(CYCLES[CYMULT[0]+j0], CYCLES[CYMULT[1]+j0], sg_orig, n, tv, FALSE);
+ }
+ SPECIALGENERATORS
+ }
+ factorial(grpsize1, grpsize2, counts);
+ }
+ }
+ k += abs(CYLGTH[i1]);
+ CYLGTH[i1] = -CYLGTH[i1];
+ }
+
+ for (c1=0; c1<CyInd; c1++) {
+ c = CYCPOS[c1]+WorkArray[c1];
+ for (c2=CYCPOS[c1]; c2<c; c2++) {
+ Place(CYCLES[c2], Cand, Part);
+ if ((TheGraph[CYCLES[c2]].d >= 0) && (TheGraph[CYCLES[c2]].d < sg_orig->d[CYCLES[c2]])) {
+ MakeCanTree(CYCLES[c2], sg_orig, n, Cand, Part, tv);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Degree 1, and nghb too */
+ SETMARK(Markers, tv->mark)
+ for (ind = 0; ind < NSFCInd; ind++) {
+ i = NSFCells[ind];
+ if (Part->cls[i] > 1) {
+ tmp = Cand->lab[i];
+ if ((TheGraph[tmp].d == 1) && (TheGraph[TheGraph[tmp].e[0]].d == 1) && (i == Part->inv[Cand->invlab[TheGraph[tmp].e[0]]])) {
+ factorial2(grpsize1, grpsize2, Part->cls[i]);
+ /* the cell has size two */
+ if (Part->cls[i] == 2) {
+ val = Cand->lab[i+1];
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ arg = tmp;
+ SETPAIRSAUTANDTREE(arg, val)
+ SETPAIRSAUTANDTREE(val, arg)
+ SPECIALGENERATORS
+ }
+ else {
+ /* the cell has size greater than two */
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ SETMARK(Markers, tv->mark)
+ halfsize = Part->cls[i]/2;
+ i1 = 0;
+ for (j=i; j<i+Part->cls[i]; j++) {
+ if (Markers[Cand->lab[j]] != tv->mark) {
+ Markers[TheGraph[Cand->lab[j]].e[0]] = tv->mark;
+ PERMSTACK[i1] = Cand->lab[j];
+ PERMSTACK[i1+halfsize] = TheGraph[Cand->lab[j]].e[0];
+ i1++;
+ }
+ }
+ temp = PERMSTACK[0];
+ for (j=0; j<Part->cls[i]-1; j++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j], PERMSTACK[j+1])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j], temp)
+ SPECIALGENERATORS
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ memmove(PERMSTACK+halfsize, PERMSTACK+halfsize+1, (halfsize-1)*sizeof(int));
+ temp = PERMSTACK[1];
+ for (j=1; j<Part->cls[i]-2; j++) {
+ SETPAIRSAUTANDTREE(PERMSTACK[j], PERMSTACK[j+1])
+ }
+ SETPAIRSAUTANDTREE(PERMSTACK[j], temp)
+ SPECIALGENERATORS
+ }
+
+ SETMARK(Markers, tv->mark)
+ for (j=i; j<i+Part->cls[i]; j++) {
+ temp = Cand->lab[j];
+ if (Markers[temp] != tv->mark) {
+ if ((TheGraph[temp].d >= 0) && (TheGraph[temp].d < sg_orig->d[temp])) {
+ MakeCanTree(temp, sg_orig, n, Cand, Part, tv);
+ }
+ tmp = Cand->lab[j+1];
+ Markers[TheGraph[temp].e[0]] = tv->mark;
+ i1 = Cand->invlab[TheGraph[temp].e[0]];
+ Cand->lab[j+1] = TheGraph[temp].e[0];
+
+ if ((TheGraph[TheGraph[temp].e[0]].d >= 0) && (TheGraph[TheGraph[temp].e[0]].d < sg_orig->d[TheGraph[temp].e[0]])) {
+ MakeCanTree(TheGraph[temp].e[0], sg_orig, n, Cand, Part, tv);
+ }
+ Cand->invlab[TheGraph[temp].e[0]] = j+1;
+ Cand->lab[i1] = tmp;
+ Cand->invlab[tmp] = i1;
+ }
+ }
+ }
+ }
+ }
+
+ /* Degree 0 */
+ for (ind = 0; ind < NSFCInd; ind++) {
+ i = NSFCells[ind];
+ if (Part->cls[i] > 1) {
+ tmp = Cand->lab[i];
+ if ((TheGraph[0].e != NULL) && (TheGraph[tmp].d != 0) && (TheGraph[tmp].d != numvertices-1))
+ nghcell = Part->inv[Cand->invlab[TheGraph[tmp].e[0]]]; else nghcell = i;
+ if ((TheGraph[tmp].d == 0) ||
+ ((TheGraph[tmp].d == numvertices-1) && (TheGraph[tmp].d > 2)) ||
+ ((TheGraph[tmp].d == 1) && (TheGraph[TheGraph[tmp].e[0]].d == 1) && (i < nghcell))) {
+ do_ngh = FALSE;
+ if ((TheGraph[tmp].d == 1) && (TheGraph[TheGraph[tmp].e[0]].d == 1) && (i != nghcell)) {
+ do_ngh = TRUE;
+ }
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (j=i; j<i+Part->cls[i]-1; j++) {
+ arg = Cand->lab[j];
+ val = Cand->lab[j+1];
+ SETPAIRSAUTANDTREE(arg, val)
+ if (do_ngh) {
+ SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
+
+ }
+ }
+ arg = Cand->lab[j];
+ val = tmp;
+ SETPAIRSAUTANDTREE(arg, val)
+ if (do_ngh) {
+ SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
+ }
+ SPECIALGENERATORS
+ if (Part->cls[i] > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ arg = tmp;
+ val = Cand->lab[i+1];
+ SETPAIRSAUTANDTREE(arg, val)
+ if (do_ngh) {
+ SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
+ }
+ arg = Cand->lab[i+1];
+ val = tmp;
+ SETPAIRSAUTANDTREE(arg, val)
+ if (do_ngh) {
+ SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
+ }
+ SPECIALGENERATORS
+ }
+ factorial(grpsize1, grpsize2, Part->cls[i]);
+ if (do_ngh) {
+ for (j=i; j<i+Part->cls[i]; j++) {
+ temp = TheGraph[Cand->lab[j]].e[0];
+ Cand->lab[nghcell] = temp;
+ Cand->invlab[temp] = nghcell;
+ nghcell++;
+ }
+ }
+
+ k = i+Part->cls[i];
+ for (j=i; j<k; j++) {
+ Place(Cand->lab[j], Cand, Part);
+ if ((TheGraph[Cand->lab[j]].d >= 0) && (TheGraph[Cand->lab[j]].d < sg_orig->d[Cand->lab[j]])) {
+ MakeCanTree(Cand->lab[j], sg_orig, n, Cand, Part, tv);
+ if (do_ngh) {
+ MakeCanTree(TheGraph[Cand->lab[j]].e[0], sg_orig, n, Cand, Part, tv);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ /* Orbit Count */
+ SETMARK(Markers, tv->mark)
+ i1=0;
+ for (c1=0; c1<n; c1++) {
+ if (Markers[tv->orbits[c1]] != tv->mark) {
+ i1++;
+ Markers[tv->orbits[c1]] = tv->mark;
+ }
+ }
+ tv->stats->numorbits = i1;
+ return;
+}
+
+void Individualize(Partition *NextPart, Candidate *NextCand, int K, int Tc, int Cl, int Pos) {
+ int i, j;
+
+ NextCand->do_it = TRUE;
+ if (NextPart->cls[Tc] > 1) {
+ NextPart->cells = Cl+1;
+ NextPart->active = 1;
+ NextPart->cls[Tc]--;
+ NextPart->cls[Pos] = 1;
+ }
+ NextPart->inv[Pos] = Pos;
+
+ j = NextCand->lab[Pos];
+ i = NextCand->invlab[K];
+ NextCand->lab[Pos] = K;
+ NextCand->invlab[K] = Pos;
+ NextCand->lab[i] = j;
+ NextCand->invlab[j] = i;
+ return;
+}
+
+void Initialize_Traces_Variables(TracesVars *tv, TracesOptions *options_arg,
+ TracesStats *stats_arg, int *orbits_arg,
+ sparsegraph *g_arg, sparsegraph *canong_arg,
+ int n) {
+ tv->augmented_cells = n;
+ tv->canlist = 0;
+ tv->compstage = 0;
+ tv->expathlength = n;
+ tv->finalnumcells = n;
+ tv->firstpathlength = 0;
+ tv->group_level = 0;
+ tv->lev_of_lastauto = 0;
+ tv->linelgth = 0;
+ tv->name = 0;
+ tv->maxspineorblevel = 0;
+ tv->nfix = 0;
+ tv->options = options_arg;
+ tv->orbits = orbits_arg;
+ tv->permInd = 0;
+ tv->maxdeg = 0;
+ tv->mindeg = n;
+
+ if (tv->options->generators || tv->options->writeautoms || tv->options->userautomproc)
+ tv->build_autom = TRUE;
+ else
+ tv->build_autom = FALSE;
+
+ tv->specialgens = 0;
+ tv->stats = stats_arg;
+ tv->treedepth = 0;
+ tv->gotonode = NULL;
+ tv->input_graph = tv->graph = g_arg;
+ tv->cangraph = canong_arg;
+ tv->mark = tv->stackmark = tv->treemark = tv->autmark = tv->markcell1 = tv->markcell2 = NAUTY_INFINITY-1;
+ tv->conta0 = tv->conta1 = tv->conta2 = tv->conta3 = tv->conta4 = tv->conta5 = tv->conta6 = tv->conta7 = tv->contatc = 0;
+
+ if (tv->options->strategy == 0) {
+ tv->steps = n;
+ tv->strategy = 0;
+ }
+ else {
+ tv->strategy = 1;
+ tv->steps = tv->options->strategy;
+ if (tv->steps > n) {
+ tv->steps = n;
+ }
+ }
+}
+
+void Initialize_Traces_Statistics (TracesStats *stats_arg, int n) {
+ stats_arg->grpsize1 = 1;
+ stats_arg->grpsize2 = 0;
+ stats_arg->numorbits = n;
+ stats_arg->treedepth= 0;
+ stats_arg->numgenerators = 0;
+ stats_arg->numnodes = 1;
+ stats_arg->errstatus = 0;
+ stats_arg->interrupted = 0;
+ stats_arg->canupdates = 0;
+ stats_arg->peaknodes = 0;
+}
+
+void Initialize_Traces_Time_Variables (TracesVars *tv) {
+ tv->autchk = 0;
+ tv->expaths = 0;
+ tv->schreier1 = 0;
+ tv->schreier2 = 0;
+ tv->schreier3 = 0;
+}
+
+boolean isautom_sg_pair(graph *g, int *p, boolean digraph, int m, int n, struct TracesVars *tv) {
+ int *d, *e;
+ size_t *v;
+ int i, k, pi, di;
+ size_t vi, vpi, j;
+
+ SG_VDE(g, v, d, e);
+
+ for (k = 0; k < tv->permInd; ++k)
+ {
+ i = PrmPairs[k].arg;
+ pi = p[i];
+ di = d[i];
+ if (d[pi] != di) return FALSE;
+
+ vi = v[i];
+ vpi = v[pi];
+ SETMARK(AutMarkers, tv->autmark)
+ for (j = 0; j < di; ++j) AutMarkers[p[e[vi+j]]] = tv->autmark;
+ for (j = 0; j < di; ++j) if (AutMarkers[e[vpi+j]] != tv->autmark) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+boolean lookup(searchtrie *t) {
+ searchtrie *TreeNode;
+
+ TreeNode = t;
+ while (TreeNode->level >= 1) {
+ if (TreeNode->goes_to) {
+ return FALSE;
+ }
+ TreeNode = TreeNode->father;
+ }
+ return TRUE;
+}
+
+void MakeCanTree(int v1, sparsegraph *sg_orig, int n, Candidate *Cand, Partition *Part, struct TracesVars* tv) {
+ int ind, vtx, ngh, trind, deg0, deg1;
+ size_t j1;
+ int *sge1;
+
+ trind = 1;
+ ind = 0;
+ TreeStack[0] = v1;
+ SETMARK(TreeMarkers, tv->treemark);
+
+ while (ind < trind) {
+ vtx = TreeStack[ind++];
+ if (TreeNodes[vtx]) {
+ return;
+ }
+
+ if (TheGraph[vtx].d == -1) {
+ Place(vtx, Cand, Part);
+ TreeNodes[vtx] = TRUE;
+ }
+
+ TreeMarkers[vtx] = tv->treemark;
+ deg0 = maxint(TheGraph[vtx].d, 0);
+ deg1 = sg_orig->d[vtx];
+ sge1 = TheGraph[vtx].e;
+
+ for (j1 = deg0; j1 < deg1; j1++) {
+ ngh = sge1[j1];
+ if ((TheGraph[ngh].d == -1) && (TreeMarkers[ngh] != tv->treemark)) {
+ TreeStack[trind++] = ngh;
+ }
+ }
+ }
+ return;
+}
+
+void MakeDiscrete(Partition *Part, int cell) {
+ int i, k;
+
+ Part->cells += (Part->cls[cell] - 1);
+ k = cell + Part->cls[cell];
+
+ for (i = cell; i < k; i++) {
+ Part->cls[i] = 1;
+ Part->inv[i] = i;
+ }
+}
+
+void MakeTree(int v1, int v2, sparsegraph *sg, int n, struct TracesVars* tv, boolean forceautom) {
+ int ind, vtx1, vtx2, ngh1, ngh2, trind, deg0, deg1;
+ size_t j1;
+ int *sge1, *sge2;
+ boolean build_autom;
+
+ if (v1 == v2) return;
+ build_autom = tv->build_autom || forceautom;
+ trind = 2;
+ ind = 0;
+ TreeStack[0] = v1;
+ TreeStack[1] = v2;
+ SETMARK(TreeMarkers, tv->treemark);
+
+ while (ind < trind) {
+ vtx1 = TreeStack[ind++];
+ vtx2 = TreeStack[ind++];
+
+ TreeMarkers[vtx1] = tv->treemark;
+ TreeMarkers[vtx2] = tv->treemark;
+
+ deg0 = maxint(TheGraph[vtx1].d, 0);
+ deg1 = sg->d[vtx1];
+ sge1 = TheGraph[vtx1].e;
+ sge2 = TheGraph[vtx2].e;
+ for (j1 = deg0; j1 < deg1; j1++) {
+ ngh1 = sge1[j1];
+ ngh2 = sge2[j1];
+ if ((TreeMarkers[ngh1] != tv->treemark) && (ngh1 != ngh2)) {
+ TreeStack[trind++] = ngh1;
+ TreeStack[trind++] = ngh2;
+ if (ngh1 != ngh2) {
+ if (build_autom) {
+ AUTPERM[ngh1] = ngh2;
+ PrmPairs[tv->permInd].arg = ngh1;
+ PrmPairs[tv->permInd].val = ngh2;
+ tv->permInd++;
+ }
+ orbjoin_sp_pair(tv->orbits, OrbList, n,
+ ngh1, ngh2, &tv->stats->numorbits);
+ }
+ }
+ }
+ }
+ return;
+}
+
+int maxint(int u, int v) {
+ if (u > v) {
+ return u;
+ }
+ else {
+ return v;
+ }
+}
+
+int minint(int u, int v) {
+ if (u < v) {
+ return u;
+ }
+ else {
+ return v;
+ }
+}
+
+int NextNeighbour(int vtx, Candidate *Cand, Partition *Part, int* Markers, int mark, int *ngh, int n) {
+ int *e_vtx;
+ int i, j, deg, cell1, nghi;
+ int cell[2];
+ int vert[2];
+
+ deg = TheGraph[vtx].d;
+ e_vtx = TheGraph[vtx].e;
+
+ if (deg == n-1) {
+ return 0;
+ }
+ j = 0;
+ cell[0] = cell[1] = n;
+ for (i=0; i<deg; i++) {
+ nghi = e_vtx[i];
+ if (Markers[nghi] != mark) {
+ cell1 = Part->inv[Cand->invlab[nghi]];
+ if (Part->cls[cell1] > 1) {
+ cell[j] = cell1;
+ vert[j] = nghi;
+ j++;
+ if (j==2) break;
+ }
+ }
+ }
+ if (j>0) {
+ if (cell[0] < cell[1]) {
+ *ngh = vert[0];
+ } else {
+ *ngh = vert[1];
+ }
+ return 1;
+ }
+ else return 0;
+}
+
+int NonSingDeg(int vtx, Candidate *Cand, Partition *Part) {
+ int *e_vtx;
+ int i, deg, retdeg;
+
+ retdeg = TheGraph[vtx].d;
+ deg = retdeg;
+ e_vtx = TheGraph[vtx].e;
+ for (i=0; i<deg; i++) {
+ if (Part->cls[Part->inv[Cand->invlab[e_vtx[i]]]] == 1) {
+ retdeg--;
+ }
+ }
+ return retdeg;
+}
+
+int NonSingDegPlus1(Candidate *Cand, Partition *Part, int cell, TracesVars *tv) {
+
+ int *e_vtx;
+ int vtx, sing;
+ int i, j, deg, retdeg, n, singcount;
+
+ n = tv->input_graph->nv;
+ singcount = 0;
+
+ SETMARK(StackMarkers, tv->stackmark)
+
+ for (j=cell; j<cell+Part->cls[cell]; j++) {
+ vtx = Cand->lab[j];
+ deg = TheGraph[vtx].d;
+ retdeg = 0;
+ e_vtx = TheGraph[vtx].e;
+
+ for (i=0; i<deg; i++) {
+ if (SingNonSing[e_vtx[i]] != 1) {
+ e_vtx[retdeg++] = e_vtx[i];
+ }
+ else {
+ if (StackMarkers[e_vtx[i]] != tv->stackmark) {
+ sing = e_vtx[i];
+ WorkArray2[singcount] = Part->inv[Cand->invlab[sing]];
+ WorkArray[singcount++] = sing;
+
+ StackMarkers[e_vtx[i]] = tv->stackmark;
+ }
+ }
+ }
+ if (j == cell) {
+ sort2ints(WorkArray2, WorkArray, singcount);
+ }
+ if (deg != retdeg) {
+ memcpy(e_vtx+retdeg, WorkArray, singcount*sizeof(int));
+ TheGraph[vtx].d = retdeg;
+ }
+ }
+ return retdeg;
+}
+
+void NonSingDegPlus2(Candidate *Cand, Partition *Part, int cell, TracesVars *tv) {
+
+ int *e_sing;
+ int sing;
+ int k, deg1, singdeg, singcount;
+
+ singcount = 0;
+
+ sing = Cand->lab[cell];
+ singdeg = 0;
+ deg1 = TheGraph[sing].d;
+ e_sing = TheGraph[sing].e;
+
+ for (k=0; k<deg1; k++) {
+ if (SingNonSing[e_sing[k]] != 2) {
+ e_sing[singdeg++] = e_sing[k];
+ }
+ }
+ TheGraph[sing].d = singdeg;
+}
+
+void orbjoin_sp_pair(int *orbits, int *list, int n, int u, int v, int *numorbs) {
+ int j1, j2, k1, k2;
+
+ j1 = orbits[u];
+ while (orbits[j1] != j1) j1 = orbits[j1];
+ j2 = orbits[v];
+ while (orbits[j2] != j2) j2 = orbits[j2];
+
+ if (j1 != j2) {
+ k1 = j1;
+ k2 = j2;
+ if (k1 < k2) {
+ (*numorbs)--;
+ while (list[j2] != k2) {
+ orbits[j2] = k1;
+ j2 = list[j2];
+ }
+ orbits[j2] = k1;
+ k1 = list[k1];
+ list[j2] = k1;
+ list[j1] = k2;
+ }
+ else if (k1 > k2) {
+ (*numorbs)--;
+ while (list[j1] != k1) {
+ orbits[j1] = k2;
+ j1 = list[j1];
+ }
+ orbits[j1] = k2;
+ k2 = list[k2];
+ list[j1] = k2;
+ list[j2] = k1;
+ }
+ }
+ return;
+}
+
+void orbjoin_sp_perm(int *orbits, int *map, int *list, int n, int *numorbs) {
+ int i, j1, j2, k1, k2;
+
+ for (i = 0; i < n; ++i)
+ if (map[i] != i)
+ {
+ j1 = orbits[i];
+ while (orbits[j1] != j1) j1 = orbits[j1];
+ j2 = orbits[map[i]];
+ while (orbits[j2] != j2) j2 = orbits[j2];
+ k1 = j1;
+ k2 = j2;
+ if (k1 < k2) {
+ (*numorbs)--;
+ while (OrbList[j2] != k2) {
+ orbits[j2] = k1;
+ j2 = OrbList[j2];
+ }
+ orbits[j2] = k1;
+ k1 = OrbList[k1];
+ OrbList[j2] = k1;
+ OrbList[j1] = k2;
+ }
+ else if (k1 > k2) {
+ (*numorbs)--;
+ while (OrbList[j1] != k1) {
+ orbits[j1] = k2;
+ j1 = OrbList[j1];
+ }
+ orbits[j1] = k2;
+ k2 = OrbList[k2];
+ OrbList[j1] = k2;
+ OrbList[j2] = k1;
+ }
+ }
+}
+
+struct Partition *NewPartition(int n) {
+ struct Partition *P;
+
+ P = malloc(sizeof(*(P)));
+ if (P == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ P->cls = malloc(n*sizeof(int));
+ if (P->cls == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ P->inv = malloc(n*sizeof(int));
+ if (P->inv == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ P->code = -1;
+ P->cells = 0;
+ return P;
+}
+
+void NewPartSpine(int Lev, int n) {
+
+ if (Lev > 3) {
+ Spine[Lev].part = malloc(sizeof(*(Spine[Lev].part)));
+ if (Spine[Lev].part == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ Spine[Lev].part->cls = Spine[Lev-3].part->cls;
+ Spine[Lev].part->inv = Spine[Lev-3].part->inv;
+ Spine[Lev-3].part->cls = Spine[Lev-3].part->inv = NULL;
+ Spine[Lev].part->code = -1;
+ Spine[Lev].part->cells = 0;
+ }
+ else {
+ Spine[Lev].part = NewPartition(n);
+ }
+}
+
+void Place(int vtx, Candidate *Cand, Partition *Part) {
+ int vtxto, vtxpos;
+
+ vtxpos = Cand->invlab[vtx];
+ vtxto = CanonIndices[Part->inv[vtxpos]]++;
+ if (Cand->lab[vtxpos] != Cand->lab[vtxto]) {
+ Cand->lab[vtxpos] = Cand->lab[vtxto];
+ Cand->lab[vtxto] = vtx;
+ Cand->invlab[Cand->lab[vtxpos]] = vtxpos;
+ Cand->invlab[Cand->lab[vtxto]] = vtxto;
+ }
+ if (Part->cls[vtxto] > 1) {
+ Part->cls[vtxto+1] = Part->cls[vtxto]-1;
+ Part->cls[vtxto] = 1;
+ }
+}
+
+boolean Prefix(Candidate *Cand1, Candidate *Cand2, int k) {
+ int i;
+
+ for (i=1; i<=k; i++) {
+ if (Cand1->lab[Spine[k].tgtpos] != Cand2->lab[Spine[k].tgtpos]) {
+ break;
+ }
+ }
+ return (i>k);
+}
+
+int Preprocess(sparsegraph *sg,
+ permnode **ring,
+ Candidate *Cand,
+ int n,
+ Partition *Part,
+ struct TracesVars* tv) {
+
+ int i, j, j0, k, curr_cell, ind, ind0, ind1, ind2;
+ int *sge;
+ int HitClsInd, labi, nghb, value, SplInd, SplCntInd, sc, iend, CStackInd, newcell, TraceInd;
+
+#define SETPAIRSAUTANDTREE_PREPROC(arg, val) \
+if (tv->build_autom) SETPAIRSAUT(arg, val) \
+if (arg != val) \
+orbjoin_sp_pair(tv->orbits, OrbList, n, arg, val, &tv->stats->numorbits); \
+MakeTree(arg, val, sg, n, tv, FALSE);
+
+ CStackInd = 0;
+ for (i = 0; i < n; i += Part->cls[i]) {
+ if (TheGraph[Cand->lab[i]].d == 1) {
+ CStack[CStackInd++] = i;
+ }
+ }
+
+ TraceInd = Part->cells;
+
+ if (CStackInd > 0) {
+ ind = 0;
+ while (ind < CStackInd) {
+
+ if (tv->mark > (NAUTY_INFINITY-2)) {
+ memset(Markers, 0, n*sizeof(int));
+ memset(MarkHitVtx, 0, n*sizeof(int));
+ tv->mark = 0;
+ }
+ tv->mark++;
+
+ curr_cell = CStack[ind++];
+ ind2 = curr_cell+Part->cls[curr_cell];
+ HitClsInd = 0;
+ for (i = curr_cell; i < ind2; i++) {
+ labi = Cand->lab[i];
+ nghb = *(TheGraph[labi].e);
+
+ if (TheGraph[nghb].d != 1) {
+ TheGraph[labi].d = -1;
+ TheGraph[labi].one = TRUE;
+ }
+
+ if (MarkHitVtx[nghb] == tv->mark) {
+ NghCounts[nghb]++;
+ }
+ else {
+ value = Part->inv[Cand->invlab[nghb]];
+ MarkHitVtx[nghb] = tv->mark;
+ NghCounts[nghb] = 1;
+ if (Markers[value] != tv->mark) {
+ HitCls[HitClsInd++] = value;
+ Markers[value] = tv->mark;
+ HitVtx[value] = nghb;
+ ElmHitCll[value] = 1;
+ }
+ else {
+ HitVtx[value+ElmHitCll[value]++] = nghb;
+ }
+ }
+ }
+ tv->mark++;
+
+ sort_Split_Array(HitCls,HitClsInd);
+ SplInd = 0;
+ SplCls[0] = n;
+ for (j = 0; j < HitClsInd; j++) {
+ ind1 = HitCls[j];
+ if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < Part->cls[ind1])) {
+ SplCls[SplInd++] = ind1;
+ }
+ else {
+ ind2 = ind1+Part->cls[ind1];
+ value = NghCounts[Cand->lab[ind1++]];
+ for (i = ind1; i < ind2; i++) {
+ if (NghCounts[Cand->lab[i]] != value) {
+ SplCls[SplInd++] = HitCls[j];
+ break;
+ }
+ }
+ if (i == ind2) {
+ ind1 = HitCls[j];
+ if (TheGraph[Cand->lab[ind1]].d != 1) {
+ for (i = ind1; i < ind2; i++) {
+ value = Cand->lab[i];
+ Edge_Delete(value, NghCounts[value], Cand, tv);
+ sge = TheGraph[value].e+TheGraph[value].d;
+ if (NghCounts[value]>1) {
+ factorial(&(tv->stats->grpsize1), &(tv->stats->grpsize2), NghCounts[value]);
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (j0=0; j0<NghCounts[value]-1; j0++) {
+ SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[j0+1])
+ }
+ SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[0])
+ SPECIALGENERATORS
+ if (NghCounts[value] > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ SETPAIRSAUTANDTREE_PREPROC(sge[0], sge[1])
+ if (tv->build_autom) {
+ SETPAIRSAUT(sge[1], sge[0])
+ }
+ MakeTree(sge[1], sge[0], sg, n, tv, FALSE);
+ SPECIALGENERATORS
+ }
+ }
+ }
+ if (TheGraph[Cand->lab[ind1]].d == 1) {
+ CStack[CStackInd++] = ind1;
+ }
+ }
+ }
+ }
+ }
+
+ if (SplInd) {
+
+ for (sc = 0; sc < SplInd; sc++) { /* For each cell C to be split */
+ ind0 = SplCls[sc];
+ ind1 = ind0 + Part->cls[ind0];
+ SplCntInd = 0;
+ if (ElmHitCll[ind0] < Part->cls[ind0]) {
+ SplCnt[SplCntInd++] = 0;
+ SplPos[0] = Part->cls[ind0] - ElmHitCll[ind0];
+ }
+
+ /* According to the numbers of neighbors of C into the current cell */
+ /* compute how many vertices in C will be placed into the same new cell */
+ iend = ind0 + ElmHitCll[ind0];
+ for (i = ind0; i < iend; i++) {
+ value = NghCounts[HitVtx[i]];
+ if (Markers[value] != tv->mark) {
+ Markers[value] = tv->mark;
+ SplCnt[SplCntInd++] = value;
+ SplPos[value] = 1;
+ }
+ else {
+ SplPos[value]++;
+ }
+ }
+ tv->mark++;
+
+ /* Sort the values deriving from the previous step */
+ sort_Split_Array(SplCnt, SplCntInd);
+
+ Part->cells += SplCntInd-1;
+
+ /* Split the cell C and update the information for sizes of new cells */
+ /* Put the new cells into the stack */
+ i = ind0;
+ for (k = 0; k < SplCntInd; k++) {
+ value = SplPos[SplCnt[k]];
+ Part->cls[i] = value;
+ SplPos[SplCnt[k]] = i;
+ i += value;
+ if (i < ind1) {
+ TheTrace[TraceInd++] = i;
+ }
+ }
+
+ /* Permute elements of the cell C */
+ iend = ind0 + ElmHitCll[ind0];
+
+ for (i = ind0; i < iend; i++) {
+ value = HitVtx[i];
+ Edge_Delete(value, NghCounts[value], Cand, tv);
+ sge = TheGraph[value].e+TheGraph[value].d;
+ if (NghCounts[value] > 1) {
+ factorial(&(tv->stats->grpsize1), &(tv->stats->grpsize2), NghCounts[value]);
+
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ for (j0=0; j0<NghCounts[value]-1; j0++) {
+ SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[j0+1])
+ }
+ SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[0])
+ SPECIALGENERATORS
+ if (NghCounts[value] > 2) {
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ SETPAIRSAUTANDTREE_PREPROC(sge[0], sge[1])
+ if (tv->build_autom) {
+ SETPAIRSAUT(sge[1], sge[0])
+ }
+ MakeTree(sge[1], sge[0], sg, n, tv, FALSE);
+ SPECIALGENERATORS
+ }
+ }
+
+ j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
+ k = Cand->invlab[value]; /* where HitVtx[i] is in lab */
+ Cand->lab[k] = Cand->lab[j];
+ Cand->lab[j] = value;
+ Cand->invlab[value] = j;
+ Cand->invlab[Cand->lab[k]] = k;
+ NghCounts[value] = 0;
+ }
+
+ /* Reconstruct the cell C and update the inverse partition */
+ newcell = ind1 - ElmHitCll[ind0];
+ i = newcell;
+ ind2 = newcell+Part->cls[newcell]-1;
+ do {
+ Part->inv[i] = newcell;
+ if (i == ind2) {
+ newcell = i+1;
+ if (newcell < n) ind2 = newcell+Part->cls[newcell]-1;
+ }
+ }
+ while (++i < ind1);
+
+ for (i = ind0, k = 0; k < SplCntInd; i+=Part->cls[i], k++) {
+ if ((k > 0) || (SplCnt[0] > 0)) {
+ if (TheGraph[Cand->lab[i]].d == 1) {
+ CStack[CStackInd++] = i;
+ }
+ }
+ if (Part->cls[i] == 1) {
+ Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
+ }
+ }
+
+ }
+ }
+ }
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+void PrintPartition(int *v, int *cls, int n, int l, int line) {
+ int i, j, k;
+
+ k=0;
+ fprintf(outfile, "[ ");
+ for (i=0; i<n; i+=cls[i]) {
+ if ((cls[i]<=0) || i>=n) {
+ printf("WRONG");
+ break;
+ }
+ for (j=i; j<i+cls[i]; j++) {
+ fprintf(outfile, "%d ", v[j]+l);
+ if (k++ > 50) {
+ fprintf(outfile,"\n");
+ k=0;
+ }
+ }
+ if ((i+cls[i])<n) fprintf(outfile, "| ");
+ }
+ fprintf(outfile, "] at line %d\n", line);
+ return;
+}
+
+void PrintVect(int *v, int z, int n, int l) {
+ int i;
+ printf("[");
+ for (i = z; i<n; i++)
+ printf(" %2d", v[i]+l);
+ printf(" ]\n");
+ return;
+}
+
+void PrintWeightedGraph1(sparsegraph *g_arg, int n, char msg[30]) {
+ int i, j;
+ int *ngh1, *wgh1;
+
+ printf("%s\n",msg);
+ for (i=0; i<n; i++) {
+ ngh1 = g_arg->e+g_arg->v[i];
+ wgh1 = g_arg->w+g_arg->v[i];
+ printf("%2d: ",i+labelorg);
+ for (j=0; j<g_arg->d[i]; j++) {
+ printf("%2d ",ngh1[j]);
+ printf("(%d) ",wgh1[j]);
+ }
+ printf("\n");
+ }
+ printf("\n");
+}
+
+void PrintWeightedGraph2(int n, char msg[30]) {
+ int i, j;
+ int *ngh1, *wgh1;
+
+ printf("%s\n",msg);
+ for (i=0; i<n; i++) {
+ ngh1 = TheGraph[i].e;
+ printf("%2d: ",i+labelorg);
+ for (j=0; j<TheGraph[i].d; j++) {
+ printf("%2d ",ngh1[j]+labelorg);
+ }
+ printf(";\n");
+ }
+ printf("\n");
+}
+
+void PrintBlissGraph(int n) {
+ int i, j;
+ int *ngh1, *wgh1;
+
+ fprintf(outfile,"p edge %d\n",n);
+ for (i=0; i<n; i++) {
+ ngh1 = TheGraph[i].e;
+ for (j=0; j<TheGraph[i].d; j++) {
+ if (i < ngh1[j]) {
+ fprintf(outfile, "e %d %d\n",i+labelorg,ngh1[j]+labelorg);
+ }
+ }
+ }
+ printf("\n");
+}
+
+void putgraphplus_sg(FILE *f, sparsegraph *sg, int linelength)
+{
+ int i,n,curlen,slen;
+ int *d,*e;
+ size_t *v,j;
+ char s[60];
+
+ n = sg->nv;
+ SG_VDE(sg,v,d,e);
+
+ for (i = 0; i < n; ++i)
+ {
+ fprintf(f,"%3d : ",i+labelorg);
+ curlen = 7;
+
+ for (j = v[i]; j < v[i]+d[i]; ++j)
+ {
+ if (sg->w) {
+ if (sg->w[j] != 1) {
+ slen = itos(sg->w[j],s);
+ if (linelength > 0 && curlen + slen + 1 > linelength)
+ {
+ putstring(f,"\n ");
+ curlen = 2;
+ }
+ PUTC(' ',f);
+ PUTC('w',f);
+ putstring(f,s);
+ curlen += slen + 3;
+ }
+ }
+
+ slen = itos(e[j]+labelorg,s);
+ if (linelength > 0 && curlen + slen + 1 > linelength)
+ {
+ putstring(f,"\n ");
+ curlen = 2;
+ }
+ PUTC(' ',f);
+ putstring(f,s);
+ curlen += slen + 1;
+ }
+ putstring(f,";\n");
+ }
+}
+
+void quickSort(int *arr, int elements) {
+
+#define MAX_LEVELS 300
+
+ int piv, beg[MAX_LEVELS], end[MAX_LEVELS], i = 0, L, R, swap;
+ int k, value;
+
+ beg[0] = 0;
+ end[0] = elements;
+ while (i>= 0) {
+ L = beg[i];
+ R = end[i]-1;
+ if (L<R-8) {
+ piv = arr[(L+R)/2];
+ arr[(L+R)/2] = arr[L];
+ arr[L] = piv;
+ while (L<R) {
+ while (arr[R]>= piv && L<R) R--;
+ if (L<R) arr[L++] = arr[R];
+ while (arr[L]<= piv && L<R) L++;
+ if (L<R) arr[R--] = arr[L];
+ }
+ arr[L] = piv;
+ beg[i+1] = L+1;
+ end[i+1] = end[i]; end[i++] = L;
+ if (end[i]-beg[i]>end[i-1]-beg[i-1]) {
+ swap = beg[i];
+ beg[i] = beg[i-1];
+ beg[i-1] = swap;
+ swap = end[i];
+ end[i] = end[i-1];
+ end[i-1] = swap;
+ }
+ }
+ else {
+ i--;
+ }
+ }
+ for (k = 1; k < elements; ++k) {
+ value = arr[k];
+ i = k - 1;
+ while ((i >= 0) && (value < arr[i])) {
+ arr[i + 1] = arr[i];
+ --i;
+ }
+ arr[i + 1] = value;
+ }
+}
+
+void RemoveFromLevel(int from, int to, int strategy, boolean reinit) {
+ int i;
+
+ for (i=from; i<=to; i++) {
+ if (Spine[i].listend) {
+ (Spine[i].listend)->next = GarbList;
+ GarbList = Spine[i].liststart;
+ Spine[i].liststart = Spine[i].listend = NULL;
+ }
+ if (strategy == 0 || reinit) {
+ Spine[i].listcounter = 0;
+ if (i>from) {
+ Spine[i].thetracexists = FALSE;
+ Spine[i].part->code = -1;
+ }
+ }
+ }
+}
+
+searchtrie *searchtrie_make(Candidate *CurrCand, Candidate *NextCand, int n, struct TracesVars *tv) {
+
+ searchtrie *st;
+ if (tv->strienext == n) {
+ tv->strienext = 0;
+ tv->strielist->next = malloc(sizeof(struct trielist));
+ if (tv->strielist->next == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ tv->strielist->next->prev = tv->strielist;
+ tv->strielist = tv->strielist->next;
+ tv->strielist->next = NULL;
+ tv->strielist->triearray = malloc(n*sizeof(searchtrie));
+ if (tv->strielist->triearray == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ }
+ st = &(tv->strielist->triearray[tv->strienext]);
+ st->father = CurrCand->stnode;
+ st->name = NextCand->name;
+ st->index = tv->newindex+1;
+ st->vtx = NextCand->vertex;
+ st->level = tv->tolevel;
+ st->first_child = st->next_sibling = st->last_child = st->goes_to = NULL;
+ if (st->father) {
+ if (st->father->first_child) {
+ st->father->last_child->next_sibling = st;
+ st->father->last_child = st;
+ }
+ else {
+ st->father->first_child = st->father->last_child = st;
+ }
+ }
+ NextCand->stnode = st;
+ if (tv->newgotonode) {
+ tv->newgotonode->goes_to = st;
+ }
+ if (tv->gotonode) {
+ st->goes_to = tv->gotonode;
+ tv->gotonode = NULL;
+ }
+ tv->strienext++;
+ return st;
+}
+
+trielist *searchtrie_new(int n, struct TracesVars *tv) {
+
+ tv->strielist = malloc(sizeof(struct trielist));
+ if (tv->strielist == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ tv->strielist->prev = tv->strielist->next = NULL;
+ tv->strielist->triearray = malloc(n*sizeof(searchtrie));
+ if (tv->strielist->triearray == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ tv->strielist->triearray[0].father = tv->strielist->triearray[0].first_child = NULL;
+ tv->strielist->triearray[0].next_sibling = tv->strielist->triearray[0].last_child = NULL;
+ tv->strielist->triearray[0].goes_to = NULL;
+ tv->strielist->triearray[0].index = 1;
+ tv->strielist->triearray[0].name = tv->strielist->triearray[0].level = 0;
+ tv->strielist->triearray[0].vtx = n;
+
+ tv->strienext = 1;
+ return tv->strielist;
+}
+
+int Select_from_CStack(int *cls, int CStackInd) {
+ int j, k;
+
+ j = CStackInd;
+ k = CStackInd;
+ while (--j > 0) {
+ if (cls[CStack[j]] < cls[CStack[k]]) {
+ k = j;
+ }
+ if ((cls[CStack[k]] == 1) || (j < CStackInd - 12)) {
+ break;
+ }
+ }
+ return k;
+}
+
+boolean SelectNextLevel(int n, struct TracesVars *tv, struct TracesInfo *ti) {
+ int i, j, val;
+ Candidate *FirstCand;
+ boolean orbitcell;
+ VERB_PRINT("SelNxtLev",3,FALSE)
+
+ switch (tv->compstage) {
+ case 2:
+ tv->nextlevel = tv->maxtreelevel;
+ while (tv->nextlevel >=0) {
+ if (Spine[tv->nextlevel].liststart) {
+ break;
+ }
+ tv->nextlevel--;
+ }
+ if (tv->nextlevel < 0) {
+ return FALSE;
+ }
+ break;
+ default:
+ switch (tv->strategy) {
+ case 0:
+ tv->nextlevel = tv->fromlevel;
+ while (!Spine[tv->nextlevel].liststart) {
+ (tv->nextlevel)++;
+ }
+ PRINTF2("SelectNextLevel 1?: finalnumcells: %d; ", tv->finalnumcells);
+ PRINTF2("Spine[tv->nextlevel].part->cells: %d; ", Spine[tv->nextlevel].part->cells);
+ PRINTF2("tv->maxtreelevel: %d; ", tv->maxtreelevel);
+ PRINTF2("tv->nextlevel: %d\n", tv->nextlevel);
+ if ((Spine[tv->nextlevel].part->cells == tv->finalnumcells) || (tv->nextlevel > tv->maxtreelevel)) {
+ return FALSE;
+ }
+ else {
+ /* Check the whole group */
+ if ((tv->group_level < tv->tolevel) && !ti->first_matching && ti->thegrouphaschanged) {
+
+ FirstCand = Spine[tv->nextlevel].liststart;
+ val = tv->orbits[FirstCand->lab[Spine[1].tgtcell]];
+ for (i=Spine[1].tgtcell; i<Spine[1].tgtend; i++) {
+ if (tv->orbits[FirstCand->lab[i]] != val) {
+ break;
+ }
+ }
+ if (i<Spine[1].tgtend) {
+ orbitcell = FALSE;
+ } else {
+ orbitcell = TRUE;
+ }
+ if (orbitcell) {
+ FirstCand = Spine[tv->nextlevel].liststart;
+ FixBase(fix, tv, FirstCand, 0, tv->firstpathlength);
+ if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
+ getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit, NULL, n, n, TRUE);
+ if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
+ for (j=2; j<=tv->firstpathlength; j++) {
+ tv->currorbit = findcurrorbits(gpB, j-1);
+ val = tv->currorbit[FirstCand->lab[Spine[j].tgtcell]];
+ for (i=Spine[j].tgtcell; i<Spine[j].tgtend; i++) {
+ if (tv->currorbit[FirstCand->lab[i]] != val) {
+ break;
+ }
+ }
+ if (i<Spine[j].tgtend) {
+ break;
+ }
+ }
+ tv->group_level = j-1;
+ if (tv->group_level >= tv->tolevel) {
+ ti->thegrouphaschanged = FALSE;
+ }
+ }
+ /* End check the whole group */
+ }
+
+ }
+ break;
+ case 1:
+ tv->nextlevel = tv->maxtreelevel;
+ PRINTF2("SelectNextLevel 2?: finalnumcells: %d; ", tv->finalnumcells);
+ PRINTF2("Spine[tv->nextlevel].part->cells: %d; ", Spine[tv->nextlevel].part->cells);
+ if (Spine[tv->nextlevel].part->cells == tv->finalnumcells) {
+ (tv->nextlevel)--;
+ }
+ while (tv->nextlevel >= 0) {
+ if (Spine[tv->nextlevel].liststart) {
+ break;
+ }
+ tv->nextlevel--;
+ }
+ if (tv->nextlevel < 0) {
+ return FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ return TRUE;
+}
+
+void SetAutom(int q, int n, struct TracesVars *tv) {
+ int i;
+
+ for (i=0; i<q; i++) {
+ AUTPERM[PrmPairs[i].arg] = PrmPairs[i].val;
+ }
+ return;
+}
+
+void ResetAutom(int q, int n, struct TracesVars *tv) {
+ int i;
+
+ if (n/q < 256) {
+ memcpy(AUTPERM, IDENTITY_PERM, n*sizeof(int));
+ }
+ else {
+ for (i=0; i<q; i++) {
+ AUTPERM[PrmPairs[i].arg] = PrmPairs[i].arg;
+ }
+ }
+ tv->permInd = 0;
+ return;
+}
+
+void sort_Split_Array(int *Array, int Ind){
+ int i, k, value;
+
+ switch (Ind) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ if (Array[0] > Array[1]) {
+ value = Array[0];
+ Array[0] = Array[1];
+ Array[1] = value;
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ for (k = 1; k < Ind; ++k) {
+ value = Array[k];
+ i = k - 1;
+ while ((i >= 0) && (value < Array[i])) {
+ Array[i + 1] = Array[i];
+ --i;
+ }
+ Array[i + 1] = value;
+ }
+ break;
+ default:
+ quickSort(Array, Ind);
+ break;
+ }
+}
+
+int spinelementorbsize(int *orbits, int *lab, int size, int elem) {
+ int i, j, val;
+
+ j = 0;
+ val = orbits[elem];
+ for (i = 0; i < size; ++i) {
+ if (orbits[lab[i]] == val) ++j;
+ }
+ return j;
+}
+
+boolean TargetCell(Candidate *TargCand, Partition *Part, int n, struct TracesVars* tv, int Lv) {
+ int TCell = -1, TCSize = 1;
+ int i;
+ VERB_PRINT("TCELL",3,FALSE)
+ if (Part->cells == n) {
+ tv->finalnumcells = n;
+ return FALSE;
+ }
+ if (tv->maxdeg <=2) {
+ return FALSE;
+ }
+
+ if (Lv < tv->tcellevel) {
+ tv->tcell = Spine[Lv+1].tgtcell;
+ return TRUE;
+ }
+ else {
+ if (Part->cls[0] == n) {
+ tv->tcell = 0;
+ return TRUE;
+ }
+ while (TCell < 0) {
+ for (i = Spine[Lv].tgtcell; i < Spine[Lv].tgtend; i += Part->cls[i]) {
+ if (Part->cls[i] > TCSize) {
+ if (NonSingDeg(TargCand->lab[i], TargCand, Part) > 2) {
+ TCSize = Part->cls[i];
+ TCell = i;
+ }
+ }
+ }
+ Lv--;
+ if ((Lv < 0) && (TCell < 0)) return FALSE;
+ }
+ tv->tcell = TCell;
+ return TRUE;
+ }
+}
+
+int TargetCellExpPath(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
+ int Lv, n;
+ VERB_PRINT("TCEP",3,FALSE)
+
+ n = tv->input_graph->nv;
+ if (Part->cells == n) {
+ return 0;
+ }
+
+ Lv = tv->tolevel_tl+1;
+ SpineTL_tl = Spine+Lv;
+ if (tv->tolevel_tl < tv->tcellevel) {
+ tv->tcellexpath = Part->inv[SpineTL_tl->tgtcell];
+ tv->tolevel_tl++;
+ if (Part->cls[tv->tcellexpath] == 1) {
+ if (tv->options->verbosity >= 2) {
+ if (tv->tolevel_tl-tv->tolevel == 6) {
+ fprintf(outfile, "... ");
+ }
+ }
+ return TargetCellExpPath(TargCand, Part, tv);
+ } else {
+ return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
+ }
+ }
+ else {
+ if (TargetCellFirstPath(TargCand, Part, tv)) {
+ return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
+ }
+ else {
+ return 0;
+ }
+ }
+}
+
+boolean TargetCellFirstPath(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
+ int n, TCell, TCSize, TCell1, TCSize1;
+ int Lv, i, Lev, vtx, vtx_d;
+ int loopstart, loopend;
+ boolean divided;
+ VERB_PRINT("TCFP",3,FALSE)
+
+ n = tv->input_graph->nv;
+
+ if (Part->cells == n) {
+ return 0;
+ }
+
+ Lev = tv->tolevel_tl;
+ Lv = tv->tolevel_tl;
+
+ TCell = TCell1 = -1;
+ TCSize = TCSize1 = 1;
+
+ while (TCell < 0) {
+
+ if (tv->compstage == 2) {
+ loopstart = Spine[Lv].tgtcell;
+ divided = FALSE;
+ } else {
+ loopstart = Part->inv[Spine[Lv].tgtcell];
+ divided = FALSE;
+
+ if (Lv == tv->lastlev) {
+ loopstart = Part->inv[tv->lastcell];
+ divided = TRUE;
+ }
+ }
+
+ i = loopstart;
+ loopend = Spine[Lv].tgtend;
+ while (i < loopend) {
+ if (Part->cls[i] > TCSize) {
+ vtx = TargCand->lab[i];
+ vtx_d = TheGraph[vtx].d;
+ if (vtx_d > 2) {
+ if (NonSingDeg(vtx, TargCand, Part) > 2) {
+ TCSize = Part->cls[i];
+ TCell = i;
+ if (TCSize == WorkArray[Lv]) {
+ break;
+ }
+ }
+ }
+ }
+ i += Part->cls[i];
+ if (divided && (i == loopend)) {
+ i = loopstart = Part->inv[Spine[Lv].tgtcell];
+ loopend = tv->lastcell;
+ divided = FALSE;
+ TCSize1 = TCSize;
+ TCell1 = TCell;
+ TCell = -1;
+ TCSize = 1;
+ }
+ }
+
+ if (TCSize1 > TCSize) {
+ TCell = TCell1;
+ TCSize = TCSize1;
+ }
+
+ if (TCell < 0) {
+ if (Lv == 0) {
+ if (tv->answ == 2) {
+ tv->finalnumcells = minint(Part->cells,tv->finalnumcells); /* 160712 */
+ tv->finalnumcells = Part->cells;
+ }
+ return FALSE;
+ } else {
+ Lv = Spine[Lv].tgtfrom;
+ }
+ }
+ }
+
+ tv->tcellexpath = tv->lastcell = TCell;
+ tv->tolevel_tl++;
+
+ Spine[tv->tolevel_tl].tgtfrom = tv->lastlev = Lv;
+ Spine[tv->tolevel_tl].tgtcell = tv->tcellexpath;
+ Spine[tv->tolevel_tl].tgtsize = WorkArray[Lv] = TCSize;
+ Spine[tv->tolevel_tl].tgtend = Spine[tv->tolevel_tl].tgtcell + TCSize;
+ Spine[tv->tolevel_tl].tgtpos = Spine[tv->tolevel_tl].tgtend - 1;
+ tv->tcellevel = tv->tolevel_tl;
+
+ if (Lv != Lev) {
+ BreakSteps[Lev] = ++tv->brkstpcount;
+ if (Spine[tv->tolevel].liststart) {
+ if (!Spine[tv->tolevel].liststart->firstsingcode) {
+ Spine[tv->tolevel].liststart->firstsingcode = Spine[tv->tolevel].liststart->pathsingcode;
+ }
+ }
+ }
+ return TRUE;
+}
+
+void traces_freedyn(void) {
+ /* Free the static dynamic memory used by Traces */
+#if !MAXN
+ DYNFREE(AUTPERM, AUTPERM_sz);
+ DYNFREE(BreakSteps, BreakSteps_sz);
+ DYNFREE(CStack, CStack_sz);
+ DYNFREE(CurrOrbSize, CurrOrbSize_sz);
+ DYNFREE(CurrRefCells, CurrRefCells_sz);
+ DYNFREE(Diff, Diff_sz);
+ DYNFREE(Factorials, Factorials_sz);
+ DYNFREE(fix, fix_sz);
+ DYNFREE(IDENTITY_PERM, IDENTITY_PERM_sz);
+ DYNFREE(Markers, Markers_sz);
+ DYNFREE(TreeMarkers, TreeMarkers_sz);
+ DYNFREE(AutMarkers, AutMarkers_sz);
+ DYNFREE(MarkHitVtx, MarkHitVtx_sz);
+ DYNFREE(MultRefCells, MultRefCells_sz);
+ DYNFREE(NghCounts, NghCounts_sz);
+ DYNFREE(OrbSize, OrbSize_sz);
+ DYNFREE(OrbList, OrbList_sz);
+ DYNFREE(PrmPairs, PrmPairs_sz);
+ DYNFREE(TempOrbList, TempOrbList_sz);
+ DYNFREE(RefCells, RefCells_sz);
+ DYNFREE(RefPath, RefPath_sz);
+ DYNFREE(Singletons, Singletons_sz);
+ DYNFREE(SplCls, SplCls_sz);
+ DYNFREE(SplCnt, SplCnt_sz);
+ DYNFREE(SplPos, SplPos_sz);
+ DYNFREE(StackMarkers, StackMarkers_sz);
+ DYNFREE(TheTrace, TheTrace_sz);
+ DYNFREE(TheTraceCC, TheTraceCC_sz);
+ DYNFREE(TheTraceSplNum, TheTraceSplNum_sz);
+ DYNFREE(TheTraceSteps, TheTraceSteps_sz);
+ DYNFREE(TEMPLAB, TEMPLAB_sz);
+ DYNFREE(TEMPINVLAB, TEMPINVLAB_sz);
+ DYNFREE(WeightsSeq, WeightsSeq_sz);
+ DYNFREE(WorkArray, WorkArray_sz);
+ DYNFREE(WorkArray0, WorkArray0_sz);
+ DYNFREE(WorkArray1, WorkArray1_sz);
+ DYNFREE(WorkArray2, WorkArray2_sz);
+ DYNFREE(WorkArray3, WorkArray3_sz);
+ DYNFREE(WorkArray4, WorkArray4_sz);
+ DYNFREE(WorkArray5, WorkArray5_sz);
+ DYNFREE(WorkArray6, WorkArray6_sz);
+ DYNFREE(WorkArray7, WorkArray7_sz);
+ DYNFREE(Neighbs1, Neighbs1_sz);
+ DYNFREE(Neighbs2, Neighbs2_sz);
+ DYNFREE(TreeStack, TreeStack_sz);
+ DYNFREE(Spine, Spine_sz);
+ DYNFREE(TrieArray, TrieArray_sz);
+ DYNFREE(TheGraph, TheGraph_sz);
+ DYNFREE(EPCodes, EPCodes_sz);
+ DYNFREE(CyclesPart, CyclesPart_sz);
+ DYNFREE(CyclesLength, CyclesLength_sz);
+#endif
+}
+
+boolean TreeFyTwo(int From, Candidate *Cand1, Candidate *Cand2, Partition *Part, int n,
+ struct TracesVars* tv, struct TracesInfo *ti) {
+ int i, i1, i2, j1, j2, k;
+ int vtx1, vtx2, ngh1, ngh2, arg, val;
+ int *tgtc1, *tgtc2, *adj1, *adj2;
+ int iend;
+
+ SETMARK(Markers, tv->mark)
+
+ i2=0;
+
+ if (tv->permInd) ResetAutom(tv->permInd, n, tv);
+ i1 = Spine[From].tgtsize;
+ tgtc1 = Cand1->lab+Spine[From].tgtcell;
+ tgtc2 = Cand2->lab+Spine[From].tgtcell;
+ for (i=0; i<i1; i++) {
+ arg = tgtc1[i];
+ val = tgtc2[i];
+ if ((Markers[arg] != tv->mark) && (Markers[val] != tv->mark)) {
+ SETPAIRSAUT(arg, val)
+ SETPAIRSAUT(val, arg)
+ Markers[arg] = tv->mark;
+ Markers[val] = tv->mark;
+ } else {
+ return FALSE; /* 160715 */
+ }
+ }
+
+ while (i2 < tv->permInd) {
+ vtx1 = PrmPairs[i2].arg;
+ vtx2 = PrmPairs[i2++].val;
+ adj1 = TheGraph[vtx1].e;
+ adj2 = TheGraph[vtx2].e;
+ iend = TheGraph[vtx1].d;
+ j1 = j2 = 0;
+ for (k=0; k < iend; k++) {
+ ngh1 = adj1[k];
+ if (Markers[ngh1] != tv->mark) {
+ Neighbs1[j1++] = Cand1->invlab[ngh1];
+ }
+ ngh2 = adj2[k];
+ if (Markers[ngh2] != tv->mark) {
+ Neighbs2[j2++] = Cand2->invlab[ngh2];
+ }
+ }
+
+ k = tv->permInd;
+ if (j1 == j2) {
+ quickSort(Neighbs1, j1);
+ quickSort(Neighbs2, j2);
+ for (i=0; i<j1; i++) {
+ arg = Cand1->lab[Neighbs1[i]];
+ val = Cand2->lab[Neighbs2[i]];
+ if ((Markers[arg] != tv->mark) && (Markers[val] != tv->mark)) {
+ SETPAIRSAUT(arg, val)
+ SETPAIRSAUT(val, arg)
+ Markers[arg] = tv->mark;
+ Markers[val] = tv->mark;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*****************************************************************************
+ * *
+ * trie_class(t,c) classifies vertices according to weights of their edges *
+ * *
+ *****************************************************************************/
+
+void trie_class(trie *t, int *count) {
+
+ if (t->first_child == NULL) {
+ WeightsSeq[t->value] = *count;
+ if (t->next_sibling == NULL) (*count)++;
+ return;
+ }
+ else {
+ t = t->first_child;
+ while (t) {
+ trie_class(t,count);
+ t = t->next_sibling;
+ }
+ }
+}
+
+int trie_classify(int n, TracesVars *tv) {
+
+ int i, j, ord;
+ int *ngh1, *wgh1;
+
+ trieroot = trie_new(n, tv);
+ ord = 0;
+
+ for (i=0; i<n; i++) {
+ ngh1 = TheGraph[i].e;
+ wgh1 = TheGraph[i].w;
+ sort2ints(wgh1, ngh1, TheGraph[i].d);
+
+ trieref = trieroot;
+ for (j=0; j<TheGraph[i].d; j++) {
+ trieref = trie_make(trieref, wgh1[j], n, tv);
+ }
+ trieref = trie_make(trieref, n, n, tv);
+ trie_make(trieref, i, n, tv);
+ }
+ trie_class(trieroot,&ord);
+
+ for (i=0; i<=tv->triepos; i++) {
+ free(TrieArray[i]);
+ }
+ trieroot = NULL;
+ return ord-1;
+}
+
+struct trie *trie_comp(trie *t, int value) {
+
+ if (t->first_child) {
+ t = t->first_child;
+ while (t) {
+ if (value != t->value) {
+ t = t->next_sibling;
+ }
+ else {
+ break;
+ }
+ }
+ return t;
+ }
+ else {
+ return NULL;
+ }
+}
+
+void trie_dump(trie *t) {
+ if (t->first_child == NULL) return;
+ else {
+ printf("( ");
+ t = t->first_child;
+ while (t) {
+ printf("%d ",t->value);
+ trie_dump(t);
+ t = t->next_sibling;
+ }
+ printf(") ");
+ }
+}
+
+/*****************************************************************************
+ * *
+ * trie_make(t,v,n,tv) places the value v into the trie t *
+ * *
+ *****************************************************************************/
+
+struct trie *trie_make(trie *t, int value, int n, struct TracesVars* tv) {
+ trie *t1;
+
+ t1 = t;
+ if (tv->trienext == n) {
+ tv->trienext = 0;
+ tv->triepos++;
+ TrieArray[tv->triepos] = malloc(n*sizeof(trie));
+ if (TrieArray[tv->triepos] == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ }
+ if (t->first_child) {
+ t = t->first_child;
+ if (value < t->value) {
+ t1->first_child = &TrieArray[tv->triepos][tv->trienext++];
+ t1->first_child->next_sibling = t;
+ t1->first_child->first_child = NULL;
+ t = t1->first_child;
+ t->value = value;
+ return t;
+ }
+ while (value > t->value) {
+ t1 = t;
+ if (t->next_sibling) {
+ t = t->next_sibling;
+ }
+ else break;
+ }
+ if (value == t->value) {
+ return t;
+ }
+ t1->next_sibling = &TrieArray[tv->triepos][tv->trienext++];
+ t1->next_sibling->first_child = t1->next_sibling->next_sibling = NULL;
+ if (t != t1) {
+ t1->next_sibling->next_sibling = t;
+ }
+ t = t1->next_sibling;
+ }
+ else {
+ t->first_child = &TrieArray[tv->triepos][tv->trienext++];
+ t = t->first_child;
+ t->first_child = t->next_sibling = NULL;
+ }
+ t->value = value;
+ return t;
+}
+
+struct trie *trie_new(int n, struct TracesVars* tv) {
+
+ TrieArray[0] = malloc(n*sizeof(trie));
+ if (TrieArray[0] == NULL) {
+ fprintf(ERRFILE, "\nError, memory not allocated.\n");
+ exit(1);
+ }
+ TrieArray[0][0].first_child = TrieArray[0][0].next_sibling = NULL;
+ tv->triepos = 0;
+ tv->trienext = 1;
+ return TrieArray[0];
+}
+
+boolean VerifyCand(Candidate *Cand, int n, int line) {
+ int i, k;
+
+ for (i=0; i<n; i++) {
+ k=Cand->lab[i];
+ if (Cand->invlab[k] != i) {
+ printf("Cand->invlab wrong at %d (vtx: %d), line %d\n", i, k, line);
+ PrintVect(Cand->lab, 0, n, 0);
+ PrintVect(Cand->invlab, 0, n, 0);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+boolean VerifyId(int *p, int n) {
+ int i, r;
+
+ r = TRUE;
+ for (i=0; i<n; i++) {
+ if (p[i] != i) {
+ printf("p[%d] = %d\n", i, p[i]);
+ r = FALSE;
+ }
+ }
+ return r;
+}
+
+boolean VerifyPart(Partition *Part, int start, int end) {
+ int i,j;
+
+ for (i=start; i<end; i+=Part->cls[i]) {
+ if (Part->cls[i] == 0 || i>=end) {
+ printf("WRONG cls\n");
+ return FALSE;
+ }
+ for (j=0; j<Part->cls[i]; j++) {
+ if (Part->inv[i+j] != i) {
+ printf("WRONG inv\n");
+ return FALSE;
+ }
+ }
+ }
+ printf("OK\n");
+ return TRUE;
+}
+
+int VerifyPerm(int *perm, int n,int where) {
+ int i;
+
+ memset(Markers, 0, n*sizeof(int));
+
+ for (i=0; i<n; i++) {
+ if ((perm[i] >= n) || (Markers[perm[i]])) {
+ fprintf(stderr,"wrong permutation @ %d\n",where);
+ PrintVect(perm,0,i+1,labelorg);
+ }
+ Markers[perm[i]] = TRUE;
+ }
+ return TRUE;
+}
+
+/*****************************************************************************
+ * *
+ * WeightCodes(n) transforms the weight w(u,v) of an edge into a new weight *
+ * W(u,v) such that W(a,b) = W(c,d) iff w(a,b) = w(c,d) and w(b,a) = w(d,c). *
+ * *
+ *****************************************************************************/
+
+void WeightCodes(int n) {
+ int i,j,aux;
+ int sumdegs;
+ int deg, vtx1, vtx2, *ngh1, *ngh2, *wgh1, *wgh2, ord;
+
+ sumdegs = 0;
+ for (i=0; i<n; i++) {
+ sumdegs += TheGraph[i].d;
+ }
+
+ DYNALLSTAT(int, VArray, VArray_sz);
+ DYNALLSTAT(weightwhere, WArray, WArray_sz);
+ DYNALLSTAT(grph_strct, TheAuxGraph, TheAuxGraph_sz);
+
+ DYNALLOC1(int, VArray, VArray_sz, sumdegs, "WeightCodes");
+ DYNALLOC1(weightwhere, WArray, WArray_sz, sumdegs, "WeightCodes");
+ DYNALLOC1(grph_strct, TheAuxGraph, TheAuxGraph_sz, n, "WeightCodes");
+
+ memcpy(TheAuxGraph,TheGraph,n*sizeof(grph_strct));
+
+ ord = 0;
+ for (vtx1=0; vtx1<n; vtx1++) {
+ ngh1 = (TheAuxGraph[vtx1].e)++;
+ wgh1 = TheAuxGraph[vtx1].w;
+ deg = TheAuxGraph[vtx1].d;
+ for (i=0; i<deg; i++) {
+ vtx2 = ngh1[i];
+ ngh2 = (TheAuxGraph[vtx2].e)++;
+ wgh2 = (TheAuxGraph[vtx2].w)++;
+ (TheAuxGraph[vtx1].d)--;
+ (TheAuxGraph[vtx2].d)--;
+ VArray[ord] = wgh1[i];
+ WArray[ord].weight = wgh2[0];
+ WArray[ord++].ref = (TheAuxGraph[vtx1].w)++;
+ VArray[ord] = wgh2[0];
+ WArray[ord].weight = wgh1[i];
+ WArray[ord++].ref = wgh2;
+ }
+ }
+
+ sortweights(VArray,WArray,ord);
+
+ /* swap VArray and WArray.weight */
+ for (i=0; i<sumdegs; i++) {
+ aux = VArray[i];
+ VArray[i] = WArray[i].weight;
+ WArray[i].weight = aux;
+ }
+
+ i = j = 0;
+ do {
+ if (WArray[i].weight == WArray[j].weight) {
+ j++;
+ } else {
+ sortweights(VArray+i,WArray+i,j-i);
+ i = j;
+ }
+ } while (j<sumdegs);
+ sortweights(VArray+i,WArray+i,j-i);
+
+ /* weight class */
+ ord = 0;
+ *(WArray[0].ref) = 0;
+ for (i=1; i<sumdegs; i++) {
+ if ((WArray[i].weight != WArray[i-1].weight) || (VArray[i] != VArray[i-1])) {
+ ord++;
+ }
+ *(WArray[i].ref) = ord;
+ }
+
+ DYNFREE(VArray, VArray_sz);
+ DYNFREE(WArray, WArray_sz);
+ DYNFREE(TheAuxGraph, TheAuxGraph_sz);
+
+}
+
+
+
+boolean TargetCellSmall(Candidate *TargCand, Partition *Part, int n, struct TracesVars* tv, int Lv) {
+ int TCell = -1, TCSize = n;
+ int i;
+
+ if (tv->maxdeg <=2) {
+ return FALSE;
+ }
+
+ if (Lv < tv->tcellevel) {
+ tv->tcell = Spine[Lv+1].tgtcell;
+ return TRUE;
+ }
+ else {
+ if (Part->cls[0] == n) {
+ tv->tcell = 0;
+ return TRUE;
+ }
+ while (TCell < 0) {
+ for (i = Spine[Lv].tgtcell; i < Spine[Lv].tgtend; i += Part->cls[i]) {
+ if (Part->cls[i] < TCSize) {
+ if (NonSingDeg(TargCand->lab[i], TargCand, Part) > 2) {
+ TCSize = Part->cls[i];
+ TCell = i;
+ }
+ }
+ }
+ Lv--;
+ if ((Lv < 0) && (TCell < 0)) return FALSE;
+ }
+ tv->tcell = TCell;
+ return TRUE;
+ }
+}
+
+int TargetCellExpPathSmall(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
+ int Lv, n;
+
+ n = tv->input_graph->nv;
+ if (Part->cells == n) {
+ return 0;
+ }
+
+ Lv = tv->tolevel_tl+1;
+ SpineTL_tl = Spine+Lv;
+ if (tv->tolevel_tl < tv->tcellevel) {
+ tv->tcellexpath = Part->inv[SpineTL_tl->tgtcell];
+ tv->tolevel_tl++;
+ if (Part->cls[tv->tcellexpath] == 1) {
+ if (tv->options->verbosity >= 2) {
+ if (tv->tolevel_tl-tv->tolevel == 6) {
+ fprintf(outfile, "... ");
+ }
+ }
+ return TargetCellExpPath(TargCand, Part, tv);
+ } else {
+ return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
+ }
+ }
+ else {
+ if (TargetCellFirstPath(TargCand, Part, tv)) {
+ return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
+ }
+ else {
+ return 0;
+ }
+ }
+}
+
+boolean TargetCellFirstPathSmall(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
+ int n, TCell, TCSize, TCell1, TCSize1;
+ int Lv, i, Lev, vtx, vtx_d;
+ int loopstart, loopend;
+ boolean divided;
+
+ n = tv->input_graph->nv;
+ if (Part->cells == n) {
+ return 0;
+ }
+ Lev = tv->tolevel_tl;
+ Lv = tv->tolevel_tl;
+ TCell = TCell1 = -1;
+ TCSize = TCSize1 = n;
+
+ while (TCell < 0) {
+ loopstart = Part->inv[Spine[Lv].tgtcell];
+ divided = FALSE;
+
+ if (Lv == tv->lastlev) {
+ loopstart = Part->inv[tv->lastcell];
+ divided = TRUE;
+ }
+
+ i = loopstart;
+ loopend = Spine[Lv].tgtend;
+
+ while (i < loopend) {
+ if ((Part->cls[i] > 1) && (Part->cls[i] < TCSize)) {
+ vtx = TargCand->lab[i];
+ vtx_d = TheGraph[vtx].d;
+
+ if (vtx_d > 2) {
+ if (NonSingDeg(vtx, TargCand, Part) > 2) {
+ TCSize = Part->cls[i];
+ TCell = i;
+ if (TCSize == WorkArray[Lv]) {
+ break;
+ }
+ }
+ }
+ }
+ i += Part->cls[i];
+ if (divided && (i == loopend)) {
+ i = loopstart = Spine[Lv].tgtcell;
+ loopend = tv->lastcell;
+ divided = FALSE;
+ TCSize1 = TCSize;
+ TCell1 = TCell;
+ TCell = -1;
+ TCSize = n;
+ }
+ }
+
+ if (TCSize1 < TCSize) {
+ TCell = TCell1;
+ TCSize = TCSize1;
+ }
+
+ if (TCell < 0) {
+ if (Lv == 0) {
+ tv->finalnumcells = minint(Part->cells,tv->finalnumcells); /* 160712 */
+ tv->finalnumcells = Part->cells;
+ return FALSE;
+ } else {
+ Lv = Spine[Lv].tgtfrom;
+ }
+ }
+ }
+ tv->tcellexpath = tv->lastcell = TCell;
+ tv->tolevel_tl++;
+
+ Spine[tv->tolevel_tl].tgtfrom = tv->lastlev = Lv;
+ Spine[tv->tolevel_tl].tgtcell = tv->tcellexpath;
+ Spine[tv->tolevel_tl].tgtsize = WorkArray[Lv] = TCSize;
+ Spine[tv->tolevel_tl].tgtend = Spine[tv->tolevel_tl].tgtcell + TCSize;
+ Spine[tv->tolevel_tl].tgtpos = Spine[tv->tolevel_tl].tgtend - 1;
+ tv->tcellevel = tv->tolevel_tl;
+
+ if (Lv != Lev) {
+ BreakSteps[Lev] = ++tv->brkstpcount;
+ if (Spine[tv->tolevel].liststart) {
+ if (!Spine[tv->tolevel].liststart->firstsingcode) {
+ Spine[tv->tolevel].liststart->firstsingcode = Spine[tv->tolevel].liststart->pathsingcode;
+ }
+ }
+ }
+ return TRUE;
+}