static boolean accept2(graph *g, int n2, int x, graph *gx, int *deg, boolean nuniq) /* decide if n in theta(g+x) -- version for n+1 == maxn */ { int i,n; int lab[MAXN],ptn[MAXN],orbits[MAXN]; int degx[MAXN],invar[MAXN]; setword vmax,gv; int qn,qv; int count[MAXN]; int xw; int nx,numcells,code; int degn,i0,i1,j,j0,j1; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a2calls; if (nuniq) ++a2uniq; #endif n = n1 + n2; nx = n + 1; for (i = 0; i < n; ++i) { gx[i] = g[i]; degx[i] = deg[i]; } gx[n] = 0; degx[n] = degn = XPOPCOUNT(x); xw = x; while (xw) { i = XNEXTBIT(xw); xw &= ~xbit[i]; gx[i] |= bit[n]; gx[n] |= bit[i]; ++degx[i]; } #ifdef PRUNE1 if (PRUNE1(gx,degx,n1,n2+1,maxn2)) return FALSE; #endif if (nuniq) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } for (i = 0; i < n1; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n1-1] = 0; i0 = n1; i1 = n; for (i = n1; i < nx; ++i) { if (degx[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == n1) { numcells = 2; active[0] = bit[0] | bit[n1]; if (!distinvar(gx,invar,n1,n2+1)) return FALSE; qn = invar[n]; j0 = n1; j1 = n; while (j0 <= j1) { j = lab[j0]; qv = invar[j]; if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > n1) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } else { numcells = 3; ptn[i1] = 0; active[0] = bit[0] | bit[n1] | bit[i1+1]; vmax = 0; j = MAXN; for (i = 0; i < n1; ++i) if (degx[i] < j && degx[i] > 0) { j = degx[i]; vmax = bit[i]; } else if (degx[i] == j) vmax |= bit[i]; gv = gx[n] & vmax; qn = POPCOUNT(gv); j0 = i1+1; j1 = n; while (j0 <= j1) { j = lab[j0]; gv = gx[j] & vmax; qv = POPCOUNT(gv); if (qv > qn) return FALSE; else if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > i1+1) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } refinex(gx,lab,ptn,0,&numcells,count,active,TRUE,&code,1,nx); if (code < 0) return FALSE; else if (code > 0 || numcells >= nx-4) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } options.writemarkers = FALSE; options.writeautoms = FALSE; options.getcanon = TRUE; options.defaultptn = FALSE; active[0] = 0; #ifdef INSTRUMENT ++a2nauty; #endif nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan); if (orbits[lab[n]] == orbits[n]) { #ifdef INSTRUMENT ++a2succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE; #endif if (canonise) makecanon(gx,gcan,n1,n2+1); return TRUE; } else return FALSE; }
static void makeleveldata(void) /* make the level data for each level */ { int i,j,h; int nn,nxsets,tttn; long ncj; leveldata *d; int xw,cw; nn = maxdeg2 <= n1 ? maxdeg2 : n1; ncj = nxsets = 1; for (j = 1; j <= nn; ++j) { ncj = (ncj * (n1 - j + 1)) / j; nxsets += ncj; } tttn = 1 << n1; xset = (int*) ALLOCS(nxsets,sizeof(int)); xcard = (int*) ALLOCS(nxsets,sizeof(int)); xinv = (int*) ALLOCS(tttn,sizeof(int)); if (xset==NULL || xcard==NULL || xinv==NULL) { fprintf(stderr,">E genbg: malloc failed in makeleveldata()\n"); exit(2); } j = 0; for (i = 0; i < tttn; ++i) if ((h = XPOPCOUNT(i)) <= maxdeg2) { xset[j] = i; xcard[j] = h; ++j; } if (j != nxsets) { fprintf(stderr,">E genbg: j=%d mxsets=%d\n",j,nxsets); exit(2); } /* The following is not SORT_OF_SORT 1, 2 or 3 */ h = 1; do h = 3 * h + 1; while (h < nxsets); do { for (i = h; i < nxsets; ++i) { xw = xset[i]; cw = xcard[i]; for (j = i; xcard[j-h] > cw || (xcard[j-h] == cw && xset[j-h] > xw); ) { xset[j] = xset[j-h]; xcard[j] = xcard[j-h]; if ((j -= h) < h) break; } xset[j] = xw; xcard[j] = cw; } h /= 3; } while (h > 0); for (i = 0; i < nxsets; ++i) xinv[xset[i]] = i; xstart[0] = 0; for (i = 1; i < nxsets; ++i) if (xcard[i] > xcard[i-1]) xstart[xcard[i]] = i; xstart[xcard[nxsets-1]+1] = nxsets; for (i = 0; i < maxn2; ++i) { d = &data[i]; d->xorb = (int*) ALLOCS(nxsets,sizeof(int)); if (d->xorb==NULL) { fprintf(stderr,">E genbg: malloc failed in makeleveldata()\n"); exit(2); } d->ne = d->dmax = d->xlb = d->xub = -1; } }
static boolean accept1(graph *g, int n2, int x, graph *gx, int *deg, boolean *rigid) /* decide if n2 in theta(g+x) -- version for n2+1 < maxn2 */ { int i,n; int lab[MAXN],ptn[MAXN],orbits[MAXN]; int count[MAXN]; graph h[MAXN]; int xw; int nx,numcells,code; int i0,i1,degn; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a1calls; #endif n = n1 + n2; nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; gx[n] = 0; deg[n] = degn = XPOPCOUNT(x); xw = x; while (xw) { i = XNEXTBIT(xw); xw &= ~xbit[i]; gx[i] |= bit[n]; gx[n] |= bit[i]; ++deg[i]; } #ifdef PRUNE1 if (PRUNE1(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif for (i = 0; i < n1; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n1-1] = 0; i0 = n1; i1 = n; for (i = n1; i < nx; ++i) { if (deg[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == n1) { numcells = 2; active[0] = bit[0] | bit[n1]; } else { numcells = 3; active[0] = bit[0] | bit[n1] | bit[i1+1]; ptn[i1] = 0; } refinex(gx,lab,ptn,0,&numcells,count,active,FALSE,&code,1,nx); if (code < 0) return FALSE; if (numcells == nx) { *rigid = TRUE; #ifdef INSTRUMENT ++a1succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif return TRUE; } options.writemarkers = FALSE; options.writeautoms = FALSE; options.getcanon = TRUE; options.defaultptn = FALSE; options.userautomproc = userautomproc; active[0] = 0; #ifdef INSTRUMENT ++a1nauty; #endif nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,h); if (orbits[lab[n]] == orbits[n]) { *rigid = stats.numorbits == nx; #ifdef INSTRUMENT ++a1succs; #endif #ifdef PRUNE2 if (PRUNE2(gx,deg,n1,n2+1,maxn2)) return FALSE; #endif return TRUE; } else return FALSE; }
static void genextend(graph *g, int n2, int *deg, int ne, boolean rigid, int xlb, int xub) /* extend from n2 to n2+1 */ { int x,y,d; int *xorb,xc; int nx,i,j,imin,imax,dmax; int xlbx,xubx,n; graph gx[MAXN]; int degx[MAXN]; boolean rigidx; int dneed,need,nfeet,hideg,deg1,ft[MAXN],nfrag,frag[MAXN]; #ifdef INSTRUMENT boolean haschild; haschild = FALSE; ++nodes[n2]; if (rigid) ++rigidnodes[n2]; #endif n = n1 + n2; nx = n2 + 1; dmax = deg[n-1]; d = 0; dneed = mindeg1 - maxn2 + n2; need = 0; hideg = 0; deg1 = 0; for (i = 0; i < n1; ++i) { if (deg[i] == maxdeg1) d |= xbit[i]; if (deg[i] <= dneed) need |= xbit[i]; if (deg[i] >= 2) hideg |= xbit[i]; if (deg[i] == 1) deg1 |= xbit[i]; } if (xlb < XPOPCOUNT(need)) xlb = XPOPCOUNT(need); if (xlb > xub) return; imin = xstart[xlb]; imax = xstart[xub+1]; xorb = data[n2].xorb; if (nx == maxn2) { if (footfree) { nfeet = 0; for (j = 0; j < n2; ++j) { x = xval[j] & hideg; IFLE1BITS(x) ft[nfeet++] = xval[j] & deg1; } } if (cutfree) fragments(xval,n2,frag,&nfrag); for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if ((x & d) != 0) continue; if ((need & ~x) != 0) continue; if (simple) { for (j = n2; --j >= 0;) if (x == xval[j]) break; if (j >= 0) continue; } if (maxcommon >= 0) { for (j = n2; --j >= 0;) { y = x & xval[j]; if (XPOPCOUNT(y) > maxcommon) break; } if (j >= 0) continue; } if (antichain) { for (j = 0; j < n2; ++j) if ((xval[j] & ~x) == 0) break; if (j < n2) continue; } if (footfree) { y = x & (hideg | deg1); IFLE1BITS(y) continue; for (j = 0; j < nfeet; ++j) if ((x & ft[j]) == 0) break; if (j < nfeet) continue; } if (cutfree) { y = x & (hideg | deg1); IFLE1BITS(y) continue; for (j = 0; j < nfrag; ++j) if ((x & frag[j]) == 0) break; if (j < nfrag) continue; } xval[n2] = x; if (nx == nprune) { if (curres == 0) curres = mod; #ifdef SPLITTEST --curres; ++splitcases; continue; #else if (--curres != 0) continue; #endif } if (accept2(g,n2,x,gx,deg,xc > dmax)) if (!connec || isconnected(gx,n+1)) { ADDBIG(ecount[ne+xc],1); #ifdef INSTRUMENT haschild = TRUE; #endif (*outproc)(outfile,canonise ? gcan : gx,n1,n2+1); } } } else { for (i = imin; i < imax; ++i)
static boolean accept2(graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq) /* decide if n in theta(g+x) -- version for n+1 == maxn */ { int i; int lab[MAXN],ptn[MAXN],orbits[MAXN]; int degx[MAXN],invar[MAXN]; setword vmax,gv,gxn; int qn,qv; int count[MAXN]; int nx,numcells,code; int degn,i0,i1,j,j0,j1; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; boolean cheapacc; #ifdef INSTRUMENT ++a2calls; if (nuniq) ++a2uniq; #endif nx = n + 1; gxn = 0; for (i = 0; i < n; ++i) { if ((xbit[i] & x)) { gxn |= bit[i]; gx[i] = g[i]; degx[i] = deg[i]; } else { gx[i] = g[i] | bit[n]; degx[i] = deg[i] + 1; } } gx[n] = gxn; degx[n] = degn = XPOPCOUNT(x); #ifdef PREPRUNE if (PREPRUNE(gx,n+1,maxn)) return FALSE; #endif if (nuniq) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } i0 = 0; i1 = n; for (i = 0; i < nx; ++i) { if (degx[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == 0) { numcells = 1; active[0] = bit[0]; if (!hitinvar(gx,invar,nx)) return FALSE; qn = invar[n]; j0 = 0; j1 = n; while (j0 <= j1) { j = lab[j0]; qv = invar[j]; if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > 0) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } else { numcells = 2; ptn[i1] = 0; active[0] = bit[0] | bit[i1+1]; vmax = 0; for (i = i1+1; i < nx; ++i) vmax |= bit[lab[i]]; gv = gx[n] & vmax; qn = POPCOUNT(gv); j0 = i1+1; j1 = n; while (j0 <= j1) { j = lab[j0]; gv = gx[j] & vmax; qv = POPCOUNT(gv); if (qv > qn) return FALSE; else if (qv < qn) ++j0; else { lab[j0] = lab[j1]; lab[j1] = j; --j1; } } if (j0 > i1+1) { if (j0 == n) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } ptn[j1] = 0; ++numcells; active[0] |= bit[j0]; } } refinex(gx,lab,ptn,0,&numcells,count,active,TRUE,&code,1,nx); if (code < 0) return FALSE; cheapacc = FALSE; if (code > 0) cheapacc = TRUE; if (cheapacc) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } options.getcanon = TRUE; options.digraph = TRUE; options.defaultptn = FALSE; active[0] = 0; #ifdef INSTRUMENT ++a2nauty; #endif nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan); if (orbits[lab[n]] == orbits[n]) { #ifdef INSTRUMENT ++a2succs; #endif if (canonise) makecanon(gx,gcan,nx); return TRUE; } else return FALSE; }
static boolean accept1(graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid) /* decide if n in theta(g+x) - version for n+1 < maxn */ { int i; int lab[MAXN],ptn[MAXN],orbits[MAXN]; int count[MAXN]; graph h[MAXN]; int nx,numcells,code; int i0,i1,degn; set active[MAXM]; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; #ifdef INSTRUMENT ++a1calls; #endif nx = n + 1; for (i = 0; i < n; ++i) gx[i] = g[i]; gx[n] = 0; deg[n] = degn = XPOPCOUNT(x); for (i = 0; i < n; ++i) { if ((xbit[i] & x)) gx[n] |= bit[i]; else { gx[i] |= bit[n]; ++deg[i]; } } #ifdef PREPRUNE if (PREPRUNE(gx,n+1,maxn)) return FALSE; #endif i0 = 0; i1 = n; for (i = 0; i < nx; ++i) { if (deg[i] == degn) lab[i1--] = i; else lab[i0++] = i; ptn[i] = 1; } ptn[n] = 0; if (i0 == 0) { numcells = 1; active[0] = bit[0]; } else { numcells = 2; active[0] = bit[0] | bit[i1+1]; ptn[i1] = 0; } refinex(gx,lab,ptn,0,&numcells,count,active,FALSE,&code,1,nx); if (code < 0) return FALSE; if (numcells == nx) { *rigid = TRUE; #ifdef INSTRUMENT ++a1succs; #endif return TRUE; } options.getcanon = TRUE; options.digraph = TRUE; options.defaultptn = FALSE; options.userautomproc = userautomproc; /* if (!regular || nx != maxn-1) options.userautomproc = userautomproc; else options.userautomproc = NULL; */ active[0] = 0; #ifdef INSTRUMENT ++a1nauty; #endif nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,h); if (orbits[lab[n]] == orbits[n]) { *rigid = stats.numorbits == nx; #ifdef INSTRUMENT ++a1succs; #endif return TRUE; } else return FALSE; }
static void makeleveldata(void) /* make the level data for each level */ { long h; int n,dmax,dmin; long ncj; leveldata *d; xword *xcard,*xinv; xword *xset,xw,tttn,nxsets; xword cw; xword i,j; for (n = 1; n < maxn; ++n) { dmax = n/2; if (maxdeg < dmax) dmax = maxdeg; dmin = mindeg - maxn + n + 1; if (dmin < 0) dmin = 0; ncj = 1; nxsets = (dmin == 0 ? 1 : 0); for (j = 1; j <= dmax; ++j) { ncj = (ncj * (n-j+1)) / j; if (j >= dmin) nxsets += ncj; } tttn = 1L << n; d = &data[n]; d->xset = xset = (xword*) calloc(nxsets,sizeof(xword)); d->xcard = xcard = (xword*) calloc(nxsets,sizeof(xword)); d->xinv = xinv = (xword*) calloc(tttn,sizeof(xword)); d->xorb = (xword*) calloc(nxsets,sizeof(xword)); if (xset==NULL || xcard==NULL || xinv==NULL || d->xorb==NULL) { fprintf(stderr, ">E gentourng: calloc failed in makeleveldata()\n"); exit(2); } j = 0; for (i = 0;; ++i) { if ((h = XPOPCOUNT(i)) <= dmax && h >= dmin) { xset[j] = i; xcard[j] = h; ++j; } if (i == (xword)((1L<<n)-1)) break; } if (j != nxsets) { fprintf(stderr,">E gentourng: j=%u mxsets=%u\n", j,(unsigned)nxsets); exit(2); } h = 1; do h = 3 * h + 1; while (h < nxsets); do { for (i = h; i < nxsets; ++i) { xw = xset[i]; cw = xcard[i]; for (j = i; xcard[j-h] > cw || (xcard[j-h] == cw && xset[j-h] > xw); ) { xset[j] = xset[j-h]; xcard[j] = xcard[j-h]; if ((j -= h) < h) break; } xset[j] = xw; xcard[j] = cw; } h /= 3; } while (h > 0); for (i = 0; i < nxsets; ++i) xinv[xset[i]] = i; d->xstart[0] = 0; for (i = 1; i < nxsets; ++i) if (xcard[i] > xcard[i-1]) d->xstart[xcard[i]] = i; d->xstart[xcard[nxsets-1]+1] = nxsets; } }
static void genextend(graph *g, int n, int *deg, boolean rigid) /* extend from n to n+1 -- version for general graphs */ { xword x,dlow,dhigh,dcrit; xword *xset,*xcard,*xorb; xword i,imin,imax; int nx,xc,j,dmax; int xlb,xub,xlbx,xubx; graph gx[MAXN]; int degx[MAXN]; boolean rigidx; boolean subconnec; #ifdef INSTRUMENT boolean haschild; haschild = FALSE; if (rigid) ++rigidnodes[n]; #endif nx = n + 1; ADDBIG(nodes[n],1); if (regular && nx == maxn) { x = 0; for (i = 0; i < n; ++i) if (deg[i] == maxdeg) x |= xbit[i]; if (accept2(g,n,x,gx,deg,FALSE)) { #ifdef PRUNE if (!PRUNE(gx,nx,maxn)) #endif { #ifdef INSTRUMENT haschild = TRUE; #endif ADDBIG(nout,1); (*outproc)(outfile,canonise ? gcan : gx,nx); } } #ifdef INSTRUMENT if (haschild) ++fertilenodes[n]; #endif return; } dmax = deg[n-1]; xlb = mindeg + n + 1 - maxn; if (0 > xlb) xlb = 0; xub = dmax+1; if (n/2 < xub) xub = n/2; if (maxdeg < xub) xub = maxdeg; if (xlb > xub) return; dlow = dcrit = dhigh = 0; for (i = 0; i < n; ++i) { if (deg[i] == dmax) dlow |= xbit[i]; if (deg[i] == maxdeg) dhigh |= xbit[i]; if (deg[i] == mindeg + n - maxn) dcrit |= xbit[i]; } if (XPOPCOUNT(dhigh) > xlb) xlb = XPOPCOUNT(dhigh); if (n-XPOPCOUNT(dcrit) < xub) xub = n - XPOPCOUNT(dcrit); if (xub == dmax+1 && XPOPCOUNT(dlow)+dmax >= n) --xub; if (xlb > xub) return; #ifdef PRUNE if (PRUNE(g,n,maxn)) return; #endif imin = data[n].xstart[xlb]; imax = data[n].xstart[xub+1]; xset = data[n].xset; xcard = data[n].xcard; xorb = data[n].xorb; if (nx == maxn) { subconnec = connec && isstrong(g,n); for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if (xc == dmax+1 && (x & dlow) != 0) continue; if ((dhigh & ~x) != 0) continue; if ((dcrit & x) != 0) continue; if (accept2(g,n,x,gx,deg, xc < dmax || (xc == dmax && (x & dlow) == 0))) if (!connec || (subconnec && x != 0) || isstrong(gx,nx)) { #ifdef PRUNE if (!PRUNE(gx,nx,maxn)) #endif { #ifdef INSTRUMENT haschild = TRUE; #endif ADDBIG(nout,1); (*outproc)(outfile,canonise ? gcan : gx,nx); } } } } else { for (i = imin; i < imax; ++i) { if (!rigid && xorb[i] != i) continue; x = xset[i]; xc = xcard[i]; if (xc == dmax+1 && (x & dlow) != 0) continue; if ((dhigh & ~x) != 0) continue; if ((dcrit & x) != 0) continue; if (nx == splitlevel) { if (odometer-- != 0) continue; odometer = mod - 1; } for (j = 0; j < n; ++j) degx[j] = deg[j]; xlbx = mindeg+nx+1-maxn; if (xlbx < 0) xlbx = 0; xubx = xc + 1; if (maxdeg < xubx) xubx = maxdeg; if (nx/2 < xubx) xubx = nx/2; if (xlbx > xubx) continue; data[nx].lo = data[nx].xstart[xlbx]; data[nx].hi = data[nx].xstart[xubx+1]; if (accept1(g,n,x,gx,degx,&rigidx)) { #ifdef INSTRUMENT haschild = TRUE; #endif genextend(gx,nx,degx,rigidx); } } } if (n == splitlevel-1 && n >= min_splitlevel && ISASBIG(nodes[n],multiplicity)) --splitlevel; #ifdef INSTRUMENT if (haschild) ++fertilenodes[n]; #endif }