int main(int argc, char** argv) { char buffer[1500]; int print_orig = 0; if ( argc > 1 ) { print_orig = 1; } while ( scanf("%s", buffer) != EOF ) { /* buffer holds an s6 string */ sparsegraph g; SG_INIT(g); int num_loops; stringtosparsegraph(buffer, &g, &num_loops); int nv = g.nv; int m = (nv + WORDSIZE - 1) / WORDSIZE; nauty_check(WORDSIZE, m, nv, NAUTYVERSIONID); DYNALLSTAT(int, lab, lab_n); DYNALLSTAT(int, ptn, ptn_n); DYNALLSTAT(int, orbits, orbits_n); DYNALLOC1(int, lab, lab_n, nv, "malloc"); DYNALLOC1(int, ptn, ptn_n, nv, "malloc"); DYNALLOC1(int, orbits, orbits_n, nv, "malloc"); static DEFAULTOPTIONS_SPARSEGRAPH( options); options.defaultptn = TRUE; /* Don't need colors */ options.getcanon = TRUE; /* gets labels */ options.digraph = TRUE; statsblk stats; /* we'll use this at the end */ DYNALLSTAT(setword, workspace, worksize); DYNALLOC1(setword, workspace, worksize, 50 * m, "malloc"); sparsegraph canon_g; SG_INIT(canon_g); /* call nauty */ nauty((graph*) &g, lab, ptn, NULL, orbits, &options, &stats, workspace, 50 * m, m, g.nv, (graph*) &canon_g); sortlists_sg(&canon_g); char* canon_str = sgtos6(&canon_g); int canon_len = strlen(canon_str); if ( print_orig == 0 ) { printf("%s", canon_str); } else { canon_str[canon_len-1] = 0; printf("%s", canon_str); printf("\t%s\n", buffer); } /* free workspace */ DYNFREE(workspace, worksize); DYNFREE(lab,lab_n); DYNFREE(ptn,ptn_n); DYNFREE(orbits,orbits_n); SG_FREE(canon_g); SG_FREE(g); } return 0; }
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 inline void callNauty(){ //call nauty generatorCount = 0; nauty((graph*) &ng, lab, ptn, NULL, orbits, &options, &stats, workspace, WORKSIZE, m, n, NULL); }
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); }
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; }
unsigned char *graph_key(T const &graph) { setword N = graph.num_vertices(); setword NN = N + graph.num_multiedges(); setword M = ((NN % WORDSIZE) > 0) ? (NN / WORDSIZE)+1 : NN / WORDSIZE; // allocate a clear space for graph if((NN*M) >= nauty_graph_buf_size) { // need to increase size of temporary buffer! delete [] nauty_graph_buf; nauty_graph_buf = new setword[NN*M]; nauty_graph_buf_size = NN*M; // SHOULD CHECK FOR INCREASE IN WORKSPACE SIZE? delete [] nauty_workspace; nauty_workspace = new setword[100 * M]; _nauty_workspace_size = 100 * M; } memset(nauty_graph_buf,0,nauty_graph_buf_size * sizeof(setword)); // build map from graph vertex space to nauty vertex space unsigned int vtxmap[graph.domain_size()]; unsigned int idx=0; for(typename T::vertex_iterator i(graph.begin_verts()); i!=graph.end_verts();++i,++idx) { vtxmap[*i] = idx; } // now, build nauty graph. int mes = N; // multi-edge start for(typename T::vertex_iterator i(graph.begin_verts());i!=graph.end_verts();++i) { unsigned int _v = *i; for(typename T::edge_iterator j(graph.begin_edges(_v));j!=graph.end_edges(_v);++j) { unsigned int _w = j->first; // convert vertices into nauty graph vertex space unsigned int v = vtxmap[_v]; unsigned int w = vtxmap[_w]; // now add this edge(s) to nauty graph if(v <= w) { nauty_add_edge(v,w,M); unsigned int k=j->second-1; if(k > 0) { // this is a multi-edge! for(;k!=0;--k,++mes) { nauty_add_edge(v,mes,M); nauty_add_edge(mes,w,M); } } } } } // At this stage, we have constructed a nauty graph representing our // original graph. We now need to run nauty to generate the // canonical graph which essentially corresponds to our "graph key" statsblk stats; DEFAULTOPTIONS(opts); opts.getcanon = TRUE; opts.defaultptn = FALSE; opts.writemarkers = FALSE; // could optimise this further by making lab and ptn static int lab[NN]; int ptn[NN]; for(int i=0;i!=NN;++i) { lab[i] = i; ptn[i] = 1; } ptn[NN-1] = 0; ptn[N-1]=0; nvector orbits[NN]; setword *nauty_canong_buf = new setword[((NN*M)+NAUTY_HEADER_SIZE)]; // call nauty nauty(nauty_graph_buf, lab, ptn, NULL, orbits, &opts, &stats, nauty_workspace, nauty_workspace_size(), M, NN, // true graph size, since includes vertices added for multi edges. nauty_canong_buf+NAUTY_HEADER_SIZE // add two for header ); // check for error if(stats.errstatus != 0) { throw std::runtime_error("internal error: nauty returned an error?"); } nauty_canong_buf[0] = NN; nauty_canong_buf[1] = N; return (unsigned char*) nauty_canong_buf; }
/* Cette fonction génère les structures qui vont bien pour les appels à Nauty */ void Carquois::genGraph() { int i,j,m,nbSommetsNauty; int lab1[MAXN],ptn[MAXN],orbits[MAXN]; static DEFAULTOPTIONS_GRAPH(options); statsblk stats; setword workspace[5*MAXM]; if(!this->graphAJour) { nbSommetsNauty = 2 * this->getN(); m=(nbSommetsNauty + WORDSIZE - 1)/WORDSIZE; /* Si on trouve une valeur strictement positive dans la matrice d'incidence, alors on ajoute une arrête dans notre graphe */ for(i=0;i<this->getN();i++) { gv=GRAPHROW(nautyG,i+this->getN(),m); EMPTYSET(gv,m); gv=GRAPHROW(nautyG,i,m); EMPTYSET(gv,m); /* On ajoute les fausses arrêtes entre le layer 0 et le layer 1 */ ADDELEMENT(gv,i+this->getN()); for(j=0;j<this->getN();j++) { /* multiplicité de 1 */ if(this->getM(i,j)==1) { gv=GRAPHROW(nautyG,i,m); ADDELEMENT(gv,j); } else { if(this->getM(i,j)==2) { gv=GRAPHROW(nautyG,i+this->getN(),m); ADDELEMENT(gv,j+this->getN()); } } } } options.getcanon = TRUE; options.digraph = TRUE; options.defaultptn = FALSE; nauty_check(WORDSIZE,m,nbSommetsNauty,NAUTYVERSIONID); for(i=0;i<2*n;i++) { lab1[i]=i; ptn[i]=1; } ptn[n-1]=0; ptn[2*n-1]=0; nauty(nautyG,lab1,ptn,NULL,orbits,&options,&stats, workspace,5*MAXM,m,nbSommetsNauty,nautyGC); this->graphAJour=1; } }