src/cuBdd/cuddSymmetry.c File Reference

#include "util.h"
#include "cuddInt.h"
Include dependency graph for cuddSymmetry.c:

Go to the source code of this file.

Defines

#define MV_OOM   (Move *)1

Functions

static int ddSymmUniqueCompare (int *ptrX, int *ptrY)
static int ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh)
static int ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh)
static MoveddSymmSiftingUp (DdManager *table, int y, int xLow)
static MoveddSymmSiftingDown (DdManager *table, int x, int xHigh)
static int ddSymmGroupMove (DdManager *table, int x, int y, Move **moves)
static int ddSymmGroupMoveBackward (DdManager *table, int x, int y)
static int ddSymmSiftingBackward (DdManager *table, Move *moves, int size)
static void ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups)
void Cudd_SymmProfile (DdManager *table, int lower, int upper)
int cuddSymmCheck (DdManager *table, int x, int y)
int cuddSymmSifting (DdManager *table, int lower, int upper)
int cuddSymmSiftingConv (DdManager *table, int lower, int upper)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $"
static int * entry
int ddTotalNumberSwapping

Define Documentation

#define MV_OOM   (Move *)1

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

FileName [cuddSymmetry.c]

PackageName [cudd]

Synopsis [Functions for symmetry-based variable reordering.]

Description [External procedures included in this file:

Internal procedures included in this module:

Static procedures included in this module:

]

Author [Shipra Panda, Fabio Somenzi]

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 75 of file cuddSymmetry.c.


Function Documentation

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

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

Synopsis [Prints statistics on symmetric variables.]

Description []

SideEffects [None]

Definition at line 138 of file cuddSymmetry.c.

00142 {
00143     int i,x,gbot;
00144     int TotalSymm = 0;
00145     int TotalSymmGroups = 0;
00146 
00147     for (i = lower; i <= upper; i++) {
00148         if (table->subtables[i].next != (unsigned) i) {
00149             x = i;
00150             (void) fprintf(table->out,"Group:");
00151             do {
00152                 (void) fprintf(table->out,"  %d",table->invperm[x]);
00153                 TotalSymm++;
00154                 gbot = x;
00155                 x = table->subtables[x].next;
00156             } while (x != i);
00157             TotalSymmGroups++;
00158 #ifdef DD_DEBUG
00159             assert(table->subtables[gbot].next == (unsigned) i);
00160 #endif
00161             i = gbot;
00162             (void) fprintf(table->out,"\n");
00163         }
00164     }
00165     (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm);
00166     (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups);
00167 
00168 } /* end of Cudd_SymmProfile */

int cuddSymmCheck ( 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]

Definition at line 188 of file cuddSymmetry.c.

00192 {
00193     DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
00194     int comple;         /* f0 is complemented */
00195     int xsymmy;         /* x and y may be positively symmetric */
00196     int xsymmyp;        /* x and y may be negatively symmetric */
00197     int arccount;       /* number of arcs from layer x to layer y */
00198     int TotalRefCount;  /* total reference count of layer y minus 1 */
00199     int yindex;
00200     int i;
00201     DdNodePtr *list;
00202     int slots;
00203     DdNode *sentinel = &(table->sentinel);
00204 #ifdef DD_DEBUG
00205     int xindex;
00206 #endif
00207 
00208     /* Checks that x and y are not the projection functions.
00209     ** For x it is sufficient to check whether there is only one
00210     ** node; indeed, if there is one node, it is the projection function
00211     ** and it cannot point to y. Hence, if y isn't just the projection
00212     ** function, it has one arc coming from a layer different from x.
00213     */
00214     if (table->subtables[x].keys == 1) {
00215         return(0);
00216     }
00217     yindex = table->invperm[y];
00218     if (table->subtables[y].keys == 1) {
00219         if (table->vars[yindex]->ref == 1)
00220             return(0);
00221     }
00222 
00223     xsymmy = xsymmyp = 1;
00224     arccount = 0;
00225     slots = table->subtables[x].slots;
00226     list = table->subtables[x].nodelist;
00227     for (i = 0; i < slots; i++) {
00228         f = list[i];
00229         while (f != sentinel) {
00230             /* Find f1, f0, f11, f10, f01, f00. */
00231             f1 = cuddT(f);
00232             f0 = Cudd_Regular(cuddE(f));
00233             comple = Cudd_IsComplement(cuddE(f));
00234             if ((int) f1->index == yindex) {
00235                 arccount++;
00236                 f11 = cuddT(f1); f10 = cuddE(f1);
00237             } else {
00238                 if ((int) f0->index != yindex) {
00239                     /* If f is an isolated projection function it is
00240                     ** allowed to bypass layer y.
00241                     */
00242                     if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
00243                         return(0); /* f bypasses layer y */
00244                 }
00245                 f11 = f10 = f1;
00246             }
00247             if ((int) f0->index == yindex) {
00248                 arccount++;
00249                 f01 = cuddT(f0); f00 = cuddE(f0);
00250             } else {
00251                 f01 = f00 = f0;
00252             }
00253             if (comple) {
00254                 f01 = Cudd_Not(f01);
00255                 f00 = Cudd_Not(f00);
00256             }
00257 
00258             if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
00259                 xsymmy &= f01 == f10;
00260                 xsymmyp &= f11 == f00;
00261                 if ((xsymmy == 0) && (xsymmyp == 0))
00262                     return(0);
00263             }
00264 
00265             f = f->next;
00266         } /* while */
00267     } /* for */
00268 
00269     /* Calculate the total reference counts of y */
00270     TotalRefCount = -1; /* -1 for projection function */
00271     slots = table->subtables[y].slots;
00272     list = table->subtables[y].nodelist;
00273     for (i = 0; i < slots; i++) {
00274         f = list[i];
00275         while (f != sentinel) {
00276             TotalRefCount += f->ref;
00277             f = f->next;
00278         }
00279     }
00280 
00281 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00282     if (arccount == TotalRefCount) {
00283         xindex = table->invperm[x];
00284         (void) fprintf(table->out,
00285                        "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00286                        xindex,yindex,x,y);
00287     }
00288 #endif
00289 
00290     return(arccount == TotalRefCount);
00291 
00292 } /* end of cuddSymmCheck */

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

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

Synopsis [Symmetric sifting algorithm.]

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 DD 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 [cuddSymmSiftingConv]

