src/bdd/cudd/cuddZddLin.c File Reference

#include "util_hack.h"
#include "cuddInt.h"
Include dependency graph for cuddZddLin.c:

Go to the source code of this file.

Defines

#define CUDD_SWAP_MOVE   0
#define CUDD_LINEAR_TRANSFORM_MOVE   1
#define CUDD_INVERSE_TRANSFORM_MOVE   2

Functions

static int cuddZddLinearAux ARGS ((DdManager *table, int x, int xLow, int xHigh))
static Move *cuddZddLinearUp ARGS ((DdManager *table, int y, int xLow, Move *prevMoves))
static Move *cuddZddLinearDown ARGS ((DdManager *table, int x, int xHigh, Move *prevMoves))
static int cuddZddLinearBackward ARGS ((DdManager *table, int size, Move *moves))
static Move *cuddZddUndoMoves ARGS ((DdManager *table, Move *moves))
int cuddZddLinearSifting (DdManager *table, int lower, int upper)
int cuddZddLinearInPlace (DdManager *table, int x, int y)
static int cuddZddLinearAux (DdManager *table, int x, int xLow, int xHigh)
static MovecuddZddLinearUp (DdManager *table, int y, int xLow, Move *prevMoves)
static MovecuddZddLinearDown (DdManager *table, int x, int xHigh, Move *prevMoves)
static int cuddZddLinearBackward (DdManager *table, int size, Move *moves)
static MovecuddZddUndoMoves (DdManager *table, Move *moves)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"
int * zdd_entry
int zddTotalNumberSwapping
static int zddTotalNumberLinearTr
static DdNodeempty

Define Documentation

#define CUDD_INVERSE_TRANSFORM_MOVE   2

Definition at line 44 of file cuddZddLin.c.

#define CUDD_LINEAR_TRANSFORM_MOVE   1

Definition at line 43 of file cuddZddLin.c.

#define CUDD_SWAP_MOVE   0

CFile***********************************************************************

FileName [cuddZddLin.c]

PackageName [cudd]

Synopsis [Procedures for dynamic variable ordering of ZDDs.]

Description [Internal procedures included in this module:

Static procedures included in this module:

]

SeeAlso [cuddLinear.c cuddZddReord.c]

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.]

Definition at line 42 of file cuddZddLin.c.


Function Documentation

static Move* cuddZddUndoMoves ARGS ( (DdManager *table, Move *moves)   )  [static]
static int cuddZddLinearBackward ARGS ( (DdManager *table, int size, Move *moves)   )  [static]
static Move* cuddZddLinearDown ARGS ( (DdManager *table, int x, int xHigh, Move *prevMoves)   )  [static]
static Move* cuddZddLinearUp ARGS ( (DdManager *table, int y, int xLow, Move *prevMoves)   )  [static]
static int cuddZddLinearAux ARGS ( (DdManager *table, int x, int xLow, int xHigh)   )  [static]

AutomaticStart

static int cuddZddLinearAux ( DdManager table,
int  x,
int  xLow,
int  xHigh 
) [static]

Function********************************************************************

Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]

Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 545 of file cuddZddLin.c.

