#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 or, if there is none, by the\n\
format of the first input graph. Also see -S. \n\
\n\
The output file will have a header ifand 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\
-t# With -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\
-L# Limit 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 */
typedefstruct addrval_struct
{ int *addr; int value;
} addrval;
staticlong 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; }
typedefstruct 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); staticint *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;
staticvoid
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;
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;
f1 = bluefarend[w1];
f2 = bluefarend[w2]; if (f1 == w2 && !lastok) returnFALSE;
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
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;
f1 = redfarend[w1];
f2 = redfarend[w2]; if (f1 == w2 && !lastok) returnFALSE;
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
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)) returnFALSE;
++*nblue;
}
}
} elseif (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)) returnFALSE;
++*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)) returnFALSE;
++*nblue;
} else
{ if (!makered(j,*nred==n-1)) returnFALSE;
++*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)) returnFALSE;
++*nred;
} else
{ if (!makeblue(j,*nblue==n-1)) returnFALSE;
++*nblue;
}
}
}
}
}
staticint
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]);
staticint
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
staticint
dispatchsearch(int n, int *e, int nblue, int nred) /* Multiple tries at solution */
{ int i,status;
addrval *valptr;
boolean ok;
nauty_counter remaininglimit;
staticint
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;
staticint
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; elseif (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;
}
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;
}
staticint
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; elseif (status == TIMEOUT) return -2;
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;
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 (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");
}
}
} elseif (xstatus == 3)
{
fprintf(stderr,">H Graph " COUNTER_FMT " timed out\n",nin); if (outcode == SPARSE6) writes6_sg(outfile,&sg); elseif (outcode == GRAPH6) writeg6_sg(outfile,&sg);
++nout;
}
} elseif (yswitch || Yswitch)
{
ystatus = p4decomposition(*this,tvalue,Yswitch); if (ystatus != 0)
{ if (outcode == SPARSE6) writes6_sg(outfile,&sg); elseif (outcode == GRAPH6) writeg6_sg(outfile,&sg);
++nout;
}
if (ystatus == -2)
{
fprintf(stderr,">H Graph " COUNTER_FMT " timed out\n",nin);
} elseif (vswitch)
{ if (ystatus == -1)
{
fprintf(stderr,">H Graph " COUNTER_FMT " is indecomposable\n",nin);
} elseif (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); elseif (outcode == GRAPH6) writeg6_sg(outfile,&sg);
if (status == TIMEOUT)
fprintf(stderr,">H Graph " COUNTER_FMT " timed out\n",nin); elseif (vswitch)
fprintf(stderr,">H Graph " COUNTER_FMT " is indecomposable\n",nin);
++nout;
} elseif (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
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet)
¤
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.