#include "util_hack.h"
#include "cuddInt.h"
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)) |
MtrNode * | Cudd_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 |
static void zddMergeGroups ARGS | ( | (DdManager *table, MtrNode *treenode, int low, int high) | ) | [static] |
static int zddGroupMoveBackward ARGS | ( | (DdManager *table, int x, int y) | ) | [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 */
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 */
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 */
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 */
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 */
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.
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.