static boolean fromsort(FILE *f, char **cdstr, char **dstr, unsigned long *index) /* read one graph from sort process */ { int j; char *s; if ((s = getline(f)) == NULL) return FALSE; *cdstr = s; for (j = 0; s[j] != ' ' && s[j] != '\t' && s[j] != '\n'; ++j) {} if (s[j] == ' ') { s[j] = '\0'; *dstr = &s[j+1]; for (++j; s[j] != '\t' && s[j] != '\n'; ++j) {} } else *dstr = NULL; if (s[j] == '\t') { if (sscanf(&s[j+1],"%lu",index) != 1) gt_abort(">E shortg: index field corrupted\n"); } else *index = 0; s[j] = '\0'; return TRUE; }
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); } }
long cyclecount(graph *g, int m, int n) /* The total number of cycles in g (assumed no loops) */ { if (m == 1) return cyclecount1(g,n); gt_abort("cycle counting is only implemented for n <= WORDSIZE"); return 0; }
static int trythisone(grouprec *group, int ne, int n) { int i,k; boolean accept; first = TRUE; ADDBIG(ngen,1); nix = ne; newgroupsize = 1; if (!group || groupsize == 1) accept = TRUE; else if (lastrejok && !ismax(lastreject,n)) accept = FALSE; else if (lastrejok && groupsize == 2) accept = TRUE; else { newgroupsize = 1; if (allgroup2(group,testmax) == 0) accept = TRUE; else accept = FALSE; } if (accept) { #ifdef GROUPTEST if (groupsize % newgroupsize != 0) gt_abort("group size error\n"); totallab += groupsize/newgroupsize; #endif ADDBIG(nout,1); if (outfile) { fprintf(outfile,"%d %ld",n,ne); if (Gswitch) fprintf(outfile," %lu",newgroupsize); for (i = -1; (i = nextelement(x,me,i)) >= 0; ) { k = i >> 1; if (i & 1) fprintf(outfile," %d %d",v1[k],v0[k]); else fprintf(outfile," %d %d",v0[k],v1[k]); } fprintf(outfile,"\n"); } return MAXNE+1; } else return rejectlevel;
static pid_t beginsort(FILE **sortin, FILE **sortout, char *tempdir, boolean vdswitch, boolean keep) /* begin sort process, open streams for i/o to it, and return its pid */ { int pid; int inpipe[2],outpipe[2]; if (pipe(inpipe) < 0 || pipe(outpipe) < 0) gt_abort(">E shortg: can't create pipes to sort process\n"); if ((pid = fork()) < 0) gt_abort(">E shortg: can't fork\n"); if (pid > 0) /* parent */ { close(inpipe[0]); close(outpipe[1]); if ((*sortin = fdopen(inpipe[1],"w")) == NULL) gt_abort(">E shortg: can't open stream to sort process\n"); if ((*sortout = fdopen(outpipe[0],"r")) == NULL) gt_abort(">E shortg: can't open stream from sort process\n"); } else /* child */ { SET_C_COLLATION; close(inpipe[1]); close(outpipe[0]); if (dup2(inpipe[0],0) < 0 || dup2(outpipe[1],1) < 0) gt_abort(">E shortg: dup2 failed\n"); if (tempdir == NULL) { if (vdswitch) if (keep) execlp(VSORTCOMMAND2,NULL); else execlp(VSORTCOMMAND1,NULL); else execlp(SORTCOMMAND,NULL); } else { if (vdswitch) if (keep) execlp(VSORTCOMMANDT2,NULL); else execlp(VSORTCOMMANDT1,NULL); else execlp(SORTCOMMANDT,NULL); } gt_abort(">E shortg: can't start sort process\n"); } return pid; }
void write_ascii(FILE *f, graph *g, int n) /* write tournament g (n vertices) to file f in ascii format */ { char s[MAXN*(MAXN-1)/2+2]; int i,j; size_t k; k = 0; for (i = 0; i < n-1; ++i) for (j = i+1; j < n; ++j) if ((g[i] & bit[j])) s[k++] = '1'; else s[k++] = '0'; s[k++] = '\n'; s[k] = '\0'; if (fwrite(s,1,k,f) != k || ferror(f)) gt_abort(">E write_ascii : error on writing\n"); }
static boolean fromsort(FILE *f, char **cdstr, char **dstr, nauty_counter *index) /* read one graph from sort process */ { int j; char *s; if ((s = gtools_getline(f)) == NULL) return FALSE; *cdstr = s; for (j = 0; s[j] != ' ' && s[j] != '\t' && s[j] != '\n'; ++j) {} if (s[j] == ' ') { s[j] = '\0'; *dstr = &s[j+1]; for (++j; s[j] != '\t' && s[j] != '\n'; ++j) {} } else *dstr = NULL; if (s[j] == '\t') { #if LONG_LONG_COUNTERS if (sscanf(&s[j+1],"%llu",index) != 1) #else if (sscanf(&s[j+1],"%lu",index) != 1) #endif gt_abort(">E shortg: index field corrupted\n"); } else *index = 0; s[j] = '\0'; return TRUE; }
static int trythisone(grouprec *group, int ne, int n) { int i,k; boolean accept; #ifdef PROCESS graph g[WORDSIZE]; #endif first = TRUE; ++gd_ngen; nix = ne; newgroupsize = 1; ntgroup = FALSE; if (!group || groupsize == 1) accept = TRUE; else if (lastrejok && !ismax(lastreject,n)) accept = FALSE; else if (lastrejok && groupsize == 2) accept = TRUE; else { newgroupsize = 1; ntgroup = FALSE; if (allgroup2(group,testmax) == 0) accept = TRUE; else accept = FALSE; } if (accept) { #ifdef GROUPTEST if (groupsize % newgroupsize != 0) gt_abort("group size error\n"); totallab += groupsize/newgroupsize; #endif if (Vswitch && !ntisol && !ntgroup) return MAXNE+1; ++dg_nout; #ifdef PROCESS EMPTYSET(g,n); for (i = -1; (i = nextelement(x,me,i)) >= 0; ) { k = i >> 1; if (i & 1) g[v1[k]] |= bit[v0[k]]; else g[v0[k]] |= bit[v1[k]]; } PROCESS(outfile,g,n); #endif if (outfile) { fprintf(outfile,"%d %d",n,ne); if (Gswitch) fprintf(outfile," %lu",newgroupsize); for (i = -1; (i = nextelement(x,me,i)) >= 0; ) { k = i >> 1; if (i & 1) fprintf(outfile," %d %d",v1[k],v0[k]); else fprintf(outfile," %d %d",v0[k],v1[k]); } fprintf(outfile,"\n"); } return MAXNE+1; } else return rejectlevel;
static int p4decomposition(sparsegraph sg, int vertex, boolean vertical) /* Test which non-triangular P4s extend to a decomposition. Return -2: timeout -1: not decomposable at all >=0: number of P4s missed If 0 <= vertex < n, only P4s starting at that vertex are considered. If vertical (only for prisms), the central edge must be vertical. The paths missed can be found in p4list[]. */ { int i,j,k,l,n,c; int ans,status; int imin,imax,nump4; int v1,v2,v3,v4,e1,e2,e3,j1,j2,j3; n = sg.nv; if (vertex >= n) gt_abort(">E vertex given to -t is too large"); status = isdecomposable(sg,FALSE,FALSE); if (status == NO) return -1; else if (status == TIMEOUT) return -2; if (vertex >= 0) { imin = imax = vertex; DYNALLOC1(p4,p4list,p4list_sz,36,"malloc"); } else { imin = 0; imax = n-1; DYNALLOC1(p4,p4list,p4list_sz,18*n,"malloc"); } nump4 = 0; for (v1 = imin; v1 <= imax; ++v1) for (j1 = 0; j1 < 4; ++j1) { v2 = sg.e[4*v1+j1]; e1 = eno[4*v1+j1]; for (j2 = 0; j2 < 4; ++j2) { v3 = sg.e[4*v2+j2]; if (v3 == v1) continue; if (vertical && (v2|1) != (v3|1)) continue; e2 = eno[4*v2+j2]; for (j3 = 0; j3 < 4; ++j3) { v4 = sg.e[4*v3+j3]; if (v4 == v1 || v4 == v2) continue; e3 = eno[4*v3+j3]; if (vertex >= 0 || v1 < v4) { p4list[nump4].v1 = v1; p4list[nump4].v2 = v2; p4list[nump4].v3 = v3; p4list[nump4].v4 = v4; p4list[nump4].e1 = e1; p4list[nump4].e2 = e2; p4list[nump4].e3 = e3; p4list[nump4].ok = FALSE; ++nump4; } } } } for (i = 0; i < nump4; ++i) if (colour[p4list[i].e1] == colour[p4list[i].e2] && colour[p4list[i].e1] == colour[p4list[i].e3]) p4list[i].ok = TRUE; for (i = 0; i < nump4; ++i) if (!p4list[i].ok) { initialise_colouring(n); if (makeblue(p4list[i].e1,FALSE) && makeblue(p4list[i].e2,n==2) && makeblue(p4list[i].e3,n==3)) { status = dispatchsearch(n,sg.e,3,0); if (status == TIMEOUT) return -2; if (status == YES) { for (k = 0; k < nump4; ++k) { if (p4list[k].ok) continue; if (colour[p4list[k].e1] == colour[p4list[k].e2] && colour[p4list[k].e1] == colour[p4list[k].e3]) p4list[k].ok = TRUE; } } } } ans = 0; for (i = 0; i < nump4; ++i) if (!p4list[i].ok) ++ans; return ans; }
static int iscrossdecomposable(sparsegraph sg, int vertex) /* Test if sg is decomposable as two hamiltonian cycles in all ways through each vertex (or the given vertex if it is >= 0. Details left in cross[]. Return -1: not decomposable at all 0: misses some 2-paths including two at some vertices 1: misses some 2-paths but at most one per vertex 2: fully decomposable 3: timeout */ { int i,j,k,l,n,c; int ans,status; int imin,imax; n = sg.nv; DYNALLOC1(int,cross,cross_sz,4*n,"malloc"); if (vertex >= n) gt_abort(">E vertex given to -t is too large"); for (i = 0; i < 4*n; ++i) cross[i] = 0; status = isdecomposable(sg,FALSE,FALSE); if (status == NO) return -1; else if (status == TIMEOUT) return 3; for (i = 0; i < n; ++i) { c = colour[eno[4*i]]; for (j = 1; j < 4; ++j) if (colour[eno[4*i+j]] == c) cross[4*i+j] = 1; } ans = 2; if (vertex >= 0) { imin = imax = vertex; } else { imin = 0; imax = n-1; } for (i = imin; i <= imax; ++i) for (j = 1; j < 4; ++j) if (!cross[4*i+j]) { initialise_colouring(n); if (makeblue(eno[4*i],FALSE) && makeblue(eno[4*i+j],n==2)) { status = dispatchsearch(n,sg.e,2,0); if (status == TIMEOUT) return 3; if (status == YES) { for (k = 0; k < n; ++k) { c = colour[eno[4*k]]; for (l = 1; l < 4; ++l) if (colour[eno[4*k+l]] == c) cross[4*k+l] = 1; } } else ans = 1; } else ans = 1; } if (ans == 1) for (i = 0; i < n; ++i) { if (cross[4*i+1] + cross[4*i+2] + cross[4*i+3] <= 1) ans = 0; } return ans; }
static void initialise_g(int n, int *e) /* Allocate all and initialise eno[],v1[],v2[] e is a vector like sg.e */ { int ne,i,j,k,l; DYNALLOC1(addrval,valstack,valstack_sz,10*n,"malloc"); DYNALLOC1(int,bluefarend,bluefarend_sz,n,"malloc"); DYNALLOC1(int,redfarend,redfarend_sz,n,"malloc"); DYNALLOC1(int,eno,eno_sz,4*n,"malloc"); DYNALLOC1(int,v1,v1_sz,2*n,"malloc"); DYNALLOC1(int,v2,v2_sz,2*n,"malloc"); DYNALLOC1(int,colour,colour_sz,2*n,"malloc"); DYNALLOC1(int,bluedeg,bluedeg_sz,n,"malloc"); DYNALLOC1(int,reddeg,reddeg_sz,n,"malloc"); DYNALLOC1(int,vstack,vstack_sz,n,"malloc"); DYNALLOC1(boolean,onstack,onstack_sz,n,"malloc"); DYNALLOC1(int,beste,beste_sz,2*n,"malloc"); /* Randomize e; seems to be no purpose for this any more. */ for (i = 0; i < n; ++i) { j = KRAN(4); k = e[4*i+j]; e[4*i+j] = e[4*i+3]; e[4*i+3] = k; j = KRAN(3); k = e[4*i+j]; e[4*i+j] = e[4*i+2]; e[4*i+2] = k; j = KRAN(2); k = e[4*i+j]; e[4*i+j] = e[4*i+1]; e[4*i+1] = k; } ne = 0; for (i = 0; i < n; ++i) { for (j = 0; j < 4; ++j) { k = e[4*i+j]; if (k > i) { v1[ne] = i; v2[ne] = k; eno[4*i+j] = ne++; } else /* Note: this code assumes a simple graph */ { for (l = 0; l < 4; ++l) if (e[4*k+l] == i) break; eno[4*i+j] = eno[4*k+l]; } } } if (ne != 2*n) gt_abort(">E ne is incorrect"); #if DEBUG { int ii; printf("===== n=%d === ne=%d ===================\n",n,ne); for (ii = 0; ii < n; ++ii) printf("%2d: %2d %2d %2d %2d %2d %2d %2d %2d\n", ii,e[4*ii],e[4*ii+1],e[4*ii+2],e[4*ii+3], eno[4*ii],eno[4*ii+1],eno[4*ii+2],eno[4*ii+3]); } #endif }
int main(int argc, char *argv[]) { FILE *infile; int j; SG_DECL(g); size_t flen; boolean ispipe; char zcmd[515]; HELP; if (argc == 1) { if (!readblissgraph(stdin,&g)) { fprintf(stderr,">E Bliss error in file %s\n","stdin"); gt_abort(NULL); } else writes6_sg(stdout,&g); } else { for (j = 1; j < argc; ++j) { flen = strlen(argv[j]); if (flen >= 3 && strcmp(argv[j]+flen-3,".gz") == 0) { sprintf(zcmd,"%s \"%s\"",ZCAT,argv[j]); if ((infile = popen(zcmd,"r")) == NULL) { fprintf(stderr, ">E blisstog: cannot open zcat pipe for \"%s\"\n", argv[j]); gt_abort(NULL); } ispipe = TRUE; } else { if ((infile = fopen(argv[j],"r")) == NULL) { fprintf(stderr,">E Can't open file %s\n",argv[j]); gt_abort(NULL); } ispipe = FALSE; } if (!readblissgraph(infile,&g)) { fprintf(stderr,">E Bliss error in file %s\n",argv[j]); gt_abort(NULL); } else writes6_sg(stdout,&g); if (ispipe) pclose(infile); else fclose(infile); } } exit(0); }
static void trythisone(grouprec *group, boolean lswitch, int *deg, int maxdeg, int ne, int n) /* Try one solution, accept if minimal. */ { int i,ne2; boolean accept; nix = ne; newgroupsize = 1; if (!group || groupsize == 1) accept = TRUE; else if (lastrejok && !ismax(lastreject,n)) accept = FALSE; else if (lastrejok && groupsize == 2) accept = TRUE; else { newgroupsize = 1; first = TRUE; if (allgroup2(group,testmax) == 0) accept = TRUE; else accept = FALSE; } if (accept) { #ifdef GROUPTEST if (groupsize % newgroupsize != 0) gt_abort("group size error\n"); totallab += groupsize/newgroupsize; #endif ++mg_nout; if (outfile) { ne2 = ne; if (lswitch) for (i = 0; i < n; ++i) if (deg[i] < maxdeg) { v0[ne2] = v1[ne2] = i; ix[ne2] = (maxdeg-deg[i])/2; ++ne2; } #ifdef OUTPROC OUTPROC(outfile,n,ne2,newgroupsize,v0,v1,ix); #else if (Aswitch || Bswitch) printam(outfile,n,ne2,ix); else { fprintf(outfile,"%d %d",n,ne2); if (Gswitch) fprintf(outfile," %lu",newgroupsize); for (i = 0; i < ne2; ++i) fprintf(outfile," %d %d %d",v0[i],v1[i],ix[i]); fprintf(outfile,"\n"); } #endif } return; } else return; }
static void subdivisiongraph(sparsegraph *g, int k, sparsegraph *h) /* h := subdivision graph of g, k new vertices per edge */ { DYNALLSTAT(size_t,eno,eno_sz); /* edge number */ int *ge,*gd,*he,*hd; size_t *gv,*hv; int gnv,hnv; size_t i,j,l,gnde,hnde,num; size_t hi,lo,mid,w; if (k == 0) { copy_sg(g,h); return; } sortlists_sg(g); SG_VDE(g,gv,gd,ge); gnv = g->nv; gnde = g->nde; DYNALLOC1(size_t,eno,eno_sz,gnde,"subdivideg"); hnv = gnv + k*(gnde/2); if (hnv <= 0 || (gnde > 0 && ((size_t)(hnv-gnv))/(gnde/2) != k)) gt_abort(">E subdivideg: output graph too large\n"); hnde = gnde * (k+1); if (hnde/(k+1) != gnde) gt_abort(">E subdivideg: output graph too large\n"); num = 0; for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]; ++j) { if (ge[j] == i) gt_abort(">E subdivideg can't handle undirected loops\n"); else if (ge[j] > i) eno[j] = num++; else { lo = gv[ge[j]]; hi = lo + gd[ge[j]] - 1; while (lo <= hi) { mid = lo + (hi-lo)/2; if (ge[mid] == i) break; else if (ge[mid] < i) lo = mid+1; else hi = mid-1; } if (lo > hi) gt_abort(">E subdivideg : binary search failed\n"); eno[j] = eno[mid]; } } } SG_ALLOC(*h,hnv,hnde,"subdivideg"); h->nv = hnv; h->nde = hnde; SG_VDE(h,hv,hd,he); for (i = 0; i < gnv; ++i) { hd[i] = gd[i]; hv[i] = gv[i]; } for (i = gnv; i < hnv; ++i) { hd[i] = 2; hv[i] = gnde + 2*(i-gnv); } for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]; ++j) if (ge[j] > i) { w = gnv + k*eno[j]; he[j] = w; he[hv[w]] = i; for (l = 1; l < k; ++l) { he[hv[w]+1] = w+1; he[hv[w+1]] = w; ++w; } } else { w = gnv + k*eno[j] + k - 1; he[j] = w; he[hv[w]+1] = i; } } }
static void linegraph(sparsegraph *g, sparsegraph *h) /* h := linegraph of g */ { DYNALLSTAT(size_t,eno,eno_sz); /* edge number */ int *ge,*gd,*he,*hd; size_t *gv,*hv; int gnv,hnv; size_t i,j,k,gnde,hnde,xhnde,num; size_t hi,lo,mid,v,w; sortlists_sg(g); SG_VDE(g,gv,gd,ge); gnv = g->nv; gnde = g->nde; DYNALLOC1(size_t,eno,eno_sz,gnde,"linegraphg"); hnv = gnde/2; if (hnv != gnde/2) gt_abort(">E linegraphg: too many input edges\n"); hnde = 0; num = 0; for (i = 0; i < gnv; ++i) { xhnde = hnde; hnde += gd[i]*((size_t)gd[i]-1); if (hnde < xhnde) gt_abort(">E linegraphg: too many output edges\n"); for (j = gv[i]; j < gv[i]+gd[i]; ++j) { if (ge[j] == i) gt_abort(">E linegraphg can't handle loops\n"); else if (ge[j] > i) eno[j] = num++; else { lo = gv[ge[j]]; hi = lo + gd[ge[j]] - 1; while (lo <= hi) { mid = lo + (hi-lo)/2; if (ge[mid] == i) break; else if (ge[mid] < i) lo = mid+1; else hi = mid-1; } if (lo > hi) gt_abort(">E linegraphg : binary search failed\n"); eno[j] = eno[mid]; } } } SG_ALLOC(*h,hnv,hnde,"linegraphg"); h->nv = hnv; h->nde = hnde; SG_VDE(h,hv,hd,he); for (i = 0; i < hnv; ++i) hd[i] = 0; for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]; ++j) hd[eno[j]] += gd[i]-1; } hv[0] = 0; for (i = 1; i < hnv; ++i) hv[i] = hv[i-1] + hd[i-1]; for (i = 0; i < hnv; ++i) hd[i] = 0; for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]-1; ++j) for (k = j+1; k < gv[i]+gd[i]; ++k) { v = eno[j]; w = eno[k]; he[hv[v]+(hd[v]++)] = w; he[hv[w]+(hd[w]++)] = v; } } }