static PointSet *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. */
/* Function matrixAutoGroup. Returns a new permutation group representing theautomorphismgroupofthematrixM.IfMisan(0,1)-matrix,the functiondesignAutoGroupshouldbeinvokedinstead.Thealgorithmisbased onFigure9inthepaper"Permutationgroupalgorithmsbasedonpartitions"bythe
author. */
#define familyParm familyParm_L
PermGroup *matrixAutoGroup(
Matrix_01 *const M, /* The matrix whose group is to be found. */
PermGroup *const L, /* A (possibly trivial) known subgroup of the automorphismgroupofD.(Anullpointer
designates a trivial group.) */
Code *const C, /* If nonnull, the auto grp of the code C is */ const BOOLEAN monomialFlag) /* computed, assuming its group is contained
in that of the design. */
{
RefinementFamily SSS_Lambda, IIIg_M;
RefinementFamily *refnFamList[3];
ReducChkFn *reducChkList[3];
SpecialRefinementDescriptor *specialRefinement[3];
ExtraDomain *extra[1];
PointSet *Lambda; /* Set of rows. */
Partition *Pi; /* Rows, cols, identity cols. */
PermGroup *G; Unsigned degree = M->numberOfRows + M->numberOfCols; Unsigned i;
Property *pp;
/* Construct the symmetric group G of degree rows+cols. */
G = allocPermGroup();
sprintf( G->name, "%c%d", SYMMETRIC_GROUP_CHAR, degree);
G->degree = degree;
G->baseSize = 0;
/* Construct the set Lambda of points, ie. Lambda = {1,...,numberOfRows} or
the partition Pi. */ if ( monomialFlag ) {
Pi = allocPartition();
Pi->degree = degree;
Pi->pointList = allocIntArrayDegree();
Pi->invPointList = allocIntArrayDegree();
Pi->cellNumber = allocIntArrayDegree();
Pi->startCell = allocIntArrayDegree(); for ( i = 1 ; i <= degree ; ++i ) {
Pi->pointList[i] = Pi->invPointList[i] = i;
Pi->cellNumber[i] = ( i <= M->numberOfRows) ? 1 :
( i <= degree - M->numberOfRows ) ? 2 : 3;
}
Pi->startCell[1] = 1;
Pi->startCell[2] = M->numberOfRows + 1;
Pi->startCell[3] = degree - M->numberOfRows + 1;
Pi->startCell[4] = degree + 1;;
SSS_Lambda.refine = partnStabRefine;
SSS_Lambda.familyParm[0].ptrParm = (void *) Pi;
} else {
Lambda = allocPointSet();
Lambda->degree = degree;
Lambda->size = M->numberOfRows;
Lambda->pointList = allocIntArrayDegree(); for ( i = 1 ; i <= M->numberOfRows ; ++i )
Lambda->pointList[i] = i;
Lambda->pointList[M->numberOfRows+1] = 0;
Lambda->inSet = allocBooleanArrayDegree(); for ( i = 1 ; i <= degree ; ++i )
Lambda->inSet[i] = ( i <= M->numberOfRows);
SSS_Lambda.refine = setStabRefine;
SSS_Lambda.familyParm[0].ptrParm = (void *) Lambda;
}
IIIg_M.refine = gRowVsColRefine;
IIIg_M.familyParm[0].ptrParm = (void *) M;
/* Function matrixIsomorphism. Returns a permutation mapping one specified matrixM_LtoanothermatrixM_R.Thetwomatricesmusthave thesamenumberofrowsandthesamenumberofcolumns.Thealgorithmis basedonFigure9inthepaper"Permutationgroupalgorithmsbasedon
partitions" by the author. */
Permutation *matrixIsomorphism(
Matrix_01 *const M_L, /* The first design. */
Matrix_01 *const M_R, /* The second design. */
PermGroup *const L_L, /* A known subgroup of Aut(M_L), or NULL. */
PermGroup *const L_R, /* A known subgroup of Aut(M_R), or NULL. */
Code *const C_L, /* If nonnull, C_R must also be nonull, and */
Code *const C_R, /* any isomorphism of C_L to C_R must map */ const BOOLEAN monomialFlag, /* M_L to M_R. A code isomorphism is */ /* computed. */ const BOOLEAN colInformFlag) /* Print iso on columns to std output. */
{
RefinementFamily SSS_Lambda_Lambda, IIIg_ML_MR;
RefinementFamily *refnFamList[3];
ReducChkFn *reducChkList[3];
SpecialRefinementDescriptor *specialRefinement[3];
ExtraDomain *extra[1];
PointSet *Lambda; /* Set of rows. */
Partition *Pi; /* Rows, cols, identity cols. */
PermGroup *G; Unsigned degree = M_L->numberOfRows + M_L->numberOfCols; Unsigned i;
Property *pp;
/* Construct the symmetric group G of degree rows+cols. */
G = allocPermGroup();
sprintf( G->name, "%c%d", SYMMETRIC_GROUP_CHAR, degree);
G->degree = degree;
G->baseSize = 0;
/* Construct the set Lambda of points, ie. Lambda = {1,...,numberOfRows} or
the partition Pi. */ if ( monomialFlag ) {
Pi = allocPartition();
Pi->degree = degree;
Pi->pointList = allocIntArrayDegree();
Pi->invPointList = allocIntArrayDegree();
Pi->cellNumber = allocIntArrayDegree();
Pi->startCell = allocIntArrayDegree(); for ( i = 1 ; i <= degree ; ++i ) {
Pi->pointList[i] = Pi->invPointList[i] = i;
Pi->cellNumber[i] = ( i <= M_L->numberOfRows) ? 1 :
( i <= degree - M_L->numberOfRows ) ? 2 : 3;
}
Pi->startCell[1] = 1;
Pi->startCell[2] = M_L->numberOfRows + 1;
Pi->startCell[3] = degree - M_L->numberOfRows + 1;
Pi->startCell[4] = degree + 1;;
SSS_Lambda_Lambda.refine = partnStabRefine;
SSS_Lambda_Lambda.familyParm_L[0].ptrParm = (void *) Pi;
SSS_Lambda_Lambda.familyParm_R[0].ptrParm = (void *) Pi;
} else {
Lambda = allocPointSet();
Lambda->degree = degree;
Lambda->size = M_L->numberOfRows;
Lambda->pointList = allocIntArrayDegree(); for ( i = 1 ; i <= M_L->numberOfRows ; ++i )
Lambda->pointList[i] = i;
Lambda->pointList[M_L->numberOfRows+1] = 0;
Lambda->inSet = allocBooleanArrayDegree(); for ( i = 1 ; i <= degree ; ++i )
Lambda->inSet[i] = ( i <= M_L->numberOfRows);
SSS_Lambda_Lambda.refine = setStabRefine;
SSS_Lambda_Lambda.familyParm_L[0].ptrParm = (void *) Lambda;
SSS_Lambda_Lambda.familyParm_R[0].ptrParm = (void *) Lambda;
}
/* The function implements the refinement family setStabRefine (denoted SSS_Lambdainthereference).Thisfamilyconsistsoftheelementary refinementsssS_{Lambda,i},whereLambdafixed.(Itisthesettobe stabilized)andwhere1<=i<=degree.ApplicationofsSS_{Lambda,i}to UpsilonStacksplitsofffromUpsilonToptheintersectionofLambdaandthe i'thcellofUpsilonTopfromcelliofthetoppartitionofUpsilonStackand pushestheresultingpartitionontoUpsilonStack,unlesssSS_{Lambda,i}acts triviallyonUpsilonTop,inwhichcaseUpsilonStackremainsunchanged.
/* First check if the refinement acts nontrivially on UpsilonTop. If not
return immediately. */ for ( m = startCell[cellToSplit] , last = m + cellSize[cellToSplit] ;
m < last && (inLambdaCount == 0 || outLambdaCount == 0) ; ++m ) if ( inSet[pointList[m]] )
++inLambdaCount; else
++outLambdaCount; if ( inLambdaCount == 0 || outLambdaCount == 0 ) {
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. */
i = startCell[cellToSplit]-1;
j = last; while ( i < j ) { while ( !inSet[pointList[++i]] ); while ( inSet[pointList[--j]] ); if ( i < j ) {
EXCHANGE( pointList[i], pointList[j], temp)
EXCHANGE( invPointList[pointList[i]], invPointList[pointList[j]], temp)
}
}
++UpsilonStack->height; for ( m = i ; m < last ; ++m )
cellNumber[pointList[m]] = UpsilonStack->height;
startCell[UpsilonStack->height] = i;
parent[UpsilonStack->height] = cellToSplit;
cellSize[UpsilonStack->height] = last - i;
cellSize[cellToSplit] -= (last - i);
split.oldCellSize = cellSize[cellToSplit];
split.newCellSize = cellSize[UpsilonStack->height]; return split;
}
/* The function isSetStabReducible checks whether the top partition on a given partitionstackisSSS_Lambda-reducible,whereLambdaisafixedset.If so,itreturnsapairconsistingofarefinementactingnontriviallyon thetoppartitionandapriority.Otherwiseitreturnsastructureof typeRefinementPriorityPairinwhichthepriorityfieldisIRREDUCIBLE.Assuming thatareducingrefinementisfound,the(reverse)priorityissetvery low(1).Notethat,oncethisfunctionreturnsnegativeinthepriority fieldonce,itwilldosoonallsubsequentcalls.(Thestaticvariable knownIrreducibleissettotrueinthissituation.)Again,noattempt
at efficiency has been made. */
/* Check that the refinement mapping really is setStabRefn, as required. */ if ( family->refine != setStabRefine )
ERROR( "isSetStabReducible", "Error: incorrect refinement mapping");
/* If the top partition has previously been found to be SSS-irreducible, we
return immediately. */ for ( i = 0 ; knownIrreducible[i] && knownIrreducible[i] != Lambda ; ++i )
; if ( knownIrreducible[i] ) {
reducingRefn.priority = IRREDUCIBLE; return reducingRefn;
}
/* If we reach here, the top partition has not been previously found to be SSS-irreducible.Wecheckeachcellinturntoseeifitintersectsboth LambdaandOmega-Lambda.Ifsuchacellisfound,wereturn
immediately. */ for ( cellNo = 1 ; cellNo <= UpsilonStack->height ; ++cellNo ) {
ptsInLambda = ptsNotInLambda = FALSE; for ( position = startCell[cellNo] ; position < startCell[cellNo] +
cellSize[cellNo] ; ++position ) { if ( inSet[pointList[position]] )
ptsInLambda = TRUE; else
ptsNotInLambda = TRUE; if ( ptsInLambda && ptsNotInLambda ) {
reducingRefn.refn.family = (RefinementFamily *)(family);
reducingRefn.refn.refnParm[0].intParm = cellNo;
reducingRefn.priority = 1; return reducingRefn;
}
}
}
/* If we reach here, we have found the top partition to be SSS_Lambda
irreducible, so we add Lambda to the list knownIrreducible and return. */ for ( i = 0 ; knownIrreducible[i] ; ++i )
; if ( i < 9 ) {
knownIrreducible[i] = Lambda;
knownIrreducible[i+1] = NULL;
} else
ERROR( "isSetStabReducible", "Number of point sets exceeded max of 9.")
/* The function implements the refinement families III_RC and III_CR. Here III_RCconsistsoftheelementaryrefinementsIIi_RC_{D,i,j,m},where IIi_RC_{D,i,j,m}splitsfromrowcellithoserowsthathavemonesin columncellj,andIIi_CR_{D,i,j,m}splitsfromcolumncellithosecolumns thathavemonesinrowcellj.Notethatfromiandjtheroutinecan tellwhetherIII_RCorIII_CRshouldbeapplied. Thefamilyparameteris: familyParm[0].ptrParm:D(thematrix) Therefinementparametersare: refnParm[0].intParm:i. refnParm[1].intParm:j. refnParm[2].intParm:m.
/* Allocate header, etc, if not already done. */ if ( !header ) {
header = (Unsigned *) malloc( twoExpRandBits * sizeof(Unsigned)); for ( k = 0 ; k < twoExpRandBits ; ++k ) /* Note degree+1 needed */
header[k] = 0;
nonZeroPosition = allocIntArrayDegree();
nonZeroCount = 0;
node = (Node *) malloc( (degree+2) * sizeof(Node) );
}
/* First we check whether we need to compute row/col sums across cells, orwhetherthiswasalreadydoneonapreviouscall.Ifso,wefirst
clear the array header. */ if ( j != 0 && !skipFlag ) { for ( k = 1 ; k <= nonZeroCount ; ++k )
header[nonZeroPosition[k]] = 0;
nonZeroCount = 0;
familySelector = (pointList[startCell[i]] <= nRows ) ? RC : CR; for ( k = startCell[i] , last = k + cellSize[i] , cnt = 1; k < last ;
++k , ++cnt ) {
rowOrCol = pointList[k];
rowOrColSum = 0; switch( familySelector ) { case RC: for ( t = startCell[j] , last1 = t + cellSize[j] ; t < last1 ;
++t )
rowOrColSum += randArray[M->entry[rowOrCol][pointList[t]-nRows]]; break; case CR: for ( t = startCell[j] , last1 = t + cellSize[j] ; t < last1 ;
++t )
rowOrColSum += randArray[M->entry[pointList[t]][rowOrCol-nRows]]; break;
}
rowOrColSum &= randBitsFlag;
node[cnt].rowOrCol = rowOrCol;
node[cnt].link = header[rowOrColSum]; if ( header[rowOrColSum] == 0 )
nonZeroPosition[++nonZeroCount] = rowOrColSum;
header[rowOrColSum] = cnt;
}
numberOfSubcells = nonZeroCount;
}
skipFlag = FALSE;
/* If cell i does not split, return at once. */ if ( m == UNKNOWN || header[m] == 0 || numberOfSubcells == 1 ) {
split.oldCellSize = cellSize[i];
split.newCellSize = 0; return split;
}
/* Now split cell i. */
last = startCell[i] + cellSize[i]; for ( k = last-1 , p = header[m] ; p != 0 ; --k , p = node[p].link ) {
t = node[p].rowOrCol;
r = invPointList[t];
pointList[r] = pointList[k];
pointList[k] = t;
invPointList[t] = k;
invPointList[pointList[r]] = r;
}
++k;
++UpsilonStack->height; for ( r = k ; r < last ; ++r )
cellNumber[pointList[r]] = UpsilonStack->height;
startCell[UpsilonStack->height] = k;
parent[UpsilonStack->height] = i;
cellSize[UpsilonStack->height] = last - k;
cellSize[i] -= (last - k);
split.oldCellSize = cellSize[i];
split.newCellSize = cellSize[UpsilonStack->height];
--numberOfSubcells; return split;
}
/* Allocate and construct randArray the first time. */ if ( !randArray ) {
initializeSeed( initialSeed);
randBits = 6;
twoExpRandBits = 64; while ( randBits < INT_SIZE && twoExpRandBits <
(unsignedlong) UpsilonStack->degree + M_L->setSize ) {
++randBits;
twoExpRandBits <<=1;
} for ( i = 0 ; i < randBits ; ++ i)
randBitsFlag |= (1u << i);
randArray = (Unsigned *) malloc( sizeof(Unsigned *) * M_L->setSize); for ( i = 0 ; i < M_L->setSize ; ++i )
randArray[i] = 2 * randInteger( 1, twoExpRandBits>>1) - 1;
}
/* Allocate list, freq, and nextCellSameType the first time. */ if ( !list )
list = allocIntArrayDegree(); if ( !freq )
freq = allocIntArrayDegree(); if ( !nextCellSameType ) {
nextCellSameType = allocIntArrayDegree();
nextCellSameType[0] = 0;
}
/* Check that the refinement mapping really is rowVsColRefine, as
required. */ if ( family->refine != gRowVsColRefine )
ERROR( "isGRowVsColReducible", "Error: incorrect refinement mapping");
/* If the height is 1 (row/col split not yet performed), for regular
matrices, or 1 or 2, for monomial matrices, return irreducible. */ if ( UpsilonStack->height <= 1 + checkMonomialProperty ) {
reducingRefn.priority = IRREDUCIBLE; return reducingRefn;
}
/* When the stack height reaches 2 (1 row cell, 1 col cell), for normal matrices,or3(1rowcell,2colcells),formonomialmatrices,perform
initializations for nextCellSameType, etc. */ if ( UpsilonStack->height == 2 + checkMonomialProperty ) {
firstRowCell = (CELL_TYPE(1) == ROW) ? 1 : 2;
firstColCell = 3 - firstRowCell;
lastRowCell = firstRowCell;
lastColCell = firstColCell;
nextCellSameType[1] = nextCellSameType[2] = 0;
}
/* If we can split the same cell as before using a different weighted
sum, do so immediately (priority 1). */ if ( listSize > 0 ) {
reducingRefn.refn.family = (RefinementFamily *)(family);
reducingRefn.refn.refnParm[0].intParm = opposingCell;
reducingRefn.refn.refnParm[1].intParm = 0;
reducingRefn.refn.refnParm[2].intParm = list[listSize--];
reducingRefn.priority = 1;
skipFlag = TRUE; return reducingRefn;
}
/* Consider the next opposing cell for the cell being processed, or the nextcelltobeprocessediftherearenomoreopposingcells.First
we update nextCellSameType (Note this must be done only here). */ for (;;) { if ( nextCellSameType[opposingCell] != 0 )
opposingCell = nextCellSameType[opposingCell]; elseif ( processingCell < UpsilonStack->height ) {
++processingCell; for ( i = MAX(lastRowCell,lastColCell)+1 ; i <= UpsilonStack->height ;
++i ) switch( CELL_TYPE(i) ) { case ROW:
nextCellSameType[lastRowCell] = i;
lastRowCell = i;
nextCellSameType[i] = 0; break; case COL:
nextCellSameType[lastColCell] = i;
lastColCell = i;
nextCellSameType[i] = 0; break;
}
opposingCell = ( CELL_TYPE(processingCell) == ROW) ? firstColCell:
firstRowCell;
} else {
reducingRefn.priority = IRREDUCIBLE; return reducingRefn;
}
/* Now we try to split opposingCell using processingCell, and an intersectionCountthatguaranteesfailure.(ThisforcesrowVsColRefine
to compute the header, etc). */
reducingRefn.refn.refnParm[0].intParm = opposingCell;
reducingRefn.refn.refnParm[1].intParm = processingCell;
reducingRefn.refn.refnParm[2].intParm = UNKNOWN;
dummySplit = gRowVsColRefine( family->familyParm, reducingRefn.refn.refnParm,
(PartitionStack *const)(UpsilonStack));
/* If no splitting occured of opposing cell via processing cell is possible,nonZeroCountwillbe1.Ifthisoccurs,skiptothenext
pair (processingCell,opposingCell). */ if ( nonZeroCount == 1 ) continue;
/* Now we consider all the possible splittings of opposingCell, reject
that giving the largest new cell, and put the others on the list. */ for ( k = 1 ; k <= nonZeroCount ; ++k) {
freq[k] = 1;
p = header[nonZeroPosition[k]]; while ( node[p].link != 0 ) {
++freq[k];
p = node[p].link;
}
}
maxPos = 1; for ( k = 2 ; k <= nonZeroCount ; ++k ) if ( freq[k] > freq[maxPos] )
maxPos = k;
listSize = 0; for ( k = 1 ; k <= nonZeroCount ; ++k ) if ( k != maxPos )
list[++listSize] = nonZeroPosition[k];
/* Finally return the first entry on the list. */
reducingRefn.refn.family = (RefinementFamily *)(family);
reducingRefn.refn.refnParm[0].intParm = opposingCell;
reducingRefn.refn.refnParm[1].intParm = processingCell;
reducingRefn.refn.refnParm[2].intParm = list[listSize--];
reducingRefn.priority = 1;
skipFlag = TRUE; return reducingRefn;
}
}
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.