src/bdd/cudd/cuddZddSymm.c File Reference

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

Go to the source code of this file.

Defines

#define ZDD_MV_OOM   (Move *)1

Functions

static int cuddZddSymmSiftingAux ARGS ((DdManager *table, int x, int x_low, int x_high))
static Move *cuddZddSymmSifting_up ARGS ((DdManager *table, int x, int x_low, int initial_size))
static Move
*cuddZddSymmSifting_down 
ARGS ((DdManager *table, int x, int x_high, int initial_size))
static int
cuddZddSymmSiftingBackward 
ARGS ((DdManager *table, Move *moves, int size))
static int zdd_group_move ARGS ((DdManager *table, int x, int y, Move **moves))
static int zdd_group_move_backward ARGS ((DdManager *table, int x, int y))
static void cuddZddSymmSummary ARGS ((DdManager *table, int lower, int upper, int *symvars, int *symgroups))
void Cudd_zddSymmProfile (DdManager *table, int lower, int upper)
int cuddZddSymmCheck (DdManager *table, int x, int y)
int cuddZddSymmSifting (DdManager *table, int lower, int upper)
int cuddZddSymmSiftingConv (DdManager *table, int lower, int upper)
static int cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high)
static int cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high)
static MovecuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size)
static MovecuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size)
static int cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size)
static int zdd_group_move (DdManager *table, int x, int y, Move **moves)
static int zdd_group_move_backward (DdManager *table, int x, int y)
static void cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"
int * zdd_entry
int zddTotalNumberSwapping
static DdNodeempty

Define Documentation

#define ZDD_MV_OOM   (Move *)1

CFile***********************************************************************

FileName [cuddZddSymm.c]

PackageName [cudd]

Synopsis [Functions for symmetry-based ZDD variable reordering.]

Description [External procedures included in this module:

Internal procedures included in this module:

Static procedures included in this module:

]

SeeAlso [cuddSymmetry.c]

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 50 of file cuddZddSymm.c.


Function Documentation

static void cuddZddSymmSummary ARGS ( (DdManager *table, int lower, int upper, int *symvars, int *symgroups)   )  [static]
static int zdd_group_move_backward ARGS ( (DdManager *table, int x, int y)   )  [static]
static int zdd_group_move ARGS ( (DdManager *table, int x, int y, Move **moves)   )  [static]
static int cuddZddSymmSiftingBackward ARGS ( (DdManager *table, Move *moves, int size  )  [static]
static Move* cuddZddSymmSifting_down ARGS ( (DdManager *table, int x, int x_high, int initial_size)   )  [static]
static Move* cuddZddSymmSifting_up ARGS ( (DdManager *table, int x, int x_low, int initial_size)   )  [static]
static int cuddZddSymmSiftingConvAux ARGS ( (DdManager *table, int x, int x_low, int x_high)   )  [static]

AutomaticStart

void Cudd_zddSymmProfile ( DdManager table,
int  lower,
int  upper 
)

AutomaticEnd Function********************************************************************

Synopsis [Prints statistics on symmetric ZDD variables.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 114 of file cuddZddSymm.c.

00118 {
00119     int         i, x, gbot;
00120     int         TotalSymm = 0;
00121     int         TotalSymmGroups = 0;
00122     int         nvars;
00123 
00124     nvars = table->sizeZ;
00125 
00126     for (i = lower; i < upper; i++) {
00127         if (table->subtableZ[i].next != (unsigned) i) {
00128             x = i;
00129             (void) fprintf(table->out,"Group:");
00130             do {
00131                 (void) fprintf(table->out,"  %d", table->invpermZ[x]);
00132                 TotalSymm++;
00133                 gbot = x;
00134                 x = table->subtableZ[x].next;
00135             } while (x != i);
00136             TotalSymmGroups++;
00137 #ifdef DD_DEBUG
00138             assert(table->subtableZ[gbot].next == (unsigned) i);
00139 #endif
00140             i = gbot;
00141             (void) fprintf(table->out,"\n");
00142         }
00143     }
00144     (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm);
00145     (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups);
00146 
00147 } /* end of Cudd_zddSymmProfile */

int cuddZddSymmCheck ( DdManager table,
int  x,
int  y 
)

Function********************************************************************

Synopsis [Checks for symmetry of x and y.]

Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 169 of file cuddZddSymm.c.

00173 {
00174     int         i;
00175     DdNode      *f, *f0, *f1, *f01, *f00, *f11, *f10;
00176     int         yindex;
00177     int         xsymmy = 1;
00178     int         xsymmyp = 1;
00179     int         arccount = 0;
00180     int         TotalRefCount = 0;
00181     int         symm_found;
00182 
00183     empty = table->zero;
00184 
00185     yindex = table->invpermZ[y];
00186     for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
00187         f = table->subtableZ[x].nodelist[i];
00188         while (f != NULL) {
00189             /* Find f1, f0, f11, f10, f01, f00 */
00190             f1 = cuddT(f);
00191             f0 = cuddE(f);
00192             if ((int) f1->index == yindex) {
00193                 f11 = cuddT(f1);
00194                 f10 = cuddE(f1);
00195                 if (f10 != empty)
00196                     arccount++;
00197             } else {
00198                 if ((int) f0->index != yindex) {
00199                     return(0); /* f bypasses layer y */
00200                 }
00201                 f11 = empty;
00202                 f10 = f1;
00203             }
00204             if ((int) f0->index == yindex) {
00205                 f01 = cuddT(f0);
00206                 f00 = cuddE(f0);
00207                 if (f00 != empty)
00208                     arccount++;
00209             } else {
00210                 f01 = empty;
00211                 f00 = f0;
00212             }
00213             if (f01 != f10)
00214                 xsymmy = 0;
00215             if (f11 != f00)
00216                 xsymmyp = 0;
00217             if ((xsymmy == 0) && (xsymmyp == 0))
00218                 return(0);
00219 
00220             f = f->next;
00221         } /* for each element of the collision list */
00222     } /* for each slot of the subtable */
00223 
00224     /* Calculate the total reference counts of y
00225     ** whose else arc is not empty.
00226     */
00227     for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
00228         f = table->subtableZ[y].nodelist[i];
00229         while (f != NIL(DdNode)) {
00230             if (cuddE(f) != empty)
00231                 TotalRefCount += f->ref;
00232             f = f->next;
00233         }
00234     }
00235 
00236     symm_found = (arccount == TotalRefCount);
00237 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00238     if (symm_found) {
00239         int xindex = table->invpermZ[x];
00240         (void) fprintf(table->out,
00241                        "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00242                        xindex,yindex,x,y);
00243     }
00244 #endif
00245 
00246     return(symm_found);
00247 
00248 } /* end cuddZddSymmCheck */

int cuddZddSymmSifting ( DdManager table,
int  lower,
int  upper 
)

Function********************************************************************

Synopsis [Symmetric sifting algorithm for ZDDs.]

Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.

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

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddSymmSiftingConv]

