diff options
Diffstat (limited to 'src/bdd/cudd/cuddZddGroup.c')
-rw-r--r-- | src/bdd/cudd/cuddZddGroup.c | 1317 |
1 files changed, 0 insertions, 1317 deletions
diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c deleted file mode 100644 index 621fa43f..00000000 --- a/src/bdd/cudd/cuddZddGroup.c +++ /dev/null @@ -1,1317 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddGroup.c] - - PackageName [cudd] - - Synopsis [Functions for ZDD group sifting.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_MakeZddTreeNode() - </ul> - Internal procedures included in this file: - <ul> - <li> cuddZddTreeSifting() - </ul> - Static procedures included in this module: - <ul> - <li> zddTreeSiftingAux() - <li> zddCountInternalMtrNodes() - <li> zddReorderChildren() - <li> zddFindNodeHiLo() - <li> zddUniqueCompareGroup() - <li> zddGroupSifting() - <li> zddGroupSiftingAux() - <li> zddGroupSiftingUp() - <li> zddGroupSiftingDown() - <li> zddGroupMove() - <li> zddGroupMoveBackward() - <li> zddGroupSiftingBackward() - <li> zddMergeGroups() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -static int *entry; -extern int zddTotalNumberSwapping; -#ifdef DD_STATS -static int extsymmcalls; -static int extsymm; -static int secdiffcalls; -static int secdiff; -static int secdiffmisfire; -#endif -#ifdef DD_DEBUG -static int pr = 0; /* flag to enable printing while debugging */ - /* by depositing a 1 into it */ -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int zddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -#ifdef DD_STATS -static int zddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode)); -#endif -static int zddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -static void zddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper)); -static int zddUniqueCompareGroup ARGS((int *ptrX, int *ptrY)); -static int zddGroupSifting ARGS((DdManager *table, int lower, int upper)); -static int zddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static int zddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, Move **moves)); -static int zddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, Move **moves)); -static int zddGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); -static int zddGroupMoveBackward ARGS((DdManager *table, int x, int y)); -static int zddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void zddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Creates a new ZDD variable group.] - - Description [Creates a new ZDD variable group. The group starts at - variable and contains size variables. The parameter low is the index - of the first variable. If the variable already exists, its current - position in the order is known to the manager. If the variable does - not exist yet, the position is assumed to be the same as the index. - The group tree is created if it does not exist yet. - Returns a pointer to the group if successful; NULL otherwise.] - - SideEffects [The ZDD variable tree is changed.] - - SeeAlso [Cudd_MakeTreeNode] - -******************************************************************************/ -MtrNode * -Cudd_MakeZddTreeNode( - DdManager * dd /* manager */, - unsigned int low /* index of the first group variable */, - unsigned int size /* number of variables in the group */, - unsigned int type /* MTR_DEFAULT or MTR_FIXED */) -{ - MtrNode *group; - MtrNode *tree; - unsigned int level; - - /* If the variable does not exist yet, the position is assumed to be - ** the same as the index. Therefore, applications that rely on - ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new - ** variables have to create the variables before they group them. - */ - level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low; - - if (level + size - 1> (int) MTR_MAXHIGH) - return(NULL); - - /* If the tree does not exist yet, create it. */ - tree = dd->treeZ; - if (tree == NULL) { - dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ); - if (tree == NULL) - return(NULL); - tree->index = dd->invpermZ[0]; - } - - /* Extend the upper bound of the tree if necessary. This allows the - ** application to create groups even before the variables are created. - */ - tree->size = ddMax(tree->size, level + size); - - /* Create the group. */ - group = Mtr_MakeGroup(tree, level, size, type); - if (group == NULL) - return(NULL); - - /* Initialize the index field to the index of the variable currently - ** in position low. This field will be updated by the reordering - ** procedure to provide a handle to the group once it has been moved. - */ - group->index = (MtrHalfWord) low; - - return(group); - -} /* end of Cudd_MakeZddTreeNode */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Tree sifting algorithm for ZDDs.] - - Description [Tree sifting algorithm for ZDDs. Assumes that a tree - representing a group hierarchy is passed as a parameter. It then - reorders each group in postorder fashion by calling - zddTreeSiftingAux. Assumes that no dead nodes are present. Returns - 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddZddTreeSifting( - DdManager * table /* DD table */, - Cudd_ReorderingType method /* reordering method for the groups of leaves */) -{ - int i; - int nvars; - int result; - int tempTree; - - /* If no tree is provided we create a temporary one in which all - ** variables are in a single group. After reordering this tree is - ** destroyed. - */ - tempTree = table->treeZ == NULL; - if (tempTree) { - table->treeZ = Mtr_InitGroupTree(0,table->sizeZ); - table->treeZ->index = table->invpermZ[0]; - } - nvars = table->sizeZ; - -#ifdef DD_DEBUG - if (pr > 0 && !tempTree) - (void) fprintf(table->out,"cuddZddTreeSifting:"); - Mtr_PrintGroups(table->treeZ,pr <= 0); -#endif -#if 0 - /* Debugging code. */ - if (table->tree && table->treeZ) { - (void) fprintf(table->out,"\n"); - Mtr_PrintGroups(table->tree, 0); - cuddPrintVarGroups(table,table->tree,0,0); - for (i = 0; i < table->size; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->invperm[i]); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < table->size; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->perm[i]); - } - (void) fprintf(table->out,"\n\n"); - Mtr_PrintGroups(table->treeZ,0); - cuddPrintVarGroups(table,table->treeZ,1,0); - for (i = 0; i < table->sizeZ; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->invpermZ[i]); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < table->sizeZ; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->permZ[i]); - } - (void) fprintf(table->out,"\n"); - } - /* End of debugging code. */ -#endif -#ifdef DD_STATS - extsymmcalls = 0; - extsymm = 0; - secdiffcalls = 0; - secdiff = 0; - secdiffmisfire = 0; - - (void) fprintf(table->out,"\n"); - if (!tempTree) - (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", - zddCountInternalMtrNodes(table,table->treeZ)); -#endif - - /* Initialize the group of each subtable to itself. Initially - ** there are no groups. Groups are created according to the tree - ** structure in postorder fashion. - */ - for (i = 0; i < nvars; i++) - table->subtableZ[i].next = i; - - /* Reorder. */ - result = zddTreeSiftingAux(table, table->treeZ, method); - -#ifdef DD_STATS /* print stats */ - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - (table->groupcheck == CUDD_GROUP_CHECK7 || - table->groupcheck == CUDD_GROUP_CHECK5)) { - (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); - (void) fprintf(table->out,"extsymm = %d",extsymm); - } - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - table->groupcheck == CUDD_GROUP_CHECK7) { - (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); - (void) fprintf(table->out,"secdiff = %d\n",secdiff); - (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); - } -#endif - - if (tempTree) - Cudd_FreeZddTree(table); - return(result); - -} /* end of cuddZddTreeSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Visits the group tree and reorders each group.] - - Description [Recursively visits the group tree and reorders each - group in postorder fashion. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddTreeSiftingAux( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - MtrNode *auxnode; - int res; - -#ifdef DD_DEBUG - Mtr_PrintGroups(treenode,1); -#endif - - auxnode = treenode; - while (auxnode != NULL) { - if (auxnode->child != NULL) { - if (!zddTreeSiftingAux(table, auxnode->child, method)) - return(0); - res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); - if (res == 0) - return(0); - } else if (auxnode->size > 1) { - if (!zddReorderChildren(table, auxnode, method)) - return(0); - } - auxnode = auxnode->younger; - } - - return(1); - -} /* end of zddTreeSiftingAux */ - - -#ifdef DD_STATS -/**Function******************************************************************** - - Synopsis [Counts the number of internal nodes of the group tree.] - - Description [Counts the number of internal nodes of the group tree. - Returns the count.] - - SideEffects [None] - -******************************************************************************/ -static int -zddCountInternalMtrNodes( - DdManager * table, - MtrNode * treenode) -{ - MtrNode *auxnode; - int count,nodeCount; - - - nodeCount = 0; - auxnode = treenode; - while (auxnode != NULL) { - if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { - nodeCount++; - count = zddCountInternalMtrNodes(table,auxnode->child); - nodeCount += count; - } - auxnode = auxnode->younger; - } - - return(nodeCount); - -} /* end of zddCountInternalMtrNodes */ -#endif - - -/**Function******************************************************************** - - Synopsis [Reorders the children of a group tree node according to - the options.] - - Description [Reorders the children of a group tree node according to - the options. After reordering puts all the variables in the group - and/or its descendents in a single group. This allows hierarchical - reordering. If the variables in the group do not exist yet, simply - does nothing. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddReorderChildren( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - int lower; - int upper; - int result; - unsigned int initialSize; - - zddFindNodeHiLo(table,treenode,&lower,&upper); - /* If upper == -1 these variables do not exist yet. */ - if (upper == -1) - return(1); - - if (treenode->flags == MTR_FIXED) { - result = 1; - } else { -#ifdef DD_STATS - (void) fprintf(table->out," "); -#endif - switch (method) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - result = cuddZddSwapping(table,lower,upper,method); - break; - case CUDD_REORDER_SIFT: - result = cuddZddSifting(table,lower,upper); - break; - case CUDD_REORDER_SIFT_CONVERGE: - do { - initialSize = table->keysZ; - result = cuddZddSifting(table,lower,upper); - if (initialSize <= table->keysZ) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_SYMM_SIFT: - result = cuddZddSymmSifting(table,lower,upper); - break; - case CUDD_REORDER_SYMM_SIFT_CONV: - result = cuddZddSymmSiftingConv(table,lower,upper); - break; - case CUDD_REORDER_GROUP_SIFT: - result = zddGroupSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR: - result = cuddZddLinearSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR_CONVERGE: - do { - initialSize = table->keysZ; - result = cuddZddLinearSifting(table,lower,upper); - if (initialSize <= table->keysZ) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - default: - return(0); - } - } - - /* Create a single group for all the variables that were sifted, - ** so that they will be treated as a single block by successive - ** invocations of zddGroupSifting. - */ - zddMergeGroups(table,treenode,lower,upper); - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:"); -#endif - - return(result); - -} /* end of zddReorderChildren */ - - -/**Function******************************************************************** - - Synopsis [Finds the lower and upper bounds of the group represented - by treenode.] - - Description [Finds the lower and upper bounds of the group represented - by treenode. The high and low fields of treenode are indices. From - those we need to derive the current positions, and find maximum and - minimum.] - - SideEffects [The bounds are returned as side effects.] - - SeeAlso [] - -******************************************************************************/ -static void -zddFindNodeHiLo( - DdManager * table, - MtrNode * treenode, - int * lower, - int * upper) -{ - int low; - int high; - - /* Check whether no variables in this group already exist. - ** If so, return immediately. The calling procedure will know from - ** the values of upper that no reordering is needed. - */ - if ((int) treenode->low >= table->sizeZ) { - *lower = table->sizeZ; - *upper = -1; - return; - } - - *lower = low = (unsigned int) table->permZ[treenode->index]; - high = (int) (low + treenode->size - 1); - - if (high >= table->sizeZ) { - /* This is the case of a partially existing group. The aim is to - ** reorder as many variables as safely possible. If the tree - ** node is terminal, we just reorder the subset of the group - ** that is currently in existence. If the group has - ** subgroups, then we only reorder those subgroups that are - ** fully instantiated. This way we avoid breaking up a group. - */ - MtrNode *auxnode = treenode->child; - if (auxnode == NULL) { - *upper = (unsigned int) table->sizeZ - 1; - } else { - /* Search the subgroup that strands the table->sizeZ line. - ** If the first group starts at 0 and goes past table->sizeZ - ** upper will get -1, thus correctly signaling that no reordering - ** should take place. - */ - while (auxnode != NULL) { - int thisLower = table->permZ[auxnode->low]; - int thisUpper = thisLower + auxnode->size - 1; - if (thisUpper >= table->sizeZ && thisLower < table->sizeZ) - *upper = (unsigned int) thisLower - 1; - auxnode = auxnode->younger; - } - } - } else { - /* Normal case: All the variables of the group exist. */ - *upper = (unsigned int) high; - } - -#ifdef DD_DEBUG - /* Make sure that all variables in group are contiguous. */ - assert(treenode->size >= *upper - *lower + 1); -#endif - - return; - -} /* end of zddFindNodeHiLo */ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the variables - according to the number of keys in the subtables. Returns the - difference in number of keys between the two variables being - compared.] - - SideEffects [None] - -******************************************************************************/ -static int -zddUniqueCompareGroup( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of zddUniqueCompareGroup */ - - -/**Function******************************************************************** - - Synopsis [Sifts from treenode->low to treenode->high.] - - Description [Sifts from treenode->low to treenode->high. If - croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the - end of the initial sifting. If a group is created, it is then sifted - again. After sifting one variable, the group that contains it is - dissolved. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSifting( - DdManager * table, - int lower, - int upper) -{ - int *var; - int i,j,x,xInit; - int nvars; - int classes; - int result; - int *sifted; -#ifdef DD_STATS - unsigned previousSize; -#endif - int xindex; - - nvars = table->sizeZ; - - /* Order variables to sift. */ - entry = NULL; - sifted = NULL; - var = ALLOC(int,nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - entry = ALLOC(int,nvars); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - sifted = ALLOC(int,nvars); - if (sifted == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - - /* Here we consider only one representative for each group. */ - for (i = 0, classes = 0; i < nvars; i++) { - sifted[i] = 0; - x = table->permZ[i]; - if ((unsigned) x >= table->subtableZ[x].next) { - entry[i] = table->subtableZ[x].keys; - var[classes] = i; - classes++; - } - } - - qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))zddUniqueCompareGroup); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - xindex = var[i]; - if (sifted[xindex] == 1) /* variable already sifted as part of group */ - continue; - x = table->permZ[xindex]; /* find current level of this variable */ - if (x < lower || x > upper) - continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - result = zddGroupSiftingAux(table,x,lower,upper); - if (!result) goto zddGroupSiftingOutOfMem; - -#ifdef DD_STATS - if (table->keysZ < previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > previousSize) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - - /* Mark variables in the group just sifted. */ - x = table->permZ[xindex]; - if ((unsigned) x != table->subtableZ[x].next) { - xInit = x; - do { - j = table->invpermZ[x]; - sifted[j] = 1; - x = table->subtableZ[x].next; - } while (x != xInit); - } - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:"); -#endif - } /* for */ - - FREE(sifted); - FREE(var); - FREE(entry); - - return(1); - -zddGroupSiftingOutOfMem: - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - if (sifted != NULL) FREE(sifted); - - return(0); - -} /* end of zddGroupSifting */ - - -/**Function******************************************************************** - - Synopsis [Sifts one variable up and down until it has taken all - positions. Checks for aggregation.] - - Description [Sifts one variable up and down until it has taken all - positions. Checks for aggregation. There may be at most two sweeps, - even if the group grows. Assumes that x is either an isolated - variable, or it is the bottom of a group. All groups may not have - been found. The variable being moved is returned to the best position - seen during sifting. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moves; /* list of moves */ - int initialSize; - int result; - - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh); - assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */ -#endif - - initialSize = table->keysZ; - moves = NULL; - - if (x == xLow) { /* Sift down */ -#ifdef DD_DEBUG - /* x must be a singleton */ - assert((unsigned) x == table->subtableZ[x].next); -#endif - if (x == xHigh) return(1); /* just one variable */ - - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */ -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - /* Find top of x's group */ - x = table->subtableZ[x].next; - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xLow, unless early term */ - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* Find top of group */ - if (moves) { - x = moves->y; - } - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; -#ifdef DD_DEBUG - /* x should be the top of a group */ - assert((unsigned) x <= table->subtableZ[x].next); -#endif - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's group */ - x = table->subtableZ[x].next; - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - if (moves) { - x = moves->x; - } - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; -#ifdef DD_DEBUG - /* x is bottom of a group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - } - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(1); - -zddGroupSiftingAuxOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(0); - -} /* end of zddGroupSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts up a variable until either it reaches position xLow - or the size of the DD heap increases too much.] - - Description [Sifts up a variable until either it reaches position - xLow or the size of the DD heap increases too much. Assumes that y is - the top of a group (or a singleton). Checks y for aggregation to the - adjacent variables. Records all the moves that are appended to the - list of moves received as input and returned as a side effect. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingUp( - DdManager * table, - int y, - int xLow, - Move ** moves) -{ - Move *move; - int x; - int size; - int gxtop; - int limitSize; - int xindex, yindex; - - yindex = table->invpermZ[y]; - - limitSize = table->keysZ; - - x = cuddZddNextLow(table,y); - while (x >= xLow) { - gxtop = table->subtableZ[x].next; - if (table->subtableZ[x].next == (unsigned) x && - table->subtableZ[y].next == (unsigned) y) { - /* x and y are self groups */ - xindex = table->invpermZ[x]; - size = cuddZddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtableZ[x].next == (unsigned) x); - assert(table->subtableZ[y].next == (unsigned) y); -#endif - if (size == 0) goto zddGroupSiftingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } else { /* group move */ - size = zddGroupMove(table,x,y,moves); - if (size == 0) goto zddGroupSiftingUpOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - y = gxtop; - x = cuddZddNextLow(table,y); - } - - return(1); - -zddGroupSiftingUpOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of zddGroupSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts down a variable until it reaches position xHigh.] - - Description [Sifts down a variable until it reaches position xHigh. - Assumes that x is the bottom of a group (or a singleton). Records - all the moves. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingDown( - DdManager * table, - int x, - int xHigh, - Move ** moves) -{ - Move *move; - int y; - int size; - int limitSize; - int gxtop,gybot; - int xindex; - - - /* Initialize R */ - xindex = table->invpermZ[x]; - gxtop = table->subtableZ[x].next; - limitSize = size = table->keysZ; - y = cuddZddNextHigh(table,x); - while (y <= xHigh) { - /* Find bottom of y group. */ - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - - if (table->subtableZ[x].next == (unsigned) x && - table->subtableZ[y].next == (unsigned) y) { - /* x and y are self groups */ - size = cuddZddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtableZ[x].next == (unsigned) x); - assert(table->subtableZ[y].next == (unsigned) y); -#endif - if (size == 0) goto zddGroupSiftingDownOutOfMem; - - /* Record move. */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - x = y; - y = cuddZddNextHigh(table,x); - } else { /* Group move */ - size = zddGroupMove(table,x,y,moves); - if (size == 0) goto zddGroupSiftingDownOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - x = gybot; - y = cuddZddNextHigh(table,x); - } - - return(1); - -zddGroupSiftingDownOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - - return(0); - -} /* end of zddGroupSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups and records the move.] - - Description [Swaps two groups and records the move. Returns the - number of keys in the DD table in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupMove( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - int swapx,swapy; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - int initialSize,bestSize; -#endif - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtableZ[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtableZ[ybot].next) - ybot = table->subtableZ[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - initialSize = bestSize = table->keysZ; -#endif - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddZddSwapInPlace(table,x,y); - if (size == 0) goto zddGroupMoveOutOfMem; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (size < bestSize) - bestSize = size; -#endif - swapx = x; swapy = y; - y = x; - x = cuddZddNextLow(table,y); - } - y = ytop + i; - x = cuddZddNextLow(table,y); - } -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if ((bestSize < initialSize) && (bestSize < size)) - (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); -#endif - - /* fix groups */ - y = xtop; /* ytop is now where xtop used to be */ - for (i = 0; i < ysize - 1; i++) { - table->subtableZ[y].next = cuddZddNextHigh(table,y); - y = cuddZddNextHigh(table,y); - } - table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ - /* it to top of its group */ - x = cuddZddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtableZ[x].next = cuddZddNextHigh(table,x); - x = cuddZddNextHigh(table,x); - } - table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ - /* it to top of its group */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n"); -#endif - - /* Store group move */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupMoveOutOfMem; - move->x = swapx; - move->y = swapy; - move->flags = MTR_DEFAULT; - move->size = table->keysZ; - move->next = *moves; - *moves = move; - - return(table->keysZ); - -zddGroupMoveOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of zddGroupMove */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap two groups.] - - Description [Undoes the swap two groups. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupMoveBackward( - DdManager * table, - int x, - int y) -{ - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtableZ[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtableZ[ybot].next) - ybot = table->subtableZ[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddZddSwapInPlace(table,x,y); - if (size == 0) - return(0); - y = x; - x = cuddZddNextLow(table,y); - } - y = ytop + i; - x = cuddZddNextLow(table,y); - } - - /* fix groups */ - y = xtop; - for (i = 0; i < ysize - 1; i++) { - table->subtableZ[y].next = cuddZddNextHigh(table,y); - y = cuddZddNextHigh(table,y); - } - table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ - /* to its top */ - x = cuddZddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtableZ[x].next = cuddZddNextHigh(table,x); - x = cuddZddNextHigh(table,x); - } - table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ - /* to its top */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n"); -#endif - - return(1); - -} /* end of zddGroupMoveBackward */ - - -/**Function******************************************************************** - - Synopsis [Determines the best position for a variables and returns - it there.] - - Description [Determines the best position for a variables and returns - it there. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - Move *move; - int res; - - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if ((table->subtableZ[move->x].next == move->x) && - (table->subtableZ[move->y].next == move->y)) { - res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n"); - assert(table->subtableZ[move->x].next == move->x); - assert(table->subtableZ[move->y].next == move->y); -#endif - } else { /* Group move necessary */ - res = zddGroupMoveBackward(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - return(1); - -} /* end of zddGroupSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Merges groups in the DD table.] - - Description [Creates a single group from low to high and adjusts the - idex field of the tree node.] - - SideEffects [None] - -******************************************************************************/ -static void -zddMergeGroups( - DdManager * table, - MtrNode * treenode, - int low, - int high) -{ - int i; - MtrNode *auxnode; - int saveindex; - int newindex; - - /* Merge all variables from low to high in one group, unless - ** this is the topmost group. In such a case we do not merge lest - ** we lose the symmetry information. */ - if (treenode != table->treeZ) { - for (i = low; i < high; i++) - table->subtableZ[i].next = i+1; - table->subtableZ[high].next = low; - } - - /* Adjust the index fields of the tree nodes. If a node is the - ** first child of its parent, then the parent may also need adjustment. */ - saveindex = treenode->index; - newindex = table->invpermZ[low]; - auxnode = treenode; - do { - auxnode->index = newindex; - if (auxnode->parent == NULL || - (int) auxnode->parent->index != saveindex) - break; - auxnode = auxnode->parent; - } while (1); - return; - -} /* end of zddMergeGroups */ - |