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