summaryrefslogtreecommitdiffstats
path: root/src/bdd/cudd/cuddExact.c
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2007-09-30 08:01:00 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2007-09-30 08:01:00 -0700
commite54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 (patch)
treede3ffe87c3e17950351e3b7d97fa18318bd5ea9a /src/bdd/cudd/cuddExact.c
parent7d7e60f2dc84393cd4c5db22d2eaf7b1fb1a79b2 (diff)
downloadabc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.gz
abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.bz2
abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.zip
Version abc70930
Diffstat (limited to 'src/bdd/cudd/cuddExact.c')
-rw-r--r--src/bdd/cudd/cuddExact.c1004
1 files changed, 0 insertions, 1004 deletions
diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c
deleted file mode 100644
index 6852be68..00000000
--- a/src/bdd/cudd/cuddExact.c
+++ /dev/null
@@ -1,1004 +0,0 @@
-/**CFile***********************************************************************
-
- FileName [cuddExact.c]
-
- PackageName [cudd]
-
- Synopsis [Functions for exact variable reordering.]
-
- Description [External procedures included in this file:
- <ul>
- </ul>
- Internal procedures included in this module:
- <ul>
- <li> cuddExact()
- </ul>
- Static procedures included in this module:
- <ul>
- <li> getMaxBinomial()
- <li> gcd()
- <li> getMatrix()
- <li> freeMatrix()
- <li> getLevelKeys()
- <li> ddShuffle()
- <li> ddSiftUp()
- <li> updateUB()
- <li> ddCountRoots()
- <li> ddClearGlobal()
- <li> computeLB()
- <li> updateEntry()
- <li> pushDown()
- <li> initSymmInfo()
- </ul>]
-
- Author [Cheng Hua, 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: cuddExact.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $";
-#endif
-
-#ifdef DD_STATS
-static int ddTotalShuffles;
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Macro declarations */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-static int getMaxBinomial ARGS((int n));
-static int gcd ARGS((int x, int y));
-static DdHalfWord ** getMatrix ARGS((int rows, int cols));
-static void freeMatrix ARGS((DdHalfWord **matrix));
-static int getLevelKeys ARGS((DdManager *table, int l));
-static int ddShuffle ARGS((DdManager *table, DdHalfWord *permutation, int lower, int upper));
-static int ddSiftUp ARGS((DdManager *table, int x, int xLow));
-static int updateUB ARGS((DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper));
-static int ddCountRoots ARGS((DdManager *table, int lower, int upper));
-static void ddClearGlobal ARGS((DdManager *table, int lower, int maxlevel));
-static int computeLB ARGS((DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level));
-static int updateEntry ARGS((DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper));
-static void pushDown ARGS((DdHalfWord *order, int j, int level));
-static DdHalfWord * initSymmInfo ARGS((DdManager *table, int lower, int upper));
-static int checkSymmInfo ARGS((DdManager *table, DdHalfWord *symmInfo, int index, int level));
-
-/**AutomaticEnd***************************************************************/
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of exported functions */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Definition of internal functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**Function********************************************************************
-
- Synopsis [Exact variable ordering algorithm.]
-
- Description [Exact variable ordering algorithm. Finds an optimum
- order for the variables between lower and upper. Returns 1 if
- successful; 0 otherwise.]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-int
-cuddExact(
- DdManager * table,
- int lower,
- int upper)
-{
- int k, i, j;
- int maxBinomial, oldSubsets, newSubsets;
- int subsetCost;
- int size; /* number of variables to be reordered */
- int unused, nvars, level, result;
- int upperBound, lowerBound, cost;
- int roots;
- char *mask = NULL;
- DdHalfWord *symmInfo = NULL;
- DdHalfWord **newOrder = NULL;
- DdHalfWord **oldOrder = NULL;
- int *newCost = NULL;
- int *oldCost = NULL;
- DdHalfWord **tmpOrder;
- int *tmpCost;
- DdHalfWord *bestOrder = NULL;
- DdHalfWord *order;
-#ifdef DD_STATS
- int ddTotalSubsets;
-#endif
-
- /* Restrict the range to be reordered by excluding unused variables
- ** at the two ends. */
- while (table->subtables[lower].keys == 1 &&
- table->vars[table->invperm[lower]]->ref == 1 &&
- lower < upper)
- lower++;
- while (table->subtables[upper].keys == 1 &&
- table->vars[table->invperm[upper]]->ref == 1 &&
- lower < upper)
- upper--;
- if (lower == upper) return(1); /* trivial problem */
-
- /* Apply symmetric sifting to get a good upper bound and to extract
- ** symmetry information. */
- result = cuddSymmSiftingConv(table,lower,upper);
- if (result == 0) goto cuddExactOutOfMem;
-
-#ifdef DD_STATS
- (void) fprintf(table->out,"\n");
- ddTotalShuffles = 0;
- ddTotalSubsets = 0;
-#endif
-
- /* Initialization. */
- nvars = table->size;
- size = upper - lower + 1;
- /* Count unused variable among those to be reordered. This is only
- ** used to compute maxBinomial. */
- unused = 0;
- for (i = lower + 1; i < upper; i++) {
- if (table->subtables[i].keys == 1 &&
- table->vars[table->invperm[i]]->ref == 1)
- unused++;
- }
-
- /* Find the maximum number of subsets we may have to store. */
- maxBinomial = getMaxBinomial(size - unused);
- if (maxBinomial == -1) goto cuddExactOutOfMem;
-
- newOrder = getMatrix(maxBinomial, size);
- if (newOrder == NULL) goto cuddExactOutOfMem;
-
- newCost = ALLOC(int, maxBinomial);
- if (newCost == NULL) goto cuddExactOutOfMem;
-
- oldOrder = getMatrix(maxBinomial, size);
- if (oldOrder == NULL) goto cuddExactOutOfMem;
-
- oldCost = ALLOC(int, maxBinomial);
- if (oldCost == NULL) goto cuddExactOutOfMem;
-
- bestOrder = ALLOC(DdHalfWord, size);
- if (bestOrder == NULL) goto cuddExactOutOfMem;
-
- mask = ALLOC(char, nvars);
- if (mask == NULL) goto cuddExactOutOfMem;
-
- symmInfo = initSymmInfo(table, lower, upper);
- if (symmInfo == NULL) goto cuddExactOutOfMem;
-
- roots = ddCountRoots(table, lower, upper);
-
- /* Initialize the old order matrix for the empty subset and the best
- ** order to the current order. The cost for the empty subset includes
- ** the cost of the levels between upper and the constants. These levels
- ** are not going to change. Hence, we count them only once.
- */
- oldSubsets = 1;
- for (i = 0; i < size; i++) {
- oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower];
- }
- subsetCost = table->constants.keys;
- for (i = upper + 1; i < nvars; i++)
- subsetCost += getLevelKeys(table,i);
- oldCost[0] = subsetCost;
- /* The upper bound is initialized to the current size of the BDDs. */
- upperBound = table->keys - table->isolated;
-
- /* Now consider subsets of increasing size. */
- for (k = 1; k <= size; k++) {
-#if DD_STATS
- (void) fprintf(table->out,"Processing subsets of size %d\n", k);
- fflush(table->out);
-#endif
- newSubsets = 0;
- level = size - k; /* offset of first bottom variable */
-
- for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */
- order = oldOrder[i];
- cost = oldCost[i];
- lowerBound = computeLB(table, order, roots, cost, lower, upper,
- level);
- if (lowerBound >= upperBound)
- continue;
- /* Impose new order. */
- result = ddShuffle(table, order, lower, upper);
- if (result == 0) goto cuddExactOutOfMem;
- upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
- /* For each top bottom variable. */
- for (j = level; j >= 0; j--) {
- /* Skip unused variables. */
- if (table->subtables[j+lower-1].keys == 1 &&
- table->vars[table->invperm[j+lower-1]]->ref == 1) continue;
- /* Find cost under this order. */
- subsetCost = cost + getLevelKeys(table, lower + level);
- newSubsets = updateEntry(table, order, level, subsetCost,
- newOrder, newCost, newSubsets, mask,
- lower, upper);
- if (j == 0)
- break;
- if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0)
- continue;
- pushDown(order,j-1,level);
- /* Impose new order. */
- result = ddShuffle(table, order, lower, upper);
- if (result == 0) goto cuddExactOutOfMem;
- upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
- } /* for each bottom variable */
- } /* for each subset of size k */
-
- /* New orders become old orders in preparation for next iteration. */
- tmpOrder = oldOrder; tmpCost = oldCost;
- oldOrder = newOrder; oldCost = newCost;
- newOrder = tmpOrder; newCost = tmpCost;
-#ifdef DD_STATS
- ddTotalSubsets += newSubsets;
-#endif
- oldSubsets = newSubsets;
- }
- result = ddShuffle(table, bestOrder, lower, upper);
- if (result == 0) goto cuddExactOutOfMem;
-#ifdef DD_STATS
-#ifdef DD_VERBOSE
- (void) fprintf(table->out,"\n");
-#endif
- (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n",
- ddTotalSubsets);
- (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles",
- ddTotalShuffles);
-#endif
-
- freeMatrix(newOrder);
- freeMatrix(oldOrder);
- FREE(bestOrder);
- FREE(oldCost);
- FREE(newCost);
- FREE(symmInfo);
- FREE(mask);
- return(1);
-
-cuddExactOutOfMem:
-
- if (newOrder != NULL) freeMatrix(newOrder);
- if (oldOrder != NULL) freeMatrix(oldOrder);
- if (bestOrder != NULL) FREE(bestOrder);
- if (oldCost != NULL) FREE(oldCost);
- if (newCost != NULL) FREE(newCost);
- if (symmInfo != NULL) FREE(symmInfo);
- if (mask != NULL) FREE(mask);
- table->errorCode = CUDD_MEMORY_OUT;
- return(0);
-
-} /* end of cuddExact */
-
-
-/**Function********************************************************************
-
- Synopsis [Returns the maximum value of (n choose k) for a given n.]
-
- Description [Computes the maximum value of (n choose k) for a given
- n. The maximum value occurs for k = n/2 when n is even, or k =
- (n-1)/2 when n is odd. The algorithm used in this procedure is
- quite inefficient, but it avoids intermediate overflow problems.
- Returns the computed value if successful; -1 otherwise.]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-getMaxBinomial(
- int n)
-{
- int *numerator;
- int i, j, k, y, g, result;
-
- k = (n & ~1) >> 1;
-
- numerator = ALLOC(int,k);
- if (numerator == NULL) return(-1);
-
- for (i = 0; i < k; i++)
- numerator[i] = n - i;
-
- for (i = k; i > 1; i--) {
- y = i;
- for (j = 0; j < k; j++) {
- if (numerator[j] == 1) continue;
- g = gcd(numerator[j], y);
- if (g != 1) {
- numerator[j] /= g;
- if (y == g) break;
- y /= g;
- }
- }
- }
-
- result = 1;
- for (i = 0; i < k; i++)
- result *= numerator[i];
-
- FREE(numerator);
- return(result);
-
-} /* end of getMaxBinomial */
-
-
-/**Function********************************************************************
-
- Synopsis [Returns the gcd of two integers.]
-
- Description [Returns the gcd of two integers. Uses the binary GCD
- algorithm described in Cormen, Leiserson, and Rivest.]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-gcd(
- int x,
- int y)
-{
- int a;
- int b;
- int lsbMask;
-
- /* GCD(n,0) = n. */
- if (x == 0) return(y);
- if (y == 0) return(x);
-
- a = x; b = y; lsbMask = 1;
-
- /* Here both a and b are != 0. The iteration maintains this invariant.
- ** Hence, we only need to check for when they become equal.
- */
- while (a != b) {
- if (a & lsbMask) {
- if (b & lsbMask) { /* both odd */
- if (a < b) {
- b = (b - a) >> 1;
- } else {
- a = (a - b) >> 1;
- }
- } else { /* a odd, b even */
- b >>= 1;
- }
- } else {
- if (b & lsbMask) { /* a even, b odd */
- a >>= 1;
- } else { /* both even */
- lsbMask <<= 1;
- }
- }
- }
-
- return(a);
-
-} /* end of gcd */
-
-
-/**Function********************************************************************
-
- Synopsis [Allocates a two-dimensional matrix of ints.]
-
- Description [Allocates a two-dimensional matrix of ints.
- Returns the pointer to the matrix if successful; NULL otherwise.]
-
- SideEffects [None]
-
- SeeAlso [freeMatrix]
-
-******************************************************************************/
-static DdHalfWord **
-getMatrix(
- int rows /* number of rows */,
- int cols /* number of columns */)
-{
- DdHalfWord **matrix;
- int i;
-
- if (cols*rows == 0) return(NULL);
- matrix = ALLOC(DdHalfWord *, rows);
- if (matrix == NULL) return(NULL);
- matrix[0] = ALLOC(DdHalfWord, cols*rows);
- if (matrix[0] == NULL) return(NULL);
- for (i = 1; i < rows; i++) {
- matrix[i] = matrix[i-1] + cols;
- }
- return(matrix);
-
-} /* end of getMatrix */
-
-
-/**Function********************************************************************
-
- Synopsis [Frees a two-dimensional matrix allocated by getMatrix.]
-
- Description []
-
- SideEffects [None]
-
- SeeAlso [getMatrix]
-
-******************************************************************************/
-static void
-freeMatrix(
- DdHalfWord ** matrix)
-{
- FREE(matrix[0]);
- FREE(matrix);
- return;
-
-} /* end of freeMatrix */
-
-
-/**Function********************************************************************
-
- Synopsis [Returns the number of nodes at one level of a unique table.]
-
- Description [Returns the number of nodes at one level of a unique table.
- The projection function, if isolated, is not counted.]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-getLevelKeys(
- DdManager * table,
- int l)
-{
- int isolated;
- int x; /* x is an index */
-
- x = table->invperm[l];
- isolated = table->vars[x]->ref == 1;
-
- return(table->subtables[l].keys - isolated);
-
-} /* end of getLevelKeys */
-
-
-/**Function********************************************************************
-
- Synopsis [Reorders variables according to a given permutation.]
-
- Description [Reorders 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. ddShuffle assumes that no
- dead nodes are present and that the interaction matrix is properly
- initialized. The reordering is achieved by a series of upward sifts.
- Returns 1 if successful; 0 otherwise.]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-ddShuffle(
- DdManager * table,
- DdHalfWord * permutation,
- int lower,
- int upper)
-{
- DdHalfWord index;
- int level;
- int position;
- int numvars;
- int result;
-#ifdef DD_STATS
- long localTime;
- int initialSize;
-#ifdef DD_VERBOSE
- int finalSize;
-#endif
- int previousSize;
-#endif
-
-#ifdef DD_STATS
- localTime = util_cpu_time();
- initialSize = table->keys - table->isolated;
-#endif
-
- numvars = table->size;
-
-#if 0
- (void) fprintf(table->out,"%d:", ddTotalShuffles);
- for (level = 0; level < numvars; level++) {
- (void) fprintf(table->out," %d", table->invperm[level]);
- }
- (void) fprintf(table->out,"\n");
-#endif
-
- for (level = 0; level <= upper - lower; level++) {
- index = permutation[level];
- position = table->perm[index];
-#ifdef DD_STATS
- previousSize = table->keys - table->isolated;
-#endif
- result = ddSiftUp(table,position,level+lower);
- if (!result) return(0);
- }
-
-#ifdef DD_STATS
- ddTotalShuffles++;
-#ifdef DD_VERBOSE
- finalSize = table->keys - table->isolated;
- if (finalSize < initialSize) {
- (void) fprintf(table->out,"-");
- } else if (finalSize > initialSize) {
- (void) fprintf(table->out,"+");
- } else {
- (void) fprintf(table->out,"=");
- }
- if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n");
- fflush(table->out);
-#endif
-#endif
-
- return(1);
-
-} /* end of ddShuffle */
-
-
-/**Function********************************************************************
-
- Synopsis [Moves one variable up.]
-
- Description [Takes a 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
-ddSiftUp(
- DdManager * table,
- int x,
- int xLow)
-{
- int y;
- int size;
-
- y = cuddNextLow(table,x);
- while (y >= xLow) {
- size = cuddSwapInPlace(table,y,x);
- if (size == 0) {
- return(0);
- }
- x = y;
- y = cuddNextLow(table,x);
- }
- return(1);
-
-} /* end of ddSiftUp */
-
-
-/**Function********************************************************************
-
- Synopsis [Updates the upper bound and saves the best order seen so far.]
-
- Description [Updates the upper bound and saves the best order seen so far.
- Returns the current value of the upper bound.]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-updateUB(
- DdManager * table,
- int oldBound,
- DdHalfWord * bestOrder,
- int lower,
- int upper)
-{
- int i;
- int newBound = table->keys - table->isolated;
-
- if (newBound < oldBound) {
-#ifdef DD_STATS
- (void) fprintf(table->out,"New upper bound = %d\n", newBound);
- fflush(table->out);
-#endif
- for (i = lower; i <= upper; i++)
- bestOrder[i-lower] = (DdHalfWord) table->invperm[i];
- return(newBound);
- } else {
- return(oldBound);
- }
-
-} /* end of updateUB */
-
-
-/**Function********************************************************************
-
- Synopsis [Counts the number of roots.]
-
- Description [Counts the number of roots at the levels between lower and
- upper. The computation is based on breadth-first search.
- A node is a root if it is not reachable from any previously visited node.
- (All the nodes at level lower are therefore considered roots.)
- The visited flag uses the LSB of the next pointer. Returns the root
- count. The roots that are constant nodes are always ignored.]
-
- SideEffects [None]
-
- SeeAlso [ddClearGlobal]
-
-******************************************************************************/
-static int
-ddCountRoots(
- DdManager * table,
- int lower,
- int upper)
-{
- int i,j;
- DdNode *f;
- DdNodePtr *nodelist;
- DdNode *sentinel = &(table->sentinel);
- int slots;
- int roots = 0;
- int maxlevel = lower;
-
- for (i = lower; i <= upper; i++) {
- nodelist = table->subtables[i].nodelist;
- slots = table->subtables[i].slots;
- for (j = 0; j < slots; j++) {
- f = nodelist[j];
- while (f != sentinel) {
- /* A node is a root of the DAG if it cannot be
- ** reached by nodes above it. If a node was never
- ** reached during the previous depth-first searches,
- ** then it is a root, and we start a new depth-first
- ** search from it.
- */
- if (!Cudd_IsComplement(f->next)) {
- if (f != table->vars[f->index]) {
- roots++;
- }
- }
- if (!Cudd_IsConstant(cuddT(f))) {
- cuddT(f)->next = Cudd_Complement(cuddT(f)->next);
- if (table->perm[cuddT(f)->index] > maxlevel)
- maxlevel = table->perm[cuddT(f)->index];
- }
- if (!Cudd_IsConstant(cuddE(f))) {
- Cudd_Regular(cuddE(f))->next =
- Cudd_Complement(Cudd_Regular(cuddE(f))->next);
- if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel)
- maxlevel = table->perm[Cudd_Regular(cuddE(f))->index];
- }
- f = Cudd_Regular(f->next);
- }
- }
- }
- ddClearGlobal(table, lower, maxlevel);
-
- return(roots);
-
-} /* end of ddCountRoots */
-
-
-/**Function********************************************************************
-
- Synopsis [Scans the DD and clears the LSB of the next pointers.]
-
- Description [Scans the DD and clears the LSB of the next pointers.
- The LSB of the next pointers are used as markers to tell whether a
- node was reached. Once the roots are counted, these flags are
- reset.]
-
- SideEffects [None]
-
- SeeAlso [ddCountRoots]
-
-******************************************************************************/
-static void
-ddClearGlobal(
- DdManager * table,
- int lower,
- int maxlevel)
-{
- int i,j;
- DdNode *f;
- DdNodePtr *nodelist;
- DdNode *sentinel = &(table->sentinel);
- int slots;
-
- for (i = lower; i <= maxlevel; i++) {
- nodelist = table->subtables[i].nodelist;
- slots = table->subtables[i].slots;
- for (j = 0; j < slots; j++) {
- f = nodelist[j];
- while (f != sentinel) {
- f->next = Cudd_Regular(f->next);
- f = f->next;
- }
- }
- }
-
-} /* end of ddClearGlobal */
-
-
-/**Function********************************************************************
-
- Synopsis [Computes a lower bound on the size of a BDD.]
-
- Description [Computes a lower bound on the size of a BDD from the
- following factors:
- <ul>
- <li> size of the lower part of it;
- <li> size of the part of the upper part not subjected to reordering;
- <li> number of roots in the part of the BDD subjected to reordering;
- <li> variable in the support of the roots in the upper part of the
- BDD subjected to reordering.
- <ul/>]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-computeLB(
- DdManager * table /* manager */,
- DdHalfWord * order /* optimal order for the subset */,
- int roots /* roots between lower and upper */,
- int cost /* minimum cost for the subset */,
- int lower /* lower level to be reordered */,
- int upper /* upper level to be reordered */,
- int level /* offset for the current top bottom var */
- )
-{
- int i;
- int lb = cost;
- int lb1 = 0;
- int lb2;
- int support;
- DdHalfWord ref;
-
- /* The levels not involved in reordering are not going to change.
- ** Add their sizes to the lower bound.
- */
- for (i = 0; i < lower; i++) {
- lb += getLevelKeys(table,i);
- }
- /* If a variable is in the support, then there is going
- ** to be at least one node labeled by that variable.
- */
- for (i = lower; i <= lower+level; i++) {
- support = table->subtables[i].keys > 1 ||
- table->vars[order[i-lower]]->ref > 1;
- lb1 += support;
- }
-
- /* Estimate the number of nodes required to connect the roots to
- ** the nodes in the bottom part. */
- if (lower+level+1 < table->size) {
- if (lower+level < upper)
- ref = table->vars[order[level+1]]->ref;
- else
- ref = table->vars[table->invperm[upper+1]]->ref;
- lb2 = table->subtables[lower+level+1].keys -
- (ref > (DdHalfWord) 1) - roots;
- } else {
- lb2 = 0;
- }
-
- lb += lb1 > lb2 ? lb1 : lb2;
-
- return(lb);
-
-} /* end of computeLB */
-
-
-/**Function********************************************************************
-
- Synopsis [Updates entry for a subset.]
-
- Description [Updates entry for a subset. Finds the subset, if it exists.
- If the new order for the subset has lower cost, or if the subset did not
- exist, it stores the new order and cost. Returns the number of subsets
- currently in the table.]
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-updateEntry(
- DdManager * table,
- DdHalfWord * order,
- int level,
- int cost,
- DdHalfWord ** orders,
- int * costs,
- int subsets,
- char * mask,
- int lower,
- int upper)
-{
- int i, j;
- int size = upper - lower + 1;
-
- /* Build a mask that says what variables are in this subset. */
- for (i = lower; i <= upper; i++)
- mask[table->invperm[i]] = 0;
- for (i = level; i < size; i++)
- mask[order[i]] = 1;
-
- /* Check each subset until a match is found or all subsets are examined. */
- for (i = 0; i < subsets; i++) {
- DdHalfWord *subset = orders[i];
- for (j = level; j < size; j++) {
- if (mask[subset[j]] == 0)
- break;
- }
- if (j == size) /* no mismatches: success */
- break;
- }
- if (i == subsets || cost < costs[i]) { /* add or replace */
- for (j = 0; j < size; j++)
- orders[i][j] = order[j];
- costs[i] = cost;
- subsets += (i == subsets);
- }
- return(subsets);
-
-} /* end of updateEntry */
-
-
-/**Function********************************************************************
-
- Synopsis [Pushes a variable in the order down to position "level."]
-
- Description []
-
- SideEffects [None]
-
- SeeAlso []
-
-******************************************************************************/
-static void
-pushDown(
- DdHalfWord * order,
- int j,
- int level)
-{
- int i;
- DdHalfWord tmp;
-
- tmp = order[j];
- for (i = j; i < level; i++) {
- order[i] = order[i+1];
- }
- order[level] = tmp;
- return;
-
-} /* end of pushDown */
-
-
-/**Function********************************************************************
-
- Synopsis [Gathers symmetry information.]
-
- Description [Translates the symmetry information stored in the next
- field of each subtable from level to indices. This procedure is called
- immediately after symmetric sifting, so that the next fields are correct.
- By translating this informaton in terms of indices, we make it independent
- of subsequent reorderings. The format used is that of the next fields:
- a circular list where each variable points to the next variable in the
- same symmetry group. Only the entries between lower and upper are
- considered. The procedure returns a pointer to an array
- holding the symmetry information if successful; NULL otherwise.]
-
- SideEffects [None]
-
- SeeAlso [checkSymmInfo]
-
-******************************************************************************/
-static DdHalfWord *
-initSymmInfo(
- DdManager * table,
- int lower,
- int upper)
-{
- int level, index, next, nextindex;
- DdHalfWord *symmInfo;
-
- symmInfo = ALLOC(DdHalfWord, table->size);
- if (symmInfo == NULL) return(NULL);
-
- for (level = lower; level <= upper; level++) {
- index = table->invperm[level];
- next = table->subtables[level].next;
- nextindex = table->invperm[next];
- symmInfo[index] = nextindex;
- }
- return(symmInfo);
-
-} /* end of initSymmInfo */
-
-
-/**Function********************************************************************
-
- Synopsis [Check symmetry condition.]
-
- Description [Returns 1 if a variable is the one with the highest index
- among those belonging to a symmetry group that are in the top part of
- the BDD. The top part is given by level.]
-
- SideEffects [None]
-
- SeeAlso [initSymmInfo]
-
-******************************************************************************/
-static int
-checkSymmInfo(
- DdManager * table,
- DdHalfWord * symmInfo,
- int index,
- int level)
-{
- int i;
-
- i = symmInfo[index];
- while (i != index) {
- if (index < i && table->perm[i] <= level)
- return(0);
- i = symmInfo[i];
- }
- return(1);
-
-} /* end of checkSymmInfo */
-