Example #1
0
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;
}
Example #2
0
static boolean
distinvar(graph *g, int *invar, int n1, int n2)
 /* make distance invariant/
    exit immediately FALSE if n-1 not maximal else exit TRUE
    Note: only invar[n1..n1+n2-1] set */
{
    int w,n;
    setword workset,frontier;
    setword sofar;
    int inv,d,v;

    n = n1 + n2;
    for (v = n-1; v >= n1; --v)
    {
        inv = 0;
        sofar = frontier = bit[v];
        for (d = 1; frontier != 0; ++d)
        {
            workset = 0;
            inv += POPCOUNT(frontier) ^ (0x57 + d);
            while (frontier)
            {
                w = FIRSTBITNZ(frontier);
                frontier &= ~bit[w];
                workset |= g[w];
            }
            frontier = workset & ~sofar;
            sofar |= frontier;
        }
        invar[v] = inv;
        if (v < n-1 && inv > invar[n-1]) return FALSE;
    }
    return TRUE;
}
Example #3
0
static boolean
hitinvar(graph *g, int *invar, int n)
/* make hitting invariant
 *    return FALSE if n-1 not maximal else return TRUE */
{
        setword x,y,z;
        int inv,i,v,d;

        for (v = n-1; v >= 0; --v)
        {
            inv = 0;
            x = y = g[v];
	    while (y)
	    {
		TAKEBIT(i,y);
		z = x & g[i];
		d = POPCOUNT(z);
		if (d > inv) inv = d;
	    }

            invar[v] = inv;
            if (v < n-1 && inv > invar[n-1]) return FALSE;
        }
        return TRUE;
}
Example #4
0
void
degstats(graph *g, int m, int n, unsigned long *edges, int *mindeg,
     int *mincount, int *maxdeg, int *maxcount, boolean *eulerian)
/* Compute degree-related graph properties.
   *edges = number of edges
   *mindeg, *mincount = minimum degree and how many there are
   *maxdeg, *maxcount = maximum degree and how many there are
   *eulerian = whether the graph has only even degrees
*/
{
    setword *pg;
    int i,j,d,dor;
    int mind,mindc,maxd,maxdc;
    unsigned long ned;

    mind = n;
    mindc = 0;
    maxd = 0;
    maxdc = 0;
    ned = 0;
    dor = 0;

    pg = (setword*)g;
    for (i = 0; i < n; ++i)
    {
        d = 0;
        for (j = 0; j < m; ++j, ++pg)
            if (*pg) d += POPCOUNT(*pg);

        if (d == mind)
            ++mindc;
        else if (d < mind)
        {
            mind = d;
            mindc = 1;
        }

        if (d == maxd)
            ++maxdc;
        else if (d > maxd)
        {
            maxd = d;
            maxdc = 1;
        }

        dor |= d;
        ned += d;
    }

    *mindeg = mind;
    *mincount = mindc;
    *maxdeg = maxd;
    *maxcount = maxdc;
    *edges = ned / 2;
    *eulerian = (dor & 1) == 0;
}
Example #5
0
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;
}
Example #6
0
void
commonnbrs(graph *g, int *minadj, int *maxadj, int *minnon, int *maxnon,
       int m, int n)
