src/bdd/cudd/cuddLinear.c File Reference

#include "util_hack.h"
#include "cuddInt.h"
Include dependency graph for cuddLinear.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
#define BPL   32
#define LOGBPL   5

Functions

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))
int Cudd_PrintLinear (DdManager *table)
int Cudd_ReadLinear (DdManager *table, int x, int y)
int cuddLinearAndSifting (DdManager *table, int lower, int upper)
static int ddLinearUniqueCompare (int *ptrX, int *ptrY)
static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh)
static MoveddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves)
static MoveddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves)
static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves)
static MoveddUndoMoves (DdManager *table, Move *moves)
static int cuddLinearInPlace (DdManager *table, int x, int y)
static void ddUpdateInteractionMatrix (DdManager *table, int xindex, int yindex)
static int cuddInitLinear (DdManager *table)
static int cuddResizeLinear (DdManager *table)
static void cuddXorLinear (DdManager *table, int x, int y)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"
static int * entry

Define Documentation

#define BPL   32

Definition at line 51 of file cuddLinear.c.

#define CUDD_INVERSE_TRANSFORM_MOVE   2

Definition at line 46 of file cuddLinear.c.

#define CUDD_LINEAR_TRANSFORM_MOVE   1

Definition at line 45 of file cuddLinear.c.

#define CUDD_SWAP_MOVE   0

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

FileName [cuddLinear.c]

PackageName [cudd]

Synopsis [Functions for DD reduction by linear transformations.]

Description [ Internal procedures included in this module:

Static procedures included in this module:

]

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 44 of file cuddLinear.c.

#define LOGBPL   5

Definition at line 52 of file cuddLinear.c.


Function Documentation

static int cuddInitLinear ARGS ( (DdManager *table)   )  [static]
static void ddUpdateInteractionMatrix ARGS ( (DdManager *table, int xindex, int yindex)   )  [static]
static int cuddLinearInPlace ARGS ( (DdManager *table, int x, int y)   )  [static]
static Move* ddUndoMoves ARGS ( (DdManager *table, Move *moves)   )  [static]
static int ddLinearAndSiftingBackward ARGS ( (DdManager *table, int size, Move *moves)   )  [static]
static Move* ddLinearAndSiftingDown ARGS ( (DdManager *table, int x, int xHigh, Move *prevMoves)   )  [static]
static Move* ddLinearAndSiftingUp ARGS ( (DdManager *table, int y, int xLow, Move *prevMoves)   )  [static]
static int ddLinearAndSiftingAux ARGS ( (DdManager *table, int x, int xLow, int xHigh)   )  [static]
static int ddLinearUniqueCompare ARGS ( (int *ptrX, int *ptrY)   )  [static]

AutomaticStart

int Cudd_PrintLinear ( DdManager table  ) 

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

Synopsis [Prints the linear transform matrix.]

Description [Prints the linear transform matrix. Returns 1 in case of success; 0 otherwise.]

SideEffects [none]

SeeAlso []

Definition at line 126 of file cuddLinear.c.

00128 {
00129     int i,j,k;
00130     int retval;
00131     int nvars = table->linearSize;
00132     int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00133     long word;
00134 
00135     for (i = 0; i < nvars; i++) {
00136         for (j = 0; j < wordsPerRow; j++) {
00137             word = table->linear[i*wordsPerRow + j];
00138             for (k = 0; k < BPL; k++) {
00139                 retval = fprintf(table->out,"%ld",word & 1);
00140                 if (retval == 0) return(0);
00141                 word >>= 1;
00142             }
00143         }
00144         retval = fprintf(table->out,"\n");
00145         if (retval == 0) return(0);
00146     }
00147     return(1);
00148 
00149 } /* end of Cudd_PrintLinear */

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

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

Synopsis [Reads an entry of the linear transform matrix.]

Description [Reads an entry of the linear transform matrix.]

SideEffects [none]

SeeAlso []

Definition at line 164 of file cuddLinear.c.

00168 {
00169     int nvars = table->size;
00170     int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00171     long word;
00172     int bit;
00173     int result;
00174 
00175     assert(table->size == table->linearSize);
00176 
00177     word = wordsPerRow * x + (y >> LOGBPL);
00178     bit  = y & (BPL-1);
00179     result = (int) ((table->linear[word] >> bit) & 1);
00180     return(result);
00181 
00182 } /* end of Cudd_ReadLinear */

static int cuddInitLinear ( DdManager table  )  [static]

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

