void fmperm(permutation *perm, set *fix, set *mcr, int m, int n) { register int i,k,l; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"writeperm"); #endif EMPTYSET(fix,m); EMPTYSET(mcr,m); for (i = n; --i >= 0;) workperm[i] = 0; for (i = 0; i < n; ++i) if (perm[i] == i) { ADDELEMENT(fix,i); ADDELEMENT(mcr,i); } else if (workperm[i] == 0) { l = i; do { k = l; l = perm[l]; workperm[k] = 1; } while (l != i); ADDELEMENT(mcr,i); } }
static boolean ismax(int *p, int n) /* test if x^p <= x */ { int i,j,k; set px[MAXME]; EMPTYSET(px,me); for (j = 0; j < nix; ++j) { i = ix[j]; k = i >> 1; if (i & 1) ADDELEMENT(px,edgeno[p[v1[k]]][p[v0[k]]]); else ADDELEMENT(px,edgeno[p[v0[k]]][p[v1[k]]]); if (px[0] > x[0]) { rejectlevel = k; return FALSE; } } rejectlevel = MAXNE+1; if (px[0] < x[0]) return TRUE; for (i = 1; i < me; ++i) if (px[i] > x[i]) return FALSE; else if (px[i] < x[i]) return TRUE; ++newgroupsize; ntgroup = TRUE; return TRUE; }
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 }
static void makecanon(graph *g, graph *gcan, int n1, int n2) /* gcan := canonise(g) */ { int lab[MAXN],ptn[MAXN],orbits[MAXN]; setword active[1]; int i; statsblk stats; static DEFAULTOPTIONS_GRAPH(options); setword workspace[50]; options.writemarkers = FALSE; options.writeautoms = FALSE; options.getcanon = TRUE; options.defaultptn = FALSE; for (i = 0; i < n1+n2; ++i) { lab[i] = i; ptn[i] = 1; } ptn[n1-1] = ptn[n1+n2-1] = 0; EMPTYSET(active,1); ADDELEMENT(active,0); ADDELEMENT(active,n1); nauty(g,lab,ptn,active,orbits,&options,&stats, workspace,50,1,n1+n2,gcan); }
static void add_edges(graph_info *g, unsigned start, int extended_m, level *my_level) { //setup m and k[n] for the children //note that these values will not change b/w each child //of this node in the search tree g->m++; g->k[g->n - 1]++; unsigned old_max_k = g->max_k; if(g->k[g->n - 1] > g->max_k) g->max_k = g->k[g->n - 1]; //if the child has a node of degree greater than MAX_K, //don't search it if(g->k[g->n - 1] <= my_level->max_k) { for(unsigned i = start; i < g->n - 1; i++) { g->k[i]++; //same as comment above if(g->k[i] <= my_level->max_k) { unsigned old_max_k = g->max_k; if(g->k[i] > g->max_k) g->max_k = g->k[i]; g->distances[g->n*i + (g->n-1)] = g->distances[g->n*(g->n-1) + i] = 1; ADDELEMENT(GRAPHROW(g->nauty_graph, i, extended_m), g->n-1); ADDELEMENT(GRAPHROW(g->nauty_graph, g->n-1, extended_m), i); add_edges(g, i + 1, extended_m, my_level); DELELEMENT(GRAPHROW(g->nauty_graph, i, extended_m), g->n-1); DELELEMENT(GRAPHROW(g->nauty_graph, g->n-1, extended_m), i); g->distances[g->n*i + (g->n-1)] = g->distances[g->n*(g->n-1) + i] = GRAPH_INFINITY; g->max_k = old_max_k; } g->k[i]--; } } //tear down values we created in the beginning g->max_k = old_max_k; g->m--; g->k[g->n - 1]--; if(g->k[g->n - 1] > 0) { graph_info *temporary = new_graph_info(*g); fill_dist_matrix(*temporary); temporary->diameter = calc_diameter(*temporary); temporary->sum_of_distances = calc_sum(*temporary); if(!add_graph_to_level(temporary, my_level)) graph_info_destroy(temporary); } }
void translate(GRAPH *g, NAUTYGRAPH nautyg, int m, int newOrder) { int i, j, k, dummy; dummy = g->order; for (i = 0; i < newOrder * m; i++) nautyg[i] = 0; for (i = 0; i < g->order; i++) { for (j = 0; j < 3; j++) { int neighbour = g->adjacency[i][j]; if (neighbour == SEMIEDGE) neighbour = dummy++; if (neighbour > i) { if (g->colours[i][j] == 0) { ADDELEMENT(nautyg + (m * i), neighbour); ADDELEMENT(nautyg + (m * neighbour), i); } else { int next = dummy++; ADDELEMENT(nautyg + (m * i), next); ADDELEMENT(nautyg + (m * next), i); for (k = 0; k < g->colours[i][j] - 1; k++) { ADDELEMENT(nautyg + (m * dummy), next); ADDELEMENT(nautyg + (m * next), dummy); next = dummy++; } ADDELEMENT(nautyg + (m * neighbour), next); ADDELEMENT(nautyg + (m * next), neighbour); } } } } }
void Nauty::addElement(int ix, int jx) { // Right now die if bad index. Can throw exception later //printf("addelement %d %d \n", ix, jx); assert(ix < n_ && jx < n_); if(ix != jx){ //No Loops set *gv = GRAPHROW(G_, ix, m_); ADDELEMENT(gv, jx); set *gv2 = GRAPHROW(G_, jx, m_); ADDELEMENT(gv2, ix); autoComputed_ = false; } }
void targetcell(graph *g, int *lab, int *ptn, int level, int numcells, set *tcell, int *tcellsize, int *cellpos, int tc_level, int hint, int (*goodcell)(graph*,int*,int*,int,int,int,int), int m, int n) { register int i,j,k; if (hint >= 0 && ptn[hint] > level && (hint == 0 || ptn[hint-1] <= level)) i = hint; else if (level <= tc_level && goodcell != NULL) i = (*goodcell)(g,lab,ptn,level,tc_level,m,n); else for (i = 0; i < n && ptn[i] <= level; ++i) {} if (i == n) i = j = 0; else for (j = i + 1; ptn[j] > level; ++j) {} *tcellsize = j - i + 1; EMPTYSET(tcell,m); for (k = i; k <= j; ++k) ADDELEMENT(tcell,lab[k]); *cellpos = i; }
void compl(graph *g, int m, int n, graph *h) /* h := complement of g */ { int i,j; setword *gi,*hi; #if MAXN set all[MAXM]; #else DYNALLSTAT(set,all,all_sz); DYNALLOC1(set,all,all_sz,m,"complg"); #endif EMPTYSET(all,m); for (i = 0; i < n; ++i) ADDELEMENT(all,i); gi = (setword*) g; hi = (setword*) h; for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) hi[j] = gi[j] ^ all[j]; DELELEMENT(hi,i); gi += m; hi += m; } }
static void newedge(graph *g1, int m1, int n1, int v1, int v2, int w1, int w2, graph *g2, int m2) /* Make g2 by subdividing edges v1-v2 and w1-w2 in g1 and adding an edge between them. Must have m2 >= m1. */ { int i,j; setword *s1,*s2; s1 = g1; s2 = g2; for (i = 0; i < n1; ++i) { for (j = 0; j < m1; ++j) *(s2++) = *(s1++); for (; j < m2; ++j) *(s2++) = 0; } s2 = GRAPHROW(g2,v1,m2); DELELEMENT(s2,v2); ADDELEMENT(s2,n1); s2 = GRAPHROW(g2,v2,m2); DELELEMENT(s2,v1); ADDELEMENT(s2,n1); s2 = GRAPHROW(g2,w1,m2); DELELEMENT(s2,w2); ADDELEMENT(s2,n1+1); s2 = GRAPHROW(g2,w2,m2); DELELEMENT(s2,w1); ADDELEMENT(s2,n1+1); s2 = GRAPHROW(g2,n1,m2); EMPTYSET(s2,m2); ADDELEMENT(s2,v1); ADDELEMENT(s2,v2); ADDELEMENT(s2,n1+1); s2 = GRAPHROW(g2,n1+1,m2); EMPTYSET(s2,m2); ADDELEMENT(s2,w1); ADDELEMENT(s2,w2); ADDELEMENT(s2,n1); }
void translate(GRAPH *g, NAUTYGRAPH nautyg, int m, int newOrder) { int i, j, dummy; dummy = g->order; for (i = 0; i < newOrder * m; i++) nautyg[i] = 0; for (i = 0; i < g->order; i++) { boolean multiedgeHandled = FALSE; for (j = 0; j < 3; j++) { int neighbour = g->adjacency[i][j]; if (neighbour == SEMIEDGE) neighbour = dummy++; if (neighbour > i) { if (g->multiedge[i] == neighbour && !multiedgeHandled) { int extraNeighbour = dummy++; ADDELEMENT(nautyg + (m * i), extraNeighbour); ADDELEMENT(nautyg + (m * extraNeighbour), i); ADDELEMENT(nautyg + (m * extraNeighbour), neighbour); ADDELEMENT(nautyg + (m * neighbour), extraNeighbour); multiedgeHandled = TRUE; } else { ADDELEMENT(nautyg + (m * i), neighbour); ADDELEMENT(nautyg + (m * neighbour), i); } } } } }
int permcycles(int *p, int n, int *len, boolean sort) /* Puts in len[0..] the cycle lengths of p. If sort, sort them. Return the number of cycles. */ { int m,i,j,k,h,nc,leni; m = (n + WORDSIZE - 1) / WORDSIZE; DYNALLOC1(set,workset,workset_sz,m,"malloc"); EMPTYSET(workset,m); nc = 0; for (i = 0; i < n; ++i) if (!ISELEMENT(workset,i)) { k = 1; for (j = p[i]; j != i; j = p[j]) { ADDELEMENT(workset,j); ++k; } len[nc++] = k; } if (sort && nc > 1) { j = nc / 3; h = 1; do h = 3 * h + 1; while (h < j); do { for (i = h; i < nc; ++i) { leni = len[i]; for (j = i; len[j-h] > leni; ) { len[j] = len[j-h]; if ((j -= h) < h) break; } len[j] = leni; } h /= 3; } while (h > 0); } return nc; }
void fmptn(int *lab, int *ptn, int level, set *fix, set *mcr, int m, int n) { register int i,lmin; EMPTYSET(fix,m); EMPTYSET(mcr,m); for (i = 0; i < n; ++i) if (ptn[i] <= level) { ADDELEMENT(fix,lab[i]); ADDELEMENT(mcr,lab[i]); } else { lmin = lab[i]; do if (lab[++i] < lmin) lmin = lab[i]; while (ptn[i] > level); ADDELEMENT(mcr,lmin); } }
void maketargetcell(graphnau *g, int *lab, int *ptn, int level, set *tcell, int *tcellsize, int *cellpos, int tc_level, boolean digraph, int hint, int (*targetcell)(graphnau*,int*,int*,int,int,boolean,int,int,int), int m, int n) { int i,j,k; i = (*targetcell)(g,lab,ptn,level,tc_level,digraph,hint,m,n); for (j = i + 1; ptn[j] > level; ++j) {} *tcellsize = j - i + 1; EMPTYSET(tcell,m); for (k = i; k <= j; ++k) ADDELEMENT(tcell,lab[k]); *cellpos = i; }
void breakout(int *lab, int *ptn, int level, int tc, int tv, set *active, int m) { register int i,prev,next; EMPTYSET(active,m); ADDELEMENT(active,tc); i = tc; prev = tv; do { next = lab[i]; lab[i++] = prev; prev = next; } while (prev != tv); ptn[tc] = level; }
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); }
void doref(graph *g, int *lab, int *ptn, int level, int *numcells, int *qinvar, permutation *invar, set *active, int *code, void (*refproc)(graph*,int*,int*,int,int*,permutation*,set*,int*,int,int), void (*invarproc)(graph*,int*,int*,int,int,int,permutation*, int,boolean,int,int), int mininvarlev, int maxinvarlev, int invararg, boolean digraph, int m, int n) { register int j,h; register permutation pw; int iw; int i,cell1,cell2,nc,tvpos,minlev,maxlev; long longcode; boolean same; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"doref"); #endif if ((tvpos = nextelement(active,M,-1)) < 0) tvpos = 0; (*refproc)(g,lab,ptn,level,numcells,invar,active,code,M,n); minlev = (mininvarlev < 0 ? -mininvarlev : mininvarlev); maxlev = (maxinvarlev < 0 ? -maxinvarlev : maxinvarlev); if (invarproc != NULL && *numcells < n && level >= minlev && level <= maxlev) { (*invarproc)(g,lab,ptn,level,*numcells,tvpos,invar,invararg, digraph,M,n); EMPTYSET(active,m); for (i = n; --i >= 0;) workperm[i] = invar[lab[i]]; nc = *numcells; for (cell1 = 0; cell1 < n; cell1 = cell2 + 1) { pw = workperm[cell1]; same = TRUE; for (cell2 = cell1; ptn[cell2] > level; ++cell2) if (workperm[cell2+1] != pw) same = FALSE; if (same) continue; j = (cell2 - cell1 + 1) / 3; h = 1; do h = 3 * h + 1; while (h < j); do /* shell sort */ { for (i = cell1 + h; i <= cell2; ++i) { iw = lab[i]; pw = workperm[i]; for (j = i; workperm[j-h] > pw; ) { workperm[j] = workperm[j-h]; lab[j] = lab[j-h]; if ((j -= h) < cell1 + h) break; } workperm[j] = pw; lab[j] = iw; } h /= 3; } while (h > 0); for (i = cell1 + 1; i <= cell2; ++i) if (workperm[i] != workperm[i-1]) { ptn[i-1] = level; ++*numcells; ADDELEMENT(active,i); } } if (*numcells > nc) { *qinvar = 2; longcode = *code; (*refproc)(g,lab,ptn,level,numcells,invar,active,code,M,n); longcode = MASH(longcode,*code); *code = CLEANUP(longcode); } else *qinvar = 1; } else *qinvar = 0; }
/* 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; } }