Jan 15, 2001 : Increased graph order limit from 2^16-1 to 2^22-1. Aug 9, 2001 : Added fgroup_inv() and fcanonise_inv() Sep 15, 2004 : Completed prototypes Oct 16, 2004 : DEAFULTOPTIONS_GRAPH Nov 17, 2005 : Added fcanonise_inv_sg() May 11, 2010 : use sorttemplates.c Sep 5, 2013 : Unify format processing and remove 2^22 limit Oct 14, 2017 : Include code for n=0 Sep 28, 2019 : Define breakcellwt
#define SORT_OF_SORT 3 #define SORT_NAME sortwt #define SORT_TYPE1 int #define SORT_TYPE2 int #include"sorttemplates.c" /* Creates static void sortwt(int *lab, int *wt, int n) */
void
setlabptn(int *weight, int *lab, int *ptn, int n) /* Define (lab,ptn) with cells in increasing order of weight. */
{ int i;
if (n == 0) return;
for (i = 0; i < n; ++i) lab[i] = i;
if (weight)
{
sortwt(lab,weight,n); for (i = 0; i < n-1; ++i)
{ if (weight[lab[i]] != weight[lab[i+1]])
ptn[i] = 0; else
ptn[i] = 1;
}
ptn[n-1] = 0;
} else
{ for (i = 0; i < n-1; ++i) ptn[i] = 1;
ptn[n-1] = 0;
}
}
int
breakcellwt(int *weight, int *lab, int *ptn, int n1, int n2) /* Break (lab[n1..n2-1],ptn[n1..n2-1]) into cells in increasing order of weight. If is assumed that lab[n1..n2-1] are defined but ptn[n1..n2-1] are ignored. The weight of lab[i] is weight[lab[i]].
The number of cells is returned. */
{ int i,nc;
if (n2 <= n1) return 0;
nc = 1; if (weight)
{
sortwt(lab+n1,weight,n2-n1); for (i = n1; i < n2-1; ++i)
{ if (weight[lab[i]] != weight[lab[i+1]])
{
ptn[i] = 0;
++nc;
} else
ptn[i] = 1;
}
ptn[n2-1] = 0;
} else
{ for (i = n1; i < n2-1; ++i) ptn[i] = 1;
ptn[n2-1] = 0;
}
return nc;
}
staticint
setlabptnfmt(char *fmt, int *lab, int *ptn, set *active, int m, int n) /* Define (lab,ptn,active) according to format string.
Return number of cells */
{ int i,nc; #if MAXN int wt[MAXN]; #else
DYNALLSTAT(int,wt,wt_sz);
DYNALLOC1(int,wt,wt_sz,n,"setlabptnfmt"); #endif
if (n == 0) return 0;
EMPTYSET(active,m);
ADDELEMENT(active,0);
nc = 1;
if (fmt != NULL && fmt[0] != '\0')
{ #if !MAXN
DYNALLOC1(int,wt,wt_sz,n,"setlabptnfmt"); #endif for (i = 0; i < n && fmt[i] != '\0'; ++i)
wt[i] = (unsignedchar)fmt[i]; for ( ; i < n; ++i)
wt[i] = 'z';
setlabptn(wt,lab,ptn,n); for (i = 0; i < n-1; ++i) if (ptn[i] == 0)
{
++nc;
ADDELEMENT(active,i+1);
}
} else
{ for (i = 0; i < n; ++i)
{
lab[i] = i;
ptn[i] = 1;
}
ptn[n-1] = 0;
}
static boolean
hasloops(graph *g, int m, int n) /* Test for loops */
{ int i;
set *gi;
for (i = 0, gi = g; i < n; ++i, gi += m) if (ISELEMENT(gi,i)) returnTRUE;
returnFALSE;
}
static boolean
hasloops_sg(sparsegraph *sg)
{
size_t *v,vi,j; int *d,*e,n,i;
n = sg->nv;
SG_VDE(sg,v,d,e); for (i = 0; i < n; ++i)
{
vi = v[i]; for (j = vi; j < vi + d[i]; ++j) if (e[vi] == i) returnTRUE;
}
returnFALSE;
}
void
fcanonise(graph *g, int m, int n, graph *h, char *fmt, boolean digraph) /* canonise g under format fmt; result in h. fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it
is assumed to continue with the colour 'z' indefinitely. */
{ #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 numcells,code;
statsblk stats; static DEFAULTOPTIONS_GRAPH(options);
if (n == 0) return;
#if MAXN if (n > MAXN || m > MAXM)
{
fprintf(stderr,">E fcanonise: m or n too large\n");
ABORT(">E fcanonise");
} #else
DYNALLOC1(int,lab,lab_sz,n,"fcanonise");
DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise");
DYNALLOC1(int,orbits,orbits_sz,n,"fcanonise");
DYNALLOC1(int,count,count_sz,n,"fcanonise");
DYNALLOC1(set,active,active_sz,m,"fcanonise");
DYNALLOC1(setword,workspace,workspace_sz,24*m,"fcanonise"); #endif
digraph = digraph || hasloops(g,m,n);
numcells = setlabptnfmt(fmt,lab,ptn,active,m,n);
if (m == 1)
refine1(g,lab,ptn,0,&numcells,count,active,&code,1,n); else
refine(g,lab,ptn,0,&numcells,count,active,&code,m,n);
if (numcells == n || (numcells == n-1 && !digraph))
{ for (i = 0; i < n; ++i) count[i] = lab[i];
updatecan(g,h,count,0,m,n);
gt_numorbits = numcells;
} else
{
options.getcanon = TRUE;
options.defaultptn = FALSE;
options.digraph = digraph; #ifdef REFINE
options.userrefproc = REFINE; #endif if (n >= MIN_SCHREIER) options.schreier = TRUE;
void
fcanonise_inv(graph *g, int m, int n, graph *h, char *fmt, void (*invarproc)(graph*,int*,int*,int,int,int,int*,int,
boolean,int,int), int mininvarlevel, int maxinvarlevel, int invararg, boolean digraph) /* Canonise g under format fmt; result in h. fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. This is like fcanonise() except that a invariant and its arguments
can be specified. */
{ #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 numcells,code;
statsblk stats; static DEFAULTOPTIONS_GRAPH(options);
if (n == 0) return;
#if MAXN if (n > MAXN || m > MAXM)
{
fprintf(stderr,">E fcanonise: m or n too large\n");
ABORT(">E fcanonise");
} #else
DYNALLOC1(int,lab,lab_sz,n,"fcanonise");
DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise");
DYNALLOC1(int,orbits,orbits_sz,n,"fcanonise");
DYNALLOC1(int,count,count_sz,n,"fcanonise");
DYNALLOC1(set,active,active_sz,m,"fcanonise");
DYNALLOC1(setword,workspace,workspace_sz,24*m,"fcanonise"); #endif
void
fcanonise_inv_sg(sparsegraph *g, int m, int n, sparsegraph *h, char *fmt, void (*invarproc)(graph*,int*,int*,int,int,int,int*,int,
boolean,int,int), int mininvarlevel, int maxinvarlevel, int invararg, boolean digraph) /* canonise g under format fmt; result in h. fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. This is like fcanonise() except that a invariant and its arguments
can be specified. Version for sparse graphs. */
{ #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 numcells,code;
statsblk stats; static DEFAULTOPTIONS_SPARSEGRAPH(options);
if (n == 0)
{
h->nv = 0;
h->nde = 0; return;
}
#if MAXN if (n > MAXN || m > MAXM)
{
fprintf(stderr,">E fcanonise: m or n too large\n");
ABORT(">E fcanonise");
} #else
DYNALLOC1(int,lab,lab_sz,n,"fcanonise");
DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise");
DYNALLOC1(int,orbits,orbits_sz,n,"fcanonise");
DYNALLOC1(int,count,count_sz,n,"fcanonise");
DYNALLOC1(set,active,active_sz,m,"fcanonise");
DYNALLOC1(setword,workspace,workspace_sz,24*m,"fcanonise"); #endif
void
fgroup(graph *g, int m, int n, char *fmt, int *orbits, int *numorbits) /* Find the orbits of undirected graph g stabilised by format fmt. The orbits are put into orbits[] and the number of them into *numorbits fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it
is assumed to continue with the colour 'z' indefinitely. */
{ #if MAXN int lab[MAXN],ptn[MAXN]; int count[MAXN];
set active[MAXM];
setword workspace[24*MAXM]; #else
DYNALLSTAT(int,lab,lab_sz);
DYNALLSTAT(int,ptn,ptn_sz);
DYNALLSTAT(int,count,count_sz);
DYNALLSTAT(set,active,active_sz);
DYNALLSTAT(setword,workspace,workspace_sz); #endif int i,j; int orbrep; int numcells,code;
boolean digraph;
statsblk stats; static DEFAULTOPTIONS_GRAPH(options);
if (n == 0)
{
*numorbits = 0; return;
}
#if MAXN if (n > MAXN || m > MAXM)
{
fprintf(stderr,">E fcanonise: m or n too large\n");
ABORT(">E fcanonise");
} #else
DYNALLOC1(int,lab,lab_sz,n,"fcanonise");
DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise");
DYNALLOC1(int,count,count_sz,n,"fcanonise");
DYNALLOC1(set,active,active_sz,m,"fcanonise");
DYNALLOC1(setword,workspace,workspace_sz,24*m,"fcanonise"); #endif
void
fgroup_inv(graph *g, int m, int n, char *fmt, int *orbits, int *numorbits, void (*invarproc)(graph*,int*,int*,int,int,int,int*,int,
boolean,int,int), int mininvarlevel, int maxinvarlevel, int invararg) /* Find the orbits of undirected graph g stabilised by format fmt. The orbits are put into orbits[] and the number of them into *numorbits fmt is either NULL (for no vertex classification) or is a string with char-valued colours for the vertices. If it ends early, it is assumed to continue with the colour 'z' indefinitely. This is like fgroup() except that a invariant and its arguments
can be specified. */
{ #if MAXN int lab[MAXN],ptn[MAXN]; int count[MAXN];
set active[MAXM];
setword workspace[24*MAXM]; #else
DYNALLSTAT(int,lab,lab_sz);
DYNALLSTAT(int,ptn,ptn_sz);
DYNALLSTAT(int,count,count_sz);
DYNALLSTAT(set,active,active_sz);
DYNALLSTAT(setword,workspace,workspace_sz); #endif int i,j; int orbrep;
boolean digraph; int numcells,code;
statsblk stats; static DEFAULTOPTIONS_GRAPH(options);
if (n == 0)
{
*numorbits = 0; return;
}
#if MAXN if (n > MAXN || m > MAXM)
{
fprintf(stderr,">E fcanonise: m or n too large\n");
ABORT(">E fcanonise");
} #else
DYNALLOC1(int,lab,lab_sz,n,"fcanonise");
DYNALLOC1(int,ptn,ptn_sz,n,"fcanonise");
DYNALLOC1(int,count,count_sz,n,"fcanonise");
DYNALLOC1(set,active,active_sz,m,"fcanonise");
DYNALLOC1(setword,workspace,workspace_sz,24*m,"fcanonise"); #endif
staticvoid
userlevel(int *lab, int *ptn, int level, int *orbits, statsblk *stats, int tv, int index, int tcellsize, int numcells, int cc, int n)
{ int i0,i;
if (level != 2) return;
issymm = TRUE;
i0 = nextelement(g0,gm,-1); if (i0 >= 0) for (i = i0; (i = nextelement(g0,gm,i)) >= 0;) if (orbits[i] != i0)
{
issymm = FALSE; return;
}
}
g is an input undirected graph without loops m,n of standard meaning. h is a place to put an output graph.
If g is transitive, return 1 or 2 and put a canonically labelled version of g into h. The value is 2 for symmetric graphs, and 1 for other transitive graphs. If g is not transitive, return 0. In that case h may or may not have something in it.
*/ int
istransitive(graph *g, int m, int n, graph *h)
{ int i,inv;
set *gw; short wt; int d,inv0,v,w;
statsblk stats; static DEFAULTOPTIONS_GRAPH(options); #if MAXN int lab[MAXN],ptn[MAXN],orbits[MAXN]; long x[MAXN]; int count[MAXN];
setword workspace[24*MAXM];
set workset[MAXM];
set sofar[MAXM],frontier[MAXM]; #else
DYNALLSTAT(int,lab,lab_sz);
DYNALLSTAT(int,ptn,ptn_sz);
DYNALLSTAT(int,orbits,orbits_sz);
DYNALLSTAT(int,count,count_sz);
DYNALLSTAT(setword,workspace,workspace_sz);
DYNALLSTAT(set,workset,workset_sz);
DYNALLSTAT(set,sofar,sofar_sz);
DYNALLSTAT(set,frontier,frontier_sz); #endif
void
tg_canonise(graph *g, graph *h, int m, int n) /* Canonise vertex-transitive graph */
{ int i; #if MAXN int lab[MAXN],ptn[MAXN],orbits[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(set,active,active_sz);
DYNALLSTAT(setword,workspace,workspace_sz); #endif
statsblk stats; static DEFAULTOPTIONS_GRAPH(options);
#if MAXN if (n > MAXN || m > MAXM)
{
fprintf(stderr,">E tg_canonise: m or n too large\n");
ABORT(">E tg_canonise");
} #else
DYNALLOC1(int,lab,lab_sz,n,"tg_canonise");
DYNALLOC1(int,ptn,ptn_sz,n,"tg_canonise");
DYNALLOC1(int,orbits,orbits_sz,n,"tg_canonise");
DYNALLOC1(set,active,active_sz,m,"tg_canonise");
DYNALLOC1(setword,workspace,workspace_sz,24*m,"tg_canonise"); #endif
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.