Definition at line 318 of file cuddSymmetry.c.

00322 {
00323     int         i;
00324     int         *var;
00325     int         size;
00326     int         x;
00327     int         result;
00328     int         symvars;
00329     int         symgroups;
00330 #ifdef DD_STATS
00331     int         previousSize;
00332 #endif
00333 
00334     size = table->size;
00335 
00336     /* Find order in which to sift variables. */
00337     var = NULL;
00338     entry = ALLOC(int,size);
00339     if (entry == NULL) {
00340         table->errorCode = CUDD_MEMORY_OUT;
00341         goto ddSymmSiftingOutOfMem;
00342     }
00343     var = ALLOC(int,size);
00344     if (var == NULL) {
00345         table->errorCode = CUDD_MEMORY_OUT;
00346         goto ddSymmSiftingOutOfMem;
00347     }
00348 
00349     for (i = 0; i < size; i++) {
00350         x = table->perm[i];
00351         entry[i] = table->subtables[x].keys;
00352         var[i] = i;
00353     }
00354 
00355     qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00356 
00357     /* Initialize the symmetry of each subtable to itself. */
00358     for (i = lower; i <= upper; i++) {
00359         table->subtables[i].next = i;
00360     }
00361 
00362     for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00363         if (ddTotalNumberSwapping >= table->siftMaxSwap)
00364             break;
00365         x = table->perm[var[i]];
00366 #ifdef DD_STATS
00367         previousSize = table->keys - table->isolated;
00368 #endif
00369         if (x < lower || x > upper) continue;
00370         if (table->subtables[x].next == (unsigned) x) {
00371             result = ddSymmSiftingAux(table,x,lower,upper);
00372             if (!result) goto ddSymmSiftingOutOfMem;
00373 #ifdef DD_STATS
00374             if (table->keys < (unsigned) previousSize + table->isolated) {
00375                 (void) fprintf(table->out,"-");
00376             } else if (table->keys > (unsigned) previousSize +
00377                        table->isolated) {
00378                 (void) fprintf(table->out,"+"); /* should never happen */
00379             } else {
00380                 (void) fprintf(table->out,"=");
00381             }
00382             fflush(table->out);
00383 #endif
00384         }
00385     }
00386 
00387     FREE(var);
00388     FREE(entry);
00389 
00390     ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00391 
00392 #ifdef DD_STATS
00393     (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00394                    symvars);
00395     (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00396                    symgroups);
00397 #endif
00398 
00399     return(1+symvars);
00400 
00401 ddSymmSiftingOutOfMem:
00402 
00403     if (entry != NULL) FREE(entry);
00404     if (var != NULL) FREE(var);
00405 
00406     return(0);
00407 
00408 } /* end of cuddSymmSifting */

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

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

Synopsis [Symmetric sifting to convergence algorithm.]

Description [Symmetric sifting to convergence 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 DD 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 [cuddSymmSifting]

Definition at line 435 of file cuddSymmetry.c.

00439 {
00440     int         i;
00441     int         *var;
00442     int         size;
00443     int         x;
00444     int         result;
00445     int         symvars;
00446     int         symgroups;
00447     int         classes;
00448     int         initialSize;
00449 #ifdef DD_STATS
00450     int         previousSize;
00451 #endif
00452 
00453     initialSize = table->keys - table->isolated;
00454 
00455     size = table->size;
00456 
00457     /* Find order in which to sift variables. */
00458     var = NULL;
00459     entry = ALLOC(int,size);
00460     if (entry == NULL) {
00461         table->errorCode = CUDD_MEMORY_OUT;
00462         goto ddSymmSiftingConvOutOfMem;
00463     }
00464     var = ALLOC(int,size);
00465     if (var == NULL) {
00466         table->errorCode = CUDD_MEMORY_OUT;
00467         goto ddSymmSiftingConvOutOfMem;
00468     }
00469 
00470     for (i = 0; i < size; i++) {
00471         x = table->perm[i];
00472         entry[i] = table->subtables[x].keys;
00473         var[i] = i;
00474     }
00475 
00476     qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00477 
00478     /* Initialize the symmetry of each subtable to itself
00479     ** for first pass of converging symmetric sifting.
00480     */
00481     for (i = lower; i <= upper; i++) {
00482         table->subtables[i].next = i;
00483     }
00484 
00485     for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
00486         if (ddTotalNumberSwapping >= table->siftMaxSwap)
00487             break;
00488         x = table->perm[var[i]];
00489         if (x < lower || x > upper) continue;
00490         /* Only sift if not in symmetry group already. */
00491         if (table->subtables[x].next == (unsigned) x) {
00492 #ifdef DD_STATS
00493             previousSize = table->keys - table->isolated;
00494 #endif
00495             result = ddSymmSiftingAux(table,x,lower,upper);
00496             if (!result) goto ddSymmSiftingConvOutOfMem;
00497 #ifdef DD_STATS
00498             if (table->keys < (unsigned) previousSize + table->isolated) {
00499                 (void) fprintf(table->out,"-");
00500             } else if (table->keys > (unsigned) previousSize +
00501                        table->isolated) {
00502                 (void) fprintf(table->out,"+");
00503             } else {
00504                 (void) fprintf(table->out,"=");
00505             }
00506             fflush(table->out);
00507 #endif
00508         }
00509     }
00510 
00511     /* Sifting now until convergence. */
00512     while ((unsigned) initialSize > table->keys - table->isolated) {
00513         initialSize = table->keys - table->isolated;
00514 #ifdef DD_STATS
00515         (void) fprintf(table->out,"\n");
00516 #endif
00517         /* Here we consider only one representative for each symmetry class. */
00518         for (x = lower, classes = 0; x <= upper; x++, classes++) {
00519             while ((unsigned) x < table->subtables[x].next) {
00520                 x = table->subtables[x].next;
00521             }
00522             /* Here x is the largest index in a group.
00523             ** Groups consist of adjacent variables.
00524             ** Hence, the next increment of x will move it to a new group.
00525             */
00526             i = table->invperm[x];
00527             entry[i] = table->subtables[x].keys;
00528             var[classes] = i;
00529         }
00530 
00531         qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00532 
00533         /* Now sift. */
00534         for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00535             if (ddTotalNumberSwapping >= table->siftMaxSwap)
00536                 break;
00537             x = table->perm[var[i]];
00538             if ((unsigned) x >= table->subtables[x].next) {
00539 #ifdef DD_STATS
00540                 previousSize = table->keys - table->isolated;
00541 #endif
00542                 result = ddSymmSiftingConvAux(table,x,lower,upper);
00543                 if (!result ) goto ddSymmSiftingConvOutOfMem;
00544 #ifdef DD_STATS
00545                 if (table->keys < (unsigned) previousSize + table->isolated) {
00546                     (void) fprintf(table->out,"-");
00547                 } else if (table->keys > (unsigned) previousSize +
00548                            table->isolated) {
00549                     (void) fprintf(table->out,"+");
00550                 } else {
00551                     (void) fprintf(table->out,"=");
00552                 }
00553                 fflush(table->out);
00554 #endif
00555             }
00556         } /* for */
00557     }
00558 
00559     ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00560 
00561 #ifdef DD_STATS
00562     (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00563                    symvars);
00564     (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00565                    symgroups);
00566 #endif
00567 
00568     FREE(var);
00569     FREE(entry);
00570 
00571     return(1+symvars);
00572 
00573 ddSymmSiftingConvOutOfMem:
00574 
00575     if (entry != NULL) FREE(entry);
00576     if (var != NULL) FREE(var);
00577 
00578     return(0);
00579 
00580 } /* end of cuddSymmSiftingConv */

