src/bdd/cudd/cuddZddReord.c File Reference

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

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 MovezddSwapAny (DdManager *table, int x, int y)
static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high)
static MovecuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size)
static MovecuddZddSiftingDown (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 DdNodeempty

Define Documentation

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


Function Documentation

static void zddFixTree ARGS ( (DdManager *table, MtrNode *treenode)   )  [static]
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 int cuddZddSiftingBackward ARGS ( (DdManager *table, Move *moves, int size  )  [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]
static Move* zddSwapAny ARGS ( (DdManager *table, int x, int y)   )  [static]

AutomaticStart

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:

  • Swapping
  • Sifting
  • Symmetric Sifting

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.

00385 {
00386     return(x + 1);
00387 
00388 } /* end of cuddZddNextHigh */

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.

00407 {
00408     return(x - 1);
00409 
00410 } /* end of cuddZddNextLow */

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.

  1. Order all the variables according to the number of entries in each unique table.
  2. Sift the variable up and down, remembering each time the total size of the DD heap.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

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 */

static int cuddZddSiftingBackward ( DdManager table,
Move moves,
int  size 
) [static]

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 */

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 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 */

static Move* cuddZddSiftingUp ( DdManager table,
int  x,
int  x_low,
int  initial_size 
) [static]

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.

  1. Select two variables (RANDOM or HEURISTIC).
  2. Permute these variables.
  3. If the nodes have decreased accept the permutation.
  4. Otherwise reconstruct the original heap.
  5. Loop.

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.

00431 {
00432     return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
00433 
00434 } /* end of cuddZddUniqueCompare */

static void zddFixTree ( DdManager table,
MtrNode treenode 
) [static]

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 */

static Move* zddSwapAny ( DdManager table,
int  x,
int  y 
) [static]

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 */


Variable Documentation

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.

DdNode* empty [static]

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.


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