src/bdd/cudd/cuddExact.c File Reference

#include "util_hack.h"
#include "cuddInt.h"
Include dependency graph for cuddExact.c:

Go to the source code of this file.

Functions

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 int checkSymmInfo ARGS ((DdManager *table, DdHalfWord *symmInfo, int index, int level))
int cuddExact (DdManager *table, int lower, int upper)
static int getMaxBinomial (int n)
static int gcd (int x, int y)
static DdHalfWord ** getMatrix (int rows, int cols)
static void freeMatrix (DdHalfWord **matrix)
static int getLevelKeys (DdManager *table, int l)
static int ddShuffle (DdManager *table, DdHalfWord *permutation, int lower, int upper)
static int ddSiftUp (DdManager *table, int x, int xLow)
static int updateUB (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)
static int ddCountRoots (DdManager *table, int lower, int upper)
static void ddClearGlobal (DdManager *table, int lower, int maxlevel)
static int computeLB (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)
static int updateEntry (DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper)
static void pushDown (DdHalfWord *order, int j, int level)
static DdHalfWordinitSymmInfo (DdManager *table, int lower, int upper)
static int checkSymmInfo (DdManager *table, DdHalfWord *symmInfo, int index, int level)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"

Function Documentation

static int checkSymmInfo ARGS ( (DdManager *table, DdHalfWord *symmInfo, int index, int level)   )  [static]
static void pushDown ARGS ( (DdHalfWord *order, int j, int level)   )  [static]
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]
static int computeLB ARGS ( (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)   )  [static]
static void ddClearGlobal ARGS ( (DdManager *table, int lower, int maxlevel)   )  [static]
static int ddCountRoots ARGS ( (DdManager *table, int lower, int upper)   )  [static]
static int updateUB ARGS ( (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)   )  [static]
static int ddSiftUp ARGS ( (DdManager *table, int x, int xLow)   )  [static]
static int ddShuffle ARGS ( (DdManager *table, DdHalfWord *permutation, int lower, int upper)   )  [static]
static int getLevelKeys ARGS ( (DdManager *table, int l)   )  [static]
static void freeMatrix ARGS ( (DdHalfWord **matrix)   )  [static]
static DdHalfWord** getMatrix ARGS ( (int rows, int cols)   )  [static]
static int gcd ARGS ( (int x, int y)   )  [static]
static int getMaxBinomial ARGS ( (int n)   )  [static]

AutomaticStart

static int checkSymmInfo ( DdManager table,
DdHalfWord symmInfo,
int  index,
int  level 
) [static]

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]

Definition at line 987 of file cuddExact.c.

00992 {
00993     int i;
00994 
00995     i = symmInfo[index];
00996     while (i != index) {
00997         if (index < i && table->perm[i] <= level)
00998             return(0);
00999         i = symmInfo[i];
01000     }
01001     return(1);
01002 
01003 } /* end of checkSymmInfo */

static int computeLB ( DdManager table,
DdHalfWord order,
int  roots,
int  cost,
int  lower,
int  upper,
int  level 
) [static]

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:

  • size of the lower part of it;
  • size of the part of the upper part not subjected to reordering;
  • number of roots in the part of the BDD subjected to reordering;
  • variable in the support of the roots in the upper part of the BDD subjected to reordering.

    SideEffects [None]

    SeeAlso []

Definition at line 792 of file cuddExact.c.

00801 {
00802     int i;
00803     int lb = cost;
00804     int lb1 = 0;
00805     int lb2;
00806     int support;
00807     DdHalfWord ref;
00808 
00809     /* The levels not involved in reordering are not going to change.
00810     ** Add their sizes to the lower bound.
00811     */
00812     for (i = 0; i < lower; i++) {
00813         lb += getLevelKeys(table,i);
00814     }
00815     /* If a variable is in the support, then there is going
00816     ** to be at least one node labeled by that variable.
00817     */
00818     for (i = lower; i <= lower+level; i++) {
00819         support = table->subtables[i].keys > 1 ||
00820             table->vars[order[i-lower]]->ref > 1;
00821         lb1 += support;
00822     }
00823 
00824     /* Estimate the number of nodes required to connect the roots to
00825     ** the nodes in the bottom part. */
00826     if (lower+level+1 < table->size) {
00827         if (lower+level < upper)
00828             ref = table->vars[order[level+1]]->ref;
00829         else
00830             ref = table->vars[table->invperm[upper+1]]->ref;
00831         lb2 = table->subtables[lower+level+1].keys -
00832             (ref > (DdHalfWord) 1) - roots;
00833     } else {
00834         lb2 = 0;
00835     }
00836 
00837     lb += lb1 > lb2 ? lb1 : lb2;
00838 
00839     return(lb);
00840 
00841 } /* end of computeLB */

