/* File cuprstab.c. Contains function uPartnStabilizer, the main function for a program that may be used to compute the stabilizer in a permutation group of an unordered partition. Also contains functions as follows:
uParStabRefnInitialize: Initialize set stabilizer refinement functions. setStabRefine: A refinement family based on the set stabilizer property.
isSetStabReducible: A function to check SSS-reducibility. */
static Partition *knownIrreducible[10] /* Null terminated 0-base list of */
= {NULL}; /* point sets Lambda for which top */ /* partition on UpsilonStack is */ /* known to be SSS_Lambda irred. */
/* COPIED FROM ORBREFN */ #define HASH( i, j) ( (7L * i + j) % hashTableSize )
typedefstruct RefnListEntry { Unsigned i; /* Cell number in UpsilonTop to split. */ Unsigned j; /* Orbit number of G^(level) in split. */ Unsigned newCellSize; /* Size of new cell created by split. */ struct RefnListEntry *hashLink; /* List of refns with same hash value. */ struct RefnListEntry *next; /* Next refn on list of all refinements. */ struct RefnListEntry *last; /* Last refn on list of all refinements. */
} RefnListEntry;
/* Function uPartnStabilizer. Returns a new permutation group representing the stabilizer in a permutation group G of an unordered partition Lambda of the point set Omega. The algorithm is based on Figure 9 in the paper
"Permutation group algorithms based on partitions" by the author. */
#define familyParm familyParm_L
PermGroup *uPartnStabilizer(
PermGroup *const G, /* The containing permutation group. */ const Partition *const Lambda, /* The point set to be stabilized. */
PermGroup *const L) /* A (possibly trivial) known subgroup of the stabilizer in G of Lambda. (A null pointer
designates a trivial group.) */
{ #ifdef xxxx
RefinementFamily OOO_G, SSS_Lambda;
RefinementFamily *refnFamList[3];
ReducChkFn *reducChkList[3];
SpecialRefinementDescriptor *specialRefinement[3];
ExtraDomain* extra[2];
/* Function uPartnImage. Returns a new permutation in a specified group G mapping a specified unordered partition Lambda to a specified unordered partition Xi. The algorithm is based on Figure 9 in the paper "Permutation group algorithms
based on partitions" by the author. */
Permutation *uPartnImage(
PermGroup *const G, /* The containing permutation group. */ const Partition *const Lambda, /* One of the partitions. */ const Partition *const Xi, /* The other partition. */
PermGroup *const L_L, /* A (possibly trivial) known subgroup of the stabilizer in G of Lambda. (A null pointer
designates a trivial group.) */
PermGroup *const L_R) /* A (possibly trivial) known subgroup of the stabilizer in G of Xi. (A null pointer
designates a trivial group.) */
{ #ifdef XXXXXX
RefinementFamily OOO_G, SSS_Lambda_Xi;
RefinementFamily *refnFamList[3];
ReducChkFn *reducChkList[3];
SpecialRefinementDescriptor *specialRefinement[3];
/* The function implements the refinement family uPartnStabRefine. Here ssS_{Lambda,i,j,p} acting on Pi (the top partition of UpsilonStack) splits from cell i of Pi those points lying in the union of the j'th cell group of Pi^(p) (the top partition on extra[p]->xUpsilonStack) on Omega^(p). Note Lambda is the base partition for extra[p]->xUpsilonStack
The family parameter is: familyParm[0].ptrParm: extra[p]->xUpsilonStack The refinement parameters are: refnParm[0].intParm: i, refnParm[1].intParm: j.
*/
// First check if the refinement acts nontrivially on UpsilonTop. If not // return immediately. cellSplits = FALSE; for ( m = startCell[cellToSplit]+1 , last = m -1 + cellSize[cellToSplit] ; m < last ; ++m ) if ( (xCellGroupNumber[LambdaCellNumber[pointList[m]]] == j) != (xCellGroupNumber[LambdaCelllNumber[pointList[m-1]]] == j) ) { cellSplits = TRUE; break; } if ( !cellSplits ) { split.oldCellSize = cellSize[cellToSplit]; split.newCellSize = 0; return split; }
// Now split cell cellToSplit of UpsilonTop. A variation of the splitting // algorithm used in quicksort is applied. if ( cellSize[i] <= xUpsilonStack->totalGroupSize[j] ) { left = startCell[i] - 1; right = startCell[i] + cellSize[i]; while ( left < right ) { while ( xCellGroupNumber[LambdaCellNumber[pointList[++left]]] != j ) ; while ( xCellGroupNumber[LambdaCellNumber[pointList[--right]]] == j ) ; if ( left < right ) { EXCHANGE( pointList[left], pointList[right], temp) EXCHANGE( invPointList[pointList[left]], invPointList[pointList[right]], temp) } } startNewCell = left; } else { startNewCell = startCell[i] + cellSize[i]; for ( k = xStartCellGroup[j] ; k < xStartCellGroup[j] + xCellGroupSize[j] ; ++k ) { t = xCellList[k]; for ( r = Lambda->startCell[t] ; LambdaCellNumber[Lambda->pointList[r]] == t ; ++r) { pt = Lambda->pointList[r]; if ( cellNumber[pt] == i ) { --startNewCell; m = invPointList[pt]; EXCHANGE( pointList[m], pointList[startNewCell], temp); EXCHANGE( invPointList[pointList[m]], invPointList[pointList[startNewCell]], temp); } } } }
++UpsilonStack->height; for ( m = startNewCell ; m < last ; ++m ) cellNumber[pointList[m]] = UpsilonStack->height; startCell[UpsilonStack->height] = startNewCell; parent[UpsilonStack->height] = i; cellSize[UpsilonStack->height] = last - startNewCell; cellSize[cellToSplit] -= cellSize[UpsilonStack->height]; split.oldCellSize = cellSize[i]; split.newCellSize = cellSize[UpsilonStack->height]; return split; #endif }
*/
#define RESTORE_ZERO for ( r = 1 ; r <= nonZeroCount ; ++r ) \
zeroArray[nonZeroPosition[r]] = 0; \
nonZeroCount = 0;
// The function implements the refinement family xPartnStabRefine. Here // xssS_{Pi,i,j,m,p} acting on Pi^(p) (the top partition of PiStack^(p)) // splits from cell group i of Pi^(p) those cells intersecting cell j of Pi // in exactly m points. / // // The family parameter is: // familyParm[0].ptrParm: extra[p]->xUpsilonStack // The refinement parameters are: // refnParm[0].intParm: i, // refnParm[1].intParm: j. // refnParm[2].intParm: m.
// Here we set zeroArray[j] to the cardinality of // (cell j of UpsilonTop) intersect (cell k of Lambda) for each k in // cell group i of xUpsilonTop. if ( xUpsilonStack->totalGroupSize[i] <= cellSize[j] ) for ( k = xStartCellGroup[i] ; k < xStartCellGroup[i] + xCellGroupSize[i] ; ++k ) { for ( r = Lambda->startCell[k] ; r <= Lambda->startCell[k] + Lambda->cellSize[k] ; ++ r ) { if ( cellNumber[Lambda->pointList[r]] == j ) { if ( zeroArray[k] == 0 ) nonZeroPosition[++nonZeroCount] = k; ++zeroArray[k]; } } else for ( r = startCell[j] ; r < startCell[j]+cellSize[j] ; ++j ) { t = LambdaCellNumber[pointList[r]] ); if ( xCellGroupNumber[t] == i ) { if ( zeroArray[t] == 0 ) nonZeroPosition[++nonZeroCount] = t; ++zeroArray[t]; } }
// Now reset zeroArray and return immediately if the cell group does not // split. splitFlag = nonSplitFlag = FALSE; if ( xUpsilonStack->cellCount > nonZeroCount ) if ( m == 0 ) splitFlag = TRUE; else nonSplitFlag = TRUE; for ( r = 1 ; r <= nonZeroCount && !splitFlag ; ++r ) if ( zeroArray[nonZeroPosition[r]] == m ) splitFlag = TRUE; for ( r = 1 ; r <= nonZeroCount && !nonSplitFlag ; ++r ) if ( zeroArray[nonZeroPosition[r]] != m ) nonSplitFlag = TRUE; if ( !splitFlag || !nonSplitFlag ) { RESTORE_ZERO split.oldCellSize = cellSize[cellToSplit]; split.newCellSize = 0; return split; }
// Now split cell group i of xUpsilonTop. A variation of the splitting // algorithm used in quicksort is applied. last = xStartCellGroup[i] + xCellGroupSize[i]; if ( xUpsilonStack->cellGroupSize[i] <= cellSize[j] ) { left = xStartCellGroup[i] - 1; right = xStartCellGroup[i] + xCellGroupSize[i]; while ( left < right ) { while ( zeroArray[++left]) != m ) ; while ( zeroArray[--right]) == m ) ; if ( left < right ) { EXCHANGE( xCellList[left], xCellList[right], temp) EXCHANGE( xInvCellList[xCellList[left]], xInvCellList[xCellList[right]], temp) } xStartNewCellGroup = left; } } else { xStartNewCellGroup = last; for ( r = startCell[j] ; r < startCell[j] + cellSize[j] ; ++r ) { t = LambdaCellNumber[pointList[r]]; if ( zeroArray[t] == m ) { zeroArray[t] = UNDEFINED; --xStartNewCellGroup; EXCHANGE( xCellList[t], xCellList[xStartNewCellGroup], temp) EXCHANGE( xInvCellList[xCellList[t]], xInvCellList[xCellList[xStartNewCellGroup]], temp) } } }
RefinementPriorityPair isOrbReducible( const RefinementFamily *family, // The refinement family mapping // must be orbRefine; family parm[0] // is the group. const PartitionStack *const UpsilonStack) { BOOLEAN cellWillSplit; Unsigned i, j, m, groupNumber, hashPosition, newCellNumber, oldCellNumber, count; unsigned long minPriority, thisPriority; UnsignedS *oldLevelAddr; UnsignedS *const pointList = UpsilonStack->pointList, *const startCell = UpsilonStack->startCell, *const cellSize = UpsilonStack->cellSize; PermGroup *G = family->familyParm_L[0].ptrParm; Unsigned level = family->familyParm_L[1].intParm; UnsignedS *orbNumberOfPt = G->orbNumberOfPt[level]; UnsignedS *const startOfOrbitNo = G->startOfOrbitNo[level]; RefinementPriorityPair reducingRefn; RefnListEntry *refnList; RefnListEntry *p, *oldP, *position, *minPosition;
// Check that the refinement mapping really is pointStabRefn, as required, // and that the group is one for which initializeOrbRefine has been // called. if ( family->refine != orbRefine ) ERROR( "isOrbReducible", "Error: incorrect refinement mapping"); for ( groupNumber = 0 ; groupNumber < refnData.groupCount && refnData.group[groupNumber] != G ; ++groupNumber ) ; if ( groupNumber >= refnData.groupCount ) ERROR( "isOrbReducible", "Routine not initialized for group.") hashTable = refnData.hashTable[groupNumber]; refnList = refnData.refnList[groupNumber]; oldLevelAddr = &refnData.oldLevel[groupNumber];
// If this is a new level, we reconstruct the list of potential refinements from scratch. if ( level != *oldLevelAddr ) {
// Initialize data structures. *oldLevelAddr = level; for ( i = 0 ; i < hashTableSize ; ++i ) hashTable[i] = NULL; freeListHeader = &refnList[0]; inUseListHeader = NULL; for ( i = 0 ; i < G->degree ; ++i) refnList[i].next = &refnList[i+1]; refnList[G->degree].next = NULL;
// Process the i'th cell of the top partition for i = 1,2,...., finding all // possible refinements. for ( i = 1 ; i <= UpsilonStack->height ; ++i ) {
// First check if the i'th cell will split. If not, proceed directly // to the next cell. for ( m = startCell[i]+1 , cellWillSplit = FALSE ; m < startCell[i] + cellSize[i] && !cellWillSplit ; ++m ) if ( orbNumberOfPt[ pointList[m] ] != orbNumberOfPt[ pointList[m-1] ] ) cellWillSplit = TRUE; if ( !cellWillSplit ) continue;
// Now find all splittings of the i'th cell and insert them into the // list in sorted order. for ( m = startCell[i] ; m < startCell[i]+cellSize[i] ; ++m ) { j = orbNumberOfPt[pointList[m]]; hashPosition = HASH( i, j); p = hashTable[hashPosition]; while ( p && (p->i != i || p->j != j) ) p = p->hashLink; if ( p ) ++p->newCellSize; else { if ( !freeListHeader ) ERROR( "isOrbReducible", "Refinement list exceeded bound (should not occur).") p = freeListHeader; freeListHeader = freeListHeader->next; p->next = inUseListHeader; if ( inUseListHeader ) inUseListHeader->last = p; p->last = NULL; inUseListHeader = p; p->hashLink = hashTable[hashPosition]; hashTable[hashPosition] = p; p->i = i; p->j = j; p->newCellSize = 1; } } } }
// If this is not a new level, we merely fix up the old list. The entries // for the new cell must be created and those for its parent must be // adjusted. else { freeListHeader = refnData.freeListHeader[groupNumber]; inUseListHeader = refnData.inUseListHeader[groupNumber]; newCellNumber = UpsilonStack->height; oldCellNumber = UpsilonStack->parent[UpsilonStack->height]; for ( m = startCell[newCellNumber] , cellWillSplit = FALSE ; m < startCell[newCellNumber] + cellSize[newCellNumber] ; ++m ) { if ( m > startCell[newCellNumber] && orbNumberOfPt[pointList[m]] != orbNumberOfPt[pointList[m-1]] ) cellWillSplit = TRUE; j = orbNumberOfPt[pointList[m]]; hashPosition = HASH( oldCellNumber, j); p = hashTable[hashPosition]; oldP = NULL; while ( p && (p->i != oldCellNumber || p->j != j) ) { oldP = p; p = p->hashLink; } if ( p ) { --p->newCellSize; if ( p->newCellSize == 0 ) deleteRefnListEntry( p, hashPosition, oldP); } } if ( cellWillSplit ) for ( m = startCell[newCellNumber] , cellWillSplit = FALSE ; m < startCell[newCellNumber] + cellSize[newCellNumber] ; ++m ) { hashPosition = HASH( newCellNumber, j); p = hashTable[hashPosition]; while ( p && (p->i != newCellNumber || p->j != j) ) p = p->hashLink; if ( p ) ++p->newCellSize; else { if ( !freeListHeader ) ERROR( "isOrbReducible", "Refinement list exceeded bound (should not occur).") p = freeListHeader; freeListHeader = freeListHeader->next; p->next = inUseListHeader; if ( inUseListHeader ) inUseListHeader->last = p; p->last = NULL; inUseListHeader = p; p->hashLink = hashTable[hashPosition]; hashTable[hashPosition] = p; p->i = newCellNumber; p->j = j; p->newCellSize = 1; } } }
// Now we return a refinement of minimal priority. While searching the // list, we also check for refinements invalidated by previous splittings. minPosition = inUseListHeader; minPriority = ULONG_MAX; count = 1; for ( position = inUseListHeader ; position && count < 100 ; position = position->next , ++count ) { while ( position && position->newCellSize == cellSize[position->i] ) { p = position; position = position->next; deleteRefnListEntry( p, hashTableSize+1, NULL); } if ( !position ) break; if ( (thisPriority = (unsigned long) position->newCellSize + MIN( cellSize[position->i], SIZE_OF_ORBIT(position->j) )) < minPriority ) { minPriority = thisPriority; minPosition = position; } } if ( minPriority == ULONG_MAX ) reducingRefn.priority = IRREDUCIBLE; else { reducingRefn.refn.family = (RefinementFamily *)(family); reducingRefn.refn.refnParm[0].intParm = minPosition->i; reducingRefn.refn.refnParm[1].intParm = minPosition->j; reducingRefn.priority = thisPriority; }
// If this is the last call to isOrbReducible for this group (UpsilonStack // has height degree-1), free memory and reinitialize. if ( UpsilonStack->height == G->degree - 1 ) { freePtrArrayDegree( refnData.hashTable[groupNumber]); free( refnData.refnList[groupNumber]); refnData.group[groupNumber] = NULL; --trueGroupCount; if ( trueGroupCount == 0 ) refnData.groupCount = 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.