src/cuBdd/cuddZddReord.c File Reference

#include "util.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 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)
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 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 [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.


Function Documentation

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

00412 {
00413     return(x + 1);
00414 
00415 } /* 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 431 of file cuddZddReord.c.

00434 {
00435     return(x - 1);
00436 
00437 } /* 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 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 */

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

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

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

00458 {
00459     return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
00460 
00461 } /* 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 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 */

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

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


Variable Documentation

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.

DdNode* empty [static]

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.


Generated on Tue Jan 12 13:57:22 2010 for glu-2.2 by  doxygen 1.6.1