/* File cuprstab.c. Contains function uPartnStabilizer, the main function for a programthatmaybeusedtocomputethestabilizerinapermutationgroup ofanunorderedpartition.Alsocontainsfunctionsasfollows:
uParStabRefnInitialize:Initializesetstabilizerrefinementfunctions. setStabRefine:Arefinementfamilybasedonthesetstabilizer 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 stabilizerinapermutationgroupGofanunorderedpartitionLambdaofthe pointsetOmega.ThealgorithmisbasedonFigure9inthepaper
"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 stabilizerinGofLambda.(Anullpointer
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 aspecifiedunorderedpartitionLambdatoaspecifiedunorderedpartition Xi.ThealgorithmisbasedonFigure9inthepaper"Permutationgroupalgorithms
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 stabilizerinGofLambda.(Anullpointer
designates a trivial group.) */
PermGroup *const L_R) /* A (possibly trivial) known subgroup of the stabilizerinGofXi.(Anullpointer
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}actingonPi(thetoppartitionofUpsilonStack)splits fromcelliofPithosepointslyingintheunionofthej'thcellgroupof Pi^(p)(thetoppartitiononextra[p]->xUpsilonStack)onOmega^(p).Note Lambdaisthebasepartitionforextra[p]->xUpsilonStack
// 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; returnsplit; }
// 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); } } } }
#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; returnsplit; }
// 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) } } }
RefinementPriorityPairisOrbReducible( constRefinementFamily*family,// The refinement family mapping // must be orbRefine; family parm[0] // is the group. constPartitionStack*constUpsilonStack) { BOOLEANcellWillSplit; Unsignedi,j,m,groupNumber,hashPosition,newCellNumber,oldCellNumber, count; unsignedlongminPriority,thisPriority; UnsignedS*oldLevelAddr; UnsignedS*constpointList=UpsilonStack->pointList, *conststartCell=UpsilonStack->startCell, *constcellSize=UpsilonStack->cellSize; PermGroup*G=family->familyParm_L[0].ptrParm; Unsignedlevel=family->familyParm_L[1].intParm; UnsignedS*orbNumberOfPt=G->orbNumberOfPt[level]; UnsignedS*conststartOfOrbitNo=G->startOfOrbitNo[level]; RefinementPriorityPairreducingRefn; 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:incorrectrefinementmapping"); for(groupNumber=0;groupNumber<refnData.groupCount&& refnData.group[groupNumber]!=G; ++groupNumber) ; if(groupNumber>=refnData.groupCount) ERROR("isOrbReducible","Routinenotinitializedforgroup.") 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 fromscratch. if(level!=*oldLevelAddr){
// 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", "Refinementlistexceededbound(shouldnotoccur).") 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", "Refinementlistexceededbound(shouldnotoccur).") 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=(unsignedlong)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.