src/bdd/cudd/cuddZddGroup.c File Reference

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

Go to the source code of this file.

Functions

static int zddTreeSiftingAux ARGS ((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method))
static void zddFindNodeHiLo ARGS ((DdManager *table, MtrNode *treenode, int *lower, int *upper))
static int zddUniqueCompareGroup ARGS ((int *ptrX, int *ptrY))
static int zddGroupSifting ARGS ((DdManager *table, int lower, int upper))
static int zddGroupSiftingAux ARGS ((DdManager *table, int x, int xLow, int xHigh))
static int zddGroupSiftingUp ARGS ((DdManager *table, int y, int xLow, Move **moves))
static int zddGroupSiftingDown ARGS ((DdManager *table, int x, int xHigh, Move **moves))
static int zddGroupMove ARGS ((DdManager *table, int x, int y, Move **moves))
static int zddGroupMoveBackward ARGS ((DdManager *table, int x, int y))
static int zddGroupSiftingBackward ARGS ((DdManager *table, Move *moves, int size))
static void zddMergeGroups ARGS ((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)
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)

Variables

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

Function Documentation

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

AutomaticStart

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

00137 {
00138     MtrNode *group;
00139     MtrNode *tree;
00140     unsigned int level;
00141 
00142     /* If the variable does not exist yet, the position is assumed to be
00143     ** the same as the index. Therefore, applications that rely on
00144     ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
00145     ** variables have to create the variables before they group them.
00146     */
00147     level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low;
00148 
00149     if (level + size - 1> (int) MTR_MAXHIGH)
00150         return(NULL);
00151 
00152     /* If the tree does not exist yet, create it. */
00153     tree = dd->treeZ;
00154     if (tree == NULL) {
00155         dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ);
00156         if (tree == NULL)
00157             return(NULL);
00158         tree->index = dd->invpermZ[0];
00159     }
00160 
00161     /* Extend the upper bound of the tree if necessary. This allows the
00162     ** application to create groups even before the variables are created.
00163     */
00164     tree->size = ddMax(tree->size, level + size);
00165 
00166     /* Create the group. */
00167     group = Mtr_MakeGroup(tree, level, size, type);
00168     if (group == NULL)
00169         return(NULL);
00170 
00171     /* Initialize the index field to the index of the variable currently
00172     ** in position low. This field will be updated by the reordering
00173     ** procedure to provide a handle to the group once it has been moved.
00174     */
00175     group->index = (MtrHalfWord) low;
00176 
00177     return(group);
00178 
00179 } /* 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 201 of file cuddZddGroup.c.

00204 {
00205     int i;
00206     int nvars;
00207     int result;
00208     int tempTree;
00209 
00210     /* If no tree is provided we create a temporary one in which all
00211     ** variables are in a single group. After reordering this tree is
00212     ** destroyed.
00213     */
00214     tempTree = table->treeZ == NULL;
00215     if (tempTree) {
00216         table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
00217         table->treeZ->index = table->invpermZ[0];
00218     }
00219     nvars = table->sizeZ;
00220 
00221 #ifdef DD_DEBUG
00222     if (pr > 0 && !tempTree)
00223         (void) fprintf(table->out,"cuddZddTreeSifting:");
00224     Mtr_PrintGroups(table->treeZ,pr <= 0);
00225 #endif
00226 #if 0
00227     /* Debugging code. */
00228     if (table->tree && table->treeZ) {
00229         (void) fprintf(table->out,"\n");
00230         Mtr_PrintGroups(table->tree, 0);
00231         cuddPrintVarGroups(table,table->tree,0,0);
00232         for (i = 0; i < table->size; i++) {
00233             (void) fprintf(table->out,"%s%d",
00234                            (i == 0) ? "" : ",", table->invperm[i]);
00235         }
00236         (void) fprintf(table->out,"\n");
00237         for (i = 0; i < table->size; i++) {
00238             (void) fprintf(table->out,"%s%d",
00239                            (i == 0) ? "" : ",", table->perm[i]);
00240         }
00241         (void) fprintf(table->out,"\n\n");
00242         Mtr_PrintGroups(table->treeZ,0);
00243         cuddPrintVarGroups(table,table->treeZ,1,0);
00244         for (i = 0; i < table->sizeZ; i++) {
00245             (void) fprintf(table->out,"%s%d",
00246                            (i == 0) ? "" : ",", table->invpermZ[i]);
00247         }
00248         (void) fprintf(table->out,"\n");
00249         for (i = 0; i < table->sizeZ; i++) {
00250             (void) fprintf(table->out,"%s%d",
00251                            (i == 0) ? "" : ",", table->permZ[i]);
00252         }
00253         (void) fprintf(table->out,"\n");
00254     }
00255     /* End of debugging code. */
00256 #endif
00257 #ifdef DD_STATS
00258     extsymmcalls = 0;
00259     extsymm = 0;
00260     secdiffcalls = 0;
00261     secdiff = 0;
00262     secdiffmisfire = 0;
00263 
00264     (void) fprintf(table->out,"\n");
00265     if (!tempTree)
00266         (void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
00267                        zddCountInternalMtrNodes(table,table->treeZ));
00268 #endif
00269 
00270     /* Initialize the group of each subtable to itself. Initially
00271     ** there are no groups. Groups are created according to the tree
00272     ** structure in postorder fashion.
00273     */
00274     for (i = 0; i < nvars; i++)
00275         table->subtableZ[i].next = i;
00276 
00277     /* Reorder. */
00278     result = zddTreeSiftingAux(table, table->treeZ, method);
00279 
00280 #ifdef DD_STATS         /* print stats */
00281     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00282         (table->groupcheck == CUDD_GROUP_CHECK7 ||
00283          table->groupcheck == CUDD_GROUP_CHECK5)) {
00284         (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00285         (void) fprintf(table->out,"extsymm = %d",extsymm);
00286     }
00287     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00288         table->groupcheck == CUDD_GROUP_CHECK7) {
00289         (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00290         (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00291         (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00292     }
00293 #endif
00294 
00295     if (tempTree)
00296         Cudd_FreeZddTree(table);
00297     return(result);
00298 
00299 } /* 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 503 of file cuddZddGroup.c.

00508 {
00509     int low;
00510     int high;
00511 
00512     /* Check whether no variables in this group already exist.
00513     ** If so, return immediately. The calling procedure will know from
00514     ** the values of upper that no reordering is needed.
00515     */
00516     if ((int) treenode->low >= table->sizeZ) {
00517         *lower = table->sizeZ;
00518         *upper = -1;
00519         return;
00520     }
00521 
00522     *lower = low = (unsigned int) table->permZ[treenode->index];
00523     high = (int) (low + treenode->size - 1);
00524 
00525     if (high >= table->sizeZ) {
00526         /* This is the case of a partially existing group. The aim is to
00527         ** reorder as many variables as safely possible.  If the tree
00528         ** node is terminal, we just reorder the subset of the group
00529         ** that is currently in existence.  If the group has
00530         ** subgroups, then we only reorder those subgroups that are
00531         ** fully instantiated.  This way we avoid breaking up a group.
00532         */
00533         MtrNode *auxnode = treenode->child;
00534         if (auxnode == NULL) {
00535             *upper = (unsigned int) table->sizeZ - 1;
00536         } else {
00537             /* Search the subgroup that strands the table->sizeZ line.
00538             ** If the first group starts at 0 and goes past table->sizeZ
00539             ** upper will get -1, thus correctly signaling that no reordering
00540             ** should take place.
00541             */
00542             while (auxnode != NULL) {
00543                 int thisLower = table->permZ[auxnode->low];
00544                 int thisUpper = thisLower + auxnode->size - 1;
00545                 if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
00546                     *upper = (unsigned int) thisLower - 1;
00547                 auxnode = auxnode->younger;
00548             }
00549         }
00550     } else {
00551         /* Normal case: All the variables of the group exist. */
00552         *upper = (unsigned int) high;
00553     }
00554 
00555 #ifdef DD_DEBUG
00556     /* Make sure that all variables in group are contiguous. */
00557     assert(treenode->size >= *upper - *lower + 1);
00558 #endif
00559 
00560     return;
00561 
00562 } /* 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 1054 of file cuddZddGroup.c.

01059 {
01060     Move *move;
01061     int  size;
01062     int  i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01063     int  swapx,swapy;
01064 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01065     int  initialSize,bestSize;
01066 #endif
01067 
01068 #if DD_DEBUG
01069     /* We assume that x < y */
01070     assert(x < y);
01071 #endif
01072     /* Find top, bottom, and size for the two groups. */
01073     xbot = x;
01074     xtop = table->subtableZ[x].next;
01075     xsize = xbot - xtop + 1;
01076     ybot = y;
01077     while ((unsigned) ybot < table->subtableZ[ybot].next)
01078         ybot = table->subtableZ[ybot].next;
01079     ytop = y;
01080     ysize = ybot - ytop + 1;
01081 
01082 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01083     initialSize = bestSize = table->keysZ;
01084 #endif
01085     /* Sift the variables of the second group up through the first group */
01086     for (i = 1; i <= ysize; i++) {
01087         for (j = 1; j <= xsize; j++) {
01088             size = cuddZddSwapInPlace(table,x,y);
01089             if (size == 0) goto zddGroupMoveOutOfMem;
01090 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01091             if (size < bestSize)
01092                 bestSize = size;
01093 #endif
01094             swapx = x; swapy = y;
01095             y = x;
01096             x = cuddZddNextLow(table,y);
01097         }
01098         y = ytop + i;
01099         x = cuddZddNextLow(table,y);
01100     }
01101 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01102     if ((bestSize < initialSize) && (bestSize < size))
01103         (void) fprintf(table->out,"Missed local minimum: initialSize:%d  bestSize:%d  finalSize:%d\n",initialSize,bestSize,size);
01104 #endif
01105 
01106     /* fix groups */
01107     y = xtop; /* ytop is now where xtop used to be */
01108     for (i = 0; i < ysize - 1; i++) {
01109         table->subtableZ[y].next = cuddZddNextHigh(table,y);
01110         y = cuddZddNextHigh(table,y);
01111     }
01112     table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
01113                                     /* it to top of its group */
01114     x = cuddZddNextHigh(table,y);
01115     newxtop = x;
01116     for (i = 0; i < xsize - 1; i++) {
01117         table->subtableZ[x].next = cuddZddNextHigh(table,x);
01118         x = cuddZddNextHigh(table,x);
01119     }
01120     table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
01121                                     /* it to top of its group */
01122 #ifdef DD_DEBUG
01123     if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
01124 #endif
01125 
01126     /* Store group move */
01127     move = (Move *) cuddDynamicAllocNode(table);
01128     if (move == NULL) goto zddGroupMoveOutOfMem;
01129     move->x = swapx;
01130     move->y = swapy;
01131     move->flags = MTR_DEFAULT;
01132     move->size = table->keysZ;
01133     move->next = *moves;
01134     *moves = move;
01135 
01136     return(table->keysZ);
01137 
01138 zddGroupMoveOutOfMem:
01139     while (*moves != NULL) {
01140         move = (*moves)->next;
01141         cuddDeallocNode(table, (DdNode *) *moves);
01142         *moves = move;
01143     }
01144     return(0);
01145 
01146 } /* 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 1160 of file cuddZddGroup.c.

01164 {
01165     int size;
01166     int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01167 
01168 
01169 #if DD_DEBUG
01170     /* We assume that x < y */
01171     assert(x < y);
01172 #endif
01173 
01174     /* Find top, bottom, and size for the two groups. */
01175     xbot = x;
01176     xtop = table->subtableZ[x].next;
01177     xsize = xbot - xtop + 1;
01178     ybot = y;
01179     while ((unsigned) ybot < table->subtableZ[ybot].next)
01180         ybot = table->subtableZ[ybot].next;
01181     ytop = y;
01182     ysize = ybot - ytop + 1;
01183 
01184     /* Sift the variables of the second group up through the first group */
01185     for (i = 1; i <= ysize; i++) {
01186         for (j = 1; j <= xsize; j++) {
01187             size = cuddZddSwapInPlace(table,x,y);
01188             if (size == 0)
01189                 return(0);
01190             y = x;
01191             x = cuddZddNextLow(table,y);
01192         }
01193         y = ytop + i;
01194         x = cuddZddNextLow(table,y);
01195     }
01196 
01197     /* fix groups */
01198     y = xtop;
01199     for (i = 0; i < ysize - 1; i++) {
01200         table->subtableZ[y].next = cuddZddNextHigh(table,y);
01201         y = cuddZddNextHigh(table,y);
01202     }
01203     table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
01204                                     /* to its top */
01205     x = cuddZddNextHigh(table,y);
01206     newxtop = x;
01207     for (i = 0; i < xsize - 1; i++) {
01208         table->subtableZ[x].next = cuddZddNextHigh(table,x);
01209         x = cuddZddNextHigh(table,x);
01210     }
01211     table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
01212                                     /* to its top */
01213 #ifdef DD_DEBUG
01214     if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
01215 #endif
01216 
01217     return(1);
01218 
01219 } /* 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 606 of file cuddZddGroup.c.

00610 {
00611     int         *var;
00612     int         i,j,x,xInit;
00613     int         nvars;
00614     int         classes;
00615     int         result;
00616     int         *sifted;
00617 #ifdef DD_STATS
00618     unsigned    previousSize;
00619 #endif
00620     int         xindex;
00621 
00622     nvars = table->sizeZ;
00623 
00624     /* Order variables to sift. */
00625     entry = NULL;
00626     sifted = NULL;
00627     var = ALLOC(int,nvars);
00628     if (var == NULL) {
00629         table->errorCode = CUDD_MEMORY_OUT;
00630         goto zddGroupSiftingOutOfMem;
00631     }
00632     entry = ALLOC(int,nvars);
00633     if (entry == NULL) {
00634         table->errorCode = CUDD_MEMORY_OUT;
00635         goto zddGroupSiftingOutOfMem;
00636     }
00637     sifted = ALLOC(int,nvars);
00638     if (sifted == NULL) {
00639         table->errorCode = CUDD_MEMORY_OUT;
00640         goto zddGroupSiftingOutOfMem;
00641     }
00642 
00643     /* Here we consider only one representative for each group. */
00644     for (i = 0, classes = 0; i < nvars; i++) {
00645         sifted[i] = 0;
00646         x = table->permZ[i];
00647         if ((unsigned) x >= table->subtableZ[x].next) {
00648             entry[i] = table->subtableZ[x].keys;
00649             var[classes] = i;
00650             classes++;
00651         }
00652     }
00653 
00654     qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))zddUniqueCompareGroup);
00655 
00656     /* Now sift. */
00657     for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00658         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00659             break;
00660         xindex = var[i];
00661         if (sifted[xindex] == 1) /* variable already sifted as part of group */
00662             continue;
00663         x = table->permZ[xindex]; /* find current level of this variable */
00664         if (x < lower || x > upper)
00665             continue;
00666 #ifdef DD_STATS
00667         previousSize = table->keysZ;
00668 #endif
00669 #ifdef DD_DEBUG
00670         /* x is bottom of group */
00671         assert((unsigned) x >= table->subtableZ[x].next);
00672 #endif
00673         result = zddGroupSiftingAux(table,x,lower,upper);
00674         if (!result) goto zddGroupSiftingOutOfMem;
00675 
00676 #ifdef DD_STATS
00677         if (table->keysZ < previousSize) {
00678             (void) fprintf(table->out,"-");
00679         } else if (table->keysZ > previousSize) {
00680             (void) fprintf(table->out,"+");
00681         } else {
00682             (void) fprintf(table->out,"=");
00683         }
00684         fflush(table->out);
00685 #endif
00686 
00687         /* Mark variables in the group just sifted. */
00688         x = table->permZ[xindex];
00689         if ((unsigned) x != table->subtableZ[x].next) {
00690             xInit = x;
00691             do {
00692                 j = table->invpermZ[x];
00693                 sifted[j] = 1;
00694                 x = table->subtableZ[x].next;
00695             } while (x != xInit);
00696         }
00697 
00698 #ifdef DD_DEBUG
00699         if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
00700 #endif
00701     } /* for */
00702 
00703     FREE(sifted);
00704     FREE(var);
00705     FREE(entry);
00706 
00707     return(1);
00708 
00709 zddGroupSiftingOutOfMem:
00710     if (entry != NULL)  FREE(entry);
00711     if (var != NULL)    FREE(var);
00712     if (sifted != NULL) FREE(sifted);
00713 
00714     return(0);
00715 
00716 } /* 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 735 of file cuddZddGroup.c.

00740 {
00741     Move *move;
00742     Move *moves;        /* list of moves */
00743     int  initialSize;
00744     int  result;
00745 
00746 
00747 #ifdef DD_DEBUG
00748     if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
00749     assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */
00750 #endif
00751 
00752     initialSize = table->keysZ;
00753     moves = NULL;
00754 
00755     if (x == xLow) { /* Sift down */
00756 #ifdef DD_DEBUG
00757         /* x must be a singleton */
00758         assert((unsigned) x == table->subtableZ[x].next);
00759 #endif
00760         if (x == xHigh) return(1);      /* just one variable */
00761 
00762         if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00763             goto zddGroupSiftingAuxOutOfMem;
00764         /* at this point x == xHigh, unless early term */
00765 
00766         /* move backward and stop at best position */
00767         result = zddGroupSiftingBackward(table,moves,initialSize);
00768 #ifdef DD_DEBUG
00769         assert(table->keysZ <= (unsigned) initialSize);
00770 #endif
00771         if (!result) goto zddGroupSiftingAuxOutOfMem;
00772 
00773     } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */
00774 #ifdef DD_DEBUG
00775         /* x is bottom of group */
00776         assert((unsigned) x >= table->subtableZ[x].next);
00777 #endif
00778         /* Find top of x's group */
00779         x = table->subtableZ[x].next;
00780 
00781         if (!zddGroupSiftingUp(table,x,xLow,&moves))
00782             goto zddGroupSiftingAuxOutOfMem;
00783         /* at this point x == xLow, unless early term */
00784 
00785         /* move backward and stop at best position */
00786         result = zddGroupSiftingBackward(table,moves,initialSize);
00787 #ifdef DD_DEBUG
00788         assert(table->keysZ <= (unsigned) initialSize);
00789 #endif
00790         if (!result) goto zddGroupSiftingAuxOutOfMem;
00791 
00792     } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
00793         if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00794             goto zddGroupSiftingAuxOutOfMem;
00795         /* at this point x == xHigh, unless early term */
00796 
00797         /* Find top of group */
00798         if (moves) {
00799             x = moves->y;
00800         }
00801         while ((unsigned) x < table->subtableZ[x].next)
00802             x = table->subtableZ[x].next;
00803         x = table->subtableZ[x].next;
00804 #ifdef DD_DEBUG
00805         /* x should be the top of a group */
00806         assert((unsigned) x <= table->subtableZ[x].next);
00807 #endif
00808 
00809         if (!zddGroupSiftingUp(table,x,xLow,&moves))
00810             goto zddGroupSiftingAuxOutOfMem;
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 { /* moving up first: shorter */
00820         /* Find top of x's group */
00821         x = table->subtableZ[x].next;
00822 
00823         if (!zddGroupSiftingUp(table,x,xLow,&moves))
00824             goto zddGroupSiftingAuxOutOfMem;
00825         /* at this point x == xHigh, unless early term */
00826 
00827         if (moves) {
00828             x = moves->x;
00829         }
00830         while ((unsigned) x < table->subtableZ[x].next)
00831             x = table->subtableZ[x].next;
00832 #ifdef DD_DEBUG
00833         /* x is bottom of a group */
00834         assert((unsigned) x >= table->subtableZ[x].next);
00835 #endif
00836 
00837         if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00838             goto zddGroupSiftingAuxOutOfMem;
00839 
00840         /* move backward and stop at best position */
00841         result = zddGroupSiftingBackward(table,moves,initialSize);
00842 #ifdef DD_DEBUG
00843         assert(table->keysZ <= (unsigned) initialSize);
00844 #endif
00845         if (!result) goto zddGroupSiftingAuxOutOfMem;
00846     }
00847 
00848     while (moves != NULL) {
00849         move = moves->next;
00850         cuddDeallocNode(table, (DdNode *) moves);
00851         moves = move;
00852     }
00853 
00854     return(1);
00855 
00856 zddGroupSiftingAuxOutOfMem:
00857     while (moves != NULL) {
00858         move = moves->next;
00859         cuddDeallocNode(table, (DdNode *) moves);
00860         moves = move;
00861     }
00862 
00863     return(0);
00864 
00865 } /* 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 1234 of file cuddZddGroup.c.

01238 {
01239     Move *move;
01240     int  res;
01241 
01242 
01243     for (move = moves; move != NULL; move = move->next) {
01244         if (move->size < size) {
01245             size = move->size;
01246         }
01247     }
01248 
01249     for (move = moves; move != NULL; move = move->next) {
01250         if (move->size == size) return(1);
01251         if ((table->subtableZ[move->x].next == move->x) &&
01252         (table->subtableZ[move->y].next == move->y)) {
01253             res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
01254             if (!res) return(0);
01255 #ifdef DD_DEBUG
01256             if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
01257             assert(table->subtableZ[move->x].next == move->x);
01258             assert(table->subtableZ[move->y].next == move->y);
01259 #endif
01260         } else { /* Group move necessary */
01261             res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
01262             if (!res) return(0);
01263         }
01264     }
01265 
01266     return(1);
01267 
01268 } /* 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 965 of file cuddZddGroup.c.

00970 {
00971     Move *move;
00972     int  y;
00973     int  size;
00974     int  limitSize;
00975     int  gxtop,gybot;
00976     int  xindex;
00977 
00978 
00979     /* Initialize R */
00980     xindex = table->invpermZ[x];
00981     gxtop = table->subtableZ[x].next;
00982     limitSize = size = table->keysZ;
00983     y = cuddZddNextHigh(table,x);
00984     while (y <= xHigh) {
00985         /* Find bottom of y group. */
00986         gybot = table->subtableZ[y].next;
00987         while (table->subtableZ[gybot].next != (unsigned) y)
00988             gybot = table->subtableZ[gybot].next;
00989 
00990         if (table->subtableZ[x].next == (unsigned) x &&
00991             table->subtableZ[y].next == (unsigned) y) {
00992             /* x and y are self groups */
00993             size = cuddZddSwapInPlace(table,x,y);
00994 #ifdef DD_DEBUG
00995             assert(table->subtableZ[x].next == (unsigned) x);
00996             assert(table->subtableZ[y].next == (unsigned) y);
00997 #endif
00998             if (size == 0) goto zddGroupSiftingDownOutOfMem;
00999 
01000             /* Record move. */
01001             move = (Move *) cuddDynamicAllocNode(table);
01002             if (move == NULL) goto zddGroupSiftingDownOutOfMem;
01003             move->x = x;
01004             move->y = y;
01005             move->flags = MTR_DEFAULT;
01006             move->size = size;
01007             move->next = *moves;
01008             *moves = move;
01009 
01010 #ifdef DD_DEBUG
01011             if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
01012 #endif
01013             if ((double) size > (double) limitSize * table->maxGrowth)
01014                 return(1);
01015             if (size < limitSize) limitSize = size;
01016             x = y;
01017             y = cuddZddNextHigh(table,x);
01018         } else { /* Group move */
01019             size = zddGroupMove(table,x,y,moves);
01020             if (size == 0) goto zddGroupSiftingDownOutOfMem;
01021             if ((double) size > (double) limitSize * table->maxGrowth)
01022                 return(1);
01023             if (size < limitSize) limitSize = size;
01024         }
01025         x = gybot;
01026         y = cuddZddNextHigh(table,x);
01027     }
01028 
01029     return(1);
01030 
01031 zddGroupSiftingDownOutOfMem:
01032     while (*moves != NULL) {
01033         move = (*moves)->next;
01034         cuddDeallocNode(table, (DdNode *) *moves);
01035         *moves = move;
01036     }
01037 
01038     return(0);
01039 
01040 } /* 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 884 of file cuddZddGroup.c.

00889 {
00890     Move *move;
00891     int  x;
00892     int  size;
00893     int  gxtop;
00894     int  limitSize;
00895     int  xindex, yindex;
00896 
00897     yindex = table->invpermZ[y];
00898 
00899     limitSize = table->keysZ;
00900 
00901     x = cuddZddNextLow(table,y);
00902     while (x >= xLow) {
00903         gxtop = table->subtableZ[x].next;
00904         if (table->subtableZ[x].next == (unsigned) x &&
00905             table->subtableZ[y].next == (unsigned) y) {
00906             /* x and y are self groups */
00907             xindex = table->invpermZ[x];
00908             size = cuddZddSwapInPlace(table,x,y);
00909 #ifdef DD_DEBUG
00910             assert(table->subtableZ[x].next == (unsigned) x);
00911             assert(table->subtableZ[y].next == (unsigned) y);
00912 #endif
00913             if (size == 0) goto zddGroupSiftingUpOutOfMem;
00914             move = (Move *)cuddDynamicAllocNode(table);
00915             if (move == NULL) goto zddGroupSiftingUpOutOfMem;
00916             move->x = x;
00917             move->y = y;
00918             move->flags = MTR_DEFAULT;
00919             move->size = size;
00920             move->next = *moves;
00921             *moves = move;
00922 
00923 #ifdef DD_DEBUG
00924             if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
00925 #endif
00926             if ((double) size > (double) limitSize * table->maxGrowth)
00927                 return(1);
00928             if (size < limitSize) limitSize = size;
00929         } else { /* group move */
00930             size = zddGroupMove(table,x,y,moves);
00931             if (size == 0) goto zddGroupSiftingUpOutOfMem;
00932             if ((double) size > (double) limitSize * table->maxGrowth)
00933                 return(1);
00934             if (size < limitSize) limitSize = size;
00935         }
00936         y = gxtop;
00937         x = cuddZddNextLow(table,y);
00938     }
00939 
00940     return(1);
00941 
00942 zddGroupSiftingUpOutOfMem:
00943     while (*moves != NULL) {
00944         move = (*moves)->next;
00945         cuddDeallocNode(table, (DdNode *) *moves);
00946         *moves = move;
00947     }
00948     return(0);
00949 
00950 } /* 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 1282 of file cuddZddGroup.c.

01287 {
01288     int i;
01289     MtrNode *auxnode;
01290     int saveindex;
01291     int newindex;
01292 
01293     /* Merge all variables from low to high in one group, unless
01294     ** this is the topmost group. In such a case we do not merge lest
01295     ** we lose the symmetry information. */
01296     if (treenode != table->treeZ) {
01297         for (i = low; i < high; i++)
01298             table->subtableZ[i].next = i+1;
01299         table->subtableZ[high].next = low;
01300     }
01301 
01302     /* Adjust the index fields of the tree nodes. If a node is the
01303     ** first child of its parent, then the parent may also need adjustment. */
01304     saveindex = treenode->index;
01305     newindex = table->invpermZ[low];
01306     auxnode = treenode;
01307     do {
01308         auxnode->index = newindex;
01309         if (auxnode->parent == NULL ||
01310                 (int) auxnode->parent->index != saveindex)
01311             break;
01312         auxnode = auxnode->parent;
01313     } while (1);
01314     return;
01315 
01316 } /* 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 402 of file cuddZddGroup.c.

00406 {
00407     int lower;
00408     int upper;
00409     int result;
00410     unsigned int initialSize;
00411 
00412     zddFindNodeHiLo(table,treenode,&lower,&upper);
00413     /* If upper == -1 these variables do not exist yet. */
00414     if (upper == -1)
00415         return(1);
00416 
00417     if (treenode->flags == MTR_FIXED) {
00418         result = 1;
00419     } else {
00420 #ifdef DD_STATS
00421         (void) fprintf(table->out," ");
00422 #endif
00423         switch (method) {
00424         case CUDD_REORDER_RANDOM:
00425         case CUDD_REORDER_RANDOM_PIVOT:
00426             result = cuddZddSwapping(table,lower,upper,method);
00427             break;
00428         case CUDD_REORDER_SIFT:
00429             result = cuddZddSifting(table,lower,upper);
00430             break;
00431         case CUDD_REORDER_SIFT_CONVERGE:
00432             do {
00433                 initialSize = table->keysZ;
00434                 result = cuddZddSifting(table,lower,upper);
00435                 if (initialSize <= table->keysZ)
00436                     break;
00437 #ifdef DD_STATS
00438                 else
00439                     (void) fprintf(table->out,"\n");
00440 #endif
00441             } while (result != 0);
00442             break;
00443         case CUDD_REORDER_SYMM_SIFT:
00444             result = cuddZddSymmSifting(table,lower,upper);
00445             break;
00446         case CUDD_REORDER_SYMM_SIFT_CONV:
00447             result = cuddZddSymmSiftingConv(table,lower,upper);
00448             break;
00449         case CUDD_REORDER_GROUP_SIFT:
00450             result = zddGroupSifting(table,lower,upper);
00451             break;
00452         case CUDD_REORDER_LINEAR:
00453             result = cuddZddLinearSifting(table,lower,upper);
00454             break;
00455         case CUDD_REORDER_LINEAR_CONVERGE:
00456             do {
00457                 initialSize = table->keysZ;
00458                 result = cuddZddLinearSifting(table,lower,upper);
00459                 if (initialSize <= table->keysZ)
00460                     break;
00461 #ifdef DD_STATS
00462                 else
00463                     (void) fprintf(table->out,"\n");
00464 #endif
00465             } while (result != 0);
00466             break;
00467         default:
00468             return(0);
00469         }
00470     }
00471 
00472     /* Create a single group for all the variables that were sifted,
00473     ** so that they will be treated as a single block by successive
00474     ** invocations of zddGroupSifting.
00475     */
00476     zddMergeGroups(table,treenode,lower,upper);
00477 
00478 #ifdef DD_DEBUG
00479     if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
00480 #endif
00481 
00482     return(result);
00483 
00484 } /* end of zddReorderChildren */

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

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

