Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/grape/nauty2_8_6/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 6.8.2025 mit Größe 33 kB image not shown  

Quelle  twohamg.c   Sprache: C

 
/* twohamg.c  */

#define USAGE "twohamg [-sgvq] [-L#] [infile [outfile]]"

#define HELPTEXT \
" Partition quartic graphs into two hamiltonian cycles.\n\
  Output those which cannot be partitioned.\n\
\n\
    -s  force output to sparse6 format\n\
    -g  force output to graph6 format\n\
        If neither -s or -g are given, the output format is\n\
        determined by the header orif there is none, by the\n\
        format of the first input graph. Also see -S. \n\
\n\
    The output file will have a header if and only if the input file does.\n\
\n\
    -p  Read a cubic graph and use its prism. Vertex i of the input becomes\n\
           vertices 2*i,2*i+1 in the prism.\n\
    -x  Test for decompositions using each 2-path\n\
    -X  As -x but only output if two 2-paths are missed at some vertex\n\
    -y  Test for decompositions using each non-triangular 3-path\n\
    -tWith -x and -X, consider only paths with center #\n\
        With -y, consider only paths starting at #\n\
    -Y  With -p, only consider paths whose central edge is vertical\n\
    -v  Give a partition for those graphs who have one and a message\n\
        for those which don't. With -x, list exceptional 2-paths.\n\
    -LLimit to 1000*iterations; write with message if timeout.\n\
        Graphs that time out are written to the output.\n\
\n\
    -q  suppress auxiliary information\n"

#define DEBUG 0
#define FISHTAIL 1   /* Whether to use fish-tail rule */

/*************************************************************************/

#include "gtools.h"

#define WHITE 0  /* unknown colour */
#define BLUE 1
#define RED 2

#define NO 0
#define YES 1
#define TIMEOUT 2
#define NOTHING 3

typedef struct addrval_struct
{
    int *addr;
    int value;
} addrval;

static long seed = 314159265;

/* valstack is a stack to save and restore degrees, farends, and colours */
DYNALLSTAT(addrval,valstack,valstack_sz);
static addrval *valstacktop;
#define SETVAL(ad,val) { valstacktop->addr = &(ad); \
     valstacktop->value = ad; ++valstacktop; ad = val; }
#define UNSETVAL { --valstacktop; *(valstacktop->addr) = valstacktop->value; }

typedef struct p4
{
    int e1,e2,e3;
    int v1,v2,v3,v4;
    boolean ok;
} p4;

DYNALLSTAT(int,bluefarend,bluefarend_sz);   /* Parallel to sg.v */
DYNALLSTAT(int,redfarend,redfarend_sz);   /* Parallel to sg.v */
DYNALLSTAT(int,eno,eno_sz);         /* Edge numbers, parallel to sg.e */
DYNALLSTAT(int,cross,cross_sz);         /* Parallel to sg.eno */
DYNALLSTAT(int,colour,colour_sz);   /* indexed by edge number */
DYNALLSTAT(int,v1,v1_sz); 
DYNALLSTAT(int,v2,v2_sz); 
DYNALLSTAT(int,bluedeg,bluedeg_sz); /* Parallel to sg.v */
DYNALLSTAT(int,reddeg,reddeg_sz);   /* Parallel to sg.v */
DYNALLSTAT(int,beste,beste_sz);  /* List of possible best edges */
DYNALLSTAT(p4,p4list,p4list_sz);  /* List of non-triangular p4s */

/* vstack is a stack of interesting vertices; onstack says whether a
   vertex is on vstack so that we don't put it there twice */

DYNALLSTAT(int,vstack,vstack_sz);
DYNALLSTAT(boolean,onstack,onstack_sz);
static int *top;
#define PUSH(v) if (!onstack[v]) { *(top++) = (v); onstack[v] = TRUE; }
#define POP(v) { v = *(--top); onstack[v] = FALSE; }
#define STACKISEMPTY (top == vstack)

static nauty_counter nodes,limit,totallimit;
static nauty_counter locallimit[]
  = {5,7,10,20,30,40,50,60,70,100,200,400,600,1000,2000,4000,8000,
     20000,50000,100000,200000,5000000,0};
