#include "util_hack.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#define | DD_NORMAL_SIFT 0 |
#define | DD_LAZY_SIFT 1 |
#define | DD_SIFT_DOWN 0 |
#define | DD_SIFT_UP 1 |
Functions | |
static int ddTreeSiftingAux | ARGS ((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)) |
static void ddFindNodeHiLo | ARGS ((DdManager *table, MtrNode *treenode, int *lower, int *upper)) |
static int ddUniqueCompareGroup | ARGS ((int *ptrX, int *ptrY)) |
static int ddGroupSifting | ARGS ((DdManager *table, int lower, int upper, int(*checkFunction)(DdManager *, int, int), int lazyFlag)) |
static void ddCreateGroup | ARGS ((DdManager *table, int x, int y)) |
static int ddGroupSiftingAux | ARGS ((DdManager *table, int x, int xLow, int xHigh, int(*checkFunction)(DdManager *, int, int), int lazyFlag)) |
static int ddGroupSiftingUp | ARGS ((DdManager *table, int y, int xLow, int(*checkFunction)(DdManager *, int, int), Move **moves)) |
static int ddGroupSiftingDown | ARGS ((DdManager *table, int x, int xHigh, int(*checkFunction)(DdManager *, int, int), Move **moves)) |
static int ddGroupMove | ARGS ((DdManager *table, int x, int y, Move **moves)) |
static int ddGroupSiftingBackward | ARGS ((DdManager *table, Move *moves, int size, int upFlag, int lazyFlag)) |
static void ddMergeGroups | ARGS ((DdManager *table, MtrNode *treenode, int low, int high)) |
static int ddSetVarHandled | ARGS ((DdManager *dd, int index)) |
MtrNode * | Cudd_MakeTreeNode (DdManager *dd, unsigned int low, unsigned int size, unsigned int type) |
int | cuddTreeSifting (DdManager *table, Cudd_ReorderingType method) |
static int | ddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method) |
static int | ddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method) |
static void | ddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper) |
static int | ddUniqueCompareGroup (int *ptrX, int *ptrY) |
static int | ddGroupSifting (DdManager *table, int lower, int upper, int(*checkFunction)(DdManager *, int, int), int lazyFlag) |
static void | ddCreateGroup (DdManager *table, int x, int y) |
static int | ddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh, int(*checkFunction)(DdManager *, int, int), int lazyFlag) |
static int | ddGroupSiftingUp (DdManager *table, int y, int xLow, int(*checkFunction)(DdManager *, int, int), Move **moves) |
static int | ddGroupSiftingDown (DdManager *table, int x, int xHigh, int(*checkFunction)(DdManager *, int, int), Move **moves) |
static int | ddGroupMove (DdManager *table, int x, int y, Move **moves) |
static int | ddGroupMoveBackward (DdManager *table, int x, int y) |
static int | ddGroupSiftingBackward (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag) |
static void | ddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high) |
static void | ddDissolveGroup (DdManager *table, int x, int y) |
static int | ddNoCheck (DdManager *table, int x, int y) |
static int | ddSecDiffCheck (DdManager *table, int x, int y) |
static int | ddExtSymmCheck (DdManager *table, int x, int y) |
static int | ddVarGroupCheck (DdManager *table, int x, int y) |
static int | ddSetVarHandled (DdManager *dd, int index) |
static int | ddResetVarHandled (DdManager *dd, int index) |
static int | ddIsVarHandled (DdManager *dd, int index) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddGroup.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $" |
static int * | entry |
int | ddTotalNumberSwapping |
static int | originalSize |
static int | originalLevel |
#define DD_LAZY_SIFT 1 |
Definition at line 61 of file cuddGroup.c.
#define DD_NORMAL_SIFT 0 |
CFile***********************************************************************
FileName [cuddGroup.c]
PackageName [cudd]
Synopsis [Functions for group sifting.]
Description [External procedures included in this file:
Internal procedures included in this file:
Static procedures included in this module:
]
Author [Shipra Panda, 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 60 of file cuddGroup.c.
#define DD_SIFT_DOWN 0 |
Definition at line 64 of file cuddGroup.c.
#define DD_SIFT_UP 1 |
Definition at line 65 of file cuddGroup.c.
static int ddSetVarHandled ARGS | ( | (DdManager *dd, int index) | ) | [static] |
static void ddMergeGroups ARGS | ( | (DdManager *table, MtrNode *treenode, int low, int high) | ) | [static] |
static int ddGroupSiftingBackward ARGS | ( | (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag) | ) | [static] |
static int ddGroupSiftingDown ARGS | ( | (DdManager *table, int x, int xHigh, int(*checkFunction)(DdManager *, int, int), Move **moves) | ) | [static] |
static int ddGroupSiftingUp ARGS | ( | (DdManager *table, int y, int xLow, int(*checkFunction)(DdManager *, int, int), Move **moves) | ) | [static] |
static int ddGroupSiftingAux ARGS | ( | (DdManager *table, int x, int xLow, int xHigh, int(*checkFunction)(DdManager *, int, int), int lazyFlag) | ) | [static] |
static void ddCreateGroup ARGS | ( | (DdManager *table, int x, int y) | ) | [static] |
static int ddGroupSifting ARGS | ( | (DdManager *table, int lower, int upper, int(*checkFunction)(DdManager *, int, int), int lazyFlag) | ) | [static] |
static int ddUniqueCompareGroup ARGS | ( | (int *ptrX, int *ptrY) | ) | [static] |
static void ddFindNodeHiLo ARGS | ( | (DdManager *table, MtrNode *treenode, int *lower, int *upper) | ) | [static] |
static int ddReorderChildren ARGS | ( | (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method) | ) | [static] |
AutomaticStart
MtrNode* Cudd_MakeTreeNode | ( | DdManager * | dd, | |
unsigned int | low, | |||
unsigned int | size, | |||
unsigned int | type | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Creates a new variable group.]
Description [Creates a new 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 variable tree is changed.]
SeeAlso [Cudd_MakeZddTreeNode]
Definition at line 161 of file cuddGroup.c.
00166 { 00167 MtrNode *group; 00168 MtrNode *tree; 00169 unsigned int level; 00170 00171 /* If the variable does not exist yet, the position is assumed to be 00172 ** the same as the index. Therefore, applications that rely on 00173 ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new 00174 ** variables have to create the variables before they group them. 00175 */ 00176 level = (low < (unsigned int) dd->size) ? dd->perm[low] : low; 00177 00178 if (level + size - 1> (int) MTR_MAXHIGH) 00179 return(NULL); 00180 00181 /* If the tree does not exist yet, create it. */ 00182 tree = dd->tree; 00183 if (tree == NULL) { 00184 dd->tree = tree = Mtr_InitGroupTree(0, dd->size); 00185 if (tree == NULL) 00186 return(NULL); 00187 tree->index = dd->invperm[0]; 00188 } 00189 00190 /* Extend the upper bound of the tree if necessary. This allows the 00191 ** application to create groups even before the variables are created. 00192 */ 00193 tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size)); 00194 00195 /* Create the group. */ 00196 group = Mtr_MakeGroup(tree, level, size, type); 00197 if (group == NULL) 00198 return(NULL); 00199 00200 /* Initialize the index field to the index of the variable currently 00201 ** in position low. This field will be updated by the reordering 00202 ** procedure to provide a handle to the group once it has been moved. 00203 */ 00204 group->index = (MtrHalfWord) low; 00205 00206 return(group); 00207 00208 } /* end of Cudd_MakeTreeNode */
int cuddTreeSifting | ( | DdManager * | table, | |
Cudd_ReorderingType | method | |||
) |
Function********************************************************************
Synopsis [Tree sifting algorithm.]
Description [Tree sifting algorithm. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling ddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 229 of file cuddGroup.c.
00232 { 00233 int i; 00234 int nvars; 00235 int result; 00236 int tempTree; 00237 00238 /* If no tree is provided we create a temporary one in which all 00239 ** variables are in a single group. After reordering this tree is 00240 ** destroyed. 00241 */ 00242 tempTree = table->tree == NULL; 00243 if (tempTree) { 00244 table->tree = Mtr_InitGroupTree(0,table->size); 00245 table->tree->index = table->invperm[0]; 00246 } 00247 nvars = table->size; 00248 00249 #ifdef DD_DEBUG 00250 if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:"); 00251 Mtr_PrintGroups(table->tree,pr <= 0); 00252 #endif 00253 00254 #ifdef DD_STATS 00255 extsymmcalls = 0; 00256 extsymm = 0; 00257 secdiffcalls = 0; 00258 secdiff = 0; 00259 secdiffmisfire = 0; 00260 00261 (void) fprintf(table->out,"\n"); 00262 if (!tempTree) 00263 (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", 00264 ddCountInternalMtrNodes(table,table->tree)); 00265 #endif 00266 00267 /* Initialize the group of each subtable to itself. Initially 00268 ** there are no groups. Groups are created according to the tree 00269 ** structure in postorder fashion. 00270 */ 00271 for (i = 0; i < nvars; i++) 00272 table->subtables[i].next = i; 00273 00274 00275 /* Reorder. */ 00276 result = ddTreeSiftingAux(table, table->tree, method); 00277 00278 #ifdef DD_STATS /* print stats */ 00279 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && 00280 (table->groupcheck == CUDD_GROUP_CHECK7 || 00281 table->groupcheck == CUDD_GROUP_CHECK5)) { 00282 (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); 00283 (void) fprintf(table->out,"extsymm = %d",extsymm); 00284 } 00285 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && 00286 table->groupcheck == CUDD_GROUP_CHECK7) { 00287 (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); 00288 (void) fprintf(table->out,"secdiff = %d\n",secdiff); 00289 (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); 00290 } 00291 #endif 00292 00293 if (tempTree) 00294 Cudd_FreeTree(table); 00295 return(result); 00296 00297 } /* end of cuddTreeSifting */
static void ddCreateGroup | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Creates a group encompassing variables from x to y in the DD table.]
Description [Creates a group encompassing variables from x to y in the DD table. In the current implementation it must be y == x+1. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 870 of file cuddGroup.c.
00874 { 00875 int gybot; 00876 00877 #ifdef DD_DEBUG 00878 assert(y == x+1); 00879 #endif 00880 00881 /* Find bottom of second group. */ 00882 gybot = y; 00883 while ((unsigned) gybot < table->subtables[gybot].next) 00884 gybot = table->subtables[gybot].next; 00885 00886 /* Link groups. */ 00887 table->subtables[x].next = y; 00888 table->subtables[gybot].next = x; 00889 00890 return; 00891 00892 } /* ddCreateGroup */
static void ddDissolveGroup | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Dissolves a group in the DD table.]
Description [x and y are variables in a group to be cut in two. The cut is to pass between x and y.]
SideEffects [None]
Definition at line 1782 of file cuddGroup.c.
01786 { 01787 int topx; 01788 int boty; 01789 01790 /* find top and bottom of the two groups */ 01791 boty = y; 01792 while ((unsigned) boty < table->subtables[boty].next) 01793 boty = table->subtables[boty].next; 01794 01795 topx = table->subtables[boty].next; 01796 01797 table->subtables[boty].next = y; 01798 table->subtables[x].next = topx; 01799 01800 return; 01801 01802 } /* end of ddDissolveGroup */
static int ddExtSymmCheck | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Checks for extended symmetry of x and y.]
Description [Checks for extended symmetry of x and y. Returns 1 in case of extended symmetry; 0 otherwise.]
SideEffects [None]
Definition at line 1897 of file cuddGroup.c.
01901 { 01902 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; 01903 DdNode *one; 01904 int comple; /* f0 is complemented */ 01905 int notproj; /* f is not a projection function */ 01906 int arccount; /* number of arcs from layer x to layer y */ 01907 int TotalRefCount; /* total reference count of layer y minus 1 */ 01908 int counter; /* number of nodes of layer x that are allowed */ 01909 /* to violate extended symmetry conditions */ 01910 int arccounter; /* number of arcs into layer y that are allowed */ 01911 /* to come from layers other than x */ 01912 int i; 01913 int xindex; 01914 int yindex; 01915 int res; 01916 int slots; 01917 DdNodePtr *list; 01918 DdNode *sentinel = &(table->sentinel); 01919 01920 xindex = table->invperm[x]; 01921 yindex = table->invperm[y]; 01922 01923 /* If the two variables do not interact, we do not want to merge them. */ 01924 if (!cuddTestInteract(table,xindex,yindex)) 01925 return(0); 01926 01927 #ifdef DD_DEBUG 01928 /* Checks that x and y do not contain just the projection functions. 01929 ** With the test on interaction, these test become redundant, 01930 ** because an isolated projection function does not interact with 01931 ** any other variable. 01932 */ 01933 if (table->subtables[x].keys == 1) { 01934 assert(table->vars[xindex]->ref != 1); 01935 } 01936 if (table->subtables[y].keys == 1) { 01937 assert(table->vars[yindex]->ref != 1); 01938 } 01939 #endif 01940 01941 #ifdef DD_STATS 01942 extsymmcalls++; 01943 #endif 01944 01945 arccount = 0; 01946 counter = (int) (table->subtables[x].keys * 01947 (table->symmviolation/100.0) + 0.5); 01948 one = DD_ONE(table); 01949 01950 slots = table->subtables[x].slots; 01951 list = table->subtables[x].nodelist; 01952 for (i = 0; i < slots; i++) { 01953 f = list[i]; 01954 while (f != sentinel) { 01955 /* Find f1, f0, f11, f10, f01, f00. */ 01956 f1 = cuddT(f); 01957 f0 = Cudd_Regular(cuddE(f)); 01958 comple = Cudd_IsComplement(cuddE(f)); 01959 notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1; 01960 if (f1->index == yindex) { 01961 arccount++; 01962 f11 = cuddT(f1); f10 = cuddE(f1); 01963 } else { 01964 if ((int) f0->index != yindex) { 01965 /* If f is an isolated projection function it is 01966 ** allowed to bypass layer y. 01967 */ 01968 if (notproj) { 01969 if (counter == 0) 01970 return(0); 01971 counter--; /* f bypasses layer y */ 01972 } 01973 } 01974 f11 = f10 = f1; 01975 } 01976 if ((int) f0->index == yindex) { 01977 arccount++; 01978 f01 = cuddT(f0); f00 = cuddE(f0); 01979 } else { 01980 f01 = f00 = f0; 01981 } 01982 if (comple) { 01983 f01 = Cudd_Not(f01); 01984 f00 = Cudd_Not(f00); 01985 } 01986 01987 /* Unless we are looking at a projection function 01988 ** without external references except the one from the 01989 ** table, we insist that f01 == f10 or f11 == f00 01990 */ 01991 if (notproj) { 01992 if (f01 != f10 && f11 != f00) { 01993 if (counter == 0) 01994 return(0); 01995 counter--; 01996 } 01997 } 01998 01999 f = f->next; 02000 } /* while */ 02001 } /* for */ 02002 02003 /* Calculate the total reference counts of y */ 02004 TotalRefCount = -1; /* -1 for projection function */ 02005 slots = table->subtables[y].slots; 02006 list = table->subtables[y].nodelist; 02007 for (i = 0; i < slots; i++) { 02008 f = list[i]; 02009 while (f != sentinel) { 02010 TotalRefCount += f->ref; 02011 f = f->next; 02012 } 02013 } 02014 02015 arccounter = (int) (table->subtables[y].keys * 02016 (table->arcviolation/100.0) + 0.5); 02017 res = arccount >= TotalRefCount - arccounter; 02018 02019 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 02020 if (res) { 02021 (void) fprintf(table->out, 02022 "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n", 02023 xindex,yindex,x,y); 02024 } 02025 #endif 02026 02027 #ifdef DD_STATS 02028 if (res) 02029 extsymm++; 02030 #endif 02031 return(res); 02032 02033 } /* end ddExtSymmCheck */
static void ddFindNodeHiLo | ( | 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. From the index and size fields we need to derive the current positions, and find maximum and minimum.]
SideEffects [The bounds are returned as side effects.]
SeeAlso []
Definition at line 572 of file cuddGroup.c.
00577 { 00578 int low; 00579 int high; 00580 00581 /* Check whether no variables in this group already exist. 00582 ** If so, return immediately. The calling procedure will know from 00583 ** the values of upper that no reordering is needed. 00584 */ 00585 if ((int) treenode->low >= table->size) { 00586 *lower = table->size; 00587 *upper = -1; 00588 return; 00589 } 00590 00591 *lower = low = (unsigned int) table->perm[treenode->index]; 00592 high = (int) (low + treenode->size - 1); 00593 00594 if (high >= table->size) { 00595 /* This is the case of a partially existing group. The aim is to 00596 ** reorder as many variables as safely possible. If the tree 00597 ** node is terminal, we just reorder the subset of the group 00598 ** that is currently in existence. If the group has 00599 ** subgroups, then we only reorder those subgroups that are 00600 ** fully instantiated. This way we avoid breaking up a group. 00601 */ 00602 MtrNode *auxnode = treenode->child; 00603 if (auxnode == NULL) { 00604 *upper = (unsigned int) table->size - 1; 00605 } else { 00606 /* Search the subgroup that strands the table->size line. 00607 ** If the first group starts at 0 and goes past table->size 00608 ** upper will get -1, thus correctly signaling that no reordering 00609 ** should take place. 00610 */ 00611 while (auxnode != NULL) { 00612 int thisLower = table->perm[auxnode->low]; 00613 int thisUpper = thisLower + auxnode->size - 1; 00614 if (thisUpper >= table->size && thisLower < table->size) 00615 *upper = (unsigned int) thisLower - 1; 00616 auxnode = auxnode->younger; 00617 } 00618 } 00619 } else { 00620 /* Normal case: All the variables of the group exist. */ 00621 *upper = (unsigned int) high; 00622 } 00623 00624 #ifdef DD_DEBUG 00625 /* Make sure that all variables in group are contiguous. */ 00626 assert(treenode->size >= *upper - *lower + 1); 00627 #endif 00628 00629 return; 00630 00631 } /* end of ddFindNodeHiLo */
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 1449 of file cuddGroup.c.
01454 { 01455 Move *move; 01456 int size; 01457 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; 01458 int swapx,swapy; 01459 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 01460 int initialSize,bestSize; 01461 #endif 01462 01463 #if DD_DEBUG 01464 /* We assume that x < y */ 01465 assert(x < y); 01466 #endif 01467 /* Find top, bottom, and size for the two groups. */ 01468 xbot = x; 01469 xtop = table->subtables[x].next; 01470 xsize = xbot - xtop + 1; 01471 ybot = y; 01472 while ((unsigned) ybot < table->subtables[ybot].next) 01473 ybot = table->subtables[ybot].next; 01474 ytop = y; 01475 ysize = ybot - ytop + 1; 01476 01477 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 01478 initialSize = bestSize = table->keys - table->isolated; 01479 #endif 01480 /* Sift the variables of the second group up through the first group */ 01481 for (i = 1; i <= ysize; i++) { 01482 for (j = 1; j <= xsize; j++) { 01483 size = cuddSwapInPlace(table,x,y); 01484 if (size == 0) goto ddGroupMoveOutOfMem; 01485 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 01486 if (size < bestSize) 01487 bestSize = size; 01488 #endif 01489 swapx = x; swapy = y; 01490 y = x; 01491 x = cuddNextLow(table,y); 01492 } 01493 y = ytop + i; 01494 x = cuddNextLow(table,y); 01495 } 01496 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 01497 if ((bestSize < initialSize) && (bestSize < size)) 01498 (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); 01499 #endif 01500 01501 /* fix groups */ 01502 y = xtop; /* ytop is now where xtop used to be */ 01503 for (i = 0; i < ysize - 1; i++) { 01504 table->subtables[y].next = cuddNextHigh(table,y); 01505 y = cuddNextHigh(table,y); 01506 } 01507 table->subtables[y].next = xtop; /* y is bottom of its group, join */ 01508 /* it to top of its group */ 01509 x = cuddNextHigh(table,y); 01510 newxtop = x; 01511 for (i = 0; i < xsize - 1; i++) { 01512 table->subtables[x].next = cuddNextHigh(table,x); 01513 x = cuddNextHigh(table,x); 01514 } 01515 table->subtables[x].next = newxtop; /* x is bottom of its group, join */ 01516 /* it to top of its group */ 01517 #ifdef DD_DEBUG 01518 if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n"); 01519 #endif 01520 01521 /* Store group move */ 01522 move = (Move *) cuddDynamicAllocNode(table); 01523 if (move == NULL) goto ddGroupMoveOutOfMem; 01524 move->x = swapx; 01525 move->y = swapy; 01526 move->flags = MTR_DEFAULT; 01527 move->size = table->keys - table->isolated; 01528 move->next = *moves; 01529 *moves = move; 01530 01531 return(table->keys - table->isolated); 01532 01533 ddGroupMoveOutOfMem: 01534 while (*moves != NULL) { 01535 move = (*moves)->next; 01536 cuddDeallocNode(table, (DdNode *) *moves); 01537 *moves = move; 01538 } 01539 return(0); 01540 01541 } /* end of ddGroupMove */
static int ddGroupMoveBackward | ( | 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 1555 of file cuddGroup.c.
01559 { 01560 int size; 01561 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; 01562 01563 01564 #if DD_DEBUG 01565 /* We assume that x < y */ 01566 assert(x < y); 01567 #endif 01568 01569 /* Find top, bottom, and size for the two groups. */ 01570 xbot = x; 01571 xtop = table->subtables[x].next; 01572 xsize = xbot - xtop + 1; 01573 ybot = y; 01574 while ((unsigned) ybot < table->subtables[ybot].next) 01575 ybot = table->subtables[ybot].next; 01576 ytop = y; 01577 ysize = ybot - ytop + 1; 01578 01579 /* Sift the variables of the second group up through the first group */ 01580 for (i = 1; i <= ysize; i++) { 01581 for (j = 1; j <= xsize; j++) { 01582 size = cuddSwapInPlace(table,x,y); 01583 if (size == 0) 01584 return(0); 01585 y = x; 01586 x = cuddNextLow(table,y); 01587 } 01588 y = ytop + i; 01589 x = cuddNextLow(table,y); 01590 } 01591 01592 /* fix groups */ 01593 y = xtop; 01594 for (i = 0; i < ysize - 1; i++) { 01595 table->subtables[y].next = cuddNextHigh(table,y); 01596 y = cuddNextHigh(table,y); 01597 } 01598 table->subtables[y].next = xtop; /* y is bottom of its group, join */ 01599 /* to its top */ 01600 x = cuddNextHigh(table,y); 01601 newxtop = x; 01602 for (i = 0; i < xsize - 1; i++) { 01603 table->subtables[x].next = cuddNextHigh(table,x); 01604 x = cuddNextHigh(table,x); 01605 } 01606 table->subtables[x].next = newxtop; /* x is bottom of its group, join */ 01607 /* to its top */ 01608 #ifdef DD_DEBUG 01609 if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n"); 01610 #endif 01611 01612 return(1); 01613 01614 } /* end of ddGroupMoveBackward */
static int ddGroupSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper, | |||
int(*)(DdManager *, int, int) | checkFunction, | |||
int | lazyFlag | |||
) | [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 675 of file cuddGroup.c.
00681 { 00682 int *var; 00683 int i,j,x,xInit; 00684 int nvars; 00685 int classes; 00686 int result; 00687 int *sifted; 00688 int merged; 00689 int dissolve; 00690 #ifdef DD_STATS 00691 unsigned previousSize; 00692 #endif 00693 int xindex; 00694 00695 nvars = table->size; 00696 00697 /* Order variables to sift. */ 00698 entry = NULL; 00699 sifted = NULL; 00700 var = ALLOC(int,nvars); 00701 if (var == NULL) { 00702 table->errorCode = CUDD_MEMORY_OUT; 00703 goto ddGroupSiftingOutOfMem; 00704 } 00705 entry = ALLOC(int,nvars); 00706 if (entry == NULL) { 00707 table->errorCode = CUDD_MEMORY_OUT; 00708 goto ddGroupSiftingOutOfMem; 00709 } 00710 sifted = ALLOC(int,nvars); 00711 if (sifted == NULL) { 00712 table->errorCode = CUDD_MEMORY_OUT; 00713 goto ddGroupSiftingOutOfMem; 00714 } 00715 00716 /* Here we consider only one representative for each group. */ 00717 for (i = 0, classes = 0; i < nvars; i++) { 00718 sifted[i] = 0; 00719 x = table->perm[i]; 00720 if ((unsigned) x >= table->subtables[x].next) { 00721 entry[i] = table->subtables[x].keys; 00722 var[classes] = i; 00723 classes++; 00724 } 00725 } 00726 00727 qsort((void *)var,classes,sizeof(int), 00728 (int (*)(const void *, const void *)) ddUniqueCompareGroup); 00729 00730 if (lazyFlag) { 00731 for (i = 0; i < nvars; i ++) { 00732 ddResetVarHandled(table, i); 00733 } 00734 } 00735 00736 /* Now sift. */ 00737 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { 00738 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00739 break; 00740 xindex = var[i]; 00741 if (sifted[xindex] == 1) /* variable already sifted as part of group */ 00742 continue; 00743 x = table->perm[xindex]; /* find current level of this variable */ 00744 00745 if (x < lower || x > upper || table->subtables[x].bindVar == 1) 00746 continue; 00747 #ifdef DD_STATS 00748 previousSize = table->keys - table->isolated; 00749 #endif 00750 #ifdef DD_DEBUG 00751 /* x is bottom of group */ 00752 assert((unsigned) x >= table->subtables[x].next); 00753 #endif 00754 if ((unsigned) x == table->subtables[x].next) { 00755 dissolve = 1; 00756 result = ddGroupSiftingAux(table,x,lower,upper,checkFunction, 00757 lazyFlag); 00758 } else { 00759 dissolve = 0; 00760 result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); 00761 } 00762 if (!result) goto ddGroupSiftingOutOfMem; 00763 00764 /* check for aggregation */ 00765 merged = 0; 00766 if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) { 00767 x = table->perm[xindex]; /* find current level */ 00768 if ((unsigned) x == table->subtables[x].next) { /* not part of a group */ 00769 if (x != upper && sifted[table->invperm[x+1]] == 0 && 00770 (unsigned) x+1 == table->subtables[x+1].next) { 00771 if (ddSecDiffCheck(table,x,x+1)) { 00772 merged =1; 00773 ddCreateGroup(table,x,x+1); 00774 } 00775 } 00776 if (x != lower && sifted[table->invperm[x-1]] == 0 && 00777 (unsigned) x-1 == table->subtables[x-1].next) { 00778 if (ddSecDiffCheck(table,x-1,x)) { 00779 merged =1; 00780 ddCreateGroup(table,x-1,x); 00781 } 00782 } 00783 } 00784 } 00785 00786 if (merged) { /* a group was created */ 00787 /* move x to bottom of group */ 00788 while ((unsigned) x < table->subtables[x].next) 00789 x = table->subtables[x].next; 00790 /* sift */ 00791 result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); 00792 if (!result) goto ddGroupSiftingOutOfMem; 00793 #ifdef DD_STATS 00794 if (table->keys < previousSize + table->isolated) { 00795 (void) fprintf(table->out,"_"); 00796 } else if (table->keys > previousSize + table->isolated) { 00797 (void) fprintf(table->out,"^"); 00798 } else { 00799 (void) fprintf(table->out,"*"); 00800 } 00801 fflush(table->out); 00802 } else { 00803 if (table->keys < previousSize + table->isolated) { 00804 (void) fprintf(table->out,"-"); 00805 } else if (table->keys > previousSize + table->isolated) { 00806 (void) fprintf(table->out,"+"); 00807 } else { 00808 (void) fprintf(table->out,"="); 00809 } 00810 fflush(table->out); 00811 #endif 00812 } 00813 00814 /* Mark variables in the group just sifted. */ 00815 x = table->perm[xindex]; 00816 if ((unsigned) x != table->subtables[x].next) { 00817 xInit = x; 00818 do { 00819 j = table->invperm[x]; 00820 sifted[j] = 1; 00821 x = table->subtables[x].next; 00822 } while (x != xInit); 00823 00824 /* Dissolve the group if it was created. */ 00825 if (lazyFlag == 0 && dissolve) { 00826 do { 00827 j = table->subtables[x].next; 00828 table->subtables[x].next = x; 00829 x = j; 00830 } while (x != xInit); 00831 } 00832 } 00833 00834 #ifdef DD_DEBUG 00835 if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:"); 00836 #endif 00837 00838 if (lazyFlag) ddSetVarHandled(table, xindex); 00839 } /* for */ 00840 00841 FREE(sifted); 00842 FREE(var); 00843 FREE(entry); 00844 00845 return(1); 00846 00847 ddGroupSiftingOutOfMem: 00848 if (entry != NULL) FREE(entry); 00849 if (var != NULL) FREE(var); 00850 if (sifted != NULL) FREE(sifted); 00851 00852 return(0); 00853 00854 } /* end of ddGroupSifting */
static int ddGroupSiftingAux | ( | DdManager * | table, | |
int | x, | |||
int | xLow, | |||
int | xHigh, | |||
int(*)(DdManager *, int, int) | checkFunction, | |||
int | lazyFlag | |||
) | [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 911 of file cuddGroup.c.
00918 { 00919 Move *move; 00920 Move *moves; /* list of moves */ 00921 int initialSize; 00922 int result; 00923 int y; 00924 int topbot; 00925 00926 #ifdef DD_DEBUG 00927 if (pr > 0) (void) fprintf(table->out, 00928 "ddGroupSiftingAux from %d to %d\n",xLow,xHigh); 00929 assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */ 00930 #endif 00931 00932 initialSize = table->keys - table->isolated; 00933 moves = NULL; 00934 00935 originalSize = initialSize; /* for lazy sifting */ 00936 00937 /* If we have a singleton, we check for aggregation in both 00938 ** directions before we sift. 00939 */ 00940 if ((unsigned) x == table->subtables[x].next) { 00941 /* Will go down first, unless x == xHigh: 00942 ** Look for aggregation above x. 00943 */ 00944 for (y = x; y > xLow; y--) { 00945 if (!checkFunction(table,y-1,y)) 00946 break; 00947 topbot = table->subtables[y-1].next; /* find top of y-1's group */ 00948 table->subtables[y-1].next = y; 00949 table->subtables[x].next = topbot; /* x is bottom of group so its */ 00950 /* next is top of y-1's group */ 00951 y = topbot + 1; /* add 1 for y--; new y is top of group */ 00952 } 00953 /* Will go up first unless x == xlow: 00954 ** Look for aggregation below x. 00955 */ 00956 for (y = x; y < xHigh; y++) { 00957 if (!checkFunction(table,y,y+1)) 00958 break; 00959 /* find bottom of y+1's group */ 00960 topbot = y + 1; 00961 while ((unsigned) topbot < table->subtables[topbot].next) { 00962 topbot = table->subtables[topbot].next; 00963 } 00964 table->subtables[topbot].next = table->subtables[y].next; 00965 table->subtables[y].next = y + 1; 00966 y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */ 00967 } 00968 } 00969 00970 /* Now x may be in the middle of a group. 00971 ** Find bottom of x's group. 00972 */ 00973 while ((unsigned) x < table->subtables[x].next) 00974 x = table->subtables[x].next; 00975 00976 originalLevel = x; /* for lazy sifting */ 00977 00978 if (x == xLow) { /* Sift down */ 00979 #ifdef DD_DEBUG 00980 /* x must be a singleton */ 00981 assert((unsigned) x == table->subtables[x].next); 00982 #endif 00983 if (x == xHigh) return(1); /* just one variable */ 00984 00985 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) 00986 goto ddGroupSiftingAuxOutOfMem; 00987 /* at this point x == xHigh, unless early term */ 00988 00989 /* move backward and stop at best position */ 00990 result = ddGroupSiftingBackward(table,moves,initialSize, 00991 DD_SIFT_DOWN,lazyFlag); 00992 #ifdef DD_DEBUG 00993 assert(table->keys - table->isolated <= (unsigned) initialSize); 00994 #endif 00995 if (!result) goto ddGroupSiftingAuxOutOfMem; 00996 00997 } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ 00998 #ifdef DD_DEBUG 00999 /* x is bottom of group */ 01000 assert((unsigned) x >= table->subtables[x].next); 01001 #endif 01002 /* Find top of x's group */ 01003 x = table->subtables[x].next; 01004 01005 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) 01006 goto ddGroupSiftingAuxOutOfMem; 01007 /* at this point x == xLow, unless early term */ 01008 01009 /* move backward and stop at best position */ 01010 result = ddGroupSiftingBackward(table,moves,initialSize, 01011 DD_SIFT_UP,lazyFlag); 01012 #ifdef DD_DEBUG 01013 assert(table->keys - table->isolated <= (unsigned) initialSize); 01014 #endif 01015 if (!result) goto ddGroupSiftingAuxOutOfMem; 01016 01017 } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ 01018 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) 01019 goto ddGroupSiftingAuxOutOfMem; 01020 /* at this point x == xHigh, unless early term */ 01021 01022 /* Find top of group */ 01023 if (moves) { 01024 x = moves->y; 01025 } 01026 while ((unsigned) x < table->subtables[x].next) 01027 x = table->subtables[x].next; 01028 x = table->subtables[x].next; 01029 #ifdef DD_DEBUG 01030 /* x should be the top of a group */ 01031 assert((unsigned) x <= table->subtables[x].next); 01032 #endif 01033 01034 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) 01035 goto ddGroupSiftingAuxOutOfMem; 01036 01037 /* move backward and stop at best position */ 01038 result = ddGroupSiftingBackward(table,moves,initialSize, 01039 DD_SIFT_UP,lazyFlag); 01040 #ifdef DD_DEBUG 01041 assert(table->keys - table->isolated <= (unsigned) initialSize); 01042 #endif 01043 if (!result) goto ddGroupSiftingAuxOutOfMem; 01044 01045 } else { /* moving up first: shorter */ 01046 /* Find top of x's group */ 01047 x = table->subtables[x].next; 01048 01049 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) 01050 goto ddGroupSiftingAuxOutOfMem; 01051 /* at this point x == xHigh, unless early term */ 01052 01053 if (moves) { 01054 x = moves->x; 01055 } 01056 while ((unsigned) x < table->subtables[x].next) 01057 x = table->subtables[x].next; 01058 #ifdef DD_DEBUG 01059 /* x is bottom of a group */ 01060 assert((unsigned) x >= table->subtables[x].next); 01061 #endif 01062 01063 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) 01064 goto ddGroupSiftingAuxOutOfMem; 01065 01066 /* move backward and stop at best position */ 01067 result = ddGroupSiftingBackward(table,moves,initialSize, 01068 DD_SIFT_DOWN,lazyFlag); 01069 #ifdef DD_DEBUG 01070 assert(table->keys - table->isolated <= (unsigned) initialSize); 01071 #endif 01072 if (!result) goto ddGroupSiftingAuxOutOfMem; 01073 } 01074 01075 while (moves != NULL) { 01076 move = moves->next; 01077 cuddDeallocNode(table, (DdNode *) moves); 01078 moves = move; 01079 } 01080 01081 return(1); 01082 01083 ddGroupSiftingAuxOutOfMem: 01084 while (moves != NULL) { 01085 move = moves->next; 01086 cuddDeallocNode(table, (DdNode *) moves); 01087 moves = move; 01088 } 01089 01090 return(0); 01091 01092 } /* end of ddGroupSiftingAux */
static int ddGroupSiftingBackward | ( | DdManager * | table, | |
Move * | moves, | |||
int | size, | |||
int | upFlag, | |||
int | lazyFlag | |||
) | [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 1629 of file cuddGroup.c.
01635 { 01636 Move *move; 01637 int res; 01638 Move *end_move; 01639 int diff, tmp_diff; 01640 int index, pairlev; 01641 01642 if (lazyFlag) { 01643 end_move = NULL; 01644 01645 /* Find the minimum size, and the earliest position at which it 01646 ** was achieved. */ 01647 for (move = moves; move != NULL; move = move->next) { 01648 if (move->size < size) { 01649 size = move->size; 01650 end_move = move; 01651 } else if (move->size == size) { 01652 if (end_move == NULL) end_move = move; 01653 } 01654 } 01655 01656 /* Find among the moves that give minimum size the one that 01657 ** minimizes the distance from the corresponding variable. */ 01658 if (moves != NULL) { 01659 diff = Cudd_ReadSize(table) + 1; 01660 index = (upFlag == 1) ? 01661 table->invperm[moves->x] : table->invperm[moves->y]; 01662 pairlev = table->perm[Cudd_bddReadPairIndex(table, index)]; 01663 01664 for (move = moves; move != NULL; move = move->next) { 01665 if (move->size == size) { 01666 if (upFlag == 1) { 01667 tmp_diff = (move->x > pairlev) ? 01668 move->x - pairlev : pairlev - move->x; 01669 } else { 01670 tmp_diff = (move->y > pairlev) ? 01671 move->y - pairlev : pairlev - move->y; 01672 } 01673 if (tmp_diff < diff) { 01674 diff = tmp_diff; 01675 end_move = move; 01676 } 01677 } 01678 } 01679 } 01680 } else { 01681 /* Find the minimum size. */ 01682 for (move = moves; move != NULL; move = move->next) { 01683 if (move->size < size) { 01684 size = move->size; 01685 } 01686 } 01687 } 01688 01689 /* In case of lazy sifting, end_move identifies the position at 01690 ** which we want to stop. Otherwise, we stop as soon as we meet 01691 ** the minimum size. */ 01692 for (move = moves; move != NULL; move = move->next) { 01693 if (lazyFlag) { 01694 if (move == end_move) return(1); 01695 } else { 01696 if (move->size == size) return(1); 01697 } 01698 if ((table->subtables[move->x].next == move->x) && 01699 (table->subtables[move->y].next == move->y)) { 01700 res = cuddSwapInPlace(table,(int)move->x,(int)move->y); 01701 if (!res) return(0); 01702 #ifdef DD_DEBUG 01703 if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n"); 01704 assert(table->subtables[move->x].next == move->x); 01705 assert(table->subtables[move->y].next == move->y); 01706 #endif 01707 } else { /* Group move necessary */ 01708 if (move->flags == MTR_NEWNODE) { 01709 ddDissolveGroup(table,(int)move->x,(int)move->y); 01710 } else { 01711 res = ddGroupMoveBackward(table,(int)move->x,(int)move->y); 01712 if (!res) return(0); 01713 } 01714 } 01715 01716 } 01717 01718 return(1); 01719 01720 } /* end of ddGroupSiftingBackward */
static int ddGroupSiftingDown | ( | DdManager * | table, | |
int | x, | |||
int | xHigh, | |||
int(*)(DdManager *, int, int) | checkFunction, | |||
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 1271 of file cuddGroup.c.
01277 { 01278 Move *move; 01279 int y; 01280 int size; 01281 int limitSize; 01282 int gxtop,gybot; 01283 int R; /* upper bound on node decrease */ 01284 int xindex, yindex; 01285 int isolated, allVars; 01286 int z; 01287 int zindex; 01288 #ifdef DD_DEBUG 01289 int checkR; 01290 #endif 01291 01292 /* If the group consists of simple variables, there is no point in 01293 ** sifting it down. This check is redundant if the projection functions 01294 ** do not have external references, because the computation of the 01295 ** lower bound takes care of the problem. It is necessary otherwise to 01296 ** prevent the sifting down of simple variables. */ 01297 y = x; 01298 allVars = 1; 01299 do { 01300 if (table->subtables[y].keys != 1) { 01301 allVars = 0; 01302 break; 01303 } 01304 y = table->subtables[y].next; 01305 } while (table->subtables[y].next != (unsigned) x); 01306 if (allVars) 01307 return(1); 01308 01309 /* Initialize R. */ 01310 xindex = table->invperm[x]; 01311 gxtop = table->subtables[x].next; 01312 limitSize = size = table->keys - table->isolated; 01313 R = 0; 01314 for (z = xHigh; z > gxtop; z--) { 01315 zindex = table->invperm[z]; 01316 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01317 isolated = table->vars[zindex]->ref == 1; 01318 R += table->subtables[z].keys - isolated; 01319 } 01320 } 01321 01322 originalLevel = x; /* for lazy sifting */ 01323 01324 y = cuddNextHigh(table,x); 01325 while (y <= xHigh && size - R < limitSize) { 01326 #ifdef DD_DEBUG 01327 gxtop = table->subtables[x].next; 01328 checkR = 0; 01329 for (z = xHigh; z > gxtop; z--) { 01330 zindex = table->invperm[z]; 01331 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01332 isolated = table->vars[zindex]->ref == 1; 01333 checkR += table->subtables[z].keys - isolated; 01334 } 01335 } 01336 assert(R >= checkR); 01337 #endif 01338 /* Find bottom of y group. */ 01339 gybot = table->subtables[y].next; 01340 while (table->subtables[gybot].next != (unsigned) y) 01341 gybot = table->subtables[gybot].next; 01342 01343 if (checkFunction(table,x,y)) { 01344 /* Group found: attach groups and record move. */ 01345 gxtop = table->subtables[x].next; 01346 table->subtables[x].next = y; 01347 table->subtables[gybot].next = gxtop; 01348 move = (Move *)cuddDynamicAllocNode(table); 01349 if (move == NULL) goto ddGroupSiftingDownOutOfMem; 01350 move->x = x; 01351 move->y = y; 01352 move->flags = MTR_NEWNODE; 01353 move->size = table->keys - table->isolated; 01354 move->next = *moves; 01355 *moves = move; 01356 } else if (table->subtables[x].next == (unsigned) x && 01357 table->subtables[y].next == (unsigned) y) { 01358 /* x and y are self groups */ 01359 /* Update upper bound on node decrease. */ 01360 yindex = table->invperm[y]; 01361 if (cuddTestInteract(table,xindex,yindex)) { 01362 isolated = table->vars[yindex]->ref == 1; 01363 R -= table->subtables[y].keys - isolated; 01364 } 01365 size = cuddSwapInPlace(table,x,y); 01366 #ifdef DD_DEBUG 01367 assert(table->subtables[x].next == (unsigned) x); 01368 assert(table->subtables[y].next == (unsigned) y); 01369 #endif 01370 if (size == 0) goto ddGroupSiftingDownOutOfMem; 01371 01372 /* Record move. */ 01373 move = (Move *) cuddDynamicAllocNode(table); 01374 if (move == NULL) goto ddGroupSiftingDownOutOfMem; 01375 move->x = x; 01376 move->y = y; 01377 move->flags = MTR_DEFAULT; 01378 move->size = size; 01379 move->next = *moves; 01380 *moves = move; 01381 01382 #ifdef DD_DEBUG 01383 if (pr > 0) (void) fprintf(table->out, 01384 "ddGroupSiftingDown (2 single groups):\n"); 01385 #endif 01386 if ((double) size > (double) limitSize * table->maxGrowth) 01387 return(1); 01388 if (size < limitSize) limitSize = size; 01389 01390 x = y; 01391 y = cuddNextHigh(table,x); 01392 } else { /* Group move */ 01393 /* Update upper bound on node decrease: first phase. */ 01394 gxtop = table->subtables[x].next; 01395 z = gxtop + 1; 01396 do { 01397 zindex = table->invperm[z]; 01398 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01399 isolated = table->vars[zindex]->ref == 1; 01400 R -= table->subtables[z].keys - isolated; 01401 } 01402 z++; 01403 } while (z <= gybot); 01404 size = ddGroupMove(table,x,y,moves); 01405 if (size == 0) goto ddGroupSiftingDownOutOfMem; 01406 if ((double) size > (double) limitSize * table->maxGrowth) 01407 return(1); 01408 if (size < limitSize) limitSize = size; 01409 01410 /* Update upper bound on node decrease: second phase. */ 01411 gxtop = table->subtables[gybot].next; 01412 for (z = gxtop + 1; z <= gybot; z++) { 01413 zindex = table->invperm[z]; 01414 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01415 isolated = table->vars[zindex]->ref == 1; 01416 R += table->subtables[z].keys - isolated; 01417 } 01418 } 01419 } 01420 x = gybot; 01421 y = cuddNextHigh(table,x); 01422 } 01423 01424 return(1); 01425 01426 ddGroupSiftingDownOutOfMem: 01427 while (*moves != NULL) { 01428 move = (*moves)->next; 01429 cuddDeallocNode(table, (DdNode *) *moves); 01430 *moves = move; 01431 } 01432 01433 return(0); 01434 01435 } /* end of ddGroupSiftingDown */
static int ddGroupSiftingUp | ( | DdManager * | table, | |
int | y, | |||
int | xLow, | |||
int(*)(DdManager *, int, int) | checkFunction, | |||
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 1111 of file cuddGroup.c.
01117 { 01118 Move *move; 01119 int x; 01120 int size; 01121 int i; 01122 int gxtop,gybot; 01123 int limitSize; 01124 int xindex, yindex; 01125 int zindex; 01126 int z; 01127 int isolated; 01128 int L; /* lower bound on DD size */ 01129 #ifdef DD_DEBUG 01130 int checkL; 01131 #endif 01132 01133 yindex = table->invperm[y]; 01134 01135 /* Initialize the lower bound. 01136 ** The part of the DD below the bottom of y's group will not change. 01137 ** The part of the DD above y that does not interact with any 01138 ** variable of y's group will not change. 01139 ** The rest may vanish in the best case, except for 01140 ** the nodes at level xLow, which will not vanish, regardless. 01141 ** What we use here is not really a lower bound, because we ignore 01142 ** the interactions with all variables except y. 01143 */ 01144 limitSize = L = table->keys - table->isolated; 01145 gybot = y; 01146 while ((unsigned) gybot < table->subtables[gybot].next) 01147 gybot = table->subtables[gybot].next; 01148 for (z = xLow + 1; z <= gybot; z++) { 01149 zindex = table->invperm[z]; 01150 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { 01151 isolated = table->vars[zindex]->ref == 1; 01152 L -= table->subtables[z].keys - isolated; 01153 } 01154 } 01155 01156 originalLevel = y; /* for lazy sifting */ 01157 01158 x = cuddNextLow(table,y); 01159 while (x >= xLow && L <= limitSize) { 01160 #ifdef DD_DEBUG 01161 gybot = y; 01162 while ((unsigned) gybot < table->subtables[gybot].next) 01163 gybot = table->subtables[gybot].next; 01164 checkL = table->keys - table->isolated; 01165 for (z = xLow + 1; z <= gybot; z++) { 01166 zindex = table->invperm[z]; 01167 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { 01168 isolated = table->vars[zindex]->ref == 1; 01169 checkL -= table->subtables[z].keys - isolated; 01170 } 01171 } 01172 if (pr > 0 && L != checkL) { 01173 (void) fprintf(table->out, 01174 "Inaccurate lower bound: L = %d checkL = %d\n", 01175 L, checkL); 01176 } 01177 #endif 01178 gxtop = table->subtables[x].next; 01179 if (checkFunction(table,x,y)) { 01180 /* Group found, attach groups */ 01181 table->subtables[x].next = y; 01182 i = table->subtables[y].next; 01183 while (table->subtables[i].next != (unsigned) y) 01184 i = table->subtables[i].next; 01185 table->subtables[i].next = gxtop; 01186 move = (Move *)cuddDynamicAllocNode(table); 01187 if (move == NULL) goto ddGroupSiftingUpOutOfMem; 01188 move->x = x; 01189 move->y = y; 01190 move->flags = MTR_NEWNODE; 01191 move->size = table->keys - table->isolated; 01192 move->next = *moves; 01193 *moves = move; 01194 } else if (table->subtables[x].next == (unsigned) x && 01195 table->subtables[y].next == (unsigned) y) { 01196 /* x and y are self groups */ 01197 xindex = table->invperm[x]; 01198 size = cuddSwapInPlace(table,x,y); 01199 #ifdef DD_DEBUG 01200 assert(table->subtables[x].next == (unsigned) x); 01201 assert(table->subtables[y].next == (unsigned) y); 01202 #endif 01203 if (size == 0) goto ddGroupSiftingUpOutOfMem; 01204 /* Update the lower bound. */ 01205 if (cuddTestInteract(table,xindex,yindex)) { 01206 isolated = table->vars[xindex]->ref == 1; 01207 L += table->subtables[y].keys - isolated; 01208 } 01209 move = (Move *)cuddDynamicAllocNode(table); 01210 if (move == NULL) goto ddGroupSiftingUpOutOfMem; 01211 move->x = x; 01212 move->y = y; 01213 move->flags = MTR_DEFAULT; 01214 move->size = size; 01215 move->next = *moves; 01216 *moves = move; 01217 01218 #ifdef DD_DEBUG 01219 if (pr > 0) (void) fprintf(table->out, 01220 "ddGroupSiftingUp (2 single groups):\n"); 01221 #endif 01222 if ((double) size > (double) limitSize * table->maxGrowth) 01223 return(1); 01224 if (size < limitSize) limitSize = size; 01225 } else { /* Group move */ 01226 size = ddGroupMove(table,x,y,moves); 01227 if (size == 0) goto ddGroupSiftingUpOutOfMem; 01228 /* Update the lower bound. */ 01229 z = (*moves)->y; 01230 do { 01231 zindex = table->invperm[z]; 01232 if (cuddTestInteract(table,zindex,yindex)) { 01233 isolated = table->vars[zindex]->ref == 1; 01234 L += table->subtables[z].keys - isolated; 01235 } 01236 z = table->subtables[z].next; 01237 } while (z != (int) (*moves)->y); 01238 if ((double) size > (double) limitSize * table->maxGrowth) 01239 return(1); 01240 if (size < limitSize) limitSize = size; 01241 } 01242 y = gxtop; 01243 x = cuddNextLow(table,y); 01244 } 01245 01246 return(1); 01247 01248 ddGroupSiftingUpOutOfMem: 01249 while (*moves != NULL) { 01250 move = (*moves)->next; 01251 cuddDeallocNode(table, (DdNode *) *moves); 01252 *moves = move; 01253 } 01254 return(0); 01255 01256 } /* end of ddGroupSiftingUp */
static int ddIsVarHandled | ( | DdManager * | dd, | |
int | index | |||
) | [static] |
Function********************************************************************
Synopsis [Checks whether a variables is already handled.]
Description [Checks whether a variables is already handled. This function is used for lazy sifting.]
SideEffects [none]
SeeAlso []
Definition at line 2135 of file cuddGroup.c.
02138 { 02139 if (index >= dd->size || index < 0) return(-1); 02140 return dd->subtables[dd->perm[index]].varHandled; 02141 02142 } /* end of ddIsVarHandled */
Function********************************************************************
Synopsis [Merges groups in the DD table.]
Description [Creates a single group from low to high and adjusts the index field of the tree node.]
SideEffects [None]
Definition at line 1734 of file cuddGroup.c.
01739 { 01740 int i; 01741 MtrNode *auxnode; 01742 int saveindex; 01743 int newindex; 01744 01745 /* Merge all variables from low to high in one group, unless 01746 ** this is the topmost group. In such a case we do not merge lest 01747 ** we lose the symmetry information. */ 01748 if (treenode != table->tree) { 01749 for (i = low; i < high; i++) 01750 table->subtables[i].next = i+1; 01751 table->subtables[high].next = low; 01752 } 01753 01754 /* Adjust the index fields of the tree nodes. If a node is the 01755 ** first child of its parent, then the parent may also need adjustment. */ 01756 saveindex = treenode->index; 01757 newindex = table->invperm[low]; 01758 auxnode = treenode; 01759 do { 01760 auxnode->index = newindex; 01761 if (auxnode->parent == NULL || 01762 (int) auxnode->parent->index != saveindex) 01763 break; 01764 auxnode = auxnode->parent; 01765 } while (1); 01766 return; 01767 01768 } /* end of ddMergeGroups */
static int ddNoCheck | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Pretends to check two variables for aggregation.]
Description [Pretends to check two variables for aggregation. Always returns 0.]
SideEffects [None]
Definition at line 1816 of file cuddGroup.c.
static int ddReorderChildren | ( | 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 408 of file cuddGroup.c.
00412 { 00413 int lower; 00414 int upper; 00415 int result; 00416 unsigned int initialSize; 00417 00418 ddFindNodeHiLo(table,treenode,&lower,&upper); 00419 /* If upper == -1 these variables do not exist yet. */ 00420 if (upper == -1) 00421 return(1); 00422 00423 if (treenode->flags == MTR_FIXED) { 00424 result = 1; 00425 } else { 00426 #ifdef DD_STATS 00427 (void) fprintf(table->out," "); 00428 #endif 00429 switch (method) { 00430 case CUDD_REORDER_RANDOM: 00431 case CUDD_REORDER_RANDOM_PIVOT: 00432 result = cuddSwapping(table,lower,upper,method); 00433 break; 00434 case CUDD_REORDER_SIFT: 00435 result = cuddSifting(table,lower,upper); 00436 break; 00437 case CUDD_REORDER_SIFT_CONVERGE: 00438 do { 00439 initialSize = table->keys - table->isolated; 00440 result = cuddSifting(table,lower,upper); 00441 if (initialSize <= table->keys - table->isolated) 00442 break; 00443 #ifdef DD_STATS 00444 else 00445 (void) fprintf(table->out,"\n"); 00446 #endif 00447 } while (result != 0); 00448 break; 00449 case CUDD_REORDER_SYMM_SIFT: 00450 result = cuddSymmSifting(table,lower,upper); 00451 break; 00452 case CUDD_REORDER_SYMM_SIFT_CONV: 00453 result = cuddSymmSiftingConv(table,lower,upper); 00454 break; 00455 case CUDD_REORDER_GROUP_SIFT: 00456 if (table->groupcheck == CUDD_NO_CHECK) { 00457 result = ddGroupSifting(table,lower,upper,ddNoCheck, 00458 DD_NORMAL_SIFT); 00459 } else if (table->groupcheck == CUDD_GROUP_CHECK5) { 00460 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, 00461 DD_NORMAL_SIFT); 00462 } else if (table->groupcheck == CUDD_GROUP_CHECK7) { 00463 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, 00464 DD_NORMAL_SIFT); 00465 } else { 00466 (void) fprintf(table->err, 00467 "Unknown group ckecking method\n"); 00468 result = 0; 00469 } 00470 break; 00471 case CUDD_REORDER_GROUP_SIFT_CONV: 00472 do { 00473 initialSize = table->keys - table->isolated; 00474 if (table->groupcheck == CUDD_NO_CHECK) { 00475 result = ddGroupSifting(table,lower,upper,ddNoCheck, 00476 DD_NORMAL_SIFT); 00477 } else if (table->groupcheck == CUDD_GROUP_CHECK5) { 00478 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, 00479 DD_NORMAL_SIFT); 00480 } else if (table->groupcheck == CUDD_GROUP_CHECK7) { 00481 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, 00482 DD_NORMAL_SIFT); 00483 } else { 00484 (void) fprintf(table->err, 00485 "Unknown group ckecking method\n"); 00486 result = 0; 00487 } 00488 #ifdef DD_STATS 00489 (void) fprintf(table->out,"\n"); 00490 #endif 00491 result = cuddWindowReorder(table,lower,upper, 00492 CUDD_REORDER_WINDOW4); 00493 if (initialSize <= table->keys - table->isolated) 00494 break; 00495 #ifdef DD_STATS 00496 else 00497 (void) fprintf(table->out,"\n"); 00498 #endif 00499 } while (result != 0); 00500 break; 00501 case CUDD_REORDER_WINDOW2: 00502 case CUDD_REORDER_WINDOW3: 00503 case CUDD_REORDER_WINDOW4: 00504 case CUDD_REORDER_WINDOW2_CONV: 00505 case CUDD_REORDER_WINDOW3_CONV: 00506 case CUDD_REORDER_WINDOW4_CONV: 00507 result = cuddWindowReorder(table,lower,upper,method); 00508 break; 00509 case CUDD_REORDER_ANNEALING: 00510 result = cuddAnnealing(table,lower,upper); 00511 break; 00512 case CUDD_REORDER_GENETIC: 00513 result = cuddGa(table,lower,upper); 00514 break; 00515 case CUDD_REORDER_LINEAR: 00516 result = cuddLinearAndSifting(table,lower,upper); 00517 break; 00518 case CUDD_REORDER_LINEAR_CONVERGE: 00519 do { 00520 initialSize = table->keys - table->isolated; 00521 result = cuddLinearAndSifting(table,lower,upper); 00522 if (initialSize <= table->keys - table->isolated) 00523 break; 00524 #ifdef DD_STATS 00525 else 00526 (void) fprintf(table->out,"\n"); 00527 #endif 00528 } while (result != 0); 00529 break; 00530 case CUDD_REORDER_EXACT: 00531 result = cuddExact(table,lower,upper); 00532 break; 00533 case CUDD_REORDER_LAZY_SIFT: 00534 result = ddGroupSifting(table,lower,upper,ddVarGroupCheck, 00535 DD_LAZY_SIFT); 00536 break; 00537 default: 00538 return(0); 00539 } 00540 } 00541 00542 /* Create a single group for all the variables that were sifted, 00543 ** so that they will be treated as a single block by successive 00544 ** invocations of ddGroupSifting. 00545 */ 00546 ddMergeGroups(table,treenode,lower,upper); 00547 00548 #ifdef DD_DEBUG 00549 if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:"); 00550 #endif 00551 00552 return(result); 00553 00554 } /* end of ddReorderChildren */
static int ddResetVarHandled | ( | DdManager * | dd, | |
int | index | |||
) | [static] |
Function********************************************************************
Synopsis [Resets a variable to be processed.]
Description [Resets a variable to be processed. This function is used for lazy sifting.]
SideEffects [none]
SeeAlso []
Definition at line 2111 of file cuddGroup.c.
02114 { 02115 if (index >= dd->size || index < 0) return(0); 02116 dd->subtables[dd->perm[index]].varHandled = 0; 02117 return(1); 02118 02119 } /* end of ddResetVarHandled */
static int ddSecDiffCheck | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Checks two variables for aggregation.]
Description [Checks two variables for aggregation. The check is based on the second difference of the number of nodes as a function of the layer. If the second difference is lower than a given threshold (typically negative) then the two variables should be aggregated. Returns 1 if the two variables pass the test; 0 otherwise.]
SideEffects [None]
Definition at line 1840 of file cuddGroup.c.
01844 { 01845 double Nx,Nx_1; 01846 double Sx; 01847 double threshold; 01848 int xindex,yindex; 01849 01850 if (x==0) return(0); 01851 01852 #ifdef DD_STATS 01853 secdiffcalls++; 01854 #endif 01855 Nx = (double) table->subtables[x].keys; 01856 Nx_1 = (double) table->subtables[x-1].keys; 01857 Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1); 01858 01859 threshold = table->recomb / 100.0; 01860 if (Sx < threshold) { 01861 xindex = table->invperm[x]; 01862 yindex = table->invperm[y]; 01863 if (cuddTestInteract(table,xindex,yindex)) { 01864 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 01865 (void) fprintf(table->out, 01866 "Second difference for %d = %g Pos(%d)\n", 01867 table->invperm[x],Sx,x); 01868 #endif 01869 #ifdef DD_STATS 01870 secdiff++; 01871 #endif 01872 return(1); 01873 } else { 01874 #ifdef DD_STATS 01875 secdiffmisfire++; 01876 #endif 01877 return(0); 01878 } 01879 01880 } 01881 return(0); 01882 01883 } /* end of ddSecDiffCheck */
static int ddSetVarHandled | ( | DdManager * | dd, | |
int | index | |||
) | [static] |
Function********************************************************************
Synopsis [Sets a variable to already handled.]
Description [Sets a variable to already handled. This function is used for lazy sifting.]
SideEffects [none]
SeeAlso []
Definition at line 2087 of file cuddGroup.c.
02090 { 02091 if (index >= dd->size || index < 0) return(0); 02092 dd->subtables[dd->perm[index]].varHandled = 1; 02093 return(1); 02094 02095 } /* end of ddSetVarHandled */
static int ddTreeSiftingAux | ( | 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 316 of file cuddGroup.c.
00320 { 00321 MtrNode *auxnode; 00322 int res; 00323 Cudd_AggregationType saveCheck; 00324 00325 #ifdef DD_DEBUG 00326 Mtr_PrintGroups(treenode,1); 00327 #endif 00328 00329 auxnode = treenode; 00330 while (auxnode != NULL) { 00331 if (auxnode->child != NULL) { 00332 if (!ddTreeSiftingAux(table, auxnode->child, method)) 00333 return(0); 00334 saveCheck = table->groupcheck; 00335 table->groupcheck = CUDD_NO_CHECK; 00336 if (method != CUDD_REORDER_LAZY_SIFT) 00337 res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); 00338 else 00339 res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT); 00340 table->groupcheck = saveCheck; 00341 00342 if (res == 0) 00343 return(0); 00344 } else if (auxnode->size > 1) { 00345 if (!ddReorderChildren(table, auxnode, method)) 00346 return(0); 00347 } 00348 auxnode = auxnode->younger; 00349 } 00350 00351 return(1); 00352 00353 } /* end of ddTreeSiftingAux */
static int ddUniqueCompareGroup | ( | 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 647 of file cuddGroup.c.
static int ddVarGroupCheck | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Checks for grouping of x and y.]
Description [Checks for grouping of x and y. Returns 1 in case of grouping; 0 otherwise. This function is used for lazy sifting.]
SideEffects [None]
Definition at line 2047 of file cuddGroup.c.
02051 { 02052 int xindex = table->invperm[x]; 02053 int yindex = table->invperm[y]; 02054 02055 if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0); 02056 02057 if (Cudd_bddReadPairIndex(table, xindex) == yindex) { 02058 if (ddIsVarHandled(table, xindex) || 02059 ddIsVarHandled(table, yindex)) { 02060 if (Cudd_bddIsVarToBeGrouped(table, xindex) || 02061 Cudd_bddIsVarToBeGrouped(table, yindex) ) { 02062 if (table->keys - table->isolated <= originalSize) { 02063 return(1); 02064 } 02065 } 02066 } 02067 } 02068 02069 return(0); 02070 02071 } /* end of ddVarGroupCheck */
char rcsid [] DD_UNUSED = "$Id: cuddGroup.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $" [static] |
Definition at line 80 of file cuddGroup.c.
Definition at line 76 of file cuddReorder.c.
int* entry [static] |
Definition at line 83 of file cuddGroup.c.
int originalLevel [static] |
Definition at line 98 of file cuddGroup.c.
int originalSize [static] |
Definition at line 97 of file cuddGroup.c.