Definition at line 274 of file cuddZddSymm.c.

00278 {
00279     int         i;
00280     int         *var;
00281     int         nvars;
00282     int         x;
00283     int         result;
00284     int         symvars;
00285     int         symgroups;
00286     int         iteration;
00287 #ifdef DD_STATS
00288     int         previousSize;
00289 #endif
00290 
00291     nvars = table->sizeZ;
00292 
00293     /* Find order in which to sift variables. */
00294     var = NULL;
00295     zdd_entry = ALLOC(int, nvars);
00296     if (zdd_entry == NULL) {
00297         table->errorCode = CUDD_MEMORY_OUT;
00298         goto cuddZddSymmSiftingOutOfMem;
00299     }
00300     var = ALLOC(int, nvars);
00301     if (var == NULL) {
00302         table->errorCode = CUDD_MEMORY_OUT;
00303         goto cuddZddSymmSiftingOutOfMem;
00304     }
00305 
00306     for (i = 0; i < nvars; i++) {
00307         x = table->permZ[i];
00308         zdd_entry[i] = table->subtableZ[x].keys;
00309         var[i] = i;
00310     }
00311 
00312     qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare);
00313 
00314     /* Initialize the symmetry of each subtable to itself. */
00315     for (i = lower; i <= upper; i++)
00316         table->subtableZ[i].next = i;
00317 
00318     iteration = ddMin(table->siftMaxVar, nvars);
00319     for (i = 0; i < iteration; i++) {
00320         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00321             break;
00322         x = table->permZ[var[i]];
00323 #ifdef DD_STATS
00324         previousSize = table->keysZ;
00325 #endif
00326         if (x < lower || x > upper) continue;
00327         if (table->subtableZ[x].next == (unsigned) x) {
00328             result = cuddZddSymmSiftingAux(table, x, lower, upper);
00329             if (!result)
00330                 goto cuddZddSymmSiftingOutOfMem;
00331 #ifdef DD_STATS
00332             if (table->keysZ < (unsigned) previousSize) {
00333                 (void) fprintf(table->out,"-");
00334             } else if (table->keysZ > (unsigned) previousSize) {
00335                 (void) fprintf(table->out,"+");
00336 #ifdef DD_VERBOSE
00337                 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00338 #endif
00339             } else {
00340                 (void) fprintf(table->out,"=");
00341             }
00342             fflush(table->out);
00343 #endif
00344         }
00345     }
00346 
00347     FREE(var);
00348     FREE(zdd_entry);
00349 
00350     cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00351 
00352 #ifdef DD_STATS
00353     (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
00354     (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
00355 #endif
00356 
00357     return(1+symvars);
00358 
00359 cuddZddSymmSiftingOutOfMem:
00360 
00361     if (zdd_entry != NULL)
00362         FREE(zdd_entry);
00363     if (var != NULL)
00364         FREE(var);
00365 
00366     return(0);
00367 
00368 } /* end of cuddZddSymmSifting */

static Move* cuddZddSymmSifting_down ( DdManager table,
int  x,
int  x_high,
int  initial_size 
) [static]

Function********************************************************************

Synopsis [Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much.]

Description [Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much. Assumes that x is the bottom of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; ZDD_MV_OOM if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 1310 of file cuddZddSymm.c.

01315 {
01316     Move        *moves;
01317     Move        *move;
01318     int         y;
01319     int         size;
01320     int         limit_size = initial_size;
01321     int         i, gxtop, gybot;
01322 
01323     moves = NULL;
01324     y = cuddZddNextHigh(table, x);
01325     while (y <= x_high) {
01326         gybot = table->subtableZ[y].next;
01327         while (table->subtableZ[gybot].next != (unsigned) y)
01328             gybot = table->subtableZ[gybot].next;
01329         if (cuddZddSymmCheck(table, x, y)) {
01330             /* Symmetry found, attach symm groups */
01331             gxtop = table->subtableZ[x].next;
01332             table->subtableZ[x].next = y;
01333             i = table->subtableZ[y].next;
01334             while (table->subtableZ[i].next != (unsigned) y)
01335                 i = table->subtableZ[i].next;
01336             table->subtableZ[i].next = gxtop;
01337         }
01338         else if ((table->subtableZ[x].next == (unsigned) x) &&
01339             (table->subtableZ[y].next == (unsigned) y)) {
01340             /* x and y have self symmetry */
01341             size = cuddZddSwapInPlace(table, x, y);
01342             if (size == 0)
01343                 goto cuddZddSymmSifting_downOutOfMem;
01344             move = (Move *)cuddDynamicAllocNode(table);
01345             if (move == NULL)
01346                 goto cuddZddSymmSifting_downOutOfMem;
01347             move->x = x;
01348             move->y = y;
01349             move->size = size;
01350             move->next = moves;
01351             moves = move;
01352             if ((double)size >
01353                 (double)limit_size * table->maxGrowth)
01354                 return(moves);
01355             if (size < limit_size)
01356                 limit_size = size;
01357             x = y;
01358             y = cuddZddNextHigh(table, x);
01359         }
01360         else { /* Group move */
01361             size = zdd_group_move(table, x, y, &moves);
01362             if ((double)size >
01363                 (double)limit_size * table->maxGrowth)
01364                 return(moves);
01365             if (size < limit_size)
01366                 limit_size = size;
01367         }
01368         x = gybot;
01369         y = cuddZddNextHigh(table, x);
01370     }
01371 
01372     return(moves);
01373 
01374 cuddZddSymmSifting_downOutOfMem:
01375     while (moves != NULL) {
01376         move = moves->next;
01377         cuddDeallocNode(table, (DdNode *)moves);
01378         moves = move;
01379     }
01380     return(ZDD_MV_OOM);
01381 
01382 } /* end of cuddZddSymmSifting_down */

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

Function********************************************************************

Synopsis [Moves x up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much.]

Description [Moves x up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much. Assumes that x is the top of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; ZDD_MV_OOM if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 1222 of file cuddZddSymm.c.

01227 {
01228     Move        *moves;
01229     Move        *move;
01230     int         y;
01231     int         size;
01232     int         limit_size = initial_size;
01233     int         i, gytop;
01234 
01235     moves = NULL;
01236     y = cuddZddNextLow(table, x);
01237     while (y >= x_low) {
01238         gytop = table->subtableZ[y].next;
01239         if (cuddZddSymmCheck(table, y, x)) {
01240             /* Symmetry found, attach symm groups */
01241             table->subtableZ[y].next = x;
01242             i = table->subtableZ[x].next;
01243             while (table->subtableZ[i].next != (unsigned) x)
01244                 i = table->subtableZ[i].next;
01245             table->subtableZ[i].next = gytop;
01246         }
01247         else if ((table->subtableZ[x].next == (unsigned) x) &&
01248             (table->subtableZ[y].next == (unsigned) y)) {
01249             /* x and y have self symmetry */
01250             size = cuddZddSwapInPlace(table, y, x);
01251             if (size == 0)
01252                 goto cuddZddSymmSifting_upOutOfMem;
01253             move = (Move *)cuddDynamicAllocNode(table);
01254             if (move == NULL)
01255                 goto cuddZddSymmSifting_upOutOfMem;
01256             move->x = y;
01257             move->y = x;
01258             move->size = size;
01259             move->next = moves;
01260             moves = move;
01261             if ((double)size >
01262                 (double)limit_size * table->maxGrowth)
01263                 return(moves);
01264             if (size < limit_size)
01265                 limit_size = size;
01266         }
01267         else { /* Group move */
01268             size = zdd_group_move(table, y, x, &moves);
01269             if ((double)size >
01270                 (double)limit_size * table->maxGrowth)
01271                 return(moves);
01272             if (size < limit_size)
01273                 limit_size = size;
01274         }
01275         x = gytop;
01276         y = cuddZddNextLow(table, x);
01277     }
01278 
01279     return(moves);
01280 
01281 cuddZddSymmSifting_upOutOfMem:
01282     while (moves != NULL) {
01283         move = moves->next;
01284         cuddDeallocNode(table, (DdNode *)moves);
01285         moves = move;
01286     }
01287     return(ZDD_MV_OOM);
01288 
01289 } /* end of cuddZddSymmSifting_up */

static int cuddZddSymmSiftingAux ( DdManager table,
int  x,
int  x_low,
int  x_high 
) [static]

Function********************************************************************

Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.]

Description [Given x_low <= x <= x_high moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is not part of a symmetry group. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 573 of file cuddZddSymm.c.

00578 {
00579     Move *move;
00580     Move *move_up;      /* list of up move */
00581     Move *move_down;    /* list of down move */
00582     int  initial_size;
00583     int  result;
00584     int  i;
00585     int  topbot;        /* index to either top or bottom of symmetry group */
00586     int  init_group_size, final_group_size;
00587 
00588     initial_size = table->keysZ;
00589 
00590     move_down = NULL;
00591     move_up = NULL;
00592 
00593     /* Look for consecutive symmetries above x. */
00594     for (i = x; i > x_low; i--) {
00595         if (!cuddZddSymmCheck(table, i - 1, i))
00596             break;
00597         /* find top of i-1's symmetry */
00598         topbot = table->subtableZ[i - 1].next;
00599         table->subtableZ[i - 1].next = i;
00600         table->subtableZ[x].next = topbot;
00601         /* x is bottom of group so its symmetry is top of i-1's
00602            group */
00603         i = topbot + 1; /* add 1 for i--, new i is top of symm group */
00604     }
00605     /* Look for consecutive symmetries below x. */
00606     for (i = x; i < x_high; i++) {
00607         if (!cuddZddSymmCheck(table, i, i + 1))
00608             break;
00609         /* find bottom of i+1's symm group */
00610         topbot = i + 1;
00611         while ((unsigned) topbot < table->subtableZ[topbot].next)
00612             topbot = table->subtableZ[topbot].next;
00613 
00614         table->subtableZ[topbot].next = table->subtableZ[i].next;
00615         table->subtableZ[i].next = i + 1;
00616         i = topbot - 1; /* add 1 for i++,
00617                            new i is bottom of symm group */
00618     }
00619 
00620     /* Now x maybe in the middle of a symmetry group. */
00621     if (x == x_low) { /* Sift down */
00622         /* Find bottom of x's symm group */
00623         while ((unsigned) x < table->subtableZ[x].next)
00624             x = table->subtableZ[x].next;
00625 
00626         i = table->subtableZ[x].next;
00627         init_group_size = x - i + 1;
00628 
00629         move_down = cuddZddSymmSifting_down(table, x, x_high,
00630             initial_size);
00631         /* after that point x --> x_high, unless early term */
00632         if (move_down == ZDD_MV_OOM)
00633             goto cuddZddSymmSiftingAuxOutOfMem;
00634 
00635         if (move_down == NULL ||
00636             table->subtableZ[move_down->y].next != move_down->y) {
00637             /* symmetry detected may have to make another complete
00638                pass */
00639             if (move_down != NULL)
00640                 x = move_down->y;
00641             else
00642                 x = table->subtableZ[x].next;
00643             i = x;
00644             while ((unsigned) i < table->subtableZ[i].next) {
00645                 i = table->subtableZ[i].next;
00646             }
00647             final_group_size = i - x + 1;
00648 
00649             if (init_group_size == final_group_size) {
00650                 /* No new symmetry groups detected,
00651                    return to best position */
00652                 result = cuddZddSymmSiftingBackward(table,
00653                     move_down, initial_size);
00654             }
00655             else {
00656                 initial_size = table->keysZ;
00657                 move_up = cuddZddSymmSifting_up(table, x, x_low,
00658                     initial_size);
00659                 result = cuddZddSymmSiftingBackward(table, move_up,
00660                     initial_size);
00661             }
00662         }
00663         else {
00664             result = cuddZddSymmSiftingBackward(table, move_down,
00665                 initial_size);
00666             /* move backward and stop at best position */
00667         }
00668         if (!result)
00669             goto cuddZddSymmSiftingAuxOutOfMem;
00670     }
00671     else if (x == x_high) { /* Sift up */
00672         /* Find top of x's symm group */
00673         while ((unsigned) x < table->subtableZ[x].next)
00674             x = table->subtableZ[x].next;
00675         x = table->subtableZ[x].next;
00676 
00677         i = x;
00678         while ((unsigned) i < table->subtableZ[i].next) {
00679             i = table->subtableZ[i].next;
00680         }
00681         init_group_size = i - x + 1;
00682 
00683         move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00684         /* after that point x --> x_low, unless early term */
00685         if (move_up == ZDD_MV_OOM)
00686             goto cuddZddSymmSiftingAuxOutOfMem;
00687 
00688         if (move_up == NULL ||
00689             table->subtableZ[move_up->x].next != move_up->x) {
00690             /* symmetry detected may have to make another complete
00691                 pass */
00692             if (move_up != NULL)
00693                 x = move_up->x;
00694             else {
00695                 while ((unsigned) x < table->subtableZ[x].next)
00696                     x = table->subtableZ[x].next;
00697             }
00698             i = table->subtableZ[x].next;
00699             final_group_size = x - i + 1;
00700 
00701             if (init_group_size == final_group_size) {
00702                 /* No new symmetry groups detected,
00703                    return to best position */
00704                 result = cuddZddSymmSiftingBackward(table, move_up,
00705                     initial_size);
00706             }
00707             else {
00708                 initial_size = table->keysZ;
00709                 move_down = cuddZddSymmSifting_down(table, x, x_high,
00710                     initial_size);
00711                 result = cuddZddSymmSiftingBackward(table, move_down,
00712                     initial_size);
00713             }
00714         }
00715         else {
00716             result = cuddZddSymmSiftingBackward(table, move_up,
00717                 initial_size);
00718             /* move backward and stop at best position */
00719         }
00720         if (!result)
00721             goto cuddZddSymmSiftingAuxOutOfMem;
00722     }
00723     else if ((x - x_low) > (x_high - x)) { /* must go down first:
00724                                                 shorter */
00725         /* Find bottom of x's symm group */
00726         while ((unsigned) x < table->subtableZ[x].next)
00727             x = table->subtableZ[x].next;
00728 
00729         move_down = cuddZddSymmSifting_down(table, x, x_high,
00730             initial_size);
00731         /* after that point x --> x_high, unless early term */
00732         if (move_down == ZDD_MV_OOM)
00733             goto cuddZddSymmSiftingAuxOutOfMem;
00734 
00735         if (move_down != NULL) {
00736             x = move_down->y;
00737         }
00738         else {
00739             x = table->subtableZ[x].next;
00740         }
00741         i = x;
00742         while ((unsigned) i < table->subtableZ[i].next) {
00743             i = table->subtableZ[i].next;
00744         }
00745         init_group_size = i - x + 1;
00746 
00747         move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00748         if (move_up == ZDD_MV_OOM)
00749             goto cuddZddSymmSiftingAuxOutOfMem;
00750 
00751         if (move_up == NULL ||
00752             table->subtableZ[move_up->x].next != move_up->x) {
00753             /* symmetry detected may have to make another complete
00754                pass */
00755             if (move_up != NULL) {
00756                 x = move_up->x;
00757             }
00758             else {
00759                 while ((unsigned) x < table->subtableZ[x].next)
00760                     x = table->subtableZ[x].next;
00761             }
00762             i = table->subtableZ[x].next;
00763             final_group_size = x - i + 1;
00764 
00765             if (init_group_size == final_group_size) {
00766                 /* No new symmetry groups detected,
00767                    return to best position */
00768                 result = cuddZddSymmSiftingBackward(table, move_up,
00769                     initial_size);
00770             }
00771             else {
00772                 while (move_down != NULL) {
00773                     move = move_down->next;
00774                     cuddDeallocNode(table, (DdNode *)move_down);
00775                     move_down = move;
00776                 }
00777                 initial_size = table->keysZ;
00778                 move_down = cuddZddSymmSifting_down(table, x, x_high,
00779                     initial_size);
00780                 result = cuddZddSymmSiftingBackward(table, move_down,
00781                     initial_size);
00782             }
00783         }
00784         else {
00785             result = cuddZddSymmSiftingBackward(table, move_up,
00786                 initial_size);
00787             /* move backward and stop at best position */
00788         }
00789         if (!result)
00790             goto cuddZddSymmSiftingAuxOutOfMem;
00791     }
00792     else { /* moving up first:shorter */
00793         /* Find top of x's symmetry group */
00794         while ((unsigned) x < table->subtableZ[x].next)
00795             x = table->subtableZ[x].next;
00796         x = table->subtableZ[x].next;
00797 
00798         move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00799         /* after that point x --> x_high, unless early term */
00800         if (move_up == ZDD_MV_OOM)
00801             goto cuddZddSymmSiftingAuxOutOfMem;
00802 
00803         if (move_up != NULL) {
00804             x = move_up->x;
00805         }
00806         else {
00807             while ((unsigned) x < table->subtableZ[x].next)
00808                 x = table->subtableZ[x].next;
00809         }
00810         i = table->subtableZ[x].next;
00811         init_group_size = x - i + 1;
00812 
00813         move_down = cuddZddSymmSifting_down(table, x, x_high,
00814             initial_size);
00815         if (move_down == ZDD_MV_OOM)
00816             goto cuddZddSymmSiftingAuxOutOfMem;
00817 
00818         if (move_down == NULL ||
00819             table->subtableZ[move_down->y].next != move_down->y) {
00820             /* symmetry detected may have to make another complete
00821                pass */
00822             if (move_down != NULL) {
00823                 x = move_down->y;
00824             }
00825             else {
00826                 x = table->subtableZ[x].next;
00827             }
00828             i = x;
00829             while ((unsigned) i < table->subtableZ[i].next) {
00830                 i = table->subtableZ[i].next;
00831             }
00832             final_group_size = i - x + 1;
00833 
00834             if (init_group_size == final_group_size) {
00835                 /* No new symmetries detected,
00836                    go back to best position */
00837                 result = cuddZddSymmSiftingBackward(table, move_down,
00838                     initial_size);
00839             }
00840             else {
00841                 while (move_up != NULL) {
00842                     move = move_up->next;
00843                     cuddDeallocNode(table, (DdNode *)move_up);
00844                     move_up = move;
00845                 }
00846                 initial_size = table->keysZ;
00847                 move_up = cuddZddSymmSifting_up(table, x, x_low,
00848                     initial_size);
00849                 result = cuddZddSymmSiftingBackward(table, move_up,
00850                     initial_size);
00851             }
00852         }
00853         else {
00854             result = cuddZddSymmSiftingBackward(table, move_down,
00855                 initial_size);
00856             /* move backward and stop at best position */
00857         }
00858         if (!result)
00859             goto cuddZddSymmSiftingAuxOutOfMem;
00860     }
00861 
00862     while (move_down != NULL) {
00863         move = move_down->next;
00864         cuddDeallocNode(table, (DdNode *)move_down);
00865         move_down = move;
00866     }
00867     while (move_up != NULL) {
00868         move = move_up->next;
00869         cuddDeallocNode(table, (DdNode *)move_up);
00870         move_up = move;
00871     }
00872 
00873     return(1);
00874 
00875 cuddZddSymmSiftingAuxOutOfMem:
00876     if (move_down != ZDD_MV_OOM) {
00877         while (move_down != NULL) {
00878             move = move_down->next;
00879             cuddDeallocNode(table, (DdNode *)move_down);
00880             move_down = move;
00881         }
00882     }
00883     if (move_up != ZDD_MV_OOM) {
00884         while (move_up != NULL) {
00885             move = move_up->next;
00886             cuddDeallocNode(table, (DdNode *)move_up);
00887             move_up = move;
00888         }
00889     }
00890 
00891     return(0);
00892 
00893 } /* end of cuddZddSymmSiftingAux */

static int cuddZddSymmSiftingBackward ( 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 1401 of file cuddZddSymm.c.

01405 {
01406     int         i;
01407     int         i_best;
01408     Move        *move;
01409     int         res;
01410 
01411     i_best = -1;
01412     for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01413         if (move->size < size) {
01414             i_best = i;
01415             size = move->size;
01416         }
01417     }
01418 
01419     for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01420         if (i == i_best) break;
01421         if ((table->subtableZ[move->x].next == move->x) &&
01422             (table->subtableZ[move->y].next == move->y)) {
01423             res = cuddZddSwapInPlace(table, move->x, move->y);
01424             if (!res) return(0);
01425         }
01426         else { /* Group move necessary */
01427             res = zdd_group_move_backward(table, move->x, move->y);
01428         }
01429         if (i_best == -1 && res == size)
01430             break;
01431     }
01432 
01433     return(1);
01434 
01435 } /* end of cuddZddSymmSiftingBackward */

int cuddZddSymmSiftingConv ( DdManager table,
int  lower,
int  upper 
)

Function********************************************************************

Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]

Description [Symmetric sifting to convergence algorithm for ZDDs. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique subtable.
  2. Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.
  5. Repeat 1-4 until no further improvement.

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddSymmSifting]

Definition at line 395 of file cuddZddSymm.c.

00399 {
00400     int         i;
00401     int         *var;
00402     int         nvars;
00403     int         initialSize;
00404     int         x;
00405     int         result;
00406     int         symvars;
00407     int         symgroups;
00408     int         classes;
00409     int         iteration;
00410 #ifdef DD_STATS
00411     int         previousSize;
00412 #endif
00413 
00414     initialSize = table->keysZ;
00415 
00416     nvars = table->sizeZ;
00417 
00418     /* Find order in which to sift variables. */
00419     var = NULL;
00420     zdd_entry = ALLOC(int, nvars);
00421     if (zdd_entry == NULL) {
00422         table->errorCode = CUDD_MEMORY_OUT;
00423         goto cuddZddSymmSiftingConvOutOfMem;
00424     }
00425     var = ALLOC(int, nvars);
00426     if (var == NULL) {
00427         table->errorCode = CUDD_MEMORY_OUT;
00428         goto cuddZddSymmSiftingConvOutOfMem;
00429     }
00430 
00431     for (i = 0; i < nvars; i++) {
00432         x = table->permZ[i];
00433         zdd_entry[i] = table->subtableZ[x].keys;
00434         var[i] = i;
00435     }
00436 
00437     qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare);
00438 
00439     /* Initialize the symmetry of each subtable to itself
00440     ** for first pass of converging symmetric sifting.
00441     */
00442     for (i = lower; i <= upper; i++)
00443         table->subtableZ[i].next = i;
00444 
00445     iteration = ddMin(table->siftMaxVar, table->sizeZ);
00446     for (i = 0; i < iteration; i++) {
00447         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00448             break;
00449         x = table->permZ[var[i]];
00450         if (x < lower || x > upper) continue;
00451         /* Only sift if not in symmetry group already. */
00452         if (table->subtableZ[x].next == (unsigned) x) {
00453 #ifdef DD_STATS
00454             previousSize = table->keysZ;
00455 #endif
00456             result = cuddZddSymmSiftingAux(table, x, lower, upper);
00457             if (!result)
00458                 goto cuddZddSymmSiftingConvOutOfMem;
00459 #ifdef DD_STATS
00460             if (table->keysZ < (unsigned) previousSize) {
00461                 (void) fprintf(table->out,"-");
00462             } else if (table->keysZ > (unsigned) previousSize) {
00463                 (void) fprintf(table->out,"+");
00464 #ifdef DD_VERBOSE
00465                 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00466 #endif
00467             } else {
00468                 (void) fprintf(table->out,"=");
00469             }
00470             fflush(table->out);
00471 #endif
00472         }
00473     }
00474 
00475     /* Sifting now until convergence. */
00476     while ((unsigned) initialSize > table->keysZ) {
00477         initialSize = table->keysZ;
00478 #ifdef DD_STATS
00479         (void) fprintf(table->out,"\n");
00480 #endif
00481         /* Here we consider only one representative for each symmetry class. */
00482         for (x = lower, classes = 0; x <= upper; x++, classes++) {
00483             while ((unsigned) x < table->subtableZ[x].next)
00484                 x = table->subtableZ[x].next;
00485             /* Here x is the largest index in a group.
00486             ** Groups consists of adjacent variables.
00487             ** Hence, the next increment of x will move it to a new group.
00488             */
00489             i = table->invpermZ[x];
00490             zdd_entry[i] = table->subtableZ[x].keys;
00491             var[classes] = i;
00492         }
00493 
00494         qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))cuddZddUniqueCompare);
00495 
00496         /* Now sift. */
00497         iteration = ddMin(table->siftMaxVar, nvars);
00498         for (i = 0; i < iteration; i++) {
00499             if (zddTotalNumberSwapping >= table->siftMaxSwap)
00500                 break;
00501             x = table->permZ[var[i]];
00502             if ((unsigned) x >= table->subtableZ[x].next) {
00503 #ifdef DD_STATS
00504                 previousSize = table->keysZ;
00505 #endif
00506                 result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
00507                 if (!result)
00508                     goto cuddZddSymmSiftingConvOutOfMem;
00509 #ifdef DD_STATS
00510                 if (table->keysZ < (unsigned) previousSize) {
00511                     (void) fprintf(table->out,"-");
00512                 } else if (table->keysZ > (unsigned) previousSize) {
00513                     (void) fprintf(table->out,"+");
00514 #ifdef DD_VERBOSE
00515                 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00516 #endif
00517                 } else {
00518                     (void) fprintf(table->out,"=");
00519                 }
00520                 fflush(table->out);
00521 #endif
00522             }
00523         } /* for */
00524     }
00525 
00526     cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00527 
00528 #ifdef DD_STATS
00529     (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
00530                    symvars);
00531     (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
00532                    symgroups);
00533 #endif
00534 
00535     FREE(var);
00536     FREE(zdd_entry);
00537 
00538     return(1+symvars);
00539 
00540 cuddZddSymmSiftingConvOutOfMem:
00541 
00542     if (zdd_entry != NULL)
00543         FREE(zdd_entry);
00544     if (var != NULL)
00545         FREE(var);
00546 
00547     return(0);
00548 
00549 } /* end of cuddZddSymmSiftingConv */

