static void no4path(graph *g, int m, int n, int v, int *dist) /* For each i, set dist[i]=0 if there is a 4-path from v to i */ { set *gv,*gv1,*gv2,*gv3; int v1,v2,v3,v4; gv = GRAPHROW(g,v,m); for (v1 = -1; (v1 = nextelement(gv,m,v1)) >= 0; ) { gv1 = GRAPHROW(g,v1,m); for (v2 = -1; (v2 = nextelement(gv1,m,v2)) >= 0; ) { if (v2 == v) continue; gv2 = GRAPHROW(g,v2,m); for (v3 = -1; (v3 = nextelement(gv2,m,v3)) >= 0; ) { if (v3 == v || v3 == v1) continue; gv3 = GRAPHROW(g,v3,m); for (v4 = -1; (v4 = nextelement(gv3,m,v4)) >= 0; ) if (v4 != v && v4 != v1 && v4 != v2) dist[v4] = 0; } } } }
boolean isbiconnected(graph *g, int m, int n) /* test if g is biconnected */ { int sp,v,vc; int numvis; set *gv; #if MAXN int num[MAXN],lp[MAXN],stack[MAXN]; #else DYNALLSTAT(int,num,num_sz); DYNALLSTAT(int,lp,lp_sz); DYNALLSTAT(int,stack,stack_sz); #endif if (n <= 2) return FALSE; if (m == 1) return isbiconnected1(g,n); #if !MAXN DYNALLOC1(int,num,num_sz,n,"isbiconnected"); DYNALLOC1(int,lp,lp_sz,n,"isbiconnected"); DYNALLOC1(int,stack,stack_sz,n,"isbiconnected"); #endif num[0] = 0; for (v = 1; v < n; ++v) num[v] = -1; lp[0] = 0; numvis = 1; sp = 0; v = 0; vc = -1; gv = (set*)g; for (;;) { vc = nextelement(gv,m,vc); if (vc < 0) { if (sp <= 1) return numvis == n; vc = v; v = stack[--sp]; gv = GRAPHROW(g,v,m); if (lp[vc] >= num[v]) return FALSE; if (lp[vc] < lp[v]) lp[v] = lp[vc]; } else if (num[vc] < 0) { stack[++sp] = vc; v = vc; gv = GRAPHROW(g,v,m); vc = -1; lp[v] = num[v] = numvis++; } else if (vc != v) { if (num[vc] < lp[v]) lp[v] = num[vc]; } } }
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 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; } }
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; }
void print_graph(graph_info g) { for (int i = 0; i < g.n; i++) { for (int j = 0; j < g.n; j++) printf("%d\t", g.distances[g.n*i + j]); printf("\n"); } for (int i = 0; i < g.n; i++) printf("%d ", g.k[i]); printf("\n"); unsigned m = (g.n + WORDSIZE - 1) / WORDSIZE; for(int i = 0; i < g.n; i++) { for(int j = 0; j < g.n; j++) { if(ISELEMENT(GRAPHROW(g.nauty_graph, i, m), j)) printf("1, "); else printf("0, "); } printf("\n"); } printf("\n"); printf("K: %d, D: %d, S: %d, M: %d\n", g.max_k, g.diameter, g.sum_of_distances, g.m); }
void updatecan(graphnau *g, graphnau *canong, permutation *lab, int samerows, int m, int n) { int i; set *ph; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"updatecan"); #endif for (i = 0; i < n; ++i) workperm[lab[i]] = i; for (i = samerows, ph = GRAPHROW(canong,samerows,M); i < n; ++i, ph += M) permset(GRAPHROW(g,lab[i],M),ph,M,workperm); }
int testcanlab(graphnau *g, graphnau *canong, int *lab, int *samerows, int m, int n) { int i,j; set *ph; #if !MAXN DYNALLOC1(permutation,workperm,workperm_sz,n,"testcanlab"); DYNALLOC1(set,workset,workset_sz,m,"testcanlab"); #endif for (i = 0; i < n; ++i) workperm[lab[i]] = i; for (i = 0, ph = canong; i < n; ++i, ph += M) { permset(GRAPHROW(g,lab[i],M),workset,M,workperm); for (j = 0; j < M; ++j) if (workset[j] < ph[j]) { *samerows = i; return -1; } else if (workset[j] > ph[j]) { *samerows = i; return 1; } } *samerows = n; return 0; }
boolean isautom(graph *g, permutation *perm, boolean digraph, int m, int n) { boolean autom=TRUE; #ifdef _OPENMP #pragma omp parallel #endif { int stride=1, offs=0; register set *pg; register int pos; set *pgp; int posp,i; #ifdef _OPENMP offs=omp_get_thread_num(); stride=omp_get_num_threads(); #endif for (i = offs; autom && i < n; i+=stride) { pg=g+M*i; pgp = GRAPHROW(g,perm[i],M); pos = (digraph ? -1 : i); while ((pos = nextelement(pg,M,pos)) >= 0) { posp = perm[pos]; if (!ISELEMENT(pgp,posp)) autom=FALSE; } } } return autom; }
void Nauty::deleteElement(int ix, int jx) { // Right now die if bad index. Can throw exception later assert(ix < n_ && jx < n_); set *gv = GRAPHROW(G_, ix, m_); if (ISELEMENT(gv, jx)) { DELELEMENT(gv, jx); } autoComputed_ = false; }
static void no3path(graph *g, int m, int n, int v, int *dist) /* For each i, set dist[i]=0 if there is a 3-path from v to i */ { set *gv,*gv1,*gv2; int v1,v2,v3; gv = GRAPHROW(g,v,m); for (v1 = -1; (v1 = nextelement(gv,m,v1)) >= 0; ) { gv1 = GRAPHROW(g,v1,m); for (v2 = -1; (v2 = nextelement(gv1,m,v2)) >= 0; ) { if (v2 == v) continue; gv2 = GRAPHROW(g,v2,m); for (v3 = -1; (v3 = nextelement(gv2,m,v3)) >= 0; ) if (v3 != v && v3 != v1) dist[v3] = 0; } } }
int girth(graph *g, int m, int n) /* Find the girth of graph g. 0 means acyclic. */ { int i,head,tail,v,w; int best,c,dw1; set *gw; #if MAXN int dist[MAXN],queue[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,dist,dist_sz); DYNALLOC1(int,queue,queue_sz,n,"girth"); DYNALLOC1(int,dist,dist_sz,n,"girth"); #endif best = n+1; for (v = 0; v < n; ++v) { for (i = 0; i < n; ++i) dist[i] = -1; queue[0] = v; dist[v] = 0; head = 0; tail = 1; while (head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); dw1 = dist[w] + 1; for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (dist[i] < 0) { dist[i] = dw1; queue[tail++] = i; } else if (dist[i] >= dist[w]) { c = dw1 + dist[i]; if (c < best) best = c; if ((c & 1) != 0 || c > best) break; } } if (i >= 0) break; } if (best == 3) return 3; } return (best > n ? 0 : best); }
static void dump_graph(graph *g, int n) { for (int i = 0; i < n; i++) { set *gv = GRAPHROW(g, i, MAXM); for (int j = 0; j < n; j++) { fputs(ISELEMENT(gv, j) ? "+" : ".", stderr); } fputs("\n", stderr); } }
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; }
boolean twocolouring(graph *g, int *colour, int m, int n) /* If g is bipartite, set colour[*] to 0 or 1 to indicate an example of 2-colouring and return TRUE. Otherwise return FALSE. Colour 0 is assigned to the first vertex of each component. */ { int i,head,tail,v,w,need; set *gw; #if MAXN int queue[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); #endif #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"twocolouring"); #endif for (i = 0; i < n; ++i) colour[i] = -1; for (v = 0; v < n; ++v) if (colour[v] < 0) { queue[0] = v; colour[v] = 0; head = 0; tail = 1; while (head < tail) { w = queue[head++]; need = 1 - colour[w]; gw = GRAPHROW(g,w,m); for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (colour[i] < 0) { colour[i] = need; queue[tail++] = i; } else if (colour[i] != need) return FALSE; } } } return TRUE; }
void findEdgeOrbits(GRAPH graph, ADJACENCY adj){ VERTEXPAIR edges[MAXN * (MAXN - 1)/2]; n = graph[0][0]; initNautyRelatedVariables(); translateGraphToNautyDenseGraph(graph, adj); int i, v, edgeCount = 0, edgeOrbitCount; setword *gv; //call Nauty so we have the automorphism group callNauty(); //build a list of all edges for(v = 0; v < n; v++){ gv = GRAPHROW(ng, v, m); for (i = -1; (i = nextelement(gv,m,i)) >= 0;){ if(v < i){ edges[edgeCount][0] = v; edges[edgeCount][1] = i; edgeCount++; } } } //using malloc to dynamically allocate the arrays on the heap //otherwise we might run out of stack space for large, dense graphs int *edgeOrbits = (int *) malloc(sizeof(int) * edgeCount); int *edgeOrbitSizes = (int *) malloc(sizeof(int) * edgeCount); //partition the edges into orbits determineEdgeOrbits(edges, edgeCount, edgeOrbits, edgeOrbitSizes, &edgeOrbitCount); fprintf(stderr, "Graph %d has %d edge orbit%s.\n", graphCount, edgeOrbitCount, edgeOrbitCount == 1 ? "" : "s"); int orbitCount = 0; for(i = 0; i < edgeCount; i++){ if(edgeOrbits[i] == i){ fprintf(stderr, "Orbit %d (representative %d - %d) contains %d edge%s.\n", ++orbitCount, edges[i][0] + 1, edges[i][1] + 1, edgeOrbitSizes[i], edgeOrbitSizes[i] == 1 ? "" : "s"); } } }
boolean isconnected(graph *g, int m, int n) /* Test if g is connected */ { int i,head,tail,w; set *gw; #if MAXN int queue[MAXN],visited[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,visited,visited_sz); #endif if (m == 1) return isconnected1(g,n); #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"isconnected"); DYNALLOC1(int,visited,visited_sz,n,"isconnected"); #endif for (i = 0; i < n; ++i) visited[i] = 0; queue[0] = 0; visited[0] = 1; head = 0; tail = 1; while (head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (!visited[i]) { visited[i] = 1; queue[tail++] = i; } } } return tail == n; }
boolean isautom(graphnau *g, permutation *perm, boolean digraph, int m, int n) { set *pg; int pos; set *pgp; int posp,i; for (pg = g, i = 0; i < n; pg += M, ++i) { pgp = GRAPHROW(g,perm[i],M); pos = (digraph ? -1 : i); while ((pos = nextelement(pg,M,pos)) >= 0) { posp = perm[pos]; if (!ISELEMENT(pgp,posp)) return FALSE; } } return TRUE; }
graph_info *graph_info_from_nauty(graph *g, int n) { graph_info *ret = malloc(sizeof(graph_info)); ret->n = n; ret->distances = malloc(n * n * sizeof(*ret->distances)); ret->k = malloc(n * sizeof(*ret->k)); int m = (n + WORDSIZE - 1) / WORDSIZE; ret->m = 0; //total number of edges for (int i = 0; i < n; i++) { ret->k[i] = 0; for (int j = 0; j < n; j++) { if(i == j) ret->distances[n*i + j] = 0; else if(ISELEMENT(GRAPHROW(g, i, m), j)) { ret->distances[n*i + j] = 1; ret->k[i]++; ret->m++; } else ret->distances[n*i + j] = GRAPH_INFINITY; } } ret->m /= 2; ret->max_k = 0; for (int i = 0; i < n; i++) if (ret->k[i] > ret->max_k) ret->max_k = ret->k[i]; floyd_warshall(*ret); ret->sum_of_distances = calc_sum(*ret); ret->diameter = calc_diameter(*ret); ret->nauty_graph = malloc(n * m * sizeof(graph)); ret->gcan = NULL; memcpy(ret->nauty_graph, g, n * m * sizeof(graph)); return ret; }
void find_dist2(graph *g, int m, int n, int v, int w, int *dist) /* Put in dist[0..n-1] the distance of each vertex from {v,w}. Vertices in a different component are given the distance n. */ { int i,head,tail,x; set *gx; #if MAXN int queue[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); #endif #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"isconnected"); #endif for (i = 0; i < n; ++i) dist[i] = n; queue[0] = v; queue[1] = w; dist[v] = dist[w] = 0; head = 0; tail = 2; while (tail < n && head < tail) { x = queue[head++]; gx = GRAPHROW(g,x,m); for (i = -1; (i = nextelement(gx,m,i)) >= 0;) { if (dist[i] == n) { dist[i] = dist[x] + 1; queue[tail++] = i; } } } }
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 diamstats(graph *g, int m, int n, int *radius, int *diameter) /* Find the radius and diameter. Both -1 if g is disconnected. We use an O(mn) algorithm, which is pretty disgraceful. */ { int v,i,head,tail,w; int ecc,diam,rad; set *gw; #if MAXN int queue[MAXN],dist[MAXN]; #else DYNALLSTAT(int,queue,queue_sz); DYNALLSTAT(int,dist,dist_sz); #endif /* if (m == 1) {diamstats1(g,n,radius,diameter); return; } */ #if !MAXN DYNALLOC1(int,queue,queue_sz,n,"isconnected"); DYNALLOC1(int,dist,dist_sz,n,"isconnected"); #endif diam = -1; rad = n; for (v = 0; v < n; ++v) { for (i = 0; i < n; ++i) dist[i] = -1; queue[0] = v; dist[v] = 0; head = 0; tail = 1; while (tail < n && head < tail) { w = queue[head++]; gw = GRAPHROW(g,w,m); for (i = -1; (i = nextelement(gw,m,i)) >= 0;) { if (dist[i] < 0) { dist[i] = dist[w] + 1; queue[tail++] = i; } } } if (tail < n) { *diameter = *radius = -1; return; } ecc = dist[queue[n-1]]; if (ecc > diam) diam = ecc; if (ecc < rad) rad = ecc; } *diameter = diam; *radius = rad; }
Nauty::Nauty(int vertices) { n_ = vertices; m_ = (n_ + WORDSIZE - 1)/WORDSIZE; //printf ("size of long = %d (%d)\nwordsize = %d\nn,m = %d,%d\n", // SIZEOF_LONG, sizeof (long), WORDSIZE, n_, m_); nauty_check (WORDSIZE, m_, n_, NAUTYVERSIONID); /// Apparently sizes are skewed on 64bit machines #define MULTIPLIER 2 G_ = (graph *) malloc(MULTIPLIER * m_ * n_ * sizeof(int)); lab_ = (int *) malloc(MULTIPLIER * n_ * sizeof(int)); ptn_ = (int *) malloc(MULTIPLIER * n_ * sizeof(int)); active_ = NULL; orbits_ = (int *) malloc(MULTIPLIER * n_ * sizeof(int)); options_ = (optionblk *) malloc(MULTIPLIER * sizeof(optionblk)); stats_ = (statsblk *) malloc(MULTIPLIER * sizeof(statsblk)); worksize_ = 100*m_; workspace_ = (setword *) malloc(MULTIPLIER * worksize_*sizeof(setword)); canonG_ = NULL; if (G_ == 0 || lab_ == 0 || ptn_ == 0 || orbits_ == 0 || options_ == 0 || stats_ == 0 || workspace_ == 0) assert(0); // Zero allocated memory memset(G_, 0, m_*n_*sizeof(int)); memset(lab_, 0, n_*sizeof(int)); memset(ptn_, 0, n_*sizeof(int)); memset(orbits_, 0, n_*sizeof(int)); memset(workspace_, 0, worksize_*sizeof(setword)); // Set the options you want options_->getcanon = FALSE; options_->digraph = FALSE; options_->writeautoms = FALSE; options_->writemarkers = FALSE; options_->defaultptn = TRUE; options_->cartesian = FALSE; options_->linelength = 78; options_->outfile = NULL; options_->userrefproc = NULL; options_->userautomproc = NULL; options_->userlevelproc = NULL; options_->usernodeproc = NULL; // options_->usertcellproc = NULL; options_->invarproc = NULL; options_->tc_level = 100; options_->mininvarlevel = 0; options_->maxinvarlevel = 1; options_->invararg = 0; options_->dispatch = &dispatch_graph; // Make an empty graph for (int j = 0; j < n_; j++) { set *gv = GRAPHROW(G_, j, m_); EMPTYSET(gv, m_); } vstat_ = new int[n_]; clearPartitions(); afp_ = NULL; }
static boolean seemsbad(char *s) /* Check graph string for apparent problem, if so, correct it */ { int i,j,k,m,n; char *p,x,pq; set *gj; long ii; int r,rr,topbit,nb,lastj; graph g[16]; if (s[0] != ':') return FALSE; /* not sparse6 */ n = graphsize(s); if (n != 2 && n != 4 && n != 8 && n != 16) return FALSE; m = 1; stringtograph(s,g,m); if (g[n-1] != bit[n-1]) return FALSE; if (g[n-2] == 0) return FALSE; g[n-1] = 0; p = s+2; for (i = n-1, nb = 0; i != 0 ; i >>= 1, ++nb) {} topbit = 1 << (nb-1); k = 6; x = 0; lastj = 0; for (j = 0; j < n; ++j) { gj = GRAPHROW(g,j,m); for (i = 0; i <= j; ++i) { if (ISELEMENT(gj,i)) { if (j == lastj) { x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } else { x = (x << 1) | 1; if (--k == 0) { p++; k = 6; x = 0; } if (j > lastj+1) { for (r = 0, rr = j; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } lastj = j; } for (r = 0, rr = i; r < nb; ++r, rr <<= 1) { if (rr & topbit) x = (x << 1) | 1; else x <<= 1; if (--k == 0) { p++; k = 6; x = 0; } } } } } if (k != 6) { if (k >= nb+1 && lastj == n-2 && n == (1<<nb)) { *p++ = BIAS6 + ((x << k) | ((1 << (k-1)) - 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; } } } } }
/* 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; } }