/* The function insertBasePoint may be used to insert a new point into the baseforapermutationgroupataspecifiedlevel.Basepointsata lowerlevelareunchanged.Atahigherlevel,thenewbasepointsare arbitrary;redundantbasepointsatahigherlevelareremoved.Itis assumedthatthebasepointtobeinserteddiffersfromallbasepoints atahigherlevel.ArandomSchreierapproachisused.Currentlyall wordsaremultipliedoutatgenerated.
Note:insertBasePointdoesnotworkforgroupsthathavebeencompressed
nor on groups for which inverse permutations exist. */
void insertBasePoint(
PermGroup *G, /* The permutation group (base and sgs known). */ Unsigned newLevel, /* If newLevel = i and newBasePoint = b, the */ Unsigned newBasePoint) /* base for G is changed from (b[1],..., */ /* b(i-1),...) to (b[1],...,b[i-1],b,...). */
{ Unsigned level, pt, image, i, uTemp1, uTemp2, uTemp3;
UnsignedS *conjugateMap, *conjugateMapInv, *tempImg;
UnsignedS *temp1, *temp2, *temp3, *temp4;
FactoredInt oldOrder, oldLen;
Permutation *gen, *tempGen, *randGen;
Permutation **svec, **tempSVec, **temp5;
UnsignedS *oldBasicOrbLen = allocIntArrayBaseSize();
UnsignedS **oldBasicOrbit = (UnsignedS **) allocPtrArrayBaseSize();
Permutation ***oldSchreierVec = (Permutation ***) allocPtrArrayBaseSize(); char *isGenAtLevel = allocBooleanArrayBaseSize(); unsigned loopCount = 0; /* For bug fix wrt random number generator. */
/* First we handle the trivial case in which newLevel == G->baseSize+1 (Thelargestvalueitshouldeverhave).Herewejustextend
the base. */ if ( newLevel == G->baseSize+1 ) {
G->base[++G->baseSize] = newBasePoint;
G->basicOrbLen[G->baseSize] = 1;
G->basicOrbit[G->baseSize] = allocIntArrayDegree();
G->basicOrbit[G->baseSize][1] = G->base[G->baseSize];
G->schreierVec[G->baseSize] = allocPtrArrayDegree(); for ( i = 1 ; i <= G->degree ; ++i )
G->schreierVec[G->baseSize][i] = NULL;
G->schreierVec[G->baseSize][G->base[G->baseSize]] = FIRST_IN_ORBIT;
freeIntArrayBaseSize( oldBasicOrbLen);
freePtrArrayBaseSize( oldBasicOrbit);
freePtrArrayBaseSize( oldSchreierVec);
freeBooleanArrayBaseSize( isGenAtLevel); return;
}
/* If the base point is already present at the correct level, there is
nothing to do, so return. */ if ( G->base[newLevel] == newBasePoint ) {
freeIntArrayBaseSize( oldBasicOrbLen);
freePtrArrayBaseSize( oldBasicOrbit);
freePtrArrayBaseSize( oldSchreierVec);
freeBooleanArrayBaseSize( isGenAtLevel); return;
}
/* If the new base point is conjugate in G^(newLevel) to the old, and if newLevel<=MAX_CONJ_LEVEL,wemerelyconjugatetheoldbaseand
return. */ if ( newLevel <= MAX_CONJ_LEVEL && G->schreierVec[newLevel][newBasePoint] ) {
conjugateMapInv = allocIntArrayDegree();
conjugateMap = allocIntArrayDegree();
tempSVec = allocPtrArrayDegree(); for ( pt = 1 ; pt <= G->degree ; ++pt )
conjugateMapInv[pt] =
G->schreierVec[newLevel][newBasePoint]->invImage[pt];
image = conjugateMapInv[newBasePoint]; while ( image != G->base[newLevel] ) {
REPLACE_BY_INV_IMAGE( conjugateMapInv, G->schreierVec[newLevel][image],
G->degree, temp1, temp2, temp3, temp4)
image = conjugateMapInv[newBasePoint];
}
SET_TO_INVERSE( conjugateMapInv, conjugateMap, G->degree,
temp1, temp2, uTemp1, uTemp2, uTemp3) for ( level = 1 ; level <= G->baseSize ; ++level ) {
G->base[level] = conjugateMap[G->base[level]]; for ( i = 1 ; i <= G->basicOrbLen[level] ; ++i )
G->basicOrbit[level][i] = conjugateMap[G->basicOrbit[level][i]]; for ( pt = 1 ; pt <= G->degree ; ++pt )
tempSVec[conjugateMap[pt]] = G->schreierVec[level][pt];
EXCHANGE( G->schreierVec[level], tempSVec, temp5)
}
tempImg = conjugateMapInv; for ( gen = G->generator ; gen ; gen = gen->next ) { for ( pt = 1 ; pt <= G->degree ; ++pt )
tempImg[conjugateMap[pt]] = conjugateMap[gen->image[pt]];
EXCHANGE( gen->image, tempImg, temp4); if ( gen->invImage == tempImg )
gen->invImage = gen->image; else {
SET_TO_INVERSE( gen->image, gen->invImage, G->degree,
temp1, temp2, uTemp1, uTemp2, uTemp3)
}
}
freeIntArrayDegree( conjugateMap);
freeIntArrayDegree( tempImg);
freePtrArrayDegree( tempSVec);
freeIntArrayBaseSize( oldBasicOrbLen);
freePtrArrayBaseSize( oldBasicOrbit);
freePtrArrayBaseSize( oldSchreierVec);
freeBooleanArrayBaseSize( isGenAtLevel); return;
}
/* Now we insert the new base point into the base for G. Note the base point maybeduplicatedatahigherlevel.Thisshouldn'tcauseaproblem,and lateritwillbedeletedasredundant.Atthispoint,wedon'tallocate
another basic orbit vector or Schreier vector. */
randGen = newIdentityPerm(G->degree);
++G->baseSize; if ( G->baseSize > options.maxBaseSize )
ERROR1i( "insertBasePoint", "Base size exceeded maximum of ",
options.maxBaseSize, ". Rerun with -mb option."); for ( level = G->baseSize ; level > newLevel ; --level )
G->base[level] = G->base[level-1];
G->base[newLevel] = newBasePoint;
/* Here we allocate new basic-orbit vectors and Schreier vectors for G atlevelsnewLevelandhigher.(Theoldbasic-orbitvectorsand Schreiervectorsattheselevelsmustpreservedatthispoint;thiswill bedoneinarraysoldBasicOrbitandoldSchreierVec,andtheold basicorbitlengthsatlevelsnewLevelandhigherwillbepreservedin
oldBasicOrbLen.) */ for ( level = newLevel ; level <= G->baseSize ; ++level ) {
oldBasicOrbLen[level] = G->basicOrbLen[level];
oldBasicOrbit[level] = G->basicOrbit[level];
oldSchreierVec[level] = G->schreierVec[level];
G->basicOrbit[level] = allocIntArrayDegree();
G->schreierVec[level] = allocPtrArrayDegree();
}
/* Here we record the order of G, and then modify it to remove the contributionofthebasicorbitsatlevelsnewLevelandabove.We
also set these basic orbit lengths to 1. */
oldOrder = *G->order; for ( level = newLevel ; level < G->baseSize ; ++level ) {
oldLen = factorize( oldBasicOrbLen[level]);
factDivide( G->order, &oldLen);
G->basicOrbLen[level] = 1;
}
G->basicOrbLen[G->baseSize] = 1;
/* Here we adjust the levels of the generators of G. Generators not essentialatsomelevellessthannewLevelareflaggedforlater removalbysettingtheirlevelto0.Thesegeneratorscannotbe deletednowbecausetheirinvImagefieldsarestillneededbelow. However,theimagefieldwillbedeletednowunlessitisthe invImagefieldofanothergenerator(i.e.,unlessthe inversePermutationfieldisnonnull.(Notethattemporarily wehaveaninvaliddatastructureforpermutations.)Wealsoflag thoseintegersiwithi>=newLevelforwhichthereremainsa
generator at level i. */ for ( level = newLevel ; level <= G->baseSize ; ++level )
isGenAtLevel[level] = FALSE; for ( gen = G->generator ; gen ; gen = gen->next ) if ( ESSENTIAL_BELOW_LEVEL(gen,newLevel) ) { if ( gen->level >= newLevel ) {
gen->level = (gen->image[newBasePoint] != newBasePoint ) ?
newLevel : (gen->level + 1);
isGenAtLevel[gen->level] = TRUE;
}
} else {
gen->level = 0; if ( gen->image != gen->invImage ) {
freeIntArrayDegree( gen->image);
gen->image = NULL;
}
MAKE_NOT_ESSENTIAL_ALL( gen);
}
/* Now we construct the initial basic orbits at levels newLevel and higher,usinganyoldgeneratorsretainedbecausetheywere essentialatahigherlevel.NoteconstructBasicOrbitmust
must flag essential generators. We also adjust the order of G*/ for ( level = newLevel ; level <= G->baseSize ; ++level ) if ( isGenAtLevel[level] )
constructBasicOrbit( G, level, "FindEssential"); else {
G->basicOrbit[level][1] = G->base[level]; for ( pt = 1 ; pt <= G->degree ; ++pt )
G->schreierVec[level][pt] = NULL;
G->schreierVec[level][G->base[level]] = FIRST_IN_ORBIT;
}
/* Now we repeatedly construct and test random elements of G^(newLevel) untiltheproductofthebasicorbitlengthsislargeenough,i.e.,
until newOrder = oldOrder. */ while ( !factEqual( &oldOrder, G->order) ) {
/* Set randGen to a random permutation of G^(newLevel). */ for ( i = 1 ; i <= G->degree ; ++i )
randGen->image[i] = i; for ( level = newLevel ; level < G->baseSize ; ++level ) {
++loopCount; /* These four lines shouldn't */ if ( loopCount % 37 == 0 || /* be needed. They overcome */
loopCount % 181 == 0 ) /* a deficiency in the random */
randInteger(1,2); /* number generator. */
pt = oldBasicOrbit[level][ randInteger(1,oldBasicOrbLen[level]) ];
svec = oldSchreierVec[level]; while ( svec[pt] != FIRST_IN_ORBIT ) {
REPLACE_BY_INV_IMAGE( randGen->image, svec[pt], G->degree,
temp1, temp2, temp3, temp4)
pt = svec[pt]->invImage[pt];
}
}
/* Attempt to factor randGen in terms of the new base. The loop terminatesnormallywithlevel==G->baseSize+1ifgcanbefactored, anditterminatesviatheexitstatementwithlevel<=G->baseSize
otherwise. */ for ( level = newLevel ; level <= G->baseSize ; ++level ) { if ( G->schreierVec[level][randGen->image[G->base[level]]] == NULL ) break; while ( randGen->image[G->base[level]] != G->base[level] ) {
REPLACE_BY_INV_IMAGE( randGen->image,
G->schreierVec[level][randGen->image[G->base[level]]],
G->degree, temp1, temp2, temp3, temp4)
}
}
/* If randGen could not be factored, we adjoin it (as modified above) asastronggeneratorrelativetothenewbase.Notethatthelevelof randGenisthecurrentvalueofthevariablelevel.Ifrandpermis
added, we reallocate it. */ if ( level <= G->baseSize ) { if ( isInvolution( randGen) ) { if ( randGen->image != randGen->invImage )
freeIntArrayDegree( randGen->invImage);
randGen->invImage = randGen->image;
} else { if ( randGen->image == randGen->invImage )
randGen->invImage = allocIntArrayDegree();
SET_TO_INVERSE( randGen->image, randGen->invImage, G->degree,
temp1, temp2, uTemp1, uTemp2, uTemp3)
}
addStrongGenerator( G, randGen, newLevel==1);
randGen = newIdentityPerm( G->degree);
}
}
/* Now we free the old basic orbit vectors and Schreier vectors, as well as
the permutation randGen. */ for ( level = newLevel ; level < G->baseSize ; ++level ) {
freeIntArrayDegree( oldBasicOrbit[level]);
freePtrArrayDegree( oldSchreierVec[level]);
}
deletePermutation( randGen);
/* Now we remove generators flagged for removal above. Note we cannot employdeletePermutationbecausewedonothaveavalidpermutation
data structure, as noted above. */
gen = G->generator; while ( gen ) if ( gen->level == 0 ) { if ( gen->last )
gen->last->next = gen->next; else
G->generator = gen->next; if ( gen->next )
gen->next->last = gen->last;
tempGen = gen;
gen = gen->next;
freeIntArrayDegree( tempGen->invImage);
freePermutation( tempGen);
} else
gen = gen->next;
/* Finally we remove redundant base points at level newLevel+1 or greater. */ for ( level = newLevel+1 ; level <= G->baseSize ; ++level ) if ( G->basicOrbLen[level] == 1 ) {
--G->baseSize;
freeIntArrayDegree( G->basicOrbit[level]);
freePtrArrayDegree( G->schreierVec[level]); for ( i = level ; i <= G->baseSize ; ++i ) {
G->base[i] = G->base[i+1];
G->basicOrbLen[i] = G->basicOrbLen[i+1];
G->basicOrbit[i] = G->basicOrbit[i+1];
G->schreierVec[i] = G->schreierVec[i+1];
} for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->level > level ) {
--gen->level; for ( i = level ; i <= G->baseSize ; ++i ) if ( ESSENTIAL_AT_LEVEL(gen,i+1) )
MAKE_ESSENTIAL_AT_LEVEL(gen,i); else
MAKE_NOT_ESSENTIAL_AT_LEVEL(gen,i);
MAKE_NOT_ESSENTIAL_AT_LEVEL(gen,G->baseSize+1);
}
--level;
}
/* The function changeBase changes the base (and updates the strong generatingset)forapermutationgroupwithknownbaseandstrong
generating set. */
void changeBase(
PermGroup *G, /* The permutation group. */
UnsignedS *newBase) /* An origin-1 null-terminated sequence of points. */ /* The new base will consist of newBase, followed */ /* by arbitrary extra points as needed. Redundant */ /* base points will not be deleted from newBase, */ /* but no redundant points will be adjoined. */
{ Unsigned level;
/* This static function constructCandidateList( G, level) is called only by functionremoveRedunSGens.ItconstructsandreturnsanxNext-linkedlist ofallgeneratorsofGatlevellevelorabove,orderedsothatpresumably "desirable"generatorsoccurfirst.Theorderingisasfollows: 0)Generatorsessentialatlevelslevel-1orhighercomefirst. 1)Asinglegeneratoratlevellevel,ifnotpresentin(1)above,comes next. 2)Generatorsessentialatlevelslevel+1,..,G->baseSizecomenext. 3)Anyremaininggeneratorsatlevellevelcomenext. 4)Finally,anyremaininggeneratorsatlevelslevel+1,...,G->baseSize comelast. Atagivenlevel,involutorygeneratorsprecedenoninvolutoryones. NotethexLastfieldisusedasaflaghere;anullvaluesignifiesthat thegeneratorisnottobeconsideredforadditiontothelist,either
because it has level below level or it is already on the list. */
/* Initializer xLast, as above. */ for ( gen = G->generator ; gen ; gen = gen->next )
gen->xLast = ( gen->level >= level ) ? (Permutation *) TRUE : NULL;
/* First we add any generators in class (0) above. */ for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->xLast && ESSENTIAL_BELOW_LEVEL(gen,level) ) {
ADD_TO_LIST(0); if ( gen->level == level )
genAtLevelAdded = TRUE;
}
/* Next we add a possible generator in class (1) above. */ if ( !genAtLevelAdded ) for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->xLast && gen->level == level ) {
ADD_TO_LIST(1); break;
}
/* Next we add any generators in class (2) above. */ for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->xLast && ESSENTIAL_ABOVE_LEVEL(gen,level) )
ADD_TO_LIST(2);
/* Next we add any generators in class (3) above. */ for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->xLast && gen->level == level )
ADD_TO_LIST(3);
/* Finally we add any generators in class (4) above. */ for ( gen = G->generator ; gen ; gen = gen->next ) if ( gen->xLast )
ADD_TO_LIST(4);
/* Finally we concatenate the lists. */
combinedList = NULL;
endPreviousList = NULL; for ( m = 0 ; m <= 9 ; ++ m ) if ( listHeader[m] ) { if ( endPreviousList )
endPreviousList->xNext = listHeader[m]; else
combinedList = listHeader[m]; for ( endPreviousList = listHeader[m] ;
endPreviousList->xNext ;
endPreviousList = endPreviousList->xNext )
;
endPreviousList->xNext = NULL;
}
/* Return a pointer to the list. */ return combinedList;
}
/* The function removeRedunSGens( G, startLevel) removes redundant strong generatorsfromthegroupGatlevelsstartLevel,startLevel+1,..,G->baseSize. Theessentialfieldsatlevels1,...,startLevel-1mustbeset;thefunction setsthoseatotherlevels.Inversepermutationsmustnotyethavebeen
added. The function returns the number of generators removed. */
/* Flag all generators as nonessential at levels startLevel,startLevel+1,...,
G->baseSize. */ for ( gen = G->generator ; gen ; gen = gen->next )
MAKE_NOT_ESSENTIAL_ATABOV_LEVEL( gen, startLevel);
/* Free generators that are not essential at any level. */
gen = G->generator; while ( gen ) if ( ! ESSENTIAL_BELOW_LEVEL(gen,G->baseSize+1 ) ) { if ( gen->last )
gen->last->next = gen->next; else
G->generator = gen->next; if ( gen->next )
gen->next->last = gen->last;
tempGen = gen;
gen = gen->next;
deletePermutation( tempGen);
++removalCount;
} else
gen = gen->next;
/* The function restrictBasePoints( G, acceptablePoint) attempts to change thebaseforGsothatallbasepointslieinthe1-basednull-terminated listacceptablePointofpoints.Itproducesabaseoftheform a[1],...,a[m],a[m+1],...,a[k],wherea[1],...,a[m]lieinthelistof acceptablepointsandwhereanypermutationinG^(m+1)fixesanypointin
the list. It returns m. */
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.