#define NUMLIMITS (sizeof(locallimit)/sizeof(locallimit[0]))
static nauty_counter nphases[100];  /* Must be greater than NUMLIMITS */
static nauty_counter ntimeouts;

/**************************************************************************/

static void
makeprism_sg(sparsegraph *sg, sparsegraph *sh)
/* Make the cartesian product sh = sg x K2.
   sh must be initialized. */

{
    size_t *v,*vv,vi,vvi;
    int *d,*dd,*e,*ee;
    int i,j,n;

    SG_VDE(sg,v,d,e);
    n = sg->nv;

    SG_ALLOC(*sh,2*sg->nv,2*(n+sg->nde),"makeprism_sg");
    sh->nv = 2*n;
    sh->nde = 2*(n+sg->nde);
    SG_VDE(sh,vv,dd,ee);
 
    vvi = 0;
    for (i = 0; i < n; ++i)
    {
        vi = v[i];
        dd[2*i] = dd[2*i+1] = d[i] + 1;
        vv[2*i] = vvi;
        for (j = 0; j < d[i]; ++j) ee[vvi++] = 2*e[vi++];
        ee[vvi++] = 2*i+1;
        vi = v[i];
        vv[2*i+1] = vvi;
        for (j = 0; j < d[i]; ++j) ee[vvi++] = 2*e[vi++]+1;
        ee[vvi++] = 2*i;
    }
}

/**************************************************************************/

static void
dumpdata(int id, int nblue, int nred, int n)
{
    int i;

    printf("%d: nblue=%d nred=%d -------------------------\n",id,nblue,nred);

#if DEBUG > 1
    for (i = 0; i < n; ++i)
    {
        printf("%2d: ",i);
        for (j = 0; j < 4; ++j)
            printf(" %2d%c",eno[4*i+j],"wbr"[colour[eno[4*i+j]]]);
        printf(" b=%d r=%d bfe=%d rfe=%d\n",
            bluedeg[i],reddeg[i],bluefarend[i],redfarend[i]);
    }
#endif
}

/**************************************************************************/

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
}

/**************************************************************************/

static void
initialise_colouring(int n)
/* Make all edges white */
{
    int i;

    for (i = 0; i < 2*n; ++i) colour[i] = WHITE;

    for (i = 0; i < n; ++i)
    {
        bluefarend[i] = i;
        redfarend[i] = i;
        bluedeg[i] = 0;
        reddeg[i] = 0;
        onstack[i] = FALSE;
    }    

    top = vstack;
    valstacktop = valstack;
}

/**************************************************************************/

static boolean
makeblue(int edge, boolean lastok)
/* Colour WHITE edge BLUE, return success. 
   lastok indicates if it is ok to add the final blue edge */

{
    int w1,w2,f1,f2;

    w1 = v1[edge];
    w2 = v2[edge];
    if (bluedeg[w1] == 2 || bluedeg[w2] == 2) return FALSE;

    f1 = bluefarend[w1];
    f2 = bluefarend[w2];
    if (f1 == w2 && !lastok) return FALSE;

    SETVAL(colour[edge],BLUE);
    SETVAL(bluedeg[w1],bluedeg[w1]+1);
    SETVAL(bluedeg[w2],bluedeg[w2]+1);
    SETVAL(bluefarend[f1],f2);
    SETVAL(bluefarend[f2],f1);
    PUSH(w1);
    PUSH(w2);
    PUSH(f1);
    // PUSH(f2);   not sure this one is needed

    return TRUE;
}

/**************************************************************************/

static boolean
makered(int edge, boolean lastok)
/* Colour WHITE edge RED, return success. 
   lastok indicates if it is ok to add the final red edge */