int cuddExact ( DdManager table,
int  lower,
int  upper 
)

AutomaticEnd 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 []

Definition at line 123 of file cuddExact.c.

00127 {
00128     int k, i, j;
00129     int maxBinomial, oldSubsets, newSubsets;
00130     int subsetCost;
00131     int size;                   /* number of variables to be reordered */
00132     int unused, nvars, level, result;
00133     int upperBound, lowerBound, cost;
00134     int roots;
00135     char *mask = NULL;
00136     DdHalfWord  *symmInfo = NULL;
00137     DdHalfWord **newOrder = NULL;
00138     DdHalfWord **oldOrder = NULL;
00139     int *newCost = NULL;
00140     int *oldCost = NULL;
00141     DdHalfWord **tmpOrder;
00142     int *tmpCost;
00143     DdHalfWord *bestOrder = NULL;
00144     DdHalfWord *order;
00145 #ifdef DD_STATS
00146     int  ddTotalSubsets;
00147 #endif
00148 
00149     /* Restrict the range to be reordered by excluding unused variables
00150     ** at the two ends. */
00151     while (table->subtables[lower].keys == 1 &&
00152            table->vars[table->invperm[lower]]->ref == 1 &&
00153            lower < upper)
00154         lower++;
00155     while (table->subtables[upper].keys == 1 &&
00156            table->vars[table->invperm[upper]]->ref == 1 &&
00157            lower < upper)
00158         upper--;
00159     if (lower == upper) return(1); /* trivial problem */
00160 
00161     /* Apply symmetric sifting to get a good upper bound and to extract
00162     ** symmetry information. */
00163     result = cuddSymmSiftingConv(table,lower,upper);
00164     if (result == 0) goto cuddExactOutOfMem;
00165 
00166 #ifdef DD_STATS
00167     (void) fprintf(table->out,"\n");
00168     ddTotalShuffles = 0;
00169     ddTotalSubsets = 0;
00170 #endif
00171 
00172     /* Initialization. */
00173     nvars = table->size;
00174     size = upper - lower + 1;
00175     /* Count unused variable among those to be reordered.  This is only
00176     ** used to compute maxBinomial. */
00177     unused = 0;
00178     for (i = lower + 1; i < upper; i++) {
00179         if (table->subtables[i].keys == 1 &&
00180             table->vars[table->invperm[i]]->ref == 1)
00181             unused++;
00182     }
00183 
00184     /* Find the maximum number of subsets we may have to store. */
00185     maxBinomial = getMaxBinomial(size - unused);
00186     if (maxBinomial == -1) goto cuddExactOutOfMem;
00187 
00188     newOrder = getMatrix(maxBinomial, size);
00189     if (newOrder == NULL) goto cuddExactOutOfMem;
00190 
00191     newCost = ALLOC(int, maxBinomial);
00192     if (newCost == NULL) goto cuddExactOutOfMem;
00193 
00194     oldOrder = getMatrix(maxBinomial, size);
00195     if (oldOrder == NULL) goto cuddExactOutOfMem;
00196 
00197     oldCost = ALLOC(int, maxBinomial);
00198     if (oldCost == NULL) goto cuddExactOutOfMem;
00199 
00200     bestOrder = ALLOC(DdHalfWord, size);
00201     if (bestOrder == NULL) goto cuddExactOutOfMem;
00202 
00203     mask = ALLOC(char, nvars);
00204     if (mask == NULL) goto cuddExactOutOfMem;
00205 
00206     symmInfo = initSymmInfo(table, lower, upper);
00207     if (symmInfo == NULL) goto cuddExactOutOfMem;
00208 
00209     roots = ddCountRoots(table, lower, upper);
00210 
00211     /* Initialize the old order matrix for the empty subset and the best
00212     ** order to the current order. The cost for the empty subset includes
00213     ** the cost of the levels between upper and the constants. These levels
00214     ** are not going to change. Hence, we count them only once.
00215     */
00216     oldSubsets = 1;
00217     for (i = 0; i < size; i++) {
00218         oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower];
00219     }
00220     subsetCost = table->constants.keys;
00221     for (i = upper + 1; i < nvars; i++)
00222         subsetCost += getLevelKeys(table,i);
00223     oldCost[0] = subsetCost;
00224     /* The upper bound is initialized to the current size of the BDDs. */
00225     upperBound = table->keys - table->isolated;
00226 
00227     /* Now consider subsets of increasing size. */
00228     for (k = 1; k <= size; k++) {
00229 #if DD_STATS
00230         (void) fprintf(table->out,"Processing subsets of size %d\n", k);
00231         fflush(table->out);
00232 #endif
00233         newSubsets = 0;
00234         level = size - k;               /* offset of first bottom variable */
00235 
00236         for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */
00237             order = oldOrder[i];
00238             cost = oldCost[i];
00239             lowerBound = computeLB(table, order, roots, cost, lower, upper,
00240                                    level);
00241             if (lowerBound >= upperBound)
00242                 continue;
00243             /* Impose new order. */
00244             result = ddShuffle(table, order, lower, upper);
00245             if (result == 0) goto cuddExactOutOfMem;
00246             upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
00247             /* For each top bottom variable. */
00248             for (j = level; j >= 0; j--) {
00249                 /* Skip unused variables. */
00250                 if (table->subtables[j+lower-1].keys == 1 &&
00251                     table->vars[table->invperm[j+lower-1]]->ref == 1) continue;
00252                 /* Find cost under this order. */
00253                 subsetCost = cost + getLevelKeys(table, lower + level);
00254                 newSubsets = updateEntry(table, order, level, subsetCost,
00255                                          newOrder, newCost, newSubsets, mask,
00256                                          lower, upper);
00257                 if (j == 0)
00258                     break;
00259                 if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0)
00260                     continue;
00261                 pushDown(order,j-1,level);
00262                 /* Impose new order. */
00263                 result = ddShuffle(table, order, lower, upper);
00264                 if (result == 0) goto cuddExactOutOfMem;
00265                 upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
00266             } /* for each bottom variable */
00267         } /* for each subset of size k */
00268 
00269         /* New orders become old orders in preparation for next iteration. */
00270         tmpOrder = oldOrder; tmpCost = oldCost;
00271         oldOrder = newOrder; oldCost = newCost;
00272         newOrder = tmpOrder; newCost = tmpCost;
00273 #ifdef DD_STATS
00274         ddTotalSubsets += newSubsets;
00275 #endif
00276         oldSubsets = newSubsets;
00277     }
00278     result = ddShuffle(table, bestOrder, lower, upper);
00279     if (result == 0) goto cuddExactOutOfMem;
00280 #ifdef DD_STATS
00281 #ifdef DD_VERBOSE
00282     (void) fprintf(table->out,"\n");
00283 #endif
00284     (void) fprintf(table->out,"#:S_EXACT   %8d: total subsets\n",
00285                    ddTotalSubsets);
00286     (void) fprintf(table->out,"#:H_EXACT   %8d: total shuffles",
00287                    ddTotalShuffles);
00288 #endif
00289 
00290     freeMatrix(newOrder);
00291     freeMatrix(oldOrder);
00292     FREE(bestOrder);
00293     FREE(oldCost);
00294     FREE(newCost);
00295     FREE(symmInfo);
00296     FREE(mask);
00297     return(1);
00298 
00299 cuddExactOutOfMem:
00300 
00301     if (newOrder != NULL) freeMatrix(newOrder);
00302     if (oldOrder != NULL) freeMatrix(oldOrder);
00303     if (bestOrder != NULL) FREE(bestOrder);
00304     if (oldCost != NULL) FREE(oldCost);
00305     if (newCost != NULL) FREE(newCost);
00306     if (symmInfo != NULL) FREE(symmInfo);
00307     if (mask != NULL) FREE(mask);
00308     table->errorCode = CUDD_MEMORY_OUT;
00309     return(0);
00310 
00311 } /* end of cuddExact */

