summaryrefslogtreecommitdiffstats
path: root/abc70930/src/bdd/cudd/cuddSymmetry.c
diff options
context:
space:
mode:
Diffstat (limited to 'abc70930/src/bdd/cudd/cuddSymmetry.c')
-rw-r--r--abc70930/src/bdd/cudd/cuddSymmetry.c1668
1 files changed, 0 insertions, 1668 deletions
diff --git a/abc70930/src/bdd/cudd/cuddSymmetry.c b/abc70930/src/bdd/cudd/cuddSymmetry.c
deleted file mode 100644
index e5488b17..00000000
--- a/abc70930/src/bdd/cudd/cuddSymmetry.c
+++ /dev/null
@@ -1,1668 +0,0 @@
-/**CFile***********************************************************************
-
- FileName [cuddSymmetry.c]
-
- PackageName [cudd]
-
- Synopsis [Functions for symmetry-based variable reordering.]
-
- Description [External procedures included in this file:
- <ul>
- <li> Cudd_SymmProfile()
- </ul>
- Internal procedures included in this module:
- <ul>
- <li> cuddSymmCheck()
- <li> cuddSymmSifting()
- <li> cuddSymmSiftingConv()
- </ul>
- Static procedures included in this module:
- <ul>
- <li> ddSymmUniqueCompare()
- <li> ddSymmSiftingAux()
- <li> ddSymmSiftingConvAux()
- <li> ddSymmSiftingUp()
- <li> ddSymmSiftingDown()
- <li> ddSymmGroupMove()
- <li> ddSymmGroupMoveBackward()
- <li> ddSymmSiftingBackward()
- <li> ddSymmSummary()
- </ul>]
-
- Author [Shipra Panda, Fabio Somenzi]
-
- Copyright [This file was created at the University of Colorado at
- Boulder. The University of Colorado at Boulder makes no warranty
- about the suitability of this software for any purpose. It is
- presented on an AS IS basis.]
-
-******************************************************************************/
-
-#include "util_hack.h"
-#include "cuddInt.h"
-
-/*---------------------------------------------------------------------------*/
-/* Constant declarations */
-/*---------------------------------------------------------------------------*/
-
-#define MV_OOM (Move *)1
-
-/*---------------------------------------------------------------------------*/
-/* Stucture declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Type declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Variable declarations */
-/*---------------------------------------------------------------------------*/
-
-#ifndef lint
-static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $";
-#endif
-
-static int *entry;
-
-extern int ddTotalNumberSwapping;
-#ifdef DD_STATS
-extern int ddTotalNISwaps;
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Macro declarations */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-static int ddSymmUniqueCompare ARGS((int *ptrX, int *ptrY));
-static int ddSymmSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh));
-static int ddSymmSiftingConvAux ARGS((DdManager *table, int x, int xLow, int xHigh));
-static Move * ddSymmSiftingUp ARGS((DdManager *table, int y, int xLow));
-static Move * ddSymmSiftingDown ARGS((DdManager *table, int x, int xHigh));
-static int ddSymmGroupMove ARGS((DdManager *table, int x, int y, Move **moves));
-static int ddSymmGroupMoveBackward ARGS((DdManager *table, int x, int y));
-static int ddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size));
-static void ddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups));
-
-/**AutomaticEnd***************************************************************/
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of exported functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**Function********************************************************************
-
- Synopsis [Prints statistics on symmetric variables.]
-
- Description []
-
- SideEffects [None]
-
-******************************************************************************/
-void
-Cudd_SymmProfile(
- DdManager * table,
- int lower,
- int upper)
-{
- int i,x,gbot;
- int TotalSymm = 0;
- int TotalSymmGroups = 0;
-
- for (i = lower; i <= upper; i++) {
- if (table->subtables[i].next != (unsigned) i) {
- x = i;
- (void) fprintf(table->out,"Group:");
- do {
- (void) fprintf(table->out," %d",table->invperm[x]);
- TotalSymm++;
- gbot = x;
- x = table->subtables[x].next;
- } while (x != i);
- TotalSymmGroups++;
-#ifdef DD_DEBUG
- assert(table->subtables[gbot].next == (unsigned) i);
-#endif
- i = gbot;
- (void) fprintf(table->out,"\n");
- }
- }
- (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm);
- (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups);
-
-} /* end of Cudd_SymmProfile */
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of internal functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**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]
-
-******************************************************************************/
-int
-cuddSymmCheck(
- DdManager * table,
- int x,
- int y)
-{
- DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
- int comple; /* f0 is complemented */
- int xsymmy; /* x and y may be positively symmetric */
- int xsymmyp; /* x and y may be negatively symmetric */
- int arccount; /* number of arcs from layer x to layer y */
- int TotalRefCount; /* total reference count of layer y minus 1 */
- int yindex;
- int i;
- DdNodePtr *list;
- int slots;
- DdNode *sentinel = &(table->sentinel);
-#ifdef DD_DEBUG
- int xindex;
-#endif
-
- /* Checks that x and y are not the projection functions.
- ** For x it is sufficient to check whether there is only one
- ** node; indeed, if there is one node, it is the projection function
- ** and it cannot point to y. Hence, if y isn't just the projection
- ** function, it has one arc coming from a layer different from x.
- */
- if (table->subtables[x].keys == 1) {
- return(0);
- }
- yindex = table->invperm[y];
- if (table->subtables[y].keys == 1) {
- if (table->vars[yindex]->ref == 1)
- return(0);
- }
-
- xsymmy = xsymmyp = 1;
- arccount = 0;
- slots = table->subtables[x].slots;
- list = table->subtables[x].nodelist;
- for (i = 0; i < slots; i++) {
- f = list[i];
- while (f != sentinel) {
- /* Find f1, f0, f11, f10, f01, f00. */
- f1 = cuddT(f);
- f0 = Cudd_Regular(cuddE(f));
- comple = Cudd_IsComplement(cuddE(f));
- if ((int) f1->index == yindex) {
- arccount++;
- f11 = cuddT(f1); f10 = cuddE(f1);
- } else {
- if ((int) f0->index != yindex) {
- /* If f is an isolated projection function it is
- ** allowed to bypass layer y.
- */
- if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
- return(0); /* f bypasses layer y */
- }
- f11 = f10 = f1;
- }
- if ((int) f0->index == yindex) {
- arccount++;
- f01 = cuddT(f0); f00 = cuddE(f0);
- } else {
- f01 = f00 = f0;
- }
- if (comple) {
- f01 = Cudd_Not(f01);
- f00 = Cudd_Not(f00);
- }
-
- if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
- xsymmy &= f01 == f10;
- xsymmyp &= f11 == f00;
- if ((xsymmy == 0) && (xsymmyp == 0))
- return(0);
- }
-
- f = f->next;
- } /* while */
- } /* for */
-
- /* Calculate the total reference counts of y */
- TotalRefCount = -1; /* -1 for projection function */
- slots = table->subtables[y].slots;
- list = table->subtables[y].nodelist;
- for (i = 0; i < slots; i++) {
- f = list[i];
- while (f != sentinel) {
- TotalRefCount += f->ref;
- f = f->next;
- }
- }
-
-#if defined(DD_DEBUG) && defined(DD_VERBOSE)
- if (arccount == TotalRefCount) {
- xindex = table->invperm[x];
- (void) fprintf(table->out,
- "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
- xindex,yindex,x,y);
- }
-#endif
-
- return(arccount == TotalRefCount);
-
-} /* end of cuddSymmCheck */
-
-
-/**Function********************************************************************
-
- Synopsis [Symmetric sifting algorithm.]
-
- Description [Symmetric sifting algorithm.
- Assumes that no dead nodes are present.
- <ol>
- <li> Order all the variables according to the number of entries in
- each unique subtable.
- <li> Sift the variable up and down, remembering each time the total
- size of the DD heap and grouping variables that are symmetric.
- <li> Select the best permutation.
- <li> Repeat 3 and 4 for all variables.
- </ol>
- Returns 1 plus the number of symmetric variables if successful; 0
- otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddSymmSiftingConv]
-
-******************************************************************************/
-int
-cuddSymmSifting(
- DdManager * table,
- int lower,
- int upper)
-{
- int i;
- int *var;
- int size;
- int x;
- int result;
- int symvars;
- int symgroups;
-#ifdef DD_STATS
- int previousSize;
-#endif
-
- size = table->size;
-
- /* Find order in which to sift variables. */
- var = NULL;
- entry = ALLOC(int,size);
- if (entry == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- goto ddSymmSiftingOutOfMem;
- }
- var = ALLOC(int,size);
- if (var == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- goto ddSymmSiftingOutOfMem;
- }
-
- for (i = 0; i < size; i++) {
- x = table->perm[i];
- entry[i] = table->subtables[x].keys;
- var[i] = i;
- }
-
- qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare);
-
- /* Initialize the symmetry of each subtable to itself. */
- for (i = lower; i <= upper; i++) {
- table->subtables[i].next = i;
- }
-
- for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
- if (ddTotalNumberSwapping >= table->siftMaxSwap)
- break;
- x = table->perm[var[i]];
-#ifdef DD_STATS
- previousSize = table->keys - table->isolated;
-#endif
- if (x < lower || x > upper) continue;
- if (table->subtables[x].next == (unsigned) x) {
- result = ddSymmSiftingAux(table,x,lower,upper);
- if (!result) goto ddSymmSiftingOutOfMem;
-#ifdef DD_STATS
- if (table->keys < (unsigned) previousSize + table->isolated) {
- (void) fprintf(table->out,"-");
- } else if (table->keys > (unsigned) previousSize +
- table->isolated) {
- (void) fprintf(table->out,"+"); /* should never happen */
- } else {
- (void) fprintf(table->out,"=");
- }
- fflush(table->out);
-#endif
- }
- }
-
- FREE(var);
- FREE(entry);
-
- ddSymmSummary(table, lower, upper, &symvars, &symgroups);
-
-#ifdef DD_STATS
- (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
- symvars);
- (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
- symgroups);
-#endif
-
- return(1+symvars);
-
-ddSymmSiftingOutOfMem:
-
- if (entry != NULL) FREE(entry);
- if (var != NULL) FREE(var);
-
- return(0);
-
-} /* end of cuddSymmSifting */
-
-
-/**Function********************************************************************
-
- Synopsis [Symmetric sifting to convergence algorithm.]
-
- Description [Symmetric sifting to convergence algorithm.
- Assumes that no dead nodes are present.
- <ol>
- <li> Order all the variables according to the number of entries in
- each unique subtable.
- <li> Sift the variable up and down, remembering each time the total
- size of the DD heap and grouping variables that are symmetric.
- <li> Select the best permutation.
- <li> Repeat 3 and 4 for all variables.
- <li> Repeat 1-4 until no further improvement.
- </ol>
- Returns 1 plus the number of symmetric variables if successful; 0
- otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddSymmSifting]
-
-******************************************************************************/
-int
-cuddSymmSiftingConv(
- DdManager * table,
- int lower,
- int upper)
-{
- int i;
- int *var;
- int size;
- int x;
- int result;
- int symvars;
- int symgroups;
- int classes;
- int initialSize;
-#ifdef DD_STATS
- int previousSize;
-#endif
-
- initialSize = table->keys - table->isolated;
-
- size = table->size;
-
- /* Find order in which to sift variables. */
- var = NULL;
- entry = ALLOC(int,size);
- if (entry == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- goto ddSymmSiftingConvOutOfMem;
- }
- var = ALLOC(int,size);
- if (var == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- goto ddSymmSiftingConvOutOfMem;
- }
-
- for (i = 0; i < size; i++) {
- x = table->perm[i];
- entry[i] = table->subtables[x].keys;
- var[i] = i;
- }
-
- qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare);
-
- /* Initialize the symmetry of each subtable to itself
- ** for first pass of converging symmetric sifting.
- */
- for (i = lower; i <= upper; i++) {
- table->subtables[i].next = i;
- }
-
- for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
- if (ddTotalNumberSwapping >= table->siftMaxSwap)
- break;
- x = table->perm[var[i]];
- if (x < lower || x > upper) continue;
- /* Only sift if not in symmetry group already. */
- if (table->subtables[x].next == (unsigned) x) {
-#ifdef DD_STATS
- previousSize = table->keys - table->isolated;
-#endif
- result = ddSymmSiftingAux(table,x,lower,upper);
- if (!result) goto ddSymmSiftingConvOutOfMem;
-#ifdef DD_STATS
- if (table->keys < (unsigned) previousSize + table->isolated) {
- (void) fprintf(table->out,"-");
- } else if (table->keys > (unsigned) previousSize +
- table->isolated) {
- (void) fprintf(table->out,"+");
- } else {
- (void) fprintf(table->out,"=");
- }
- fflush(table->out);
-#endif
- }
- }
-
- /* Sifting now until convergence. */
- while ((unsigned) initialSize > table->keys - table->isolated) {
- initialSize = table->keys - table->isolated;
-#ifdef DD_STATS
- (void) fprintf(table->out,"\n");
-#endif
- /* Here we consider only one representative for each symmetry class. */
- for (x = lower, classes = 0; x <= upper; x++, classes++) {
- while ((unsigned) x < table->subtables[x].next) {
- x = table->subtables[x].next;
- }
- /* Here x is the largest index in a group.
- ** Groups consist of adjacent variables.
- ** Hence, the next increment of x will move it to a new group.
- */
- i = table->invperm[x];
- entry[i] = table->subtables[x].keys;
- var[classes] = i;
- }
-
- qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare);
-
- /* Now sift. */
- for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
- if (ddTotalNumberSwapping >= table->siftMaxSwap)
- break;
- x = table->perm[var[i]];
- if ((unsigned) x >= table->subtables[x].next) {
-#ifdef DD_STATS
- previousSize = table->keys - table->isolated;
-#endif
- result = ddSymmSiftingConvAux(table,x,lower,upper);
- if (!result ) goto ddSymmSiftingConvOutOfMem;
-#ifdef DD_STATS
- if (table->keys < (unsigned) previousSize + table->isolated) {
- (void) fprintf(table->out,"-");
- } else if (table->keys > (unsigned) previousSize +
- table->isolated) {
- (void) fprintf(table->out,"+");
- } else {
- (void) fprintf(table->out,"=");
- }
- fflush(table->out);
-#endif
- }
- } /* for */
- }
-
- ddSymmSummary(table, lower, upper, &symvars, &symgroups);
-
-#ifdef DD_STATS
- (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
- symvars);
- (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
- symgroups);
-#endif
-
- FREE(var);
- FREE(entry);
-
- return(1+symvars);
-
-ddSymmSiftingConvOutOfMem:
-
- if (entry != NULL) FREE(entry);
- if (var != NULL) FREE(var);
-
- return(0);
-
-} /* end of cuddSymmSiftingConv */
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of static functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**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]
-
-******************************************************************************/
-static int
-ddSymmUniqueCompare(
- int * ptrX,
- int * ptrY)
-{
-#if 0
- if (entry[*ptrY] == entry[*ptrX]) {
- return((*ptrX) - (*ptrY));
- }
-#endif
- return(entry[*ptrY] - entry[*ptrX]);
-
-} /* end of ddSymmUniqueCompare */
-
-
-/**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]
-
-******************************************************************************/
-static int
-ddSymmSiftingAux(
- DdManager * table,
- int x,
- int xLow,
- int xHigh)
-{
- Move *move;
- Move *moveUp; /* list of up moves */
- Move *moveDown; /* list of down moves */
- int initialSize;
- int result;
- int i;
- int topbot; /* index to either top or bottom of symmetry group */
- int initGroupSize, finalGroupSize;
-
-
-#ifdef DD_DEBUG
- /* check for previously detected symmetry */
- assert(table->subtables[x].next == (unsigned) x);
-#endif
-
- initialSize = table->keys - table->isolated;
-
- moveDown = NULL;
- moveUp = NULL;
-
- if ((x - xLow) > (xHigh - x)) {
- /* Will go down first, unless x == xHigh:
- ** Look for consecutive symmetries above x.
- */
- for (i = x; i > xLow; i--) {
- if (!cuddSymmCheck(table,i-1,i))
- break;
- topbot = table->subtables[i-1].next; /* find top of i-1's group */
- table->subtables[i-1].next = i;
- table->subtables[x].next = topbot; /* x is bottom of group so its */
- /* next is top of i-1's group */
- i = topbot + 1; /* add 1 for i--; new i is top of symm group */
- }
- } else {
- /* Will go up first unless x == xlow:
- ** Look for consecutive symmetries below x.
- */
- for (i = x; i < xHigh; i++) {
- if (!cuddSymmCheck(table,i,i+1))
- break;
- /* find bottom of i+1's symm group */
- topbot = i + 1;
- while ((unsigned) topbot < table->subtables[topbot].next) {
- topbot = table->subtables[topbot].next;
- }
- table->subtables[topbot].next = table->subtables[i].next;
- table->subtables[i].next = i + 1;
- i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */
- }
- }
-
- /* Now x may be in the middle of a symmetry group.
- ** Find bottom of x's symm group.
- */
- while ((unsigned) x < table->subtables[x].next)
- x = table->subtables[x].next;
-
- if (x == xLow) { /* Sift down */
-
-#ifdef DD_DEBUG
- /* x must be a singleton */
- assert((unsigned) x == table->subtables[x].next);
-#endif
- if (x == xHigh) return(1); /* just one variable */
-
- initGroupSize = 1;
-
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- /* after this point x --> xHigh, unless early term */
- if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
- if (moveDown == NULL) return(1);
-
- x = moveDown->y;
- /* Find bottom of x's group */
- i = x;
- while ((unsigned) i < table->subtables[i].next) {
- i = table->subtables[i].next;
- }
-#ifdef DD_DEBUG
- /* x should be the top of the symmetry group and i the bottom */
- assert((unsigned) i >= table->subtables[i].next);
- assert((unsigned) x == table->subtables[i].next);
-#endif
- finalGroupSize = i - x + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetry groups detected, return to best position */
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- } else {
- initialSize = table->keys - table->isolated;
- moveUp = ddSymmSiftingUp(table,x,xLow);
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- }
- if (!result) goto ddSymmSiftingAuxOutOfMem;
-
- } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
- /* Find top of x's symm group */
- i = x; /* bottom */
- x = table->subtables[x].next; /* top */
-
- if (x == xLow) return(1); /* just one big group */
-
- initGroupSize = i - x + 1;
-
- moveUp = ddSymmSiftingUp(table,x,xLow);
- /* after this point x --> xLow, unless early term */
- if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
- if (moveUp == NULL) return(1);
-
- x = moveUp->x;
- /* Find top of x's group */
- i = table->subtables[x].next;
-#ifdef DD_DEBUG
- /* x should be the bottom of the symmetry group and i the top */
- assert((unsigned) x >= table->subtables[x].next);
- assert((unsigned) i == table->subtables[x].next);
-#endif
- finalGroupSize = x - i + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetry groups detected, return to best position */
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- } else {
- initialSize = table->keys - table->isolated;
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- }
- if (!result) goto ddSymmSiftingAuxOutOfMem;
-
- } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
-
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- /* at this point x == xHigh, unless early term */
- if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
-
- if (moveDown != NULL) {
- x = moveDown->y; /* x is top here */
- i = x;
- while ((unsigned) i < table->subtables[i].next) {
- i = table->subtables[i].next;
- }
- } else {
- i = x;
- while ((unsigned) i < table->subtables[i].next) {
- i = table->subtables[i].next;
- }
- x = table->subtables[i].next;
- }
-#ifdef DD_DEBUG
- /* x should be the top of the symmetry group and i the bottom */
- assert((unsigned) i >= table->subtables[i].next);
- assert((unsigned) x == table->subtables[i].next);
-#endif
- initGroupSize = i - x + 1;
-
- moveUp = ddSymmSiftingUp(table,x,xLow);
- if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
-
- if (moveUp != NULL) {
- x = moveUp->x;
- i = table->subtables[x].next;
- } else {
- i = x;
- while ((unsigned) x < table->subtables[x].next)
- x = table->subtables[x].next;
- }
-#ifdef DD_DEBUG
- /* x should be the bottom of the symmetry group and i the top */
- assert((unsigned) x >= table->subtables[x].next);
- assert((unsigned) i == table->subtables[x].next);
-#endif
- finalGroupSize = x - i + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetry groups detected, return to best position */
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- } else {
- while (moveDown != NULL) {
- move = moveDown->next;
- cuddDeallocNode(table, (DdNode *) moveDown);
- moveDown = move;
- }
- initialSize = table->keys - table->isolated;
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- }
- if (!result) goto ddSymmSiftingAuxOutOfMem;
-
- } else { /* moving up first: shorter */
- /* Find top of x's symmetry group */
- x = table->subtables[x].next;
-
- moveUp = ddSymmSiftingUp(table,x,xLow);
- /* at this point x == xHigh, unless early term */
- if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
-
- if (moveUp != NULL) {
- x = moveUp->x;
- i = table->subtables[x].next;
- } else {
- while ((unsigned) x < table->subtables[x].next)
- x = table->subtables[x].next;
- i = table->subtables[x].next;
- }
-#ifdef DD_DEBUG
- /* x is bottom of the symmetry group and i is top */
- assert((unsigned) x >= table->subtables[x].next);
- assert((unsigned) i == table->subtables[x].next);
-#endif
- initGroupSize = x - i + 1;
-
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
-
- if (moveDown != NULL) {
- x = moveDown->y;
- i = x;
- while ((unsigned) i < table->subtables[i].next) {
- i = table->subtables[i].next;
- }
- } else {
- i = x;
- x = table->subtables[x].next;
- }
-#ifdef DD_DEBUG
- /* x should be the top of the symmetry group and i the bottom */
- assert((unsigned) i >= table->subtables[i].next);
- assert((unsigned) x == table->subtables[i].next);
-#endif
- finalGroupSize = i - x + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetries detected, go back to best position */
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- } else {
- while (moveUp != NULL) {
- move = moveUp->next;
- cuddDeallocNode(table, (DdNode *) moveUp);
- moveUp = move;
- }
- initialSize = table->keys - table->isolated;
- moveUp = ddSymmSiftingUp(table,x,xLow);
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- }
- if (!result) goto ddSymmSiftingAuxOutOfMem;
- }
-
- while (moveDown != NULL) {
- move = moveDown->next;
- cuddDeallocNode(table, (DdNode *) moveDown);
- moveDown = move;
- }
- while (moveUp != NULL) {
- move = moveUp->next;
- cuddDeallocNode(table, (DdNode *) moveUp);
- moveUp = move;
- }
-
- return(1);
-
-ddSymmSiftingAuxOutOfMem:
- if (moveDown != MV_OOM) {
- while (moveDown != NULL) {
- move = moveDown->next;
- cuddDeallocNode(table, (DdNode *) moveDown);
- moveDown = move;
- }
- }
- if (moveUp != MV_OOM) {
- while (moveUp != NULL) {
- move = moveUp->next;
- cuddDeallocNode(table, (DdNode *) moveUp);
- moveUp = move;
- }
- }
-
- return(0);
-
-} /* end of ddSymmSiftingAux */
-
-
-/**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]
-
-******************************************************************************/
-static int
-ddSymmSiftingConvAux(
- DdManager * table,
- int x,
- int xLow,
- int xHigh)
-{
- Move *move;
- Move *moveUp; /* list of up moves */
- Move *moveDown; /* list of down moves */
- int initialSize;
- int result;
- int i;
- int initGroupSize, finalGroupSize;
-
-
- initialSize = table->keys - table->isolated;
-
- moveDown = NULL;
- moveUp = NULL;
-
- if (x == xLow) { /* Sift down */
-#ifdef DD_DEBUG
- /* x is bottom of symmetry group */
- assert((unsigned) x >= table->subtables[x].next);
-#endif
- i = table->subtables[x].next;
- initGroupSize = x - i + 1;
-
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- /* at this point x == xHigh, unless early term */
- if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
- if (moveDown == NULL) return(1);
-
- x = moveDown->y;
- i = x;
- while ((unsigned) i < table->subtables[i].next) {
- i = table->subtables[i].next;
- }
-#ifdef DD_DEBUG
- /* x should be the top of the symmetric group and i the bottom */
- assert((unsigned) i >= table->subtables[i].next);
- assert((unsigned) x == table->subtables[i].next);
-#endif
- finalGroupSize = i - x + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetries detected, go back to best position */
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- } else {
- initialSize = table->keys - table->isolated;
- moveUp = ddSymmSiftingUp(table,x,xLow);
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- }
- if (!result) goto ddSymmSiftingConvAuxOutOfMem;
-
- } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
- /* Find top of x's symm group */
- while ((unsigned) x < table->subtables[x].next)
- x = table->subtables[x].next;
- i = x; /* bottom */
- x = table->subtables[x].next; /* top */
-
- if (x == xLow) return(1);
-
- initGroupSize = i - x + 1;
-
- moveUp = ddSymmSiftingUp(table,x,xLow);
- /* at this point x == xLow, unless early term */
- if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
- if (moveUp == NULL) return(1);
-
- x = moveUp->x;
- i = table->subtables[x].next;
-#ifdef DD_DEBUG
- /* x should be the bottom of the symmetry group and i the top */
- assert((unsigned) x >= table->subtables[x].next);
- assert((unsigned) i == table->subtables[x].next);
-#endif
- finalGroupSize = x - i + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetry groups detected, return to best position */
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- } else {
- initialSize = table->keys - table->isolated;
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- }
- if (!result)
- goto ddSymmSiftingConvAuxOutOfMem;
-
- } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- /* at this point x == xHigh, unless early term */
- if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
-
- if (moveDown != NULL) {
- x = moveDown->y;
- i = x;
- while ((unsigned) i < table->subtables[i].next) {
- i = table->subtables[i].next;
- }
- } else {
- while ((unsigned) x < table->subtables[x].next)
- x = table->subtables[x].next;
- i = x;
- x = table->subtables[x].next;
- }
-#ifdef DD_DEBUG
- /* x should be the top of the symmetry group and i the bottom */
- assert((unsigned) i >= table->subtables[i].next);
- assert((unsigned) x == table->subtables[i].next);
-#endif
- initGroupSize = i - x + 1;
-
- moveUp = ddSymmSiftingUp(table,x,xLow);
- if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
-
- if (moveUp != NULL) {
- x = moveUp->x;
- i = table->subtables[x].next;
- } else {
- i = x;
- while ((unsigned) x < table->subtables[x].next)
- x = table->subtables[x].next;
- }
-#ifdef DD_DEBUG
- /* x should be the bottom of the symmetry group and i the top */
- assert((unsigned) x >= table->subtables[x].next);
- assert((unsigned) i == table->subtables[x].next);
-#endif
- finalGroupSize = x - i + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetry groups detected, return to best position */
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- } else {
- while (moveDown != NULL) {
- move = moveDown->next;
- cuddDeallocNode(table, (DdNode *) moveDown);
- moveDown = move;
- }
- initialSize = table->keys - table->isolated;
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- }
- if (!result) goto ddSymmSiftingConvAuxOutOfMem;
-
- } else { /* moving up first: shorter */
- /* Find top of x's symmetry group */
- x = table->subtables[x].next;
-
- moveUp = ddSymmSiftingUp(table,x,xLow);
- /* at this point x == xHigh, unless early term */
- if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
-
- if (moveUp != NULL) {
- x = moveUp->x;
- i = table->subtables[x].next;
- } else {
- i = x;
- while ((unsigned) x < table->subtables[x].next)
- x = table->subtables[x].next;
- }
-#ifdef DD_DEBUG
- /* x is bottom of the symmetry group and i is top */
- assert((unsigned) x >= table->subtables[x].next);
- assert((unsigned) i == table->subtables[x].next);
-#endif
- initGroupSize = x - i + 1;
-
- moveDown = ddSymmSiftingDown(table,x,xHigh);
- if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
-
- if (moveDown != NULL) {
- x = moveDown->y;
- i = x;
- while ((unsigned) i < table->subtables[i].next) {
- i = table->subtables[i].next;
- }
- } else {
- i = x;
- x = table->subtables[x].next;
- }
-#ifdef DD_DEBUG
- /* x should be the top of the symmetry group and i the bottom */
- assert((unsigned) i >= table->subtables[i].next);
- assert((unsigned) x == table->subtables[i].next);
-#endif
- finalGroupSize = i - x + 1;
-
- if (initGroupSize == finalGroupSize) {
- /* No new symmetries detected, go back to best position */
- result = ddSymmSiftingBackward(table,moveDown,initialSize);
- } else {
- while (moveUp != NULL) {
- move = moveUp->next;
- cuddDeallocNode(table, (DdNode *) moveUp);
- moveUp = move;
- }
- initialSize = table->keys - table->isolated;
- moveUp = ddSymmSiftingUp(table,x,xLow);
- result = ddSymmSiftingBackward(table,moveUp,initialSize);
- }
- if (!result) goto ddSymmSiftingConvAuxOutOfMem;
- }
-
- while (moveDown != NULL) {
- move = moveDown->next;
- cuddDeallocNode(table, (DdNode *) moveDown);
- moveDown = move;
- }
- while (moveUp != NULL) {
- move = moveUp->next;
- cuddDeallocNode(table, (DdNode *) moveUp);
- moveUp = move;
- }
-
- return(1);
-
-ddSymmSiftingConvAuxOutOfMem:
- if (moveDown != MV_OOM) {
- while (moveDown != NULL) {
- move = moveDown->next;
- cuddDeallocNode(table, (DdNode *) moveDown);
- moveDown = move;
- }
- }
- if (moveUp != MV_OOM) {
- while (moveUp != NULL) {
- move = moveUp->next;
- cuddDeallocNode(table, (DdNode *) moveUp);
- moveUp = move;
- }
- }
-
- return(0);
-
-} /* end of ddSymmSiftingConvAux */
-
-
-/**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]
-
-******************************************************************************/
-static Move *
-ddSymmSiftingUp(
- DdManager * table,
- int y,
- int xLow)
-{
- Move *moves;
- Move *move;
- int x;
- int size;
- int i;
- int gxtop,gybot;
- int limitSize;
- int xindex, yindex;
- int zindex;
- int z;
- int isolated;
- int L; /* lower bound on DD size */
-#ifdef DD_DEBUG
- int checkL;
-#endif
-
-
- moves = NULL;
- yindex = table->invperm[y];
-
- /* Initialize the lower bound.
- ** The part of the DD below the bottom of y' group will not change.
- ** The part of the DD above y that does not interact with y will not
- ** change. The rest may vanish in the best case, except for
- ** the nodes at level xLow, which will not vanish, regardless.
- */
- limitSize = L = table->keys - table->isolated;
- gybot = y;
- while ((unsigned) gybot < table->subtables[gybot].next)
- gybot = table->subtables[gybot].next;
- for (z = xLow + 1; z <= gybot; z++) {
- zindex = table->invperm[z];
- if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
- isolated = table->vars[zindex]->ref == 1;
- L -= table->subtables[z].keys - isolated;
- }
- }
-
- x = cuddNextLow(table,y);
- while (x >= xLow && L <= limitSize) {
-#ifdef DD_DEBUG
- gybot = y;
- while ((unsigned) gybot < table->subtables[gybot].next)
- gybot = table->subtables[gybot].next;
- checkL = table->keys - table->isolated;
- for (z = xLow + 1; z <= gybot; z++) {
- zindex = table->invperm[z];
- if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
- isolated = table->vars[zindex]->ref == 1;
- checkL -= table->subtables[z].keys - isolated;
- }
- }
- assert(L == checkL);
-#endif
- gxtop = table->subtables[x].next;
- if (cuddSymmCheck(table,x,y)) {
- /* Symmetry found, attach symm groups */
- table->subtables[x].next = y;
- i = table->subtables[y].next;
- while (table->subtables[i].next != (unsigned) y)
- i = table->subtables[i].next;
- table->subtables[i].next = gxtop;
- } else if (table->subtables[x].next == (unsigned) x &&
- table->subtables[y].next == (unsigned) y) {
- /* x and y have self symmetry */
- xindex = table->invperm[x];
- size = cuddSwapInPlace(table,x,y);
-#ifdef DD_DEBUG
- assert(table->subtables[x].next == (unsigned) x);
- assert(table->subtables[y].next == (unsigned) y);
-#endif
- if (size == 0) goto ddSymmSiftingUpOutOfMem;
- /* Update the lower bound. */
- if (cuddTestInteract(table,xindex,yindex)) {
- isolated = table->vars[xindex]->ref == 1;
- L += table->subtables[y].keys - isolated;
- }
- move = (Move *) cuddDynamicAllocNode(table);
- if (move == NULL) goto ddSymmSiftingUpOutOfMem;
- move->x = x;
- move->y = y;
- move->size = size;
- move->next = moves;
- moves = move;
- if ((double) size > (double) limitSize * table->maxGrowth)
- return(moves);
- if (size < limitSize) limitSize = size;
- } else { /* Group move */
- size = ddSymmGroupMove(table,x,y,&moves);
- if (size == 0) goto ddSymmSiftingUpOutOfMem;
- /* Update the lower bound. */
- z = moves->y;
- do {
- zindex = table->invperm[z];
- if (cuddTestInteract(table,zindex,yindex)) {
- isolated = table->vars[zindex]->ref == 1;
- L += table->subtables[z].keys - isolated;
- }
- z = table->subtables[z].next;
- } while (z != (int) moves->y);
- if ((double) size > (double) limitSize * table->maxGrowth)
- return(moves);
- if (size < limitSize) limitSize = size;
- }
- y = gxtop;
- x = cuddNextLow(table,y);
- }
-
- return(moves);
-
-ddSymmSiftingUpOutOfMem:
- while (moves != NULL) {
- move = moves->next;
- cuddDeallocNode(table, (DdNode *) moves);
- moves = move;
- }
- return(MV_OOM);
-
-} /* end of ddSymmSiftingUp */
-
-
-/**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]
-
-******************************************************************************/
-static Move *
-ddSymmSiftingDown(
- DdManager * table,
- int x,
- int xHigh)
-{
- Move *moves;
- Move *move;
- int y;
- int size;
- int limitSize;
- int gxtop,gybot;
- int R; /* upper bound on node decrease */
- int xindex, yindex;
- int isolated;
- int z;
- int zindex;
-#ifdef DD_DEBUG
- int checkR;
-#endif
-
- moves = NULL;
- /* Initialize R */
- xindex = table->invperm[x];
- gxtop = table->subtables[x].next;
- limitSize = size = table->keys - table->isolated;
- R = 0;
- for (z = xHigh; z > gxtop; z--) {
- zindex = table->invperm[z];
- if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
- isolated = table->vars[zindex]->ref == 1;
- R += table->subtables[z].keys - isolated;
- }
- }
-
- y = cuddNextHigh(table,x);
- while (y <= xHigh && size - R < limitSize) {
-#ifdef DD_DEBUG
- gxtop = table->subtables[x].next;
- checkR = 0;
- for (z = xHigh; z > gxtop; z--) {
- zindex = table->invperm[z];
- if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
- isolated = table->vars[zindex]->ref == 1;
- checkR += table->subtables[z].keys - isolated;
- }
- }
- assert(R == checkR);
-#endif
- gybot = table->subtables[y].next;
- while (table->subtables[gybot].next != (unsigned) y)
- gybot = table->subtables[gybot].next;
- if (cuddSymmCheck(table,x,y)) {
- /* Symmetry found, attach symm groups */
- gxtop = table->subtables[x].next;
- table->subtables[x].next = y;
- table->subtables[gybot].next = gxtop;
- } else if (table->subtables[x].next == (unsigned) x &&
- table->subtables[y].next == (unsigned) y) {
- /* x and y have self symmetry */
- /* Update upper bound on node decrease. */
- yindex = table->invperm[y];
- if (cuddTestInteract(table,xindex,yindex)) {
- isolated = table->vars[yindex]->ref == 1;
- R -= table->subtables[y].keys - isolated;
- }
- size = cuddSwapInPlace(table,x,y);
-#ifdef DD_DEBUG
- assert(table->subtables[x].next == (unsigned) x);
- assert(table->subtables[y].next == (unsigned) y);
-#endif
- if (size == 0) goto ddSymmSiftingDownOutOfMem;
- move = (Move *) cuddDynamicAllocNode(table);
- if (move == NULL) goto ddSymmSiftingDownOutOfMem;
- move->x = x;
- move->y = y;
- move->size = size;
- move->next = moves;
- moves = move;
- if ((double) size > (double) limitSize * table->maxGrowth)
- return(moves);
- if (size < limitSize) limitSize = size;
- } else { /* Group move */
- /* Update upper bound on node decrease: first phase. */
- gxtop = table->subtables[x].next;
- z = gxtop + 1;
- do {
- zindex = table->invperm[z];
- if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
- isolated = table->vars[zindex]->ref == 1;
- R -= table->subtables[z].keys - isolated;
- }
- z++;
- } while (z <= gybot);
- size = ddSymmGroupMove(table,x,y,&moves);
- if (size == 0) goto ddSymmSiftingDownOutOfMem;
- if ((double) size > (double) limitSize * table->maxGrowth)
- return(moves);
- if (size < limitSize) limitSize = size;
- /* Update upper bound on node decrease: second phase. */
- gxtop = table->subtables[gybot].next;
- for (z = gxtop + 1; z <= gybot; z++) {
- zindex = table->invperm[z];
- if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
- isolated = table->vars[zindex]->ref == 1;
- R += table->subtables[z].keys - isolated;
- }
- }
- }
- x = gybot;
- y = cuddNextHigh(table,x);
- }
-
- return(moves);
-
-ddSymmSiftingDownOutOfMem:
- while (moves != NULL) {
- move = moves->next;
- cuddDeallocNode(table, (DdNode *) moves);
- moves = move;
- }
- return(MV_OOM);
-
-} /* end of ddSymmSiftingDown */
-
-
-/**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]
-
-******************************************************************************/
-static int
-ddSymmGroupMove(
- DdManager * table,
- int x,
- int y,
- Move ** moves)
-{
- Move *move;
- int size;
- int i,j;
- int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
- int swapx,swapy;
-
-#if DD_DEBUG
- assert(x < y); /* we assume that x < y */
-#endif
- /* Find top, bottom, and size for the two groups. */
- xbot = x;
- xtop = table->subtables[x].next;
- xsize = xbot - xtop + 1;
- ybot = y;
- while ((unsigned) ybot < table->subtables[ybot].next)
- ybot = table->subtables[ybot].next;
- ytop = y;
- ysize = ybot - ytop + 1;
-
- /* Sift the variables of the second group up through the first group. */
- for (i = 1; i <= ysize; i++) {
- for (j = 1; j <= xsize; j++) {
- size = cuddSwapInPlace(table,x,y);
- if (size == 0) return(0);
- swapx = x; swapy = y;
- y = x;
- x = y - 1;
- }
- y = ytop + i;
- x = y - 1;
- }
-
- /* fix symmetries */
- y = xtop; /* ytop is now where xtop used to be */
- for (i = 0; i < ysize-1 ; i++) {
- table->subtables[y].next = y + 1;
- y = y + 1;
- }
- table->subtables[y].next = xtop; /* y is bottom of its group, join */
- /* its symmetry to top of its group */
- x = y + 1;
- newxtop = x;
- for (i = 0; i < xsize - 1 ; i++) {
- table->subtables[x].next = x + 1;
- x = x + 1;
- }
- table->subtables[x].next = newxtop; /* x is bottom of its group, join */
- /* its symmetry to top of its group */
- /* Store group move */
- move = (Move *) cuddDynamicAllocNode(table);
- if (move == NULL) return(0);
- move->x = swapx;
- move->y = swapy;
- move->size = size;
- move->next = *moves;
- *moves = move;
-
- return(size);
-
-} /* end of ddSymmGroupMove */
-
-
-/**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]
-
-******************************************************************************/
-static int
-ddSymmGroupMoveBackward(
- DdManager * table,
- int x,
- int y)
-{
- int size;
- int i,j;
- int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
-
-#if DD_DEBUG
- assert(x < y); /* We assume that x < y */
-#endif
-
- /* Find top, bottom, and size for the two groups. */
- xbot = x;
- xtop = table->subtables[x].next;
- xsize = xbot - xtop + 1;
- ybot = y;
- while ((unsigned) ybot < table->subtables[ybot].next)
- ybot = table->subtables[ybot].next;
- ytop = y;
- ysize = ybot - ytop + 1;
-
- /* Sift the variables of the second group up through the first group. */
- for (i = 1; i <= ysize; i++) {
- for (j = 1; j <= xsize; j++) {
- size = cuddSwapInPlace(table,x,y);
- if (size == 0) return(0);
- y = x;
- x = cuddNextLow(table,y);
- }
- y = ytop + i;
- x = y - 1;
- }
-
- /* Fix symmetries. */
- y = xtop;
- for (i = 0; i < ysize-1 ; i++) {
- table->subtables[y].next = y + 1;
- y = y + 1;
- }
- table->subtables[y].next = xtop; /* y is bottom of its group, join */
- /* its symmetry to top of its group */
- x = y + 1;
- newxtop = x;
- for (i = 0; i < xsize-1 ; i++) {
- table->subtables[x].next = x + 1;
- x = x + 1;
- }
- table->subtables[x].next = newxtop; /* x is bottom of its group, join */
- /* its symmetry to top of its group */
-
- return(size);
-
-} /* end of ddSymmGroupMoveBackward */
-
-
-/**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]
-
-******************************************************************************/
-static int
-ddSymmSiftingBackward(
- DdManager * table,
- Move * moves,
- int size)
-{
- Move *move;
- int res;
-
- for (move = moves; move != NULL; move = move->next) {
- if (move->size < size) {
- size = move->size;
- }
- }
-
- for (move = moves; move != NULL; move = move->next) {
- if (move->size == size) return(1);
- if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
- res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
-#ifdef DD_DEBUG
- assert(table->subtables[move->x].next == move->x);
- assert(table->subtables[move->y].next == move->y);
-#endif
- } else { /* Group move necessary */
- res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
- }
- if (!res) return(0);
- }
-
- return(1);
-
-} /* end of ddSymmSiftingBackward */
-
-
-/**Function********************************************************************
-
- Synopsis [Counts numbers of symmetric variables and symmetry
- groups.]
-
- Description []
-
- SideEffects [None]
-
-******************************************************************************/
-static void
-ddSymmSummary(
- DdManager * table,
- int lower,
- int upper,
- int * symvars,
- int * symgroups)
-{
- int i,x,gbot;
- int TotalSymm = 0;
- int TotalSymmGroups = 0;
-
- for (i = lower; i <= upper; i++) {
- if (table->subtables[i].next != (unsigned) i) {
- TotalSymmGroups++;
- x = i;
- do {
- TotalSymm++;
- gbot = x;
- x = table->subtables[x].next;
- } while (x != i);
-#ifdef DD_DEBUG
- assert(table->subtables[gbot].next == (unsigned) i);
-#endif
- i = gbot;
- }
- }
- *symvars = TotalSymm;
- *symgroups = TotalSymmGroups;
-
- return;
-
-} /* end of ddSymmSummary */