#include "util.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#define | ZDD_MV_OOM (Move *)1 |
Functions | |
static int | cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high) |
static int | cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high) |
static Move * | cuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size) |
static Move * | cuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size) |
static int | cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size) |
static int | zdd_group_move (DdManager *table, int x, int y, Move **moves) |
static int | zdd_group_move_backward (DdManager *table, int x, int y) |
static void | cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups) |
void | Cudd_zddSymmProfile (DdManager *table, int lower, int upper) |
int | cuddZddSymmCheck (DdManager *table, int x, int y) |
int | cuddZddSymmSifting (DdManager *table, int lower, int upper) |
int | cuddZddSymmSiftingConv (DdManager *table, int lower, int upper) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio Exp $" |
int * | zdd_entry |
int | zddTotalNumberSwapping |
static DdNode * | empty |
#define ZDD_MV_OOM (Move *)1 |
CFile***********************************************************************
FileName [cuddZddSymm.c]
PackageName [cudd]
Synopsis [Functions for symmetry-based ZDD variable reordering.]
Description [External procedures included in this module:
Internal procedures included in this module:
Static procedures included in this module:
]
SeeAlso [cuddSymmetry.c]
Author [Hyong-Kyoon Shin, In-Ho Moon]
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 77 of file cuddZddSymm.c.
void Cudd_zddSymmProfile | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Prints statistics on symmetric ZDD variables.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 141 of file cuddZddSymm.c.
00145 { 00146 int i, x, gbot; 00147 int TotalSymm = 0; 00148 int TotalSymmGroups = 0; 00149 00150 for (i = lower; i < upper; i++) { 00151 if (table->subtableZ[i].next != (unsigned) i) { 00152 x = i; 00153 (void) fprintf(table->out,"Group:"); 00154 do { 00155 (void) fprintf(table->out," %d", table->invpermZ[x]); 00156 TotalSymm++; 00157 gbot = x; 00158 x = table->subtableZ[x].next; 00159 } while (x != i); 00160 TotalSymmGroups++; 00161 #ifdef DD_DEBUG 00162 assert(table->subtableZ[gbot].next == (unsigned) i); 00163 #endif 00164 i = gbot; 00165 (void) fprintf(table->out,"\n"); 00166 } 00167 } 00168 (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm); 00169 (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups); 00170 00171 } /* end of Cudd_zddSymmProfile */
int cuddZddSymmCheck | ( | 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]
SeeAlso []
Definition at line 193 of file cuddZddSymm.c.
00197 { 00198 int i; 00199 DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10; 00200 int yindex; 00201 int xsymmy = 1; 00202 int xsymmyp = 1; 00203 int arccount = 0; 00204 int TotalRefCount = 0; 00205 int symm_found; 00206 00207 empty = table->zero; 00208 00209 yindex = table->invpermZ[y]; 00210 for (i = table->subtableZ[x].slots - 1; i >= 0; i--) { 00211 f = table->subtableZ[x].nodelist[i]; 00212 while (f != NULL) { 00213 /* Find f1, f0, f11, f10, f01, f00 */ 00214 f1 = cuddT(f); 00215 f0 = cuddE(f); 00216 if ((int) f1->index == yindex) { 00217 f11 = cuddT(f1); 00218 f10 = cuddE(f1); 00219 if (f10 != empty) 00220 arccount++; 00221 } else { 00222 if ((int) f0->index != yindex) { 00223 return(0); /* f bypasses layer y */ 00224 } 00225 f11 = empty; 00226 f10 = f1; 00227 } 00228 if ((int) f0->index == yindex) { 00229 f01 = cuddT(f0); 00230 f00 = cuddE(f0); 00231 if (f00 != empty) 00232 arccount++; 00233 } else { 00234 f01 = empty; 00235 f00 = f0; 00236 } 00237 if (f01 != f10) 00238 xsymmy = 0; 00239 if (f11 != f00) 00240 xsymmyp = 0; 00241 if ((xsymmy == 0) && (xsymmyp == 0)) 00242 return(0); 00243 00244 f = f->next; 00245 } /* for each element of the collision list */ 00246 } /* for each slot of the subtable */ 00247 00248 /* Calculate the total reference counts of y 00249 ** whose else arc is not empty. 00250 */ 00251 for (i = table->subtableZ[y].slots - 1; i >= 0; i--) { 00252 f = table->subtableZ[y].nodelist[i]; 00253 while (f != NIL(DdNode)) { 00254 if (cuddE(f) != empty) 00255 TotalRefCount += f->ref; 00256 f = f->next; 00257 } 00258 } 00259 00260 symm_found = (arccount == TotalRefCount); 00261 #if defined(DD_DEBUG) && defined(DD_VERBOSE) 00262 if (symm_found) { 00263 int xindex = table->invpermZ[x]; 00264 (void) fprintf(table->out, 00265 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", 00266 xindex,yindex,x,y); 00267 } 00268 #endif 00269 00270 return(symm_found); 00271 00272 } /* end cuddZddSymmCheck */
int cuddZddSymmSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting algorithm for ZDDs.]
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 [cuddZddSymmSiftingConv]
Definition at line 298 of file cuddZddSymm.c.
00302 { 00303 int i; 00304 int *var; 00305 int nvars; 00306 int x; 00307 int result; 00308 int symvars; 00309 int symgroups; 00310 int iteration; 00311 #ifdef DD_STATS 00312 int previousSize; 00313 #endif 00314 00315 nvars = table->sizeZ; 00316 00317 /* Find order in which to sift variables. */ 00318 var = NULL; 00319 zdd_entry = ALLOC(int, nvars); 00320 if (zdd_entry == NULL) { 00321 table->errorCode = CUDD_MEMORY_OUT; 00322 goto cuddZddSymmSiftingOutOfMem; 00323 } 00324 var = ALLOC(int, nvars); 00325 if (var == NULL) { 00326 table->errorCode = CUDD_MEMORY_OUT; 00327 goto cuddZddSymmSiftingOutOfMem; 00328 } 00329 00330 for (i = 0; i < nvars; i++) { 00331 x = table->permZ[i]; 00332 zdd_entry[i] = table->subtableZ[x].keys; 00333 var[i] = i; 00334 } 00335 00336 qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); 00337 00338 /* Initialize the symmetry of each subtable to itself. */ 00339 for (i = lower; i <= upper; i++) 00340 table->subtableZ[i].next = i; 00341 00342 iteration = ddMin(table->siftMaxVar, nvars); 00343 for (i = 0; i < iteration; i++) { 00344 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00345 break; 00346 x = table->permZ[var[i]]; 00347 #ifdef DD_STATS 00348 previousSize = table->keysZ; 00349 #endif 00350 if (x < lower || x > upper) continue; 00351 if (table->subtableZ[x].next == (unsigned) x) { 00352 result = cuddZddSymmSiftingAux(table, x, lower, upper); 00353 if (!result) 00354 goto cuddZddSymmSiftingOutOfMem; 00355 #ifdef DD_STATS 00356 if (table->keysZ < (unsigned) previousSize) { 00357 (void) fprintf(table->out,"-"); 00358 } else if (table->keysZ > (unsigned) previousSize) { 00359 (void) fprintf(table->out,"+"); 00360 #ifdef DD_VERBOSE 00361 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); 00362 #endif 00363 } else { 00364 (void) fprintf(table->out,"="); 00365 } 00366 fflush(table->out); 00367 #endif 00368 } 00369 } 00370 00371 FREE(var); 00372 FREE(zdd_entry); 00373 00374 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); 00375 00376 #ifdef DD_STATS 00377 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars); 00378 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups); 00379 #endif 00380 00381 return(1+symvars); 00382 00383 cuddZddSymmSiftingOutOfMem: 00384 00385 if (zdd_entry != NULL) 00386 FREE(zdd_entry); 00387 if (var != NULL) 00388 FREE(var); 00389 00390 return(0); 00391 00392 } /* end of cuddZddSymmSifting */
static Move * cuddZddSymmSifting_down | ( | DdManager * | table, | |
int | x, | |||
int | x_high, | |||
int | initial_size | |||
) | [static] |
Function********************************************************************
Synopsis [Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much.]
Description [Moves x down until either it reaches the bound (x_high) or the size of the ZDD 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; ZDD_MV_OOM if memory is full.]
SideEffects [None]
SeeAlso []
Definition at line 1334 of file cuddZddSymm.c.
01339 { 01340 Move *moves; 01341 Move *move; 01342 int y; 01343 int size; 01344 int limit_size = initial_size; 01345 int i, gxtop, gybot; 01346 01347 moves = NULL; 01348 y = cuddZddNextHigh(table, x); 01349 while (y <= x_high) { 01350 gybot = table->subtableZ[y].next; 01351 while (table->subtableZ[gybot].next != (unsigned) y) 01352 gybot = table->subtableZ[gybot].next; 01353 if (cuddZddSymmCheck(table, x, y)) { 01354 /* Symmetry found, attach symm groups */ 01355 gxtop = table->subtableZ[x].next; 01356 table->subtableZ[x].next = y; 01357 i = table->subtableZ[y].next; 01358 while (table->subtableZ[i].next != (unsigned) y) 01359 i = table->subtableZ[i].next; 01360 table->subtableZ[i].next = gxtop; 01361 } 01362 else if ((table->subtableZ[x].next == (unsigned) x) && 01363 (table->subtableZ[y].next == (unsigned) y)) { 01364 /* x and y have self symmetry */ 01365 size = cuddZddSwapInPlace(table, x, y); 01366 if (size == 0) 01367 goto cuddZddSymmSifting_downOutOfMem; 01368 move = (Move *)cuddDynamicAllocNode(table); 01369 if (move == NULL) 01370 goto cuddZddSymmSifting_downOutOfMem; 01371 move->x = x; 01372 move->y = y; 01373 move->size = size; 01374 move->next = moves; 01375 moves = move; 01376 if ((double)size > 01377 (double)limit_size * table->maxGrowth) 01378 return(moves); 01379 if (size < limit_size) 01380 limit_size = size; 01381 x = y; 01382 y = cuddZddNextHigh(table, x); 01383 } 01384 else { /* Group move */ 01385 size = zdd_group_move(table, x, y, &moves); 01386 if ((double)size > 01387 (double)limit_size * table->maxGrowth) 01388 return(moves); 01389 if (size < limit_size) 01390 limit_size = size; 01391 } 01392 x = gybot; 01393 y = cuddZddNextHigh(table, x); 01394 } 01395 01396 return(moves); 01397 01398 cuddZddSymmSifting_downOutOfMem: 01399 while (moves != NULL) { 01400 move = moves->next; 01401 cuddDeallocMove(table, moves); 01402 moves = move; 01403 } 01404 return(ZDD_MV_OOM); 01405 01406 } /* end of cuddZddSymmSifting_down */
static Move * cuddZddSymmSifting_up | ( | DdManager * | table, | |
int | x, | |||
int | x_low, | |||
int | initial_size | |||
) | [static] |
Function********************************************************************
Synopsis [Moves x up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much.]
Description [Moves x up until either it reaches the bound (x_low) or the size of the ZDD 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; ZDD_MV_OOM if memory is full.]
SideEffects [None]
SeeAlso []
Definition at line 1246 of file cuddZddSymm.c.
01251 { 01252 Move *moves; 01253 Move *move; 01254 int y; 01255 int size; 01256 int limit_size = initial_size; 01257 int i, gytop; 01258 01259 moves = NULL; 01260 y = cuddZddNextLow(table, x); 01261 while (y >= x_low) { 01262 gytop = table->subtableZ[y].next; 01263 if (cuddZddSymmCheck(table, y, x)) { 01264 /* Symmetry found, attach symm groups */ 01265 table->subtableZ[y].next = x; 01266 i = table->subtableZ[x].next; 01267 while (table->subtableZ[i].next != (unsigned) x) 01268 i = table->subtableZ[i].next; 01269 table->subtableZ[i].next = gytop; 01270 } 01271 else if ((table->subtableZ[x].next == (unsigned) x) && 01272 (table->subtableZ[y].next == (unsigned) y)) { 01273 /* x and y have self symmetry */ 01274 size = cuddZddSwapInPlace(table, y, x); 01275 if (size == 0) 01276 goto cuddZddSymmSifting_upOutOfMem; 01277 move = (Move *)cuddDynamicAllocNode(table); 01278 if (move == NULL) 01279 goto cuddZddSymmSifting_upOutOfMem; 01280 move->x = y; 01281 move->y = x; 01282 move->size = size; 01283 move->next = moves; 01284 moves = move; 01285 if ((double)size > 01286 (double)limit_size * table->maxGrowth) 01287 return(moves); 01288 if (size < limit_size) 01289 limit_size = size; 01290 } 01291 else { /* Group move */ 01292 size = zdd_group_move(table, y, x, &moves); 01293 if ((double)size > 01294 (double)limit_size * table->maxGrowth) 01295 return(moves); 01296 if (size < limit_size) 01297 limit_size = size; 01298 } 01299 x = gytop; 01300 y = cuddZddNextLow(table, x); 01301 } 01302 01303 return(moves); 01304 01305 cuddZddSymmSifting_upOutOfMem: 01306 while (moves != NULL) { 01307 move = moves->next; 01308 cuddDeallocMove(table, moves); 01309 moves = move; 01310 } 01311 return(ZDD_MV_OOM); 01312 01313 } /* end of cuddZddSymmSifting_up */
static int cuddZddSymmSiftingAux | ( | DdManager * | table, | |
int | x, | |||
int | x_low, | |||
int | x_high | |||
) | [static] |
AutomaticStart
Function********************************************************************
Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.]
Description [Given x_low <= x <= x_high 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]
SeeAlso []
Definition at line 597 of file cuddZddSymm.c.
00602 { 00603 Move *move; 00604 Move *move_up; /* list of up move */ 00605 Move *move_down; /* list of down move */ 00606 int initial_size; 00607 int result; 00608 int i; 00609 int topbot; /* index to either top or bottom of symmetry group */ 00610 int init_group_size, final_group_size; 00611 00612 initial_size = table->keysZ; 00613 00614 move_down = NULL; 00615 move_up = NULL; 00616 00617 /* Look for consecutive symmetries above x. */ 00618 for (i = x; i > x_low; i--) { 00619 if (!cuddZddSymmCheck(table, i - 1, i)) 00620 break; 00621 /* find top of i-1's symmetry */ 00622 topbot = table->subtableZ[i - 1].next; 00623 table->subtableZ[i - 1].next = i; 00624 table->subtableZ[x].next = topbot; 00625 /* x is bottom of group so its symmetry is top of i-1's 00626 group */ 00627 i = topbot + 1; /* add 1 for i--, new i is top of symm group */ 00628 } 00629 /* Look for consecutive symmetries below x. */ 00630 for (i = x; i < x_high; i++) { 00631 if (!cuddZddSymmCheck(table, i, i + 1)) 00632 break; 00633 /* find bottom of i+1's symm group */ 00634 topbot = i + 1; 00635 while ((unsigned) topbot < table->subtableZ[topbot].next) 00636 topbot = table->subtableZ[topbot].next; 00637 00638 table->subtableZ[topbot].next = table->subtableZ[i].next; 00639 table->subtableZ[i].next = i + 1; 00640 i = topbot - 1; /* add 1 for i++, 00641 new i is bottom of symm group */ 00642 } 00643 00644 /* Now x maybe in the middle of a symmetry group. */ 00645 if (x == x_low) { /* Sift down */ 00646 /* Find bottom of x's symm group */ 00647 while ((unsigned) x < table->subtableZ[x].next) 00648 x = table->subtableZ[x].next; 00649 00650 i = table->subtableZ[x].next; 00651 init_group_size = x - i + 1; 00652 00653 move_down = cuddZddSymmSifting_down(table, x, x_high, 00654 initial_size); 00655 /* after that point x --> x_high, unless early term */ 00656 if (move_down == ZDD_MV_OOM) 00657 goto cuddZddSymmSiftingAuxOutOfMem; 00658 00659 if (move_down == NULL || 00660 table->subtableZ[move_down->y].next != move_down->y) { 00661 /* symmetry detected may have to make another complete 00662 pass */ 00663 if (move_down != NULL) 00664 x = move_down->y; 00665 else 00666 x = table->subtableZ[x].next; 00667 i = x; 00668 while ((unsigned) i < table->subtableZ[i].next) { 00669 i = table->subtableZ[i].next; 00670 } 00671 final_group_size = i - x + 1; 00672 00673 if (init_group_size == final_group_size) { 00674 /* No new symmetry groups detected, 00675 return to best position */ 00676 result = cuddZddSymmSiftingBackward(table, 00677 move_down, initial_size); 00678 } 00679 else { 00680 initial_size = table->keysZ; 00681 move_up = cuddZddSymmSifting_up(table, x, x_low, 00682 initial_size); 00683 result = cuddZddSymmSiftingBackward(table, move_up, 00684 initial_size); 00685 } 00686 } 00687 else { 00688 result = cuddZddSymmSiftingBackward(table, move_down, 00689 initial_size); 00690 /* move backward and stop at best position */ 00691 } 00692 if (!result) 00693 goto cuddZddSymmSiftingAuxOutOfMem; 00694 } 00695 else if (x == x_high) { /* Sift up */ 00696 /* Find top of x's symm group */ 00697 while ((unsigned) x < table->subtableZ[x].next) 00698 x = table->subtableZ[x].next; 00699 x = table->subtableZ[x].next; 00700 00701 i = x; 00702 while ((unsigned) i < table->subtableZ[i].next) { 00703 i = table->subtableZ[i].next; 00704 } 00705 init_group_size = i - x + 1; 00706 00707 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); 00708 /* after that point x --> x_low, unless early term */ 00709 if (move_up == ZDD_MV_OOM) 00710 goto cuddZddSymmSiftingAuxOutOfMem; 00711 00712 if (move_up == NULL || 00713 table->subtableZ[move_up->x].next != move_up->x) { 00714 /* symmetry detected may have to make another complete 00715 pass */ 00716 if (move_up != NULL) 00717 x = move_up->x; 00718 else { 00719 while ((unsigned) x < table->subtableZ[x].next) 00720 x = table->subtableZ[x].next; 00721 } 00722 i = table->subtableZ[x].next; 00723 final_group_size = x - i + 1; 00724 00725 if (init_group_size == final_group_size) { 00726 /* No new symmetry groups detected, 00727 return to best position */ 00728 result = cuddZddSymmSiftingBackward(table, move_up, 00729 initial_size); 00730 } 00731 else { 00732 initial_size = table->keysZ; 00733 move_down = cuddZddSymmSifting_down(table, x, x_high, 00734 initial_size); 00735 result = cuddZddSymmSiftingBackward(table, move_down, 00736 initial_size); 00737 } 00738 } 00739 else { 00740 result = cuddZddSymmSiftingBackward(table, move_up, 00741 initial_size); 00742 /* move backward and stop at best position */ 00743 } 00744 if (!result) 00745 goto cuddZddSymmSiftingAuxOutOfMem; 00746 } 00747 else if ((x - x_low) > (x_high - x)) { /* must go down first: 00748 shorter */ 00749 /* Find bottom of x's symm group */ 00750 while ((unsigned) x < table->subtableZ[x].next) 00751 x = table->subtableZ[x].next; 00752 00753 move_down = cuddZddSymmSifting_down(table, x, x_high, 00754 initial_size); 00755 /* after that point x --> x_high, unless early term */ 00756 if (move_down == ZDD_MV_OOM) 00757 goto cuddZddSymmSiftingAuxOutOfMem; 00758 00759 if (move_down != NULL) { 00760 x = move_down->y; 00761 } 00762 else { 00763 x = table->subtableZ[x].next; 00764 } 00765 i = x; 00766 while ((unsigned) i < table->subtableZ[i].next) { 00767 i = table->subtableZ[i].next; 00768 } 00769 init_group_size = i - x + 1; 00770 00771 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); 00772 if (move_up == ZDD_MV_OOM) 00773 goto cuddZddSymmSiftingAuxOutOfMem; 00774 00775 if (move_up == NULL || 00776 table->subtableZ[move_up->x].next != move_up->x) { 00777 /* symmetry detected may have to make another complete 00778 pass */ 00779 if (move_up != NULL) { 00780 x = move_up->x; 00781 } 00782 else { 00783 while ((unsigned) x < table->subtableZ[x].next) 00784 x = table->subtableZ[x].next; 00785 } 00786 i = table->subtableZ[x].next; 00787 final_group_size = x - i + 1; 00788 00789 if (init_group_size == final_group_size) { 00790 /* No new symmetry groups detected, 00791 return to best position */ 00792 result = cuddZddSymmSiftingBackward(table, move_up, 00793 initial_size); 00794 } 00795 else { 00796 while (move_down != NULL) { 00797 move = move_down->next; 00798 cuddDeallocMove(table, move_down); 00799 move_down = move; 00800 } 00801 initial_size = table->keysZ; 00802 move_down = cuddZddSymmSifting_down(table, x, x_high, 00803 initial_size); 00804 result = cuddZddSymmSiftingBackward(table, move_down, 00805 initial_size); 00806 } 00807 } 00808 else { 00809 result = cuddZddSymmSiftingBackward(table, move_up, 00810 initial_size); 00811 /* move backward and stop at best position */ 00812 } 00813 if (!result) 00814 goto cuddZddSymmSiftingAuxOutOfMem; 00815 } 00816 else { /* moving up first:shorter */ 00817 /* Find top of x's symmetry group */ 00818 while ((unsigned) x < table->subtableZ[x].next) 00819 x = table->subtableZ[x].next; 00820 x = table->subtableZ[x].next; 00821 00822 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); 00823 /* after that point x --> x_high, unless early term */ 00824 if (move_up == ZDD_MV_OOM) 00825 goto cuddZddSymmSiftingAuxOutOfMem; 00826 00827 if (move_up != NULL) { 00828 x = move_up->x; 00829 } 00830 else { 00831 while ((unsigned) x < table->subtableZ[x].next) 00832 x = table->subtableZ[x].next; 00833 } 00834 i = table->subtableZ[x].next; 00835 init_group_size = x - i + 1; 00836 00837 move_down = cuddZddSymmSifting_down(table, x, x_high, 00838 initial_size); 00839 if (move_down == ZDD_MV_OOM) 00840 goto cuddZddSymmSiftingAuxOutOfMem; 00841 00842 if (move_down == NULL || 00843 table->subtableZ[move_down->y].next != move_down->y) { 00844 /* symmetry detected may have to make another complete 00845 pass */ 00846 if (move_down != NULL) { 00847 x = move_down->y; 00848 } 00849 else { 00850 x = table->subtableZ[x].next; 00851 } 00852 i = x; 00853 while ((unsigned) i < table->subtableZ[i].next) { 00854 i = table->subtableZ[i].next; 00855 } 00856 final_group_size = i - x + 1; 00857 00858 if (init_group_size == final_group_size) { 00859 /* No new symmetries detected, 00860 go back to best position */ 00861 result = cuddZddSymmSiftingBackward(table, move_down, 00862 initial_size); 00863 } 00864 else { 00865 while (move_up != NULL) { 00866 move = move_up->next; 00867 cuddDeallocMove(table, move_up); 00868 move_up = move; 00869 } 00870 initial_size = table->keysZ; 00871 move_up = cuddZddSymmSifting_up(table, x, x_low, 00872 initial_size); 00873 result = cuddZddSymmSiftingBackward(table, move_up, 00874 initial_size); 00875 } 00876 } 00877 else { 00878 result = cuddZddSymmSiftingBackward(table, move_down, 00879 initial_size); 00880 /* move backward and stop at best position */ 00881 } 00882 if (!result) 00883 goto cuddZddSymmSiftingAuxOutOfMem; 00884 } 00885 00886 while (move_down != NULL) { 00887 move = move_down->next; 00888 cuddDeallocMove(table, move_down); 00889 move_down = move; 00890 } 00891 while (move_up != NULL) { 00892 move = move_up->next; 00893 cuddDeallocMove(table, move_up); 00894 move_up = move; 00895 } 00896 00897 return(1); 00898 00899 cuddZddSymmSiftingAuxOutOfMem: 00900 if (move_down != ZDD_MV_OOM) { 00901 while (move_down != NULL) { 00902 move = move_down->next; 00903 cuddDeallocMove(table, move_down); 00904 move_down = move; 00905 } 00906 } 00907 if (move_up != ZDD_MV_OOM) { 00908 while (move_up != NULL) { 00909 move = move_up->next; 00910 cuddDeallocMove(table, move_up); 00911 move_up = move; 00912 } 00913 } 00914 00915 return(0); 00916 00917 } /* end of cuddZddSymmSiftingAux */
Function********************************************************************
Synopsis [Given a set of moves, returns the ZDD heap to the position giving the minimum size.]
Description [Given a set of moves, returns the ZDD 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]
SeeAlso []
Definition at line 1425 of file cuddZddSymm.c.
01429 { 01430 int i; 01431 int i_best; 01432 Move *move; 01433 int res; 01434 01435 i_best = -1; 01436 for (move = moves, i = 0; move != NULL; move = move->next, i++) { 01437 if (move->size < size) { 01438 i_best = i; 01439 size = move->size; 01440 } 01441 } 01442 01443 for (move = moves, i = 0; move != NULL; move = move->next, i++) { 01444 if (i == i_best) break; 01445 if ((table->subtableZ[move->x].next == move->x) && 01446 (table->subtableZ[move->y].next == move->y)) { 01447 res = cuddZddSwapInPlace(table, move->x, move->y); 01448 if (!res) return(0); 01449 } 01450 else { /* Group move necessary */ 01451 res = zdd_group_move_backward(table, move->x, move->y); 01452 } 01453 if (i_best == -1 && res == size) 01454 break; 01455 } 01456 01457 return(1); 01458 01459 } /* end of cuddZddSymmSiftingBackward */
int cuddZddSymmSiftingConv | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]
Description [Symmetric sifting to convergence algorithm for ZDDs. Assumes that no dead nodes are present.
Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddZddSymmSifting]
Definition at line 419 of file cuddZddSymm.c.
00423 { 00424 int i; 00425 int *var; 00426 int nvars; 00427 int initialSize; 00428 int x; 00429 int result; 00430 int symvars; 00431 int symgroups; 00432 int classes; 00433 int iteration; 00434 #ifdef DD_STATS 00435 int previousSize; 00436 #endif 00437 00438 initialSize = table->keysZ; 00439 00440 nvars = table->sizeZ; 00441 00442 /* Find order in which to sift variables. */ 00443 var = NULL; 00444 zdd_entry = ALLOC(int, nvars); 00445 if (zdd_entry == NULL) { 00446 table->errorCode = CUDD_MEMORY_OUT; 00447 goto cuddZddSymmSiftingConvOutOfMem; 00448 } 00449 var = ALLOC(int, nvars); 00450 if (var == NULL) { 00451 table->errorCode = CUDD_MEMORY_OUT; 00452 goto cuddZddSymmSiftingConvOutOfMem; 00453 } 00454 00455 for (i = 0; i < nvars; i++) { 00456 x = table->permZ[i]; 00457 zdd_entry[i] = table->subtableZ[x].keys; 00458 var[i] = i; 00459 } 00460 00461 qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); 00462 00463 /* Initialize the symmetry of each subtable to itself 00464 ** for first pass of converging symmetric sifting. 00465 */ 00466 for (i = lower; i <= upper; i++) 00467 table->subtableZ[i].next = i; 00468 00469 iteration = ddMin(table->siftMaxVar, table->sizeZ); 00470 for (i = 0; i < iteration; i++) { 00471 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00472 break; 00473 x = table->permZ[var[i]]; 00474 if (x < lower || x > upper) continue; 00475 /* Only sift if not in symmetry group already. */ 00476 if (table->subtableZ[x].next == (unsigned) x) { 00477 #ifdef DD_STATS 00478 previousSize = table->keysZ; 00479 #endif 00480 result = cuddZddSymmSiftingAux(table, x, lower, upper); 00481 if (!result) 00482 goto cuddZddSymmSiftingConvOutOfMem; 00483 #ifdef DD_STATS 00484 if (table->keysZ < (unsigned) previousSize) { 00485 (void) fprintf(table->out,"-"); 00486 } else if (table->keysZ > (unsigned) previousSize) { 00487 (void) fprintf(table->out,"+"); 00488 #ifdef DD_VERBOSE 00489 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); 00490 #endif 00491 } else { 00492 (void) fprintf(table->out,"="); 00493 } 00494 fflush(table->out); 00495 #endif 00496 } 00497 } 00498 00499 /* Sifting now until convergence. */ 00500 while ((unsigned) initialSize > table->keysZ) { 00501 initialSize = table->keysZ; 00502 #ifdef DD_STATS 00503 (void) fprintf(table->out,"\n"); 00504 #endif 00505 /* Here we consider only one representative for each symmetry class. */ 00506 for (x = lower, classes = 0; x <= upper; x++, classes++) { 00507 while ((unsigned) x < table->subtableZ[x].next) 00508 x = table->subtableZ[x].next; 00509 /* Here x is the largest index in a group. 00510 ** Groups consists of adjacent variables. 00511 ** Hence, the next increment of x will move it to a new group. 00512 */ 00513 i = table->invpermZ[x]; 00514 zdd_entry[i] = table->subtableZ[x].keys; 00515 var[classes] = i; 00516 } 00517 00518 qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare); 00519 00520 /* Now sift. */ 00521 iteration = ddMin(table->siftMaxVar, nvars); 00522 for (i = 0; i < iteration; i++) { 00523 if (zddTotalNumberSwapping >= table->siftMaxSwap) 00524 break; 00525 x = table->permZ[var[i]]; 00526 if ((unsigned) x >= table->subtableZ[x].next) { 00527 #ifdef DD_STATS 00528 previousSize = table->keysZ; 00529 #endif 00530 result = cuddZddSymmSiftingConvAux(table, x, lower, upper); 00531 if (!result) 00532 goto cuddZddSymmSiftingConvOutOfMem; 00533 #ifdef DD_STATS 00534 if (table->keysZ < (unsigned) previousSize) { 00535 (void) fprintf(table->out,"-"); 00536 } else if (table->keysZ > (unsigned) previousSize) { 00537 (void) fprintf(table->out,"+"); 00538 #ifdef DD_VERBOSE 00539 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); 00540 #endif 00541 } else { 00542 (void) fprintf(table->out,"="); 00543 } 00544 fflush(table->out); 00545 #endif 00546 } 00547 } /* for */ 00548 } 00549 00550 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); 00551 00552 #ifdef DD_STATS 00553 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n", 00554 symvars); 00555 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n", 00556 symgroups); 00557 #endif 00558 00559 FREE(var); 00560 FREE(zdd_entry); 00561 00562 return(1+symvars); 00563 00564 cuddZddSymmSiftingConvOutOfMem: 00565 00566 if (zdd_entry != NULL) 00567 FREE(zdd_entry); 00568 if (var != NULL) 00569 FREE(var); 00570 00571 return(0); 00572 00573 } /* end of cuddZddSymmSiftingConv */
static int cuddZddSymmSiftingConvAux | ( | DdManager * | table, | |
int | x, | |||
int | x_low, | |||
int | x_high | |||
) | [static] |
Function********************************************************************
Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.]
Description [Given x_low <= x <= x_high 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]
SeeAlso []
Definition at line 937 of file cuddZddSymm.c.
00942 { 00943 Move *move; 00944 Move *move_up; /* list of up move */ 00945 Move *move_down; /* list of down move */ 00946 int initial_size; 00947 int result; 00948 int i; 00949 int init_group_size, final_group_size; 00950 00951 initial_size = table->keysZ; 00952 00953 move_down = NULL; 00954 move_up = NULL; 00955 00956 if (x == x_low) { /* Sift down */ 00957 i = table->subtableZ[x].next; 00958 init_group_size = x - i + 1; 00959 00960 move_down = cuddZddSymmSifting_down(table, x, x_high, 00961 initial_size); 00962 /* after that point x --> x_high, unless early term */ 00963 if (move_down == ZDD_MV_OOM) 00964 goto cuddZddSymmSiftingConvAuxOutOfMem; 00965 00966 if (move_down == NULL || 00967 table->subtableZ[move_down->y].next != move_down->y) { 00968 /* symmetry detected may have to make another complete 00969 pass */ 00970 if (move_down != NULL) 00971 x = move_down->y; 00972 else { 00973 while ((unsigned) x < table->subtableZ[x].next) 00974 x = table->subtableZ[x].next; 00975 x = table->subtableZ[x].next; 00976 } 00977 i = x; 00978 while ((unsigned) i < table->subtableZ[i].next) { 00979 i = table->subtableZ[i].next; 00980 } 00981 final_group_size = i - x + 1; 00982 00983 if (init_group_size == final_group_size) { 00984 /* No new symmetries detected, 00985 go back to best position */ 00986 result = cuddZddSymmSiftingBackward(table, move_down, 00987 initial_size); 00988 } 00989 else { 00990 initial_size = table->keysZ; 00991 move_up = cuddZddSymmSifting_up(table, x, x_low, 00992 initial_size); 00993 result = cuddZddSymmSiftingBackward(table, move_up, 00994 initial_size); 00995 } 00996 } 00997 else { 00998 result = cuddZddSymmSiftingBackward(table, move_down, 00999 initial_size); 01000 /* move backward and stop at best position */ 01001 } 01002 if (!result) 01003 goto cuddZddSymmSiftingConvAuxOutOfMem; 01004 } 01005 else if (x == x_high) { /* Sift up */ 01006 /* Find top of x's symm group */ 01007 while ((unsigned) x < table->subtableZ[x].next) 01008 x = table->subtableZ[x].next; 01009 x = table->subtableZ[x].next; 01010 01011 i = x; 01012 while ((unsigned) i < table->subtableZ[i].next) { 01013 i = table->subtableZ[i].next; 01014 } 01015 init_group_size = i - x + 1; 01016 01017 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); 01018 /* after that point x --> x_low, unless early term */ 01019 if (move_up == ZDD_MV_OOM) 01020 goto cuddZddSymmSiftingConvAuxOutOfMem; 01021 01022 if (move_up == NULL || 01023 table->subtableZ[move_up->x].next != move_up->x) { 01024 /* symmetry detected may have to make another complete 01025 pass */ 01026 if (move_up != NULL) 01027 x = move_up->x; 01028 else { 01029 while ((unsigned) x < table->subtableZ[x].next) 01030 x = table->subtableZ[x].next; 01031 } 01032 i = table->subtableZ[x].next; 01033 final_group_size = x - i + 1; 01034 01035 if (init_group_size == final_group_size) { 01036 /* No new symmetry groups detected, 01037 return to best position */ 01038 result = cuddZddSymmSiftingBackward(table, move_up, 01039 initial_size); 01040 } 01041 else { 01042 initial_size = table->keysZ; 01043 move_down = cuddZddSymmSifting_down(table, x, x_high, 01044 initial_size); 01045 result = cuddZddSymmSiftingBackward(table, move_down, 01046 initial_size); 01047 } 01048 } 01049 else { 01050 result = cuddZddSymmSiftingBackward(table, move_up, 01051 initial_size); 01052 /* move backward and stop at best position */ 01053 } 01054 if (!result) 01055 goto cuddZddSymmSiftingConvAuxOutOfMem; 01056 } 01057 else if ((x - x_low) > (x_high - x)) { /* must go down first: 01058 shorter */ 01059 move_down = cuddZddSymmSifting_down(table, x, x_high, 01060 initial_size); 01061 /* after that point x --> x_high */ 01062 if (move_down == ZDD_MV_OOM) 01063 goto cuddZddSymmSiftingConvAuxOutOfMem; 01064 01065 if (move_down != NULL) { 01066 x = move_down->y; 01067 } 01068 else { 01069 while ((unsigned) x < table->subtableZ[x].next) 01070 x = table->subtableZ[x].next; 01071 x = table->subtableZ[x].next; 01072 } 01073 i = x; 01074 while ((unsigned) i < table->subtableZ[i].next) { 01075 i = table->subtableZ[i].next; 01076 } 01077 init_group_size = i - x + 1; 01078 01079 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); 01080 if (move_up == ZDD_MV_OOM) 01081 goto cuddZddSymmSiftingConvAuxOutOfMem; 01082 01083 if (move_up == NULL || 01084 table->subtableZ[move_up->x].next != move_up->x) { 01085 /* symmetry detected may have to make another complete 01086 pass */ 01087 if (move_up != NULL) { 01088 x = move_up->x; 01089 } 01090 else { 01091 while ((unsigned) x < table->subtableZ[x].next) 01092 x = table->subtableZ[x].next; 01093 } 01094 i = table->subtableZ[x].next; 01095 final_group_size = x - i + 1; 01096 01097 if (init_group_size == final_group_size) { 01098 /* No new symmetry groups detected, 01099 return to best position */ 01100 result = cuddZddSymmSiftingBackward(table, move_up, 01101 initial_size); 01102 } 01103 else { 01104 while (move_down != NULL) { 01105 move = move_down->next; 01106 cuddDeallocMove(table, move_down); 01107 move_down = move; 01108 } 01109 initial_size = table->keysZ; 01110 move_down = cuddZddSymmSifting_down(table, x, x_high, 01111 initial_size); 01112 result = cuddZddSymmSiftingBackward(table, move_down, 01113 initial_size); 01114 } 01115 } 01116 else { 01117 result = cuddZddSymmSiftingBackward(table, move_up, 01118 initial_size); 01119 /* move backward and stop at best position */ 01120 } 01121 if (!result) 01122 goto cuddZddSymmSiftingConvAuxOutOfMem; 01123 } 01124 else { /* moving up first:shorter */ 01125 /* Find top of x's symmetry group */ 01126 x = table->subtableZ[x].next; 01127 01128 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); 01129 /* after that point x --> x_high, unless early term */ 01130 if (move_up == ZDD_MV_OOM) 01131 goto cuddZddSymmSiftingConvAuxOutOfMem; 01132 01133 if (move_up != NULL) { 01134 x = move_up->x; 01135 } 01136 else { 01137 while ((unsigned) x < table->subtableZ[x].next) 01138 x = table->subtableZ[x].next; 01139 } 01140 i = table->subtableZ[x].next; 01141 init_group_size = x - i + 1; 01142 01143 move_down = cuddZddSymmSifting_down(table, x, x_high, 01144 initial_size); 01145 if (move_down == ZDD_MV_OOM) 01146 goto cuddZddSymmSiftingConvAuxOutOfMem; 01147 01148 if (move_down == NULL || 01149 table->subtableZ[move_down->y].next != move_down->y) { 01150 /* symmetry detected may have to make another complete 01151 pass */ 01152 if (move_down != NULL) { 01153 x = move_down->y; 01154 } 01155 else { 01156 while ((unsigned) x < table->subtableZ[x].next) 01157 x = table->subtableZ[x].next; 01158 x = table->subtableZ[x].next; 01159 } 01160 i = x; 01161 while ((unsigned) i < table->subtableZ[i].next) { 01162 i = table->subtableZ[i].next; 01163 } 01164 final_group_size = i - x + 1; 01165 01166 if (init_group_size == final_group_size) { 01167 /* No new symmetries detected, 01168 go back to best position */ 01169 result = cuddZddSymmSiftingBackward(table, move_down, 01170 initial_size); 01171 } 01172 else { 01173 while (move_up != NULL) { 01174 move = move_up->next; 01175 cuddDeallocMove(table, move_up); 01176 move_up = move; 01177 } 01178 initial_size = table->keysZ; 01179 move_up = cuddZddSymmSifting_up(table, x, x_low, 01180 initial_size); 01181 result = cuddZddSymmSiftingBackward(table, move_up, 01182 initial_size); 01183 } 01184 } 01185 else { 01186 result = cuddZddSymmSiftingBackward(table, move_down, 01187 initial_size); 01188 /* move backward and stop at best position */ 01189 } 01190 if (!result) 01191 goto cuddZddSymmSiftingConvAuxOutOfMem; 01192 } 01193 01194 while (move_down != NULL) { 01195 move = move_down->next; 01196 cuddDeallocMove(table, move_down); 01197 move_down = move; 01198 } 01199 while (move_up != NULL) { 01200 move = move_up->next; 01201 cuddDeallocMove(table, move_up); 01202 move_up = move; 01203 } 01204 01205 return(1); 01206 01207 cuddZddSymmSiftingConvAuxOutOfMem: 01208 if (move_down != ZDD_MV_OOM) { 01209 while (move_down != NULL) { 01210 move = move_down->next; 01211 cuddDeallocMove(table, move_down); 01212 move_down = move; 01213 } 01214 } 01215 if (move_up != ZDD_MV_OOM) { 01216 while (move_up != NULL) { 01217 move = move_up->next; 01218 cuddDeallocMove(table, move_up); 01219 move_up = move; 01220 } 01221 } 01222 01223 return(0); 01224 01225 } /* end of cuddZddSymmSiftingConvAux */
static void cuddZddSymmSummary | ( | 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 1667 of file cuddZddSymm.c.
01673 { 01674 int i,x,gbot; 01675 int TotalSymm = 0; 01676 int TotalSymmGroups = 0; 01677 01678 for (i = lower; i <= upper; i++) { 01679 if (table->subtableZ[i].next != (unsigned) i) { 01680 TotalSymmGroups++; 01681 x = i; 01682 do { 01683 TotalSymm++; 01684 gbot = x; 01685 x = table->subtableZ[x].next; 01686 } while (x != i); 01687 #ifdef DD_DEBUG 01688 assert(table->subtableZ[gbot].next == (unsigned) i); 01689 #endif 01690 i = gbot; 01691 } 01692 } 01693 *symvars = TotalSymm; 01694 *symgroups = TotalSymmGroups; 01695 01696 return; 01697 01698 } /* end of cuddZddSymmSummary */
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]
SeeAlso []
Definition at line 1477 of file cuddZddSymm.c.
01482 { 01483 Move *move; 01484 int size; 01485 int i, temp, gxtop, gxbot, gybot, yprev; 01486 int swapx, swapy; 01487 01488 #ifdef DD_DEBUG 01489 assert(x < y); /* we assume that x < y */ 01490 #endif 01491 /* Find top and bottom for the two groups. */ 01492 gxtop = table->subtableZ[x].next; 01493 gxbot = x; 01494 gybot = table->subtableZ[y].next; 01495 while (table->subtableZ[gybot].next != (unsigned) y) 01496 gybot = table->subtableZ[gybot].next; 01497 yprev = gybot; 01498 01499 while (x <= y) { 01500 while (y > gxtop) { 01501 /* Set correct symmetries. */ 01502 temp = table->subtableZ[x].next; 01503 if (temp == x) 01504 temp = y; 01505 i = gxtop; 01506 for (;;) { 01507 if (table->subtableZ[i].next == (unsigned) x) { 01508 table->subtableZ[i].next = y; 01509 break; 01510 } else { 01511 i = table->subtableZ[i].next; 01512 } 01513 } 01514 if (table->subtableZ[y].next != (unsigned) y) { 01515 table->subtableZ[x].next = table->subtableZ[y].next; 01516 } else { 01517 table->subtableZ[x].next = x; 01518 } 01519 01520 if (yprev != y) { 01521 table->subtableZ[yprev].next = x; 01522 } else { 01523 yprev = x; 01524 } 01525 table->subtableZ[y].next = temp; 01526 01527 size = cuddZddSwapInPlace(table, x, y); 01528 if (size == 0) 01529 goto zdd_group_moveOutOfMem; 01530 swapx = x; 01531 swapy = y; 01532 y = x; 01533 x--; 01534 } /* while y > gxtop */ 01535 01536 /* Trying to find the next y. */ 01537 if (table->subtableZ[y].next <= (unsigned) y) { 01538 gybot = y; 01539 } else { 01540 y = table->subtableZ[y].next; 01541 } 01542 01543 yprev = gxtop; 01544 gxtop++; 01545 gxbot++; 01546 x = gxbot; 01547 } /* while x <= y, end of group movement */ 01548 move = (Move *)cuddDynamicAllocNode(table); 01549 if (move == NULL) 01550 goto zdd_group_moveOutOfMem; 01551 move->x = swapx; 01552 move->y = swapy; 01553 move->size = table->keysZ; 01554 move->next = *moves; 01555 *moves = move; 01556 01557 return(table->keysZ); 01558 01559 zdd_group_moveOutOfMem: 01560 while (*moves != NULL) { 01561 move = (*moves)->next; 01562 cuddDeallocMove(table, *moves); 01563 *moves = move; 01564 } 01565 return(0); 01566 01567 } /* end of zdd_group_move */
static int zdd_group_move_backward | ( | 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 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
Definition at line 1584 of file cuddZddSymm.c.
01588 { 01589 int size; 01590 int i, temp, gxtop, gxbot, gybot, yprev; 01591 01592 #ifdef DD_DEBUG 01593 assert(x < y); /* we assume that x < y */ 01594 #endif 01595 /* Find top and bottom of the two groups. */ 01596 gxtop = table->subtableZ[x].next; 01597 gxbot = x; 01598 gybot = table->subtableZ[y].next; 01599 while (table->subtableZ[gybot].next != (unsigned) y) 01600 gybot = table->subtableZ[gybot].next; 01601 yprev = gybot; 01602 01603 while (x <= y) { 01604 while (y > gxtop) { 01605 /* Set correct symmetries. */ 01606 temp = table->subtableZ[x].next; 01607 if (temp == x) 01608 temp = y; 01609 i = gxtop; 01610 for (;;) { 01611 if (table->subtableZ[i].next == (unsigned) x) { 01612 table->subtableZ[i].next = y; 01613 break; 01614 } else { 01615 i = table->subtableZ[i].next; 01616 } 01617 } 01618 if (table->subtableZ[y].next != (unsigned) y) { 01619 table->subtableZ[x].next = table->subtableZ[y].next; 01620 } else { 01621 table->subtableZ[x].next = x; 01622 } 01623 01624 if (yprev != y) { 01625 table->subtableZ[yprev].next = x; 01626 } else { 01627 yprev = x; 01628 } 01629 table->subtableZ[y].next = temp; 01630 01631 size = cuddZddSwapInPlace(table, x, y); 01632 if (size == 0) 01633 return(0); 01634 y = x; 01635 x--; 01636 } /* while y > gxtop */ 01637 01638 /* Trying to find the next y. */ 01639 if (table->subtableZ[y].next <= (unsigned) y) { 01640 gybot = y; 01641 } else { 01642 y = table->subtableZ[y].next; 01643 } 01644 01645 yprev = gxtop; 01646 gxtop++; 01647 gxbot++; 01648 x = gxbot; 01649 } /* while x <= y, end of group movement backward */ 01650 01651 return(size); 01652 01653 } /* end of zdd_group_move_backward */
char rcsid [] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio Exp $" [static] |
Definition at line 92 of file cuddZddSymm.c.
Definition at line 99 of file cuddZddSymm.c.
int* zdd_entry |
Definition at line 104 of file cuddZddReord.c.
Definition at line 106 of file cuddZddReord.c.