static int ddSymmGroupMove ( 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]

Definition at line 1468 of file cuddSymmetry.c.

01473 {
01474     Move *move;
01475     int  size;
01476     int  i,j;
01477     int  xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01478     int  swapx,swapy;
01479 
01480 #ifdef DD_DEBUG
01481     assert(x < y);      /* we assume that x < y */
01482 #endif
01483     /* Find top, bottom, and size for the two groups. */
01484     xbot = x;
01485     xtop = table->subtables[x].next;
01486     xsize = xbot - xtop + 1;
01487     ybot = y;
01488     while ((unsigned) ybot < table->subtables[ybot].next)
01489         ybot = table->subtables[ybot].next;
01490     ytop = y;
01491     ysize = ybot - ytop + 1;
01492 
01493     /* Sift the variables of the second group up through the first group. */
01494     for (i = 1; i <= ysize; i++) {
01495         for (j = 1; j <= xsize; j++) {
01496             size = cuddSwapInPlace(table,x,y);
01497             if (size == 0) return(0);
01498             swapx = x; swapy = y;
01499             y = x;
01500             x = y - 1;
01501         }
01502         y = ytop + i;
01503         x = y - 1;
01504     }
01505 
01506     /* fix symmetries */
01507     y = xtop; /* ytop is now where xtop used to be */
01508     for (i = 0; i < ysize-1 ; i++) {
01509         table->subtables[y].next = y + 1;
01510         y = y + 1;
01511     }
01512     table->subtables[y].next = xtop; /* y is bottom of its group, join */
01513                                      /* its symmetry to top of its group */
01514     x = y + 1;
01515     newxtop = x;
01516     for (i = 0; i < xsize - 1 ; i++) {
01517         table->subtables[x].next = x + 1;
01518         x = x + 1;
01519     }
01520     table->subtables[x].next = newxtop; /* x is bottom of its group, join */
01521                                         /* its symmetry to top of its group */
01522     /* Store group move */
01523     move = (Move *) cuddDynamicAllocNode(table);
01524     if (move == NULL) return(0);
01525     move->x = swapx;
01526     move->y = swapy;
01527     move->size = size;
01528     move->next = *moves;
01529     *moves = move;
01530 
01531     return(size);
01532 
01533 } /* end of ddSymmGroupMove */

static int ddSymmGroupMoveBackward ( 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 the number of keys in the table if successful; 0 otherwise.]

SideEffects [None]

Definition at line 1549 of file cuddSymmetry.c.

01553 {
01554     int size;
01555     int i,j;
01556     int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01557 
01558 #ifdef DD_DEBUG
01559     assert(x < y); /* We assume that x < y */
01560 #endif
01561 
01562     /* Find top, bottom, and size for the two groups. */
01563     xbot = x;
01564     xtop = table->subtables[x].next;
01565     xsize = xbot - xtop + 1;
01566     ybot = y;
01567     while ((unsigned) ybot < table->subtables[ybot].next)
01568         ybot = table->subtables[ybot].next;
01569     ytop = y;
01570     ysize = ybot - ytop + 1;
01571 
01572     /* Sift the variables of the second group up through the first group. */
01573     for (i = 1; i <= ysize; i++) {
01574         for (j = 1; j <= xsize; j++) {
01575             size = cuddSwapInPlace(table,x,y);
01576             if (size == 0) return(0);
01577             y = x;
01578             x = cuddNextLow(table,y);
01579         }
01580         y = ytop + i;
01581         x = y - 1;
01582     }
01583 
01584     /* Fix symmetries. */
01585     y = xtop;
01586     for (i = 0; i < ysize-1 ; i++) {
01587         table->subtables[y].next = y + 1;
01588         y = y + 1;
01589     }
01590     table->subtables[y].next = xtop; /* y is bottom of its group, join */
01591                                      /* its symmetry to top of its group */
01592     x = y + 1;
01593     newxtop = x;
01594     for (i = 0; i < xsize-1 ; i++) {
01595         table->subtables[x].next = x + 1;
01596         x = x + 1;
01597     }
01598     table->subtables[x].next = newxtop; /* x is bottom of its group, join */
01599                                         /* its symmetry to top of its group */
01600 
01601     return(size);
01602 
01603 } /* end of ddSymmGroupMoveBackward */

static int ddSymmSiftingAux ( DdManager table,
int  x,
int  xLow,
int  xHigh 
) [static]

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

Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]

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

SideEffects [None]

Definition at line 629 of file cuddSymmetry.c.

