src/cuBdd/cuddZddSymm.c File Reference

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

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio 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 [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 77 of file cuddZddSymm.c.


Function Documentation

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

00145 {
00146     int         i, x, gbot;
00147     int         TotalSymm = 0;
00148     int         TotalSymmGroups = 0;
00149 
00150     for (i = lower; i < upper; i++) {
00151         if (table->subtableZ[i].next != (unsigned) i) {
00152             x = i;
00153             (void) fprintf(table->out,"Group:");
00154             do {
00155                 (void) fprintf(table->out,"  %d", table->invpermZ[x]);
00156                 TotalSymm++;
00157                 gbot = x;
00158                 x = table->subtableZ[x].next;
00159             } while (x != i);
00160             TotalSymmGroups++;
00161 #ifdef DD_DEBUG
00162             assert(table->subtableZ[gbot].next == (unsigned) i);
00163 #endif
00164             i = gbot;
00165             (void) fprintf(table->out,"\n");
00166         }
00167     }
00168     (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm);
00169     (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups);
00170 
00171 } /* 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 193 of file cuddZddSymm.c.

00197 {
00198     int         i;
00199     DdNode      *f, *f0, *f1, *f01, *f00, *f11, *f10;
00200     int         yindex;
00201     int         xsymmy = 1;
00202     int         xsymmyp = 1;
00203     int         arccount = 0;
00204     int         TotalRefCount = 0;
00205     int         symm_found;
00206 
00207     empty = table->zero;
00208 
00209     yindex = table->invpermZ[y];
00210     for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
00211         f = table->subtableZ[x].nodelist[i];
00212         while (f != NULL) {
00213             /* Find f1, f0, f11, f10, f01, f00 */
00214             f1 = cuddT(f);
00215             f0 = cuddE(f);
00216             if ((int) f1->index == yindex) {
00217                 f11 = cuddT(f1);
00218                 f10 = cuddE(f1);
00219                 if (f10 != empty)
00220                     arccount++;
00221             } else {
00222                 if ((int) f0->index != yindex) {
00223                     return(0); /* f bypasses layer y */
00224                 }
00225                 f11 = empty;
00226                 f10 = f1;
00227             }
00228             if ((int) f0->index == yindex) {
00229                 f01 = cuddT(f0);
00230                 f00 = cuddE(f0);
00231                 if (f00 != empty)
00232                     arccount++;
00233             } else {
00234                 f01 = empty;
00235                 f00 = f0;
00236             }
00237             if (f01 != f10)
00238                 xsymmy = 0;
00239             if (f11 != f00)
00240                 xsymmyp = 0;
00241             if ((xsymmy == 0) && (xsymmyp == 0))
00242                 return(0);
00243 
00244             f = f->next;
00245         } /* for each element of the collision list */
00246     } /* for each slot of the subtable */
00247 
00248     /* Calculate the total reference counts of y
00249     ** whose else arc is not empty.
00250     */
00251     for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
00252         f = table->subtableZ[y].nodelist[i];
00253         while (f != NIL(DdNode)) {
00254             if (cuddE(f) != empty)
00255                 TotalRefCount += f->ref;
00256             f = f->next;
00257         }
00258     }
00259 
00260     symm_found = (arccount == TotalRefCount);
00261 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00262     if (symm_found) {
00263         int xindex = table->invpermZ[x];
00264         (void) fprintf(table->out,
00265                        "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00266                        xindex,yindex,x,y);
00267     }
00268 #endif
00269 
00270     return(symm_found);
00271 
00272 } /* 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 298 of file cuddZddSymm.c.

00302 {
00303     int         i;
00304     int         *var;
00305     int         nvars;
00306     int         x;
00307     int         result;
00308     int         symvars;
00309     int         symgroups;
00310     int         iteration;
00311 #ifdef DD_STATS
00312     int         previousSize;
00313 #endif
00314 
00315     nvars = table->sizeZ;
00316 
00317     /* Find order in which to sift variables. */
00318     var = NULL;
00319     zdd_entry = ALLOC(int, nvars);
00320     if (zdd_entry == NULL) {
00321         table->errorCode = CUDD_MEMORY_OUT;
00322         goto cuddZddSymmSiftingOutOfMem;
00323     }
00324     var = ALLOC(int, nvars);
00325     if (var == NULL) {
00326         table->errorCode = CUDD_MEMORY_OUT;
00327         goto cuddZddSymmSiftingOutOfMem;
00328     }
00329 
00330     for (i = 0; i < nvars; i++) {
00331         x = table->permZ[i];
00332         zdd_entry[i] = table->subtableZ[x].keys;
00333         var[i] = i;
00334     }
00335 
00336     qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00337 
00338     /* Initialize the symmetry of each subtable to itself. */
00339     for (i = lower; i <= upper; i++)
00340         table->subtableZ[i].next = i;
00341 
00342     iteration = ddMin(table->siftMaxVar, nvars);
00343     for (i = 0; i < iteration; i++) {
00344         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00345             break;
00346         x = table->permZ[var[i]];
00347 #ifdef DD_STATS
00348         previousSize = table->keysZ;
00349 #endif
00350         if (x < lower || x > upper) continue;
00351         if (table->subtableZ[x].next == (unsigned) x) {
00352             result = cuddZddSymmSiftingAux(table, x, lower, upper);
00353             if (!result)
00354                 goto cuddZddSymmSiftingOutOfMem;
00355 #ifdef DD_STATS
00356             if (table->keysZ < (unsigned) previousSize) {
00357                 (void) fprintf(table->out,"-");
00358             } else if (table->keysZ > (unsigned) previousSize) {
00359                 (void) fprintf(table->out,"+");
00360 #ifdef DD_VERBOSE
00361                 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00362 #endif
00363             } else {
00364                 (void) fprintf(table->out,"=");
00365             }
00366             fflush(table->out);
00367 #endif
00368         }
00369     }
00370 
00371     FREE(var);
00372     FREE(zdd_entry);
00373 
00374     cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00375 
00376 #ifdef DD_STATS
00377     (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
00378     (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
00379 #endif
00380 
00381     return(1+symvars);
00382 
00383 cuddZddSymmSiftingOutOfMem:
00384 
00385     if (zdd_entry != NULL)
00386         FREE(zdd_entry);
00387     if (var != NULL)
00388         FREE(var);
00389 
00390     return(0);
00391 
00392 } /* 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 1334 of file cuddZddSymm.c.

01339 {
01340     Move        *moves;
01341     Move        *move;
01342     int         y;
01343     int         size;
01344     int         limit_size = initial_size;
01345     int         i, gxtop, gybot;
01346 
01347     moves = NULL;
01348     y = cuddZddNextHigh(table, x);
01349     while (y <= x_high) {
01350         gybot = table->subtableZ[y].next;
01351         while (table->subtableZ[gybot].next != (unsigned) y)
01352             gybot = table->subtableZ[gybot].next;
01353         if (cuddZddSymmCheck(table, x, y)) {
01354             /* Symmetry found, attach symm groups */
01355             gxtop = table->subtableZ[x].next;
01356             table->subtableZ[x].next = y;
01357             i = table->subtableZ[y].next;
01358             while (table->subtableZ[i].next != (unsigned) y)
01359                 i = table->subtableZ[i].next;
01360             table->subtableZ[i].next = gxtop;
01361         }
01362         else if ((table->subtableZ[x].next == (unsigned) x) &&
01363             (table->subtableZ[y].next == (unsigned) y)) {
01364             /* x and y have self symmetry */
01365             size = cuddZddSwapInPlace(table, x, y);
01366             if (size == 0)
01367                 goto cuddZddSymmSifting_downOutOfMem;
01368             move = (Move *)cuddDynamicAllocNode(table);
01369             if (move == NULL)
01370                 goto cuddZddSymmSifting_downOutOfMem;
01371             move->x = x;
01372             move->y = y;
01373             move->size = size;
01374             move->next = moves;
01375             moves = move;
01376             if ((double)size >
01377                 (double)limit_size * table->maxGrowth)
01378                 return(moves);
01379             if (size < limit_size)
01380                 limit_size = size;
01381             x = y;
01382             y = cuddZddNextHigh(table, x);
01383         }
01384         else { /* Group move */
01385             size = zdd_group_move(table, x, y, &moves);
01386             if ((double)size >
01387                 (double)limit_size * table->maxGrowth)
01388                 return(moves);
01389             if (size < limit_size)
01390                 limit_size = size;
01391         }
01392         x = gybot;
01393         y = cuddZddNextHigh(table, x);
01394     }
01395 
01396     return(moves);
01397 
01398 cuddZddSymmSifting_downOutOfMem:
01399     while (moves != NULL) {
01400         move = moves->next;
01401         cuddDeallocMove(table, moves);
01402         moves = move;
01403     }
01404     return(ZDD_MV_OOM);
01405 
01406 } /* 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 1246 of file cuddZddSymm.c.

01251 {
01252     Move        *moves;
01253     Move        *move;
01254     int         y;
01255     int         size;
01256     int         limit_size = initial_size;
01257     int         i, gytop;
01258 
01259     moves = NULL;
01260     y = cuddZddNextLow(table, x);
01261     while (y >= x_low) {
01262         gytop = table->subtableZ[y].next;
01263         if (cuddZddSymmCheck(table, y, x)) {
01264             /* Symmetry found, attach symm groups */
01265             table->subtableZ[y].next = x;
01266             i = table->subtableZ[x].next;
01267             while (table->subtableZ[i].next != (unsigned) x)
01268                 i = table->subtableZ[i].next;
01269             table->subtableZ[i].next = gytop;
01270         }
01271         else if ((table->subtableZ[x].next == (unsigned) x) &&
01272             (table->subtableZ[y].next == (unsigned) y)) {
01273             /* x and y have self symmetry */
01274             size = cuddZddSwapInPlace(table, y, x);
01275             if (size == 0)
01276                 goto cuddZddSymmSifting_upOutOfMem;
01277             move = (Move *)cuddDynamicAllocNode(table);
01278             if (move == NULL)
01279                 goto cuddZddSymmSifting_upOutOfMem;
01280             move->x = y;
01281             move->y = x;
01282             move->size = size;
01283             move->next = moves;
01284             moves = move;
01285             if ((double)size >
01286                 (double)limit_size * table->maxGrowth)
01287                 return(moves);
01288             if (size < limit_size)
01289                 limit_size = size;
01290         }
01291         else { /* Group move */
01292             size = zdd_group_move(table, y, x, &moves);
01293             if ((double)size >
01294                 (double)limit_size * table->maxGrowth)
01295                 return(moves);
01296             if (size < limit_size)
01297                 limit_size = size;
01298         }
01299         x = gytop;
01300         y = cuddZddNextLow(table, x);
01301     }
01302 
01303     return(moves);
01304 
01305 cuddZddSymmSifting_upOutOfMem:
01306     while (moves != NULL) {
01307         move = moves->next;
01308         cuddDeallocMove(table, moves);
01309         moves = move;
01310     }
01311     return(ZDD_MV_OOM);
01312 
01313 } /* end of cuddZddSymmSifting_up */

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

