diff options
Diffstat (limited to 'src/bdd/cudd/cuddZddReord.c')
-rw-r--r-- | src/bdd/cudd/cuddZddReord.c | 1633 |
1 files changed, 0 insertions, 1633 deletions
diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c deleted file mode 100644 index e2da37f2..00000000 --- a/src/bdd/cudd/cuddZddReord.c +++ /dev/null @@ -1,1633 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddReord.c] - - PackageName [cudd] - - Synopsis [Procedures for dynamic variable ordering of ZDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddReduceHeap() - <li> Cudd_zddShuffleHeap() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddZddAlignToBdd() - <li> cuddZddNextHigh() - <li> cuddZddNextLow() - <li> cuddZddUniqueCompare() - <li> cuddZddSwapInPlace() - <li> cuddZddSwapping() - <li> cuddZddSifting() - </ul> - Static procedures included in this module: - <ul> - <li> zddSwapAny() - <li> cuddZddSiftingAux() - <li> cuddZddSiftingUp() - <li> cuddZddSiftingDown() - <li> cuddZddSiftingBackward() - <li> zddReorderPreprocess() - <li> zddReorderPostprocess() - <li> zddShuffle() - <li> zddSiftUp() - </ul> - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - 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 */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAX_SUBTABLE_SPARSITY 8 -#define DD_SHRINK_FACTOR 2 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -int *zdd_entry; - -int zddTotalNumberSwapping; - -static DdNode *empty; - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static Move * zddSwapAny ARGS((DdManager *table, int x, int y)); -static int cuddZddSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high)); -static Move * cuddZddSiftingUp ARGS((DdManager *table, int x, int x_low, int initial_size)); -static Move * cuddZddSiftingDown ARGS((DdManager *table, int x, int x_high, int initial_size)); -static int cuddZddSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void zddReorderPreprocess ARGS((DdManager *table)); -static int zddReorderPostprocess ARGS((DdManager *table)); -static int zddShuffle ARGS((DdManager *table, int *permutation)); -static int zddSiftUp ARGS((DdManager *table, int x, int xLow)); -static void zddFixTree ARGS((DdManager *table, MtrNode *treenode)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Main dynamic reordering routine for ZDDs.] - - Description [Main dynamic reordering routine for ZDDs. - Calls one of the possible reordering procedures: - <ul> - <li>Swapping - <li>Sifting - <li>Symmetric Sifting - </ul> - - For sifting and symmetric sifting it is possible to request reordering - to convergence.<p> - - The core of all methods is the reordering procedure - cuddZddSwapInPlace() which swaps two adjacent variables. - Returns 1 in case of success; 0 otherwise. In the case of symmetric - sifting (with and without convergence) returns 1 plus the number of - symmetric variables, in case of success.] - - SideEffects [Changes the variable order for all ZDDs and clears - the cache.] - -******************************************************************************/ -int -Cudd_zddReduceHeap( - DdManager * table /* DD manager */, - Cudd_ReorderingType heuristic /* method used for reordering */, - int minsize /* bound below which no reordering occurs */) -{ - DdHook *hook; - int result; - unsigned int nextDyn; -#ifdef DD_STATS - unsigned int initialSize; - unsigned int finalSize; -#endif - long localTime; - - /* Don't reorder if there are too many dead nodes. */ - if (table->keysZ - table->deadZ < (unsigned) minsize) - return(1); - - if (heuristic == CUDD_REORDER_SAME) { - heuristic = table->autoMethodZ; - } - if (heuristic == CUDD_REORDER_NONE) { - return(1); - } - - /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore - ** we count it. - */ - table->reorderings++; - empty = table->zero; - - localTime = util_cpu_time(); - - /* Run the hook functions. */ - hook = table->preReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "ZDD", (void *)heuristic); - if (res == 0) return(0); - hook = hook->next; - } - - /* Clear the cache and collect garbage. */ - zddReorderPreprocess(table); - zddTotalNumberSwapping = 0; - -#ifdef DD_STATS - initialSize = table->keysZ; - - switch(heuristic) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - (void) fprintf(table->out,"#:I_RANDOM "); - break; - case CUDD_REORDER_SIFT: - case CUDD_REORDER_SIFT_CONVERGE: - case CUDD_REORDER_SYMM_SIFT: - case CUDD_REORDER_SYMM_SIFT_CONV: - (void) fprintf(table->out,"#:I_SIFTING "); - break; - case CUDD_REORDER_LINEAR: - case CUDD_REORDER_LINEAR_CONVERGE: - (void) fprintf(table->out,"#:I_LINSIFT "); - break; - default: - (void) fprintf(table->err,"Unsupported ZDD reordering method\n"); - return(0); - } - (void) fprintf(table->out,"%8d: initial size",initialSize); -#endif - - result = cuddZddTreeSifting(table,heuristic); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keysZ; - (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", - zddTotalNumberSwapping); -#endif - - if (result == 0) - return(0); - - if (!zddReorderPostprocess(table)) - return(0); - - if (table->realignZ) { - if (!cuddBddAlignToZdd(table)) - return(0); - } - - nextDyn = table->keysZ * DD_DYN_RATIO; - if (table->reorderings < 20 || nextDyn > table->nextDyn) - table->nextDyn = nextDyn; - else - table->nextDyn += 20; - - table->reordered = 1; - - /* Run hook functions. */ - hook = table->postReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "ZDD", (void *)localTime); - if (res == 0) return(0); - hook = hook->next; - } - /* Update cumulative reordering time. */ - table->reordTime += util_cpu_time() - localTime; - - return(result); - -} /* end of Cudd_zddReduceHeap */ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to given permutation.] - - Description [Reorders ZDD variables according to given permutation. - The i-th entry of the permutation array contains the index of the variable - that should be brought to the i-th level. The size of the array should be - equal or greater to the number of variables currently in use. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [Changes the ZDD variable order for all diagrams and clears - the cache.] - - SeeAlso [Cudd_zddReduceHeap] - -******************************************************************************/ -int -Cudd_zddShuffleHeap( - DdManager * table /* DD manager */, - int * permutation /* required variable permutation */) -{ - - int result; - - empty = table->zero; - zddReorderPreprocess(table); - - result = zddShuffle(table,permutation); - - if (!zddReorderPostprocess(table)) return(0); - - return(result); - -} /* end of Cudd_zddShuffleHeap */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to the order of the BDD - variables.] - - Description [Reorders ZDD variables according to the order of the - BDD variables. This function can be called at the end of BDD - reordering to insure that the order of the ZDD variables is - consistent with the order of the BDD variables. The number of ZDD - variables must be a multiple of the number of BDD variables. Let - <code>M</code> be the ratio of the two numbers. cuddZddAlignToBdd - then considers the ZDD variables from <code>M*i</code> to - <code>(M+1)*i-1</code> as corresponding to BDD variable - <code>i</code>. This function should be normally called from - Cudd_ReduceHeap, which clears the cache. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [Changes the ZDD variable order for all diagrams and performs - garbage collection of the ZDD unique table.] - - SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap] - -******************************************************************************/ -int -cuddZddAlignToBdd( - DdManager * table /* DD manager */) -{ - int *invpermZ; /* permutation array */ - int M; /* ratio of ZDD variables to BDD variables */ - int i,j; /* loop indices */ - int result; /* return value */ - - /* We assume that a ratio of 0 is OK. */ - if (table->sizeZ == 0) - return(1); - - empty = table->zero; - M = table->sizeZ / table->size; - /* Check whether the number of ZDD variables is a multiple of the - ** number of BDD variables. - */ - if (M * table->size != table->sizeZ) - return(0); - /* Create and initialize the inverse permutation array. */ - invpermZ = ALLOC(int,table->sizeZ); - if (invpermZ == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < table->size; i++) { - int index = table->invperm[i]; - int indexZ = index * M; - int levelZ = table->permZ[indexZ]; - levelZ = (levelZ / M) * M; - for (j = 0; j < M; j++) { - invpermZ[M * i + j] = table->invpermZ[levelZ + j]; - } - } - /* Eliminate dead nodes. Do not scan the cache again, because we - ** assume that Cudd_ReduceHeap has already cleared it. - */ - cuddGarbageCollectZdd(table,0); - - result = zddShuffle(table, invpermZ); - FREE(invpermZ); - /* Fix the ZDD variable group tree. */ - zddFixTree(table,table->treeZ); - return(result); - -} /* end of cuddZddAlignToBdd */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a larger index.] - - Description [Finds the next subtable with a larger index. Returns the - index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddNextHigh( - DdManager * table, - int x) -{ - return(x + 1); - -} /* end of cuddZddNextHigh */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a smaller index.] - - Description [Finds the next subtable with a smaller index. Returns the - index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddNextLow( - DdManager * table, - int x) -{ - return(x - 1); - -} /* end of cuddZddNextLow */ - - -/**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] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddUniqueCompare( - int * ptr_x, - int * ptr_y) -{ - return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]); - -} /* end of cuddZddUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Swaps two adjacent variables.] - - Description [Swaps two adjacent variables. It assumes that no dead - nodes are present on entry to this procedure. The procedure then - guarantees that no dead nodes will be present when it terminates. - cuddZddSwapInPlace assumes that x < y. Returns the number of keys in - the table if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSwapInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int i; - int posn; - DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; - DdNode *newf1, *newf0, *next; - DdNodePtr g, *lastP, *previousP; - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddZddNextHigh(table,x) == y); - assert(table->subtableZ[x].keys != 0); - assert(table->subtableZ[y].keys != 0); - assert(table->subtableZ[x].dead == 0); - assert(table->subtableZ[y].dead == 0); -#endif - - zddTotalNumberSwapping++; - - /* Get parameters of x subtable. */ - xindex = table->invpermZ[x]; - xlist = table->subtableZ[x].nodelist; - oldxkeys = table->subtableZ[x].keys; - xslots = table->subtableZ[x].slots; - xshift = table->subtableZ[x].shift; - newxkeys = 0; - - yindex = table->invpermZ[y]; - ylist = table->subtableZ[y].nodelist; - oldykeys = table->subtableZ[y].keys; - yslots = table->subtableZ[y].slots; - yshift = table->subtableZ[y].shift; - newykeys = oldykeys; - - /* The nodes in the x layer that don't depend on y directly - ** will stay there; the others are put in a chain. - ** The chain is handled as a FIFO; g points to the beginning and - ** last points to the end. - */ - - g = NULL; - lastP = &g; - for (i = 0; i < xslots; i++) { - previousP = &(xlist[i]); - f = *previousP; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); f0 = cuddE(f); - if ((f1->index != (DdHalfWord) yindex) && - (f0->index != (DdHalfWord) yindex)) { /* stays */ - newxkeys++; - *previousP = f; - previousP = &(f->next); - } else { - f->index = yindex; - *lastP = f; - lastP = &(f->next); - } - f = next; - } /* while there are elements in the collision chain */ - *previousP = NULL; - } /* for each slot of the x subtable */ - *lastP = NULL; - - -#ifdef DD_COUNT - table->swapSteps += oldxkeys - newxkeys; -#endif - /* Take care of the x nodes that must be re-expressed. - ** They form a linked list pointed by g. Their index has been - ** changed to yindex already. - */ - f = g; - while (f != NULL) { - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - if ((int) f1->index == yindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = empty; f10 = f1; - } - f0 = cuddE(f); - if ((int) f0->index == yindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = empty; f00 = f0; - } - - /* Decrease ref count of f1. */ - cuddSatDec(f1->ref); - /* Create the new T child. */ - if (f11 == empty) { - if (f01 != empty) { - newf1 = f01; - cuddSatInc(newf1->ref); - } - /* else case was already handled when finding nodes - ** with both children below level y - */ - } else { - /* Check xlist for triple (xindex, f11, f01). */ - posn = ddHash(f11, f01, xshift); - /* For each element newf1 in collision list xlist[posn]. */ - newf1 = xlist[posn]; - while (newf1 != NULL) { - if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { - cuddSatInc(newf1->ref); - break; /* match */ - } - newf1 = newf1->next; - } /* while newf1 */ - if (newf1 == NULL) { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto zddSwapOutOfMem; - newf1->index = xindex; newf1->ref = 1; - cuddT(newf1) = f11; - cuddE(newf1) = f01; - /* Insert newf1 in the collision list xlist[pos]; - ** increase the ref counts of f11 and f01 - */ - newxkeys++; - newf1->next = xlist[posn]; - xlist[posn] = newf1; - cuddSatInc(f11->ref); - cuddSatInc(f01->ref); - } - } - cuddT(f) = newf1; - - /* Do the same for f0. */ - /* Decrease ref count of f0. */ - cuddSatDec(f0->ref); - /* Create the new E child. */ - if (f10 == empty) { - newf0 = f00; - cuddSatInc(newf0->ref); - } else { - /* Check xlist for triple (xindex, f10, f00). */ - posn = ddHash(f10, f00, xshift); - /* For each element newf0 in collision list xlist[posn]. */ - newf0 = xlist[posn]; - while (newf0 != NULL) { - if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { - cuddSatInc(newf0->ref); - break; /* match */ - } - newf0 = newf0->next; - } /* while newf0 */ - if (newf0 == NULL) { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto zddSwapOutOfMem; - newf0->index = xindex; newf0->ref = 1; - cuddT(newf0) = f10; cuddE(newf0) = f00; - /* Insert newf0 in the collision list xlist[posn]; - ** increase the ref counts of f10 and f00. - */ - newxkeys++; - newf0->next = xlist[posn]; - xlist[posn] = newf0; - cuddSatInc(f10->ref); - cuddSatInc(f00->ref); - } - } - cuddE(f) = newf0; - - /* Insert the modified f in ylist. - ** The modified f does not already exists in ylist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, yshift); - newykeys++; - f->next = ylist[posn]; - ylist[posn] = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previousP = &(ylist[i]); - f = *previousP; - while (f != NULL) { - next = f->next; - if (f->ref == 0) { - cuddSatDec(cuddT(f)->ref); - cuddSatDec(cuddE(f)->ref); - cuddDeallocNode(table, f); - newykeys--; - } else { - *previousP = f; - previousP = &(f->next); - } - f = next; - } /* while f */ - *previousP = NULL; - } /* for i */ - - /* Set the appropriate fields in table. */ - table->subtableZ[x].nodelist = ylist; - table->subtableZ[x].slots = yslots; - table->subtableZ[x].shift = yshift; - table->subtableZ[x].keys = newykeys; - table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; - - table->subtableZ[y].nodelist = xlist; - table->subtableZ[y].slots = xslots; - table->subtableZ[y].shift = xshift; - table->subtableZ[y].keys = newxkeys; - table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; - - table->permZ[xindex] = y; table->permZ[yindex] = x; - table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; - - table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; - - /* Update univ section; univ[x] remains the same. */ - table->univ[y] = cuddT(table->univ[x]); - - return (table->keysZ); - -zddSwapOutOfMem: - (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); - - return (0); - -} /* end of cuddZddSwapInPlace */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] - - Description [Implementation of Plessier's algorithm that reorders - variables by a sequence of (non-adjacent) swaps. - <ol> - <li> Select two variables (RANDOM or HEURISTIC). - <li> Permute these variables. - <li> If the nodes have decreased accept the permutation. - <li> Otherwise reconstruct the original heap. - <li> Loop. - </ol> - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSwapping( - DdManager * table, - int lower, - int upper, - Cudd_ReorderingType heuristic) -{ - int i, j; - int max, keys; - int nvars; - int x, y; - int iterate; - int previousSize; - Move *moves, *move; - int pivot; - int modulo; - int result; - -#ifdef DD_DEBUG - /* Sanity check */ - assert(lower >= 0 && upper < table->sizeZ && lower <= upper); -#endif - - nvars = upper - lower + 1; - iterate = nvars; - - for (i = 0; i < iterate; i++) { - if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { - /* Find pivot <= id with maximum keys. */ - for (max = -1, j = lower; j <= upper; j++) { - if ((keys = table->subtableZ[j].keys) > max) { - max = keys; - pivot = j; - } - } - - modulo = upper - pivot; - if (modulo == 0) { - y = pivot; /* y = nvars-1 */ - } else { - /* y = random # from {pivot+1 .. nvars-1} */ - y = pivot + 1 + (int) (Cudd_Random() % modulo); - } - - modulo = pivot - lower - 1; - if (modulo < 1) { /* if pivot = 1 or 0 */ - x = lower; - } else { - do { /* x = random # from {0 .. pivot-2} */ - x = (int) Cudd_Random() % modulo; - } while (x == y); - /* Is this condition really needed, since x and y - are in regions separated by pivot? */ - } - } else { - x = (int) (Cudd_Random() % nvars) + lower; - do { - y = (int) (Cudd_Random() % nvars) + lower; - } while (x == y); - } - - previousSize = table->keysZ; - moves = zddSwapAny(table, x, y); - if (moves == NULL) - goto cuddZddSwappingOutOfMem; - - result = cuddZddSiftingBackward(table, moves, previousSize); - if (!result) - goto cuddZddSwappingOutOfMem; - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - return(1); - -cuddZddSwappingOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(0); - -} /* end of cuddZddSwapping */ - - -/**Function******************************************************************** - - Synopsis [Implementation of Rudell's sifting algorithm.] - - Description [Implementation of Rudell's sifting algorithm. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries - in each unique table. - <li> Sift the variable up and down, remembering each time the - total size of the DD heap. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - </ol> - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->sizeZ; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, size); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - var = ALLOC(int, size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if (x < lower || x > upper) continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddSiftingAux(table, x, lower, upper); - if (!result) - goto cuddZddSiftingOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - FREE(var); - FREE(zdd_entry); - - return(1); - -cuddZddSiftingOutOfMem: - - if (zdd_entry != NULL) FREE(zdd_entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddZddSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Swaps any two variables.] - - Description [Swaps any two variables. Returns the set of moves.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -zddSwapAny( - DdManager * table, - int x, - int y) -{ - Move *move, *moves; - int tmp, size; - int x_ref, y_ref; - int x_next, y_next; - int limit_size; - - if (x > y) { /* make x precede y */ - tmp = x; x = y; y = tmp; - } - - x_ref = x; y_ref = y; - - x_next = cuddZddNextHigh(table, x); - y_next = cuddZddNextLow(table, y); - moves = NULL; - limit_size = table->keysZ; - - for (;;) { - if (x_next == y_next) { /* x < x_next = y_next < y */ - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - - } else if (x == y_next) { /* x = y_next < y = x_next */ - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - } else { - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - x = x_next; y = y_next; - } - - x_next = cuddZddNextHigh(table, x); - y_next = cuddZddNextLow(table, y); - if (x_next > y_ref) - break; /* if x == y_ref */ - - if ((double) size > table->maxGrowth * (double) limit_size) - break; - if (size < limit_size) - limit_size = size; - } - if (y_next >= x_ref) { - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - } - - return(moves); - -zddSwapAnyOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of zddSwapAny */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSiftingAux( - DdManager * table, - int x, - int x_low, - int x_high) -{ - Move *move; - Move *moveUp; /* list of up move */ - Move *moveDown; /* list of down move */ - - int initial_size; - int result; - - initial_size = table->keysZ; - -#ifdef DD_DEBUG - assert(table->subtableZ[x].keys > 0); -#endif - - moveDown = NULL; - moveUp = NULL; - - if (x == x_low) { - moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); - /* after that point x --> x_high */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveDown, - initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - - } - else if (x == x_high) { - moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); - /* after that point x --> x_low */ - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveUp, initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - else if ((x - x_low) > (x_high - x)) { - /* must go down first:shorter */ - moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); - /* after that point x --> x_high */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - moveUp = cuddZddSiftingUp(table, moveDown->y, x_low, - initial_size); - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveUp, initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - else { - moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); - /* after that point x --> x_high */ - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - moveDown = cuddZddSiftingDown(table, moveUp->x, x_high, - initial_size); - /* then move up */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveDown, - initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(1); - -cuddZddSiftingAuxOutOfMem: - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(0); - -} /* end of cuddZddSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up.] - - Description [Sifts a variable up. Moves y up until either it reaches - the bound (x_low) or the size of the ZDD heap increases too much. - Returns the set of moves in case of success; NULL if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSiftingUp( - DdManager * table, - int x, - int x_low, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddZddNextLow(table, x); - while (y >= x_low) { - size = cuddZddSwapInPlace(table, y, x); - if (size == 0) - goto cuddZddSiftingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSiftingUpOutOfMem; - move->x = y; - move->y = x; - move->size = size; - move->next = moves; - moves = move; - - if ((double)size > (double)limit_size * table->maxGrowth) - break; - if (size < limit_size) - limit_size = size; - - x = y; - y = cuddZddNextLow(table, x); - } - return(moves); - -cuddZddSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of cuddZddSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down.] - - Description [Sifts a variable down. Moves x down until either it - reaches the bound (x_high) or the size of the ZDD heap increases too - much. Returns the set of moves in case of success; NULL if memory is - full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSiftingDown( - DdManager * table, - int x, - int x_high, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddZddNextHigh(table, x); - while (y <= x_high) { - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddSiftingDownOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - if ((double)size > (double)limit_size * table->maxGrowth) - break; - if (size < limit_size) - limit_size = size; - - x = y; - y = cuddZddNextHigh(table, x); - } - return(moves); - -cuddZddSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of cuddZddSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the ZDD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - int i; - int i_best; - Move *move; - int res; - - /* Find the minimum size among moves. */ - i_best = -1; - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (move->size < size) { - i_best = i; - size = move->size; - } - } - - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (i == i_best) - break; - res = cuddZddSwapInPlace(table, move->x, move->y); - if (!res) - return(0); - if (i_best == -1 && res == size) - break; - } - - return(1); - -} /* end of cuddZddSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Prepares the ZDD heap for dynamic reordering.] - - Description [Prepares the ZDD heap for dynamic reordering. Does - garbage collection, to guarantee that there are no dead nodes; - and clears the cache, which is invalidated by dynamic reordering.] - - SideEffects [None] - -******************************************************************************/ -static void -zddReorderPreprocess( - DdManager * table) -{ - - /* Clear the cache. */ - cuddCacheFlush(table); - - /* Eliminate dead nodes. Do not scan the cache again. */ - cuddGarbageCollectZdd(table,0); - - return; - -} /* end of ddReorderPreprocess */ - - -/**Function******************************************************************** - - Synopsis [Shrinks almost empty ZDD subtables at the end of reordering - to guarantee that they have a reasonable load factor.] - - Description [Shrinks almost empty subtables at the end of reordering to - guarantee that they have a reasonable load factor. However, if there many - nodes are being reclaimed, then no resizing occurs. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddReorderPostprocess( - DdManager * table) -{ - int i, j, posn; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - unsigned int slots, oldslots; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - -#ifdef DD_VERBOSE - (void) fflush(table->out); -#endif - - /* If we have very many reclaimed nodes, we do not want to shrink - ** the subtables, because this will lead to more garbage - ** collections. More garbage collections mean shorter mean life for - ** nodes with zero reference count; hence lower probability of finding - ** a result in the cache. - */ - if (table->reclaimed > table->allocated * 0.5) return(1); - - /* Resize subtables. */ - for (i = 0; i < table->sizeZ; i++) { - int shift; - oldslots = table->subtableZ[i].slots; - if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY || - oldslots <= table->initSlots) continue; - oldnodelist = table->subtableZ[i].nodelist; - slots = oldslots >> 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - return(1); - } - table->subtableZ[i].nodelist = nodelist; - table->subtableZ[i].slots = slots; - table->subtableZ[i].shift++; - table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; -#ifdef DD_VERBOSE - (void) fprintf(table->err, - "shrunk layer %d (%d keys) from %d to %d slots\n", - i, table->subtableZ[i].keys, oldslots, slots); -#endif - - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - shift = table->subtableZ[i].shift; - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != NULL) { - next = node->next; - posn = ddHash(cuddT(node), cuddE(node), shift); - node->next = nodelist[posn]; - nodelist[posn] = node; - node = next; - } - } - FREE(oldnodelist); - - table->memused += (slots - oldslots) * sizeof(DdNode *); - table->slots += slots - oldslots; - table->minDead = (unsigned) (table->gcFrac * (double) table->slots); - table->cacheSlack = (int) ddMin(table->maxCacheHard, - DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) - - 2 * (int) table->cacheSlots; - } - /* We don't look at the constant subtable, because it is not - ** affected by reordering. - */ - - return(1); - -} /* end of zddReorderPostprocess */ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to a given permutation.] - - Description [Reorders ZDD variables according to a given permutation. - The i-th permutation array contains the index of the variable that - should be brought to the i-th level. zddShuffle assumes that no - dead nodes are present. The reordering is achieved by a series of - upward sifts. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zddShuffle( - DdManager * table, - int * permutation) -{ - int index; - int level; - int position; - int numvars; - int result; -#ifdef DD_STATS - long localTime; - int initialSize; - int finalSize; - int previousSize; -#endif - - zddTotalNumberSwapping = 0; -#ifdef DD_STATS - localTime = util_cpu_time(); - initialSize = table->keysZ; - (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", - initialSize); -#endif - - numvars = table->sizeZ; - - for (level = 0; level < numvars; level++) { - index = permutation[level]; - position = table->permZ[index]; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = zddSiftUp(table,position,level); - if (!result) return(0); -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keysZ; - (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", - zddTotalNumberSwapping); -#endif - - return(1); - -} /* end of zddShuffle */ - - -/**Function******************************************************************** - - Synopsis [Moves one ZDD variable up.] - - Description [Takes a ZDD variable from position x and sifts it up to - position xLow; xLow should be less than or equal to x. - Returns 1 if successful; 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zddSiftUp( - DdManager * table, - int x, - int xLow) -{ - int y; - int size; - - y = cuddZddNextLow(table,x); - while (y >= xLow) { - size = cuddZddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddZddNextLow(table,x); - } - return(1); - -} /* end of zddSiftUp */ - - -/**Function******************************************************************** - - Synopsis [Fixes the ZDD variable group tree after a shuffle.] - - Description [Fixes the ZDD variable group tree after a - shuffle. Assumes that the order of the variables in a terminal node - has not been changed.] - - SideEffects [Changes the ZDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static void -zddFixTree( - DdManager * table, - MtrNode * treenode) -{ - if (treenode == NULL) return; - treenode->low = ((int) treenode->index < table->sizeZ) ? - table->permZ[treenode->index] : treenode->index; - if (treenode->child != NULL) { - zddFixTree(table, treenode->child); - } - if (treenode->younger != NULL) - zddFixTree(table, treenode->younger); - if (treenode->parent != NULL && treenode->low < treenode->parent->low) { - treenode->parent->low = treenode->low; - treenode->parent->index = treenode->index; - } - return; - -} /* end of zddFixTree */ - |