00634 {
00635     Move *move;
00636     Move *moveUp;       /* list of up moves */
00637     Move *moveDown;     /* list of down moves */
00638     int  initialSize;
00639     int  result;
00640     int  i;
00641     int  topbot;        /* index to either top or bottom of symmetry group */
00642     int  initGroupSize, finalGroupSize;
00643 
00644 
00645 #ifdef DD_DEBUG
00646     /* check for previously detected symmetry */
00647     assert(table->subtables[x].next == (unsigned) x);
00648 #endif
00649 
00650     initialSize = table->keys - table->isolated;
00651 
00652     moveDown = NULL;
00653     moveUp = NULL;
00654 
00655     if ((x - xLow) > (xHigh - x)) {
00656         /* Will go down first, unless x == xHigh:
00657         ** Look for consecutive symmetries above x.
00658         */
00659         for (i = x; i > xLow; i--) {
00660             if (!cuddSymmCheck(table,i-1,i))
00661                 break;
00662             topbot = table->subtables[i-1].next; /* find top of i-1's group */
00663             table->subtables[i-1].next = i;
00664             table->subtables[x].next = topbot; /* x is bottom of group so its */
00665                                                /* next is top of i-1's group */
00666             i = topbot + 1; /* add 1 for i--; new i is top of symm group */
00667         }
00668     } else {
00669         /* Will go up first unless x == xlow:
00670         ** Look for consecutive symmetries below x.
00671         */
00672         for (i = x; i < xHigh; i++) {
00673             if (!cuddSymmCheck(table,i,i+1))
00674                 break;
00675             /* find bottom of i+1's symm group */
00676             topbot = i + 1;
00677             while ((unsigned) topbot < table->subtables[topbot].next) {
00678                 topbot = table->subtables[topbot].next;
00679             }
00680             table->subtables[topbot].next = table->subtables[i].next;
00681             table->subtables[i].next = i + 1;
00682             i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */
00683         }
00684     }
00685 
00686     /* Now x may be in the middle of a symmetry group.
00687     ** Find bottom of x's symm group.
00688     */
00689     while ((unsigned) x < table->subtables[x].next)
00690         x = table->subtables[x].next;
00691 
00692     if (x == xLow) { /* Sift down */
00693 
00694 #ifdef DD_DEBUG
00695         /* x must be a singleton */
00696         assert((unsigned) x == table->subtables[x].next);
00697 #endif
00698         if (x == xHigh) return(1);      /* just one variable */
00699 
00700         initGroupSize = 1;
00701 
00702         moveDown = ddSymmSiftingDown(table,x,xHigh);
00703             /* after this point x --> xHigh, unless early term */
00704         if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00705         if (moveDown == NULL) return(1);
00706 
00707         x = moveDown->y;
00708         /* Find bottom of x's group */
00709         i = x;
00710         while ((unsigned) i < table->subtables[i].next) {
00711             i = table->subtables[i].next;
00712         }
00713 #ifdef DD_DEBUG
00714         /* x should be the top of the symmetry group and i the bottom */
00715         assert((unsigned) i >= table->subtables[i].next);
00716         assert((unsigned) x == table->subtables[i].next);
00717 #endif
00718         finalGroupSize = i - x + 1;
00719 
00720         if (initGroupSize == finalGroupSize) {
00721             /* No new symmetry groups detected, return to best position */
00722             result = ddSymmSiftingBackward(table,moveDown,initialSize);
00723         } else {
00724             initialSize = table->keys - table->isolated;
00725             moveUp = ddSymmSiftingUp(table,x,xLow);
00726             result = ddSymmSiftingBackward(table,moveUp,initialSize);
00727         }
00728         if (!result) goto ddSymmSiftingAuxOutOfMem;
00729 
00730     } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
00731         /* Find top of x's symm group */
00732         i = x;                          /* bottom */
00733         x = table->subtables[x].next;   /* top */
00734 
00735         if (x == xLow) return(1); /* just one big group */
00736 
00737         initGroupSize = i - x + 1;
00738 
00739         moveUp = ddSymmSiftingUp(table,x,xLow);
00740             /* after this point x --> xLow, unless early term */
00741         if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00742         if (moveUp == NULL) return(1);
00743 
00744         x = moveUp->x;
00745         /* Find top of x's group */
00746         i = table->subtables[x].next;
00747 #ifdef DD_DEBUG
00748         /* x should be the bottom of the symmetry group and i the top */
00749         assert((unsigned) x >= table->subtables[x].next);
00750         assert((unsigned) i == table->subtables[x].next);
00751 #endif
00752         finalGroupSize = x - i + 1;
00753 
00754         if (initGroupSize == finalGroupSize) {
00755             /* No new symmetry groups detected, return to best position */
00756             result = ddSymmSiftingBackward(table,moveUp,initialSize);
00757         } else {
00758             initialSize = table->keys - table->isolated;
00759             moveDown = ddSymmSiftingDown(table,x,xHigh);
00760             result = ddSymmSiftingBackward(table,moveDown,initialSize);
00761         }
00762         if (!result) goto ddSymmSiftingAuxOutOfMem;
00763 
00764     } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
00765 
00766         moveDown = ddSymmSiftingDown(table,x,xHigh);
00767         /* at this point x == xHigh, unless early term */
00768         if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00769 
00770         if (moveDown != NULL) {
00771             x = moveDown->y;    /* x is top here */
00772             i = x;
00773             while ((unsigned) i < table->subtables[i].next) {
00774                 i = table->subtables[i].next;
00775             }
00776         } else {
00777             i = x;
00778             while ((unsigned) i < table->subtables[i].next) {
00779                 i = table->subtables[i].next;
00780             }
00781             x = table->subtables[i].next;
00782         }
00783 #ifdef DD_DEBUG
00784         /* x should be the top of the symmetry group and i the bottom */
00785         assert((unsigned) i >= table->subtables[i].next);
00786         assert((unsigned) x == table->subtables[i].next);
00787 #endif
00788         initGroupSize = i - x + 1;
00789 
00790         moveUp = ddSymmSiftingUp(table,x,xLow);
00791         if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00792 
00793         if (moveUp != NULL) {
00794             x = moveUp->x;
00795             i = table->subtables[x].next;
00796         } else {
00797             i = x;
00798             while ((unsigned) x < table->subtables[x].next)
00799                 x = table->subtables[x].next;
00800         }
00801 #ifdef DD_DEBUG
00802         /* x should be the bottom of the symmetry group and i the top */
00803         assert((unsigned) x >= table->subtables[x].next);
00804         assert((unsigned) i == table->subtables[x].next);
00805 #endif
00806         finalGroupSize = x - i + 1;
00807 
00808         if (initGroupSize == finalGroupSize) {
00809             /* No new symmetry groups detected, return to best position */
00810             result = ddSymmSiftingBackward(table,moveUp,initialSize);
00811         } else {
00812             while (moveDown != NULL) {
00813                 move = moveDown->next;
00814                 cuddDeallocMove(table, moveDown);
00815                 moveDown = move;
00816             }
00817             initialSize = table->keys - table->isolated;
00818             moveDown = ddSymmSiftingDown(table,x,xHigh);
00819             result = ddSymmSiftingBackward(table,moveDown,initialSize);
00820         }
00821         if (!result) goto ddSymmSiftingAuxOutOfMem;
00822 
00823     } else { /* moving up first: shorter */
00824         /* Find top of x's symmetry group */
00825         x = table->subtables[x].next;
00826 
00827         moveUp = ddSymmSiftingUp(table,x,xLow);
00828         /* at this point x == xHigh, unless early term */
00829         if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00830 
00831         if (moveUp != NULL) {
00832             x = moveUp->x;
00833             i = table->subtables[x].next;
00834         } else {
00835             while ((unsigned) x < table->subtables[x].next)
00836                 x = table->subtables[x].next;
00837             i = table->subtables[x].next;
00838         }
00839 #ifdef DD_DEBUG
00840         /* x is bottom of the symmetry group and i is top */
00841         assert((unsigned) x >= table->subtables[x].next);
00842         assert((unsigned) i == table->subtables[x].next);
00843 #endif
00844         initGroupSize = x - i + 1;
00845 
00846         moveDown = ddSymmSiftingDown(table,x,xHigh);
00847         if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00848 
00849         if (moveDown != NULL) {
00850             x = moveDown->y;
00851             i = x;
00852             while ((unsigned) i < table->subtables[i].next) {
00853                 i = table->subtables[i].next;
00854             }
00855         } else {
00856             i = x;
00857             x = table->subtables[x].next;
00858         }
00859 #ifdef DD_DEBUG
00860         /* x should be the top of the symmetry group and i the bottom */
00861         assert((unsigned) i >= table->subtables[i].next);
00862         assert((unsigned) x == table->subtables[i].next);
00863 #endif
00864         finalGroupSize = i - x + 1;
00865 
00866         if (initGroupSize == finalGroupSize) {
00867             /* No new symmetries detected, go back to best position */
00868             result = ddSymmSiftingBackward(table,moveDown,initialSize);
00869         } else {
00870             while (moveUp != NULL) {
00871                 move = moveUp->next;
00872                 cuddDeallocMove(table, moveUp);
00873                 moveUp = move;
00874             }
00875             initialSize = table->keys - table->isolated;
00876             moveUp = ddSymmSiftingUp(table,x,xLow);
00877             result = ddSymmSiftingBackward(table,moveUp,initialSize);
00878         }
00879         if (!result) goto ddSymmSiftingAuxOutOfMem;
00880     }
00881 
00882     while (moveDown != NULL) {
00883         move = moveDown->next;
00884         cuddDeallocMove(table, moveDown);
00885         moveDown = move;
00886     }
00887     while (moveUp != NULL) {
00888         move = moveUp->next;
00889         cuddDeallocMove(table, moveUp);
00890         moveUp = move;
00891     }
00892 
00893     return(1);
00894 
00895 ddSymmSiftingAuxOutOfMem:
00896     if (moveDown != MV_OOM) {
00897         while (moveDown != NULL) {
00898             move = moveDown->next;
00899             cuddDeallocMove(table, moveDown);
00900             moveDown = move;
00901         }
00902     }
00903     if (moveUp != MV_OOM) {
00904         while (moveUp != NULL) {
00905             move = moveUp->next;
00906             cuddDeallocMove(table, moveUp);
00907             moveUp = move;
00908         }
00909     }
00910 
00911     return(0);
00912 
00913 } /* end of ddSymmSiftingAux */

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

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