Synopsis [Initializes the linear transform matrix.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 1209 of file cuddLinear.c.

01211 {
01212     int words;
01213     int wordsPerRow;
01214     int nvars;
01215     int word;
01216     int bit;
01217     int i;
01218     long *linear;
01219 
01220     nvars = table->size;
01221     wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01222     words = wordsPerRow * nvars;
01223     table->linear = linear = ALLOC(long,words);
01224     if (linear == NULL) {
01225         table->errorCode = CUDD_MEMORY_OUT;
01226         return(0);
01227     }
01228     table->memused += words * sizeof(long);
01229     table->linearSize = nvars;
01230     for (i = 0; i < words; i++) linear[i] = 0;
01231     for (i = 0; i < nvars; i++) {
01232         word = wordsPerRow * i + (i >> LOGBPL);
01233         bit  = i & (BPL-1);
01234         linear[word] = 1 << bit;
01235     }
01236     return(1);
01237 
01238 } /* end of cuddInitLinear */

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

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.

  1. Order all the variables according to the number of entries in each unique table.
  2. 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.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 213 of file cuddLinear.c.

00217 {
00218     int         i;
00219     int         *var;
00220     int         size;
00221     int         x;
00222     int         result;
00223 #ifdef DD_STATS
00224     int         previousSize;
00225 #endif
00226 
00227 #ifdef DD_STATS
00228     ddTotalNumberLinearTr = 0;
00229 #endif
00230 
00231     size = table->size;
00232 
00233     var = NULL;
00234     entry = NULL;
00235     if (table->linear == NULL) {
00236         result = cuddInitLinear(table);
00237         if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
00238 #if 0
00239         (void) fprintf(table->out,"\n");
00240         result = Cudd_PrintLinear(table);
00241         if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
00242 #endif
00243     } else if (table->size != table->linearSize) {
00244         result = cuddResizeLinear(table);
00245         if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
00246 #if 0
00247         (void) fprintf(table->out,"\n");
00248         result = Cudd_PrintLinear(table);
00249         if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
00250 #endif
00251     }
00252 
00253     /* Find order in which to sift variables. */
00254     entry = ALLOC(int,size);
00255     if (entry == NULL) {
00256         table->errorCode = CUDD_MEMORY_OUT;
00257         goto cuddLinearAndSiftingOutOfMem;
00258     }
00259     var = ALLOC(int,size);
00260     if (var == NULL) {
00261         table->errorCode = CUDD_MEMORY_OUT;
00262         goto cuddLinearAndSiftingOutOfMem;
00263     }
00264 
00265     for (i = 0; i < size; i++) {
00266         x = table->perm[i];
00267         entry[i] = table->subtables[x].keys;
00268         var[i] = i;
00269     }
00270 
00271     qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddLinearUniqueCompare);
00272 
00273     /* Now sift. */
00274     for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00275         x = table->perm[var[i]];
00276         if (x < lower || x > upper) continue;
00277 #ifdef DD_STATS
00278         previousSize = table->keys - table->isolated;
00279 #endif
00280         result = ddLinearAndSiftingAux(table,x,lower,upper);
00281         if (!result) goto cuddLinearAndSiftingOutOfMem; 
00282 #ifdef DD_STATS
00283         if (table->keys < (unsigned) previousSize + table->isolated) {
00284             (void) fprintf(table->out,"-");
00285         } else if (table->keys > (unsigned) previousSize + table->isolated) {
00286             (void) fprintf(table->out,"+");     /* should never happen */
00287             (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00288         } else {
00289             (void) fprintf(table->out,"=");
00290         }
00291         fflush(table->out);
00292 #endif
00293 #ifdef DD_DEBUG
00294         (void) Cudd_DebugCheck(table);
00295 #endif
00296     }
00297 
00298     FREE(var);
00299     FREE(entry);
00300 
00301 #ifdef DD_STATS
00302     (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
00303                    ddTotalNumberLinearTr);
00304 #endif
00305 
00306     return(1);
00307 
00308 cuddLinearAndSiftingOutOfMem:
00309 
00310     if (entry != NULL) FREE(entry);
00311     if (var != NULL) FREE(var);
00312 
00313     return(0); 
00314 
00315 } /* end of cuddLinearAndSifting */

static int cuddLinearInPlace ( DdManager table,
int  x,
int  y 
) [static]

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

Definition at line 823 of file cuddLinear.c.