{
    int w1,w2,f1,f2;

    w1 = v1[edge];
    w2 = v2[edge];
    if (reddeg[w1] == 2 || reddeg[w2] == 2) return FALSE;

    f1 = redfarend[w1];
    f2 = redfarend[w2];
    if (f1 == w2 && !lastok) return FALSE;

    SETVAL(colour[edge],RED);
    SETVAL(reddeg[w1],reddeg[w1]+1);
    SETVAL(reddeg[w2],reddeg[w2]+1);
    SETVAL(redfarend[f1],f2);
    SETVAL(redfarend[f2],f1);
    PUSH(w1);
    PUSH(w2);
    PUSH(f1);
    // PUSH(f2);   not sure this one is needed

    return TRUE;
}

/**************************************************************************/

static boolean
propagate(int n, int *e, int *nblue, int *nred)
/* Look at active vertices and propagate colourings */
{
    int i,j,v,w;

    while (!STACKISEMPTY)
    {
        POP(v);

        if (reddeg[v] == 2 && bluedeg[v] < 2)
        {
            for (i = 0; i < 4; ++i)
            {
                j = eno[4*v+i];
                if (colour[j] == WHITE)
                {
                    if (!makeblue(j,*nblue==n-1)) return FALSE;
                    ++*nblue;
                }
            }
        }
        else if (bluedeg[v] == 2 && reddeg[v] < 2)
        {
            for (i = 0; i < 4; ++i)
            {
                j = eno[4*v+i];
                if (colour[j] == WHITE)
                {
                    if (!makered(j,*nred==n-1)) return FALSE;
                    ++*nred;
                }
            }
        }

        if (bluedeg[v] == 1)
        {
            w = bluefarend[v];
            for (i = 0; i < 4; ++i)
                if (e[4*v+i] == w) break;
            if (i < 4)
            {
                j = eno[4*v+i];
                if (colour[j] == WHITE)
                {
                    if (*nblue == n-1)
                    {
                        if (!makeblue(j,TRUE)) return FALSE;
                        ++*nblue;
                    }
                    else
                    {
                        if (!makered(j,*nred==n-1)) return FALSE;
                        ++*nred;
                    }
                }
            }
        }

        if (reddeg[v] == 1)
        {
            w = redfarend[v];
            for (i = 0; i < 4; ++i)
                if (e[4*v+i] == w) break;
            if (i < 4)
            {
                j = eno[4*v+i];
                if (colour[j] == WHITE)
                {
                    if (*nred == n-1)
                    {
                        if (!makered(j,TRUE)) return FALSE;
                        ++*nred;
                    }    
                    else
                    {
                        if (!makeblue(j,*nblue==n-1)) return FALSE;
                        ++*nblue;
                    }
                }
            }
        }
    }

    return TRUE;
}

/**************************************************************************/

static int
fishtail(int n, int *nblue, int *nred)
/* Try to colour edges by the fishtail method
   Return NO (contradiction), YES (did some good), or NOTHING.  */

{
    int i,j;
    int e1,w1,e2,w2,e3,w3;
    int edge,col;
    int ans;

    ans = NOTHING;

    for (i = 0; i < n; ++i)
    {
        edge = -1;

        if (reddeg[i] == 1 && bluedeg[i] == 0 && *nblue < n-2)
        {
            j = 4*i;
            if (colour[eno[j]] != WHITE) ++j;
            e1 = eno[j];
            w1 = (v1[e1] == i ? v2[e1] : v1[e1]);
            ++j;
            if (colour[eno[j]] != WHITE) ++j;
            e2 = eno[j];
            w2 = (v1[e2] == i ? v2[e2] : v1[e2]);
            ++j;
            if (colour[eno[j]] != WHITE) ++j;
            e3 = eno[j];
            w3 = (v1[e3] == i ? v2[e3] : v1[e3]);

            if (bluedeg[w1] == 1 && bluefarend[w1] == w2)
            {
                edge = e3;
                col = BLUE;
            }
            else if (bluedeg[w1] == 1 && bluefarend[w1] == w3)
            {
                edge = e2;
                col = BLUE;
            }
            else if (bluedeg[w2] == 1 && bluefarend[w2] == w3)
            {
                edge = e1;
                col = BLUE;
            }
        }
        else if (reddeg[i] == 0 && bluedeg[i] == 1 && *nred < n-2)
        {
            j = 4*i;
            if (colour[eno[j]] != WHITE) ++j;
            e1 = eno[j];
            w1 = (v1[e1] == i ? v2[e1] : v1[e1]);
            ++j;
            if (colour[eno[j]] != WHITE) ++j;
            e2 = eno[j];
            w2 = (v1[e2] == i ? v2[e2] : v1[e2]);
            ++j;
            if (colour[eno[j]] != WHITE) ++j;
            e3 = eno[j];
            w3 = (v1[e3] == i ? v2[e3] : v1[e3]);

            if (reddeg[w1] == 1 && redfarend[w1] == w2)
            {
                edge = e3;
                col = RED;
            }
            else if (reddeg[w1] == 1 && redfarend[w1] == w3)
            {
                edge = e2;
                col = RED;
            }
            else if (reddeg[w2] == 1 && redfarend[w2] == w3)
            {
                edge = e1;
                col = RED;
            }
        }
        if (edge >= 0)
        {
            if (col == BLUE)
            {
                if (!makeblue(edge,*nblue == n-1)) return NO;
                ++*nblue;
            }
            else
            {
                if (!makered(edge,*nred == n-1)) return NO;
                ++*nred;
            }
            ans = YES;
#if DEBUG
            printf("Fishtail: %d=(%d-%d) -> %c\n",
                               edge,v1[edge],v2[edge],"wbr"[col]);
#endif
        }
    }

    return ans;
}

