#include "util_hack.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#define | DD_MAX_SUBTABLE_SPARSITY 8 |
#define | DD_SHRINK_FACTOR 2 |
Functions | |
static int ddUniqueCompare | ARGS ((int *ptrX, int *ptrY)) |
static Move *ddSwapAny | ARGS ((DdManager *table, int x, int y)) |
static int ddSiftingAux | ARGS ((DdManager *table, int x, int xLow, int xHigh)) |
static Move *ddSiftingUp | ARGS ((DdManager *table, int y, int xLow)) |
static Move *ddSiftingDown | ARGS ((DdManager *table, int x, int xHigh)) |
static int ddSiftingBackward | ARGS ((DdManager *table, int size, Move *moves)) |
static int ddReorderPreprocess | ARGS ((DdManager *table)) |
static int ddShuffle | ARGS ((DdManager *table, int *permutation)) |
static int ddSiftUp | ARGS ((DdManager *table, int x, int xLow)) |
static void bddFixTree | ARGS ((DdManager *table, MtrNode *treenode)) |
static int ddUpdateMtrTree | ARGS ((DdManager *table, MtrNode *treenode, int *perm, int *invperm)) |
int | Cudd_ReduceHeap (DdManager *table, Cudd_ReorderingType heuristic, int minsize) |
int | Cudd_ShuffleHeap (DdManager *table, int *permutation) |
DdNode * | cuddDynamicAllocNode (DdManager *table) |
int | cuddSifting (DdManager *table, int lower, int upper) |
int | cuddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic) |
int | cuddNextHigh (DdManager *table, int x) |
int | cuddNextLow (DdManager *table, int x) |
int | cuddSwapInPlace (DdManager *table, int x, int y) |
int | cuddBddAlignToZdd (DdManager *table) |
static int | ddUniqueCompare (int *ptrX, int *ptrY) |
static Move * | ddSwapAny (DdManager *table, int x, int y) |
static int | ddSiftingAux (DdManager *table, int x, int xLow, int xHigh) |
static Move * | ddSiftingUp (DdManager *table, int y, int xLow) |
static Move * | ddSiftingDown (DdManager *table, int x, int xHigh) |
static int | ddSiftingBackward (DdManager *table, int size, Move *moves) |
static int | ddReorderPreprocess (DdManager *table) |
static int | ddReorderPostprocess (DdManager *table) |
static int | ddShuffle (DdManager *table, int *permutation) |
static int | ddSiftUp (DdManager *table, int x, int xLow) |
static void | bddFixTree (DdManager *table, MtrNode *treenode) |
static int | ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm) |
static int | ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddReorder.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" |
static int * | entry |
int | ddTotalNumberSwapping |
#define DD_MAX_SUBTABLE_SPARSITY 8 |
CFile***********************************************************************
FileName [cuddReorder.c]
PackageName [cudd]
Synopsis [Functions for dynamic variable reordering.]
Description [External procedures included in this file:
Internal procedures included in this module:
Static procedures included in this module:
]
Author [Shipra Panda, Bernard Plessier, 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 55 of file cuddReorder.c.
#define DD_SHRINK_FACTOR 2 |
Definition at line 56 of file cuddReorder.c.
static int ddCheckPermuation ARGS | ( | (DdManager *table, MtrNode *treenode, int *perm, int *invperm) | ) | [static] |
static int ddSiftUp ARGS | ( | (DdManager *table, int x, int xLow) | ) | [static] |
static int ddShuffle ARGS | ( | (DdManager *table, int *permutation) | ) | [static] |
static int ddReorderPreprocess ARGS | ( | (DdManager *table) | ) | [static] |
static int ddSiftingAux ARGS | ( | (DdManager *table, int x, int xLow, int xHigh) | ) | [static] |
static int ddUniqueCompare ARGS | ( | (int *ptrX, int *ptrY) | ) | [static] |
AutomaticStart
Function********************************************************************
Synopsis [Fixes the BDD variable group tree after a shuffle.]
Description [Fixes the BDD variable group tree after a shuffle. Assumes that the order of the variables in a terminal node has not been changed.]
SideEffects [Changes the BDD variable group tree.]
SeeAlso []
Definition at line 1967 of file cuddReorder.c.
01970 { 01971 if (treenode == NULL) return; 01972 treenode->low = ((int) treenode->index < table->size) ? 01973 table->perm[treenode->index] : treenode->index; 01974 if (treenode->child != NULL) { 01975 bddFixTree(table, treenode->child); 01976 } 01977 if (treenode->younger != NULL) 01978 bddFixTree(table, treenode->younger); 01979 if (treenode->parent != NULL && treenode->low < treenode->parent->low) { 01980 treenode->parent->low = treenode->low; 01981 treenode->parent->index = treenode->index; 01982 } 01983 return; 01984 01985 } /* end of bddFixTree */
int Cudd_ReduceHeap | ( | DdManager * | table, | |
Cudd_ReorderingType | heuristic, | |||
int | minsize | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Main dynamic reordering routine.]
Description [Main dynamic reordering routine. Calls one of the possible reordering procedures:
For sifting, symmetric sifting, group sifting, and window permutation it is possible to request reordering to convergence.
The core of all methods is the reordering procedure cuddSwapInPlace() which swaps two adjacent variables and is based on Rudell's paper. 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 diagrams and clears the cache.]
Definition at line 145 of file cuddReorder.c.
00149 { 00150 DdHook *hook; 00151 int result; 00152 unsigned int nextDyn; 00153 #ifdef DD_STATS 00154 unsigned int initialSize; 00155 unsigned int finalSize; 00156 #endif 00157 long localTime; 00158 00159 /* Don't reorder if there are too many dead nodes. */ 00160 if (table->keys - table->dead < (unsigned) minsize) 00161 return(1); 00162 00163 if (heuristic == CUDD_REORDER_SAME) { 00164 heuristic = table->autoMethod; 00165 } 00166 if (heuristic == CUDD_REORDER_NONE) { 00167 return(1); 00168 } 00169 00170 /* This call to Cudd_ReduceHeap does initiate reordering. Therefore 00171 ** we count it. 00172 */ 00173 table->reorderings++; 00174 00175 localTime = util_cpu_time(); 00176 00177 /* Run the hook functions. */ 00178 hook = table->preReorderingHook; 00179 while (hook != NULL) { 00180 int res = (hook->f)(table, "BDD", (void *)heuristic); 00181 if (res == 0) return(0); 00182 hook = hook->next; 00183 } 00184 00185 if (!ddReorderPreprocess(table)) return(0); 00186 ddTotalNumberSwapping = 0; 00187 00188 if (table->keys > table->peakLiveNodes) { 00189 table->peakLiveNodes = table->keys; 00190 } 00191 #ifdef DD_STATS 00192 initialSize = table->keys - table->isolated; 00193 ddTotalNISwaps = 0; 00194 00195 switch(heuristic) { 00196 case CUDD_REORDER_RANDOM: 00197 case CUDD_REORDER_RANDOM_PIVOT: 00198 (void) fprintf(table->out,"#:I_RANDOM "); 00199 break; 00200 case CUDD_REORDER_SIFT: 00201 case CUDD_REORDER_SIFT_CONVERGE: 00202 case CUDD_REORDER_SYMM_SIFT: 00203 case CUDD_REORDER_SYMM_SIFT_CONV: 00204 case CUDD_REORDER_GROUP_SIFT: 00205 case CUDD_REORDER_GROUP_SIFT_CONV: 00206 (void) fprintf(table->out,"#:I_SIFTING "); 00207 break; 00208 case CUDD_REORDER_WINDOW2: 00209 case CUDD_REORDER_WINDOW3: 00210 case CUDD_REORDER_WINDOW4: 00211 case CUDD_REORDER_WINDOW2_CONV: 00212 case CUDD_REORDER_WINDOW3_CONV: 00213 case CUDD_REORDER_WINDOW4_CONV: 00214 (void) fprintf(table->out,"#:I_WINDOW "); 00215 break; 00216 case CUDD_REORDER_ANNEALING: 00217 (void) fprintf(table->out,"#:I_ANNEAL "); 00218 break; 00219 case CUDD_REORDER_GENETIC: 00220 (void) fprintf(table->out,"#:I_GENETIC "); 00221 break; 00222 case CUDD_REORDER_LINEAR: 00223 case CUDD_REORDER_LINEAR_CONVERGE: 00224 (void) fprintf(table->out,"#:I_LINSIFT "); 00225 break; 00226 case CUDD_REORDER_EXACT: 00227 (void) fprintf(table->out,"#:I_EXACT "); 00228 break; 00229 default: 00230 return(0); 00231 } 00232 (void) fprintf(table->out,"%8d: initial size",initialSize); 00233 #endif 00234 00235 /* See if we should use alternate threshold for maximum growth. */ 00236 if (table->reordCycle && table->reorderings % table->reordCycle == 0) { 00237 double saveGrowth = table->maxGrowth; 00238 table->maxGrowth = table->maxGrowthAlt; 00239 result = cuddTreeSifting(table,heuristic); 00240 table->maxGrowth = saveGrowth; 00241 } else { 00242 result = cuddTreeSifting(table,heuristic); 00243 } 00244 00245 #ifdef DD_STATS 00246 (void) fprintf(table->out,"\n"); 00247 finalSize = table->keys - table->isolated; 00248 (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); 00249 (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", 00250 ((double)(util_cpu_time() - localTime)/1000.0)); 00251 (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", 00252 ddTotalNumberSwapping); 00253 (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps); 00254 #endif 00255 00256 if (result == 0) 00257 return(0); 00258 00259 if (!ddReorderPostprocess(table)) 00260 return(0); 00261 00262 if (table->realign) { 00263 if (!cuddZddAlignToBdd(table)) 00264 return(0); 00265 } 00266 00267 nextDyn = (table->keys - table->constants.keys + 1) * 00268 DD_DYN_RATIO + table->constants.keys; 00269 if (table->reorderings < 20 || nextDyn > table->nextDyn) 00270 table->nextDyn = nextDyn; 00271 else 00272 table->nextDyn += 20; 00273 table->reordered = 1; 00274 00275 /* Run hook functions. */ 00276 hook = table->postReorderingHook; 00277 while (hook != NULL) { 00278 int res = (hook->f)(table, "BDD", (void *)localTime); 00279 if (res == 0) return(0); 00280 hook = hook->next; 00281 } 00282 /* Update cumulative reordering time. */ 00283 table->reordTime += util_cpu_time() - localTime; 00284 00285 return(result); 00286 00287 } /* end of Cudd_ReduceHeap */
int Cudd_ShuffleHeap | ( | DdManager * | table, | |
int * | permutation | |||
) |
Function********************************************************************
Synopsis [Reorders variables according to given permutation.]
Description [Reorders 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 variable order for all diagrams and clears the cache.]
SeeAlso [Cudd_ReduceHeap]
Definition at line 307 of file cuddReorder.c.
00310 { 00311 00312 int result; 00313 int i; 00314 int identity = 1; 00315 int *perm; 00316 00317 /* Don't waste time in case of identity permutation. */ 00318 for (i = 0; i < table->size; i++) { 00319 if (permutation[i] != table->invperm[i]) { 00320 identity = 0; 00321 break; 00322 } 00323 } 00324 if (identity == 1) { 00325 return(1); 00326 } 00327 if (!ddReorderPreprocess(table)) return(0); 00328 if (table->keys > table->peakLiveNodes) { 00329 table->peakLiveNodes = table->keys; 00330 } 00331 00332 perm = ALLOC(int, table->size); 00333 for (i = 0; i < table->size; i++) 00334 perm[permutation[i]] = i; 00335 if (!ddCheckPermuation(table,table->tree,perm,permutation)) { 00336 FREE(perm); 00337 return(0); 00338 } 00339 if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) { 00340 FREE(perm); 00341 return(0); 00342 } 00343 FREE(perm); 00344 00345 result = ddShuffle(table,permutation); 00346 00347 if (!ddReorderPostprocess(table)) return(0); 00348 00349 return(result); 00350 00351 } /* end of Cudd_ShuffleHeap */
int cuddBddAlignToZdd | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Reorders BDD variables according to the order of the ZDD variables.]
Description [Reorders BDD variables according to the order of the ZDD variables. This function can be called at the end of ZDD reordering to insure that the order of the BDD variables is consistent with the order of the ZDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M
be the ratio of the two numbers. cuddBddAlignToZdd then considers the ZDD variables from M*i
to (M+1)*i-1
as corresponding to BDD variable i
. This function should be normally called from Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]
SideEffects [Changes the BDD variable order for all diagrams and performs garbage collection of the BDD unique table.]
SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap]
Definition at line 1208 of file cuddReorder.c.
01210 { 01211 int *invperm; /* permutation array */ 01212 int M; /* ratio of ZDD variables to BDD variables */ 01213 int i; /* loop index */ 01214 int result; /* return value */ 01215 01216 /* We assume that a ratio of 0 is OK. */ 01217 if (table->size == 0) 01218 return(1); 01219 01220 M = table->sizeZ / table->size; 01221 /* Check whether the number of ZDD variables is a multiple of the 01222 ** number of BDD variables. 01223 */ 01224 if (M * table->size != table->sizeZ) 01225 return(0); 01226 /* Create and initialize the inverse permutation array. */ 01227 invperm = ALLOC(int,table->size); 01228 if (invperm == NULL) { 01229 table->errorCode = CUDD_MEMORY_OUT; 01230 return(0); 01231 } 01232 for (i = 0; i < table->sizeZ; i += M) { 01233 int indexZ = table->invpermZ[i]; 01234 int index = indexZ / M; 01235 invperm[i / M] = index; 01236 } 01237 /* Eliminate dead nodes. Do not scan the cache again, because we 01238 ** assume that Cudd_zddReduceHeap has already cleared it. 01239 */ 01240 cuddGarbageCollect(table,0); 01241 01242 /* Initialize number of isolated projection functions. */ 01243 table->isolated = 0; 01244 for (i = 0; i < table->size; i++) { 01245 if (table->vars[i]->ref == 1) table->isolated++; 01246 } 01247 01248 /* Initialize the interaction matrix. */ 01249 result = cuddInitInteract(table); 01250 if (result == 0) return(0); 01251 01252 result = ddShuffle(table, invperm); 01253 FREE(invperm); 01254 /* Free interaction matrix. */ 01255 FREE(table->interact); 01256 /* Fix the BDD variable group tree. */ 01257 bddFixTree(table,table->tree); 01258 return(result); 01259 01260 } /* end of cuddBddAlignToZdd */
Function********************************************************************
Synopsis [Dynamically allocates a Node.]
Description [Dynamically allocates a Node. This procedure is similar to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage collection, because during reordering there are no dead nodes. Returns a pointer to a new node if successful; NULL is memory is full.]
SideEffects [None]
SeeAlso [cuddAllocNode]
Definition at line 375 of file cuddReorder.c.
00377 { 00378 int i; 00379 DdNodePtr *mem; 00380 DdNode *list, *node; 00381 extern void (*MMoutOfMemory)(long); 00382 void (*saveHandler)(long); 00383 00384 if (table->nextFree == NULL) { /* free list is empty */ 00385 /* Try to allocate a new block. */ 00386 saveHandler = MMoutOfMemory; 00387 MMoutOfMemory = Cudd_OutOfMem; 00388 mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1); 00389 MMoutOfMemory = saveHandler; 00390 if (mem == NULL && table->stash != NULL) { 00391 FREE(table->stash); 00392 table->stash = NULL; 00393 /* Inhibit resizing of tables. */ 00394 table->maxCacheHard = table->cacheSlots - 1; 00395 table->cacheSlack = -(table->cacheSlots + 1); 00396 for (i = 0; i < table->size; i++) { 00397 table->subtables[i].maxKeys <<= 2; 00398 } 00399 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00400 } 00401 if (mem == NULL) { 00402 /* Out of luck. Call the default handler to do 00403 ** whatever it specifies for a failed malloc. If this 00404 ** handler returns, then set error code, print 00405 ** warning, and return. */ 00406 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); 00407 table->errorCode = CUDD_MEMORY_OUT; 00408 #ifdef DD_VERBOSE 00409 (void) fprintf(table->err, 00410 "cuddDynamicAllocNode: out of memory"); 00411 (void) fprintf(table->err,"Memory in use = %ld\n", 00412 table->memused); 00413 #endif 00414 return(NULL); 00415 } else { /* successful allocation; slice memory */ 00416 unsigned long offset; 00417 table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); 00418 mem[0] = (DdNode *) table->memoryList; 00419 table->memoryList = mem; 00420 00421 /* Here we rely on the fact that the size of a DdNode is a 00422 ** power of 2 and a multiple of the size of a pointer. 00423 ** If we align one node, all the others will be aligned 00424 ** as well. */ 00425 offset = (unsigned long) mem & (sizeof(DdNode) - 1); 00426 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); 00427 #ifdef DD_DEBUG 00428 assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0); 00429 #endif 00430 list = (DdNode *) mem; 00431 00432 i = 1; 00433 do { 00434 list[i - 1].next = &list[i]; 00435 } while (++i < DD_MEM_CHUNK); 00436 00437 list[DD_MEM_CHUNK - 1].next = NULL; 00438 00439 table->nextFree = &list[0]; 00440 } 00441 } /* if free list empty */ 00442 00443 node = table->nextFree; 00444 table->nextFree = node->next; 00445 return (node); 00446 00447 } /* end of cuddDynamicAllocNode */
int cuddNextHigh | ( | DdManager * | table, | |
int | x | |||
) |
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 [cuddNextLow]
Definition at line 678 of file cuddReorder.c.
int cuddNextLow | ( | DdManager * | table, | |
int | x | |||
) |
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 [cuddNextHigh]
Definition at line 700 of file cuddReorder.c.
int cuddSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Implementation of Rudell's sifting algorithm.]
Description [Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 470 of file cuddReorder.c.
00474 { 00475 int i; 00476 int *var; 00477 int size; 00478 int x; 00479 int result; 00480 #ifdef DD_STATS 00481 int previousSize; 00482 #endif 00483 00484 size = table->size; 00485 00486 /* Find order in which to sift variables. */ 00487 var = NULL; 00488 entry = ALLOC(int,size); 00489 if (entry == NULL) { 00490 table->errorCode = CUDD_MEMORY_OUT; 00491 goto cuddSiftingOutOfMem; 00492 } 00493 var = ALLOC(int,size); 00494 if (var == NULL) { 00495 table->errorCode = CUDD_MEMORY_OUT; 00496 goto cuddSiftingOutOfMem; 00497 } 00498 00499 for (i = 0; i < size; i++) { 00500 x = table->perm[i]; 00501 entry[i] = table->subtables[x].keys; 00502 var[i] = i; 00503 } 00504 00505 qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddUniqueCompare); 00506 00507 /* Now sift. */ 00508 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { 00509 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00510 break; 00511 x = table->perm[var[i]]; 00512 00513 if (x < lower || x > upper || table->subtables[x].bindVar == 1) 00514 continue; 00515 #ifdef DD_STATS 00516 previousSize = table->keys - table->isolated; 00517 #endif 00518 result = ddSiftingAux(table, x, lower, upper); 00519 if (!result) goto cuddSiftingOutOfMem; 00520 #ifdef DD_STATS 00521 if (table->keys < (unsigned) previousSize + table->isolated) { 00522 (void) fprintf(table->out,"-"); 00523 } else if (table->keys > (unsigned) previousSize + table->isolated) { 00524 (void) fprintf(table->out,"+"); /* should never happen */ 00525 (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); 00526 } else { 00527 (void) fprintf(table->out,"="); 00528 } 00529 fflush(table->out); 00530 #endif 00531 } 00532 00533 FREE(var); 00534 FREE(entry); 00535 00536 return(1); 00537 00538 cuddSiftingOutOfMem: 00539 00540 if (entry != NULL) FREE(entry); 00541 if (var != NULL) FREE(var); 00542 00543 return(0); 00544 00545 } /* end of cuddSifting */
int cuddSwapInPlace | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
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. cuddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [None]
Definition at line 723 of file cuddReorder.c.
00727 { 00728 DdNodePtr *xlist, *ylist; 00729 int xindex, yindex; 00730 int xslots, yslots; 00731 int xshift, yshift; 00732 int oldxkeys, oldykeys; 00733 int newxkeys, newykeys; 00734 int comple, newcomplement; 00735 int i; 00736 Cudd_VariableType varType; 00737 Cudd_LazyGroupType groupType; 00738 int posn; 00739 int isolated; 00740 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; 00741 DdNode *g,*next; 00742 DdNodePtr *previousP; 00743 DdNode *tmp; 00744 DdNode *sentinel = &(table->sentinel); 00745 extern void (*MMoutOfMemory)(long); 00746 void (*saveHandler)(long); 00747 00748 #if DD_DEBUG 00749 int count,idcheck; 00750 #endif 00751 00752 #ifdef DD_DEBUG 00753 assert(x < y); 00754 assert(cuddNextHigh(table,x) == y); 00755 assert(table->subtables[x].keys != 0); 00756 assert(table->subtables[y].keys != 0); 00757 assert(table->subtables[x].dead == 0); 00758 assert(table->subtables[y].dead == 0); 00759 #endif 00760 00761 ddTotalNumberSwapping++; 00762 00763 /* Get parameters of x subtable. */ 00764 xindex = table->invperm[x]; 00765 xlist = table->subtables[x].nodelist; 00766 oldxkeys = table->subtables[x].keys; 00767 xslots = table->subtables[x].slots; 00768 xshift = table->subtables[x].shift; 00769 00770 /* Get parameters of y subtable. */ 00771 yindex = table->invperm[y]; 00772 ylist = table->subtables[y].nodelist; 00773 oldykeys = table->subtables[y].keys; 00774 yslots = table->subtables[y].slots; 00775 yshift = table->subtables[y].shift; 00776 00777 if (!cuddTestInteract(table,xindex,yindex)) { 00778 #ifdef DD_STATS 00779 ddTotalNISwaps++; 00780 #endif 00781 newxkeys = oldxkeys; 00782 newykeys = oldykeys; 00783 } else { 00784 newxkeys = 0; 00785 newykeys = oldykeys; 00786 00787 /* Check whether the two projection functions involved in this 00788 ** swap are isolated. At the end, we'll be able to tell how many 00789 ** isolated projection functions are there by checking only these 00790 ** two functions again. This is done to eliminate the isolated 00791 ** projection functions from the node count. 00792 */ 00793 isolated = - ((table->vars[xindex]->ref == 1) + 00794 (table->vars[yindex]->ref == 1)); 00795 00796 /* The nodes in the x layer that do not depend on 00797 ** y will stay there; the others are put in a chain. 00798 ** The chain is handled as a LIFO; g points to the beginning. 00799 */ 00800 g = NULL; 00801 if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) && 00802 oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) { 00803 for (i = 0; i < xslots; i++) { 00804 previousP = &(xlist[i]); 00805 f = *previousP; 00806 while (f != sentinel) { 00807 next = f->next; 00808 f1 = cuddT(f); f0 = cuddE(f); 00809 if (f1->index != (DdHalfWord) yindex && 00810 Cudd_Regular(f0)->index != (DdHalfWord) yindex) { 00811 /* stays */ 00812 newxkeys++; 00813 *previousP = f; 00814 previousP = &(f->next); 00815 } else { 00816 f->index = yindex; 00817 f->next = g; 00818 g = f; 00819 } 00820 f = next; 00821 } /* while there are elements in the collision chain */ 00822 *previousP = sentinel; 00823 } /* for each slot of the x subtable */ 00824 } else { /* resize xlist */ 00825 DdNode *h = NULL; 00826 DdNodePtr *newxlist; 00827 unsigned int newxslots; 00828 int newxshift; 00829 /* Empty current xlist. Nodes that stay go to list h; 00830 ** nodes that move go to list g. */ 00831 for (i = 0; i < xslots; i++) { 00832 f = xlist[i]; 00833 while (f != sentinel) { 00834 next = f->next; 00835 f1 = cuddT(f); f0 = cuddE(f); 00836 if (f1->index != (DdHalfWord) yindex && 00837 Cudd_Regular(f0)->index != (DdHalfWord) yindex) { 00838 /* stays */ 00839 f->next = h; 00840 h = f; 00841 newxkeys++; 00842 } else { 00843 f->index = yindex; 00844 f->next = g; 00845 g = f; 00846 } 00847 f = next; 00848 } /* while there are elements in the collision chain */ 00849 } /* for each slot of the x subtable */ 00850 /* Decide size of new subtable. */ 00851 if (oldxkeys > DD_MAX_SUBTABLE_DENSITY * xslots) { 00852 newxshift = xshift - 1; 00853 newxslots = xslots << 1; 00854 } else { 00855 newxshift = xshift + 1; 00856 newxslots = xslots >> 1; 00857 } 00858 /* Try to allocate new table. Be ready to back off. */ 00859 saveHandler = MMoutOfMemory; 00860 MMoutOfMemory = Cudd_OutOfMem; 00861 newxlist = ALLOC(DdNodePtr, newxslots); 00862 MMoutOfMemory = saveHandler; 00863 if (newxlist == NULL) { 00864 (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i); 00865 newxlist = xlist; 00866 newxslots = xslots; 00867 newxshift = xshift; 00868 } else { 00869 table->slots += (newxslots - xslots); 00870 table->minDead = (unsigned) 00871 (table->gcFrac * (double) table->slots); 00872 table->cacheSlack = (int) 00873 ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO 00874 * table->slots) - 2 * (int) table->cacheSlots; 00875 table->memused += (newxslots - xslots) * sizeof(DdNodePtr); 00876 FREE(xlist); 00877 xslots = newxslots; 00878 xshift = newxshift; 00879 xlist = newxlist; 00880 } 00881 /* Initialize new subtable. */ 00882 for (i = 0; i < xslots; i++) { 00883 xlist[i] = sentinel; 00884 } 00885 /* Move nodes that were parked in list h to their new home. */ 00886 f = h; 00887 while (f != NULL) { 00888 next = f->next; 00889 f1 = cuddT(f); 00890 f0 = cuddE(f); 00891 /* Check xlist for pair (f11,f01). */ 00892 posn = ddHash(f1, f0, xshift); 00893 /* For each element tmp in collision list xlist[posn]. */ 00894 previousP = &(xlist[posn]); 00895 tmp = *previousP; 00896 while (f1 < cuddT(tmp)) { 00897 previousP = &(tmp->next); 00898 tmp = *previousP; 00899 } 00900 while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) { 00901 previousP = &(tmp->next); 00902 tmp = *previousP; 00903 } 00904 f->next = *previousP; 00905 *previousP = f; 00906 f = next; 00907 } 00908 } 00909 00910 #ifdef DD_COUNT 00911 table->swapSteps += oldxkeys - newxkeys; 00912 #endif 00913 /* Take care of the x nodes that must be re-expressed. 00914 ** They form a linked list pointed by g. Their index has been 00915 ** already changed to yindex. 00916 */ 00917 f = g; 00918 while (f != NULL) { 00919 next = f->next; 00920 /* Find f1, f0, f11, f10, f01, f00. */ 00921 f1 = cuddT(f); 00922 #ifdef DD_DEBUG 00923 assert(!(Cudd_IsComplement(f1))); 00924 #endif 00925 if ((int) f1->index == yindex) { 00926 f11 = cuddT(f1); f10 = cuddE(f1); 00927 } else { 00928 f11 = f10 = f1; 00929 } 00930 #ifdef DD_DEBUG 00931 assert(!(Cudd_IsComplement(f11))); 00932 #endif 00933 f0 = cuddE(f); 00934 comple = Cudd_IsComplement(f0); 00935 f0 = Cudd_Regular(f0); 00936 if ((int) f0->index == yindex) { 00937 f01 = cuddT(f0); f00 = cuddE(f0); 00938 } else { 00939 f01 = f00 = f0; 00940 } 00941 if (comple) { 00942 f01 = Cudd_Not(f01); 00943 f00 = Cudd_Not(f00); 00944 } 00945 /* Decrease ref count of f1. */ 00946 cuddSatDec(f1->ref); 00947 /* Create the new T child. */ 00948 if (f11 == f01) { 00949 newf1 = f11; 00950 cuddSatInc(newf1->ref); 00951 } else { 00952 /* Check xlist for triple (xindex,f11,f01). */ 00953 posn = ddHash(f11, f01, xshift); 00954 /* For each element newf1 in collision list xlist[posn]. */ 00955 previousP = &(xlist[posn]); 00956 newf1 = *previousP; 00957 while (f11 < cuddT(newf1)) { 00958 previousP = &(newf1->next); 00959 newf1 = *previousP; 00960 } 00961 while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) { 00962 previousP = &(newf1->next); 00963 newf1 = *previousP; 00964 } 00965 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { 00966 cuddSatInc(newf1->ref); 00967 } else { /* no match */ 00968 newf1 = cuddDynamicAllocNode(table); 00969 if (newf1 == NULL) 00970 goto cuddSwapOutOfMem; 00971 newf1->index = xindex; newf1->ref = 1; 00972 cuddT(newf1) = f11; 00973 cuddE(newf1) = f01; 00974 /* Insert newf1 in the collision list xlist[posn]; 00975 ** increase the ref counts of f11 and f01. 00976 */ 00977 newxkeys++; 00978 newf1->next = *previousP; 00979 *previousP = newf1; 00980 cuddSatInc(f11->ref); 00981 tmp = Cudd_Regular(f01); 00982 cuddSatInc(tmp->ref); 00983 } 00984 } 00985 cuddT(f) = newf1; 00986 #ifdef DD_DEBUG 00987 assert(!(Cudd_IsComplement(newf1))); 00988 #endif 00989 00990 /* Do the same for f0, keeping complement dots into account. */ 00991 /* Decrease ref count of f0. */ 00992 tmp = Cudd_Regular(f0); 00993 cuddSatDec(tmp->ref); 00994 /* Create the new E child. */ 00995 if (f10 == f00) { 00996 newf0 = f00; 00997 tmp = Cudd_Regular(newf0); 00998 cuddSatInc(tmp->ref); 00999 } else { 01000 /* make sure f10 is regular */ 01001 newcomplement = Cudd_IsComplement(f10); 01002 if (newcomplement) { 01003 f10 = Cudd_Not(f10); 01004 f00 = Cudd_Not(f00); 01005 } 01006 /* Check xlist for triple (xindex,f10,f00). */ 01007 posn = ddHash(f10, f00, xshift); 01008 /* For each element newf0 in collision list xlist[posn]. */ 01009 previousP = &(xlist[posn]); 01010 newf0 = *previousP; 01011 while (f10 < cuddT(newf0)) { 01012 previousP = &(newf0->next); 01013 newf0 = *previousP; 01014 } 01015 while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) { 01016 previousP = &(newf0->next); 01017 newf0 = *previousP; 01018 } 01019 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { 01020 cuddSatInc(newf0->ref); 01021 } else { /* no match */ 01022 newf0 = cuddDynamicAllocNode(table); 01023 if (newf0 == NULL) 01024 goto cuddSwapOutOfMem; 01025 newf0->index = xindex; newf0->ref = 1; 01026 cuddT(newf0) = f10; 01027 cuddE(newf0) = f00; 01028 /* Insert newf0 in the collision list xlist[posn]; 01029 ** increase the ref counts of f10 and f00. 01030 */ 01031 newxkeys++; 01032 newf0->next = *previousP; 01033 *previousP = newf0; 01034 cuddSatInc(f10->ref); 01035 tmp = Cudd_Regular(f00); 01036 cuddSatInc(tmp->ref); 01037 } 01038 if (newcomplement) { 01039 newf0 = Cudd_Not(newf0); 01040 } 01041 } 01042 cuddE(f) = newf0; 01043 01044 /* Insert the modified f in ylist. 01045 ** The modified f does not already exists in ylist. 01046 ** (Because of the uniqueness of the cofactors.) 01047 */ 01048 posn = ddHash(newf1, newf0, yshift); 01049 newykeys++; 01050 previousP = &(ylist[posn]); 01051 tmp = *previousP; 01052 while (newf1 < cuddT(tmp)) { 01053 previousP = &(tmp->next); 01054 tmp = *previousP; 01055 } 01056 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { 01057 previousP = &(tmp->next); 01058 tmp = *previousP; 01059 } 01060 f->next = *previousP; 01061 *previousP = f; 01062 f = next; 01063 } /* while f != NULL */ 01064 01065 /* GC the y layer. */ 01066 01067 /* For each node f in ylist. */ 01068 for (i = 0; i < yslots; i++) { 01069 previousP = &(ylist[i]); 01070 f = *previousP; 01071 while (f != sentinel) { 01072 next = f->next; 01073 if (f->ref == 0) { 01074 tmp = cuddT(f); 01075 cuddSatDec(tmp->ref); 01076 tmp = Cudd_Regular(cuddE(f)); 01077 cuddSatDec(tmp->ref); 01078 cuddDeallocNode(table,f); 01079 newykeys--; 01080 } else { 01081 *previousP = f; 01082 previousP = &(f->next); 01083 } 01084 f = next; 01085 } /* while f */ 01086 *previousP = sentinel; 01087 } /* for i */ 01088 01089 #if DD_DEBUG 01090 #if 0 01091 (void) fprintf(table->out,"Swapping %d and %d\n",x,y); 01092 #endif 01093 count = 0; 01094 idcheck = 0; 01095 for (i = 0; i < yslots; i++) { 01096 f = ylist[i]; 01097 while (f != sentinel) { 01098 count++; 01099 if (f->index != (DdHalfWord) yindex) 01100 idcheck++; 01101 f = f->next; 01102 } 01103 } 01104 if (count != newykeys) { 01105 (void) fprintf(table->out, 01106 "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n", 01107 oldykeys,newykeys,count); 01108 } 01109 if (idcheck != 0) 01110 (void) fprintf(table->out, 01111 "Error in id's of ylist\twrong id's = %d\n", 01112 idcheck); 01113 count = 0; 01114 idcheck = 0; 01115 for (i = 0; i < xslots; i++) { 01116 f = xlist[i]; 01117 while (f != sentinel) { 01118 count++; 01119 if (f->index != (DdHalfWord) xindex) 01120 idcheck++; 01121 f = f->next; 01122 } 01123 } 01124 if (count != newxkeys) { 01125 (void) fprintf(table->out, 01126 "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n", 01127 oldxkeys,newxkeys,count); 01128 } 01129 if (idcheck != 0) 01130 (void) fprintf(table->out, 01131 "Error in id's of xlist\twrong id's = %d\n", 01132 idcheck); 01133 #endif 01134 01135 isolated += (table->vars[xindex]->ref == 1) + 01136 (table->vars[yindex]->ref == 1); 01137 table->isolated += isolated; 01138 } 01139 01140 /* Set the appropriate fields in table. */ 01141 table->subtables[x].nodelist = ylist; 01142 table->subtables[x].slots = yslots; 01143 table->subtables[x].shift = yshift; 01144 table->subtables[x].keys = newykeys; 01145 table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; 01146 i = table->subtables[x].bindVar; 01147 table->subtables[x].bindVar = table->subtables[y].bindVar; 01148 table->subtables[y].bindVar = i; 01149 /* Adjust filds for lazy sifting. */ 01150 varType = table->subtables[x].varType; 01151 table->subtables[x].varType = table->subtables[y].varType; 01152 table->subtables[y].varType = varType; 01153 i = table->subtables[x].pairIndex; 01154 table->subtables[x].pairIndex = table->subtables[y].pairIndex; 01155 table->subtables[y].pairIndex = i; 01156 i = table->subtables[x].varHandled; 01157 table->subtables[x].varHandled = table->subtables[y].varHandled; 01158 table->subtables[y].varHandled = i; 01159 groupType = table->subtables[x].varToBeGrouped; 01160 table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped; 01161 table->subtables[y].varToBeGrouped = groupType; 01162 01163 table->subtables[y].nodelist = xlist; 01164 table->subtables[y].slots = xslots; 01165 table->subtables[y].shift = xshift; 01166 table->subtables[y].keys = newxkeys; 01167 table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; 01168 01169 table->perm[xindex] = y; table->perm[yindex] = x; 01170 table->invperm[x] = yindex; table->invperm[y] = xindex; 01171 01172 table->keys += newxkeys + newykeys - oldxkeys - oldykeys; 01173 01174 return(table->keys - table->isolated); 01175 01176 cuddSwapOutOfMem: 01177 (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n"); 01178 01179 return (0); 01180 01181 } /* end of cuddSwapInPlace */
int cuddSwapping | ( | DdManager * | table, | |
int | lower, | |||
int | upper, | |||
Cudd_ReorderingType | heuristic | |||
) |
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.
Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 567 of file cuddReorder.c.
00572 { 00573 int i, j; 00574 int max, keys; 00575 int nvars; 00576 int x, y; 00577 int iterate; 00578 int previousSize; 00579 Move *moves, *move; 00580 int pivot; 00581 int modulo; 00582 int result; 00583 00584 #ifdef DD_DEBUG 00585 /* Sanity check */ 00586 assert(lower >= 0 && upper < table->size && lower <= upper); 00587 #endif 00588 00589 nvars = upper - lower + 1; 00590 iterate = nvars; 00591 00592 for (i = 0; i < iterate; i++) { 00593 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00594 break; 00595 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { 00596 max = -1; 00597 for (j = lower; j <= upper; j++) { 00598 if ((keys = table->subtables[j].keys) > max) { 00599 max = keys; 00600 pivot = j; 00601 } 00602 } 00603 00604 modulo = upper - pivot; 00605 if (modulo == 0) { 00606 y = pivot; 00607 } else{ 00608 y = pivot + 1 + ((int) Cudd_Random() % modulo); 00609 } 00610 00611 modulo = pivot - lower - 1; 00612 if (modulo < 1) { 00613 x = lower; 00614 } else{ 00615 do { 00616 x = (int) Cudd_Random() % modulo; 00617 } while (x == y); 00618 } 00619 } else { 00620 x = ((int) Cudd_Random() % nvars) + lower; 00621 do { 00622 y = ((int) Cudd_Random() % nvars) + lower; 00623 } while (x == y); 00624 } 00625 previousSize = table->keys - table->isolated; 00626 moves = ddSwapAny(table,x,y); 00627 if (moves == NULL) goto cuddSwappingOutOfMem; 00628 result = ddSiftingBackward(table,previousSize,moves); 00629 if (!result) goto cuddSwappingOutOfMem; 00630 while (moves != NULL) { 00631 move = moves->next; 00632 cuddDeallocNode(table, (DdNode *) moves); 00633 moves = move; 00634 } 00635 #ifdef DD_STATS 00636 if (table->keys < (unsigned) previousSize + table->isolated) { 00637 (void) fprintf(table->out,"-"); 00638 } else if (table->keys > (unsigned) previousSize + table->isolated) { 00639 (void) fprintf(table->out,"+"); /* should never happen */ 00640 } else { 00641 (void) fprintf(table->out,"="); 00642 } 00643 fflush(table->out); 00644 #endif 00645 #if 0 00646 (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n", 00647 table->keys - table->isolated); 00648 #endif 00649 } 00650 00651 return(1); 00652 00653 cuddSwappingOutOfMem: 00654 while (moves != NULL) { 00655 move = moves->next; 00656 cuddDeallocNode(table, (DdNode *) moves); 00657 moves = move; 00658 } 00659 00660 return(0); 00661 00662 } /* end of cuddSwapping */
static int ddCheckPermuation | ( | DdManager * | table, | |
MtrNode * | treenode, | |||
int * | perm, | |||
int * | invperm | |||
) | [static] |
Function********************************************************************
Synopsis [Checks the BDD variable group tree before a shuffle.]
Description [Checks the BDD variable group tree before a shuffle. Returns 1 if successful; 0 otherwise.]
SideEffects [Changes the BDD variable group tree.]
SeeAlso []
Definition at line 2055 of file cuddReorder.c.
02060 { 02061 int i, size, index, level; 02062 int minLevel, maxLevel; 02063 02064 if (treenode == NULL) return(1); 02065 02066 minLevel = table->size; 02067 maxLevel = 0; 02068 /* i : level */ 02069 for (i = treenode->low; i < treenode->low + treenode->size; i++) { 02070 index = table->invperm[i]; 02071 level = perm[index]; 02072 if (level < minLevel) 02073 minLevel = level; 02074 if (level > maxLevel) 02075 maxLevel = level; 02076 } 02077 size = maxLevel - minLevel + 1; 02078 if (size != treenode->size) 02079 return(0); 02080 02081 if (treenode->child != NULL) { 02082 if (!ddCheckPermuation(table, treenode->child, perm, invperm)) 02083 return(0); 02084 } 02085 if (treenode->younger != NULL) { 02086 if (!ddCheckPermuation(table, treenode->younger, perm, invperm)) 02087 return(0); 02088 } 02089 return(1); 02090 }
static int ddReorderPostprocess | ( | DdManager * | table | ) | [static] |
Function********************************************************************
Synopsis [Cleans up at the end of reordering.]
Description []
SideEffects [None]
Definition at line 1821 of file cuddReorder.c.
static int ddReorderPreprocess | ( | DdManager * | table | ) | [static] |
Function********************************************************************
Synopsis [Prepares the DD heap for dynamic reordering.]
Description [Prepares the DD heap for dynamic reordering. Does garbage collection, to guarantee that there are no dead nodes; clears the cache, which is invalidated by dynamic reordering; initializes the number of isolated projection functions; and initializes the interaction matrix. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 1783 of file cuddReorder.c.
01785 { 01786 int i; 01787 int res; 01788 01789 /* Clear the cache. */ 01790 cuddCacheFlush(table); 01791 cuddLocalCacheClearAll(table); 01792 01793 /* Eliminate dead nodes. Do not scan the cache again. */ 01794 cuddGarbageCollect(table,0); 01795 01796 /* Initialize number of isolated projection functions. */ 01797 table->isolated = 0; 01798 for (i = 0; i < table->size; i++) { 01799 if (table->vars[i]->ref == 1) table->isolated++; 01800 } 01801 01802 /* Initialize the interaction matrix. */ 01803 res = cuddInitInteract(table); 01804 if (res == 0) return(0); 01805 01806 return(1); 01807 01808 } /* end of ddReorderPreprocess */
static int ddShuffle | ( | DdManager * | table, | |
int * | permutation | |||
) | [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 1854 of file cuddReorder.c.
01857 { 01858 int index; 01859 int level; 01860 int position; 01861 int numvars; 01862 int result; 01863 #ifdef DD_STATS 01864 long localTime; 01865 int initialSize; 01866 int finalSize; 01867 int previousSize; 01868 #endif 01869 01870 ddTotalNumberSwapping = 0; 01871 #ifdef DD_STATS 01872 localTime = util_cpu_time(); 01873 initialSize = table->keys - table->isolated; 01874 (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", 01875 initialSize); 01876 ddTotalNISwaps = 0; 01877 #endif 01878 01879 numvars = table->size; 01880 01881 for (level = 0; level < numvars; level++) { 01882 index = permutation[level]; 01883 position = table->perm[index]; 01884 #ifdef DD_STATS 01885 previousSize = table->keys - table->isolated; 01886 #endif 01887 result = ddSiftUp(table,position,level); 01888 if (!result) return(0); 01889 #ifdef DD_STATS 01890 if (table->keys < (unsigned) previousSize + table->isolated) { 01891 (void) fprintf(table->out,"-"); 01892 } else if (table->keys > (unsigned) previousSize + table->isolated) { 01893 (void) fprintf(table->out,"+"); /* should never happen */ 01894 } else { 01895 (void) fprintf(table->out,"="); 01896 } 01897 fflush(table->out); 01898 #endif 01899 } 01900 01901 #ifdef DD_STATS 01902 (void) fprintf(table->out,"\n"); 01903 finalSize = table->keys - table->isolated; 01904 (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); 01905 (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", 01906 ((double)(util_cpu_time() - localTime)/1000.0)); 01907 (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", 01908 ddTotalNumberSwapping); 01909 (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps); 01910 #endif 01911 01912 return(1); 01913 01914 } /* end of ddShuffle */
static int ddSiftingAux | ( | DdManager * | table, | |
int | x, | |||
int | xLow, | |||
int | xHigh | |||
) | [static] |
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]
Definition at line 1445 of file cuddReorder.c.
01450 { 01451 01452 Move *move; 01453 Move *moveUp; /* list of up moves */ 01454 Move *moveDown; /* list of down moves */ 01455 int initialSize; 01456 int result; 01457 01458 initialSize = table->keys - table->isolated; 01459 01460 moveDown = NULL; 01461 moveUp = NULL; 01462 01463 if (x == xLow) { 01464 moveDown = ddSiftingDown(table,x,xHigh); 01465 /* At this point x --> xHigh unless bounding occurred. */ 01466 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; 01467 /* Move backward and stop at best position. */ 01468 result = ddSiftingBackward(table,initialSize,moveDown); 01469 if (!result) goto ddSiftingAuxOutOfMem; 01470 01471 } else if (x == xHigh) { 01472 moveUp = ddSiftingUp(table,x,xLow); 01473 /* At this point x --> xLow unless bounding occurred. */ 01474 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; 01475 /* Move backward and stop at best position. */ 01476 result = ddSiftingBackward(table,initialSize,moveUp); 01477 if (!result) goto ddSiftingAuxOutOfMem; 01478 01479 } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ 01480 moveDown = ddSiftingDown(table,x,xHigh); 01481 /* At this point x --> xHigh unless bounding occurred. */ 01482 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; 01483 if (moveDown != NULL) { 01484 x = moveDown->y; 01485 } 01486 moveUp = ddSiftingUp(table,x,xLow); 01487 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; 01488 /* Move backward and stop at best position */ 01489 result = ddSiftingBackward(table,initialSize,moveUp); 01490 if (!result) goto ddSiftingAuxOutOfMem; 01491 01492 } else { /* must go up first: shorter */ 01493 moveUp = ddSiftingUp(table,x,xLow); 01494 /* At this point x --> xLow unless bounding occurred. */ 01495 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; 01496 if (moveUp != NULL) { 01497 x = moveUp->x; 01498 } 01499 moveDown = ddSiftingDown(table,x,xHigh); 01500 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; 01501 /* Move backward and stop at best position. */ 01502 result = ddSiftingBackward(table,initialSize,moveDown); 01503 if (!result) goto ddSiftingAuxOutOfMem; 01504 } 01505 01506 while (moveDown != NULL) { 01507 move = moveDown->next; 01508 cuddDeallocNode(table, (DdNode *) moveDown); 01509 moveDown = move; 01510 } 01511 while (moveUp != NULL) { 01512 move = moveUp->next; 01513 cuddDeallocNode(table, (DdNode *) moveUp); 01514 moveUp = move; 01515 } 01516 01517 return(1); 01518 01519 ddSiftingAuxOutOfMem: 01520 if (moveDown != (Move *) CUDD_OUT_OF_MEM) { 01521 while (moveDown != NULL) { 01522 move = moveDown->next; 01523 cuddDeallocNode(table, (DdNode *) moveDown); 01524 moveDown = move; 01525 } 01526 } 01527 if (moveUp != (Move *) CUDD_OUT_OF_MEM) { 01528 while (moveUp != NULL) { 01529 move = moveUp->next; 01530 cuddDeallocNode(table, (DdNode *) moveUp); 01531 moveUp = move; 01532 } 01533 } 01534 01535 return(0); 01536 01537 } /* end of ddSiftingAux */
Function********************************************************************
Synopsis [Given a set of moves, returns the DD heap to the position giving the minimum size.]
Description [Given a set of moves, returns the DD 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]
Definition at line 1744 of file cuddReorder.c.
01748 { 01749 Move *move; 01750 int res; 01751 01752 for (move = moves; move != NULL; move = move->next) { 01753 if (move->size < size) { 01754 size = move->size; 01755 } 01756 } 01757 01758 for (move = moves; move != NULL; move = move->next) { 01759 if (move->size == size) return(1); 01760 res = cuddSwapInPlace(table,(int)move->x,(int)move->y); 01761 if (!res) return(0); 01762 } 01763 01764 return(1); 01765 01766 } /* end of ddSiftingBackward */
Function********************************************************************
Synopsis [Sifts a variable down.]
Description [Sifts a variable down. Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
Definition at line 1652 of file cuddReorder.c.
01656 { 01657 Move *moves; 01658 Move *move; 01659 int y; 01660 int size; 01661 int R; /* upper bound on node decrease */ 01662 int limitSize; 01663 int xindex, yindex; 01664 int isolated; 01665 #ifdef DD_DEBUG 01666 int checkR; 01667 int z; 01668 int zindex; 01669 #endif 01670 01671 moves = NULL; 01672 /* Initialize R */ 01673 xindex = table->invperm[x]; 01674 limitSize = size = table->keys - table->isolated; 01675 R = 0; 01676 for (y = xHigh; y > x; y--) { 01677 yindex = table->invperm[y]; 01678 if (cuddTestInteract(table,xindex,yindex)) { 01679 isolated = table->vars[yindex]->ref == 1; 01680 R += table->subtables[y].keys - isolated; 01681 } 01682 } 01683 01684 y = cuddNextHigh(table,x); 01685 while (y <= xHigh && size - R < limitSize) { 01686 #ifdef DD_DEBUG 01687 checkR = 0; 01688 for (z = xHigh; z > x; z--) { 01689 zindex = table->invperm[z]; 01690 if (cuddTestInteract(table,xindex,zindex)) { 01691 isolated = table->vars[zindex]->ref == 1; 01692 checkR += table->subtables[z].keys - isolated; 01693 } 01694 } 01695 assert(R == checkR); 01696 #endif 01697 /* Update upper bound on node decrease. */ 01698 yindex = table->invperm[y]; 01699 if (cuddTestInteract(table,xindex,yindex)) { 01700 isolated = table->vars[yindex]->ref == 1; 01701 R -= table->subtables[y].keys - isolated; 01702 } 01703 size = cuddSwapInPlace(table,x,y); 01704 if (size == 0) goto ddSiftingDownOutOfMem; 01705 move = (Move *) cuddDynamicAllocNode(table); 01706 if (move == NULL) goto ddSiftingDownOutOfMem; 01707 move->x = x; 01708 move->y = y; 01709 move->size = size; 01710 move->next = moves; 01711 moves = move; 01712 if ((double) size > (double) limitSize * table->maxGrowth) break; 01713 if (size < limitSize) limitSize = size; 01714 x = y; 01715 y = cuddNextHigh(table,x); 01716 } 01717 return(moves); 01718 01719 ddSiftingDownOutOfMem: 01720 while (moves != NULL) { 01721 move = moves->next; 01722 cuddDeallocNode(table, (DdNode *) moves); 01723 moves = move; 01724 } 01725 return((Move *) CUDD_OUT_OF_MEM); 01726 01727 } /* end of ddSiftingDown */
Function********************************************************************
Synopsis [Sifts a variable up.]
Description [Sifts a variable up. Moves y up until either it reaches the bound (xLow) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
Definition at line 1552 of file cuddReorder.c.
01556 { 01557 Move *moves; 01558 Move *move; 01559 int x; 01560 int size; 01561 int limitSize; 01562 int xindex, yindex; 01563 int isolated; 01564 int L; /* lower bound on DD size */ 01565 #ifdef DD_DEBUG 01566 int checkL; 01567 int z; 01568 int zindex; 01569 #endif 01570 01571 moves = NULL; 01572 yindex = table->invperm[y]; 01573 01574 /* Initialize the lower bound. 01575 ** The part of the DD below y will not change. 01576 ** The part of the DD above y that does not interact with y will not 01577 ** change. The rest may vanish in the best case, except for 01578 ** the nodes at level xLow, which will not vanish, regardless. 01579 */ 01580 limitSize = L = table->keys - table->isolated; 01581 for (x = xLow + 1; x < y; x++) { 01582 xindex = table->invperm[x]; 01583 if (cuddTestInteract(table,xindex,yindex)) { 01584 isolated = table->vars[xindex]->ref == 1; 01585 L -= table->subtables[x].keys - isolated; 01586 } 01587 } 01588 isolated = table->vars[yindex]->ref == 1; 01589 L -= table->subtables[y].keys - isolated; 01590 01591 x = cuddNextLow(table,y); 01592 while (x >= xLow && L <= limitSize) { 01593 xindex = table->invperm[x]; 01594 #ifdef DD_DEBUG 01595 checkL = table->keys - table->isolated; 01596 for (z = xLow + 1; z < y; z++) { 01597 zindex = table->invperm[z]; 01598 if (cuddTestInteract(table,zindex,yindex)) { 01599 isolated = table->vars[zindex]->ref == 1; 01600 checkL -= table->subtables[z].keys - isolated; 01601 } 01602 } 01603 isolated = table->vars[yindex]->ref == 1; 01604 checkL -= table->subtables[y].keys - isolated; 01605 assert(L == checkL); 01606 #endif 01607 size = cuddSwapInPlace(table,x,y); 01608 if (size == 0) goto ddSiftingUpOutOfMem; 01609 /* Update the lower bound. */ 01610 if (cuddTestInteract(table,xindex,yindex)) { 01611 isolated = table->vars[xindex]->ref == 1; 01612 L += table->subtables[y].keys - isolated; 01613 } 01614 move = (Move *) cuddDynamicAllocNode(table); 01615 if (move == NULL) goto ddSiftingUpOutOfMem; 01616 move->x = x; 01617 move->y = y; 01618 move->size = size; 01619 move->next = moves; 01620 moves = move; 01621 if ((double) size > (double) limitSize * table->maxGrowth) break; 01622 if (size < limitSize) limitSize = size; 01623 y = x; 01624 x = cuddNextLow(table,y); 01625 } 01626 return(moves); 01627 01628 ddSiftingUpOutOfMem: 01629 while (moves != NULL) { 01630 move = moves->next; 01631 cuddDeallocNode(table, (DdNode *) moves); 01632 moves = move; 01633 } 01634 return((Move *) CUDD_OUT_OF_MEM); 01635 01636 } /* end of ddSiftingUp */
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 1931 of file cuddReorder.c.
01935 { 01936 int y; 01937 int size; 01938 01939 y = cuddNextLow(table,x); 01940 while (y >= xLow) { 01941 size = cuddSwapInPlace(table,y,x); 01942 if (size == 0) { 01943 return(0); 01944 } 01945 x = y; 01946 y = cuddNextLow(table,x); 01947 } 01948 return(1); 01949 01950 } /* end of ddSiftUp */
Function********************************************************************
Synopsis [Swaps any two variables.]
Description [Swaps any two variables. Returns the set of moves.]
SideEffects [None]
Definition at line 1304 of file cuddReorder.c.
01308 { 01309 Move *move, *moves; 01310 int xRef,yRef; 01311 int xNext,yNext; 01312 int size; 01313 int limitSize; 01314 int tmp; 01315 01316 if (x >y) { 01317 tmp = x; x = y; y = tmp; 01318 } 01319 01320 xRef = x; yRef = y; 01321 01322 xNext = cuddNextHigh(table,x); 01323 yNext = cuddNextLow(table,y); 01324 moves = NULL; 01325 limitSize = table->keys - table->isolated; 01326 01327 for (;;) { 01328 if ( xNext == yNext) { 01329 size = cuddSwapInPlace(table,x,xNext); 01330 if (size == 0) goto ddSwapAnyOutOfMem; 01331 move = (Move *) cuddDynamicAllocNode(table); 01332 if (move == NULL) goto ddSwapAnyOutOfMem; 01333 move->x = x; 01334 move->y = xNext; 01335 move->size = size; 01336 move->next = moves; 01337 moves = move; 01338 01339 size = cuddSwapInPlace(table,yNext,y); 01340 if (size == 0) goto ddSwapAnyOutOfMem; 01341 move = (Move *) cuddDynamicAllocNode(table); 01342 if (move == NULL) goto ddSwapAnyOutOfMem; 01343 move->x = yNext; 01344 move->y = y; 01345 move->size = size; 01346 move->next = moves; 01347 moves = move; 01348 01349 size = cuddSwapInPlace(table,x,xNext); 01350 if (size == 0) goto ddSwapAnyOutOfMem; 01351 move = (Move *) cuddDynamicAllocNode(table); 01352 if (move == NULL) goto ddSwapAnyOutOfMem; 01353 move->x = x; 01354 move->y = xNext; 01355 move->size = size; 01356 move->next = moves; 01357 moves = move; 01358 01359 tmp = x; x = y; y = tmp; 01360 01361 } else if (x == yNext) { 01362 01363 size = cuddSwapInPlace(table,x,xNext); 01364 if (size == 0) goto ddSwapAnyOutOfMem; 01365 move = (Move *) cuddDynamicAllocNode(table); 01366 if (move == NULL) goto ddSwapAnyOutOfMem; 01367 move->x = x; 01368 move->y = xNext; 01369 move->size = size; 01370 move->next = moves; 01371 moves = move; 01372 01373 tmp = x; x = y; y = tmp; 01374 01375 } else { 01376 size = cuddSwapInPlace(table,x,xNext); 01377 if (size == 0) goto ddSwapAnyOutOfMem; 01378 move = (Move *) cuddDynamicAllocNode(table); 01379 if (move == NULL) goto ddSwapAnyOutOfMem; 01380 move->x = x; 01381 move->y = xNext; 01382 move->size = size; 01383 move->next = moves; 01384 moves = move; 01385 01386 size = cuddSwapInPlace(table,yNext,y); 01387 if (size == 0) goto ddSwapAnyOutOfMem; 01388 move = (Move *) cuddDynamicAllocNode(table); 01389 if (move == NULL) goto ddSwapAnyOutOfMem; 01390 move->x = yNext; 01391 move->y = y; 01392 move->size = size; 01393 move->next = moves; 01394 moves = move; 01395 01396 x = xNext; 01397 y = yNext; 01398 } 01399 01400 xNext = cuddNextHigh(table,x); 01401 yNext = cuddNextLow(table,y); 01402 if (xNext > yRef) break; 01403 01404 if ((double) size > table->maxGrowth * (double) limitSize) break; 01405 if (size < limitSize) limitSize = size; 01406 } 01407 if (yNext>=xRef) { 01408 size = cuddSwapInPlace(table,yNext,y); 01409 if (size == 0) goto ddSwapAnyOutOfMem; 01410 move = (Move *) cuddDynamicAllocNode(table); 01411 if (move == NULL) goto ddSwapAnyOutOfMem; 01412 move->x = yNext; 01413 move->y = y; 01414 move->size = size; 01415 move->next = moves; 01416 moves = move; 01417 } 01418 01419 return(moves); 01420 01421 ddSwapAnyOutOfMem: 01422 while (moves != NULL) { 01423 move = moves->next; 01424 cuddDeallocNode(table, (DdNode *) moves); 01425 moves = move; 01426 } 01427 return(NULL); 01428 01429 } /* end of ddSwapAny */
static int ddUniqueCompare | ( | int * | ptrX, | |
int * | ptrY | |||
) | [static] |
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]
Definition at line 1280 of file cuddReorder.c.
static int ddUpdateMtrTree | ( | DdManager * | table, | |
MtrNode * | treenode, | |||
int * | perm, | |||
int * | invperm | |||
) | [static] |
Function********************************************************************
Synopsis [Updates the BDD variable group tree before a shuffle.]
Description [Updates the BDD variable group tree before a shuffle. Returns 1 if successful; 0 otherwise.]
SideEffects [Changes the BDD variable group tree.]
SeeAlso []
Definition at line 2001 of file cuddReorder.c.
02006 { 02007 int i, size, index, level; 02008 int minLevel, maxLevel, minIndex; 02009 02010 if (treenode == NULL) return(1); 02011 02012 /* i : level */ 02013 for (i = treenode->low; i < treenode->low + treenode->size; i++) { 02014 index = table->invperm[i]; 02015 level = perm[index]; 02016 if (level < minLevel) { 02017 minLevel = level; 02018 minIndex = index; 02019 } 02020 if (level > maxLevel) 02021 maxLevel = level; 02022 } 02023 size = maxLevel - minLevel + 1; 02024 if (size == treenode->size) { 02025 treenode->low = minLevel; 02026 treenode->index = minIndex; 02027 } else 02028 return(0); 02029 02030 if (treenode->child != NULL) { 02031 if (!ddUpdateMtrTree(table, treenode->child, perm, invperm)) 02032 return(0); 02033 } 02034 if (treenode->younger != NULL) { 02035 if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm)) 02036 return(0); 02037 } 02038 return(1); 02039 }
char rcsid [] DD_UNUSED = "$Id: cuddReorder.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static] |
Definition at line 71 of file cuddReorder.c.
Definition at line 76 of file cuddReorder.c.
int* entry [static] |
Definition at line 74 of file cuddReorder.c.