static void ddClearGlobal ( DdManager table,
int  lower,
int  maxlevel 
) [static]

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]

Definition at line 746 of file cuddExact.c.

00750 {
00751     int i,j;
00752     DdNode *f;
00753     DdNodePtr *nodelist;
00754     DdNode *sentinel = &(table->sentinel);
00755     int slots;
00756 
00757     for (i = lower; i <= maxlevel; i++) {
00758         nodelist = table->subtables[i].nodelist;
00759         slots = table->subtables[i].slots;
00760         for (j = 0; j < slots; j++) {
00761             f = nodelist[j];
00762             while (f != sentinel) {
00763                 f->next = Cudd_Regular(f->next);
00764                 f = f->next;
00765             }
00766         }
00767     }
00768 
00769 } /* end of ddClearGlobal */

static int ddCountRoots ( DdManager table,
int  lower,
int  upper 
) [static]

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]

Definition at line 679 of file cuddExact.c.

00683 {
00684     int i,j;
00685     DdNode *f;
00686     DdNodePtr *nodelist;
00687     DdNode *sentinel = &(table->sentinel);
00688     int slots;
00689     int roots = 0;
00690     int maxlevel = lower;
00691 
00692     for (i = lower; i <= upper; i++) {
00693         nodelist = table->subtables[i].nodelist;
00694         slots = table->subtables[i].slots;
00695         for (j = 0; j < slots; j++) {
00696             f = nodelist[j];
00697             while (f != sentinel) {
00698                 /* A node is a root of the DAG if it cannot be
00699                 ** reached by nodes above it. If a node was never
00700                 ** reached during the previous depth-first searches,
00701                 ** then it is a root, and we start a new depth-first
00702                 ** search from it.
00703                 */
00704                 if (!Cudd_IsComplement(f->next)) {
00705                     if (f != table->vars[f->index]) {
00706                         roots++;
00707                     }
00708                 }
00709                 if (!Cudd_IsConstant(cuddT(f))) {
00710                     cuddT(f)->next = Cudd_Complement(cuddT(f)->next);
00711                     if (table->perm[cuddT(f)->index] > maxlevel)
00712                         maxlevel = table->perm[cuddT(f)->index];
00713                 }
00714                 if (!Cudd_IsConstant(cuddE(f))) {
00715                     Cudd_Regular(cuddE(f))->next =
00716                         Cudd_Complement(Cudd_Regular(cuddE(f))->next);
00717                     if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel)
00718                         maxlevel = table->perm[Cudd_Regular(cuddE(f))->index];
00719                 }
00720                 f = Cudd_Regular(f->next);
00721             }
00722         }
00723     }
00724     ddClearGlobal(table, lower, maxlevel);
00725 
00726     return(roots);
00727 
00728 } /* end of ddCountRoots */

