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;
}
示例#2
0
文件: naugroup.c 项目: 3ki5tj/nauty
int
allgroup2(grouprec *grp, void (*action)(permutation*,int,int*))
/* Call action(p,n,&abort) for every element of the group, including
   the identity.  The identity is always the first call.
   If action() stores a non-zero value in abort, group generation is
   aborted and the abort value is returned by this procedure.  If no
   non-zero value is ever returned in abort by action(), this
   procedure returns 0. */
{
    int i,depth,n,abort;

    depth = grp->depth;
    n = grp->n;

    DYNALLOC1(permutation,id,id_sz,n,"malloc");
    for (i = 0; i < n; ++i) id[i] = i;

    abort = 0;
    if (depth == 0)
    {
	(*action)(id,n,&abort);
	return abort;
    }

    DYNALLOC1(permutation,allp,allp_sz,n*depth,"malloc");

    groupelts2(grp->levelinfo,n,depth-1,action,NULL,allp,id,&abort);

    return abort;
}
示例#3
0
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);
        }
}
示例#4
0
文件: complg.c 项目: 3ki5tj/nauty
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;
	}
}
示例#5
0
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;
}
示例#6
0
文件: naugroup.c 项目: 3ki5tj/nauty
void
allgroup(grouprec *grp, void (*action)(permutation*,int))
/* Call action(p,n) for every element of the group, including the identity. 
   The identity is always the first call. */
{
    int i,depth,n;

    depth = grp->depth;
    n = grp->n;

    DYNALLOC1(permutation,id,id_sz,n,"malloc");
    for (i = 0; i < n; ++i) id[i] = i;

    if (depth == 0)
    {
	(*action)(id,n);
	return;
    }

    DYNALLOC1(permutation,allp,allp_sz,n*depth,"malloc");

    groupelts(grp->levelinfo,n,depth-1,action,NULL,allp,id);
}
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);
}
示例#8
0
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;
}
示例#9
0
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
}
示例#10
0
文件: blisstog.c 项目: 3ki5tj/nauty
static boolean
readblissgraph(FILE *f, sparsegraph *g)
/* Reads a graph from Bliss format into a sparse graph */
{
    int n,c;
    unsigned long ne,j;
    int haven;
    int i,v,w;
    int haveptn;
    DYNALLSTAT(vpair,elist,elist_sz);

    haven = 0;
    j = 0;
    while ((c = nextchar(f)) >= 0)
    {
	switch (c)
	{
	case 'c':
	    while ((c = getc(f)) != '\n' && c != EOF) {}
	    break;

	case 'p':
	    if (haven)
	    {
		fprintf(stderr,"Duplicate p line\n");
		exit(1);
	    }
	    if (fscanf(f," edge %d %lu",&n,&ne) != 2)
	    {
		fprintf(stderr,"Bad p line\n");
		return FALSE;
	    }
	    haven = 1;
            DYNALLOC1(vpair,elist,elist_sz,ne,"Alloc vpair");
	    break;

	case 'n':
	    if (!haven)
	    {
                fprintf(stderr,"Missing p line\n");
                return FALSE;
            }  
            if (fscanf(f,"%d%d",&w,&v) != 2 || w < 1 || w > n)
            {
                fprintf(stderr,"Bad n line\n");
                return FALSE;
            }
	    break;

	case 'e':
	    if (!haven || j == ne)
	    {
		fprintf(stderr,"Missing p line or too many e lines\n");
		return FALSE;
	    }
	    if (fscanf(f,"%d%d",&v,&w) != 2 || v < 1 || w < 1 || v > n || w > n)
	    {
		fprintf(stderr,"Bad e line\n");
		return FALSE;
	    }
	    elist[j].v = v-1; elist[j].w = w-1;
	    ++j;
	    break;

	default:
	    fprintf(stderr,"Unknown line %c\n",c);
	    return FALSE;
	}
    }

    if (j != ne)
    {
        fprintf(stderr,"Wrong number of e lines\n");
        exit(1);
    }

    SG_ALLOC(*g,n,2*ne,"SG_ALLOC");
    g->nv = n;
    g->nde = 2*ne;

    for (i = 0; i < n; ++i) g->d[i] = 0;
    for (j = 0; j < ne; ++j) 
    {
	++(g->d[elist[j].v]);
	++(g->d[elist[j].w]);
    }
    g->v[0] = 0;
    for (i = 1; i < n; ++i) g->v[i] = g->v[i-1] + g->d[i-1];
    for (i = 0; i < n; ++i) g->d[i] = 0;

    for (j = 0; j < ne; ++j) 
    {
	v = elist[j].v;
	w = elist[j].w;
        g->e[g->v[v]+(g->d[v])++] = w;
        g->e[g->v[w]+(g->d[w])++] = v;
    }

    return TRUE;
}
示例#11
0
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;
}
示例#12
0
void
writeperm(FILE *f, permutation *perm, boolean cartesian, int linelength, int n)
{
    register int i,k,l,curlen,intlen;
    char s[30];

#if !MAXN
    DYNALLOC1(permutation,workperm,workperm_sz,n,"writeperm");
#endif

    /* CONDNL(x) writes end-of-line and 3 spaces if x characters
       won't fit on the current line. */
#define CONDNL(x) if (linelength>0 && curlen+(x)>linelength)\
	          {putstring(f,"\n   ");curlen=3;}

    curlen = 0;
    if (cartesian)
    {
        for (i = 0; i < n; ++i)
        {
            intlen = itos(perm[i]+labelorg,s);
            CONDNL(intlen+1);
            PUTC(' ',f);
            putstring(f,s);
            curlen += intlen + 1;
        }
        PUTC('\n',f);
    }
    else
    {
        for (i = n; --i >= 0;) workperm[i] = 0;

        for (i = 0; i < n; ++i)
        {
            if (workperm[i] == 0 && perm[i] != i)
            {
                l = i;
                intlen = itos(l+labelorg,s);
                if (curlen > 3) CONDNL(2*intlen+4);
                PUTC('(',f);
                do
                {
                    putstring(f,s);
                    curlen += intlen + 1;
                    k = l;
                    l = perm[l];
                    workperm[k] = 1;
                    if (l != i)
                    {
                        intlen = itos(l+labelorg,s);
                        CONDNL(intlen+2);
                        PUTC(' ',f);
                    }
                }
                while (l != i);
                PUTC(')',f);
                ++curlen;
            }
        }

        if (curlen == 0) putstring(f,"(1)\n");
        else             PUTC('\n',f);
    }
}
示例#13
0
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;
	    }
    }
}
示例#14
0
文件: linegraphg.c 项目: 3ki5tj/nauty
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;
        }
    }
}