Synopsis [Given a set of moves, returns the DD heap to the position giving the minimum size.]

Description [Given a set of moves, returns the DD 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]

Definition at line 1620 of file cuddSymmetry.c.

01624 {
01625     Move *move;
01626     int  res;
01627 
01628     for (move = moves; move != NULL; move = move->next) {
01629         if (move->size < size) {
01630             size = move->size;
01631         }
01632     }
01633 
01634     for (move = moves; move != NULL; move = move->next) {
01635         if (move->size == size) return(1);
01636         if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
01637             res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01638 #ifdef DD_DEBUG
01639             assert(table->subtables[move->x].next == move->x);
01640             assert(table->subtables[move->y].next == move->y);
01641 #endif
01642         } else { /* Group move necessary */
01643             res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
01644         }
01645         if (!res) return(0);
01646     }
01647 
01648     return(1);
01649 
01650 } /* end of ddSymmSiftingBackward */

static int ddSymmSiftingConvAux ( DdManager table,
int  x,
int  xLow,
int  xHigh 
) [static]

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

Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]

Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. 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]

Definition at line 931 of file cuddSymmetry.c.

00936 {
00937     Move *move;
00938     Move *moveUp;       /* list of up moves */
00939     Move *moveDown;     /* list of down moves */
00940     int  initialSize;
00941     int  result;
00942     int  i;
00943     int  initGroupSize, finalGroupSize;
00944 
00945 
00946     initialSize = table->keys - table->isolated;
00947 
00948     moveDown = NULL;
00949     moveUp = NULL;
00950 
00951     if (x == xLow) { /* Sift down */
00952 #ifdef DD_DEBUG
00953         /* x is bottom of symmetry group */
00954         assert((unsigned) x >= table->subtables[x].next);
00955 #endif
00956         i = table->subtables[x].next;
00957         initGroupSize = x - i + 1;
00958 
00959         moveDown = ddSymmSiftingDown(table,x,xHigh);
00960         /* at this point x == xHigh, unless early term */
00961         if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
00962         if (moveDown == NULL) return(1);
00963 
00964         x = moveDown->y;
00965         i = x;
00966         while ((unsigned) i < table->subtables[i].next) {
00967             i = table->subtables[i].next;
00968         }
00969 #ifdef DD_DEBUG
00970         /* x should be the top of the symmetric group and i the bottom */
00971         assert((unsigned) i >= table->subtables[i].next);
00972         assert((unsigned) x == table->subtables[i].next);
00973 #endif
00974         finalGroupSize = i - x + 1;
00975 
00976         if (initGroupSize == finalGroupSize) {
00977             /* No new symmetries detected, go back to best position */
00978             result = ddSymmSiftingBackward(table,moveDown,initialSize);
00979         } else {
00980             initialSize = table->keys - table->isolated;
00981             moveUp = ddSymmSiftingUp(table,x,xLow);
00982             result = ddSymmSiftingBackward(table,moveUp,initialSize);
00983         }
00984         if (!result) goto ddSymmSiftingConvAuxOutOfMem;
00985 
00986     } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
00987         /* Find top of x's symm group */
00988         while ((unsigned) x < table->subtables[x].next)
00989             x = table->subtables[x].next;
00990         i = x;                          /* bottom */
00991         x = table->subtables[x].next;   /* top */
00992 
00993         if (x == xLow) return(1);
00994 
00995         initGroupSize = i - x + 1;
00996 
00997         moveUp = ddSymmSiftingUp(table,x,xLow);
00998             /* at this point x == xLow, unless early term */
00999         if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01000         if (moveUp == NULL) return(1);
01001 
01002         x = moveUp->x;
01003         i = table->subtables[x].next;
01004 #ifdef DD_DEBUG
01005         /* x should be the bottom of the symmetry group and i the top */
01006         assert((unsigned) x >= table->subtables[x].next);
01007         assert((unsigned) i == table->subtables[x].next);
01008 #endif
01009         finalGroupSize = x - i + 1;
01010 
01011         if (initGroupSize == finalGroupSize) {
01012             /* No new symmetry groups detected, return to best position */
01013             result = ddSymmSiftingBackward(table,moveUp,initialSize);
01014         } else {
01015             initialSize = table->keys - table->isolated;
01016             moveDown = ddSymmSiftingDown(table,x,xHigh);
01017             result = ddSymmSiftingBackward(table,moveDown,initialSize);
01018         }
01019         if (!result)
01020             goto ddSymmSiftingConvAuxOutOfMem;
01021 
01022     } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
01023         moveDown = ddSymmSiftingDown(table,x,xHigh);
01024             /* at this point x == xHigh, unless early term */
01025         if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01026 
01027         if (moveDown != NULL) {
01028             x = moveDown->y;
01029             i = x;
01030             while ((unsigned) i < table->subtables[i].next) {
01031                 i = table->subtables[i].next;
01032             }
01033         } else {
01034             while ((unsigned) x < table->subtables[x].next)
01035                 x = table->subtables[x].next;
01036             i = x;
01037             x = table->subtables[x].next;
01038         }
01039 #ifdef DD_DEBUG
01040         /* x should be the top of the symmetry group and i the bottom */
01041         assert((unsigned) i >= table->subtables[i].next);
01042         assert((unsigned) x == table->subtables[i].next);
01043 #endif
01044         initGroupSize = i - x + 1;
01045 
01046         moveUp = ddSymmSiftingUp(table,x,xLow);
01047         if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01048 
01049         if (moveUp != NULL) {
01050             x = moveUp->x;
01051             i = table->subtables[x].next;
01052         } else {
01053             i = x;
01054             while ((unsigned) x < table->subtables[x].next)
01055                 x = table->subtables[x].next;
01056         }
01057 #ifdef DD_DEBUG
01058         /* x should be the bottom of the symmetry group and i the top */
01059         assert((unsigned) x >= table->subtables[x].next);
01060         assert((unsigned) i == table->subtables[x].next);
01061 #endif
01062         finalGroupSize = x - i + 1;
01063 
01064         if (initGroupSize == finalGroupSize) {
01065             /* No new symmetry groups detected, return to best position */
01066             result = ddSymmSiftingBackward(table,moveUp,initialSize);
01067         } else {
01068             while (moveDown != NULL) {
01069                 move = moveDown->next;
01070                 cuddDeallocMove(table, moveDown);
01071                 moveDown = move;
01072             }
01073             initialSize = table->keys - table->isolated;
01074             moveDown = ddSymmSiftingDown(table,x,xHigh);
01075             result = ddSymmSiftingBackward(table,moveDown,initialSize);
01076         }
01077         if (!result) goto ddSymmSiftingConvAuxOutOfMem;
01078 
01079     } else { /* moving up first: shorter */
01080         /* Find top of x's symmetry group */
01081         x = table->subtables[x].next;
01082 
01083         moveUp = ddSymmSiftingUp(table,x,xLow);
01084         /* at this point x == xHigh, unless early term */
01085         if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01086 
01087         if (moveUp != NULL) {
01088             x = moveUp->x;
01089             i = table->subtables[x].next;
01090         } else {
01091             i = x;
01092             while ((unsigned) x < table->subtables[x].next)
01093                 x = table->subtables[x].next;
01094         }
01095 #ifdef DD_DEBUG
01096         /* x is bottom of the symmetry group and i is top */
01097         assert((unsigned) x >= table->subtables[x].next);
01098         assert((unsigned) i == table->subtables[x].next);
01099 #endif
01100         initGroupSize = x - i + 1;
01101 
01102         moveDown = ddSymmSiftingDown(table,x,xHigh);
01103         if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01104 
01105         if (moveDown != NULL) {
01106             x = moveDown->y;
01107             i = x;
01108             while ((unsigned) i < table->subtables[i].next) {
01109                 i = table->subtables[i].next;
01110             }
01111         } else {
01112             i = x;
01113             x = table->subtables[x].next;
01114         }
01115 #ifdef DD_DEBUG
01116         /* x should be the top of the symmetry group and i the bottom */
01117         assert((unsigned) i >= table->subtables[i].next);
01118         assert((unsigned) x == table->subtables[i].next);
01119 #endif
01120         finalGroupSize = i - x + 1;
01121 
01122         if (initGroupSize == finalGroupSize) {
01123             /* No new symmetries detected, go back to best position */
01124             result = ddSymmSiftingBackward(table,moveDown,initialSize);
01125         } else {
01126             while (moveUp != NULL) {
01127                 move = moveUp->next;
01128                 cuddDeallocMove(table, moveUp);
01129                 moveUp = move;
01130             }
01131             initialSize = table->keys - table->isolated;
01132             moveUp = ddSymmSiftingUp(table,x,xLow);
01133             result = ddSymmSiftingBackward(table,moveUp,initialSize);
01134         }
01135         if (!result) goto ddSymmSiftingConvAuxOutOfMem;
01136     }
01137 
01138     while (moveDown != NULL) {
01139         move = moveDown->next;
01140         cuddDeallocMove(table, moveDown);
01141         moveDown = move;
01142     }
01143     while (moveUp != NULL) {
01144         move = moveUp->next;
01145         cuddDeallocMove(table, moveUp);
01146         moveUp = move;
01147     }
01148 
01149     return(1);
01150 
01151 ddSymmSiftingConvAuxOutOfMem:
01152     if (moveDown != MV_OOM) {
01153         while (moveDown != NULL) {
01154             move = moveDown->next;
01155             cuddDeallocMove(table, moveDown);
01156             moveDown = move;
01157         }
01158     }
01159     if (moveUp != MV_OOM) {
01160         while (moveUp != NULL) {
01161             move = moveUp->next;
01162             cuddDeallocMove(table, moveUp);
01163             moveUp = move;
01164         }
01165     }
01166 
01167     return(0);
01168 
01169 } /* end of ddSymmSiftingConvAux */