static int ddShuffle ( DdManager table,
DdHalfWord permutation,
int  lower,
int  upper 
) [static]

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 []

Definition at line 522 of file cuddExact.c.

00527 {
00528     DdHalfWord  index;
00529     int         level;
00530     int         position;
00531     int         numvars;
00532     int         result;
00533 #ifdef DD_STATS
00534     long        localTime;
00535     int         initialSize;
00536 #ifdef DD_VERBOSE
00537     int         finalSize;
00538 #endif
00539     int         previousSize;
00540 #endif
00541 
00542 #ifdef DD_STATS
00543     localTime = util_cpu_time();
00544     initialSize = table->keys - table->isolated;
00545 #endif
00546 
00547     numvars = table->size;
00548 
00549 #if 0
00550     (void) fprintf(table->out,"%d:", ddTotalShuffles);
00551     for (level = 0; level < numvars; level++) {
00552         (void) fprintf(table->out," %d", table->invperm[level]);
00553     }
00554     (void) fprintf(table->out,"\n");
00555 #endif
00556 
00557     for (level = 0; level <= upper - lower; level++) {
00558         index = permutation[level];
00559         position = table->perm[index];
00560 #ifdef DD_STATS
00561         previousSize = table->keys - table->isolated;
00562 #endif
00563         result = ddSiftUp(table,position,level+lower);
00564         if (!result) return(0);
00565     }
00566 
00567 #ifdef DD_STATS
00568     ddTotalShuffles++;
00569 #ifdef DD_VERBOSE
00570     finalSize = table->keys - table->isolated;
00571     if (finalSize < initialSize) {
00572         (void) fprintf(table->out,"-");
00573     } else if (finalSize > initialSize) {
00574         (void) fprintf(table->out,"+");
00575     } else {
00576         (void) fprintf(table->out,"=");
00577     }
00578     if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n");
00579     fflush(table->out);
00580 #endif
00581 #endif
00582 
00583     return(1);
00584 
00585 } /* end of ddShuffle */

