#include "util.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#define | MV_OOM (Move *)1 |
Functions | |
static int | ddSymmUniqueCompare (int *ptrX, int *ptrY) |
static int | ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh) |
static int | ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh) |
static Move * | ddSymmSiftingUp (DdManager *table, int y, int xLow) |
static Move * | ddSymmSiftingDown (DdManager *table, int x, int xHigh) |
static int | ddSymmGroupMove (DdManager *table, int x, int y, Move **moves) |
static int | ddSymmGroupMoveBackward (DdManager *table, int x, int y) |
static int | ddSymmSiftingBackward (DdManager *table, Move *moves, int size) |
static void | ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups) |
void | Cudd_SymmProfile (DdManager *table, int lower, int upper) |
int | cuddSymmCheck (DdManager *table, int x, int y) |
int | cuddSymmSifting (DdManager *table, int lower, int upper) |
int | cuddSymmSiftingConv (DdManager *table, int lower, int upper) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $" |
static int * | entry |
int | ddTotalNumberSwapping |
#define MV_OOM (Move *)1 |
CFile***********************************************************************
FileName [cuddSymmetry.c]
PackageName [cudd]
Synopsis [Functions for symmetry-based variable reordering.]
Description [External procedures included in this file:
Internal procedures included in this module:
Static procedures included in this module:
]
Author [Shipra Panda, Fabio Somenzi]
Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]
Definition at line 75 of file cuddSymmetry.c.
void Cudd_SymmProfile | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Prints statistics on symmetric variables.]
Description []
SideEffects [None]
Definition at line 138 of file cuddSymmetry.c.
00142 { 00143 int i,x,gbot; 00144 int TotalSymm = 0; 00145 int TotalSymmGroups = 0; 00146 00147 for (i = lower; i <= upper; i++) { 00148 if (table->subtables[i].next != (unsigned) i) { 00149 x = i; 00150 (void) fprintf(table->out,"Group:"); 00151 do { 00152 (void) fprintf(table->out," %d",table->invperm[x]); 00153 TotalSymm++; 00154 gbot = x; 00155 x = table->subtables[x].next; 00156 } while (x != i); 00157 TotalSymmGroups++; 00158 #ifdef DD_DEBUG 00159 assert(table->subtables[gbot].next == (unsigned) i); 00160 #endif 00161 i = gbot; 00162 (void) fprintf(table->out,"\n"); 00163 } 00164 } 00165 (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm); 00166 (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups); 00167 00168 } /* end of Cudd_SymmProfile */
int cuddSymmCheck | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Checks for symmetry of x and y.]
Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.]
SideEffects [None]
Definition at line 188 of file cuddSymmetry.c.
00192 { 00193 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; 00194 int comple; /* f0 is complemented */ 00195 int xsymmy; /* x and y may be positively symmetric */ 00196 int xsymmyp; /* x and y may be negatively symmetric */ 00197 int arccount; /* number of arcs from layer x to layer y */ 00198 int TotalRefCount; /* total reference count of layer y minus 1 */ 00199 int yindex; 00200 int i; 00201 DdNodePtr *list; 00202 int slots; 00203 DdNode *sentinel = &(table->sentinel); 00204 #ifdef DD_DEBUG 00205 int xindex; 00206 #endif 00207 00208 /* Checks that x and y are not the projection functions. 00209 ** For x it is sufficient to check whether there is only one 00210 ** node; indeed, if there is one node, it is the projection function 00211 ** and it cannot point to y. Hence, if y isn't just the projection 00212 ** function, it has one arc coming from a layer different from x. 00213 */ 00214 if (table->subtables[x].keys == 1) { 00215 return(0); 00216 } 00217 yindex = table->invperm[y]; 00218 if (table->subtables[y].keys == 1) { 00219 if (table->vars[yindex]->ref == 1) 00220 return(0); 00221 } 00222 00223 xsymmy = xsymmyp = 1; 00224 arccount = 0; 00225 slots = table->subtables[x].slots; 00226 list = table->subtables[x].nodelist; 00227 for (i = 0; i < slots; i++) { 00228 f = list[i]; 00229 while (f != sentinel) { 00230 /* Find f1, f0, f11, f10, f01, f00. */ 00231 f1 = cuddT(f); 00232 f0 = Cudd_Regular(cuddE(f)); 00233 comple = Cudd_IsComplement(cuddE(f)); 00234 if ((int) f1->index == yindex) { 00235 arccount++; 00236 f11 = cuddT(f1); f10 = cuddE(f1); 00237 } else { 00238 if ((int) f0->index != yindex) { 00239 /* If f is an isolated projection function it is 00240 ** allowed to bypass layer y. 00241 */ 00242 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) 00243 return(0); /* f bypasses layer y */ 00244 } 00245 f11 = f10 = f1; 00246 } 00247 if ((int) f0->index == yindex) { 00248 arccount++; 00249 f01 = cuddT(f0); f00 = cuddE(f0); 00250 } else { 00251 f01 = f00 = f0; 00252 } 00253 if (comple) { 00254 f01 = Cudd_Not(f01); 00255 f00 = Cudd_Not(f00); 00256 } 00257 00258 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) { 00259 xsymmy &= f01 == f10; 00260 xsymmyp &= f11 == f00; 00261 if ((xsymmy == 0) && (xsymmyp == 0)) 00262 return(0); 00263 } 00264 00265 f = f->next; 00266 } /* while */ 00267 } /* for */ 00268 00269 /* Calculate the total reference counts of y */ 00270 TotalRefCount = -1; /* -1 for projection function */ 00271 slots = table->subtables[y].slots; 00272 list = table->subtables[y].nodelist; 00273 for (i = 0; i < slots; i++) { 00274 f = list[i]; 00275 while (f != sentinel) { 00276 TotalRefCount += f->ref; 00277 f = f->next; 00278 } 00279 } 00280 00281 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 00282 if (arccount == TotalRefCount) { 00283 xindex = table->invperm[x]; 00284 (void) fprintf(table->out, 00285 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", 00286 xindex,yindex,x,y); 00287 } 00288 #endif 00289 00290 return(arccount == TotalRefCount); 00291 00292 } /* end of cuddSymmCheck */
int cuddSymmSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting algorithm.]
Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.
Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddSymmSiftingConv]
Definition at line 318 of file cuddSymmetry.c.
00322 { 00323 int i; 00324 int *var; 00325 int size; 00326 int x; 00327 int result; 00328 int symvars; 00329 int symgroups; 00330 #ifdef DD_STATS 00331 int previousSize; 00332 #endif 00333 00334 size = table->size; 00335 00336 /* Find order in which to sift variables. */ 00337 var = NULL; 00338 entry = ALLOC(int,size); 00339 if (entry == NULL) { 00340 table->errorCode = CUDD_MEMORY_OUT; 00341 goto ddSymmSiftingOutOfMem; 00342 } 00343 var = ALLOC(int,size); 00344 if (var == NULL) { 00345 table->errorCode = CUDD_MEMORY_OUT; 00346 goto ddSymmSiftingOutOfMem; 00347 } 00348 00349 for (i = 0; i < size; i++) { 00350 x = table->perm[i]; 00351 entry[i] = table->subtables[x].keys; 00352 var[i] = i; 00353 } 00354 00355 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); 00356 00357 /* Initialize the symmetry of each subtable to itself. */ 00358 for (i = lower; i <= upper; i++) { 00359 table->subtables[i].next = i; 00360 } 00361 00362 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { 00363 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00364 break; 00365 x = table->perm[var[i]]; 00366 #ifdef DD_STATS 00367 previousSize = table->keys - table->isolated; 00368 #endif 00369 if (x < lower || x > upper) continue; 00370 if (table->subtables[x].next == (unsigned) x) { 00371 result = ddSymmSiftingAux(table,x,lower,upper); 00372 if (!result) goto ddSymmSiftingOutOfMem; 00373 #ifdef DD_STATS 00374 if (table->keys < (unsigned) previousSize + table->isolated) { 00375 (void) fprintf(table->out,"-"); 00376 } else if (table->keys > (unsigned) previousSize + 00377 table->isolated) { 00378 (void) fprintf(table->out,"+"); /* should never happen */ 00379 } else { 00380 (void) fprintf(table->out,"="); 00381 } 00382 fflush(table->out); 00383 #endif 00384 } 00385 } 00386 00387 FREE(var); 00388 FREE(entry); 00389 00390 ddSymmSummary(table, lower, upper, &symvars, &symgroups); 00391 00392 #ifdef DD_STATS 00393 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", 00394 symvars); 00395 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", 00396 symgroups); 00397 #endif 00398 00399 return(1+symvars); 00400 00401 ddSymmSiftingOutOfMem: 00402 00403 if (entry != NULL) FREE(entry); 00404 if (var != NULL) FREE(var); 00405 00406 return(0); 00407 00408 } /* end of cuddSymmSifting */
int cuddSymmSiftingConv | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting to convergence algorithm.]
Description [Symmetric sifting to convergence algorithm. Assumes that no dead nodes are present.
Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddSymmSifting]
Definition at line 435 of file cuddSymmetry.c.
00439 { 00440 int i; 00441 int *var; 00442 int size; 00443 int x; 00444 int result; 00445 int symvars; 00446 int symgroups; 00447 int classes; 00448 int initialSize; 00449 #ifdef DD_STATS 00450 int previousSize; 00451 #endif 00452 00453 initialSize = table->keys - table->isolated; 00454 00455 size = table->size; 00456 00457 /* Find order in which to sift variables. */ 00458 var = NULL; 00459 entry = ALLOC(int,size); 00460 if (entry == NULL) { 00461 table->errorCode = CUDD_MEMORY_OUT; 00462 goto ddSymmSiftingConvOutOfMem; 00463 } 00464 var = ALLOC(int,size); 00465 if (var == NULL) { 00466 table->errorCode = CUDD_MEMORY_OUT; 00467 goto ddSymmSiftingConvOutOfMem; 00468 } 00469 00470 for (i = 0; i < size; i++) { 00471 x = table->perm[i]; 00472 entry[i] = table->subtables[x].keys; 00473 var[i] = i; 00474 } 00475 00476 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); 00477 00478 /* Initialize the symmetry of each subtable to itself 00479 ** for first pass of converging symmetric sifting. 00480 */ 00481 for (i = lower; i <= upper; i++) { 00482 table->subtables[i].next = i; 00483 } 00484 00485 for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) { 00486 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00487 break; 00488 x = table->perm[var[i]]; 00489 if (x < lower || x > upper) continue; 00490 /* Only sift if not in symmetry group already. */ 00491 if (table->subtables[x].next == (unsigned) x) { 00492 #ifdef DD_STATS 00493 previousSize = table->keys - table->isolated; 00494 #endif 00495 result = ddSymmSiftingAux(table,x,lower,upper); 00496 if (!result) goto ddSymmSiftingConvOutOfMem; 00497 #ifdef DD_STATS 00498 if (table->keys < (unsigned) previousSize + table->isolated) { 00499 (void) fprintf(table->out,"-"); 00500 } else if (table->keys > (unsigned) previousSize + 00501 table->isolated) { 00502 (void) fprintf(table->out,"+"); 00503 } else { 00504 (void) fprintf(table->out,"="); 00505 } 00506 fflush(table->out); 00507 #endif 00508 } 00509 } 00510 00511 /* Sifting now until convergence. */ 00512 while ((unsigned) initialSize > table->keys - table->isolated) { 00513 initialSize = table->keys - table->isolated; 00514 #ifdef DD_STATS 00515 (void) fprintf(table->out,"\n"); 00516 #endif 00517 /* Here we consider only one representative for each symmetry class. */ 00518 for (x = lower, classes = 0; x <= upper; x++, classes++) { 00519 while ((unsigned) x < table->subtables[x].next) { 00520 x = table->subtables[x].next; 00521 } 00522 /* Here x is the largest index in a group. 00523 ** Groups consist of adjacent variables. 00524 ** Hence, the next increment of x will move it to a new group. 00525 */ 00526 i = table->invperm[x]; 00527 entry[i] = table->subtables[x].keys; 00528 var[classes] = i; 00529 } 00530 00531 qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); 00532 00533 /* Now sift. */ 00534 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { 00535 if (ddTotalNumberSwapping >= table->siftMaxSwap) 00536 break; 00537 x = table->perm[var[i]]; 00538 if ((unsigned) x >= table->subtables[x].next) { 00539 #ifdef DD_STATS 00540 previousSize = table->keys - table->isolated; 00541 #endif 00542 result = ddSymmSiftingConvAux(table,x,lower,upper); 00543 if (!result ) goto ddSymmSiftingConvOutOfMem; 00544 #ifdef DD_STATS 00545 if (table->keys < (unsigned) previousSize + table->isolated) { 00546 (void) fprintf(table->out,"-"); 00547 } else if (table->keys > (unsigned) previousSize + 00548 table->isolated) { 00549 (void) fprintf(table->out,"+"); 00550 } else { 00551 (void) fprintf(table->out,"="); 00552 } 00553 fflush(table->out); 00554 #endif 00555 } 00556 } /* for */ 00557 } 00558 00559 ddSymmSummary(table, lower, upper, &symvars, &symgroups); 00560 00561 #ifdef DD_STATS 00562 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", 00563 symvars); 00564 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", 00565 symgroups); 00566 #endif 00567 00568 FREE(var); 00569 FREE(entry); 00570 00571 return(1+symvars); 00572 00573 ddSymmSiftingConvOutOfMem: 00574 00575 if (entry != NULL) FREE(entry); 00576 if (var != NULL) FREE(var); 00577 00578 return(0); 00579 00580 } /* end of cuddSymmSiftingConv */
Function********************************************************************
Synopsis [Swaps two groups.]
Description [Swaps two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Updates the list of moves. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [None]
Definition at line 1468 of file cuddSymmetry.c.
01473 { 01474 Move *move; 01475 int size; 01476 int i,j; 01477 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; 01478 int swapx,swapy; 01479 01480 #ifdef DD_DEBUG 01481 assert(x < y); /* we assume that x < y */ 01482 #endif 01483 /* Find top, bottom, and size for the two groups. */ 01484 xbot = x; 01485 xtop = table->subtables[x].next; 01486 xsize = xbot - xtop + 1; 01487 ybot = y; 01488 while ((unsigned) ybot < table->subtables[ybot].next) 01489 ybot = table->subtables[ybot].next; 01490 ytop = y; 01491 ysize = ybot - ytop + 1; 01492 01493 /* Sift the variables of the second group up through the first group. */ 01494 for (i = 1; i <= ysize; i++) { 01495 for (j = 1; j <= xsize; j++) { 01496 size = cuddSwapInPlace(table,x,y); 01497 if (size == 0) return(0); 01498 swapx = x; swapy = y; 01499 y = x; 01500 x = y - 1; 01501 } 01502 y = ytop + i; 01503 x = y - 1; 01504 } 01505 01506 /* fix symmetries */ 01507 y = xtop; /* ytop is now where xtop used to be */ 01508 for (i = 0; i < ysize-1 ; i++) { 01509 table->subtables[y].next = y + 1; 01510 y = y + 1; 01511 } 01512 table->subtables[y].next = xtop; /* y is bottom of its group, join */ 01513 /* its symmetry to top of its group */ 01514 x = y + 1; 01515 newxtop = x; 01516 for (i = 0; i < xsize - 1 ; i++) { 01517 table->subtables[x].next = x + 1; 01518 x = x + 1; 01519 } 01520 table->subtables[x].next = newxtop; /* x is bottom of its group, join */ 01521 /* its symmetry to top of its group */ 01522 /* Store group move */ 01523 move = (Move *) cuddDynamicAllocNode(table); 01524 if (move == NULL) return(0); 01525 move->x = swapx; 01526 move->y = swapy; 01527 move->size = size; 01528 move->next = *moves; 01529 *moves = move; 01530 01531 return(size); 01532 01533 } /* end of ddSymmGroupMove */
static int ddSymmGroupMoveBackward | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Undoes the swap of two groups.]
Description [Undoes the swap of two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [None]
Definition at line 1549 of file cuddSymmetry.c.
01553 { 01554 int size; 01555 int i,j; 01556 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; 01557 01558 #ifdef DD_DEBUG 01559 assert(x < y); /* We assume that x < y */ 01560 #endif 01561 01562 /* Find top, bottom, and size for the two groups. */ 01563 xbot = x; 01564 xtop = table->subtables[x].next; 01565 xsize = xbot - xtop + 1; 01566 ybot = y; 01567 while ((unsigned) ybot < table->subtables[ybot].next) 01568 ybot = table->subtables[ybot].next; 01569 ytop = y; 01570 ysize = ybot - ytop + 1; 01571 01572 /* Sift the variables of the second group up through the first group. */ 01573 for (i = 1; i <= ysize; i++) { 01574 for (j = 1; j <= xsize; j++) { 01575 size = cuddSwapInPlace(table,x,y); 01576 if (size == 0) return(0); 01577 y = x; 01578 x = cuddNextLow(table,y); 01579 } 01580 y = ytop + i; 01581 x = y - 1; 01582 } 01583 01584 /* Fix symmetries. */ 01585 y = xtop; 01586 for (i = 0; i < ysize-1 ; i++) { 01587 table->subtables[y].next = y + 1; 01588 y = y + 1; 01589 } 01590 table->subtables[y].next = xtop; /* y is bottom of its group, join */ 01591 /* its symmetry to top of its group */ 01592 x = y + 1; 01593 newxtop = x; 01594 for (i = 0; i < xsize-1 ; i++) { 01595 table->subtables[x].next = x + 1; 01596 x = x + 1; 01597 } 01598 table->subtables[x].next = newxtop; /* x is bottom of its group, join */ 01599 /* its symmetry to top of its group */ 01600 01601 return(size); 01602 01603 } /* end of ddSymmGroupMoveBackward */
static int ddSymmSiftingAux | ( | DdManager * | table, | |
int | x, | |||
int | xLow, | |||
int | xHigh | |||
) | [static] |
Function********************************************************************
Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]
Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is not part of a symmetry group. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 629 of file cuddSymmetry.c.
00634 { 00635 Move *move; 00636 Move *moveUp; /* list of up moves */ 00637 Move *moveDown; /* list of down moves */ 00638 int initialSize; 00639 int result; 00640 int i; 00641 int topbot; /* index to either top or bottom of symmetry group */ 00642 int initGroupSize, finalGroupSize; 00643 00644 00645 #ifdef DD_DEBUG 00646 /* check for previously detected symmetry */ 00647 assert(table->subtables[x].next == (unsigned) x); 00648 #endif 00649 00650 initialSize = table->keys - table->isolated; 00651 00652 moveDown = NULL; 00653 moveUp = NULL; 00654 00655 if ((x - xLow) > (xHigh - x)) { 00656 /* Will go down first, unless x == xHigh: 00657 ** Look for consecutive symmetries above x. 00658 */ 00659 for (i = x; i > xLow; i--) { 00660 if (!cuddSymmCheck(table,i-1,i)) 00661 break; 00662 topbot = table->subtables[i-1].next; /* find top of i-1's group */ 00663 table->subtables[i-1].next = i; 00664 table->subtables[x].next = topbot; /* x is bottom of group so its */ 00665 /* next is top of i-1's group */ 00666 i = topbot + 1; /* add 1 for i--; new i is top of symm group */ 00667 } 00668 } else { 00669 /* Will go up first unless x == xlow: 00670 ** Look for consecutive symmetries below x. 00671 */ 00672 for (i = x; i < xHigh; i++) { 00673 if (!cuddSymmCheck(table,i,i+1)) 00674 break; 00675 /* find bottom of i+1's symm group */ 00676 topbot = i + 1; 00677 while ((unsigned) topbot < table->subtables[topbot].next) { 00678 topbot = table->subtables[topbot].next; 00679 } 00680 table->subtables[topbot].next = table->subtables[i].next; 00681 table->subtables[i].next = i + 1; 00682 i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */ 00683 } 00684 } 00685 00686 /* Now x may be in the middle of a symmetry group. 00687 ** Find bottom of x's symm group. 00688 */ 00689 while ((unsigned) x < table->subtables[x].next) 00690 x = table->subtables[x].next; 00691 00692 if (x == xLow) { /* Sift down */ 00693 00694 #ifdef DD_DEBUG 00695 /* x must be a singleton */ 00696 assert((unsigned) x == table->subtables[x].next); 00697 #endif 00698 if (x == xHigh) return(1); /* just one variable */ 00699 00700 initGroupSize = 1; 00701 00702 moveDown = ddSymmSiftingDown(table,x,xHigh); 00703 /* after this point x --> xHigh, unless early term */ 00704 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; 00705 if (moveDown == NULL) return(1); 00706 00707 x = moveDown->y; 00708 /* Find bottom of x's group */ 00709 i = x; 00710 while ((unsigned) i < table->subtables[i].next) { 00711 i = table->subtables[i].next; 00712 } 00713 #ifdef DD_DEBUG 00714 /* x should be the top of the symmetry group and i the bottom */ 00715 assert((unsigned) i >= table->subtables[i].next); 00716 assert((unsigned) x == table->subtables[i].next); 00717 #endif 00718 finalGroupSize = i - x + 1; 00719 00720 if (initGroupSize == finalGroupSize) { 00721 /* No new symmetry groups detected, return to best position */ 00722 result = ddSymmSiftingBackward(table,moveDown,initialSize); 00723 } else { 00724 initialSize = table->keys - table->isolated; 00725 moveUp = ddSymmSiftingUp(table,x,xLow); 00726 result = ddSymmSiftingBackward(table,moveUp,initialSize); 00727 } 00728 if (!result) goto ddSymmSiftingAuxOutOfMem; 00729 00730 } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ 00731 /* Find top of x's symm group */ 00732 i = x; /* bottom */ 00733 x = table->subtables[x].next; /* top */ 00734 00735 if (x == xLow) return(1); /* just one big group */ 00736 00737 initGroupSize = i - x + 1; 00738 00739 moveUp = ddSymmSiftingUp(table,x,xLow); 00740 /* after this point x --> xLow, unless early term */ 00741 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; 00742 if (moveUp == NULL) return(1); 00743 00744 x = moveUp->x; 00745 /* Find top of x's group */ 00746 i = table->subtables[x].next; 00747 #ifdef DD_DEBUG 00748 /* x should be the bottom of the symmetry group and i the top */ 00749 assert((unsigned) x >= table->subtables[x].next); 00750 assert((unsigned) i == table->subtables[x].next); 00751 #endif 00752 finalGroupSize = x - i + 1; 00753 00754 if (initGroupSize == finalGroupSize) { 00755 /* No new symmetry groups detected, return to best position */ 00756 result = ddSymmSiftingBackward(table,moveUp,initialSize); 00757 } else { 00758 initialSize = table->keys - table->isolated; 00759 moveDown = ddSymmSiftingDown(table,x,xHigh); 00760 result = ddSymmSiftingBackward(table,moveDown,initialSize); 00761 } 00762 if (!result) goto ddSymmSiftingAuxOutOfMem; 00763 00764 } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ 00765 00766 moveDown = ddSymmSiftingDown(table,x,xHigh); 00767 /* at this point x == xHigh, unless early term */ 00768 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; 00769 00770 if (moveDown != NULL) { 00771 x = moveDown->y; /* x is top here */ 00772 i = x; 00773 while ((unsigned) i < table->subtables[i].next) { 00774 i = table->subtables[i].next; 00775 } 00776 } else { 00777 i = x; 00778 while ((unsigned) i < table->subtables[i].next) { 00779 i = table->subtables[i].next; 00780 } 00781 x = table->subtables[i].next; 00782 } 00783 #ifdef DD_DEBUG 00784 /* x should be the top of the symmetry group and i the bottom */ 00785 assert((unsigned) i >= table->subtables[i].next); 00786 assert((unsigned) x == table->subtables[i].next); 00787 #endif 00788 initGroupSize = i - x + 1; 00789 00790 moveUp = ddSymmSiftingUp(table,x,xLow); 00791 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; 00792 00793 if (moveUp != NULL) { 00794 x = moveUp->x; 00795 i = table->subtables[x].next; 00796 } else { 00797 i = x; 00798 while ((unsigned) x < table->subtables[x].next) 00799 x = table->subtables[x].next; 00800 } 00801 #ifdef DD_DEBUG 00802 /* x should be the bottom of the symmetry group and i the top */ 00803 assert((unsigned) x >= table->subtables[x].next); 00804 assert((unsigned) i == table->subtables[x].next); 00805 #endif 00806 finalGroupSize = x - i + 1; 00807 00808 if (initGroupSize == finalGroupSize) { 00809 /* No new symmetry groups detected, return to best position */ 00810 result = ddSymmSiftingBackward(table,moveUp,initialSize); 00811 } else { 00812 while (moveDown != NULL) { 00813 move = moveDown->next; 00814 cuddDeallocMove(table, moveDown); 00815 moveDown = move; 00816 } 00817 initialSize = table->keys - table->isolated; 00818 moveDown = ddSymmSiftingDown(table,x,xHigh); 00819 result = ddSymmSiftingBackward(table,moveDown,initialSize); 00820 } 00821 if (!result) goto ddSymmSiftingAuxOutOfMem; 00822 00823 } else { /* moving up first: shorter */ 00824 /* Find top of x's symmetry group */ 00825 x = table->subtables[x].next; 00826 00827 moveUp = ddSymmSiftingUp(table,x,xLow); 00828 /* at this point x == xHigh, unless early term */ 00829 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; 00830 00831 if (moveUp != NULL) { 00832 x = moveUp->x; 00833 i = table->subtables[x].next; 00834 } else { 00835 while ((unsigned) x < table->subtables[x].next) 00836 x = table->subtables[x].next; 00837 i = table->subtables[x].next; 00838 } 00839 #ifdef DD_DEBUG 00840 /* x is bottom of the symmetry group and i is top */ 00841 assert((unsigned) x >= table->subtables[x].next); 00842 assert((unsigned) i == table->subtables[x].next); 00843 #endif 00844 initGroupSize = x - i + 1; 00845 00846 moveDown = ddSymmSiftingDown(table,x,xHigh); 00847 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; 00848 00849 if (moveDown != NULL) { 00850 x = moveDown->y; 00851 i = x; 00852 while ((unsigned) i < table->subtables[i].next) { 00853 i = table->subtables[i].next; 00854 } 00855 } else { 00856 i = x; 00857 x = table->subtables[x].next; 00858 } 00859 #ifdef DD_DEBUG 00860 /* x should be the top of the symmetry group and i the bottom */ 00861 assert((unsigned) i >= table->subtables[i].next); 00862 assert((unsigned) x == table->subtables[i].next); 00863 #endif 00864 finalGroupSize = i - x + 1; 00865 00866 if (initGroupSize == finalGroupSize) { 00867 /* No new symmetries detected, go back to best position */ 00868 result = ddSymmSiftingBackward(table,moveDown,initialSize); 00869 } else { 00870 while (moveUp != NULL) { 00871 move = moveUp->next; 00872 cuddDeallocMove(table, moveUp); 00873 moveUp = move; 00874 } 00875 initialSize = table->keys - table->isolated; 00876 moveUp = ddSymmSiftingUp(table,x,xLow); 00877 result = ddSymmSiftingBackward(table,moveUp,initialSize); 00878 } 00879 if (!result) goto ddSymmSiftingAuxOutOfMem; 00880 } 00881 00882 while (moveDown != NULL) { 00883 move = moveDown->next; 00884 cuddDeallocMove(table, moveDown); 00885 moveDown = move; 00886 } 00887 while (moveUp != NULL) { 00888 move = moveUp->next; 00889 cuddDeallocMove(table, moveUp); 00890 moveUp = move; 00891 } 00892 00893 return(1); 00894 00895 ddSymmSiftingAuxOutOfMem: 00896 if (moveDown != MV_OOM) { 00897 while (moveDown != NULL) { 00898 move = moveDown->next; 00899 cuddDeallocMove(table, moveDown); 00900 moveDown = move; 00901 } 00902 } 00903 if (moveUp != MV_OOM) { 00904 while (moveUp != NULL) { 00905 move = moveUp->next; 00906 cuddDeallocMove(table, moveUp); 00907 moveUp = move; 00908 } 00909 } 00910 00911 return(0); 00912 00913 } /* end of ddSymmSiftingAux */
Function********************************************************************
Synopsis [Given a set of moves, returns the DD heap to the position giving the minimum size.]
Description [Given a set of moves, returns the DD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 1620 of file cuddSymmetry.c.
01624 { 01625 Move *move; 01626 int res; 01627 01628 for (move = moves; move != NULL; move = move->next) { 01629 if (move->size < size) { 01630 size = move->size; 01631 } 01632 } 01633 01634 for (move = moves; move != NULL; move = move->next) { 01635 if (move->size == size) return(1); 01636 if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) { 01637 res = cuddSwapInPlace(table,(int)move->x,(int)move->y); 01638 #ifdef DD_DEBUG 01639 assert(table->subtables[move->x].next == move->x); 01640 assert(table->subtables[move->y].next == move->y); 01641 #endif 01642 } else { /* Group move necessary */ 01643 res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y); 01644 } 01645 if (!res) return(0); 01646 } 01647 01648 return(1); 01649 01650 } /* end of ddSymmSiftingBackward */
static int ddSymmSiftingConvAux | ( | DdManager * | table, | |
int | x, | |||
int | xLow, | |||
int | xHigh | |||
) | [static] |
Function********************************************************************
Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]
Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is either an isolated variable, or it is the bottom of a symmetry group. All symmetries may not have been found, because of exceeded growth limit. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 931 of file cuddSymmetry.c.
00936 { 00937 Move *move; 00938 Move *moveUp; /* list of up moves */ 00939 Move *moveDown; /* list of down moves */ 00940 int initialSize; 00941 int result; 00942 int i; 00943 int initGroupSize, finalGroupSize; 00944 00945 00946 initialSize = table->keys - table->isolated; 00947 00948 moveDown = NULL; 00949 moveUp = NULL; 00950 00951 if (x == xLow) { /* Sift down */ 00952 #ifdef DD_DEBUG 00953 /* x is bottom of symmetry group */ 00954 assert((unsigned) x >= table->subtables[x].next); 00955 #endif 00956 i = table->subtables[x].next; 00957 initGroupSize = x - i + 1; 00958 00959 moveDown = ddSymmSiftingDown(table,x,xHigh); 00960 /* at this point x == xHigh, unless early term */ 00961 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; 00962 if (moveDown == NULL) return(1); 00963 00964 x = moveDown->y; 00965 i = x; 00966 while ((unsigned) i < table->subtables[i].next) { 00967 i = table->subtables[i].next; 00968 } 00969 #ifdef DD_DEBUG 00970 /* x should be the top of the symmetric group and i the bottom */ 00971 assert((unsigned) i >= table->subtables[i].next); 00972 assert((unsigned) x == table->subtables[i].next); 00973 #endif 00974 finalGroupSize = i - x + 1; 00975 00976 if (initGroupSize == finalGroupSize) { 00977 /* No new symmetries detected, go back to best position */ 00978 result = ddSymmSiftingBackward(table,moveDown,initialSize); 00979 } else { 00980 initialSize = table->keys - table->isolated; 00981 moveUp = ddSymmSiftingUp(table,x,xLow); 00982 result = ddSymmSiftingBackward(table,moveUp,initialSize); 00983 } 00984 if (!result) goto ddSymmSiftingConvAuxOutOfMem; 00985 00986 } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ 00987 /* Find top of x's symm group */ 00988 while ((unsigned) x < table->subtables[x].next) 00989 x = table->subtables[x].next; 00990 i = x; /* bottom */ 00991 x = table->subtables[x].next; /* top */ 00992 00993 if (x == xLow) return(1); 00994 00995 initGroupSize = i - x + 1; 00996 00997 moveUp = ddSymmSiftingUp(table,x,xLow); 00998 /* at this point x == xLow, unless early term */ 00999 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; 01000 if (moveUp == NULL) return(1); 01001 01002 x = moveUp->x; 01003 i = table->subtables[x].next; 01004 #ifdef DD_DEBUG 01005 /* x should be the bottom of the symmetry group and i the top */ 01006 assert((unsigned) x >= table->subtables[x].next); 01007 assert((unsigned) i == table->subtables[x].next); 01008 #endif 01009 finalGroupSize = x - i + 1; 01010 01011 if (initGroupSize == finalGroupSize) { 01012 /* No new symmetry groups detected, return to best position */ 01013 result = ddSymmSiftingBackward(table,moveUp,initialSize); 01014 } else { 01015 initialSize = table->keys - table->isolated; 01016 moveDown = ddSymmSiftingDown(table,x,xHigh); 01017 result = ddSymmSiftingBackward(table,moveDown,initialSize); 01018 } 01019 if (!result) 01020 goto ddSymmSiftingConvAuxOutOfMem; 01021 01022 } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ 01023 moveDown = ddSymmSiftingDown(table,x,xHigh); 01024 /* at this point x == xHigh, unless early term */ 01025 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; 01026 01027 if (moveDown != NULL) { 01028 x = moveDown->y; 01029 i = x; 01030 while ((unsigned) i < table->subtables[i].next) { 01031 i = table->subtables[i].next; 01032 } 01033 } else { 01034 while ((unsigned) x < table->subtables[x].next) 01035 x = table->subtables[x].next; 01036 i = x; 01037 x = table->subtables[x].next; 01038 } 01039 #ifdef DD_DEBUG 01040 /* x should be the top of the symmetry group and i the bottom */ 01041 assert((unsigned) i >= table->subtables[i].next); 01042 assert((unsigned) x == table->subtables[i].next); 01043 #endif 01044 initGroupSize = i - x + 1; 01045 01046 moveUp = ddSymmSiftingUp(table,x,xLow); 01047 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; 01048 01049 if (moveUp != NULL) { 01050 x = moveUp->x; 01051 i = table->subtables[x].next; 01052 } else { 01053 i = x; 01054 while ((unsigned) x < table->subtables[x].next) 01055 x = table->subtables[x].next; 01056 } 01057 #ifdef DD_DEBUG 01058 /* x should be the bottom of the symmetry group and i the top */ 01059 assert((unsigned) x >= table->subtables[x].next); 01060 assert((unsigned) i == table->subtables[x].next); 01061 #endif 01062 finalGroupSize = x - i + 1; 01063 01064 if (initGroupSize == finalGroupSize) { 01065 /* No new symmetry groups detected, return to best position */ 01066 result = ddSymmSiftingBackward(table,moveUp,initialSize); 01067 } else { 01068 while (moveDown != NULL) { 01069 move = moveDown->next; 01070 cuddDeallocMove(table, moveDown); 01071 moveDown = move; 01072 } 01073 initialSize = table->keys - table->isolated; 01074 moveDown = ddSymmSiftingDown(table,x,xHigh); 01075 result = ddSymmSiftingBackward(table,moveDown,initialSize); 01076 } 01077 if (!result) goto ddSymmSiftingConvAuxOutOfMem; 01078 01079 } else { /* moving up first: shorter */ 01080 /* Find top of x's symmetry group */ 01081 x = table->subtables[x].next; 01082 01083 moveUp = ddSymmSiftingUp(table,x,xLow); 01084 /* at this point x == xHigh, unless early term */ 01085 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; 01086 01087 if (moveUp != NULL) { 01088 x = moveUp->x; 01089 i = table->subtables[x].next; 01090 } else { 01091 i = x; 01092 while ((unsigned) x < table->subtables[x].next) 01093 x = table->subtables[x].next; 01094 } 01095 #ifdef DD_DEBUG 01096 /* x is bottom of the symmetry group and i is top */ 01097 assert((unsigned) x >= table->subtables[x].next); 01098 assert((unsigned) i == table->subtables[x].next); 01099 #endif 01100 initGroupSize = x - i + 1; 01101 01102 moveDown = ddSymmSiftingDown(table,x,xHigh); 01103 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; 01104 01105 if (moveDown != NULL) { 01106 x = moveDown->y; 01107 i = x; 01108 while ((unsigned) i < table->subtables[i].next) { 01109 i = table->subtables[i].next; 01110 } 01111 } else { 01112 i = x; 01113 x = table->subtables[x].next; 01114 } 01115 #ifdef DD_DEBUG 01116 /* x should be the top of the symmetry group and i the bottom */ 01117 assert((unsigned) i >= table->subtables[i].next); 01118 assert((unsigned) x == table->subtables[i].next); 01119 #endif 01120 finalGroupSize = i - x + 1; 01121 01122 if (initGroupSize == finalGroupSize) { 01123 /* No new symmetries detected, go back to best position */ 01124 result = ddSymmSiftingBackward(table,moveDown,initialSize); 01125 } else { 01126 while (moveUp != NULL) { 01127 move = moveUp->next; 01128 cuddDeallocMove(table, moveUp); 01129 moveUp = move; 01130 } 01131 initialSize = table->keys - table->isolated; 01132 moveUp = ddSymmSiftingUp(table,x,xLow); 01133 result = ddSymmSiftingBackward(table,moveUp,initialSize); 01134 } 01135 if (!result) goto ddSymmSiftingConvAuxOutOfMem; 01136 } 01137 01138 while (moveDown != NULL) { 01139 move = moveDown->next; 01140 cuddDeallocMove(table, moveDown); 01141 moveDown = move; 01142 } 01143 while (moveUp != NULL) { 01144 move = moveUp->next; 01145 cuddDeallocMove(table, moveUp); 01146 moveUp = move; 01147 } 01148 01149 return(1); 01150 01151 ddSymmSiftingConvAuxOutOfMem: 01152 if (moveDown != MV_OOM) { 01153 while (moveDown != NULL) { 01154 move = moveDown->next; 01155 cuddDeallocMove(table, moveDown); 01156 moveDown = move; 01157 } 01158 } 01159 if (moveUp != MV_OOM) { 01160 while (moveUp != NULL) { 01161 move = moveUp->next; 01162 cuddDeallocMove(table, moveUp); 01163 moveUp = move; 01164 } 01165 } 01166 01167 return(0); 01168 01169 } /* end of ddSymmSiftingConvAux */
Function********************************************************************
Synopsis [Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much.]
Description [Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much. Assumes that x is the bottom of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; MV_OOM if memory is full.]
SideEffects [None]
Definition at line 1330 of file cuddSymmetry.c.
01334 { 01335 Move *moves; 01336 Move *move; 01337 int y; 01338 int size; 01339 int limitSize; 01340 int gxtop,gybot; 01341 int R; /* upper bound on node decrease */ 01342 int xindex, yindex; 01343 int isolated; 01344 int z; 01345 int zindex; 01346 #ifdef DD_DEBUG 01347 int checkR; 01348 #endif 01349 01350 moves = NULL; 01351 /* Initialize R */ 01352 xindex = table->invperm[x]; 01353 gxtop = table->subtables[x].next; 01354 limitSize = size = table->keys - table->isolated; 01355 R = 0; 01356 for (z = xHigh; z > gxtop; z--) { 01357 zindex = table->invperm[z]; 01358 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01359 isolated = table->vars[zindex]->ref == 1; 01360 R += table->subtables[z].keys - isolated; 01361 } 01362 } 01363 01364 y = cuddNextHigh(table,x); 01365 while (y <= xHigh && size - R < limitSize) { 01366 #ifdef DD_DEBUG 01367 gxtop = table->subtables[x].next; 01368 checkR = 0; 01369 for (z = xHigh; z > gxtop; z--) { 01370 zindex = table->invperm[z]; 01371 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01372 isolated = table->vars[zindex]->ref == 1; 01373 checkR += table->subtables[z].keys - isolated; 01374 } 01375 } 01376 assert(R == checkR); 01377 #endif 01378 gybot = table->subtables[y].next; 01379 while (table->subtables[gybot].next != (unsigned) y) 01380 gybot = table->subtables[gybot].next; 01381 if (cuddSymmCheck(table,x,y)) { 01382 /* Symmetry found, attach symm groups */ 01383 gxtop = table->subtables[x].next; 01384 table->subtables[x].next = y; 01385 table->subtables[gybot].next = gxtop; 01386 } else if (table->subtables[x].next == (unsigned) x && 01387 table->subtables[y].next == (unsigned) y) { 01388 /* x and y have self symmetry */ 01389 /* Update upper bound on node decrease. */ 01390 yindex = table->invperm[y]; 01391 if (cuddTestInteract(table,xindex,yindex)) { 01392 isolated = table->vars[yindex]->ref == 1; 01393 R -= table->subtables[y].keys - isolated; 01394 } 01395 size = cuddSwapInPlace(table,x,y); 01396 #ifdef DD_DEBUG 01397 assert(table->subtables[x].next == (unsigned) x); 01398 assert(table->subtables[y].next == (unsigned) y); 01399 #endif 01400 if (size == 0) goto ddSymmSiftingDownOutOfMem; 01401 move = (Move *) cuddDynamicAllocNode(table); 01402 if (move == NULL) goto ddSymmSiftingDownOutOfMem; 01403 move->x = x; 01404 move->y = y; 01405 move->size = size; 01406 move->next = moves; 01407 moves = move; 01408 if ((double) size > (double) limitSize * table->maxGrowth) 01409 return(moves); 01410 if (size < limitSize) limitSize = size; 01411 } else { /* Group move */ 01412 /* Update upper bound on node decrease: first phase. */ 01413 gxtop = table->subtables[x].next; 01414 z = gxtop + 1; 01415 do { 01416 zindex = table->invperm[z]; 01417 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01418 isolated = table->vars[zindex]->ref == 1; 01419 R -= table->subtables[z].keys - isolated; 01420 } 01421 z++; 01422 } while (z <= gybot); 01423 size = ddSymmGroupMove(table,x,y,&moves); 01424 if (size == 0) goto ddSymmSiftingDownOutOfMem; 01425 if ((double) size > (double) limitSize * table->maxGrowth) 01426 return(moves); 01427 if (size < limitSize) limitSize = size; 01428 /* Update upper bound on node decrease: second phase. */ 01429 gxtop = table->subtables[gybot].next; 01430 for (z = gxtop + 1; z <= gybot; z++) { 01431 zindex = table->invperm[z]; 01432 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { 01433 isolated = table->vars[zindex]->ref == 1; 01434 R += table->subtables[z].keys - isolated; 01435 } 01436 } 01437 } 01438 x = gybot; 01439 y = cuddNextHigh(table,x); 01440 } 01441 01442 return(moves); 01443 01444 ddSymmSiftingDownOutOfMem: 01445 while (moves != NULL) { 01446 move = moves->next; 01447 cuddDeallocMove(table, moves); 01448 moves = move; 01449 } 01450 return(MV_OOM); 01451 01452 } /* end of ddSymmSiftingDown */
Function********************************************************************
Synopsis [Moves x up until either it reaches the bound (xLow) or the size of the DD heap increases too much.]
Description [Moves x up until either it reaches the bound (xLow) or the size of the DD heap increases too much. Assumes that x is the top of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; MV_OOM if memory is full.]
SideEffects [None]
Definition at line 1188 of file cuddSymmetry.c.
01192 { 01193 Move *moves; 01194 Move *move; 01195 int x; 01196 int size; 01197 int i; 01198 int gxtop,gybot; 01199 int limitSize; 01200 int xindex, yindex; 01201 int zindex; 01202 int z; 01203 int isolated; 01204 int L; /* lower bound on DD size */ 01205 #ifdef DD_DEBUG 01206 int checkL; 01207 #endif 01208 01209 01210 moves = NULL; 01211 yindex = table->invperm[y]; 01212 01213 /* Initialize the lower bound. 01214 ** The part of the DD below the bottom of y' group will not change. 01215 ** The part of the DD above y that does not interact with y will not 01216 ** change. The rest may vanish in the best case, except for 01217 ** the nodes at level xLow, which will not vanish, regardless. 01218 */ 01219 limitSize = L = table->keys - table->isolated; 01220 gybot = y; 01221 while ((unsigned) gybot < table->subtables[gybot].next) 01222 gybot = table->subtables[gybot].next; 01223 for (z = xLow + 1; z <= gybot; z++) { 01224 zindex = table->invperm[z]; 01225 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { 01226 isolated = table->vars[zindex]->ref == 1; 01227 L -= table->subtables[z].keys - isolated; 01228 } 01229 } 01230 01231 x = cuddNextLow(table,y); 01232 while (x >= xLow && L <= limitSize) { 01233 #ifdef DD_DEBUG 01234 gybot = y; 01235 while ((unsigned) gybot < table->subtables[gybot].next) 01236 gybot = table->subtables[gybot].next; 01237 checkL = table->keys - table->isolated; 01238 for (z = xLow + 1; z <= gybot; z++) { 01239 zindex = table->invperm[z]; 01240 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { 01241 isolated = table->vars[zindex]->ref == 1; 01242 checkL -= table->subtables[z].keys - isolated; 01243 } 01244 } 01245 assert(L == checkL); 01246 #endif 01247 gxtop = table->subtables[x].next; 01248 if (cuddSymmCheck(table,x,y)) { 01249 /* Symmetry found, attach symm groups */ 01250 table->subtables[x].next = y; 01251 i = table->subtables[y].next; 01252 while (table->subtables[i].next != (unsigned) y) 01253 i = table->subtables[i].next; 01254 table->subtables[i].next = gxtop; 01255 } else if (table->subtables[x].next == (unsigned) x && 01256 table->subtables[y].next == (unsigned) y) { 01257 /* x and y have self symmetry */ 01258 xindex = table->invperm[x]; 01259 size = cuddSwapInPlace(table,x,y); 01260 #ifdef DD_DEBUG 01261 assert(table->subtables[x].next == (unsigned) x); 01262 assert(table->subtables[y].next == (unsigned) y); 01263 #endif 01264 if (size == 0) goto ddSymmSiftingUpOutOfMem; 01265 /* Update the lower bound. */ 01266 if (cuddTestInteract(table,xindex,yindex)) { 01267 isolated = table->vars[xindex]->ref == 1; 01268 L += table->subtables[y].keys - isolated; 01269 } 01270 move = (Move *) cuddDynamicAllocNode(table); 01271 if (move == NULL) goto ddSymmSiftingUpOutOfMem; 01272 move->x = x; 01273 move->y = y; 01274 move->size = size; 01275 move->next = moves; 01276 moves = move; 01277 if ((double) size > (double) limitSize * table->maxGrowth) 01278 return(moves); 01279 if (size < limitSize) limitSize = size; 01280 } else { /* Group move */ 01281 size = ddSymmGroupMove(table,x,y,&moves); 01282 if (size == 0) goto ddSymmSiftingUpOutOfMem; 01283 /* Update the lower bound. */ 01284 z = moves->y; 01285 do { 01286 zindex = table->invperm[z]; 01287 if (cuddTestInteract(table,zindex,yindex)) { 01288 isolated = table->vars[zindex]->ref == 1; 01289 L += table->subtables[z].keys - isolated; 01290 } 01291 z = table->subtables[z].next; 01292 } while (z != (int) moves->y); 01293 if ((double) size > (double) limitSize * table->maxGrowth) 01294 return(moves); 01295 if (size < limitSize) limitSize = size; 01296 } 01297 y = gxtop; 01298 x = cuddNextLow(table,y); 01299 } 01300 01301 return(moves); 01302 01303 ddSymmSiftingUpOutOfMem: 01304 while (moves != NULL) { 01305 move = moves->next; 01306 cuddDeallocMove(table, moves); 01307 moves = move; 01308 } 01309 return(MV_OOM); 01310 01311 } /* end of ddSymmSiftingUp */
static void ddSymmSummary | ( | DdManager * | table, | |
int | lower, | |||
int | upper, | |||
int * | symvars, | |||
int * | symgroups | |||
) | [static] |
Function********************************************************************
Synopsis [Counts numbers of symmetric variables and symmetry groups.]
Description []
SideEffects [None]
Definition at line 1664 of file cuddSymmetry.c.
01670 { 01671 int i,x,gbot; 01672 int TotalSymm = 0; 01673 int TotalSymmGroups = 0; 01674 01675 for (i = lower; i <= upper; i++) { 01676 if (table->subtables[i].next != (unsigned) i) { 01677 TotalSymmGroups++; 01678 x = i; 01679 do { 01680 TotalSymm++; 01681 gbot = x; 01682 x = table->subtables[x].next; 01683 } while (x != i); 01684 #ifdef DD_DEBUG 01685 assert(table->subtables[gbot].next == (unsigned) i); 01686 #endif 01687 i = gbot; 01688 } 01689 } 01690 *symvars = TotalSymm; 01691 *symgroups = TotalSymmGroups; 01692 01693 return; 01694 01695 } /* end of ddSymmSummary */
static int ddSymmUniqueCompare | ( | int * | ptrX, | |
int * | ptrY | |||
) | [static] |
AutomaticStart
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 601 of file cuddSymmetry.c.
char rcsid [] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $" [static] |
Definition at line 90 of file cuddSymmetry.c.
Definition at line 103 of file cuddReorder.c.
int* entry [static] |
Definition at line 93 of file cuddSymmetry.c.