static void fragments(int *x, int nx, int *frag, int *nfrag) /* For each v in union(x[0..nx-1]), find the components of the hypergraph x - v and add them to frag if there are more than one. */ /* This implementation is shocking. Improve it! */ { int allx,i,j,v; int vbit,nw,w[MAXN]; boolean done; allx = 0; for (i = 0; i < nx; ++i) allx |= x[i]; *nfrag = 0; while (allx) { v = XNEXTBIT(allx); vbit = xbit[v]; allx &= ~vbit; for (i = 0; i < nx; ++i) w[i] = x[i] & ~vbit; nw = nx; done = FALSE; while (!done && nw > 1) { done = TRUE; for (i = 0; i < nw-1; ++i) for (j = i+1; j < nw; ) if ((w[i] & w[j]) != 0) { w[i] |= w[j]; w[j] = w[nw-1]; --nw; done = FALSE; } else ++j; } if (nw > 1) for (i = 0; i < nw; ++i) frag[(*nfrag)++] = w[i]; } }
static UPROC userautomproc(int count, int *p, int *orbits, int numorbits, int stabvertex, int n) /* Automorphism procedure called by nauty Form orbits on powerset of VG Operates on data[n-n1] */ { int i,j1,j2; int moved,pxi,pi; int w,lo,hi; int *xorb; xorb = data[n-n1].xorb; lo = data[n-n1].lo; hi = data[n-n1].hi; if (count == 1) /* first automorphism */ for (i = lo; i < hi; ++i) xorb[i] = i; moved = 0; for (i = 0; i < n; ++i) if (p[i] != i) moved |= xbit[i]; for (i = lo; i < hi; ++i) { if ((w = xset[i] & moved) == 0) continue; pxi = xset[i] & ~moved; while (w) { j1 = XNEXTBIT(w); w &= ~xbit[j1]; pxi |= xbit[p[j1]]; } pi = xinv[pxi]; j1 = xorb[i]; while (xorb[j1] != j1) j1 = xorb[j1]; j2 = xorb[pi]; while (xorb[j2] != j2) j2 = xorb[j2]; if (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1; else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2; } }
static void userautomproc(int count, int *p, int *orbits, int numorbits, int stabvertex, int n) /* form orbits on powerset of VG called by nauty; operates on data[n] */ { xword i,j1,j2,moved,pi,pxi; xword lo,hi; xword *xorb,*xinv,*xset,w; xorb = data[n].xorb; xset = data[n].xset; xinv = data[n].xinv; lo = data[n].lo; hi = data[n].hi; if (count == 1) /* first automorphism */ for (i = lo; i < hi; ++i) xorb[i] = i; moved = 0; for (i = 0; i < n; ++i) if (p[i] != i) moved |= xbit[i]; for (i = lo; i < hi; ++i) { if ((w = xset[i] & moved) == 0) continue; pxi = xset[i] & ~moved; while (w) { j1 = XNEXTBIT(w); w ^= xbit[j1]; pxi |= xbit[p[j1]]; } pi = xinv[pxi]; j1 = xorb[i]; while (xorb[j1] != j1) j1 = xorb[j1]; j2 = xorb[pi]; while (xorb[j2] != j2) j2 = xorb[j2]; if (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1; else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2; } }
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 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; }