static int ddSiftUp ( DdManager table,
int  x,
int  xLow 
) [static]

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 []

Definition at line 602 of file cuddExact.c.

00606 {
00607     int        y;
00608     int        size;
00609 
00610     y = cuddNextLow(table,x);
00611     while (y >= xLow) {
00612         size = cuddSwapInPlace(table,y,x);
00613         if (size == 0) {
00614             return(0);
00615         }
00616         x = y;
00617         y = cuddNextLow(table,x);
00618     }
00619     return(1);
00620 
00621 } /* end of ddSiftUp */

static void freeMatrix ( DdHalfWord **  matrix  )  [static]

Function********************************************************************

Synopsis [Frees a two-dimensional matrix allocated by getMatrix.]

Description []

SideEffects [None]

SeeAlso [getMatrix]

Definition at line 467 of file cuddExact.c.

00469 {
00470     FREE(matrix[0]);
00471     FREE(matrix);
00472     return;
00473 
00474 } /* end of freeMatrix */

static int gcd ( int  x,
int  y 
) [static]

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 []

Definition at line 380 of file cuddExact.c.

00383 {
00384     int a;
00385     int b;
00386     int lsbMask;
00387 
00388     /* GCD(n,0) = n. */
00389     if (x == 0) return(y);
00390     if (y == 0) return(x);
00391 
00392     a = x; b = y; lsbMask = 1;
00393     
00394     /* Here both a and b are != 0. The iteration maintains this invariant.
00395     ** Hence, we only need to check for when they become equal.
00396     */
00397     while (a != b) {
00398         if (a & lsbMask) {
00399             if (b & lsbMask) {  /* both odd */
00400                 if (a < b) {
00401                     b = (b - a) >> 1;
00402                 } else {
00403                     a = (a - b) >> 1;
00404                 }
00405             } else {            /* a odd, b even */
00406                 b >>= 1;
00407             }
00408         } else {
00409             if (b & lsbMask) {  /* a even, b odd */
00410                 a >>= 1;
00411             } else {            /* both even */
00412                 lsbMask <<= 1;
00413             }
00414         }
00415     }
00416 
00417     return(a);
00418 
00419 } /* end of gcd */

static int getLevelKeys ( DdManager table,
int  l 
) [static]

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 []

Definition at line 490 of file cuddExact.c.

00493 {
00494     int isolated;
00495     int x;        /* x is an index */
00496 
00497     x = table->invperm[l];
00498     isolated = table->vars[x]->ref == 1;
00499 
00500     return(table->subtables[l].keys - isolated);
00501 
00502 } /* end of getLevelKeys */

static DdHalfWord** getMatrix ( int  rows,
int  cols 
) [static]

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]

Definition at line 435 of file cuddExact.c.

00438 {
00439     DdHalfWord **matrix;
00440     int i;
00441 
00442     if (cols*rows == 0) return(NULL);
00443     matrix = ALLOC(DdHalfWord *, rows);
00444     if (matrix == NULL) return(NULL);
00445     matrix[0] = ALLOC(DdHalfWord, cols*rows);
00446     if (matrix[0] == NULL) return(NULL);
00447     for (i = 1; i < rows; i++) {
00448         matrix[i] = matrix[i-1] + cols;
00449     }
00450     return(matrix);
00451 
00452 } /* end of getMatrix */

static int getMaxBinomial ( int  n  )  [static]

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 []

Definition at line 330 of file cuddExact.c.

