1 /******************************************************************************
2  *                                                                            *
3  * This is the main file for traces() version 2.2, which is included into     *
4  *   nauty() version 2.7.                                                     *
5  *                                                                            *
6  *   nauty is Copyright (1984-2018) Brendan McKay.  All rights reserved.      *
7  *   Traces is Copyright Adolfo Piperno, 2008-2018.  All rights reserved.     *
8  *   See the file COPYRIGHT for the details of the software license.          *
9  *                                                                            *
10  *   CHANGE HISTORY                                                           *
11  *       28-Dec-12 : final changes for version 2.0                            *
12  *       20-Jan-13 : add code for ^C catching in Traces                       *
13  *       29-Mar-13 : bug correction in automorphism mode                      *
14  *       02-Apr-13 : add preprocessing                                        *
15  *       21-May-13 : bug correction (coloured lists)                          *
16  *       29-Jun-13 : bug correction (coloured lists and cycles)               *
17  *       07-Dec-13 : bug correction in automorphism mode (wrong group size    *
18  *                   due to randomness in Schreier-Sims orbit computation)    *
19  *                   bug correction (discrete initial partition)              *
20  *       15-Feb-14 : CPUDEFS removed (already declared in gtools.h)           *
21  *       01-Sep-15 : add weighted edges (not active)                          *
22  *       28-Jan-16 : version ready for nauty and Traces v.2.6 distribution    *
23  *       12-Jul-16 : bug correction (reaching degree 2 vertices)              *
24  *       07-Jun-18 : bug correction (finalnumcells, thanks R.Kralovic)        *
25  *       07-Jun-18 : bug correction (index computation when findperm)         *
26  *****************************************************************************/
27 
28 #include "traces.h"
29 
30 #ifdef NAUTY_IN_MAGMA
31 #include "cleanup.e"
32 #endif
33 
34 #define SORT_OF_SORT 2
35 #define SORT_NAME sort2ints
36 #define SORT_TYPE1 int
37 #define SORT_TYPE2 int
38 #include "sorttemplates.c"
39 
40 typedef struct weightwhere {
41     int weight;
42     int *ref;
43 } weightwhere;
44 
45 #define SORT_OF_SORT 2
46 #define SORT_NAME sortweights
47 #undef SORT_TYPE2
48 #define SORT_TYPE1 int
49 #define SORT_TYPE2 weightwhere
50 #include "sorttemplates.c"
51 
52 #define NAUTY_ABORTED (-11)
53 #define NAUTY_KILLED (-12)
54 
55 typedef struct Candidate {
56     boolean sortedlab;
57     int *invlab;
58     int *lab;
59     int code;
60     int do_it;
61     int indnum;
62     int name;
63     int vertex;
64     struct Candidate *next;
65     struct searchtrie *stnode;
66     unsigned int firstsingcode;
67     unsigned int pathsingcode;
68     unsigned int singcode;
69 } Candidate;
70 
71 typedef struct Partition {
72     int *cls;
73     int *inv;
74     int active;
75     int cells;
76     int code;
77 } Partition;
78 
79 typedef struct trielist {
80     struct searchtrie *triearray;
81     struct trielist *prev;
82     struct trielist *next;
83 } trielist;
84 
85 typedef struct TracesVars {
86     char digstring[25];
87     double autchk;
88     double expaths;
89     double schreier1;
90     double schreier2;
91     double schreier3;
92     int augmented_cells;
93     int build_autom;
94     int *currorbit;
95     int *orbits;
96     int answ;
97     int brkstpcount;
98     int compstage;
99     int cand_level;
100     int canlist;
101     int digits;
102     int expathlength;
103     int firstpathlength;
104     int fromlevel;
105     int group_level;
106     int indivend;
107     int indivstart;
108     int indiv_vtx;
109     int lastcell;
110     int lastlev;
111     int lev_of_lastauto;
112     int levelfromCS0;
113     int linelgth;
114     int mark;
115     int treemark;
116     int autmark;
117     int markcell1;
118     int markcell2;
119     int maxdeg;
120     int maxtreelevel;
121     int maxspineorblevel;
122     int mindeg;
123     int name;
124     struct searchtrie *gotonode;
125     struct searchtrie *newgotonode;
126     struct searchtrie *newst_stage1;
127     int newindex;
128     int nextlevel;
129     int nfix;
130     int finalnumcells;
131     int permInd;
132     int preprocessed;
133     int samepref;
134     int specialgens;
135     int stackmark;
136     int steps;
137     int strategy;
138     trielist *strielist;
139     int strienext;
140     int tcell_sz;
141     int tcell;
142     int tcellevel;
143     int tcellexpath_sz;
144     int tcellexpath;
145     int tolevel_tl;
146     int tolevel;
147     int treedepth;
148     int trienext;
149     int triepos;
150     TracesOptions *options;
151     TracesStats *stats;
152     unsigned int singlongcode;
153     sparsegraph *graph;
154     sparsegraph *cangraph;
155     sparsegraph *input_graph;
156     int conta0;
157     int conta1;
158     int conta2;
159     int conta3;
160     int conta4;
161     int conta5;
162     int conta6;
163     int conta7;
164     int contatc;
165 } TracesVars;
166 
167 typedef struct TracesInfo {
168     boolean autofound;
169     boolean deg_one;
170     boolean first_matching;
171     boolean regular;
172     boolean exitfromref;
173     boolean identitygroup;
174     boolean minimalinorbits;
175     boolean thegraphisparse;
176     boolean thegrouphaschanged;
177     boolean thereisnextlevel;
178     boolean useTempOrbits1;
179     boolean useTempOrbits2;
180 } TracesInfo;
181 
182 typedef struct TracesSpine {
183     boolean thetracexists;
184     Candidate *listend;
185     Candidate *liststart;
186     int ccend;
187     int ccstart;
188     int listcounter;
189     int stpend;
190     int stpstart;
191     int tgtcell;
192     int tgtend;
193     int tgtfrom;
194     int tgtpos;
195     int tgtsize;
196     int trcend;
197     int trcstart;
198     int singend;
199     int singstart;
200     int updates;
201     unsigned long keptcounter;
202     unsigned long levelcounter;
203     Partition *part;
204     unsigned int singcode;
205 } TracesSpine;
206 
207 typedef struct trie {
208     int value;
209     struct trie *first_child;
210     struct trie *next_sibling;
211 } trie;
212 
213 typedef struct searchtrie {
214     int index;
215     int name;
216     int vtx;
217     int level;
218     struct searchtrie *father;
219     struct searchtrie *first_child;
220     struct searchtrie *last_child;
221     struct searchtrie *next_sibling;
222     struct searchtrie *goes_to;
223 } searchtrie;
224 
225 typedef struct pair {
226     int arg;
227     int val;
228 } pair;
229 
230 typedef struct grph_strct {
231     int *e;
232     int *w;
233     int d;
234     boolean one;
235 } grph_strct;
236 
237 typedef struct ExpPathInfo {
238     int code;
239     int cell;
240     int info;
241 } ExpPathInfo;
242 
243 static boolean traces_degree_refine(sparsegraph*, Candidate*, int, Partition*,
244                                     struct TracesVars*, struct TracesInfo*, int, int*);
245 static int  traces_vertexclass_refine (int, int*, int*, Candidate*, Partition*, int*);
246 static int  traces_refine(Candidate*, int, Partition*,
247                           struct TracesVars*, struct TracesInfo*, int, boolean);
248 static void traces_refine_notrace(Candidate*, int, Partition*,
249                                   struct TracesVars*, struct TracesInfo*);
250 static void traces_refine_maketrie(Candidate*, int, Partition*,
251                                    struct TracesVars*, struct TracesInfo*);
252 static int  traces_refine_comptrie(Candidate*, int, Partition*,
253                                    struct TracesVars*, struct TracesInfo*);
254 static int  traces_refine_sametrace(Candidate*, int, Partition*,
255                                     struct TracesVars*, struct TracesInfo*);
256 static int  traces_refine_refine(sparsegraph*, Candidate*, int, Partition*,
257                                  struct TracesVars*, struct TracesInfo*);
258 static void  refine_tr_refine(Candidate*, int, Partition*,
259                              struct TracesVars*, struct TracesInfo*);
260 static int given_gens(sparsegraph*, permnode*, int*, boolean);
261 static void quickSort(int*, int);
262 static struct Partition* NewPartition(int);
263 static struct Candidate* NewCandidate(int, Candidate**, int);
264 static void NewPartSpine(int, int);
265 static int FreeList(Candidate*, int);
266 static int FixBase(int*, struct TracesVars*, Candidate*, int, int);
267 static boolean FixedBase(int*, struct TracesVars*, Candidate*, int, int);
268 static void factorial(double*, int*, int);
269 static void factorial2(double*, int*, int);
270 static int CheckForAutomorphisms(Candidate*, Candidate*, struct TracesVars*, struct TracesInfo*, int, int, Partition*);
271 static int CheckForSingAutomorphisms(Candidate*, Partition*, Candidate*, struct TracesVars*, struct TracesInfo*, int, int);
272 static int CheckForMatching(Candidate*, Candidate*, Partition*, struct TracesVars*, struct TracesInfo*, int, int);
273 static void Individualize(Partition*, Candidate*, int, int, int, int);
274 static boolean TreeFyTwo(int, Candidate*, Candidate*, Partition*, int, struct TracesVars*, struct TracesInfo*);
275 static void ExperimentalStep(Partition*, Candidate*, struct TracesVars*, struct TracesInfo*, int, int);
276 static boolean TargetCell(Candidate*, Partition*, int, struct TracesVars*, int);
277 static boolean TargetCellFirstPath(Candidate*, Partition*, struct TracesVars*);
278 static int TargetCellExpPath(Candidate*, Partition*, struct TracesVars*);
279 static boolean TargetCellSmall(Candidate*, Partition*, int, struct TracesVars*, int);
280 static boolean TargetCellFirstPathSmall(Candidate*, Partition*, struct TracesVars*);
281 static int TargetCellExpPathSmall(Candidate*, Partition*, struct TracesVars*);
282 static boolean SelectNextLevel(int, struct TracesVars*, struct TracesInfo*);
283 static void CopyCand(Candidate*, Candidate*, int, int*, int*);
284 static struct trie* trie_new(int, struct TracesVars*);
285 static struct trie* trie_make(trie*, int, int, struct TracesVars*);
286 static struct trie* trie_comp(trie*, int);
287 static void trie_dump(trie*);
288 static void trie_class(trie*, int*);
289 static void RemoveFromLevel(int, int, int, boolean);
290 static int CompStage0(Partition*, Partition*, Candidate*, Candidate*, int, int, struct TracesVars*, struct TracesInfo*);
291 static int CompStage1(Partition*, Partition*, Candidate*, Candidate*, int, int, struct TracesVars*, struct TracesInfo*);
292 static int CompStage2(Partition*, Partition*, Candidate*, Candidate*, int, int, struct TracesVars*, struct TracesInfo*);
293 static void grouporderplus(sparsegraph*, Candidate*, Partition*, permnode**, double*, int*, int, struct TracesVars*, struct TracesInfo*);
294 static boolean Prefix(Candidate*, Candidate*, int);
295 static boolean findperm(permnode*, int*, int);
296 static int spinelementorbsize(int*, int*, int, int);
297 static trielist* searchtrie_new(int, struct TracesVars*);
298 static searchtrie* searchtrie_make(Candidate*, Candidate*, int, struct TracesVars*);
299 static boolean lookup(searchtrie*);
300 static int* findcurrorbits(schreier*, int);
301 static int Preprocess(sparsegraph*, permnode**, Candidate*, int, Partition*, struct TracesVars*);
302 static void MakeTree(int, int, sparsegraph*, int, struct TracesVars*, boolean);
303 static void MakeCanTree(int, sparsegraph*, int, Candidate*, Partition*, struct TracesVars*);
304 static int maxint(int, int);
305 static int minint(int, int);
306 static void orbjoin_sp_perm(int*, int*, int*, int, int*);
307 static void orbjoin_sp_pair(int*, int*, int, int, int, int*);
308 static boolean isautom_sg_pair(graph*, int*, boolean, int, int, struct TracesVars*);
309 static void SetAutom(int, int, struct TracesVars*);
310 static void ResetAutom(int, int, struct TracesVars*);
311 static void PrintVect(int*, int, int, int);
312 static void putgraphplus_sg(FILE*, sparsegraph*, int);
313 static boolean VerifyId(int *p, int n);
314 static void PrintPartition(int*, int*, int, int, int);
315 static void Place(int, Candidate*, Partition*);
316 static int NonSingDeg(int, Candidate*, Partition*);
317 static int NonSingDegPlus1(Candidate*, Partition*, int, TracesVars*);
318 static void NonSingDegPlus2(Candidate*, Partition*, int, TracesVars*);
319 static void Edge_Delete(int, int, Candidate*, TracesVars*);
320 static boolean VerifyPart(Partition*, int, int);
321 static int VerifyPerm(int*, int,int);
322 static boolean VerifyCand(Candidate*, int, int);
323 static int FirstNeighbour(int, Candidate*, Partition*, int*, int, int*, int);
324 static int NextNeighbour(int, Candidate*, Partition*, int*, int, int*, int);
325 static sparsegraph* copy_sg_structure(sparsegraph*, sparsegraph*);
326 static void WeightCodes (int);
327 static void PrintWeightedGraph1(sparsegraph*, int, char[30]);
328 static void PrintWeightedGraph2(int n, char msg[30]);
329 static void MakeDiscrete(Partition*, int);
330 static void Complete(sparsegraph*, Candidate*, Partition*, int, TracesVars*, double*, int*,permnode**, int);
331 static void Allocate_Traces_Structures(int);
332 static void Allocate_refine_Structures(int);
333 static void Initialize_Traces_Variables(TracesVars*, TracesOptions*, TracesStats*, int*, sparsegraph*, sparsegraph*, int);
334 static void Initialize_Traces_Statistics (TracesStats*, int);
335 static void Initialize_Traces_Time_Variables (TracesVars*);
336 static int trie_classify(int, TracesVars*);
337 static int Check_degree_one(sparsegraph*, Candidate*, Partition*, int);
338 static void sort_Split_Array(int*, int);
339 static const unsigned int fuzz1[] = {037541, 061532, 005257, 026416};
340 static const unsigned int fuzz2[] = {006532, 070236, 035523, 062437};
341 static int Select_from_CStack(int*, int);
342 static void PrintBlissGraph(int);
343 static void CodeClassify(int, int, int);
344 
345 #define FUZZ1(x) ((x) ^ fuzz1[(x)&3])
346 #define FUZZ2(x) ((x) ^ fuzz2[(x)&3])
347 
348 #define MASHCOMM(l, i) ((l) + FUZZ1(i))
349 #define MASHNONCOMM(l, i) (FUZZ2(l) + (i))
350 #define MASH(l, i) ((((l) ^ 065435) + (i)) & 077777)
351 #define MASH1(l, i) ((l + (i*i)) & 077777)
352 #define CLEANUP(l) ((int)((l) % 0x7FFF))
353 #define SS(n, sing, plur)  (n), ((n) == 1?(sing):(plur))
354 
355 #define SETMARK(Arr, Mrk) if (Mrk > (NAUTY_INFINITY-2)) { memset(Arr, 0, n*sizeof(int)); Mrk = 0; } Mrk++;
356 
357 #define COPYNODE(W, V) { \
358 memcpy(W->lab, V->lab, n*sizeof(int)); \
359 memcpy(W->invlab, V->invlab, n*sizeof(int)); \
360 W->code = V->code; \
361 W->singcode = V->singcode; \
362 W->do_it = V->do_it; }
363 
364 #define NEXTLINE fprintf(outfile, "\n");
365 
366 #define PRINTCHAR(c) fprintf(outfile, "%s", c);
367 
368 #define PRINTCAND(V, Lev) PRINTCHAR(" ") for (tmp=1; tmp<=Lev; tmp++) {fprintf(outfile, tv->digstring, V->lab[Spine[tmp].tgtpos]+labelorg);}
369 
370 #define PRINTCANDF(V, Lev) { NEXTLINE for (tmp=1; tmp<=Lev; tmp++) {fprintf(outfile, "F%di", V->lab[Spine[tmp].tgtpos]+labelorg);} NEXTLINE }
371 
372 #define PRINTCANDBIG(V, Lev) { PRINTCHAR(" ") \
373 for (tmp=1; tmp<=5; tmp++) {fprintf(outfile, tv->digstring, V->lab[Spine[tmp].tgtpos]+labelorg);} \
374 fprintf(outfile, "... "); \
375 for (tmp=Lev-4; tmp<=Lev; tmp++) {fprintf(outfile, tv->digstring, V->lab[Spine[tmp].tgtpos]+labelorg);} }
376 
377 #define LINE(K, c) { PRINTCHAR(c) for (tmp=1; tmp<=K; tmp++) {fprintf(outfile, c);} }
378 
379 #define TRACE_CHECK(Tr, Ind, Arg, End) { TracePos = Tr+Ind; \
380 if (newtrace) { \
381 *TracePos = Arg; \
382 } \
383 else { \
384 if (Ind < *End) { \
385 if (*TracePos != Arg) { \
386 if (*TracePos > Arg) { \
387 return FALSE; \
388 } \
389 else { \
390 *TracePos = Arg; \
391 newtrace = TRUE; \
392 } \
393 } \
394 } \
395 else { \
396 *TracePos = Arg; \
397 newtrace = TRUE; \
398 } \
399 } \
400 Ind++; }
401 
402 #define SAMETRACE_CHECK(Tr, Ind, Arg, End) { TracePos = Tr+Ind; \
403 if (Ind < *End) { \
404 if (*TracePos != Arg) { \
405 return FALSE; \
406 } \
407 } \
408 else { \
409 return FALSE; \
410 } \
411 Ind++; }
412 
413 #define NEWPARTSPINE(Lev) { if (Lev > 3) { \
414 Spine[Lev].part = malloc(sizeof(*(Spine[Lev].part))); \
415 if (Spine[Lev].part == NULL) { \
416 fprintf(ERRFILE, "\nError, memory not allocated.\n"); \
417 exit(1); \
418 } \
419 Spine[Lev].part->cls = Spine[Lev-3].part->cls; \
420 Spine[Lev].part->inv = Spine[Lev-3].part->inv; \
421 Spine[Lev-3].part->cls = Spine[Lev-3].part->inv = NULL; \
422 Spine[Lev].part->code = -1; \
423 Spine[Lev].part->cells = 0; \
424 } \
425 else { \
426 Spine[Lev].part = NewPartition(n); \
427 } }
428 
429 #define FIND_SPLIT_CELLS SplInd = 0; \
430 for (j = 0; j < HitClsInd; j++) { \
431 ind1 = HitCls[j]; \
432 ElmHitCll[ind1] -= ind1; \
433 if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) { \
434 SplCls[SplInd++] = ind1; \
435 } \
436 }
437 
438 #define FREEPART(Part) { if (Part) { \
439 if (Part->cls) free(Part->cls); \
440 if (Part->inv) free(Part->inv); \
441 free(Part); } \
442 }
443 
444 #define FREECAND(Cand) { if (Cand) { \
445 if (Cand->lab) free(Cand->lab); \
446 if (Cand->invlab) free(Cand->invlab); \
447 free(Cand); \
448 } }
449 
450 #define COPYPART(P, Q) { memcpy(P->cls, Q->cls, n*sizeof(int)); \
451 memcpy(P->inv, Q->inv, n*sizeof(int)); \
452 P->cells = Q->cells; \
453 P->code = Q->code; } \
454 
455 #define ADDTONEXTLEVEL { if (SpineTL->listend) { \
456 (SpineTL->listend)->next = NewCandidate(n, &GarbList, TRUE); \
457 if ((tv->compstage < 2) && (SpineTL->listcounter <= (NAUTY_INFINITY-2))) SpineTL->listcounter++; \
458 SpineTL->listend = (SpineTL->listend)->next; \
459 CopyCand(SpineTL->listend, NextCand, n, NULL, NULL); \
460 } \
461 else { \
462 SpineTL->liststart = NewCandidate(n, &GarbList, TRUE); \
463 if (tv->compstage < 2) SpineTL->listcounter = 1; \
464 SpineTL->listend = SpineTL->liststart; \
465 CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL); \
466 } }
467 
468 #define ORBITSIZES { memset(OrbSize, 0, n*sizeof(int)); \
469 for (i=0; i<n; i++) { \
470 OrbSize[tv->orbits[i]]++; \
471 } }
472 
473 #define CURRORBITSIZES { memset(CurrOrbSize, 0, n*sizeof(int)); \
474 for (i=SpineTL->tgtcell; i<SpineTL->tgtend; i++) { \
475 CurrOrbSize[tv->currorbit[CurrCand->lab[i]]]++; \
476 } }
477 
478 #define EXITFROMSTAGE0REFINE { PRINT_LINE_PLUS(tv->tolevel) \
479 if (tv->options->verbosity >= 2) fprintf(outfile, "-=="); \
480 CurrCand->indnum--; \
481 RemoveFromLevel(tv->tolevel, tv->treedepth, tv->strategy, FALSE); \
482 tv->compstage = 1; \
483 TempOrbits = NULL; \
484 trieroot = trie_new(n, tv); \
485 trieref = trieroot; \
486 tv->nextlevel = tv->maxtreelevel = tv->fromlevel; \
487 ti->thereisnextlevel = TRUE; \
488 ti->exitfromref = TRUE; \
489 return 0; }
490 
491 #define EXITFROMSTAGE0EXPATH2 { PRINT_LINE_PLUS(tv->tolevel) \
492 if (tv->options->verbosity >= 2) fprintf(outfile, "=-="); \
493 tv->compstage = 1; \
494 TempOrbits = NULL; \
495 trieroot = trie_new(n, tv); \
496 trieref = trieroot; \
497 tv->nextlevel = tv->maxtreelevel = tv->tolevel; \
498 ti->thereisnextlevel = TRUE; \
499 ti->exitfromref = FALSE; \
500 return 0; }
501 
502 #define EXITFROMSTAGE0EXPATH1 { PRINT_RETURN PRINT_LINE_PLUS(tv->tolevel) \
503 if (tv->options->verbosity >= 2) fprintf(outfile, "==-"); \
504 if (SpineTL->liststart) { \
505 AuxCand = SpineTL->liststart; \
506 SpineTL->liststart = NewCandidate(n, &GarbList, TRUE); \
507 CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL); \
508 SpineTL->liststart->next = AuxCand; \
509 } \
510 else { \
511 SpineTL->liststart = NewCandidate(n, &GarbList, TRUE); \
512 SpineTL->listend = SpineTL->liststart; \
513 SpineTL->liststart->next = NULL; \
514 CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL); \
515 } \
516 tv->compstage = 1; \
517 TempOrbits = NULL; \
518 trieroot = trie_new(n, tv); \
519 trieref = trieroot; \
520 tv->nextlevel = tv->maxtreelevel = tv->tolevel; \
521 ti->thereisnextlevel = TRUE; \
522 ti->exitfromref = FALSE; \
523 return 0; }
524 
525 #define UPDATE_LINELGTH { if (tv->options->verbosity >= 2) { \
526 if (tv->tolevel < 12) { \
527 tv->linelgth = (tv->digits+1)*tv->tolevel+16; \
528 } \
529 else { \
530 tv->linelgth = (tv->digits+1)*10+20; \
531 } \
532 } }
533 
534 #define PRINT_LINE { if ((tv->options->verbosity >= 1) && (tv->strategy == 0)) { \
535 if (tv->options->verbosity >= 2) { LINE(tv->linelgth, "-"); \
536 NEXTLINE} \
537 } \
538 }
539 
540 #define PRINT_LINE_PLUS(Lev) { if ((tv->options->verbosity >= 1) && (tv->strategy == 0)) { \
541 if (tv->options->verbosity >= 2) { LINE(16+tv->digits+1, "-");} \
542 fprintf(outfile, " Level %d:  %d cell%s; %d singleton%s; target cell: %d; %d orbit%s; %lu node%s (%lu kept); %d update%s;", \
543 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"), \
544 SS(Spine[Lev].levelcounter, "", "s"), Spine[Lev].keptcounter, SS(Spine[Lev].updates, "", "s")); \
545 if (Lev <= tv->group_level) fprintf(outfile, " group_level: %d", tv->group_level); \
546 NEXTLINE \
547 } \
548 }
549 
550 #define PRINT_CANDIDATE(Cand, Lev) { \
551 for (tmp = Cand->name, cu = 0; tmp > 0; tmp /= 10, ++cu) {} \
552 for (tmp = Lev, cu1 = 0; tmp > 0; tmp /= 10, ++cu1) {} \
553 cu = 14-cu-cu1; \
554 LINE(cu, "-") \
555 fprintf(outfile, " %d, %d) ", Lev % 10000, Cand->name % 10000000); \
556 if (Lev < 12) { \
557 PRINTCAND(Cand, Lev) \
558 } \
559 else { \
560 PRINTCANDBIG(Cand, Lev) \
561 } \
562 PRINTCHAR("| ")    \
563 fprintf(outfile, "{%x, %x} ", Cand->code, Cand->singcode); \
564 }
565 
566 #define PRINT_CANDIDATEPLUS(PrevCand, Cand, Lev) { \
567 for (tmp = Cand->name, cu = 0; tmp > 0; tmp /= 10, ++cu) {} \
568 for (tmp = Lev, cu1 = 0; tmp > 0; tmp /= 10, ++cu1) {} \
569 cu = 14-cu-cu1; \
570 LINE(cu, "-") \
571 fprintf(outfile, " %d, %d, %d) ", Lev % 10000, Cand->name % 10000000, PrevCand->name); \
572 if (Lev < 12) { \
573 PRINTCAND(Cand, Lev) \
574 } \
575 else { \
576 PRINTCANDBIG(Cand, Lev) \
577 } \
578 PRINTCHAR("| ")    \
579 fprintf(outfile, "{%x, %x} ", Cand->code, Cand->singcode); \
580 }
581 
582 #define PRINT_EXPPATHSTEP(Cand, Boo) { \
583 if (tv->options->verbosity >= 2) { \
584 if ((tv->tolevel_tl-tv->tolevel < 6) || !has_nexttcell) { \
585 fprintf(outfile, "%d ", tv->indiv_vtx+labelorg); \
586 if (Boo) { \
587 if (tv->options->verbosity >= 2) fprintf(outfile, "{%d:%x} ", tv->tcellexpath, Cand->code); \
588 } \
589 else fprintf(outfile, "{interr.(%d)} ", NextPart->cells); \
590 if ((!has_nexttcell) && (tv->compstage == 0)) { \
591 fprintf(outfile, "(%d) ", tv->tolevel_tl); \
592 } \
593 } \
594 else { \
595 if (tv->tolevel_tl-tv->tolevel == 6) { \
596 fprintf(outfile, "... "); \
597 } \
598 } \
599 } \
600 }
601 
602 #define PRINT_RETURN { if (tv->options->verbosity >= 2) { \
603 fprintf(outfile, "\n"); \
604 } }
605 
606 #define PRINT_FROM_VERB(Verb,Lev) { if (tv->options->verbosity >= Verb) { \
607 fprintf(outfile, "FROM: "); \
608 if (Lev < 12) { \
609 PRINTCAND(CurrCand, tv->fromlevel) \
610 } \
611 else { \
612 PRINTCANDBIG(CurrCand, tv->fromlevel) \
613 } \
614 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); \
615 PRINT_RETURN \
616 } }
617 
618 #define PRINT_NOTMIN_VERB(Verb) { if (tv->options->verbosity >= Verb) { \
619 fprintf(outfile, " is NOT minimal in orbits (1, %d) [%d]; ", gom_level, CurrCand->lab[Spine[gom_level+1].tgtpos]+labelorg); \
620 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); } }
621 
622 #define PRINT_SKIPPED_VERB(Verb) { if (tv->options->verbosity >= Verb) \
623 fprintf(outfile, " skipped (0) (orbit[%d] = %d)\n", \
624 NextCand->vertex+labelorg, tv->currorbit[NextCand->vertex]+labelorg); }
625 
626 #define PRINT_REFINE_VERB(Verb,where) { if (tv->options->verbosity >= Verb) \
627 fprintf(outfile, " REFINE(%c) (orbit[%d] = %d)\n",where, NextCand->vertex+labelorg, tv->currorbit[NextCand->vertex]+labelorg); }
628 
629 #define PRINT_INDIV_VERB(Verb,Lev) { if (tv->options->verbosity >= Verb) { \
630 if (Lev < 12) { \
631 PRINTCAND(CurrCand, tv->fromlevel) \
632 } \
633 else { \
634 PRINTCANDBIG(CurrCand, tv->fromlevel) \
635 } \
636 fprintf(outfile, "| "); \
637 fprintf(outfile, tv->digstring, NextCand->vertex+labelorg); \
638 } }
639 
640 #define PRINT_INDEX(V,Verb,where) if (tv->options->verbosity >= Verb) \
641 fprintf(outfile,"Set index @ %d: Name %d, index %d\n",where,V->name,V->index);
642 
643 #define SPECIALGENERATORS { if (tv->options->generators) addpermutation(ring, AUTPERM, n); \
644 tv->stats->numgenerators++; \
645 tv->specialgens++; \
646 if (tv->options->writeautoms) { \
647 fprintf(outfile, "Gen #%d: ", tv->stats->numgenerators); \
648 writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n); \
649 } \
650 if (tv->options->userautomproc) { \
651 (*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n); \
652 } }
653 
654 #define UPDATEMIN(A, B) if (B < A) A = B;
655 
656 #define PAIRORBJOIN(A, V) { if (A != V) { \
657 PrmPairs[tv->permInd].arg = A; \
658 PrmPairs[tv->permInd].val = V; \
659 tv->permInd++; \
660 orbjoin_sp_pair(tv->orbits, OrbList, n, A, V, &tv->stats->numorbits); \
661 MakeTree(A, V, sg, n, tv, FALSE); \
662 } }
663 
664 #define SETPAIRS(A, V) { if (A != V) { \
665 PrmPairs[tv->permInd].arg = A; \
666 PrmPairs[tv->permInd].val = V; \
667 tv->permInd++; \
668 } }
669 
670 #define SETPAIRSAUT(A, V) { if ((A != V) && (AUTPERM[A] != V)) { \
671 AUTPERM[A] = V; \
672 PrmPairs[tv->permInd].arg = A; \
673 PrmPairs[tv->permInd].val = V; \
674 tv->permInd++; \
675 } }
676 
677 #define SETPAIRSAUTANDTREE(arg, val) { if (tv->build_autom) { SETPAIRSAUT(arg, val) } \
678 if (arg != val) orbjoin_sp_pair(tv->orbits, OrbList, n, arg, val, &tv->stats->numorbits); \
679 MakeTree(arg, val, sg_orig, n, tv, FALSE); }
680 
681 #define PRINTF2(A, B) if (tv->options->verbosity > 3) printf(A, B)
682 #define PRINTF2_2(A, B, C) if (tv->options->verbosity > 3) printf(A, B, C)
683 #define PRINTF2_3(A, B, C, D) if (tv->options->verbosity > 3) printf(A, B, C, D)
684 #define PRINTF2_4(A, B, C, D, E) if (tv->options->verbosity > 3) printf(A, B, C, D, E)
685 
686 #define VERB_PRINT(V,Verb,R) if (tv->options->verbosity >= Verb) { \
687 fprintf(outfile,"\033[0;32m%s\033[0m ",V); \
688 if (R) fprintf(outfile,"\n"); }
689 
690 /* data decls. for CPUTIME */
691 #ifdef  CPUDEFS
692 CPUDEFS
693 #endif
694 
695 #if !MAXN
696 DYNALLSTAT(int, AUTPERM, AUTPERM_sz);
697 DYNALLSTAT(int, BreakSteps, BreakSteps_sz);
698 DYNALLSTAT(int, CStack, CStack_sz);
699 DYNALLSTAT(int, CurrOrbSize, CurrOrbSize_sz);
700 DYNALLSTAT(int, CurrRefCells, CurrRefCells_sz);
701 DYNALLSTAT(boolean, Diff, Diff_sz);
702 DYNALLSTAT(boolean, Factorials, Factorials_sz);
703 DYNALLSTAT(int, fix, fix_sz);
704 DYNALLSTAT(int, IDENTITY_PERM, IDENTITY_PERM_sz);
705 DYNALLSTAT(int, Markers, Markers_sz);
706 DYNALLSTAT(int, TreeMarkers, TreeMarkers_sz);
707 DYNALLSTAT(int, AutMarkers, AutMarkers_sz);
708 DYNALLSTAT(int, MarkHitVtx, MarkHitVtx_sz);
709 DYNALLSTAT(int, MultRefCells, MultRefCells_sz);
710 DYNALLSTAT(int, NghCounts, NghCounts_sz);
711 DYNALLSTAT(int, OrbSize, OrbSize_sz);
712 DYNALLSTAT(int, OrbList, OrbList_sz);
713 DYNALLSTAT(pair, PrmPairs, PrmPairs_sz);
714 DYNALLSTAT(int, TempOrbList, TempOrbList_sz);
715 DYNALLSTAT(int, RefCells, RefCells_sz);
716 DYNALLSTAT(searchtrie*, RefPath, RefPath_sz);
717 DYNALLSTAT(int, Singletons, Singletons_sz);
718 DYNALLSTAT(int, SplCls, SplCls_sz);
719 DYNALLSTAT(int, SplCnt, SplCnt_sz);
720 DYNALLSTAT(int, SplPos, SplPos_sz);
721 DYNALLSTAT(int, StackMarkers, StackMarkers_sz);
722 DYNALLSTAT(int, TheTrace, TheTrace_sz);
723 DYNALLSTAT(int, TheTraceCC, TheTraceCC_sz);
724 DYNALLSTAT(int, TheTraceSplNum, TheTraceSplNum_sz);
725 DYNALLSTAT(int, TheTraceSteps, TheTraceSteps_sz);
726 DYNALLSTAT(int, TEMPLAB, TEMPLAB_sz);
727 DYNALLSTAT(int, TEMPINVLAB, TEMPINVLAB_sz);
728 DYNALLSTAT(int, WeightsSeq, WeightsSeq_sz);
729 DYNALLSTAT(int, WorkArray, WorkArray_sz);
730 DYNALLSTAT(int, WorkArray0, WorkArray0_sz);
731 DYNALLSTAT(int, WorkArray1, WorkArray1_sz);
732 DYNALLSTAT(int, WorkArray2, WorkArray2_sz);
733 DYNALLSTAT(int, WorkArray3, WorkArray3_sz);
734 DYNALLSTAT(int, WorkArray4, WorkArray4_sz);
735 DYNALLSTAT(int, WorkArray5, WorkArray5_sz);
736 DYNALLSTAT(int, WorkArray6, WorkArray6_sz);
737 DYNALLSTAT(int, WorkArray7, WorkArray7_sz);
738 DYNALLSTAT(int, Neighbs1, Neighbs1_sz);
739 DYNALLSTAT(int, Neighbs2, Neighbs2_sz);
740 DYNALLSTAT(int, TreeStack, TreeStack_sz);
741 DYNALLSTAT(TracesSpine, Spine, Spine_sz);
742 DYNALLSTAT(trie*, TrieArray, TrieArray_sz);
743 DYNALLSTAT(grph_strct, TheGraph, TheGraph_sz);
744 DYNALLSTAT(ExpPathInfo, EPCodes, EPCodes_sz);
745 #else
746 static TLS_ATTR int CStack[MAXN];
747 static TLS_ATTR int AUTPERM[MAXN];
748 static TLS_ATTR int BreakSteps[MAXN];
749 static TLS_ATTR int CurrOrbSize[MAXN];
750 static TLS_ATTR int CurrRefCells[MAXN];
751 static TLS_ATTR boolean Diff[MAXN];
752 static TLS_ATTR boolean Factorials[MAXN];
753 static TLS_ATTR int fix[MAXN];
754 static TLS_ATTR int IDENTITY_PERM[MAXN];
755 static TLS_ATTR int Markers[MAXN];
756 static TLS_ATTR int TreeMarkers[MAXN];
757 static TLS_ATTR int AutMarkers[MAXN];
758 static TLS_ATTR int MarkHitVtx[MAXN];
759 static TLS_ATTR int MultRefCells[MAXN];
760 static TLS_ATTR int NghCounts[MAXN];
761 static TLS_ATTR int OrbSize[MAXN];
762 static TLS_ATTR int OrbList[MAXN];
763 static TLS_ATTR pair PrmPairs[MAXN];
764 static TLS_ATTR int TempOrbList[MAXN];
765 static TLS_ATTR int RefCells[MAXN];
766 static TLS_ATTR searchtrie* RefPath[MAXN];
767 static TLS_ATTR int Singletons[MAXN];
768 static TLS_ATTR int SplCls[MAXN];
769 static TLS_ATTR int SplCnt[MAXN];
770 static TLS_ATTR int SplPos[MAXN];
771 static TLS_ATTR int StackMarkers[MAXN];
772 static TLS_ATTR int TheTrace[MAXN];
773 static TLS_ATTR int TheTraceCC[MAXN];
774 static TLS_ATTR int TheTraceSplNum[MAXN];
775 static TLS_ATTR int TheTraceSteps[MAXN];
776 static TLS_ATTR int TEMPLAB[MAXN];
777 static TLS_ATTR int TEMPINVLAB[MAXN];
778 static TLS_ATTR int WeightsSeq[MAXN];
779 static TLS_ATTR int WorkArray[MAXN];
780 static TLS_ATTR int WorkArray0[MAXN];
781 static TLS_ATTR int WorkArray1[MAXN];
782 static TLS_ATTR int WorkArray2[MAXN];
783 static TLS_ATTR int WorkArray3[MAXN];
784 static TLS_ATTR int WorkArray4[MAXN];
785 static TLS_ATTR int WorkArray5[MAXN];
786 static TLS_ATTR int WorkArray6[MAXN];
787 static TLS_ATTR int WorkArray7[MAXN];
788 static TLS_ATTR int TreeStack[MAXN];
789 static TLS_ATTR TracesSpine Spine[MAXN];
790 static TLS_ATTR trie* TrieArray[MAXN];
791 static TLS_ATTR grph_strct TheGraph[MAXN];
792 static TLS_ATTR int Neighbs1[MAXN];
793 static TLS_ATTR int Neighbs2[MAXN];
794 static TLS_ATTR ExpPathInfo EPCodes[MAXN];
795 #endif
796 
797 #define PERMSTACK WorkArray1
798 #define CYCLES WorkArray1
799 #define HitCls WorkArray2
800 #define CYCOLR WorkArray2
801 #define HitVtx WorkArray3
802 #define CYLGTH WorkArray3
803 #define CYMULT WorkArray4
804 #define HitCount WorkArray5
805 #define ElmHitCll WorkArray5
806 #define CYCPOS WorkArray5
807 #define CYCHIT TempOrbList
808 #define LGHATTR RefCells
809 #define CYCREP MultRefCells
810 #define TempOrbSize TEMPLAB
811 #define AutomCount TEMPINVLAB
812 #define CanonIndices MarkHitVtx
813 #define NSFCells NghCounts
814 #define TreeNodes AutMarkers
815 #define CellMarkers1 WorkArray6
816 #define CellMarkers2 WorkArray7
817 #define SingNonSing Singletons
818 
819 static TLS_ATTR FILE *outfile;
820 
821 /* Brendan's SCHREIER */
822 static TLS_ATTR schreier  *gpB;                /* This will point to the Schreier structure */
823 static TLS_ATTR permnode  *gensB;            /* This will point to the stored generators */
824 
825 static TLS_ATTR Candidate *GarbList, *SpOrd, *SpCyc, *SpSwp;
826 static TLS_ATTR Partition *SpPart1, *SpPart2;
827 static TLS_ATTR TracesSpine *SpineTL, *SpineFL, *SpineTL_tl;
828 static TLS_ATTR trie *trieroot, *trieref;
829 static TLS_ATTR int *TempOrbits = NULL;
830 static TLS_ATTR sparsegraph redgraph;
831 
832 
833 void
Traces(sparsegraph * g_arg,int * lab,int * ptn,int * orbits_arg,TracesOptions * options_arg,TracesStats * stats_arg,sparsegraph * canong_arg)834 Traces(sparsegraph *g_arg, int *lab, int *ptn,
835        int *orbits_arg, TracesOptions *options_arg, TracesStats *stats_arg,
836        sparsegraph *canong_arg) {
837     int i, j;
838     int tmp;
839     int deg, vtx1, vtx2, *ngh1, *ngh2, *wgh1, *wgh2, ord;
840     size_t j1;
841 
842     trielist *STStart, *STAux;
843     searchtrie *TrieNode;
844     int retval;
845     Partition *CurrPart, *NextPart;
846     Candidate *CurrCand, *NextCand, *BestCand, *AuxCand;
847 
848     const int n = g_arg->nv;
849     const int m = SETWORDSNEEDED(n);
850 
851     if (g_arg->nv > (NAUTY_INFINITY-2))
852     {
853         fprintf(ERRFILE, "Traces: need n <= %d, but n=%d\n\n",
854                 NAUTY_INFINITY-2, g_arg->nv);
855         return;
856     }
857 
858     Allocate_Traces_Structures(n);
859 
860     struct TracesVars *tv = malloc(sizeof(struct TracesVars));
861     if (tv == NULL) {
862         fprintf(ERRFILE, "\nError, memory not allocated.\n");
863         exit(1);
864     }
865     struct TracesInfo *ti = malloc(sizeof(struct TracesInfo));
866     if (ti == NULL) {
867         fprintf(ERRFILE, "\nError, memory not allocated.\n");
868         exit(1);
869     }
870 
871     trieroot = NULL;
872     NextCand = GarbList = NULL;
873     DYNFREE(g_arg->w,g_arg->wlen);   /* to be removed in presence of weightd edges */
874 
875     Initialize_Traces_Variables(tv, options_arg, stats_arg, orbits_arg, g_arg, canong_arg, n);
876 
877     outfile = (tv->options->outfile == NULL ? stdout : tv->options->outfile);
878 
879     SpOrd = SpCyc = SpSwp = NULL;
880     SpPart1 = SpPart2 = NULL;
881 
882     if (tv->options->verbosity >= 2) {
883         for (i = n, tv->digits = 0; i > 0; i /= 10, ++tv->digits) {}
884         sprintf(tv->digstring, "%s%dd ", "%", tv->digits);
885     }
886 
887     /* Initialize group and statistics */
888     Initialize_Traces_Statistics(stats_arg,n);
889 
890     if (tv->options->verbosity >= 2) {
891         Initialize_Traces_Time_Variables(tv);
892     }
893 
894     /* Initialize lab and ptn when in the unit partition case */
895     if (tv->options->defaultptn) {
896         for (i = 0; i < n; i++) {
897             IDENTITY_PERM[i] = i;
898             ptn[i] = NAUTY_INFINITY;
899         }
900         ptn[n-1] = 0;
901         memcpy(lab, IDENTITY_PERM, n*sizeof(int));
902     } else {
903         for (i = 0; i < n; i++) {
904             IDENTITY_PERM[i] = i;
905         }
906     }
907 
908     memcpy(orbits_arg, IDENTITY_PERM, n*sizeof(int));
909 
910     if (tv->options->generators) {
911         tv->stats->numorbits = given_gens(g_arg, *tv->options->generators,
912                                           orbits_arg, tv->options->digraph);
913         newgroup(&gpB, NULL, n);
914         gensB = *tv->options->generators;
915         expandschreier(gpB, &gensB, n);
916         ti->thegrouphaschanged = TRUE;
917         ti->identitygroup = FALSE;
918         memcpy(OrbList, gpB->orbits, n*sizeof(int));
919     }
920     else {
921         newgroup(&gpB, &gensB, n);
922         memcpy(OrbList, IDENTITY_PERM, n*sizeof(int));
923         tv->stats->numorbits = n;
924         ti->thegrouphaschanged = FALSE;
925         ti->identitygroup = TRUE;
926     }
927 
928     copy_sg_structure(&redgraph, g_arg);
929 
930     tv->graph = &redgraph;
931     if (g_arg->w) memcpy(tv->graph->w, g_arg->w, tv->graph->wlen*sizeof(int));
932     memcpy(tv->graph->e, g_arg->e, tv->graph->elen*sizeof(int));
933 
934     for (i=0; i<n; i++) {
935         EPCodes[i].info = 0;
936         TheGraph[i].d = g_arg->d[i];
937         if (TheGraph[i].d > tv->maxdeg) {
938             tv->maxdeg = TheGraph[i].d;
939         }
940         if (TheGraph[i].d < tv->mindeg) {
941             tv->mindeg = TheGraph[i].d;
942         }
943         TheGraph[i].e = tv->graph->e + g_arg->v[i];
944         if (g_arg->w)
945             TheGraph[i].w = tv->graph->w + g_arg->v[i];
946         else
947             TheGraph[i].w = NULL;
948         TheGraph[i].one = FALSE;
949     }
950 
951     ord = 0;
952 
953     /*----------- WEIGHTS --------------*/
954     if (tv->options->weighted) {
955         WeightCodes(n);
956         ord = trie_classify(n,tv);
957     }
958     /*----------------------------------*/
959 
960     if ((tv->maxdeg == tv->mindeg) && (ord == 0)) ti->regular = TRUE; else ti->regular = FALSE;
961 
962     tv->currorbit = gpB->orbits;
963 
964     memcpy(AUTPERM, IDENTITY_PERM, n*sizeof(int));
965     tv->permInd = 0;
966 
967     memset(fix, 0, n*sizeof(int));
968     memset(TheTraceCC, 0, n*sizeof(int));
969     memset(Factorials, 0, n*sizeof(int));
970     /* ran_init(1234);  any long int as an argument */
971 
972     /* The graph is sparse? */
973     if (g_arg->nde < n || g_arg->nde / n < n / (g_arg->nde / n)) {
974         ti->thegraphisparse = TRUE;
975     }
976     else {
977         ti->thegraphisparse = FALSE;
978     }
979 
980     tv->preprocessed = 0;
981     ti->deg_one = FALSE;
982     ti->first_matching = FALSE;
983     retval = 0;
984 
985     /* Initialize candidate, partition, cells, orbits */
986     Spine[0].part = NewPartition(n);
987     CurrPart = Spine[0].part;
988     memset(CurrPart->inv, 0, n*sizeof(int));
989 
990     NextPart = NewPartition(n);
991     CurrCand = NewCandidate(n, &GarbList, TRUE);
992 
993     CurrCand->singcode = 0;
994     TempOrbits = NULL;
995     STStart = NULL;
996 
997     if (ti->regular) {
998         if (tv->options->defaultptn) {
999             memcpy(CurrCand->lab, IDENTITY_PERM, n*sizeof(int));
1000             memcpy(CurrCand->invlab, IDENTITY_PERM, n*sizeof(int));
1001             CurrPart->cells = 1;
1002             CurrPart->cls[0] = n;
1003             TheTrace[0] = 0;
1004         }
1005         else {
1006             memcpy(CurrCand->lab, lab, n*sizeof(int));
1007             CurrPart->cells = 0;
1008             j = 0;
1009             for (i = 0; i < n; i++) {
1010                 if (j) CurrPart->inv[i] = j;
1011                 CurrCand->invlab[CurrCand->lab[i]] = i;
1012                 if (!ptn[i]) {
1013                     CurrPart->cls[j] = i-j+1;
1014                     if (CurrPart->cls[j] == 1) {
1015                         CurrCand->singcode = MASHCOMM(CurrCand->singcode, CurrCand->lab[j]);
1016                     }
1017                     TheTrace[CurrPart->cells++] = j;
1018                     j = i+1;
1019                 }
1020             }
1021         }
1022     } else {
1023         if (tv->options->weighted) {
1024             CurrPart->cells = traces_vertexclass_refine(n, lab, ptn,
1025                                                         CurrCand, CurrPart, WeightsSeq);
1026         }
1027         else {
1028             CurrPart->cells = traces_vertexclass_refine (n, lab, ptn,
1029                                                          CurrCand, CurrPart, g_arg->d);
1030         }
1031     }
1032 
1033     memset(NghCounts,0,n*sizeof(int));
1034     if (tv->options->verbosity == 7) PrintPartition(CurrCand->lab,CurrPart->cls,n,labelorg,1323);
1035 
1036     /* Check for deg 1 vertices */
1037     ti->deg_one = Check_degree_one(g_arg, CurrCand, CurrPart, n);
1038 
1039 #if !MAXN
1040     DYNALLOC1(int, Neighbs1, Neighbs1_sz, tv->maxdeg, "Traces");
1041     DYNALLOC1(int, Neighbs2, Neighbs2_sz, tv->maxdeg, "Traces");
1042 #endif
1043 
1044     if (ti->deg_one) {
1045         tv->preprocessed = Preprocess(g_arg, &gensB, CurrCand, n, CurrPart, tv);
1046     }
1047 
1048     if (tv->preprocessed) {
1049         memset(Diff,0,n*sizeof(boolean));
1050         for (i=0; i<n; i++) {
1051             if ((TheGraph[i].d > 1) && (tv->input_graph->d[i] != TheGraph[i].d))
1052                 Diff[i] = TRUE;
1053         }
1054     }
1055 
1056     /* Initialization of Spine structure */
1057     SpineFL = Spine;
1058     SpineFL->tgtcell = SpineFL->tgtpos = 0;
1059     SpineFL->tgtend = n;
1060     SpineFL->tgtfrom = -1;
1061     SpineFL->trcstart = 0;
1062     SpineFL->trcend = CurrPart->active = CurrPart->cells;
1063     SpineFL->ccstart = SpineFL->ccend = 0;
1064     SpineFL->stpstart = SpineFL->stpend = 0;
1065     SpineFL->singstart = SpineFL->singend = 0;
1066     SpineFL->thetracexists = FALSE;
1067     SpineFL->liststart = SpineFL->listend = CurrCand;
1068     SpineFL->levelcounter = 1;
1069     SpineFL->keptcounter = 1;
1070     SpineFL->updates = 1;
1071 
1072     /* Further initializations */
1073     tv->maxtreelevel = 0;
1074     tv->tolevel = 0;
1075     tv->tcell = 0;
1076     UPDATE_LINELGTH
1077 
1078     /* First refinement */
1079     if (tv->preprocessed < 2)
1080         traces_refine(CurrCand, n, CurrPart, tv, ti, 0, FALSE);
1081 
1082     CurrCand->name = 0;
1083 
1084     if (CurrPart->cells == n) {
1085         tv->stats->canupdates++;
1086 
1087         /* CANONICAL FORM ? */
1088         if (tv->options->getcanon) {
1089             memcpy(lab, CurrCand->lab, n*sizeof(int));
1090             if (canong_arg) memcpy(CurrPart->inv, CurrCand->invlab, n*sizeof(int));
1091             if (tv->options->usercanonproc != NULL)
1092             {
1093                 (*tv->options->usercanonproc)((graph*)g_arg, lab, (graph*)canong_arg, tv->stats->canupdates, CurrCand->code, m, n);
1094             }
1095         }
1096     }
1097     else {
1098         STStart = searchtrie_new(n, tv);
1099         CurrCand->stnode = tv->strielist->triearray;
1100         NextCand = NewCandidate(n, &GarbList, TRUE);
1101         SpineFL->listcounter = 1;
1102         tv->tcellevel = 0;
1103         ti->exitfromref = FALSE;
1104         Spine[1].levelcounter = 0;
1105         Spine[1].updates = 0;
1106         Spine[1].tgtfrom = 0;
1107 
1108         memset(WorkArray, 0, n*sizeof(int));
1109 
1110         do {
1111             tv->fromlevel = tv->tolevel;
1112             SpineFL = Spine+tv->fromlevel;
1113 
1114             if (CurrCand) {
1115                 switch (tv->compstage) {
1116                     case 0: retval = CompStage0(CurrPart, NextPart, CurrCand, NextCand, m, n, tv, ti);
1117                         break;
1118                     case 1:
1119                         if (!TempOrbits) {
1120                             memcpy(WorkArray1, tv->currorbit, n*sizeof(int));
1121                             TempOrbits = WorkArray1;
1122                         }
1123                         memset(TempOrbSize, 0, n*sizeof(int));
1124                         for (i=SpineTL->tgtcell; i<SpineTL->tgtend; i++) {
1125                             TempOrbSize[TempOrbits[CurrCand->lab[i]]]++;
1126                         }
1127                         retval = CompStage1(CurrPart, NextPart, CurrCand, NextCand, m, n, tv, ti);
1128                         break;
1129                     case 2:
1130                         retval = CompStage2(CurrPart, NextPart, CurrCand, NextCand, m, n, tv, ti);
1131                         break;
1132                     default:
1133                         break;
1134                 }
1135                 if (retval == NAUTY_ABORTED)
1136                     tv->stats->errstatus = NAUABORTED;
1137                 else if (retval == NAUTY_KILLED) {
1138                     tv->stats->errstatus = NAUKILLED;
1139                     return;
1140                 }
1141             }
1142             /* NEXT CANDIDATE */
1143             if (ti->thereisnextlevel) {
1144                 if (tv->nextlevel != tv->fromlevel) {
1145                     UPDATE_LINELGTH
1146                 }
1147                 tv->tolevel = tv->nextlevel;
1148                 CurrCand = Spine[tv->nextlevel].liststart;
1149                 CurrPart = Spine[tv->nextlevel].part;
1150             }
1151         }
1152         while (ti->thereisnextlevel);
1153 
1154         if (!retval) {
1155             if (tv->compstage) {
1156                 memset(CurrOrbSize, 0, n*sizeof(int));
1157                 for (i=0; i<n; i++) {
1158                     CurrOrbSize[TempOrbits[i]]++;
1159                 }
1160             }
1161 
1162             if (!tv->options->getcanon) {
1163                 if (tv->compstage) {
1164                     tv->maxtreelevel++;
1165                     TrieNode = Spine[tv->maxtreelevel].liststart->stnode;
1166                     if (TrieNode->father) {
1167                         TrieNode = TrieNode->father;
1168                     }
1169                     if (!ti->exitfromref) {
1170                         TrieNode->index = 0;
1171                         for (i=1; i<AutomCount[0]; i++) {
1172                             TrieNode->index += CurrOrbSize[AutomCount[i]];
1173                             PRINT_INDEX(TrieNode,4,30)
1174                         }
1175                     }
1176                 }
1177             }
1178 
1179             if (tv->maxtreelevel) PRINT_LINE_PLUS(tv->maxtreelevel);
1180 
1181             AuxCand = Spine[tv->maxtreelevel].liststart;
1182             while (!AuxCand->do_it) {
1183                 AuxCand = AuxCand->next;
1184             }
1185 
1186             /* CANONICAL FORM ? */
1187             if (tv->options->getcanon) {
1188                 BestCand = AuxCand;
1189                 AuxCand = AuxCand->next;
1190                 while (AuxCand) {
1191                     if (AuxCand->do_it) {
1192                         if (comparelab_tr(g_arg, BestCand->lab, BestCand->invlab, AuxCand->lab, AuxCand->invlab, Spine[tv->maxtreelevel].part->cls, Spine[tv->maxtreelevel].part->inv) == 1) {
1193                             BestCand = AuxCand;
1194                             tv->stats->canupdates++;
1195                             if (tv->options->usercanonproc != NULL)
1196                             {
1197                                 (*tv->options->usercanonproc)((graph*)g_arg, lab, (graph*)canong_arg, tv->stats->canupdates, CurrCand->code, m, n);
1198                             }
1199                         }
1200                     }
1201                     AuxCand = AuxCand->next;
1202                 }
1203 
1204                 grouporderplus(g_arg, BestCand, Spine[tv->maxtreelevel].part, &gensB, &(tv->stats->grpsize1), &(tv->stats->grpsize2), n, tv, ti);
1205 
1206                 if (tv->options->verbosity >= 2) {
1207                     LINE(32, "-")
1208                     NEXTLINE
1209                     fprintf(outfile, "Canonical:");
1210                     PRINTCAND(BestCand, tv->maxtreelevel)
1211                     PRINT_RETURN
1212                 }
1213                 memcpy(lab, BestCand->lab, n*sizeof(int));
1214                 if (canong_arg) memcpy(CurrPart->inv, BestCand->invlab, n*sizeof(int));
1215             }
1216             else {
1217                 grouporderplus(g_arg, AuxCand, Spine[tv->maxtreelevel].part, &gensB, &(tv->stats->grpsize1), &(tv->stats->grpsize2), n, tv, ti);
1218             }
1219 
1220             if (tv->options->verbosity >= 2) {
1221                 if (tv->linelgth < 40) {
1222                     tv->linelgth = 40;
1223                 }
1224                 LINE(32, "-")
1225                 NEXTLINE
1226             }
1227 
1228         }
1229     }
1230     tv->stats->treedepth = tv->treedepth;
1231     if (Spine[tv->treedepth].part->code == -1) {
1232         tv->stats->treedepth--;
1233     }
1234 
1235     if (tv->options->verbosity >= 2) {
1236         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,
1237                 tv->expaths, tv->autchk, SS(tv->stats->interrupted, "", "s"), (tv->options->strategy == 0 ? "breadth-first" : "depth-first"), tv->specialgens);
1238         PRINT_RETURN
1239     }
1240     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);
1241 
1242     if (tv->options->getcanon && canong_arg) {
1243         canong_arg->nv  = g_arg->nv;
1244         canong_arg->nde  = g_arg->nde;
1245         SG_ALLOC(*canong_arg, g_arg->nv, g_arg->nde, "traces canong");
1246         updatecan_tr(g_arg, canong_arg, lab, CurrPart->inv, 0);
1247     }
1248 
1249     if (tv->options->generators) {
1250         deleteunmarked(&gensB);
1251         *tv->options->generators = gensB;
1252         freeschreier(&gpB, NULL);
1253     }
1254     else {
1255         freeschreier(&gpB, &gensB);
1256         schreier_freedyn();
1257     }
1258 
1259     while (STStart) {
1260         STAux = STStart;
1261         free(STAux->triearray);
1262         STStart = STStart->next;
1263         free(STAux);
1264     }
1265 
1266     tv->canlist = 0;
1267     for (i=0; i<=tv->treedepth; i++) {
1268         if (Spine[i].liststart) {
1269             tv->canlist += FreeList(Spine[i].liststart, TRUE);
1270             Spine[i].liststart = Spine[i].listend = NULL;
1271         }
1272     }
1273 
1274     if (GarbList) {
1275         tv->stats->peaknodes = FreeList(GarbList, FALSE);
1276     }
1277 
1278     FREECAND(NextCand)
1279     FREECAND(SpOrd)
1280     FREECAND(SpCyc)
1281     FREECAND(SpSwp)
1282     FREEPART(NextPart)
1283     FREEPART(SpPart1)
1284     FREEPART(SpPart2)
1285 
1286     if (!tv->options->getcanon && trieroot) {
1287         for (i=0; i<=tv->triepos; i++) {
1288             free(TrieArray[i]);
1289         }
1290     }
1291 
1292     for (i=0; i <= tv->treedepth; i++) {
1293         FREEPART(Spine[i].part)
1294     }
1295 
1296     CurrCand = GarbList = NULL;
1297     tv->stats->peaknodes += tv->canlist;
1298 
1299     if (tv->graph != g_arg) {
1300         SG_FREE(redgraph);
1301     }
1302     free(tv);
1303     free(ti);
1304     traces_freedyn();
1305 
1306     return;
1307 }
1308 
traces_vertexclass_refine(int n,int * lab,int * ptn,Candidate * Cand,Partition * Part,int * RefArray)1309 int traces_vertexclass_refine (int n, int *lab, int *ptn, Candidate *Cand, Partition *Part, int *RefArray) {
1310 
1311     int i, j, k, aux, cells, end;
1312 
1313     memcpy(Cand->lab, lab, n*sizeof(int));
1314 
1315     cells = 0;
1316     j = 0;
1317 
1318     for (i = 0; i < n; i++) {
1319         WorkArray1[i] = RefArray[Cand->lab[i]];
1320         if (!ptn[i]) {
1321             TheTrace[cells++] = j;
1322 
1323             sort2ints(WorkArray1+j,Cand->lab+j,i-j+1);
1324 
1325             aux = WorkArray1[j];
1326             Part->cls[j] = 1;
1327             Part->inv[j] = j;
1328             Cand->invlab[Cand->lab[j]] = j;
1329 
1330             if (i == j) {
1331                 Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[j]);
1332                 j++;
1333             } else {
1334                 end = i+1;
1335                 for (k=j+1; k<end; k++) {
1336                     if (WorkArray1[k] == aux) {
1337                         (Part->cls[j])++;
1338                         Part->inv[k] = j;
1339                         Cand->invlab[Cand->lab[k]] = k;
1340                     } else {
1341                         if (Part->cls[j] == 1) {
1342                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[j]);
1343                         }
1344 
1345                         TheTrace[cells++] = k;
1346                         j = k;
1347                         aux = WorkArray1[j];
1348                         Part->cls[j] = 1;
1349                         Part->inv[j] = j;
1350                         Cand->invlab[Cand->lab[j]] = j;
1351                     }
1352                 }
1353                 j = end;
1354             }
1355         }
1356     }
1357     return cells;
1358 }
1359 
traces_refine(Candidate * Cand,int n,Partition * Part,struct TracesVars * tv,struct TracesInfo * ti,int num_indv,boolean make_code)1360 int traces_refine(Candidate *Cand,
1361                   int n,
1362                   Partition *Part,
1363                   struct TracesVars* tv,
1364                   struct TracesInfo *ti,
1365                   int num_indv,
1366                   boolean make_code) {
1367 
1368     int i, j, k, jk, sc, ind0, ind1, ind2, ind3, ind4, tlp1, labi;
1369     int value, iend, newcell;
1370     int HitClsInd, SplInd, SplCntInd, CStackInd, TraceInd, TraceCCInd, TraceStepsInd, SingInd;
1371     int j1int, iend1int;
1372     unsigned int longcode;
1373     int newtrace = FALSE;
1374     int Sparse = TRUE;
1375     int *lab, *cls, *InvLab, *TracePos, *SplitCell, *LabCell, *TraceEnd, Traceccend, *Tracestpend;
1376     int BigCell, BigCellPos, BigCellSize;
1377     boolean TraceCell = FALSE;
1378     int *nghb;
1379     int conta;
1380     const int variation = 0;
1381     int currentweight, weightstart, weightend, currentcell, currentsize;
1382 
1383     VERB_PRINT("RFLT",3,FALSE)
1384 
1385     HitClsInd = 0;
1386     if (tv->stackmark > (NAUTY_INFINITY-2)) {
1387         memset(StackMarkers, 0, n*sizeof(int));
1388         tv->stackmark = 0;
1389     }
1390     tv->stackmark++;
1391     tv->augmented_cells = Part->cells;
1392 
1393     SpineTL = Spine+tv->tolevel;
1394     TraceEnd = &(SpineTL->trcend);
1395     Traceccend = SpineTL->ccend;
1396     Tracestpend = &(SpineTL->stpend);
1397     TraceCCInd = SpineTL->ccstart;
1398     TraceStepsInd = SpineTL->stpstart;
1399 
1400     SingInd = SpineTL->singstart + num_indv;
1401 
1402     lab = Cand->lab;
1403     InvLab = Cand->invlab;
1404     cls = Part->cls;
1405 
1406     UPDATEMIN(Part->active, n-1);
1407     memcpy(CStack+1, TheTrace+SpineTL->trcstart, (Part->active)*sizeof(int));
1408     CStackInd = Part->active;
1409     for (i = 1; i <= CStackInd; i++) {
1410         StackMarkers[CStack[i]] = tv->stackmark;
1411     }
1412 
1413     longcode = Part->cells;
1414     TraceInd = SpineTL->trcstart+Part->active;
1415     if (!SpineTL->thetracexists) {
1416         newtrace = TRUE;
1417     }
1418     conta=0;
1419 
1420     while (CStackInd > 0) {
1421 
1422         weightend = 0;
1423 
1424         if (tv->mark > (NAUTY_INFINITY-2)) {
1425             memset(Markers, 0, n*sizeof(int));
1426             memset(MarkHitVtx, 0, n*sizeof(int));
1427             tv->mark = 0;
1428         }
1429         tv->mark++;
1430 
1431         if (Part->cells == n) break;
1432 
1433         k = Select_from_CStack(cls, CStackInd);
1434 
1435         currentcell = CStack[k];
1436         currentsize = currentcell+cls[currentcell];
1437         CStack[k] = CStack[CStackInd--];
1438         StackMarkers[currentcell] = 0;
1439 
1440         labi = lab[currentcell];
1441         iend1int = TheGraph[labi].d;
1442         nghb =  TheGraph[labi].e;
1443 
1444         do {
1445             ind0 = currentcell;
1446             ind2 = currentsize;
1447             weightstart = weightend;
1448 
1449             if (tv->options->weighted) {
1450                 currentweight = (TheGraph[labi].w)[weightstart];
1451                 while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
1452                     weightend++;
1453                 }
1454             } else {
1455                 weightend = TheGraph[labi].d;
1456             }
1457 
1458             if (!newtrace) {
1459                 TraceCell = ((ind0 == TheTraceCC[TraceCCInd]) && (TraceCCInd < Traceccend));
1460             }
1461 
1462             /* Analysis of occurrences of neighbors of the current cell */
1463             /* The list of cells with neighbors in the current cell is  built */
1464             if (cls[ind0] == 1) {            /* SINGLETON CURRENT CELL CASE */
1465 
1466                 /* NEIGHCOUNT_SING_MULT */
1467                 HitClsInd = 0;
1468                 for (j1int = weightstart; j1int < weightend; ++j1int) {
1469                     k = nghb[j1int];
1470                     value = Part->inv[InvLab[k]];
1471                     if (cls[value] > 1) {
1472                         if (Markers[value] != tv->mark) {
1473                             HitCls[HitClsInd++] = value;
1474                             Markers[value] = tv->mark;
1475                             ElmHitCll[value] = value;
1476                         }
1477                         HitVtx[ElmHitCll[value]++] = k;
1478                     } else {
1479                         switch (variation) {
1480                             case 1:
1481                                 longcode = MASHCOMM(longcode, value);
1482                                 break;
1483                             default:
1484                                 break;
1485                         }
1486                     }
1487                 }
1488                 /* end NEIGHCOUNT_SING_MULT */
1489 
1490                 tv->mark++;
1491                 FIND_SPLIT_CELLS;
1492 
1493                 /* SINGLETON CC CASE */
1494                 if (SplInd) {
1495                     if (newtrace) {
1496                         TheTraceCC[TraceCCInd] = ind0;
1497                     }
1498                     if (!TraceCell) {
1499                         TheTraceCC[TraceCCInd] = ind0;
1500                         newtrace = TRUE;
1501                     }
1502 
1503                     TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd, &Traceccend)
1504 
1505                     /* Sorting the cells to be split */
1506                     sort_Split_Array(SplCls, SplInd);
1507 
1508                     for (j = 0; j < SplInd; j++) {
1509                         ind1 = SplCls[j];
1510                         i = ind1+cls[ind1]-ElmHitCll[ind1];
1511                         TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
1512                     }
1513 
1514                     for (j = 0; j < SplInd; j++) {
1515                         /* REARRANGE_CELLS */
1516                         ind1 = SplCls[j];
1517                         cls[ind1] = cls[ind1]-ElmHitCll[ind1];
1518                         newcell = ind1+cls[ind1];
1519                         cls[newcell] = ElmHitCll[ind1];
1520                         Part->cells++;
1521                         if (StackMarkers[ind1] != tv->stackmark) {
1522                             if (cls[newcell] < cls[ind1]) {
1523                                 CStack[++CStackInd] = newcell;
1524                                 StackMarkers[newcell] = tv->stackmark;
1525                             }
1526                             else {
1527                                 CStack[++CStackInd] = ind1;
1528                                 StackMarkers[ind1] = tv->stackmark;
1529                             }
1530                         }
1531                         else {
1532                             CStack[++CStackInd] = newcell;
1533                             StackMarkers[newcell] = tv->stackmark;
1534                         }
1535                         SplitCell = HitVtx+ind1;
1536                         ind3 = cls[newcell];
1537                         LabCell = lab+newcell;
1538                         for (jk = 0; jk < ind3; jk++) {
1539                             k = SplitCell[jk];
1540                             i = LabCell[jk];
1541                             Part->inv[newcell+jk] = newcell;
1542                             lab[InvLab[k]] = i;
1543                             InvLab[i] = InvLab[k];
1544                             LabCell[jk] = k;
1545                             InvLab[k] = newcell+jk;
1546                         }
1547                         /* END REARRANGE_CELLS */
1548 
1549                         if (cls[ind1] == 1) {
1550                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[ind1]);
1551                             if (newtrace) Singletons[SingInd] = ind1;
1552                             SingInd++;
1553                         }
1554                         if (cls[newcell] == 1) {
1555                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[newcell]);
1556                             if (newtrace) Singletons[SingInd] = newcell;
1557                             SingInd++;
1558                         }
1559                     }
1560                 }
1561                 else {
1562                     if ((!newtrace) && TraceCell) {
1563                         if (!tv->options->weighted) return 0;
1564                     }
1565                 }
1566             }
1567             else {
1568                 if (ti->thegraphisparse) {
1569 
1570                     /* NEIGHCOUNT_SPARSE_MULT */
1571                     HitClsInd = 0;
1572                     if (cls[ind0] != n) {
1573                         for (i = ind0; i < ind2; i++) {
1574                             labi = lab[i];
1575                             nghb = TheGraph[labi].e;
1576                             for (j = weightstart; j < weightend; j++) {
1577                                 k = nghb[j];
1578                                 if (MarkHitVtx[k] == tv->mark) {
1579                                     NghCounts[k]++;
1580                                 }
1581                                 else {
1582                                     value = Part->inv[InvLab[k]];
1583                                     if (cls[value] > 1) {
1584                                         MarkHitVtx[k] = tv->mark;
1585                                         NghCounts[k] = 1;
1586                                         if (Markers[value] != tv->mark) {
1587                                             HitCls[HitClsInd++] = value;
1588                                             Markers[value] = tv->mark;
1589                                             HitVtx[value] = k;
1590                                             ElmHitCll[value] = 1;
1591                                         }
1592                                         else {
1593                                             HitVtx[value+ElmHitCll[value]++] = k;
1594                                         }
1595                                     }
1596                                     else {
1597                                         switch (variation) {
1598                                             case 1:
1599                                                 longcode = MASHCOMM(longcode, value);
1600                                                 break;
1601                                             default:
1602                                                 break;
1603                                         }
1604                                     }
1605                                 }
1606                             }
1607                         }
1608                     }
1609                     /* End NEIGHCOUNT_SPARSE_MULT */
1610 
1611                     tv->mark++;
1612 
1613                     SplInd = 0;
1614                     SplCls[0] = n;
1615                     for (j = 0; j < HitClsInd; j++) {
1616                         ind1 = HitCls[j];
1617                         if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
1618                             SplCls[SplInd++] = ind1;
1619                         }
1620                         else {
1621                             ind2 = ind1+cls[ind1];
1622                             value = NghCounts[lab[ind1++]];
1623                             for (i = ind1; i < ind2; i++)
1624                             {
1625                                 if (NghCounts[lab[i]] != value)
1626                                 {
1627                                     SplCls[SplInd++] = HitCls[j];
1628                                     break;
1629                                 }
1630                             }
1631                         }
1632                     }
1633 
1634                     /* SPARSE CASE */
1635                     if (SplInd) {
1636                         if (newtrace) {
1637                             TheTraceCC[TraceCCInd] = ind0;
1638                         }
1639                         if (!TraceCell) {
1640                             TheTraceCC[TraceCCInd] = ind0;
1641                             newtrace = TRUE;
1642                         }
1643                         TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+n, &Traceccend)
1644 
1645                         /* Sorting the cells to be split */
1646                         sort_Split_Array(SplCls, SplInd);
1647 
1648                         for (sc = 0; sc < SplInd; sc++) {    /* For each cell C to be split */
1649                             ind0 = SplCls[sc];
1650                             ind1 = ind0 + cls[ind0];
1651                             SplCntInd = 0;
1652                             if (ElmHitCll[ind0] < cls[ind0]) {
1653                                 SplCnt[SplCntInd++] = 0;
1654                                 SplPos[0] = cls[ind0] - ElmHitCll[ind0];
1655                             }
1656 
1657                             /* According to the numbers of neighbors of C into the current cell */
1658                             /* compute how many vertices in C will be placed into the same new cell */
1659                             iend = ind0 + ElmHitCll[ind0];
1660                             for (i = ind0; i < iend; i++) {
1661                                 value = NghCounts[HitVtx[i]];
1662                                 if (Markers[value] != tv->mark) {
1663                                     Markers[value] = tv->mark;
1664                                     SplCnt[SplCntInd++] = value;
1665                                     SplPos[value] = 1;
1666                                 }
1667                                 else {
1668                                     SplPos[value]++;
1669                                 }
1670                             }
1671                             tv->mark++;
1672 
1673                             if (SplCntInd) {
1674                                 TRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+n, Tracestpend)
1675                             }
1676 
1677                             /* Sort the values deriving from the previous step */
1678                             sort_Split_Array(SplCnt,SplCntInd);
1679                             Part->cells += SplCntInd-1;
1680 
1681                             /* Split the cell C and update the information for sizes of new cells */
1682                             /* Put the new cells into the stack */
1683                             i = ind0;
1684                             if (StackMarkers[i] != tv->stackmark) {
1685                                 BigCellSize = 0;
1686                             }
1687                             for (k = 0; k < SplCntInd; k++) {
1688                                 value = SplPos[SplCnt[k]];
1689                                 cls[i] = value;
1690                                 if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
1691                                     BigCell = i;
1692                                     BigCellPos = CStackInd;
1693                                     BigCellSize = cls[i];
1694                                 }
1695                                 SplPos[SplCnt[k]] = i;
1696                                 i += value;
1697                                 if (i < ind1) {
1698                                     CStack[++CStackInd] = i;
1699                                     StackMarkers[i] = tv->stackmark;
1700                                     TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
1701                                 }
1702                             }
1703 
1704                             if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
1705                                 CStack[BigCellPos] = ind0;
1706                                 StackMarkers[BigCell] = 0;
1707                                 StackMarkers[ind0] = tv->stackmark;
1708                             }
1709                             /* Permute elements of the cell C */
1710                             iend = ind0 + ElmHitCll[ind0];
1711                             for (i = ind0; i < iend; i++) {
1712                                 value = HitVtx[i];
1713                                 j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
1714                                 k = InvLab[value];                /* where HitVtx[i] is in lab */
1715                                 lab[k] = lab[j];
1716                                 lab[j] = value;
1717                                 InvLab[value] = j;
1718                                 InvLab[lab[k]] = k;
1719                                 NghCounts[value] = 0;
1720                             }
1721 
1722                             /* Reconstruct the cell C and update the inverse partition */
1723                             newcell = ind1 - ElmHitCll[ind0];
1724                             i = newcell;
1725                             ind2 = newcell+cls[newcell]-1;
1726                             do {
1727                                 Part->inv[i] = newcell;
1728                                 if (i == ind2) {
1729                                     newcell = i+1;
1730                                     if (newcell < n) ind2 = newcell+cls[newcell]-1;
1731                                 }
1732                             }
1733                             while (++i < ind1);
1734 
1735                             for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
1736                                 if (cls[i] == 1) {
1737                                     Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
1738                                     if (newtrace) Singletons[SingInd] = i;
1739                                     SingInd++;
1740                                 }
1741                             }
1742 
1743                         }
1744                     }
1745                     else {
1746                         if ((!newtrace) && TraceCell) {
1747                             return 0;
1748                         }
1749                     }
1750 
1751                 }
1752                 else {
1753                     if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
1754                         Sparse = FALSE;
1755                     }
1756                     else {
1757                         Sparse = TRUE;
1758                     }
1759                     Sparse = TRUE;
1760                     if (Sparse) {
1761                         /* Counting occurrences of neighbors of the current cell */
1762                         /* The list of cells with neighbors in the current cell is also built */
1763                         if (cls[ind0] == n) {
1764                             for (i = 0; i < n; i++) {
1765                                 NghCounts[i] = TheGraph[i].d;
1766                             }
1767                             HitCls[0] = 0;
1768                             HitClsInd = 1;
1769                         }
1770                         else {
1771                             memset(NghCounts, 0, n*sizeof(int));
1772 
1773                             /* NEIGHCOUNT_DENSE_SPARSE_MULT */
1774                             HitClsInd = 0;
1775                             for (i = ind0; i < ind2; i++) {
1776                                 labi = lab[i];
1777                                 nghb =  TheGraph[labi].e;
1778                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
1779                                     k = nghb[j1int];
1780                                     (NghCounts[k])++;
1781                                     value = Part->inv[InvLab[k]];
1782                                     if (Markers[value] != tv->mark) {
1783                                         if (cls[value] > 1) HitCls[HitClsInd++] = value;
1784                                         Markers[value] = tv->mark;
1785                                     }
1786                                 }
1787                             }
1788                             /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
1789 
1790                         }
1791 
1792                         tv->mark++;
1793 
1794 
1795                         SplInd = 0;
1796                         for (j = 0; j < HitClsInd; j++) {
1797                             ind1 = HitCls[j];
1798                             ind2 = ind1+cls[ind1];
1799                             value = NghCounts[lab[ind1++]];
1800                             for (i = ind1; i < ind2; i++)
1801                             {
1802                                 if (NghCounts[lab[i]] != value)
1803                                 {
1804                                     SplCls[SplInd++] = HitCls[j];
1805                                     break;
1806                                 }
1807                             }
1808                         }
1809 
1810                         /* DENSE-SPARSE CASE */
1811                         if (SplInd) {
1812                             if (newtrace) {
1813                                 TheTraceCC[TraceCCInd] = ind0;
1814                             }
1815                             if (!TraceCell) {
1816                                 TheTraceCC[TraceCCInd] = ind0;
1817                                 newtrace = TRUE;
1818                             }
1819                             TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+2*n, &Traceccend)
1820 
1821                             /* Sorting the cells to be split */
1822                             sort_Split_Array(SplCls, SplInd);
1823 
1824                             for (j = 0; j < SplInd; j++) {    /* For each cell C to be split */
1825                                 ind0 = SplCls[j];
1826                                 ind1 = ind0+cls[ind0];
1827                                 SplCntInd = 0;
1828 
1829                                 /* According to the numbers of neighbors of C into the current cell */
1830                                 /* compute how many vertices in C will be placed into the same new cell */
1831                                 for (i = ind0; i < ind1; i++) {
1832                                     value = NghCounts[lab[i]];
1833                                     if (Markers[value] != tv->mark) {
1834                                         Markers[value] = tv->mark;
1835                                         SplCnt[SplCntInd++] = value;
1836                                         SplPos[value] = 1;
1837                                     }
1838                                     else {
1839                                         SplPos[value]++;
1840                                     }
1841                                 }
1842                                 tv->mark++;
1843 
1844                                 if (SplCntInd) {
1845                                     TRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+2*n, Tracestpend)
1846                                 }
1847 
1848                                 /* Sort the values deriving from the previous step */
1849                                 sort_Split_Array(SplCnt, SplCntInd);
1850 
1851                                 Part->cells += SplCntInd-1;
1852 
1853                                 /* Split the cell C and update the information for sizes of new cells */
1854                                 /* Put the new cells into the stack */
1855                                 i = ind0;
1856                                 if (StackMarkers[i] != tv->stackmark) {
1857                                     BigCellSize = 0;
1858                                 }
1859                                 for (k = 0; k < SplCntInd; k++) {
1860                                     value = SplPos[SplCnt[k]];
1861                                     cls[i] = value;
1862 
1863                                     if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
1864                                         BigCell = i;
1865                                         BigCellPos = CStackInd;
1866                                         BigCellSize = cls[i];
1867                                     }
1868                                     SplPos[SplCnt[k]] = i;
1869                                     i += value;
1870                                     if (i < ind1) {
1871                                         CStack[++CStackInd] = i;
1872                                         StackMarkers[i] = tv->stackmark;
1873                                         TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
1874                                     }
1875                                 }
1876 
1877                                 if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
1878                                     CStack[BigCellPos] = ind0;
1879                                     StackMarkers[BigCell] = 0;
1880                                     StackMarkers[ind0] = tv->stackmark;
1881                                 }
1882 
1883                                 /* Permute elements of the cell C */
1884                                 i = ind0;
1885                                 do {
1886                                     SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
1887                                 }
1888                                 while(++i < ind1);
1889 
1890                                 /* Reconstruct the cell C and update the inverse partition */
1891                                 newcell = ind0;
1892                                 i = ind0;
1893                                 ind2 = newcell+cls[newcell]-1;
1894                                 do {
1895                                     lab[i] = SplCnt[i];
1896                                     InvLab[lab[i]] = i;
1897 
1898                                     Part->inv[i] = newcell;
1899                                     if (i == ind2) {
1900                                         newcell = i+1;
1901                                         if (newcell < n) ind2 = newcell+cls[newcell]-1;
1902                                     }
1903                                 }
1904                                 while (++i < ind1);
1905 
1906                                 for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
1907                                     if (cls[i] == 1) {
1908                                         Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
1909                                         if (newtrace) Singletons[SingInd] = i;
1910                                         SingInd++;
1911                                     }
1912                                 }
1913 
1914                             }
1915                         }
1916                         else {
1917                             if ((!newtrace) && TraceCell) {
1918                                 return 0;
1919                             }
1920                         }
1921 
1922                     }
1923                     else {
1924                         if (cls[ind0] == n) {
1925                             for (i = 0; i < n; i++) {
1926                                 NghCounts[i] = TheGraph[i].d;
1927                             }
1928                         }
1929                         else {
1930                             memset(NghCounts, 0, n*sizeof(int));
1931 
1932                             /* NEIGHCOUNT_DENSE_DENSE_MULT */
1933                             for (i = ind0; i < ind2; i++) {
1934                                 labi = lab[i];
1935                                 nghb = TheGraph[labi].e;
1936                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
1937                                     k = nghb[j1int];
1938                                     (NghCounts[k])++;
1939                                 }
1940                             }
1941                             /* End NEIGHCOUNT_DENSE_DENSE_MULT */
1942 
1943                         }
1944                         SplInd = 0;
1945                         ind4 = 0;
1946                         while (ind4 < n) {    /* For each cell C with size(C) > 1 */
1947                             ind1 = ind4+cls[ind4];
1948                             if (cls[ind4] > 1) {
1949 
1950 
1951                                 /* Determine whether C must be split */
1952                                 SplCntInd = 0;
1953                                 value = NghCounts[lab[ind4]];
1954                                 for (i = ind4+1; i < ind1; i++) {
1955                                     if (NghCounts[lab[i]] != value)
1956                                     {
1957                                         SplInd++;
1958                                         Markers[value] = tv->mark;
1959                                         SplCnt[SplCntInd++] = value;
1960                                         SplPos[value] = i-ind4;
1961                                         do {
1962                                             value = NghCounts[lab[i++]];
1963                                             if (Markers[value] != tv->mark) {
1964                                                 Markers[value] = tv->mark;
1965                                                 SplCnt[SplCntInd++] = value;
1966                                                 SplPos[value] = 1;
1967                                             }
1968                                             else {
1969                                                 SplPos[value]++;
1970                                             }
1971                                         }
1972                                         while(i != ind1);
1973                                         break;
1974                                     }
1975                                 }
1976                                 tv->mark++;
1977 
1978                                 if (SplInd && !TraceCell) newtrace = TRUE;
1979 
1980                                 if (SplCntInd) {
1981                                     TRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+3*n, Tracestpend)
1982 
1983                                     /* Sort the values deriving from the previous step */
1984                                     sort_Split_Array(SplCnt, SplCntInd);
1985 
1986                                     Part->cells += SplCntInd-1;
1987 
1988                                     /* Split the cell C and update the information for sizes of new cells */
1989                                     /* Put the new cells into the stack */
1990                                     i = ind4;
1991                                     if (StackMarkers[i] != tv->stackmark) {
1992                                         BigCellSize = 0;
1993                                     }
1994                                     for (k = 0; k < SplCntInd; k++) {
1995                                         value = SplPos[SplCnt[k]];
1996                                         cls[i] = value;
1997 
1998                                         if ((StackMarkers[ind4] != tv->stackmark) && (value > BigCellSize)) {
1999                                             BigCell = i;
2000                                             BigCellPos = CStackInd;
2001                                             BigCellSize = cls[i];
2002                                         }
2003                                         SplPos[SplCnt[k]] = i;
2004                                         i += value;
2005                                         if (i < ind1) {
2006                                             CStack[++CStackInd] = i;
2007                                             StackMarkers[i] = tv->stackmark;
2008                                             TRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
2009                                         }
2010                                     }
2011                                     if ((StackMarkers[ind4] != tv->stackmark) && (BigCell != ind4)) {
2012                                         CStack[BigCellPos] = ind4;
2013                                         StackMarkers[BigCell] = 0;
2014                                         StackMarkers[ind4] = tv->stackmark;
2015                                     }
2016 
2017                                     /* Permute elements of the cell C */
2018                                     i = ind4;
2019                                     do {
2020                                         SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
2021                                     }
2022                                     while(++i < ind1);
2023 
2024                                     /* Reconstruct the cell C and update the inverse partition */
2025                                     newcell = ind4;
2026                                     i = ind4;
2027                                     ind2 = newcell+cls[newcell]-1;
2028                                     do {
2029                                         lab[i] = SplCnt[i];
2030                                         InvLab[lab[i]] = i;
2031                                         Part->inv[i] = newcell;
2032                                         if (i == ind2) {
2033                                             newcell = i+1;
2034                                             if (newcell < n) ind2 = newcell+cls[newcell]-1;
2035                                         }
2036                                     }
2037                                     while (++i < ind1);
2038 
2039                                     for (i = ind4; i < ind1; i+=cls[i]) {
2040                                         if (cls[i] == 1) {
2041                                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
2042                                             if (newtrace) Singletons[SingInd] = i;
2043                                             SingInd++;
2044                                         }
2045                                     }
2046                                 }
2047                             }
2048                             ind4 = ind1;
2049                         }
2050 
2051                         /* DENSE-DENSE CASE */
2052                         if (SplInd) {
2053                             if (!TraceCell) {
2054                                 newtrace = TRUE;
2055                             }
2056                             TRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+3*n, &Traceccend)
2057                             if (newtrace) {
2058                                 TheTraceCC[TraceCCInd-1] = ind0;
2059                             }
2060                         }
2061                         else {
2062                             if ((!newtrace) && TraceCell) {
2063                                 return 0;
2064                             }
2065                         }
2066 
2067                     }
2068                 }
2069             }
2070         }
2071         while (weightend < iend1int);
2072     }  /* end while (CStackInd > 0) */
2073 
2074     tv->augmented_cells = Part->cells - tv->augmented_cells;
2075 
2076     if (make_code) {
2077         for (i=SpineTL->trcstart; i < TraceInd; i++) {
2078             ind0 = TheTrace[i];
2079             longcode = MASHNONCOMM(longcode, Part->inv[ind0]);
2080             labi = lab[ind0];
2081             iend1int = TheGraph[labi].d;
2082             nghb = TheGraph[labi].e;
2083             for (j1int = 0; j1int < iend1int; ++j1int) {
2084                 k = nghb[j1int];
2085                 value = Part->inv[InvLab[k]];
2086                 longcode = MASHCOMM(longcode, value);
2087             }
2088         }
2089     }
2090     Part->code = Cand->code = CLEANUP(longcode);
2091     tlp1 = tv->tolevel+1;
2092     if (newtrace) {
2093         if ((tlp1 < n) && (tlp1 > tv->treedepth)) {
2094             tv->treedepth = tlp1;
2095             if (tv->strategy) {
2096                 Spine[tlp1].part = NewPartition(n);
2097             }
2098             else {
2099                 NewPartSpine(tlp1,n);
2100             }
2101             Spine[tlp1].liststart = Spine[tlp1].listend = NULL;
2102             Spine[tlp1].listcounter = 0;
2103         }
2104         *TraceEnd = TraceInd;
2105         SpineTL->ccend = TraceCCInd;
2106         SpineTL->singend = SingInd;
2107         *Tracestpend = TraceStepsInd;
2108 
2109         SpineTL->thetracexists = TRUE;
2110         if (tlp1 < n) {
2111             Spine[tlp1].ccstart = TraceCCInd;
2112             Spine[tlp1].singstart = Spine[tlp1].singend = SingInd;
2113             Spine[tlp1].stpstart = TraceStepsInd;
2114             Spine[tlp1].thetracexists = FALSE;
2115             Spine[tlp1].part->code = -1;
2116         }
2117         return 2;
2118     }
2119     else {
2120         if (TraceInd < *TraceEnd) {
2121             return 0;
2122         }
2123         if (Cand->code > SpineTL->part->code) {
2124             return 2;
2125         }
2126         else {
2127             if (Cand->code < SpineTL->part->code) {
2128                 return 0;
2129             }
2130         }
2131         return 1;
2132     }
2133 }
2134 
traces_refine_notrace(Candidate * Cand,int n,Partition * Part,struct TracesVars * tv,struct TracesInfo * ti)2135 void traces_refine_notrace(Candidate *Cand,
2136                            int n,
2137                            Partition *Part,
2138                            struct TracesVars* tv,
2139                            struct TracesInfo *ti) {
2140     int i, j, k, jk, sc, ind0, ind1, ind2, ind3, labi, auxcells;
2141     int value, iend, newcell;
2142     int HitClsInd, SplInd, SplCntInd, CStackInd;
2143     int iend1int, j1int;
2144     unsigned int longcode;
2145     int Split = 0;
2146     int Sparse = TRUE;
2147     int *lab, *cls, *InvLab, *SplitCell, *LabCell;
2148     int BigCell, BigCellPos, BigCellSize;
2149     int *nghb;
2150     const int variation = 1;
2151     int currentweight, weightstart, weightend, currentcell, currentsize;
2152 
2153     if (tv->stackmark > (NAUTY_INFINITY-2)) {
2154         memset(StackMarkers, 0, n*sizeof(int));
2155         tv->stackmark = 0;
2156     }
2157     tv->stackmark++;
2158 
2159     tv->augmented_cells = Part->cells;
2160 
2161     lab = Cand->lab;
2162     InvLab = Cand->invlab;
2163     cls = Part->cls;
2164 
2165     CStackInd = 1;
2166     CStack[1] = tv->tcellexpath+cls[tv->tcellexpath];
2167 
2168     for (i = 1; i <= CStackInd; i++) {
2169         StackMarkers[CStack[i]] = tv->stackmark;
2170     }
2171 
2172     longcode = Part->cells;
2173 
2174     while (CStackInd > 0) {
2175 
2176         weightend = 0;
2177 
2178         if (tv->mark > (NAUTY_INFINITY-2)) {
2179             memset(Markers, 0, n*sizeof(int));
2180             memset(MarkHitVtx, 0, n*sizeof(int));
2181             tv->mark = 0;
2182         }
2183         tv->mark++;
2184 
2185         k = Select_from_CStack(cls, CStackInd);
2186 
2187         currentcell = CStack[k];
2188         currentsize = currentcell+cls[currentcell];
2189         CStack[k] = CStack[CStackInd--];        /* Current Cell */
2190         longcode = MASHNONCOMM(longcode, currentcell);
2191         StackMarkers[currentcell] = 0;
2192 
2193         labi = lab[currentcell];
2194         iend1int = TheGraph[labi].d;
2195         nghb =  TheGraph[labi].e;
2196 
2197         do {
2198             ind0 = currentcell;
2199             ind2 = currentsize;
2200             weightstart = weightend;
2201 
2202             if (tv->options->weighted) {
2203                 currentweight = (TheGraph[labi].w)[weightstart];
2204                 while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
2205                     weightend++;
2206                 }
2207             } else {
2208                 weightend = TheGraph[labi].d;
2209             }
2210 
2211             /* Analysis of occurrences of neighbors of the current cell */
2212             /* The list of cells with neighbors in the current cell is  built */
2213 
2214             if (cls[ind0] == 1) {   /* SINGLETON CURRENT CELL CASE */
2215 
2216                 /* NEIGHCOUNT_SING_MULT */
2217                 HitClsInd = 0;
2218                 for (j1int = weightstart; j1int < weightend; ++j1int) {
2219                     k = nghb[j1int];
2220                     value = Part->inv[InvLab[k]];
2221                     if (cls[value] > 1) {
2222                         if (Markers[value] != tv->mark) {
2223                             HitCls[HitClsInd++] = value;
2224                             Markers[value] = tv->mark;
2225                             ElmHitCll[value] = value;
2226                         }
2227                         HitVtx[ElmHitCll[value]++] = k;
2228                     } else {
2229                         switch (variation) {
2230                             case 1:
2231                                 longcode = MASHCOMM(longcode, value);
2232                                 break;
2233                             default:
2234                                 break;
2235                         }
2236                     }
2237                 }
2238                 /* end NEIGHCOUNT_SING_MULT */
2239 
2240                 tv->mark++;
2241                 FIND_SPLIT_CELLS;
2242 
2243                 /* Sorting the cells to be split */
2244                 sort_Split_Array(SplCls, SplInd);
2245 
2246                 /* REARRANGE THE CELLS */
2247                 for (j = 0; j < SplInd; j++) {
2248                     /* REARRANGE_CELLS */
2249                     ind1 = SplCls[j];
2250                     cls[ind1] = cls[ind1]-ElmHitCll[ind1];
2251                     newcell = ind1+cls[ind1];
2252                     cls[newcell] = ElmHitCll[ind1];
2253                     Part->cells++;
2254                     if (StackMarkers[ind1] != tv->stackmark) {
2255                         if (cls[newcell] < cls[ind1]) {
2256                             CStack[++CStackInd] = newcell;
2257                             StackMarkers[newcell] = tv->stackmark;
2258                         }
2259                         else {
2260                             CStack[++CStackInd] = ind1;
2261                             StackMarkers[ind1] = tv->stackmark;
2262                         }
2263                     }
2264                     else {
2265                         CStack[++CStackInd] = newcell;
2266                         StackMarkers[newcell] = tv->stackmark;
2267                     }
2268                     SplitCell = HitVtx+ind1;
2269                     ind3 = cls[newcell];
2270                     LabCell = lab+newcell;
2271                     for (jk = 0; jk < ind3; jk++) {
2272                         k = SplitCell[jk];
2273                         i = LabCell[jk];
2274                         Part->inv[newcell+jk] = newcell;
2275                         lab[InvLab[k]] = i;
2276                         InvLab[i] = InvLab[k];
2277                         LabCell[jk] = k;
2278                         InvLab[k] = newcell+jk;
2279                     }
2280                     /* END REARRANGE_CELLS */
2281 
2282                     if (cls[ind1] == 1) {
2283                         Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[ind1]);
2284                     }
2285                     if (cls[newcell] == 1) {
2286                         Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[newcell]);
2287                     }
2288                 }
2289             }
2290             else {
2291                 if (ti->thegraphisparse) {
2292 
2293                     /* NEIGHCOUNT_SPARSE_MULT */
2294                     HitClsInd = 0;
2295                     if (cls[ind0] != n) {
2296                         for (i = ind0; i < ind2; i++) {
2297                             labi = lab[i];
2298                             nghb = TheGraph[labi].e;
2299                             for (j = weightstart; j < weightend; j++) {
2300                                 k = nghb[j];
2301                                 if (MarkHitVtx[k] == tv->mark) {
2302                                     NghCounts[k]++;
2303                                 }
2304                                 else {
2305                                     value = Part->inv[InvLab[k]];
2306                                     if (cls[value] > 1) {
2307                                         MarkHitVtx[k] = tv->mark;
2308                                         NghCounts[k] = 1;
2309                                         if (Markers[value] != tv->mark) {
2310                                             HitCls[HitClsInd++] = value;
2311                                             Markers[value] = tv->mark;
2312                                             HitVtx[value] = k;
2313                                             ElmHitCll[value] = 1;
2314                                         }
2315                                         else {
2316                                             HitVtx[value+ElmHitCll[value]++] = k;
2317                                         }
2318                                     }
2319                                     else {
2320                                         switch (variation) {
2321                                             case 1:
2322                                                 longcode = MASHCOMM(longcode, value);
2323                                                 break;
2324                                             default:
2325                                                 break;
2326                                         }
2327                                     }
2328                                 }
2329                             }
2330                         }
2331                     }
2332                     /* End NEIGHCOUNT_SPARSE_MULT */
2333 
2334                     tv->mark++;
2335 
2336                     SplInd = 0;
2337                     SplCls[0] = n;
2338                     for (j = 0; j < HitClsInd; j++) {
2339                         ind1 = HitCls[j];
2340                         if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
2341                             SplCls[SplInd++] = ind1;
2342                         }
2343                         else {
2344                             ind2 = ind1+cls[ind1];
2345                             Split = FALSE;
2346                             value = NghCounts[lab[ind1++]];
2347                             for (i = ind1; i < ind2; i++)
2348                             {
2349                                 if (NghCounts[lab[i]] != value)
2350                                 {
2351                                     SplCls[SplInd++] = HitCls[j];
2352                                     Split = TRUE;
2353                                     break;
2354                                 }
2355                             }
2356                             if (!Split) {
2357                                 longcode = MASHCOMM(longcode, ind1);
2358                             }
2359                         }
2360                     }
2361 
2362                     /* Sorting the cells to be split */
2363                     sort_Split_Array(SplCls, SplInd);
2364 
2365                     for (sc = 0; sc < SplInd; sc++) {    /* For each cell C to be split */
2366                         ind0 = SplCls[sc];
2367                         ind1 = ind0 + cls[ind0];
2368                         SplCntInd = 0;
2369                         if (ElmHitCll[ind0] < cls[ind0]) {
2370                             SplCnt[SplCntInd++] = 0;
2371                             SplPos[0] = cls[ind0] - ElmHitCll[ind0];
2372                         }
2373 
2374                         /* According to the numbers of neighbors of C into the current cell */
2375                         /* compute how many vertices in C will be placed into the same new cell */
2376                         iend = ind0 + ElmHitCll[ind0];
2377                         for (i = ind0; i < iend; i++) {
2378                             value = NghCounts[HitVtx[i]];
2379                             if (Markers[value] != tv->mark) {
2380                                 Markers[value] = tv->mark;
2381                                 SplCnt[SplCntInd++] = value;
2382                                 SplPos[value] = 1;
2383                             }
2384                             else {
2385                                 SplPos[value]++;
2386                             }
2387                         }
2388                         tv->mark++;
2389 
2390                         /* Sort the values deriving from the previous step */
2391                         sort_Split_Array(SplCnt, SplCntInd);
2392                         Part->cells += SplCntInd-1;
2393 
2394                         /* Split the cell C and update the information for sizes of new cells */
2395                         /* Put the new cells into the stack */
2396                         i = ind0;
2397                         if (StackMarkers[i] != tv->stackmark) {
2398                             BigCellSize = 0;
2399                         }
2400                         for (k = 0; k < SplCntInd; k++) {
2401                             value = SplPos[SplCnt[k]];
2402                             cls[i] = value;
2403                             if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
2404                                 BigCell = i;
2405                                 BigCellPos = CStackInd;
2406                                 BigCellSize = cls[i];
2407                             }
2408                             SplPos[SplCnt[k]] = i;
2409                             i += value;
2410                             if (i < ind1) {
2411                                 CStack[++CStackInd] = i;
2412                                 StackMarkers[i] = tv->stackmark;
2413                             }
2414                         }
2415 
2416                         if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
2417                             CStack[BigCellPos] = ind0;
2418                             StackMarkers[BigCell] = 0;
2419                             StackMarkers[ind0] = tv->stackmark;
2420                         }
2421 
2422                         /* Permute elements of the cell C */
2423                         iend = ind0 + ElmHitCll[ind0];
2424                         for (i = ind0; i < iend; i++) {
2425                             value = HitVtx[i];
2426                             j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
2427                             k = InvLab[value];                /* where HitVtx[i] is in lab */
2428                             lab[k] = lab[j];
2429                             lab[j] = value;
2430                             InvLab[value] = j;
2431                             InvLab[lab[k]] = k;
2432                             NghCounts[value] = 0;
2433                         }
2434 
2435                         /* Reconstruct the cell C and update the inverse partition */
2436                         newcell = ind1 - ElmHitCll[ind0];
2437                         i = newcell;
2438                         ind2 = newcell+cls[newcell]-1;
2439                         do {
2440                             Part->inv[i] = newcell;
2441                             if (i == ind2) {
2442                                 newcell = i+1;
2443                                 if (newcell < n) ind2 = newcell+cls[newcell]-1;
2444                             }
2445                         }
2446                         while (++i < ind1);
2447 
2448                         for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
2449                             if (cls[i] == 1) {
2450                                 Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[i]);
2451                             }
2452                         }
2453 
2454                     }
2455                 }
2456                 else {
2457                     if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
2458                         Sparse = FALSE;
2459                     }
2460                     else {
2461                         Sparse = TRUE;
2462                     }
2463                     Sparse = TRUE;
2464                     if (Sparse) {
2465                         /* Counting occurrences of neighbors of the current cell */
2466                         /* The list of cells with neighbors in the current cell is also built */
2467                         if (cls[ind0] == n) {
2468                             for (i = 0; i < n; i++) {
2469                                 NghCounts[i] = TheGraph[i].d;
2470                             }
2471                             HitCls[0] = 0;
2472                             HitClsInd = 1;
2473                         }
2474                         else {
2475                             memset(NghCounts, 0, n*sizeof(int));
2476 
2477                             /* NEIGHCOUNT_DENSE_SPARSE_MULT */
2478                             HitClsInd = 0;
2479                             for (i = ind0; i < ind2; i++) {
2480                                 labi = lab[i];
2481                                 nghb =  TheGraph[labi].e;
2482                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
2483                                     k = nghb[j1int];
2484                                     (NghCounts[k])++;
2485                                     value = Part->inv[InvLab[k]];
2486                                     if (Markers[value] != tv->mark) {
2487                                         if (cls[value] > 1) HitCls[HitClsInd++] = value;
2488                                         Markers[value] = tv->mark;
2489                                     }
2490                                 }
2491                             }
2492                             /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
2493 
2494                         }
2495 
2496                         tv->mark++;
2497 
2498                         SplInd = 0;
2499                         for (j = 0; j < HitClsInd; j++) {
2500                             ind1 = HitCls[j];
2501                             ind2 = ind1+cls[ind1];
2502                             value = NghCounts[lab[ind1++]];
2503                             for (i = ind1; i < ind2; i++)
2504                             {
2505                                 if (NghCounts[lab[i]] != value)
2506                                 {
2507                                     SplCls[SplInd++] = HitCls[j];
2508                                     break;
2509                                 }
2510                             }
2511                         }
2512 
2513                         /* Sorting the cells to be split */
2514                         sort_Split_Array(SplCls, SplInd);
2515 
2516                         for (j = 0; j < SplInd; j++) {    /* For each cell C to be split */
2517                             ind0 = SplCls[j];
2518                             ind1 = ind0+cls[ind0];
2519                             SplCntInd = 0;
2520 
2521                             /* According to the numbers of neighbors of C into the current cell */
2522                             /* compute how many vertices in C will be placed into the same new cell */
2523                             for (i = ind0; i < ind1; i++) {
2524                                 value = NghCounts[lab[i]];
2525                                 if (Markers[value] != tv->mark) {
2526                                     Markers[value] = tv->mark;
2527                                     SplCnt[SplCntInd++] = value;
2528                                     SplPos[value] = 1;
2529                                 }
2530                                 else {
2531                                     SplPos[value]++;
2532                                 }
2533                             }
2534 
2535                             tv->mark++;
2536 
2537                             /* Sort the values deriving from the previous step */
2538                             sort_Split_Array(SplCnt, SplCntInd);
2539 
2540                             Part->cells += SplCntInd-1;
2541 
2542                             /* Split the cell C and update the information for sizes of new cells */
2543                             /* Put the new cells into the stack */
2544                             i = ind0;
2545                             if (StackMarkers[i] != tv->stackmark) {
2546                                 BigCellSize = 0;
2547                             }
2548                             for (k = 0; k < SplCntInd; k++) {
2549                                 value = SplPos[SplCnt[k]];
2550                                 cls[i] = value;
2551                                 if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
2552                                     BigCell = i;
2553                                     BigCellPos = CStackInd;
2554                                     BigCellSize = cls[i];
2555                                 }
2556                                 SplPos[SplCnt[k]] = i;
2557                                 i += value;
2558                                 if (i < ind1) {
2559                                     CStack[++CStackInd] = i;
2560                                     StackMarkers[i] = tv->stackmark;
2561                                 }
2562                             }
2563                             if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
2564                                 CStack[BigCellPos] = ind0;
2565                                 StackMarkers[BigCell] = 0;
2566                                 StackMarkers[ind0] = tv->stackmark;
2567                             }
2568 
2569                             /* Permute elements of the cell C */
2570                             i = ind0;
2571                             do {
2572                                 SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
2573                             }
2574                             while(++i < ind1);
2575 
2576                             /* Reconstruct the cell C and update the inverse partition */
2577                             newcell = ind0;
2578                             i = ind0;
2579                             ind2 = newcell+cls[newcell]-1;
2580                             do {
2581                                 lab[i] = SplCnt[i];
2582                                 InvLab[lab[i]] = i;
2583                                 Part->inv[i] = newcell;
2584 
2585                                 if (i == ind2) {
2586                                     newcell = i+1;
2587                                     if (newcell < n) ind2 = newcell+cls[newcell]-1;
2588                                 }
2589                             }
2590                             while (++i < ind1);
2591 
2592                             for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
2593                                 if (cls[i] == 1) {
2594                                     Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[i]);
2595                                 }
2596                             }
2597 
2598                         }
2599                     }
2600                     else {
2601                         if (cls[ind0] == n) {
2602                             for (i = 0; i < n; i++) {
2603                                 NghCounts[i] = TheGraph[i].d;
2604                             }
2605                         }
2606                         else {
2607                             memset(NghCounts, 0, n*sizeof(int));
2608 
2609                             /* NEIGHCOUNT_DENSE_DENSE_MULT */
2610                             for (i = ind0; i < ind2; i++) {
2611                                 labi = lab[i];
2612                                 nghb = TheGraph[labi].e;
2613                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
2614                                     k = nghb[j1int];
2615                                     (NghCounts[k])++;
2616                                 }
2617                             }
2618                             /* End NEIGHCOUNT_DENSE_DENSE_MULT */
2619 
2620                         }
2621 
2622                         ind0 = 0;
2623                         while (ind0 < n) {    /* For each cell C with size(C) > 1 */
2624                             ind1 = ind0+cls[ind0];
2625                             if (cls[ind0] > 1) {
2626 
2627                                 /* Determine whether C must be split */
2628                                 SplCntInd = 0;
2629                                 value = NghCounts[lab[ind0]];
2630                                 for (i = ind0+1; i < ind1; i++)
2631                                 {
2632                                     if (NghCounts[lab[i]] != value)
2633                                     {
2634                                         Markers[value] = tv->mark;
2635                                         SplCnt[SplCntInd++] = value;
2636                                         SplPos[value] = i-ind0;
2637                                         do {
2638                                             value = NghCounts[lab[i++]];
2639                                             if (Markers[value] != tv->mark) {
2640                                                 Markers[value] = tv->mark;
2641                                                 SplCnt[SplCntInd++] = value;
2642                                                 SplPos[value] = 1;
2643                                             }
2644                                             else {
2645                                                 SplPos[value]++;
2646                                             }
2647                                         }
2648                                         while(i != ind1);
2649                                         break;
2650                                     }
2651                                 }
2652 
2653                                 if (SplCntInd) {
2654                                     tv->mark++;
2655 
2656                                     /* Sort the values deriving from the previous step */
2657                                     sort_Split_Array(SplCnt, SplCntInd);
2658                                     Part->cells += SplCntInd-1;
2659 
2660                                     /* Split the cell C and update the information for sizes of new cells */
2661                                     /* Put the new cells into the stack */
2662                                     i = ind0;
2663                                     if (StackMarkers[i] != tv->stackmark) {
2664                                         BigCellSize = 0;
2665                                     }
2666                                     for (k = 0; k < SplCntInd; k++) {
2667                                         value = SplPos[SplCnt[k]];
2668                                         cls[i] = value;
2669                                         if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
2670                                             BigCell = i;
2671                                             BigCellPos = CStackInd;
2672                                             BigCellSize = cls[i];
2673                                         }
2674                                         SplPos[SplCnt[k]] = i;
2675                                         i += value;
2676                                         if (i < ind1) {
2677                                             CStack[++CStackInd] = i;
2678                                             StackMarkers[i] = tv->stackmark;
2679                                         }
2680                                     }
2681                                     if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
2682                                         CStack[BigCellPos] = ind0;
2683                                         StackMarkers[BigCell] = 0;
2684                                         StackMarkers[ind0] = tv->stackmark;
2685                                     }
2686 
2687                                     /* Permute elements of the cell C */
2688                                     i = ind0;
2689                                     do {
2690                                         SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
2691                                     }
2692                                     while(++i < ind1);
2693 
2694                                     /* Reconstruct the cell C and update the inverse partition */
2695                                     newcell = ind0;
2696                                     i = ind0;
2697                                     ind2 = newcell+cls[newcell]-1;
2698                                     do {
2699                                         lab[i] = SplCnt[i];
2700                                         InvLab[lab[i]] = i;
2701                                         Part->inv[i] = newcell;
2702                                         if (i == ind2) {
2703                                             newcell = i+1;
2704                                             if (newcell < n) ind2 = newcell+cls[newcell]-1;
2705                                         }
2706                                     }
2707                                     while (++i < ind1);
2708 
2709                                     for (i = ind0; i < ind1; i+=cls[i]) {
2710                                         if (cls[i] == 1) {
2711                                             Cand->pathsingcode = MASHCOMM(Cand->pathsingcode, lab[i]);
2712                                         }
2713                                     }
2714 
2715                                 }
2716                             }
2717                             ind0 = ind1;
2718                         }
2719                     }
2720                 }
2721             }
2722         }
2723         while (weightend < iend1int);
2724     }  /* end while (CStackInd > 0) */
2725 
2726     tv->augmented_cells = Part->cells - tv->augmented_cells;
2727     Cand->code = CLEANUP(longcode);
2728     return;
2729 }
2730 
traces_refine_maketrie(Candidate * Cand,int n,Partition * Part,struct TracesVars * tv,struct TracesInfo * ti)2731 void traces_refine_maketrie(Candidate *Cand,
2732                             int n,
2733                             Partition *Part,
2734                             struct TracesVars* tv,
2735                             struct TracesInfo *ti) {
2736     int i, j, k, jk, sc, ind0, ind1, ind2, ind3, labi;
2737     int value, iend, newcell;
2738     int HitClsInd, SplInd, SplCntInd, CStackInd;
2739     int j1int, iend1int;
2740     unsigned int longcode;
2741     int Split = 0;
2742     int Sparse = TRUE;
2743     int *lab, *cls, *InvLab, *SplitCell, *LabCell;
2744     int BigCell, BigCellPos, BigCellSize;
2745     int *nghb;
2746     const int variation = 1;
2747     int currentweight, weightstart, weightend, currentcell, currentsize;
2748 
2749     if (tv->stackmark > (NAUTY_INFINITY-2)) {
2750         memset(StackMarkers, 0, n*sizeof(int));
2751         tv->stackmark = 0;
2752     }
2753     tv->stackmark++;
2754 
2755     tv->augmented_cells = Part->cells;
2756 
2757     lab = Cand->lab;
2758     InvLab = Cand->invlab;
2759     cls = Part->cls;
2760 
2761     CStack[1] = Spine[tv->tolevel_tl].tgtpos;
2762     CStackInd = 1;
2763     for (i = 1; i <= CStackInd; i++) {
2764         StackMarkers[CStack[i]] = tv->stackmark;
2765     }
2766 
2767     longcode = Part->cells;
2768 
2769     while (CStackInd > 0)
2770     {
2771         weightend = 0;
2772 
2773         if (tv->mark > (NAUTY_INFINITY-2)) {
2774             memset(Markers, 0, n*sizeof(int));
2775             memset(MarkHitVtx, 0, n*sizeof(int));
2776             tv->mark = 0;
2777         }
2778         tv->mark++;
2779 
2780         if (Part->cells == n) break;
2781 
2782         k = Select_from_CStack(cls, CStackInd);
2783 
2784         currentcell = CStack[k];
2785         currentsize = currentcell+cls[currentcell];
2786         CStack[k] = CStack[CStackInd--];
2787         longcode = MASHNONCOMM(longcode, currentcell);
2788         StackMarkers[currentcell] = 0;
2789 
2790         labi = lab[currentcell];
2791         iend1int = TheGraph[labi].d;
2792         nghb =  TheGraph[labi].e;
2793 
2794         do {
2795             ind0 = currentcell;
2796             ind2 = currentsize;
2797             weightstart = weightend;
2798 
2799             if (tv->options->weighted) {
2800                 currentweight = (TheGraph[labi].w)[weightstart];
2801                 while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
2802                     weightend++;
2803                 }
2804             } else {
2805                 weightend = TheGraph[labi].d;
2806             }
2807 
2808             /* Analysis of occurrences of neighbors of the current cell */
2809             /* The list of cells with neighbors in the current cell is  built */
2810             if (cls[ind0] == 1) {  /* SINGLETON CURRENT CELL CASE */
2811 
2812                 /* NEIGHCOUNT_SING_MULT */
2813                 HitClsInd = 0;
2814                 for (j1int = weightstart; j1int < weightend; ++j1int) {
2815                     k = nghb[j1int];
2816                     value = Part->inv[InvLab[k]];
2817                     if (cls[value] > 1) {
2818                         if (Markers[value] != tv->mark) {
2819                             HitCls[HitClsInd++] = value;
2820                             Markers[value] = tv->mark;
2821                             ElmHitCll[value] = value;
2822                         }
2823                         HitVtx[ElmHitCll[value]++] = k;
2824                     } else {
2825                         switch (variation) {
2826                             case 1:
2827                                 longcode = MASHCOMM(longcode, value);
2828                                 break;
2829                             default:
2830                                 break;
2831                         }
2832                     }
2833                 }
2834                 /* end NEIGHCOUNT_SING_MULT */
2835 
2836                 tv->mark++;
2837                 FIND_SPLIT_CELLS;
2838 
2839                 /* Sorting the cells to be split */
2840                 sort_Split_Array(SplCls, SplInd);
2841 
2842                 for (j = 0; j < SplInd; j++) {
2843                     ind1 = SplCls[j];
2844                     i = ind1+cls[ind1]-ElmHitCll[ind1];
2845                     trieref = trie_make(trieref, i, n, tv);
2846                 }
2847 
2848                 /* REARRANGE THE CELLS */
2849                 for (j = 0; j < SplInd; j++) {
2850                     /* REARRANGE_CELLS */
2851                     ind1 = SplCls[j];
2852                     cls[ind1] = cls[ind1]-ElmHitCll[ind1];
2853                     newcell = ind1+cls[ind1];
2854                     cls[newcell] = ElmHitCll[ind1];
2855                     Part->cells++;
2856                     if (StackMarkers[ind1] != tv->stackmark) {
2857                         if (cls[newcell] < cls[ind1]) {
2858                             CStack[++CStackInd] = newcell;
2859                             StackMarkers[newcell] = tv->stackmark;
2860                         }
2861                         else {
2862                             CStack[++CStackInd] = ind1;
2863                             StackMarkers[ind1] = tv->stackmark;
2864                         }
2865                     }
2866                     else {
2867                         CStack[++CStackInd] = newcell;
2868                         StackMarkers[newcell] = tv->stackmark;
2869                     }
2870                     SplitCell = HitVtx+ind1;
2871                     ind3 = cls[newcell];
2872                     LabCell = lab+newcell;
2873                     for (jk = 0; jk < ind3; jk++) {
2874                         k = SplitCell[jk];
2875                         i = LabCell[jk];
2876                         Part->inv[newcell+jk] = newcell;
2877                         lab[InvLab[k]] = i;
2878                         InvLab[i] = InvLab[k];
2879                         LabCell[jk] = k;
2880                         InvLab[k] = newcell+jk;
2881                     }
2882                     /* END REARRANGE_CELLS */
2883                 }
2884             }
2885             else {
2886                 if (ti->thegraphisparse) {
2887 
2888                     /* NEIGHCOUNT_SPARSE_MULT */
2889                     HitClsInd = 0;
2890                     if (cls[ind0] != n) {
2891                         for (i = ind0; i < ind2; i++) {
2892                             labi = lab[i];
2893                             nghb = TheGraph[labi].e;
2894                             for (j = weightstart; j < weightend; j++) {
2895                                 k = nghb[j];
2896                                 if (MarkHitVtx[k] == tv->mark) {
2897                                     NghCounts[k]++;
2898                                 }
2899                                 else {
2900                                     value = Part->inv[InvLab[k]];
2901                                     if (cls[value] > 1) {
2902                                         MarkHitVtx[k] = tv->mark;
2903                                         NghCounts[k] = 1;
2904                                         if (Markers[value] != tv->mark) {
2905                                             HitCls[HitClsInd++] = value;
2906                                             Markers[value] = tv->mark;
2907                                             HitVtx[value] = k;
2908                                             ElmHitCll[value] = 1;
2909                                         }
2910                                         else {
2911                                             HitVtx[value+ElmHitCll[value]++] = k;
2912                                         }
2913                                     }
2914                                     else {
2915                                         switch (variation) {
2916                                             case 1:
2917                                                 longcode = MASHCOMM(longcode, value);
2918                                                 break;
2919                                             default:
2920                                                 break;
2921                                         }
2922                                     }
2923                                 }
2924                             }
2925                         }
2926                     }
2927                     /* End NEIGHCOUNT_SPARSE_MULT */
2928 
2929                     tv->mark++;
2930 
2931                     SplInd = 0;
2932                     SplCls[0] = n;
2933                     for (j = 0; j < HitClsInd; j++) {
2934                         ind1 = HitCls[j];
2935                         if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
2936                             SplCls[SplInd++] = ind1;
2937                         }
2938                         else {
2939                             ind2 = ind1+cls[ind1];
2940                             Split = FALSE;
2941                             value = NghCounts[lab[ind1++]];
2942                             for (i = ind1; i < ind2; i++)
2943                             {
2944                                 if (NghCounts[lab[i]] != value)
2945                                 {
2946                                     SplCls[SplInd++] = HitCls[j];
2947                                     Split = TRUE;
2948                                     break;
2949                                 }
2950                             }
2951                             if (!Split) {
2952                                 longcode = MASHCOMM(longcode, ind1);
2953                             }
2954                         }
2955                     }
2956 
2957                     /* Sorting the cells to be split */
2958                     sort_Split_Array(SplCls, SplInd);
2959 
2960                     for (sc = 0; sc < SplInd; sc++) {    /* For each cell C to be split */
2961                         ind0 = SplCls[sc];
2962                         ind1 = ind0 + cls[ind0];
2963                         SplCntInd = 0;
2964                         if (ElmHitCll[ind0] < cls[ind0]) {
2965                             SplCnt[SplCntInd++] = 0;
2966                             SplPos[0] = cls[ind0] - ElmHitCll[ind0];
2967                         }
2968 
2969                         /* According to the numbers of neighbors of C into the current cell */
2970                         /* compute how many vertices in C will be placed into the same new cell */
2971                         iend = ind0 + ElmHitCll[ind0];
2972                         for (i = ind0; i < iend; i++) {
2973                             value = NghCounts[HitVtx[i]];
2974                             if (Markers[value] != tv->mark) {
2975                                 Markers[value] = tv->mark;
2976                                 SplCnt[SplCntInd++] = value;
2977                                 SplPos[value] = 1;
2978                             }
2979                             else {
2980                                 SplPos[value]++;
2981                             }
2982                         }
2983 
2984                         tv->mark++;
2985 
2986                         /* Sort the values deriving from the previous step */
2987                         sort_Split_Array(SplCnt, SplCntInd);
2988                         Part->cells += SplCntInd-1;
2989 
2990                         /* Split the cell C and update the information for sizes of new cells */
2991                         /* Put the new cells into the stack */
2992                         i = ind0;
2993                         if (StackMarkers[i] != tv->stackmark) {
2994                             BigCellSize = 0;
2995                         }
2996                         for (k = 0; k < SplCntInd; k++) {
2997                             value = SplPos[SplCnt[k]];
2998                             cls[i] = value;
2999                             if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
3000                                 BigCell = i;
3001                                 BigCellPos = CStackInd;
3002                                 BigCellSize = cls[i];
3003                             }
3004                             SplPos[SplCnt[k]] = i;
3005                             i += value;
3006                             if (i < ind1) {
3007                                 CStack[++CStackInd] = i;
3008                                 StackMarkers[i] = tv->stackmark;
3009                                 trieref = trie_make(trieref, i, n, tv);
3010                             }
3011                         }
3012 
3013                         if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
3014                             CStack[BigCellPos] = ind0;
3015                             StackMarkers[BigCell] = 0;
3016                             StackMarkers[ind0] = tv->stackmark;
3017                         }
3018                         /* Permute elements of the cell C */
3019                         iend = ind0 + ElmHitCll[ind0];
3020                         for (i = ind0; i < iend; i++) {
3021                             value = HitVtx[i];
3022                             j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
3023                             k = InvLab[value];                /* where HitVtx[i] is in lab */
3024                             lab[k] = lab[j];
3025                             lab[j] = value;
3026                             InvLab[value] = j;
3027                             InvLab[lab[k]] = k;
3028                             NghCounts[value] = 0;
3029                         }
3030 
3031                         /* Reconstruct the cell C and update the inverse partition */
3032                         newcell = ind1 - ElmHitCll[ind0];
3033                         i = newcell;
3034                         ind2 = newcell+cls[newcell]-1;
3035                         do {
3036                             Part->inv[i] = newcell;
3037                             if (i == ind2) {
3038                                 newcell = i+1;
3039                                 if (newcell < n) ind2 = newcell+cls[newcell]-1;
3040                             }
3041                         }
3042                         while (++i < ind1);
3043                     }
3044                 }
3045                 else {
3046                     if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
3047                         Sparse = FALSE;
3048                     }
3049                     else {
3050                         Sparse = TRUE;
3051                     }
3052                     Sparse = TRUE;
3053                     if (Sparse) {
3054                         /* Counting occurrences of neighbors of the current cell */
3055                         /* The list of cells with neighbors in the current cell is also built */
3056                         if (cls[ind0] == n) {
3057                             for (i = 0; i < n; i++) {
3058                                 NghCounts[i] = TheGraph[i].d;
3059                             }
3060                             HitCls[0] = 0;
3061                             HitClsInd = 1;
3062                         }
3063                         else {
3064                             memset(NghCounts, 0, n*sizeof(int));
3065 
3066                             /* NEIGHCOUNT_DENSE_SPARSE_MULT */
3067                             HitClsInd = 0;
3068                             for (i = ind0; i < ind2; i++) {
3069                                 labi = lab[i];
3070                                 nghb =  TheGraph[labi].e;
3071                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
3072                                     k = nghb[j1int];
3073                                     (NghCounts[k])++;
3074                                     value = Part->inv[InvLab[k]];
3075                                     if (Markers[value] != tv->mark) {
3076                                         if (cls[value] > 1) HitCls[HitClsInd++] = value;
3077                                         Markers[value] = tv->mark;
3078                                     }
3079                                 }
3080                             }
3081                             /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
3082 
3083                         }
3084 
3085                         tv->mark++;
3086 
3087                         SplInd = 0;
3088                         for (j = 0; j < HitClsInd; j++) {
3089                             ind1 = HitCls[j];
3090                             ind2 = ind1+cls[ind1];
3091                             value = NghCounts[lab[ind1++]];
3092                             for (i = ind1; i < ind2; i++)
3093                             {
3094                                 if (NghCounts[lab[i]] != value)
3095                                 {
3096                                     SplCls[SplInd++] = HitCls[j];
3097                                     break;
3098                                 }
3099                             }
3100                         }
3101 
3102                         /* Sorting the cells to be split */
3103                         sort_Split_Array(SplCls, SplInd);
3104 
3105                         for (j = 0; j < SplInd; j++) {    /* For each cell C to be split */
3106                             ind0 = SplCls[j];
3107                             ind1 = ind0+cls[ind0];
3108                             SplCntInd = 0;
3109 
3110                             /* According to the numbers of neighbors of C into the current cell */
3111                             /* compute how many vertices in C will be placed into the same new cell */
3112                             for (i = ind0; i < ind1; i++) {
3113                                 value = NghCounts[lab[i]];
3114                                 if (Markers[value] != tv->mark) {
3115                                     Markers[value] = tv->mark;
3116                                     SplCnt[SplCntInd++] = value;
3117                                     SplPos[value] = 1;
3118                                 }
3119                                 else {
3120                                     SplPos[value]++;
3121                                 }
3122                             }
3123 
3124                             tv->mark++;
3125 
3126                             /* Sort the values deriving from the previous step */
3127                             sort_Split_Array(SplCnt, SplCntInd);
3128                             Part->cells += SplCntInd-1;
3129 
3130                             /* Split the cell C and update the information for sizes of new cells */
3131                             /* Put the new cells into the stack */
3132                             i = ind0;
3133                             if (StackMarkers[i] != tv->stackmark) {
3134                                 BigCellSize = 0;
3135                             }
3136                             for (k = 0; k < SplCntInd; k++) {
3137                                 value = SplPos[SplCnt[k]];
3138                                 cls[i] = value;
3139                                 if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
3140                                     BigCell = i;
3141                                     BigCellPos = CStackInd;
3142                                     BigCellSize = cls[i];
3143                                 }
3144                                 SplPos[SplCnt[k]] = i;
3145                                 i += value;
3146                                 if (i < ind1) {
3147                                     CStack[++CStackInd] = i;
3148                                     StackMarkers[i] = tv->stackmark;
3149                                     trieref = trie_make(trieref, i, n, tv);
3150                                 }
3151                             }
3152                             if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
3153                                 CStack[BigCellPos] = ind0;
3154                                 StackMarkers[BigCell] = 0;
3155                                 StackMarkers[ind0] = tv->stackmark;
3156                             }
3157 
3158                             /* Permute elements of the cell C */
3159                             i = ind0;
3160                             do {
3161                                 SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
3162                             }
3163                             while(++i < ind1);
3164 
3165                             /* Reconstruct the cell C and update the inverse partition */
3166                             newcell = ind0;
3167                             i = ind0;
3168                             ind2 = newcell+cls[newcell]-1;
3169                             do {
3170                                 lab[i] = SplCnt[i];
3171                                 InvLab[lab[i]] = i;
3172                                 Part->inv[i] = newcell;
3173                                 if (i == ind2) {
3174                                     newcell = i+1;
3175                                     if (newcell < n) ind2 = newcell+cls[newcell]-1;
3176                                 }
3177                             }
3178                             while (++i < ind1);
3179                         }
3180                     }
3181                     else {
3182                         if (cls[ind0] == n) {
3183                             for (i = 0; i < n; i++) {
3184                                 NghCounts[i] = TheGraph[i].d;
3185                             }
3186                         }
3187                         else {
3188                             memset(NghCounts, 0, n*sizeof(int));
3189 
3190                             /* NEIGHCOUNT_DENSE_DENSE_MULT */
3191                             for (i = ind0; i < ind2; i++) {
3192                                 labi = lab[i];
3193                                 nghb = TheGraph[labi].e;
3194                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
3195                                     k = nghb[j1int];
3196                                     (NghCounts[k])++;
3197                                 }
3198                             }
3199                             /* End NEIGHCOUNT_DENSE_DENSE_MULT */
3200 
3201                         }
3202 
3203                         ind0 = 0;
3204                         while (ind0 < n) {    /* For each cell C with size(C) > 1 */
3205                             ind1 = ind0+cls[ind0];
3206                             if (cls[ind0] > 1) {
3207 
3208                                 /* Determine whether C must be split */
3209                                 SplCntInd = 0;
3210                                 value = NghCounts[lab[ind0]];
3211                                 for (i = ind0+1; i < ind1; i++)
3212                                 {
3213                                     if (NghCounts[lab[i]] != value)
3214                                     {
3215                                         Markers[value] = tv->mark;
3216                                         SplCnt[SplCntInd++] = value;
3217                                         SplPos[value] = i-ind0;
3218                                         do {
3219                                             value = NghCounts[lab[i++]];
3220                                             if (Markers[value] != tv->mark) {
3221                                                 Markers[value] = tv->mark;
3222                                                 SplCnt[SplCntInd++] = value;
3223                                                 SplPos[value] = 1;
3224                                             }
3225                                             else {
3226                                                 SplPos[value]++;
3227                                             }
3228                                         }
3229                                         while(i != ind1);
3230                                         break;
3231                                     }
3232                                 }
3233 
3234                                 if (SplCntInd) {
3235                                     tv->mark++;
3236 
3237                                     /* Sort the values deriving from the previous step */
3238                                     sort_Split_Array(SplCnt, SplCntInd);
3239 
3240                                     Part->cells += SplCntInd-1;
3241 
3242                                     /* Split the cell C and update the information for sizes of new cells */
3243                                     /* Put the new cells into the stack */
3244                                     i = ind0;
3245                                     if (StackMarkers[i] != tv->stackmark) {
3246                                         BigCellSize = 0;
3247                                     }
3248                                     for (k = 0; k < SplCntInd; k++) {
3249                                         value = SplPos[SplCnt[k]];
3250                                         cls[i] = value;
3251                                         if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
3252                                             BigCell = i;
3253                                             BigCellPos = CStackInd;
3254                                             BigCellSize = cls[i];
3255                                         }
3256                                         SplPos[SplCnt[k]] = i;
3257                                         i += value;
3258                                         if (i < ind1) {
3259                                             CStack[++CStackInd] = i;
3260                                             StackMarkers[i] = tv->stackmark;
3261                                         }
3262                                     }
3263                                     if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
3264                                         CStack[BigCellPos] = ind0;
3265                                         StackMarkers[BigCell] = 0;
3266                                         StackMarkers[ind0] = tv->stackmark;
3267                                         trieref = trie_make(trieref, i, n, tv);
3268                                     }
3269 
3270                                     /* Permute elements of the cell C */
3271                                     i = ind0;
3272                                     do {
3273                                         SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
3274                                     }
3275                                     while(++i < ind1);
3276 
3277                                     /* Reconstruct the cell C and update the inverse partition */
3278                                     newcell = ind0;
3279                                     i = ind0;
3280                                     ind2 = newcell+cls[newcell]-1;
3281                                     do {
3282                                         lab[i] = SplCnt[i];
3283                                         InvLab[lab[i]] = i;
3284                                         Part->inv[i] = newcell;
3285                                         if (i == ind2) {
3286                                             newcell = i+1;
3287                                             if (newcell < n) ind2 = newcell+cls[newcell]-1;
3288                                         }
3289                                     }
3290                                     while (++i < ind1);
3291                                 }
3292                             }
3293                             ind0 = ind1;
3294                         }
3295                     }
3296                 }
3297             }
3298         }
3299         while (weightend < iend1int);
3300     } /* end while (CStackInd > 0) */
3301 
3302     tv->augmented_cells = Part->cells - tv->augmented_cells;
3303 
3304     Cand->code = CLEANUP(longcode);
3305     return;
3306 }
3307 
traces_refine_comptrie(Candidate * Cand,int n,Partition * Part,struct TracesVars * tv,struct TracesInfo * ti)3308 int traces_refine_comptrie(Candidate *Cand,
3309                            int n,
3310                            Partition *Part,
3311                            struct TracesVars* tv,
3312                            struct TracesInfo *ti) {
3313     int i, j, k, jk, sc, ind0, ind1, ind2, ind3, labi;
3314     int value, iend, newcell;
3315     int HitClsInd, SplInd, SplCntInd, CStackInd;
3316     int j1int, iend1int;
3317     unsigned int longcode;
3318     int Split = 0;
3319     int Sparse = TRUE;
3320     int *lab, *cls, *InvLab, *SplitCell, *LabCell;
3321     int BigCell, BigCellPos, BigCellSize;
3322     int *nghb;
3323     const int variation = 1;
3324     int currentweight, weightstart, weightend, currentcell, currentsize;
3325 
3326     if (tv->stackmark > (NAUTY_INFINITY-2)) {
3327         memset(StackMarkers, 0, n*sizeof(int));
3328         tv->stackmark = 0;
3329     }
3330     tv->stackmark++;
3331 
3332     tv->augmented_cells = Part->cells;
3333 
3334     lab = Cand->lab;
3335     InvLab = Cand->invlab;
3336     cls = Part->cls;
3337 
3338     CStack[1] = Spine[tv->tolevel_tl].tgtpos;
3339     CStackInd = 1;
3340     for (i = 1; i <= CStackInd; i++) {
3341         StackMarkers[CStack[i]] = tv->stackmark;
3342     }
3343 
3344     longcode = Part->cells;
3345     while (CStackInd > 0)
3346     {
3347 
3348         weightend = 0;
3349 
3350         if (tv->mark > (NAUTY_INFINITY-2)) {
3351             memset(Markers, 0, n*sizeof(int));
3352             memset(MarkHitVtx, 0, n*sizeof(int));
3353             tv->mark = 0;
3354         }
3355         tv->mark++;
3356 
3357         if (Part->cells == n) break;
3358 
3359         k = Select_from_CStack(cls, CStackInd);
3360 
3361         currentcell = CStack[k];
3362         currentsize = currentcell+cls[currentcell];
3363         CStack[k] = CStack[CStackInd--];        /* Current Cell */
3364         longcode = MASHNONCOMM(longcode, currentcell);
3365         StackMarkers[currentcell] = 0;
3366 
3367         labi = lab[currentcell];
3368         iend1int = TheGraph[labi].d;
3369         nghb =  TheGraph[labi].e;
3370 
3371         do {
3372             ind0 = currentcell;
3373             ind2 = currentsize;
3374             weightstart = weightend;
3375 
3376             if (tv->options->weighted) {
3377                 currentweight = (TheGraph[labi].w)[weightstart];
3378                 while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
3379                     weightend++;
3380                 }
3381             } else {
3382                 weightend = TheGraph[labi].d;
3383             }
3384 
3385             /* Analysis of occurrences of neighbors of the current cell */
3386             /* The list of cells with neighbors in the current cell is  built */
3387             if (cls[ind0] == 1) {  /* SINGLETON CURRENT CELL CASE */
3388 
3389                 /* NEIGHCOUNT_SING_MULT */
3390                 HitClsInd = 0;
3391                 for (j1int = weightstart; j1int < weightend; ++j1int) {
3392                     k = nghb[j1int];
3393                     value = Part->inv[InvLab[k]];
3394                     if (cls[value] > 1) {
3395                         if (Markers[value] != tv->mark) {
3396                             HitCls[HitClsInd++] = value;
3397                             Markers[value] = tv->mark;
3398                             ElmHitCll[value] = value;
3399                         }
3400                         HitVtx[ElmHitCll[value]++] = k;
3401                     } else {
3402                         switch (variation) {
3403                             case 1:
3404                                 longcode = MASHCOMM(longcode, value);
3405                                 break;
3406                             default:
3407                                 break;
3408                         }
3409                     }
3410                 }
3411                 /* end NEIGHCOUNT_SING_MULT */
3412 
3413                 tv->mark++;
3414                 FIND_SPLIT_CELLS;
3415 
3416                 /* Sorting the cells to be split */
3417                 sort_Split_Array(SplCls, SplInd);
3418 
3419                 for (j = 0; j < SplInd; j++) {
3420                     ind1 = SplCls[j];
3421                     i = ind1+cls[ind1]-ElmHitCll[ind1];
3422                     trieref = trie_comp(trieref, i);
3423                     if (trieref == NULL) return 0;
3424                 }
3425 
3426                 /* REARRANGE THE CELLS */
3427                 for (j = 0; j < SplInd; j++) {
3428                     /* REARRANGE_CELLS */
3429                     ind1 = SplCls[j];
3430                     cls[ind1] = cls[ind1]-ElmHitCll[ind1];
3431                     newcell = ind1+cls[ind1];
3432                     cls[newcell] = ElmHitCll[ind1];
3433                     Part->cells++;
3434                     if (StackMarkers[ind1] != tv->stackmark) {
3435                         if (cls[newcell] < cls[ind1]) {
3436                             CStack[++CStackInd] = newcell;
3437                             StackMarkers[newcell] = tv->stackmark;
3438                         }
3439                         else {
3440                             CStack[++CStackInd] = ind1;
3441                             StackMarkers[ind1] = tv->stackmark;
3442                         }
3443                     }
3444                     else {
3445                         CStack[++CStackInd] = newcell;
3446                         StackMarkers[newcell] = tv->stackmark;
3447                     }
3448                     SplitCell = HitVtx+ind1;
3449                     ind3 = cls[newcell];
3450                     LabCell = lab+newcell;
3451                     for (jk = 0; jk < ind3; jk++) {
3452                         k = SplitCell[jk];
3453                         i = LabCell[jk];
3454                         Part->inv[newcell+jk] = newcell;
3455                         lab[InvLab[k]] = i;
3456                         InvLab[i] = InvLab[k];
3457                         LabCell[jk] = k;
3458                         InvLab[k] = newcell+jk;
3459                     }
3460                     /* END REARRANGE_CELLS */
3461                 }
3462             }
3463             else {
3464                 if (ti->thegraphisparse) {
3465 
3466                     /* NEIGHCOUNT_SPARSE_MULT */
3467                     HitClsInd = 0;
3468                     if (cls[ind0] != n) {
3469                         for (i = ind0; i < ind2; i++) {
3470                             labi = lab[i];
3471                             nghb = TheGraph[labi].e;
3472                             for (j = weightstart; j < weightend; j++) {
3473                                 k = nghb[j];
3474                                 if (MarkHitVtx[k] == tv->mark) {
3475                                     NghCounts[k]++;
3476                                 }
3477                                 else {
3478                                     value = Part->inv[InvLab[k]];
3479                                     if (cls[value] > 1) {
3480                                         MarkHitVtx[k] = tv->mark;
3481                                         NghCounts[k] = 1;
3482                                         if (Markers[value] != tv->mark) {
3483                                             HitCls[HitClsInd++] = value;
3484                                             Markers[value] = tv->mark;
3485                                             HitVtx[value] = k;
3486                                             ElmHitCll[value] = 1;
3487                                         }
3488                                         else {
3489                                             HitVtx[value+ElmHitCll[value]++] = k;
3490                                         }
3491                                     }
3492                                     else {
3493                                         switch (variation) {
3494                                             case 1:
3495                                                 longcode = MASHCOMM(longcode, value);
3496                                                 break;
3497                                             default:
3498                                                 break;
3499                                         }
3500                                     }
3501                                 }
3502                             }
3503                         }
3504                     }
3505                     /* End NEIGHCOUNT_SPARSE_MULT */
3506 
3507                     tv->mark++;
3508 
3509                     SplInd = 0;
3510                     SplCls[0] = n;
3511                     for (j = 0; j < HitClsInd; j++) {
3512                         ind1 = HitCls[j];
3513                         if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
3514                             SplCls[SplInd++] = ind1;
3515                         }
3516                         else {
3517                             ind2 = ind1+cls[ind1];
3518                             Split = FALSE;
3519                             value = NghCounts[lab[ind1++]];
3520                             for (i = ind1; i < ind2; i++)
3521                             {
3522                                 if (NghCounts[lab[i]] != value)
3523                                 {
3524                                     SplCls[SplInd++] = HitCls[j];
3525                                     Split = TRUE;
3526                                     break;
3527                                 }
3528                             }
3529                             if (!Split) {
3530                                 longcode = MASHCOMM(longcode, ind1);
3531                             }
3532                         }
3533                     }
3534 
3535                     /* Sorting the cells to be split */
3536                     sort_Split_Array(SplCls, SplInd);
3537 
3538                     for (sc = 0; sc < SplInd; sc++) {    /* For each cell C to be split */
3539                         ind0 = SplCls[sc];
3540                         ind1 = ind0 + cls[ind0];
3541                         SplCntInd = 0;
3542                         if (ElmHitCll[ind0] < cls[ind0]) {
3543                             SplCnt[SplCntInd++] = 0;
3544                             SplPos[0] = cls[ind0] - ElmHitCll[ind0];
3545                         }
3546 
3547                         /* According to the numbers of neighbors of C into the current cell */
3548                         /* compute how many vertices in C will be placed into the same new cell */
3549                         iend = ind0 + ElmHitCll[ind0];
3550                         for (i = ind0; i < iend; i++) {
3551                             value = NghCounts[HitVtx[i]];
3552                             if (Markers[value] != tv->mark) {
3553                                 Markers[value] = tv->mark;
3554                                 SplCnt[SplCntInd++] = value;
3555                                 SplPos[value] = 1;
3556                             }
3557                             else {
3558                                 SplPos[value]++;
3559                             }
3560                         }
3561 
3562                         tv->mark++;
3563 
3564                         /* Sort the values deriving from the previous step */
3565                         sort_Split_Array(SplCnt, SplCntInd);
3566                         Part->cells += SplCntInd-1;
3567 
3568                         /* Split the cell C and update the information for sizes of new cells */
3569                         /* Put the new cells into the stack */
3570                         i = ind0;
3571                         if (StackMarkers[i] != tv->stackmark) {
3572                             BigCellSize = 0;
3573                         }
3574                         for (k = 0; k < SplCntInd; k++) {
3575                             value = SplPos[SplCnt[k]];
3576                             cls[i] = value;
3577                             if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
3578                                 BigCell = i;
3579                                 BigCellPos = CStackInd;
3580                                 BigCellSize = cls[i];
3581                             }
3582                             SplPos[SplCnt[k]] = i;
3583                             i += value;
3584                             if (i < ind1) {
3585                                 CStack[++CStackInd] = i;
3586                                 StackMarkers[i] = tv->stackmark;
3587                                 trieref = trie_comp(trieref, i);
3588                                 if (trieref == NULL) return 0;
3589                             }
3590                         }
3591 
3592                         if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
3593                             CStack[BigCellPos] = ind0;
3594                             StackMarkers[BigCell] = 0;
3595                             StackMarkers[ind0] = tv->stackmark;
3596                         }
3597                         /* Permute elements of the cell C */
3598                         iend = ind0 + ElmHitCll[ind0];
3599                         for (i = ind0; i < iend; i++) {
3600                             value = HitVtx[i];
3601                             j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
3602                             k = InvLab[value];                /* where HitVtx[i] is in lab */
3603                             lab[k] = lab[j];
3604                             lab[j] = value;
3605                             InvLab[value] = j;
3606                             InvLab[lab[k]] = k;
3607                             NghCounts[value] = 0;
3608                         }
3609 
3610                         /* Reconstruct the cell C and update the inverse partition */
3611                         newcell = ind1 - ElmHitCll[ind0];
3612                         i = newcell;
3613                         ind2 = newcell+cls[newcell]-1;
3614                         do {
3615                             Part->inv[i] = newcell;
3616                             if (i == ind2) {
3617                                 newcell = i+1;
3618                                 if (newcell < n) ind2 = newcell+cls[newcell]-1;
3619                             }
3620                         }
3621                         while (++i < ind1);
3622                     }
3623                 }
3624                 else {
3625                     if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
3626                         Sparse = FALSE;
3627                     }
3628                     else {
3629                         Sparse = TRUE;
3630                     }
3631                     Sparse = TRUE;
3632                     if (Sparse) {
3633                         /* Counting occurrences of neighbors of the current cell */
3634                         /* The list of cells with neighbors in the current cell is also built */
3635                         if (cls[ind0] == n) {
3636                             for (i = 0; i < n; i++) {
3637                                 NghCounts[i] = TheGraph[i].d;
3638                             }
3639                             HitCls[0] = 0;
3640                             HitClsInd = 1;
3641                         }
3642                         else {
3643                             memset(NghCounts, 0, n*sizeof(int));
3644 
3645                             /* NEIGHCOUNT_DENSE_SPARSE_MULT */
3646                             HitClsInd = 0;
3647                             for (i = ind0; i < ind2; i++) {
3648                                 labi = lab[i];
3649                                 nghb =  TheGraph[labi].e;
3650                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
3651                                     k = nghb[j1int];
3652                                     (NghCounts[k])++;
3653                                     value = Part->inv[InvLab[k]];
3654                                     if (Markers[value] != tv->mark) {
3655                                         if (cls[value] > 1) HitCls[HitClsInd++] = value;
3656                                         Markers[value] = tv->mark;
3657                                     }
3658                                 }
3659                             }
3660                             /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
3661                             ;
3662                         }
3663 
3664                         tv->mark++;
3665 
3666                         SplInd = 0;
3667                         for (j = 0; j < HitClsInd; j++) {
3668                             ind1 = HitCls[j];
3669                             ind2 = ind1+cls[ind1];
3670                             value = NghCounts[lab[ind1++]];
3671                             for (i = ind1; i < ind2; i++)
3672                             {
3673                                 if (NghCounts[lab[i]] != value)
3674                                 {
3675                                     SplCls[SplInd++] = HitCls[j];
3676                                     break;
3677                                 }
3678                             }
3679                         }
3680 
3681                         /* Sorting the cells to be split */
3682                         sort_Split_Array(SplCls, SplInd);
3683 
3684                         for (j = 0; j < SplInd; j++) {    /* For each cell C to be split */
3685                             ind0 = SplCls[j];
3686                             ind1 = ind0+cls[ind0];
3687                             SplCntInd = 0;
3688 
3689                             /* According to the numbers of neighbors of C into the current cell */
3690                             /* compute how many vertices in C will be placed into the same new cell */
3691                             for (i = ind0; i < ind1; i++) {
3692                                 value = NghCounts[lab[i]];
3693                                 if (Markers[value] != tv->mark) {
3694                                     Markers[value] = tv->mark;
3695                                     SplCnt[SplCntInd++] = value;
3696                                     SplPos[value] = 1;
3697                                 }
3698                                 else {
3699                                     SplPos[value]++;
3700                                 }
3701                             }
3702 
3703                             tv->mark++;
3704 
3705                             /* Sort the values deriving from the previous step */
3706                             sort_Split_Array(SplCnt, SplCntInd);
3707 
3708                             Part->cells += SplCntInd-1;
3709 
3710                             /* Split the cell C and update the information for sizes of new cells */
3711                             /* Put the new cells into the stack */
3712                             i = ind0;
3713                             if (StackMarkers[i] != tv->stackmark) {
3714                                 BigCellSize = 0;
3715                             }
3716                             for (k = 0; k < SplCntInd; k++) {
3717                                 value = SplPos[SplCnt[k]];
3718                                 cls[i] = value;
3719                                 if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
3720                                     BigCell = i;
3721                                     BigCellPos = CStackInd;
3722                                     BigCellSize = cls[i];
3723                                 }
3724                                 SplPos[SplCnt[k]] = i;
3725                                 i += value;
3726                                 if (i < ind1) {
3727                                     CStack[++CStackInd] = i;
3728                                     StackMarkers[i] = tv->stackmark;
3729                                     trieref = trie_comp(trieref, i);
3730                                     if (trieref == NULL) return 0;
3731                                 }
3732                             }
3733                             if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
3734                                 CStack[BigCellPos] = ind0;
3735                                 StackMarkers[BigCell] = 0;
3736                                 StackMarkers[ind0] = tv->stackmark;
3737                             }
3738 
3739                             /* Permute elements of the cell C */
3740                             i = ind0;
3741                             do {
3742                                 SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
3743                             }
3744                             while(++i < ind1);
3745 
3746                             /* Reconstruct the cell C and update the inverse partition */
3747                             newcell = ind0;
3748                             i = ind0;
3749                             ind2 = newcell+cls[newcell]-1;
3750                             do {
3751                                 lab[i] = SplCnt[i];
3752                                 InvLab[lab[i]] = i;
3753                                 Part->inv[i] = newcell;
3754 
3755                                 if (i == ind2) {
3756                                     newcell = i+1;
3757                                     if (newcell < n) ind2 = newcell+cls[newcell]-1;
3758                                 }
3759                             }
3760                             while (++i < ind1);
3761                         }
3762                     }
3763                     else {
3764                         if (cls[ind0] == n) {
3765                             for (i = 0; i < n; i++) {
3766                                 NghCounts[i] = TheGraph[i].d;
3767                             }
3768                         }
3769                         else {
3770                             memset(NghCounts, 0, n*sizeof(int));
3771 
3772                             /* NEIGHCOUNT_DENSE_DENSE_MULT */
3773                             for (i = ind0; i < ind2; i++) {
3774                                 labi = lab[i];
3775                                 nghb = TheGraph[labi].e;
3776                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
3777                                     k = nghb[j1int];
3778                                     (NghCounts[k])++;
3779                                 }
3780                             }
3781                             /* End NEIGHCOUNT_DENSE_DENSE_MULT */
3782 
3783                         }
3784 
3785                         ind0 = 0;
3786                         while (ind0 < n) {    /* For each cell C with size(C) > 1 */
3787                             ind1 = ind0+cls[ind0];
3788                             if (cls[ind0] > 1) {
3789 
3790                                 /* Determine whether C must be split */
3791                                 SplCntInd = 0;
3792                                 value = NghCounts[lab[ind0]];
3793                                 for (i = ind0+1; i < ind1; i++)
3794                                 {
3795                                     if (NghCounts[lab[i]] != value)
3796                                     {
3797                                         Markers[value] = tv->mark;
3798                                         SplCnt[SplCntInd++] = value;
3799                                         SplPos[value] = i-ind0;
3800                                         do {
3801                                             value = NghCounts[lab[i++]];
3802                                             if (Markers[value] != tv->mark) {
3803                                                 Markers[value] = tv->mark;
3804                                                 SplCnt[SplCntInd++] = value;
3805                                                 SplPos[value] = 1;
3806                                             }
3807                                             else {
3808                                                 SplPos[value]++;
3809                                             }
3810                                         }
3811                                         while(i != ind1);
3812                                         break;
3813                                     }
3814                                 }
3815 
3816                                 if (SplCntInd) {
3817                                     tv->mark++;
3818 
3819                                     /* Sort the values deriving from the previous step */
3820                                     sort_Split_Array(SplCnt, SplCntInd);
3821 
3822                                     Part->cells += SplCntInd-1;
3823 
3824                                     /* Split the cell C and update the information for sizes of new cells */
3825                                     /* Put the new cells into the stack */
3826                                     i = ind0;
3827                                     if (StackMarkers[i] != tv->stackmark) {
3828                                         BigCellSize = 0;
3829                                     }
3830                                     for (k = 0; k < SplCntInd; k++) {
3831                                         value = SplPos[SplCnt[k]];
3832                                         cls[i] = value;
3833                                         if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
3834                                             BigCell = i;
3835                                             BigCellPos = CStackInd;
3836                                             BigCellSize = cls[i];
3837                                         }
3838                                         SplPos[SplCnt[k]] = i;
3839                                         i += value;
3840                                         if (i < ind1) {
3841                                             CStack[++CStackInd] = i;
3842                                             StackMarkers[i] = tv->stackmark;
3843                                         }
3844                                     }
3845                                     if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
3846                                         CStack[BigCellPos] = ind0;
3847                                         StackMarkers[BigCell] = 0;
3848                                         StackMarkers[ind0] = tv->stackmark;
3849                                         trieref = trie_comp(trieref, i);
3850                                         if (trieref == NULL) return 0;
3851                                     }
3852 
3853                                     /* Permute elements of the cell C */
3854                                     i = ind0;
3855                                     do {
3856                                         SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
3857                                     }
3858                                     while(++i < ind1);
3859 
3860                                     /* Reconstruct the cell C and update the inverse partition */
3861                                     newcell = ind0;
3862                                     i = ind0;
3863                                     ind2 = newcell+cls[newcell]-1;
3864                                     do {
3865                                         lab[i] = SplCnt[i];
3866                                         InvLab[lab[i]] = i;
3867                                         Part->inv[i] = newcell;
3868                                         if (i == ind2) {
3869                                             newcell = i+1;
3870                                             if (newcell < n) ind2 = newcell+cls[newcell]-1;
3871                                         }
3872                                     }
3873                                     while (++i < ind1);
3874                                 }
3875                             }
3876                             ind0 = ind1;
3877                         }
3878                     }
3879                 }
3880             }
3881         }
3882         while (weightend < iend1int);
3883     }  /* end while (CStackInd > 0) */
3884 
3885     tv->augmented_cells = Part->cells - tv->augmented_cells;
3886 
3887     Cand->code = CLEANUP(longcode);
3888     return 1;
3889 }
3890 
traces_refine_sametrace(Candidate * Cand,int n,Partition * Part,struct TracesVars * tv,struct TracesInfo * ti)3891 int traces_refine_sametrace(Candidate *Cand,
3892                             int n,
3893                             Partition *Part,
3894                             struct TracesVars* tv,
3895                             struct TracesInfo *ti) {
3896     int i, j, k, jk, sc, ind0, ind1, ind2, ind3, ind4, labi;
3897     int value, iend, newcell;
3898     int HitClsInd, SplInd, SplCntInd, CStackInd, TraceInd, TraceCCInd, TraceStepsInd;
3899     int j1int, iend1int;
3900     unsigned int longcode;
3901     int Sparse = TRUE;
3902     int *lab, *cls, *InvLab, *TracePos, *SplitCell, *LabCell, *TraceEnd, Traceccend, *Tracestpend;
3903     int BigCell, BigCellPos, BigCellSize;
3904     boolean TraceCell = FALSE;
3905     int *nghb;
3906     const int variation = 0;
3907     int currentweight, weightstart, weightend, currentcell, currentsize;
3908 
3909     if (tv->stackmark > (NAUTY_INFINITY-2)) {
3910         memset(StackMarkers, 0, n*sizeof(int));
3911         tv->stackmark = 0;
3912     }
3913     tv->stackmark++;
3914 
3915     tv->augmented_cells = Part->cells;
3916 
3917     SpineTL = Spine+tv->tolevel;
3918     TraceEnd = &(SpineTL->trcend);
3919     Traceccend = SpineTL->ccend;
3920     Tracestpend = &(SpineTL->stpend);
3921     TraceCCInd = SpineTL->ccstart;
3922     TraceStepsInd = SpineTL->stpstart;
3923 
3924     lab = Cand->lab;
3925     InvLab = Cand->invlab;
3926     cls = Part->cls;
3927 
3928     UPDATEMIN(Part->active, n-1);
3929     memcpy(CStack+1, TheTrace+SpineTL->trcstart, (Part->active)*sizeof(int));
3930     CStackInd = Part->active;
3931     for (i = 1; i <= CStackInd; i++) {
3932         StackMarkers[CStack[i]] = tv->stackmark;
3933     }
3934 
3935     longcode = Part->cells;
3936     TraceInd = SpineTL->trcstart+Part->active;
3937 
3938     while (CStackInd > 0)
3939     {
3940 
3941         weightend = 0;
3942 
3943         if (tv->mark > (NAUTY_INFINITY-2)) {
3944             memset(Markers, 0, n*sizeof(int));
3945             memset(MarkHitVtx, 0, n*sizeof(int));
3946             tv->mark = 0;
3947         }
3948         tv->mark++;
3949 
3950         if (Part->cells == n) break;
3951 
3952         k = Select_from_CStack(cls, CStackInd);
3953 
3954         currentcell = CStack[k];
3955         currentsize = currentcell+cls[currentcell];
3956         CStack[k] = CStack[CStackInd--];        /* Current Cell */
3957         StackMarkers[currentcell] = 0;
3958 
3959         labi = lab[currentcell];
3960         iend1int = TheGraph[labi].d;
3961         nghb =  TheGraph[labi].e;
3962 
3963         do {
3964             ind0 = currentcell;
3965             ind2 = currentsize;
3966             weightstart = weightend;
3967 
3968             if (tv->options->weighted) {
3969                 currentweight = (TheGraph[labi].w)[weightstart];
3970                 while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
3971                     weightend++;
3972                 }
3973             } else {
3974                 weightend = TheGraph[labi].d;
3975             }
3976 
3977             TraceCell = ((ind0 == TheTraceCC[TraceCCInd]) && (TraceCCInd < Traceccend));
3978 
3979             /* Analysis of occurrences of neighbors of the current cell */
3980             /* The list of cells with neighbors in the current cell is  built */
3981             if (cls[ind0] == 1) {  /* SINGLETON CURRENT CELL CASE */
3982 
3983                 /* NEIGHCOUNT_SING_MULT */
3984                 HitClsInd = 0;
3985                 for (j1int = weightstart; j1int < weightend; ++j1int) {
3986                     k = nghb[j1int];
3987                     value = Part->inv[InvLab[k]];
3988                     if (cls[value] > 1) {
3989                         if (Markers[value] != tv->mark) {
3990                             HitCls[HitClsInd++] = value;
3991                             Markers[value] = tv->mark;
3992                             ElmHitCll[value] = value;
3993                         }
3994                         HitVtx[ElmHitCll[value]++] = k;
3995                     } else {
3996                         switch (variation) {
3997                             case 1:
3998                                 longcode = MASHCOMM(longcode, value);
3999                                 break;
4000                             default:
4001                                 break;
4002                         }
4003                     }
4004                 }
4005                 /* end NEIGHCOUNT_SING_MULT */
4006 
4007                 tv->mark++;
4008                 FIND_SPLIT_CELLS;
4009 
4010                 /* SINGLETON CC CASE */
4011                 if (SplInd) {
4012                     SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd, &Traceccend)
4013 
4014                     /* Sorting the cells to be split */
4015                     sort_Split_Array(SplCls, SplInd);
4016 
4017                     for (j = 0; j < SplInd; j++) {
4018                         ind1 = SplCls[j];
4019                         i = ind1+cls[ind1]-ElmHitCll[ind1];
4020                         SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
4021                     }
4022 
4023                     /* REARRANGE THE CELLS */
4024                     for (j = 0; j < SplInd; j++) {
4025                         /* REARRANGE_CELLS */
4026                         ind1 = SplCls[j];
4027                         cls[ind1] = cls[ind1]-ElmHitCll[ind1];
4028                         newcell = ind1+cls[ind1];
4029                         cls[newcell] = ElmHitCll[ind1];
4030                         Part->cells++;
4031                         if (StackMarkers[ind1] != tv->stackmark) {
4032                             if (cls[newcell] < cls[ind1]) {
4033                                 CStack[++CStackInd] = newcell;
4034                                 StackMarkers[newcell] = tv->stackmark;
4035                             }
4036                             else {
4037                                 CStack[++CStackInd] = ind1;
4038                                 StackMarkers[ind1] = tv->stackmark;
4039                             }
4040                         }
4041                         else {
4042                             CStack[++CStackInd] = newcell;
4043                             StackMarkers[newcell] = tv->stackmark;
4044                         }
4045                         SplitCell = HitVtx+ind1;
4046                         ind3 = cls[newcell];
4047                         LabCell = lab+newcell;
4048                         for (jk = 0; jk < ind3; jk++) {
4049                             k = SplitCell[jk];
4050                             i = LabCell[jk];
4051                             Part->inv[newcell+jk] = newcell;
4052                             lab[InvLab[k]] = i;
4053                             InvLab[i] = InvLab[k];
4054                             LabCell[jk] = k;
4055                             InvLab[k] = newcell+jk;
4056                         }
4057                         /* END REARRANGE_CELLS */
4058 
4059                         if (cls[ind1] == 1) {
4060                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[ind1]);
4061                         }
4062                         if (cls[newcell] == 1) {
4063                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[newcell]);
4064                         }
4065                     }
4066                 }
4067                 else {
4068                     if (TraceCell) {
4069                         return 0;
4070                     }
4071                 }
4072 
4073             }
4074             else {
4075                 if (ti->thegraphisparse) {
4076 
4077                     /* NEIGHCOUNT_SPARSE_MULT */
4078                     HitClsInd = 0;
4079                     if (cls[ind0] != n) {
4080                         for (i = ind0; i < ind2; i++) {
4081                             labi = lab[i];
4082                             nghb = TheGraph[labi].e;
4083                             for (j = weightstart; j < weightend; j++) {
4084                                 k = nghb[j];
4085                                 if (MarkHitVtx[k] == tv->mark) {
4086                                     NghCounts[k]++;
4087                                 }
4088                                 else {
4089                                     value = Part->inv[InvLab[k]];
4090                                     if (cls[value] > 1) {
4091                                         MarkHitVtx[k] = tv->mark;
4092                                         NghCounts[k] = 1;
4093                                         if (Markers[value] != tv->mark) {
4094                                             HitCls[HitClsInd++] = value;
4095                                             Markers[value] = tv->mark;
4096                                             HitVtx[value] = k;
4097                                             ElmHitCll[value] = 1;
4098                                         }
4099                                         else {
4100                                             HitVtx[value+ElmHitCll[value]++] = k;
4101                                         }
4102                                     }
4103                                     else {
4104                                         switch (variation) {
4105                                             case 1:
4106                                                 longcode = MASHCOMM(longcode, value);
4107                                                 break;
4108                                             default:
4109                                                 break;
4110                                         }
4111                                     }
4112                                 }
4113                             }
4114                         }
4115                     }
4116                     /* End NEIGHCOUNT_SPARSE_MULT */
4117 
4118                     tv->mark++;
4119 
4120                     SplInd = 0;
4121                     SplCls[0] = n;
4122                     for (j = 0; j < HitClsInd; j++) {
4123                         ind1 = HitCls[j];
4124                         if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
4125                             SplCls[SplInd++] = ind1;
4126                         }
4127                         else {
4128                             ind2 = ind1+cls[ind1];
4129                             value = NghCounts[lab[ind1++]];
4130                             for (i = ind1; i < ind2; i++)
4131                             {
4132                                 if (NghCounts[lab[i]] != value)
4133                                 {
4134                                     SplCls[SplInd++] = HitCls[j];
4135                                     break;
4136                                 }
4137                             }
4138                         }
4139                     }
4140 
4141                     /* SPARSE CASE */
4142                     if (SplInd) {
4143                         SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+n, &Traceccend)
4144 
4145                         /* Sorting the cells to be split */
4146                         sort_Split_Array(SplCls, SplInd);
4147 
4148                         for (sc = 0; sc < SplInd; sc++) {    /* For each cell C to be split */
4149                             ind0 = SplCls[sc];
4150                             ind1 = ind0 + cls[ind0];
4151                             SplCntInd = 0;
4152                             if (ElmHitCll[ind0] < cls[ind0]) {
4153                                 SplCnt[SplCntInd++] = 0;
4154                                 SplPos[0] = cls[ind0] - ElmHitCll[ind0];
4155                             }
4156 
4157                             /* According to the numbers of neighbors of C into the current cell */
4158                             /* compute how many vertices in C will be placed into the same new cell */
4159                             iend = ind0 + ElmHitCll[ind0];
4160                             for (i = ind0; i < iend; i++) {
4161                                 value = NghCounts[HitVtx[i]];
4162                                 if (Markers[value] != tv->mark) {
4163                                     Markers[value] = tv->mark;
4164                                     SplCnt[SplCntInd++] = value;
4165                                     SplPos[value] = 1;
4166                                 }
4167                                 else {
4168                                     SplPos[value]++;
4169                                 }
4170                             }
4171                             tv->mark++;
4172 
4173                             if (SplCntInd) {
4174                                 SAMETRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+n, Tracestpend)
4175                             }
4176 
4177                             /* Sort the values deriving from the previous step */
4178                             sort_Split_Array(SplCnt, SplCntInd);
4179 
4180                             Part->cells += SplCntInd-1;
4181 
4182                             /* Split the cell C and update the information for sizes of new cells */
4183                             /* Put the new cells into the stack */
4184                             i = ind0;
4185                             if (StackMarkers[i] != tv->stackmark) {
4186                                 BigCellSize = 0;
4187                             }
4188                             for (k = 0; k < SplCntInd; k++) {
4189                                 value = SplPos[SplCnt[k]];
4190                                 cls[i] = value;
4191                                 if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
4192                                     BigCell = i;
4193                                     BigCellPos = CStackInd;
4194                                     BigCellSize = cls[i];
4195                                 }
4196                                 SplPos[SplCnt[k]] = i;
4197                                 i += value;
4198                                 if (i < ind1) {
4199                                     CStack[++CStackInd] = i;
4200                                     StackMarkers[i] = tv->stackmark;
4201                                     SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
4202                                 }
4203                             }
4204 
4205                             if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
4206                                 CStack[BigCellPos] = ind0;
4207                                 StackMarkers[BigCell] = 0;
4208                                 StackMarkers[ind0] = tv->stackmark;
4209                             }
4210                             /* Permute elements of the cell C */
4211                             iend = ind0 + ElmHitCll[ind0];
4212                             for (i = ind0; i < iend; i++) {
4213                                 value = HitVtx[i];
4214                                 j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
4215                                 k = InvLab[value];                /* where HitVtx[i] is in lab */
4216                                 lab[k] = lab[j];
4217                                 lab[j] = value;
4218                                 InvLab[value] = j;
4219                                 InvLab[lab[k]] = k;
4220                                 NghCounts[value] = 0;
4221                             }
4222 
4223                             /* Reconstruct the cell C and update the inverse partition */
4224                             newcell = ind1 - ElmHitCll[ind0];
4225                             i = newcell;
4226                             ind2 = newcell+cls[newcell]-1;
4227                             do {
4228                                 Part->inv[i] = newcell;
4229                                 if (i == ind2) {
4230                                     newcell = i+1;
4231                                     if (newcell < n) ind2 = newcell+cls[newcell]-1;
4232                                 }
4233                             }
4234                             while (++i < ind1);
4235 
4236                             for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
4237                                 if (cls[i] == 1) {
4238                                     Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
4239                                 }
4240                             }
4241 
4242                         }
4243                     }
4244                     else {
4245                         if (TraceCell) {
4246                             return 0;
4247                         }
4248                     }
4249 
4250                 }
4251                 else {
4252                     if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
4253                         Sparse = FALSE;
4254                     }
4255                     else {
4256                         Sparse = TRUE;
4257                     }
4258                     Sparse = TRUE;
4259                     if (Sparse) {
4260                         /* Counting occurrences of neighbors of the current cell */
4261                         /* The list of cells with neighbors in the current cell is also built */
4262                         if (cls[ind0] == n) {
4263                             for (i = 0; i < n; i++) {
4264                                 NghCounts[i] = TheGraph[i].d;
4265                             }
4266                             HitCls[0] = 0;
4267                             HitClsInd = 1;
4268                         }
4269                         else {
4270                             memset(NghCounts, 0, n*sizeof(int));
4271 
4272                             /* NEIGHCOUNT_DENSE_SPARSE_MULT */
4273                             HitClsInd = 0;
4274                             for (i = ind0; i < ind2; i++) {
4275                                 labi = lab[i];
4276                                 nghb =  TheGraph[labi].e;
4277                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
4278                                     k = nghb[j1int];
4279                                     (NghCounts[k])++;
4280                                     value = Part->inv[InvLab[k]];
4281                                     if (Markers[value] != tv->mark) {
4282                                         if (cls[value] > 1) HitCls[HitClsInd++] = value;
4283                                         Markers[value] = tv->mark;
4284                                     }
4285                                 }
4286                             }
4287                             /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
4288 
4289                         }
4290 
4291                         tv->mark++;
4292 
4293                         SplInd = 0;
4294                         for (j = 0; j < HitClsInd; j++) {
4295                             ind1 = HitCls[j];
4296                             ind2 = ind1+cls[ind1];
4297                             value = NghCounts[lab[ind1++]];
4298                             for (i = ind1; i < ind2; i++)
4299                             {
4300                                 if (NghCounts[lab[i]] != value)
4301                                 {
4302                                     SplCls[SplInd++] = HitCls[j];
4303                                     break;
4304                                 }
4305                             }
4306                         }
4307 
4308                         /* DENSE-SPARSE CASE */
4309                         if (SplInd) {
4310                             SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+2*n, &Traceccend)
4311 
4312                             /* Sorting the cells to be split */
4313                             sort_Split_Array(SplCls, SplInd);
4314 
4315                             for (j = 0; j < SplInd; j++) {    /* For each cell C to be split */
4316                                 ind0 = SplCls[j];
4317                                 ind1 = ind0+cls[ind0];
4318                                 SplCntInd = 0;
4319 
4320                                 /* According to the numbers of neighbors of C into the current cell */
4321                                 /* compute how many vertices in C will be placed into the same new cell */
4322                                 for (i = ind0; i < ind1; i++) {
4323                                     value = NghCounts[lab[i]];
4324                                     if (Markers[value] != tv->mark) {
4325                                         Markers[value] = tv->mark;
4326                                         SplCnt[SplCntInd++] = value;
4327                                         SplPos[value] = 1;
4328                                     }
4329                                     else {
4330                                         SplPos[value]++;
4331                                     }
4332                                 }
4333                                 tv->mark++;
4334 
4335                                 if (SplCntInd) {
4336                                     SAMETRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+2*n, Tracestpend)
4337                                 }
4338 
4339                                 /* Sort the values deriving from the previous step */
4340                                 sort_Split_Array(SplCnt, SplCntInd);
4341                                 Part->cells += SplCntInd-1;
4342 
4343                                 /* Split the cell C and update the information for sizes of new cells */
4344                                 /* Put the new cells into the stack */
4345                                 i = ind0;
4346                                 if (StackMarkers[i] != tv->stackmark) {
4347                                     BigCellSize = 0;
4348                                 }
4349                                 for (k = 0; k < SplCntInd; k++) {
4350                                     value = SplPos[SplCnt[k]];
4351                                     cls[i] = value;
4352                                     if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
4353                                         BigCell = i;
4354                                         BigCellPos = CStackInd;
4355                                         BigCellSize = cls[i];
4356                                     }
4357                                     SplPos[SplCnt[k]] = i;
4358                                     i += value;
4359                                     if (i < ind1) {
4360                                         CStack[++CStackInd] = i;
4361                                         StackMarkers[i] = tv->stackmark;
4362                                         SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
4363                                     }
4364                                 }
4365 
4366                                 if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
4367                                     CStack[BigCellPos] = ind0;
4368                                     StackMarkers[BigCell] = 0;
4369                                     StackMarkers[ind0] = tv->stackmark;
4370                                 }
4371 
4372                                 /* Permute elements of the cell C */
4373                                 i = ind0;
4374                                 do {
4375                                     SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
4376                                 }
4377                                 while(++i < ind1);
4378 
4379                                 /* Reconstruct the cell C and update the inverse partition */
4380                                 newcell = ind0;
4381                                 i = ind0;
4382                                 ind2 = newcell+cls[newcell]-1;
4383                                 do {
4384                                     lab[i] = SplCnt[i];
4385                                     InvLab[lab[i]] = i;
4386                                     Part->inv[i] = newcell;
4387                                     if (i == ind2) {
4388                                         newcell = i+1;
4389                                         if (newcell < n) ind2 = newcell+cls[newcell]-1;
4390                                     }
4391                                 }
4392                                 while (++i < ind1);
4393 
4394                                 for (i = ind0, k = 0; k < SplCntInd; i+=cls[i], k++) {
4395                                     if (cls[i] == 1) {
4396                                         Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
4397                                     }
4398                                 }
4399 
4400                             }
4401                         }
4402                         else {
4403                             if (TraceCell) {
4404                                 return 0;
4405                             }
4406                         }
4407 
4408                     }
4409                     else {
4410                         if (cls[ind0] == n) {
4411                             for (i = 0; i < n; i++) {
4412                                 NghCounts[i] = TheGraph[i].d;
4413                             }
4414                         }
4415                         else {
4416                             memset(NghCounts, 0, n*sizeof(int));
4417 
4418                             /* NEIGHCOUNT_DENSE_DENSE_MULT */
4419                             for (i = ind0; i < ind2; i++) {
4420                                 labi = lab[i];
4421                                 nghb = TheGraph[labi].e;
4422                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
4423                                     k = nghb[j1int];
4424                                     (NghCounts[k])++;
4425                                 }
4426                             }
4427                             /* End NEIGHCOUNT_DENSE_DENSE_MULT */
4428 
4429                         }
4430                         SplInd = 0;
4431                         ind4 = 0;
4432                         while (ind4 < n) {    /* For each cell C with size(C) > 1 */
4433                             ind1 = ind4+cls[ind4];
4434                             if (cls[ind4] > 1) {
4435 
4436                                 /* Determine whether C must be split */
4437                                 SplCntInd = 0;
4438                                 value = NghCounts[lab[ind4]];
4439                                 for (i = ind4+1; i < ind1; i++) {
4440                                     if (NghCounts[lab[i]] != value)
4441                                     {
4442                                         SplInd++;
4443                                         Markers[value] = tv->mark;
4444                                         SplCnt[SplCntInd++] = value;
4445                                         SplPos[value] = i-ind4;
4446                                         do {
4447                                             value = NghCounts[lab[i++]];
4448                                             if (Markers[value] != tv->mark) {
4449                                                 Markers[value] = tv->mark;
4450                                                 SplCnt[SplCntInd++] = value;
4451                                                 SplPos[value] = 1;
4452                                             }
4453                                             else {
4454                                                 SplPos[value]++;
4455                                             }
4456                                         }
4457                                         while(i != ind1);
4458                                         break;
4459                                     }
4460                                 }
4461                                 tv->mark++;
4462 
4463                                 if (SplCntInd) {
4464                                     SAMETRACE_CHECK(TheTraceSteps, TraceStepsInd, SplCntInd+3*n, Tracestpend)
4465 
4466                                     /* Sort the values deriving from the previous step */
4467                                     sort_Split_Array(SplCnt, SplCntInd);
4468 
4469                                     Part->cells += SplCntInd-1;
4470 
4471                                     /* Split the cell C and update the information for sizes of new cells */
4472                                     /* Put the new cells into the stack */
4473                                     i = ind4;
4474                                     if (StackMarkers[i] != tv->stackmark) {
4475                                         BigCellSize = 0;
4476                                     }
4477                                     for (k = 0; k < SplCntInd; k++) {
4478                                         value = SplPos[SplCnt[k]];
4479                                         cls[i] = value;
4480                                         if ((StackMarkers[ind4] != tv->stackmark) && (value > BigCellSize)) {
4481                                             BigCell = i;
4482                                             BigCellPos = CStackInd;
4483                                             BigCellSize = cls[i];
4484                                         }
4485                                         SplPos[SplCnt[k]] = i;
4486                                         i += value;
4487                                         if (i < ind1) {
4488                                             CStack[++CStackInd] = i;
4489                                             StackMarkers[i] = tv->stackmark;
4490                                             SAMETRACE_CHECK(TheTrace, TraceInd, i, TraceEnd)
4491                                         }
4492                                     }
4493                                     if ((StackMarkers[ind4] != tv->stackmark) && (BigCell != ind4)) {
4494                                         CStack[BigCellPos] = ind4;
4495                                         StackMarkers[BigCell] = 0;
4496                                         StackMarkers[ind4] = tv->stackmark;
4497                                     }
4498 
4499                                     /* Permute elements of the cell C */
4500                                     i = ind4;
4501                                     do {
4502                                         SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
4503                                     }
4504                                     while(++i < ind1);
4505 
4506                                     /* Reconstruct the cell C and update the inverse partition */
4507                                     newcell = ind4;
4508                                     i = ind4;
4509                                     ind2 = newcell+cls[newcell]-1;
4510                                     do {
4511                                         lab[i] = SplCnt[i];
4512                                         InvLab[lab[i]] = i;
4513                                         Part->inv[i] = newcell;
4514                                         if (i == ind2) {
4515                                             newcell = i+1;
4516                                             if (newcell < n) ind2 = newcell+cls[newcell]-1;
4517                                         }
4518                                     }
4519                                     while (++i < ind1);
4520 
4521                                     for (i = ind4, k = 0; k < SplCntInd; i+=cls[i], k++) {
4522                                         if (cls[i] == 1) {
4523                                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
4524                                         }
4525                                     }
4526 
4527                                 }
4528                             }
4529                             ind4 = ind1;
4530                         }
4531 
4532                         /* DENSE-DENSE CASE */
4533                         if (SplInd) {
4534                             SAMETRACE_CHECK(TheTraceSplNum, TraceCCInd, SplInd+3*n, &Traceccend)
4535                         }
4536                         else {
4537                             if (TraceCell) {
4538                                 return 0;
4539                             }
4540                         }
4541 
4542                     }
4543                 }
4544             }
4545         }
4546         while (weightend < iend1int);
4547     }  /* end while (CStackInd > 0) */
4548 
4549     for (i=SpineTL->trcstart; i < TraceInd; i++) {
4550         ind0 = TheTrace[i];
4551         longcode = MASHNONCOMM(longcode, Part->inv[ind0]);
4552         labi = lab[ind0];
4553         iend1int = TheGraph[labi].d;
4554         nghb = TheGraph[labi].e;
4555         for (j1int = 0; j1int < iend1int; ++j1int) {
4556             k = nghb[j1int];
4557             value = Part->inv[InvLab[k]];
4558             longcode = MASHCOMM(longcode, value);
4559         }
4560     }
4561 
4562     tv->augmented_cells = Part->cells - tv->augmented_cells;
4563 
4564     Part->code = Cand->code = CLEANUP(longcode);
4565     if ((Cand->code != SpineTL->part->code) || (TraceInd != *TraceEnd)) return FALSE;
4566     return TRUE;
4567 }
4568 
refine_tr(sparsegraph * sg,int * lab,int * ptn,int * numcells,int * code,TracesOptions * options_arg)4569 void refine_tr(sparsegraph *sg, int *lab, int *ptn, int *numcells, int *code, TracesOptions *options_arg) {
4570 
4571     const int n = sg->nv;
4572     const int m = SETWORDSNEEDED(n);
4573 
4574     int i, j, ord;
4575     Partition *CurrPart;
4576     Candidate *CurrCand;
4577     struct TracesVars tvar, *tv;
4578     struct TracesInfo tinf, *ti;
4579 
4580     if (n > (NAUTY_INFINITY-2))
4581     {
4582         fprintf(ERRFILE, "Traces: need n <= %d, but n=%d\n\n",
4583                 NAUTY_INFINITY-2, n);
4584         return;
4585     }
4586 
4587     Allocate_refine_Structures(n);
4588 
4589     tv = &tvar;
4590     ti = &tinf;
4591 
4592     tv->options = options_arg;
4593     tv->mark = tv->stackmark = NAUTY_INFINITY-1;
4594     tv->maxdeg = 0;
4595     tv->mindeg = n;
4596 
4597     outfile = (tv->options->outfile == NULL ? stdout : tv->options->outfile);
4598 
4599     for (i = 0; i < n; i++) {
4600         IDENTITY_PERM[i] = i;
4601     }
4602 
4603     copy_sg_structure(&redgraph, sg);
4604 
4605     tv->graph = &redgraph;
4606     if (tv->options->weighted) {
4607         tv->graph->w = malloc(tv->graph->wlen*sizeof(int));
4608         if (tv->graph->w == NULL) {
4609             fprintf(ERRFILE, "\nError, memory not allocated.\n");
4610             exit(1);
4611         }
4612         memcpy(tv->graph->w, sg->w, tv->graph->wlen*sizeof(int));
4613     }
4614     memcpy(tv->graph->e, sg->e, tv->graph->elen*sizeof(int));
4615 
4616     for (i=0; i<n; i++) {
4617         TheGraph[i].d = sg->d[i];
4618         if (TheGraph[i].d > tv->maxdeg) {
4619             tv->maxdeg = TheGraph[i].d;
4620         }
4621         if (TheGraph[i].d < tv->mindeg) {
4622             tv->mindeg = TheGraph[i].d;
4623         }
4624         TheGraph[i].e = tv->graph->e + sg->v[i];
4625         if (sg->w)
4626             TheGraph[i].w = tv->graph->w + sg->v[i];
4627         else
4628             TheGraph[i].w = NULL;
4629         TheGraph[i].one = FALSE;
4630     }
4631 
4632     ord = 0;
4633 
4634     /*----------- WEIGHTS --------------*/
4635     if (tv->options->weighted) {
4636         WeightCodes(n);
4637         ord = trie_classify(n,tv);
4638     }
4639     /*----------------------------------*/
4640 
4641     if ((tv->maxdeg == tv->mindeg) && (ord == 0)) ti->regular = TRUE; else ti->regular = FALSE;
4642 
4643     /* The graph is sparse? */
4644     if (sg->nde < n || sg->nde / n < n / (sg->nde / n)) {
4645         ti->thegraphisparse = TRUE;
4646     }
4647     else {
4648         ti->thegraphisparse = FALSE;
4649     }
4650 
4651     /* Initialize candidate, partition, cells, orbits */
4652     CurrCand = NewCandidate(n, &GarbList, TRUE);
4653     CurrPart = NewPartition(n);
4654     memset(CurrPart->inv, 0, n*sizeof(int));
4655 
4656     CurrCand->singcode = 0;
4657 
4658     if (ti->regular) {
4659         memcpy(CurrCand->lab, lab, n*sizeof(int));
4660         CurrPart->cells = 0;
4661         j = 0;
4662         for (i = 0; i < n; i++) {
4663             if (j) CurrPart->inv[i] = j;
4664             CurrCand->invlab[CurrCand->lab[i]] = i;
4665             if (!ptn[i]) {
4666                 CurrPart->cls[j] = i-j+1;
4667                 if (CurrPart->cls[j] == 1) {
4668                     CurrCand->singcode = MASHCOMM(CurrCand->singcode, CurrCand->lab[j]);
4669                 }
4670                 TheTrace[CurrPart->cells++] = j;
4671                 j = i+1;
4672             }
4673         }
4674     } else {
4675         if (tv->options->weighted) {
4676             CurrPart->cells = traces_vertexclass_refine (n, lab, ptn, CurrCand, CurrPart, WeightsSeq);
4677         }
4678         else {
4679             CurrPart->cells = traces_vertexclass_refine (n, lab, ptn, CurrCand, CurrPart, sg->d);
4680         }
4681     }
4682 
4683     /* First refinement */
4684     refine_tr_refine(CurrCand, n, CurrPart, tv, ti);
4685 
4686     for (i = CurrPart->cls[0]; i < n; i+=CurrPart->cls[i]) {
4687         ptn[i-1] = 0;
4688     }
4689     ptn[n-1] = 0;
4690 
4691     memcpy(lab, CurrCand->lab, n*sizeof(int));
4692     *code = CurrCand->code;
4693     *numcells = CurrPart->cells;
4694 
4695     FREECAND(CurrCand)
4696     FREEPART(CurrPart)
4697 
4698     if (tv->graph != sg) {
4699         SG_FREE(redgraph);
4700     }
4701 
4702 #if !MAXN
4703     DYNFREE(CStack, CStack_sz);
4704     DYNFREE(IDENTITY_PERM, IDENTITY_PERM_sz);
4705     DYNFREE(Markers, Markers_sz);
4706     DYNFREE(MarkHitVtx, MarkHitVtx_sz);
4707     DYNFREE(TreeMarkers, TreeMarkers_sz);
4708     DYNFREE(NghCounts, NghCounts_sz);
4709     DYNFREE(Singletons, Singletons_sz);
4710     DYNFREE(SplPos, SplPos_sz);
4711     DYNFREE(SplCls, SplCls_sz);
4712     DYNFREE(SplCnt, SplCnt_sz);
4713     DYNFREE(StackMarkers, StackMarkers_sz);
4714     DYNFREE(TheTrace, TheTrace_sz);
4715     DYNFREE(TheTraceSteps, TheTraceSteps_sz);
4716     DYNFREE(TheTraceCC, TheTraceCC_sz);
4717     DYNFREE(TheTraceSplNum, TheTraceSplNum_sz);
4718     DYNFREE(WeightsSeq, WeightsSeq_sz);
4719     DYNFREE(WorkArray1, WorkArray1_sz);
4720     DYNFREE(WorkArray2, WorkArray2_sz);
4721     DYNFREE(WorkArray3, WorkArray3_sz);
4722     DYNFREE(WorkArray4, WorkArray4_sz);
4723     DYNFREE(WorkArray5, WorkArray5_sz);
4724     DYNFREE(TreeStack, TreeStack_sz);
4725     DYNFREE(Spine, Spine_sz);
4726     DYNFREE(TrieArray, TrieArray_sz);
4727     DYNFREE(TheGraph, TheGraph_sz);
4728 #endif
4729 }
4730 
refine_tr_refine(Candidate * Cand,int n,Partition * Part,struct TracesVars * tv,struct TracesInfo * ti)4731 void refine_tr_refine(Candidate *Cand,
4732                      int n,
4733                      Partition *Part,
4734                      struct TracesVars* tv,
4735                      struct TracesInfo *ti) {
4736 
4737     int i, j, k, jk, sc, ind0, ind1, ind2, ind3, ind4, labi;
4738     int value, iend, newcell;
4739     int HitClsInd, SplInd, SplCntInd, CStackInd, TraceInd, TraceCCInd, TraceStepsInd;
4740     int j1int, iend1int;
4741     unsigned int longcode;
4742     int newtrace = FALSE;
4743     int Sparse = TRUE;
4744     int *lab, *cls, *InvLab, *TracePos, *SplitCell, *LabCell, TraceEnd, Traceccend, Tracestpend;
4745     int BigCell, BigCellPos, BigCellSize;
4746     boolean TraceCell = FALSE;
4747     int *nghb;
4748     const int variation = 0;
4749     int currentweight, weightstart, weightend, currentcell, currentsize;
4750 
4751     HitClsInd = 0;
4752     if (tv->stackmark > (NAUTY_INFINITY-2)) {
4753         memset(StackMarkers, 0, n*sizeof(int));
4754         tv->stackmark = 0;
4755     }
4756     tv->stackmark++;
4757 
4758     lab = Cand->lab;
4759     InvLab = Cand->invlab;
4760     cls = Part->cls;
4761 
4762     UPDATEMIN(Part->active, n-1);
4763     memcpy(CStack+1, TheTrace, (Part->cells)*sizeof(int));
4764     CStackInd = Part->cells;
4765 
4766     for (i = 1; i <= CStackInd; i++) {
4767         StackMarkers[CStack[i]] = tv->stackmark;
4768     }
4769 
4770     longcode = Part->cells;
4771     newtrace = TRUE;
4772     while (CStackInd > 0) {
4773 
4774         weightend = 0;
4775 
4776         if (tv->mark > (NAUTY_INFINITY-2)) {
4777             memset(Markers, 0, n*sizeof(int));
4778             memset(MarkHitVtx, 0, n*sizeof(int));
4779             tv->mark = 0;
4780         }
4781         tv->mark++;
4782 
4783         if (Part->cells == n) break;
4784 
4785         k = Select_from_CStack(cls, CStackInd);
4786 
4787         currentcell = CStack[k];
4788         currentsize = currentcell+cls[currentcell];
4789         CStack[k] = CStack[CStackInd--];
4790         StackMarkers[currentcell] = 0;
4791 
4792         labi = lab[currentcell];
4793         iend1int = TheGraph[labi].d;
4794         nghb =  TheGraph[labi].e;
4795 
4796         do {
4797 
4798             ind0 = currentcell;
4799             ind2 = currentsize;
4800             weightstart = weightend;
4801 
4802             if (tv->options->weighted) {
4803                 currentweight = (TheGraph[labi].w)[weightstart];
4804                 while ((iend1int > weightend) && ((TheGraph[labi].w)[weightend] == currentweight)) {
4805                     weightend++;
4806                 }
4807             } else {
4808                 weightend = TheGraph[labi].d;
4809             }
4810 
4811             /* Analysis of occurrences of neighbors of the current cell */
4812             /* The list of cells with neighbors in the current cell is  built */
4813             if (cls[ind0] == 1) {            /* SINGLETON CURRENT CELL CASE */
4814 
4815                 /* NEIGHCOUNT_SING_MULT */
4816                 HitClsInd = 0;
4817                 for (j1int = weightstart; j1int < weightend; ++j1int) {
4818                     k = nghb[j1int];
4819                     value = Part->inv[InvLab[k]];
4820                     if (cls[value] > 1) {
4821                         if (Markers[value] != tv->mark) {
4822                             HitCls[HitClsInd++] = value;
4823                             Markers[value] = tv->mark;
4824                             ElmHitCll[value] = value;
4825                         }
4826                         HitVtx[ElmHitCll[value]++] = k;
4827                     } else {
4828                         switch (variation) {
4829                             case 1:
4830                                 longcode = MASHCOMM(longcode, value);
4831                                 break;
4832                             default:
4833                                 break;
4834                         }
4835                     }
4836                 }
4837                 /* end NEIGHCOUNT_SING_MULT */
4838 
4839                 tv->mark++;
4840                 FIND_SPLIT_CELLS;
4841 
4842                 /* SINGLETON CC CASE */
4843                 if (SplInd) {
4844 
4845                     /* Sorting the cells to be split */
4846                     sort_Split_Array(SplCls, SplInd);
4847 
4848                     for (j = 0; j < SplInd; j++) {
4849                         ind1 = SplCls[j];
4850                         i = ind1+cls[ind1]-ElmHitCll[ind1];
4851                     }
4852 
4853                     /* REARRANGE THE CELLS */
4854                     for (j = 0; j < SplInd; j++) {
4855                         /* REARRANGE_CELLS */
4856                         ind1 = SplCls[j];
4857                         cls[ind1] = cls[ind1]-ElmHitCll[ind1];
4858                         newcell = ind1+cls[ind1];
4859                         cls[newcell] = ElmHitCll[ind1];
4860                         Part->cells++;
4861                         if (StackMarkers[ind1] != tv->stackmark) {
4862                             if (cls[newcell] < cls[ind1]) {
4863                                 CStack[++CStackInd] = newcell;
4864                                 StackMarkers[newcell] = tv->stackmark;
4865                             }
4866                             else {
4867                                 CStack[++CStackInd] = ind1;
4868                                 StackMarkers[ind1] = tv->stackmark;
4869                             }
4870                         }
4871                         else {
4872                             CStack[++CStackInd] = newcell;
4873                             StackMarkers[newcell] = tv->stackmark;
4874                         }
4875                         SplitCell = HitVtx+ind1;
4876                         ind3 = cls[newcell];
4877                         LabCell = lab+newcell;
4878                         for (jk = 0; jk < ind3; jk++) {
4879                             k = SplitCell[jk];
4880                             i = LabCell[jk];
4881                             Part->inv[newcell+jk] = newcell;
4882                             lab[InvLab[k]] = i;
4883                             InvLab[i] = InvLab[k];
4884                             LabCell[jk] = k;
4885                             InvLab[k] = newcell+jk;
4886                         }
4887                         /* END REARRANGE_CELLS */
4888 
4889                     }
4890                 }
4891                 else {
4892                 }
4893             }
4894             else {
4895                 if (ti->thegraphisparse) {
4896 
4897                     /* NEIGHCOUNT_SPARSE_MULT */
4898                     HitClsInd = 0;
4899                     if (cls[ind0] != n) {
4900                         for (i = ind0; i < ind2; i++) {
4901                             labi = lab[i];
4902                             nghb = TheGraph[labi].e;
4903                             for (j = weightstart; j < weightend; j++) {
4904                                 k = nghb[j];
4905                                 if (MarkHitVtx[k] == tv->mark) {
4906                                     NghCounts[k]++;
4907                                 }
4908                                 else {
4909                                     value = Part->inv[InvLab[k]];
4910                                     if (cls[value] > 1) {
4911                                         MarkHitVtx[k] = tv->mark;
4912                                         NghCounts[k] = 1;
4913                                         if (Markers[value] != tv->mark) {
4914                                             HitCls[HitClsInd++] = value;
4915                                             Markers[value] = tv->mark;
4916                                             HitVtx[value] = k;
4917                                             ElmHitCll[value] = 1;
4918                                         }
4919                                         else {
4920                                             HitVtx[value+ElmHitCll[value]++] = k;
4921                                         }
4922                                     }
4923                                     else {
4924                                         switch (variation) {
4925                                             case 1:
4926                                                 longcode = MASHCOMM(longcode, value);
4927                                                 break;
4928                                             default:
4929                                                 break;
4930                                         }
4931                                     }
4932                                 }
4933                             }
4934                         }
4935                     }
4936                     /* End NEIGHCOUNT_SPARSE_MULT */
4937 
4938                     tv->mark++;
4939 
4940                     SplInd = 0;
4941                     SplCls[0] = n;
4942                     for (j = 0; j < HitClsInd; j++) {
4943                         ind1 = HitCls[j];
4944                         if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < cls[ind1])) {
4945                             SplCls[SplInd++] = ind1;
4946                         }
4947                         else {
4948                             ind2 = ind1+cls[ind1];
4949                             value = NghCounts[lab[ind1++]];
4950                             for (i = ind1; i < ind2; i++)
4951                             {
4952                                 if (NghCounts[lab[i]] != value)
4953                                 {
4954                                     SplCls[SplInd++] = HitCls[j];
4955                                     break;
4956                                 }
4957                             }
4958                         }
4959                     }
4960 
4961                     /* SPARSE CASE */
4962                     if (SplInd) {
4963 
4964                         /* Sorting the cells to be split */
4965                         sort_Split_Array(SplCls, SplInd);
4966 
4967                         for (sc = 0; sc < SplInd; sc++) {    /* For each cell C to be split */
4968                             ind0 = SplCls[sc];
4969                             ind1 = ind0 + cls[ind0];
4970                             SplCntInd = 0;
4971                             if (ElmHitCll[ind0] < cls[ind0]) {
4972                                 SplCnt[SplCntInd++] = 0;
4973                                 SplPos[0] = cls[ind0] - ElmHitCll[ind0];
4974                             }
4975 
4976                             /* According to the numbers of neighbors of C into the current cell */
4977                             /* compute how many vertices in C will be placed into the same new cell */
4978                             iend = ind0 + ElmHitCll[ind0];
4979                             for (i = ind0; i < iend; i++) {
4980                                 value = NghCounts[HitVtx[i]];
4981                                 if (Markers[value] != tv->mark) {
4982                                     Markers[value] = tv->mark;
4983                                     SplCnt[SplCntInd++] = value;
4984                                     SplPos[value] = 1;
4985                                 }
4986                                 else {
4987                                     SplPos[value]++;
4988                                 }
4989                             }
4990                             tv->mark++;
4991 
4992                             sort_Split_Array(SplCnt,SplCntInd);
4993                             Part->cells += SplCntInd-1;
4994 
4995                             /* Split the cell C and update the information for sizes of new cells */
4996                             /* Put the new cells into the stack */
4997                             i = ind0;
4998                             if (StackMarkers[i] != tv->stackmark) {
4999                                 BigCellSize = 0;
5000                             }
5001                             for (k = 0; k < SplCntInd; k++) {
5002                                 value = SplPos[SplCnt[k]];
5003                                 cls[i] = value;
5004                                 if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
5005                                     BigCell = i;
5006                                     BigCellPos = CStackInd;
5007                                     BigCellSize = cls[i];
5008                                 }
5009                                 SplPos[SplCnt[k]] = i;
5010                                 i += value;
5011                                 if (i < ind1) {
5012                                     CStack[++CStackInd] = i;
5013                                     StackMarkers[i] = tv->stackmark;
5014                                 }
5015                             }
5016 
5017                             if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
5018                                 CStack[BigCellPos] = ind0;
5019                                 StackMarkers[BigCell] = 0;
5020                                 StackMarkers[ind0] = tv->stackmark;
5021                             }
5022                             /* Permute elements of the cell C */
5023                             iend = ind0 + ElmHitCll[ind0];
5024                             for (i = ind0; i < iend; i++) {
5025                                 value = HitVtx[i];
5026                                 j = SplPos[NghCounts[value]]++; /* where HitVtx[i] goes */
5027                                 k = InvLab[value];                /* where HitVtx[i] is in lab */
5028                                 lab[k] = lab[j];
5029                                 lab[j] = value;
5030                                 InvLab[value] = j;
5031                                 InvLab[lab[k]] = k;
5032                                 NghCounts[value] = 0;
5033                             }
5034 
5035                             /* Reconstruct the cell C and update the inverse partition */
5036                             newcell = ind1 - ElmHitCll[ind0];
5037                             i = newcell;
5038                             ind2 = newcell+cls[newcell]-1;
5039                             do {
5040                                 Part->inv[i] = newcell;
5041                                 if (i == ind2) {
5042                                     newcell = i+1;
5043                                     if (newcell < n) ind2 = newcell+cls[newcell]-1;
5044                                 }
5045                             }
5046                             while (++i < ind1);
5047                         }
5048                     }
5049                 }
5050                 else {
5051                     if (TheGraph[lab[ind0]].d > n/cls[ind0]) {
5052                         Sparse = FALSE;
5053                     }
5054                     else {
5055                         Sparse = TRUE;
5056                     }
5057                     Sparse = TRUE;
5058                     if (Sparse) {
5059                         /* Counting occurrences of neighbors of the current cell */
5060                         /* The list of cells with neighbors in the current cell is also built */
5061                         if (cls[ind0] == n) {
5062                             for (i = 0; i < n; i++) {
5063                                 NghCounts[i] = TheGraph[i].d;
5064                             }
5065                             HitCls[0] = 0;
5066                             HitClsInd = 1;
5067                         }
5068                         else {
5069                             memset(NghCounts, 0, n*sizeof(int));
5070 
5071                             /* NEIGHCOUNT_DENSE_SPARSE_MULT */
5072                             HitClsInd = 0;
5073                             for (i = ind0; i < ind2; i++) {
5074                                 labi = lab[i];
5075                                 nghb =  TheGraph[labi].e;
5076                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
5077                                     k = nghb[j1int];
5078                                     (NghCounts[k])++;
5079                                     value = Part->inv[InvLab[k]];
5080                                     if (Markers[value] != tv->mark) {
5081                                         if (cls[value] > 1) HitCls[HitClsInd++] = value;
5082                                         Markers[value] = tv->mark;
5083                                     }
5084                                 }
5085                             }
5086                             /* End NEIGHCOUNT_DENSE_SPARSE_MULT */
5087 
5088                         }
5089 
5090                         tv->mark++;
5091 
5092 
5093                         SplInd = 0;
5094                         for (j = 0; j < HitClsInd; j++) {
5095                             ind1 = HitCls[j];
5096                             ind2 = ind1+cls[ind1];
5097                             value = NghCounts[lab[ind1++]];
5098                             for (i = ind1; i < ind2; i++)
5099                             {
5100                                 if (NghCounts[lab[i]] != value)
5101                                 {
5102                                     SplCls[SplInd++] = HitCls[j];
5103                                     break;
5104                                 }
5105                             }
5106                         }
5107 
5108                         /* DENSE-SPARSE CASE */
5109                         if (SplInd) {
5110 
5111                             /* Sorting the cells to be split */
5112                             sort_Split_Array(SplCls, SplInd);
5113 
5114                             for (j = 0; j < SplInd; j++) {    /* For each cell C to be split */
5115                                 ind0 = SplCls[j];
5116                                 ind1 = ind0+cls[ind0];
5117                                 SplCntInd = 0;
5118 
5119                                 /* According to the numbers of neighbors of C into the current cell */
5120                                 /* compute how many vertices in C will be placed into the same new cell */
5121                                 for (i = ind0; i < ind1; i++) {
5122                                     value = NghCounts[lab[i]];
5123                                     if (Markers[value] != tv->mark) {
5124                                         Markers[value] = tv->mark;
5125                                         SplCnt[SplCntInd++] = value;
5126                                         SplPos[value] = 1;
5127                                     }
5128                                     else {
5129                                         SplPos[value]++;
5130                                     }
5131                                 }
5132                                 tv->mark++;
5133 
5134                                 /* Sort the values deriving from the previous step */
5135                                 sort_Split_Array(SplCnt, SplCntInd);
5136                                 Part->cells += SplCntInd-1;
5137 
5138                                 /* Split the cell C and update the information for sizes of new cells */
5139                                 /* Put the new cells into the stack */
5140                                 i = ind0;
5141                                 if (StackMarkers[i] != tv->stackmark) {
5142                                     BigCellSize = 0;
5143                                 }
5144                                 for (k = 0; k < SplCntInd; k++) {
5145                                     value = SplPos[SplCnt[k]];
5146                                     cls[i] = value;
5147 
5148                                     if ((StackMarkers[ind0] != tv->stackmark) && (value > BigCellSize)) {
5149                                         BigCell = i;
5150                                         BigCellPos = CStackInd;
5151                                         BigCellSize = cls[i];
5152                                     }
5153                                     SplPos[SplCnt[k]] = i;
5154                                     i += value;
5155                                     if (i < ind1) {
5156                                         CStack[++CStackInd] = i;
5157                                         StackMarkers[i] = tv->stackmark;
5158                                     }
5159                                 }
5160 
5161                                 if ((StackMarkers[ind0] != tv->stackmark) && (BigCell != ind0)) {
5162                                     CStack[BigCellPos] = ind0;
5163                                     StackMarkers[BigCell] = 0;
5164                                     StackMarkers[ind0] = tv->stackmark;
5165                                 }
5166 
5167                                 /* Permute elements of the cell C */
5168                                 i = ind0;
5169                                 do {
5170                                     SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
5171                                 }
5172                                 while(++i < ind1);
5173 
5174                                 /* Reconstruct the cell C and update the inverse partition */
5175                                 newcell = ind0;
5176                                 i = ind0;
5177                                 ind2 = newcell+cls[newcell]-1;
5178                                 do {
5179                                     lab[i] = SplCnt[i];
5180                                     InvLab[lab[i]] = i;
5181 
5182                                     Part->inv[i] = newcell;
5183                                     if (i == ind2) {
5184                                         newcell = i+1;
5185                                         if (newcell < n) ind2 = newcell+cls[newcell]-1;
5186                                     }
5187                                 }
5188                                 while (++i < ind1);
5189                             }
5190                         }
5191                     }
5192                     else {
5193                         if (cls[ind0] == n) {
5194                             for (i = 0; i < n; i++) {
5195                                 NghCounts[i] = TheGraph[i].d;
5196                             }
5197                         }
5198                         else {
5199                             memset(NghCounts, 0, n*sizeof(int));
5200 
5201                             /* NEIGHCOUNT_DENSE_DENSE_MULT */
5202                             for (i = ind0; i < ind2; i++) {
5203                                 labi = lab[i];
5204                                 nghb = TheGraph[labi].e;
5205                                 for (j1int = weightstart; j1int < weightend; ++j1int) {
5206                                     k = nghb[j1int];
5207                                     (NghCounts[k])++;
5208                                 }
5209                             }
5210                             /* End NEIGHCOUNT_DENSE_DENSE_MULT */
5211 
5212                         }
5213                         SplInd = 0;
5214                         ind4 = 0;
5215                         while (ind4 < n) {    /* For each cell C with size(C) > 1 */
5216                             ind1 = ind4+cls[ind4];
5217                             if (cls[ind4] > 1) {
5218 
5219 
5220                                 /* Determine whether C must be split */
5221                                 SplCntInd = 0;
5222                                 value = NghCounts[lab[ind4]];
5223                                 for (i = ind4+1; i < ind1; i++) {
5224                                     if (NghCounts[lab[i]] != value)
5225                                     {
5226                                         SplInd++;
5227                                         Markers[value] = tv->mark;
5228                                         SplCnt[SplCntInd++] = value;
5229                                         SplPos[value] = i-ind4;
5230                                         do {
5231                                             value = NghCounts[lab[i++]];
5232                                             if (Markers[value] != tv->mark) {
5233                                                 Markers[value] = tv->mark;
5234                                                 SplCnt[SplCntInd++] = value;
5235                                                 SplPos[value] = 1;
5236                                             }
5237                                             else {
5238                                                 SplPos[value]++;
5239                                             }
5240                                         }
5241                                         while(i != ind1);
5242                                         break;
5243                                     }
5244                                 }
5245                                 tv->mark++;
5246 
5247                                 if (SplCntInd) {
5248 
5249                                     /* Sort the values deriving from the previous step */
5250                                     sort_Split_Array(SplCnt, SplCntInd);
5251                                     Part->cells += SplCntInd-1;
5252 
5253                                     /* Split the cell C and update the information for sizes of new cells */
5254                                     /* Put the new cells into the stack */
5255                                     i = ind4;
5256                                     if (StackMarkers[i] != tv->stackmark) {
5257                                         BigCellSize = 0;
5258                                     }
5259                                     for (k = 0; k < SplCntInd; k++) {
5260                                         value = SplPos[SplCnt[k]];
5261                                         cls[i] = value;
5262 
5263                                         if ((StackMarkers[ind4] != tv->stackmark) && (value > BigCellSize)) {
5264                                             BigCell = i;
5265                                             BigCellPos = CStackInd;
5266                                             BigCellSize = cls[i];
5267                                         }
5268                                         SplPos[SplCnt[k]] = i;
5269                                         i += value;
5270                                         if (i < ind1) {
5271                                             CStack[++CStackInd] = i;
5272                                             StackMarkers[i] = tv->stackmark;
5273                                         }
5274                                     }
5275                                     if ((StackMarkers[ind4] != tv->stackmark) && (BigCell != ind4)) {
5276                                         CStack[BigCellPos] = ind4;
5277                                         StackMarkers[BigCell] = 0;
5278                                         StackMarkers[ind4] = tv->stackmark;
5279                                     }
5280 
5281                                     /* Permute elements of the cell C */
5282                                     i = ind4;
5283                                     do {
5284                                         SplCnt[SplPos[NghCounts[lab[i]]]++] = lab[i];
5285                                     }
5286                                     while(++i < ind1);
5287 
5288                                     /* Reconstruct the cell C and update the inverse partition */
5289                                     newcell = ind4;
5290                                     i = ind4;
5291                                     ind2 = newcell+cls[newcell]-1;
5292                                     do {
5293                                         lab[i] = SplCnt[i];
5294                                         InvLab[lab[i]] = i;
5295                                         Part->inv[i] = newcell;
5296                                         if (i == ind2) {
5297                                             newcell = i+1;
5298                                             if (newcell < n) ind2 = newcell+cls[newcell]-1;
5299                                         }
5300                                     }
5301                                     while (++i < ind1);
5302                                 }
5303                             }
5304                             ind4 = ind1;
5305                         }
5306 
5307                         /* DENSE-DENSE CASE */
5308                     }
5309                 }
5310             }
5311         }
5312         while (weightend < iend1int);
5313     }  /* end while (CStackInd > 0) */
5314 
5315     Cand->code = CLEANUP(longcode);
5316     for (ind0=Part->cls[0]; ind0 < n; ind0+=Part->cls[ind0]) {
5317         longcode = MASHNONCOMM(longcode, Part->inv[ind0]);
5318         labi = lab[ind0];
5319         iend1int = TheGraph[labi].d;
5320         nghb = TheGraph[labi].e;
5321         for (j1int = 0; j1int < iend1int; ++j1int) {
5322             k = nghb[j1int];
5323             value = Part->inv[InvLab[k]];
5324             longcode = MASHCOMM(longcode, value);
5325         }
5326     }
5327     Part->code = Cand->code = CLEANUP(longcode);
5328     return;
5329 }
5330 
Allocate_Traces_Structures(int n)5331 void Allocate_Traces_Structures(int n) {
5332 #if !MAXN
5333     DYNALLOC1(int, AUTPERM, AUTPERM_sz, n, "Traces");
5334     DYNALLOC1(int, BreakSteps, BreakSteps_sz, n, "Traces");
5335     DYNALLOC1(int, CurrOrbSize, CurrOrbSize_sz, n, "Traces");
5336     DYNALLOC1(int, CurrRefCells, CurrRefCells_sz, n, "Traces");
5337     DYNALLOC1(boolean, Diff, Diff_sz, n, "Traces");
5338     DYNALLOC1(int, CStack, CStack_sz, n, "Traces");
5339     DYNALLOC1(boolean, Factorials, Factorials_sz, n, "Traces");
5340     DYNALLOC1(int, fix, fix_sz, n, "Traces");
5341     DYNALLOC1(int, IDENTITY_PERM, IDENTITY_PERM_sz, n, "Traces");
5342     DYNALLOC1(int, Markers, Markers_sz, n, "Traces");
5343     DYNALLOC1(int, TreeMarkers, TreeMarkers_sz, n, "Traces");
5344     DYNALLOC1(int, AutMarkers, AutMarkers_sz, n, "Traces");
5345     DYNALLOC1(int, MarkHitVtx, MarkHitVtx_sz, n, "Traces");
5346     DYNALLOC1(int, MultRefCells, MultRefCells_sz, n, "Traces");
5347     DYNALLOC1(int, NghCounts, NghCounts_sz, n, "Traces");
5348     DYNALLOC1(int, OrbSize, OrbSize_sz, n, "Traces");
5349     DYNALLOC1(int, OrbList, OrbList_sz, n, "Traces");
5350     DYNALLOC1(pair, PrmPairs, PrmPairs_sz, n, "Traces");
5351     DYNALLOC1(int, TempOrbList, TempOrbList_sz, n, "Traces");
5352     DYNALLOC1(int, RefCells, RefCells_sz, n, "Traces");
5353     DYNALLOC1(int, Singletons, Singletons_sz, n, "Traces");
5354     DYNALLOC1(int, SplCls, SplCls_sz, n, "Traces");
5355     DYNALLOC1(int, SplCnt, SplCnt_sz, n, "Traces");
5356     DYNALLOC1(int, SplPos, SplPos_sz, n, "Traces");
5357     DYNALLOC1(int, StackMarkers, StackMarkers_sz, n, "Traces");
5358     DYNALLOC1(int, TheTrace, TheTrace_sz, n+10, "Traces");
5359     DYNALLOC1(int, TheTraceCC, TheTraceCC_sz, n, "Traces");
5360     DYNALLOC1(int, TheTraceSplNum, TheTraceSplNum_sz, n, "Traces");
5361     DYNALLOC1(int, TheTraceSteps, TheTraceSteps_sz, n+10, "Traces");
5362     DYNALLOC1(int, TEMPLAB, TEMPLAB_sz, n, "Traces");
5363     DYNALLOC1(int, TEMPINVLAB, TEMPINVLAB_sz, n, "Traces");
5364     DYNALLOC1(int, WeightsSeq, WeightsSeq_sz, n, "Traces");
5365     DYNALLOC1(int, WorkArray, WorkArray_sz, n, "Traces");
5366     DYNALLOC1(int, WorkArray0, WorkArray0_sz, n, "Traces");
5367     DYNALLOC1(int, WorkArray1, WorkArray1_sz, n, "Traces");
5368     DYNALLOC1(int, WorkArray2, WorkArray2_sz, n, "Traces");
5369     DYNALLOC1(int, WorkArray3, WorkArray3_sz, n, "Traces");
5370     DYNALLOC1(int, WorkArray4, WorkArray4_sz, n, "Traces");
5371     DYNALLOC1(int, WorkArray5, WorkArray5_sz, n, "Traces");
5372     DYNALLOC1(int, WorkArray6, WorkArray6_sz, n, "Traces");
5373     DYNALLOC1(int, WorkArray7, WorkArray7_sz, n, "Traces");
5374     DYNALLOC1(int, TreeStack, TreeStack_sz, n, "Traces");
5375     DYNALLOC1(TracesSpine, Spine, Spine_sz, n, "Traces");
5376     DYNALLOC1(trie*, TrieArray, TrieArray_sz, n, "Traces");
5377     DYNALLOC1(grph_strct, TheGraph, TheGraph_sz, n, "Traces");
5378     DYNALLOC1(ExpPathInfo, EPCodes, EPCodes_sz, n, "Traces");
5379 #endif
5380     return;
5381 }
5382 
Allocate_refine_Structures(int n)5383 void Allocate_refine_Structures(int n) {
5384 #if !MAXN
5385     DYNALLOC1(int, CStack, CStack_sz, n, "refine_tr");
5386     DYNALLOC1(int, IDENTITY_PERM, IDENTITY_PERM_sz, n, "refine_tr");
5387     DYNALLOC1(int, Markers, Markers_sz, n, "refine_tr");
5388     DYNALLOC1(int, MarkHitVtx, MarkHitVtx_sz, n, "refine_tr");
5389     DYNALLOC1(int, TreeMarkers, TreeMarkers_sz, n, "refine_tr");
5390     DYNALLOC1(int, NghCounts, NghCounts_sz, n, "refine_tr");
5391     DYNALLOC1(int, Singletons, Singletons_sz, n, "refine_tr");
5392     DYNALLOC1(int, SplPos, SplPos_sz, n, "refine_tr");
5393     DYNALLOC1(int, SplCls, SplCls_sz, n, "refine_tr");
5394     DYNALLOC1(int, SplCnt, SplCnt_sz, n, "refine_tr");
5395     DYNALLOC1(int, StackMarkers, StackMarkers_sz, n, "refine_tr");
5396     DYNALLOC1(int, TheTrace, TheTrace_sz, n+10, "refine_tr");
5397     DYNALLOC1(int, TheTraceSteps, TheTraceSteps_sz, n+10, "refine_tr");
5398     DYNALLOC1(int, TheTraceCC, TheTraceCC_sz, n, "refine_tr");
5399     DYNALLOC1(int, TheTraceSplNum, TheTraceSplNum_sz, n, "refine_tr");
5400     DYNALLOC1(int, WeightsSeq, WeightsSeq_sz, n, "refine_tr");
5401     DYNALLOC1(int, WorkArray1, WorkArray1_sz, n, "refine_tr");
5402     DYNALLOC1(int, WorkArray2, WorkArray2_sz, n, "refine_tr");
5403     DYNALLOC1(int, WorkArray3, WorkArray3_sz, n, "refine_tr");
5404     DYNALLOC1(int, WorkArray4, WorkArray4_sz, n, "refine_tr");
5405     DYNALLOC1(int, WorkArray5, WorkArray5_sz, n, "refine_tr");
5406     DYNALLOC1(int, TreeStack, TreeStack_sz, n, "refine_tr");
5407     DYNALLOC1(TracesSpine, Spine, Spine_sz, n, "refine_tr");
5408     DYNALLOC1(trie*, TrieArray, TrieArray_sz, n, "refine_tr");
5409     DYNALLOC1(grph_strct, TheGraph, TheGraph_sz, n, "refine_tr");
5410 #endif
5411 
5412 #define HitCls WorkArray2
5413 #define HitVtx WorkArray3
5414 #define ElmHitCll WorkArray5
5415     return;
5416 }
5417 
NewCandidate(int n,Candidate ** GarbList,int Mrk)5418 struct Candidate *NewCandidate(int n, Candidate **GarbList, int Mrk) {
5419     struct Candidate *Cand;
5420 
5421     if (*GarbList) {
5422         Cand = *GarbList;
5423         *GarbList = (*GarbList)->next;
5424     }
5425     else {
5426         Cand = malloc(sizeof(*Cand));
5427         if (Cand == NULL) {
5428             fprintf(ERRFILE, "\nError, memory not allocated.\n");
5429             exit(1);
5430         }
5431         Cand->lab = malloc(n*sizeof(*Cand->lab));
5432         if (Cand->lab == NULL) {
5433             fprintf(ERRFILE, "\nError, memory not allocated.\n");
5434             exit(1);
5435         }
5436         Cand->invlab = malloc(n*sizeof(*Cand->invlab));
5437         if (Cand->invlab == NULL) {
5438             fprintf(ERRFILE, "\nError, memory not allocated.\n");
5439             exit(1);
5440         }
5441     }
5442     Cand->do_it = Mrk;
5443     Cand->indnum = 0;
5444     Cand->code = 0;
5445     Cand->next = NULL;
5446     Cand->stnode = NULL;
5447     Cand->sortedlab = FALSE;
5448     return Cand;
5449 }
5450 
Check_degree_one(sparsegraph * sg,Candidate * Cand,Partition * Part,int n)5451 int Check_degree_one(sparsegraph *sg, Candidate *Cand, Partition *Part, int n) {
5452 
5453     int i;
5454 
5455     for (i=0; i<n; i += Part->cls[i]) {
5456         if (sg->d[Cand->lab[i]] == 1) {
5457             return TRUE;
5458         }
5459     }
5460     return FALSE;
5461 }
5462 
CheckForAutomorphisms(Candidate * CurrCand,Candidate * NextCand,struct TracesVars * tv,struct TracesInfo * ti,int m,int n,Partition * Part)5463 int CheckForAutomorphisms(Candidate *CurrCand, Candidate *NextCand,
5464                           struct TracesVars* tv, struct TracesInfo* ti,
5465                           int m, int n, Partition* Part) {
5466     Candidate *CheckAutList;
5467     int i, j, k, tgt_level, numtemporbits;
5468     int CheckLevel, CheckLevelEnd;
5469     int temp, tmp, tmp1, arg, arg1, val, val1;
5470     searchtrie *TrieCandFrom, *TrieCheckFrom;
5471 
5472     CheckLevel = 0;
5473     CheckLevelEnd = 0;
5474     temp = 0;
5475     tv->gotonode = NULL;
5476     tv->conta6++;
5477 
5478     switch (tv->compstage) {
5479         case 0:
5480             if (tv->strategy) {
5481                 CheckLevel = CheckLevelEnd = tv->maxtreelevel;
5482             }
5483             else {
5484                 if ((Spine[tv->tolevel].part)->cells == tv->finalnumcells) {
5485                     CheckLevel = CheckLevelEnd = tv->maxtreelevel;
5486                 }
5487                 else {
5488                     CheckLevel = 1;
5489                     if ((Spine[tv->maxtreelevel].part)->cells == tv->finalnumcells) {
5490                         CheckLevelEnd = tv->maxtreelevel - 1;
5491                     }
5492                     else {
5493                         CheckLevelEnd = tv->maxtreelevel;
5494                     }
5495                 }
5496             }
5497             break;
5498         case 1:
5499             CheckLevel = CheckLevelEnd = tv->tolevel;
5500             break;
5501         case 2:
5502             if (m || (tv->tolevel == tv->maxtreelevel+1)) {
5503                 CheckLevel = CheckLevelEnd = tv->maxtreelevel+1;
5504             }
5505             else {
5506                 CheckLevel = 1;
5507                 if ((Spine[tv->maxtreelevel].part)->cells == tv->finalnumcells) {
5508                     CheckLevelEnd = tv->maxtreelevel - 1;
5509                 }
5510                 else {
5511                     CheckLevelEnd = tv->maxtreelevel;
5512                 }
5513             }
5514             break;
5515         default:
5516             break;
5517     }
5518     while (CheckLevel <= CheckLevelEnd) {
5519         CheckAutList = Spine[CheckLevel].liststart;
5520         while (CheckAutList) {
5521             if (CheckAutList->do_it && lookup(CheckAutList->stnode) && (CheckAutList != NextCand) && (CheckAutList != CurrCand)) {
5522                 if (CheckAutList->code == NextCand->code) {
5523                     SETMARK(Markers, tv->mark)
5524                     if (Part->cells == n) {
5525                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
5526                         for (i = 0; i < n; i++) {
5527                             arg = NextCand->lab[i];
5528                             val = CheckAutList->lab[i];
5529                             SETPAIRSAUT(arg, val)
5530                         }
5531                     }
5532                     else {
5533                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
5534                         SETMARK(CellMarkers1, tv->markcell1)
5535                         SETMARK(CellMarkers2, tv->markcell2)
5536                         for (i=0; i<n; i+=Part->cls[i]) {
5537                             if (Part->cls[i] == 1) {
5538                                 arg = NextCand->lab[i];
5539                                 val = CheckAutList->lab[i];
5540                                 SETPAIRSAUT(arg, val)
5541                                 if (tv->preprocessed && Diff[arg])
5542                                     MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
5543                             }
5544                             else {
5545                                 k = i;
5546                                 for (j=i; j<i+Part->cls[i]; j++) {
5547                                     arg = arg1 = NextCand->lab[j];
5548                                     if (CellMarkers1[arg] != tv->markcell1) {
5549                                         CellMarkers1[arg] = tv->markcell1;
5550                                         while ((CellMarkers2[CheckAutList->lab[k]] == tv->markcell2) && (k < i+Part->cls[i])) {
5551                                             k++;
5552                                         }
5553                                         if (k < i+Part->cls[i]) {
5554                                             val = val1 = CheckAutList->lab[k];
5555                                             CellMarkers2[val] = tv->markcell2;
5556                                             SETPAIRSAUT(arg, val)
5557                                             if (tv->preprocessed && Diff[arg])
5558                                                 MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
5559                                             tmp = FirstNeighbour(arg, NextCand, Part, CellMarkers1, tv->markcell1, &arg, n);
5560                                             if (tmp) {
5561                                                 CellMarkers1[arg] = tv->markcell1;
5562                                                 tmp = FirstNeighbour(val, CheckAutList, Part, CellMarkers2, tv->markcell2, &val, n);
5563                                                 CellMarkers2[val] = tv->markcell2;
5564                                                 SETPAIRSAUT(arg, val)
5565                                                 if (tv->preprocessed && Diff[arg])
5566                                                     MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
5567                                                 while (tmp) {
5568                                                     tmp = NextNeighbour(arg, NextCand, Part, CellMarkers1, tv->markcell1, &arg, n);
5569                                                     if (tmp) {
5570                                                         CellMarkers1[arg] = tv->markcell1;
5571                                                         tmp = NextNeighbour(val, CheckAutList, Part, CellMarkers2, tv->markcell2, &val, n);
5572                                                         if (tmp) {
5573                                                             CellMarkers2[val] = tv->markcell2;
5574                                                             SETPAIRSAUT(arg, val)
5575                                                             if (tv->preprocessed && Diff[arg])
5576                                                                 MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
5577                                                         }
5578                                                     }
5579                                                 }
5580                                                 arg = arg1;
5581                                                 val = val1;
5582                                                 do {
5583                                                     tmp = NextNeighbour(arg, NextCand, Part, CellMarkers1, tv->markcell1, &arg, n);
5584                                                     if (tmp) {
5585                                                         CellMarkers1[arg] = tv->markcell1;
5586                                                         tmp = NextNeighbour(val, CheckAutList, Part, CellMarkers2, tv->markcell2, &val, n);
5587                                                         if (tmp) {
5588                                                             CellMarkers2[val] = tv->markcell2;
5589                                                             SETPAIRSAUT(arg, val)
5590                                                             if (tv->preprocessed && Diff[arg])
5591                                                                 MakeTree(arg, val, tv->input_graph, n, tv, TRUE);
5592                                                         }
5593                                                     }
5594                                                 } while (tmp);
5595                                             }
5596                                         }
5597                                     }
5598                                 }
5599                             }
5600                         }
5601                     }
5602 
5603                     if (isautom_sg_pair((graph*)tv->input_graph, AUTPERM, tv->options->digraph, m, n, tv)) {
5604                         if (!findperm(gensB, AUTPERM, n)) {
5605                             if (tv->options->verbosity >= 2) tv->schreier3 -= CPUTIME;
5606                             addgenerator(&gpB, &gensB, AUTPERM, n);
5607                             if (tv->options->verbosity >= 2) tv->schreier3 += CPUTIME;
5608                             if (tv->options->verbosity >= 2) {
5609                                 fprintf(outfile, "[A(%d,%d)] ", CheckLevel, CheckAutList->name);
5610                             }
5611                             tv->lev_of_lastauto = tv->tolevel;
5612                             tv->stats->numgenerators++;
5613                             orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
5614                             ti->thegrouphaschanged = TRUE;
5615                             ti->identitygroup = FALSE;
5616                             if (tv->options->verbosity >= 2 && tv->options->writeautoms) {
5617                                 PRINT_RETURN
5618                             }
5619                             if (tv->options->writeautoms) {
5620                                 fprintf(outfile, "Gen(A) #%d: ", tv->stats->numgenerators);
5621                                 writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n);
5622                             }
5623                             if (tv->options->userautomproc) {
5624                                 (*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n);
5625                             }
5626                         }
5627                         else {
5628                             orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
5629                             if (tv->options->verbosity >= 2) {
5630                                 fprintf(outfile, "[A*(%d,%d)] ", CheckLevel, CheckAutList->name);
5631                             }
5632                         }
5633                         TrieCandFrom = NULL;
5634                         TrieCheckFrom = CheckAutList->stnode;
5635                         if (CurrCand->stnode->level <= 1) {
5636                             tgt_level = CurrCand->stnode->level + 1;
5637                             while (TrieCheckFrom->level > tgt_level) {
5638                                 TrieCheckFrom = TrieCheckFrom->father;
5639                             }
5640                         }
5641                         else {
5642                             if (tv->tolevel <= TrieCheckFrom->level) {
5643                                 tgt_level = tv->tolevel;
5644                                 while (TrieCheckFrom->level != tgt_level) {
5645                                     TrieCheckFrom = TrieCheckFrom->father;
5646                                 }
5647                             }
5648                             else {
5649                                 TrieCandFrom = CurrCand->stnode;
5650                                 tgt_level = TrieCheckFrom->level;
5651                                 while (TrieCandFrom->level != tgt_level) {
5652                                     TrieCandFrom = TrieCandFrom->father;
5653                                 }
5654                             }
5655                         }
5656                         if (TrieCandFrom) {
5657                             while (TrieCandFrom->father != TrieCheckFrom->father) {
5658                                 TrieCandFrom = TrieCandFrom->father;
5659                                 TrieCheckFrom = TrieCheckFrom->father;
5660                             }
5661                         }
5662                         else {
5663                             if ((TrieCheckFrom->level > 1) && (TrieCheckFrom->father != CurrCand->stnode)) {
5664                                 TrieCandFrom = CurrCand->stnode;
5665                                 TrieCheckFrom = TrieCheckFrom->father;
5666                                 while (TrieCandFrom->father != TrieCheckFrom->father) {
5667                                     TrieCandFrom = TrieCandFrom->father;
5668                                     TrieCheckFrom = TrieCheckFrom->father;
5669                                 }
5670                             }
5671                         }
5672 
5673                         while (TrieCheckFrom->goes_to) {
5674                             TrieCheckFrom = TrieCheckFrom->goes_to;
5675                         }
5676 
5677                         for (temp=1; temp<=tv->tolevel; temp++) {
5678                             if (CheckAutList->lab[Spine[temp].tgtpos] != NextCand->lab[Spine[temp].tgtpos]) {
5679                                 break;
5680                             }
5681                         }
5682 
5683                         if (temp == tv->tolevel) {
5684                             if (TempOrbits) {
5685                                 if (tv->compstage == 0) {
5686                                     for (j=0; j<tv->permInd; j++) {
5687                                         orbjoin_sp_pair(TempOrbits, TempOrbList, n,
5688                                                         PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
5689                                     }
5690                                 }
5691                                 else {
5692                                     orbjoin(TempOrbits, AUTPERM, n);
5693                                 }
5694                             } else {
5695                                 orbjoin(tv->currorbit, AUTPERM, n);
5696                             }
5697                         }
5698 
5699                         switch (tv->compstage) {
5700                             case 0:
5701                                 if (tv->strategy && (tv->steps == 1)) {
5702                                     RemoveFromLevel(temp, tv->maxtreelevel-1, tv->strategy, FALSE);
5703                                     if (TrieCandFrom) {
5704                                         TrieCheckFrom->index += TrieCandFrom->index;
5705                                         TrieCandFrom->goes_to = TrieCheckFrom;
5706                                         PRINT_INDEX(TrieCheckFrom,4,1)
5707                                     }
5708                                     else {
5709                                         TrieCheckFrom->index++;
5710                                         PRINT_INDEX(TrieCheckFrom,4,2)
5711                                     }
5712                                     NextCand->do_it = FALSE;
5713                                 }
5714                                 else {
5715                                     if (CheckAutList->lab[Spine[temp].tgtpos] >= NextCand->lab[Spine[temp].tgtpos]) {
5716                                         CheckAutList->do_it = FALSE;
5717                                         if (TrieCandFrom) {
5718                                             TrieCandFrom->index += TrieCheckFrom->index;
5719                                             tv->newindex = 0;
5720                                             TrieCheckFrom->goes_to = TrieCandFrom;
5721                                             PRINT_INDEX(TrieCandFrom,4,3)
5722                                         }
5723                                         else {
5724                                             if (CurrCand->stnode->level > 1) {
5725                                                 tv->newgotonode = TrieCheckFrom;
5726                                                 tv->newindex = TrieCheckFrom->index;
5727                                             }
5728                                             else {
5729                                                 tv->newgotonode = NULL;
5730                                                 tv->newindex = 0;
5731                                             }
5732                                         }
5733                                     }
5734                                     else {
5735                                         if (TrieCandFrom) {
5736                                             TrieCheckFrom->index += TrieCandFrom->index;
5737                                             TrieCandFrom->goes_to = TrieCheckFrom;
5738                                             PRINT_INDEX(TrieCheckFrom,4,4)
5739                                         }
5740                                         else {
5741                                             TrieCheckFrom->index++;
5742                                             PRINT_INDEX(TrieCheckFrom,4,5)
5743                                         }
5744                                         NextCand->do_it = FALSE;
5745                                     }
5746                                 }
5747                                 break;
5748                             case 1:
5749                                 TrieCheckFrom->index ++;
5750                                 PRINT_INDEX(TrieCheckFrom,4,6)
5751                                 tv->gotonode = TrieCheckFrom;
5752                                 break;
5753                             case 2:
5754                                 if (TrieCandFrom) {
5755                                     TrieCheckFrom->index += TrieCandFrom->index;
5756                                     TrieCandFrom->goes_to = TrieCheckFrom;
5757                                     PRINT_INDEX(TrieCheckFrom,4,7)
5758                                 }
5759                                 else {
5760                                     TrieCheckFrom->index++;
5761                                     PRINT_INDEX(TrieCheckFrom,4,8)
5762                                 }
5763                                 if (temp == tv->maxtreelevel) {
5764                                     tmp1 = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
5765 
5766                                     if (CheckAutList->lab[Spine[temp].tgtpos] == AutomCount[1]) {
5767                                         for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == tmp1) break;
5768                                         if (i == AutomCount[0]) {
5769                                             AutomCount[AutomCount[0]++] = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
5770                                         }
5771                                     }
5772 
5773                                 }
5774                                 break;
5775                             default:
5776                                 break;
5777                         }
5778                         return temp;
5779                     }
5780                 }
5781             }
5782             CheckAutList = CheckAutList->next;
5783         }
5784         CheckLevel++;
5785     }
5786     return FALSE;
5787 }
5788 
5789 
CheckForSingAutomorphisms(Candidate * CurrCand,Partition * NextPart,Candidate * NextCand,struct TracesVars * tv,struct TracesInfo * ti,int m,int n)5790 int CheckForSingAutomorphisms(Candidate *CurrCand, Partition *NextPart, Candidate *NextCand,
5791                               struct TracesVars* tv, struct TracesInfo* ti,
5792                               int m, int n) {
5793     int i, j, temp, tmp, tmp1, result, tgt_level, numtemporbits;
5794     TracesSpine *SpineTL;
5795     Candidate *CheckAutList;
5796     searchtrie *TrieCandFrom, *TrieCheckFrom;
5797 
5798     SpineTL = Spine+tv->tolevel;
5799     CheckAutList = SpineTL->liststart;
5800     tv->gotonode = NULL;
5801 
5802     result = 0;
5803     while (CheckAutList != NULL) {
5804         if (CheckAutList->do_it && (CheckAutList->stnode->father == CurrCand->stnode)) {
5805             if (CheckAutList->firstsingcode == NextCand->firstsingcode) {
5806                 if (tv->permInd) ResetAutom(tv->permInd, n, tv);
5807                 if ((tv->tolevel == 1) && (Spine[0].part->cells == 1)) tmp = 2; else tmp = tv->tolevel;
5808                 if (TreeFyTwo(tmp, CheckAutList, NextCand, NextPart, n, tv, ti)) {
5809                     if (isautom_sg((graph*)tv->input_graph, AUTPERM, tv->options->digraph, m, n)) {
5810                         if (!findperm(gensB, AUTPERM, n)) {
5811                             if (tv->options->verbosity >= 2) tv->schreier3 -= CPUTIME;
5812                             addgenerator(&gpB, &gensB, AUTPERM, n);
5813                             if (tv->options->verbosity >= 2) tv->schreier3 += CPUTIME;
5814                             result = CheckAutList->name;
5815                             if (TempOrbits) {
5816                                 if (tv->compstage == 0) {
5817                                     for (j=0; j<tv->permInd; j++) {
5818                                         orbjoin_sp_pair(TempOrbits, TempOrbList, n,
5819                                                         PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
5820                                     }
5821                                 }
5822                                 else {
5823                                     orbjoin(TempOrbits, AUTPERM, n);
5824                                 }
5825                             }
5826                             tv->stats->numgenerators++;
5827                             orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
5828 
5829                             ti->thegrouphaschanged = TRUE;
5830                             ti->identitygroup = FALSE;
5831                             tv->lev_of_lastauto = tv->tolevel;
5832                             if (tv->options->verbosity >= 2) fprintf(outfile, "[a(%d)] ", CheckAutList->name);
5833                             if (tv->options->verbosity >= 2 && tv->options->writeautoms) {
5834                                 PRINT_RETURN
5835                             }
5836                             if (tv->options->writeautoms) {
5837                                 fprintf(outfile, "Gen(a) #%d: ", tv->stats->numgenerators);
5838                                 writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n);
5839                             }
5840                             if (tv->options->userautomproc) {
5841                                 (*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n);
5842                             }
5843                         }
5844                         else {
5845                             if (tv->options->verbosity >= 2) {
5846                                 fprintf(outfile, "[a*]");
5847                             }
5848                             if (TempOrbits) {
5849                                 if (tv->compstage == 0) {
5850                                     for (j=0; j<tv->permInd; j++) {
5851                                         orbjoin_sp_pair(TempOrbits, TempOrbList, n,
5852                                                         PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
5853                                     }
5854                                 }
5855                                 else {
5856                                     orbjoin(TempOrbits, AUTPERM, n);
5857                                 }
5858                             }
5859                             else {
5860                                 orbjoin(tv->currorbit, AUTPERM, n);
5861                             }
5862                             orbjoin_sp_perm(tv->orbits, AUTPERM, OrbList, n, &tv->stats->numorbits);
5863 
5864                             result = -CheckAutList->name;
5865                         }
5866 
5867                         TrieCandFrom = NULL;
5868                         TrieCheckFrom = CheckAutList->stnode;
5869                         if (CurrCand->stnode->level <= 1) {
5870                             tgt_level = CurrCand->stnode->level + 1;
5871                             while (TrieCheckFrom->level > tgt_level) {
5872                                 TrieCheckFrom = TrieCheckFrom->father;
5873                             }
5874                         }
5875                         else {
5876                             if (tv->tolevel <= TrieCheckFrom->level) {
5877                                 tgt_level = tv->tolevel;
5878                                 while (TrieCheckFrom->level != tgt_level) {
5879                                     TrieCheckFrom = TrieCheckFrom->father;
5880                                 }
5881                             }
5882                             else {
5883                                 TrieCandFrom = CurrCand->stnode;
5884                                 tgt_level = TrieCheckFrom->level;
5885                                 while (TrieCandFrom->level != tgt_level) {
5886                                     TrieCandFrom = TrieCandFrom->father;
5887                                 }
5888                             }
5889                         }
5890                         if (TrieCandFrom) {
5891                             while (TrieCandFrom->father != TrieCheckFrom->father) {
5892                                 TrieCandFrom = TrieCandFrom->father;
5893                                 TrieCheckFrom = TrieCheckFrom->father;
5894                             }
5895                         }
5896                         else {
5897                             if ((TrieCheckFrom->level > 1) && (TrieCheckFrom->father != CurrCand->stnode)) {
5898                                 TrieCandFrom = CurrCand->stnode;
5899                                 TrieCheckFrom = TrieCheckFrom->father;
5900                                 while (TrieCandFrom->father != TrieCheckFrom->father) {
5901                                     TrieCandFrom = TrieCandFrom->father;
5902                                     TrieCheckFrom = TrieCheckFrom->father;
5903                                 }
5904                             }
5905                         }
5906 
5907                         while (TrieCheckFrom->goes_to) {
5908                             TrieCheckFrom = TrieCheckFrom->goes_to;
5909                         }
5910 
5911                         for (temp=1; temp<=tv->tolevel; temp++) {
5912                             if (CheckAutList->lab[Spine[temp].tgtpos] != NextCand->lab[Spine[temp].tgtpos]) {
5913                                 break;
5914                             }
5915                         }
5916 
5917                         switch (tv->compstage) {
5918                             case 0:
5919                                 if (tv->strategy && (tv->steps == 1)) {
5920                                     RemoveFromLevel(temp, tv->maxtreelevel-1, tv->strategy, FALSE);
5921                                     if (TrieCandFrom) {
5922                                         TrieCheckFrom->index += TrieCandFrom->index;
5923                                         TrieCandFrom->goes_to = TrieCheckFrom;
5924                                         PRINT_INDEX(TrieCheckFrom,4,9)
5925                                     }
5926                                     else {
5927                                         TrieCheckFrom->index++;
5928                                         PRINT_INDEX(TrieCheckFrom,4,10)
5929                                     }
5930                                     NextCand->do_it = FALSE;
5931                                 }
5932                                 else {
5933                                     if (CheckAutList->lab[Spine[temp].tgtpos] >= NextCand->lab[Spine[temp].tgtpos]) {
5934                                         CheckAutList->do_it = FALSE;
5935                                         if (TrieCandFrom) {
5936                                             TrieCandFrom->index += TrieCheckFrom->index;
5937                                             tv->newindex = 0;
5938                                             TrieCheckFrom->goes_to = TrieCandFrom;
5939                                             PRINT_INDEX(TrieCandFrom,4,11)
5940                                         }
5941                                         else {
5942                                             if (CurrCand->stnode->level > 1) {
5943                                                 tv->newgotonode = TrieCheckFrom;
5944                                                 tv->newindex = TrieCheckFrom->index;
5945                                             }
5946                                             else {
5947                                                 tv->newgotonode = NULL;
5948                                                 tv->newindex = 0;
5949                                             }
5950                                         }
5951                                     }
5952                                     else {
5953                                         if (TrieCandFrom) {
5954                                             TrieCheckFrom->index += TrieCandFrom->index;
5955                                             TrieCandFrom->goes_to = TrieCheckFrom;
5956                                             PRINT_INDEX(TrieCheckFrom,4,12)
5957                                         }
5958                                         else {
5959                                             TrieCheckFrom->index++;
5960                                             PRINT_INDEX(TrieCheckFrom,4,13)
5961                                         }
5962                                         NextCand->do_it = FALSE;
5963                                     }
5964                                 }
5965                                 break;
5966                             case 1:
5967                                 TrieCheckFrom->index++;
5968                                 PRINT_INDEX(TrieCheckFrom,4,14)
5969                                 tv->gotonode = TrieCheckFrom;
5970                                 break;
5971                             case 2:
5972                                 if (TrieCandFrom) {
5973                                     TrieCheckFrom->index += TrieCandFrom->index;
5974                                     TrieCandFrom->goes_to = TrieCheckFrom;
5975                                     PRINT_INDEX(TrieCheckFrom,4,15)
5976                                 }
5977                                 else {
5978                                     TrieCheckFrom->index++;
5979                                     PRINT_INDEX(TrieCheckFrom,4,16)
5980                                 }
5981                                 if ((temp == tv->maxtreelevel) && (CheckAutList->lab[Spine[temp].tgtpos] == AutomCount[1])) {
5982                                     tmp1 = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
5983                                     for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == tmp1) break;
5984                                     if (i == AutomCount[0]) {
5985                                         AutomCount[AutomCount[0]++] = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
5986                                     }
5987                                 }
5988                                 break;
5989                             default:
5990                                 break;
5991                         }
5992                         return result;
5993                     }
5994                 }
5995             }
5996         }
5997         CheckAutList = CheckAutList->next;
5998     }
5999     return result;
6000 }
6001 
CheckForMatching(Candidate * CurrCand,Candidate * NextCand,Partition * Part,struct TracesVars * tv,struct TracesInfo * ti,int m,int n)6002 int CheckForMatching(Candidate *CurrCand, Candidate *NextCand, Partition *Part, struct TracesVars* tv, struct TracesInfo* ti, int m, int n) {
6003     int i, j, vtx, vtx1, temp, tmp1, tgt_level, numtemporbits, pos;
6004     TracesSpine *SpineTL;
6005     Candidate *CheckAutList;
6006     int *cls;
6007     searchtrie *TrieCandFrom, *TrieCheckFrom;
6008     boolean CodeVerify;
6009 
6010     SpineTL = Spine+tv->tolevel;
6011     CheckAutList = SpineTL->liststart;
6012     cls = Part->cls;
6013     numtemporbits = 0;
6014     tv->gotonode = NULL;
6015 
6016     while (CheckAutList != NULL) {
6017         if (CheckAutList->do_it && (CheckAutList->singcode == NextCand->singcode)) {
6018             TrieCheckFrom = CheckAutList->stnode->father;
6019             TrieCandFrom = CurrCand->stnode;
6020             while (TrieCandFrom != TrieCheckFrom) {
6021                 TrieCandFrom = TrieCandFrom->father;
6022                 TrieCheckFrom = TrieCheckFrom->father;
6023             }
6024 
6025             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
6026 
6027             CodeVerify = TRUE;
6028             for (i=Spine[TrieCheckFrom->level+1].singstart; i<SpineTL->singend; i++) {
6029                 Markers[NextCand->lab[Singletons[i]]] = tv->mark;
6030             }
6031             for (i=Spine[TrieCheckFrom->level+1].singstart; i<SpineTL->singend; i++) {
6032                 pos = Singletons[i];
6033                 vtx1 = CheckAutList->lab[pos];
6034                 if (Markers[vtx1] != tv->mark) {
6035                     CodeVerify = FALSE;
6036                     break;
6037                 }
6038                 vtx = NextCand->lab[pos];
6039                 SETPAIRSAUT(vtx, vtx1)
6040 
6041                 if (tv->preprocessed && Diff[vtx1]) {
6042                     MakeTree(vtx, vtx1, tv->input_graph, n, tv, TRUE);
6043                 }
6044             }
6045             tv->conta7++;
6046 
6047             if (CodeVerify) {
6048                 if (isautom_sg_pair((graph*)tv->input_graph, AUTPERM, tv->options->digraph, m, n, tv)) {
6049 
6050                     if (!findperm(gensB, AUTPERM, n)) {
6051                         if (tv->options->verbosity >= 2) tv->schreier3 -= CPUTIME;
6052                         if (tv->options->generators) addpermutation(&gensB, AUTPERM, n);
6053 
6054                         if (tv->options->verbosity >= 2) tv->schreier3 += CPUTIME;
6055 
6056                         if (CheckAutList->stnode->father == CurrCand->stnode) {
6057                             if (TempOrbits) {
6058                                 if (tv->compstage == 0) {
6059                                     for (j=0; j<tv->permInd; j++) {
6060                                         orbjoin_sp_pair(TempOrbits, TempOrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
6061                                     }
6062                                 }
6063                                 else {
6064                                     orbjoin(TempOrbits, AUTPERM, n);
6065                                 }
6066                             } else {
6067                                 orbjoin(tv->currorbit, AUTPERM, n);
6068                             }
6069                         }
6070 
6071                         tv->stats->numgenerators++;
6072 
6073                         for (j=0; j<tv->permInd; j++) {
6074                             orbjoin_sp_pair(tv->orbits, OrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &tv->stats->numorbits);
6075                         }
6076 
6077                         ti->thegrouphaschanged = TRUE;
6078                         ti->first_matching = TRUE;
6079                         tv->lev_of_lastauto = tv->tolevel;
6080                         if (tv->options->verbosity >= 2) fprintf(outfile, "[M(%d)] ", CheckAutList->name);
6081                         if (tv->options->verbosity >= 2 && tv->options->writeautoms) {
6082                             PRINT_RETURN
6083                         }
6084                         if (tv->options->writeautoms) {
6085                             fprintf(outfile, "Gen(M) #%d: ", tv->stats->numgenerators);
6086                             writeperm(outfile, AUTPERM, tv->options->cartesian, tv->options->linelength, n);
6087                         }
6088                         if (tv->options->userautomproc) {
6089                             (*tv->options->userautomproc)(tv->stats->numgenerators, AUTPERM, n);
6090                         }
6091 
6092                     }
6093                     else {
6094                         if (tv->options->verbosity >= 2) {
6095                             fprintf(outfile, "[M*]");
6096                         }
6097                         if (CheckAutList->stnode->father == CurrCand->stnode) {
6098                             if (TempOrbits) {
6099                                 if (tv->compstage == 0) {
6100                                     for (j=0; j<tv->permInd; j++) {
6101                                         orbjoin_sp_pair(TempOrbits, TempOrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &numtemporbits);
6102                                     }
6103                                 }
6104                                 else {
6105                                     orbjoin(TempOrbits, AUTPERM, n);
6106                                 }
6107                             } else {
6108                                 orbjoin(tv->currorbit, AUTPERM, n);
6109                             }
6110                         }
6111 
6112                         for (j=0; j<tv->permInd; j++) {
6113                             orbjoin_sp_pair(tv->orbits, OrbList, n, PrmPairs[j].arg, PrmPairs[j].val, &tv->stats->numorbits);
6114                         }
6115                     }
6116 
6117                     TrieCandFrom = NULL;
6118                     TrieCheckFrom = CheckAutList->stnode;
6119                     if (CurrCand->stnode->level <= 1) {
6120                         tgt_level = CurrCand->stnode->level + 1;
6121                         while (TrieCheckFrom->level > tgt_level) {
6122                             TrieCheckFrom = TrieCheckFrom->father;
6123                         }
6124                     }
6125                     else {
6126                         if (tv->tolevel <= TrieCheckFrom->level) {
6127                             tgt_level = tv->tolevel;
6128                             while (TrieCheckFrom->level != tgt_level) {
6129                                 TrieCheckFrom = TrieCheckFrom->father;
6130                             }
6131                         }
6132                         else {
6133                             TrieCandFrom = CurrCand->stnode;
6134                             tgt_level = TrieCheckFrom->level;
6135                             while (TrieCandFrom->level != tgt_level) {
6136                                 TrieCandFrom = TrieCandFrom->father;
6137                             }
6138                         }
6139                     }
6140                     if (TrieCandFrom) {
6141                         while (TrieCandFrom->father != TrieCheckFrom->father) {
6142                             TrieCandFrom = TrieCandFrom->father;
6143                             TrieCheckFrom = TrieCheckFrom->father;
6144                         }
6145                     }
6146                     else {
6147                         if ((TrieCheckFrom->level > 1) && (TrieCheckFrom->father != CurrCand->stnode)) {
6148                             TrieCandFrom = CurrCand->stnode;
6149                             TrieCheckFrom = TrieCheckFrom->father;
6150                             while (TrieCandFrom->father != TrieCheckFrom->father) {
6151                                 TrieCandFrom = TrieCandFrom->father;
6152                                 TrieCheckFrom = TrieCheckFrom->father;
6153                             }
6154                         }
6155                     }
6156 
6157                     while (TrieCheckFrom->goes_to) {
6158                         TrieCheckFrom = TrieCheckFrom->goes_to;
6159                     }
6160 
6161                     for (temp=1; temp<=tv->tolevel; temp++) {
6162                         if (CheckAutList->lab[Spine[temp].tgtpos] != NextCand->lab[Spine[temp].tgtpos]) {
6163                             break;
6164                         }
6165                     }
6166                     switch (tv->compstage) {
6167                         case 0:
6168                             if (tv->strategy && (tv->steps == 1)) {
6169                                 RemoveFromLevel(temp, tv->maxtreelevel-1, tv->strategy, FALSE);
6170                                 if (TrieCandFrom) {
6171                                     TrieCheckFrom->index += TrieCandFrom->index;
6172                                     TrieCandFrom->goes_to = TrieCheckFrom;
6173                                     PRINT_INDEX(TrieCheckFrom,4,17)
6174                                 }
6175                                 else {
6176                                     TrieCheckFrom->index++;
6177                                     PRINT_INDEX(TrieCheckFrom,4,18)
6178                                 }
6179                                 NextCand->do_it = FALSE;
6180                             }
6181                             else {
6182                                 if (CheckAutList->lab[Spine[temp].tgtpos] >= NextCand->lab[Spine[temp].tgtpos]) {
6183                                     CheckAutList->do_it = FALSE;
6184                                     if (TrieCandFrom) {
6185                                         TrieCandFrom->index += TrieCheckFrom->index;
6186                                         tv->newindex = 0;
6187                                         TrieCheckFrom->goes_to = TrieCandFrom;
6188                                         PRINT_INDEX(TrieCandFrom,4,19)
6189                                     }
6190                                     else {
6191                                         if (CurrCand->stnode->level > 1) {
6192                                             tv->newgotonode = TrieCheckFrom;
6193                                             tv->newindex = TrieCheckFrom->index;
6194                                         }
6195                                         else {
6196                                             tv->newgotonode = NULL;
6197                                             tv->newindex = 0;
6198                                         }
6199                                     }
6200                                 }
6201                                 else {
6202                                     if (TrieCandFrom) {
6203                                         TrieCheckFrom->index += TrieCandFrom->index;
6204                                         TrieCandFrom->goes_to = TrieCheckFrom;
6205                                         PRINT_INDEX(TrieCheckFrom,4,20)
6206                                     }
6207                                     else {
6208                                         TrieCheckFrom->index++;
6209                                         PRINT_INDEX(TrieCheckFrom,4,21)
6210                                     }
6211                                     NextCand->do_it = FALSE;
6212                                 }
6213                             }
6214                             break;
6215                         case 1:
6216                             TrieCheckFrom->index ++;
6217                             tv->gotonode = TrieCheckFrom;
6218                             PRINT_INDEX(TrieCheckFrom,4,22)
6219                             break;
6220                         case 2:
6221                             if (TrieCandFrom) {
6222                                 TrieCheckFrom->index += TrieCandFrom->index;
6223                                 TrieCandFrom->goes_to = TrieCheckFrom;
6224                                 PRINT_INDEX(TrieCheckFrom,4,23)
6225                             }
6226                             else {
6227                                 TrieCheckFrom->index++;
6228                                 PRINT_INDEX(TrieCheckFrom,4,24)
6229                             }
6230                             if ((temp == tv->maxtreelevel) && (CheckAutList->lab[Spine[temp].tgtpos] == AutomCount[1])) {
6231                                 tmp1 = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
6232                                 for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == tmp1) break;
6233                                 if (i == AutomCount[0]) {
6234                                     AutomCount[AutomCount[0]++] = TempOrbits[NextCand->lab[Spine[temp].tgtpos]];
6235                                 }
6236                             }
6237                             break;
6238                         default:
6239                             break;
6240                     }
6241                     return temp;
6242                 }
6243             }
6244         }
6245         CheckAutList = CheckAutList->next;
6246     }
6247     return FALSE;
6248 }
6249 
CodeClassify(int Level,int code,int cell)6250 void CodeClassify(int Level, int code, int cell) {
6251     switch (EPCodes[Level].info) {
6252         case 0:
6253             EPCodes[Level].code = code;
6254             EPCodes[Level].cell = cell;
6255             EPCodes[Level].info = 1;
6256             break;
6257         case 1:
6258             if (EPCodes[Level].cell != cell) {
6259                 EPCodes[Level].info = 3;
6260             } else {
6261                 if (EPCodes[Level].code != code) {
6262                     EPCodes[Level].info = 2;
6263                 }
6264             }
6265             break;
6266         case 2:
6267             if (EPCodes[Level].cell != cell) {
6268                 EPCodes[Level].info = 3;
6269             }
6270             break;
6271         default:
6272             break;
6273     }
6274 }
6275 
Complete(sparsegraph * sg_orig,Candidate * Cand,Partition * Part,int cell,TracesVars * tv,double * grpsize1,int * grpsize2,permnode ** ring,int n)6276 void Complete(sparsegraph *sg_orig, Candidate *Cand, Partition *Part, int cell, TracesVars *tv,
6277               double *grpsize1, int *grpsize2, permnode **ring, int n) {
6278     int i, j, k;
6279     int arg, val;
6280     int numtemporbits;
6281     k = cell + Part->cls[cell];
6282 
6283     if (tv->permInd) ResetAutom(tv->permInd, n, tv);
6284     for (i = cell; i < k; i++) {
6285         tv->currorbit[Cand->lab[i]] = Cand->lab[k];
6286         arg = Cand->lab[i];
6287         val = Cand->lab[i+1];
6288         SETPAIRSAUTANDTREE(arg, val)
6289     }
6290     arg = Cand->lab[i];
6291     val = Cand->lab[cell];
6292     SETPAIRSAUTANDTREE(arg, val)
6293     SPECIALGENERATORS
6294 
6295     if (Part->cls[cell] > 1) {
6296         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
6297         arg = Cand->lab[cell];
6298         val = Cand->lab[cell+1];
6299         SETPAIRSAUTANDTREE(arg, val)
6300         arg = Cand->lab[cell+1];
6301         val = Cand->lab[cell];
6302         SETPAIRSAUTANDTREE(arg, val)
6303         SPECIALGENERATORS
6304     }
6305 }
6306 
CompStage0(Partition * CurrPart,Partition * NextPart,Candidate * CurrCand,Candidate * NextCand,int m,int n,struct TracesVars * tv,struct TracesInfo * ti)6307 int CompStage0(Partition *CurrPart, Partition *NextPart, Candidate *CurrCand, Candidate *NextCand,
6308                int m, int n, struct TracesVars* tv, struct TracesInfo *ti) {
6309     int i, j, i1, j2, k, cu, cu1, num_indv;
6310     int temp, tmp, auxcode, search_vtx, gom_level;
6311     boolean closeloop, firstsing, has_nexttcell;
6312     Candidate *SpTLliststart, *AuxCand;
6313     searchtrie *TreeNode, *TreeNode1, *TreeNode2;
6314 
6315 #ifdef NAUTY_IN_MAGMA
6316     if (main_seen_interrupt) return NAUTY_KILLED;
6317 #else
6318     if (nauty_kill_request) return NAUTY_KILLED;
6319 #endif
6320 
6321     PRINT_FROM_VERB(4,tv->tolevel)
6322     if (TargetCell(CurrCand, CurrPart, n, tv, tv->tolevel)) {
6323         ++tv->tolevel;
6324         SpineTL = Spine+tv->tolevel;
6325         SpineTL->tgtcell = tv->tcell;
6326         SpineTL->tgtsize = CurrPart->cls[tv->tcell];
6327         SpineTL->tgtend = tv->tcell+SpineTL->tgtsize;
6328         SpineTL->tgtpos = SpineTL->tgtend - 1;
6329     }
6330     else {
6331         tv->finalnumcells = CurrPart->cells;
6332         ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
6333         return 0;
6334     }
6335 
6336     tv->newgotonode = NULL;
6337 
6338     /*  CANDIDATE */
6339     temp = CurrCand->lab[Spine[1].tgtpos];
6340     k = SpineTL->tgtend;
6341 
6342     TreeNode = CurrCand->stnode;
6343     while (TreeNode) {
6344         if (TreeNode->goes_to) {
6345             CurrCand->do_it = FALSE;
6346             break;
6347         }
6348         TreeNode = TreeNode->father;
6349     }
6350 
6351     if (CurrCand->do_it) {
6352         if ((tv->orbits[temp] == temp) || tv->tolevel == 1) {
6353             ti->minimalinorbits = TRUE;
6354 
6355             if ((tv->group_level >= tv->tolevel) && (FixedBase(fix, tv, CurrCand, 0, tv->fromlevel))) {
6356                 tv->nfix = tv->fromlevel;
6357                 tv->currorbit = findcurrorbits(gpB, tv->nfix);
6358             } else {
6359                 if ((!ti->identitygroup) &&
6360                     (((Spine[tv->fromlevel].liststart != Spine[tv->fromlevel].listend)
6361                       && (CurrPart->cls[tv->tcell] > 10))
6362                      || tv->strategy
6363                      || (tv->expathlength <=10)
6364                      )) {
6365 
6366                         TempOrbits = NULL;
6367                         tv->samepref = FixBase(fix, tv, CurrCand, 0, tv->fromlevel);
6368                         if ((tv->samepref != tv->nfix) || ti->thegrouphaschanged) {
6369                             if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
6370                             gom_level = getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit, CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell], n, TRUE);
6371                             if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
6372                             ti->thegrouphaschanged = FALSE;
6373 
6374                             if (gom_level < tv->nfix) {
6375                                 PRINT_NOTMIN_VERB(4)
6376 
6377                                 TreeNode = CurrCand->stnode;
6378                                 j2 = CurrCand->lab[Spine[gom_level+1].tgtpos];
6379                                 i1 = tv->currorbit[j2];
6380                                 for (j=0; j < tv->nfix - gom_level; j++) {
6381                                     TreeNode = TreeNode->father;
6382                                 }
6383                                 TreeNode1 = TreeNode->first_child;
6384                                 while (TreeNode1) {
6385                                     if (TreeNode1->vtx == i1) {
6386                                         break;
6387                                     }
6388                                     TreeNode1 = TreeNode1->next_sibling;
6389                                 }
6390                                 if (TreeNode1) {
6391                                     while (TreeNode1->goes_to) {
6392                                         TreeNode1 = TreeNode1->goes_to;
6393                                     }
6394                                     TreeNode2 = TreeNode1->next_sibling;
6395                                     while (TreeNode2->vtx != j2) {
6396                                         TreeNode2 = TreeNode2->next_sibling;
6397                                     }
6398                                     TreeNode1->index += TreeNode2->index;
6399                                     TreeNode2->goes_to = TreeNode1;
6400                                     PRINT_INDEX(TreeNode1,4,25)
6401 
6402                                     ti->minimalinorbits = FALSE;
6403                                 }
6404                                 else {
6405                                     tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
6406                                 }
6407                             }
6408                         }
6409                         else {
6410                             tv->currorbit = findcurrorbits(gpB, tv->nfix);
6411                         }
6412                     }
6413                 else {
6414                     TempOrbits = WorkArray1;
6415                     memcpy(TempOrbits, IDENTITY_PERM, n*sizeof(int));
6416                     memcpy(TempOrbList, IDENTITY_PERM, n*sizeof(int));
6417 
6418                     tv->conta1++;
6419                     tv->currorbit = TempOrbits;
6420                 }
6421             }
6422             if (ti->minimalinorbits) {
6423                 memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
6424                 memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
6425                 tv->conta2++;
6426                 auxcode = CurrCand->code;
6427                 SpineTL->trcstart = CurrPart->cells;
6428                 TheTrace[SpineTL->trcstart] = SpineTL->tgtpos;
6429                 if (!CurrCand->sortedlab) {
6430                     quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
6431                     for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
6432                         CurrCand->invlab[CurrCand->lab[i]] = i;
6433                     }
6434                     CurrCand->sortedlab = TRUE;
6435                 }
6436 
6437                 tv->indivstart = tv->tcell+CurrCand->indnum;
6438                 tv->indivend = tv->indivstart+tv->steps;
6439                 if (tv->indivend > SpineTL->tgtend) {
6440                     tv->indivend = SpineTL->tgtend;
6441                 }
6442 
6443                 temp = CurrCand->lab[tv->indivstart];
6444                 for (k = tv->indivstart; k < tv->indivend; k++) {
6445                     CurrCand->indnum++;
6446                     NextCand->singcode = CurrCand->singcode;
6447                     NextCand->vertex = CurrCand->lab[k];
6448                     NextCand->name = ++tv->name;
6449                     if (NextCand->name == (NAUTY_INFINITY-2)) {
6450                         NextCand->name = tv->name = 1;
6451                     }
6452 
6453                     PRINT_INDIV_VERB(4,tv->tolevel)
6454                     if (tv->currorbit[NextCand->vertex] != NextCand->vertex) {
6455                         PRINT_SKIPPED_VERB(4)
6456 
6457                         search_vtx = tv->currorbit[NextCand->vertex];
6458                         TreeNode = CurrCand->stnode;
6459                         if (TreeNode->first_child) {
6460                             TreeNode = TreeNode->first_child;
6461                             while (TreeNode) {
6462                                 if (TreeNode->vtx == search_vtx) {
6463                                     break;
6464                                 }
6465                                 TreeNode = TreeNode->next_sibling;
6466                             }
6467                             if (TreeNode) {
6468                                 while (TreeNode->goes_to) {
6469                                     TreeNode = TreeNode->goes_to;
6470                                 }
6471                                 TreeNode->index++;
6472                                 PRINT_INDEX(TreeNode,4,26)
6473                                 continue;
6474                             }
6475                         }
6476                     }
6477                     else {
6478                         PRINT_REFINE_VERB(4,'a')
6479 
6480                         memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
6481                         memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
6482 
6483                         tv->conta3++;
6484 
6485                         if (NextPart->cls[tv->tcell] == 2) {
6486                             num_indv = 2;
6487                             NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell]);
6488                             NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell+1]);
6489                             if (SpineTL->singstart == SpineTL->singend) {
6490                                 Singletons[SpineTL->singend++] = tv->tcell;
6491                                 Singletons[SpineTL->singend++] = tv->tcell+1;
6492                             }
6493                         }
6494                         else {
6495                             num_indv = 1;
6496                             NextCand->singcode = MASHCOMM(NextCand->singcode, NextCand->vertex);
6497                             if (SpineTL->singstart == SpineTL->singend) {
6498                                 Singletons[SpineTL->singend++] = tv->tcell + NextPart->cls[tv->tcell] - 1;
6499                             }
6500                         }
6501 
6502                         Individualize(NextPart, NextCand, NextCand->vertex, tv->tcell, CurrPart->cells, SpineTL->tgtpos);
6503                         tv->stats->numnodes++;
6504                         tv->answ = traces_refine(NextCand,
6505                                                  n,
6506                                                  NextPart, tv, ti, num_indv, TRUE);
6507                         switch (tv->answ) {
6508                             case 0:                /* Interrupted refinement: do not add to the list */
6509                                 tv->stats->interrupted++;
6510                                 SpineTL->levelcounter++;
6511                                 break;
6512                             case 1 :            /* The same trace has been found once more : add to the list */
6513                                 SpineTL->levelcounter++;
6514 
6515                                 NextCand->do_it = TRUE;
6516                                 if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel);
6517 
6518                                 tv->tolevel_tl = tv->tolevel;
6519                                 NextCand->pathsingcode = NextCand->singcode;
6520                                 NextCand->firstsingcode = 0;
6521 
6522                                 if (tv->steps > 1) {
6523                                     if (tv->fromlevel <= tv->lev_of_lastauto) {
6524 
6525                                         closeloop = CheckForMatching(CurrCand, NextCand, NextPart, tv, ti, m, n);
6526                                     }
6527                                     if (NextCand->do_it) {
6528                                         firstsing = TRUE;
6529 
6530                                         /* EXPERIMENTAL PATH */
6531                                         if (NextPart->cells != tv->finalnumcells) {    /* 160712 */
6532                                             if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
6533                                             while (NextPart->cells < n) {
6534                                                 if (firstsing && BreakSteps[tv->tolevel]) {
6535                                                     firstsing = FALSE;
6536                                                     NextCand->firstsingcode = NextCand->pathsingcode;
6537                                                     if (CheckForSingAutomorphisms(CurrCand, NextPart, NextCand, tv, ti, m, n))
6538                                                         if (!NextCand->do_it) {
6539                                                             break;
6540                                                         }
6541                                                 }
6542 
6543                                                 has_nexttcell = TargetCellExpPath(NextCand, NextPart, tv);
6544 
6545                                                 if (!has_nexttcell) {
6546                                                     NextCand->firstsingcode = NextCand->pathsingcode;
6547                                                     if (tv->options->verbosity >= 2) {
6548                                                         if (tv->tolevel_tl-tv->tolevel >= 6) {
6549                                                             PRINT_EXPPATHSTEP(NextCand, TRUE)
6550                                                         }
6551                                                         else {
6552                                                             fprintf(outfile, "(%d) ", tv->tolevel_tl);
6553                                                         }
6554                                                     }
6555                                                     break;
6556                                                 }
6557                                                 ExperimentalStep(NextPart, NextCand, tv, ti, m, n);
6558                                                 if (NextPart->cells == n) {
6559                                                     has_nexttcell = FALSE;
6560                                                 }
6561                                                 PRINT_EXPPATHSTEP(NextCand, TRUE)
6562                                             }
6563                                             if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
6564                                         }
6565                                     }
6566                                     else {
6567                                         if (closeloop < tv->tolevel) k = SpineTL->tgtend;
6568                                         PRINT_RETURN
6569                                         break;
6570                                     }
6571 
6572                                     if (!tv->strategy && !tv->options->getcanon && (tv->tolevel_tl == tv->tolevel + 1) && ((NextPart->cells > tv->finalnumcells) || (NextPart->cells == n))) {    /* 160717 */
6573                                         tv->levelfromCS0 = tv->tolevel;
6574                                         tv->maxtreelevel = tv->tolevel_tl;
6575                                         tv->finalnumcells = NextPart->cells;
6576                                         if (tv->tolevel == 1) {
6577                                             tv->newst_stage1 = searchtrie_make(CurrCand, NextCand, n, tv);
6578                                             EXITFROMSTAGE0EXPATH1
6579                                         }
6580                                         else {
6581                                             temp = 0;
6582                                             for (i=0; i<tv->tolevel; i++) {
6583                                                 temp += Spine[i].listcounter;
6584                                             }
6585                                             if (temp > 5) {
6586                                                 tv->newst_stage1 = searchtrie_make(CurrCand, NextCand, n, tv);
6587                                                 EXITFROMSTAGE0EXPATH1
6588                                             }
6589                                         }
6590                                     }
6591 
6592                                     /* ANY AUTOMORPHISM? */
6593                                     if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
6594                                     tv->newindex = 0;
6595                                     if (NextCand->do_it) {
6596                                         closeloop = CheckForAutomorphisms(CurrCand, NextCand, tv, ti, m, n, NextPart);
6597                                         if (!NextCand->do_it && closeloop < tv->tolevel) k = SpineTL->tgtend;
6598                                     }
6599                                     if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
6600 
6601                                     if (NextCand->do_it) {
6602                                         ADDTONEXTLEVEL;
6603                                         SpineTL->keptcounter++;
6604                                         searchtrie_make(CurrCand, SpineTL->listend, n, tv);
6605                                     }
6606                                 }
6607                                 else {
6608                                     if (BreakSteps[tv->tolevel]) {
6609                                         NextCand->firstsingcode = NextCand->pathsingcode;
6610                                         if (CheckForSingAutomorphisms(CurrCand, NextPart, NextCand, tv, ti, m, n))
6611                                             if (!NextCand->do_it) {
6612                                                 PRINT_RETURN
6613                                                 break;
6614                                             }
6615                                     }
6616 
6617                                     /* ANY AUTOMORPHISM? */
6618                                     if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
6619                                     tv->newindex = 0;
6620                                     if (NextCand->do_it) {
6621                                         closeloop = CheckForAutomorphisms(CurrCand, NextCand, tv, ti, m, n, NextPart);
6622                                         if (!NextCand->do_it && closeloop < tv->tolevel) k = SpineTL->tgtend;
6623                                     }
6624                                     if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
6625 
6626                                     if (NextCand->do_it) {
6627                                         ADDTONEXTLEVEL;
6628                                         SpineTL->keptcounter++;
6629                                         searchtrie_make(CurrCand, SpineTL->listend, n, tv);
6630                                     }
6631                                 }
6632                                 PRINT_RETURN
6633                                 break;
6634                             case 2 :    /* Delete the old list and start a new one: a better trace has been found */
6635 
6636                                 if (NextPart->cells > tv->finalnumcells) {
6637                                     tv->finalnumcells = NextPart->cells;
6638                                 }
6639                                 tv->tolevel_tl = tv->tolevel;
6640                                 has_nexttcell = FALSE;
6641                                 if (NextPart->cells == n) {
6642                                     tv->stats->canupdates++;
6643                                     if (tv->options->usercanonproc != NULL)
6644                                     {
6645                                         (*tv->options->usercanonproc)((graph*)tv->input_graph, NextCand->lab, (graph*)tv->cangraph, tv->stats->canupdates, NextCand->code, m, n);
6646                                     }
6647                                 }
6648 
6649                                 if (tv->tolevel > tv->treedepth) {
6650                                     tv->treedepth = tv->tolevel;
6651                                     if (tv->strategy) {
6652                                         SpineTL->part = NewPartition(n);
6653                                     }
6654                                     else {
6655                                         NewPartSpine(tv->tolevel,n);
6656                                     }
6657                                 }
6658 
6659                                 if (!tv->strategy && (tv->tolevel > 1) && !SpineTL->liststart) {
6660                                     /* First Candidate at current level */
6661                                     tv->maxtreelevel = tv->tolevel;
6662 
6663                                     SpineTL->liststart = NewCandidate(n, &GarbList, TRUE);
6664                                     SpineTL->listend = SpineTL->liststart;
6665 
6666                                     tv->conta0++;
6667                                     CopyCand(SpineTL->liststart, NextCand, n, TEMPLAB, TEMPINVLAB);
6668                                     if (NextPart->cells < tv->finalnumcells) SpineTL->liststart->code = auxcode;
6669                                     COPYPART(SpineTL->part, NextPart);
6670                                     tv->newindex = 0;
6671                                     tv->newst_stage1 = searchtrie_make(CurrCand, SpineTL->listend, n, tv);
6672 
6673                                     SpineTL->listcounter = 1;
6674                                     SpTLliststart = SpineTL->liststart;
6675 
6676                                     i = tv->tolevel;
6677                                     if (tv->brkstpcount) {
6678                                         while ((i<n) && !BreakSteps[i]) {
6679                                             i++;
6680                                         }
6681                                         if (i<n) SpineTL->liststart->firstsingcode = Spine[i].singcode;
6682                                     }
6683 
6684                                     SpineTL->updates = 1;
6685                                     SpineTL->levelcounter = 1;
6686                                     SpineTL->keptcounter = 1;
6687 
6688                                     PRINT_LINE_PLUS(tv->fromlevel)
6689 
6690                                     if (tv->options->verbosity >= 2) PRINT_CANDIDATE(SpineTL->liststart, tv->tolevel);
6691                                     PRINT_RETURN;
6692 
6693                                     if (!tv->strategy && !tv->options->getcanon && (tv->tolevel+1 == tv->firstpathlength) && ((NextPart->cells > tv->finalnumcells) || (NextPart->cells == n))) {
6694                                         tv->finalnumcells = NextPart->cells;
6695                                         if ((tv->tolevel == 1) && (CurrPart->cls[tv->tcell] > 5)) {
6696                                             EXITFROMSTAGE0EXPATH2;
6697                                         }
6698                                         else {
6699                                             temp = 0;
6700                                             for (i=0; i<tv->tolevel; i++) {
6701                                                 temp += Spine[i].listcounter;
6702                                             }
6703                                             if (temp > 5) {
6704                                                 EXITFROMSTAGE0EXPATH2;
6705                                             }
6706                                         }
6707                                     }
6708                                 }
6709                                 else {
6710                                     memset(WorkArray, 0, n*sizeof(int));
6711 
6712                                     tv->lastcell = tv->lastlev = -1;
6713                                     has_nexttcell = TargetCellFirstPath(NextCand, NextPart, tv);
6714 
6715                                     if (!has_nexttcell) {
6716                                         tv->stats->canupdates++;
6717                                         if (tv->options->usercanonproc != NULL) {
6718                                             (*tv->options->usercanonproc)((graph*)tv->input_graph, NextCand->lab, (graph*)tv->cangraph, tv->stats->canupdates, NextCand->code, m, n);
6719                                         }
6720                                     }
6721 
6722                                     tv->tcellevel = tv->maxtreelevel = tv->tolevel;
6723                                     SpineTL->levelcounter++;
6724                                     SpineTL->updates++;
6725                                     SpineTL->keptcounter = 1;
6726 
6727                                     RemoveFromLevel(tv->tolevel, tv->treedepth, tv->strategy, TRUE);
6728                                     SpineTL->liststart = NewCandidate(n, &GarbList, TRUE);
6729                                     SpineTL->listend = SpineTL->liststart;
6730 
6731                                     tv->conta0++;
6732                                     CopyCand(SpineTL->liststart, NextCand, n, NULL, NULL);
6733                                     COPYPART(SpineTL->part, NextPart);
6734 
6735                                     tv->newindex = 0;
6736 
6737                                     tv->newst_stage1 = searchtrie_make(CurrCand, SpineTL->listend, n, tv);
6738 
6739                                     SpineTL->listcounter = 1;
6740                                     SpTLliststart = SpineTL->liststart;
6741 
6742                                     SpTLliststart->pathsingcode = SpineTL->singcode = SpTLliststart->singcode;
6743                                     SpTLliststart->firstsingcode = 0;
6744 
6745                                     PRINT_LINE
6746                                     if (tv->options->verbosity >= 2) PRINT_CANDIDATE(SpTLliststart, tv->tolevel);
6747 
6748                                     memset(BreakSteps, 0, n*sizeof(int));
6749                                     tv->brkstpcount = 0;
6750 
6751                                     if (tv->steps > 1) {
6752 
6753                                         /* EXPERIMENTAL PATH */
6754                                         if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
6755                                         PRINTF2("CStage0 2: %d\n", tv->finalnumcells);
6756                                         tv->finalnumcells = n;
6757 
6758                                         while (has_nexttcell) {
6759                                             ExperimentalStep(NextPart, SpTLliststart, tv, ti, m, n);
6760 
6761                                             Spine[tv->tolevel_tl].singcode = SpTLliststart->pathsingcode;
6762                                             has_nexttcell = TargetCellFirstPath(SpTLliststart, NextPart, tv);
6763                                             PRINT_EXPPATHSTEP(SpTLliststart, TRUE)
6764                                         }
6765                                         if (NextPart->cells < n) {
6766                                             PRINTF2("CStage0 3: %d\n", tv->finalnumcells);
6767                                             tv->finalnumcells = minint(NextPart->cells,tv->finalnumcells);    /* 160712 */
6768                                             tv->finalnumcells = NextPart->cells;
6769 
6770                                             PRINTF2("CStage0 3<: %d\n", tv->finalnumcells);
6771                                         }
6772 
6773                                         PRINTF2("CS0 2?: finalnumcells: %d\n", tv->finalnumcells);
6774                                         if (NextPart->cells == tv->finalnumcells) {
6775                                             UPDATEMIN(tv->expathlength, tv->tolevel_tl);
6776                                         }
6777 
6778                                         if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
6779 
6780                                         tv->firstpathlength = tv->tolevel_tl;
6781                                         PRINT_RETURN
6782                                         if (!tv->strategy && !tv->options->getcanon && (NextPart->cells == tv->finalnumcells) && (tv->tolevel_tl == tv->tolevel + 1) && ((NextPart->cells > tv->finalnumcells) || (NextPart->cells == n))) {
6783                                             tv->maxtreelevel = tv->tolevel_tl;
6784                                             tv->finalnumcells = NextPart->cells;
6785                                             if ((tv->tolevel == 1) && (CurrPart->cls[tv->tcell] > 5)) {
6786                                                 EXITFROMSTAGE0EXPATH2
6787                                             }
6788                                             else {
6789                                                 temp = 0;
6790                                                 for (i=0; i<tv->tolevel; i++) {
6791                                                     temp += Spine[i].listcounter;
6792                                                 }
6793                                                 if (temp > 5) {
6794                                                     EXITFROMSTAGE0EXPATH2
6795                                                 }
6796                                             }
6797                                         }
6798                                         memcpy(TEMPLAB, SpTLliststart->lab, n*sizeof(int));
6799                                         memcpy(TEMPINVLAB, SpTLliststart->invlab, n*sizeof(int));
6800                                         tv->conta5++;
6801                                     }
6802                                     else {
6803                                         PRINT_RETURN
6804                                     }
6805                                 }
6806 
6807                                 break;
6808                             default:
6809                                 break;
6810                         }
6811                     }
6812                 } /* end for */
6813             }
6814         }
6815     }
6816 
6817     /* REMOVE CURRENT CANDIDATE */
6818     if (SpineFL->liststart && (k >= SpineTL->tgtend)) {
6819         SpineFL->liststart = CurrCand->next;
6820         if (CurrCand->next == NULL) {
6821             SpineFL->listend = NULL;
6822         }
6823         SpineFL->listcounter--;
6824         CurrCand->next = GarbList;
6825         GarbList = CurrCand;
6826     }
6827     ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
6828     return 0;
6829 }
6830 
CompStage1(Partition * CurrPart,Partition * NextPart,Candidate * CurrCand,Candidate * NextCand,int m,int n,struct TracesVars * tv,struct TracesInfo * ti)6831 int CompStage1(Partition *CurrPart, Partition *NextPart, Candidate *CurrCand, Candidate *NextCand,
6832                int m, int n,
6833                struct TracesVars* tv, struct TracesInfo *ti) {
6834     int i, k, cu, cu1, tmp, gom_level, search_vtx, temp;
6835     searchtrie *TreeNode, *TrieNode;
6836 
6837 #ifdef NAUTY_IN_MAGMA
6838     if (main_seen_interrupt) return NAUTY_KILLED;
6839 #else
6840     if (nauty_kill_request) return NAUTY_KILLED;
6841 #endif
6842 
6843     CurrCand->stnode = tv->newst_stage1;
6844 
6845     tv->tolevel++;
6846     SpineTL = Spine+tv->tolevel;
6847     tv->tcell = SpineTL->tgtcell;
6848     SpineTL->levelcounter = 0;
6849     SpineTL->keptcounter = 0;
6850     SpineTL->updates = 1;
6851 
6852 
6853     if (tv->options->verbosity >= 2) {
6854         LINE(32, "=")
6855         NEXTLINE
6856     }
6857 
6858     memset(RefCells, 0, n*sizeof(int));
6859     memset(MultRefCells, 0, n*sizeof(int));
6860     ti->thegrouphaschanged = TRUE;
6861 
6862     /*  CANDIDATE */
6863     memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
6864     memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
6865     NextCand->do_it = TRUE;
6866     SpineTL->trcstart = CurrPart->cells;
6867 
6868     tv->indivstart = tv->tcell;
6869     tv->indivend = SpineTL->tgtend;
6870     if (TheGraph[CurrCand->lab[tv->indivstart]].d == 1) {
6871         tv->indivstart = SpineTL->tgtend-1;
6872     }
6873 
6874     FixBase(fix, tv, NextCand, 0, tv->fromlevel);
6875 
6876     if (!ti->identitygroup) {
6877         if (tv->options->verbosity >= 2) tv->schreier2 -= CPUTIME;
6878         tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
6879         if (tv->options->verbosity >= 2) tv->schreier2 += CPUTIME;
6880     }
6881     else {
6882         memcpy(tv->currorbit, IDENTITY_PERM, n*sizeof(int));
6883     }
6884 
6885     if (!CurrCand->sortedlab) {
6886         quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
6887         for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
6888             CurrCand->invlab[CurrCand->lab[i]] = i;
6889         }
6890         CurrCand->sortedlab = TRUE;
6891     }
6892     for (k = tv->indivstart; k < tv->indivend; k++) {
6893         NextCand->vertex = CurrCand->lab[k];
6894         NextCand->name = ++tv->name;
6895         if (NextCand->name == (NAUTY_INFINITY-2)) {
6896             NextCand->name = tv->name = 1;
6897         }
6898         if (tv->currorbit[CurrCand->lab[k]] != CurrCand->lab[k]) {
6899             search_vtx = tv->currorbit[NextCand->vertex];
6900             TreeNode = CurrCand->stnode;
6901             if (TreeNode->first_child) {
6902                 TreeNode = TreeNode->first_child;
6903                 while (TreeNode) {
6904                     if (TreeNode->vtx == search_vtx) {
6905                         break;
6906                     }
6907                     TreeNode = TreeNode->next_sibling;
6908                 }
6909                 if (TreeNode) {
6910                     while (TreeNode->goes_to) {
6911                         TreeNode = TreeNode->goes_to;
6912                     }
6913                     TreeNode->index++;
6914                     PRINT_INDEX(TreeNode,4,27)
6915                 }
6916             }
6917             continue;
6918         }
6919         PRINT_REFINE_VERB(4,'b')
6920         memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
6921         memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
6922 
6923         Individualize(NextPart, NextCand, CurrCand->lab[k], tv->tcell, CurrPart->cells, SpineTL->tgtpos);
6924 
6925         tv->stats->numnodes++;
6926         SpineTL->levelcounter++;
6927         tv->tolevel_tl = tv->tolevel;
6928         trieref = trieroot;
6929         SpineTL->levelcounter++;
6930 
6931         traces_refine_maketrie(NextCand,
6932                                n,
6933                                NextPart, tv, ti);
6934 
6935         RefCells[CurrCand->lab[k]] = NextPart->cells;
6936         PRINTF2("CS1 1?: finalnumcells: %d\n", tv->finalnumcells);
6937         if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
6938             if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel);
6939 
6940             /* ANY AUTOMORPHISM? */
6941             if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
6942 
6943             PRINTF2("CS1 2?: finalnumcells: %d\n", tv->finalnumcells);
6944             CheckForAutomorphisms(CurrCand, NextCand, tv, ti, m, n, NextPart);
6945             if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
6946 
6947             PRINT_RETURN
6948 
6949             /* ADD TO NEXT LEVEL */
6950             SpineTL->keptcounter++;
6951             if (!Spine[tv->tolevel].listend) COPYPART(Spine[tv->tolevel].part, NextPart);
6952             ADDTONEXTLEVEL;
6953             searchtrie_make(CurrCand, SpineTL->listend, n, tv);
6954         }
6955     } /* end for */
6956     PRINTF2("CS1 3: finalnumcells: %d\n", tv->finalnumcells);
6957     for (k = tv->indivstart; k < tv->indivend; k++) {
6958         MultRefCells[RefCells[tv->currorbit[CurrCand->lab[k]]] % n]++;
6959     }
6960 
6961     if (tv->options->verbosity >= 2) {
6962         if (MultRefCells[0]) {
6963             fprintf(outfile, tv->digstring, n);
6964             fprintf(outfile, "cells: %d; ", MultRefCells[0]);
6965         }
6966         for (k=1; k<n; k++) {
6967             if (MultRefCells[k]) {
6968                 fprintf(outfile, tv->digstring, k);
6969                 fprintf(outfile, "cells: %d; ", MultRefCells[k]);
6970             }
6971         }
6972         NEXTLINE
6973 
6974     }
6975 
6976 #if !MAXN
6977     DYNALLOC1(searchtrie*, RefPath, RefPath_sz, tv->tolevel, "Traces-CS1");
6978 #endif
6979 
6980     TreeNode = CurrCand->stnode;
6981     while (TreeNode) {
6982         RefPath[TreeNode->level] = TreeNode;
6983         TreeNode = TreeNode->father;
6984     }
6985 
6986     /* REMOVE CURRENT CANDIDATE */
6987     SpineFL->liststart = CurrCand->next;
6988     if (CurrCand->next == NULL) {
6989         SpineFL->listend = NULL;
6990         SpineFL->listcounter = 1;
6991     }
6992     SpineFL->listcounter--;
6993     CurrCand->next = GarbList;
6994     GarbList = CurrCand;
6995 
6996     if (tv->options->verbosity >= 2) {
6997         LINE(32, "=")
6998         NEXTLINE
6999     }
7000     tv->compstage = 2;
7001     tv->steps = n;
7002 
7003     if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
7004 
7005     gom_level = getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit,
7006                              CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell], n, TRUE);
7007     if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
7008     ORBITSIZES
7009     ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
7010     PRINTF2("CS1 4: finalnumcells: %d\n", tv->finalnumcells);
7011     SpineTL->part->cells = tv->finalnumcells;
7012 
7013     AutomCount[0] = 2;
7014     AutomCount[1] = CurrCand->vertex;
7015 
7016     return 0;
7017 }
7018 
CompStage2(Partition * CurrPart,Partition * NextPart,Candidate * CurrCand,Candidate * NextCand,int m,int n,struct TracesVars * tv,struct TracesInfo * ti)7019 int CompStage2(Partition *CurrPart, Partition *NextPart, Candidate *CurrCand, Candidate *NextCand,
7020                int m, int n,
7021                struct TracesVars* tv, struct TracesInfo *ti) {
7022     int i, j, i1, j2, k, cu, cu1, vertex, gom_level;
7023     int temp, tmp, autom;
7024     Candidate *AuxCand;
7025     searchtrie *TreeNode, *TreeNode1, *TreeNode2;
7026     int *CuOrb,*AuxOrb;
7027     boolean has_nexttcell = FALSE;
7028     searchtrie *TrieNode;
7029     boolean schreierwrong;
7030 
7031 #ifdef NAUTY_IN_MAGMA
7032     if (main_seen_interrupt) return NAUTY_KILLED;
7033 #else
7034     if (nauty_kill_request) return NAUTY_KILLED;
7035 #endif
7036 
7037     autom = 0;
7038     schreierwrong = FALSE;
7039 
7040     TreeNode = CurrCand->stnode;
7041     tv->cand_level = 0;
7042 
7043     while (TreeNode) {
7044         if (TreeNode->goes_to) {
7045             CurrCand->do_it = FALSE;
7046         }
7047         if (!tv->cand_level && TreeNode == RefPath[TreeNode->level]) {
7048             tv->cand_level = TreeNode->level;
7049         }
7050         TreeNode = TreeNode->father;
7051     }
7052     if (tv->cand_level+1 == tv->maxtreelevel) {
7053         ti->useTempOrbits1 = TRUE;
7054     }
7055     else {
7056         ti->useTempOrbits1 = FALSE;
7057     }
7058     if (tv->cand_level == tv->fromlevel) {
7059         ti->useTempOrbits2 = TRUE;
7060     }
7061     else {
7062         ti->useTempOrbits2 = FALSE;
7063     }
7064 
7065     PRINT_FROM_VERB(4,tv->tolevel)
7066 
7067     if (CurrCand->do_it) {
7068         if (tv->tolevel == 0) {
7069             vertex = Spine[tv->maxtreelevel+1].liststart->lab[Spine[1].tgtpos];
7070             k = n;
7071 
7072             tv->fromlevel = tv->tolevel++;
7073             SpineFL = Spine+tv->fromlevel;
7074             SpineTL = Spine+tv->tolevel;
7075             tv->tcell = Spine[tv->tolevel].tgtcell;
7076 
7077             memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
7078             memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
7079             SpineTL->trcstart = CurrPart->cells;
7080             TheTrace[SpineTL->trcstart] = SpineTL->tgtpos;
7081 
7082             tv->indivstart = tv->tcell+CurrCand->indnum;
7083             tv->indivend = tv->indivstart+tv->steps;
7084             if (tv->indivend > SpineTL->tgtend) {
7085                 tv->indivend = SpineTL->tgtend;
7086             }
7087             memset(CurrRefCells, 0, n*sizeof(int));
7088             ti->thegrouphaschanged = TRUE;
7089 
7090             if (!CurrCand->sortedlab) {
7091                 quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
7092                 for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
7093                     CurrCand->invlab[CurrCand->lab[i]] = i;
7094                 }
7095                 CurrCand->sortedlab = TRUE;
7096             }
7097 
7098             for (k = tv->indivstart; k < tv->indivend; k++) {
7099                 if ((tv->orbits[CurrCand->lab[k]] == CurrCand->lab[k]) && ((tv->finalnumcells < n) || (OrbSize[tv->orbits[CurrCand->lab[k]]] >= OrbSize[tv->orbits[vertex]]))) {
7100 
7101                     CurrCand->indnum++;
7102                     NextCand->singcode = CurrCand->singcode;
7103                     NextCand->vertex = CurrCand->lab[k];
7104                     NextCand->name = ++tv->name;
7105                     if (NextCand->name == (NAUTY_INFINITY-2)) {
7106                         NextCand->name = tv->name = 1;
7107                     }
7108 
7109                     if (ti->thegrouphaschanged) {
7110                         if (tv->fromlevel == tv->maxtreelevel) {
7111                             CURRORBITSIZES
7112                         }
7113                         ti->thegrouphaschanged = FALSE;
7114                     }
7115 
7116                     if (tv->currorbit[CurrCand->lab[k]] != CurrCand->lab[k]) {
7117                         continue;
7118                     }
7119 
7120                     memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
7121                     memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
7122                     if (NextPart->cls[tv->tcell] == 2) {
7123                         NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell]);
7124                         NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell+1]);
7125                     }
7126                     else {
7127                         NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[k]+labelorg);
7128                     }
7129 
7130                     Individualize(NextPart, NextCand, CurrCand->lab[k], tv->tcell, CurrPart->cells, SpineTL->tgtpos);
7131 
7132                     tv->stats->numnodes++;
7133                     Spine[tv->tolevel+1].levelcounter++;
7134                     if (tv->fromlevel == tv->maxtreelevel) {
7135                         tv->tolevel_tl = tv->tolevel;
7136                         trieref = trieroot;
7137 
7138                         tv->answ = traces_refine_comptrie(NextCand,
7139                                                           n,
7140                                                           NextPart, tv, ti);
7141                         if (tv->answ) {
7142                             if (NextPart->cells != tv->finalnumcells) {
7143                                 CurrRefCells[NextPart->cells % n] += CurrOrbSize[CurrCand->lab[k]];
7144                                 if (CurrRefCells[NextPart->cells % n] > MultRefCells[NextPart->cells % n]) {
7145                                     k = n;
7146                                     break;
7147                                 }
7148                                 continue;
7149                             }
7150                             if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel)
7151                                 }
7152                     }
7153                     else {
7154                         tv->answ = traces_refine_sametrace(NextCand,
7155                                                            n,
7156                                                            NextPart, tv, ti);
7157 
7158                         if (tv->answ) {
7159                             if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel)
7160                                 if (tv->tolevel == tv->maxtreelevel) {
7161                                     tv->tolevel_tl = tv->tolevel;
7162                                     if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
7163                                     TargetCellExpPath(NextCand, NextPart, tv);
7164                                     ExperimentalStep(NextPart, NextCand, tv, ti, m, n);
7165                                     PRINT_EXPPATHSTEP(NextCand, tv->answ)
7166                                     PRINTF2("CS2 1?: finalnumcells: %d\n", tv->finalnumcells);
7167                                     if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
7168                                         UPDATEMIN(tv->expathlength, tv->tolevel_tl);
7169                                     }
7170 
7171                                     if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
7172                                     if (!tv->answ) {
7173                                         PRINT_RETURN
7174                                     }
7175                                 }
7176                         }
7177                     }
7178                     if (tv->answ) {
7179                         PRINTF2("CS2 2?: finalnumcells: %d\n", tv->finalnumcells);
7180                         if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
7181                             if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
7182                             temp = (tv->tolevel_tl == tv->tolevel+1);
7183                             autom = CheckForAutomorphisms(CurrCand, NextCand,
7184                                                           tv, ti, temp, n, NextPart);
7185                             if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
7186 
7187                             if (ti->thegrouphaschanged) {
7188                                 ORBITSIZES
7189                             }
7190                         }
7191                         PRINT_RETURN
7192 
7193                         /* ADD TO NEXT LEVEL */
7194                         PRINTF2_2("CS2 3?: cells: %d, finalnumcells: %d\n", NextPart->cells, tv->finalnumcells);
7195                         if ((NextPart->cells != tv->finalnumcells) || (tv->tolevel != tv->maxtreelevel) || (tv->tolevel_tl != tv->tolevel+1)) {
7196                             ADDTONEXTLEVEL;
7197                             searchtrie_make(CurrCand, SpineTL->listend, n, tv);
7198                         }
7199                     }
7200                     else {
7201                         tv->stats->interrupted++;
7202                     }
7203                     if (tv->fromlevel == tv->maxtreelevel) {
7204                         k = n;
7205                         break;
7206                     }
7207                 }
7208             } /* end for */
7209         }
7210         else {
7211 
7212             temp = CurrCand->lab[Spine[1].tgtpos];
7213             vertex = Spine[tv->maxtreelevel+1].liststart->lab[Spine[1].tgtpos];
7214             k = n;
7215 
7216             if (tv->cand_level ||
7217                 ((tv->orbits[temp] == temp) && ((tv->finalnumcells < n) || (OrbSize[tv->orbits[temp]] >= OrbSize[tv->orbits[vertex]])))) {
7218                 tv->fromlevel = tv->tolevel++;
7219                 SpineFL = Spine+tv->fromlevel;
7220                 SpineTL = Spine+tv->tolevel;
7221                 tv->tcell = Spine[tv->tolevel].tgtcell;
7222 
7223                 ti->minimalinorbits = TRUE;
7224 
7225                 if (!ti->identitygroup) {
7226 
7227                     if (ti->useTempOrbits1 && ti->useTempOrbits2) {
7228                         CuOrb = TempOrbits;
7229                     }
7230                     else {
7231                         FixBase(fix, tv, CurrCand, 0, tv->fromlevel);
7232                         if (ti->useTempOrbits1 && tv->fromlevel == tv->maxtreelevel) {
7233                             tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
7234                             CuOrb = tv->currorbit;
7235                         }
7236                         else {
7237                             if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
7238 
7239                             gom_level = getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit,
7240                                                      CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell], n, TRUE);
7241                             if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
7242 
7243                             CuOrb = tv->currorbit;
7244                             if (gom_level < tv->nfix) {
7245                                 PRINT_NOTMIN_VERB(4)
7246                                 if (ti->useTempOrbits1) {
7247                                     for (i=1; i<AutomCount[0]; i++) if (AutomCount[i] == CuOrb[tv->currorbit[CurrCand->vertex]]) break;
7248                                     if (i < AutomCount[0]) {
7249                                         AutomCount[AutomCount[0]++] = CurrCand->vertex;
7250                                     }
7251                                     ti->minimalinorbits = FALSE;
7252                                 }
7253                                 else {
7254                                     TreeNode = CurrCand->stnode;
7255                                     j2 = CurrCand->lab[Spine[gom_level+1].tgtpos];
7256                                     i1 = tv->currorbit[j2];
7257                                     for (j=0; j < tv->nfix - gom_level; j++) {
7258                                         TreeNode = TreeNode->father;
7259                                     }
7260                                     TreeNode1 = TreeNode->first_child;
7261                                     while (TreeNode1) {
7262                                         if (TreeNode1->vtx == i1) {
7263                                             break;
7264                                         }
7265                                         TreeNode1 = TreeNode1->next_sibling;
7266                                     }
7267                                     schreierwrong = FALSE;
7268                                     if (TreeNode1) {
7269                                         while (TreeNode1->goes_to) {
7270                                             TreeNode1 = TreeNode1->goes_to;
7271                                         }
7272                                         TreeNode2 = TreeNode->first_child;
7273                                         while (TreeNode2->vtx != j2) {
7274                                             TreeNode2 = TreeNode2->next_sibling;
7275                                         }
7276 
7277                                         TreeNode1->index += TreeNode2->index;
7278                                         TreeNode2->goes_to = TreeNode1;
7279                                         PRINT_INDEX(TreeNode1,4,28)
7280                                         PRINT_INDEX(TreeNode2,4,29)
7281                                         ti->minimalinorbits = FALSE;
7282                                     }
7283                                     else {
7284                                         tv->currorbit = getorbits(fix, tv->nfix, gpB, &gensB, n);
7285                                         schreierwrong = TRUE;
7286                                     }
7287                                 }
7288                             }
7289                         }
7290                     }
7291                     ti->thegrouphaschanged = FALSE;
7292                 }
7293                 else {
7294                     CuOrb = IDENTITY_PERM;
7295                 }
7296 
7297                 if (ti->minimalinorbits) {
7298                     memcpy(NextCand->lab, CurrCand->lab, n*sizeof(int));
7299                     memcpy(NextCand->invlab, CurrCand->invlab, n*sizeof(int));
7300                     SpineTL->trcstart = CurrPart->cells;
7301                     TheTrace[SpineTL->trcstart] = SpineTL->tgtpos;
7302 
7303                     tv->indivstart = tv->tcell+CurrCand->indnum;
7304                     tv->indivend = tv->indivstart+tv->steps;
7305                     if (tv->indivend > SpineTL->tgtend) {
7306                         tv->indivend = SpineTL->tgtend;
7307                     }
7308                     memset(CurrRefCells, 0, n*sizeof(int));
7309                     ti->thegrouphaschanged = TRUE;
7310 
7311                     if (!CurrCand->sortedlab) {
7312                         quickSort(CurrCand->lab+tv->tcell, CurrPart->cls[tv->tcell]);
7313                         for (i=tv->tcell; i<tv->tcell+CurrPart->cls[tv->tcell]; i++) {
7314                             CurrCand->invlab[CurrCand->lab[i]] = i;
7315                         }
7316                         CurrCand->sortedlab = TRUE;
7317                     }
7318 
7319                     for (k = tv->indivstart; k < tv->indivend; k++) {
7320                         CurrCand->indnum++;
7321                         NextCand->singcode = CurrCand->singcode;
7322                         NextCand->vertex = CurrCand->lab[k];
7323                         NextCand->name = ++tv->name;
7324                         if (NextCand->name == (NAUTY_INFINITY-2)) {
7325                             NextCand->name = tv->name = 1;
7326                         }
7327 
7328                         if (ti->thegrouphaschanged) {
7329                             if (tv->fromlevel == tv->maxtreelevel) {
7330                                 CURRORBITSIZES
7331                             }
7332                             ti->thegrouphaschanged = FALSE;
7333                         }
7334 
7335                         if (!schreierwrong) {
7336                             if (CuOrb[CurrCand->lab[k]] != CurrCand->lab[k]) {
7337                                 continue;
7338                             }
7339                         }
7340 
7341                         memcpy(NextPart->cls, CurrPart->cls, n*sizeof(int));
7342                         memcpy(NextPart->inv, CurrPart->inv, n*sizeof(int));
7343                         if (NextPart->cls[tv->tcell] == 2) {
7344                             NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell]);
7345                             NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[tv->tcell+1]);
7346                         }
7347                         else {
7348                             NextCand->singcode = MASHCOMM(NextCand->singcode, CurrCand->lab[k]);
7349                         }
7350 
7351                         Individualize(NextPart, NextCand, CurrCand->lab[k], tv->tcell, CurrPart->cells, SpineTL->tgtpos);
7352 
7353                         tv->stats->numnodes++;
7354                         Spine[tv->tolevel+1].levelcounter++;
7355                         if (tv->fromlevel == tv->maxtreelevel) {
7356                             tv->tolevel_tl = tv->tolevel;
7357                             trieref = trieroot;
7358 
7359                             tv->answ = traces_refine_comptrie(NextCand,
7360                                                               n,
7361                                                               NextPart, tv, ti);
7362 
7363                             if (tv->answ) {
7364                                 PRINTF2("CS2 4?: finalnumcells: %d\n", tv->finalnumcells);
7365                                 if (NextPart->cells != tv->finalnumcells) {
7366                                     CurrRefCells[NextPart->cells % n] += CurrOrbSize[CurrCand->lab[k]];
7367                                     if (CurrRefCells[NextPart->cells % n] > MultRefCells[NextPart->cells % n]) {
7368                                         k = n;
7369                                         break;
7370                                     }
7371                                     continue;
7372                                 }
7373                                 if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel);
7374                             }
7375                         }
7376                         else
7377                         {
7378                             tv->answ = traces_refine_sametrace(NextCand,
7379                                                                n,
7380                                                                NextPart, tv, ti);
7381 
7382                             if (tv->answ) {
7383                                 if (tv->options->verbosity >= 2) PRINT_CANDIDATE(NextCand, tv->tolevel)
7384                                     if (tv->tolevel == tv->maxtreelevel) {
7385                                         tv->tolevel_tl = tv->tolevel;
7386                                         if (tv->options->verbosity >= 2) tv->expaths -= CPUTIME;
7387                                         if (TargetCellExpPath(NextCand, NextPart, tv)) {
7388                                             ExperimentalStep(NextPart, NextCand, tv, ti, m, n);
7389                                             PRINT_EXPPATHSTEP(NextCand, tv->answ)
7390                                             PRINTF2("CS2 5?: finalnumcells: %d\n", tv->finalnumcells);
7391                                             if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
7392                                                 UPDATEMIN(tv->expathlength, tv->tolevel_tl);
7393                                             }
7394 
7395                                         }
7396                                         if (tv->options->verbosity >= 2) tv->expaths += CPUTIME;
7397                                         if (!tv->answ) {
7398                                             PRINT_RETURN
7399                                         }
7400                                     }
7401                             }
7402                         }
7403                         if (tv->answ) {
7404                             PRINTF2("CS2 6?: finalnumcells: %d\n", tv->finalnumcells);
7405                             if ((NextPart->cells == tv->finalnumcells) || (NextPart->cells == n)) {
7406                                 if (tv->options->verbosity >= 2) tv->autchk -= CPUTIME;
7407                                 temp = (tv->tolevel_tl == tv->tolevel+1);
7408                                 autom = CheckForAutomorphisms(CurrCand, NextCand,
7409                                                               tv, ti, temp, n, NextPart);
7410                                 if (tv->options->verbosity >= 2) tv->autchk += CPUTIME;
7411                                 if (autom) {
7412                                     for (i=autom; i<=tv->maxtreelevel; i++) {
7413                                         AuxCand = Spine[i].liststart;
7414                                         while (AuxCand && Prefix(AuxCand, NextCand, autom)) {
7415                                             AuxCand->do_it = FALSE;
7416                                             AuxCand = AuxCand->next;
7417                                         }
7418                                     }
7419                                     if (autom == tv->tolevel) {
7420                                         autom = 0;
7421                                     }
7422                                 }
7423 
7424                                 if (ti->thegrouphaschanged) {
7425                                     ORBITSIZES
7426                                 }
7427                             }
7428                             PRINT_RETURN
7429 
7430                             /* ADD TO NEXT LEVEL */
7431                             PRINTF2("CS2 7?: finalnumcells: %d\n", tv->finalnumcells);
7432                             if ((NextPart->cells != tv->finalnumcells) || (tv->tolevel != tv->maxtreelevel) || (tv->tolevel_tl != tv->tolevel+1)) {
7433                                 ADDTONEXTLEVEL;
7434                                 searchtrie_make(CurrCand, SpineTL->listend, n, tv);
7435                             }
7436                         }
7437                         else {
7438                             tv->stats->interrupted++;
7439                         }
7440                         if (autom) {
7441                             k = n;
7442                             autom = 0;
7443                             break;
7444                         }
7445                         if (tv->fromlevel == tv->maxtreelevel) {
7446                             k = n;
7447                             break;
7448                         }
7449                     } /* end for */
7450                     TreeNode = RefPath[tv->maxtreelevel];
7451                 }
7452             }
7453             else SpineTL = &Spine[tv->tolevel+1];
7454         }
7455 
7456     }
7457 
7458     /* REMOVE CURRENT CANDIDATE */
7459     if (!CurrCand->do_it || k >= SpineTL->tgtend) {
7460         SpineFL->liststart = CurrCand->next;
7461         if (CurrCand->next == NULL) {
7462             SpineFL->listend = NULL;
7463         }
7464         CurrCand->next = GarbList;
7465         GarbList = CurrCand;
7466     }
7467     ti->thereisnextlevel = SelectNextLevel(n, tv, ti);
7468     return 0;
7469 }
7470 
CopyCand(Candidate * W,Candidate * V,int n,int * lab,int * invlab)7471 void CopyCand(Candidate *W, Candidate *V,int n, int *lab, int *invlab) {
7472 
7473     if (lab) {
7474         memcpy(W->lab, lab, n*sizeof(int));
7475         memcpy(W->invlab, invlab, n*sizeof(int));
7476     }
7477     else {
7478         memcpy(W->lab, V->lab, n*sizeof(int));
7479         memcpy(W->invlab, V->invlab, n*sizeof(int));
7480     }
7481     W->name = V->name;
7482     W->vertex = V->vertex;
7483     W->code = V->code;
7484     W->singcode = V->singcode;
7485     W->firstsingcode = V->firstsingcode;
7486     W->do_it = V->do_it;
7487     W->sortedlab = FALSE;
7488 }
7489 
copy_sg_structure(sparsegraph * sg2,sparsegraph * sg1)7490 sparsegraph* copy_sg_structure(sparsegraph *sg2, sparsegraph *sg1) {
7491     int *d1, *e1, *d2, *e2;
7492     int i, n;
7493     size_t *v1, *v2, k;
7494 
7495     if (!sg2)
7496     {
7497         if ((sg2 = (sparsegraph*)ALLOCS(1, sizeof(sparsegraph))) == NULL)
7498         {
7499             fprintf(ERRFILE, "copy_sg: malloc failed\n");
7500             exit(1);
7501         }
7502         SG_INIT(*sg2);
7503     }
7504 
7505     SG_VDE(sg1, v1, d1, e1);
7506 
7507     n = sg1->nv;
7508 
7509     k = 0;
7510     for (i = 0; i < n; ++i)
7511         if (v1[i]+d1[i]>k) k = v1[i] + d1[i];
7512     SG_ALLOC(*sg2, n, k, "copy_sg malloc");
7513 
7514     sg2->nv = n;
7515     sg2->nde = sg1->nde;
7516     sg2->elen = k;
7517     /* sg2->wlen = k; */
7518     return sg2;
7519 }
7520 
Edge_Delete(int vertex,int sons,Candidate * Cand,TracesVars * tv)7521 void Edge_Delete(int vertex, int sons, Candidate *Cand, TracesVars *tv) {
7522     int d_vtx, j1, temp;
7523     int *sge, *sgw;
7524 
7525     if (TheGraph[vertex].d <= 1) {
7526         return;
7527     }
7528 
7529     d_vtx = TheGraph[vertex].d = TheGraph[vertex].d - sons;
7530     sge = TheGraph[vertex].e;
7531     sgw = TheGraph[vertex].w;
7532 
7533     for (j1=0; j1<d_vtx; j1++) {
7534         if (TheGraph[sge[j1]].one) {
7535             while (TheGraph[sge[TheGraph[vertex].d]].d == -1) {
7536                 (TheGraph[vertex].d)++;
7537             }
7538             temp = sge[j1];
7539             sge[j1] = sge[TheGraph[vertex].d];
7540             sge[TheGraph[vertex].d] = temp;
7541             if (sgw) {
7542                 temp = sgw[j1];
7543                 sgw[j1] = sgw[TheGraph[vertex].d];
7544                 sgw[TheGraph[vertex].d] = temp;
7545             }
7546         }
7547     }
7548     TheGraph[vertex].d = d_vtx;
7549 }
7550 
ExperimentalStep(Partition * NextPart,Candidate * NextCand,TracesVars * tv,TracesInfo * ti,int m,int n)7551 void ExperimentalStep(Partition *NextPart, Candidate *NextCand,
7552                       TracesVars *tv, TracesInfo *ti, int m, int n) {
7553     int i, iend, min, tmp;
7554 
7555     SpineTL_tl = Spine+tv->tolevel_tl;
7556     NextPart->active = 1;
7557     VERB_PRINT("EXSTP ",3,FALSE)
7558     if (SpineTL_tl) {
7559     }
7560 
7561     /* EXPERIMENTAL PATH INDIVIDUALIZATION AND REFINEMENT */
7562     if (tv->answ == 2) {
7563         min = NextCand->lab[tv->tcellexpath];
7564         tmp = tv->tcellexpath;
7565         iend = tv->tcellexpath + NextPart->cls[tv->tcellexpath];
7566         for (i=tv->tcellexpath + 1; i<iend ; i++) {
7567             if (NextCand->lab[i] < min) {
7568                 min = NextCand->lab[i];
7569                 tmp = i;
7570             }
7571         }
7572     }
7573     else {
7574         tmp = tv->tcellexpath+KRAN(NextPart->cls[tv->tcellexpath]);
7575     }
7576     if (NextPart->cls[tv->tcellexpath] == 2) {
7577         NextCand->pathsingcode = MASHCOMM(NextCand->pathsingcode, NextCand->lab[tv->tcellexpath]);
7578         NextCand->pathsingcode = MASHCOMM(NextCand->pathsingcode, NextCand->lab[tv->tcellexpath+1]);
7579     }
7580     else {
7581         NextCand->pathsingcode = MASHCOMM(NextCand->pathsingcode, NextCand->lab[tmp]);
7582     }
7583 
7584     tv->indiv_vtx = NextCand->lab[tmp];
7585     Individualize(NextPart, NextCand, NextCand->lab[tmp], tv->tcellexpath, NextPart->cells, tv->tcellexpath + NextPart->cls[tv->tcellexpath]-1);
7586 
7587     tv->stats->numnodes++;
7588     if (tv->compstage == 0) {
7589         traces_refine_notrace(NextCand,
7590                               n,
7591                               NextPart, tv, ti);
7592     }
7593     else {
7594         if (tv->tolevel_tl == tv->maxtreelevel+1) {
7595             trieref = trieroot;
7596             tv->answ = traces_refine_comptrie(NextCand,
7597                                               n,
7598                                               NextPart, tv, ti);
7599             if (tv->answ == 0 ) {
7600                 tv->stats->interrupted++;
7601             }
7602         }
7603         else {
7604             traces_refine_notrace(NextCand,
7605                                   n,
7606                                   NextPart, tv, ti);
7607         }
7608     }
7609 
7610     CodeClassify(tv->tolevel_tl, NextCand->code, tv->tcellexpath);
7611 
7612 }
7613 
factorial(double * size1,int * size2,int k)7614 void factorial(double *size1, int *size2, int k) {
7615     int i;
7616 
7617     for(i = k; i; i--) {
7618         MULTIPLY(*size1, *size2, i);
7619     }
7620 }
7621 
factorial2(double * size1,int * size2,int k)7622 void factorial2(double *size1, int *size2, int k) {
7623     int i;
7624 
7625     for(i = k; i > 0; i -= 2) {
7626         MULTIPLY(*size1, *size2, i);
7627     }
7628 }
7629 
findperm(permnode * pn,int * p,int n)7630 boolean findperm(permnode *pn, int *p, int n) {
7631     permnode *rn;
7632 
7633     if (!pn) {
7634         return FALSE;
7635     }
7636     rn = pn;
7637     do {
7638         if (!memcmp(rn->p, p, n*sizeof(int))) {
7639             return TRUE;
7640         }
7641         rn = rn->next;
7642     } while (rn != pn);
7643     return FALSE;
7644 }
7645 
findcurrorbits(schreier * gp,int k)7646 int *findcurrorbits(schreier *gp, int k) {
7647     int i;
7648     schreier *sh;
7649 
7650     sh = gp;
7651     for (i = 0; i < k; i++) {
7652         sh = sh->next;
7653     }
7654     return sh->orbits;
7655 }
7656 
FirstNeighbour(int vtx,Candidate * Cand,Partition * Part,int * Markers,int mark,int * ngh,int n)7657 int FirstNeighbour(int vtx, Candidate *Cand, Partition *Part, int* Markers, int mark, int *ngh, int n) {
7658     int *e_vtx;
7659     int i, k, deg;
7660     int ngh1, ngh2, cell1, cell2;
7661 
7662     k = 0;
7663 
7664     deg = TheGraph[vtx].d;
7665     e_vtx = TheGraph[vtx].e;
7666 
7667     if (deg == n-1) {
7668         return 0;
7669     }
7670 
7671     for (i=0; i<deg; i++) {
7672         if (Markers[e_vtx[i]] != mark) {
7673             cell1 = Part->inv[Cand->invlab[e_vtx[i]]];
7674             if (Part->cls[cell1] > 1) {
7675                 ngh1 = e_vtx[i++];
7676                 k++;
7677                 break;
7678             }
7679         }
7680     }
7681     for (; i<deg; i++) {
7682         if (Markers[e_vtx[i]] != mark) {
7683             cell2 = Part->inv[Cand->invlab[e_vtx[i]]];
7684             if (Part->cls[cell2] > 1) {
7685                 ngh2 = e_vtx[i];
7686                 k++;
7687                 break;
7688             }
7689         }
7690     }
7691     switch (k) {
7692         case 0:
7693             break;
7694 
7695         case 1:
7696             *ngh = ngh1;
7697             break;
7698 
7699         case 2:
7700             if (cell1 < cell2) {
7701                 *ngh = ngh1;
7702             }
7703             else {
7704                 *ngh = ngh2;
7705             }
7706             break;
7707 
7708         default:
7709             break;
7710     }
7711     return k;
7712 }
7713 
FixBase(int * fix,struct TracesVars * tv,Candidate * Cand,int from,int to)7714 int FixBase(int *fix, struct TracesVars *tv, Candidate *Cand, int from, int to) {
7715     int i, j, k, go, nfix;
7716 
7717     nfix = j = 0;
7718     go = TRUE;
7719     for (i = from; i < to; i++) {
7720         k = Cand->lab[Spine[i+1].tgtpos];
7721         if (go && (nfix < tv->nfix) && (fix[nfix] == k)) {
7722             j++;
7723         }
7724         else {
7725             fix[nfix] = k;
7726             if (go) go = FALSE;
7727         }
7728         nfix++;
7729     }
7730     tv->nfix = nfix;
7731     return j;
7732 }
7733 
FixedBase(int * fix,struct TracesVars * tv,Candidate * Cand,int from,int to)7734 boolean FixedBase(int *fix, struct TracesVars *tv, Candidate *Cand, int from, int to) {
7735     int i, k, nfix;
7736 
7737     nfix = 0;
7738     for (i = from; i < to; i++) {
7739         k = Cand->lab[Spine[i+1].tgtpos];
7740         if (fix[nfix] != k) {
7741             return FALSE;
7742         }
7743         nfix++;
7744     }
7745     return TRUE;
7746 }
7747 
FreeList(Candidate * List,int cond)7748 int FreeList(Candidate *List, int cond) {
7749     Candidate *Temp;
7750     int conta = 0;
7751     int conta1 = 0;
7752 
7753     while (List) {
7754         if (List->do_it == cond) {
7755             conta1++;
7756         }
7757         conta++;
7758         Temp = List;
7759         if (List->lab) free(List->lab);
7760         if (List->invlab) free(List->invlab);
7761         List = List->next;
7762         free(Temp);
7763     }
7764 
7765     if (cond) {
7766         return conta1;
7767     }
7768     else {
7769         return conta;
7770     }
7771 }
7772 
7773 /* Check if the permutations in the list gens are automorphisms,
7774  * also set mark and refcount fields and initialise orbits. */
given_gens(sparsegraph * g,permnode * gens,int * orbits,boolean digraph)7775 int given_gens(sparsegraph *g, permnode *gens, int *orbits, boolean digraph) {
7776     int i, m, n, norbs;
7777     permnode *pn;
7778 
7779     n = g->nv;
7780     for (i = 0; i < n; ++i) orbits[i] = i;
7781     memcpy(IDENTITY_PERM, orbits, n*sizeof(int));
7782     norbs = n;
7783 
7784     if (!gens) return norbs;
7785 
7786     m = SETWORDSNEEDED(n);
7787     pn = gens;
7788     do {
7789         if (!isautom_sg((graph*)g, pn->p, digraph, m, n)) {
7790             fprintf(ERRFILE, "Input permutation is not an automorphism\n");
7791             exit(1);
7792         }
7793         norbs = orbjoin(orbits, pn->p, n);
7794         pn->mark = 1;
7795         pn->refcount = 0;
7796         pn = pn->next;
7797     } while (pn != gens);
7798 
7799     return norbs;
7800 }
7801 
grouporderplus(sparsegraph * sg_orig,Candidate * Cand,Partition * Part,permnode ** ring,double * grpsize1,int * grpsize2,int n,TracesVars * tv,TracesInfo * ti)7802 void grouporderplus(sparsegraph *sg_orig, Candidate *Cand, Partition *Part, permnode **ring,
7803                     double *grpsize1, int *grpsize2, int n, TracesVars *tv, TracesInfo *ti) {
7804 
7805     int i, i1, j, j0, j2, k, k1, k2, w, w1, w2, c, c1, c2, n1, n2;
7806     int prev, step, start, counts, StInd, CyInd, cycnum;
7807     int tmp, temp, halfsize, nghcell, numvertices;
7808     int arg, val;
7809 
7810     searchtrie *TrieNode;
7811     int NSFCInd, ind;
7812     boolean do_ngh = FALSE;
7813 
7814     numvertices = n;
7815     memcpy(CanonIndices, IDENTITY_PERM, n*sizeof(int));
7816     memset(TreeNodes, 0, n*sizeof(int));
7817 
7818     TrieNode = Spine[tv->maxtreelevel].liststart->stnode;
7819     if (TrieNode->father) {
7820         if (tv->options->verbosity >= 2) {
7821             LINE(32, "-")
7822             NEXTLINE
7823             fprintf(outfile, "group structure: ");
7824             while (TrieNode->father) {
7825                 if (Factorials[TrieNode->level]) {
7826                     fprintf(outfile, "%d (%d!), ", TrieNode->name, TrieNode->index);
7827                     factorial(grpsize1, grpsize2, TrieNode->index);
7828                 } else {
7829                     if (TrieNode->father->name) {
7830                         fprintf(outfile, "%d (%d), ", TrieNode->name, TrieNode->index);
7831                         MULTIPLY(tv->stats->grpsize1, tv->stats->grpsize2, TrieNode->index);
7832                     }
7833                     else {
7834                         temp = spinelementorbsize(tv->orbits, Spine[tv->maxtreelevel].liststart->lab+Spine[1].tgtcell, Spine[1].tgtsize, TrieNode->vtx);
7835                         MULTIPLY(*grpsize1, *grpsize2, temp);
7836                         fprintf(outfile, "%d (%d)\n",
7837                                 TrieNode->name, temp);
7838                     }
7839                 }
7840                 TrieNode = TrieNode->father;
7841             }
7842         }
7843         else {
7844             while (TrieNode->father) {
7845                 if (Factorials[TrieNode->level]) {
7846                     factorial(grpsize1, grpsize2, TrieNode->index);
7847                 } else {
7848                     if (TrieNode->father->name) {
7849                         MULTIPLY(tv->stats->grpsize1, tv->stats->grpsize2, TrieNode->index);
7850                     }
7851                     else {
7852                         temp = spinelementorbsize(tv->orbits, Spine[tv->maxtreelevel].liststart->lab+Spine[1].tgtcell, Spine[1].tgtsize, TrieNode->vtx);
7853                         MULTIPLY(*grpsize1, *grpsize2, temp);
7854                     }
7855                 }
7856                 TrieNode = TrieNode->father;
7857             }
7858         }
7859     }
7860 
7861     if (Part->cells < n) {
7862 
7863         if (!ti->deg_one) {
7864             memcpy(tv->graph->e, sg_orig->e, tv->graph->elen*sizeof(int));
7865             for (i=0; i<n; i++) {
7866                 TheGraph[i].e = tv->graph->e + sg_orig->v[i];
7867             }
7868         }
7869         NSFCInd = 0;
7870 
7871         /* Trees */
7872         if (tv->options->getcanon && tv->preprocessed) {
7873             for (i = 0; i < n; i += Part->cls[i]) {
7874                 if (Part->cls[i] == 1) {
7875                     tmp = Cand->lab[i];
7876                     if ((TheGraph[tmp].d >= 0) && (TheGraph[tmp].d < sg_orig->d[tmp])) {
7877                         for (j=i; j<i+Part->cls[i]; j++) {
7878                             MakeCanTree(Cand->lab[j], sg_orig, n, Cand, Part, tv);
7879                         }
7880                     }
7881                 }
7882             }
7883         }
7884 
7885         memset(SingNonSing, 0, n*sizeof(int));
7886 
7887         for (i = 0; i < n; i += Part->cls[i]) {
7888             if (Part->cls[i] > 1) {
7889                 if (TheGraph[Cand->lab[i]].d > 2) {
7890                     for (j=i; j<i+Part->cls[i]; j++) {
7891                         SingNonSing[Cand->lab[j]] = 2;
7892                     }
7893                 }
7894             }
7895             else {
7896                 SingNonSing[Cand->lab[i]] = 1;
7897             }
7898         }
7899 
7900         for (i = 0; i < n; i += Part->cls[i]) {
7901             if (Part->cls[i] > 1) {
7902                 if (TheGraph[Cand->lab[i]].d > 2) NonSingDegPlus1(Cand, Part, i, tv);
7903                 NSFCells[NSFCInd++] = i;
7904             }
7905             else {
7906                 NonSingDegPlus2(Cand, Part, i, tv);
7907                 numvertices--;
7908             }
7909         }
7910 
7911         /* Degree 2 and at least one nghb with deg > 2 */
7912         SETMARK(StackMarkers, tv->stackmark)
7913         for (ind = 0; ind < NSFCInd; ind++) {
7914             i = NSFCells[ind];
7915             SETMARK(Markers, tv->mark)
7916             if (Part->cls[i] > 1) {
7917                 tmp = Cand->lab[i];
7918                 if ((TheGraph[tmp].d == 2) && ((TheGraph[TheGraph[tmp].e[0]].d > 2) || ((TheGraph[TheGraph[tmp].e[1]].d > 2)))) {
7919                     n1 = TheGraph[tmp].e[0];
7920                     n2 = TheGraph[tmp].e[1];
7921                     if (TheGraph[n1].d > 2) {
7922                         if (TheGraph[n2].d > 2) {
7923                             if (Cand->invlab[n1] < Cand->invlab[n2]) {
7924                                 start = n1;
7925                             }
7926                             else {
7927                                 start = n2;
7928                             }
7929                         }
7930                         else {
7931                             start = n1;
7932                         }
7933                     }
7934                     else {
7935                         start = n2;
7936                     }
7937                     counts = 0;
7938                     StInd = 0;
7939                     for (j=i; j<i+Part->cls[i]; j++) {
7940                         step = Cand->lab[j];
7941                         if (Markers[step] != tv->mark) {
7942                             prev = start;
7943                             counts++;
7944                             do {
7945                                 Markers[step] = tv->mark;
7946                                 PERMSTACK[StInd++] = step;
7947                                 if (TheGraph[step].e[0] != prev) {
7948                                     prev = step;
7949                                     step = TheGraph[step].e[0];
7950                                 }
7951                                 else {
7952                                     prev = step;
7953                                     step = TheGraph[step].e[1];
7954                                 }
7955                             } while (TheGraph[step].d == 2);
7956 
7957                             if (TheGraph[step].d == 1) {
7958                                 PERMSTACK[StInd++] = step;
7959                             }
7960                         }
7961                     }
7962 
7963                     if (counts == Part->cls[i]) {
7964                         factorial(grpsize1, grpsize2, Part->cls[i]);
7965                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
7966                         for (k=0; k<StInd/counts; k++) {
7967                             i1 = PERMSTACK[k];
7968                             for (j0=0; j0<counts-1; j0++) {
7969                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
7970                             }
7971                             SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
7972                         }
7973                         SPECIALGENERATORS
7974                         if (counts > 2) {
7975                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
7976                             for (k=0; k<StInd/counts; k++) {
7977                                 i1 = PERMSTACK[k];
7978                                 for (j0=0; j0<1; j0++) {
7979                                     SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
7980                                 }
7981                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
7982                             }
7983                             SPECIALGENERATORS
7984                         }
7985                     }
7986                     else {
7987                         factorial2(grpsize1, grpsize2, Part->cls[i]);
7988                         for (j=0; j<counts; j++) {
7989                             j0 = j*(StInd/counts);
7990                             k1 = (j+1)*(StInd/counts);
7991                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
7992                             for (k=j0, i1=k1-1; k<k1; k++, i1--) {
7993                                 SETPAIRSAUTANDTREE(PERMSTACK[k], PERMSTACK[i1])
7994                             }
7995                             SPECIALGENERATORS
7996                         }
7997                         if (counts > 1) {
7998                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
7999                             for (k=0; k<StInd/counts; k++) {
8000                                 i1 = PERMSTACK[k];
8001                                 for (j0=0; j0<counts-1; j0++) {
8002                                     SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
8003                                 }
8004                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
8005                             }
8006                             SPECIALGENERATORS
8007                         }
8008                         if (counts > 2) {
8009                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8010                             for (k=0; k<StInd/counts; k++) {
8011                                 i1 = PERMSTACK[k];
8012                                 for (j0=0; j0<1; j0++) {
8013                                     SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
8014                                 }
8015                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
8016                             }
8017                             SPECIALGENERATORS
8018                         }
8019                     }
8020                     for (j=0; j<StInd; j++) {
8021                         Place(PERMSTACK[j], Cand, Part);
8022                         if ((TheGraph[PERMSTACK[j]].d >= 0) && (TheGraph[PERMSTACK[j]].d < sg_orig->d[PERMSTACK[j]])) {
8023                             MakeCanTree(PERMSTACK[j], sg_orig, n, Cand, Part, tv);
8024                         }
8025                     }
8026                 }
8027             }
8028         }
8029 
8030         /* Degree 2 and at least one nghb with == 1 */
8031         for (ind = 0; ind < NSFCInd; ind++) {
8032             SETMARK(Markers, tv->mark)
8033             i = NSFCells[ind];
8034             if (Part->cls[i] > 1) {
8035                 tmp = Cand->lab[i];
8036                 if ((TheGraph[tmp].d == 2) && ((TheGraph[TheGraph[tmp].e[0]].d == 1) || ((TheGraph[TheGraph[tmp].e[1]].d == 1)))) {
8037                     counts = 0;
8038                     StInd = 0;
8039                     for (j=i; j<i+Part->cls[i]; j++) {
8040                         step = Cand->lab[j];
8041                         if (Markers[step] != tv->mark) {
8042                             n1 = TheGraph[step].e[0];
8043                             n2 = TheGraph[step].e[1];
8044                             if (TheGraph[n1].d == 1) {
8045                                 if (TheGraph[n2].d == 1) {
8046                                     if (Cand->invlab[n1] < Cand->invlab[n2]) {
8047                                         start = n1;
8048                                     }
8049                                     else {
8050                                         start = n2;
8051                                     }
8052                                 }
8053                                 else {
8054                                     start = n1;
8055                                 }
8056                             }
8057                             else {
8058                                 start = n2;
8059                             }
8060                             PERMSTACK[StInd++] = start;
8061                             prev = start;
8062                             counts++;
8063 
8064                             do {
8065                                 Markers[step] = tv->mark;
8066                                 PERMSTACK[StInd++] = step;
8067                                 if (TheGraph[step].e[0] != prev) {
8068                                     prev = step;
8069                                     step = TheGraph[step].e[0];
8070                                 } else {
8071                                     prev = step;
8072                                     step = TheGraph[step].e[1];
8073                                 }
8074                             } while (TheGraph[step].d == 2);
8075                             PERMSTACK[StInd++] = step;
8076                         }
8077                     }
8078 
8079                     if (counts == Part->cls[i]) {
8080                         if (Part->inv[Cand->invlab[PERMSTACK[0]]] != Part->inv[Cand->invlab[PERMSTACK[StInd/counts-1]]]) {
8081                             factorial(grpsize1, grpsize2, Part->cls[i]);
8082                         }
8083                         else {
8084                             factorial2(grpsize1, grpsize2, 2*Part->cls[i]);
8085                             for (j=0; j<counts; j++) {
8086                                 j0 = j*(StInd/counts);
8087                                 k1 = (j+1)*(StInd/counts);
8088                                 if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8089                                 for (k=j0, i1=k1-1; k<k1; k++, i1--) {
8090                                     SETPAIRSAUTANDTREE(PERMSTACK[k], PERMSTACK[i1])
8091                                 }
8092                                 SPECIALGENERATORS
8093                             }
8094                         }
8095                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8096                         for (k=0; k<StInd/counts; k++) {
8097                             i1 = PERMSTACK[k];
8098                             for (j0=0; j0<counts-1; j0++) {
8099                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
8100                             }
8101                             SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
8102                         }
8103                         SPECIALGENERATORS
8104                         if (counts > 2) {
8105                             for (k=0; k<StInd/counts; k++) {
8106                                 i1 = PERMSTACK[k];
8107                                 for (j0=0; j0<1; j0++) {
8108                                     SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
8109                                 }
8110                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
8111                             }
8112                             SPECIALGENERATORS
8113                         }
8114                     }
8115                     else {
8116                         factorial2(grpsize1, grpsize2, Part->cls[i]);
8117                         for (j=0; j<counts; j++) {
8118                             j0 = j*(StInd/counts);
8119                             k1 = (j+1)*(StInd/counts);
8120                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8121                             for (k=j0, i1=k1-1; k<k1; k++, i1--) {
8122                                 SETPAIRSAUTANDTREE(PERMSTACK[k], PERMSTACK[i1])
8123                             }
8124                             SPECIALGENERATORS
8125                         }
8126                         if (counts > 1) {
8127                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8128                             for (k=0; k<StInd/counts; k++) {
8129                                 i1 = PERMSTACK[k];
8130                                 for (j0=0; j0<counts-1; j0++) {
8131                                     SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
8132                                 }
8133                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
8134                             }
8135                             SPECIALGENERATORS
8136                         }
8137                         if (counts > 2) {
8138                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8139                             for (k=0; k<StInd/counts; k++) {
8140                                 i1 = PERMSTACK[k];
8141                                 for (j0=0; j0<1; j0++) {
8142                                     SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], PERMSTACK[(j0+1)*(StInd/counts)+k])
8143                                 }
8144                                 SETPAIRSAUTANDTREE(PERMSTACK[j0*(StInd/counts)+k], i1)
8145                             }
8146                             SPECIALGENERATORS
8147                         }
8148                     }
8149                     for (j=0; j<StInd; j++) {
8150                         Place(PERMSTACK[j], Cand, Part);
8151                         if ((TheGraph[PERMSTACK[j]].d >= 0) && (TheGraph[PERMSTACK[j]].d < sg_orig->d[PERMSTACK[j]])) {
8152                             MakeCanTree(PERMSTACK[j], sg_orig, n, Cand, Part, tv);
8153                         }
8154                     }
8155                 }
8156             }
8157         }
8158 
8159         /* Cycles */
8160         for (ind = 0; ind < NSFCInd; ind++) {
8161             i = NSFCells[ind];
8162             SETMARK(Markers, tv->mark)
8163             if (Part->cls[i] > 1) {
8164                 tmp = Cand->lab[i];
8165                 if (TheGraph[tmp].d == 2) {
8166                     CyInd = StInd = cycnum = 0;
8167                     for (j=i; j<i+Part->cls[i]; j++) {
8168                         start = Cand->lab[j];
8169                         if (Markers[start] != tv->mark) {
8170                             counts = 1;
8171                             CYCLES[StInd] = start;
8172                             CYCOLR[StInd++] = Part->inv[Cand->invlab[start]];
8173                             Markers[start] = tv->mark;
8174                             k = Cand->invlab[TheGraph[start].e[0]];
8175                             k1 = Cand->invlab[TheGraph[start].e[1]];
8176                             if (Part->inv[k] < Part->inv[k1]) {
8177                                 step = TheGraph[start].e[0];
8178                             }
8179                             else {
8180                                 step = TheGraph[start].e[1];
8181                             }
8182                             prev = start;
8183                             do {
8184                                 counts++;
8185                                 Markers[step] = tv->mark;
8186                                 CYCLES[StInd] = step;
8187                                 CYCOLR[StInd++] = Part->inv[Cand->invlab[step]];
8188 
8189                                 if (TheGraph[step].e[0] != prev) {
8190                                     prev = step;
8191                                     step = TheGraph[step].e[0];
8192                                 }
8193                                 else {
8194                                     prev = step;
8195                                     step = TheGraph[step].e[1];
8196                                 }
8197                             } while (step != start);
8198                             CYLGTH[CyInd++] = counts;
8199                             cycnum++;
8200                         }
8201                     }
8202 
8203                     CYCPOS[0] = 0;
8204                     for (j=1; j<CyInd; j++) {
8205                         CYCPOS[j] = CYCPOS[j-1]+CYLGTH[j-1];
8206                     }
8207                     memcpy(WorkArray, CYLGTH, CyInd*sizeof(int));
8208                     sort2ints(WorkArray, CYCPOS, CyInd);
8209 
8210                     k = 0;
8211                     for (i1=0; i1<CyInd; i1++) {
8212                         k1 = CYCOLR[k];
8213                         k2 = CYCOLR[k+1];
8214                         for (j=1; j<=CYLGTH[i1]/2; j++) {
8215                             w1 = CYCOLR[j+k];
8216                             w2 = CYCOLR[j+1+k];
8217                             if ((w1 == k1) && (w2 == k2)) {
8218                                 if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8219                                 for (w=0; w<CYLGTH[i1]; w++) {
8220                                     if (CYCOLR[w+k] == CYCOLR[((w+j) % CYLGTH[i1]) + k]) {
8221                                         SETPAIRSAUTANDTREE(CYCLES[w+k], CYCLES[((w+j) % CYLGTH[i1]) + k])
8222                                     }
8223                                     else {
8224                                         break;
8225                                     }
8226                                 }
8227                                 if (w == CYLGTH[i1]) { SPECIALGENERATORS }
8228                                 if (w == CYLGTH[i1]) {
8229                                     MULTIPLY(*grpsize1, *grpsize2, CYLGTH[i1]/j);
8230                                     break;
8231                                 }
8232                             }
8233                         }
8234 
8235                         if (Part->cls[k1] >= Part->cls[k2]) {
8236                             for (j=CYLGTH[i1]-1; j>0; j--) {
8237                                 w1 = CYCOLR[j % CYLGTH[i1] + k];
8238                                 w2 = CYCOLR[(j-1) % CYLGTH[i1] + k];
8239                                 if ((w1 == k1) && (w2 == k2)) {
8240                                     if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8241                                     for (w=0; w<CYLGTH[i1]; w++) {
8242                                         SETPAIRSAUTANDTREE(CYCLES[w+k], CYCLES[((j-w+(w>j)*CYLGTH[i1]) % CYLGTH[i1]) + k])
8243                                     }
8244                                     SPECIALGENERATORS
8245                                     MULTIPLY(*grpsize1, *grpsize2, 2);
8246                                     break;
8247                                 }
8248                             }
8249                         }
8250                         else {
8251                             j=CYLGTH[i1]-1;
8252                             w2 = CYCOLR[j % CYLGTH[i1] + k];
8253                             if (w2 == k2) {
8254                                 if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8255                                 for (w=1; w<CYLGTH[i1]; w++) {
8256                                     SETPAIRSAUTANDTREE(CYCLES[w+k], CYCLES[CYLGTH[i1]-w+k])
8257                                 }
8258                                 SPECIALGENERATORS
8259                                 MULTIPLY(*grpsize1, *grpsize2, 2);
8260                             }
8261                         }
8262                         k += CYLGTH[i1];
8263                     }
8264                     k = 0;
8265                     for (i1=0; i1<CyInd; i1++) {
8266                         if (CYLGTH[i1] > 0) {
8267                             CYMULT[0] = k;
8268                             k1 = k;
8269                             counts = 1;
8270                             for (j0=i1+1; j0<CyInd; j0++) {
8271                                 k1 += abs(CYLGTH[j0]);
8272                                 if (CYLGTH[j0] == CYLGTH[i1]) {
8273                                     CYMULT[counts++] = k1;
8274                                     CYLGTH[j0] = -CYLGTH[j0];
8275                                 }
8276                             }
8277                             if (counts > 1) {
8278                                 if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8279                                 for (j0=0; j0<CYLGTH[i1]; j0++) {
8280                                     for (j2 = 0; j2<counts-1; j2++) {
8281                                         SETPAIRSAUTANDTREE(CYCLES[CYMULT[j2]+j0], CYCLES[CYMULT[j2+1]+j0])
8282                                     }
8283                                     SETPAIRSAUTANDTREE(CYCLES[CYMULT[j2]+j0], CYCLES[CYMULT[0]+j0])
8284                                 }
8285                                 SPECIALGENERATORS
8286                                 if (counts > 2) {
8287                                     if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8288                                     for (j0=0; j0<CYLGTH[i1]; j0++) {
8289                                         SETPAIRSAUTANDTREE(CYCLES[CYMULT[1]+j0], CYCLES[CYMULT[0]+j0])
8290                                         if (tv->build_autom) {
8291                                             SETPAIRSAUT(CYCLES[CYMULT[0]+j0], CYCLES[CYMULT[1]+j0])
8292                                         }
8293                                         MakeTree(CYCLES[CYMULT[0]+j0], CYCLES[CYMULT[1]+j0], sg_orig, n, tv, FALSE);
8294                                     }
8295                                     SPECIALGENERATORS
8296                                 }
8297                                 factorial(grpsize1, grpsize2, counts);
8298                             }
8299                         }
8300                         k += abs(CYLGTH[i1]);
8301                         CYLGTH[i1] = -CYLGTH[i1];
8302                     }
8303 
8304                     for (c1=0; c1<CyInd; c1++) {
8305                         c = CYCPOS[c1]+WorkArray[c1];
8306                         for (c2=CYCPOS[c1]; c2<c; c2++) {
8307                             Place(CYCLES[c2], Cand, Part);
8308                             if ((TheGraph[CYCLES[c2]].d >= 0) && (TheGraph[CYCLES[c2]].d < sg_orig->d[CYCLES[c2]])) {
8309                                 MakeCanTree(CYCLES[c2], sg_orig, n, Cand, Part, tv);
8310                             }
8311                         }
8312                     }
8313                 }
8314             }
8315         }
8316 
8317         /* Degree 1, and nghb too */
8318         SETMARK(Markers, tv->mark)
8319         for (ind = 0; ind < NSFCInd; ind++) {
8320             i = NSFCells[ind];
8321             if (Part->cls[i] > 1) {
8322                 tmp = Cand->lab[i];
8323                 if ((TheGraph[tmp].d == 1) && (TheGraph[TheGraph[tmp].e[0]].d == 1) && (i == Part->inv[Cand->invlab[TheGraph[tmp].e[0]]])) {
8324                     factorial2(grpsize1, grpsize2, Part->cls[i]);
8325                     /* the cell has size two */
8326                     if (Part->cls[i] == 2) {
8327                         val = Cand->lab[i+1];
8328                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8329                         arg = tmp;
8330                         SETPAIRSAUTANDTREE(arg, val)
8331                         SETPAIRSAUTANDTREE(val, arg)
8332                         SPECIALGENERATORS
8333                     }
8334                     else {
8335                         /* the cell has size greater than two */
8336                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8337                         SETMARK(Markers, tv->mark)
8338                         halfsize = Part->cls[i]/2;
8339                         i1 = 0;
8340                         for (j=i; j<i+Part->cls[i]; j++) {
8341                             if (Markers[Cand->lab[j]] != tv->mark) {
8342                                 Markers[TheGraph[Cand->lab[j]].e[0]] = tv->mark;
8343                                 PERMSTACK[i1] = Cand->lab[j];
8344                                 PERMSTACK[i1+halfsize] = TheGraph[Cand->lab[j]].e[0];
8345                                 i1++;
8346                             }
8347                         }
8348                         temp = PERMSTACK[0];
8349                         for (j=0; j<Part->cls[i]-1; j++) {
8350                             SETPAIRSAUTANDTREE(PERMSTACK[j], PERMSTACK[j+1])
8351                         }
8352                         SETPAIRSAUTANDTREE(PERMSTACK[j], temp)
8353                         SPECIALGENERATORS
8354                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8355                         memmove(PERMSTACK+halfsize, PERMSTACK+halfsize+1, (halfsize-1)*sizeof(int));
8356                         temp = PERMSTACK[1];
8357                         for (j=1; j<Part->cls[i]-2; j++) {
8358                             SETPAIRSAUTANDTREE(PERMSTACK[j], PERMSTACK[j+1])
8359                         }
8360                         SETPAIRSAUTANDTREE(PERMSTACK[j], temp)
8361                         SPECIALGENERATORS
8362                     }
8363 
8364                     SETMARK(Markers, tv->mark)
8365                     for (j=i; j<i+Part->cls[i]; j++) {
8366                         temp = Cand->lab[j];
8367                         if (Markers[temp] != tv->mark) {
8368                             if ((TheGraph[temp].d >= 0) && (TheGraph[temp].d < sg_orig->d[temp])) {
8369                                 MakeCanTree(temp, sg_orig, n, Cand, Part, tv);
8370                             }
8371                             tmp = Cand->lab[j+1];
8372                             Markers[TheGraph[temp].e[0]] = tv->mark;
8373                             i1 = Cand->invlab[TheGraph[temp].e[0]];
8374                             Cand->lab[j+1] = TheGraph[temp].e[0];
8375 
8376                             if ((TheGraph[TheGraph[temp].e[0]].d >= 0) && (TheGraph[TheGraph[temp].e[0]].d < sg_orig->d[TheGraph[temp].e[0]])) {
8377                                 MakeCanTree(TheGraph[temp].e[0], sg_orig, n, Cand, Part, tv);
8378                             }
8379                             Cand->invlab[TheGraph[temp].e[0]] = j+1;
8380                             Cand->lab[i1] = tmp;
8381                             Cand->invlab[tmp] = i1;
8382                         }
8383                     }
8384                 }
8385             }
8386         }
8387 
8388         /* Degree 0 */
8389         for (ind = 0; ind < NSFCInd; ind++) {
8390             i = NSFCells[ind];
8391             if (Part->cls[i] > 1) {
8392                 tmp = Cand->lab[i];
8393                 if ((TheGraph[0].e != NULL) && (TheGraph[tmp].d != 0) && (TheGraph[tmp].d != numvertices-1))
8394                     nghcell = Part->inv[Cand->invlab[TheGraph[tmp].e[0]]]; else nghcell = i;
8395                 if ((TheGraph[tmp].d == 0) ||
8396                     ((TheGraph[tmp].d == numvertices-1) && (TheGraph[tmp].d > 2)) ||
8397                     ((TheGraph[tmp].d == 1) && (TheGraph[TheGraph[tmp].e[0]].d == 1) && (i < nghcell))) {
8398                     do_ngh = FALSE;
8399                     if ((TheGraph[tmp].d == 1) && (TheGraph[TheGraph[tmp].e[0]].d == 1) && (i != nghcell)) {
8400                         do_ngh = TRUE;
8401                     }
8402                     if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8403                     for (j=i; j<i+Part->cls[i]-1; j++) {
8404                         arg = Cand->lab[j];
8405                         val = Cand->lab[j+1];
8406                         SETPAIRSAUTANDTREE(arg, val)
8407                         if (do_ngh) {
8408                             SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
8409 
8410                         }
8411                     }
8412                     arg = Cand->lab[j];
8413                     val = tmp;
8414                     SETPAIRSAUTANDTREE(arg, val)
8415                     if (do_ngh) {
8416                         SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
8417                     }
8418                     SPECIALGENERATORS
8419                     if (Part->cls[i] > 2) {
8420                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
8421                         arg = tmp;
8422                         val = Cand->lab[i+1];
8423                         SETPAIRSAUTANDTREE(arg, val)
8424                         if (do_ngh) {
8425                             SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
8426                         }
8427                         arg = Cand->lab[i+1];
8428                         val = tmp;
8429                         SETPAIRSAUTANDTREE(arg, val)
8430                         if (do_ngh) {
8431                             SETPAIRSAUTANDTREE(TheGraph[arg].e[0], TheGraph[val].e[0])
8432                         }
8433                         SPECIALGENERATORS
8434                     }
8435                     factorial(grpsize1, grpsize2, Part->cls[i]);
8436                     if (do_ngh) {
8437                         for (j=i; j<i+Part->cls[i]; j++) {
8438                             temp = TheGraph[Cand->lab[j]].e[0];
8439                             Cand->lab[nghcell] = temp;
8440                             Cand->invlab[temp] = nghcell;
8441                             nghcell++;
8442                         }
8443                     }
8444 
8445                     k = i+Part->cls[i];
8446                     for (j=i; j<k; j++) {
8447                         Place(Cand->lab[j], Cand, Part);
8448                         if ((TheGraph[Cand->lab[j]].d >= 0) && (TheGraph[Cand->lab[j]].d < sg_orig->d[Cand->lab[j]])) {
8449                             MakeCanTree(Cand->lab[j], sg_orig, n, Cand, Part, tv);
8450                             if (do_ngh) {
8451                                 MakeCanTree(TheGraph[Cand->lab[j]].e[0], sg_orig, n, Cand, Part, tv);
8452                             }
8453                         }
8454                     }
8455                 }
8456             }
8457         }
8458 
8459     }
8460 
8461     /* Orbit Count */
8462     SETMARK(Markers, tv->mark)
8463     i1=0;
8464     for (c1=0; c1<n; c1++) {
8465         if (Markers[tv->orbits[c1]] != tv->mark) {
8466             i1++;
8467             Markers[tv->orbits[c1]] = tv->mark;
8468         }
8469     }
8470     tv->stats->numorbits = i1;
8471     return;
8472 }
8473 
Individualize(Partition * NextPart,Candidate * NextCand,int K,int Tc,int Cl,int Pos)8474 void Individualize(Partition *NextPart, Candidate *NextCand, int K, int Tc, int Cl, int Pos) {
8475     int i, j;
8476 
8477     NextCand->do_it = TRUE;
8478     if (NextPart->cls[Tc] > 1) {
8479         NextPart->cells = Cl+1;
8480         NextPart->active = 1;
8481         NextPart->cls[Tc]--;
8482         NextPart->cls[Pos] = 1;
8483     }
8484     NextPart->inv[Pos] = Pos;
8485 
8486     j = NextCand->lab[Pos];
8487     i = NextCand->invlab[K];
8488     NextCand->lab[Pos] = K;
8489     NextCand->invlab[K] = Pos;
8490     NextCand->lab[i] = j;
8491     NextCand->invlab[j] = i;
8492     return;
8493 }
8494 
Initialize_Traces_Variables(TracesVars * tv,TracesOptions * options_arg,TracesStats * stats_arg,int * orbits_arg,sparsegraph * g_arg,sparsegraph * canong_arg,int n)8495 void Initialize_Traces_Variables(TracesVars *tv, TracesOptions *options_arg,
8496                                  TracesStats *stats_arg, int *orbits_arg,
8497                                  sparsegraph *g_arg, sparsegraph *canong_arg,
8498                                  int n) {
8499     tv->augmented_cells = n;
8500     tv->canlist = 0;
8501     tv->compstage = 0;
8502     tv->expathlength = n;
8503     tv->finalnumcells = n;
8504     tv->firstpathlength = 0;
8505     tv->group_level = 0;
8506     tv->lev_of_lastauto = 0;
8507     tv->linelgth = 0;
8508     tv->name = 0;
8509     tv->maxspineorblevel = 0;
8510     tv->nfix = 0;
8511     tv->options = options_arg;
8512     tv->orbits = orbits_arg;
8513     tv->permInd = 0;
8514     tv->maxdeg = 0;
8515     tv->mindeg = n;
8516 
8517     if (tv->options->generators || tv->options->writeautoms || tv->options->userautomproc)
8518         tv->build_autom = TRUE;
8519     else
8520         tv->build_autom = FALSE;
8521 
8522     tv->specialgens = 0;
8523     tv->stats = stats_arg;
8524     tv->treedepth = 0;
8525     tv->gotonode = NULL;
8526     tv->input_graph = tv->graph = g_arg;
8527     tv->cangraph = canong_arg;
8528     tv->mark = tv->stackmark = tv->treemark = tv->autmark = tv->markcell1 = tv->markcell2 = NAUTY_INFINITY-1;
8529     tv->conta0 = tv->conta1 = tv->conta2 = tv->conta3 = tv->conta4 = tv->conta5 = tv->conta6 = tv->conta7 = tv->contatc = 0;
8530 
8531     if (tv->options->strategy == 0) {
8532         tv->steps = n;
8533         tv->strategy = 0;
8534     }
8535     else {
8536         tv->strategy = 1;
8537         tv->steps = tv->options->strategy;
8538         if (tv->steps > n) {
8539             tv->steps = n;
8540         }
8541     }
8542 }
8543 
Initialize_Traces_Statistics(TracesStats * stats_arg,int n)8544 void Initialize_Traces_Statistics (TracesStats *stats_arg, int n) {
8545     stats_arg->grpsize1 = 1;
8546     stats_arg->grpsize2 = 0;
8547     stats_arg->numorbits = n;
8548     stats_arg->treedepth= 0;
8549     stats_arg->numgenerators = 0;
8550     stats_arg->numnodes = 1;
8551     stats_arg->errstatus = 0;
8552     stats_arg->interrupted = 0;
8553     stats_arg->canupdates = 0;
8554     stats_arg->peaknodes = 0;
8555 }
8556 
Initialize_Traces_Time_Variables(TracesVars * tv)8557 void Initialize_Traces_Time_Variables (TracesVars *tv) {
8558     tv->autchk = 0;
8559     tv->expaths = 0;
8560     tv->schreier1 = 0;
8561     tv->schreier2 = 0;
8562     tv->schreier3 = 0;
8563 }
8564 
isautom_sg_pair(graph * g,int * p,boolean digraph,int m,int n,struct TracesVars * tv)8565 boolean isautom_sg_pair(graph *g, int *p, boolean digraph, int m, int n, struct TracesVars *tv) {
8566     int *d, *e;
8567     size_t *v;
8568     int i, k, pi, di;
8569     size_t vi, vpi, j;
8570 
8571     SG_VDE(g, v, d, e);
8572 
8573     for (k = 0; k < tv->permInd; ++k)
8574     {
8575         i = PrmPairs[k].arg;
8576         pi = p[i];
8577         di = d[i];
8578         if (d[pi] != di) return FALSE;
8579 
8580         vi = v[i];
8581         vpi = v[pi];
8582         SETMARK(AutMarkers, tv->autmark)
8583         for (j = 0; j < di; ++j) AutMarkers[p[e[vi+j]]] = tv->autmark;
8584         for (j = 0; j < di; ++j) if (AutMarkers[e[vpi+j]] != tv->autmark) {
8585             return FALSE;
8586         }
8587     }
8588 
8589     return TRUE;
8590 }
8591 
lookup(searchtrie * t)8592 boolean lookup(searchtrie *t) {
8593     searchtrie *TreeNode;
8594 
8595     TreeNode = t;
8596     while (TreeNode->level >= 1) {
8597         if (TreeNode->goes_to) {
8598             return FALSE;
8599         }
8600         TreeNode = TreeNode->father;
8601     }
8602     return TRUE;
8603 }
8604 
MakeCanTree(int v1,sparsegraph * sg_orig,int n,Candidate * Cand,Partition * Part,struct TracesVars * tv)8605 void MakeCanTree(int v1, sparsegraph *sg_orig, int n, Candidate *Cand, Partition *Part, struct TracesVars* tv) {
8606     int ind, vtx, ngh, trind, deg0, deg1;
8607     size_t j1;
8608     int *sge1;
8609 
8610     trind = 1;
8611     ind = 0;
8612     TreeStack[0] = v1;
8613     SETMARK(TreeMarkers, tv->treemark);
8614 
8615     while (ind < trind) {
8616         vtx = TreeStack[ind++];
8617         if (TreeNodes[vtx]) {
8618             return;
8619         }
8620 
8621         if (TheGraph[vtx].d == -1) {
8622             Place(vtx, Cand, Part);
8623             TreeNodes[vtx] = TRUE;
8624         }
8625 
8626         TreeMarkers[vtx] = tv->treemark;
8627         deg0 = maxint(TheGraph[vtx].d, 0);
8628         deg1 = sg_orig->d[vtx];
8629         sge1 = TheGraph[vtx].e;
8630 
8631         for (j1 = deg0; j1 < deg1; j1++) {
8632             ngh = sge1[j1];
8633             if ((TheGraph[ngh].d == -1) && (TreeMarkers[ngh] != tv->treemark)) {
8634                 TreeStack[trind++] = ngh;
8635             }
8636         }
8637     }
8638     return;
8639 }
8640 
MakeDiscrete(Partition * Part,int cell)8641 void MakeDiscrete(Partition *Part, int cell) {
8642     int i, k;
8643 
8644     Part->cells += (Part->cls[cell] - 1);
8645     k = cell + Part->cls[cell];
8646 
8647     for (i = cell; i < k; i++) {
8648         Part->cls[i] = 1;
8649         Part->inv[i] = i;
8650     }
8651 }
8652 
MakeTree(int v1,int v2,sparsegraph * sg,int n,struct TracesVars * tv,boolean forceautom)8653 void MakeTree(int v1, int v2, sparsegraph *sg, int n, struct TracesVars* tv, boolean forceautom) {
8654     int ind, vtx1, vtx2, ngh1, ngh2, trind, deg0, deg1;
8655     size_t j1;
8656     int *sge1, *sge2;
8657     boolean build_autom;
8658 
8659     if (v1 == v2) return;
8660     build_autom = tv->build_autom || forceautom;
8661     trind = 2;
8662     ind = 0;
8663     TreeStack[0] = v1;
8664     TreeStack[1] = v2;
8665     SETMARK(TreeMarkers, tv->treemark);
8666 
8667     while (ind < trind) {
8668         vtx1 = TreeStack[ind++];
8669         vtx2 = TreeStack[ind++];
8670 
8671         TreeMarkers[vtx1] = tv->treemark;
8672         TreeMarkers[vtx2] = tv->treemark;
8673 
8674         deg0 = maxint(TheGraph[vtx1].d, 0);
8675         deg1 = sg->d[vtx1];
8676         sge1 = TheGraph[vtx1].e;
8677         sge2 = TheGraph[vtx2].e;
8678         for (j1 = deg0; j1 < deg1; j1++) {
8679             ngh1 = sge1[j1];
8680             ngh2 = sge2[j1];
8681             if ((TreeMarkers[ngh1] != tv->treemark) && (ngh1 != ngh2)) {
8682                 TreeStack[trind++] = ngh1;
8683                 TreeStack[trind++] = ngh2;
8684                 if (ngh1 != ngh2) {
8685                     if (build_autom) {
8686                         AUTPERM[ngh1] = ngh2;
8687                         PrmPairs[tv->permInd].arg = ngh1;
8688                         PrmPairs[tv->permInd].val = ngh2;
8689                         tv->permInd++;
8690                     }
8691                     orbjoin_sp_pair(tv->orbits, OrbList, n,
8692                                     ngh1, ngh2, &tv->stats->numorbits);
8693                 }
8694             }
8695         }
8696     }
8697     return;
8698 }
8699 
maxint(int u,int v)8700 int maxint(int u, int v) {
8701     if (u > v) {
8702         return u;
8703     }
8704     else {
8705         return v;
8706     }
8707 }
8708 
minint(int u,int v)8709 int minint(int u, int v) {
8710     if (u < v) {
8711         return u;
8712     }
8713     else {
8714         return v;
8715     }
8716 }
8717 
NextNeighbour(int vtx,Candidate * Cand,Partition * Part,int * Markers,int mark,int * ngh,int n)8718 int NextNeighbour(int vtx, Candidate *Cand, Partition *Part, int* Markers, int mark, int *ngh, int n) {
8719     int *e_vtx;
8720     int i, deg;
8721     int cell1;
8722 
8723     deg = TheGraph[vtx].d;
8724     e_vtx = TheGraph[vtx].e;
8725 
8726     if (deg == n-1) {
8727         return 0;
8728     }
8729 
8730     for (i=0; i<deg; i++) {
8731         if (Markers[e_vtx[i]] != mark) {
8732             cell1 = Part->inv[Cand->invlab[e_vtx[i]]];
8733             if (Part->cls[cell1] > 1) {
8734                 *ngh = e_vtx[i];
8735                 break;
8736             }
8737         }
8738     }
8739     if (i<deg) return 1; else return 0;
8740 }
8741 
NonSingDeg(int vtx,Candidate * Cand,Partition * Part)8742 int NonSingDeg(int vtx, Candidate *Cand, Partition *Part) {
8743     int *e_vtx;
8744     int i, deg, retdeg;
8745 
8746     retdeg = TheGraph[vtx].d;
8747     deg = retdeg;
8748     e_vtx = TheGraph[vtx].e;
8749     for (i=0; i<deg; i++) {
8750         if (Part->cls[Part->inv[Cand->invlab[e_vtx[i]]]] == 1) {
8751             retdeg--;
8752         }
8753     }
8754     return retdeg;
8755 }
8756 
NonSingDegPlus1(Candidate * Cand,Partition * Part,int cell,TracesVars * tv)8757 int NonSingDegPlus1(Candidate *Cand, Partition *Part, int cell, TracesVars *tv) {
8758 
8759     int *e_vtx;
8760     int vtx, sing;
8761     int i, j, deg, retdeg, n, singcount;
8762 
8763     n = tv->input_graph->nv;
8764     singcount = 0;
8765 
8766     SETMARK(StackMarkers, tv->stackmark)
8767 
8768     for (j=cell; j<cell+Part->cls[cell]; j++) {
8769         vtx = Cand->lab[j];
8770         deg = TheGraph[vtx].d;
8771         retdeg = 0;
8772         e_vtx = TheGraph[vtx].e;
8773 
8774         for (i=0; i<deg; i++) {
8775             if (SingNonSing[e_vtx[i]] != 1) {
8776                 e_vtx[retdeg++] = e_vtx[i];
8777             }
8778             else {
8779                 if (StackMarkers[e_vtx[i]] != tv->stackmark) {
8780                     sing = e_vtx[i];
8781                     WorkArray2[singcount] = Part->inv[Cand->invlab[sing]];
8782                     WorkArray[singcount++] = sing;
8783 
8784                     StackMarkers[e_vtx[i]] = tv->stackmark;
8785                 }
8786             }
8787         }
8788         if (j == cell) {
8789             sort2ints(WorkArray2, WorkArray, singcount);
8790         }
8791         if (deg != retdeg) {
8792             memcpy(e_vtx+retdeg, WorkArray, singcount*sizeof(int));
8793             TheGraph[vtx].d = retdeg;
8794         }
8795     }
8796     return retdeg;
8797 }
8798 
NonSingDegPlus2(Candidate * Cand,Partition * Part,int cell,TracesVars * tv)8799 void NonSingDegPlus2(Candidate *Cand, Partition *Part, int cell, TracesVars *tv) {
8800 
8801     int *e_sing;
8802     int sing;
8803     int k, deg1, singdeg, singcount;
8804 
8805     singcount = 0;
8806 
8807     sing = Cand->lab[cell];
8808     singdeg = 0;
8809     deg1 = TheGraph[sing].d;
8810     e_sing = TheGraph[sing].e;
8811 
8812     for (k=0; k<deg1; k++) {
8813         if (SingNonSing[e_sing[k]] != 2) {
8814             e_sing[singdeg++] = e_sing[k];
8815         }
8816     }
8817     TheGraph[sing].d = singdeg;
8818 }
8819 
orbjoin_sp_pair(int * orbits,int * list,int n,int u,int v,int * numorbs)8820 void orbjoin_sp_pair(int *orbits, int *list, int n, int u, int v, int *numorbs) {
8821     int j1, j2, k1, k2;
8822 
8823     j1 = orbits[u];
8824     while (orbits[j1] != j1) j1 = orbits[j1];
8825     j2 = orbits[v];
8826     while (orbits[j2] != j2) j2 = orbits[j2];
8827 
8828     if (j1 != j2) {
8829         k1 = j1;
8830         k2 = j2;
8831         if (k1 < k2) {
8832             (*numorbs)--;
8833             while (list[j2] != k2) {
8834                 orbits[j2] = k1;
8835                 j2 = list[j2];
8836             }
8837             orbits[j2] = k1;
8838             k1 = list[k1];
8839             list[j2] = k1;
8840             list[j1] = k2;
8841         }
8842         else if (k1 > k2) {
8843             (*numorbs)--;
8844             while (list[j1] != k1) {
8845                 orbits[j1] = k2;
8846                 j1 = list[j1];
8847             }
8848             orbits[j1] = k2;
8849             k2 = list[k2];
8850             list[j1] = k2;
8851             list[j2] = k1;
8852         }
8853     }
8854     return;
8855 }
8856 
orbjoin_sp_perm(int * orbits,int * map,int * list,int n,int * numorbs)8857 void orbjoin_sp_perm(int *orbits, int *map, int *list, int n, int *numorbs) {
8858     int i, j1, j2, k1, k2;
8859 
8860     for (i = 0; i < n; ++i)
8861         if (map[i] != i)
8862         {
8863             j1 = orbits[i];
8864             while (orbits[j1] != j1) j1 = orbits[j1];
8865             j2 = orbits[map[i]];
8866             while (orbits[j2] != j2) j2 = orbits[j2];
8867             k1 = j1;
8868             k2 = j2;
8869             if (k1 < k2) {
8870                 (*numorbs)--;
8871                 while (OrbList[j2] != k2) {
8872                     orbits[j2] = k1;
8873                     j2 = OrbList[j2];
8874                 }
8875                 orbits[j2] = k1;
8876                 k1 = OrbList[k1];
8877                 OrbList[j2] = k1;
8878                 OrbList[j1] = k2;
8879             }
8880             else if (k1 > k2) {
8881                 (*numorbs)--;
8882                 while (OrbList[j1] != k1) {
8883                     orbits[j1] = k2;
8884                     j1 = OrbList[j1];
8885                 }
8886                 orbits[j1] = k2;
8887                 k2 = OrbList[k2];
8888                 OrbList[j1] = k2;
8889                 OrbList[j2] = k1;
8890             }
8891         }
8892 }
8893 
NewPartition(int n)8894 struct Partition *NewPartition(int n) {
8895     struct Partition *P;
8896 
8897     P = malloc(sizeof(*(P)));
8898     if (P == NULL) {
8899         fprintf(ERRFILE, "\nError, memory not allocated.\n");
8900         exit(1);
8901     }
8902     P->cls = malloc(n*sizeof(int));
8903     if (P->cls == NULL) {
8904         fprintf(ERRFILE, "\nError, memory not allocated.\n");
8905         exit(1);
8906     }
8907     P->inv = malloc(n*sizeof(int));
8908     if (P->inv == NULL) {
8909         fprintf(ERRFILE, "\nError, memory not allocated.\n");
8910         exit(1);
8911     }
8912     P->code = -1;
8913     P->cells = 0;
8914     return P;
8915 }
8916 
NewPartSpine(int Lev,int n)8917 void NewPartSpine(int Lev, int n) {
8918 
8919     if (Lev > 3) {
8920         Spine[Lev].part = malloc(sizeof(*(Spine[Lev].part)));
8921         if (Spine[Lev].part == NULL) {
8922             fprintf(ERRFILE, "\nError, memory not allocated.\n");
8923             exit(1);
8924         }
8925         Spine[Lev].part->cls = Spine[Lev-3].part->cls;
8926         Spine[Lev].part->inv = Spine[Lev-3].part->inv;
8927         Spine[Lev-3].part->cls = Spine[Lev-3].part->inv = NULL;
8928         Spine[Lev].part->code = -1;
8929         Spine[Lev].part->cells = 0;
8930     }
8931     else {
8932         Spine[Lev].part = NewPartition(n);
8933     }
8934 }
8935 
Place(int vtx,Candidate * Cand,Partition * Part)8936 void Place(int vtx, Candidate *Cand, Partition *Part) {
8937     int vtxto, vtxpos;
8938 
8939     vtxpos = Cand->invlab[vtx];
8940     vtxto = CanonIndices[Part->inv[vtxpos]]++;
8941     if (Cand->lab[vtxpos] != Cand->lab[vtxto]) {
8942         Cand->lab[vtxpos] = Cand->lab[vtxto];
8943         Cand->lab[vtxto] = vtx;
8944         Cand->invlab[Cand->lab[vtxpos]] = vtxpos;
8945         Cand->invlab[Cand->lab[vtxto]] = vtxto;
8946     }
8947     if (Part->cls[vtxto] > 1) {
8948         Part->cls[vtxto+1] = Part->cls[vtxto]-1;
8949         Part->cls[vtxto] = 1;
8950     }
8951 }
8952 
Prefix(Candidate * Cand1,Candidate * Cand2,int k)8953 boolean Prefix(Candidate *Cand1, Candidate *Cand2, int k) {
8954     int i;
8955 
8956     for (i=1; i<=k; i++) {
8957         if (Cand1->lab[Spine[k].tgtpos] != Cand2->lab[Spine[k].tgtpos]) {
8958             break;
8959         }
8960     }
8961     return (i>k);
8962 }
8963 
Preprocess(sparsegraph * sg,permnode ** ring,Candidate * Cand,int n,Partition * Part,struct TracesVars * tv)8964 int Preprocess(sparsegraph *sg,
8965                permnode **ring,
8966                Candidate *Cand,
8967                int n,
8968                Partition *Part,
8969                struct TracesVars* tv) {
8970 
8971     int i, j, j0, k, curr_cell, ind, ind0, ind1, ind2;
8972     int *sge;
8973     int HitClsInd, labi, nghb, value, SplInd, SplCntInd, sc, iend, CStackInd, newcell, TraceInd;
8974 
8975 #define SETPAIRSAUTANDTREE_PREPROC(arg, val) \
8976 if (tv->build_autom) SETPAIRSAUT(arg, val) \
8977 if (arg != val) \
8978 orbjoin_sp_pair(tv->orbits, OrbList, n, arg, val, &tv->stats->numorbits); \
8979 MakeTree(arg, val, sg, n, tv, FALSE);
8980 
8981     CStackInd = 0;
8982     for (i = 0; i < n; i += Part->cls[i]) {
8983         if (TheGraph[Cand->lab[i]].d == 1) {
8984             CStack[CStackInd++] = i;
8985         }
8986     }
8987 
8988     TraceInd = Part->cells;
8989 
8990     if (CStackInd > 0) {
8991         ind = 0;
8992         while (ind < CStackInd) {
8993 
8994             if (tv->mark > (NAUTY_INFINITY-2)) {
8995                 memset(Markers, 0, n*sizeof(int));
8996                 memset(MarkHitVtx, 0, n*sizeof(int));
8997                 tv->mark = 0;
8998             }
8999             tv->mark++;
9000 
9001             curr_cell = CStack[ind++];
9002             ind2 = curr_cell+Part->cls[curr_cell];
9003             HitClsInd = 0;
9004             for (i = curr_cell; i < ind2; i++) {
9005                 labi = Cand->lab[i];
9006                 nghb = *(TheGraph[labi].e);
9007 
9008                 if (TheGraph[nghb].d != 1) {
9009                     TheGraph[labi].d = -1;
9010                     TheGraph[labi].one = TRUE;
9011                 }
9012 
9013                 if (MarkHitVtx[nghb] == tv->mark) {
9014                     NghCounts[nghb]++;
9015                 }
9016                 else {
9017                     value = Part->inv[Cand->invlab[nghb]];
9018                     MarkHitVtx[nghb] = tv->mark;
9019                     NghCounts[nghb] = 1;
9020                     if (Markers[value] != tv->mark) {
9021                         HitCls[HitClsInd++] = value;
9022                         Markers[value] = tv->mark;
9023                         HitVtx[value] = nghb;
9024                         ElmHitCll[value] = 1;
9025                     }
9026                     else {
9027                         HitVtx[value+ElmHitCll[value]++] = nghb;
9028                     }
9029                 }
9030             }
9031             tv->mark++;
9032 
9033             sort_Split_Array(HitCls,HitClsInd);
9034             SplInd = 0;
9035             SplCls[0] = n;
9036             for (j = 0; j < HitClsInd; j++) {
9037                 ind1 = HitCls[j];
9038                 if ((ElmHitCll[ind1] > 0) && (ElmHitCll[ind1] < Part->cls[ind1])) {
9039                     SplCls[SplInd++] = ind1;
9040                 }
9041                 else {
9042                     ind2 = ind1+Part->cls[ind1];
9043                     value = NghCounts[Cand->lab[ind1++]];
9044                     for (i = ind1; i < ind2; i++) {
9045                         if (NghCounts[Cand->lab[i]] != value) {
9046                             SplCls[SplInd++] = HitCls[j];
9047                             break;
9048                         }
9049                     }
9050                     if (i == ind2) {
9051                         ind1 = HitCls[j];
9052                         if (TheGraph[Cand->lab[ind1]].d != 1) {
9053                             for (i = ind1; i < ind2; i++) {
9054                                 value = Cand->lab[i];
9055                                 Edge_Delete(value, NghCounts[value], Cand, tv);
9056                                 sge = TheGraph[value].e+TheGraph[value].d;
9057                                 if (NghCounts[value]>1) {
9058                                     factorial(&(tv->stats->grpsize1), &(tv->stats->grpsize2), NghCounts[value]);
9059                                     if (tv->permInd) ResetAutom(tv->permInd, n, tv);
9060                                     for (j0=0; j0<NghCounts[value]-1; j0++) {
9061                                         SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[j0+1])
9062                                     }
9063                                     SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[0])
9064                                     SPECIALGENERATORS
9065                                     if (NghCounts[value] > 2) {
9066                                         if (tv->permInd) ResetAutom(tv->permInd, n, tv);
9067                                         SETPAIRSAUTANDTREE_PREPROC(sge[0], sge[1])
9068                                         if (tv->build_autom) {
9069                                             SETPAIRSAUT(sge[1], sge[0])
9070                                         }
9071                                         MakeTree(sge[1], sge[0], sg, n, tv, FALSE);
9072                                         SPECIALGENERATORS
9073                                     }
9074                                 }
9075                             }
9076                             if (TheGraph[Cand->lab[ind1]].d == 1) {
9077                                 CStack[CStackInd++] = ind1;
9078                             }
9079                         }
9080                     }
9081                 }
9082             }
9083 
9084             if (SplInd) {
9085 
9086                 for (sc = 0; sc < SplInd; sc++) {    /* For each cell C to be split */
9087                     ind0 = SplCls[sc];
9088                     ind1 = ind0 + Part->cls[ind0];
9089                     SplCntInd = 0;
9090                     if (ElmHitCll[ind0] < Part->cls[ind0]) {
9091                         SplCnt[SplCntInd++] = 0;
9092                         SplPos[0] = Part->cls[ind0] - ElmHitCll[ind0];
9093                     }
9094 
9095                     /* According to the numbers of neighbors of C into the current cell */
9096                     /* compute how many vertices in C will be placed into the same new cell */
9097                     iend = ind0 + ElmHitCll[ind0];
9098                     for (i = ind0; i < iend; i++) {
9099                         value = NghCounts[HitVtx[i]];
9100                         if (Markers[value] != tv->mark) {
9101                             Markers[value] = tv->mark;
9102                             SplCnt[SplCntInd++] = value;
9103                             SplPos[value] = 1;
9104                         }
9105                         else {
9106                             SplPos[value]++;
9107                         }
9108                     }
9109                     tv->mark++;
9110 
9111                     /* Sort the values deriving from the previous step */
9112                     sort_Split_Array(SplCnt, SplCntInd);
9113 
9114                     Part->cells += SplCntInd-1;
9115 
9116                     /* Split the cell C and update the information for sizes of new cells */
9117                     /* Put the new cells into the stack */
9118                     i = ind0;
9119                     for (k = 0; k < SplCntInd; k++) {
9120                         value = SplPos[SplCnt[k]];
9121                         Part->cls[i] = value;
9122                         SplPos[SplCnt[k]] = i;
9123                         i += value;
9124                         if (i < ind1) {
9125                             TheTrace[TraceInd++] = i;
9126                         }
9127                     }
9128 
9129                     /* Permute elements of the cell C */
9130                     iend = ind0 + ElmHitCll[ind0];
9131 
9132                     for (i = ind0; i < iend; i++) {
9133                         value = HitVtx[i];
9134                         Edge_Delete(value, NghCounts[value], Cand, tv);
9135                         sge = TheGraph[value].e+TheGraph[value].d;
9136                         if (NghCounts[value] > 1) {
9137                             factorial(&(tv->stats->grpsize1), &(tv->stats->grpsize2), NghCounts[value]);
9138 
9139                             if (tv->permInd) ResetAutom(tv->permInd, n, tv);
9140                             for (j0=0; j0<NghCounts[value]-1; j0++) {
9141                                 SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[j0+1])
9142                             }
9143                             SETPAIRSAUTANDTREE_PREPROC(sge[j0], sge[0])
9144                             SPECIALGENERATORS
9145                             if (NghCounts[value] > 2) {
9146                                 if (tv->permInd) ResetAutom(tv->permInd, n, tv);
9147                                 SETPAIRSAUTANDTREE_PREPROC(sge[0], sge[1])
9148                                 if (tv->build_autom) {
9149                                     SETPAIRSAUT(sge[1], sge[0])
9150                                 }
9151                                 MakeTree(sge[1], sge[0], sg, n, tv, FALSE);
9152                                 SPECIALGENERATORS
9153                             }
9154                         }
9155 
9156                         j = SplPos[NghCounts[value]]++;         /* where HitVtx[i] goes */
9157                         k = Cand->invlab[value];                /* where HitVtx[i] is in lab */
9158                         Cand->lab[k] = Cand->lab[j];
9159                         Cand->lab[j] = value;
9160                         Cand->invlab[value] = j;
9161                         Cand->invlab[Cand->lab[k]] = k;
9162                         NghCounts[value] = 0;
9163                     }
9164 
9165                     /* Reconstruct the cell C and update the inverse partition */
9166                     newcell = ind1 - ElmHitCll[ind0];
9167                     i = newcell;
9168                     ind2 = newcell+Part->cls[newcell]-1;
9169                     do {
9170                         Part->inv[i] = newcell;
9171                         if (i == ind2) {
9172                             newcell = i+1;
9173                             if (newcell < n) ind2 = newcell+Part->cls[newcell]-1;
9174                         }
9175                     }
9176                     while (++i < ind1);
9177 
9178                     for (i = ind0, k = 0; k < SplCntInd; i+=Part->cls[i], k++) {
9179                         if ((k > 0) || (SplCnt[0] > 0)) {
9180                             if (TheGraph[Cand->lab[i]].d == 1) {
9181                                 CStack[CStackInd++] = i;
9182                             }
9183                         }
9184                         if (Part->cls[i] == 1) {
9185                             Cand->singcode = MASHCOMM(Cand->singcode, Cand->lab[i]);
9186                         }
9187                     }
9188 
9189                 }
9190             }
9191         }
9192         return 1;
9193     }
9194     else {
9195         return 0;
9196     }
9197 }
9198 
PrintPartition(int * v,int * cls,int n,int l,int line)9199 void PrintPartition(int *v, int *cls, int n, int l, int line) {
9200     int i, j, k;
9201 
9202     k=0;
9203     fprintf(outfile, "[ ");
9204     for (i=0; i<n; i+=cls[i]) {
9205         if ((cls[i]<=0) || i>=n) {
9206             printf("WRONG");
9207             break;
9208         }
9209         for (j=i; j<i+cls[i]; j++) {
9210             fprintf(outfile, "%d ", v[j]+l);
9211             if (k++ > 50) {
9212                 fprintf(outfile,"\n");
9213                 k=0;
9214             }
9215         }
9216         if ((i+cls[i])<n) fprintf(outfile, "| ");
9217     }
9218     fprintf(outfile, "] at line %d\n", line);
9219     return;
9220 }
9221 
PrintVect(int * v,int z,int n,int l)9222 void PrintVect(int *v, int z, int n, int l) {
9223     int i;
9224     printf("[");
9225     for (i = z; i<n; i++)
9226         printf(" %2d", v[i]+l);
9227     printf(" ]\n");
9228     return;
9229 }
9230 
PrintWeightedGraph1(sparsegraph * g_arg,int n,char msg[30])9231 void PrintWeightedGraph1(sparsegraph *g_arg, int n, char msg[30]) {
9232     int i, j;
9233     int *ngh1, *wgh1;
9234 
9235     printf("%s\n",msg);
9236     for (i=0; i<n; i++) {
9237         ngh1 = g_arg->e+g_arg->v[i];
9238         wgh1 = g_arg->w+g_arg->v[i];
9239         printf("%2d: ",i+labelorg);
9240         for (j=0; j<g_arg->d[i]; j++) {
9241             printf("%2d ",ngh1[j]);
9242             printf("(%d) ",wgh1[j]);
9243         }
9244         printf("\n");
9245     }
9246     printf("\n");
9247 }
9248 
PrintWeightedGraph2(int n,char msg[30])9249 void PrintWeightedGraph2(int n, char msg[30]) {
9250     int i, j;
9251     int *ngh1, *wgh1;
9252 
9253     printf("%s\n",msg);
9254     for (i=0; i<n; i++) {
9255         ngh1 = TheGraph[i].e;
9256         printf("%2d: ",i+labelorg);
9257         for (j=0; j<TheGraph[i].d; j++) {
9258             printf("%2d ",ngh1[j]+labelorg);
9259         }
9260         printf(";\n");
9261     }
9262     printf("\n");
9263 }
9264 
PrintBlissGraph(int n)9265 void PrintBlissGraph(int n) {
9266     int i, j;
9267     int *ngh1, *wgh1;
9268 
9269     fprintf(outfile,"p edge %d\n",n);
9270     for (i=0; i<n; i++) {
9271         ngh1 = TheGraph[i].e;
9272         for (j=0; j<TheGraph[i].d; j++) {
9273             if (i < ngh1[j]) {
9274                 fprintf(outfile, "e %d %d\n",i+labelorg,ngh1[j]+labelorg);
9275             }
9276         }
9277     }
9278     printf("\n");
9279 }
9280 
putgraphplus_sg(FILE * f,sparsegraph * sg,int linelength)9281 void putgraphplus_sg(FILE *f, sparsegraph *sg, int linelength)
9282 {
9283     int i,n,curlen,slen;
9284     int *d,*e;
9285     size_t *v,j;
9286     char s[60];
9287 
9288     n = sg->nv;
9289     SG_VDE(sg,v,d,e);
9290 
9291     for (i = 0; i < n; ++i)
9292     {
9293         fprintf(f,"%3d : ",i+labelorg);
9294         curlen = 7;
9295 
9296         for (j = v[i]; j < v[i]+d[i]; ++j)
9297         {
9298             if (sg->w) {
9299                 if (sg->w[j] != 1) {
9300                     slen = itos(sg->w[j],s);
9301                     if (linelength > 0 && curlen + slen + 1 > linelength)
9302                     {
9303                         putstring(f,"\n  ");
9304                         curlen = 2;
9305                     }
9306                     PUTC(' ',f);
9307                     PUTC('w',f);
9308                     putstring(f,s);
9309                     curlen += slen + 3;
9310                 }
9311             }
9312 
9313             slen = itos(e[j]+labelorg,s);
9314             if (linelength > 0 && curlen + slen + 1 > linelength)
9315             {
9316                 putstring(f,"\n  ");
9317                 curlen = 2;
9318             }
9319             PUTC(' ',f);
9320             putstring(f,s);
9321             curlen += slen + 1;
9322         }
9323         putstring(f,";\n");
9324     }
9325 }
9326 
quickSort(int * arr,int elements)9327 void quickSort(int *arr, int elements) {
9328 
9329 #define MAX_LEVELS 300
9330 
9331     int piv, beg[MAX_LEVELS], end[MAX_LEVELS], i = 0, L, R, swap;
9332     int k, value;
9333 
9334     beg[0] = 0;
9335     end[0] = elements;
9336     while (i>= 0) {
9337         L = beg[i];
9338         R = end[i]-1;
9339         if (L<R-8) {
9340             piv = arr[(L+R)/2];
9341             arr[(L+R)/2] = arr[L];
9342             arr[L] = piv;
9343             while (L<R) {
9344                 while (arr[R]>= piv && L<R) R--;
9345                 if (L<R) arr[L++] = arr[R];
9346                 while (arr[L]<= piv && L<R) L++;
9347                 if (L<R) arr[R--] = arr[L];
9348             }
9349             arr[L] = piv;
9350             beg[i+1] = L+1;
9351             end[i+1] = end[i]; end[i++] = L;
9352             if (end[i]-beg[i]>end[i-1]-beg[i-1]) {
9353                 swap = beg[i];
9354                 beg[i] = beg[i-1];
9355                 beg[i-1] = swap;
9356                 swap = end[i];
9357                 end[i] = end[i-1];
9358                 end[i-1] = swap;
9359             }
9360         }
9361         else {
9362             i--;
9363         }
9364     }
9365     for (k = 1; k < elements; ++k) {
9366         value = arr[k];
9367         i = k - 1;
9368         while ((i >= 0) && (value < arr[i])) {
9369             arr[i + 1] = arr[i];
9370             --i;
9371         }
9372         arr[i + 1] = value;
9373     }
9374 }
9375 
RemoveFromLevel(int from,int to,int strategy,boolean reinit)9376 void RemoveFromLevel(int from, int to, int strategy, boolean reinit) {
9377     int i;
9378 
9379     for (i=from; i<=to; i++) {
9380         if (Spine[i].listend) {
9381             (Spine[i].listend)->next = GarbList;
9382             GarbList = Spine[i].liststart;
9383             Spine[i].liststart = Spine[i].listend = NULL;
9384         }
9385         if (strategy == 0 || reinit) {
9386             Spine[i].listcounter = 0;
9387             if (i>from) {
9388                 Spine[i].thetracexists = FALSE;
9389                 Spine[i].part->code = -1;
9390             }
9391         }
9392     }
9393 }
9394 
searchtrie_make(Candidate * CurrCand,Candidate * NextCand,int n,struct TracesVars * tv)9395 searchtrie *searchtrie_make(Candidate *CurrCand, Candidate *NextCand, int n, struct TracesVars *tv) {
9396 
9397     searchtrie *st;
9398     if (tv->strienext == n) {
9399         tv->strienext = 0;
9400         tv->strielist->next = malloc(sizeof(struct trielist));
9401         if (tv->strielist->next == NULL) {
9402             fprintf(ERRFILE, "\nError, memory not allocated.\n");
9403             exit(1);
9404         }
9405         tv->strielist->next->prev = tv->strielist;
9406         tv->strielist = tv->strielist->next;
9407         tv->strielist->next = NULL;
9408         tv->strielist->triearray = malloc(n*sizeof(searchtrie));
9409         if (tv->strielist->triearray == NULL) {
9410             fprintf(ERRFILE, "\nError, memory not allocated.\n");
9411             exit(1);
9412         }
9413     }
9414     st = &(tv->strielist->triearray[tv->strienext]);
9415     st->father = CurrCand->stnode;
9416     st->name = NextCand->name;
9417     st->index = tv->newindex+1;
9418     st->vtx = NextCand->vertex;
9419     st->level = tv->tolevel;
9420     st->first_child = st->next_sibling = st->last_child = st->goes_to = NULL;
9421     if (st->father) {
9422         if (st->father->first_child) {
9423             st->father->last_child->next_sibling = st;
9424             st->father->last_child = st;
9425         }
9426         else {
9427             st->father->first_child = st->father->last_child = st;
9428         }
9429     }
9430     NextCand->stnode = st;
9431     if (tv->newgotonode) {
9432         tv->newgotonode->goes_to = st;
9433     }
9434     if (tv->gotonode) {
9435         st->goes_to = tv->gotonode;
9436         tv->gotonode = NULL;
9437     }
9438     tv->strienext++;
9439     return st;
9440 }
9441 
searchtrie_new(int n,struct TracesVars * tv)9442 trielist *searchtrie_new(int n, struct TracesVars *tv) {
9443 
9444     tv->strielist = malloc(sizeof(struct trielist));
9445     if (tv->strielist == NULL) {
9446         fprintf(ERRFILE, "\nError, memory not allocated.\n");
9447         exit(1);
9448     }
9449     tv->strielist->prev = tv->strielist->next = NULL;
9450     tv->strielist->triearray = malloc(n*sizeof(searchtrie));
9451     if (tv->strielist->triearray == NULL) {
9452         fprintf(ERRFILE, "\nError, memory not allocated.\n");
9453         exit(1);
9454     }
9455     tv->strielist->triearray[0].father = tv->strielist->triearray[0].first_child = NULL;
9456     tv->strielist->triearray[0].next_sibling = tv->strielist->triearray[0].last_child = NULL;
9457     tv->strielist->triearray[0].goes_to = NULL;
9458     tv->strielist->triearray[0].index = 1;
9459     tv->strielist->triearray[0].name = tv->strielist->triearray[0].level = 0;
9460     tv->strielist->triearray[0].vtx = n;
9461 
9462     tv->strienext = 1;
9463     return tv->strielist;
9464 }
9465 
Select_from_CStack(int * cls,int CStackInd)9466 int Select_from_CStack(int *cls, int CStackInd) {
9467     int j, k;
9468 
9469     j = CStackInd;
9470     k = CStackInd;
9471     while (--j > 0) {
9472         if (cls[CStack[j]] < cls[CStack[k]]) {
9473             k = j;
9474         }
9475         if ((cls[CStack[k]] == 1) || (j < CStackInd - 12)) {
9476             break;
9477         }
9478     }
9479     return k;
9480 }
9481 
SelectNextLevel(int n,struct TracesVars * tv,struct TracesInfo * ti)9482 boolean SelectNextLevel(int n, struct TracesVars *tv, struct TracesInfo *ti) {
9483     int i, j, val;
9484     Candidate *FirstCand;
9485     boolean orbitcell;
9486     VERB_PRINT("SelNxtLev",3,FALSE)
9487 
9488     switch (tv->compstage) {
9489         case 2:
9490             tv->nextlevel = tv->maxtreelevel;
9491             while (tv->nextlevel >=0) {
9492                 if (Spine[tv->nextlevel].liststart) {
9493                     break;
9494                 }
9495                 tv->nextlevel--;
9496             }
9497             if (tv->nextlevel < 0) {
9498                 return FALSE;
9499             }
9500             break;
9501         default:
9502             switch (tv->strategy) {
9503                 case 0:
9504                     tv->nextlevel = tv->fromlevel;
9505                     while (!Spine[tv->nextlevel].liststart) {
9506                         (tv->nextlevel)++;
9507                     }
9508                     PRINTF2("SelectNextLevel 1?: finalnumcells: %d; ", tv->finalnumcells);
9509                     PRINTF2("Spine[tv->nextlevel].part->cells: %d; ", Spine[tv->nextlevel].part->cells);
9510                     PRINTF2("tv->maxtreelevel: %d; ", tv->maxtreelevel);
9511                     PRINTF2("tv->nextlevel: %d\n", tv->nextlevel);
9512                     if ((Spine[tv->nextlevel].part->cells == tv->finalnumcells) || (tv->nextlevel > tv->maxtreelevel)) {
9513                         return FALSE;
9514                     }
9515                     else {
9516                         /* Check the whole group */
9517                         if ((tv->group_level < tv->tolevel) && !ti->first_matching && ti->thegrouphaschanged) {
9518 
9519                             FirstCand = Spine[tv->nextlevel].liststart;
9520                             val = tv->orbits[FirstCand->lab[Spine[1].tgtcell]];
9521                             for (i=Spine[1].tgtcell; i<Spine[1].tgtend; i++) {
9522                                 if (tv->orbits[FirstCand->lab[i]] != val) {
9523                                     break;
9524                                 }
9525                             }
9526                             if (i<Spine[1].tgtend) {
9527                                 orbitcell = FALSE;
9528                             } else {
9529                                 orbitcell = TRUE;
9530                             }
9531                             if (orbitcell) {
9532                                 FirstCand = Spine[tv->nextlevel].liststart;
9533                                 FixBase(fix, tv, FirstCand, 0, tv->firstpathlength);
9534                                 if (tv->options->verbosity >= 2) tv->schreier1 -= CPUTIME;
9535                                 getorbitsmin(fix, tv->nfix, gpB, &gensB, &tv->currorbit, NULL, n, n, TRUE);
9536                                 if (tv->options->verbosity >= 2) tv->schreier1 += CPUTIME;
9537                                 for (j=2; j<=tv->firstpathlength; j++) {
9538                                     tv->currorbit = findcurrorbits(gpB, j-1);
9539                                     val = tv->currorbit[FirstCand->lab[Spine[j].tgtcell]];
9540                                     for (i=Spine[j].tgtcell; i<Spine[j].tgtend; i++) {
9541                                         if (tv->currorbit[FirstCand->lab[i]] != val) {
9542                                             break;
9543                                         }
9544                                     }
9545                                     if (i<Spine[j].tgtend) {
9546                                         break;
9547                                     }
9548                                 }
9549                                 tv->group_level = j-1;
9550                                 if (tv->group_level >= tv->tolevel) {
9551                                     ti->thegrouphaschanged = FALSE;
9552                                 }
9553                             }
9554                             /* End check the whole group */
9555                         }
9556 
9557                     }
9558                     break;
9559                 case 1:
9560                     tv->nextlevel = tv->maxtreelevel;
9561                     PRINTF2("SelectNextLevel 2?: finalnumcells: %d; ", tv->finalnumcells);
9562                     PRINTF2("Spine[tv->nextlevel].part->cells: %d; ", Spine[tv->nextlevel].part->cells);
9563                     if (Spine[tv->nextlevel].part->cells == tv->finalnumcells) {
9564                         (tv->nextlevel)--;
9565                     }
9566                     while (tv->nextlevel >= 0) {
9567                         if (Spine[tv->nextlevel].liststart) {
9568                             break;
9569                         }
9570                         tv->nextlevel--;
9571                     }
9572                     if (tv->nextlevel < 0) {
9573                         return FALSE;
9574                     }
9575                     break;
9576                 default:
9577                     break;
9578             }
9579             break;
9580     }
9581     return TRUE;
9582 }
9583 
SetAutom(int q,int n,struct TracesVars * tv)9584 void SetAutom(int q, int n, struct TracesVars *tv) {
9585     int i;
9586 
9587     for (i=0; i<q; i++) {
9588         AUTPERM[PrmPairs[i].arg] = PrmPairs[i].val;
9589     }
9590     return;
9591 }
9592 
ResetAutom(int q,int n,struct TracesVars * tv)9593 void ResetAutom(int q, int n, struct TracesVars *tv) {
9594     int i;
9595 
9596     if (n/q < 256) {
9597         memcpy(AUTPERM, IDENTITY_PERM, n*sizeof(int));
9598     }
9599     else {
9600         for (i=0; i<q; i++) {
9601             AUTPERM[PrmPairs[i].arg] = PrmPairs[i].arg;
9602         }
9603     }
9604     tv->permInd = 0;
9605     return;
9606 }
9607 
sort_Split_Array(int * Array,int Ind)9608 void sort_Split_Array(int *Array, int Ind){
9609     int i, k, value;
9610 
9611     switch (Ind) {
9612         case 0:
9613         case 1:
9614             break;
9615         case 2:
9616             if (Array[0] > Array[1]) {
9617                 value = Array[0];
9618                 Array[0] = Array[1];
9619                 Array[1] = value;
9620             }
9621             break;
9622         case 3:
9623         case 4:
9624         case 5:
9625         case 6:
9626         case 7:
9627         case 8:
9628             for (k = 1; k < Ind; ++k) {
9629                 value = Array[k];
9630                 i = k - 1;
9631                 while ((i >= 0) && (value < Array[i])) {
9632                     Array[i + 1] = Array[i];
9633                     --i;
9634                 }
9635                 Array[i + 1] = value;
9636             }
9637             break;
9638         default:
9639             quickSort(Array, Ind);
9640             break;
9641     }
9642 }
9643 
spinelementorbsize(int * orbits,int * lab,int size,int elem)9644 int spinelementorbsize(int *orbits, int *lab, int size, int elem) {
9645     int i, j, val;
9646 
9647     j = 0;
9648     val = orbits[elem];
9649     for (i = 0; i < size; ++i) {
9650         if (orbits[lab[i]] == val) ++j;
9651     }
9652     return j;
9653 }
9654 
TargetCell(Candidate * TargCand,Partition * Part,int n,struct TracesVars * tv,int Lv)9655 boolean TargetCell(Candidate *TargCand, Partition *Part, int n, struct TracesVars* tv, int Lv) {
9656     int TCell = -1, TCSize = 1;
9657     int i;
9658     VERB_PRINT("TCELL",3,FALSE)
9659     if (Part->cells == n) {
9660         tv->finalnumcells = n;
9661         return FALSE;
9662     }
9663     if (tv->maxdeg <=2) {
9664         return FALSE;
9665     }
9666 
9667     if (Lv < tv->tcellevel) {
9668         tv->tcell = Spine[Lv+1].tgtcell;
9669         return TRUE;
9670     }
9671     else {
9672         if (Part->cls[0] == n) {
9673             tv->tcell = 0;
9674             return TRUE;
9675         }
9676         while (TCell < 0) {
9677             for (i = Spine[Lv].tgtcell; i < Spine[Lv].tgtend; i += Part->cls[i]) {
9678                 if (Part->cls[i] > TCSize) {
9679                     if (NonSingDeg(TargCand->lab[i], TargCand, Part) > 2) {
9680                         TCSize = Part->cls[i];
9681                         TCell = i;
9682                     }
9683                 }
9684             }
9685             Lv--;
9686             if ((Lv < 0) && (TCell < 0)) return FALSE;
9687         }
9688         tv->tcell = TCell;
9689         return TRUE;
9690     }
9691 }
9692 
TargetCellExpPath(Candidate * TargCand,Partition * Part,struct TracesVars * tv)9693 int TargetCellExpPath(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
9694     int Lv, n;
9695     VERB_PRINT("TCEP",3,FALSE)
9696 
9697     n = tv->input_graph->nv;
9698     if (Part->cells == n) {
9699         return 0;
9700     }
9701 
9702     Lv = tv->tolevel_tl+1;
9703     SpineTL_tl = Spine+Lv;
9704     if (tv->tolevel_tl < tv->tcellevel) {
9705         tv->tcellexpath = Part->inv[SpineTL_tl->tgtcell];
9706         tv->tolevel_tl++;
9707         if (Part->cls[tv->tcellexpath] == 1) {
9708             if (tv->options->verbosity >= 2) {
9709                 if (tv->tolevel_tl-tv->tolevel == 6) {
9710                     fprintf(outfile, "... ");
9711                 }
9712             }
9713             return TargetCellExpPath(TargCand, Part, tv);
9714         } else {
9715             return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
9716         }
9717     }
9718     else {
9719         if (TargetCellFirstPath(TargCand, Part, tv)) {
9720             return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
9721         }
9722         else {
9723             return 0;
9724         }
9725     }
9726 }
9727 
TargetCellFirstPath(Candidate * TargCand,Partition * Part,struct TracesVars * tv)9728 boolean TargetCellFirstPath(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
9729     int n, TCell, TCSize, TCell1, TCSize1;
9730     int Lv, i, Lev, vtx, vtx_d;
9731     int loopstart, loopend;
9732     boolean divided;
9733     VERB_PRINT("TCFP",3,FALSE)
9734 
9735     n = tv->input_graph->nv;
9736 
9737     if (Part->cells == n) {
9738         return 0;
9739     }
9740 
9741     Lev = tv->tolevel_tl;
9742     Lv = tv->tolevel_tl;
9743 
9744     TCell = TCell1 = -1;
9745     TCSize = TCSize1 = 1;
9746 
9747     while (TCell < 0) {
9748 
9749         if (tv->compstage == 2) {
9750             loopstart = Spine[Lv].tgtcell;
9751             divided = FALSE;
9752         } else {
9753             loopstart = Part->inv[Spine[Lv].tgtcell];
9754             divided = FALSE;
9755 
9756             if (Lv == tv->lastlev) {
9757                 loopstart = Part->inv[tv->lastcell];
9758                 divided = TRUE;
9759             }
9760         }
9761 
9762         i = loopstart;
9763         loopend = Spine[Lv].tgtend;
9764         while (i < loopend) {
9765             if (Part->cls[i] > TCSize) {
9766                 vtx = TargCand->lab[i];
9767                 vtx_d = TheGraph[vtx].d;
9768                 if (vtx_d > 2) {
9769                     if (NonSingDeg(vtx, TargCand, Part) > 2) {
9770                         TCSize = Part->cls[i];
9771                         TCell = i;
9772                         if (TCSize == WorkArray[Lv]) {
9773                             break;
9774                         }
9775                     }
9776                 }
9777             }
9778             i += Part->cls[i];
9779             if (divided && (i == loopend)) {
9780                 i = loopstart = Part->inv[Spine[Lv].tgtcell];
9781                 loopend = tv->lastcell;
9782                 divided = FALSE;
9783                 TCSize1 = TCSize;
9784                 TCell1 = TCell;
9785                 TCell = -1;
9786                 TCSize = 1;
9787             }
9788         }
9789 
9790         if (TCSize1 > TCSize) {
9791             TCell = TCell1;
9792             TCSize = TCSize1;
9793         }
9794 
9795         if (TCell < 0) {
9796             if (Lv == 0) {
9797                 if (tv->answ == 2) {
9798                     tv->finalnumcells = minint(Part->cells,tv->finalnumcells);    /* 160712 */
9799                     tv->finalnumcells = Part->cells;
9800                 }
9801                 return FALSE;
9802             } else {
9803                 Lv = Spine[Lv].tgtfrom;
9804             }
9805         }
9806     }
9807 
9808     tv->tcellexpath = tv->lastcell = TCell;
9809     tv->tolevel_tl++;
9810 
9811     Spine[tv->tolevel_tl].tgtfrom = tv->lastlev = Lv;
9812     Spine[tv->tolevel_tl].tgtcell = tv->tcellexpath;
9813     Spine[tv->tolevel_tl].tgtsize = WorkArray[Lv] = TCSize;
9814     Spine[tv->tolevel_tl].tgtend = Spine[tv->tolevel_tl].tgtcell + TCSize;
9815     Spine[tv->tolevel_tl].tgtpos = Spine[tv->tolevel_tl].tgtend - 1;
9816     tv->tcellevel = tv->tolevel_tl;
9817 
9818     if (Lv != Lev) {
9819         BreakSteps[Lev] = ++tv->brkstpcount;
9820         if (Spine[tv->tolevel].liststart) {
9821             if (!Spine[tv->tolevel].liststart->firstsingcode) {
9822                 Spine[tv->tolevel].liststart->firstsingcode = Spine[tv->tolevel].liststart->pathsingcode;
9823             }
9824         }
9825     }
9826     return TRUE;
9827 }
9828 
traces_freedyn(void)9829 void traces_freedyn(void) {
9830     /* Free the static dynamic memory used by Traces */
9831 #if !MAXN
9832     DYNFREE(AUTPERM, AUTPERM_sz);
9833     DYNFREE(BreakSteps, BreakSteps_sz);
9834     DYNFREE(CStack, CStack_sz);
9835     DYNFREE(CurrOrbSize, CurrOrbSize_sz);
9836     DYNFREE(CurrRefCells, CurrRefCells_sz);
9837     DYNFREE(Diff, Diff_sz);
9838     DYNFREE(Factorials, Factorials_sz);
9839     DYNFREE(fix, fix_sz);
9840     DYNFREE(IDENTITY_PERM, IDENTITY_PERM_sz);
9841     DYNFREE(Markers, Markers_sz);
9842     DYNFREE(TreeMarkers, TreeMarkers_sz);
9843     DYNFREE(AutMarkers, AutMarkers_sz);
9844     DYNFREE(MarkHitVtx, MarkHitVtx_sz);
9845     DYNFREE(MultRefCells, MultRefCells_sz);
9846     DYNFREE(NghCounts, NghCounts_sz);
9847     DYNFREE(OrbSize, OrbSize_sz);
9848     DYNFREE(OrbList, OrbList_sz);
9849     DYNFREE(PrmPairs, PrmPairs_sz);
9850     DYNFREE(TempOrbList, TempOrbList_sz);
9851     DYNFREE(RefCells, RefCells_sz);
9852     DYNFREE(RefPath, RefPath_sz);
9853     DYNFREE(Singletons, Singletons_sz);
9854     DYNFREE(SplCls, SplCls_sz);
9855     DYNFREE(SplCnt, SplCnt_sz);
9856     DYNFREE(SplPos, SplPos_sz);
9857     DYNFREE(StackMarkers, StackMarkers_sz);
9858     DYNFREE(TheTrace, TheTrace_sz);
9859     DYNFREE(TheTraceCC, TheTraceCC_sz);
9860     DYNFREE(TheTraceSplNum, TheTraceSplNum_sz);
9861     DYNFREE(TheTraceSteps, TheTraceSteps_sz);
9862     DYNFREE(TEMPLAB, TEMPLAB_sz);
9863     DYNFREE(TEMPINVLAB, TEMPINVLAB_sz);
9864     DYNFREE(WeightsSeq, WeightsSeq_sz);
9865     DYNFREE(WorkArray, WorkArray_sz);
9866     DYNFREE(WorkArray0, WorkArray0_sz);
9867     DYNFREE(WorkArray1, WorkArray1_sz);
9868     DYNFREE(WorkArray2, WorkArray2_sz);
9869     DYNFREE(WorkArray3, WorkArray3_sz);
9870     DYNFREE(WorkArray4, WorkArray4_sz);
9871     DYNFREE(WorkArray5, WorkArray5_sz);
9872     DYNFREE(WorkArray6, WorkArray6_sz);
9873     DYNFREE(WorkArray7, WorkArray7_sz);
9874     DYNFREE(Neighbs1, Neighbs1_sz);
9875     DYNFREE(Neighbs2, Neighbs2_sz);
9876     DYNFREE(TreeStack, TreeStack_sz);
9877     DYNFREE(Spine, Spine_sz);
9878     DYNFREE(TrieArray, TrieArray_sz);
9879     DYNFREE(TheGraph, TheGraph_sz);
9880     DYNFREE(EPCodes, EPCodes_sz);
9881 #endif
9882 }
9883 
TreeFyTwo(int From,Candidate * Cand1,Candidate * Cand2,Partition * Part,int n,struct TracesVars * tv,struct TracesInfo * ti)9884 boolean TreeFyTwo(int From, Candidate *Cand1, Candidate *Cand2, Partition *Part, int n,
9885                   struct TracesVars* tv, struct TracesInfo *ti) {
9886     int i, i1, i2, j1, j2, k;
9887     int vtx1, vtx2, ngh1, ngh2, arg, val;
9888     int *tgtc1, *tgtc2, *adj1, *adj2;
9889     int iend;
9890 
9891     SETMARK(Markers, tv->mark)
9892 
9893     i2=0;
9894 
9895     if (tv->permInd) ResetAutom(tv->permInd, n, tv);
9896     i1 = Spine[From].tgtsize;
9897     tgtc1 = Cand1->lab+Spine[From].tgtcell;
9898     tgtc2 = Cand2->lab+Spine[From].tgtcell;
9899     for (i=0; i<i1; i++) {
9900         arg = tgtc1[i];
9901         val = tgtc2[i];
9902         if ((Markers[arg] != tv->mark) && (Markers[val] != tv->mark)) {
9903             SETPAIRSAUT(arg, val)
9904             SETPAIRSAUT(val, arg)
9905             Markers[arg] = tv->mark;
9906             Markers[val] = tv->mark;
9907         } else {
9908             return FALSE;    /*  160715  */
9909         }
9910     }
9911 
9912     while (i2 < tv->permInd) {
9913         vtx1 = PrmPairs[i2].arg;
9914         vtx2 = PrmPairs[i2++].val;
9915         adj1 = TheGraph[vtx1].e;
9916         adj2 = TheGraph[vtx2].e;
9917         iend = TheGraph[vtx1].d;
9918         j1 = j2 = 0;
9919         for (k=0; k < iend; k++) {
9920             ngh1 = adj1[k];
9921             if (Markers[ngh1] != tv->mark) {
9922                 Neighbs1[j1++] = Cand1->invlab[ngh1];
9923             }
9924             ngh2 = adj2[k];
9925             if (Markers[ngh2] != tv->mark) {
9926                 Neighbs2[j2++] = Cand2->invlab[ngh2];
9927             }
9928         }
9929 
9930         k = tv->permInd;
9931         if (j1 == j2) {
9932             quickSort(Neighbs1, j1);
9933             quickSort(Neighbs2, j2);
9934             for (i=0; i<j1; i++) {
9935                 arg = Cand1->lab[Neighbs1[i]];
9936                 val = Cand2->lab[Neighbs2[i]];
9937                 if ((Markers[arg] != tv->mark) && (Markers[val] != tv->mark)) {
9938                     SETPAIRSAUT(arg, val)
9939                     SETPAIRSAUT(val, arg)
9940                     Markers[arg] = tv->mark;
9941                     Markers[val] = tv->mark;
9942                 }
9943             }
9944         }
9945     }
9946     return TRUE;
9947 }
9948 
9949 /*****************************************************************************
9950  *                                                                            *
9951  *  trie_class(t,c) classifies vertices according to weights of their edges   *
9952  *                                                                            *
9953  *****************************************************************************/
9954 
trie_class(trie * t,int * count)9955 void  trie_class(trie *t, int *count) {
9956 
9957     if (t->first_child == NULL) {
9958         WeightsSeq[t->value] = *count;
9959         if (t->next_sibling == NULL) (*count)++;
9960         return;
9961     }
9962     else {
9963         t = t->first_child;
9964         while (t) {
9965             trie_class(t,count);
9966             t = t->next_sibling;
9967         }
9968     }
9969 }
9970 
trie_classify(int n,TracesVars * tv)9971 int trie_classify(int n, TracesVars *tv) {
9972 
9973     int i, j, ord;
9974     int *ngh1, *wgh1;
9975 
9976     trieroot = trie_new(n, tv);
9977     ord = 0;
9978 
9979     for (i=0; i<n; i++) {
9980         ngh1 = TheGraph[i].e;
9981         wgh1 = TheGraph[i].w;
9982         sort2ints(wgh1, ngh1, TheGraph[i].d);
9983 
9984         trieref = trieroot;
9985         for (j=0; j<TheGraph[i].d; j++) {
9986             trieref = trie_make(trieref, wgh1[j], n, tv);
9987         }
9988         trieref = trie_make(trieref, n, n, tv);
9989         trie_make(trieref, i, n, tv);
9990     }
9991     trie_class(trieroot,&ord);
9992 
9993     for (i=0; i<=tv->triepos; i++) {
9994         free(TrieArray[i]);
9995     }
9996     trieroot = NULL;
9997     return ord-1;
9998 }
9999 
trie_comp(trie * t,int value)10000 struct trie *trie_comp(trie *t, int value) {
10001 
10002     if (t->first_child) {
10003         t = t->first_child;
10004         while (t) {
10005             if  (value != t->value) {
10006                 t = t->next_sibling;
10007             }
10008             else {
10009                 break;
10010             }
10011         }
10012         return t;
10013     }
10014     else {
10015         return NULL;
10016     }
10017 }
10018 
trie_dump(trie * t)10019 void  trie_dump(trie *t) {
10020     if (t->first_child == NULL) return;
10021     else {
10022         printf("( ");
10023         t = t->first_child;
10024         while (t) {
10025             printf("%d ",t->value);
10026             trie_dump(t);
10027             t = t->next_sibling;
10028         }
10029         printf(") ");
10030     }
10031 }
10032 
10033 /*****************************************************************************
10034  *                                                                            *
10035  *  trie_make(t,v,n,tv) places the value v into the trie t                    *
10036  *                                                                            *
10037  *****************************************************************************/
10038 
trie_make(trie * t,int value,int n,struct TracesVars * tv)10039 struct trie *trie_make(trie *t, int value, int n, struct TracesVars* tv) {
10040     trie *t1;
10041 
10042     t1 = t;
10043     if (tv->trienext == n) {
10044         tv->trienext = 0;
10045         tv->triepos++;
10046         TrieArray[tv->triepos] = malloc(n*sizeof(trie));
10047         if (TrieArray[tv->triepos] == NULL) {
10048             fprintf(ERRFILE, "\nError, memory not allocated.\n");
10049             exit(1);
10050         }
10051     }
10052     if (t->first_child) {
10053         t = t->first_child;
10054         if (value < t->value) {
10055             t1->first_child = &TrieArray[tv->triepos][tv->trienext++];
10056             t1->first_child->next_sibling = t;
10057             t1->first_child->first_child = NULL;
10058             t = t1->first_child;
10059             t->value = value;
10060             return t;
10061         }
10062         while (value > t->value) {
10063             t1 = t;
10064             if (t->next_sibling) {
10065                 t = t->next_sibling;
10066             }
10067             else break;
10068         }
10069         if (value == t->value) {
10070             return t;
10071         }
10072         t1->next_sibling = &TrieArray[tv->triepos][tv->trienext++];
10073         t1->next_sibling->first_child = t1->next_sibling->next_sibling = NULL;
10074         if (t != t1) {
10075             t1->next_sibling->next_sibling = t;
10076         }
10077         t = t1->next_sibling;
10078     }
10079     else {
10080         t->first_child = &TrieArray[tv->triepos][tv->trienext++];
10081         t = t->first_child;
10082         t->first_child = t->next_sibling = NULL;
10083     }
10084     t->value = value;
10085     return t;
10086 }
10087 
trie_new(int n,struct TracesVars * tv)10088 struct trie *trie_new(int n, struct TracesVars* tv) {
10089 
10090     TrieArray[0] = malloc(n*sizeof(trie));
10091     if (TrieArray[0] == NULL) {
10092         fprintf(ERRFILE, "\nError, memory not allocated.\n");
10093         exit(1);
10094     }
10095     TrieArray[0][0].first_child = TrieArray[0][0].next_sibling = NULL;
10096     tv->triepos = 0;
10097     tv->trienext = 1;
10098     return TrieArray[0];
10099 }
10100 
VerifyCand(Candidate * Cand,int n,int line)10101 boolean VerifyCand(Candidate *Cand, int n, int line) {
10102     int i, k;
10103 
10104     for (i=0; i<n; i++) {
10105         k=Cand->lab[i];
10106         if (Cand->invlab[k] != i) {
10107             printf("Cand->invlab wrong at %d (vtx: %d), line %d\n", i, k, line);
10108             PrintVect(Cand->lab, 0, n, 0);
10109             PrintVect(Cand->invlab, 0, n, 0);
10110             return FALSE;
10111         }
10112     }
10113     return TRUE;
10114 }
10115 
VerifyId(int * p,int n)10116 boolean VerifyId(int *p, int n) {
10117     int i, r;
10118 
10119     r = TRUE;
10120     for (i=0; i<n; i++) {
10121         if (p[i] != i) {
10122             printf("p[%d] = %d\n", i, p[i]);
10123             r = FALSE;
10124         }
10125     }
10126     return r;
10127 }
10128 
VerifyPart(Partition * Part,int start,int end)10129 boolean VerifyPart(Partition *Part, int start, int end) {
10130     int i,j;
10131 
10132     for (i=start; i<end; i+=Part->cls[i]) {
10133         if (Part->cls[i] == 0 || i>=end) {
10134             printf("WRONG cls\n");
10135             return FALSE;
10136         }
10137         for (j=0; j<Part->cls[i]; j++) {
10138             if (Part->inv[i+j] != i) {
10139                 printf("WRONG inv\n");
10140                 return FALSE;
10141             }
10142         }
10143     }
10144     printf("OK\n");
10145     return TRUE;
10146 }
10147 
VerifyPerm(int * perm,int n,int where)10148 int VerifyPerm(int *perm, int n,int where) {
10149     int i;
10150 
10151     memset(Markers, 0, n*sizeof(int));
10152 
10153     for (i=0; i<n; i++) {
10154         if ((perm[i] >= n) || (Markers[perm[i]])) {
10155             fprintf(stderr,"wrong permutation @ %d\n",where);
10156             PrintVect(perm,0,i+1,labelorg);
10157         }
10158         Markers[perm[i]] = TRUE;
10159     }
10160     return TRUE;
10161 }
10162 
10163 /*****************************************************************************
10164  *                                                                            *
10165  *  WeightCodes(n) transforms the weight w(u,v) of an edge into a new weight  *
10166  *  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). *
10167  *                                                                            *
10168  *****************************************************************************/
10169 
WeightCodes(int n)10170 void WeightCodes(int n) {
10171     int i,j,aux;
10172     int sumdegs;
10173     int deg, vtx1, vtx2, *ngh1, *ngh2, *wgh1, *wgh2, ord;
10174 
10175     sumdegs = 0;
10176     for (i=0; i<n; i++) {
10177         sumdegs += TheGraph[i].d;
10178     }
10179 
10180     DYNALLSTAT(int, VArray, VArray_sz);
10181     DYNALLSTAT(weightwhere, WArray, WArray_sz);
10182     DYNALLSTAT(grph_strct, TheAuxGraph, TheAuxGraph_sz);
10183 
10184     DYNALLOC1(int, VArray, VArray_sz, sumdegs, "WeightCodes");
10185     DYNALLOC1(weightwhere, WArray, WArray_sz, sumdegs, "WeightCodes");
10186     DYNALLOC1(grph_strct, TheAuxGraph, TheAuxGraph_sz, n, "WeightCodes");
10187 
10188     memcpy(TheAuxGraph,TheGraph,n*sizeof(grph_strct));
10189 
10190     ord = 0;
10191     for (vtx1=0; vtx1<n; vtx1++) {
10192         ngh1 = (TheAuxGraph[vtx1].e)++;
10193         wgh1 = TheAuxGraph[vtx1].w;
10194         deg = TheAuxGraph[vtx1].d;
10195         for (i=0; i<deg; i++) {
10196             vtx2 = ngh1[i];
10197             ngh2 = (TheAuxGraph[vtx2].e)++;
10198             wgh2 = (TheAuxGraph[vtx2].w)++;
10199             (TheAuxGraph[vtx1].d)--;
10200             (TheAuxGraph[vtx2].d)--;
10201             VArray[ord] = wgh1[i];
10202             WArray[ord].weight = wgh2[0];
10203             WArray[ord++].ref = (TheAuxGraph[vtx1].w)++;
10204             VArray[ord] = wgh2[0];
10205             WArray[ord].weight = wgh1[i];
10206             WArray[ord++].ref = wgh2;
10207         }
10208     }
10209 
10210     sortweights(VArray,WArray,ord);
10211 
10212     /* swap VArray and WArray.weight */
10213     for (i=0; i<sumdegs; i++) {
10214         aux = VArray[i];
10215         VArray[i] = WArray[i].weight;
10216         WArray[i].weight = aux;
10217     }
10218 
10219     i = j = 0;
10220     do {
10221         if (WArray[i].weight == WArray[j].weight) {
10222             j++;
10223         } else {
10224             sortweights(VArray+i,WArray+i,j-i);
10225             i = j;
10226         }
10227     } while (j<sumdegs);
10228     sortweights(VArray+i,WArray+i,j-i);
10229 
10230     /* weight class */
10231     ord = 0;
10232     *(WArray[0].ref) = 0;
10233     for (i=1; i<sumdegs; i++) {
10234         if ((WArray[i].weight != WArray[i-1].weight) || (VArray[i] != VArray[i-1])) {
10235             ord++;
10236         }
10237         *(WArray[i].ref) = ord;
10238     }
10239 
10240     DYNFREE(VArray, VArray_sz);
10241     DYNFREE(WArray, WArray_sz);
10242     DYNFREE(TheAuxGraph, TheAuxGraph_sz);
10243 
10244 }
10245 
10246 
10247 
TargetCellSmall(Candidate * TargCand,Partition * Part,int n,struct TracesVars * tv,int Lv)10248 boolean TargetCellSmall(Candidate *TargCand, Partition *Part, int n, struct TracesVars* tv, int Lv) {
10249     int TCell = -1, TCSize = n;
10250     int i;
10251 
10252     if (tv->maxdeg <=2) {
10253         return FALSE;
10254     }
10255 
10256     if (Lv < tv->tcellevel) {
10257         tv->tcell = Spine[Lv+1].tgtcell;
10258         return TRUE;
10259     }
10260     else {
10261         if (Part->cls[0] == n) {
10262             tv->tcell = 0;
10263             return TRUE;
10264         }
10265         while (TCell < 0) {
10266             for (i = Spine[Lv].tgtcell; i < Spine[Lv].tgtend; i += Part->cls[i]) {
10267                 if (Part->cls[i] < TCSize) {
10268                     if (NonSingDeg(TargCand->lab[i], TargCand, Part) > 2) {
10269                         TCSize = Part->cls[i];
10270                         TCell = i;
10271                     }
10272                 }
10273             }
10274             Lv--;
10275             if ((Lv < 0) && (TCell < 0)) return FALSE;
10276         }
10277         tv->tcell = TCell;
10278         return TRUE;
10279     }
10280 }
10281 
TargetCellExpPathSmall(Candidate * TargCand,Partition * Part,struct TracesVars * tv)10282 int TargetCellExpPathSmall(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
10283     int Lv, n;
10284 
10285     n = tv->input_graph->nv;
10286     if (Part->cells == n) {
10287         return 0;
10288     }
10289 
10290     Lv = tv->tolevel_tl+1;
10291     SpineTL_tl = Spine+Lv;
10292     if (tv->tolevel_tl < tv->tcellevel) {
10293         tv->tcellexpath = Part->inv[SpineTL_tl->tgtcell];
10294         tv->tolevel_tl++;
10295         if (Part->cls[tv->tcellexpath] == 1) {
10296             if (tv->options->verbosity >= 2) {
10297                 if (tv->tolevel_tl-tv->tolevel == 6) {
10298                     fprintf(outfile, "... ");
10299                 }
10300             }
10301             return TargetCellExpPath(TargCand, Part, tv);
10302         } else {
10303             return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
10304         }
10305     }
10306     else {
10307         if (TargetCellFirstPath(TargCand, Part, tv)) {
10308             return 1+((Spine[tv->tolevel_tl].tgtcell >= Spine[tv->tolevel_tl-1].tgtcell) && (Spine[tv->tolevel_tl].tgtend <= Spine[tv->tolevel_tl-1].tgtend));
10309         }
10310         else {
10311             return 0;
10312         }
10313     }
10314 }
10315 
TargetCellFirstPathSmall(Candidate * TargCand,Partition * Part,struct TracesVars * tv)10316 boolean TargetCellFirstPathSmall(Candidate *TargCand, Partition *Part, struct TracesVars* tv) {
10317     int n, TCell, TCSize, TCell1, TCSize1;
10318     int Lv, i, Lev, vtx, vtx_d;
10319     int loopstart, loopend;
10320     boolean divided;
10321 
10322     n = tv->input_graph->nv;
10323     if (Part->cells == n) {
10324         return 0;
10325     }
10326     Lev = tv->tolevel_tl;
10327     Lv = tv->tolevel_tl;
10328     TCell = TCell1 = -1;
10329     TCSize = TCSize1 = n;
10330 
10331     while (TCell < 0) {
10332         loopstart = Part->inv[Spine[Lv].tgtcell];
10333         divided = FALSE;
10334 
10335         if (Lv == tv->lastlev) {
10336             loopstart = Part->inv[tv->lastcell];
10337             divided = TRUE;
10338         }
10339 
10340         i = loopstart;
10341         loopend = Spine[Lv].tgtend;
10342 
10343         while (i < loopend) {
10344             if ((Part->cls[i] > 1) && (Part->cls[i] < TCSize)) {
10345                 vtx = TargCand->lab[i];
10346                 vtx_d = TheGraph[vtx].d;
10347 
10348                 if (vtx_d > 2) {
10349                     if (NonSingDeg(vtx, TargCand, Part) > 2) {
10350                         TCSize = Part->cls[i];
10351                         TCell = i;
10352                         if (TCSize == WorkArray[Lv]) {
10353                             break;
10354                         }
10355                     }
10356                 }
10357             }
10358             i += Part->cls[i];
10359             if (divided && (i == loopend)) {
10360                 i = loopstart = Spine[Lv].tgtcell;
10361                 loopend = tv->lastcell;
10362                 divided = FALSE;
10363                 TCSize1 = TCSize;
10364                 TCell1 = TCell;
10365                 TCell = -1;
10366                 TCSize = n;
10367             }
10368         }
10369 
10370         if (TCSize1 < TCSize) {
10371             TCell = TCell1;
10372             TCSize = TCSize1;
10373         }
10374 
10375         if (TCell < 0) {
10376             if (Lv == 0) {
10377                 tv->finalnumcells = minint(Part->cells,tv->finalnumcells);    /* 160712 */
10378                 tv->finalnumcells = Part->cells;
10379                 return FALSE;
10380             } else {
10381                 Lv = Spine[Lv].tgtfrom;
10382             }
10383         }
10384     }
10385     tv->tcellexpath = tv->lastcell = TCell;
10386     tv->tolevel_tl++;
10387 
10388     Spine[tv->tolevel_tl].tgtfrom = tv->lastlev = Lv;
10389     Spine[tv->tolevel_tl].tgtcell = tv->tcellexpath;
10390     Spine[tv->tolevel_tl].tgtsize = WorkArray[Lv] = TCSize;
10391     Spine[tv->tolevel_tl].tgtend = Spine[tv->tolevel_tl].tgtcell + TCSize;
10392     Spine[tv->tolevel_tl].tgtpos = Spine[tv->tolevel_tl].tgtend - 1;
10393     tv->tcellevel = tv->tolevel_tl;
10394 
10395     if (Lv != Lev) {
10396         BreakSteps[Lev] = ++tv->brkstpcount;
10397         if (Spine[tv->tolevel].liststart) {
10398             if (!Spine[tv->tolevel].liststart->firstsingcode) {
10399                 Spine[tv->tolevel].liststart->firstsingcode = Spine[tv->tolevel].liststart->pathsingcode;
10400             }
10401         }
10402     }
10403     return TRUE;
10404 }
10405