static int cuddZddSymmSiftingConvAux ( DdManager table,
int  x,
int  x_low,
int  x_high 
) [static]

Function********************************************************************

Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.]

Description [Given x_low <= x <= x_high moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is either an isolated variable, or it is the bottom of a symmetry group. All symmetries may not have been found, because of exceeded growth limit. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 913 of file cuddZddSymm.c.

00918 {
00919     Move        *move;
00920     Move        *move_up;       /* list of up move */
00921     Move        *move_down;     /* list of down move */
00922     int         initial_size;
00923     int         result;
00924     int         i;
00925     int         init_group_size, final_group_size;
00926 
00927     initial_size = table->keysZ;
00928 
00929     move_down = NULL;
00930     move_up = NULL;
00931 
00932     if (x == x_low) { /* Sift down */
00933         i = table->subtableZ[x].next;
00934         init_group_size = x - i + 1;
00935 
00936         move_down = cuddZddSymmSifting_down(table, x, x_high,
00937             initial_size);
00938         /* after that point x --> x_high, unless early term */
00939         if (move_down == ZDD_MV_OOM)
00940             goto cuddZddSymmSiftingConvAuxOutOfMem;
00941 
00942         if (move_down == NULL ||
00943             table->subtableZ[move_down->y].next != move_down->y) {
00944             /* symmetry detected may have to make another complete
00945                 pass */
00946             if (move_down != NULL)
00947                 x = move_down->y;
00948             else {
00949                 while ((unsigned) x < table->subtableZ[x].next);
00950                     x = table->subtableZ[x].next;
00951                 x = table->subtableZ[x].next;
00952             }
00953             i = x;
00954             while ((unsigned) i < table->subtableZ[i].next) {
00955                 i = table->subtableZ[i].next;
00956             }
00957             final_group_size = i - x + 1;
00958 
00959             if (init_group_size == final_group_size) {
00960                 /* No new symmetries detected,
00961                    go back to best position */
00962                 result = cuddZddSymmSiftingBackward(table, move_down,
00963                     initial_size);
00964             }
00965             else {
00966                 initial_size = table->keysZ;
00967                 move_up = cuddZddSymmSifting_up(table, x, x_low,
00968                     initial_size);
00969                 result = cuddZddSymmSiftingBackward(table, move_up,
00970                     initial_size);
00971             }
00972         }
00973         else {
00974             result = cuddZddSymmSiftingBackward(table, move_down,
00975                 initial_size);
00976             /* move backward and stop at best position */
00977         }
00978         if (!result)
00979             goto cuddZddSymmSiftingConvAuxOutOfMem;
00980     }
00981     else if (x == x_high) { /* Sift up */
00982         /* Find top of x's symm group */
00983         while ((unsigned) x < table->subtableZ[x].next)
00984             x = table->subtableZ[x].next;
00985         x = table->subtableZ[x].next;
00986 
00987         i = x;
00988         while ((unsigned) i < table->subtableZ[i].next) {
00989             i = table->subtableZ[i].next;
00990         }
00991         init_group_size = i - x + 1;
00992 
00993         move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00994         /* after that point x --> x_low, unless early term */
00995         if (move_up == ZDD_MV_OOM)
00996             goto cuddZddSymmSiftingConvAuxOutOfMem;
00997 
00998         if (move_up == NULL ||
00999             table->subtableZ[move_up->x].next != move_up->x) {
01000             /* symmetry detected may have to make another complete
01001                pass */
01002             if (move_up != NULL)
01003                 x = move_up->x;
01004             else {
01005                 while ((unsigned) x < table->subtableZ[x].next)
01006                     x = table->subtableZ[x].next;
01007             }
01008             i = table->subtableZ[x].next;
01009             final_group_size = x - i + 1;
01010 
01011             if (init_group_size == final_group_size) {
01012                 /* No new symmetry groups detected,
01013                    return to best position */
01014                 result = cuddZddSymmSiftingBackward(table, move_up,
01015                     initial_size);
01016             }
01017             else {
01018                 initial_size = table->keysZ;
01019                 move_down = cuddZddSymmSifting_down(table, x, x_high,
01020                     initial_size);
01021                 result = cuddZddSymmSiftingBackward(table, move_down,
01022                     initial_size);
01023             }
01024         }
01025         else {
01026             result = cuddZddSymmSiftingBackward(table, move_up,
01027                 initial_size);
01028             /* move backward and stop at best position */
01029         }
01030         if (!result)
01031             goto cuddZddSymmSiftingConvAuxOutOfMem;
01032     }
01033     else if ((x - x_low) > (x_high - x)) { /* must go down first:
01034                                                 shorter */
01035         move_down = cuddZddSymmSifting_down(table, x, x_high,
01036             initial_size);
01037         /* after that point x --> x_high */
01038         if (move_down == ZDD_MV_OOM)
01039             goto cuddZddSymmSiftingConvAuxOutOfMem;
01040 
01041         if (move_down != NULL) {
01042             x = move_down->y;
01043         }
01044         else {
01045             while ((unsigned) x < table->subtableZ[x].next)
01046                 x = table->subtableZ[x].next;
01047             x = table->subtableZ[x].next;
01048         }
01049         i = x;
01050         while ((unsigned) i < table->subtableZ[i].next) {
01051             i = table->subtableZ[i].next;
01052         }
01053         init_group_size = i - x + 1;
01054 
01055         move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
01056         if (move_up == ZDD_MV_OOM)
01057             goto cuddZddSymmSiftingConvAuxOutOfMem;
01058 
01059         if (move_up == NULL ||
01060             table->subtableZ[move_up->x].next != move_up->x) {
01061             /* symmetry detected may have to make another complete
01062                pass */
01063             if (move_up != NULL) {
01064                 x = move_up->x;
01065             }
01066             else {
01067                 while ((unsigned) x < table->subtableZ[x].next)
01068                     x = table->subtableZ[x].next;
01069             }
01070             i = table->subtableZ[x].next;
01071             final_group_size = x - i + 1;
01072 
01073             if (init_group_size == final_group_size) {
01074                 /* No new symmetry groups detected,
01075                    return to best position */
01076                 result = cuddZddSymmSiftingBackward(table, move_up,
01077                     initial_size);
01078             }
01079             else {
01080                 while (move_down != NULL) {
01081                     move = move_down->next;
01082                     cuddDeallocNode(table, (DdNode *)move_down);
01083                     move_down = move;
01084                 }
01085                 initial_size = table->keysZ;
01086                 move_down = cuddZddSymmSifting_down(table, x, x_high,
01087                     initial_size);
01088                 result = cuddZddSymmSiftingBackward(table, move_down,
01089                     initial_size);
01090             }
01091         }
01092         else {
01093             result = cuddZddSymmSiftingBackward(table, move_up,
01094                 initial_size);
01095             /* move backward and stop at best position */
01096         }
01097         if (!result)
01098             goto cuddZddSymmSiftingConvAuxOutOfMem;
01099     }
01100     else { /* moving up first:shorter */
01101         /* Find top of x's symmetry group */
01102         x = table->subtableZ[x].next;
01103 
01104         move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
01105         /* after that point x --> x_high, unless early term */
01106         if (move_up == ZDD_MV_OOM)
01107             goto cuddZddSymmSiftingConvAuxOutOfMem;
01108 
01109         if (move_up != NULL) {
01110             x = move_up->x;
01111         }
01112         else {
01113             while ((unsigned) x < table->subtableZ[x].next)
01114                 x = table->subtableZ[x].next;
01115         }
01116         i = table->subtableZ[x].next;
01117         init_group_size = x - i + 1;
01118 
01119         move_down = cuddZddSymmSifting_down(table, x, x_high,
01120             initial_size);
01121         if (move_down == ZDD_MV_OOM)
01122             goto cuddZddSymmSiftingConvAuxOutOfMem;
01123 
01124         if (move_down == NULL ||
01125             table->subtableZ[move_down->y].next != move_down->y) {
01126             /* symmetry detected may have to make another complete
01127                pass */
01128             if (move_down != NULL) {
01129                 x = move_down->y;
01130             }
01131             else {
01132                 while ((unsigned) x < table->subtableZ[x].next)
01133                     x = table->subtableZ[x].next;
01134                 x = table->subtableZ[x].next;
01135             }
01136             i = x;
01137             while ((unsigned) i < table->subtableZ[i].next) {
01138                 i = table->subtableZ[i].next;
01139             }
01140             final_group_size = i - x + 1;
01141 
01142             if (init_group_size == final_group_size) {
01143                 /* No new symmetries detected,
01144                    go back to best position */
01145                 result = cuddZddSymmSiftingBackward(table, move_down,
01146                     initial_size);
01147             }
01148             else {
01149                 while (move_up != NULL) {
01150                     move = move_up->next;
01151                     cuddDeallocNode(table, (DdNode *)move_up);
01152                     move_up = move;
01153                 }
01154                 initial_size = table->keysZ;
01155                 move_up = cuddZddSymmSifting_up(table, x, x_low,
01156                     initial_size);
01157                 result = cuddZddSymmSiftingBackward(table, move_up,
01158                     initial_size);
01159             }
01160         }
01161         else {
01162             result = cuddZddSymmSiftingBackward(table, move_down,
01163                 initial_size);
01164             /* move backward and stop at best position */
01165         }
01166         if (!result)
01167             goto cuddZddSymmSiftingConvAuxOutOfMem;
01168     }
01169 
01170     while (move_down != NULL) {
01171         move = move_down->next;
01172         cuddDeallocNode(table, (DdNode *)move_down);
01173         move_down = move;
01174     }
01175     while (move_up != NULL) {
01176         move = move_up->next;
01177         cuddDeallocNode(table, (DdNode *)move_up);
01178         move_up = move;
01179     }
01180 
01181     return(1);
01182 
01183 cuddZddSymmSiftingConvAuxOutOfMem:
01184     if (move_down != ZDD_MV_OOM) {
01185         while (move_down != NULL) {
01186             move = move_down->next;
01187             cuddDeallocNode(table, (DdNode *)move_down);
01188             move_down = move;
01189         }
01190     }
01191     if (move_up != ZDD_MV_OOM) {
01192         while (move_up != NULL) {
01193             move = move_up->next;
01194             cuddDeallocNode(table, (DdNode *)move_up);
01195             move_up = move;
01196         }
01197     }
01198 
01199     return(0);
01200 
01201 } /* end of cuddZddSymmSiftingConvAux */

static void cuddZddSymmSummary ( DdManager table,
int  lower,
int  upper,
int *  symvars,
int *  symgroups 
) [static]

Function********************************************************************

Synopsis [Counts numbers of symmetric variables and symmetry groups.]

Description []

SideEffects [None]

Definition at line 1645 of file cuddZddSymm.c.

01651 {
01652     int i,x,gbot;
01653     int TotalSymm = 0;
01654     int TotalSymmGroups = 0;
01655 
01656     for (i = lower; i <= upper; i++) {
01657         if (table->subtableZ[i].next != (unsigned) i) {
01658             TotalSymmGroups++;
01659             x = i;
01660             do {
01661                 TotalSymm++;
01662                 gbot = x;
01663                 x = table->subtableZ[x].next;
01664             } while (x != i);
01665 #ifdef DD_DEBUG
01666             assert(table->subtableZ[gbot].next == (unsigned) i);
01667 #endif
01668             i = gbot;
01669         }
01670     }
01671     *symvars = TotalSymm;
01672     *symgroups = TotalSymmGroups;
01673 
01674     return;
01675 
01676 } /* end of cuddZddSymmSummary */

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

Function********************************************************************

Synopsis [Swaps two groups.]

Description [Swaps two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Updates the list of moves. Returns the number of keys in the table if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1453 of file cuddZddSymm.c.

01458 {
01459     Move        *move;
01460     int         size;
01461     int         i, temp, gxtop, gxbot, gytop, gybot, yprev;
01462     int         swapx, swapy;
01463 
01464 #ifdef DD_DEBUG
01465     assert(x < y);      /* we assume that x < y */
01466 #endif
01467     /* Find top and bottom for the two groups. */
01468     gxtop = table->subtableZ[x].next;
01469     gytop = y;
01470     gxbot = x;
01471     gybot = table->subtableZ[y].next;
01472     while (table->subtableZ[gybot].next != (unsigned) y)
01473         gybot = table->subtableZ[gybot].next;
01474     yprev = gybot;
01475 
01476     while (x <= y) {
01477         while (y > gxtop) {
01478             /* Set correct symmetries. */
01479             temp = table->subtableZ[x].next;
01480             if (temp == x)
01481                 temp = y;
01482             i = gxtop;
01483             for (;;) {
01484                 if (table->subtableZ[i].next == (unsigned) x) {
01485                     table->subtableZ[i].next = y;
01486                     break;
01487                 } else {
01488                     i = table->subtableZ[i].next;
01489                 }
01490             }
01491             if (table->subtableZ[y].next != (unsigned) y) {
01492                 table->subtableZ[x].next = table->subtableZ[y].next;
01493             } else {
01494                 table->subtableZ[x].next = x;
01495             }
01496 
01497             if (yprev != y) {
01498                 table->subtableZ[yprev].next = x;
01499             } else {
01500                 yprev = x;
01501             }
01502             table->subtableZ[y].next = temp;
01503 
01504             size = cuddZddSwapInPlace(table, x, y);
01505             if (size == 0)
01506                 goto zdd_group_moveOutOfMem;
01507             swapx = x;
01508             swapy = y;
01509             y = x;
01510             x--;
01511         } /* while y > gxtop */
01512 
01513         /* Trying to find the next y. */
01514         if (table->subtableZ[y].next <= (unsigned) y) {
01515             gybot = y;
01516         } else {
01517             y = table->subtableZ[y].next;
01518         }
01519 
01520         yprev = gxtop;
01521         gxtop++;
01522         gxbot++;
01523         x = gxbot;
01524     } /* while x <= y, end of group movement */
01525     move = (Move *)cuddDynamicAllocNode(table);
01526     if (move == NULL)
01527         goto zdd_group_moveOutOfMem;
01528     move->x = swapx;
01529     move->y = swapy;
01530     move->size = table->keysZ;
01531     move->next = *moves;
01532     *moves = move;
01533 
01534     return(table->keysZ);
01535 
01536 zdd_group_moveOutOfMem:
01537     while (*moves != NULL) {
01538         move = (*moves)->next;
01539         cuddDeallocNode(table, (DdNode *)(*moves));
01540         *moves = move;
01541     }
01542     return(0);
01543 
01544 } /* end of zdd_group_move */

static int zdd_group_move_backward ( DdManager table,
int  x,
int  y 
) [static]

Function********************************************************************

Synopsis [Undoes the swap of two groups.]

Description [Undoes the swap of two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1561 of file cuddZddSymm.c.

01565 {
01566     int        size;
01567     int        i, temp, gxtop, gxbot, gytop, gybot, yprev;
01568 
01569 #ifdef DD_DEBUG
01570     assert(x < y);      /* we assume that x < y */
01571 #endif
01572     /* Find top and bottom of the two groups. */
01573     gxtop = table->subtableZ[x].next;
01574     gytop = y;
01575     gxbot = x;
01576     gybot = table->subtableZ[y].next;
01577     while (table->subtableZ[gybot].next != (unsigned) y)
01578         gybot = table->subtableZ[gybot].next;
01579     yprev = gybot;
01580 
01581     while (x <= y) {
01582         while (y > gxtop) {
01583             /* Set correct symmetries. */
01584             temp = table->subtableZ[x].next;
01585             if (temp == x)
01586                 temp = y;
01587             i = gxtop;
01588             for (;;) {
01589                 if (table->subtableZ[i].next == (unsigned) x) {
01590                     table->subtableZ[i].next = y;
01591                     break;
01592                 } else {
01593                     i = table->subtableZ[i].next;
01594                 }
01595             }
01596             if (table->subtableZ[y].next != (unsigned) y) {
01597                 table->subtableZ[x].next = table->subtableZ[y].next;
01598             } else {
01599                 table->subtableZ[x].next = x;
01600             }
01601 
01602             if (yprev != y) {
01603                 table->subtableZ[yprev].next = x;
01604             } else {
01605                 yprev = x;
01606             }
01607             table->subtableZ[y].next = temp;
01608 
01609             size = cuddZddSwapInPlace(table, x, y);
01610             if (size == 0)
01611                 return(0);
01612             y = x;
01613             x--;
01614         } /* while y > gxtop */
01615 
01616         /* Trying to find the next y. */
01617         if (table->subtableZ[y].next <= (unsigned) y) {
01618             gybot = y;
01619         } else {
01620             y = table->subtableZ[y].next;
01621         }
01622 
01623         yprev = gxtop;
01624         gxtop++;
01625         gxbot++;
01626         x = gxbot;
01627     } /* while x <= y, end of group movement backward */
01628 
01629     return(size);
01630 
01631 } /* end of zdd_group_move_backward */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $" [static]

Definition at line 65 of file cuddZddSymm.c.

DdNode* empty [static]

Definition at line 72 of file cuddZddSymm.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:58 2010 for abc70930 by  doxygen 1.6.1