00827 {
00828     DdNodePtr *xlist, *ylist;
00829     int    xindex, yindex;
00830     int    xslots, yslots;
00831     int    xshift, yshift;
00832     int    oldxkeys, oldykeys;
00833     int    newxkeys, newykeys;
00834     int    comple, newcomplement;
00835     int    i;
00836     int    posn;
00837     int    isolated;
00838     DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00839     DdNode *g,*next,*last;
00840     DdNodePtr *previousP;
00841     DdNode *tmp;
00842     DdNode *sentinel = &(table->sentinel);
00843 #if DD_DEBUG
00844     int    count, idcheck;
00845 #endif
00846 
00847 #ifdef DD_DEBUG
00848     assert(x < y);
00849     assert(cuddNextHigh(table,x) == y);
00850     assert(table->subtables[x].keys != 0);
00851     assert(table->subtables[y].keys != 0);
00852     assert(table->subtables[x].dead == 0);
00853     assert(table->subtables[y].dead == 0);
00854 #endif
00855 
00856     xindex = table->invperm[x];
00857     yindex = table->invperm[y];
00858 
00859     if (cuddTestInteract(table,xindex,yindex)) {
00860 #ifdef DD_STATS
00861         ddTotalNumberLinearTr++;
00862 #endif
00863         /* Get parameters of x subtable. */
00864         xlist = table->subtables[x].nodelist; 
00865         oldxkeys = table->subtables[x].keys;
00866         xslots = table->subtables[x].slots;
00867         xshift = table->subtables[x].shift;
00868 
00869         /* Get parameters of y subtable. */
00870         ylist = table->subtables[y].nodelist;
00871         oldykeys = table->subtables[y].keys;
00872         yslots = table->subtables[y].slots;
00873         yshift = table->subtables[y].shift;
00874 
00875         newxkeys = 0;
00876         newykeys = oldykeys;
00877 
00878         /* Check whether the two projection functions involved in this
00879         ** swap are isolated. At the end, we'll be able to tell how many
00880         ** isolated projection functions are there by checking only these
00881         ** two functions again. This is done to eliminate the isolated
00882         ** projection functions from the node count.
00883         */
00884         isolated = - ((table->vars[xindex]->ref == 1) +
00885                      (table->vars[yindex]->ref == 1));
00886 
00887         /* The nodes in the x layer are put in a chain.
00888         ** The chain is handled as a FIFO; g points to the beginning and
00889         ** last points to the end.
00890         */
00891         g = NULL;
00892         for (i = 0; i < xslots; i++) {
00893             f = xlist[i];
00894             if (f == sentinel) continue;
00895             xlist[i] = sentinel;
00896             if (g == NULL) {
00897                 g = f;
00898             } else {
00899                 last->next = f;
00900             }
00901             while ((next = f->next) != sentinel) {
00902                 f = next;
00903             } /* while there are elements in the collision chain */
00904             last = f;
00905         } /* for each slot of the x subtable */
00906         last->next = NULL;
00907 
00908 #ifdef DD_COUNT
00909         table->swapSteps += oldxkeys;
00910 #endif
00911         /* Take care of the x nodes that must be re-expressed.
00912         ** They form a linked list pointed by g.
00913         */
00914         f = g;
00915         while (f != NULL) {
00916             next = f->next;
00917             /* Find f1, f0, f11, f10, f01, f00. */
00918             f1 = cuddT(f);
00919 #ifdef DD_DEBUG
00920             assert(!(Cudd_IsComplement(f1)));
00921 #endif
00922             if ((int) f1->index == yindex) {
00923                 f11 = cuddT(f1); f10 = cuddE(f1);
00924             } else {
00925                 f11 = f10 = f1;
00926             }
00927 #ifdef DD_DEBUG
00928             assert(!(Cudd_IsComplement(f11)));
00929 #endif
00930             f0 = cuddE(f);
00931             comple = Cudd_IsComplement(f0);
00932             f0 = Cudd_Regular(f0);
00933             if ((int) f0->index == yindex) {
00934                 f01 = cuddT(f0); f00 = cuddE(f0);
00935             } else {
00936                 f01 = f00 = f0;
00937             }
00938             if (comple) {
00939                 f01 = Cudd_Not(f01);
00940                 f00 = Cudd_Not(f00);
00941             }
00942             /* Decrease ref count of f1. */
00943             cuddSatDec(f1->ref);
00944             /* Create the new T child. */
00945             if (f11 == f00) {
00946                 newf1 = f11;
00947                 cuddSatInc(newf1->ref);
00948             } else {
00949                 /* Check ylist for triple (yindex,f11,f00). */
00950                 posn = ddHash(f11, f00, yshift);
00951                 /* For each element newf1 in collision list ylist[posn]. */
00952                 previousP = &(ylist[posn]);
00953                 newf1 = *previousP;
00954                 while (f11 < cuddT(newf1)) {
00955                     previousP = &(newf1->next);
00956                     newf1 = *previousP;
00957                 }
00958                 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
00959                     previousP = &(newf1->next);
00960                     newf1 = *previousP;
00961                 }
00962                 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
00963                     cuddSatInc(newf1->ref);
00964                 } else { /* no match */
00965                     newf1 = cuddDynamicAllocNode(table);
00966                     if (newf1 == NULL)
00967                         goto cuddLinearOutOfMem;
00968                     newf1->index = yindex; newf1->ref = 1;
00969                     cuddT(newf1) = f11;
00970                     cuddE(newf1) = f00;
00971                     /* Insert newf1 in the collision list ylist[posn];
00972                     ** increase the ref counts of f11 and f00.
00973                     */
00974                     newykeys++;
00975                     newf1->next = *previousP;
00976                     *previousP = newf1;
00977                     cuddSatInc(f11->ref);
00978                     tmp = Cudd_Regular(f00);
00979                     cuddSatInc(tmp->ref);
00980                 }
00981             }
00982             cuddT(f) = newf1;
00983 #ifdef DD_DEBUG
00984             assert(!(Cudd_IsComplement(newf1)));
00985 #endif
00986 
00987             /* Do the same for f0, keeping complement dots into account. */
00988             /* decrease ref count of f0 */
00989             tmp = Cudd_Regular(f0);
00990             cuddSatDec(tmp->ref);
00991             /* create the new E child */
00992             if (f01 == f10) {
00993                 newf0 = f01;
00994                 tmp = Cudd_Regular(newf0);
00995                 cuddSatInc(tmp->ref); 
00996             } else {
00997                 /* make sure f01 is regular */
00998                 newcomplement = Cudd_IsComplement(f01);
00999                 if (newcomplement) {
01000                     f01 = Cudd_Not(f01);
01001                     f10 = Cudd_Not(f10);
01002                 }
01003                 /* Check ylist for triple (yindex,f01,f10). */
01004                 posn = ddHash(f01, f10, yshift);
01005                 /* For each element newf0 in collision list ylist[posn]. */
01006                 previousP = &(ylist[posn]);
01007                 newf0 = *previousP;
01008                 while (f01 < cuddT(newf0)) {
01009                     previousP = &(newf0->next);
01010                     newf0 = *previousP;
01011                 }
01012                 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
01013                     previousP = &(newf0->next);
01014                     newf0 = *previousP;
01015                 }
01016                 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
01017                     cuddSatInc(newf0->ref); 
01018                 } else { /* no match */
01019                     newf0 = cuddDynamicAllocNode(table);
01020                     if (newf0 == NULL)
01021                         goto cuddLinearOutOfMem;
01022                     newf0->index = yindex; newf0->ref = 1;
01023                     cuddT(newf0) = f01;
01024                     cuddE(newf0) = f10;
01025                     /* Insert newf0 in the collision list ylist[posn];
01026                     ** increase the ref counts of f01 and f10.
01027                     */
01028                     newykeys++;
01029                     newf0->next = *previousP;
01030                     *previousP = newf0;
01031                     cuddSatInc(f01->ref);
01032                     tmp = Cudd_Regular(f10);
01033                     cuddSatInc(tmp->ref);
01034                 }
01035                 if (newcomplement) {
01036                     newf0 = Cudd_Not(newf0);
01037                 }
01038             }
01039             cuddE(f) = newf0;
01040 
01041             /* Re-insert the modified f in xlist.
01042             ** The modified f does not already exists in xlist.
01043             ** (Because of the uniqueness of the cofactors.)
01044             */
01045             posn = ddHash(newf1, newf0, xshift);
01046             newxkeys++;
01047             previousP = &(xlist[posn]);
01048             tmp = *previousP;
01049             while (newf1 < cuddT(tmp)) {
01050                 previousP = &(tmp->next);
01051                 tmp = *previousP;
01052             }
01053             while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
01054                 previousP = &(tmp->next);
01055                 tmp = *previousP;
01056             }
01057             f->next = *previousP;
01058             *previousP = f;
01059             f = next;
01060         } /* while f != NULL */
01061 
01062         /* GC the y layer. */
01063 
01064         /* For each node f in ylist. */
01065         for (i = 0; i < yslots; i++) {
01066             previousP = &(ylist[i]);
01067             f = *previousP;
01068             while (f != sentinel) {
01069                 next = f->next;
01070                 if (f->ref == 0) {
01071                     tmp = cuddT(f);
01072                     cuddSatDec(tmp->ref);
01073                     tmp = Cudd_Regular(cuddE(f));
01074                     cuddSatDec(tmp->ref);
01075                     cuddDeallocNode(table,f);
01076                     newykeys--;
01077                 } else {
01078                     *previousP = f;
01079                     previousP = &(f->next);
01080                 }
01081                 f = next;
01082             } /* while f */
01083             *previousP = sentinel;
01084         } /* for every collision list */
01085 
01086 #if DD_DEBUG
01087 #if 0
01088         (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
01089 #endif
01090         count = 0;
01091         idcheck = 0;
01092         for (i = 0; i < yslots; i++) {
01093             f = ylist[i];
01094             while (f != sentinel) {
01095                 count++;
01096                 if (f->index != (DdHalfWord) yindex)
01097                     idcheck++;
01098                 f = f->next;
01099             }
01100         }
01101         if (count != newykeys) {
01102             fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
01103         }
01104         if (idcheck != 0)
01105             fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
01106         count = 0;
01107         idcheck = 0;
01108         for (i = 0; i < xslots; i++) {
01109             f = xlist[i];
01110             while (f != sentinel) {
01111                 count++;
01112                 if (f->index != (DdHalfWord) xindex)
01113                     idcheck++;
01114                 f = f->next;
01115             }
01116         }
01117         if (count != newxkeys || newxkeys != oldxkeys) {
01118             fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
01119         }
01120         if (idcheck != 0)
01121             fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
01122 #endif
01123 
01124         isolated += (table->vars[xindex]->ref == 1) +
01125                     (table->vars[yindex]->ref == 1);
01126         table->isolated += isolated;
01127 
01128         /* Set the appropriate fields in table. */
01129         table->subtables[y].keys = newykeys;
01130 
01131         /* Here we should update the linear combination table
01132         ** to record that x <- x EXNOR y. This is done by complementing
01133         ** the (x,y) entry of the table.
01134         */
01135 
01136         table->keys += newykeys - oldykeys;
01137 
01138         cuddXorLinear(table,xindex,yindex);
01139     }
01140 
01141 #ifdef DD_DEBUG
01142     if (zero) {
01143         (void) Cudd_DebugCheck(table);
01144     }
01145 #endif
01146 
01147     return(table->keys - table->isolated);
01148 
01149 cuddLinearOutOfMem:
01150     (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
01151 
01152     return (0);
01153 
01154 } /* end of cuddLinearInPlace */

