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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. */ 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 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 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 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 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 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 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 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 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 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 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 8700 int maxint(int u, int v) { 8701 if (u > v) { 8702 return u; 8703 } 8704 else { 8705 return v; 8706 } 8707 } 8708 8709 int minint(int u, int v) { 8710 if (u < v) { 8711 return u; 8712 } 8713 else { 8714 return v; 8715 } 8716 } 8717 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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