/* testg.c : Find properties of graphs. This is the source file for bothpickg(selectbyproperty)andcountg(countbyproperty).
Version 2.2 of June 2022. */ /* TODO - write a header if input has one;
Fix clunky practice of storing a pointer in a long long. */
#define HELPTEXT \ " countg : Count graphs according to their properties.\n\
pickg : Select graphs according to their properties.\n\
\n\
ifile, ofile : Input and output files.\n\ '-'and missing names imply stdin and stdout.\n\
\n\
Miscellaneous switches:\n\
-p# -p#:# Specify range of input lines (first is 1)\n\
May fail if input is incremental.\n\
-f With -p, assume input lines of fixed length\n\
(only used with a file in graph6/digraph6 format)\n\
-v Negate all constraints (but not -p)\n\
-X Reverse selection (but -p still observed)\n\
-V List properties of every input matching constraints.\n\
-l Put a blank line whenever the first parameter changes,\n\ if there are at least two parameters.\n\
-1 Write output as lines of numbers separated by spaces,\n\
with 0/1for boolean and both endpoints of ranges given\n\
separately even if they are the same, and the count at\n\
the end of the line. Also, no total is written.\n\
-2 The same as -1 but counts are not written.\n\
-q Suppress informative output.\n\
\n\
Constraints:\n\
Numerical constraints (shown here with following #) can take\n\
a single integer value, or a range like #:#,#:, or :#. Each\n\
can also be preceded by '~', which negates it. (For example,\n\
-~D2:4 will match any maximum degree which is _not_ 2, 3, or4.)\n\
Constraints are applied to all input graphs, and only those\n\
which match all constraints are counted or selected.\n\
\n\
-n# number of vertices -e# number of edges\n\
-ee# number of non-edges (including loops for digraphs)\n\
-L# number of loops -C strongly connected\n\
-LL# number of 2-cycles -cc# number of components\n\
-d# minimum (out-)degree -D# maximum (out-)degree\n\
-m# vertices of min (out-)degree -M# vertices of max (out-)degree\n\
-u# minimum (in-)degree -U# maximum (in-)degree\n\
-s# vertices of min (in-)degree -S# vertices of max (in-)degree\n\
-r regular -b bipartite\n\
-z# radius -Z# diameter\n\
-g# girth (0=acyclic) -Y# total number of cycles\n\
-h# maximum independent set -k# maximum clique\n\
-T# number of triangles -K# number of maximal cliques\n\
-TT# number independent sets of size 3\n\
-B# smallest possible first side of a bipartition (0if nonbipartite)\n\
-H# number of induced cycles -W# number of 4-cycles\n\
-E Eulerian (all degrees are even, connectivity not required)\n\
-a# group size -o# orbits -F# fixed points -t vertex-transitive\n\
-c# connectivity (only implemented for0,1,2).\n\
-i# min common nbrs of adjacent vertices; -I# maximum\n\
-j# min common nbrs of non-adjacent vertices; -J# maximum\n\
-x# number of sources -xx# number of sinks\n\
-WW# number of diamonds\n\
\n\
Sort keys:\n\
Counts are made for all graphs passing the constraints. Counts\n\
are given separately for each combination of values occurring for\n\
the properties listed as sort keys. A sort key is introduced by\n\ '--'and uses one of the letters known as constraints. These can\n\
be combined: --n --e --r is the same as --ne --r and --ner.\n\
The order of sort keys is significant.\n\
A comma can be used as a separator.\n\
The sort key ':' has a special purpose: the values of sort keys\n\
following ':' are given as ranges rather than creating a separate\n\
line for each value. For example --e:zZ will give the ranges of\n\
radius and diameter that occur for each number of edges.\n\
The output format matches the input, except that sparse6 is used\n\
to output an incremental graph whose predecessor is not output.\n"
#define MAXKEYS NUMCONSTRAINTS /* Maximum number of keys to sort by */
/* splay_st is the generic structure of a splay tree node. The data[]fieldhasvaryinglengthsaccordingtoneed.Thisprogram usestwosplaytrees:oneforcountsandoneforlargedataitems.
*/
typedefstruct node_st /* variant for count tree */
{ struct splay_st *left,*right,*parent;
nauty_counter count;
range val[MAXKEYS]; /* Need this big? */
} count_node;
typedefstruct value_st /* variant for value tree */
{ struct splay_st *left,*right,*parent;
size_t size;
value_t data[1];
} value_node;
staticint
add_count(count_node *newval, count_node *oldval) /* add new value into old value; numsplitkeys are the thesame-updaterangesforotherkeys.
newval has equal lo & hi values. */
{ int i;
group_node *sza,*szb;
++oldval->count;
for (i = numsplitkeys; i < numkeys; ++i)
{ if (VALTYPE(key[i]) == GROUPSIZE)
{
sza = (group_node*)newval->val[i].lo;
szb = (group_node*)oldval->val[i].lo; if (compare_groupnodes(sza,szb) < 0)
oldval->val[i].lo = newval->val[i].lo;
szb = (group_node*)oldval->val[i].hi; if (compare_groupnodes(sza,szb) > 0)
oldval->val[i].hi = newval->val[i].lo;
} elseif (newval->val[i].lo < oldval->val[i].lo)
oldval->val[i].lo = newval->val[i].lo; elseif (newval->val[i].lo > oldval->val[i].hi)
oldval->val[i].hi = newval->val[i].lo;
}
if (oneswitch)
{ for (i = 0; i < numkeys; ++i)
{
ki = key[i]; if (i > 0) fprintf(f," ");
if (VALTYPE(ki) == BOOLTYPE)
{ if (!VAL(ki)) fprintf(f,"0"); else fprintf(f,"1");
} elseif (VALTYPE(ki) == GROUPSIZE)
write_group_size(f,(group_node*)VAL(ki)); else
fprintf(f,VALUE_FMT,VAL(ki));
}
} else
{ for (i = 0; i < numkeys; ++i)
{
ki = key[i]; if (i > 0) fprintf(f,"; ");
staticvoid
groupstats(graph *g, boolean digraph, int m, int n, group_node *sz, int *numorbits, int *fixedpts) /* Find the automorphism group of the undirected graph g.
Return the group size and number of orbits and fixed points. */
{ #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; int count[MAXN];
set active[MAXM];
setword workspace[24*MAXM]; #else
DYNALLSTAT(int,lab,lab_sz);
DYNALLSTAT(int,ptn,ptn_sz);
DYNALLSTAT(int,orbits,orbits_sz);
DYNALLSTAT(int,count,count_sz);
DYNALLSTAT(set,active,active_sz);
DYNALLSTAT(setword,workspace,workspace_sz); #endif int i; int fixed; int numcells,code;
statsblk stats; static DEFAULTOPTIONS_GRAPH(options);
staticvoid
compute(graph *g, int m, int n, int code, boolean digraph) /* Compute property i assuming the prerequisites are known. */
{ int mind,maxd,mincount,maxcount; int minind,maxind,minincount,maxincount; int rad,diam,loops; unsignedlong ned;
boolean eul;
group_node sz; int norbs,fixedpts; int minadj,maxadj,minnon,maxnon; int sources,sinks;
case I_c: if (isbiconnected(g,m,n)) VAL(I_c) = 2; elseif (isconnected(g,m,n)) VAL(I_c) = 1; else VAL(I_c) = 0;
COMPUTED(I_c) = TRUE; break;
case I_n: case I_d: case I_D: case I_E: case I_r: case I_o: case I_t: case I_m: case I_M:
fprintf(stderr,">E Property %d should be known already\n",code); exit(1);
case I_Y:
VAL(I_Y) = cyclecount(g,m,n);
COMPUTED(I_Y) = TRUE; break;
case I_H:
VAL(I_H) = indcyclecount(g,m,n);
COMPUTED(I_H) = TRUE; break;
case I_T: if (digraph) VAL(I_T) = numdirtriangles(g,m,n); else VAL(I_T) = numtriangles(g,m,n);
COMPUTED(I_T) = TRUE; break;
case I_W:
VAL(I_W) = numsquares(g,m,n);
COMPUTED(I_W) = TRUE; break;
case I_WW:
VAL(I_WW) = numdiamonds(g,m,n);
COMPUTED(I_WW) = TRUE; break;
case I_TT:
VAL(I_TT) = numind3sets(g,m,n);
COMPUTED(I_TT) = TRUE; break;
case I_x: case I_xx:
sources_sinks(g,m,n,&sources,&sinks);
VAL(I_x) = sources;
VAL(I_xx) = sinks; break;
case I_i: case I_I: case I_j: case I_J:
commonnbrs(g,&minadj,&maxadj,&minnon,&maxnon,m,n);
VAL(I_i) = minadj;
VAL(I_I) = maxadj;
VAL(I_j) = minnon;
VAL(I_J) = maxnon;
COMPUTED(I_i) = COMPUTED(I_I) = TRUE;
COMPUTED(I_j) = COMPUTED(I_J) = TRUE; break;
staticvoid
decodekeys(char *s) /* Extract key symbols from -- string */
{ int i,j,k;
for (i = 0; s[i] != '\0'; ++i)
{ if (s[i] == ':')
{ if (rangemarkerseen)
{
fprintf(stderr,">E --: is only allowed once\n"); exit(1);
}
rangemarkerseen = TRUE; continue;
}
if (vswitch)
{ for (j = 0; j < NUMCONSTRAINTS; ++j) if (ISCONSTRAINT(j)) INVERSE(j) = !INVERSE(j);
}
if (!qswitch)
{
fprintf(stderr,">A %s",argv[0]); if (fswitch || pswitch || oneswitch || twoswitch)
fprintf(stderr," -"); if (fswitch) fprintf(stderr,"f"); if (oneswitch) fprintf(stderr,"1"); if (twoswitch) fprintf(stderr,"2"); if (pswitch) writeparamrange(stderr,'p',FALSE,pval1,pval2);
if (numkeys > 0)
{
fprintf(stderr," --"); for (j = 0; j < numkeys; ++j) if (j == numsplitkeys && j != 0)
{ if (ISDOUBLED(key[j]))
fprintf(stderr,":%c%c",SYMBOL(key[j]),SYMBOL(key[j])); else
fprintf(stderr,":%c",SYMBOL(key[j]));
} else
{ if (ISDOUBLED(key[j]))
fprintf(stderr,"%c%c",SYMBOL(key[j]),SYMBOL(key[j])); else
fprintf(stderr,"%c",SYMBOL(key[j]));
}
}
if (havecon) fprintf(stderr," -"); for (j = 0; j < NUMCONSTRAINTS; ++j) if (ISCONSTRAINT(j))
{ if (INVERSE(j)) fprintf(stderr,"~"); if (ISDOUBLED(j))
{ if (VALTYPE(j) == BOOLTYPE)
fprintf(stderr,"%c%c",SYMBOL(j),SYMBOL(j)); else
writeparamrange(stderr,SYMBOL(j),TRUE,LO(j),HI(j));
} else
{ if (VALTYPE(j) == BOOLTYPE)
fprintf(stderr,"%c",SYMBOL(j)); else
writeparamrange(stderr,(int)SYMBOL(j),FALSE,LO(j),HI(j));
}
}
if (argnum > 0) fprintf(stderr," %s",infilename); if (argnum > 1) fprintf(stderr," %s",outfilename);
fprintf(stderr,"\n");
fflush(stderr);
}
oneswitch = (oneswitch || twoswitch);
if (infilename && infilename[0] == '-') infilename = NULL;
infile = opengraphfile(infilename,&codetype,fswitch,
pswitch ? pval1 : 1); if (!infile) exit(1); if (!infilename) infilename = "stdin";
/* outcode is ignored unless a header is written */ if ((codetype&SPARSE6)) outcode = SPARSE6; elseif ((codetype&DIGRAPH6)) outcode = DIGRAPH6; else outcode = GRAPH6;
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.