src/cuBdd/cuddZddGroup.c File Reference

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

Go to the source code of this file.

Functions

static int zddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
static int zddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
static void zddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper)
static int zddUniqueCompareGroup (int *ptrX, int *ptrY)
static int zddGroupSifting (DdManager *table, int lower, int upper)
static int zddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh)
static int zddGroupSiftingUp (DdManager *table, int y, int xLow, Move **moves)
static int zddGroupSiftingDown (DdManager *table, int x, int xHigh, Move **moves)
static int zddGroupMove (DdManager *table, int x, int y, Move **moves)
static int zddGroupMoveBackward (DdManager *table, int x, int y)
static int zddGroupSiftingBackward (DdManager *table, Move *moves, int size)
static void zddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high)
MtrNodeCudd_MakeZddTreeNode (DdManager *dd, unsigned int low, unsigned int size, unsigned int type)
int cuddZddTreeSifting (DdManager *table, Cudd_ReorderingType method)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.20 2009/02/19 16:25:36 fabio Exp $"
static int * entry
int zddTotalNumberSwapping
static int pr = 0

Function Documentation

MtrNode* Cudd_MakeZddTreeNode ( DdManager dd,
unsigned int  low,
unsigned int  size,
unsigned int  type 
)

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

Synopsis [Creates a new ZDD variable group.]

Description [Creates a new ZDD variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.]

SideEffects [The ZDD variable tree is changed.]

SeeAlso [Cudd_MakeTreeNode]

Definition at line 159 of file cuddZddGroup.c.

00164 {
00165     MtrNode *group;
00166     MtrNode *tree;
00167     unsigned int level;
00168 
00169     /* If the variable does not exist yet, the position is assumed to be
00170     ** the same as the index. Therefore, applications that rely on
00171     ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
00172     ** variables have to create the variables before they group them.
00173     */
00174     level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low;
00175 
00176     if (level + size - 1> (int) MTR_MAXHIGH)
00177         return(NULL);
00178 
00179     /* If the tree does not exist yet, create it. */
00180     tree = dd->treeZ;
00181     if (tree == NULL) {
00182         dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ);
00183         if (tree == NULL)
00184             return(NULL);
00185         tree->index = dd->invpermZ[0];
00186     }
00187 
00188     /* Extend the upper bound of the tree if necessary. This allows the
00189     ** application to create groups even before the variables are created.
00190     */
00191     tree->size = ddMax(tree->size, level + size);
00192 
00193     /* Create the group. */
00194     group = Mtr_MakeGroup(tree, level, size, type);
00195     if (group == NULL)
00196         return(NULL);
00197 
00198     /* Initialize the index field to the index of the variable currently
00199     ** in position low. This field will be updated by the reordering
00200     ** procedure to provide a handle to the group once it has been moved.
00201     */
00202     group->index = (MtrHalfWord) low;
00203 
00204     return(group);
00205 
00206 } /* end of Cudd_MakeZddTreeNode */

int cuddZddTreeSifting ( DdManager table,
Cudd_ReorderingType  method 
)

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

Synopsis [Tree sifting algorithm for ZDDs.]