static int cuddResizeLinear ( DdManager table  )  [static]

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

Synopsis [Resizes the linear transform matrix.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 1253 of file cuddLinear.c.

01255 {
01256     int words,oldWords;
01257     int wordsPerRow,oldWordsPerRow;
01258     int nvars,oldNvars;
01259     int word,oldWord;
01260     int bit;
01261     int i,j;
01262     long *linear,*oldLinear;
01263 
01264     oldNvars = table->linearSize;
01265     oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
01266     oldWords = oldWordsPerRow * oldNvars;
01267     oldLinear = table->linear;
01268 
01269     nvars = table->size;
01270     wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01271     words = wordsPerRow * nvars;
01272     table->linear = linear = ALLOC(long,words);
01273     if (linear == NULL) {
01274         table->errorCode = CUDD_MEMORY_OUT;
01275         return(0);
01276     }
01277     table->memused += (words - oldWords) * sizeof(long);
01278     for (i = 0; i < words; i++) linear[i] = 0;
01279 
01280     /* Copy old matrix. */
01281     for (i = 0; i < oldNvars; i++) {
01282         for (j = 0; j < oldWordsPerRow; j++) {
01283             oldWord = oldWordsPerRow * i + j;
01284             word = wordsPerRow * i + j;
01285             linear[word] = oldLinear[oldWord];
01286         }
01287     }
01288     FREE(oldLinear);
01289 
01290     /* Add elements to the diagonal. */
01291     for (i = oldNvars; i < nvars; i++) {
01292         word = wordsPerRow * i + (i >> LOGBPL);
01293         bit  = i & (BPL-1);
01294         linear[word] = 1 << bit;
01295     }
01296     table->linearSize = nvars;
01297 
01298     return(1);
01299 
01300 } /* end of cuddResizeLinear */

static void cuddXorLinear ( DdManager table,
int  x,
int  y 
) [static]

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

Definition at line 1316 of file cuddLinear.c.

01320 {
01321     int i;
01322     int nvars = table->size;
01323     int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01324     int xstart = wordsPerRow * x;
01325     int ystart = wordsPerRow * y;
01326     long *linear = table->linear;
01327 
01328     for (i = 0; i < wordsPerRow; i++) {
01329         linear[xstart+i] ^= linear[ystart+i];
01330     }
01331 
01332 } /* end of cuddXorLinear */

static int ddLinearAndSiftingAux ( 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. 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]

Definition at line 364 of file cuddLinear.c.

00369 {
00370 
00371     Move        *move;
00372     Move        *moveUp;                /* list of up moves */
00373     Move        *moveDown;              /* list of down moves */
00374     int         initialSize;
00375     int         result;
00376 
00377     initialSize = table->keys - table->isolated;
00378 
00379     moveDown = NULL;
00380     moveUp = NULL;
00381 
00382     if (x == xLow) {
00383         moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00384         /* At this point x --> xHigh unless bounding occurred. */
00385         if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00386         /* Move backward and stop at best position. */  
00387         result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00388         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00389 
00390     } else if (x == xHigh) {
00391         moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00392         /* At this point x --> xLow unless bounding occurred. */
00393         if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00394         /* Move backward and stop at best position. */
00395         result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00396         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00397 
00398     } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
00399         moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00400         /* At this point x --> xHigh unless bounding occurred. */
00401         if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00402         moveUp = ddUndoMoves(table,moveDown);
00403 #ifdef DD_DEBUG
00404         assert(moveUp == NULL || moveUp->x == x);
00405 #endif
00406         moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
00407         if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00408         /* Move backward and stop at best position. */  
00409         result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00410         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00411 
00412     } else { /* must go up first: shorter */
00413         moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00414         /* At this point x --> xLow unless bounding occurred. */
00415         if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00416         moveDown = ddUndoMoves(table,moveUp);
00417 #ifdef DD_DEBUG
00418         assert(moveDown == NULL || moveDown->y == x);
00419 #endif
00420         moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
00421         if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00422         /* Move backward and stop at best position. */  
00423         result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00424         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00425     }
00426 
00427     while (moveDown != NULL) {
00428         move = moveDown->next;
00429         cuddDeallocNode(table, (DdNode *) moveDown);
00430         moveDown = move;
00431     }
00432     while (moveUp != NULL) {
00433         move = moveUp->next;
00434         cuddDeallocNode(table, (DdNode *) moveUp);
00435         moveUp = move;
00436     }
00437 
00438     return(1);
00439 
00440 ddLinearAndSiftingAuxOutOfMem:
00441     while (moveDown != NULL) {
00442         move = moveDown->next;
00443         cuddDeallocNode(table, (DdNode *) moveDown);
00444         moveDown = move;
00445     }
00446     while (moveUp != NULL) {
00447         move = moveUp->next;
00448         cuddDeallocNode(table, (DdNode *) moveUp);
00449         moveUp = move;
00450     }
00451 
00452     return(0);
00453 
00454 } /* end of ddLinearAndSiftingAux */

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

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]

