summaryrefslogtreecommitdiffstats
path: root/src/bdd/cudd/cuddLinear.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bdd/cudd/cuddLinear.c')
-rw-r--r--src/bdd/cudd/cuddLinear.c1333
1 files changed, 0 insertions, 1333 deletions
diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c
deleted file mode 100644
index 7f6b3678..00000000
--- a/src/bdd/cudd/cuddLinear.c
+++ /dev/null
@@ -1,1333 +0,0 @@
-/**CFile***********************************************************************
-
- FileName [cuddLinear.c]
-
- PackageName [cudd]
-
- Synopsis [Functions for DD reduction by linear transformations.]
-
- Description [ Internal procedures included in this module:
- <ul>
- <li> cuddLinearAndSifting()
- </ul>
- Static procedures included in this module:
- <ul>
- <li> ddLinearUniqueCompare()
- <li> ddLinearAndSiftingAux()
- <li> ddLinearAndSiftingUp()
- <li> ddLinearAndSiftingDown()
- <li> ddLinearAndSiftingBackward()
- <li> ddUndoMoves()
- <li> ddUpdateInteractionMatrix()
- <li> cuddLinearInPlace()
- <li> cuddInitLinear()
- <li> cuddResizeLinear()
- <li> cuddXorLinear()
- </ul>]
-
- Author [Fabio Somenzi]
-
- Copyright [This file was created at the University of Colorado at
- Boulder. The University of Colorado at Boulder makes no warranty
- about the suitability of this software for any purpose. It is
- presented on an AS IS basis.]
-
-******************************************************************************/
-
-#include "util_hack.h"
-#include "cuddInt.h"
-
-/*---------------------------------------------------------------------------*/
-/* Constant declarations */
-/*---------------------------------------------------------------------------*/
-
-#define CUDD_SWAP_MOVE 0
-#define CUDD_LINEAR_TRANSFORM_MOVE 1
-#define CUDD_INVERSE_TRANSFORM_MOVE 2
-#if SIZEOF_LONG == 8
-#define BPL 64
-#define LOGBPL 6
-#else
-#define BPL 32
-#define LOGBPL 5
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Stucture declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Type declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Variable declarations */
-/*---------------------------------------------------------------------------*/
-
-#ifndef lint
-static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $";
-#endif
-
-static int *entry;
-
-#ifdef DD_STATS
-extern int ddTotalNumberSwapping;
-extern int ddTotalNISwaps;
-static int ddTotalNumberLinearTr;
-#endif
-
-#ifdef DD_DEBUG
-static int zero = 0;
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Macro declarations */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-static int ddLinearUniqueCompare ARGS((int *ptrX, int *ptrY));
-static int ddLinearAndSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh));
-static Move * ddLinearAndSiftingUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves));
-static Move * ddLinearAndSiftingDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves));
-static int ddLinearAndSiftingBackward ARGS((DdManager *table, int size, Move *moves));
-static Move* ddUndoMoves ARGS((DdManager *table, Move *moves));
-static int cuddLinearInPlace ARGS((DdManager *table, int x, int y));
-static void ddUpdateInteractionMatrix ARGS((DdManager *table, int xindex, int yindex));
-static int cuddInitLinear ARGS((DdManager *table));
-static int cuddResizeLinear ARGS((DdManager *table));
-static void cuddXorLinear ARGS((DdManager *table, int x, int y));
-
-/**AutomaticEnd***************************************************************/
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of exported functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**Function********************************************************************
-
- Synopsis [Prints the linear transform matrix.]
-
- Description [Prints the linear transform matrix. Returns 1 in case of
- success; 0 otherwise.]
-
- SideEffects [none]
-
- SeeAlso []
-
-******************************************************************************/
-int
-Cudd_PrintLinear(
- DdManager * table)
-{
- int i,j,k;
- int retval;
- int nvars = table->linearSize;
- int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
- long word;
-
- for (i = 0; i < nvars; i++) {
- for (j = 0; j < wordsPerRow; j++) {
- word = table->linear[i*wordsPerRow + j];
- for (k = 0; k < BPL; k++) {
- retval = fprintf(table->out,"%ld",word & 1);
- if (retval == 0) return(0);
- word >>= 1;
- }
- }
- retval = fprintf(table->out,"\n");
- if (retval == 0) return(0);
- }
- return(1);
-
-} /* end of Cudd_PrintLinear */
-
-
-/**Function********************************************************************
-
- Synopsis [Reads an entry of the linear transform matrix.]
-
- Description [Reads an entry of the linear transform matrix.]
-
- SideEffects [none]
-
- SeeAlso []
-
-******************************************************************************/
-int
-Cudd_ReadLinear(
- DdManager * table /* CUDD manager */,
- int x /* row index */,
- int y /* column index */)
-{
- int nvars = table->size;
- int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
- long word;
- int bit;
- int result;
-
- assert(table->size == table->linearSize);
-
- word = wordsPerRow * x + (y >> LOGBPL);
- bit = y & (BPL-1);
- result = (int) ((table->linear[word] >> bit) & 1);
- return(result);
-
-} /* end of Cudd_ReadLinear */
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of internal functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**Function********************************************************************
-
- Synopsis [BDD reduction based on combination of sifting and linear
- transformations.]
-
- Description [BDD reduction based on combination of sifting and linear
- transformations. Assumes that no dead nodes are present.
- <ol>
- <li> Order all the variables according to the number of entries
- in each unique table.
- <li> Sift the variable up and down, remembering each time the
- total size of the DD heap. At each position, linear transformation
- of the two adjacent variables is tried and is accepted if it reduces
- the size of the DD.
- <li> Select the best permutation.
- <li> Repeat 3 and 4 for all variables.
- </ol>
- Returns 1 if successful; 0 otherwise.]
-
- SideEffects [None]
-
-******************************************************************************/
-int
-cuddLinearAndSifting(
- DdManager * table,
- int lower,
- int upper)
-{
- int i;
- int *var;
- int size;
- int x;
- int result;
-#ifdef DD_STATS
- int previousSize;
-#endif
-
-#ifdef DD_STATS
- ddTotalNumberLinearTr = 0;
-#endif
-
- size = table->size;
-
- var = NULL;
- entry = NULL;
- if (table->linear == NULL) {
- result = cuddInitLinear(table);
- if (result == 0) goto cuddLinearAndSiftingOutOfMem;
-#if 0
- (void) fprintf(table->out,"\n");
- result = Cudd_PrintLinear(table);
- if (result == 0) goto cuddLinearAndSiftingOutOfMem;
-#endif
- } else if (table->size != table->linearSize) {
- result = cuddResizeLinear(table);
- if (result == 0) goto cuddLinearAndSiftingOutOfMem;
-#if 0
- (void) fprintf(table->out,"\n");
- result = Cudd_PrintLinear(table);
- if (result == 0) goto cuddLinearAndSiftingOutOfMem;
-#endif
- }
-
- /* Find order in which to sift variables. */
- entry = ALLOC(int,size);
- if (entry == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- goto cuddLinearAndSiftingOutOfMem;
- }
- var = ALLOC(int,size);
- if (var == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- goto cuddLinearAndSiftingOutOfMem;
- }
-
- 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 *))ddLinearUniqueCompare);
-
- /* Now sift. */
- for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
- x = table->perm[var[i]];
- if (x < lower || x > upper) continue;
-#ifdef DD_STATS
- previousSize = table->keys - table->isolated;
-#endif
- result = ddLinearAndSiftingAux(table,x,lower,upper);
- if (!result) goto cuddLinearAndSiftingOutOfMem;
-#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 */
- (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
- } else {
- (void) fprintf(table->out,"=");
- }
- fflush(table->out);
-#endif
-#ifdef DD_DEBUG
- (void) Cudd_DebugCheck(table);
-#endif
- }
-
- FREE(var);
- FREE(entry);
-
-#ifdef DD_STATS
- (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
- ddTotalNumberLinearTr);
-#endif
-
- return(1);
-
-cuddLinearAndSiftingOutOfMem:
-
- if (entry != NULL) FREE(entry);
- if (var != NULL) FREE(var);
-
- return(0);
-
-} /* end of cuddLinearAndSifting */
-
-
-/*---------------------------------------------------------------------------*/
-/* 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
-ddLinearUniqueCompare(
- int * ptrX,
- int * ptrY)
-{
-#if 0
- if (entry[*ptrY] == entry[*ptrX]) {
- return((*ptrX) - (*ptrY));
- }
-#endif
- return(entry[*ptrY] - entry[*ptrX]);
-
-} /* end of ddLinearUniqueCompare */
-
-
-/**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. At each step a linear transformation is tried, and, if it
- decreases the size of the DD, it is accepted. Finds the best position
- and does the required changes. Returns 1 if successful; 0 otherwise.]
-
- SideEffects [None]
-
-******************************************************************************/
-static int
-ddLinearAndSiftingAux(
- 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;
-
- initialSize = table->keys - table->isolated;
-
- moveDown = NULL;
- moveUp = NULL;
-
- if (x == xLow) {
- moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
- /* At this point x --> xHigh unless bounding occurred. */
- if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
- /* Move backward and stop at best position. */
- result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
- if (!result) goto ddLinearAndSiftingAuxOutOfMem;
-
- } else if (x == xHigh) {
- moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
- /* At this point x --> xLow unless bounding occurred. */
- if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
- /* Move backward and stop at best position. */
- result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
- if (!result) goto ddLinearAndSiftingAuxOutOfMem;
-
- } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
- moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
- /* At this point x --> xHigh unless bounding occurred. */
- if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
- moveUp = ddUndoMoves(table,moveDown);
-#ifdef DD_DEBUG
- assert(moveUp == NULL || moveUp->x == x);
-#endif
- moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
- if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
- /* Move backward and stop at best position. */
- result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
- if (!result) goto ddLinearAndSiftingAuxOutOfMem;
-
- } else { /* must go up first: shorter */
- moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
- /* At this point x --> xLow unless bounding occurred. */
- if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
- moveDown = ddUndoMoves(table,moveUp);
-#ifdef DD_DEBUG
- assert(moveDown == NULL || moveDown->y == x);
-#endif
- moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
- if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
- /* Move backward and stop at best position. */
- result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
- if (!result) goto ddLinearAndSiftingAuxOutOfMem;
- }
-
- 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);
-
-ddLinearAndSiftingAuxOutOfMem:
- 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(0);
-
-} /* end of ddLinearAndSiftingAux */
-
-
-/**Function********************************************************************
-
- Synopsis [Sifts a variable up and applies linear transformations.]
-
- Description [Sifts a variable up and applies linear transformations.
- Moves y up until either it reaches the bound (xLow) or the size of
- the DD heap increases too much. Returns the set of moves in case of
- success; NULL if memory is full.]
-
- SideEffects [None]
-
-******************************************************************************/
-static Move *
-ddLinearAndSiftingUp(
- DdManager * table,
- int y,
- int xLow,
- Move * prevMoves)
-{
- Move *moves;
- Move *move;
- int x;
- int size, newsize;
- int limitSize;
- int xindex, yindex;
- int isolated;
- int L; /* lower bound on DD size */
-#ifdef DD_DEBUG
- int checkL;
- int z;
- int zindex;
-#endif
-
- moves = prevMoves;
- yindex = table->invperm[y];
-
- /* Initialize the lower bound.
- ** The part of the DD below y 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;
- for (x = xLow + 1; x < y; x++) {
- xindex = table->invperm[x];
- if (cuddTestInteract(table,xindex,yindex)) {
- isolated = table->vars[xindex]->ref == 1;
- L -= table->subtables[x].keys - isolated;
- }
- }
- isolated = table->vars[yindex]->ref == 1;
- L -= table->subtables[y].keys - isolated;
-
- x = cuddNextLow(table,y);
- while (x >= xLow && L <= limitSize) {
- xindex = table->invperm[x];
-#ifdef DD_DEBUG
- checkL = table->keys - table->isolated;
- for (z = xLow + 1; z < y; z++) {
- zindex = table->invperm[z];
- if (cuddTestInteract(table,zindex,yindex)) {
- isolated = table->vars[zindex]->ref == 1;
- checkL -= table->subtables[z].keys - isolated;
- }
- }
- isolated = table->vars[yindex]->ref == 1;
- checkL -= table->subtables[y].keys - isolated;
- if (L != checkL) {
- (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
- }
-#endif
- size = cuddSwapInPlace(table,x,y);
- if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
- newsize = cuddLinearInPlace(table,x,y);
- if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
- move = (Move *) cuddDynamicAllocNode(table);
- if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
- move->x = x;
- move->y = y;
- move->next = moves;
- moves = move;
- move->flags = CUDD_SWAP_MOVE;
- if (newsize >= size) {
- /* Undo transformation. The transformation we apply is
- ** its own inverse. Hence, we just apply the transformation
- ** again.
- */
- newsize = cuddLinearInPlace(table,x,y);
- if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
-#ifdef DD_DEBUG
- if (newsize != size) {
- (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
- }
-#endif
- } else if (cuddTestInteract(table,xindex,yindex)) {
- size = newsize;
- move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
- ddUpdateInteractionMatrix(table,xindex,yindex);
- }
- move->size = size;
- /* Update the lower bound. */
- if (cuddTestInteract(table,xindex,yindex)) {
- isolated = table->vars[xindex]->ref == 1;
- L += table->subtables[y].keys - isolated;
- }
- if ((double) size > (double) limitSize * table->maxGrowth) break;
- if (size < limitSize) limitSize = size;
- y = x;
- x = cuddNextLow(table,y);
- }
- return(moves);
-
-ddLinearAndSiftingUpOutOfMem:
- while (moves != NULL) {
- move = moves->next;
- cuddDeallocNode(table, (DdNode *) moves);
- moves = move;
- }
- return((Move *) CUDD_OUT_OF_MEM);
-
-} /* end of ddLinearAndSiftingUp */
-
-
-/**Function********************************************************************
-
- Synopsis [Sifts a variable down and applies linear transformations.]
-
- Description [Sifts a variable down and applies linear
- transformations. Moves x down until either it reaches the bound
- (xHigh) or the size of the DD heap increases too much. Returns the
- set of moves in case of success; NULL if memory is full.]
-
- SideEffects [None]
-
-******************************************************************************/
-static Move *
-ddLinearAndSiftingDown(
- DdManager * table,
- int x,
- int xHigh,
- Move * prevMoves)
-{
- Move *moves;
- Move *move;
- int y;
- int size, newsize;
- int R; /* upper bound on node decrease */
- int limitSize;
- int xindex, yindex;
- int isolated;
-#ifdef DD_DEBUG
- int checkR;
- int z;
- int zindex;
-#endif
-
- moves = prevMoves;
- /* Initialize R */
- xindex = table->invperm[x];
- limitSize = size = table->keys - table->isolated;
- R = 0;
- for (y = xHigh; y > x; y--) {
- yindex = table->invperm[y];
- if (cuddTestInteract(table,xindex,yindex)) {
- isolated = table->vars[yindex]->ref == 1;
- R += table->subtables[y].keys - isolated;
- }
- }
-
- y = cuddNextHigh(table,x);
- while (y <= xHigh && size - R < limitSize) {
-#ifdef DD_DEBUG
- checkR = 0;
- for (z = xHigh; z > x; z--) {
- zindex = table->invperm[z];
- if (cuddTestInteract(table,xindex,zindex)) {
- isolated = table->vars[zindex]->ref == 1;
- checkR += table->subtables[z].keys - isolated;
- }
- }
- if (R != checkR) {
- (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
- }
-#endif
- /* 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);
- if (size == 0) goto ddLinearAndSiftingDownOutOfMem;
- newsize = cuddLinearInPlace(table,x,y);
- if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
- move = (Move *) cuddDynamicAllocNode(table);
- if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
- move->x = x;
- move->y = y;
- move->next = moves;
- moves = move;
- move->flags = CUDD_SWAP_MOVE;
- if (newsize >= size) {
- /* Undo transformation. The transformation we apply is
- ** its own inverse. Hence, we just apply the transformation
- ** again.
- */
- newsize = cuddLinearInPlace(table,x,y);
- if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
- if (newsize != size) {
- (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
- }
- } else if (cuddTestInteract(table,xindex,yindex)) {
- size = newsize;
- move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
- ddUpdateInteractionMatrix(table,xindex,yindex);
- }
- move->size = size;
- if ((double) size > (double) limitSize * table->maxGrowth) break;
- if (size < limitSize) limitSize = size;
- x = y;
- y = cuddNextHigh(table,x);
- }
- return(moves);
-
-ddLinearAndSiftingDownOutOfMem:
- while (moves != NULL) {
- move = moves->next;
- cuddDeallocNode(table, (DdNode *) moves);
- moves = move;
- }
- return((Move *) CUDD_OUT_OF_MEM);
-
-} /* end of ddLinearAndSiftingDown */
-
-
-/**Function********************************************************************
-
- Synopsis [Given a set of moves, returns the DD heap to the order
- 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
-ddLinearAndSiftingBackward(
- DdManager * table,
- int size,
- Move * moves)
-{
- 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 (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
- res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
- if (!res) return(0);
- }
- res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
- if (!res) return(0);
- if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
- res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
- if (!res) return(0);
- }
- }
-
- return(1);
-
-} /* end of ddLinearAndSiftingBackward */
-
-
-/**Function********************************************************************
-
- Synopsis [Given a set of moves, returns the DD heap to the order
- in effect before the moves.]
-
- Description [Given a set of moves, returns the DD heap to the
- order in effect before the moves. Returns 1 in case of success;
- 0 otherwise.]
-
- SideEffects [None]
-
-******************************************************************************/
-static Move*
-ddUndoMoves(
- DdManager * table,
- Move * moves)
-{
- Move *invmoves = NULL;
- Move *move;
- Move *invmove;
- int size;
-
- for (move = moves; move != NULL; move = move->next) {
- invmove = (Move *) cuddDynamicAllocNode(table);
- if (invmove == NULL) goto ddUndoMovesOutOfMem;
- invmove->x = move->x;
- invmove->y = move->y;
- invmove->next = invmoves;
- invmoves = invmove;
- if (move->flags == CUDD_SWAP_MOVE) {
- invmove->flags = CUDD_SWAP_MOVE;
- size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
- if (!size) goto ddUndoMovesOutOfMem;
- } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
- invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
- size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
- if (!size) goto ddUndoMovesOutOfMem;
- size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
- if (!size) goto ddUndoMovesOutOfMem;
- } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
-#ifdef DD_DEBUG
- (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
-#endif
- invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
- size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
- if (!size) goto ddUndoMovesOutOfMem;
- size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
- if (!size) goto ddUndoMovesOutOfMem;
- }
- invmove->size = size;
- }
-
- return(invmoves);
-
-ddUndoMovesOutOfMem:
- while (invmoves != NULL) {
- move = invmoves->next;
- cuddDeallocNode(table, (DdNode *) invmoves);
- invmoves = move;
- }
- return((Move *) CUDD_OUT_OF_MEM);
-
-} /* end of ddUndoMoves */
-
-
-/**Function********************************************************************
-
- Synopsis [Linearly combines two adjacent variables.]
-
- Description [Linearly combines two adjacent variables. Specifically,
- replaces the top variable with the exclusive nor of the two variables.
- It assumes that no dead nodes are present on entry to this
- procedure. The procedure then guarantees that no dead nodes will be
- present when it terminates. cuddLinearInPlace assumes that x &lt;
- y. Returns the number of keys in the table if successful; 0
- otherwise.]
-
- SideEffects [The two subtables corrresponding to variables x and y are
- modified. The global counters of the unique table are also affected.]
-
- SeeAlso [cuddSwapInPlace]
-
-******************************************************************************/
-static int
-cuddLinearInPlace(
- DdManager * table,
- int x,
- int y)
-{
- DdNodePtr *xlist, *ylist;
- int xindex, yindex;
- int xslots, yslots;
- int xshift, yshift;
- int oldxkeys, oldykeys;
- int newxkeys, newykeys;
- int comple, newcomplement;
- int i;
- int posn;
- int isolated;
- DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
- DdNode *g,*next,*last;
- DdNodePtr *previousP;
- DdNode *tmp;
- DdNode *sentinel = &(table->sentinel);
-#if DD_DEBUG
- int count, idcheck;
-#endif
-
-#ifdef DD_DEBUG
- assert(x < y);
- assert(cuddNextHigh(table,x) == y);
- assert(table->subtables[x].keys != 0);
- assert(table->subtables[y].keys != 0);
- assert(table->subtables[x].dead == 0);
- assert(table->subtables[y].dead == 0);
-#endif
-
- xindex = table->invperm[x];
- yindex = table->invperm[y];
-
- if (cuddTestInteract(table,xindex,yindex)) {
-#ifdef DD_STATS
- ddTotalNumberLinearTr++;
-#endif
- /* Get parameters of x subtable. */
- xlist = table->subtables[x].nodelist;
- oldxkeys = table->subtables[x].keys;
- xslots = table->subtables[x].slots;
- xshift = table->subtables[x].shift;
-
- /* Get parameters of y subtable. */
- ylist = table->subtables[y].nodelist;
- oldykeys = table->subtables[y].keys;
- yslots = table->subtables[y].slots;
- yshift = table->subtables[y].shift;
-
- newxkeys = 0;
- newykeys = oldykeys;
-
- /* Check whether the two projection functions involved in this
- ** swap are isolated. At the end, we'll be able to tell how many
- ** isolated projection functions are there by checking only these
- ** two functions again. This is done to eliminate the isolated
- ** projection functions from the node count.
- */
- isolated = - ((table->vars[xindex]->ref == 1) +
- (table->vars[yindex]->ref == 1));
-
- /* The nodes in the x layer are put in a chain.
- ** The chain is handled as a FIFO; g points to the beginning and
- ** last points to the end.
- */
- g = NULL;
- for (i = 0; i < xslots; i++) {
- f = xlist[i];
- if (f == sentinel) continue;
- xlist[i] = sentinel;
- if (g == NULL) {
- g = f;
- } else {
- last->next = f;
- }
- while ((next = f->next) != sentinel) {
- f = next;
- } /* while there are elements in the collision chain */
- last = f;
- } /* for each slot of the x subtable */
- last->next = NULL;
-
-#ifdef DD_COUNT
- table->swapSteps += oldxkeys;
-#endif
- /* Take care of the x nodes that must be re-expressed.
- ** They form a linked list pointed by g.
- */
- f = g;
- while (f != NULL) {
- next = f->next;
- /* Find f1, f0, f11, f10, f01, f00. */
- f1 = cuddT(f);
-#ifdef DD_DEBUG
- assert(!(Cudd_IsComplement(f1)));
-#endif
- if ((int) f1->index == yindex) {
- f11 = cuddT(f1); f10 = cuddE(f1);
- } else {
- f11 = f10 = f1;
- }
-#ifdef DD_DEBUG
- assert(!(Cudd_IsComplement(f11)));
-#endif
- f0 = cuddE(f);
- comple = Cudd_IsComplement(f0);
- f0 = Cudd_Regular(f0);
- if ((int) f0->index == yindex) {
- f01 = cuddT(f0); f00 = cuddE(f0);
- } else {
- f01 = f00 = f0;
- }
- if (comple) {
- f01 = Cudd_Not(f01);
- f00 = Cudd_Not(f00);
- }
- /* Decrease ref count of f1. */
- cuddSatDec(f1->ref);
- /* Create the new T child. */
- if (f11 == f00) {
- newf1 = f11;
- cuddSatInc(newf1->ref);
- } else {
- /* Check ylist for triple (yindex,f11,f00). */
- posn = ddHash(f11, f00, yshift);
- /* For each element newf1 in collision list ylist[posn]. */
- previousP = &(ylist[posn]);
- newf1 = *previousP;
- while (f11 < cuddT(newf1)) {
- previousP = &(newf1->next);
- newf1 = *previousP;
- }
- while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
- previousP = &(newf1->next);
- newf1 = *previousP;
- }
- if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
- cuddSatInc(newf1->ref);
- } else { /* no match */
- newf1 = cuddDynamicAllocNode(table);
- if (newf1 == NULL)
- goto cuddLinearOutOfMem;
- newf1->index = yindex; newf1->ref = 1;
- cuddT(newf1) = f11;
- cuddE(newf1) = f00;
- /* Insert newf1 in the collision list ylist[posn];
- ** increase the ref counts of f11 and f00.
- */
- newykeys++;
- newf1->next = *previousP;
- *previousP = newf1;
- cuddSatInc(f11->ref);
- tmp = Cudd_Regular(f00);
- cuddSatInc(tmp->ref);
- }
- }
- cuddT(f) = newf1;
-#ifdef DD_DEBUG
- assert(!(Cudd_IsComplement(newf1)));
-#endif
-
- /* Do the same for f0, keeping complement dots into account. */
- /* decrease ref count of f0 */
- tmp = Cudd_Regular(f0);
- cuddSatDec(tmp->ref);
- /* create the new E child */
- if (f01 == f10) {
- newf0 = f01;
- tmp = Cudd_Regular(newf0);
- cuddSatInc(tmp->ref);
- } else {
- /* make sure f01 is regular */
- newcomplement = Cudd_IsComplement(f01);
- if (newcomplement) {
- f01 = Cudd_Not(f01);
- f10 = Cudd_Not(f10);
- }
- /* Check ylist for triple (yindex,f01,f10). */
- posn = ddHash(f01, f10, yshift);
- /* For each element newf0 in collision list ylist[posn]. */
- previousP = &(ylist[posn]);
- newf0 = *previousP;
- while (f01 < cuddT(newf0)) {
- previousP = &(newf0->next);
- newf0 = *previousP;
- }
- while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
- previousP = &(newf0->next);
- newf0 = *previousP;
- }
- if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
- cuddSatInc(newf0->ref);
- } else { /* no match */
- newf0 = cuddDynamicAllocNode(table);
- if (newf0 == NULL)
- goto cuddLinearOutOfMem;
- newf0->index = yindex; newf0->ref = 1;
- cuddT(newf0) = f01;
- cuddE(newf0) = f10;
- /* Insert newf0 in the collision list ylist[posn];
- ** increase the ref counts of f01 and f10.
- */
- newykeys++;
- newf0->next = *previousP;
- *previousP = newf0;
- cuddSatInc(f01->ref);
- tmp = Cudd_Regular(f10);
- cuddSatInc(tmp->ref);
- }
- if (newcomplement) {
- newf0 = Cudd_Not(newf0);
- }
- }
- cuddE(f) = newf0;
-
- /* Re-insert the modified f in xlist.
- ** The modified f does not already exists in xlist.
- ** (Because of the uniqueness of the cofactors.)
- */
- posn = ddHash(newf1, newf0, xshift);
- newxkeys++;
- previousP = &(xlist[posn]);
- tmp = *previousP;
- while (newf1 < cuddT(tmp)) {
- previousP = &(tmp->next);
- tmp = *previousP;
- }
- while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
- previousP = &(tmp->next);
- tmp = *previousP;
- }
- f->next = *previousP;
- *previousP = f;
- f = next;
- } /* while f != NULL */
-
- /* GC the y layer. */
-
- /* For each node f in ylist. */
- for (i = 0; i < yslots; i++) {
- previousP = &(ylist[i]);
- f = *previousP;
- while (f != sentinel) {
- next = f->next;
- if (f->ref == 0) {
- tmp = cuddT(f);
- cuddSatDec(tmp->ref);
- tmp = Cudd_Regular(cuddE(f));
- cuddSatDec(tmp->ref);
- cuddDeallocNode(table,f);
- newykeys--;
- } else {
- *previousP = f;
- previousP = &(f->next);
- }
- f = next;
- } /* while f */
- *previousP = sentinel;
- } /* for every collision list */
-
-#if DD_DEBUG
-#if 0
- (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
-#endif
- count = 0;
- idcheck = 0;
- for (i = 0; i < yslots; i++) {
- f = ylist[i];
- while (f != sentinel) {
- count++;
- if (f->index != (DdHalfWord) yindex)
- idcheck++;
- f = f->next;
- }
- }
- if (count != newykeys) {
- fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
- }
- if (idcheck != 0)
- fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
- count = 0;
- idcheck = 0;
- for (i = 0; i < xslots; i++) {
- f = xlist[i];
- while (f != sentinel) {
- count++;
- if (f->index != (DdHalfWord) xindex)
- idcheck++;
- f = f->next;
- }
- }
- if (count != newxkeys || newxkeys != oldxkeys) {
- fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
- }
- if (idcheck != 0)
- fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
-#endif
-
- isolated += (table->vars[xindex]->ref == 1) +
- (table->vars[yindex]->ref == 1);
- table->isolated += isolated;
-
- /* Set the appropriate fields in table. */
- table->subtables[y].keys = newykeys;
-
- /* Here we should update the linear combination table
- ** to record that x <- x EXNOR y. This is done by complementing
- ** the (x,y) entry of the table.
- */
-
- table->keys += newykeys - oldykeys;
-
- cuddXorLinear(table,xindex,yindex);
- }
-
-#ifdef DD_DEBUG
- if (zero) {
- (void) Cudd_DebugCheck(table);
- }
-#endif
-
- return(table->keys - table->isolated);
-
-cuddLinearOutOfMem:
- (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
-
- return (0);
-
-} /* end of cuddLinearInPlace */
-
-
-/**Function********************************************************************
-
- Synopsis [Updates the interaction matrix.]
-
- Description []
-
- SideEffects [none]
-
- SeeAlso []
-
-******************************************************************************/
-static void
-ddUpdateInteractionMatrix(
- DdManager * table,
- int xindex,
- int yindex)
-{
- int i;
- for (i = 0; i < yindex; i++) {
- if (i != xindex && cuddTestInteract(table,i,yindex)) {
- if (i < xindex) {
- cuddSetInteract(table,i,xindex);
- } else {
- cuddSetInteract(table,xindex,i);
- }
- }
- }
- for (i = yindex+1; i < table->size; i++) {
- if (i != xindex && cuddTestInteract(table,yindex,i)) {
- if (i < xindex) {
- cuddSetInteract(table,i,xindex);
- } else {
- cuddSetInteract(table,xindex,i);
- }
- }
- }
-
-} /* end of ddUpdateInteractionMatrix */
-
-
-/**Function********************************************************************
-
- Synopsis [Initializes the linear transform matrix.]
-
- Description []
-
- SideEffects [none]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-cuddInitLinear(
- DdManager * table)
-{
- int words;
- int wordsPerRow;
- int nvars;
- int word;
- int bit;
- int i;
- long *linear;
-
- nvars = table->size;
- wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
- words = wordsPerRow * nvars;
- table->linear = linear = ALLOC(long,words);
- if (linear == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- return(0);
- }
- table->memused += words * sizeof(long);
- table->linearSize = nvars;
- for (i = 0; i < words; i++) linear[i] = 0;
- for (i = 0; i < nvars; i++) {
- word = wordsPerRow * i + (i >> LOGBPL);
- bit = i & (BPL-1);
- linear[word] = 1 << bit;
- }
- return(1);
-
-} /* end of cuddInitLinear */
-
-
-/**Function********************************************************************
-
- Synopsis [Resizes the linear transform matrix.]
-
- Description []
-
- SideEffects [none]
-
- SeeAlso []
-
-******************************************************************************/
-static int
-cuddResizeLinear(
- DdManager * table)
-{
- int words,oldWords;
- int wordsPerRow,oldWordsPerRow;
- int nvars,oldNvars;
- int word,oldWord;
- int bit;
- int i,j;
- long *linear,*oldLinear;
-
- oldNvars = table->linearSize;
- oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
- oldWords = oldWordsPerRow * oldNvars;
- oldLinear = table->linear;
-
- nvars = table->size;
- wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
- words = wordsPerRow * nvars;
- table->linear = linear = ALLOC(long,words);
- if (linear == NULL) {
- table->errorCode = CUDD_MEMORY_OUT;
- return(0);
- }
- table->memused += (words - oldWords) * sizeof(long);
- for (i = 0; i < words; i++) linear[i] = 0;
-
- /* Copy old matrix. */
- for (i = 0; i < oldNvars; i++) {
- for (j = 0; j < oldWordsPerRow; j++) {
- oldWord = oldWordsPerRow * i + j;
- word = wordsPerRow * i + j;
- linear[word] = oldLinear[oldWord];
- }
- }
- FREE(oldLinear);
-
- /* Add elements to the diagonal. */
- for (i = oldNvars; i < nvars; i++) {
- word = wordsPerRow * i + (i >> LOGBPL);
- bit = i & (BPL-1);
- linear[word] = 1 << bit;
- }
- table->linearSize = nvars;
-
- return(1);
-
-} /* end of cuddResizeLinear */
-
-
-/**Function********************************************************************
-
- Synopsis [XORs two rows of the linear transform matrix.]
-
- Description [XORs two rows of the linear transform matrix and replaces
- the first row with the result.]
-
- SideEffects [none]
-
- SeeAlso []
-
-******************************************************************************/
-static void
-cuddXorLinear(
- DdManager * table,
- int x,
- int y)
-{
- int i;
- int nvars = table->size;
- int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
- int xstart = wordsPerRow * x;
- int ystart = wordsPerRow * y;
- long *linear = table->linear;
-
- for (i = 0; i < wordsPerRow; i++) {
- linear[xstart+i] ^= linear[ystart+i];
- }
-
-} /* end of cuddXorLinear */
-