00550 {
00551     Move        *move;
00552     Move        *moveUp;        /* list of up move */
00553     Move        *moveDown;      /* list of down move */
00554 
00555     int         initial_size;
00556     int         result;
00557 
00558     initial_size = table->keysZ;
00559 
00560 #ifdef DD_DEBUG
00561     assert(table->subtableZ[x].keys > 0);
00562 #endif
00563 
00564     moveDown = NULL;
00565     moveUp = NULL;
00566 
00567     if (x == xLow) {
00568         moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
00569         /* At this point x --> xHigh. */
00570         if (moveDown == (Move *) CUDD_OUT_OF_MEM)
00571             goto cuddZddLinearAuxOutOfMem;
00572         /* Move backward and stop at best position. */
00573         result = cuddZddLinearBackward(table, initial_size, moveDown);
00574         if (!result)
00575             goto cuddZddLinearAuxOutOfMem;
00576 
00577     } else if (x == xHigh) {
00578         moveUp = cuddZddLinearUp(table, x, xLow, NULL);
00579         /* At this point x --> xLow. */
00580         if (moveUp == (Move *) CUDD_OUT_OF_MEM)
00581             goto cuddZddLinearAuxOutOfMem;
00582         /* Move backward and stop at best position. */
00583         result = cuddZddLinearBackward(table, initial_size, moveUp);
00584         if (!result)
00585             goto cuddZddLinearAuxOutOfMem;
00586 
00587     } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
00588         moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
00589         /* At this point x --> xHigh. */
00590         if (moveDown == (Move *) CUDD_OUT_OF_MEM)
00591             goto cuddZddLinearAuxOutOfMem;
00592         moveUp = cuddZddUndoMoves(table,moveDown);
00593 #ifdef DD_DEBUG
00594         assert(moveUp == NULL || moveUp->x == x);
00595 #endif
00596         moveUp = cuddZddLinearUp(table, x, xLow, moveUp);
00597         if (moveUp == (Move *) CUDD_OUT_OF_MEM)
00598             goto cuddZddLinearAuxOutOfMem;
00599         /* Move backward and stop at best position. */
00600         result = cuddZddLinearBackward(table, initial_size, moveUp);
00601         if (!result)
00602             goto cuddZddLinearAuxOutOfMem;
00603 
00604     } else {
00605         moveUp = cuddZddLinearUp(table, x, xLow, NULL);
00606         /* At this point x --> xHigh. */
00607         if (moveUp == (Move *) CUDD_OUT_OF_MEM)
00608             goto cuddZddLinearAuxOutOfMem;
00609         /* Then move up. */
00610         moveDown = cuddZddUndoMoves(table,moveUp);
00611 #ifdef DD_DEBUG
00612         assert(moveDown == NULL || moveDown->y == x);
00613 #endif
00614         moveDown = cuddZddLinearDown(table, x, xHigh, moveDown);
00615         if (moveDown == (Move *) CUDD_OUT_OF_MEM)
00616             goto cuddZddLinearAuxOutOfMem;
00617         /* Move backward and stop at best position. */
00618         result = cuddZddLinearBackward(table, initial_size, moveDown);
00619         if (!result)
00620             goto cuddZddLinearAuxOutOfMem;
00621     }
00622 
00623     while (moveDown != NULL) {
00624         move = moveDown->next;
00625         cuddDeallocNode(table, (DdNode *)moveDown);
00626         moveDown = move;
00627     }
00628     while (moveUp != NULL) {
00629         move = moveUp->next;
00630         cuddDeallocNode(table, (DdNode *)moveUp);
00631         moveUp = move;
00632     }
00633 
00634     return(1);
00635 
00636 cuddZddLinearAuxOutOfMem:
00637     if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
00638         while (moveDown != NULL) {
00639             move = moveDown->next;
00640             cuddDeallocNode(table, (DdNode *)moveDown);
00641             moveDown = move;
00642         }
00643     }
00644     if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
00645         while (moveUp != NULL) {
00646             move = moveUp->next;
00647             cuddDeallocNode(table, (DdNode *)moveUp);
00648             moveUp = move;
00649         }
00650     }
00651 
00652     return(0);
00653 
00654 } /* end of cuddZddLinearAux */

static int cuddZddLinearBackward ( DdManager table,
int  size,
Move moves 
) [static]

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 841 of file cuddZddLin.c.

00845 {
00846     Move        *move;
00847     int         res;
00848 
00849     /* Find the minimum size among moves. */
00850     for (move = moves; move != NULL; move = move->next) {
00851         if (move->size < size) {
00852             size = move->size;
00853         }
00854     }
00855 
00856     for (move = moves; move != NULL; move = move->next) {
00857         if (move->size == size) return(1);
00858         if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
00859             res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
00860             if (!res) return(0);
00861         }
00862         res = cuddZddSwapInPlace(table, move->x, move->y);
00863         if (!res)
00864             return(0);
00865         if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
00866             res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
00867             if (!res) return(0);
00868         }
00869     }
00870 
00871     return(1);
00872 
00873 } /* end of cuddZddLinearBackward */

static Move* cuddZddLinearDown ( DdManager table,
int  x,
int  xHigh,
Move prevMoves 
) [static]

Function********************************************************************

Synopsis [Sifts a variable down and applies the XOR transformation.]

