/* This function removes any identity generators for a group G. It is assumedthatthegroupdoesnothaveabaseandstronggeneratingset;in particular,Schreiervectorsarenotmodified.(Presumablytheyarenot
present.) */
void removeIdentityGens(
PermGroup *const G) /* The group G mentioned above. */
{
Permutation *gen, *tempGen;
for ( gen = G->generator ; gen ; gen = gen->next ) if ( isIdentity( gen) ) {
tempGen = gen; if ( tempGen->last ) {
tempGen->last->next = tempGen->next;
gen = tempGen->last;
} else {
G->generator = tempGen->next;
gen = G->generator;
} if ( tempGen->next )
tempGen->next->last = tempGen->last;
deletePermutation( tempGen);
}
}
/* This function adjoins to each generator in a permutation group G (not havingabaseandstronggeneratingset)thearrayofinverseimages, provideditisnotalreadypresent.Forinvolutorygenerators,G->image
and G->invImage point to the same array. */
void adjoinGenInverses(
PermGroup *const G) /* The group mentioned above. */
{
Permutation *gen; for ( gen = G->generator ; gen ; gen = gen->next ) if ( !gen->invImage )
adjoinInvImage( gen);
}
/* This function constructs an initial segment of the base for a permutation groupG.Whencalled,thebasemustnotexist(G->base==NULL).The initialbasepointsareselectedsothat,uponreturn,eachgenerator movessomebasepoint.Thefunctionattemptstochoosebasepointsso thatasmanygeneratorsaspossible(butnotall)fixaninitialsegment ofthebase.TheonlyfieldinthegroupGthatisallocatedisthebase
field. */
void initializeBase(
PermGroup *const G) /* The group G mentioned above. */
{ Unsigned pt, count, maxCount, newBasePt;
BOOLEAN ok;
Permutation *gensFixingBase, *perm, *lastPerm;
G->baseSize = 0;
/* The xNext field of the generators will be used to maintain a singly- linkedlistofthosegeneratorsfixingtheinitialsegmentofthebase
chosen so far. Here the list is initialized to all generators. */
gensFixingBase = G->generator; for ( perm = G->generator ; perm ; perm = perm->next )
perm->xNext = perm->next;
/* As long as some generator fixes the initial base segment, we find a newbasepointfixedbyamaximalnumber(butnotall)suchgenerators.
A noninvolutory generator is counted twice. */ while ( gensFixingBase ) {
maxCount = UNKNOWN; for ( pt = 1 ; pt <= G->degree ; ++pt ) { for ( count = 0 , ok = FALSE , perm = gensFixingBase ; perm ;
perm = perm ->xNext ) if ( perm->image[pt] == pt )
count += (perm->image == perm->invImage) ? 1 : 2; else
ok = TRUE; if ( (maxCount == UNKNOWN || count > maxCount) && ok ) {
newBasePt = pt;
maxCount = count;
}
} if ( G->baseSize < options.maxBaseSize )
G->base[++G->baseSize] = newBasePt; else
ERROR1i( "initializeBase", "Base size exceeded maximum of ",
options.maxBaseSize, ". Rerun with -mb option.")
/* Here we reconstruct the list of generators fixing the initial base
segment. */ for ( perm = gensFixingBase , gensFixingBase = NULL ; perm ;
perm = perm->xNext ) if ( perm->image[newBasePt] == newBasePt ) { if ( gensFixingBase )
lastPerm->xNext = perm; else
gensFixingBase = perm;
lastPerm = perm;
} if ( gensFixingBase )
lastPerm->xNext = NULL;
}
}
/* This function produces a (hopefully) quasi-random element of a group G by takingapreviously-computedquasi-randomelement(randGen)anymultiplying itontherightbyarandomwordoflengthinaspecifiedrange (count1,count1+1,...,count2)inalist(genList)ofpermutations(which shouldgeneratethegroupG).Thelengthofthewordispseudo-random
in the range given above. */
staticvoid randomizeGen( constUnsigned genListLength, /* The length of the list genList. */ const Permutation *const *genList, /* The list of (generating) perms. */ constUnsigned count1, /* The minimum word length, as above. */ constUnsigned count2, /* The maximum word length, as above. */
Permutation *const randGen) /* The old and new quasi-random elt. */
{ Unsigned i,
wordLength = count1 +
( (count2 > count1) ? randInteger( 0, count2-count1) : 0); for ( i = 1 ; i <= wordLength ; ++i )
rightMultiply( randGen, *(genList + randInteger(1,genListLength)) );
}
/* This function writes an element (perm) of a permutation group G as perm=u_1'u_2'...u_{j-1}'h whereu_1',...,u_{j-1}'areinversesofcosetrepresentatives (u_p'inG^(p))andhisanelementofG^(j-1)(i.e.,hhaslevelj) suchthatoneofthefollowingholds: 1)j<=G->baseSizeandhmapsG->base[j]outsidethej'thbasicorbit. 2)j==G->baseSize+1andh!=1. 3)j==G->baseSize+1andh=1. ItreturnsTRUEincase(3)aboveandFALSEotherwise.Italsoreplaces
perm by h and returns the value of j as finalLevel. */
static BOOLEAN factorGroupElt( const PermGroup *const G, /* The permutation group, as above. */
Permutation *const perm, /* The permutation to factor, as above. */
Permutation *const h, /* Set to the permutation h, as above. Must
be preallocated of correct degree. */ Unsigned *const finalLevel) /* The value of j, as above. */
{ Unsigned level, img;
copyPermutation( perm, h); for ( level = 1 ; level <= G->baseSize ; ++level ) {
img = h->image[G->base[level]]; if ( G->schreierVec[level][img] ) while ( G->schreierVec[level][img] != FIRST_IN_ORBIT ) {
rightMultiplyInv( h, G->schreierVec[level][img]);
img = h->image[G->base[level]];
} else break;
}
*finalLevel = level; if ( *finalLevel == G->baseSize+1 ) return isIdentity( h); else returnFALSE;
}
if ( level <= G->baseSize ) { /* Replace h by h^d, where d is maximal subject to d dividing |h| and
h^d mapping G->base[level] outside the level'th basic orbit. */
img = G->base[level];
hCycleLen = 0; do {
hCycle[hCycleLen++] = img;
img = h->image[img];
} while ( img != G->base[level] ); for ( i = 2 ; i <= hCycleLen/2 ; ++i ) if ( hCycleLen % i == 0 &&
G->schreierVec[level][hCycle[hCycleLen/i]] == NULL ) {
raisePermToPower( h, hCycleLen / i); break;
}
} else { /* Replace h by h^d, where d is maximal subject to d dividing |h| and
d < |h|. */
hOrder = permOrder( h); for ( i = 0 ; primeList[i] != 0 ; ++i ) { if ( hOrder % primeList[i] == 0 )
raisePermToPower( h, hOrder / primeList[i]); break;
}
}
/* Check that fields of G that must be null initially actually are. Then
allocate these fields. */ if ( G->base || G->basicOrbLen || G->basicOrbit || G->schreierVec )
ERROR( "randschr", "A group field that must be null initially was " "nonnull.")
G->base = allocIntArrayBaseSize();
G->basicOrbLen = allocIntArrayBaseSize();
G->basicOrbit = (UnsignedS **) allocPtrArrayBaseSize();
G->schreierVec = (Permutation ***) allocPtrArrayBaseSize();
/* If the true group order is known, set trueGroupOrder to it. Otherwise allocateG->orderandmarktrueGroupOrderasundefined(i.e.,
noOfFactors == UNKNOWN). Then set G->order to 1. */ if ( G->order )
trueGroupOrder = *G->order; else {
G->order = allocFactoredInt();
trueGroupOrder.noOfFactors = UNKNOWN;
}
G->order->noOfFactors = 0;
/* Delete identity generators from G if present. Return immediately if
G is the identity group. */
removeIdentityGens( G); if ( !G->generator) { /* Should we allocate G->base, etc??? */
G->baseSize = 0; returnTRUE;
}
/* Adjoin an inverse image array to each permutation if absent. */
adjoinGenInverses( G);
/* Choose an initial segment of the base so that each generator moves
some base point. */
initializeBase( G);
/* Here we allocate and construct an array of pointers to the original
generators. */
noOfOriginalGens = 0;
originalGen = allocPtrArrayDegree(); for ( gen = G->generator ; gen ; gen = gen->next )
originalGen[++noOfOriginalGens] = gen;
/* Fill in the level of each generator, and make each generator essential
at its level and above. (????) */ for ( gen = G->generator ; gen ; gen = gen->next ) {
gen->level = levelIn( G, gen);
MAKE_NOT_ESSENTIAL_ALL( gen); for ( level = 1 ; level <= gen->level ; ++level )
MAKE_ESSENTIAL_AT_LEVEL( gen, level);
}
/* The variable successCount will count the number of consecutive times
the quasi-random group element can be factored successfully. */
successCount = 0;
nonInvolRejectCount = 0;
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.