#include "util.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 (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) |
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) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio 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 [Copyright (c) 1995-2004, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]
Definition at line 83 of file cuddZddReord.c.
#define DD_SHRINK_FACTOR 2 |
Definition at line 84 of file cuddZddReord.c.
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 167 of file cuddZddReord.c.
00171 { 00172 DdHook *hook; 00173 int result; 00174 unsigned int nextDyn; 00175 #ifdef DD_STATS 00176 unsigned int initialSize; 00177 unsigned int finalSize; 00178 #endif 00179 long localTime; 00180 00181 /* Don't reorder if there are too many dead nodes. */ 00182 if (table->keysZ - table->deadZ < (unsigned) minsize) 00183 return(1); 00184 00185 if (heuristic == CUDD_REORDER_SAME) { 00186 heuristic = table->autoMethodZ; 00187 } 00188 if (heuristic == CUDD_REORDER_NONE) { 00189 return(1); 00190 } 00191 00192 /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore 00193 ** we count it. 00194 */ 00195 table->reorderings++; 00196 empty = table->zero; 00197 00198 localTime = util_cpu_time(); 00199 00200 /* Run the hook functions. */ 00201 hook = table->preReorderingHook; 00202 while (hook != NULL) { 00203 int res = (hook->f)(table, "ZDD", (void *)heuristic); 00204 if (res == 0) return(0); 00205 hook = hook->next; 00206 } 00207 00208 /* Clear the cache and collect garbage. */ 00209 zddReorderPreprocess(table); 00210 zddTotalNumberSwapping = 0; 00211 00212 #ifdef DD_STATS 00213 initialSize = table->keysZ; 00214 00215 switch(heuristic) { 00216 case CUDD_REORDER_RANDOM: 00217 case CUDD_REORDER_RANDOM_PIVOT: 00218 (void) fprintf(table->out,"#:I_RANDOM "); 00219 break; 00220 case CUDD_REORDER_SIFT: 00221 case CUDD_REORDER_SIFT_CONVERGE: 00222 case CUDD_REORDER_SYMM_SIFT: 00223 case CUDD_REORDER_SYMM_SIFT_CONV: 00224 (void) fprintf(table->out,"#:I_SIFTING "); 00225 break; 00226 case CUDD_REORDER_LINEAR: 00227 case CUDD_REORDER_LINEAR_CONVERGE: 00228 (void) fprintf(table->out,"#:I_LINSIFT "); 00229 break; 00230 default: 00231 (void) fprintf(table->err,"Unsupported ZDD reordering method\n"); 00232 return(0); 00233 } 00234 (void) fprintf(table->out,"%8d: initial size",initialSize); 00235 #endif 00236 00237 result = cuddZddTreeSifting(table,heuristic); 00238 00239 #ifdef DD_STATS 00240 (void) fprintf(table->out,"\n"); 00241 finalSize = table->keysZ; 00242 (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); 00243 (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", 00244 ((double)(util_cpu_time() - localTime)/1000.0)); 00245 (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", 00246 zddTotalNumberSwapping); 00247 #endif 00248 00249 if (result == 0) 00250 return(0); 00251 00252 if (!zddReorderPostprocess(table)) 00253 return(0); 00254 00255 if (table->realignZ) { 00256 if (!cuddBddAlignToZdd(table)) 00257 return(0); 00258 } 00259 00260 nextDyn = table->keysZ * DD_DYN_RATIO; 00261 if (table->reorderings < 20 || nextDyn > table->nextDyn) 00262 table->nextDyn = nextDyn; 00263 else 00264 table->nextDyn += 20; 00265 00266 table->reordered = 1; 00267 00268 /* Run hook functions. */ 00269 hook = table->postReorderingHook; 00270 while (hook != NULL) { 00271 int res = (hook->f)(table, "ZDD", (void *)localTime); 00272 if (res == 0) return(0); 00273 hook = hook->next; 00274 } 00275 /* Update cumulative reordering time. */ 00276 table->reordTime += util_cpu_time() - localTime; 00277 00278 return(result); 00279 00280 } /* 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 300 of file cuddZddReord.c.
00303 { 00304 00305 int result; 00306 00307 empty = table->zero; 00308 zddReorderPreprocess(table); 00309 00310 result = zddShuffle(table,permutation); 00311 00312 if (!zddReorderPostprocess(table)) return(0); 00313 00314 return(result); 00315 00316 } /* 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 348 of file cuddZddReord.c.
00350 { 00351 int *invpermZ; /* permutation array */ 00352 int M; /* ratio of ZDD variables to BDD variables */ 00353 int i,j; /* loop indices */ 00354 int result; /* return value */ 00355 00356 /* We assume that a ratio of 0 is OK. */ 00357 if (table->sizeZ == 0) 00358 return(1); 00359 00360 empty = table->zero; 00361 M = table->sizeZ / table->size; 00362 /* Check whether the number of ZDD variables is a multiple of the 00363 ** number of BDD variables. 00364 */ 00365 if (M * table->size != table->sizeZ) 00366 return(0); 00367 /* Create and initialize the inverse permutation array. */ 00368 invpermZ = ALLOC(int,table->sizeZ); 00369 if (invpermZ == NULL) { 00370 table->errorCode = CUDD_MEMORY_OUT; 00371 return(0); 00372 } 00373 for (i = 0; i < table->size; i++) { 00374 int index = table->invperm[i]; 00375 int indexZ = index * M; 00376 int levelZ = table->permZ[indexZ]; 00377 levelZ = (levelZ / M) * M; 00378 for (j = 0; j < M; j++) { 00379 invpermZ[M * i + j] = table->invpermZ[levelZ + j]; 00380 } 00381 } 00382 /* Eliminate dead nodes. Do not scan the cache again, because we 00383 ** assume that Cudd_ReduceHeap has already cleared it. 00384 */ 00385 cuddGarbageCollect(table,0); 00386 00387 result = zddShuffle(table, invpermZ); 00388 FREE(invpermZ); 00389 /* Fix the ZDD variable group tree. */ 00390 zddFixTree(table,table->treeZ); 00391 return(result); 00392 00393 } /* 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 409 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 431 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 863 of file cuddZddReord.c.
00867 { 00868 int i; 00869 int *var; 00870 int size; 00871 int x; 00872 int result; 00873 #ifdef DD_STATS 00874 int previousSize; 00875 #endif 00876 00877 size = table->sizeZ; 00878 00879 /* Find order in which to sift variables. */ 00880 var = NULL; 00881 zdd_entry = ALLOC(int, size); 00882 if (zdd_entry == NULL) { 00883 table->errorCode = CUDD_MEMORY_OUT; 00884 goto cuddZddSiftingOutOfMem; 00885 } 00886 var = ALLOC(int, size); 00887 if (var == NULL) { 00888 table->errorCode = CUDD_MEMORY_OUT; 00889 goto cuddZddSiftingOutOfMem; 00890 } 00891 00892 for (i = 0; i < size; i++) { 00893 x = table->permZ[i]; 00894 zdd_entry[i] = table->subtableZ[x].keys; 00895 var[i] = i; 00896 } 00897 00898 qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); 00899 00900 /* Now sift. */ 00901 for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { 00902 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00903 break; 00904 x = table->permZ[var[i]]; 00905 if (x < lower || x > upper) continue; 00906 #ifdef DD_STATS 00907 previousSize = table->keysZ; 00908 #endif 00909 result = cuddZddSiftingAux(table, x, lower, upper); 00910 if (!result) 00911 goto cuddZddSiftingOutOfMem; 00912 #ifdef DD_STATS 00913 if (table->keysZ < (unsigned) previousSize) { 00914 (void) fprintf(table->out,"-"); 00915 } else if (table->keysZ > (unsigned) previousSize) { 00916 (void) fprintf(table->out,"+"); /* should never happen */ 00917 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); 00918 } else { 00919 (void) fprintf(table->out,"="); 00920 } 00921 fflush(table->out); 00922 #endif 00923 } 00924 00925 FREE(var); 00926 FREE(zdd_entry); 00927 00928 return(1); 00929 00930 cuddZddSiftingOutOfMem: 00931 00932 if (zdd_entry != NULL) FREE(zdd_entry); 00933 if (var != NULL) FREE(var); 00934 00935 return(0); 00936 00937 } /* 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 1113 of file cuddZddReord.c.
01118 { 01119 Move *move; 01120 Move *moveUp; /* list of up move */ 01121 Move *moveDown; /* list of down move */ 01122 01123 int initial_size; 01124 int result; 01125 01126 initial_size = table->keysZ; 01127 01128 #ifdef DD_DEBUG 01129 assert(table->subtableZ[x].keys > 0); 01130 #endif 01131 01132 moveDown = NULL; 01133 moveUp = NULL; 01134 01135 if (x == x_low) { 01136 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); 01137 /* after that point x --> x_high */ 01138 if (moveDown == NULL) 01139 goto cuddZddSiftingAuxOutOfMem; 01140 result = cuddZddSiftingBackward(table, moveDown, 01141 initial_size); 01142 /* move backward and stop at best position */ 01143 if (!result) 01144 goto cuddZddSiftingAuxOutOfMem; 01145 01146 } 01147 else if (x == x_high) { 01148 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); 01149 /* after that point x --> x_low */ 01150 if (moveUp == NULL) 01151 goto cuddZddSiftingAuxOutOfMem; 01152 result = cuddZddSiftingBackward(table, moveUp, initial_size); 01153 /* move backward and stop at best position */ 01154 if (!result) 01155 goto cuddZddSiftingAuxOutOfMem; 01156 } 01157 else if ((x - x_low) > (x_high - x)) { 01158 /* must go down first:shorter */ 01159 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); 01160 /* after that point x --> x_high */ 01161 if (moveDown == NULL) 01162 goto cuddZddSiftingAuxOutOfMem; 01163 moveUp = cuddZddSiftingUp(table, moveDown->y, x_low, 01164 initial_size); 01165 if (moveUp == NULL) 01166 goto cuddZddSiftingAuxOutOfMem; 01167 result = cuddZddSiftingBackward(table, moveUp, initial_size); 01168 /* move backward and stop at best position */ 01169 if (!result) 01170 goto cuddZddSiftingAuxOutOfMem; 01171 } 01172 else { 01173 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); 01174 /* after that point x --> x_high */ 01175 if (moveUp == NULL) 01176 goto cuddZddSiftingAuxOutOfMem; 01177 moveDown = cuddZddSiftingDown(table, moveUp->x, x_high, 01178 initial_size); 01179 /* then move up */ 01180 if (moveDown == NULL) 01181 goto cuddZddSiftingAuxOutOfMem; 01182 result = cuddZddSiftingBackward(table, moveDown, 01183 initial_size); 01184 /* move backward and stop at best position */ 01185 if (!result) 01186 goto cuddZddSiftingAuxOutOfMem; 01187 } 01188 01189 while (moveDown != NULL) { 01190 move = moveDown->next; 01191 cuddDeallocMove(table, moveDown); 01192 moveDown = move; 01193 } 01194 while (moveUp != NULL) { 01195 move = moveUp->next; 01196 cuddDeallocMove(table, moveUp); 01197 moveUp = move; 01198 } 01199 01200 return(1); 01201 01202 cuddZddSiftingAuxOutOfMem: 01203 while (moveDown != NULL) { 01204 move = moveDown->next; 01205 cuddDeallocMove(table, moveDown); 01206 moveDown = move; 01207 } 01208 while (moveUp != NULL) { 01209 move = moveUp->next; 01210 cuddDeallocMove(table, moveUp); 01211 moveUp = move; 01212 } 01213 01214 return(0); 01215 01216 } /* 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 1360 of file cuddZddReord.c.
01364 { 01365 int i; 01366 int i_best; 01367 Move *move; 01368 int res; 01369 01370 /* Find the minimum size among moves. */ 01371 i_best = -1; 01372 for (move = moves, i = 0; move != NULL; move = move->next, i++) { 01373 if (move->size < size) { 01374 i_best = i; 01375 size = move->size; 01376 } 01377 } 01378 01379 for (move = moves, i = 0; move != NULL; move = move->next, i++) { 01380 if (i == i_best) 01381 break; 01382 res = cuddZddSwapInPlace(table, move->x, move->y); 01383 if (!res) 01384 return(0); 01385 if (i_best == -1 && res == size) 01386 break; 01387 } 01388 01389 return(1); 01390 01391 } /* end of cuddZddSiftingBackward */
static Move * cuddZddSiftingDown | ( | DdManager * | table, | |
int | x, | |||
int | x_high, | |||
int | initial_size | |||
) | [static] |
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 1296 of file cuddZddReord.c.
01301 { 01302 Move *moves; 01303 Move *move; 01304 int y; 01305 int size; 01306 int limit_size = initial_size; 01307 01308 moves = NULL; 01309 y = cuddZddNextHigh(table, x); 01310 while (y <= x_high) { 01311 size = cuddZddSwapInPlace(table, x, y); 01312 if (size == 0) 01313 goto cuddZddSiftingDownOutOfMem; 01314 move = (Move *)cuddDynamicAllocNode(table); 01315 if (move == NULL) 01316 goto cuddZddSiftingDownOutOfMem; 01317 move->x = x; 01318 move->y = y; 01319 move->size = size; 01320 move->next = moves; 01321 moves = move; 01322 01323 if ((double)size > (double)limit_size * table->maxGrowth) 01324 break; 01325 if (size < limit_size) 01326 limit_size = size; 01327 01328 x = y; 01329 y = cuddZddNextHigh(table, x); 01330 } 01331 return(moves); 01332 01333 cuddZddSiftingDownOutOfMem: 01334 while (moves != NULL) { 01335 move = moves->next; 01336 cuddDeallocMove(table, moves); 01337 moves = move; 01338 } 01339 return(NULL); 01340 01341 } /* 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 1233 of file cuddZddReord.c.
01238 { 01239 Move *moves; 01240 Move *move; 01241 int y; 01242 int size; 01243 int limit_size = initial_size; 01244 01245 moves = NULL; 01246 y = cuddZddNextLow(table, x); 01247 while (y >= x_low) { 01248 size = cuddZddSwapInPlace(table, y, x); 01249 if (size == 0) 01250 goto cuddZddSiftingUpOutOfMem; 01251 move = (Move *)cuddDynamicAllocNode(table); 01252 if (move == NULL) 01253 goto cuddZddSiftingUpOutOfMem; 01254 move->x = y; 01255 move->y = x; 01256 move->size = size; 01257 move->next = moves; 01258 moves = move; 01259 01260 if ((double)size > (double)limit_size * table->maxGrowth) 01261 break; 01262 if (size < limit_size) 01263 limit_size = size; 01264 01265 x = y; 01266 y = cuddZddNextLow(table, x); 01267 } 01268 return(moves); 01269 01270 cuddZddSiftingUpOutOfMem: 01271 while (moves != NULL) { 01272 move = moves->next; 01273 cuddDeallocMove(table, moves); 01274 moves = move; 01275 } 01276 return(NULL); 01277 01278 } /* 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 480 of file cuddZddReord.c.
00484 { 00485 DdNodePtr *xlist, *ylist; 00486 int xindex, yindex; 00487 int xslots, yslots; 00488 int xshift, yshift; 00489 int oldxkeys, oldykeys; 00490 int newxkeys, newykeys; 00491 int i; 00492 int posn; 00493 DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; 00494 DdNode *newf1, *newf0, *next; 00495 DdNodePtr g, *lastP, *previousP; 00496 00497 #ifdef DD_DEBUG 00498 assert(x < y); 00499 assert(cuddZddNextHigh(table,x) == y); 00500 assert(table->subtableZ[x].keys != 0); 00501 assert(table->subtableZ[y].keys != 0); 00502 assert(table->subtableZ[x].dead == 0); 00503 assert(table->subtableZ[y].dead == 0); 00504 #endif 00505 00506 zddTotalNumberSwapping++; 00507 00508 /* Get parameters of x subtable. */ 00509 xindex = table->invpermZ[x]; 00510 xlist = table->subtableZ[x].nodelist; 00511 oldxkeys = table->subtableZ[x].keys; 00512 xslots = table->subtableZ[x].slots; 00513 xshift = table->subtableZ[x].shift; 00514 newxkeys = 0; 00515 00516 yindex = table->invpermZ[y]; 00517 ylist = table->subtableZ[y].nodelist; 00518 oldykeys = table->subtableZ[y].keys; 00519 yslots = table->subtableZ[y].slots; 00520 yshift = table->subtableZ[y].shift; 00521 newykeys = oldykeys; 00522 00523 /* The nodes in the x layer that don't depend on y directly 00524 ** will stay there; the others are put in a chain. 00525 ** The chain is handled as a FIFO; g points to the beginning and 00526 ** last points to the end. 00527 */ 00528 00529 g = NULL; 00530 lastP = &g; 00531 for (i = 0; i < xslots; i++) { 00532 previousP = &(xlist[i]); 00533 f = *previousP; 00534 while (f != NULL) { 00535 next = f->next; 00536 f1 = cuddT(f); f0 = cuddE(f); 00537 if ((f1->index != (DdHalfWord) yindex) && 00538 (f0->index != (DdHalfWord) yindex)) { /* stays */ 00539 newxkeys++; 00540 *previousP = f; 00541 previousP = &(f->next); 00542 } else { 00543 f->index = yindex; 00544 *lastP = f; 00545 lastP = &(f->next); 00546 } 00547 f = next; 00548 } /* while there are elements in the collision chain */ 00549 *previousP = NULL; 00550 } /* for each slot of the x subtable */ 00551 *lastP = NULL; 00552 00553 00554 #ifdef DD_COUNT 00555 table->swapSteps += oldxkeys - newxkeys; 00556 #endif 00557 /* Take care of the x nodes that must be re-expressed. 00558 ** They form a linked list pointed by g. Their index has been 00559 ** changed to yindex already. 00560 */ 00561 f = g; 00562 while (f != NULL) { 00563 next = f->next; 00564 /* Find f1, f0, f11, f10, f01, f00. */ 00565 f1 = cuddT(f); 00566 if ((int) f1->index == yindex) { 00567 f11 = cuddT(f1); f10 = cuddE(f1); 00568 } else { 00569 f11 = empty; f10 = f1; 00570 } 00571 f0 = cuddE(f); 00572 if ((int) f0->index == yindex) { 00573 f01 = cuddT(f0); f00 = cuddE(f0); 00574 } else { 00575 f01 = empty; f00 = f0; 00576 } 00577 00578 /* Decrease ref count of f1. */ 00579 cuddSatDec(f1->ref); 00580 /* Create the new T child. */ 00581 if (f11 == empty) { 00582 if (f01 != empty) { 00583 newf1 = f01; 00584 cuddSatInc(newf1->ref); 00585 } 00586 /* else case was already handled when finding nodes 00587 ** with both children below level y 00588 */ 00589 } else { 00590 /* Check xlist for triple (xindex, f11, f01). */ 00591 posn = ddHash(f11, f01, xshift); 00592 /* For each element newf1 in collision list xlist[posn]. */ 00593 newf1 = xlist[posn]; 00594 while (newf1 != NULL) { 00595 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { 00596 cuddSatInc(newf1->ref); 00597 break; /* match */ 00598 } 00599 newf1 = newf1->next; 00600 } /* while newf1 */ 00601 if (newf1 == NULL) { /* no match */ 00602 newf1 = cuddDynamicAllocNode(table); 00603 if (newf1 == NULL) 00604 goto zddSwapOutOfMem; 00605 newf1->index = xindex; newf1->ref = 1; 00606 cuddT(newf1) = f11; 00607 cuddE(newf1) = f01; 00608 /* Insert newf1 in the collision list xlist[pos]; 00609 ** increase the ref counts of f11 and f01 00610 */ 00611 newxkeys++; 00612 newf1->next = xlist[posn]; 00613 xlist[posn] = newf1; 00614 cuddSatInc(f11->ref); 00615 cuddSatInc(f01->ref); 00616 } 00617 } 00618 cuddT(f) = newf1; 00619 00620 /* Do the same for f0. */ 00621 /* Decrease ref count of f0. */ 00622 cuddSatDec(f0->ref); 00623 /* Create the new E child. */ 00624 if (f10 == empty) { 00625 newf0 = f00; 00626 cuddSatInc(newf0->ref); 00627 } else { 00628 /* Check xlist for triple (xindex, f10, f00). */ 00629 posn = ddHash(f10, f00, xshift); 00630 /* For each element newf0 in collision list xlist[posn]. */ 00631 newf0 = xlist[posn]; 00632 while (newf0 != NULL) { 00633 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { 00634 cuddSatInc(newf0->ref); 00635 break; /* match */ 00636 } 00637 newf0 = newf0->next; 00638 } /* while newf0 */ 00639 if (newf0 == NULL) { /* no match */ 00640 newf0 = cuddDynamicAllocNode(table); 00641 if (newf0 == NULL) 00642 goto zddSwapOutOfMem; 00643 newf0->index = xindex; newf0->ref = 1; 00644 cuddT(newf0) = f10; cuddE(newf0) = f00; 00645 /* Insert newf0 in the collision list xlist[posn]; 00646 ** increase the ref counts of f10 and f00. 00647 */ 00648 newxkeys++; 00649 newf0->next = xlist[posn]; 00650 xlist[posn] = newf0; 00651 cuddSatInc(f10->ref); 00652 cuddSatInc(f00->ref); 00653 } 00654 } 00655 cuddE(f) = newf0; 00656 00657 /* Insert the modified f in ylist. 00658 ** The modified f does not already exists in ylist. 00659 ** (Because of the uniqueness of the cofactors.) 00660 */ 00661 posn = ddHash(newf1, newf0, yshift); 00662 newykeys++; 00663 f->next = ylist[posn]; 00664 ylist[posn] = f; 00665 f = next; 00666 } /* while f != NULL */ 00667 00668 /* GC the y layer. */ 00669 00670 /* For each node f in ylist. */ 00671 for (i = 0; i < yslots; i++) { 00672 previousP = &(ylist[i]); 00673 f = *previousP; 00674 while (f != NULL) { 00675 next = f->next; 00676 if (f->ref == 0) { 00677 cuddSatDec(cuddT(f)->ref); 00678 cuddSatDec(cuddE(f)->ref); 00679 cuddDeallocNode(table, f); 00680 newykeys--; 00681 } else { 00682 *previousP = f; 00683 previousP = &(f->next); 00684 } 00685 f = next; 00686 } /* while f */ 00687 *previousP = NULL; 00688 } /* for i */ 00689 00690 /* Set the appropriate fields in table. */ 00691 table->subtableZ[x].nodelist = ylist; 00692 table->subtableZ[x].slots = yslots; 00693 table->subtableZ[x].shift = yshift; 00694 table->subtableZ[x].keys = newykeys; 00695 table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; 00696 00697 table->subtableZ[y].nodelist = xlist; 00698 table->subtableZ[y].slots = xslots; 00699 table->subtableZ[y].shift = xshift; 00700 table->subtableZ[y].keys = newxkeys; 00701 table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; 00702 00703 table->permZ[xindex] = y; table->permZ[yindex] = x; 00704 table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; 00705 00706 table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; 00707 00708 /* Update univ section; univ[x] remains the same. */ 00709 table->univ[y] = cuddT(table->univ[x]); 00710 00711 return (table->keysZ); 00712 00713 zddSwapOutOfMem: 00714 (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); 00715 00716 return (0); 00717 00718 } /* 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 742 of file cuddZddReord.c.
00747 { 00748 int i, j; 00749 int max, keys; 00750 int nvars; 00751 int x, y; 00752 int iterate; 00753 int previousSize; 00754 Move *moves, *move; 00755 int pivot; 00756 int modulo; 00757 int result; 00758 00759 #ifdef DD_DEBUG 00760 /* Sanity check */ 00761 assert(lower >= 0 && upper < table->sizeZ && lower <= upper); 00762 #endif 00763 00764 nvars = upper - lower + 1; 00765 iterate = nvars; 00766 00767 for (i = 0; i < iterate; i++) { 00768 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { 00769 /* Find pivot <= id with maximum keys. */ 00770 for (max = -1, j = lower; j <= upper; j++) { 00771 if ((keys = table->subtableZ[j].keys) > max) { 00772 max = keys; 00773 pivot = j; 00774 } 00775 } 00776 00777 modulo = upper - pivot; 00778 if (modulo == 0) { 00779 y = pivot; /* y = nvars-1 */ 00780 } else { 00781 /* y = random # from {pivot+1 .. nvars-1} */ 00782 y = pivot + 1 + (int) (Cudd_Random() % modulo); 00783 } 00784 00785 modulo = pivot - lower - 1; 00786 if (modulo < 1) { /* if pivot = 1 or 0 */ 00787 x = lower; 00788 } else { 00789 do { /* x = random # from {0 .. pivot-2} */ 00790 x = (int) Cudd_Random() % modulo; 00791 } while (x == y); 00792 /* Is this condition really needed, since x and y 00793 are in regions separated by pivot? */ 00794 } 00795 } else { 00796 x = (int) (Cudd_Random() % nvars) + lower; 00797 do { 00798 y = (int) (Cudd_Random() % nvars) + lower; 00799 } while (x == y); 00800 } 00801 00802 previousSize = table->keysZ; 00803 moves = zddSwapAny(table, x, y); 00804 if (moves == NULL) 00805 goto cuddZddSwappingOutOfMem; 00806 00807 result = cuddZddSiftingBackward(table, moves, previousSize); 00808 if (!result) 00809 goto cuddZddSwappingOutOfMem; 00810 00811 while (moves != NULL) { 00812 move = moves->next; 00813 cuddDeallocMove(table, moves); 00814 moves = move; 00815 } 00816 #ifdef DD_STATS 00817 if (table->keysZ < (unsigned) previousSize) { 00818 (void) fprintf(table->out,"-"); 00819 } else if (table->keysZ > (unsigned) previousSize) { 00820 (void) fprintf(table->out,"+"); /* should never happen */ 00821 } else { 00822 (void) fprintf(table->out,"="); 00823 } 00824 fflush(table->out); 00825 #endif 00826 } 00827 00828 return(1); 00829 00830 cuddZddSwappingOutOfMem: 00831 while (moves != NULL) { 00832 move = moves->next; 00833 cuddDeallocMove(table, moves); 00834 moves = move; 00835 } 00836 return(0); 00837 00838 } /* 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 455 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 1641 of file cuddZddReord.c.
01644 { 01645 if (treenode == NULL) return; 01646 treenode->low = ((int) treenode->index < table->sizeZ) ? 01647 table->permZ[treenode->index] : treenode->index; 01648 if (treenode->child != NULL) { 01649 zddFixTree(table, treenode->child); 01650 } 01651 if (treenode->younger != NULL) 01652 zddFixTree(table, treenode->younger); 01653 if (treenode->parent != NULL && treenode->low < treenode->parent->low) { 01654 treenode->parent->low = treenode->low; 01655 treenode->parent->index = treenode->index; 01656 } 01657 return; 01658 01659 } /* 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 1435 of file cuddZddReord.c.
01437 { 01438 int i, j, posn; 01439 DdNodePtr *nodelist, *oldnodelist; 01440 DdNode *node, *next; 01441 unsigned int slots, oldslots; 01442 extern DD_OOMFP MMoutOfMemory; 01443 DD_OOMFP saveHandler; 01444 01445 #ifdef DD_VERBOSE 01446 (void) fflush(table->out); 01447 #endif 01448 01449 /* If we have very many reclaimed nodes, we do not want to shrink 01450 ** the subtables, because this will lead to more garbage 01451 ** collections. More garbage collections mean shorter mean life for 01452 ** nodes with zero reference count; hence lower probability of finding 01453 ** a result in the cache. 01454 */ 01455 if (table->reclaimed > table->allocated * 0.5) return(1); 01456 01457 /* Resize subtables. */ 01458 for (i = 0; i < table->sizeZ; i++) { 01459 int shift; 01460 oldslots = table->subtableZ[i].slots; 01461 if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY || 01462 oldslots <= table->initSlots) continue; 01463 oldnodelist = table->subtableZ[i].nodelist; 01464 slots = oldslots >> 1; 01465 saveHandler = MMoutOfMemory; 01466 MMoutOfMemory = Cudd_OutOfMem; 01467 nodelist = ALLOC(DdNodePtr, slots); 01468 MMoutOfMemory = saveHandler; 01469 if (nodelist == NULL) { 01470 return(1); 01471 } 01472 table->subtableZ[i].nodelist = nodelist; 01473 table->subtableZ[i].slots = slots; 01474 table->subtableZ[i].shift++; 01475 table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01476 #ifdef DD_VERBOSE 01477 (void) fprintf(table->err, 01478 "shrunk layer %d (%d keys) from %d to %d slots\n", 01479 i, table->subtableZ[i].keys, oldslots, slots); 01480 #endif 01481 01482 for (j = 0; (unsigned) j < slots; j++) { 01483 nodelist[j] = NULL; 01484 } 01485 shift = table->subtableZ[i].shift; 01486 for (j = 0; (unsigned) j < oldslots; j++) { 01487 node = oldnodelist[j]; 01488 while (node != NULL) { 01489 next = node->next; 01490 posn = ddHash(cuddT(node), cuddE(node), shift); 01491 node->next = nodelist[posn]; 01492 nodelist[posn] = node; 01493 node = next; 01494 } 01495 } 01496 FREE(oldnodelist); 01497 01498 table->memused += (slots - oldslots) * sizeof(DdNode *); 01499 table->slots += slots - oldslots; 01500 table->minDead = (unsigned) (table->gcFrac * (double) table->slots); 01501 table->cacheSlack = (int) ddMin(table->maxCacheHard, 01502 DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) - 01503 2 * (int) table->cacheSlots; 01504 } 01505 /* We don't look at the constant subtable, because it is not 01506 ** affected by reordering. 01507 */ 01508 01509 return(1); 01510 01511 } /* 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 1406 of file cuddZddReord.c.
01408 { 01409 01410 /* Clear the cache. */ 01411 cuddCacheFlush(table); 01412 01413 /* Eliminate dead nodes. Do not scan the cache again. */ 01414 cuddGarbageCollect(table,0); 01415 01416 return; 01417 01418 } /* 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 1530 of file cuddZddReord.c.
01533 { 01534 int index; 01535 int level; 01536 int position; 01537 int numvars; 01538 int result; 01539 #ifdef DD_STATS 01540 long localTime; 01541 int initialSize; 01542 int finalSize; 01543 int previousSize; 01544 #endif 01545 01546 zddTotalNumberSwapping = 0; 01547 #ifdef DD_STATS 01548 localTime = util_cpu_time(); 01549 initialSize = table->keysZ; 01550 (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", 01551 initialSize); 01552 #endif 01553 01554 numvars = table->sizeZ; 01555 01556 for (level = 0; level < numvars; level++) { 01557 index = permutation[level]; 01558 position = table->permZ[index]; 01559 #ifdef DD_STATS 01560 previousSize = table->keysZ; 01561 #endif 01562 result = zddSiftUp(table,position,level); 01563 if (!result) return(0); 01564 #ifdef DD_STATS 01565 if (table->keysZ < (unsigned) previousSize) { 01566 (void) fprintf(table->out,"-"); 01567 } else if (table->keysZ > (unsigned) previousSize) { 01568 (void) fprintf(table->out,"+"); /* should never happen */ 01569 } else { 01570 (void) fprintf(table->out,"="); 01571 } 01572 fflush(table->out); 01573 #endif 01574 } 01575 01576 #ifdef DD_STATS 01577 (void) fprintf(table->out,"\n"); 01578 finalSize = table->keysZ; 01579 (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); 01580 (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", 01581 ((double)(util_cpu_time() - localTime)/1000.0)); 01582 (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", 01583 zddTotalNumberSwapping); 01584 #endif 01585 01586 return(1); 01587 01588 } /* 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 1605 of file cuddZddReord.c.
01609 { 01610 int y; 01611 int size; 01612 01613 y = cuddZddNextLow(table,x); 01614 while (y >= xLow) { 01615 size = cuddZddSwapInPlace(table,y,x); 01616 if (size == 0) { 01617 return(0); 01618 } 01619 x = y; 01620 y = cuddZddNextLow(table,x); 01621 } 01622 return(1); 01623 01624 } /* end of zddSiftUp */
AutomaticStart
Function********************************************************************
Synopsis [Swaps any two variables.]
Description [Swaps any two variables. Returns the set of moves.]
SideEffects [None]
SeeAlso []
Definition at line 957 of file cuddZddReord.c.
00961 { 00962 Move *move, *moves; 00963 int tmp, size; 00964 int x_ref, y_ref; 00965 int x_next, y_next; 00966 int limit_size; 00967 00968 if (x > y) { /* make x precede y */ 00969 tmp = x; x = y; y = tmp; 00970 } 00971 00972 x_ref = x; y_ref = y; 00973 00974 x_next = cuddZddNextHigh(table, x); 00975 y_next = cuddZddNextLow(table, y); 00976 moves = NULL; 00977 limit_size = table->keysZ; 00978 00979 for (;;) { 00980 if (x_next == y_next) { /* x < x_next = y_next < y */ 00981 size = cuddZddSwapInPlace(table, x, x_next); 00982 if (size == 0) 00983 goto zddSwapAnyOutOfMem; 00984 move = (Move *) cuddDynamicAllocNode(table); 00985 if (move == NULL) 00986 goto zddSwapAnyOutOfMem; 00987 move->x = x; 00988 move->y = x_next; 00989 move->size = size; 00990 move->next = moves; 00991 moves = move; 00992 00993 size = cuddZddSwapInPlace(table, y_next, y); 00994 if (size == 0) 00995 goto zddSwapAnyOutOfMem; 00996 move = (Move *)cuddDynamicAllocNode(table); 00997 if (move == NULL) 00998 goto zddSwapAnyOutOfMem; 00999 move->x = y_next; 01000 move->y = y; 01001 move->size = size; 01002 move->next = moves; 01003 moves = move; 01004 01005 size = cuddZddSwapInPlace(table, x, x_next); 01006 if (size == 0) 01007 goto zddSwapAnyOutOfMem; 01008 move = (Move *)cuddDynamicAllocNode(table); 01009 if (move == NULL) 01010 goto zddSwapAnyOutOfMem; 01011 move->x = x; 01012 move->y = x_next; 01013 move->size = size; 01014 move->next = moves; 01015 moves = move; 01016 01017 tmp = x; x = y; y = tmp; 01018 01019 } else if (x == y_next) { /* x = y_next < y = x_next */ 01020 size = cuddZddSwapInPlace(table, x, x_next); 01021 if (size == 0) 01022 goto zddSwapAnyOutOfMem; 01023 move = (Move *)cuddDynamicAllocNode(table); 01024 if (move == NULL) 01025 goto zddSwapAnyOutOfMem; 01026 move->x = x; 01027 move->y = x_next; 01028 move->size = size; 01029 move->next = moves; 01030 moves = move; 01031 01032 tmp = x; x = y; y = tmp; 01033 } else { 01034 size = cuddZddSwapInPlace(table, x, x_next); 01035 if (size == 0) 01036 goto zddSwapAnyOutOfMem; 01037 move = (Move *)cuddDynamicAllocNode(table); 01038 if (move == NULL) 01039 goto zddSwapAnyOutOfMem; 01040 move->x = x; 01041 move->y = x_next; 01042 move->size = size; 01043 move->next = moves; 01044 moves = move; 01045 01046 size = cuddZddSwapInPlace(table, y_next, y); 01047 if (size == 0) 01048 goto zddSwapAnyOutOfMem; 01049 move = (Move *)cuddDynamicAllocNode(table); 01050 if (move == NULL) 01051 goto zddSwapAnyOutOfMem; 01052 move->x = y_next; 01053 move->y = y; 01054 move->size = size; 01055 move->next = moves; 01056 moves = move; 01057 01058 x = x_next; y = y_next; 01059 } 01060 01061 x_next = cuddZddNextHigh(table, x); 01062 y_next = cuddZddNextLow(table, y); 01063 if (x_next > y_ref) 01064 break; /* if x == y_ref */ 01065 01066 if ((double) size > table->maxGrowth * (double) limit_size) 01067 break; 01068 if (size < limit_size) 01069 limit_size = size; 01070 } 01071 if (y_next >= x_ref) { 01072 size = cuddZddSwapInPlace(table, y_next, y); 01073 if (size == 0) 01074 goto zddSwapAnyOutOfMem; 01075 move = (Move *)cuddDynamicAllocNode(table); 01076 if (move == NULL) 01077 goto zddSwapAnyOutOfMem; 01078 move->x = y_next; 01079 move->y = y; 01080 move->size = size; 01081 move->next = moves; 01082 moves = move; 01083 } 01084 01085 return(moves); 01086 01087 zddSwapAnyOutOfMem: 01088 while (moves != NULL) { 01089 move = moves->next; 01090 cuddDeallocMove(table, moves); 01091 moves = move; 01092 } 01093 return(NULL); 01094 01095 } /* end of zddSwapAny */
char rcsid [] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $" [static] |
Definition at line 101 of file cuddZddReord.c.
Definition at line 108 of file cuddZddReord.c.
int* zdd_entry |
Definition at line 104 of file cuddZddReord.c.
Definition at line 106 of file cuddZddReord.c.