staticvoid addStrongGeneratorNR(
PermGroup *G, /* Group to which strong gen is adjoined. */
Permutation *newGen); /* The new strong generator. It must move */
/* If initialization is requested, perform initializations. */ if ( sOptions.initialize ) {
/* Allocate fields within G. */ if ( G->base || G->basicOrbLen || G->basicOrbit || G->schreierVec )
ERROR( "schreierToddCoxeterSims", "A group field that must be null initially was nonnull.")
G->base = allocIntArrayBaseSize();
G->basicOrbLen = allocIntArrayBaseSize();
G->basicOrbit = (UnsignedS **) allocPtrArrayBaseSize();
G->schreierVec = (Permutation ***) allocPtrArrayBaseSize();
/* Allocate G->order and set G->order to 1. */ if ( !G->order ) {
G->order = allocFactoredInt();
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; return;
}
/* 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);
/* 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);
}
/* Expand the generator arrays if extra cosets are specified. */ if ( sOptions.maxExtraCosets > 0 )
expandGenerators( G, sOptions.maxExtraCosets);
/* Adjoin inverse permutations, and construct (or reconstruct) the
Schreier vectors, using all generators at each level. */ for ( gen = G->generator ; gen ; gen = gen->next ) if ( !gen->invPermutation )
adjoinInverseGen( G, gen); for ( level = 1 ; level <= G->baseSize ; ++level ) {
constructBasicOrbit( G, level, "AllGensAtLevel" );
svecOK[level] = TRUE;
}
/* Find max size for deduction queue, if not specified. */ if ( sOptions.maxDeducQueueSize == UNKNOWN )
sOptions.maxDeducQueueSize = 2 * degree + options.maxBaseSize +
sOptions.maxExtraCosets;
/* Add generator order and product order relators to relator list. */
tempWord.position = allocPtrArrayWordSize(); for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->name[0] != '*' ) {
pOrder = permOrder( gen); if ( pOrder > 2 && pOrder <= sOptions.genOrderLimit ) {
tempWord.length = pOrder; for ( j = 1 ; j <= pOrder ; ++j )
tempWord.position[j] = gen;
newRel = addRelatorSortedFromWord( G, &tempWord, TRUE, TRUE);
++numberOfRelators;
totalRelatorLength += newRel->length;
++numberSelected;
totalSelectedLength += newRel->length;
maxRelatorLength = MAX ( maxRelatorLength, newRel->length);
}
} if ( sOptions.prodOrderLimit >= 2 ) for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->name[0] != '*' ) for ( gen1 = gen->next ; gen1 ; gen1 = gen1->next ) if ( (pOrder = prodOrderBounded( gen, gen1,
sOptions.prodOrderLimit)) > 0 ) {
tempWord.length = 2 * pOrder; for ( j = 1 ; j <= pOrder ; ++j ) {
tempWord.position[2*j-1] = gen;
tempWord.position[2*j] = gen1;
}
newRel = addRelatorSortedFromWord( G, &tempWord, TRUE, TRUE);
++numberOfRelators;
totalRelatorLength += newRel->length;
++numberSelected;
totalSelectedLength += newRel->length;
maxRelatorLength = MAX ( maxRelatorLength, newRel->length);
}
freePtrArrayDegree( tempWord.position);
/* If G has any relators, construct the appropriate occurencesOfGen
lists. */ for ( rel = G->relator ; rel ; rel = rel->next ) {
numberAdded = addOccurencesForRelator( rel, MAX_INT);
informNewRelator( rel, numberAdded);
}
/* If extra cosets are specified, construct the data structures required
for extra cosets. */ if ( sOptions.maxExtraCosets ) {
nextCos = (Unsigned *) malloc( sizeof(Unsigned) *
(sOptions.maxExtraCosets+2) ); if ( !nextCos )
ERROR( "schreierToddCoxeterSims", "Out of memory.")
nextCos -= degree;
prevCos = (Unsigned *) malloc( sizeof(Unsigned) *
(sOptions.maxExtraCosets+2) ); if ( !prevCos )
ERROR( "schreierToddCoxeterSims", "Out of memory.")
prevCos -= degree;
ff = (Unsigned *) malloc( sizeof(Unsigned) *
(sOptions.maxExtraCosets+2) ); if ( !ff )
ERROR( "schreierToddCoxeterSims", "Out of memory.")
ff -= degree;
bb = (Unsigned *) malloc( sizeof(Unsigned) *
(sOptions.maxExtraCosets+2) ); if ( !bb )
ERROR( "schreierToddCoxeterSims", "Out of memory.")
bb -= degree;
equivCoset = (Unsigned *) malloc( sizeof(Unsigned) *
(degree+sOptions.maxExtraCosets+2) ); if ( !equivCoset )
ERROR( "schreierToddCoxeterSims", "Out of memory.")
/* Link the generators at specified level, using xNext. */
genHeader = linkGensAtLevel( G, level);
/* Flag all table entries at this level. Also empty the deduction
queue. */
MAKE_EMPTY( deductionQueue); for ( gen = genHeader ; gen ; gen = gen->xNext ) for ( i = 1 ; i <= basicOrbLen ; ++i ) {
pt = basicOrbit[i];
gen->image[pt] |= HB;
++totalTableEntries;
}
/* Now put the subgroup generator entries for H^(level+1) in the table,
and enqueue them. */ for ( gen = genHeader ; gen ; gen = gen->xNext ) if ( gen->level > level ) {
gen->image[basicOrbit[1]] = basicOrbit[1];
++tableEntriesFilled;
newDeduc.pnt = newDeduc.img = basicOrbit[1]; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
}
/* Now make those definitions corresponding to the Schreier vector. */ for ( i = 2 ; i <= basicOrbLen ; ++i ) {
pt = basicOrbit[i];
gen = schreierVec[pt];
prevPt = gen->invImage[pt] & NHB;
gen->image[prevPt] = pt;
++tableEntriesFilled;
newDeduc.pnt = prevPt; newDeduc.img = pt; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc); if ( gen->invImage[pt] & HB ) {
gen->invImage[pt] = prevPt;
++tableEntriesFilled;
newDeduc.pnt = pt; newDeduc.img = prevPt;
newDeduc.gn = gen->invPermutation;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc);
}
}
/* Perform initial enumerations till deduction queue is empty. */ while ( NOT_EMPTY(deductionQueue) ) {
DEQUEUE( deductionQueue , deduc);
findConsequences( deductionQueue, level, &deduc);
}
/* First time, allocate the deduction queue and definition list. */ if ( !deductionQueue ) {
deductionQueue = (DeductionQueue *) malloc( sizeof(DeductionQueue) ); if ( !deductionQueue )
ERROR( "xCheckStabilizer", "Out of memory.")
deductionQueue->deduc = (Deduction *) malloc(
sOptions.maxDeducQueueSize * sizeof(Deduction)); if ( !deductionQueue->deduc )
ERROR( "checkStabilizer", "Out of memory.")
defnList = (DefinitionList *) malloc( sizeof(DefinitionList) ); if ( !defnList )
ERROR( "xCheckStabilizer", "Out of memory.")
defnList->coset = (Unsigned *) malloc(
sOptions.maxExtraCosets * sizeof(Unsigned) ); if ( !defnList->coset )
ERROR( "xCheckStabilizer", "Out of memory.")
defnList->image = (Unsigned *) malloc(
sOptions.maxExtraCosets * sizeof(Unsigned) ); if ( !defnList->image )
ERROR( "xCheckStabilizer", "Out of memory.")
defnList->gen = (Permutation **) malloc(
sOptions.maxExtraCosets * sizeof(Permutation *) ); if ( !defnList->gen )
ERROR( "xCheckStabilizer", "Out of memory.")
}
totalTableEntries = tableEntriesFilled = 0;
/* Compute number of extra cosets at this level. */
extraCosetsAtLevel = (Unsigned) MIN(
(unsignedlong) sOptions.maxExtraCosets,
sOptions.percentExtraCosets * ((unsignedlong) basicOrbLen + 99) / 100 );
currentExtraCosets = 0;
/* Link the generators at specified level, using xNext. */
genHeader = linkGensAtLevel( G, level);
/* Initialize data structures for extra cosets. */
firstCos = 0;
freeCosHeader = degree + 1; for ( i = 1 ; i <= degree ; ++i )
equivCoset[i] = i; for ( i = degree + 1 ; i < degree + extraCosetsAtLevel ; ++i )
nextCos[i] = i + 1;
nextCos[degree+extraCosetsAtLevel] = 0; for ( i = degree + 1 ; i <= degree + extraCosetsAtLevel ; ++i )
bb[i] = i; for ( gen = genHeader ; gen ; gen = gen->xNext ) for ( i = degree + 1 ; i <= degree + extraCosetsAtLevel ; ++i )
gen->image[i] = HB;
defnList->head = defnList->tail = defnList->size = 0;
/* Flag all table entries at this level. Also empty the deduction
queue. */
MAKE_EMPTY( deductionQueue); for ( gen = genHeader ; gen ; gen = gen->xNext ) for ( i = 1 ; i <= basicOrbLen ; ++i ) {
pt = basicOrbit[i];
gen->image[pt] |= HB;
++totalTableEntries;
}
/* Now put the subgroup generator entries for H^(level+1) in the table,
and enqueue them. */ for ( gen = genHeader ; gen ; gen = gen->xNext ) if ( gen->level > level ) {
gen->image[basicOrbit[1]] = basicOrbit[1];
++tableEntriesFilled;
newDeduc.pnt = newDeduc.img = basicOrbit[1]; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
}
/* Now make those definitions corresponding to the Schreier vector. */ for ( i = 2 ; i <= basicOrbLen ; ++i ) {
pt = basicOrbit[i];
gen = schreierVec[pt];
prevPt = gen->invImage[pt] & NHB;
gen->image[prevPt] = pt;
++tableEntriesFilled;
newDeduc.pnt = prevPt; newDeduc.img = pt; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc); if ( gen->invImage[pt] & HB ) {
gen->invImage[pt] = prevPt;
++tableEntriesFilled;
newDeduc.pnt = pt; newDeduc.img = prevPt;
newDeduc.gn = gen->invPermutation;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc);
}
}
/* Perform initial enumerations till deduction queue is empty. */ while ( NOT_EMPTY(deductionQueue) ) {
DEQUEUE( deductionQueue , deduc);
xFindConsequences( G, deductionQueue, level, &deduc, genHeader);
}
/* DEBUGGING -- REQUIRES FIXING, SINCE THERE SHOULD BE NO EXTRA COSETS HERE. */ for ( j = firstCos ; j ; j = nextCos[j] ) for ( gen = genHeader ; gen ; gen = gen->xNext ) if ( gen->image[j] < degree )
gen->invImage[gen->image[j]] = equivCoset[j];
/* The function computeSchreierGen( G, level, point, gen) computes the Schreiergeneratoru_level(point)*gen*bar(u_level(point^gen))^-1 forG^(level+1).HerepointmustlieinDelta_levelandgenmustbe ageneratorinG^(level).Thefunctionreturnsaword(withnewly allocatedpositionfield),representingtheSchreiergenerator,andanew imagearray,representingtheimageof1,2,...,nundertheword.
NOTEthisfunctiontakesaccountofthefactthatgeneratingpermutations
may have the leftmost bit set as a flag. */
/* The function xComputeSchreierGen( G, level, point, gen) is identical to computeSchreierGen(G,level,point,gen)exceptthatittakesaccount
of the possibility of temporary cosets ( > degree) in the table. */
/* The function reduce( G, level, j, wh) takes a word-image pair representing anelementofG^(level)anditmodifiesitbyright-multiplyingby u_{level+1}^-1(d_{level+1}...u_{j-1}^-1(d_{level+1})sothatitfixes a_{level+1},...,a_{j-1}andeither i)j<=G->baseSize,anda_j^whnotinDelta_j. ii)j==G->baseSize+1,andwh!=1. iii)j==G->baseSize+1,andwh==1.
It returns false in cases (i) and (ii) and true in case (iii). */
/* The function xReduce( G, level, j, wh) is identical to Reduce(G,level,j,wh)exceptthatittakesaccountofthepossibility
of temporary cosets ( > degree) in the table. */
/* This function may be used to adjoin a new strong generator to a permutationgroupWITHOUTreconstructingbasicorbits.Also,the
essential fields are not modified in any way. */
void addStrongGeneratorNR(
PermGroup *G, /* Group to which strong gen is adjoined. */
Permutation *newGen) /* The new strong generator. It must move
a base point (not checked). */
{ Unsigned i;
/* Append inverse image of new strong generator, if absent. */ if ( !newGen->invImage )
adjoinInvImage( newGen);
/* Find level of new strong generator. */
newGen->level = levelIn( G, newGen);
/* The function prodOrderBounded( perm1, perm2, bound) returns the order of theproductofpermutationsperm1andperm2,providedthisorderisless
than or equal to bound, and returns 0 otherwise. */
¤ 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.0.22Bemerkung:
(vorverarbeitet am 2026-06-26)
¤
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.