#include "util_hack.h"
#include "cuddInt.h"
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 DdHalfWord * | initSymmInfo (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 $" |
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.
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:
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.
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.
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 */
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.