/* Count the common neighbours of pairs of vertices, and give the minimum
   and maximum for adjacent and non-adjacent vertices.  Undirected only.
   Null minimums are n+1 and null maximums are -1.
*/
{
    int j,k;
    int mina,maxa,minn,maxn;
    int cn;
    set *gi,*gj;
    setword w;

    mina = minn = n+1;
    maxa = maxn = -1;

    for (j = 0, gj = g; j < n; ++j, gj += m)
    for (gi = g; gi != gj; gi += m)
    {
	cn = 0;
	for (k = 0; k < m; ++k)
	{
	    w = gi[k] & gj[k];
	    if (w) cn += POPCOUNT(w);
	}

	if (ISELEMENT(gi,j))
	{
	    if (cn < mina) mina = cn;
	    if (cn > maxa) maxa = cn;
	}
	else
	{
	    if (cn < minn) minn = cn;
	    if (cn > maxn) maxn = cn;
	}
    }

    *minadj = mina;
    *maxadj = maxa;
    *minnon = minn;
    *maxnon = maxn;
}
Example #7
0
boolean
isconnected1(graph *g, int n)
/* test if g is connected (m=1) */
{
    setword seen,expanded,toexpand;
    int i;

    seen = bit[0];
    expanded = 0;

    while ((toexpand = (seen & ~expanded)) != 0)
    {
        i = FIRSTBITNZ(toexpand);
        expanded |= bit[i];
        seen |= g[i];
    }

    return  POPCOUNT(seen) == n;
}
Example #8
0
long
pathcount1(graph *g, int start, setword body, setword last)
/* Number of paths in g starting at start, lying within body and
   ending in last.  {start} and last should be disjoint subsets of body. */
{
    long count;
    setword gs,w;
    int i;

    gs = g[start];
    w = gs & last;
    count = POPCOUNT(w);

    body &= ~bit[start];
    w = gs & body;
    while (w)
    {
	TAKEBIT(i,w);
	count += pathcount1(g,i,body,last&~bit[i]);
    }

    return count;
}
Example #9
0
static boolean
accept2(graph *g, int n2, int x, graph *gx, int *deg, boolean nuniq)
/* decide if n in theta(g+x) -- version for n+1 == maxn */
{
    int i,n;
    int lab[MAXN],ptn[MAXN],orbits[MAXN];
    int degx[MAXN],invar[MAXN];
    setword vmax,gv;
    int qn,qv;
    int count[MAXN];
    int xw;
    int nx,numcells,code;
    int degn,i0,i1,j,j0,j1;
    set active[MAXM];
    statsblk stats;
    static DEFAULTOPTIONS_GRAPH(options);
    setword workspace[50];

#ifdef INSTRUMENT
    ++a2calls;
    if (nuniq) ++a2uniq;
#endif
    n = n1 + n2;
    nx = n + 1;
    for (i = 0; i < n; ++i)
    {
        gx[i] = g[i];
        degx[i] = deg[i];
    }
    gx[n] = 0;
    degx[n] = degn = XPOPCOUNT(x);

    xw = x;
    while (xw)
    {
        i = XNEXTBIT(xw);
        xw &= ~xbit[i];
        gx[i] |= bit[n];
        gx[n] |= bit[i];
        ++degx[i];
    }
#ifdef PRUNE1
    if (PRUNE1(gx,degx,n1,n2+1,maxn2)) return FALSE;
#endif

    if (nuniq)
    {
#ifdef INSTRUMENT
        ++a2succs;
#endif
#ifdef PRUNE2
        if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
#endif
        if (canonise) makecanon(gx,gcan,n1,n2+1);
        return TRUE;
    }

    for (i = 0; i < n1; ++i)
    {
        lab[i] = i;
        ptn[i] = 1;
    }
    ptn[n1-1] = 0;

    i0 = n1;
    i1 = n;
    for (i = n1; i < nx; ++i)
    {
        if (degx[i] == degn) lab[i1--] = i;
        else                 lab[i0++] = i;
        ptn[i] = 1;
    }

    ptn[n] = 0;

    if (i0 == n1)
    {
        numcells = 2;
        active[0] = bit[0] | bit[n1];

        if (!distinvar(gx,invar,n1,n2+1)) return FALSE;
        qn = invar[n];
        j0 = n1;
        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 > n1)
        {
            if (j0 == n)
            {
#ifdef INSTRUMENT
                ++a2succs;
#endif
#ifdef PRUNE2
                if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
#endif
                if (canonise) makecanon(gx,gcan,n1,n2+1);
                return TRUE;
            }
            ptn[j1] = 0;
            ++numcells;
            active[0] |= bit[j0];
        }
    }
    else
    {
        numcells = 3;
        ptn[i1] = 0;
        active[0] = bit[0] | bit[n1] | bit[i1+1];

        vmax = 0;
        j = MAXN;
        for (i = 0; i < n1; ++i)
            if (degx[i] < j && degx[i] > 0)
            {
                j = degx[i];
                vmax = bit[i];
            }
            else if (degx[i] == j)
                vmax |= bit[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
#ifdef PRUNE2
                if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
#endif
                if (canonise) makecanon(gx,gcan,n1,n2+1);
                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;
    else if (code > 0 || numcells >= nx-4)
    {
#ifdef INSTRUMENT
        ++a2succs;
#endif
#ifdef PRUNE2
        if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
#endif
        if (canonise) makecanon(gx,gcan,n1,n2+1);
        return TRUE;
    }

    options.writemarkers = FALSE;
    options.writeautoms = FALSE;
    options.getcanon = 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
#ifdef PRUNE2
    if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
#endif
        if (canonise) makecanon(gx,gcan,n1,n2+1);
        return TRUE;
    }
    else
        return FALSE;
}
Example #10
0
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;
                }
            }
        }
    }
}
Example #11
0
int
static main(int argc, char *argv[])
{
	int i,j,bad;
	setword w,ww;

	printf("NAUTYVERSION=%s NAUTYVERSIONID=%d\n",
		NAUTYVERSION,NAUTYVERSIONID);
	printf("MAXN=%d MAXM=%d WORDSIZE=%d NAUTY_INFINITY=%d\n",
		MAXN,MAXM,WORDSIZE,NAUTY_INFINITY);
	printf("sizes: short=%d int=%d long=%d double=%d\n",
		(int)sizeof(short),(int)sizeof(int),(int)sizeof(long),
		(int)sizeof(double));
	printf("sizes: boolean=%d setword=%d\n",
		(int)sizeof(boolean),(int)sizeof(setword));
        printf("CLZ=%d,%d,%d\n",HAVE_CLZ,HAVE_CLZL,HAVE_CLZLL);

#if SIZEOF_LONGLONG > 0
	printf("sizeof(long long)=%d\n",sizeof(long long));
#endif

	printf("defined:");
#ifdef __STDC__
	printf(" __STDC__");
#endif
#ifdef BIGNAUTY
	printf(" BIGNAUTY(obsolete!)");
#endif
#ifdef SYS_UNIX
	printf(" SYS_UNIX");
#endif
#ifdef SYS_CRAY
        printf(" SYS_CRAY");
#endif
#ifdef SETWORD_SHORT
	printf(" SETWORD_SHORT");
#endif
#ifdef SETWORD_INT
	printf(" SETWORD_INT");
#endif
#ifdef SETWORD_LONG
	printf(" SETWORD_LONG");
#endif
#ifdef SETWORD_LONGLONG
	printf(" SETWORD_LONGLONG");
#endif
	printf("\n");

	bad = 0;

	if (8*sizeof(setword) != WORDSIZE)
	{
	    printf("\n ***** NOTE:  WORDSIZE mismatch *****\n\n");
	    ++bad;
	}

	for (i = 0; i < WORDSIZE; ++i)
	{
	    w = ALLMASK(i);
	    if (POPCOUNT(w) != i)
	    {
		printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i);
		++bad;
	    }
	}

	for (i = 0; i < WORDSIZE; ++i)
        {
            w = BITMASK(i);
            if (POPCOUNT(w) != WORDSIZE-i-1)
            {
                printf("\n ***** POPCOUNT(BITMASK) error %d *****\n\n",i);
                ++bad;
            }
        }

	for (i = 0; i < WORDSIZE; ++i)
	    if (POPCOUNT(ALLMASK(i)) != i)
	    {
		printf("\n ***** POPCOUNT(ALLMASK) error %d *****\n\n",i);
		++bad;
	    }

	for (i = 0; i < WORDSIZE; ++i)
            if (FIRSTBIT(BITT[i]) != i)
	    {
		printf("\n ***** FIRSTBIT(BITT) error %d *****\n\n",i);
		++bad;
	    }

	if (FIRSTBIT((setword)0) != WORDSIZE)
	{
	    printf("\n ***** FIRSTBIT(0) error *****\n\n");
	    ++bad;
	}
	
	for (i = 0; i < WORDSIZE; ++i)
            if (POPCOUNT(BITT[i]) != 1)
	    {
                printf("\n ***** POPCOUNT(BITT) error %d *****\n\n",i);
		++bad;
	    }

	for (i = 0; i < WORDSIZE; ++i)
	{
	    w = 0;
	    for (j = 1; j <= WORDSIZE; ++j)
	    {
		w |= BITT[(j*97+i)%WORDSIZE];
		if (POPCOUNT(w) != j)
		{
		    printf("\n ***** POPCOUNT(w) error %d %d *****\n\n",i,j);
		    ++bad;
		}
	    }
	}

	if (!bad) printf("\nNo errors found\n");
	else      printf("\nXXXXXXX %d errors found XXXXXXX\n",bad);

	exit(0);
} 
Example #12
0
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;
}
Example #13
0
int
conncontent(graph *g, int m, int n)
/* number of connected spanning subgraphs with an even number
   of edges minus the number with an odd number of edges */
{
    graph h[WORDSIZE];
    setword gj;
    int i,j,v1,v2,x,y;
    int minv,mindeg,deg,goodv;
    long ne;
    
    if (m > 1) ABORT("conncontent only implemented for m=1");

 /* First handle tiny graphs */

    if (n <= 3)
    {
	if (n == 1) return 1;
	if (n == 2) return (g[0] ? -1 : 0);
	if (!g[0] || !g[1] || !g[2]) return 0;    /* disconnected */
	if (g[0]^g[1]^g[2]) return 1;             /* path */
	return 2;                                 /* triangle */
    }

 /* Now compute
      ne = number of edges
      mindeg = minimum degree
      minv = a vertex of minimum degree
      goodv = a vertex with a clique neighbourhood (-1 if none)
 */

    mindeg = n;
    ne = 0;
    goodv = -1;
    for (j = 0; j < n; ++j)
    {
	gj = g[j];
	deg = POPCOUNT(gj);
	ne += deg;
	if (deg < mindeg)
	{
	    mindeg = deg;
	    minv = j;
            if (deg == 1) goodv = j;
	}
	if (deg >= 3 && deg <= 4 && goodv < 0)
	{
	    while (gj)
	    {
		TAKEBIT(i,gj);
		if (gj & ~g[i]) break;
	    }
	    if (!gj) goodv = j;
	}
    }
    ne /= 2;

/* Cases of isolated vertex or tree */

    if (mindeg == 0) return 0;

#if 0
    if (mindeg == 1 && ne == n-1)
    {
	if (isconnected1(g,n)) return ((n&1) ? 1 : -1);
	else		       return 0;
    }
#endif

/* Cases of clique and near-clique */

    if (mindeg == n-1)
    {
	j = -1;
	for (i = 2; i < n; ++i) j *= -i;
        return j;
    }

    if (mindeg == n-2 && n < 16)
    {
	if (!knm_computed)
	{
	    knm_computed = TRUE;
	    knm[1][0] = 1;
	    for (i = 2; i < 16; ++i)
	    {
		knm[i][0] = -knm[i-1][0] * (i-1);
		for (j = 1; j+j <= i; ++j)
		    knm[i][j] = knm[i][j-1] + knm[i-1][j-1];
	    }
	}
	return knm[n][(n*n-n)/2-ne];
    }

/*  Case of vertex with clique neighbourhood */

    if (goodv >= 0)
    {
	delete1(g,h,goodv,n);
	return -POPCOUNT(g[goodv]) * conncontent(h,m,n-1);
    }

/* Case of minimum degree 2 */

    if (mindeg == 2)
    {
	x = FIRSTBIT(g[minv]);
	y = FIRSTBIT(g[minv]^bit[x]);
	if (x > minv) --x;
	if (y > minv) --y;
	delete1(g,h,minv,n);
	v1 = conncontent(h,m,n-1);
	if (h[x] & bit[y]) return -2*v1;   /* adjacent neighbours */

	h[x] |= bit[y];
	h[y] |= bit[x];
	v2 = conncontent(h,m,n-1);
	return -v1 - v2;
    }

/* Case of more than 2/3 dense but not complete */

    if (3*ne > n*n-n) 
    {
	j = FIRSTBIT(g[minv] ^ bit[minv] ^ ALLMASK(n));   /* non-neighbour */

	g[minv] ^= bit[j];
        g[j] ^= bit[minv];
        v1 = conncontent(g,m,n);
        g[minv] ^= bit[j];
        g[j] ^= bit[minv];

        contract1(g,h,minv,j,n);
        v2 = conncontent(h,m,n-1);
    
        return v1 + v2;
    }
 
/* All remaining cases */

    j = FIRSTBIT(g[minv]);     /* neighbour */

    g[minv] ^= bit[j];
    g[j] ^= bit[minv];
    v1 = conncontent(g,m,n);
    g[minv] ^= bit[j];
    g[j] ^= bit[minv];
    
    contract1(g,h,minv,j,n);
    v2 = conncontent(h,m,n-1);

    return v1 - v2;
}
Example #14
0
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);
}