#include "util.h"
#include "cuddInt.h"
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) |
MtrNode * | Cudd_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 |
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 */
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 */
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 */
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 */
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 */
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.
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.