/**************************************************************************/

static int
searchnode(int level, int n, int *e, int nblue, int nred)
{
    boolean ok;
    int i,status,nbest;
    addrval *valptr;
    int best,score,bestscore;
    long ran;
     
    ok = propagate(n,e,&nblue,&nred);

#if DEBUG
    if (ok) dumpdata(level,nblue,nred,n);
    else { printf("FAIL\n"); return NO; }
#else
    if (!ok) return NO;
#endif

    if (nblue == n && nred == n) return YES;

#if FISHTAIL
    status = fishtail(n,&nblue,&nred);
    if (status == NO) return NO;
    if (status == YES) return searchnode(level+1,n,e,nblue,nred);
#endif

    valptr = valstacktop;

    bestscore = -1;
    nbest = 0;
    for (i = 0; i < 2*n; ++i)
        if (colour[i] == WHITE)
        {
            score = (bluedeg[v1[i]] == 1) + (bluedeg[v2[i]] == 1) +
                    (reddeg[v1[i]] == 1) + (reddeg[v2[i]] == 1);
            if (score > bestscore)
            {
                bestscore = score;
                beste[0] = i;
                nbest = 1;
            }
            else if (score == bestscore)
                beste[nbest++] = i;
        }

    if (bestscore == 0 && nred + nblue > 0)
        return FALSE;   /* Disconnected */

    ran = KRAN(2*nbest);
    best = beste[ran/2];

    if ((ran&1))
    {
        if (makeblue(best,nblue==n-1))
        {
#if DEBUG
            printf(" setting %d(%d-%d) blue\n",best,v1[best],v2[best]);
#endif
            status = searchnode(level+1,n,e,nblue+1,nred);
            if (status != NO) return status;
            while (valstacktop > valptr) UNSETVAL;
        }

        if (++nodes == limit) return TIMEOUT;

        if (makered(best,nred==n-1))
        {
#if DEBUG
            printf(" setting %d(%d-%d) red\n",best,v1[best],v2[best]);
#endif
            status = searchnode(level+1,n,e,nblue,nred+1);
            if (status != NO) return status;
            while (valstacktop > valptr) UNSETVAL;
        }
    }
    else
    {
        if (makered(best,nred==n-1))
        {
#if DEBUG
            printf(" setting %d(%d-%d) red\n",best,v1[best],v2[best]);
#endif
            status = searchnode(level+1,n,e,nblue,nred+1);
            if (status != NO) return status;
            while (valstacktop > valptr) UNSETVAL;
        }

        if (++nodes == limit) return TIMEOUT;

        if (makeblue(best,nblue==n-1))
        {
#if DEBUG
            printf(" setting %d(%d-%d) blue\n",best,v1[best],v2[best]);
#endif
            status = searchnode(level+1,n,e,nblue+1,nred);
            if (status != NO) return status;
            while (valstacktop > valptr) UNSETVAL;
        }
    }

    return NO;
}