static Move * ddSymmSiftingDown ( DdManager table,
int  x,
int  xHigh 
) [static]

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

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

Description [Moves x down until either it reaches the bound (xHigh) or the size of the DD 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; MV_OOM if memory is full.]

SideEffects [None]

Definition at line 1330 of file cuddSymmetry.c.

01334 {
01335     Move *moves;
01336     Move *move;
01337     int  y;
01338     int  size;
01339     int  limitSize;
01340     int  gxtop,gybot;
01341     int  R;     /* upper bound on node decrease */
01342     int  xindex, yindex;
01343     int  isolated;
01344     int  z;
01345     int  zindex;
01346 #ifdef DD_DEBUG
01347     int  checkR;
01348 #endif
01349 
01350     moves = NULL;
01351     /* Initialize R */
01352     xindex = table->invperm[x];
01353     gxtop = table->subtables[x].next;
01354     limitSize = size = table->keys - table->isolated;
01355     R = 0;
01356     for (z = xHigh; z > gxtop; z--) {
01357         zindex = table->invperm[z];
01358         if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01359             isolated = table->vars[zindex]->ref == 1;
01360             R += table->subtables[z].keys - isolated;
01361         }
01362     }
01363 
01364     y = cuddNextHigh(table,x);
01365     while (y <= xHigh && size - R < limitSize) {
01366 #ifdef DD_DEBUG
01367         gxtop = table->subtables[x].next;
01368         checkR = 0;
01369         for (z = xHigh; z > gxtop; z--) {
01370             zindex = table->invperm[z];
01371             if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01372                 isolated = table->vars[zindex]->ref == 1;
01373                 checkR += table->subtables[z].keys - isolated;
01374             }
01375         }
01376         assert(R == checkR);
01377 #endif
01378         gybot = table->subtables[y].next;
01379         while (table->subtables[gybot].next != (unsigned) y)
01380             gybot = table->subtables[gybot].next;
01381         if (cuddSymmCheck(table,x,y)) {
01382             /* Symmetry found, attach symm groups */
01383             gxtop = table->subtables[x].next;
01384             table->subtables[x].next = y;
01385             table->subtables[gybot].next = gxtop;
01386         } else if (table->subtables[x].next == (unsigned) x &&
01387                    table->subtables[y].next == (unsigned) y) {
01388             /* x and y have self symmetry */
01389             /* Update upper bound on node decrease. */
01390             yindex = table->invperm[y];
01391             if (cuddTestInteract(table,xindex,yindex)) {
01392                 isolated = table->vars[yindex]->ref == 1;
01393                 R -= table->subtables[y].keys - isolated;
01394             }
01395             size = cuddSwapInPlace(table,x,y);
01396 #ifdef DD_DEBUG
01397             assert(table->subtables[x].next == (unsigned) x);
01398             assert(table->subtables[y].next == (unsigned) y);
01399 #endif
01400             if (size == 0) goto ddSymmSiftingDownOutOfMem;
01401             move = (Move *) cuddDynamicAllocNode(table);
01402             if (move == NULL) goto ddSymmSiftingDownOutOfMem;
01403             move->x = x;
01404             move->y = y;
01405             move->size = size;
01406             move->next = moves;
01407             moves = move;
01408             if ((double) size > (double) limitSize * table->maxGrowth)
01409                 return(moves);
01410             if (size < limitSize) limitSize = size;
01411         } else { /* Group move */
01412             /* Update upper bound on node decrease: first phase. */
01413             gxtop = table->subtables[x].next;
01414             z = gxtop + 1;
01415             do {
01416                 zindex = table->invperm[z];
01417                 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01418                     isolated = table->vars[zindex]->ref == 1;
01419                     R -= table->subtables[z].keys - isolated;
01420                 }
01421                 z++;
01422             } while (z <= gybot);
01423             size = ddSymmGroupMove(table,x,y,&moves);
01424             if (size == 0) goto ddSymmSiftingDownOutOfMem;
01425             if ((double) size > (double) limitSize * table->maxGrowth)
01426                 return(moves);
01427             if (size < limitSize) limitSize = size;
01428             /* Update upper bound on node decrease: second phase. */
01429             gxtop = table->subtables[gybot].next;
01430             for (z = gxtop + 1; z <= gybot; z++) {
01431                 zindex = table->invperm[z];
01432                 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01433                     isolated = table->vars[zindex]->ref == 1;
01434                     R += table->subtables[z].keys - isolated;
01435                 }
01436             }
01437         }
01438         x = gybot;
01439         y = cuddNextHigh(table,x);
01440     }
01441 
01442     return(moves);
01443 
01444 ddSymmSiftingDownOutOfMem:
01445     while (moves != NULL) {
01446         move = moves->next;
01447         cuddDeallocMove(table, moves);
01448         moves = move;
01449     }
01450     return(MV_OOM);
01451 
01452 } /* end of ddSymmSiftingDown */

