static int regularity_degree(graph *g, int n) { if (n == 0) { return 0; } int deg0 = POPCOUNT(*GRAPHROW(g, 0, MAXM)); for (int i = 1; i < n; i++) { set *gv = GRAPHROW(g, i, MAXM); int deg = POPCOUNT(*gv); if (deg != deg0) { return -1; /* not regular */ } } return deg0; }
static boolean distinvar(graph *g, int *invar, int n1, int n2) /* make distance invariant/ exit immediately FALSE if n-1 not maximal else exit TRUE Note: only invar[n1..n1+n2-1] set */ { int w,n; setword workset,frontier; setword sofar; int inv,d,v; n = n1 + n2; for (v = n-1; v >= n1; --v) { inv = 0; sofar = frontier = bit[v]; for (d = 1; frontier != 0; ++d) { workset = 0; inv += POPCOUNT(frontier) ^ (0x57 + d); while (frontier) { w = FIRSTBITNZ(frontier); frontier &= ~bit[w]; workset |= g[w]; } frontier = workset & ~sofar; sofar |= frontier; } invar[v] = inv; if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; }
static boolean hitinvar(graph *g, int *invar, int n) /* make hitting invariant * return FALSE if n-1 not maximal else return TRUE */ { setword x,y,z; int inv,i,v,d; for (v = n-1; v >= 0; --v) { inv = 0; x = y = g[v]; while (y) { TAKEBIT(i,y); z = x & g[i]; d = POPCOUNT(z); if (d > inv) inv = d; } invar[v] = inv; if (v < n-1 && inv > invar[n-1]) return FALSE; } return TRUE; }
void degstats(graph *g, int m, int n, unsigned long *edges, int *mindeg, int *mincount, int *maxdeg, int *maxcount, boolean *eulerian) /* Compute degree-related graph properties. *edges = number of edges *mindeg, *mincount = minimum degree and how many there are *maxdeg, *maxcount = maximum degree and how many there are *eulerian = whether the graph has only even degrees */ { setword *pg; int i,j,d,dor; int mind,mindc,maxd,maxdc; unsigned long ned; mind = n; mindc = 0; maxd = 0; maxdc = 0; ned = 0; dor = 0; pg = (setword*)g; for (i = 0; i < n; ++i) { d = 0; for (j = 0; j < m; ++j, ++pg) if (*pg) d += POPCOUNT(*pg); if (d == mind) ++mindc; else if (d < mind) { mind = d; mindc = 1; } if (d == maxd) ++maxdc; else if (d > maxd) { maxd = d; maxdc = 1; } dor |= d; ned += d; } *mindeg = mind; *mincount = mindc; *maxdeg = maxd; *maxcount = maxdc; *edges = ned / 2; *eulerian = (dor & 1) == 0; }
boolean issubconnected(graph *g, set *sub, int m, int n) /* Test if the subset of g induced by sub is connected. Empty is connected. */ { int i,head,tail,w,subsize; set *gw; #if MAXN int queue[MAXN],visited[MAXN]; setword subw[MAXM]; #else DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,visited,visited_sz); DYNALLSTAT(set,subw,subw_sz); DYNALLOC1(int,queue,queue_sz,n,"issubconnected"); DYNALLOC1(int,visited,visited_sz,n,"issubconnected"); DYNALLOC1(set,subw,subw_sz,m,"issubconnected"); #endif subsize = 0; for (i = 0; i < m; ++i) subsize += (sub[i] ? POPCOUNT(sub[i]) : 0); if (subsize <= 1) return TRUE; for (i = 0; i < n; ++i) visited[i] = 0; i = nextelement(sub,m,-1); queue[0] = i; visited[i] = 1; head = 0; tail = 1; while (head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); for (i = 0; i < m; ++i) subw[i] = gw[i] & sub[i]; for (i = -1; (i = nextelement(subw,m,i)) >= 0;) { if (!visited[i]) { visited[i] = 1; queue[tail++] = i; } } } return tail == subsize; }
void commonnbrs(graph *g, int *minadj, int *maxadj, int *minnon, int *maxnon, int m, int n) /* Count the common neighbours of pairs of vertices, and give the minimum and maximum for adjacent and non-adjacent vertices. Undirected only. Null minimums are n+1 and null maximums are -1. */ { int j,k; int mina,maxa,minn,maxn; int cn; set *gi,*gj; setword w; mina = minn = n+1; maxa = maxn = -1; for (j = 0, gj = g; j < n; ++j, gj += m) for (gi = g; gi != gj; gi += m) { cn = 0; for (k = 0; k < m; ++k) { w = gi[k] & gj[k]; if (w) cn += POPCOUNT(w); } if (ISELEMENT(gi,j)) { if (cn < mina) mina = cn; if (cn > maxa) maxa = cn; } else { if (cn < minn) minn = cn; if (cn > maxn) maxn = cn; } } *minadj = mina; *maxadj = maxa; *minnon = minn; *maxnon = maxn; }
boolean isconnected1(graph *g, int n) /* test if g is connected (m=1) */ { setword seen,expanded,toexpand; int i; seen = bit[0]; expanded = 0; while ((toexpand = (seen & ~expanded)) != 0) { i = FIRSTBITNZ(toexpand); expanded |= bit[i]; seen |= g[i]; } return POPCOUNT(seen) == n; }
long pathcount1(graph *g, int start, setword body, setword last) /* Number of paths in g starting at start, lying within body and ending in last. {start} and last should be disjoint subsets of body. */ { long count; setword gs,w; int i; gs = g[start]; w = gs & last; count = POPCOUNT(w); body &= ~bit[start]; w = gs & body; while (w) { TAKEBIT(i,w); count += pathcount1(g,i,body,last&~bit[i]); } return count; }
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 refinex(graph *g, int *lab, int *ptn, int level, int *numcells, int *count, set *active, boolean goodret, int *code, int m, int n) { int i,c1,c2,labc1; setword x; int split1,split2,cell1,cell2; int cnt,bmin,bmax; set *gptr; setword workset; int workperm[MAXN]; int bucket[MAXN+2]; if (n == 1) { *code = 1; return; } *code = 0; split1 = -1; while (*numcells < n && ((split1 = nextelement(active,1,split1)) >= 0 || (split1 = nextelement(active,1,-1)) >= 0)) { DELELEMENT1(active,split1); for (split2 = split1; ptn[split2] > 0; ++split2) {} if (split1 == split2) /* trivial splitting cell */ { gptr = GRAPHROW(g,lab[split1],1); for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; c1 = cell1; c2 = cell2; while (c1 <= c2) { labc1 = lab[c1]; if (ISELEMENT1(gptr,labc1)) ++c1; else { lab[c1] = lab[c2]; lab[c2] = labc1; --c2; } } if (c2 >= cell1 && c1 <= cell2) { ptn[c2] = 0; ++*numcells; ADDELEMENT1(active,c1); } } } else /* nontrivial splitting cell */ { workset = 0; for (i = split1; i <= split2; ++i) workset |= bit[lab[i]]; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { for (cell2 = cell1; ptn[cell2] > 0; ++cell2) {} if (cell1 == cell2) continue; i = cell1; if ((x = workset & g[lab[i]])) /* not == */ cnt = POPCOUNT(x); else cnt = 0; count[i] = bmin = bmax = cnt; bucket[cnt] = 1; while (++i <= cell2) { if ((x = workset & g[lab[i]])) /* not == */ cnt = POPCOUNT(x); else cnt = 0; while (bmin > cnt) bucket[--bmin] = 0; while (bmax < cnt) bucket[++bmax] = 0; ++bucket[cnt]; count[i] = cnt; } if (bmin == bmax) continue; c1 = cell1; for (i = bmin; i <= bmax; ++i) if (bucket[i]) { c2 = c1 + bucket[i]; bucket[i] = c1; if (c1 != cell1) { ADDELEMENT1(active,c1); ++*numcells; } if (c2 <= cell2) ptn[c2-1] = 0; c1 = c2; } for (i = cell1; i <= cell2; ++i) workperm[bucket[count[i]]++] = lab[i]; for (i = cell1; i <= cell2; ++i) lab[i] = workperm[i]; } } if (ptn[n-2] == 0) { if (lab[n-1] == n-1) { *code = 1; if (goodret) return; } else { *code = -1; return; } } else { i = n - 1; while (1) { if (lab[i] == n-1) break; --i; if (ptn[i] == 0) { *code = -1; return; } } } } }
int static main(int argc, char *argv[]) { int i,j,bad; setword w,ww; printf("NAUTYVERSION=%s NAUTYVERSIONID=%d\n", NAUTYVERSION,NAUTYVERSIONID); printf("MAXN=%d MAXM=%d WORDSIZE=%d NAUTY_INFINITY=%d\n", MAXN,MAXM,WORDSIZE,NAUTY_INFINITY); printf("sizes: short=%d int=%d long=%d double=%d\n", (int)sizeof(short),(int)sizeof(int),(int)sizeof(long), (int)sizeof(double)); printf("sizes: boolean=%d setword=%d\n", (int)sizeof(boolean),(int)sizeof(setword)); printf("CLZ=%d,%d,%d\n",HAVE_CLZ,HAVE_CLZL,HAVE_CLZLL); #if SIZEOF_LONGLONG > 0 printf("sizeof(long long)=%d\n",sizeof(long long)); #endif printf("defined:"); #ifdef __STDC__ printf(" __STDC__"); #endif #ifdef BIGNAUTY printf(" BIGNAUTY(obsolete!)"); #endif #ifdef SYS_UNIX printf(" SYS_UNIX"); #endif #ifdef SYS_CRAY printf(" SYS_CRAY"); #endif #ifdef SETWORD_SHORT printf(" SETWORD_SHORT"); #endif #ifdef SETWORD_INT printf(" SETWORD_INT"); #endif #ifdef SETWORD_LONG printf(" SETWORD_LONG"); #endif #ifdef SETWORD_LONGLONG printf(" SETWORD_LONGLONG"); #endif printf("\n"); bad = 0; if (8*sizeof(setword) != WORDSIZE) { printf("\n ***** NOTE: WORDSIZE mismatch *****\n\n"); ++bad; } for (i = 0; i < WORDSIZE; ++i) { w = ALLMASK(i); if (POPCOUNT(w) != i) { printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i); ++bad; } } for (i = 0; i < WORDSIZE; ++i) { w = BITMASK(i); if (POPCOUNT(w) != WORDSIZE-i-1) { printf("\n ***** POPCOUNT(BITMASK) error %d *****\n\n",i); ++bad; } } for (i = 0; i < WORDSIZE; ++i) if (POPCOUNT(ALLMASK(i)) != i) { printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i); ++bad; } for (i = 0; i < WORDSIZE; ++i) if (FIRSTBIT(BITT[i]) != i) { printf("\n ***** FIRSTBIT(BITT) error %d *****\n\n",i); ++bad; } if (FIRSTBIT((setword)0) != WORDSIZE) { printf("\n ***** FIRSTBIT(0) error *****\n\n"); ++bad; } for (i = 0; i < WORDSIZE; ++i) if (POPCOUNT(BITT[i]) != 1) { printf("\n ***** POPCOUNT(BITT) error %d *****\n\n",i); ++bad; } for (i = 0; i < WORDSIZE; ++i) { w = 0; for (j = 1; j <= WORDSIZE; ++j) { w |= BITT[(j*97+i)%WORDSIZE]; if (POPCOUNT(w) != j) { printf("\n ***** POPCOUNT(w) error %d %d *****\n\n",i,j); ++bad; } } } if (!bad) printf("\nNo errors found\n"); else printf("\nXXXXXXX %d errors found XXXXXXX\n",bad); exit(0); }
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; }
int conncontent(graph *g, int m, int n) /* number of connected spanning subgraphs with an even number of edges minus the number with an odd number of edges */ { graph h[WORDSIZE]; setword gj; int i,j,v1,v2,x,y; int minv,mindeg,deg,goodv; long ne; if (m > 1) ABORT("conncontent only implemented for m=1"); /* First handle tiny graphs */ if (n <= 3) { if (n == 1) return 1; if (n == 2) return (g[0] ? -1 : 0); if (!g[0] || !g[1] || !g[2]) return 0; /* disconnected */ if (g[0]^g[1]^g[2]) return 1; /* path */ return 2; /* triangle */ } /* Now compute ne = number of edges mindeg = minimum degree minv = a vertex of minimum degree goodv = a vertex with a clique neighbourhood (-1 if none) */ mindeg = n; ne = 0; goodv = -1; for (j = 0; j < n; ++j) { gj = g[j]; deg = POPCOUNT(gj); ne += deg; if (deg < mindeg) { mindeg = deg; minv = j; if (deg == 1) goodv = j; } if (deg >= 3 && deg <= 4 && goodv < 0) { while (gj) { TAKEBIT(i,gj); if (gj & ~g[i]) break; } if (!gj) goodv = j; } } ne /= 2; /* Cases of isolated vertex or tree */ if (mindeg == 0) return 0; #if 0 if (mindeg == 1 && ne == n-1) { if (isconnected1(g,n)) return ((n&1) ? 1 : -1); else return 0; } #endif /* Cases of clique and near-clique */ if (mindeg == n-1) { j = -1; for (i = 2; i < n; ++i) j *= -i; return j; } if (mindeg == n-2 && n < 16) { if (!knm_computed) { knm_computed = TRUE; knm[1][0] = 1; for (i = 2; i < 16; ++i) { knm[i][0] = -knm[i-1][0] * (i-1); for (j = 1; j+j <= i; ++j) knm[i][j] = knm[i][j-1] + knm[i-1][j-1]; } } return knm[n][(n*n-n)/2-ne]; } /* Case of vertex with clique neighbourhood */ if (goodv >= 0) { delete1(g,h,goodv,n); return -POPCOUNT(g[goodv]) * conncontent(h,m,n-1); } /* Case of minimum degree 2 */ if (mindeg == 2) { x = FIRSTBIT(g[minv]); y = FIRSTBIT(g[minv]^bit[x]); if (x > minv) --x; if (y > minv) --y; delete1(g,h,minv,n); v1 = conncontent(h,m,n-1); if (h[x] & bit[y]) return -2*v1; /* adjacent neighbours */ h[x] |= bit[y]; h[y] |= bit[x]; v2 = conncontent(h,m,n-1); return -v1 - v2; } /* Case of more than 2/3 dense but not complete */ if (3*ne > n*n-n) { j = FIRSTBIT(g[minv] ^ bit[minv] ^ ALLMASK(n)); /* non-neighbour */ g[minv] ^= bit[j]; g[j] ^= bit[minv]; v1 = conncontent(g,m,n); g[minv] ^= bit[j]; g[j] ^= bit[minv]; contract1(g,h,minv,j,n); v2 = conncontent(h,m,n-1); return v1 + v2; } /* All remaining cases */ j = FIRSTBIT(g[minv]); /* neighbour */ g[minv] ^= bit[j]; g[j] ^= bit[minv]; v1 = conncontent(g,m,n); g[minv] ^= bit[j]; g[j] ^= bit[minv]; contract1(g,h,minv,j,n); v2 = conncontent(h,m,n-1); return v1 - v2; }
static void multi(graph *g, int nfixed, long minedges, long maxedges, long maxmult, int maxdeg, boolean lswitch, int m, int n) { static DEFAULTOPTIONS_GRAPH(options); statsblk stats; setword workspace[100]; grouprec *group; int ne; int i,j,k,j0,j1,thisdeg,maxd,x0,x1; set *gi; int lab[MAXNV],ptn[MAXNV],orbits[MAXNV],deg[MAXNV]; int delta[MAXNV],def[MAXNV]; set active[(MAXNV+WORDSIZE-1)/WORDSIZE]; boolean isreg; #ifdef PATHCOUNTS ++count0; #endif j0 = -1; /* last vertex with degree 0 */ j1 = n; /* first vertex with degree > 0 */ ne = 0; maxd = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { thisdeg = 0; for (j = 0; j < m; ++j) thisdeg += POPCOUNT(gi[j]); deg[i] = thisdeg; if (thisdeg > maxd) maxd = thisdeg; if (thisdeg == 0) lab[++j0] = i; else lab[--j1] = i; ne += thisdeg; } ne /= 2; if (maxdeg >= 0 && maxd > maxdeg) return; #ifdef PATHCOUNTS ++count1; #endif if (Aswitch || Bswitch) for (i = 0; i < n; ++i) for (j = 0; j < n; ++j) edgeno[i][j] = -1; if (ne == 0 && minedges <= 0 && (!lswitch || (lswitch && (maxdeg&1) == 0))) { trythisone(NULL,lswitch,deg,maxdeg,0,n); return; } #ifdef PATHCOUNTS ++count2; #endif k = 0; for (i = 0, gi = g; i < n; ++i, gi += m) { for (j = i; (j = nextelement(gi,m,j)) >= 0; ) { v0[k] = i; v1[k] = j; edgeno[i][j] = edgeno[j][i] = k; lastlev[i] = lastlev[j] = k; ++k; } } isreg = !lswitch && (maxdeg >= 0 && 2*minedges == n*(long)maxdeg); /* Case of regular multigraphs */ if (isreg) /* regular case */ /* Condition: def(v) <= total def of neighbours */ { for (i = 0; i < n; ++i) { def[i] = maxdeg - deg[i]; delta[i] = -def[i]; } for (i = 0; i < k; ++i) { x0 = v0[i]; x1 = v1[i]; delta[x0] += def[x1]; delta[x1] += def[x0]; } for (i = 0; i < n; ++i) if (delta[i] < 0) return; } if ((isreg || lswitch) && (maxdeg & n & 1) == 1) return; if (isreg && j0 >= 0 && maxdeg > 0) return; if (lswitch && j0 >= 0 && (maxdeg&1) == 1) return; #ifdef PATHCOUNTS ++count3; #endif if (maxedges == NOLIMIT) { if (maxmult == NOLIMIT) maxedges = maxdeg*n/2; else maxedges = ne*maxmult; } if (maxmult == NOLIMIT) maxmult = maxedges - ne + 1; if (maxdeg >= 0 && maxmult > maxdeg) maxmult = maxdeg; if (maxedges < ne || ne*maxmult < minedges) return; #ifdef PATHCOUNTS ++count4; #endif if (n > MAXNV || ne > MAXNE) { fprintf(stderr,">E multig: MAXNV or MAXNE exceeded\n"); exit(1); } nauty_check(WORDSIZE,m,n,NAUTYVERSIONID); for (i = 0; i < n; ++i) ptn[i] = 1; ptn[n-1] = 0; EMPTYSET(active,m); if (j0 != n-1) ADDELEMENT(active,j0+1); for (i = 0; i <= j0; ++i) ptn[i] = 0; for (i = j0+1; i < n; ++i) if (lab[i] < nfixed) break; if (i != j0+1 && i != n) { ptn[i-1] = 0; ADDELEMENT(active,i); } options.defaultptn = FALSE; options.userautomproc = groupautomproc; options.userlevelproc = grouplevelproc; nauty(g,lab,ptn,active,orbits,&options,&stats,workspace,100,m,n,NULL); if (stats.grpsize2 == 0) groupsize = stats.grpsize1 + 0.1; else groupsize = 0; group = groupptr(FALSE); makecosetreps(group); lastrejok = FALSE; if (isreg) scan_reg(0,ne,minedges,maxedges,0,maxmult,group,n,delta,def,maxdeg); else if (lswitch) scan_lp(0,ne,minedges,maxedges,0,maxmult,group,n,deg,maxdeg); else if (maxdeg >= 0) scan_md(0,ne,minedges,maxedges,0,maxmult,group,n,deg,maxdeg); else scan(0,ne,minedges,maxedges,0,maxmult,group,n); }