#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 Move *zddSwapAny | ARGS ((DdManager *table, int x, int y)) |
static int cuddZddSiftingAux | ARGS ((DdManager *table, int x, int x_low, int x_high)) |
static Move *cuddZddSiftingUp | ARGS ((DdManager *table, int x, int x_low, int initial_size)) |
static Move *cuddZddSiftingDown | ARGS ((DdManager *table, int x, int x_high, int initial_size)) |
static int cuddZddSiftingBackward | ARGS ((DdManager *table, Move *moves, int size)) |
static void zddReorderPreprocess | ARGS ((DdManager *table)) |
static int zddShuffle | ARGS ((DdManager *table, int *permutation)) |
static int zddSiftUp | ARGS ((DdManager *table, int x, int xLow)) |
static void zddFixTree | ARGS ((DdManager *table, MtrNode *treenode)) |
int | Cudd_zddReduceHeap (DdManager *table, Cudd_ReorderingType heuristic, int minsize) |
int | Cudd_zddShuffleHeap (DdManager *table, int *permutation) |
int | cuddZddAlignToBdd (DdManager *table) |
int | cuddZddNextHigh (DdManager *table, int x) |
int | cuddZddNextLow (DdManager *table, int x) |
int | cuddZddUniqueCompare (int *ptr_x, int *ptr_y) |
int | cuddZddSwapInPlace (DdManager *table, int x, int y) |
int | cuddZddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic) |
int | cuddZddSifting (DdManager *table, int lower, int upper) |
static Move * | zddSwapAny (DdManager *table, int x, int y) |
static int | cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high) |
static Move * | cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size) |
static Move * | cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size) |
static int | cuddZddSiftingBackward (DdManager *table, Move *moves, int size) |
static void | zddReorderPreprocess (DdManager *table) |
static int | zddReorderPostprocess (DdManager *table) |
static int | zddShuffle (DdManager *table, int *permutation) |
static int | zddSiftUp (DdManager *table, int x, int xLow) |
static void | zddFixTree (DdManager *table, MtrNode *treenode) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddZddReord.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $" |
int * | zdd_entry |
int | zddTotalNumberSwapping |
static DdNode * | empty |
#define DD_MAX_SUBTABLE_SPARSITY 8 |
CFile***********************************************************************
FileName [cuddZddReord.c]
PackageName [cudd]
Synopsis [Procedures for dynamic variable ordering of ZDDs.]
Description [External procedures included in this module:
Internal procedures included in this module:
Static procedures included in this module:
]
SeeAlso []
Author [Hyong-Kyoon Shin, In-Ho Moon]
Copyright [ This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]
Definition at line 56 of file cuddZddReord.c.
#define DD_SHRINK_FACTOR 2 |
Definition at line 57 of file cuddZddReord.c.
static int zddSiftUp ARGS | ( | (DdManager *table, int x, int xLow) | ) | [static] |
static int zddShuffle ARGS | ( | (DdManager *table, int *permutation) | ) | [static] |
static void zddReorderPreprocess ARGS | ( | (DdManager *table) | ) | [static] |
static Move* cuddZddSiftingDown ARGS | ( | (DdManager *table, int x, int x_high, int initial_size) | ) | [static] |
static Move* cuddZddSiftingUp ARGS | ( | (DdManager *table, int x, int x_low, int initial_size) | ) | [static] |
static int cuddZddSiftingAux ARGS | ( | (DdManager *table, int x, int x_low, int x_high) | ) | [static] |
int Cudd_zddReduceHeap | ( | DdManager * | table, | |
Cudd_ReorderingType | heuristic, | |||
int | minsize | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Main dynamic reordering routine for ZDDs.]
Description [Main dynamic reordering routine for ZDDs. Calls one of the possible reordering procedures:
For sifting and symmetric sifting it is possible to request reordering to convergence.
The core of all methods is the reordering procedure cuddZddSwapInPlace() which swaps two adjacent variables. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.]
SideEffects [Changes the variable order for all ZDDs and clears the cache.]
Definition at line 140 of file cuddZddReord.c.
00144 { 00145 DdHook *hook; 00146 int result; 00147 unsigned int nextDyn; 00148 #ifdef DD_STATS 00149 unsigned int initialSize; 00150 unsigned int finalSize; 00151 #endif 00152 long localTime; 00153 00154 /* Don't reorder if there are too many dead nodes. */ 00155 if (table->keysZ - table->deadZ < (unsigned) minsize) 00156 return(1); 00157 00158 if (heuristic == CUDD_REORDER_SAME) { 00159 heuristic = table->autoMethodZ; 00160 } 00161 if (heuristic == CUDD_REORDER_NONE) { 00162 return(1); 00163 } 00164 00165 /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore 00166 ** we count it. 00167 */ 00168 table->reorderings++; 00169 empty = table->zero; 00170 00171 localTime = util_cpu_time(); 00172 00173 /* Run the hook functions. */ 00174 hook = table->preReorderingHook; 00175 while (hook != NULL) { 00176 int res = (hook->f)(table, "ZDD", (void *)heuristic); 00177 if (res == 0) return(0); 00178 hook = hook->next; 00179 } 00180 00181 /* Clear the cache and collect garbage. */ 00182 zddReorderPreprocess(table); 00183 zddTotalNumberSwapping = 0; 00184 00185 #ifdef DD_STATS 00186 initialSize = table->keysZ; 00187 00188 switch(heuristic) { 00189 case CUDD_REORDER_RANDOM: 00190 case CUDD_REORDER_RANDOM_PIVOT: 00191 (void) fprintf(table->out,"#:I_RANDOM "); 00192 break; 00193 case CUDD_REORDER_SIFT: 00194 case CUDD_REORDER_SIFT_CONVERGE: 00195 case CUDD_REORDER_SYMM_SIFT: 00196 case CUDD_REORDER_SYMM_SIFT_CONV: 00197 (void) fprintf(table->out,"#:I_SIFTING "); 00198 break; 00199 case CUDD_REORDER_LINEAR: 00200 case CUDD_REORDER_LINEAR_CONVERGE: 00201 (void) fprintf(table->out,"#:I_LINSIFT "); 00202 break; 00203 default: 00204 (void) fprintf(table->err,"Unsupported ZDD reordering method\n"); 00205 return(0); 00206 } 00207 (void) fprintf(table->out,"%8d: initial size",initialSize); 00208 #endif 00209 00210 result = cuddZddTreeSifting(table,heuristic); 00211 00212 #ifdef DD_STATS 00213 (void) fprintf(table->out,"\n"); 00214 finalSize = table->keysZ; 00215 (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); 00216 (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", 00217 ((double)(util_cpu_time() - localTime)/1000.0)); 00218 (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", 00219 zddTotalNumberSwapping); 00220 #endif 00221 00222 if (result == 0) 00223 return(0); 00224 00225 if (!zddReorderPostprocess(table)) 00226 return(0); 00227 00228 if (table->realignZ) { 00229 if (!cuddBddAlignToZdd(table)) 00230 return(0); 00231 } 00232 00233 nextDyn = table->keysZ * DD_DYN_RATIO; 00234 if (table->reorderings < 20 || nextDyn > table->nextDyn) 00235 table->nextDyn = nextDyn; 00236 else 00237 table->nextDyn += 20; 00238 00239 table->reordered = 1; 00240 00241 /* Run hook functions. */ 00242 hook = table->postReorderingHook; 00243 while (hook != NULL) { 00244 int res = (hook->f)(table, "ZDD", (void *)localTime); 00245 if (res == 0) return(0); 00246 hook = hook->next; 00247 } 00248 /* Update cumulative reordering time. */ 00249 table->reordTime += util_cpu_time() - localTime; 00250 00251 return(result); 00252 00253 } /* end of Cudd_zddReduceHeap */
int Cudd_zddShuffleHeap | ( | DdManager * | table, | |
int * | permutation | |||
) |
Function********************************************************************
Synopsis [Reorders ZDD variables according to given permutation.]
Description [Reorders ZDD variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.]
SideEffects [Changes the ZDD variable order for all diagrams and clears the cache.]
SeeAlso [Cudd_zddReduceHeap]
Definition at line 273 of file cuddZddReord.c.
00276 { 00277 00278 int result; 00279 00280 empty = table->zero; 00281 zddReorderPreprocess(table); 00282 00283 result = zddShuffle(table,permutation); 00284 00285 if (!zddReorderPostprocess(table)) return(0); 00286 00287 return(result); 00288 00289 } /* end of Cudd_zddShuffleHeap */
int cuddZddAlignToBdd | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Reorders ZDD variables according to the order of the BDD variables.]
Description [Reorders ZDD variables according to the order of the BDD variables. This function can be called at the end of BDD reordering to insure that the order of the ZDD variables is consistent with the order of the BDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M
be the ratio of the two numbers. cuddZddAlignToBdd 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_ReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]
SideEffects [Changes the ZDD variable order for all diagrams and performs garbage collection of the ZDD unique table.]
SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap]
Definition at line 321 of file cuddZddReord.c.
00323 { 00324 int *invpermZ; /* permutation array */ 00325 int M; /* ratio of ZDD variables to BDD variables */ 00326 int i,j; /* loop indices */ 00327 int result; /* return value */ 00328 00329 /* We assume that a ratio of 0 is OK. */ 00330 if (table->sizeZ == 0) 00331 return(1); 00332 00333 empty = table->zero; 00334 M = table->sizeZ / table->size; 00335 /* Check whether the number of ZDD variables is a multiple of the 00336 ** number of BDD variables. 00337 */ 00338 if (M * table->size != table->sizeZ) 00339 return(0); 00340 /* Create and initialize the inverse permutation array. */ 00341 invpermZ = ALLOC(int,table->sizeZ); 00342 if (invpermZ == NULL) { 00343 table->errorCode = CUDD_MEMORY_OUT; 00344 return(0); 00345 } 00346 for (i = 0; i < table->size; i++) { 00347 int index = table->invperm[i]; 00348 int indexZ = index * M; 00349 int levelZ = table->permZ[indexZ]; 00350 levelZ = (levelZ / M) * M; 00351 for (j = 0; j < M; j++) { 00352 invpermZ[M * i + j] = table->invpermZ[levelZ + j]; 00353 } 00354 } 00355 /* Eliminate dead nodes. Do not scan the cache again, because we 00356 ** assume that Cudd_ReduceHeap has already cleared it. 00357 */ 00358 cuddGarbageCollectZdd(table,0); 00359 00360 result = zddShuffle(table, invpermZ); 00361 FREE(invpermZ); 00362 /* Fix the ZDD variable group tree. */ 00363 zddFixTree(table,table->treeZ); 00364 return(result); 00365 00366 } /* end of cuddZddAlignToBdd */
int cuddZddNextHigh | ( | 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 []
Definition at line 382 of file cuddZddReord.c.
int cuddZddNextLow | ( | 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 []
Definition at line 404 of file cuddZddReord.c.
int cuddZddSifting | ( | 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]
SeeAlso []
Definition at line 836 of file cuddZddReord.c.
00840 { 00841 int i; 00842 int *var; 00843 int size; 00844 int x; 00845 int result; 00846 #ifdef DD_STATS 00847 int previousSize; 00848 #endif 00849 00850 size = table->sizeZ; 00851 00852 /* Find order in which to sift variables. */ 00853 var = NULL; 00854 zdd_entry = ALLOC(int, size); 00855 if (zdd_entry == NULL) { 00856 table->errorCode = CUDD_MEMORY_OUT; 00857 goto cuddZddSiftingOutOfMem; 00858 } 00859 var = ALLOC(int, size); 00860 if (var == NULL) { 00861 table->errorCode = CUDD_MEMORY_OUT; 00862 goto cuddZddSiftingOutOfMem; 00863 } 00864 00865 for (i = 0; i < size; i++) { 00866 x = table->permZ[i]; 00867 zdd_entry[i] = table->subtableZ[x].keys; 00868 var[i] = i; 00869 } 00870 00871 qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); 00872 00873 /* Now sift. */ 00874 for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { 00875 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00876 break; 00877 x = table->permZ[var[i]]; 00878 if (x < lower || x > upper) continue; 00879 #ifdef DD_STATS 00880 previousSize = table->keysZ; 00881 #endif 00882 result = cuddZddSiftingAux(table, x, lower, upper); 00883 if (!result) 00884 goto cuddZddSiftingOutOfMem; 00885 #ifdef DD_STATS 00886 if (table->keysZ < (unsigned) previousSize) { 00887 (void) fprintf(table->out,"-"); 00888 } else if (table->keysZ > (unsigned) previousSize) { 00889 (void) fprintf(table->out,"+"); /* should never happen */ 00890 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); 00891 } else { 00892 (void) fprintf(table->out,"="); 00893 } 00894 fflush(table->out); 00895 #endif 00896 } 00897 00898 FREE(var); 00899 FREE(zdd_entry); 00900 00901 return(1); 00902 00903 cuddZddSiftingOutOfMem: 00904 00905 if (zdd_entry != NULL) FREE(zdd_entry); 00906 if (var != NULL) FREE(var); 00907 00908 return(0); 00909 00910 } /* end of cuddZddSifting */
static int cuddZddSiftingAux | ( | DdManager * | table, | |
int | x, | |||
int | x_low, | |||
int | x_high | |||
) | [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]
SeeAlso []
Definition at line 1086 of file cuddZddReord.c.
01091 { 01092 Move *move; 01093 Move *moveUp; /* list of up move */ 01094 Move *moveDown; /* list of down move */ 01095 01096 int initial_size; 01097 int result; 01098 01099 initial_size = table->keysZ; 01100 01101 #ifdef DD_DEBUG 01102 assert(table->subtableZ[x].keys > 0); 01103 #endif 01104 01105 moveDown = NULL; 01106 moveUp = NULL; 01107 01108 if (x == x_low) { 01109 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); 01110 /* after that point x --> x_high */ 01111 if (moveDown == NULL) 01112 goto cuddZddSiftingAuxOutOfMem; 01113 result = cuddZddSiftingBackward(table, moveDown, 01114 initial_size); 01115 /* move backward and stop at best position */ 01116 if (!result) 01117 goto cuddZddSiftingAuxOutOfMem; 01118 01119 } 01120 else if (x == x_high) { 01121 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); 01122 /* after that point x --> x_low */ 01123 if (moveUp == NULL) 01124 goto cuddZddSiftingAuxOutOfMem; 01125 result = cuddZddSiftingBackward(table, moveUp, initial_size); 01126 /* move backward and stop at best position */ 01127 if (!result) 01128 goto cuddZddSiftingAuxOutOfMem; 01129 } 01130 else if ((x - x_low) > (x_high - x)) { 01131 /* must go down first:shorter */ 01132 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); 01133 /* after that point x --> x_high */ 01134 if (moveDown == NULL) 01135 goto cuddZddSiftingAuxOutOfMem; 01136 moveUp = cuddZddSiftingUp(table, moveDown->y, x_low, 01137 initial_size); 01138 if (moveUp == NULL) 01139 goto cuddZddSiftingAuxOutOfMem; 01140 result = cuddZddSiftingBackward(table, moveUp, initial_size); 01141 /* move backward and stop at best position */ 01142 if (!result) 01143 goto cuddZddSiftingAuxOutOfMem; 01144 } 01145 else { 01146 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); 01147 /* after that point x --> x_high */ 01148 if (moveUp == NULL) 01149 goto cuddZddSiftingAuxOutOfMem; 01150 moveDown = cuddZddSiftingDown(table, moveUp->x, x_high, 01151 initial_size); 01152 /* then move up */ 01153 if (moveDown == NULL) 01154 goto cuddZddSiftingAuxOutOfMem; 01155 result = cuddZddSiftingBackward(table, moveDown, 01156 initial_size); 01157 /* move backward and stop at best position */ 01158 if (!result) 01159 goto cuddZddSiftingAuxOutOfMem; 01160 } 01161 01162 while (moveDown != NULL) { 01163 move = moveDown->next; 01164 cuddDeallocNode(table, (DdNode *)moveDown); 01165 moveDown = move; 01166 } 01167 while (moveUp != NULL) { 01168 move = moveUp->next; 01169 cuddDeallocNode(table, (DdNode *)moveUp); 01170 moveUp = move; 01171 } 01172 01173 return(1); 01174 01175 cuddZddSiftingAuxOutOfMem: 01176 while (moveDown != NULL) { 01177 move = moveDown->next; 01178 cuddDeallocNode(table, (DdNode *)moveDown); 01179 moveDown = move; 01180 } 01181 while (moveUp != NULL) { 01182 move = moveUp->next; 01183 cuddDeallocNode(table, (DdNode *)moveUp); 01184 moveUp = move; 01185 } 01186 01187 return(0); 01188 01189 } /* end of cuddZddSiftingAux */
Function********************************************************************
Synopsis [Given a set of moves, returns the ZDD heap to the position giving the minimum size.]
Description [Given a set of moves, returns the ZDD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 1333 of file cuddZddReord.c.
01337 { 01338 int i; 01339 int i_best; 01340 Move *move; 01341 int res; 01342 01343 /* Find the minimum size among moves. */ 01344 i_best = -1; 01345 for (move = moves, i = 0; move != NULL; move = move->next, i++) { 01346 if (move->size < size) { 01347 i_best = i; 01348 size = move->size; 01349 } 01350 } 01351 01352 for (move = moves, i = 0; move != NULL; move = move->next, i++) { 01353 if (i == i_best) 01354 break; 01355 res = cuddZddSwapInPlace(table, move->x, move->y); 01356 if (!res) 01357 return(0); 01358 if (i_best == -1 && res == size) 01359 break; 01360 } 01361 01362 return(1); 01363 01364 } /* end of cuddZddSiftingBackward */
Function********************************************************************
Synopsis [Sifts a variable down.]
Description [Sifts a variable down. Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
SeeAlso []
Definition at line 1269 of file cuddZddReord.c.
01274 { 01275 Move *moves; 01276 Move *move; 01277 int y; 01278 int size; 01279 int limit_size = initial_size; 01280 01281 moves = NULL; 01282 y = cuddZddNextHigh(table, x); 01283 while (y <= x_high) { 01284 size = cuddZddSwapInPlace(table, x, y); 01285 if (size == 0) 01286 goto cuddZddSiftingDownOutOfMem; 01287 move = (Move *)cuddDynamicAllocNode(table); 01288 if (move == NULL) 01289 goto cuddZddSiftingDownOutOfMem; 01290 move->x = x; 01291 move->y = y; 01292 move->size = size; 01293 move->next = moves; 01294 moves = move; 01295 01296 if ((double)size > (double)limit_size * table->maxGrowth) 01297 break; 01298 if (size < limit_size) 01299 limit_size = size; 01300 01301 x = y; 01302 y = cuddZddNextHigh(table, x); 01303 } 01304 return(moves); 01305 01306 cuddZddSiftingDownOutOfMem: 01307 while (moves != NULL) { 01308 move = moves->next; 01309 cuddDeallocNode(table, (DdNode *)moves); 01310 moves = move; 01311 } 01312 return(NULL); 01313 01314 } /* end of cuddZddSiftingDown */
Function********************************************************************
Synopsis [Sifts a variable up.]
Description [Sifts a variable up. Moves y up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
SeeAlso []
Definition at line 1206 of file cuddZddReord.c.
01211 { 01212 Move *moves; 01213 Move *move; 01214 int y; 01215 int size; 01216 int limit_size = initial_size; 01217 01218 moves = NULL; 01219 y = cuddZddNextLow(table, x); 01220 while (y >= x_low) { 01221 size = cuddZddSwapInPlace(table, y, x); 01222 if (size == 0) 01223 goto cuddZddSiftingUpOutOfMem; 01224 move = (Move *)cuddDynamicAllocNode(table); 01225 if (move == NULL) 01226 goto cuddZddSiftingUpOutOfMem; 01227 move->x = y; 01228 move->y = x; 01229 move->size = size; 01230 move->next = moves; 01231 moves = move; 01232 01233 if ((double)size > (double)limit_size * table->maxGrowth) 01234 break; 01235 if (size < limit_size) 01236 limit_size = size; 01237 01238 x = y; 01239 y = cuddZddNextLow(table, x); 01240 } 01241 return(moves); 01242 01243 cuddZddSiftingUpOutOfMem: 01244 while (moves != NULL) { 01245 move = moves->next; 01246 cuddDeallocNode(table, (DdNode *)moves); 01247 moves = move; 01248 } 01249 return(NULL); 01250 01251 } /* end of cuddZddSiftingUp */
int cuddZddSwapInPlace | ( | 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. cuddZddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 453 of file cuddZddReord.c.
00457 { 00458 DdNodePtr *xlist, *ylist; 00459 int xindex, yindex; 00460 int xslots, yslots; 00461 int xshift, yshift; 00462 int oldxkeys, oldykeys; 00463 int newxkeys, newykeys; 00464 int i; 00465 int posn; 00466 DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; 00467 DdNode *newf1, *newf0, *next; 00468 DdNodePtr g, *lastP, *previousP; 00469 00470 #ifdef DD_DEBUG 00471 assert(x < y); 00472 assert(cuddZddNextHigh(table,x) == y); 00473 assert(table->subtableZ[x].keys != 0); 00474 assert(table->subtableZ[y].keys != 0); 00475 assert(table->subtableZ[x].dead == 0); 00476 assert(table->subtableZ[y].dead == 0); 00477 #endif 00478 00479 zddTotalNumberSwapping++; 00480 00481 /* Get parameters of x subtable. */ 00482 xindex = table->invpermZ[x]; 00483 xlist = table->subtableZ[x].nodelist; 00484 oldxkeys = table->subtableZ[x].keys; 00485 xslots = table->subtableZ[x].slots; 00486 xshift = table->subtableZ[x].shift; 00487 newxkeys = 0; 00488 00489 yindex = table->invpermZ[y]; 00490 ylist = table->subtableZ[y].nodelist; 00491 oldykeys = table->subtableZ[y].keys; 00492 yslots = table->subtableZ[y].slots; 00493 yshift = table->subtableZ[y].shift; 00494 newykeys = oldykeys; 00495 00496 /* The nodes in the x layer that don't depend on y directly 00497 ** will stay there; the others are put in a chain. 00498 ** The chain is handled as a FIFO; g points to the beginning and 00499 ** last points to the end. 00500 */ 00501 00502 g = NULL; 00503 lastP = &g; 00504 for (i = 0; i < xslots; i++) { 00505 previousP = &(xlist[i]); 00506 f = *previousP; 00507 while (f != NULL) { 00508 next = f->next; 00509 f1 = cuddT(f); f0 = cuddE(f); 00510 if ((f1->index != (DdHalfWord) yindex) && 00511 (f0->index != (DdHalfWord) yindex)) { /* stays */ 00512 newxkeys++; 00513 *previousP = f; 00514 previousP = &(f->next); 00515 } else { 00516 f->index = yindex; 00517 *lastP = f; 00518 lastP = &(f->next); 00519 } 00520 f = next; 00521 } /* while there are elements in the collision chain */ 00522 *previousP = NULL; 00523 } /* for each slot of the x subtable */ 00524 *lastP = NULL; 00525 00526 00527 #ifdef DD_COUNT 00528 table->swapSteps += oldxkeys - newxkeys; 00529 #endif 00530 /* Take care of the x nodes that must be re-expressed. 00531 ** They form a linked list pointed by g. Their index has been 00532 ** changed to yindex already. 00533 */ 00534 f = g; 00535 while (f != NULL) { 00536 next = f->next; 00537 /* Find f1, f0, f11, f10, f01, f00. */ 00538 f1 = cuddT(f); 00539 if ((int) f1->index == yindex) { 00540 f11 = cuddT(f1); f10 = cuddE(f1); 00541 } else { 00542 f11 = empty; f10 = f1; 00543 } 00544 f0 = cuddE(f); 00545 if ((int) f0->index == yindex) { 00546 f01 = cuddT(f0); f00 = cuddE(f0); 00547 } else { 00548 f01 = empty; f00 = f0; 00549 } 00550 00551 /* Decrease ref count of f1. */ 00552 cuddSatDec(f1->ref); 00553 /* Create the new T child. */ 00554 if (f11 == empty) { 00555 if (f01 != empty) { 00556 newf1 = f01; 00557 cuddSatInc(newf1->ref); 00558 } 00559 /* else case was already handled when finding nodes 00560 ** with both children below level y 00561 */ 00562 } else { 00563 /* Check xlist for triple (xindex, f11, f01). */ 00564 posn = ddHash(f11, f01, xshift); 00565 /* For each element newf1 in collision list xlist[posn]. */ 00566 newf1 = xlist[posn]; 00567 while (newf1 != NULL) { 00568 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { 00569 cuddSatInc(newf1->ref); 00570 break; /* match */ 00571 } 00572 newf1 = newf1->next; 00573 } /* while newf1 */ 00574 if (newf1 == NULL) { /* no match */ 00575 newf1 = cuddDynamicAllocNode(table); 00576 if (newf1 == NULL) 00577 goto zddSwapOutOfMem; 00578 newf1->index = xindex; newf1->ref = 1; 00579 cuddT(newf1) = f11; 00580 cuddE(newf1) = f01; 00581 /* Insert newf1 in the collision list xlist[pos]; 00582 ** increase the ref counts of f11 and f01 00583 */ 00584 newxkeys++; 00585 newf1->next = xlist[posn]; 00586 xlist[posn] = newf1; 00587 cuddSatInc(f11->ref); 00588 cuddSatInc(f01->ref); 00589 } 00590 } 00591 cuddT(f) = newf1; 00592 00593 /* Do the same for f0. */ 00594 /* Decrease ref count of f0. */ 00595 cuddSatDec(f0->ref); 00596 /* Create the new E child. */ 00597 if (f10 == empty) { 00598 newf0 = f00; 00599 cuddSatInc(newf0->ref); 00600 } else { 00601 /* Check xlist for triple (xindex, f10, f00). */ 00602 posn = ddHash(f10, f00, xshift); 00603 /* For each element newf0 in collision list xlist[posn]. */ 00604 newf0 = xlist[posn]; 00605 while (newf0 != NULL) { 00606 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { 00607 cuddSatInc(newf0->ref); 00608 break; /* match */ 00609 } 00610 newf0 = newf0->next; 00611 } /* while newf0 */ 00612 if (newf0 == NULL) { /* no match */ 00613 newf0 = cuddDynamicAllocNode(table); 00614 if (newf0 == NULL) 00615 goto zddSwapOutOfMem; 00616 newf0->index = xindex; newf0->ref = 1; 00617 cuddT(newf0) = f10; cuddE(newf0) = f00; 00618 /* Insert newf0 in the collision list xlist[posn]; 00619 ** increase the ref counts of f10 and f00. 00620 */ 00621 newxkeys++; 00622 newf0->next = xlist[posn]; 00623 xlist[posn] = newf0; 00624 cuddSatInc(f10->ref); 00625 cuddSatInc(f00->ref); 00626 } 00627 } 00628 cuddE(f) = newf0; 00629 00630 /* Insert the modified f in ylist. 00631 ** The modified f does not already exists in ylist. 00632 ** (Because of the uniqueness of the cofactors.) 00633 */ 00634 posn = ddHash(newf1, newf0, yshift); 00635 newykeys++; 00636 f->next = ylist[posn]; 00637 ylist[posn] = f; 00638 f = next; 00639 } /* while f != NULL */ 00640 00641 /* GC the y layer. */ 00642 00643 /* For each node f in ylist. */ 00644 for (i = 0; i < yslots; i++) { 00645 previousP = &(ylist[i]); 00646 f = *previousP; 00647 while (f != NULL) { 00648 next = f->next; 00649 if (f->ref == 0) { 00650 cuddSatDec(cuddT(f)->ref); 00651 cuddSatDec(cuddE(f)->ref); 00652 cuddDeallocNode(table, f); 00653 newykeys--; 00654 } else { 00655 *previousP = f; 00656 previousP = &(f->next); 00657 } 00658 f = next; 00659 } /* while f */ 00660 *previousP = NULL; 00661 } /* for i */ 00662 00663 /* Set the appropriate fields in table. */ 00664 table->subtableZ[x].nodelist = ylist; 00665 table->subtableZ[x].slots = yslots; 00666 table->subtableZ[x].shift = yshift; 00667 table->subtableZ[x].keys = newykeys; 00668 table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; 00669 00670 table->subtableZ[y].nodelist = xlist; 00671 table->subtableZ[y].slots = xslots; 00672 table->subtableZ[y].shift = xshift; 00673 table->subtableZ[y].keys = newxkeys; 00674 table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; 00675 00676 table->permZ[xindex] = y; table->permZ[yindex] = x; 00677 table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; 00678 00679 table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; 00680 00681 /* Update univ section; univ[x] remains the same. */ 00682 table->univ[y] = cuddT(table->univ[x]); 00683 00684 return (table->keysZ); 00685 00686 zddSwapOutOfMem: 00687 (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); 00688 00689 return (0); 00690 00691 } /* end of cuddZddSwapInPlace */
int cuddZddSwapping | ( | 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]
SeeAlso []
Definition at line 715 of file cuddZddReord.c.
00720 { 00721 int i, j; 00722 int max, keys; 00723 int nvars; 00724 int x, y; 00725 int iterate; 00726 int previousSize; 00727 Move *moves, *move; 00728 int pivot; 00729 int modulo; 00730 int result; 00731 00732 #ifdef DD_DEBUG 00733 /* Sanity check */ 00734 assert(lower >= 0 && upper < table->sizeZ && lower <= upper); 00735 #endif 00736 00737 nvars = upper - lower + 1; 00738 iterate = nvars; 00739 00740 for (i = 0; i < iterate; i++) { 00741 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { 00742 /* Find pivot <= id with maximum keys. */ 00743 for (max = -1, j = lower; j <= upper; j++) { 00744 if ((keys = table->subtableZ[j].keys) > max) { 00745 max = keys; 00746 pivot = j; 00747 } 00748 } 00749 00750 modulo = upper - pivot; 00751 if (modulo == 0) { 00752 y = pivot; /* y = nvars-1 */ 00753 } else { 00754 /* y = random # from {pivot+1 .. nvars-1} */ 00755 y = pivot + 1 + (int) (Cudd_Random() % modulo); 00756 } 00757 00758 modulo = pivot - lower - 1; 00759 if (modulo < 1) { /* if pivot = 1 or 0 */ 00760 x = lower; 00761 } else { 00762 do { /* x = random # from {0 .. pivot-2} */ 00763 x = (int) Cudd_Random() % modulo; 00764 } while (x == y); 00765 /* Is this condition really needed, since x and y 00766 are in regions separated by pivot? */ 00767 } 00768 } else { 00769 x = (int) (Cudd_Random() % nvars) + lower; 00770 do { 00771 y = (int) (Cudd_Random() % nvars) + lower; 00772 } while (x == y); 00773 } 00774 00775 previousSize = table->keysZ; 00776 moves = zddSwapAny(table, x, y); 00777 if (moves == NULL) 00778 goto cuddZddSwappingOutOfMem; 00779 00780 result = cuddZddSiftingBackward(table, moves, previousSize); 00781 if (!result) 00782 goto cuddZddSwappingOutOfMem; 00783 00784 while (moves != NULL) { 00785 move = moves->next; 00786 cuddDeallocNode(table, (DdNode *) moves); 00787 moves = move; 00788 } 00789 #ifdef DD_STATS 00790 if (table->keysZ < (unsigned) previousSize) { 00791 (void) fprintf(table->out,"-"); 00792 } else if (table->keysZ > (unsigned) previousSize) { 00793 (void) fprintf(table->out,"+"); /* should never happen */ 00794 } else { 00795 (void) fprintf(table->out,"="); 00796 } 00797 fflush(table->out); 00798 #endif 00799 } 00800 00801 return(1); 00802 00803 cuddZddSwappingOutOfMem: 00804 while (moves != NULL) { 00805 move = moves->next; 00806 cuddDeallocNode(table, (DdNode *) moves); 00807 moves = move; 00808 } 00809 return(0); 00810 00811 } /* end of cuddZddSwapping */
int cuddZddUniqueCompare | ( | int * | ptr_x, | |
int * | ptr_y | |||
) |
Function********************************************************************
Synopsis [Comparison function used by qsort.]
Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.]
SideEffects [None]
SeeAlso []
Definition at line 428 of file cuddZddReord.c.
Function********************************************************************
Synopsis [Fixes the ZDD variable group tree after a shuffle.]
Description [Fixes the ZDD variable group tree after a shuffle. Assumes that the order of the variables in a terminal node has not been changed.]
SideEffects [Changes the ZDD variable group tree.]
SeeAlso []
Definition at line 1614 of file cuddZddReord.c.
01617 { 01618 if (treenode == NULL) return; 01619 treenode->low = ((int) treenode->index < table->sizeZ) ? 01620 table->permZ[treenode->index] : treenode->index; 01621 if (treenode->child != NULL) { 01622 zddFixTree(table, treenode->child); 01623 } 01624 if (treenode->younger != NULL) 01625 zddFixTree(table, treenode->younger); 01626 if (treenode->parent != NULL && treenode->low < treenode->parent->low) { 01627 treenode->parent->low = treenode->low; 01628 treenode->parent->index = treenode->index; 01629 } 01630 return; 01631 01632 } /* end of zddFixTree */
static int zddReorderPostprocess | ( | DdManager * | table | ) | [static] |
Function********************************************************************
Synopsis [Shrinks almost empty ZDD subtables at the end of reordering to guarantee that they have a reasonable load factor.]
Description [Shrinks almost empty subtables at the end of reordering to guarantee that they have a reasonable load factor. However, if there many nodes are being reclaimed, then no resizing occurs. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 1408 of file cuddZddReord.c.
01410 { 01411 int i, j, posn; 01412 DdNodePtr *nodelist, *oldnodelist; 01413 DdNode *node, *next; 01414 unsigned int slots, oldslots; 01415 extern void (*MMoutOfMemory)(long); 01416 void (*saveHandler)(long); 01417 01418 #ifdef DD_VERBOSE 01419 (void) fflush(table->out); 01420 #endif 01421 01422 /* If we have very many reclaimed nodes, we do not want to shrink 01423 ** the subtables, because this will lead to more garbage 01424 ** collections. More garbage collections mean shorter mean life for 01425 ** nodes with zero reference count; hence lower probability of finding 01426 ** a result in the cache. 01427 */ 01428 if (table->reclaimed > table->allocated * 0.5) return(1); 01429 01430 /* Resize subtables. */ 01431 for (i = 0; i < table->sizeZ; i++) { 01432 int shift; 01433 oldslots = table->subtableZ[i].slots; 01434 if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY || 01435 oldslots <= table->initSlots) continue; 01436 oldnodelist = table->subtableZ[i].nodelist; 01437 slots = oldslots >> 1; 01438 saveHandler = MMoutOfMemory; 01439 MMoutOfMemory = Cudd_OutOfMem; 01440 nodelist = ALLOC(DdNodePtr, slots); 01441 MMoutOfMemory = saveHandler; 01442 if (nodelist == NULL) { 01443 return(1); 01444 } 01445 table->subtableZ[i].nodelist = nodelist; 01446 table->subtableZ[i].slots = slots; 01447 table->subtableZ[i].shift++; 01448 table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01449 #ifdef DD_VERBOSE 01450 (void) fprintf(table->err, 01451 "shrunk layer %d (%d keys) from %d to %d slots\n", 01452 i, table->subtableZ[i].keys, oldslots, slots); 01453 #endif 01454 01455 for (j = 0; (unsigned) j < slots; j++) { 01456 nodelist[j] = NULL; 01457 } 01458 shift = table->subtableZ[i].shift; 01459 for (j = 0; (unsigned) j < oldslots; j++) { 01460 node = oldnodelist[j]; 01461 while (node != NULL) { 01462 next = node->next; 01463 posn = ddHash(cuddT(node), cuddE(node), shift); 01464 node->next = nodelist[posn]; 01465 nodelist[posn] = node; 01466 node = next; 01467 } 01468 } 01469 FREE(oldnodelist); 01470 01471 table->memused += (slots - oldslots) * sizeof(DdNode *); 01472 table->slots += slots - oldslots; 01473 table->minDead = (unsigned) (table->gcFrac * (double) table->slots); 01474 table->cacheSlack = (int) ddMin(table->maxCacheHard, 01475 DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) - 01476 2 * (int) table->cacheSlots; 01477 } 01478 /* We don't look at the constant subtable, because it is not 01479 ** affected by reordering. 01480 */ 01481 01482 return(1); 01483 01484 } /* end of zddReorderPostprocess */
static void zddReorderPreprocess | ( | DdManager * | table | ) | [static] |
Function********************************************************************
Synopsis [Prepares the ZDD heap for dynamic reordering.]
Description [Prepares the ZDD heap for dynamic reordering. Does garbage collection, to guarantee that there are no dead nodes; and clears the cache, which is invalidated by dynamic reordering.]
SideEffects [None]
Definition at line 1379 of file cuddZddReord.c.
01381 { 01382 01383 /* Clear the cache. */ 01384 cuddCacheFlush(table); 01385 01386 /* Eliminate dead nodes. Do not scan the cache again. */ 01387 cuddGarbageCollectZdd(table,0); 01388 01389 return; 01390 01391 } /* end of ddReorderPreprocess */
static int zddShuffle | ( | DdManager * | table, | |
int * | permutation | |||
) | [static] |
Function********************************************************************
Synopsis [Reorders ZDD variables according to a given permutation.]
Description [Reorders ZDD variables according to a given permutation. The i-th permutation array contains the index of the variable that should be brought to the i-th level. zddShuffle assumes that no dead nodes are present. The reordering is achieved by a series of upward sifts. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 1503 of file cuddZddReord.c.
01506 { 01507 int index; 01508 int level; 01509 int position; 01510 int numvars; 01511 int result; 01512 #ifdef DD_STATS 01513 long localTime; 01514 int initialSize; 01515 int finalSize; 01516 int previousSize; 01517 #endif 01518 01519 zddTotalNumberSwapping = 0; 01520 #ifdef DD_STATS 01521 localTime = util_cpu_time(); 01522 initialSize = table->keysZ; 01523 (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", 01524 initialSize); 01525 #endif 01526 01527 numvars = table->sizeZ; 01528 01529 for (level = 0; level < numvars; level++) { 01530 index = permutation[level]; 01531 position = table->permZ[index]; 01532 #ifdef DD_STATS 01533 previousSize = table->keysZ; 01534 #endif 01535 result = zddSiftUp(table,position,level); 01536 if (!result) return(0); 01537 #ifdef DD_STATS 01538 if (table->keysZ < (unsigned) previousSize) { 01539 (void) fprintf(table->out,"-"); 01540 } else if (table->keysZ > (unsigned) previousSize) { 01541 (void) fprintf(table->out,"+"); /* should never happen */ 01542 } else { 01543 (void) fprintf(table->out,"="); 01544 } 01545 fflush(table->out); 01546 #endif 01547 } 01548 01549 #ifdef DD_STATS 01550 (void) fprintf(table->out,"\n"); 01551 finalSize = table->keysZ; 01552 (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); 01553 (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", 01554 ((double)(util_cpu_time() - localTime)/1000.0)); 01555 (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", 01556 zddTotalNumberSwapping); 01557 #endif 01558 01559 return(1); 01560 01561 } /* end of zddShuffle */
static int zddSiftUp | ( | DdManager * | table, | |
int | x, | |||
int | xLow | |||
) | [static] |
Function********************************************************************
Synopsis [Moves one ZDD variable up.]
Description [Takes a ZDD variable from position x and sifts it up to position xLow; xLow should be less than or equal to x. Returns 1 if successful; 0 otherwise]
SideEffects [None]
SeeAlso []
Definition at line 1578 of file cuddZddReord.c.
01582 { 01583 int y; 01584 int size; 01585 01586 y = cuddZddNextLow(table,x); 01587 while (y >= xLow) { 01588 size = cuddZddSwapInPlace(table,y,x); 01589 if (size == 0) { 01590 return(0); 01591 } 01592 x = y; 01593 y = cuddZddNextLow(table,x); 01594 } 01595 return(1); 01596 01597 } /* end of zddSiftUp */
Function********************************************************************
Synopsis [Swaps any two variables.]
Description [Swaps any two variables. Returns the set of moves.]
SideEffects [None]
SeeAlso []
Definition at line 930 of file cuddZddReord.c.
00934 { 00935 Move *move, *moves; 00936 int tmp, size; 00937 int x_ref, y_ref; 00938 int x_next, y_next; 00939 int limit_size; 00940 00941 if (x > y) { /* make x precede y */ 00942 tmp = x; x = y; y = tmp; 00943 } 00944 00945 x_ref = x; y_ref = y; 00946 00947 x_next = cuddZddNextHigh(table, x); 00948 y_next = cuddZddNextLow(table, y); 00949 moves = NULL; 00950 limit_size = table->keysZ; 00951 00952 for (;;) { 00953 if (x_next == y_next) { /* x < x_next = y_next < y */ 00954 size = cuddZddSwapInPlace(table, x, x_next); 00955 if (size == 0) 00956 goto zddSwapAnyOutOfMem; 00957 move = (Move *) cuddDynamicAllocNode(table); 00958 if (move == NULL) 00959 goto zddSwapAnyOutOfMem; 00960 move->x = x; 00961 move->y = x_next; 00962 move->size = size; 00963 move->next = moves; 00964 moves = move; 00965 00966 size = cuddZddSwapInPlace(table, y_next, y); 00967 if (size == 0) 00968 goto zddSwapAnyOutOfMem; 00969 move = (Move *)cuddDynamicAllocNode(table); 00970 if (move == NULL) 00971 goto zddSwapAnyOutOfMem; 00972 move->x = y_next; 00973 move->y = y; 00974 move->size = size; 00975 move->next = moves; 00976 moves = move; 00977 00978 size = cuddZddSwapInPlace(table, x, x_next); 00979 if (size == 0) 00980 goto zddSwapAnyOutOfMem; 00981 move = (Move *)cuddDynamicAllocNode(table); 00982 if (move == NULL) 00983 goto zddSwapAnyOutOfMem; 00984 move->x = x; 00985 move->y = x_next; 00986 move->size = size; 00987 move->next = moves; 00988 moves = move; 00989 00990 tmp = x; x = y; y = tmp; 00991 00992 } else if (x == y_next) { /* x = y_next < y = x_next */ 00993 size = cuddZddSwapInPlace(table, x, x_next); 00994 if (size == 0) 00995 goto zddSwapAnyOutOfMem; 00996 move = (Move *)cuddDynamicAllocNode(table); 00997 if (move == NULL) 00998 goto zddSwapAnyOutOfMem; 00999 move->x = x; 01000 move->y = x_next; 01001 move->size = size; 01002 move->next = moves; 01003 moves = move; 01004 01005 tmp = x; x = y; y = tmp; 01006 } else { 01007 size = cuddZddSwapInPlace(table, x, x_next); 01008 if (size == 0) 01009 goto zddSwapAnyOutOfMem; 01010 move = (Move *)cuddDynamicAllocNode(table); 01011 if (move == NULL) 01012 goto zddSwapAnyOutOfMem; 01013 move->x = x; 01014 move->y = x_next; 01015 move->size = size; 01016 move->next = moves; 01017 moves = move; 01018 01019 size = cuddZddSwapInPlace(table, y_next, y); 01020 if (size == 0) 01021 goto zddSwapAnyOutOfMem; 01022 move = (Move *)cuddDynamicAllocNode(table); 01023 if (move == NULL) 01024 goto zddSwapAnyOutOfMem; 01025 move->x = y_next; 01026 move->y = y; 01027 move->size = size; 01028 move->next = moves; 01029 moves = move; 01030 01031 x = x_next; y = y_next; 01032 } 01033 01034 x_next = cuddZddNextHigh(table, x); 01035 y_next = cuddZddNextLow(table, y); 01036 if (x_next > y_ref) 01037 break; /* if x == y_ref */ 01038 01039 if ((double) size > table->maxGrowth * (double) limit_size) 01040 break; 01041 if (size < limit_size) 01042 limit_size = size; 01043 } 01044 if (y_next >= x_ref) { 01045 size = cuddZddSwapInPlace(table, y_next, y); 01046 if (size == 0) 01047 goto zddSwapAnyOutOfMem; 01048 move = (Move *)cuddDynamicAllocNode(table); 01049 if (move == NULL) 01050 goto zddSwapAnyOutOfMem; 01051 move->x = y_next; 01052 move->y = y; 01053 move->size = size; 01054 move->next = moves; 01055 moves = move; 01056 } 01057 01058 return(moves); 01059 01060 zddSwapAnyOutOfMem: 01061 while (moves != NULL) { 01062 move = moves->next; 01063 cuddDeallocNode(table, (DdNode *)moves); 01064 moves = move; 01065 } 01066 return(NULL); 01067 01068 } /* end of zddSwapAny */
char rcsid [] DD_UNUSED = "$Id: cuddZddReord.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $" [static] |
Definition at line 74 of file cuddZddReord.c.
Definition at line 81 of file cuddZddReord.c.
int* zdd_entry |
Definition at line 77 of file cuddZddReord.c.
Definition at line 79 of file cuddZddReord.c.