static Move * ddSymmSiftingUp ( DdManager table,
int  y,
int  xLow 
) [static]

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

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

Description [Moves x up until either it reaches the bound (xLow) or the size of the DD 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; MV_OOM if memory is full.]

SideEffects [None]

Definition at line 1188 of file cuddSymmetry.c.

01192 {
01193     Move *moves;
01194     Move *move;
01195     int  x;
01196     int  size;
01197     int  i;
01198     int  gxtop,gybot;
01199     int  limitSize;
01200     int  xindex, yindex;
01201     int  zindex;
01202     int  z;
01203     int  isolated;
01204     int  L;     /* lower bound on DD size */
01205 #ifdef DD_DEBUG
01206     int  checkL;
01207 #endif
01208 
01209 
01210     moves = NULL;
01211     yindex = table->invperm[y];
01212 
01213     /* Initialize the lower bound.
01214     ** The part of the DD below the bottom of y' group will not change.
01215     ** The part of the DD above y that does not interact with y will not
01216     ** change. The rest may vanish in the best case, except for
01217     ** the nodes at level xLow, which will not vanish, regardless.
01218     */
01219     limitSize = L = table->keys - table->isolated;
01220     gybot = y;
01221     while ((unsigned) gybot < table->subtables[gybot].next)
01222         gybot = table->subtables[gybot].next;
01223     for (z = xLow + 1; z <= gybot; z++) {
01224         zindex = table->invperm[z];
01225         if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01226             isolated = table->vars[zindex]->ref == 1;
01227             L -= table->subtables[z].keys - isolated;
01228         }
01229     }
01230 
01231     x = cuddNextLow(table,y);
01232     while (x >= xLow && L <= limitSize) {
01233 #ifdef DD_DEBUG
01234         gybot = y;
01235         while ((unsigned) gybot < table->subtables[gybot].next)
01236             gybot = table->subtables[gybot].next;
01237         checkL = table->keys - table->isolated;
01238         for (z = xLow + 1; z <= gybot; z++) {
01239             zindex = table->invperm[z];
01240             if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01241                 isolated = table->vars[zindex]->ref == 1;
01242                 checkL -= table->subtables[z].keys - isolated;
01243             }
01244         }
01245         assert(L == checkL);
01246 #endif
01247         gxtop = table->subtables[x].next;
01248         if (cuddSymmCheck(table,x,y)) {
01249             /* Symmetry found, attach symm groups */
01250             table->subtables[x].next = y;
01251             i = table->subtables[y].next;
01252             while (table->subtables[i].next != (unsigned) y)
01253                 i = table->subtables[i].next;
01254             table->subtables[i].next = gxtop;
01255         } else if (table->subtables[x].next == (unsigned) x &&
01256                    table->subtables[y].next == (unsigned) y) {
01257             /* x and y have self symmetry */
01258             xindex = table->invperm[x];
01259             size = cuddSwapInPlace(table,x,y);
01260 #ifdef DD_DEBUG
01261             assert(table->subtables[x].next == (unsigned) x);
01262             assert(table->subtables[y].next == (unsigned) y);
01263 #endif
01264             if (size == 0) goto ddSymmSiftingUpOutOfMem;
01265             /* Update the lower bound. */
01266             if (cuddTestInteract(table,xindex,yindex)) {
01267                 isolated = table->vars[xindex]->ref == 1;
01268                 L += table->subtables[y].keys - isolated;
01269             }
01270             move = (Move *) cuddDynamicAllocNode(table);
01271             if (move == NULL) goto ddSymmSiftingUpOutOfMem;
01272             move->x = x;
01273             move->y = y;
01274             move->size = size;
01275             move->next = moves;
01276             moves = move;
01277             if ((double) size > (double) limitSize * table->maxGrowth)
01278                 return(moves);
01279             if (size < limitSize) limitSize = size;
01280         } else { /* Group move */
01281             size = ddSymmGroupMove(table,x,y,&moves);
01282             if (size == 0) goto ddSymmSiftingUpOutOfMem;
01283             /* Update the lower bound. */
01284             z = moves->y;
01285             do {
01286                 zindex = table->invperm[z];
01287                 if (cuddTestInteract(table,zindex,yindex)) {
01288                     isolated = table->vars[zindex]->ref == 1;
01289                     L += table->subtables[z].keys - isolated;
01290                 }
01291                 z = table->subtables[z].next;
01292             } while (z != (int) moves->y);
01293             if ((double) size > (double) limitSize * table->maxGrowth)
01294                 return(moves);
01295             if (size < limitSize) limitSize = size;
01296         }
01297         y = gxtop;
01298         x = cuddNextLow(table,y);
01299     }
01300 
01301     return(moves);
01302 
01303 ddSymmSiftingUpOutOfMem:
01304     while (moves != NULL) {
01305         move = moves->next;
01306         cuddDeallocMove(table, moves);
01307         moves = move;
01308     }
01309     return(MV_OOM);
01310 
01311 } /* end of ddSymmSiftingUp */