00332 {
00333     int *numerator;
00334     int i, j, k, y, g, result;
00335 
00336     k = (n & ~1) >> 1;
00337 
00338     numerator = ALLOC(int,k);
00339     if (numerator == NULL) return(-1);
00340     
00341     for (i = 0; i < k; i++)
00342         numerator[i] = n - i;
00343     
00344     for (i = k; i > 1; i--) {
00345         y = i;
00346         for (j = 0; j < k; j++) {
00347             if (numerator[j] == 1) continue;
00348             g = gcd(numerator[j], y);
00349             if (g != 1) {
00350                 numerator[j] /= g;
00351                 if (y == g) break;
00352                 y /= g;
00353             }
00354         }
00355     }
00356 
00357     result = 1;
00358     for (i = 0; i < k; i++)
00359         result *= numerator[i];
00360 
00361     FREE(numerator);
00362     return(result);
00363 
00364 }  /* end of getMaxBinomial */

static DdHalfWord* initSymmInfo ( DdManager table,
int  lower,
int  upper 
) [static]

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]

Definition at line 951 of file cuddExact.c.

00955 {
00956     int level, index, next, nextindex;
00957     DdHalfWord *symmInfo;
00958 
00959     symmInfo =  ALLOC(DdHalfWord, table->size);
00960     if (symmInfo == NULL) return(NULL);
00961 
00962     for (level = lower; level <= upper; level++) {
00963         index = table->invperm[level];
00964         next =  table->subtables[level].next;
00965         nextindex = table->invperm[next];
00966         symmInfo[index] = nextindex;
00967     }
00968     return(symmInfo);
00969 
00970 } /* end of initSymmInfo */

static void pushDown ( DdHalfWord order,
int  j,
int  level 
) [static]

Function********************************************************************

Synopsis [Pushes a variable in the order down to position "level."]

Description []

SideEffects [None]

SeeAlso []

Definition at line 913 of file cuddExact.c.

00917 {
00918     int i;
00919     DdHalfWord tmp;
00920 
00921     tmp = order[j];
00922     for (i = j; i < level; i++) {
00923         order[i] = order[i+1];
00924     }
00925     order[level] = tmp;
00926     return;
00927 
00928 } /* end of pushDown */

static int updateEntry ( DdManager table,
DdHalfWord order,
int  level,
int  cost,
DdHalfWord **  orders,
int *  costs,
int  subsets,
char *  mask,
int  lower,
int  upper 
) [static]

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 []

Definition at line 859 of file cuddExact.c.

00870 {
00871     int i, j;
00872     int size = upper - lower + 1;
00873 
00874     /* Build a mask that says what variables are in this subset. */
00875     for (i = lower; i <= upper; i++)
00876         mask[table->invperm[i]] = 0;
00877     for (i = level; i < size; i++)
00878         mask[order[i]] = 1;
00879 
00880     /* Check each subset until a match is found or all subsets are examined. */
00881     for (i = 0; i < subsets; i++) {
00882         DdHalfWord *subset = orders[i];
00883         for (j = level; j < size; j++) {
00884             if (mask[subset[j]] == 0)
00885                 break;
00886         }
00887         if (j == size)          /* no mismatches: success */
00888             break;
00889     }
00890     if (i == subsets || cost < costs[i]) {              /* add or replace */
00891         for (j = 0; j < size; j++)
00892             orders[i][j] = order[j];
00893         costs[i] = cost;
00894         subsets += (i == subsets);
00895     }
00896     return(subsets);
00897 
00898 } /* end of updateEntry */

static int updateUB ( DdManager table,
int  oldBound,
DdHalfWord bestOrder,
int  lower,
int  upper 
) [static]

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 []

Definition at line 637 of file cuddExact.c.

00643 {
00644     int i;
00645     int newBound = table->keys - table->isolated;
00646 
00647     if (newBound < oldBound) {
00648 #ifdef DD_STATS
00649         (void) fprintf(table->out,"New upper bound = %d\n", newBound);
00650         fflush(table->out);
00651 #endif
00652         for (i = lower; i <= upper; i++)
00653             bestOrder[i-lower] = (DdHalfWord) table->invperm[i];
00654         return(newBound);
00655     } else {
00656         return(oldBound);
00657     }
00658 
00659 } /* end of updateUB */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddExact.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $" [static]

CFile***********************************************************************

FileName [cuddExact.c]

PackageName [cudd]

Synopsis [Functions for exact variable reordering.]

Description [External procedures included in this file:

procedures included in this module:

Static procedures included in this module:

]

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.]

Definition at line 64 of file cuddExact.c.


Generated on Tue Jan 5 12:18:54 2010 for abc70930 by  doxygen 1.6.1