#define HELPTEXT \ " Read undirected loop-free graphs and replace their edges with multiple\n\
edges in all possible ways (multiplicity at least 1).\n\
Isomorphic multigraphs derived from the same input are suppressed.\n\ If the input graphs are non-isomorphic then the output graphs are also.\n\
\n\
-e# | -e#:# specify a value or range of the total number of edges\n\
counting multiplicities\n\
-m# maximum edge multiplicity (minimum is 1)\n\
-D# upper bound on maximum degree\n\
-r# make regular of specified degree (incompatible with -l, -D, -e)\n\
-l# make regular multigraphs with multiloops, degree #\n\
(incompatible with -r, -D, -e)\n\
-V read the T format as produced by vcolg and obey the vertex colours\n\
in computing the automorphism group. If -T or -G is used as the\n\
output format, a list of the input colours is included.\n\
Either -l, -r, -D, -e or -m with a finite maximum must be given\n\
-f# Use the group that fixes the first # vertices setwise\n\
-T use a simple text output format (nv ne {v1 v2 mult})\n\
-G like -T but includes group size as third item (if less than 10^10)\n\
The group size does not include exchange of isolated vertices.\n\
-A write as the upper triangle of an adjacency matrix, row by row,\n\
including the diagonal, and preceded by the number of vertices\n\
-B write as an integer matrix preceded by the number of rows and\n\
number of columns, where -f determines the number of rows\n\
-u no output, just count them\n\
-q suppress auxiliary information\n"
staticvoid
trythisone(grouprec *group,
boolean lswitch, int *deg, int maxdeg, int ne, int n) /* Try one solution, accept if minimal. */
{ int i,j,ne2;
boolean accept; char line[20*(MAXNV+MAXNE)+50],s[20],*p;
staticvoid
scan(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n) /* Recursive scan for default case */
{ int left; long min,max,k;
if (level == ne)
{
trythisone(group,FALSE,NULL,0,ne,n); return;
}
left = ne - level - 1;
min = minedges - sofar - maxmult*left; if (min < 1) min = 1;
max = maxedges - sofar - left; if (max > maxmult) max = maxmult;
for (k = min; k <= max; ++k)
{
ix[level] = k;
scan(level+1,ne,minedges,maxedges,sofar+k,maxmult,group,n);
}
staticvoid
scan_md(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n, int *deg, int maxdeg) /* Recursive scan, maxdeg version */
{ int left; int min,max,k; int x1,x2;
if (level == ne)
{
trythisone(group,FALSE,deg,maxdeg,ne,n); return;
}
x1 = v0[level];
x2 = v1[level];
left = ne - level - 1;
min = minedges - sofar - maxmult*left; if (min < 1) min = 1;
max = maxedges - sofar - left; if (max > maxmult) max = maxmult; if (deg[x1] + max - 1 > maxdeg) max = maxdeg - deg[x1] + 1; if (deg[x2] + max - 1 > maxdeg) max = maxdeg - deg[x2] + 1;
staticvoid
scan_lp(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n, int *deg, int maxdeg) /* Recursive scan, regular-with-loops version. */
{ int left; long min,max,k; int x1,x2;
boolean odd,even;
if (level == ne)
{
trythisone(group,TRUE,deg,maxdeg,ne,n); return;
}
x1 = v0[level];
x2 = v1[level];
left = ne - level - 1;
min = minedges - sofar - maxmult*left; if (min < 1) min = 1;
max = maxedges - sofar - left; if (max > maxmult) max = maxmult; if (deg[x1] + max - 1 > maxdeg) max = maxdeg - deg[x1] + 1; if (deg[x2] + max - 1 > maxdeg) max = maxdeg - deg[x2] + 1;
odd = even = FALSE; if (lastlev[x1] == level)
{ if (((maxdeg-deg[x1])&1) == 1) even = TRUE; else odd = TRUE;
} if (lastlev[x2] == level)
{ if (((maxdeg-deg[x2])&1) == 1) even = TRUE; else odd = TRUE;
} if (even && odd) return;
for (k = min; k <= max; ++k)
{ if (even && (k&1) == 1) continue; if (odd && (k&1) == 0) continue;
staticvoid
scan_reg(int level, int ne, long minedges, long maxedges, long sofar, long maxmult, grouprec *group, int n, int *delta, int *def, int maxdeg) /* Recursive scan, regular version. */
{ int left; long min,max,k; int x1,x2;
if (level == ne)
{
trythisone(group,FALSE,NULL,maxdeg,ne,n); return;
}
x1 = v0[level];
x2 = v1[level];
left = ne - level - 1;
min = minedges - sofar - maxmult*left; if (min < 1) min = 1;
max = maxedges - sofar - left; if (max > maxmult) max = maxmult; if (max > def[x1] + 1) max = def[x1] + 1; if (max > def[x2] + 1) max = def[x2] + 1;
if (min < def[x2] + 1 - delta[x1]) min = def[x2] + 1 - delta[x1]; if (min < def[x1] + 1 - delta[x2]) min = def[x1] + 1 - delta[x2];
if (lastlev[x1] == level && min < def[x1] + 1) min = def[x1] + 1; if (lastlev[x2] == level && min < def[x2] + 1) min = def[x2] + 1;
staticvoid
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[2*MAXNV];
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,hasloops;
#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;
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)
gt_abort(">E multig: MAXNV or MAXNE exceeded\n");
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);
}
hasloops = FALSE; for (i = 0, gi = g; i < n; ++i, gi += m) if (ISELEMENT(gi,i))
{
hasloops = TRUE; break;
}
staticvoid
vmulti(graph *g, int nfixed, long minedges, long maxedges, long maxmult, int maxdeg, boolean lswitch, int ne, int m, int n) /* In this version, v0[0..ne-1], v1[0..ne-1], edgeno[*][*]
and colour[0..ne-1] are already filled in. */
{ static DEFAULTOPTIONS_GRAPH(options);
statsblk stats;
setword workspace[2*MAXNV];
grouprec *group; int i,j,k,thisdeg,maxd,x0,x1;
set *gi; int lab[MAXNV],ptn[MAXNV],orbits[MAXNV],deg[MAXNV]; int delta[MAXNV],def[MAXNV];
set active[SETWORDSNEEDED(MAXNV)]; int weight[MAXNV];
boolean isreg,hasloops;
#ifdef PATHCOUNTS
++count0; #endif
k = -1;
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) weight[i] = -i-1; elseif (i < nfixed) weight[i] = 2*colour[i]; else weight[i] = 2*colour[i]+1;
}
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; DECODE // 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)
gt_abort(">E multig: MAXNV or MAXNE exceeded\n");
static boolean
readvcol(FILE *f, int *m, int *n, int *ne, graph *g) /* Read the T style output as from vcolg. Theedgesgointov0[*],v1[*],eno[*][*]andthevertexcoloursintocolour[*]. ReturnFALSEifftheinputisempty.
*/
{ int i,j,nn,nne,mm,x,y;
if (fscanf(f,"%d",&nn) != 1) returnFALSE; if (nn > MAXNV) gt_abort(">E multig : too many vertices\n");
if (fscanf(f,"%d",&nne) != 1)
gt_abort(">E multig : incomplete input (1)\n"); elseif (nne > MAXNE)
gt_abort(">E multig : too many edges\n");
*n = nn;
*ne = nne;
*m = mm = SETWORDSNEEDED(nn);
for (i = 0; i < nn; ++i) if (fscanf(f,"%d",&colour[i]) != 1)
gt_abort(">E multig : incomplete input (2)\n");
EMPTYGRAPH(g,mm,nn);
if (Aswitch || Bswitch) for (i = 0; i < nn; ++i) for (j = 0; j < nn; ++j)
edgeno[i][j] = -1;
for (i = 0; i < nne; ++i)
{ if (fscanf(f,"%d%d",&v0[i],&v1[i]) != 2)
gt_abort(">E multig : incomplete input (3)\n");
ADDELEMENT(g+mm*v0[i],v1[i]);
ADDELEMENT(g+mm*v1[i],v0[i]);
edgeno[v0[i]][v1[i]] = edgeno[v1[i]][v0[i]] = i;
}
if ((Gswitch!=0) + (Tswitch!=0) + (uswitch!=0)
+ (Aswitch!=0) + (Bswitch!=0) >= 2)
gt_abort(">E multig: -G, -T, -A, -B and -u are incompatible\n");
#ifndef OUTPROC if (!Tswitch && !Gswitch && !Aswitch && !Bswitch && !uswitch)
gt_abort(">E multig: must use -A, -B, -T, -G or -u\n"); #endif
if (rswitch && (Dswitch || eswitch))
gt_abort(">E multig: -r is incompatible with -D and -e\n");
if (lswitch && (rswitch || Dswitch || eswitch))
gt_abort(">E multig: -l is incompatible with -r, -D and -e\n");
if (!eswitch)
{
minedges = 0;
maxedges = NOLIMIT;
} if (!mswitch) maxmult = NOLIMIT; if (!fswitch) nfixed = 0;
if (Bswitch && nfixed == 0)
gt_abort(">E multig: -B requires -f# with #>0\n"); if (fswitch) Brows = nfixed;
if (maxedges >= NOLIMIT && maxmult >= NOLIMIT
&& !Dswitch && !rswitch && !lswitch)
gt_abort( ">E multig: either -D or -e or -m or -r must impose a real limit\n");
if (!qswitch)
{
msg[0] = '\0';
CATMSG0(">A multig"); if (eswitch || mswitch || uswitch || (fswitch && nfixed > 0)
|| lswitch || rswitch || Dswitch || Tswitch
|| Gswitch || Aswitch || Bswitch || Vswitch)
CATMSG0(" -"); if (mswitch) CATMSG1("m%ld",maxmult); if (Vswitch) CATMSG0("V"); if (uswitch) CATMSG0("u"); if (Tswitch) CATMSG0("T"); if (Gswitch) CATMSG0("G"); if (Aswitch) CATMSG0("A"); if (Bswitch) CATMSG0("B"); if (fswitch) CATMSG1("f%d",nfixed); if (eswitch) CATMSG2("e%ld:%ld",minedges,maxedges); if (Dswitch) CATMSG1("D%d",maxdeg); if (rswitch) CATMSG1("r%d",regdeg); if (lswitch) CATMSG1("l%d",ldeg);
msglen = strlen(msg); if (argnum > 0) msglen += strlen(infilename); if (argnum > 1) msglen += strlen(outfilename); if (msglen >= 196)
{
fputs(msg,stderr); if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename);
fprintf(stderr,"\n");
} else
{ if (argnum > 0) CATMSG1(" %s",infilename); if (argnum > 1) CATMSG1(" %s",outfilename);
CATMSG0("\n");
fputs(msg,stderr);
}
fflush(stderr);
}
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.