Description [Tree sifting algorithm for ZDDs. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling zddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 228 of file cuddZddGroup.c.

00231 {
00232     int i;
00233     int nvars;
00234     int result;
00235     int tempTree;
00236 
00237     /* If no tree is provided we create a temporary one in which all
00238     ** variables are in a single group. After reordering this tree is
00239     ** destroyed.
00240     */
00241     tempTree = table->treeZ == NULL;
00242     if (tempTree) {
00243         table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
00244         table->treeZ->index = table->invpermZ[0];
00245     }
00246     nvars = table->sizeZ;
00247 
00248 #ifdef DD_DEBUG
00249     if (pr > 0 && !tempTree)
00250         (void) fprintf(table->out,"cuddZddTreeSifting:");
00251     Mtr_PrintGroups(table->treeZ,pr <= 0);
00252 #endif
00253 #if 0
00254     /* Debugging code. */
00255     if (table->tree && table->treeZ) {
00256         (void) fprintf(table->out,"\n");
00257         Mtr_PrintGroups(table->tree, 0);
00258         cuddPrintVarGroups(table,table->tree,0,0);
00259         for (i = 0; i < table->size; i++) {
00260             (void) fprintf(table->out,"%s%d",
00261                            (i == 0) ? "" : ",", table->invperm[i]);
00262         }
00263         (void) fprintf(table->out,"\n");
00264         for (i = 0; i < table->size; i++) {
00265             (void) fprintf(table->out,"%s%d",
00266                            (i == 0) ? "" : ",", table->perm[i]);
00267         }
00268         (void) fprintf(table->out,"\n\n");
00269         Mtr_PrintGroups(table->treeZ,0);
00270         cuddPrintVarGroups(table,table->treeZ,1,0);
00271         for (i = 0; i < table->sizeZ; i++) {
00272             (void) fprintf(table->out,"%s%d",
00273                            (i == 0) ? "" : ",", table->invpermZ[i]);
00274         }
00275         (void) fprintf(table->out,"\n");
00276         for (i = 0; i < table->sizeZ; i++) {
00277             (void) fprintf(table->out,"%s%d",
00278                            (i == 0) ? "" : ",", table->permZ[i]);
00279         }
00280         (void) fprintf(table->out,"\n");
00281     }
00282     /* End of debugging code. */
00283 #endif
00284 #ifdef DD_STATS
00285     extsymmcalls = 0;
00286     extsymm = 0;
00287     secdiffcalls = 0;
00288     secdiff = 0;
00289     secdiffmisfire = 0;
00290 
00291     (void) fprintf(table->out,"\n");
00292     if (!tempTree)
00293         (void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
00294                        zddCountInternalMtrNodes(table,table->treeZ));
00295 #endif
00296 
00297     /* Initialize the group of each subtable to itself. Initially
00298     ** there are no groups. Groups are created according to the tree
00299     ** structure in postorder fashion.
00300     */
00301     for (i = 0; i < nvars; i++)
00302         table->subtableZ[i].next = i;
00303 
00304     /* Reorder. */
00305     result = zddTreeSiftingAux(table, table->treeZ, method);
00306 
00307 #ifdef DD_STATS         /* print stats */
00308     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00309         (table->groupcheck == CUDD_GROUP_CHECK7 ||
00310          table->groupcheck == CUDD_GROUP_CHECK5)) {
00311         (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00312         (void) fprintf(table->out,"extsymm = %d",extsymm);
00313     }
00314     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00315         table->groupcheck == CUDD_GROUP_CHECK7) {
00316         (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00317         (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00318         (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00319     }
00320 #endif
00321 
00322     if (tempTree)
00323         Cudd_FreeZddTree(table);
00324     return(result);
00325 
00326 } /* end of cuddZddTreeSifting */

static void zddFindNodeHiLo ( DdManager table,
MtrNode treenode,
int *  lower,
int *  upper 
) [static]

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

Synopsis [Finds the lower and upper bounds of the group represented by treenode.]

Description [Finds the lower and upper bounds of the group represented by treenode. The high and low fields of treenode are indices. From those we need to derive the current positions, and find maximum and minimum.]

SideEffects [The bounds are returned as side effects.]

SeeAlso []

Definition at line 530 of file cuddZddGroup.c.

00535 {
00536     int low;
00537     int high;
00538 
00539     /* Check whether no variables in this group already exist.
00540     ** If so, return immediately. The calling procedure will know from
00541     ** the values of upper that no reordering is needed.
00542     */
00543     if ((int) treenode->low >= table->sizeZ) {
00544         *lower = table->sizeZ;
00545         *upper = -1;
00546         return;
00547     }
00548 
00549     *lower = low = (unsigned int) table->permZ[treenode->index];
00550     high = (int) (low + treenode->size - 1);
00551 
00552     if (high >= table->sizeZ) {
00553         /* This is the case of a partially existing group. The aim is to
00554         ** reorder as many variables as safely possible.  If the tree
00555         ** node is terminal, we just reorder the subset of the group
00556         ** that is currently in existence.  If the group has
00557         ** subgroups, then we only reorder those subgroups that are
00558         ** fully instantiated.  This way we avoid breaking up a group.
00559         */
00560         MtrNode *auxnode = treenode->child;
00561         if (auxnode == NULL) {
00562             *upper = (unsigned int) table->sizeZ - 1;
00563         } else {
00564             /* Search the subgroup that strands the table->sizeZ line.
00565             ** If the first group starts at 0 and goes past table->sizeZ
00566             ** upper will get -1, thus correctly signaling that no reordering
00567             ** should take place.
00568             */
00569             while (auxnode != NULL) {
00570                 int thisLower = table->permZ[auxnode->low];
00571                 int thisUpper = thisLower + auxnode->size - 1;
00572                 if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
00573                     *upper = (unsigned int) thisLower - 1;
00574                 auxnode = auxnode->younger;
00575             }
00576         }
00577     } else {
00578         /* Normal case: All the variables of the group exist. */
00579         *upper = (unsigned int) high;
00580     }
00581 
00582 #ifdef DD_DEBUG
00583     /* Make sure that all variables in group are contiguous. */
00584     assert(treenode->size >= *upper - *lower + 1);
00585 #endif
00586 
00587     return;
00588 
00589 } /* end of zddFindNodeHiLo */

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

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

Synopsis [Swaps two groups and records the move.]

Description [Swaps two groups and records the move. Returns the number of keys in the DD table in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1074 of file cuddZddGroup.c.

01079 {
01080     Move *move;
01081     int  size;
01082     int  i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01083     int  swapx,swapy;
01084 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01085     int  initialSize,bestSize;
01086 #endif
01087 
01088 #ifdef DD_DEBUG
01089     /* We assume that x < y */
01090     assert(x < y);
01091 #endif
01092     /* Find top, bottom, and size for the two groups. */
01093     xbot = x;
01094     xtop = table->subtableZ[x].next;
01095     xsize = xbot - xtop + 1;
01096     ybot = y;
01097     while ((unsigned) ybot < table->subtableZ[ybot].next)
01098         ybot = table->subtableZ[ybot].next;
01099     ytop = y;
01100     ysize = ybot - ytop + 1;
01101 
01102 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01103     initialSize = bestSize = table->keysZ;
01104 #endif
01105     /* Sift the variables of the second group up through the first group */
01106     for (i = 1; i <= ysize; i++) {
01107         for (j = 1; j <= xsize; j++) {
01108             size = cuddZddSwapInPlace(table,x,y);
01109             if (size == 0) goto zddGroupMoveOutOfMem;
01110 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01111             if (size < bestSize)
01112                 bestSize = size;
01113 #endif
01114             swapx = x; swapy = y;
01115             y = x;
01116             x = cuddZddNextLow(table,y);
01117         }
01118         y = ytop + i;
01119         x = cuddZddNextLow(table,y);
01120     }
01121 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01122     if ((bestSize < initialSize) && (bestSize < size))
01123         (void) fprintf(table->out,"Missed local minimum: initialSize:%d  bestSize:%d  finalSize:%d\n",initialSize,bestSize,size);
01124 #endif
01125 
01126     /* fix groups */
01127     y = xtop; /* ytop is now where xtop used to be */
01128     for (i = 0; i < ysize - 1; i++) {
01129         table->subtableZ[y].next = cuddZddNextHigh(table,y);
01130         y = cuddZddNextHigh(table,y);
01131     }
01132     table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
01133                                     /* it to top of its group */
01134     x = cuddZddNextHigh(table,y);
01135     newxtop = x;
01136     for (i = 0; i < xsize - 1; i++) {
01137         table->subtableZ[x].next = cuddZddNextHigh(table,x);
01138         x = cuddZddNextHigh(table,x);
01139     }
01140     table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
01141                                     /* it to top of its group */
01142 #ifdef DD_DEBUG
01143     if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
01144 #endif
01145 
01146     /* Store group move */
01147     move = (Move *) cuddDynamicAllocNode(table);
01148     if (move == NULL) goto zddGroupMoveOutOfMem;
01149     move->x = swapx;
01150     move->y = swapy;
01151     move->flags = MTR_DEFAULT;
01152     move->size = table->keysZ;
01153     move->next = *moves;
01154     *moves = move;
01155 
01156     return(table->keysZ);
01157 
01158 zddGroupMoveOutOfMem:
01159     while (*moves != NULL) {
01160         move = (*moves)->next;
01161         cuddDeallocMove(table, *moves);
01162         *moves = move;
01163     }
01164     return(0);
01165 
01166 } /* end of zddGroupMove */

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

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

Synopsis [Undoes the swap two groups.]

Description [Undoes the swap two groups. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1180 of file cuddZddGroup.c.

01184 {
01185     int size;
01186     int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01187 
01188 
01189 #ifdef DD_DEBUG
01190     /* We assume that x < y */
01191     assert(x < y);
01192 #endif
01193 
01194     /* Find top, bottom, and size for the two groups. */
01195     xbot = x;
01196     xtop = table->subtableZ[x].next;
01197     xsize = xbot - xtop + 1;
01198     ybot = y;
01199     while ((unsigned) ybot < table->subtableZ[ybot].next)
01200         ybot = table->subtableZ[ybot].next;
01201     ytop = y;
01202     ysize = ybot - ytop + 1;
01203 
01204     /* Sift the variables of the second group up through the first group */
01205     for (i = 1; i <= ysize; i++) {
01206         for (j = 1; j <= xsize; j++) {
01207             size = cuddZddSwapInPlace(table,x,y);
01208             if (size == 0)
01209                 return(0);
01210             y = x;
01211             x = cuddZddNextLow(table,y);
01212         }
01213         y = ytop + i;
01214         x = cuddZddNextLow(table,y);
01215     }
01216 
01217     /* fix groups */
01218     y = xtop;
01219     for (i = 0; i < ysize - 1; i++) {
01220         table->subtableZ[y].next = cuddZddNextHigh(table,y);
01221         y = cuddZddNextHigh(table,y);
01222     }
01223     table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
01224                                     /* to its top */
01225     x = cuddZddNextHigh(table,y);
01226     newxtop = x;
01227     for (i = 0; i < xsize - 1; i++) {
01228         table->subtableZ[x].next = cuddZddNextHigh(table,x);
01229         x = cuddZddNextHigh(table,x);
01230     }
01231     table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
01232                                     /* to its top */
01233 #ifdef DD_DEBUG
01234     if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
01235 #endif
01236 
01237     return(1);
01238 
01239 } /* end of zddGroupMoveBackward */

static int zddGroupSifting ( DdManager table,
int  lower,
int  upper 
) [static]

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

Synopsis [Sifts from treenode->low to treenode->high.]

Description [Sifts from treenode->low to treenode->high. If croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the end of the initial sifting. If a group is created, it is then sifted again. After sifting one variable, the group that contains it is dissolved. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 633 of file cuddZddGroup.c.

00637 {
00638     int         *var;
00639     int         i,j,x,xInit;
00640     int         nvars;
00641     int         classes;
00642     int         result;
00643     int         *sifted;
00644 #ifdef DD_STATS
00645     unsigned    previousSize;
00646 #endif
00647     int         xindex;
00648 
00649     nvars = table->sizeZ;
00650 
00651     /* Order variables to sift. */
00652     entry = NULL;
00653     sifted = NULL;
00654     var = ALLOC(int,nvars);
00655     if (var == NULL) {
00656         table->errorCode = CUDD_MEMORY_OUT;
00657         goto zddGroupSiftingOutOfMem;
00658     }
00659     entry = ALLOC(int,nvars);
00660     if (entry == NULL) {
00661         table->errorCode = CUDD_MEMORY_OUT;
00662         goto zddGroupSiftingOutOfMem;
00663     }
00664     sifted = ALLOC(int,nvars);
00665     if (sifted == NULL) {
00666         table->errorCode = CUDD_MEMORY_OUT;
00667         goto zddGroupSiftingOutOfMem;
00668     }
00669 
00670     /* Here we consider only one representative for each group. */
00671     for (i = 0, classes = 0; i < nvars; i++) {
00672         sifted[i] = 0;
00673         x = table->permZ[i];
00674         if ((unsigned) x >= table->subtableZ[x].next) {
00675             entry[i] = table->subtableZ[x].keys;
00676             var[classes] = i;
00677             classes++;
00678         }
00679     }
00680 
00681     qsort((void *)var,classes,sizeof(int),(DD_QSFP)zddUniqueCompareGroup);
00682 
00683     /* Now sift. */
00684     for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00685         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00686             break;
00687         xindex = var[i];
00688         if (sifted[xindex] == 1) /* variable already sifted as part of group */
00689             continue;
00690         x = table->permZ[xindex]; /* find current level of this variable */
00691         if (x < lower || x > upper)
00692             continue;
00693 #ifdef DD_STATS
00694         previousSize = table->keysZ;
00695 #endif
00696 #ifdef DD_DEBUG
00697         /* x is bottom of group */
00698         assert((unsigned) x >= table->subtableZ[x].next);
00699 #endif
00700         result = zddGroupSiftingAux(table,x,lower,upper);
00701         if (!result) goto zddGroupSiftingOutOfMem;
00702 
00703 #ifdef DD_STATS
00704         if (table->keysZ < previousSize) {
00705             (void) fprintf(table->out,"-");
00706         } else if (table->keysZ > previousSize) {
00707             (void) fprintf(table->out,"+");
00708         } else {
00709             (void) fprintf(table->out,"=");
00710         }
00711         fflush(table->out);
00712 #endif
00713 
00714         /* Mark variables in the group just sifted. */
00715         x = table->permZ[xindex];
00716         if ((unsigned) x != table->subtableZ[x].next) {
00717             xInit = x;
00718             do {
00719                 j = table->invpermZ[x];
00720                 sifted[j] = 1;
00721                 x = table->subtableZ[x].next;
00722             } while (x != xInit);
00723         }
00724 
00725 #ifdef DD_DEBUG
00726         if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
00727 #endif
00728     } /* for */
00729 
00730     FREE(sifted);
00731     FREE(var);
00732     FREE(entry);
00733 
00734     return(1);
00735 
00736 zddGroupSiftingOutOfMem:
00737     if (entry != NULL)  FREE(entry);
00738     if (var != NULL)    FREE(var);
00739     if (sifted != NULL) FREE(sifted);
00740 
00741     return(0);
00742 
00743 } /* end of zddGroupSifting */

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

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

Synopsis [Sifts one variable up and down until it has taken all positions. Checks for aggregation.]

Description [Sifts one variable up and down until it has taken all positions. Checks for aggregation. There may be at most two sweeps, even if the group grows. Assumes that x is either an isolated variable, or it is the bottom of a group. All groups may not have been found. The variable being moved is returned to the best position seen during sifting. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 762 of file cuddZddGroup.c.

00767 {
00768     Move *move;
00769     Move *moves;        /* list of moves */
00770     int  initialSize;
00771     int  result;
00772 
00773 
00774 #ifdef DD_DEBUG
00775     if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
00776     assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */
00777 #endif
00778 
00779     initialSize = table->keysZ;
00780     moves = NULL;
00781 
00782     if (x == xLow) { /* Sift down */
00783 #ifdef DD_DEBUG
00784         /* x must be a singleton */
00785         assert((unsigned) x == table->subtableZ[x].next);
00786 #endif
00787         if (x == xHigh) return(1);      /* just one variable */
00788 
00789         if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00790             goto zddGroupSiftingAuxOutOfMem;
00791         /* at this point x == xHigh, unless early term */
00792 
00793         /* move backward and stop at best position */
00794         result = zddGroupSiftingBackward(table,moves,initialSize);
00795 #ifdef DD_DEBUG
00796         assert(table->keysZ <= (unsigned) initialSize);
00797 #endif
00798         if (!result) goto zddGroupSiftingAuxOutOfMem;
00799 
00800     } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */
00801 #ifdef DD_DEBUG
00802         /* x is bottom of group */
00803         assert((unsigned) x >= table->subtableZ[x].next);
00804 #endif
00805         /* Find top of x's group */
00806         x = table->subtableZ[x].next;
00807 
00808         if (!zddGroupSiftingUp(table,x,xLow,&moves))
00809             goto zddGroupSiftingAuxOutOfMem;
00810         /* at this point x == xLow, unless early term */
00811 
00812         /* move backward and stop at best position */
00813         result = zddGroupSiftingBackward(table,moves,initialSize);
00814 #ifdef DD_DEBUG
00815         assert(table->keysZ <= (unsigned) initialSize);
00816 #endif
00817         if (!result) goto zddGroupSiftingAuxOutOfMem;
00818 
00819     } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
00820         if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00821             goto zddGroupSiftingAuxOutOfMem;
00822         /* at this point x == xHigh, unless early term */
00823 
00824         /* Find top of group */
00825         if (moves) {
00826             x = moves->y;
00827         }
00828         while ((unsigned) x < table->subtableZ[x].next)
00829             x = table->subtableZ[x].next;
00830         x = table->subtableZ[x].next;
00831 #ifdef DD_DEBUG
00832         /* x should be the top of a group */
00833         assert((unsigned) x <= table->subtableZ[x].next);
00834 #endif
00835 
00836         if (!zddGroupSiftingUp(table,x,xLow,&moves))
00837             goto zddGroupSiftingAuxOutOfMem;
00838 
00839         /* move backward and stop at best position */
00840         result = zddGroupSiftingBackward(table,moves,initialSize);
00841 #ifdef DD_DEBUG
00842         assert(table->keysZ <= (unsigned) initialSize);
00843 #endif
00844         if (!result) goto zddGroupSiftingAuxOutOfMem;
00845 
00846     } else { /* moving up first: shorter */
00847         /* Find top of x's group */
00848         x = table->subtableZ[x].next;
00849 
00850         if (!zddGroupSiftingUp(table,x,xLow,&moves))
00851             goto zddGroupSiftingAuxOutOfMem;
00852         /* at this point x == xHigh, unless early term */
00853 
00854         if (moves) {
00855             x = moves->x;
00856         }
00857         while ((unsigned) x < table->subtableZ[x].next)
00858             x = table->subtableZ[x].next;
00859 #ifdef DD_DEBUG
00860         /* x is bottom of a group */
00861         assert((unsigned) x >= table->subtableZ[x].next);
00862 #endif
00863 
00864         if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00865             goto zddGroupSiftingAuxOutOfMem;
00866 
00867         /* move backward and stop at best position */
00868         result = zddGroupSiftingBackward(table,moves,initialSize);
00869 #ifdef DD_DEBUG
00870         assert(table->keysZ <= (unsigned) initialSize);
00871 #endif
00872         if (!result) goto zddGroupSiftingAuxOutOfMem;
00873     }
00874 
00875     while (moves != NULL) {
00876         move = moves->next;
00877         cuddDeallocMove(table, moves);
00878         moves = move;
00879     }
00880 
00881     return(1);
00882 
00883 zddGroupSiftingAuxOutOfMem:
00884     while (moves != NULL) {
00885         move = moves->next;
00886         cuddDeallocMove(table, moves);
00887         moves = move;
00888     }
00889 
00890     return(0);
00891 
00892 } /* end of zddGroupSiftingAux */

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

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

Synopsis [Determines the best position for a variables and returns it there.]

Description [Determines the best position for a variables and returns it there. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1254 of file cuddZddGroup.c.

01258 {
01259     Move *move;
01260     int  res;
01261 
01262 
01263     for (move = moves; move != NULL; move = move->next) {
01264         if (move->size < size) {
01265             size = move->size;
01266         }
01267     }
01268 
01269     for (move = moves; move != NULL; move = move->next) {
01270         if (move->size == size) return(1);
01271         if ((table->subtableZ[move->x].next == move->x) &&
01272         (table->subtableZ[move->y].next == move->y)) {
01273             res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
01274             if (!res) return(0);
01275 #ifdef DD_DEBUG
01276             if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
01277             assert(table->subtableZ[move->x].next == move->x);
01278             assert(table->subtableZ[move->y].next == move->y);
01279 #endif
01280         } else { /* Group move necessary */
01281             res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
01282             if (!res) return(0);
01283         }
01284     }
01285 
01286     return(1);
01287 
01288 } /* end of zddGroupSiftingBackward */

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

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

Synopsis [Sifts down a variable until it reaches position xHigh.]

Description [Sifts down a variable until it reaches position xHigh. Assumes that x is the bottom of a group (or a singleton). Records all the moves. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 988 of file cuddZddGroup.c.

00993 {
00994     Move *move;
00995     int  y;
00996     int  size;
00997     int  limitSize;
00998     int  gybot;
00999 
01000 
01001     /* Initialize R */
01002     limitSize = size = table->keysZ;
01003     y = cuddZddNextHigh(table,x);
01004     while (y <= xHigh) {
01005         /* Find bottom of y group. */
01006         gybot = table->subtableZ[y].next;
01007         while (table->subtableZ[gybot].next != (unsigned) y)
01008             gybot = table->subtableZ[gybot].next;
01009 
01010         if (table->subtableZ[x].next == (unsigned) x &&
01011             table->subtableZ[y].next == (unsigned) y) {
01012             /* x and y are self groups */
01013             size = cuddZddSwapInPlace(table,x,y);
01014 #ifdef DD_DEBUG
01015             assert(table->subtableZ[x].next == (unsigned) x);
01016             assert(table->subtableZ[y].next == (unsigned) y);
01017 #endif
01018             if (size == 0) goto zddGroupSiftingDownOutOfMem;
01019 
01020             /* Record move. */
01021             move = (Move *) cuddDynamicAllocNode(table);
01022             if (move == NULL) goto zddGroupSiftingDownOutOfMem;
01023             move->x = x;
01024             move->y = y;
01025             move->flags = MTR_DEFAULT;
01026             move->size = size;
01027             move->next = *moves;
01028             *moves = move;
01029 
01030 #ifdef DD_DEBUG
01031             if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
01032 #endif
01033             if ((double) size > (double) limitSize * table->maxGrowth)
01034                 return(1);
01035             if (size < limitSize) limitSize = size;
01036             x = y;
01037             y = cuddZddNextHigh(table,x);
01038         } else { /* Group move */
01039             size = zddGroupMove(table,x,y,moves);
01040             if (size == 0) goto zddGroupSiftingDownOutOfMem;
01041             if ((double) size > (double) limitSize * table->maxGrowth)
01042                 return(1);
01043             if (size < limitSize) limitSize = size;
01044         }
01045         x = gybot;
01046         y = cuddZddNextHigh(table,x);
01047     }
01048 
01049     return(1);
01050 
01051 zddGroupSiftingDownOutOfMem:
01052     while (*moves != NULL) {
01053         move = (*moves)->next;
01054         cuddDeallocMove(table, *moves);
01055         *moves = move;
01056     }
01057 
01058     return(0);
01059 
01060 } /* end of zddGroupSiftingDown */

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

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

Synopsis [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much.]

Description [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much. Assumes that y is the top of a group (or a singleton). Checks y for aggregation to the adjacent variables. Records all the moves that are appended to the list of moves received as input and returned as a side effect. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 911 of file cuddZddGroup.c.

00916 {
00917     Move *move;
00918     int  x;
00919     int  size;
00920     int  gxtop;
00921     int  limitSize;
00922 
00923     limitSize = table->keysZ;
00924 
00925     x = cuddZddNextLow(table,y);
00926     while (x >= xLow) {
00927         gxtop = table->subtableZ[x].next;
00928         if (table->subtableZ[x].next == (unsigned) x &&
00929             table->subtableZ[y].next == (unsigned) y) {
00930             /* x and y are self groups */
00931             size = cuddZddSwapInPlace(table,x,y);
00932 #ifdef DD_DEBUG
00933             assert(table->subtableZ[x].next == (unsigned) x);
00934             assert(table->subtableZ[y].next == (unsigned) y);
00935 #endif
00936             if (size == 0) goto zddGroupSiftingUpOutOfMem;
00937             move = (Move *)cuddDynamicAllocNode(table);
00938             if (move == NULL) goto zddGroupSiftingUpOutOfMem;
00939             move->x = x;
00940             move->y = y;
00941             move->flags = MTR_DEFAULT;
00942             move->size = size;
00943             move->next = *moves;
00944             *moves = move;
00945 
00946 #ifdef DD_DEBUG
00947             if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
00948 #endif
00949             if ((double) size > (double) limitSize * table->maxGrowth)
00950                 return(1);
00951             if (size < limitSize) limitSize = size;
00952         } else { /* group move */
00953             size = zddGroupMove(table,x,y,moves);
00954             if (size == 0) goto zddGroupSiftingUpOutOfMem;
00955             if ((double) size > (double) limitSize * table->maxGrowth)
00956                 return(1);
00957             if (size < limitSize) limitSize = size;
00958         }
00959         y = gxtop;
00960         x = cuddZddNextLow(table,y);
00961     }
00962 
00963     return(1);
00964 
00965 zddGroupSiftingUpOutOfMem:
00966     while (*moves != NULL) {
00967         move = (*moves)->next;
00968         cuddDeallocMove(table, *moves);
00969         *moves = move;
00970     }
00971     return(0);
00972 
00973 } /* end of zddGroupSiftingUp */

static void zddMergeGroups ( DdManager table,
MtrNode treenode,
int  low,
int  high 
) [static]

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

Synopsis [Merges groups in the DD table.]

Description [Creates a single group from low to high and adjusts the idex field of the tree node.]

SideEffects [None]

Definition at line 1302 of file cuddZddGroup.c.

01307 {
01308     int i;
01309     MtrNode *auxnode;
01310     int saveindex;
01311     int newindex;
01312 
01313     /* Merge all variables from low to high in one group, unless
01314     ** this is the topmost group. In such a case we do not merge lest
01315     ** we lose the symmetry information. */
01316     if (treenode != table->treeZ) {
01317         for (i = low; i < high; i++)
01318             table->subtableZ[i].next = i+1;
01319         table->subtableZ[high].next = low;
01320     }
01321 
01322     /* Adjust the index fields of the tree nodes. If a node is the
01323     ** first child of its parent, then the parent may also need adjustment. */
01324     saveindex = treenode->index;
01325     newindex = table->invpermZ[low];
01326     auxnode = treenode;
01327     do {
01328         auxnode->index = newindex;
01329         if (auxnode->parent == NULL ||
01330                 (int) auxnode->parent->index != saveindex)
01331             break;
01332         auxnode = auxnode->parent;
01333     } while (1);
01334     return;
01335 
01336 } /* end of zddMergeGroups */

static int zddReorderChildren ( DdManager table,
MtrNode treenode,
Cudd_ReorderingType  method 
) [static]

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

Synopsis [Reorders the children of a group tree node according to the options.]

Description [Reorders the children of a group tree node according to the options. After reordering puts all the variables in the group and/or its descendents in a single group. This allows hierarchical reordering. If the variables in the group do not exist yet, simply does nothing. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 429 of file cuddZddGroup.c.

00433 {
00434     int lower;
00435     int upper;
00436     int result;
00437     unsigned int initialSize;
00438 
00439     zddFindNodeHiLo(table,treenode,&lower,&upper);
00440     /* If upper == -1 these variables do not exist yet. */
00441     if (upper == -1)
00442         return(1);
00443 
00444     if (treenode->flags == MTR_FIXED) {
00445         result = 1;
00446     } else {
00447 #ifdef DD_STATS
00448         (void) fprintf(table->out," ");
00449 #endif
00450         switch (method) {
00451         case CUDD_REORDER_RANDOM:
00452         case CUDD_REORDER_RANDOM_PIVOT:
00453             result = cuddZddSwapping(table,lower,upper,method);
00454             break;
00455         case CUDD_REORDER_SIFT:
00456             result = cuddZddSifting(table,lower,upper);
00457             break;
00458         case CUDD_REORDER_SIFT_CONVERGE:
00459             do {
00460                 initialSize = table->keysZ;
00461                 result = cuddZddSifting(table,lower,upper);
00462                 if (initialSize <= table->keysZ)
00463                     break;
00464 #ifdef DD_STATS
00465                 else
00466                     (void) fprintf(table->out,"\n");
00467 #endif
00468             } while (result != 0);
00469             break;
00470         case CUDD_REORDER_SYMM_SIFT:
00471             result = cuddZddSymmSifting(table,lower,upper);
00472             break;
00473         case CUDD_REORDER_SYMM_SIFT_CONV:
00474             result = cuddZddSymmSiftingConv(table,lower,upper);
00475             break;
00476         case CUDD_REORDER_GROUP_SIFT:
00477             result = zddGroupSifting(table,lower,upper);
00478             break;
00479         case CUDD_REORDER_LINEAR:
00480             result = cuddZddLinearSifting(table,lower,upper);
00481             break;
00482         case CUDD_REORDER_LINEAR_CONVERGE:
00483             do {
00484                 initialSize = table->keysZ;
00485                 result = cuddZddLinearSifting(table,lower,upper);
00486                 if (initialSize <= table->keysZ)
00487                     break;
00488 #ifdef DD_STATS
00489                 else
00490                     (void) fprintf(table->out,"\n");
00491 #endif
00492             } while (result != 0);
00493             break;
00494         default:
00495             return(0);
00496         }
00497     }
00498 
00499     /* Create a single group for all the variables that were sifted,
00500     ** so that they will be treated as a single block by successive
00501     ** invocations of zddGroupSifting.
00502     */
00503     zddMergeGroups(table,treenode,lower,upper);
00504 
00505 #ifdef DD_DEBUG
00506     if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
00507 #endif
00508 
00509     return(result);
00510 
00511 } /* end of zddReorderChildren */

static int zddTreeSiftingAux ( DdManager table,
MtrNode treenode,
Cudd_ReorderingType  method 
) [static]

AutomaticStart

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

Synopsis [Visits the group tree and reorders each group.]

Description [Recursively visits the group tree and reorders each group in postorder fashion. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 345 of file cuddZddGroup.c.

00349 {
00350     MtrNode  *auxnode;
00351     int res;
00352 
00353 #ifdef DD_DEBUG
00354     Mtr_PrintGroups(treenode,1);
00355 #endif
00356 
00357     auxnode = treenode;
00358     while (auxnode != NULL) {
00359         if (auxnode->child != NULL) {
00360             if (!zddTreeSiftingAux(table, auxnode->child, method))
00361                 return(0);
00362             res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
00363             if (res == 0)
00364                 return(0);
00365         } else if (auxnode->size > 1) {
00366             if (!zddReorderChildren(table, auxnode, method))
00367                 return(0);
00368         }
00369         auxnode = auxnode->younger;
00370     }
00371 
00372     return(1);
00373 
00374 } /* end of zddTreeSiftingAux */

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

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 605 of file cuddZddGroup.c.

00608 {
00609 #if 0
00610     if (entry[*ptrY] == entry[*ptrX]) {
00611         return((*ptrX) - (*ptrY));
00612     }
00613 #endif
00614     return(entry[*ptrY] - entry[*ptrX]);
00615 
00616 } /* end of zddUniqueCompareGroup */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.20 2009/02/19 16:25:36 fabio Exp $" [static]

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

FileName [cuddZddGroup.c]

PackageName [cudd]

Synopsis [Functions for ZDD group sifting.]

Description [External procedures included in this file:

Internal procedures included in this file:

Static procedures included in this module:

]

Author [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 90 of file cuddZddGroup.c.

int* entry [static]

Definition at line 93 of file cuddZddGroup.c.

int pr = 0 [static]

Definition at line 103 of file cuddZddGroup.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