Definition at line 706 of file cuddLinear.c.

00710 {
00711     Move *move;
00712     int res;
00713 
00714     for (move = moves; move != NULL; move = move->next) {
00715         if (move->size < size) {
00716             size = move->size;
00717         }
00718     }
00719 
00720     for (move = moves; move != NULL; move = move->next) {
00721         if (move->size == size) return(1);
00722         if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
00723             res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00724             if (!res) return(0);
00725         }
00726         res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00727         if (!res) return(0);
00728         if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
00729             res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00730             if (!res) return(0);
00731         }
00732     }
00733 
00734     return(1);
00735 
00736 } /* end of ddLinearAndSiftingBackward */

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

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]

Definition at line 593 of file cuddLinear.c.

00598 {
00599     Move        *moves;
00600     Move        *move;
00601     int         y;
00602     int         size, newsize;
00603     int         R;      /* upper bound on node decrease */
00604     int         limitSize;
00605     int         xindex, yindex;
00606     int         isolated;
00607 #ifdef DD_DEBUG
00608     int         checkR;
00609     int         z;
00610     int         zindex;
00611 #endif
00612 
00613     moves = prevMoves;
00614     /* Initialize R */
00615     xindex = table->invperm[x];
00616     limitSize = size = table->keys - table->isolated;
00617     R = 0;
00618     for (y = xHigh; y > x; y--) {
00619         yindex = table->invperm[y];
00620         if (cuddTestInteract(table,xindex,yindex)) {
00621             isolated = table->vars[yindex]->ref == 1;
00622             R += table->subtables[y].keys - isolated;
00623         }
00624     }
00625 
00626     y = cuddNextHigh(table,x);
00627     while (y <= xHigh && size - R < limitSize) {
00628 #ifdef DD_DEBUG
00629         checkR = 0;
00630         for (z = xHigh; z > x; z--) {
00631             zindex = table->invperm[z];
00632             if (cuddTestInteract(table,xindex,zindex)) {
00633                 isolated = table->vars[zindex]->ref == 1;
00634                 checkR += table->subtables[z].keys - isolated;
00635             }
00636         }
00637         if (R != checkR) {
00638             (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
00639         }
00640 #endif
00641         /* Update upper bound on node decrease. */
00642         yindex = table->invperm[y];
00643         if (cuddTestInteract(table,xindex,yindex)) {
00644             isolated = table->vars[yindex]->ref == 1;
00645             R -= table->subtables[y].keys - isolated;
00646         }
00647         size = cuddSwapInPlace(table,x,y);
00648         if (size == 0) goto ddLinearAndSiftingDownOutOfMem; 
00649         newsize = cuddLinearInPlace(table,x,y);
00650         if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
00651         move = (Move *) cuddDynamicAllocNode(table);
00652         if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
00653         move->x = x;
00654         move->y = y;
00655         move->next = moves;
00656         moves = move;
00657         move->flags = CUDD_SWAP_MOVE;
00658         if (newsize >= size) {
00659             /* Undo transformation. The transformation we apply is
00660             ** its own inverse. Hence, we just apply the transformation
00661             ** again.
00662             */
00663             newsize = cuddLinearInPlace(table,x,y);
00664             if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
00665             if (newsize != size) {
00666                 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
00667             }
00668         } else if (cuddTestInteract(table,xindex,yindex)) {
00669             size = newsize;
00670             move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00671             ddUpdateInteractionMatrix(table,xindex,yindex);
00672         }
00673         move->size = size;
00674         if ((double) size > (double) limitSize * table->maxGrowth) break;
00675         if (size < limitSize) limitSize = size;
00676         x = y;
00677         y = cuddNextHigh(table,x);
00678     }
00679     return(moves);
00680 
00681 ddLinearAndSiftingDownOutOfMem:
00682     while (moves != NULL) {
00683         move = moves->next;
00684         cuddDeallocNode(table, (DdNode *) moves);
00685         moves = move;
00686     }
00687     return((Move *) CUDD_OUT_OF_MEM);
00688 
00689 } /* end of ddLinearAndSiftingDown */

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

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]

