void permset(set *set1, set *set2, int m, permutation *perm) { register setword setw; register int pos,w,b; EMPTYSET(set2,m); #if MAXM==1 setw = set1[0]; while (setw != 0) { TAKEBIT(b,setw); pos = perm[b]; ADDELEMENT(set2,pos); } #else for (w = 0; w < m; ++w) { setw = set1[w]; while (setw != 0) { TAKEBIT(b,setw); pos = perm[TIMESWORDSIZE(w)+b]; ADDELEMENT(set2,pos); } } #endif }
void writegre(FILE *f, graph *g, int n1, int n2) /* write graph g (n1+n2 vertices) to file f in Greechie diagram format */ { static char atomname[] = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz!\"#$%&'()*-/:;<=>?@[\\]^_`{|}~"; char grestr[MAXN*MAXN+MAXN+5]; int i,j,k; setword gi; k = 0; for (i = n1; i < n1+n2; ++i) { if (i > n1) grestr[k++] = ','; gi = g[i]; while (gi) { TAKEBIT(j,gi); grestr[k++] = atomname[j]; } } grestr[k++] = '.'; grestr[k++] = '\n'; grestr[k] = '\0'; if (fputs(grestr,f) == EOF || ferror(f)) { fprintf(stderr,">E genbg : error on writing file\n"); gt_abort(NULL); } }
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; }
static long maxclnode1(graph *g, setword cliq, setword cov, int maxv) /* Internal search node. cov has all the vertices outside cliq that * cover all of cliq. maxv is the last vertex of cliq. */ { long ans; int i; setword w; if (cov == 0) return 1; ans = 0; w = cov & BITMASK(maxv); while (w) { TAKEBIT(i,w); ans += maxclnode1(g,cliq|bit[i],cov&g[i]&~bit[i],i); } return ans; }
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; }
long cyclecount1(graph *g, int n) /* The total number of cycles in g (assumed no loops), m=1 only */ { setword body,nbhd; long total; int i,j; body = ALLMASK(n); total = 0; for (i = 0; i < n-2; ++i) { body ^= bit[i]; nbhd = g[i] & body; while (nbhd) { TAKEBIT(j,nbhd); total += pathcount1(g,j,body,nbhd); } } return total; }
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,lact; 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; lact = *active; split1 = -1; while (*numcells < n && lact) { TAKEBIT(split1,lact); 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; lact |= bit[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]]) != 0) cnt = POPCOUNT(x); else cnt = 0; count[i] = bmin = bmax = cnt; bucket[cnt] = 1; while (++i <= cell2) { if ((x = workset & g[lab[i]]) != 0) 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) { lact |= bit[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 (TRUE) { if (lab[i] == n-1) break; --i; if (ptn[i] == 0) { *code = -1; return; } } } } }
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; }