/**************************************************************************/

static int
dispatchsearch(int n, int *e, int nblue, int nred)
/* Multiple tries at solution */
{
    int i,status;
    addrval *valptr;
    boolean ok;
    nauty_counter remaininglimit;

    ok = propagate(n,e,&nblue,&nred);

#if DEBUG
    if (ok) dumpdata(0,nblue,nred,n);
    else { printf("FAIL\n"); ++nphases[0]; return NO; }
#else
    if (!ok) { ++nphases[0]; return NO; }
#endif

    valptr = valstacktop;

    remaininglimit = totallimit;

    for (i = 0; i < NUMLIMITS; ++i)
    {
        if (totallimit > 0)
        {
            limit = locallimit[i];
            if (limit == 0 || limit > remaininglimit) limit = remaininglimit;
            remaininglimit -= limit;
            if (limit == 0) limit = 1;
        }
        else
            limit = locallimit[i];

        nodes = 0;

        status = searchnode(1,n,e,nblue,nred);
        if (status != TIMEOUT)
        {
            ++nphases[i+1];
            return status;
        }
        while (valstacktop > valptr) UNSETVAL;
    }
    
    ++ntimeouts;
    return TIMEOUT;
}

/**************************************************************************/

static int
isdecomposable(sparsegraph sg, int *ham1, int *ham2)
/* Test if sg is decomposable as two hamiltonian cycles */
{
    int nblue,nred,n,e0,status;
    int i0,i,j,lastv,laste;

    n = sg.nv;
    initialise_g(n,sg.e);
    initialise_colouring(n);

    e0 = KRAN(2*n);

    nblue = nred = 0;
    if (!makeblue(e0,nblue==n-1))   /* make edge e0 blue */
        return NO;
    ++nblue;

#if DEBUG
    printf(" setting %d(%d-%d) blue\n",e0,v1[0],v2[0]);
#endif

    // status = searchnode(1,n,sg.e,nblue,nred);
    status = dispatchsearch(n,sg.e,nblue,nred);

    if (status != YES) return status;

    if (!ham1 || !ham2) return YES;

    for (i0 = 0; colour[i0] != BLUE; ++i0) {} 
    ham1[0] = v1[i0];
    laste = i0;
    lastv = ham1[1] = v2[i0];
    for (i = 2; i < n; ++i)
    {
        for (j = 0; j < 4; ++j)
            if (eno[4*lastv+j] != laste && colour[eno[4*lastv+j]] == BLUE)
                break;
        laste = eno[4*lastv+j];
        lastv = ham1[i] = (v1[laste] == lastv ? v2[laste] : v1[laste]);
    }

    for (i0 = 0; colour[i0] != RED; ++i0) {}
    ham2[0] = v1[i0];
    laste = i0;
    lastv = ham2[1] = v2[i0];
    for (i = 2; i < n; ++i)
    {
        for (j = 0; j < 4; ++j)
            if (eno[4*lastv+j] != laste && colour[eno[4*lastv+j]] == RED)
                break;
        laste = eno[4*lastv+j];
        lastv = ham2[i] = (v1[laste] == lastv ? v2[laste] : v1[laste]);
    }

    return YES;
}

/**************************************************************************/

static int
iscrossdecomposable(sparsegraph sg, int vertex)
/* Test if sg is decomposable as two hamiltonian cycles
   in all ways through each vertex (or the given vertex if it
   is >= 0.  Details left in cross[].
   Return -1: not decomposable at all
           0: misses some 2-paths including two at some vertices
           1: misses some 2-paths but at most one per vertex
           2: fully decomposable
           3: timeout
*/