00322 {
00323     MtrNode  *auxnode;
00324     int res;
00325 
00326 #ifdef DD_DEBUG
00327     Mtr_PrintGroups(treenode,1);
00328 #endif
00329 
00330     auxnode = treenode;
00331     while (auxnode != NULL) {
00332         if (auxnode->child != NULL) {
00333             if (!zddTreeSiftingAux(table, auxnode->child, method))
00334                 return(0);
00335             res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
00336             if (res == 0)
00337                 return(0);
00338         } else if (auxnode->size > 1) {
00339             if (!zddReorderChildren(table, auxnode, method))
00340                 return(0);
00341         }
00342         auxnode = auxnode->younger;
00343     }
00344 
00345     return(1);
00346 
00347 } /* 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 578 of file cuddZddGroup.c.

00581 {
00582 #if 0
00583     if (entry[*ptrY] == entry[*ptrX]) {
00584         return((*ptrX) - (*ptrY));
00585     }
00586 #endif
00587     return(entry[*ptrY] - entry[*ptrX]);
00588 
00589 } /* end of zddUniqueCompareGroup */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang 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 [This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]

Definition at line 63 of file cuddZddGroup.c.

int* entry [static]

Definition at line 66 of file cuddZddGroup.c.

Definition at line 79 of file cuddZddReord.c.


Generated on Tue Jan 5 12:18:57 2010 for abc70930 by  doxygen 1.6.1