AutomaticStart

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

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

01429 {
01430     int         i;
01431     int         i_best;
01432     Move        *move;
01433     int         res;
01434 
01435     i_best = -1;
01436     for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01437         if (move->size < size) {
01438             i_best = i;
01439             size = move->size;
01440         }
01441     }
01442 
01443     for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01444         if (i == i_best) break;
01445         if ((table->subtableZ[move->x].next == move->x) &&
01446             (table->subtableZ[move->y].next == move->y)) {
01447             res = cuddZddSwapInPlace(table, move->x, move->y);
01448             if (!res) return(0);
01449         }
01450         else { /* Group move necessary */
01451             res = zdd_group_move_backward(table, move->x, move->y);
01452         }
01453         if (i_best == -1 && res == size)
01454             break;
01455     }
01456 
01457     return(1);
01458 
01459 } /* 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 419 of file cuddZddSymm.c.

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

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

01673 {
01674     int i,x,gbot;
01675     int TotalSymm = 0;
01676     int TotalSymmGroups = 0;
01677 
01678     for (i = lower; i <= upper; i++) {
01679         if (table->subtableZ[i].next != (unsigned) i) {
01680             TotalSymmGroups++;
01681             x = i;
01682             do {
01683                 TotalSymm++;
01684                 gbot = x;
01685                 x = table->subtableZ[x].next;
01686             } while (x != i);
01687 #ifdef DD_DEBUG
01688             assert(table->subtableZ[gbot].next == (unsigned) i);
01689 #endif
01690             i = gbot;
01691         }
01692     }
01693     *symvars = TotalSymm;
01694     *symgroups = TotalSymmGroups;
01695 
01696     return;
01697 
01698 } /* 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 1477 of file cuddZddSymm.c.

01482 {
01483     Move        *move;
01484     int         size;
01485     int         i, temp, gxtop, gxbot, gybot, yprev;
01486     int         swapx, swapy;
01487 
01488 #ifdef DD_DEBUG
01489     assert(x < y);      /* we assume that x < y */
01490 #endif
01491     /* Find top and bottom for the two groups. */
01492     gxtop = table->subtableZ[x].next;
01493     gxbot = x;
01494     gybot = table->subtableZ[y].next;
01495     while (table->subtableZ[gybot].next != (unsigned) y)
01496         gybot = table->subtableZ[gybot].next;
01497     yprev = gybot;
01498 
01499     while (x <= y) {
01500         while (y > gxtop) {
01501             /* Set correct symmetries. */
01502             temp = table->subtableZ[x].next;
01503             if (temp == x)
01504                 temp = y;
01505             i = gxtop;
01506             for (;;) {
01507                 if (table->subtableZ[i].next == (unsigned) x) {
01508                     table->subtableZ[i].next = y;
01509                     break;
01510                 } else {
01511                     i = table->subtableZ[i].next;
01512                 }
01513             }
01514             if (table->subtableZ[y].next != (unsigned) y) {
01515                 table->subtableZ[x].next = table->subtableZ[y].next;
01516             } else {
01517                 table->subtableZ[x].next = x;
01518             }
01519 
01520             if (yprev != y) {
01521                 table->subtableZ[yprev].next = x;
01522             } else {
01523                 yprev = x;
01524             }
01525             table->subtableZ[y].next = temp;
01526 
01527             size = cuddZddSwapInPlace(table, x, y);
01528             if (size == 0)
01529                 goto zdd_group_moveOutOfMem;
01530             swapx = x;
01531             swapy = y;
01532             y = x;
01533             x--;
01534         } /* while y > gxtop */
01535 
01536         /* Trying to find the next y. */
01537         if (table->subtableZ[y].next <= (unsigned) y) {
01538             gybot = y;
01539         } else {
01540             y = table->subtableZ[y].next;
01541         }
01542 
01543         yprev = gxtop;
01544         gxtop++;
01545         gxbot++;
01546         x = gxbot;
01547     } /* while x <= y, end of group movement */
01548     move = (Move *)cuddDynamicAllocNode(table);
01549     if (move == NULL)
01550         goto zdd_group_moveOutOfMem;
01551     move->x = swapx;
01552     move->y = swapy;
01553     move->size = table->keysZ;
01554     move->next = *moves;
01555     *moves = move;
01556 
01557     return(table->keysZ);
01558 
01559 zdd_group_moveOutOfMem:
01560     while (*moves != NULL) {
01561         move = (*moves)->next;
01562         cuddDeallocMove(table, *moves);
01563         *moves = move;
01564     }
01565     return(0);
01566 
01567 } /* 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 1584 of file cuddZddSymm.c.

01588 {
01589     int        size;
01590     int        i, temp, gxtop, gxbot, gybot, yprev;
01591 
01592 #ifdef DD_DEBUG
01593     assert(x < y);      /* we assume that x < y */
01594 #endif
01595     /* Find top and bottom of the two groups. */
01596     gxtop = table->subtableZ[x].next;
01597     gxbot = x;
01598     gybot = table->subtableZ[y].next;
01599     while (table->subtableZ[gybot].next != (unsigned) y)
01600         gybot = table->subtableZ[gybot].next;
01601     yprev = gybot;
01602 
01603     while (x <= y) {
01604         while (y > gxtop) {
01605             /* Set correct symmetries. */
01606             temp = table->subtableZ[x].next;
01607             if (temp == x)
01608                 temp = y;
01609             i = gxtop;
01610             for (;;) {
01611                 if (table->subtableZ[i].next == (unsigned) x) {
01612                     table->subtableZ[i].next = y;
01613                     break;
01614                 } else {
01615                     i = table->subtableZ[i].next;
01616                 }
01617             }
01618             if (table->subtableZ[y].next != (unsigned) y) {
01619                 table->subtableZ[x].next = table->subtableZ[y].next;
01620             } else {
01621                 table->subtableZ[x].next = x;
01622             }
01623 
01624             if (yprev != y) {
01625                 table->subtableZ[yprev].next = x;
01626             } else {
01627                 yprev = x;
01628             }
01629             table->subtableZ[y].next = temp;
01630 
01631             size = cuddZddSwapInPlace(table, x, y);
01632             if (size == 0)
01633                 return(0);
01634             y = x;
01635             x--;
01636         } /* while y > gxtop */
01637 
01638         /* Trying to find the next y. */
01639         if (table->subtableZ[y].next <= (unsigned) y) {
01640             gybot = y;
01641         } else {
01642             y = table->subtableZ[y].next;
01643         }
01644 
01645         yprev = gxtop;
01646         gxtop++;
01647         gxbot++;
01648         x = gxbot;
01649     } /* while x <= y, end of group movement backward */
01650 
01651     return(size);
01652 
01653 } /* end of zdd_group_move_backward */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio Exp $" [static]

Definition at line 92 of file cuddZddSymm.c.

DdNode* empty [static]

Definition at line 99 of file cuddZddSymm.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