Definition at line 470 of file cuddLinear.c.

00475 {
00476     Move        *moves;
00477     Move        *move;
00478     int         x;
00479     int         size, newsize;
00480     int         limitSize;
00481     int         xindex, yindex;
00482     int         isolated;
00483     int         L;      /* lower bound on DD size */
00484 #ifdef DD_DEBUG
00485     int checkL;
00486     int z;
00487     int zindex;
00488 #endif
00489 
00490     moves = prevMoves;
00491     yindex = table->invperm[y];
00492 
00493     /* Initialize the lower bound.
00494     ** The part of the DD below y will not change.
00495     ** The part of the DD above y that does not interact with y will not
00496     ** change. The rest may vanish in the best case, except for
00497     ** the nodes at level xLow, which will not vanish, regardless.
00498     */
00499     limitSize = L = table->keys - table->isolated;
00500     for (x = xLow + 1; x < y; x++) {
00501         xindex = table->invperm[x];
00502         if (cuddTestInteract(table,xindex,yindex)) {
00503             isolated = table->vars[xindex]->ref == 1;
00504             L -= table->subtables[x].keys - isolated;
00505         }
00506     }
00507     isolated = table->vars[yindex]->ref == 1;
00508     L -= table->subtables[y].keys - isolated;
00509 
00510     x = cuddNextLow(table,y);
00511     while (x >= xLow && L <= limitSize) {
00512         xindex = table->invperm[x];
00513 #ifdef DD_DEBUG
00514         checkL = table->keys - table->isolated;
00515         for (z = xLow + 1; z < y; z++) {
00516             zindex = table->invperm[z];
00517             if (cuddTestInteract(table,zindex,yindex)) {
00518                 isolated = table->vars[zindex]->ref == 1;
00519                 checkL -= table->subtables[z].keys - isolated;
00520             }
00521         }
00522         isolated = table->vars[yindex]->ref == 1;
00523         checkL -= table->subtables[y].keys - isolated;
00524         if (L != checkL) {
00525             (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
00526         }
00527 #endif
00528         size = cuddSwapInPlace(table,x,y);
00529         if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
00530         newsize = cuddLinearInPlace(table,x,y);
00531         if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
00532         move = (Move *) cuddDynamicAllocNode(table);
00533         if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
00534         move->x = x;
00535         move->y = y;
00536         move->next = moves;
00537         moves = move;
00538         move->flags = CUDD_SWAP_MOVE;
00539         if (newsize >= size) {
00540             /* Undo transformation. The transformation we apply is
00541             ** its own inverse. Hence, we just apply the transformation
00542             ** again.
00543             */
00544             newsize = cuddLinearInPlace(table,x,y);
00545             if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
00546 #ifdef DD_DEBUG
00547             if (newsize != size) {
00548                 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
00549             }
00550 #endif
00551         } else if (cuddTestInteract(table,xindex,yindex)) {
00552             size = newsize;
00553             move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00554             ddUpdateInteractionMatrix(table,xindex,yindex);
00555         }
00556         move->size = size;
00557         /* Update the lower bound. */
00558         if (cuddTestInteract(table,xindex,yindex)) {
00559             isolated = table->vars[xindex]->ref == 1;
00560             L += table->subtables[y].keys - isolated;
00561         }
00562         if ((double) size > (double) limitSize * table->maxGrowth) break;
00563         if (size < limitSize) limitSize = size;
00564         y = x;
00565         x = cuddNextLow(table,y);
00566     }
00567     return(moves);
00568 
00569 ddLinearAndSiftingUpOutOfMem:
00570     while (moves != NULL) {
00571         move = moves->next;
00572         cuddDeallocNode(table, (DdNode *) moves);
00573         moves = move;
00574     }
00575     return((Move *) CUDD_OUT_OF_MEM);
00576 
00577 } /* end of ddLinearAndSiftingUp */

static int ddLinearUniqueCompare ( int *  ptrX,
int *  ptrY 
) [static]

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

Synopsis [Comparison function used by qsort.]

Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.]