static void ddSymmSummary ( 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 1664 of file cuddSymmetry.c.

01670 {
01671     int i,x,gbot;
01672     int TotalSymm = 0;
01673     int TotalSymmGroups = 0;
01674 
01675     for (i = lower; i <= upper; i++) {
01676         if (table->subtables[i].next != (unsigned) i) {
01677             TotalSymmGroups++;
01678             x = i;
01679             do {
01680                 TotalSymm++;
01681                 gbot = x;
01682                 x = table->subtables[x].next;
01683             } while (x != i);
01684 #ifdef DD_DEBUG
01685             assert(table->subtables[gbot].next == (unsigned) i);
01686 #endif
01687             i = gbot;
01688         }
01689     }
01690     *symvars = TotalSymm;
01691     *symgroups = TotalSymmGroups;
01692 
01693     return;
01694 
01695 } /* end of ddSymmSummary */

static int ddSymmUniqueCompare ( int *  ptrX,
int *  ptrY 
) [static]

AutomaticStart

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

Synopsis [Comparison function used by qsort.]

Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.]

SideEffects [None]

Definition at line 601 of file cuddSymmetry.c.

00604 {
00605 #if 0
00606     if (entry[*ptrY] == entry[*ptrX]) {
00607         return((*ptrX) - (*ptrY));
00608     }
00609 #endif
00610     return(entry[*ptrY] - entry[*ptrX]);
00611 
00612 } /* end of ddSymmUniqueCompare */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $" [static]

Definition at line 90 of file cuddSymmetry.c.

Definition at line 103 of file cuddReorder.c.

int* entry [static]

Definition at line 93 of file cuddSymmetry.c.


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