{
    int i,j,k,l,n,c;
    int ans,status;
    int imin,imax;

    n = sg.nv;
    DYNALLOC1(int,cross,cross_sz,4*n,"malloc");

    if (vertex >= n) gt_abort(">E vertex given to -t is too large");

    for (i = 0; i < 4*n; ++i) cross[i] = 0;

    status = isdecomposable(sg,FALSE,FALSE);
    if (status == NO) return -1;
    else if (status == TIMEOUT) return 3;

    for (i = 0; i < n; ++i)
    {
        c = colour[eno[4*i]];
        for (j = 1; j < 4; ++j)
            if (colour[eno[4*i+j]] == c) cross[4*i+j] = 1;
    }

    ans = 2;

    if (vertex >= 0) { imin = imax = vertex; }
    else             { imin = 0; imax = n-1; }

    for (i = imin; i <= imax; ++i)
    for (j = 1; j < 4; ++j)
        if (!cross[4*i+j])
        {
            initialise_colouring(n);
            if (makeblue(eno[4*i],FALSE) && makeblue(eno[4*i+j],n==2))
            {
                status = dispatchsearch(n,sg.e,2,0);
                if (status == TIMEOUT) return 3;
                if (status == YES)
                {
                    for (k = 0; k < n; ++k)
                    {
                        c = colour[eno[4*k]];
                        for (l = 1; l < 4; ++l)
                        if (colour[eno[4*k+l]] == c) cross[4*k+l] = 1;
                    }
                }
                else
                    ans = 1;
            }
            else
                ans = 1;
        }

    if (ans == 1)
        for (i = 0; i < n; ++i)
        {
            if (cross[4*i+1] + cross[4*i+2] + cross[4*i+3] <= 1)
                ans = 0;
        }

    return ans;
}

/**************************************************************************/

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,k,n;
    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;
}

/**************************************************************************/