Description [Sifts a variable down. Moves x down until either it reaches the bound (xHigh) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 757 of file cuddZddLin.c.

00762 {
00763     Move        *moves;
00764     Move        *move;
00765     int         y;
00766     int         size, newsize;
00767     int         limitSize;
00768 
00769     moves = prevMoves;
00770     limitSize = table->keysZ;
00771 
00772     y = cuddZddNextHigh(table, x);
00773     while (y <= xHigh) {
00774         size = cuddZddSwapInPlace(table, x, y);
00775         if (size == 0)
00776             goto cuddZddLinearDownOutOfMem;
00777         newsize = cuddZddLinearInPlace(table, x, y);
00778         if (newsize == 0)
00779             goto cuddZddLinearDownOutOfMem;
00780         move = (Move *) cuddDynamicAllocNode(table);
00781         if (move == NULL)
00782             goto cuddZddLinearDownOutOfMem;
00783         move->x = x;
00784         move->y = y;
00785         move->next = moves;
00786         moves = move;
00787         move->flags = CUDD_SWAP_MOVE;
00788         if (newsize > size) {
00789             /* Undo transformation. The transformation we apply is
00790             ** its own inverse. Hence, we just apply the transformation
00791             ** again.
00792             */
00793             newsize = cuddZddLinearInPlace(table,x,y);
00794             if (newsize == 0) goto cuddZddLinearDownOutOfMem;
00795             if (newsize != size) {
00796                 (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
00797             }
00798         } else {
00799             size = newsize;
00800             move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00801         }
00802         move->size = size;
00803 
00804         if ((double)size > (double)limitSize * table->maxGrowth)
00805             break;
00806         if (size < limitSize)
00807             limitSize = size;
00808 
00809         x = y;
00810         y = cuddZddNextHigh(table, x);
00811     }
00812     return(moves);
00813 
00814 cuddZddLinearDownOutOfMem:
00815     while (moves != NULL) {
00816         move = moves->next;
00817         cuddDeallocNode(table, (DdNode *)moves);
00818         moves = move;
00819     }
00820     return((Move *) CUDD_OUT_OF_MEM);
00821 
00822 } /* end of cuddZddLinearDown */

int cuddZddLinearInPlace ( DdManager table,
int  x,
int  y 
)

Function********************************************************************

Synopsis [Linearly combines two adjacent variables.]

Description [Linearly combines two adjacent 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. cuddZddLinearInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddSwapInPlace cuddLinearInPlace]

Definition at line 223 of file cuddZddLin.c.

00227 {
00228     DdNodePtr *xlist, *ylist;
00229     int         xindex, yindex;
00230     int         xslots, yslots;
00231     int         xshift, yshift;
00232     int         oldxkeys, oldykeys;
00233     int         newxkeys, newykeys;
00234     int         i;
00235     int         posn;
00236     DdNode      *f, *f1, *f0, *f11, *f10, *f01, *f00;
00237     DdNode      *newf1, *newf0, *g, *next, *previous;
00238     DdNode      *special;
00239 
00240 #ifdef DD_DEBUG
00241     assert(x < y);
00242     assert(cuddZddNextHigh(table,x) == y);
00243     assert(table->subtableZ[x].keys != 0);
00244     assert(table->subtableZ[y].keys != 0);
00245     assert(table->subtableZ[x].dead == 0);
00246     assert(table->subtableZ[y].dead == 0);
00247 #endif
00248 
00249     zddTotalNumberLinearTr++;
00250 
00251     /* Get parameters of x subtable. */
00252     xindex   = table->invpermZ[x];
00253     xlist    = table->subtableZ[x].nodelist;
00254     oldxkeys = table->subtableZ[x].keys;
00255     xslots   = table->subtableZ[x].slots;
00256     xshift   = table->subtableZ[x].shift;
00257     newxkeys = 0;
00258 
00259     /* Get parameters of y subtable. */
00260     yindex   = table->invpermZ[y];
00261     ylist    = table->subtableZ[y].nodelist;
00262     oldykeys = table->subtableZ[y].keys;
00263     yslots   = table->subtableZ[y].slots;
00264     yshift   = table->subtableZ[y].shift;
00265     newykeys = oldykeys;
00266 
00267     /* The nodes in the x layer are put in two chains.  The chain
00268     ** pointed by g holds the normal nodes. When re-expressed they stay
00269     ** in the x list. The chain pointed by special holds the elements
00270     ** that will move to the y list.
00271     */
00272     g = special = NULL;
00273     for (i = 0; i < xslots; i++) {
00274         f = xlist[i];
00275         if (f == NULL) continue;
00276         xlist[i] = NULL;
00277         while (f != NULL) {
00278             next = f->next;
00279             f1 = cuddT(f);
00280             /* if (f1->index == yindex) */ cuddSatDec(f1->ref);
00281             f0 = cuddE(f);
00282             /* if (f0->index == yindex) */ cuddSatDec(f0->ref);
00283             if ((int) f1->index == yindex && cuddE(f1) == empty &&
00284                 (int) f0->index != yindex) {
00285                 f->next = special;
00286                 special = f;
00287             } else {
00288                 f->next = g;
00289                 g = f;
00290             }
00291             f = next;
00292         } /* while there are elements in the collision chain */
00293     } /* for each slot of the x subtable */
00294 
00295     /* Mark y nodes with pointers from above x. We mark them by
00296     **  changing their index to x.
00297     */
00298     for (i = 0; i < yslots; i++) {
00299         f = ylist[i];
00300         while (f != NULL) {
00301             if (f->ref != 0) {
00302                 f->index = xindex;
00303             }
00304             f = f->next;
00305         } /* while there are elements in the collision chain */
00306     } /* for each slot of the y subtable */
00307 
00308     /* Move special nodes to the y list. */
00309     f = special;
00310     while (f != NULL) {
00311         next = f->next;
00312         f1 = cuddT(f);
00313         f11 = cuddT(f1);
00314         cuddT(f) = f11;
00315         cuddSatInc(f11->ref);
00316         f0 = cuddE(f);
00317         cuddSatInc(f0->ref);
00318         f->index = yindex;
00319         /* Insert at the beginning of the list so that it will be
00320         ** found first if there is a duplicate. The duplicate will
00321         ** eventually be moved or garbage collected. No node
00322         ** re-expression will add a pointer to it.
00323         */
00324         posn = ddHash(f11, f0, yshift);
00325         f->next = ylist[posn];
00326         ylist[posn] = f;
00327         newykeys++;
00328         f = next;
00329     }
00330 
00331     /* Take care of the remaining x nodes that must be re-expressed.
00332     ** They form a linked list pointed by g.
00333     */
00334     f = g;
00335     while (f != NULL) {
00336 #ifdef DD_COUNT
00337         table->swapSteps++;
00338 #endif
00339         next = f->next;
00340         /* Find f1, f0, f11, f10, f01, f00. */
00341         f1 = cuddT(f);
00342         if ((int) f1->index == yindex || (int) f1->index == xindex) {
00343             f11 = cuddT(f1); f10 = cuddE(f1);
00344         } else {
00345             f11 = empty; f10 = f1;
00346         }
00347         f0 = cuddE(f);
00348         if ((int) f0->index == yindex || (int) f0->index == xindex) {
00349             f01 = cuddT(f0); f00 = cuddE(f0);
00350         } else {
00351             f01 = empty; f00 = f0;
00352         }
00353         /* Create the new T child. */
00354         if (f01 == empty) {
00355             newf1 = f10;
00356             cuddSatInc(newf1->ref);
00357         } else {
00358             /* Check ylist for triple (yindex, f01, f10). */
00359             posn = ddHash(f01, f10, yshift);
00360             /* For each element newf1 in collision list ylist[posn]. */
00361             newf1 = ylist[posn];
00362             /* Search the collision chain skipping the marked nodes. */
00363             while (newf1 != NULL) {
00364                 if (cuddT(newf1) == f01 && cuddE(newf1) == f10 &&
00365                     (int) newf1->index == yindex) {
00366                     cuddSatInc(newf1->ref);
00367                     break; /* match */
00368                 }
00369                 newf1 = newf1->next;
00370             } /* while newf1 */
00371             if (newf1 == NULL) {        /* no match */
00372                 newf1 = cuddDynamicAllocNode(table);
00373                 if (newf1 == NULL)
00374                     goto zddSwapOutOfMem;
00375                 newf1->index = yindex; newf1->ref = 1;
00376                 cuddT(newf1) = f01;
00377                 cuddE(newf1) = f10;
00378                 /* Insert newf1 in the collision list ylist[pos];
00379                 ** increase the ref counts of f01 and f10
00380                 */
00381                 newykeys++;
00382                 newf1->next = ylist[posn];
00383                 ylist[posn] = newf1;
00384                 cuddSatInc(f01->ref);
00385                 cuddSatInc(f10->ref);
00386             }
00387         }
00388         cuddT(f) = newf1;
00389 
00390         /* Do the same for f0. */
00391         /* Create the new E child. */
00392         if (f11 == empty) {
00393             newf0 = f00;
00394             cuddSatInc(newf0->ref);
00395         } else {
00396             /* Check ylist for triple (yindex, f11, f00). */
00397             posn = ddHash(f11, f00, yshift);
00398             /* For each element newf0 in collision list ylist[posn]. */
00399             newf0 = ylist[posn];
00400             while (newf0 != NULL) {
00401                 if (cuddT(newf0) == f11 && cuddE(newf0) == f00 &&
00402                     (int) newf0->index == yindex) {
00403                     cuddSatInc(newf0->ref);
00404                     break; /* match */
00405                 }
00406                 newf0 = newf0->next;
00407             } /* while newf0 */
00408             if (newf0 == NULL) {        /* no match */
00409                 newf0 = cuddDynamicAllocNode(table);
00410                 if (newf0 == NULL)
00411                     goto zddSwapOutOfMem;
00412                 newf0->index = yindex; newf0->ref = 1;
00413                 cuddT(newf0) = f11; cuddE(newf0) = f00;
00414                 /* Insert newf0 in the collision list ylist[posn];
00415                 ** increase the ref counts of f11 and f00.
00416                 */
00417                 newykeys++;
00418                 newf0->next = ylist[posn];
00419                 ylist[posn] = newf0;
00420                 cuddSatInc(f11->ref);
00421                 cuddSatInc(f00->ref);
00422             }
00423         }
00424         cuddE(f) = newf0;
00425 
00426         /* Re-insert the modified f in xlist.
00427         ** The modified f does not already exists in xlist.
00428         ** (Because of the uniqueness of the cofactors.)
00429         */
00430         posn = ddHash(newf1, newf0, xshift);
00431         newxkeys++;
00432         f->next = xlist[posn];
00433         xlist[posn] = f;
00434         f = next;
00435     } /* while f != NULL */
00436 
00437     /* GC the y layer and move the marked nodes to the x list. */
00438 
00439     /* For each node f in ylist. */
00440     for (i = 0; i < yslots; i++) {
00441         previous = NULL;
00442         f = ylist[i];
00443         while (f != NULL) {
00444             next = f->next;
00445             if (f->ref == 0) {
00446                 cuddSatDec(cuddT(f)->ref);
00447                 cuddSatDec(cuddE(f)->ref);
00448                 cuddDeallocNode(table, f);
00449                 newykeys--;
00450                 if (previous == NULL)
00451                     ylist[i] = next;
00452                 else
00453                     previous->next = next;
00454             } else if ((int) f->index == xindex) { /* move marked node */
00455                 if (previous == NULL)
00456                     ylist[i] = next;
00457                 else
00458                     previous->next = next;
00459                 f1 = cuddT(f);
00460                 cuddSatDec(f1->ref);
00461                 /* Check ylist for triple (yindex, f1, empty). */
00462                 posn = ddHash(f1, empty, yshift);
00463                 /* For each element newf1 in collision list ylist[posn]. */
00464                 newf1 = ylist[posn];
00465                 while (newf1 != NULL) {
00466                     if (cuddT(newf1) == f1 && cuddE(newf1) == empty &&
00467                         (int) newf1->index == yindex) {
00468                         cuddSatInc(newf1->ref);
00469                         break; /* match */
00470                     }
00471                     newf1 = newf1->next;
00472                 } /* while newf1 */
00473                 if (newf1 == NULL) {    /* no match */
00474                     newf1 = cuddDynamicAllocNode(table);
00475                     if (newf1 == NULL)
00476                         goto zddSwapOutOfMem;
00477                     newf1->index = yindex; newf1->ref = 1;
00478                     cuddT(newf1) = f1; cuddE(newf1) = empty;
00479                     /* Insert newf1 in the collision list ylist[posn];
00480                     ** increase the ref counts of f1 and empty.
00481                     */
00482                     newykeys++;
00483                     newf1->next = ylist[posn];
00484                     ylist[posn] = newf1;
00485                     if (posn == i && previous == NULL)
00486                         previous = newf1;
00487                     cuddSatInc(f1->ref);
00488                     cuddSatInc(empty->ref);
00489                 }
00490                 cuddT(f) = newf1;
00491                 f0 = cuddE(f);
00492                 /* Insert f in x list. */
00493                 posn = ddHash(newf1, f0, xshift);
00494                 newxkeys++;
00495                 newykeys--;
00496                 f->next = xlist[posn];
00497                 xlist[posn] = f;
00498             } else {
00499                 previous = f;
00500             }
00501             f = next;
00502         } /* while f */
00503     } /* for i */
00504 
00505     /* Set the appropriate fields in table. */
00506     table->subtableZ[x].keys     = newxkeys;
00507     table->subtableZ[y].keys     = newykeys;
00508 
00509     table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
00510 
00511     /* Update univ section; univ[x] remains the same. */
00512     table->univ[y] = cuddT(table->univ[x]);
00513 
00514 #if 0
00515     (void) fprintf(table->out,"x = %d  y = %d\n", x, y);
00516     (void) Cudd_DebugCheck(table);
00517     (void) Cudd_CheckKeys(table);
00518 #endif
00519 
00520     return (table->keysZ);
00521 
00522 zddSwapOutOfMem:
00523     (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
00524 
00525     return (0);
00526 
00527 } /* end of cuddZddLinearInPlace */

int cuddZddLinearSifting ( DdManager table,
int  lower,
int  upper 
)

AutomaticEnd Function********************************************************************

Synopsis [Implementation of the linear sifting algorithm for ZDDs.]

Description [Implementation of the linear sifting algorithm for ZDDs. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique table.
  2. Sift the variable up and down and applies the XOR transformation, remembering each time the total size of the DD heap.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 124 of file cuddZddLin.c.

00128 {
00129     int i;
00130     int *var;
00131     int size;
00132     int x;
00133     int result;
00134 #ifdef DD_STATS
00135     int previousSize;
00136 #endif
00137 
00138     size = table->sizeZ;
00139     empty = table->zero;
00140 
00141     /* Find order in which to sift variables. */
00142     var = NULL;
00143     zdd_entry = ALLOC(int, size);
00144     if (zdd_entry == NULL) {
00145         table->errorCode = CUDD_MEMORY_OUT;
00146         goto cuddZddSiftingOutOfMem;
00147     }
00148     var = ALLOC(int, size);
00149     if (var == NULL) {
00150         table->errorCode = CUDD_MEMORY_OUT;
00151         goto cuddZddSiftingOutOfMem;
00152     }
00153 
00154     for (i = 0; i < size; i++) {
00155         x = table->permZ[i];
00156         zdd_entry[i] = table->subtableZ[x].keys;
00157         var[i] = i;
00158     }
00159 
00160     qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare);
00161 
00162     /* Now sift. */
00163     for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
00164         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00165             break;
00166         x = table->permZ[var[i]];
00167         if (x < lower || x > upper) continue;
00168 #ifdef DD_STATS
00169         previousSize = table->keysZ;
00170 #endif
00171         result = cuddZddLinearAux(table, x, lower, upper);
00172         if (!result)
00173             goto cuddZddSiftingOutOfMem;
00174 #ifdef DD_STATS
00175         if (table->keysZ < (unsigned) previousSize) {
00176             (void) fprintf(table->out,"-");
00177         } else if (table->keysZ > (unsigned) previousSize) {
00178             (void) fprintf(table->out,"+");     /* should never happen */
00179             (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
00180         } else {
00181             (void) fprintf(table->out,"=");
00182         }
00183         fflush(table->out);
00184 #endif
00185     }
00186 
00187     FREE(var);
00188     FREE(zdd_entry);
00189 
00190     return(1);
00191 
00192 cuddZddSiftingOutOfMem:
00193 
00194     if (zdd_entry != NULL) FREE(zdd_entry);
00195     if (var != NULL) FREE(var);
00196 
00197     return(0);
00198 
00199 } /* end of cuddZddLinearSifting */

static Move* cuddZddLinearUp ( DdManager table,
int  y,
int  xLow,
Move prevMoves 
) [static]

Function********************************************************************

Synopsis [Sifts a variable up applying the XOR transformation.]

Description [Sifts a variable up applying the XOR transformation. Moves y up until either it reaches the bound (xLow) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 672 of file cuddZddLin.c.

00677 {
00678     Move        *moves;
00679     Move        *move;
00680     int         x;
00681     int         size, newsize;
00682     int         limitSize;
00683 
00684     moves = prevMoves;
00685     limitSize = table->keysZ;
00686 
00687     x = cuddZddNextLow(table, y);
00688     while (x >= xLow) {
00689         size = cuddZddSwapInPlace(table, x, y);
00690         if (size == 0)
00691             goto cuddZddLinearUpOutOfMem;
00692         newsize = cuddZddLinearInPlace(table, x, y);
00693         if (newsize == 0)
00694             goto cuddZddLinearUpOutOfMem;
00695         move = (Move *) cuddDynamicAllocNode(table);
00696         if (move == NULL)
00697             goto cuddZddLinearUpOutOfMem;
00698         move->x = x;
00699         move->y = y;
00700         move->next = moves;
00701         moves = move;
00702         move->flags = CUDD_SWAP_MOVE;
00703         if (newsize > size) {
00704             /* Undo transformation. The transformation we apply is
00705             ** its own inverse. Hence, we just apply the transformation
00706             ** again.
00707             */
00708             newsize = cuddZddLinearInPlace(table,x,y);
00709             if (newsize == 0) goto cuddZddLinearUpOutOfMem;
00710 #ifdef DD_DEBUG
00711             if (newsize != size) {
00712                 (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
00713             }
00714 #endif
00715         } else {
00716             size = newsize;
00717             move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00718         }
00719         move->size = size;
00720 
00721         if ((double)size > (double)limitSize * table->maxGrowth)
00722             break;
00723         if (size < limitSize)
00724             limitSize = size;
00725 
00726         y = x;
00727         x = cuddZddNextLow(table, y);
00728     }
00729     return(moves);
00730 
00731 cuddZddLinearUpOutOfMem:
00732     while (moves != NULL) {
00733         move = moves->next;
00734         cuddDeallocNode(table, (DdNode *)moves);
00735         moves = move;
00736     }
00737     return((Move *) CUDD_OUT_OF_MEM);
00738 
00739 } /* end of cuddZddLinearUp */

static Move* cuddZddUndoMoves ( DdManager table,
Move moves 
) [static]

Function********************************************************************

Synopsis [Given a set of moves, returns the ZDD heap to the order in effect before the moves.]

Description [Given a set of moves, returns the ZDD heap to the order in effect before the moves. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 889 of file cuddZddLin.c.

00892 {
00893     Move *invmoves = NULL;
00894     Move *move;
00895     Move *invmove;
00896     int size;
00897 
00898     for (move = moves; move != NULL; move = move->next) {
00899         invmove = (Move *) cuddDynamicAllocNode(table);
00900         if (invmove == NULL) goto cuddZddUndoMovesOutOfMem;
00901         invmove->x = move->x;
00902         invmove->y = move->y;
00903         invmove->next = invmoves;
00904         invmoves = invmove;
00905         if (move->flags == CUDD_SWAP_MOVE) {
00906             invmove->flags = CUDD_SWAP_MOVE;
00907             size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
00908             if (!size) goto cuddZddUndoMovesOutOfMem;
00909         } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
00910             invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
00911             size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
00912             if (!size) goto cuddZddUndoMovesOutOfMem;
00913             size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
00914             if (!size) goto cuddZddUndoMovesOutOfMem;
00915         } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
00916 #ifdef DD_DEBUG
00917             (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
00918 #endif
00919             invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00920             size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
00921             if (!size) goto cuddZddUndoMovesOutOfMem;
00922             size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
00923             if (!size) goto cuddZddUndoMovesOutOfMem;
00924         }
00925         invmove->size = size;
00926     }
00927 
00928     return(invmoves);
00929 
00930 cuddZddUndoMovesOutOfMem:
00931     while (invmoves != NULL) {
00932         move = invmoves->next;
00933         cuddDeallocNode(table, (DdNode *) invmoves);
00934         invmoves = move;
00935     }
00936     return((Move *) CUDD_OUT_OF_MEM);
00937 
00938 } /* end of cuddZddUndoMoves */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddZddLin.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $" [static]

Definition at line 61 of file cuddZddLin.c.

DdNode* empty [static]

Definition at line 67 of file cuddZddLin.c.

int* zdd_entry

Definition at line 77 of file cuddZddReord.c.

int zddTotalNumberLinearTr [static]

Definition at line 66 of file cuddZddLin.c.

Definition at line 79 of file cuddZddReord.c.


Generated on Tue Jan 5 12:18:57 2010 for abc70930 by  doxygen 1.6.1