SideEffects [None]

Definition at line 336 of file cuddLinear.c.

00339 {
00340 #if 0
00341     if (entry[*ptrY] == entry[*ptrX]) {
00342         return((*ptrX) - (*ptrY));
00343     }
00344 #endif
00345     return(entry[*ptrY] - entry[*ptrX]);
00346 
00347 } /* end of ddLinearUniqueCompare */

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

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]

Definition at line 752 of file cuddLinear.c.

00755 {
00756     Move *invmoves = NULL;
00757     Move *move;
00758     Move *invmove;
00759     int size;
00760 
00761     for (move = moves; move != NULL; move = move->next) {
00762         invmove = (Move *) cuddDynamicAllocNode(table);
00763         if (invmove == NULL) goto ddUndoMovesOutOfMem;
00764         invmove->x = move->x;
00765         invmove->y = move->y;
00766         invmove->next = invmoves;
00767         invmoves = invmove;
00768         if (move->flags == CUDD_SWAP_MOVE) {
00769             invmove->flags = CUDD_SWAP_MOVE;
00770             size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00771             if (!size) goto ddUndoMovesOutOfMem;
00772         } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
00773             invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
00774             size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00775             if (!size) goto ddUndoMovesOutOfMem;
00776             size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00777             if (!size) goto ddUndoMovesOutOfMem;
00778         } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
00779 #ifdef DD_DEBUG
00780             (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
00781 #endif
00782             invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00783             size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00784             if (!size) goto ddUndoMovesOutOfMem;
00785             size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00786             if (!size) goto ddUndoMovesOutOfMem;
00787         }
00788         invmove->size = size;
00789     }
00790 
00791     return(invmoves);
00792 
00793 ddUndoMovesOutOfMem:
00794     while (invmoves != NULL) {
00795         move = invmoves->next;
00796         cuddDeallocNode(table, (DdNode *) invmoves);
00797         invmoves = move;
00798     }
00799     return((Move *) CUDD_OUT_OF_MEM);
00800 
00801 } /* end of ddUndoMoves */

static void ddUpdateInteractionMatrix ( DdManager table,
int  xindex,
int  yindex 
) [static]

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

Synopsis [Updates the interaction matrix.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 1169 of file cuddLinear.c.

01173 {
01174     int i;
01175     for (i = 0; i < yindex; i++) {
01176         if (i != xindex && cuddTestInteract(table,i,yindex)) {
01177             if (i < xindex) {
01178                 cuddSetInteract(table,i,xindex);
01179             } else {
01180                 cuddSetInteract(table,xindex,i);
01181             }
01182         }
01183     }
01184     for (i = yindex+1; i < table->size; i++) {
01185         if (i != xindex && cuddTestInteract(table,yindex,i)) {
01186             if (i < xindex) {
01187                 cuddSetInteract(table,i,xindex);
01188             } else {
01189                 cuddSetInteract(table,xindex,i);
01190             }
01191         }
01192     }
01193 
01194 } /* end of ddUpdateInteractionMatrix */


Variable Documentation

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

Definition at line 68 of file cuddLinear.c.

int* entry [static]

Definition at line 71 of file cuddLinear.c.


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