int
main(int argc, char *argv[])
{
    sparsegraph sg,sh,*this;
    int n,codetype;
    int argnum,i,j,outcode;
    char *arg,sw;
    boolean badargs;
    boolean sswitch,gswitch,qswitch,vswitch,xswitch,Xswitch;
    boolean pswitch,Lswitch,tswitch,yswitch,Yswitch;
    long Lvalue;
    double t;
    char *infilename,*outfilename;
    FILE *infile,*outfile;
    nauty_counter nin,nout;
    int status,xstatus,ystatus,tvalue,imin,imax;
    DYNALLSTAT(int,ham1,ham1_sz);
    DYNALLSTAT(int,ham2,ham2_sz);

    HELP; PUTVERSION;

    INITRANBYTIME;

    sswitch = gswitch = yswitch = qswitch = vswitch = FALSE;
    tswitch = xswitch = Xswitch = Lswitch = pswitch = FALSE;
    Yswitch = FALSE;
    infilename = outfilename = NULL;

    argnum = 0;
    badargs = FALSE;
    for (j = 1; !badargs && j < argc; ++j)
    {
        arg = argv[j];
        if (arg[0] == '-' && arg[1] != '\0')
        {
            ++arg;
            while (*arg != '\0')
            {
                sw = *arg++;
                     SWBOOLEAN('s',sswitch)
                else SWBOOLEAN('g',gswitch)
                else SWBOOLEAN('q',qswitch)
                else SWBOOLEAN('x',xswitch)
                else SWBOOLEAN('y',yswitch)
                else SWBOOLEAN('Y',Yswitch)
                else SWBOOLEAN('X',Xswitch)
                else SWBOOLEAN('v',vswitch)
                else SWBOOLEAN('p',pswitch)
                else SWLONG('L',Lswitch,Lvalue,"-L")
                else SWINT('t',tswitch,tvalue,"-t")
                else badargs = TRUE;
            }
        }
        else
        {
            ++argnum;
            if      (argnum == 1) infilename = arg;
            else if (argnum == 2) outfilename = arg;
            else                  badargs = TRUE;
        }
    }

    if (sswitch && gswitch) 
        gt_abort(">E twohamg: -s and -g are incompatible");
    if ((xswitch != 0) + (Xswitch != 0)
               + (yswitch != 0) + (Yswitch != 0) > 1)
        gt_abort(">E twohamg: -x, -X, -y, -Y are incompatible");
    if (Yswitch && !pswitch)
        gt_abort(">E twohang: -Y is not allowed without -p");

    if (!Lswitch) totallimit = 0;
    else          totallimit = Lvalue * (nauty_counter)1000;

    if (!tswitch) tvalue = -1;

    if (badargs || argnum > 2)
    {
        fprintf(stderr,">E Usage: %s\n",USAGE);
        GETHELP;
        exit(1);
    }

    if (!qswitch)
    {
        fprintf(stderr,">A twohamg");
        if (sswitch || gswitch || vswitch || xswitch || Xswitch 
                || tswitch || pswitch || Lswitch || yswitch || Yswitch)
            fprintf(stderr," -");
        if (sswitch) fprintf(stderr,"s");
        if (gswitch) fprintf(stderr,"g");
        if (xswitch) fprintf(stderr,"x");
        if (Xswitch) fprintf(stderr,"X");
        if (yswitch) fprintf(stderr,"y");
        if (Yswitch) fprintf(stderr,"Y");
        if (pswitch) fprintf(stderr,"p");
        if (vswitch) fprintf(stderr,"v");
        if (Lswitch) fprintf(stderr,"L%ld",Lvalue);
        if (tswitch) fprintf(stderr,"t%d",tvalue);
        if (argnum > 0) fprintf(stderr," %s",infilename);
        if (argnum > 1) fprintf(stderr," %s",outfilename);
        fprintf(stderr,"\n");
        fflush(stderr);
    }

    if (infilename && infilename[0] == '-') infilename = NULL;
    infile = opengraphfile(infilename,&codetype,FALSE,1);
    if (!infile) exit(1);
    if (!infilename) infilename = "stdin";

    if (!outfilename || outfilename[0] == '-')
    {
        outfilename = "stdout";
        outfile = stdout;
    }
    else if ((outfile = fopen(outfilename,"w")) == NULL)
    {
        fprintf(stderr,"Can't open output file %s\n",outfilename);
        gt_abort(NULL);
    }

    NODIGRAPHSYET(codetype);

    if (sswitch || (!gswitch && (codetype&SPARSE6)))
        outcode = SPARSE6;
    else 
        outcode = GRAPH6;

    if (codetype&HAS_HEADER)
    {
        if (outcode == SPARSE6) writeline(outfile,SPARSE6_HEADER);
        else                    writeline(outfile,GRAPH6_HEADER);
    }

    nin = nout = 0;
    t = CPUTIME;
    SG_INIT(sg);
    SG_INIT(sh);

    while (read_sg(infile,&sg) != NULL)
    {
        ++nin;
        if (pswitch)
        {
            n = sg.nv;
            for (i = 0; i < n; ++i)
                if (sg.d[i] != 3) break;
            if (i != n)
            {
                fprintf(stderr,
                        ">W input " COUNTER_FMT " is not cubic\n",nin);
                continue;
            }
            makeprism_sg(&sg,&sh);
            n = sh.nv;
            this = &sh;
        }
        else
        {
            n = sg.nv;
            for (i = 0; i < n; ++i)
                if (sg.d[i] != 4) break;
            if (i != n)
            {
                fprintf(stderr,
                        ">W input " COUNTER_FMT " is not quartic\n",nin);
                continue;
            }
            for (i = 0; i < n; ++i)
                if (sg.v[i] != 4*i) break;
            if (i != n)
                gt_abort("readg6_sg() result is not in standard form");
            this = &sg;
        }

        if (xswitch || Xswitch)
        {
            xstatus = iscrossdecomposable(*this,tvalue);
            if ((xswitch && xstatus < 2) || (Xswitch && xstatus < 1))
            {
                if (outcode == SPARSE6) writes6_sg(outfile,&sg);   
                else if (outcode == GRAPH6) writeg6_sg(outfile,&sg);
                ++nout;

                if (vswitch)
                {
                    if (xstatus < 0)
                    {
                        fprintf(stderr,">H Graph " COUNTER_FMT
                                     " is indecomposable\n",nin);
                    }
                    else
                    {
                        fprintf(stderr,">X" COUNTER_FMT ": ",nin);
                        if (tswitch) { imin = imax = tvalue; }
                        else         { imin = 0; imax = n-1; }
                        for (i = imin; i <= imax; ++i)
                        for (j = 1; j < 4; ++j)
                            if (!cross[4*i+j])
                            {
                                fprintf(stderr," %d-%d-%d",
                                    (v1[eno[4*i]] == i
                                       ? v2[eno[4*i]] : v1[eno[4*i]]),
                                    i,
                                    (v1[eno[4*i+j]] == i
                                       ? v2[eno[4*i+j]] : v1[eno[4*i+j]]));
                            }
                        fprintf(stderr,"\n");
                    }
                }
            }
            else if (xstatus == 3)
            {
                fprintf(stderr,">H Graph " COUNTER_FMT
                                     " timed out\n",nin);
                if (outcode == SPARSE6) writes6_sg(outfile,&sg);
                else if (outcode == GRAPH6) writeg6_sg(outfile,&sg);
                ++nout;
            }
        }
        else if (yswitch || Yswitch)
        {
            ystatus = p4decomposition(*this,tvalue,Yswitch);
            if (ystatus != 0)
            {
                if (outcode == SPARSE6) writes6_sg(outfile,&sg);   
                else if (outcode == GRAPH6) writeg6_sg(outfile,&sg);
                ++nout;
            }

            if (ystatus == -2)
            {
                fprintf(stderr,">H Graph " COUNTER_FMT
                                     " timed out\n",nin);
            }
            else if (vswitch)
            {
                if (ystatus == -1)
                {
                    fprintf(stderr,">H Graph " COUNTER_FMT
                                     " is indecomposable\n",nin);
                }
                else if (ystatus > 0)
                {
                    fprintf(stderr,">X" COUNTER_FMT ": ",nin);
                    for (i = j = 0; j < ystatus; ++i)
                        if (!p4list[i].ok)
                        {
                            ++j;
                            fprintf(stderr," %d-%d-%d-%d",
                                p4list[i].v1,p4list[i].v2,
                                p4list[i].v3,p4list[i].v4);
                        }
                    fprintf(stderr,"\n");
                }
            }
        }
        else
        {
            if (vswitch)
            {
                DYNALLOC1(int,ham1,ham1_sz,n,"malloc");
                DYNALLOC1(int,ham2,ham2_sz,n,"malloc");
                status = isdecomposable(*this,ham1,ham2);
            }
            else
                status = isdecomposable(*this,NULL,NULL);
    
            if (status != YES)
            {
                if (outcode == SPARSE6) writes6_sg(outfile,&sg);
                else if (outcode == GRAPH6) writeg6_sg(outfile,&sg);

                if (status == TIMEOUT)
                    fprintf(stderr,">H Graph " COUNTER_FMT
                                     " timed out\n",nin);
                else if (vswitch)
                    fprintf(stderr,">H Graph " COUNTER_FMT
                                     " is indecomposable\n",nin);
                ++nout;
            }
            else if (vswitch)
            {
#if DEBUG
                dumpdata(0,0,0,n);
#endif
                fprintf(stderr,">H" COUNTER_FMT ": ",nin);
                for (i = 0; i < n; ++i) fprintf(stderr," %d",ham1[i]);
                fprintf(stderr,"\n ");
                for (i = 0; i < n; ++i) fprintf(stderr," %d",ham2[i]);
                fprintf(stderr,"\n");
            }
        }
    }
    t = CPUTIME - t;

    if (!qswitch)
    {
        fprintf(stderr,">T to=" COUNTER_FMT " phases=",ntimeouts);
        for (i = 0; i <= NUMLIMITS; ++i)
            fprintf(stderr," " COUNTER_FMT,nphases[i]);
        fprintf(stderr,"\n");

        fprintf(stderr,
                ">Z " COUNTER_FMT " graphs read from %s, "
                COUNTER_FMT " written to %s; %3.2f sec.\n",
                nin,infilename,nout,outfilename,t);
    }

    exit(0);
}

Messung V0.5
C=94 H=89 G=91

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.