src/cuBdd/cuddInt.h File Reference

#include <math.h>
#include "cudd.h"
#include "st.h"
Include dependency graph for cuddInt.h:

Go to the source code of this file.

Data Structures

struct  DdGen
struct  DdHook
struct  DdLocalCacheItem
struct  DdLocalCache
struct  DdHashItem
struct  DdHashTable
struct  DdCache
struct  DdSubtable
struct  DdManager
struct  Move
struct  DdQueueItem
struct  DdLevelQueue

Defines

#define DD_INLINE
#define DD_UNUSED
#define DD_MAXREF   ((DdHalfWord) ~0)
#define DD_DEFAULT_RESIZE   10
#define DD_MEM_CHUNK   1022
#define DD_ONE_VAL   (1.0)
#define DD_ZERO_VAL   (0.0)
#define DD_EPSILON   (1.0e-12)
#define DD_PLUS_INF_VAL   (10e301)
#define DD_CRI_HI_MARK   (10e150)
#define DD_CRI_LO_MARK   (-(DD_CRI_HI_MARK))
#define DD_MINUS_INF_VAL   (-(DD_PLUS_INF_VAL))
#define DD_NON_CONSTANT   ((DdNode *) 1)
#define DD_MAX_SUBTABLE_DENSITY   4
#define DD_GC_FRAC_LO   DD_MAX_SUBTABLE_DENSITY * 0.25
#define DD_GC_FRAC_HI   DD_MAX_SUBTABLE_DENSITY * 1.0
#define DD_GC_FRAC_MIN   0.2
#define DD_MIN_HIT   30
#define DD_MAX_LOOSE_FRACTION   5
#define DD_MAX_CACHE_FRACTION   3
#define DD_STASH_FRACTION   64
#define DD_MAX_CACHE_TO_SLOTS_RATIO   4
#define DD_SIFT_MAX_VAR   1000
#define DD_SIFT_MAX_SWAPS   2000000
#define DD_DEFAULT_RECOMB   0
#define DD_MAX_REORDER_GROWTH   1.2
#define DD_FIRST_REORDER   4004
#define DD_DYN_RATIO   2
#define DD_P1   12582917
#define DD_P2   4256249
#define DD_P3   741457
#define DD_P4   1618033999
#define DD_ADD_ITE_TAG   0x02
#define DD_BDD_AND_ABSTRACT_TAG   0x06
#define DD_BDD_XOR_EXIST_ABSTRACT_TAG   0x0a
#define DD_BDD_ITE_TAG   0x0e
#define DD_ADD_BDD_DO_INTERVAL_TAG   0x22
#define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG   0x26
#define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG   0x2a
#define DD_BDD_COMPOSE_RECUR_TAG   0x2e
#define DD_ADD_COMPOSE_RECUR_TAG   0x42
#define DD_ADD_NON_SIM_COMPOSE_TAG   0x46
#define DD_EQUIV_DC_TAG   0x4a
#define DD_ZDD_ITE_TAG   0x4e
#define DD_ADD_ITE_CONSTANT_TAG   0x62
#define DD_ADD_EVAL_CONST_TAG   0x66
#define DD_BDD_ITE_CONSTANT_TAG   0x6a
#define DD_ADD_OUT_SUM_TAG   0x6e
#define DD_BDD_LEQ_UNLESS_TAG   0x82
#define DD_ADD_TRIANGLE_TAG   0x86
#define CUDD_GEN_CUBES   0
#define CUDD_GEN_PRIMES   1
#define CUDD_GEN_NODES   2
#define CUDD_GEN_ZDD_PATHS   3
#define CUDD_GEN_EMPTY   0
#define CUDD_GEN_NONEMPTY   1
#define cuddDeallocNode(unique, node)
#define cuddDeallocMove(unique, node)
#define cuddRef(n)   cuddSatInc(Cudd_Regular(n)->ref)
#define cuddDeref(n)   cuddSatDec(Cudd_Regular(n)->ref)
#define cuddIsConstant(node)   ((node)->index == CUDD_CONST_INDEX)
#define cuddT(node)   ((node)->type.kids.T)
#define cuddE(node)   ((node)->type.kids.E)
#define cuddV(node)   ((node)->type.value)
#define cuddI(dd, index)   (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)])
#define cuddIZ(dd, index)   (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)])
#define ddHash(f, g, s)   ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))
#define ddCHash(o, f, g, h, s)
#define ddCHash2(o, f, g, s)   (((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))
#define cuddClean(p)   ((DdNode *)((ptruint)(p) & ~0xf))
#define ddMin(x, y)   (((y) < (x)) ? (y) : (x))
#define ddMax(x, y)   (((y) > (x)) ? (y) : (x))
#define ddAbs(x)   (((x)<0) ? -(x) : (x))
#define ddEqualVal(x, y, e)   (ddAbs((x)-(y))<(e))
#define cuddSatInc(x)   ((x) += (x) != (DdHalfWord)DD_MAXREF)
#define cuddSatDec(x)   ((x) -= (x) != (DdHalfWord)DD_MAXREF)
#define DD_ONE(dd)   ((dd)->one)
#define DD_ZERO(dd)   ((dd)->zero)
#define DD_PLUS_INFINITY(dd)   ((dd)->plusinfinity)
#define DD_MINUS_INFINITY(dd)   ((dd)->minusinfinity)
#define cuddAdjust(x)   ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x)))
#define DD_LSDIGIT(x)   ((x) & DD_APA_MASK)
#define DD_MSDIGIT(x)   ((x) >> DD_APA_BITS)
#define statLine(dd)

Typedefs

typedef int ptrint
typedef unsigned int ptruint
typedef DdNodeDdNodePtr

Functions

DdNodecuddAddExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube)
DdNodecuddAddUnivAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube)
DdNodecuddAddOrAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube)
DdNodecuddAddApplyRecur (DdManager *dd, DdNode *(*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)
DdNodecuddAddMonadicApplyRecur (DdManager *dd, DdNode *(*op)(DdManager *, DdNode *), DdNode *f)
DdNodecuddAddScalarInverseRecur (DdManager *dd, DdNode *f, DdNode *epsilon)
DdNodecuddAddIteRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
DdNodecuddAddCmplRecur (DdManager *dd, DdNode *f)
DdNodecuddAddNegateRecur (DdManager *dd, DdNode *f)
DdNodecuddAddRoundOffRecur (DdManager *dd, DdNode *f, double trunc)
DdNodecuddUnderApprox (DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)
DdNodecuddRemapUnderApprox (DdManager *dd, DdNode *f, int numVars, int threshold, double quality)
DdNodecuddBiasedUnderApprox (DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)
DdNodecuddBddAndAbstractRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)
int cuddAnnealing (DdManager *table, int lower, int upper)
DdNodecuddBddExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube)
DdNodecuddBddXorExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)
DdNodecuddBddBooleanDiffRecur (DdManager *manager, DdNode *f, DdNode *var)
DdNodecuddBddIteRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
DdNodecuddBddIntersectRecur (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddBddAndRecur (DdManager *manager, DdNode *f, DdNode *g)
DdNodecuddBddXorRecur (DdManager *manager, DdNode *f, DdNode *g)
DdNodecuddBddTransfer (DdManager *ddS, DdManager *ddD, DdNode *f)
DdNodecuddAddBddDoPattern (DdManager *dd, DdNode *f)
int cuddInitCache (DdManager *unique, unsigned int cacheSize, unsigned int maxCacheSize)
void cuddCacheInsert (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)
void cuddCacheInsert2 (DdManager *table, DdNode *(*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g, DdNode *data)
void cuddCacheInsert1 (DdManager *table, DdNode *(*)(DdManager *, DdNode *), DdNode *f, DdNode *data)
DdNodecuddCacheLookup (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
DdNodecuddCacheLookupZdd (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
DdNodecuddCacheLookup2 (DdManager *table, DdNode *(*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)
DdNodecuddCacheLookup1 (DdManager *table, DdNode *(*)(DdManager *, DdNode *), DdNode *f)
DdNodecuddCacheLookup2Zdd (DdManager *table, DdNode *(*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)
DdNodecuddCacheLookup1Zdd (DdManager *table, DdNode *(*)(DdManager *, DdNode *), DdNode *f)
DdNodecuddConstantLookup (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
int cuddCacheProfile (DdManager *table, FILE *fp)
void cuddCacheResize (DdManager *table)
void cuddCacheFlush (DdManager *table)
int cuddComputeFloorLog2 (unsigned int value)
int cuddHeapProfile (DdManager *dd)
void cuddPrintNode (DdNode *f, FILE *fp)
void cuddPrintVarGroups (DdManager *dd, MtrNode *root, int zdd, int silent)
DdNodecuddBddClippingAnd (DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction)
DdNodecuddBddClippingAndAbstract (DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction)
void cuddGetBranches (DdNode *g, DdNode **g1, DdNode **g0)
int cuddCheckCube (DdManager *dd, DdNode *g)
DdNodecuddCofactorRecur (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddBddComposeRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)
DdNodecuddAddComposeRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)
int cuddExact (DdManager *table, int lower, int upper)
DdNodecuddBddConstrainRecur (DdManager *dd, DdNode *f, DdNode *c)
DdNodecuddBddRestrictRecur (DdManager *dd, DdNode *f, DdNode *c)
DdNodecuddBddNPAndRecur (DdManager *dd, DdNode *f, DdNode *c)
DdNodecuddAddConstrainRecur (DdManager *dd, DdNode *f, DdNode *c)
DdNodecuddAddRestrictRecur (DdManager *dd, DdNode *f, DdNode *c)
DdNodecuddBddLICompaction (DdManager *dd, DdNode *f, DdNode *c)
int cuddGa (DdManager *table, int lower, int upper)
int cuddTreeSifting (DdManager *table, Cudd_ReorderingType method)
int cuddZddInitUniv (DdManager *zdd)
void cuddZddFreeUniv (DdManager *zdd)
void cuddSetInteract (DdManager *table, int x, int y)
int cuddTestInteract (DdManager *table, int x, int y)
int cuddInitInteract (DdManager *table)
DdLocalCachecuddLocalCacheInit (DdManager *manager, unsigned int keySize, unsigned int cacheSize, unsigned int maxCacheSize)
void cuddLocalCacheQuit (DdLocalCache *cache)
void cuddLocalCacheInsert (DdLocalCache *cache, DdNodePtr *key, DdNode *value)
DdNodecuddLocalCacheLookup (DdLocalCache *cache, DdNodePtr *key)
void cuddLocalCacheClearDead (DdManager *manager)
int cuddIsInDeathRow (DdManager *dd, DdNode *f)
int cuddTimesInDeathRow (DdManager *dd, DdNode *f)
void cuddLocalCacheClearAll (DdManager *manager)
DdHashTablecuddHashTableInit (DdManager *manager, unsigned int keySize, unsigned int initSize)
void cuddHashTableQuit (DdHashTable *hash)
int cuddHashTableInsert (DdHashTable *hash, DdNodePtr *key, DdNode *value, ptrint count)
DdNodecuddHashTableLookup (DdHashTable *hash, DdNodePtr *key)
int cuddHashTableInsert1 (DdHashTable *hash, DdNode *f, DdNode *value, ptrint count)
DdNodecuddHashTableLookup1 (DdHashTable *hash, DdNode *f)
int cuddHashTableInsert2 (DdHashTable *hash, DdNode *f, DdNode *g, DdNode *value, ptrint count)
DdNodecuddHashTableLookup2 (DdHashTable *hash, DdNode *f, DdNode *g)
int cuddHashTableInsert3 (DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h, DdNode *value, ptrint count)
DdNodecuddHashTableLookup3 (DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h)
DdLevelQueuecuddLevelQueueInit (int levels, int itemSize, int numBuckets)
void cuddLevelQueueQuit (DdLevelQueue *queue)
void * cuddLevelQueueEnqueue (DdLevelQueue *queue, void *key, int level)
void cuddLevelQueueDequeue (DdLevelQueue *queue, int level)
int cuddLinearAndSifting (DdManager *table, int lower, int upper)
int cuddLinearInPlace (DdManager *table, int x, int y)
void cuddUpdateInteractionMatrix (DdManager *table, int xindex, int yindex)
int cuddInitLinear (DdManager *table)
int cuddResizeLinear (DdManager *table)
DdNodecuddBddLiteralSetIntersectionRecur (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddCProjectionRecur (DdManager *dd, DdNode *R, DdNode *Y, DdNode *Ysupp)
DdNodecuddBddClosestCube (DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE bound)
void cuddReclaim (DdManager *table, DdNode *n)
void cuddReclaimZdd (DdManager *table, DdNode *n)
void cuddClearDeathRow (DdManager *table)
void cuddShrinkDeathRow (DdManager *table)
DdNodecuddDynamicAllocNode (DdManager *table)
int cuddSifting (DdManager *table, int lower, int upper)
int cuddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
int cuddNextHigh (DdManager *table, int x)
int cuddNextLow (DdManager *table, int x)
int cuddSwapInPlace (DdManager *table, int x, int y)
int cuddBddAlignToZdd (DdManager *table)
DdNodecuddBddMakePrime (DdManager *dd, DdNode *cube, DdNode *f)
DdNodecuddSolveEqnRecur (DdManager *bdd, DdNode *F, DdNode *Y, DdNode **G, int n, int *yIndex, int i)
DdNodecuddVerifySol (DdManager *bdd, DdNode *F, DdNode **G, int *yIndex, int n)
DdNodecuddSubsetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold)
DdNodecuddSubsetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)
int cuddSymmCheck (DdManager *table, int x, int y)
int cuddSymmSifting (DdManager *table, int lower, int upper)
int cuddSymmSiftingConv (DdManager *table, int lower, int upper)
DdNodecuddAllocNode (DdManager *unique)
DdManagercuddInitTable (unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo)
void cuddFreeTable (DdManager *unique)
int cuddGarbageCollect (DdManager *unique, int clearCache)
DdNodecuddZddGetNode (DdManager *zdd, int id, DdNode *T, DdNode *E)
DdNodecuddZddGetNodeIVO (DdManager *dd, int index, DdNode *g, DdNode *h)
DdNodecuddUniqueInter (DdManager *unique, int index, DdNode *T, DdNode *E)
DdNodecuddUniqueInterIVO (DdManager *unique, int index, DdNode *T, DdNode *E)
DdNodecuddUniqueInterZdd (DdManager *unique, int index, DdNode *T, DdNode *E)
DdNodecuddUniqueConst (DdManager *unique, CUDD_VALUE_TYPE value)
void cuddRehash (DdManager *unique, int i)
void cuddShrinkSubtable (DdManager *unique, int i)
int cuddInsertSubtables (DdManager *unique, int n, int level)
int cuddDestroySubtables (DdManager *unique, int n)
int cuddResizeTableZdd (DdManager *unique, int index)
void cuddSlowTableGrowth (DdManager *unique)
int cuddP (DdManager *dd, DdNode *f)
DdNodePtrcuddNodeArray (DdNode *f, int *n)
int cuddWindowReorder (DdManager *table, int low, int high, Cudd_ReorderingType submethod)
DdNodecuddZddProduct (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddZddUnateProduct (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddZddWeakDiv (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddZddWeakDivF (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddZddDivide (DdManager *dd, DdNode *f, DdNode *g)
DdNodecuddZddDivideF (DdManager *dd, DdNode *f, DdNode *g)
int cuddZddGetCofactors3 (DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0, DdNode **fd)
int cuddZddGetCofactors2 (DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0)
DdNodecuddZddComplement (DdManager *dd, DdNode *node)
int cuddZddGetPosVarIndex (DdManager *dd, int index)
int cuddZddGetNegVarIndex (DdManager *dd, int index)
int cuddZddGetPosVarLevel (DdManager *dd, int index)
int cuddZddGetNegVarLevel (DdManager *dd, int index)
int cuddZddTreeSifting (DdManager *table, Cudd_ReorderingType method)
DdNodecuddZddIsop (DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)
DdNodecuddBddIsop (DdManager *dd, DdNode *L, DdNode *U)
DdNodecuddMakeBddFromZddCover (DdManager *dd, DdNode *node)
int cuddZddLinearSifting (DdManager *table, int lower, int upper)
int cuddZddAlignToBdd (DdManager *table)
int cuddZddNextHigh (DdManager *table, int x)
int cuddZddNextLow (DdManager *table, int x)
int cuddZddUniqueCompare (int *ptr_x, int *ptr_y)
int cuddZddSwapInPlace (DdManager *table, int x, int y)
int cuddZddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
int cuddZddSifting (DdManager *table, int lower, int upper)
DdNodecuddZddIte (DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
DdNodecuddZddUnion (DdManager *zdd, DdNode *P, DdNode *Q)
DdNodecuddZddIntersect (DdManager *zdd, DdNode *P, DdNode *Q)
DdNodecuddZddDiff (DdManager *zdd, DdNode *P, DdNode *Q)
DdNodecuddZddChangeAux (DdManager *zdd, DdNode *P, DdNode *zvar)
DdNodecuddZddSubset1 (DdManager *dd, DdNode *P, int var)
DdNodecuddZddSubset0 (DdManager *dd, DdNode *P, int var)
DdNodecuddZddChange (DdManager *dd, DdNode *P, int var)
int cuddZddSymmCheck (DdManager *table, int x, int y)
int cuddZddSymmSifting (DdManager *table, int lower, int upper)
int cuddZddSymmSiftingConv (DdManager *table, int lower, int upper)
int cuddZddP (DdManager *zdd, DdNode *f)

Define Documentation

#define CUDD_GEN_CUBES   0

Definition at line 193 of file cuddInt.h.

#define CUDD_GEN_EMPTY   0

Definition at line 197 of file cuddInt.h.

#define CUDD_GEN_NODES   2

Definition at line 195 of file cuddInt.h.

#define CUDD_GEN_NONEMPTY   1

Definition at line 198 of file cuddInt.h.

#define CUDD_GEN_PRIMES   1

Definition at line 194 of file cuddInt.h.

#define CUDD_GEN_ZDD_PATHS   3

Definition at line 196 of file cuddInt.h.

#define cuddAdjust (  )     ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x)))

Macro***********************************************************************

Synopsis [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.]

Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to DD_PLUS_INF_VAL. Normally this macro is a NOOP. However, if HAVE_IEEE_754 is not defined, it makes sure that a value does not get larger than infinity in absolute value, and once it gets to infinity, stays there. If the value overflows before this macro is applied, no recovery is possible.]

SideEffects [none]

SeeAlso []

Definition at line 950 of file cuddInt.h.

#define cuddClean (  )     ((DdNode *)((ptruint)(p) & ~0xf))

Macro***********************************************************************

Synopsis [Clears the 4 least significant bits of a pointer.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 775 of file cuddInt.h.

#define cuddDeallocMove ( unique,
node   ) 
Value:
((DdNode *)(node))->ref = 0; \
    ((DdNode *)(node))->next = (unique)->nextFree; \
    (unique)->nextFree = (DdNode *)(node);

Macro***********************************************************************

Synopsis [Adds node to the head of the free list.]

Description [Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.]

SideEffects [None]

SeeAlso [cuddDeallocNode cuddDynamicAllocNode]

Definition at line 555 of file cuddInt.h.

#define cuddDeallocNode ( unique,
node   ) 
Value:
(node)->next = (unique)->nextFree; \
    (unique)->nextFree = node;

Macro***********************************************************************

Synopsis [Adds node to the head of the free list.]

Description [Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.]

SideEffects [None]

SeeAlso [cuddAllocNode cuddDynamicAllocNode cuddDeallocMove]

Definition at line 538 of file cuddInt.h.

#define cuddDeref (  )     cuddSatDec(Cudd_Regular(n)->ref)

Macro***********************************************************************

Synopsis [Decreases the reference count of a node, if it is not saturated.]

Description [Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous cuddRef. This being a macro, it is faster than Cudd_Deref, but it cannot be used in constructs like cuddDeref(a = b()).]

SideEffects [none]

SeeAlso [Cudd_Deref]

Definition at line 595 of file cuddInt.h.

#define cuddE ( node   )     ((node)->type.kids.E)

Macro***********************************************************************

Synopsis [Returns the else child of an internal node.]

Description [Returns the else child of an internal node. If node is a constant node, the result is unpredictable. The pointer passed to cuddE must be regular.]

SideEffects [none]

SeeAlso [Cudd_E]

Definition at line 643 of file cuddInt.h.

#define cuddI ( dd,
index   )     (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)])

Macro***********************************************************************

Synopsis [Finds the current position of variable index in the order.]

Description [Finds the current position of variable index in the order. This macro duplicates the functionality of Cudd_ReadPerm, but it does not check for out-of-bounds indices and it is more efficient.]

SideEffects [none]

SeeAlso [Cudd_ReadPerm]

Definition at line 677 of file cuddInt.h.

#define cuddIsConstant ( node   )     ((node)->index == CUDD_CONST_INDEX)

Macro***********************************************************************

Synopsis [Returns 1 if the node is a constant node.]

Description [Returns 1 if the node is a constant node (rather than an internal node). All constant nodes have the same index (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.]

SideEffects [none]

SeeAlso [Cudd_IsConstant]

Definition at line 611 of file cuddInt.h.

#define cuddIZ ( dd,
index   )     (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)])

Macro***********************************************************************

Synopsis [Finds the current position of ZDD variable index in the order.]

Description [Finds the current position of ZDD variable index in the order. This macro duplicates the functionality of Cudd_ReadPermZdd, but it does not check for out-of-bounds indices and it is more efficient.]

SideEffects [none]

SeeAlso [Cudd_ReadPermZdd]

Definition at line 695 of file cuddInt.h.

#define cuddRef (  )     cuddSatInc(Cudd_Regular(n)->ref)

Macro***********************************************************************

Synopsis [Increases the reference count of a node, if it is not saturated.]

Description [Increases the reference count of a node, if it is not saturated. This being a macro, it is faster than Cudd_Ref, but it cannot be used in constructs like cuddRef(a = b()).]

SideEffects [none]

SeeAlso [Cudd_Ref]

Definition at line 575 of file cuddInt.h.

#define cuddSatDec (  )     ((x) -= (x) != (DdHalfWord)DD_MAXREF)

Macro***********************************************************************

Synopsis [Saturating decrement operator.]

Description []

SideEffects [none]

SeeAlso [cuddSatInc]

Definition at line 867 of file cuddInt.h.

#define cuddSatInc (  )     ((x) += (x) != (DdHalfWord)DD_MAXREF)

Macro***********************************************************************

Synopsis [Saturating increment operator.]

Description []

SideEffects [none]

SeeAlso [cuddSatDec]

Definition at line 849 of file cuddInt.h.

#define cuddT ( node   )     ((node)->type.kids.T)

Macro***********************************************************************

Synopsis [Returns the then child of an internal node.]

Description [Returns the then child of an internal node. If node is a constant node, the result is unpredictable. The pointer passed to cuddT must be regular.]

SideEffects [none]

SeeAlso [Cudd_T]

Definition at line 627 of file cuddInt.h.

#define cuddV ( node   )     ((node)->type.value)

Macro***********************************************************************

Synopsis [Returns the value of a constant node.]

Description [Returns the value of a constant node. If node is an internal node, the result is unpredictable. The pointer passed to cuddV must be regular.]

SideEffects [none]

SeeAlso [Cudd_V]

Definition at line 659 of file cuddInt.h.

#define DD_ADD_BDD_DO_INTERVAL_TAG   0x22

Definition at line 177 of file cuddInt.h.

#define DD_ADD_COMPOSE_RECUR_TAG   0x42

Definition at line 181 of file cuddInt.h.

#define DD_ADD_EVAL_CONST_TAG   0x66

Definition at line 186 of file cuddInt.h.

#define DD_ADD_ITE_CONSTANT_TAG   0x62

Definition at line 185 of file cuddInt.h.

#define DD_ADD_ITE_TAG   0x02

Definition at line 173 of file cuddInt.h.

#define DD_ADD_NON_SIM_COMPOSE_TAG   0x46

Definition at line 182 of file cuddInt.h.

#define DD_ADD_OUT_SUM_TAG   0x6e

Definition at line 188 of file cuddInt.h.

#define DD_ADD_TRIANGLE_TAG   0x86

Definition at line 190 of file cuddInt.h.

#define DD_BDD_AND_ABSTRACT_TAG   0x06

Definition at line 174 of file cuddInt.h.

#define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG   0x2a

Definition at line 179 of file cuddInt.h.

#define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG   0x26

Definition at line 178 of file cuddInt.h.

#define DD_BDD_COMPOSE_RECUR_TAG   0x2e

Definition at line 180 of file cuddInt.h.

#define DD_BDD_ITE_CONSTANT_TAG   0x6a

Definition at line 187 of file cuddInt.h.

#define DD_BDD_ITE_TAG   0x0e

Definition at line 176 of file cuddInt.h.

#define DD_BDD_LEQ_UNLESS_TAG   0x82

Definition at line 189 of file cuddInt.h.

#define DD_BDD_XOR_EXIST_ABSTRACT_TAG   0x0a

Definition at line 175 of file cuddInt.h.

#define DD_CRI_HI_MARK   (10e150)

Definition at line 119 of file cuddInt.h.

#define DD_CRI_LO_MARK   (-(DD_CRI_HI_MARK))

Definition at line 120 of file cuddInt.h.

#define DD_DEFAULT_RECOMB   0

Definition at line 150 of file cuddInt.h.

#define DD_DEFAULT_RESIZE   10

Definition at line 103 of file cuddInt.h.

#define DD_DYN_RATIO   2

Definition at line 153 of file cuddInt.h.

#define DD_EPSILON   (1.0e-12)

Definition at line 110 of file cuddInt.h.

#define DD_EQUIV_DC_TAG   0x4a

Definition at line 183 of file cuddInt.h.

#define DD_FIRST_REORDER   4004

Definition at line 152 of file cuddInt.h.

#define DD_GC_FRAC_HI   DD_MAX_SUBTABLE_DENSITY * 1.0

Definition at line 135 of file cuddInt.h.

#define DD_GC_FRAC_LO   DD_MAX_SUBTABLE_DENSITY * 0.25

Definition at line 134 of file cuddInt.h.

#define DD_GC_FRAC_MIN   0.2

Definition at line 136 of file cuddInt.h.

#define DD_INLINE

CHeaderFile*****************************************************************

FileName [cuddInt.h]

PackageName [cudd]

Synopsis [Internal data structures of the CUDD package.]

Description []

SeeAlso []

Author [Fabio Somenzi]

Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]

Revision [

Id
cuddInt.h,v 1.139 2009/03/08 02:49:02 fabio Exp

]

Definition at line 91 of file cuddInt.h.

#define DD_LSDIGIT (  )     ((x) & DD_APA_MASK)

Macro***********************************************************************

Synopsis [Extract the least significant digit of a double digit.]

Description [Extract the least significant digit of a double digit. Used in the manipulation of arbitrary precision integers.]

SideEffects [None]

SeeAlso [DD_MSDIGIT]

Definition at line 966 of file cuddInt.h.

#define DD_MAX_CACHE_FRACTION   3

Definition at line 141 of file cuddInt.h.

#define DD_MAX_CACHE_TO_SLOTS_RATIO   4

Definition at line 145 of file cuddInt.h.

#define DD_MAX_LOOSE_FRACTION   5

Definition at line 139 of file cuddInt.h.

#define DD_MAX_REORDER_GROWTH   1.2

Definition at line 151 of file cuddInt.h.

#define DD_MAX_SUBTABLE_DENSITY   4

Definition at line 127 of file cuddInt.h.

#define DD_MAXREF   ((DdHalfWord) ~0)

Definition at line 101 of file cuddInt.h.

#define DD_MEM_CHUNK   1022

Definition at line 105 of file cuddInt.h.

#define DD_MIN_HIT   30

Definition at line 137 of file cuddInt.h.

#define DD_MINUS_INF_VAL   (-(DD_PLUS_INF_VAL))

Definition at line 122 of file cuddInt.h.

#define DD_MINUS_INFINITY ( dd   )     ((dd)->minusinfinity)

Macro***********************************************************************

Synopsis [Returns the minus infinity constant node.]

Description []

SideEffects [none]

SeeAlso [DD_ONE DD_ZERO DD_PLUS_INFINITY]

Definition at line 926 of file cuddInt.h.

#define DD_MSDIGIT (  )     ((x) >> DD_APA_BITS)

Macro***********************************************************************

Synopsis [Extract the most significant digit of a double digit.]

Description [Extract the most significant digit of a double digit. Used in the manipulation of arbitrary precision integers.]

SideEffects [None]

SeeAlso [DD_LSDIGIT]

Definition at line 981 of file cuddInt.h.

#define DD_NON_CONSTANT   ((DdNode *) 1)

Definition at line 124 of file cuddInt.h.

#define DD_ONE ( dd   )     ((dd)->one)

Macro***********************************************************************

Synopsis [Returns the constant 1 node.]

Description []

SideEffects [none]

SeeAlso [DD_ZERO DD_PLUS_INFINITY DD_MINUS_INFINITY]

Definition at line 882 of file cuddInt.h.

#define DD_ONE_VAL   (1.0)

Definition at line 108 of file cuddInt.h.

#define DD_P1   12582917

Definition at line 156 of file cuddInt.h.

#define DD_P2   4256249

Definition at line 157 of file cuddInt.h.

#define DD_P3   741457

Definition at line 158 of file cuddInt.h.

#define DD_P4   1618033999

Definition at line 159 of file cuddInt.h.

#define DD_PLUS_INF_VAL   (10e301)

Definition at line 118 of file cuddInt.h.

#define DD_PLUS_INFINITY ( dd   )     ((dd)->plusinfinity)

Macro***********************************************************************

Synopsis [Returns the plus infinity constant node.]

Description []

SideEffects [none]

SeeAlso [DD_ONE DD_ZERO DD_MINUS_INFINITY]

Definition at line 912 of file cuddInt.h.

#define DD_SIFT_MAX_SWAPS   2000000

Definition at line 149 of file cuddInt.h.

#define DD_SIFT_MAX_VAR   1000

Definition at line 148 of file cuddInt.h.

#define DD_STASH_FRACTION   64

Definition at line 143 of file cuddInt.h.

#define DD_UNUSED

Definition at line 93 of file cuddInt.h.

#define DD_ZDD_ITE_TAG   0x4e

Definition at line 184 of file cuddInt.h.

#define DD_ZERO ( dd   )     ((dd)->zero)

Macro***********************************************************************

Synopsis [Returns the arithmetic 0 constant node.]

Description [Returns the arithmetic 0 constant node. This is different from the logical zero. The latter is obtained by Cudd_Not(DD_ONE(dd)).]

SideEffects [none]

SeeAlso [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY]

Definition at line 898 of file cuddInt.h.

#define DD_ZERO_VAL   (0.0)

Definition at line 109 of file cuddInt.h.

#define ddAbs (  )     (((x)<0) ? -(x) : (x))

Macro***********************************************************************

Synopsis [Computes the absolute value of a number.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 817 of file cuddInt.h.

#define ddCHash ( o,
f,
g,
h,
 ) 
Value:
((((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2 + \
   (unsigned)(h)) * DD_P3) >> (s))

Macro***********************************************************************

Synopsis [Hash function for the cache.]

Description []

SideEffects [none]

SeeAlso [ddHash ddCHash2]

Definition at line 736 of file cuddInt.h.

#define ddCHash2 ( o,
f,
g,
 )     (((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))

Macro***********************************************************************

Synopsis [Hash function for the cache for functions with two operands.]

Description []

SideEffects [none]

SeeAlso [ddHash ddCHash]

Definition at line 759 of file cuddInt.h.

#define ddEqualVal ( x,
y,
 )     (ddAbs((x)-(y))<(e))

Macro***********************************************************************

Synopsis [Returns 1 if the absolute value of the difference of the two arguments x and y is less than e.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 832 of file cuddInt.h.

#define ddHash ( f,
g,
 )     ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))

Macro***********************************************************************

Synopsis [Hash function for the unique table.]

Description []

SideEffects [none]

SeeAlso [ddCHash ddCHash2]

Definition at line 714 of file cuddInt.h.

#define ddMax ( x,
 )     (((y) > (x)) ? (y) : (x))

Macro***********************************************************************

Synopsis [Computes the maximum of two numbers.]

Description []

SideEffects [none]

SeeAlso [ddMin]

Definition at line 803 of file cuddInt.h.

#define ddMin ( x,
 )     (((y) < (x)) ? (y) : (x))

Macro***********************************************************************

Synopsis [Computes the minimum of two numbers.]

Description []

SideEffects [none]

SeeAlso [ddMax]

Definition at line 789 of file cuddInt.h.

#define statLine ( dd   ) 

Macro***********************************************************************

Synopsis [Outputs a line of stats.]

Description [Outputs a line of stats if DD_COUNT and DD_STATS are defined. Increments the number of recursive calls if DD_COUNT is defined.]

SideEffects [None]

SeeAlso []

Definition at line 1008 of file cuddInt.h.


Typedef Documentation

typedef DdNode* DdNodePtr

Definition at line 264 of file cuddInt.h.

typedef int ptrint

Definition at line 255 of file cuddInt.h.

typedef unsigned int ptruint

Definition at line 256 of file cuddInt.h.


Function Documentation

DdNode* cuddAddApplyRecur ( DdManager dd,
DdNode *)(DdManager *, DdNode **, DdNode **,
DdNode f,
DdNode g 
)
DdNode* cuddAddBddDoPattern ( DdManager dd,
DdNode f 
)

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

Synopsis [Performs the recursive step for Cudd_addBddPattern.]

Description [Performs the recursive step for Cudd_addBddPattern. Returns a pointer to the resulting BDD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 489 of file cuddBridge.c.

00492 {
00493     DdNode *res, *T, *E;
00494     DdNode *fv, *fvn;
00495     int v;
00496 
00497     statLine(dd);
00498     /* Check terminal case. */
00499     if (cuddIsConstant(f)) {
00500         return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd)));
00501     }
00502 
00503     /* Check cache. */
00504     res = cuddCacheLookup1(dd,Cudd_addBddPattern,f);
00505     if (res != NULL) return(res);
00506 
00507     /* Recursive step. */
00508     v = f->index;
00509     fv = cuddT(f); fvn = cuddE(f);
00510 
00511     T = cuddAddBddDoPattern(dd,fv);
00512     if (T == NULL) return(NULL);
00513     cuddRef(T);
00514 
00515     E = cuddAddBddDoPattern(dd,fvn);
00516     if (E == NULL) {
00517         Cudd_RecursiveDeref(dd, T);
00518         return(NULL);
00519     }
00520     cuddRef(E);
00521     if (Cudd_IsComplement(T)) {
00522         res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
00523         if (res == NULL) {
00524             Cudd_RecursiveDeref(dd, T);
00525             Cudd_RecursiveDeref(dd, E);
00526             return(NULL);
00527         }
00528         res = Cudd_Not(res);
00529     } else {
00530         res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
00531         if (res == NULL) {
00532             Cudd_RecursiveDeref(dd, T);
00533             Cudd_RecursiveDeref(dd, E);
00534             return(NULL);
00535         }
00536     }
00537     cuddDeref(T);
00538     cuddDeref(E);
00539 
00540     /* Store result. */
00541     cuddCacheInsert1(dd,Cudd_addBddPattern,f,res);
00542 
00543     return(res);
00544 
00545 } /* end of cuddAddBddDoPattern */

DdNode* cuddAddCmplRecur ( DdManager dd,
DdNode f 
)

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

Synopsis [Performs the recursive step of Cudd_addCmpl.]

Description [Performs the recursive step of Cudd_addCmpl. Returns a pointer to the resulting ADD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_addCmpl]

Definition at line 558 of file cuddAddIte.c.

00561 {
00562     DdNode *one,*zero;
00563     DdNode *r,*Fv,*Fnv,*t,*e;
00564 
00565     statLine(dd);
00566     one = DD_ONE(dd);
00567     zero = DD_ZERO(dd); 
00568 
00569     if (cuddIsConstant(f)) {
00570         if (f == zero) {
00571             return(one);
00572         } else {
00573             return(zero);
00574         }
00575     }
00576     r = cuddCacheLookup1(dd,Cudd_addCmpl,f);
00577     if (r != NULL) {
00578         return(r);
00579     }
00580     Fv = cuddT(f);
00581     Fnv = cuddE(f);
00582     t = cuddAddCmplRecur(dd,Fv);
00583     if (t == NULL) return(NULL);
00584     cuddRef(t);
00585     e = cuddAddCmplRecur(dd,Fnv);
00586     if (e == NULL) {
00587         Cudd_RecursiveDeref(dd,t);
00588         return(NULL);
00589     }
00590     cuddRef(e);
00591     r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
00592     if (r == NULL) {
00593         Cudd_RecursiveDeref(dd, t);
00594         Cudd_RecursiveDeref(dd, e);
00595         return(NULL);
00596     }
00597     cuddDeref(t);
00598     cuddDeref(e);
00599     cuddCacheInsert1(dd,Cudd_addCmpl,f,r);
00600     return(r);
00601 
00602 } /* end of cuddAddCmplRecur */

DdNode* cuddAddComposeRecur ( DdManager dd,
DdNode f,
DdNode g,
DdNode proj 
)

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

Synopsis [Performs the recursive step of Cudd_addCompose.]

Description [Performs the recursive step of Cudd_addCompose. Returns the composed BDD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_addCompose]

Definition at line 948 of file cuddCompose.c.

00953 {
00954     DdNode *f1, *f0, *g1, *g0, *r, *t, *e;
00955     unsigned int v, topf, topg, topindex;
00956 
00957     statLine(dd);
00958     v = dd->perm[proj->index];
00959     topf = cuddI(dd,f->index);
00960 
00961     /* Terminal case. Subsumes the test for constant f. */
00962     if (topf > v) return(f);
00963 
00964     /* Check cache. */
00965     r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj);
00966     if (r != NULL) {
00967         return(r);
00968     }
00969 
00970     if (topf == v) {
00971         /* Compose. */
00972         f1 = cuddT(f);
00973         f0 = cuddE(f);
00974         r = cuddAddIteRecur(dd, g, f1, f0);
00975         if (r == NULL) return(NULL);
00976     } else {
00977         /* Compute cofactors of f and g. Remember the index of the top
00978         ** variable.
00979         */
00980         topg = cuddI(dd,g->index);
00981         if (topf > topg) {
00982             topindex = g->index;
00983             f1 = f0 = f;
00984         } else {
00985             topindex = f->index;
00986             f1 = cuddT(f);
00987             f0 = cuddE(f);
00988         }
00989         if (topg > topf) {
00990             g1 = g0 = g;
00991         } else {
00992             g1 = cuddT(g);
00993             g0 = cuddE(g);
00994         }
00995         /* Recursive step. */
00996         t = cuddAddComposeRecur(dd, f1, g1, proj);
00997         if (t == NULL) return(NULL);
00998         cuddRef(t);
00999         e = cuddAddComposeRecur(dd, f0, g0, proj);
01000         if (e == NULL) {
01001             Cudd_RecursiveDeref(dd, t);
01002             return(NULL);
01003         }
01004         cuddRef(e);
01005 
01006         if (t == e) {
01007             r = t;
01008         } else {
01009             r = cuddUniqueInter(dd, (int) topindex, t, e);
01010             if (r == NULL) {
01011                 Cudd_RecursiveDeref(dd, t);
01012                 Cudd_RecursiveDeref(dd, e);
01013                 return(NULL);
01014             }
01015         }
01016         cuddDeref(t);
01017         cuddDeref(e);
01018     }
01019 
01020     cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r);
01021 
01022     return(r);
01023 
01024 } /* end of cuddAddComposeRecur */

DdNode* cuddAddConstrainRecur ( DdManager dd,
DdNode f,
DdNode c 
)

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

Synopsis [Performs the recursive step of Cudd_addConstrain.]

Description [Performs the recursive step of Cudd_addConstrain. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_addConstrain]

Definition at line 1199 of file cuddGenCof.c.

01203 {
01204     DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
01205     DdNode       *one, *zero;
01206     unsigned int topf, topc;
01207     int          index;
01208 
01209     statLine(dd);
01210     one = DD_ONE(dd);
01211     zero = DD_ZERO(dd);
01212 
01213     /* Trivial cases. */
01214     if (c == one)               return(f);
01215     if (c == zero)              return(zero);
01216     if (Cudd_IsConstant(f))     return(f);
01217     if (f == c)                 return(one);
01218 
01219     /* Now f and c are non-constant. */
01220 
01221     /* Check the cache. */
01222     r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c);
01223     if (r != NULL) {
01224         return(r);
01225     }
01226     
01227     /* Recursive step. */
01228     topf = dd->perm[f->index];
01229     topc = dd->perm[c->index];
01230     if (topf <= topc) {
01231         index = f->index;
01232         Fv = cuddT(f); Fnv = cuddE(f);
01233     } else {
01234         index = c->index;
01235         Fv = Fnv = f;
01236     }
01237     if (topc <= topf) {
01238         Cv = cuddT(c); Cnv = cuddE(c);
01239     } else {
01240         Cv = Cnv = c;
01241     }
01242 
01243     if (!Cudd_IsConstant(Cv)) {
01244         t = cuddAddConstrainRecur(dd, Fv, Cv);
01245         if (t == NULL)
01246             return(NULL);
01247     } else if (Cv == one) {
01248         t = Fv;
01249     } else {            /* Cv == zero: return Fnv @ Cnv */
01250         if (Cnv == one) {
01251             r = Fnv;
01252         } else {
01253             r = cuddAddConstrainRecur(dd, Fnv, Cnv);
01254             if (r == NULL)
01255                 return(NULL);
01256         }
01257         return(r);
01258     }
01259     cuddRef(t);
01260 
01261     if (!Cudd_IsConstant(Cnv)) {
01262         e = cuddAddConstrainRecur(dd, Fnv, Cnv);
01263         if (e == NULL) {
01264             Cudd_RecursiveDeref(dd, t);
01265             return(NULL);
01266         }
01267     } else if (Cnv == one) {
01268         e = Fnv;
01269     } else {            /* Cnv == zero: return Fv @ Cv previously computed */
01270         cuddDeref(t);
01271         return(t);
01272     }
01273     cuddRef(e);
01274 
01275     r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
01276     if (r == NULL) {
01277         Cudd_RecursiveDeref(dd, e);
01278         Cudd_RecursiveDeref(dd, t);
01279         return(NULL);
01280     }
01281     cuddDeref(t);
01282     cuddDeref(e);
01283 
01284     cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r);
01285     return(r);
01286 
01287 } /* end of cuddAddConstrainRecur */

DdNode* cuddAddExistAbstractRecur ( DdManager manager,
DdNode f,
DdNode cube 
)

AutomaticStart

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

Synopsis [Performs the recursive step of Cudd_addExistAbstract.]

Description [Performs the recursive step of Cudd_addExistAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 252 of file cuddAddAbs.c.

00256 {
00257     DdNode      *T, *E, *res, *res1, *res2, *zero;
00258 
00259     statLine(manager);
00260     zero = DD_ZERO(manager);
00261 
00262     /* Cube is guaranteed to be a cube at this point. */        
00263     if (f == zero || cuddIsConstant(cube)) {  
00264         return(f);
00265     }
00266 
00267     /* Abstract a variable that does not appear in f => multiply by 2. */
00268     if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
00269         res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube));
00270         if (res1 == NULL) return(NULL);
00271         cuddRef(res1);
00272         /* Use the "internal" procedure to be alerted in case of
00273         ** dynamic reordering. If dynamic reordering occurs, we
00274         ** have to abort the entire abstraction.
00275         */
00276         res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two);
00277         if (res == NULL) {
00278             Cudd_RecursiveDeref(manager,res1);
00279             return(NULL);
00280         }
00281         cuddRef(res);
00282         Cudd_RecursiveDeref(manager,res1);
00283         cuddDeref(res);
00284         return(res);
00285     }
00286 
00287     if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) {
00288         return(res);
00289     }
00290 
00291     T = cuddT(f);
00292     E = cuddE(f);
00293 
00294     /* If the two indices are the same, so are their levels. */
00295     if (f->index == cube->index) {
00296         res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube));
00297         if (res1 == NULL) return(NULL);
00298         cuddRef(res1);
00299         res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube));
00300         if (res2 == NULL) {
00301             Cudd_RecursiveDeref(manager,res1);
00302             return(NULL);
00303         }
00304         cuddRef(res2);
00305         res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2);
00306         if (res == NULL) {
00307             Cudd_RecursiveDeref(manager,res1);
00308             Cudd_RecursiveDeref(manager,res2);
00309             return(NULL);
00310         }
00311         cuddRef(res);
00312         Cudd_RecursiveDeref(manager,res1);
00313         Cudd_RecursiveDeref(manager,res2);
00314         cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
00315         cuddDeref(res);
00316         return(res);
00317     } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
00318         res1 = cuddAddExistAbstractRecur(manager, T, cube);
00319         if (res1 == NULL) return(NULL);
00320         cuddRef(res1);
00321         res2 = cuddAddExistAbstractRecur(manager, E, cube);
00322         if (res2 == NULL) {
00323             Cudd_RecursiveDeref(manager,res1);
00324             return(NULL);
00325         }
00326         cuddRef(res2);
00327         res = (res1 == res2) ? res1 :
00328             cuddUniqueInter(manager, (int) f->index, res1, res2);
00329         if (res == NULL) {
00330             Cudd_RecursiveDeref(manager,res1);
00331             Cudd_RecursiveDeref(manager,res2);
00332             return(NULL);
00333         }
00334         cuddDeref(res1);
00335         cuddDeref(res2);
00336         cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
00337         return(res);
00338     }       
00339 
00340 } /* end of cuddAddExistAbstractRecur */

DdNode* cuddAddIteRecur ( DdManager dd,
DdNode f,
DdNode g,
DdNode h 
)

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

Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).]

Description [Implements the recursive step of Cudd_addIte(f,g,h). Returns a pointer to the resulting ADD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_addIte]

Definition at line 441 of file cuddAddIte.c.

00446 {
00447     DdNode *one,*zero;
00448     DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e;
00449     unsigned int topf,topg,toph,v;
00450     int index;
00451 
00452     statLine(dd);
00453     /* Trivial cases. */
00454 
00455     /* One variable cases. */
00456     if (f == (one = DD_ONE(dd))) {      /* ITE(1,G,H) = G */
00457         return(g);
00458     }
00459     if (f == (zero = DD_ZERO(dd))) {    /* ITE(0,G,H) = H */
00460         return(h);
00461     }
00462 
00463     /* From now on, f is known to not be a constant. */
00464     addVarToConst(f,&g,&h,one,zero);
00465 
00466     /* Check remaining one variable cases. */
00467     if (g == h) {                       /* ITE(F,G,G) = G */
00468         return(g);
00469     }
00470 
00471     if (g == one) {                     /* ITE(F,1,0) = F */
00472         if (h == zero) return(f);
00473     }
00474 
00475     topf = cuddI(dd,f->index);
00476     topg = cuddI(dd,g->index);
00477     toph = cuddI(dd,h->index);
00478     v = ddMin(topg,toph);
00479 
00480     /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */
00481     if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
00482         r = cuddUniqueInter(dd,(int)f->index,g,h);
00483         return(r);
00484     }
00485     if (topf < v && cuddT(f) == zero && cuddE(f) == one) {
00486         r = cuddUniqueInter(dd,(int)f->index,h,g);
00487         return(r);
00488     }
00489 
00490     /* Check cache. */
00491     r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h);
00492     if (r != NULL) {
00493         return(r);
00494     }
00495 
00496     /* Compute cofactors. */
00497     if (topf <= v) {
00498         v = ddMin(topf,v);      /* v = top_var(F,G,H) */
00499         index = f->index;
00500         Fv = cuddT(f); Fnv = cuddE(f);
00501     } else {
00502         Fv = Fnv = f;
00503     }
00504     if (topg == v) {
00505         index = g->index;
00506         Gv = cuddT(g); Gnv = cuddE(g);
00507     } else {
00508         Gv = Gnv = g;
00509     }
00510     if (toph == v) {
00511         index = h->index;
00512         Hv = cuddT(h); Hnv = cuddE(h);
00513     } else {
00514         Hv = Hnv = h;
00515     }
00516     
00517     /* Recursive step. */
00518     t = cuddAddIteRecur(dd,Fv,Gv,Hv);
00519     if (t == NULL) return(NULL);
00520     cuddRef(t);
00521 
00522     e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv);
00523     if (e == NULL) {
00524         Cudd_RecursiveDeref(dd,t);
00525         return(NULL);
00526     }
00527     cuddRef(e);
00528 
00529     r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
00530     if (r == NULL) {
00531         Cudd_RecursiveDeref(dd,t);
00532         Cudd_RecursiveDeref(dd,e);
00533         return(NULL);
00534     }
00535     cuddDeref(t);
00536     cuddDeref(e);
00537 
00538     cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r);
00539 
00540     return(r);
00541 
00542 } /* end of cuddAddIteRecur */

DdNode* cuddAddMonadicApplyRecur ( DdManager dd,
DdNode *(*)(DdManager *, DdNode *)  op,
DdNode f 
)
DdNode* cuddAddNegateRecur ( DdManager dd,
DdNode f 
)

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

Synopsis [Implements the recursive step of Cudd_addNegate.]

Description [Implements the recursive step of Cudd_addNegate. Returns a pointer to the result.]

SideEffects [None]

Definition at line 176 of file cuddAddNeg.c.

00179 {
00180     DdNode *res,
00181             *fv, *fvn,
00182             *T, *E;
00183 
00184     statLine(dd);
00185     /* Check terminal cases. */
00186     if (cuddIsConstant(f)) {
00187         res = cuddUniqueConst(dd,-cuddV(f));
00188         return(res);
00189     }
00190 
00191     /* Check cache */
00192     res = cuddCacheLookup1(dd,Cudd_addNegate,f);
00193     if (res != NULL) return(res);
00194 
00195     /* Recursive Step */
00196     fv = cuddT(f);
00197     fvn = cuddE(f);
00198     T = cuddAddNegateRecur(dd,fv);
00199     if (T == NULL) return(NULL);
00200     cuddRef(T);
00201 
00202     E = cuddAddNegateRecur(dd,fvn);
00203     if (E == NULL) {
00204         Cudd_RecursiveDeref(dd,T);
00205         return(NULL);
00206     }
00207     cuddRef(E);
00208     res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
00209     if (res == NULL) {
00210         Cudd_RecursiveDeref(dd, T);
00211         Cudd_RecursiveDeref(dd, E);
00212         return(NULL);
00213     }
00214     cuddDeref(T);
00215     cuddDeref(E);
00216 
00217     /* Store result. */
00218     cuddCacheInsert1(dd,Cudd_addNegate,f,res);
00219 
00220     return(res);
00221 
00222 } /* end of cuddAddNegateRecur */

DdNode* cuddAddOrAbstractRecur ( DdManager manager,
DdNode f,
DdNode cube 
)

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

Synopsis [Performs the recursive step of Cudd_addOrAbstract.]

Description [Performs the recursive step of Cudd_addOrAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 465 of file cuddAddAbs.c.

00469 {
00470     DdNode      *T, *E, *res, *res1, *res2, *one;
00471 
00472     statLine(manager);
00473     one = DD_ONE(manager);
00474 
00475     /* Cube is guaranteed to be a cube at this point. */
00476     if (cuddIsConstant(f) || cube == one) {  
00477         return(f);
00478     }
00479 
00480     /* Abstract a variable that does not appear in f. */
00481     if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
00482         res = cuddAddOrAbstractRecur(manager, f, cuddT(cube));
00483         return(res);
00484     }
00485 
00486     if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) {
00487         return(res);
00488     }
00489 
00490     T = cuddT(f);
00491     E = cuddE(f);
00492 
00493     /* If the two indices are the same, so are their levels. */
00494     if (f->index == cube->index) {
00495         res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube));
00496         if (res1 == NULL) return(NULL);
00497         cuddRef(res1);
00498         if (res1 != one) {
00499             res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube));
00500             if (res2 == NULL) {
00501                 Cudd_RecursiveDeref(manager,res1);
00502                 return(NULL);
00503             }
00504             cuddRef(res2);
00505             res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2);
00506             if (res == NULL) {
00507                 Cudd_RecursiveDeref(manager,res1);
00508                 Cudd_RecursiveDeref(manager,res2);
00509                 return(NULL);
00510             }
00511             cuddRef(res);
00512             Cudd_RecursiveDeref(manager,res1);
00513             Cudd_RecursiveDeref(manager,res2);
00514         } else {
00515             res = res1;
00516         }
00517         cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
00518         cuddDeref(res);
00519         return(res);
00520     } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
00521         res1 = cuddAddOrAbstractRecur(manager, T, cube);
00522         if (res1 == NULL) return(NULL);
00523         cuddRef(res1);
00524         res2 = cuddAddOrAbstractRecur(manager, E, cube);
00525         if (res2 == NULL) {
00526             Cudd_RecursiveDeref(manager,res1);
00527             return(NULL);
00528         }
00529         cuddRef(res2);
00530         res = (res1 == res2) ? res1 :
00531             cuddUniqueInter(manager, (int) f->index, res1, res2);
00532         if (res == NULL) {
00533             Cudd_RecursiveDeref(manager,res1);
00534             Cudd_RecursiveDeref(manager,res2);
00535             return(NULL);
00536         }
00537         cuddDeref(res1);
00538         cuddDeref(res2);
00539         cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
00540         return(res);
00541     }
00542 
00543 } /* end of cuddAddOrAbstractRecur */

DdNode* cuddAddRestrictRecur ( DdManager dd,
DdNode f,
DdNode c 
)

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

Synopsis [Performs the recursive step of Cudd_addRestrict.]

Description [Performs the recursive step of Cudd_addRestrict. Returns the restricted ADD if successful; otherwise NULL.]

SideEffects [None]

SeeAlso [Cudd_addRestrict]

Definition at line 1303 of file cuddGenCof.c.

01307 {
01308     DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
01309     unsigned int topf, topc;
01310     int          index;
01311 
01312     statLine(dd);
01313     one = DD_ONE(dd);
01314     zero = DD_ZERO(dd);
01315 
01316     /* Trivial cases */
01317     if (c == one)               return(f);
01318     if (c == zero)              return(zero);
01319     if (Cudd_IsConstant(f))     return(f);
01320     if (f == c)                 return(one);
01321 
01322     /* Now f and c are non-constant. */
01323 
01324     /* Check the cache. */
01325     r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c);
01326     if (r != NULL) {
01327         return(r);
01328     }
01329 
01330     topf = dd->perm[f->index];
01331     topc = dd->perm[c->index];
01332 
01333     if (topc < topf) {  /* abstract top variable from c */
01334         DdNode *d, *s1, *s2;
01335 
01336         /* Find cofactors of c. */
01337         s1 = cuddT(c);
01338         s2 = cuddE(c);
01339         /* Take the OR by applying DeMorgan. */
01340         d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2);
01341         if (d == NULL) return(NULL);
01342         cuddRef(d);
01343         r = cuddAddRestrictRecur(dd, f, d);
01344         if (r == NULL) {
01345             Cudd_RecursiveDeref(dd, d);
01346             return(NULL);
01347         }
01348         cuddRef(r);
01349         Cudd_RecursiveDeref(dd, d);
01350         cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
01351         cuddDeref(r);
01352         return(r);
01353     }
01354 
01355     /* Recursive step. Here topf <= topc. */
01356     index = f->index;
01357     Fv = cuddT(f); Fnv = cuddE(f);
01358     if (topc == topf) {
01359         Cv = cuddT(c); Cnv = cuddE(c);
01360     } else {
01361         Cv = Cnv = c;
01362     }
01363 
01364     if (!Cudd_IsConstant(Cv)) {
01365         t = cuddAddRestrictRecur(dd, Fv, Cv);
01366         if (t == NULL) return(NULL);
01367     } else if (Cv == one) {
01368         t = Fv;
01369     } else {            /* Cv == zero: return(Fnv @ Cnv) */
01370         if (Cnv == one) {
01371             r = Fnv;
01372         } else {
01373             r = cuddAddRestrictRecur(dd, Fnv, Cnv);
01374             if (r == NULL) return(NULL);
01375         }
01376         return(r);
01377     }
01378     cuddRef(t);
01379 
01380     if (!Cudd_IsConstant(Cnv)) {
01381         e = cuddAddRestrictRecur(dd, Fnv, Cnv);
01382         if (e == NULL) {
01383             Cudd_RecursiveDeref(dd, t);
01384             return(NULL);
01385         }
01386     } else if (Cnv == one) {
01387         e = Fnv;
01388     } else {            /* Cnv == zero: return (Fv @ Cv) previously computed */
01389         cuddDeref(t);
01390         return(t);
01391     }
01392     cuddRef(e);
01393 
01394     r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
01395     if (r == NULL) {
01396         Cudd_RecursiveDeref(dd, e);
01397         Cudd_RecursiveDeref(dd, t);
01398         return(NULL);
01399     }
01400     cuddDeref(t);
01401     cuddDeref(e);
01402 
01403     cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
01404     return(r);
01405 
01406 } /* end of cuddAddRestrictRecur */

DdNode* cuddAddRoundOffRecur ( DdManager dd,
DdNode f,
double  trunc 
)

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

Synopsis [Implements the recursive step of Cudd_addRoundOff.]

Description [Implements the recursive step of Cudd_addRoundOff. Returns a pointer to the result.]

SideEffects [None]

Definition at line 236 of file cuddAddNeg.c.

00240 {
00241 
00242     DdNode *res, *fv, *fvn, *T, *E;
00243     double n;
00244     DD_CTFP1 cacheOp;
00245 
00246     statLine(dd);
00247     if (cuddIsConstant(f)) {
00248         n = ceil(cuddV(f)*trunc)/trunc;
00249         res = cuddUniqueConst(dd,n);
00250         return(res);
00251     }
00252     cacheOp = (DD_CTFP1) Cudd_addRoundOff;
00253     res = cuddCacheLookup1(dd,cacheOp,f);
00254     if (res != NULL) {
00255         return(res);
00256     }
00257     /* Recursive Step */
00258     fv = cuddT(f);
00259     fvn = cuddE(f);
00260     T = cuddAddRoundOffRecur(dd,fv,trunc);
00261     if (T == NULL) {
00262        return(NULL);
00263     }
00264     cuddRef(T);
00265     E = cuddAddRoundOffRecur(dd,fvn,trunc);
00266     if (E == NULL) {
00267         Cudd_RecursiveDeref(dd,T);
00268         return(NULL);
00269     }
00270     cuddRef(E);
00271     res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
00272     if (res == NULL) {
00273         Cudd_RecursiveDeref(dd,T);
00274         Cudd_RecursiveDeref(dd,E);
00275         return(NULL);
00276     }
00277     cuddDeref(T);
00278     cuddDeref(E);
00279 
00280     /* Store result. */
00281     cuddCacheInsert1(dd,cacheOp,f,res);
00282     return(res);
00283 
00284 } /* end of cuddAddRoundOffRecur */

DdNode* cuddAddScalarInverseRecur ( DdManager dd,
DdNode f,
DdNode epsilon 
)

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

Synopsis [Performs the recursive step of addScalarInverse.]

Description [Returns a pointer to the resulting ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered.]

SideEffects [None]

Definition at line 152 of file cuddAddInv.c.

00156 {
00157     DdNode *t, *e, *res;
00158     CUDD_VALUE_TYPE value;
00159 
00160     statLine(dd);
00161     if (cuddIsConstant(f)) {
00162         if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL);
00163         value = 1.0 / cuddV(f);
00164         res = cuddUniqueConst(dd,value);
00165         return(res);
00166     }
00167 
00168     res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon);
00169     if (res != NULL) return(res);
00170 
00171     t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon);
00172     if (t == NULL) return(NULL);
00173     cuddRef(t);
00174 
00175     e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon);
00176     if (e == NULL) {
00177         Cudd_RecursiveDeref(dd, t);
00178         return(NULL);
00179     }
00180     cuddRef(e);
00181 
00182     res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
00183     if (res == NULL) {
00184         Cudd_RecursiveDeref(dd, t);
00185         Cudd_RecursiveDeref(dd, e);
00186         return(NULL);
00187     }
00188     cuddDeref(t);
00189     cuddDeref(e);
00190 
00191     cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res);
00192 
00193     return(res);
00194 
00195 } /* end of cuddAddScalarInverseRecur */

DdNode* cuddAddUnivAbstractRecur ( DdManager manager,
DdNode f,
DdNode cube 
)

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

Synopsis [Performs the recursive step of Cudd_addUnivAbstract.]

Description [Performs the recursive step of Cudd_addUnivAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 357 of file cuddAddAbs.c.

00361 {
00362     DdNode      *T, *E, *res, *res1, *res2, *one, *zero;
00363 
00364     statLine(manager);
00365     one = DD_ONE(manager);
00366     zero = DD_ZERO(manager);
00367 
00368     /* Cube is guaranteed to be a cube at this point.
00369     ** zero and one are the only constatnts c such that c*c=c.
00370     */
00371     if (f == zero || f == one || cube == one) {  
00372         return(f);
00373     }
00374 
00375     /* Abstract a variable that does not appear in f. */
00376     if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
00377         res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube));
00378         if (res1 == NULL) return(NULL);
00379         cuddRef(res1);
00380         /* Use the "internal" procedure to be alerted in case of
00381         ** dynamic reordering. If dynamic reordering occurs, we
00382         ** have to abort the entire abstraction.
00383         */
00384         res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1);
00385         if (res == NULL) {
00386             Cudd_RecursiveDeref(manager,res1);
00387             return(NULL);
00388         }
00389         cuddRef(res);
00390         Cudd_RecursiveDeref(manager,res1);
00391         cuddDeref(res);
00392         return(res);
00393     }
00394 
00395     if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) {
00396         return(res);
00397     }
00398 
00399     T = cuddT(f);
00400     E = cuddE(f);
00401 
00402     /* If the two indices are the same, so are their levels. */
00403     if (f->index == cube->index) {
00404         res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube));
00405         if (res1 == NULL) return(NULL);
00406         cuddRef(res1);
00407         res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube));
00408         if (res2 == NULL) {
00409             Cudd_RecursiveDeref(manager,res1);
00410             return(NULL);
00411         }
00412         cuddRef(res2);
00413         res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2);
00414         if (res == NULL) {
00415             Cudd_RecursiveDeref(manager,res1);
00416             Cudd_RecursiveDeref(manager,res2);
00417             return(NULL);
00418         }
00419         cuddRef(res);
00420         Cudd_RecursiveDeref(manager,res1);
00421         Cudd_RecursiveDeref(manager,res2);
00422         cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
00423         cuddDeref(res);
00424         return(res);
00425     } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
00426         res1 = cuddAddUnivAbstractRecur(manager, T, cube);
00427         if (res1 == NULL) return(NULL);
00428         cuddRef(res1);
00429         res2 = cuddAddUnivAbstractRecur(manager, E, cube);
00430         if (res2 == NULL) {
00431             Cudd_RecursiveDeref(manager,res1);
00432             return(NULL);
00433         }
00434         cuddRef(res2);
00435         res = (res1 == res2) ? res1 :
00436             cuddUniqueInter(manager, (int) f->index, res1, res2);
00437         if (res == NULL) {
00438             Cudd_RecursiveDeref(manager,res1);
00439             Cudd_RecursiveDeref(manager,res2);
00440             return(NULL);
00441         }
00442         cuddDeref(res1);
00443         cuddDeref(res2);
00444         cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
00445         return(res);
00446     }
00447 
00448 } /* end of cuddAddUnivAbstractRecur */

DdNode* cuddAllocNode ( DdManager unique  ) 

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

Synopsis [Fast storage allocation for DdNodes in the table.]

Description [Fast storage allocation for DdNodes in the table. The first 4 bytes of a chunk contain a pointer to the next block; the rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to a new node if successful; NULL is memory is full.]

SideEffects [None]

SeeAlso [cuddDynamicAllocNode]

Definition at line 231 of file cuddTable.c.

00233 {
00234     int i;
00235     DdNodePtr *mem;
00236     DdNode *list, *node;
00237     extern DD_OOMFP MMoutOfMemory;
00238     DD_OOMFP saveHandler;
00239 
00240     if (unique->nextFree == NULL) {     /* free list is empty */
00241         /* Check for exceeded limits. */
00242         if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) >
00243             unique->maxLive) {
00244             unique->errorCode = CUDD_TOO_MANY_NODES;
00245             return(NULL);
00246         }
00247         if (unique->stash == NULL || unique->memused > unique->maxmemhard) {
00248             (void) cuddGarbageCollect(unique,1);
00249             mem = NULL;
00250         }
00251         if (unique->nextFree == NULL) {
00252             if (unique->memused > unique->maxmemhard) {
00253                 unique->errorCode = CUDD_MAX_MEM_EXCEEDED;
00254                 return(NULL);
00255             }
00256             /* Try to allocate a new block. */
00257             saveHandler = MMoutOfMemory;
00258             MMoutOfMemory = Cudd_OutOfMem;
00259             mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
00260             MMoutOfMemory = saveHandler;
00261             if (mem == NULL) {
00262                 /* No more memory: Try collecting garbage. If this succeeds,
00263                 ** we end up with mem still NULL, but unique->nextFree !=
00264                 ** NULL. */
00265                 if (cuddGarbageCollect(unique,1) == 0) {
00266                     /* Last resort: Free the memory stashed away, if there
00267                     ** any. If this succeeeds, mem != NULL and
00268                     ** unique->nextFree still NULL. */
00269                     if (unique->stash != NULL) {
00270                         FREE(unique->stash);
00271                         unique->stash = NULL;
00272                         /* Inhibit resizing of tables. */
00273                         cuddSlowTableGrowth(unique);
00274                         /* Now try again. */
00275                         mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
00276                     }
00277                     if (mem == NULL) {
00278                         /* Out of luck. Call the default handler to do
00279                         ** whatever it specifies for a failed malloc.
00280                         ** If this handler returns, then set error code,
00281                         ** print warning, and return. */
00282                         (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
00283                         unique->errorCode = CUDD_MEMORY_OUT;
00284 #ifdef DD_VERBOSE
00285                         (void) fprintf(unique->err,
00286                                        "cuddAllocNode: out of memory");
00287                         (void) fprintf(unique->err, "Memory in use = %lu\n",
00288                                        unique->memused);
00289 #endif
00290                         return(NULL);
00291                     }
00292                 }
00293             }
00294             if (mem != NULL) {  /* successful allocation; slice memory */
00295                 ptruint offset;
00296                 unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
00297                 mem[0] = (DdNodePtr) unique->memoryList;
00298                 unique->memoryList = mem;
00299 
00300                 /* Here we rely on the fact that a DdNode is as large
00301                 ** as 4 pointers.  */
00302                 offset = (ptruint) mem & (sizeof(DdNode) - 1);
00303                 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
00304                 assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0);
00305                 list = (DdNode *) mem;
00306 
00307                 i = 1;
00308                 do {
00309                     list[i - 1].ref = 0;
00310                     list[i - 1].next = &list[i];
00311                 } while (++i < DD_MEM_CHUNK);
00312 
00313                 list[DD_MEM_CHUNK-1].ref = 0;
00314                 list[DD_MEM_CHUNK-1].next = NULL;
00315 
00316                 unique->nextFree = &list[0];
00317             }
00318         }
00319     }
00320     unique->allocated++;
00321     node = unique->nextFree;
00322     unique->nextFree = node->next;
00323     return(node);
00324 
00325 } /* end of cuddAllocNode */

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

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

Synopsis [Get new variable-order by simulated annealing algorithm.]

Description [Get x, y by random selection. Choose either exchange or jump randomly. In case of jump, choose between jump_up and jump_down randomly. Do exchange or jump and get optimal case. Loop until there is no improvement or temperature reaches minimum. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 154 of file cuddAnneal.c.

00158 {
00159     int         nvars;
00160     int         size;
00161     int         x,y;
00162     int         result;
00163     int         c1, c2, c3, c4;
00164     int         BestCost;
00165     int         *BestOrder;
00166     double      NewTemp, temp;
00167     double      rand1;
00168     int         innerloop, maxGen;
00169     int         ecount, ucount, dcount;
00170    
00171     nvars = upper - lower + 1;
00172 
00173     result = cuddSifting(table,lower,upper);
00174 #ifdef DD_STATS
00175     (void) fprintf(table->out,"\n");
00176 #endif
00177     if (result == 0) return(0);
00178 
00179     size = table->keys - table->isolated;
00180 
00181     /* Keep track of the best order. */
00182     BestCost = size;
00183     BestOrder = ALLOC(int,nvars);
00184     if (BestOrder == NULL) {
00185         table->errorCode = CUDD_MEMORY_OUT;
00186         return(0);
00187     }
00188     copyOrder(table,BestOrder,lower,upper);
00189 
00190     temp = BETA * size;
00191     maxGen = (int) (MAXGEN_RATIO * nvars);
00192 
00193     c1 = size + 10;
00194     c2 = c1 + 10;
00195     c3 = size;
00196     c4 = c2 + 10;
00197     ecount = ucount = dcount = 0;
00198  
00199     while (!stopping_criterion(c1, c2, c3, c4, temp)) {
00200 #ifdef DD_STATS
00201         (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t",
00202                        temp,size,maxGen);
00203         tosses = acceptances = 0;
00204 #endif
00205         for (innerloop = 0; innerloop < maxGen; innerloop++) {
00206             /* Choose x, y  randomly. */
00207             x = (int) Cudd_Random() % nvars;
00208             do {
00209                 y = (int) Cudd_Random() % nvars;
00210             } while (x == y);
00211             x += lower;
00212             y += lower;
00213             if (x > y) {
00214                 int tmp = x;
00215                 x = y;
00216                 y = tmp;
00217             }
00218 
00219             /* Choose move with roulette wheel. */
00220             rand1 = random_generator();
00221             if (rand1 < EXC_PROB) {
00222                 result = ddExchange(table,x,y,temp);       /* exchange */
00223                 ecount++;
00224 #if 0
00225                 (void) fprintf(table->out,
00226                                "Exchange of %d and %d: size = %d\n",
00227                                x,y,table->keys - table->isolated);
00228 #endif
00229             } else if (rand1 < EXC_PROB + JUMP_UP_PROB) {
00230                 result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */
00231                 ucount++;
00232 #if 0
00233                 (void) fprintf(table->out,
00234                                "Jump up of %d to %d: size = %d\n",
00235                                y,x,table->keys - table->isolated);
00236 #endif
00237             } else {
00238                 result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */
00239                 dcount++;
00240 #if 0
00241                 (void) fprintf(table->out,
00242                                "Jump down of %d to %d: size = %d\n",
00243                                x,y,table->keys - table->isolated);
00244 #endif
00245             }
00246 
00247             if (!result) {
00248                 FREE(BestOrder);
00249                 return(0);
00250             }
00251 
00252             size = table->keys - table->isolated;       /* keep current size */
00253             if (size < BestCost) {                      /* update best order */
00254                 BestCost = size;
00255                 copyOrder(table,BestOrder,lower,upper);
00256             }
00257         }
00258         c1 = c2;
00259         c2 = c3;
00260         c3 = c4;
00261         c4 = size;
00262         NewTemp = ALPHA * temp;
00263         if (NewTemp >= 1.0) {
00264             maxGen = (int)(log(NewTemp) / log(temp) * maxGen);
00265         }
00266         temp = NewTemp;                 /* control variable */
00267 #ifdef DD_STATS
00268         (void) fprintf(table->out,"uphill = %d\taccepted = %d\n",
00269                        tosses,acceptances);
00270         fflush(table->out);
00271 #endif
00272     }
00273 
00274     result = restoreOrder(table,BestOrder,lower,upper);
00275     FREE(BestOrder);
00276     if (!result) return(0);
00277 #ifdef DD_STATS
00278     fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount);
00279     fprintf(table->out,"#:N_JUMPUP   %8d : total jumps up\n",ucount);
00280     fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount);
00281 #endif
00282     return(1);
00283 
00284 } /* end of cuddAnnealing */

int cuddBddAlignToZdd ( DdManager table  ) 

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

Synopsis [Reorders BDD variables according to the order of the ZDD variables.]

Description [Reorders BDD variables according to the order of the ZDD variables. This function can be called at the end of ZDD reordering to insure that the order of the BDD variables is consistent with the order of the ZDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M be the ratio of the two numbers. cuddBddAlignToZdd then considers the ZDD variables from M*i to (M+1)*i-1 as corresponding to BDD variable i. This function should be normally called from Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]

SideEffects [Changes the BDD variable order for all diagrams and performs garbage collection of the BDD unique table.]

SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap]

Definition at line 1242 of file cuddReorder.c.

01244 {
01245     int *invperm;               /* permutation array */
01246     int M;                      /* ratio of ZDD variables to BDD variables */
01247     int i;                      /* loop index */
01248     int result;                 /* return value */
01249 
01250     /* We assume that a ratio of 0 is OK. */
01251     if (table->size == 0)
01252         return(1);
01253 
01254     M = table->sizeZ / table->size;
01255     /* Check whether the number of ZDD variables is a multiple of the
01256     ** number of BDD variables.
01257     */
01258     if (M * table->size != table->sizeZ)
01259         return(0);
01260     /* Create and initialize the inverse permutation array. */
01261     invperm = ALLOC(int,table->size);
01262     if (invperm == NULL) {
01263         table->errorCode = CUDD_MEMORY_OUT;
01264         return(0);
01265     }
01266     for (i = 0; i < table->sizeZ; i += M) {
01267         int indexZ = table->invpermZ[i];
01268         int index  = indexZ / M;
01269         invperm[i / M] = index;
01270     }
01271     /* Eliminate dead nodes. Do not scan the cache again, because we
01272     ** assume that Cudd_zddReduceHeap has already cleared it.
01273     */
01274     cuddGarbageCollect(table,0);
01275 
01276     /* Initialize number of isolated projection functions. */
01277     table->isolated = 0;
01278     for (i = 0; i < table->size; i++) {
01279         if (table->vars[i]->ref == 1) table->isolated++;
01280     }
01281 
01282     /* Initialize the interaction matrix. */
01283     result = cuddInitInteract(table);
01284     if (result == 0) return(0);
01285 
01286     result = ddShuffle(table, invperm);
01287     FREE(invperm);
01288     /* Free interaction matrix. */
01289     FREE(table->interact);
01290     /* Fix the BDD variable group tree. */
01291     bddFixTree(table,table->tree);
01292     return(result);
01293 
01294 } /* end of cuddBddAlignToZdd */

DdNode* cuddBddAndAbstractRecur ( DdManager manager,
DdNode f,
DdNode g,
DdNode cube 
)

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

Synopsis [Takes the AND of two BDDs and simultaneously abstracts the variables in cube.]

Description [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddAndAbstract]

Definition at line 196 of file cuddAndAbs.c.

00201 {
00202     DdNode *F, *ft, *fe, *G, *gt, *ge;
00203     DdNode *one, *zero, *r, *t, *e;
00204     unsigned int topf, topg, topcube, top, index;
00205 
00206     statLine(manager);
00207     one = DD_ONE(manager);
00208     zero = Cudd_Not(one);
00209 
00210     /* Terminal cases. */
00211     if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
00212     if (f == one && g == one)   return(one);
00213 
00214     if (cube == one) {
00215         return(cuddBddAndRecur(manager, f, g));
00216     }
00217     if (f == one || f == g) {
00218         return(cuddBddExistAbstractRecur(manager, g, cube));
00219     }
00220     if (g == one) {
00221         return(cuddBddExistAbstractRecur(manager, f, cube));
00222     }
00223     /* At this point f, g, and cube are not constant. */
00224 
00225     if (f > g) { /* Try to increase cache efficiency. */
00226         DdNode *tmp = f;
00227         f = g;
00228         g = tmp;
00229     }
00230 
00231     /* Here we can skip the use of cuddI, because the operands are known
00232     ** to be non-constant.
00233     */
00234     F = Cudd_Regular(f);
00235     G = Cudd_Regular(g);
00236     topf = manager->perm[F->index];
00237     topg = manager->perm[G->index];
00238     top = ddMin(topf, topg);
00239     topcube = manager->perm[cube->index];
00240 
00241     while (topcube < top) {
00242         cube = cuddT(cube);
00243         if (cube == one) {
00244             return(cuddBddAndRecur(manager, f, g));
00245         }
00246         topcube = manager->perm[cube->index];
00247     }
00248     /* Now, topcube >= top. */
00249 
00250     /* Check cache. */
00251     if (F->ref != 1 || G->ref != 1) {
00252         r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
00253         if (r != NULL) {
00254             return(r);
00255         }
00256     }
00257 
00258     if (topf == top) {
00259         index = F->index;
00260         ft = cuddT(F);
00261         fe = cuddE(F);
00262         if (Cudd_IsComplement(f)) {
00263             ft = Cudd_Not(ft);
00264             fe = Cudd_Not(fe);
00265         }
00266     } else {
00267         index = G->index;
00268         ft = fe = f;
00269     }
00270 
00271     if (topg == top) {
00272         gt = cuddT(G);
00273         ge = cuddE(G);
00274         if (Cudd_IsComplement(g)) {
00275             gt = Cudd_Not(gt);
00276             ge = Cudd_Not(ge);
00277         }
00278     } else {
00279         gt = ge = g;
00280     }
00281 
00282     if (topcube == top) {       /* quantify */
00283         DdNode *Cube = cuddT(cube);
00284         t = cuddBddAndAbstractRecur(manager, ft, gt, Cube);
00285         if (t == NULL) return(NULL);
00286         /* Special case: 1 OR anything = 1. Hence, no need to compute
00287         ** the else branch if t is 1. Likewise t + t * anything == t.
00288         ** Notice that t == fe implies that fe does not depend on the
00289         ** variables in Cube. Likewise for t == ge.
00290         */
00291         if (t == one || t == fe || t == ge) {
00292             if (F->ref != 1 || G->ref != 1)
00293                 cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
00294                                 f, g, cube, t);
00295             return(t);
00296         }
00297         cuddRef(t);
00298         /* Special case: t + !t * anything == t + anything. */
00299         if (t == Cudd_Not(fe)) {
00300             e = cuddBddExistAbstractRecur(manager, ge, Cube);
00301         } else if (t == Cudd_Not(ge)) {
00302             e = cuddBddExistAbstractRecur(manager, fe, Cube);
00303         } else {
00304             e = cuddBddAndAbstractRecur(manager, fe, ge, Cube);
00305         }
00306         if (e == NULL) {
00307             Cudd_IterDerefBdd(manager, t);
00308             return(NULL);
00309         }
00310         if (t == e) {
00311             r = t;
00312             cuddDeref(t);
00313         } else {
00314             cuddRef(e);
00315             r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
00316             if (r == NULL) {
00317                 Cudd_IterDerefBdd(manager, t);
00318                 Cudd_IterDerefBdd(manager, e);
00319                 return(NULL);
00320             }
00321             r = Cudd_Not(r);
00322             cuddRef(r);
00323             Cudd_DelayedDerefBdd(manager, t);
00324             Cudd_DelayedDerefBdd(manager, e);
00325             cuddDeref(r);
00326         }
00327     } else {
00328         t = cuddBddAndAbstractRecur(manager, ft, gt, cube);
00329         if (t == NULL) return(NULL);
00330         cuddRef(t);
00331         e = cuddBddAndAbstractRecur(manager, fe, ge, cube);
00332         if (e == NULL) {
00333             Cudd_IterDerefBdd(manager, t);
00334             return(NULL);
00335         }
00336         if (t == e) {
00337             r = t;
00338             cuddDeref(t);
00339         } else {
00340             cuddRef(e);
00341             if (Cudd_IsComplement(t)) {
00342                 r = cuddUniqueInter(manager, (int) index,
00343                                     Cudd_Not(t), Cudd_Not(e));
00344                 if (r == NULL) {
00345                     Cudd_IterDerefBdd(manager, t);
00346                     Cudd_IterDerefBdd(manager, e);
00347                     return(NULL);
00348                 }
00349                 r = Cudd_Not(r);
00350             } else {
00351                 r = cuddUniqueInter(manager,(int)index,t,e);
00352                 if (r == NULL) {
00353                     Cudd_IterDerefBdd(manager, t);
00354                     Cudd_IterDerefBdd(manager, e);
00355                     return(NULL);
00356                 }
00357             }
00358             cuddDeref(e);
00359             cuddDeref(t);
00360         }
00361     }
00362 
00363     if (F->ref != 1 || G->ref != 1)
00364         cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
00365     return (r);
00366 
00367 } /* end of cuddBddAndAbstractRecur */

DdNode* cuddBddAndRecur ( DdManager manager,
DdNode f,
DdNode g 
)

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

Synopsis [Implements the recursive step of Cudd_bddAnd.]

Description [Implements the recursive step of Cudd_bddAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddAnd]

Definition at line 882 of file cuddBddIte.c.

00886 {
00887     DdNode *F, *fv, *fnv, *G, *gv, *gnv;
00888     DdNode *one, *r, *t, *e;
00889     unsigned int topf, topg, index;
00890 
00891     statLine(manager);
00892     one = DD_ONE(manager);
00893 
00894     /* Terminal cases. */
00895     F = Cudd_Regular(f);
00896     G = Cudd_Regular(g);
00897     if (F == G) {
00898         if (f == g) return(f);
00899         else return(Cudd_Not(one));
00900     }
00901     if (F == one) {
00902         if (f == one) return(g);
00903         else return(f);
00904     }
00905     if (G == one) {
00906         if (g == one) return(f);
00907         else return(g);
00908     }
00909 
00910     /* At this point f and g are not constant. */
00911     if (f > g) { /* Try to increase cache efficiency. */
00912         DdNode *tmp = f;
00913         f = g;
00914         g = tmp;
00915         F = Cudd_Regular(f);
00916         G = Cudd_Regular(g);
00917     }
00918 
00919     /* Check cache. */
00920     if (F->ref != 1 || G->ref != 1) {
00921         r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
00922         if (r != NULL) return(r);
00923     }
00924 
00925     /* Here we can skip the use of cuddI, because the operands are known
00926     ** to be non-constant.
00927     */
00928     topf = manager->perm[F->index];
00929     topg = manager->perm[G->index];
00930 
00931     /* Compute cofactors. */
00932     if (topf <= topg) {
00933         index = F->index;
00934         fv = cuddT(F);
00935         fnv = cuddE(F);
00936         if (Cudd_IsComplement(f)) {
00937             fv = Cudd_Not(fv);
00938             fnv = Cudd_Not(fnv);
00939         }
00940     } else {
00941         index = G->index;
00942         fv = fnv = f;
00943     }
00944 
00945     if (topg <= topf) {
00946         gv = cuddT(G);
00947         gnv = cuddE(G);
00948         if (Cudd_IsComplement(g)) {
00949             gv = Cudd_Not(gv);
00950             gnv = Cudd_Not(gnv);
00951         }
00952     } else {
00953         gv = gnv = g;
00954     }
00955 
00956     t = cuddBddAndRecur(manager, fv, gv);
00957     if (t == NULL) return(NULL);
00958     cuddRef(t);
00959 
00960     e = cuddBddAndRecur(manager, fnv, gnv);
00961     if (e == NULL) {
00962         Cudd_IterDerefBdd(manager, t);
00963         return(NULL);
00964     }
00965     cuddRef(e);
00966 
00967     if (t == e) {
00968         r = t;
00969     } else {
00970         if (Cudd_IsComplement(t)) {
00971             r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
00972             if (r == NULL) {
00973                 Cudd_IterDerefBdd(manager, t);
00974                 Cudd_IterDerefBdd(manager, e);
00975                 return(NULL);
00976             }
00977             r = Cudd_Not(r);
00978         } else {
00979             r = cuddUniqueInter(manager,(int)index,t,e);
00980             if (r == NULL) {
00981                 Cudd_IterDerefBdd(manager, t);
00982                 Cudd_IterDerefBdd(manager, e);
00983                 return(NULL);
00984             }
00985         }
00986     }
00987     cuddDeref(e);
00988     cuddDeref(t);
00989     if (F->ref != 1 || G->ref != 1)
00990         cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
00991     return(r);
00992 
00993 } /* end of cuddBddAndRecur */

DdNode* cuddBddBooleanDiffRecur ( DdManager manager,
DdNode f,
DdNode var 
)

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

Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.]

Description [Performs the recursive steps of Cudd_bddBoleanDiff. Returns the BDD obtained by XORing the cofactors of f with respect to var if successful; NULL otherwise. Exploits the fact that dF/dx = dF'/dx.]

SideEffects [None]

SeeAlso []

Definition at line 630 of file cuddBddAbs.c.

00634 {
00635     DdNode *T, *E, *res, *res1, *res2;
00636 
00637     statLine(manager);
00638     if (cuddI(manager,f->index) > manager->perm[var->index]) {
00639         /* f does not depend on var. */
00640         return(Cudd_Not(DD_ONE(manager)));
00641     }
00642 
00643     /* From now on, f is non-constant. */
00644 
00645     /* If the two indices are the same, so are their levels. */
00646     if (f->index == var->index) {
00647         res = cuddBddXorRecur(manager, cuddT(f), cuddE(f));
00648         return(res);
00649     }
00650 
00651     /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */
00652 
00653     /* Check the cache. */
00654     res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var);
00655     if (res != NULL) {
00656         return(res);
00657     }
00658 
00659     /* Compute the cofactors of f. */
00660     T = cuddT(f); E = cuddE(f);
00661 
00662     res1 = cuddBddBooleanDiffRecur(manager, T, var);
00663     if (res1 == NULL) return(NULL);
00664     cuddRef(res1);
00665     res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var);
00666     if (res2 == NULL) {
00667         Cudd_IterDerefBdd(manager, res1);
00668         return(NULL);
00669     }
00670     cuddRef(res2);
00671     /* ITE takes care of possible complementation of res1 and of the
00672     ** case in which res1 == res2. */
00673     res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2);
00674     if (res == NULL) {
00675         Cudd_IterDerefBdd(manager, res1);
00676         Cudd_IterDerefBdd(manager, res2);
00677         return(NULL);
00678     }
00679     cuddDeref(res1);
00680     cuddDeref(res2);
00681     cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res);
00682     return(res);
00683 
00684 } /* end of cuddBddBooleanDiffRecur */

DdNode* cuddBddClippingAnd ( DdManager dd,
DdNode f,
DdNode g,
int  maxDepth,
int  direction 
)

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

Synopsis [Approximates the conjunction of two BDDs f and g.]

Description [Approximates the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.]

SideEffects [None]

SeeAlso [Cudd_bddClippingAnd]

Definition at line 197 of file cuddClip.c.

00203 {
00204     DdNode *res;
00205 
00206     res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction);
00207 
00208     return(res);
00209 
00210 } /* end of cuddBddClippingAnd */

DdNode* cuddBddClippingAndAbstract ( DdManager dd,
DdNode f,
DdNode g,
DdNode cube,
int  maxDepth,
int  direction 
)

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

Synopsis [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube.]

Description [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.]

SideEffects [None]

SeeAlso [Cudd_bddClippingAndAbstract]

Definition at line 229 of file cuddClip.c.

00236 {
00237     DdNode *res;
00238 
00239     res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction);
00240 
00241     return(res);
00242 
00243 } /* end of cuddBddClippingAndAbstract */

DdNode* cuddBddClosestCube ( DdManager dd,
DdNode f,
DdNode g,
CUDD_VALUE_TYPE  bound 
)

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

Synopsis [Performs the recursive step of Cudd_bddClosestCube.]

Description [Performs the recursive step of Cudd_bddClosestCube. Returns the cube if succesful; NULL otherwise. The procedure uses a four-way recursion to examine all four combinations of cofactors of f and g according to the following formula.

    H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
  

Bounding is based on the following observations.

  • If we already found two points at distance 0, there is no point in continuing. Furthermore,
  • If F == not(G) then the best we can hope for is a minimum distance of 1. If we have already found two points at distance 1, there is no point in continuing. (Indeed, H(F,G) == 1 in this case. We have to continue, though, to find the cube.)

The variable bound is set at the largest value of the distance that we are still interested in. Therefore, we desist when

    (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
  

If we were maximally aggressive in using the bound, we would always set the bound to the minimum distance seen thus far minus one. That is, we would maintain the invariant

    bound < minD,
  

except at the very beginning, when we have no value for minD.

However, we do not use bound < minD when examining the two negative cofactors, because we try to find a large cube at minimum distance. To do so, we try to find a cube in the negative cofactors at the same or smaller distance from the cube found in the positive cofactors.

When we compute H(ft,ge) and H(fe,gt) we know that we are going to add 1 to the result of the recursive call to account for the difference in the splitting variable. Therefore, we decrease the bound correspondingly.

Another important observation concerns the need of examining all four pairs of cofators only when both f and g depend on the top variable.

Suppose gt == ge == g. (That is, g does not depend on the top variable.) Then

    H(f,g) = min(H(ft,g), H(fe,g), H(ft,g)+1, H(fe,g)+1)
	   = min(H(ft,g), H(fe,g)) .
  

Therefore, under these circumstances, we skip the two "cross" cases.

An interesting feature of this function is the scheme used for caching the results in the global computed table. Since we have a cube and a distance, we combine them to form an ADD. The combination replaces the zero child of the top node of the cube with the negative of the distance. (The use of the negative is to avoid ambiguity with 1.) The degenerate cases (zero and one) are treated specially because the distance is known (0 for one, and infinity for zero).]

SideEffects [None]

SeeAlso [Cudd_bddClosestCube]

Definition at line 1642 of file cuddPriority.c.

01647 {
01648     DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee;
01649     DdNode *ctt, *cee, *cte, *cet;
01650     CUDD_VALUE_TYPE minD, dtt, dee, dte, det;
01651     DdNode *one = DD_ONE(dd);
01652     DdNode *lzero = Cudd_Not(one);
01653     DdNode *azero = DD_ZERO(dd);
01654     unsigned int topf, topg, index;
01655 
01656     statLine(dd);
01657     if (bound < (f == Cudd_Not(g))) return(azero);
01658     /* Terminal cases. */
01659     if (g == lzero || f == lzero) return(azero);
01660     if (f == one && g == one) return(one);
01661 
01662     /* Check cache. */
01663     F = Cudd_Regular(f);
01664     G = Cudd_Regular(g);
01665     if (F->ref != 1 || G->ref != 1) {
01666         res = cuddCacheLookup2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g);
01667         if (res != NULL) return(res);
01668     }
01669 
01670     topf = cuddI(dd,F->index);
01671     topg = cuddI(dd,G->index);
01672 
01673     /* Compute cofactors. */
01674     if (topf <= topg) {
01675         index = F->index;
01676         ft = cuddT(F);
01677         fe = cuddE(F);
01678         if (Cudd_IsComplement(f)) {
01679             ft = Cudd_Not(ft);
01680             fe = Cudd_Not(fe);
01681         }
01682     } else {
01683         index = G->index;
01684         ft = fe = f;
01685     }
01686 
01687     if (topg <= topf) {
01688         gt = cuddT(G);
01689         ge = cuddE(G);
01690         if (Cudd_IsComplement(g)) {
01691             gt = Cudd_Not(gt);
01692             ge = Cudd_Not(ge);
01693         }
01694     } else {
01695         gt = ge = g;
01696     }
01697 
01698     tt = cuddBddClosestCube(dd,ft,gt,bound);
01699     if (tt == NULL) return(NULL);
01700     cuddRef(tt);
01701     ctt = separateCube(dd,tt,&dtt);
01702     if (ctt == NULL) {
01703         Cudd_RecursiveDeref(dd, tt);
01704         return(NULL);
01705     }
01706     cuddRef(ctt);
01707     Cudd_RecursiveDeref(dd, tt);
01708     minD = dtt;
01709     bound = ddMin(bound,minD);
01710 
01711     ee = cuddBddClosestCube(dd,fe,ge,bound);
01712     if (ee == NULL) {
01713         Cudd_RecursiveDeref(dd, ctt);
01714         return(NULL);
01715     }
01716     cuddRef(ee);
01717     cee = separateCube(dd,ee,&dee);
01718     if (cee == NULL) {
01719         Cudd_RecursiveDeref(dd, ctt);
01720         Cudd_RecursiveDeref(dd, ee);
01721         return(NULL);
01722     }
01723     cuddRef(cee);
01724     Cudd_RecursiveDeref(dd, ee);
01725     minD = ddMin(dtt, dee);
01726     if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
01727 
01728     if (minD > 0 && topf == topg) {
01729         DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1);
01730         if (te == NULL) {
01731             Cudd_RecursiveDeref(dd, ctt);
01732             Cudd_RecursiveDeref(dd, cee);
01733             return(NULL);
01734         }
01735         cuddRef(te);
01736         cte = separateCube(dd,te,&dte);
01737         if (cte == NULL) {
01738             Cudd_RecursiveDeref(dd, ctt);
01739             Cudd_RecursiveDeref(dd, cee);
01740             Cudd_RecursiveDeref(dd, te);
01741             return(NULL);
01742         }
01743         cuddRef(cte);
01744         Cudd_RecursiveDeref(dd, te);
01745         dte += 1.0;
01746         minD = ddMin(minD, dte);
01747     } else {
01748         cte = azero;
01749         cuddRef(cte);
01750         dte = CUDD_CONST_INDEX + 1.0;
01751     }
01752     if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
01753 
01754     if (minD > 0 && topf == topg) {
01755         DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1);
01756         if (et == NULL) {
01757             Cudd_RecursiveDeref(dd, ctt);
01758             Cudd_RecursiveDeref(dd, cee);
01759             Cudd_RecursiveDeref(dd, cte);
01760             return(NULL);
01761         }
01762         cuddRef(et);
01763         cet = separateCube(dd,et,&det);
01764         if (cet == NULL) {
01765             Cudd_RecursiveDeref(dd, ctt);
01766             Cudd_RecursiveDeref(dd, cee);
01767             Cudd_RecursiveDeref(dd, cte);
01768             Cudd_RecursiveDeref(dd, et);
01769             return(NULL);
01770         }
01771         cuddRef(cet);
01772         Cudd_RecursiveDeref(dd, et);
01773         det += 1.0;
01774         minD = ddMin(minD, det);
01775     } else {
01776         cet = azero;
01777         cuddRef(cet);
01778         det = CUDD_CONST_INDEX + 1.0;
01779     }
01780 
01781     if (minD == dtt) {
01782         if (dtt == dee && ctt == cee) {
01783             res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt);
01784         } else {
01785             res = createResult(dd,index,1,ctt,dtt);
01786         }
01787     } else if (minD == dee) {
01788         res = createResult(dd,index,0,cee,dee);
01789     } else if (minD == dte) {
01790 #ifdef DD_DEBUG
01791         assert(topf == topg);
01792 #endif
01793         res = createResult(dd,index,1,cte,dte);
01794     } else {
01795 #ifdef DD_DEBUG
01796         assert(topf == topg);
01797 #endif
01798         res = createResult(dd,index,0,cet,det);
01799     }
01800     if (res == NULL) {
01801         Cudd_RecursiveDeref(dd, ctt);
01802         Cudd_RecursiveDeref(dd, cee);
01803         Cudd_RecursiveDeref(dd, cte);
01804         Cudd_RecursiveDeref(dd, cet);
01805         return(NULL);
01806     }
01807     cuddRef(res);
01808     Cudd_RecursiveDeref(dd, ctt);
01809     Cudd_RecursiveDeref(dd, cee);
01810     Cudd_RecursiveDeref(dd, cte);
01811     Cudd_RecursiveDeref(dd, cet);
01812 
01813     /* Only cache results that are different from azero to avoid
01814     ** storing results that depend on the value of the bound. */
01815     if ((F->ref != 1 || G->ref != 1) && res != azero)
01816         cuddCacheInsert2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g, res);
01817 
01818     cuddDeref(res);
01819     return(res);
01820 
01821 } /* end of cuddBddClosestCube */

DdNode* cuddBddComposeRecur ( DdManager dd,
DdNode f,
DdNode g,
DdNode proj 
)

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

Synopsis [Performs the recursive step of Cudd_bddCompose.]

Description [Performs the recursive step of Cudd_bddCompose. Exploits the fact that the composition of f' with g produces the complement of the composition of f with g to better utilize the cache. Returns the composed BDD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddCompose]

Definition at line 846 of file cuddCompose.c.

00851 {
00852     DdNode      *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e;
00853     unsigned int v, topf, topg, topindex;
00854     int         comple;
00855 
00856     statLine(dd);
00857     v = dd->perm[proj->index];
00858     F = Cudd_Regular(f);
00859     topf = cuddI(dd,F->index);
00860 
00861     /* Terminal case. Subsumes the test for constant f. */
00862     if (topf > v) return(f);
00863 
00864     /* We solve the problem for a regular pointer, and then complement
00865     ** the result if the pointer was originally complemented.
00866     */
00867     comple = Cudd_IsComplement(f);
00868 
00869     /* Check cache. */
00870     r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj);
00871     if (r != NULL) {
00872         return(Cudd_NotCond(r,comple));
00873     }
00874 
00875     if (topf == v) {
00876         /* Compose. */
00877         f1 = cuddT(F);
00878         f0 = cuddE(F);
00879         r = cuddBddIteRecur(dd, g, f1, f0);
00880         if (r == NULL) return(NULL);
00881     } else {
00882         /* Compute cofactors of f and g. Remember the index of the top
00883         ** variable.
00884         */
00885         G = Cudd_Regular(g);
00886         topg = cuddI(dd,G->index);
00887         if (topf > topg) {
00888             topindex = G->index;
00889             f1 = f0 = F;
00890         } else {
00891             topindex = F->index;
00892             f1 = cuddT(F);
00893             f0 = cuddE(F);
00894         }
00895         if (topg > topf) {
00896             g1 = g0 = g;
00897         } else {
00898             g1 = cuddT(G);
00899             g0 = cuddE(G);
00900             if (g != G) {
00901                 g1 = Cudd_Not(g1);
00902                 g0 = Cudd_Not(g0);
00903             }
00904         }
00905         /* Recursive step. */
00906         t = cuddBddComposeRecur(dd, f1, g1, proj);
00907         if (t == NULL) return(NULL);
00908         cuddRef(t);
00909         e = cuddBddComposeRecur(dd, f0, g0, proj);
00910         if (e == NULL) {
00911             Cudd_IterDerefBdd(dd, t);
00912             return(NULL);
00913         }
00914         cuddRef(e);
00915 
00916         r = cuddBddIteRecur(dd, dd->vars[topindex], t, e);
00917         if (r == NULL) {
00918             Cudd_IterDerefBdd(dd, t);
00919             Cudd_IterDerefBdd(dd, e);
00920             return(NULL);
00921         }
00922         cuddRef(r);
00923         Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */
00924         Cudd_IterDerefBdd(dd, e);
00925         cuddDeref(r);
00926     }
00927 
00928     cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r);
00929 
00930     return(Cudd_NotCond(r,comple));
00931 
00932 } /* end of cuddBddComposeRecur */

DdNode* cuddBddConstrainRecur ( DdManager dd,
DdNode f,
DdNode c 
)

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

Synopsis [Performs the recursive step of Cudd_bddConstrain.]

Description [Performs the recursive step of Cudd_bddConstrain. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddConstrain]

Definition at line 779 of file cuddGenCof.c.

00783 {
00784     DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
00785     DdNode       *one, *zero;
00786     unsigned int topf, topc;
00787     int          index;
00788     int          comple = 0;
00789 
00790     statLine(dd);
00791     one = DD_ONE(dd);
00792     zero = Cudd_Not(one);
00793 
00794     /* Trivial cases. */
00795     if (c == one)               return(f);
00796     if (c == zero)              return(zero);
00797     if (Cudd_IsConstant(f))     return(f);
00798     if (f == c)                 return(one);
00799     if (f == Cudd_Not(c))       return(zero);
00800 
00801     /* Make canonical to increase the utilization of the cache. */
00802     if (Cudd_IsComplement(f)) {
00803         f = Cudd_Not(f);
00804         comple = 1;
00805     }
00806     /* Now f is a regular pointer to a non-constant node; c is also
00807     ** non-constant, but may be complemented.
00808     */
00809 
00810     /* Check the cache. */
00811     r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c);
00812     if (r != NULL) {
00813         return(Cudd_NotCond(r,comple));
00814     }
00815     
00816     /* Recursive step. */
00817     topf = dd->perm[f->index];
00818     topc = dd->perm[Cudd_Regular(c)->index];
00819     if (topf <= topc) {
00820         index = f->index;
00821         Fv = cuddT(f); Fnv = cuddE(f);
00822     } else {
00823         index = Cudd_Regular(c)->index;
00824         Fv = Fnv = f;
00825     }
00826     if (topc <= topf) {
00827         Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
00828         if (Cudd_IsComplement(c)) {
00829             Cv = Cudd_Not(Cv);
00830             Cnv = Cudd_Not(Cnv);
00831         }
00832     } else {
00833         Cv = Cnv = c;
00834     }
00835 
00836     if (!Cudd_IsConstant(Cv)) {
00837         t = cuddBddConstrainRecur(dd, Fv, Cv);
00838         if (t == NULL)
00839             return(NULL);
00840     } else if (Cv == one) {
00841         t = Fv;
00842     } else {            /* Cv == zero: return Fnv @ Cnv */
00843         if (Cnv == one) {
00844             r = Fnv;
00845         } else {
00846             r = cuddBddConstrainRecur(dd, Fnv, Cnv);
00847             if (r == NULL)
00848                 return(NULL);
00849         }
00850         return(Cudd_NotCond(r,comple));
00851     }
00852     cuddRef(t);
00853 
00854     if (!Cudd_IsConstant(Cnv)) {
00855         e = cuddBddConstrainRecur(dd, Fnv, Cnv);
00856         if (e == NULL) {
00857             Cudd_IterDerefBdd(dd, t);
00858             return(NULL);
00859         }
00860     } else if (Cnv == one) {
00861         e = Fnv;
00862     } else {            /* Cnv == zero: return Fv @ Cv previously computed */
00863         cuddDeref(t);
00864         return(Cudd_NotCond(t,comple));
00865     }
00866     cuddRef(e);
00867 
00868     if (Cudd_IsComplement(t)) {
00869         t = Cudd_Not(t);
00870         e = Cudd_Not(e);
00871         r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
00872         if (r == NULL) {
00873             Cudd_IterDerefBdd(dd, e);
00874             Cudd_IterDerefBdd(dd, t);
00875             return(NULL);
00876         }
00877         r = Cudd_Not(r);
00878     } else {
00879         r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
00880         if (r == NULL) {
00881             Cudd_IterDerefBdd(dd, e);
00882             Cudd_IterDerefBdd(dd, t);
00883             return(NULL);
00884         }
00885     }
00886     cuddDeref(t);
00887     cuddDeref(e);
00888 
00889     cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r);
00890     return(Cudd_NotCond(r,comple));
00891 
00892 } /* end of cuddBddConstrainRecur */

DdNode* cuddBddExistAbstractRecur ( DdManager manager,
DdNode f,
DdNode cube 
)

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

Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.]

Description [Performs the recursive steps of Cudd_bddExistAbstract. Returns the BDD obtained by abstracting the variables of cube from f if successful; NULL otherwise. It is also used by Cudd_bddUnivAbstract.]

SideEffects [None]

SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract]

Definition at line 348 of file cuddBddAbs.c.

00352 {
00353     DdNode      *F, *T, *E, *res, *res1, *res2, *one;
00354 
00355     statLine(manager);
00356     one = DD_ONE(manager);
00357     F = Cudd_Regular(f);
00358 
00359     /* Cube is guaranteed to be a cube at this point. */        
00360     if (cube == one || F == one) {  
00361         return(f);
00362     }
00363     /* From now on, f and cube are non-constant. */
00364 
00365     /* Abstract a variable that does not appear in f. */
00366     while (manager->perm[F->index] > manager->perm[cube->index]) {
00367         cube = cuddT(cube);
00368         if (cube == one) return(f);
00369     }
00370 
00371     /* Check the cache. */
00372     if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) {
00373         return(res);
00374     }
00375 
00376     /* Compute the cofactors of f. */
00377     T = cuddT(F); E = cuddE(F);
00378     if (f != F) {
00379         T = Cudd_Not(T); E = Cudd_Not(E);
00380     }
00381 
00382     /* If the two indices are the same, so are their levels. */
00383     if (F->index == cube->index) {
00384         if (T == one || E == one || T == Cudd_Not(E)) {
00385             return(one);
00386         }
00387         res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube));
00388         if (res1 == NULL) return(NULL);
00389         if (res1 == one) {
00390             if (F->ref != 1)
00391                 cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one);
00392             return(one);
00393         }
00394         cuddRef(res1);
00395         res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube));
00396         if (res2 == NULL) {
00397             Cudd_IterDerefBdd(manager,res1);
00398             return(NULL);
00399         }
00400         cuddRef(res2);
00401         res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2));
00402         if (res == NULL) {
00403             Cudd_IterDerefBdd(manager, res1);
00404             Cudd_IterDerefBdd(manager, res2);
00405             return(NULL);
00406         }
00407         res = Cudd_Not(res);
00408         cuddRef(res);
00409         Cudd_IterDerefBdd(manager, res1);
00410         Cudd_IterDerefBdd(manager, res2);
00411         if (F->ref != 1)
00412             cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
00413         cuddDeref(res);
00414         return(res);
00415     } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */
00416         res1 = cuddBddExistAbstractRecur(manager, T, cube);
00417         if (res1 == NULL) return(NULL);
00418         cuddRef(res1);
00419         res2 = cuddBddExistAbstractRecur(manager, E, cube);
00420         if (res2 == NULL) {
00421             Cudd_IterDerefBdd(manager, res1);
00422             return(NULL);
00423         }
00424         cuddRef(res2);
00425         /* ITE takes care of possible complementation of res1 and of the
00426         ** case in which res1 == res2. */
00427         res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2);
00428         if (res == NULL) {
00429             Cudd_IterDerefBdd(manager, res1);
00430             Cudd_IterDerefBdd(manager, res2);
00431             return(NULL);
00432         }
00433         cuddDeref(res1);
00434         cuddDeref(res2);
00435         if (F->ref != 1)
00436             cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
00437         return(res);
00438     }       
00439 
00440 } /* end of cuddBddExistAbstractRecur */

DdNode* cuddBddIntersectRecur ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Implements the recursive step of Cudd_bddIntersect.]

Description []

SideEffects [None]

SeeAlso [Cudd_bddIntersect]

Definition at line 767 of file cuddBddIte.c.

00771 {
00772     DdNode *res;
00773     DdNode *F, *G, *t, *e;
00774     DdNode *fv, *fnv, *gv, *gnv;
00775     DdNode *one, *zero;
00776     unsigned int index, topf, topg;
00777 
00778     statLine(dd);
00779     one = DD_ONE(dd);
00780     zero = Cudd_Not(one);
00781 
00782     /* Terminal cases. */
00783     if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
00784     if (f == g || g == one) return(f);
00785     if (f == one) return(g);
00786 
00787     /* At this point f and g are not constant. */
00788     if (f > g) { DdNode *tmp = f; f = g; g = tmp; }
00789     res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g);
00790     if (res != NULL) return(res);
00791 
00792     /* Find splitting variable. Here we can skip the use of cuddI,
00793     ** because the operands are known to be non-constant.
00794     */
00795     F = Cudd_Regular(f);
00796     topf = dd->perm[F->index];
00797     G = Cudd_Regular(g);
00798     topg = dd->perm[G->index];
00799 
00800     /* Compute cofactors. */
00801     if (topf <= topg) {
00802         index = F->index;
00803         fv = cuddT(F);
00804         fnv = cuddE(F);
00805         if (Cudd_IsComplement(f)) {
00806             fv = Cudd_Not(fv);
00807             fnv = Cudd_Not(fnv);
00808         }
00809     } else {
00810         index = G->index;
00811         fv = fnv = f;
00812     }
00813 
00814     if (topg <= topf) {
00815         gv = cuddT(G);
00816         gnv = cuddE(G);
00817         if (Cudd_IsComplement(g)) {
00818             gv = Cudd_Not(gv);
00819             gnv = Cudd_Not(gnv);
00820         }
00821     } else {
00822         gv = gnv = g;
00823     }
00824 
00825     /* Compute partial results. */
00826     t = cuddBddIntersectRecur(dd,fv,gv);
00827     if (t == NULL) return(NULL);
00828     cuddRef(t);
00829     if (t != zero) {
00830         e = zero;
00831     } else {
00832         e = cuddBddIntersectRecur(dd,fnv,gnv);
00833         if (e == NULL) {
00834             Cudd_IterDerefBdd(dd, t);
00835             return(NULL);
00836         }
00837     }
00838     cuddRef(e);
00839 
00840     if (t == e) { /* both equal zero */
00841         res = t;
00842     } else if (Cudd_IsComplement(t)) {
00843         res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e));
00844         if (res == NULL) {
00845             Cudd_IterDerefBdd(dd, t);
00846             Cudd_IterDerefBdd(dd, e);
00847             return(NULL);
00848         }
00849         res = Cudd_Not(res);
00850     } else {
00851         res = cuddUniqueInter(dd,(int)index,t,e);
00852         if (res == NULL) {
00853             Cudd_IterDerefBdd(dd, t);
00854             Cudd_IterDerefBdd(dd, e);
00855             return(NULL);
00856         }
00857     }
00858     cuddDeref(e);
00859     cuddDeref(t);
00860 
00861     cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res);
00862 
00863     return(res);
00864 
00865 } /* end of cuddBddIntersectRecur */

DdNode* cuddBddIsop ( DdManager dd,
DdNode L,
DdNode U 
)

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

Synopsis [Performs the recursive step of Cudd_bddIsop.]

Description []

SideEffects [None]

SeeAlso [Cudd_bddIsop]

Definition at line 571 of file cuddZddIsop.c.

00575 {
00576     DdNode      *one = DD_ONE(dd);
00577     DdNode      *zero = Cudd_Not(one);
00578     int         v, top_l, top_u;
00579     DdNode      *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
00580     DdNode      *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
00581     DdNode      *Isub0, *Isub1, *Id;
00582     DdNode      *x;
00583     DdNode      *term0, *term1, *sum;
00584     DdNode      *Lv, *Uv, *Lnv, *Unv;
00585     DdNode      *r;
00586     int         index;
00587 
00588     statLine(dd);
00589     if (L == zero)
00590         return(zero);
00591     if (U == one)
00592         return(one);
00593 
00594     /* Check cache */
00595     r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
00596     if (r)
00597         return(r);
00598 
00599     top_l = dd->perm[Cudd_Regular(L)->index];
00600     top_u = dd->perm[Cudd_Regular(U)->index];
00601     v = ddMin(top_l, top_u);
00602 
00603     /* Compute cofactors */
00604     if (top_l == v) {
00605         index = Cudd_Regular(L)->index;
00606         Lv = Cudd_T(L);
00607         Lnv = Cudd_E(L);
00608         if (Cudd_IsComplement(L)) {
00609             Lv = Cudd_Not(Lv);
00610             Lnv = Cudd_Not(Lnv);
00611         }
00612     }
00613     else {
00614         index = Cudd_Regular(U)->index;
00615         Lv = Lnv = L;
00616     }
00617 
00618     if (top_u == v) {
00619         Uv = Cudd_T(U);
00620         Unv = Cudd_E(U);
00621         if (Cudd_IsComplement(U)) {
00622             Uv = Cudd_Not(Uv);
00623             Unv = Cudd_Not(Unv);
00624         }
00625     }
00626     else {
00627         Uv = Unv = U;
00628     }
00629 
00630     Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
00631     if (Lsub0 == NULL)
00632         return(NULL);
00633     Cudd_Ref(Lsub0);
00634     Usub0 = Unv;
00635     Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
00636     if (Lsub1 == NULL) {
00637         Cudd_RecursiveDeref(dd, Lsub0);
00638         return(NULL);
00639     }
00640     Cudd_Ref(Lsub1);
00641     Usub1 = Uv;
00642 
00643     Isub0 = cuddBddIsop(dd, Lsub0, Usub0);
00644     if (Isub0 == NULL) {
00645         Cudd_RecursiveDeref(dd, Lsub0);
00646         Cudd_RecursiveDeref(dd, Lsub1);
00647         return(NULL);
00648     }
00649     Cudd_Ref(Isub0);
00650     Isub1 = cuddBddIsop(dd, Lsub1, Usub1);
00651     if (Isub1 == NULL) {
00652         Cudd_RecursiveDeref(dd, Lsub0);
00653         Cudd_RecursiveDeref(dd, Lsub1);
00654         Cudd_RecursiveDeref(dd, Isub0);
00655         return(NULL);
00656     }
00657     Cudd_Ref(Isub1);
00658     Cudd_RecursiveDeref(dd, Lsub0);
00659     Cudd_RecursiveDeref(dd, Lsub1);
00660 
00661     Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
00662     if (Lsuper0 == NULL) {
00663         Cudd_RecursiveDeref(dd, Isub0);
00664         Cudd_RecursiveDeref(dd, Isub1);
00665         return(NULL);
00666     }
00667     Cudd_Ref(Lsuper0);
00668     Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
00669     if (Lsuper1 == NULL) {
00670         Cudd_RecursiveDeref(dd, Isub0);
00671         Cudd_RecursiveDeref(dd, Isub1);
00672         Cudd_RecursiveDeref(dd, Lsuper0);
00673         return(NULL);
00674     }
00675     Cudd_Ref(Lsuper1);
00676     Usuper0 = Unv;
00677     Usuper1 = Uv;
00678 
00679     /* Ld = Lsuper0 + Lsuper1 */
00680     Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
00681     Ld = Cudd_NotCond(Ld, Ld != NULL);
00682     if (Ld == NULL) {
00683         Cudd_RecursiveDeref(dd, Isub0);
00684         Cudd_RecursiveDeref(dd, Isub1);
00685         Cudd_RecursiveDeref(dd, Lsuper0);
00686         Cudd_RecursiveDeref(dd, Lsuper1);
00687         return(NULL);
00688     }
00689     Cudd_Ref(Ld);
00690     Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
00691     if (Ud == NULL) {
00692         Cudd_RecursiveDeref(dd, Isub0);
00693         Cudd_RecursiveDeref(dd, Isub1);
00694         Cudd_RecursiveDeref(dd, Lsuper0);
00695         Cudd_RecursiveDeref(dd, Lsuper1);
00696         Cudd_RecursiveDeref(dd, Ld);
00697         return(NULL);
00698     }
00699     Cudd_Ref(Ud);
00700     Cudd_RecursiveDeref(dd, Lsuper0);
00701     Cudd_RecursiveDeref(dd, Lsuper1);
00702 
00703     Id = cuddBddIsop(dd, Ld, Ud);
00704     if (Id == NULL) {
00705         Cudd_RecursiveDeref(dd, Isub0);
00706         Cudd_RecursiveDeref(dd, Isub1);
00707         Cudd_RecursiveDeref(dd, Ld);
00708         Cudd_RecursiveDeref(dd, Ud);
00709         return(NULL);
00710     }
00711     Cudd_Ref(Id);
00712     Cudd_RecursiveDeref(dd, Ld);
00713     Cudd_RecursiveDeref(dd, Ud);
00714 
00715     x = cuddUniqueInter(dd, index, one, zero);
00716     if (x == NULL) {
00717         Cudd_RecursiveDeref(dd, Isub0);
00718         Cudd_RecursiveDeref(dd, Isub1);
00719         Cudd_RecursiveDeref(dd, Id);
00720         return(NULL);
00721     }
00722     Cudd_Ref(x);
00723     term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
00724     if (term0 == NULL) {
00725         Cudd_RecursiveDeref(dd, Isub0);
00726         Cudd_RecursiveDeref(dd, Isub1);
00727         Cudd_RecursiveDeref(dd, Id);
00728         Cudd_RecursiveDeref(dd, x);
00729         return(NULL);
00730     }
00731     Cudd_Ref(term0);
00732     Cudd_RecursiveDeref(dd, Isub0);
00733     term1 = cuddBddAndRecur(dd, x, Isub1);
00734     if (term1 == NULL) {
00735         Cudd_RecursiveDeref(dd, Isub1);
00736         Cudd_RecursiveDeref(dd, Id);
00737         Cudd_RecursiveDeref(dd, x);
00738         Cudd_RecursiveDeref(dd, term0);
00739         return(NULL);
00740     }
00741     Cudd_Ref(term1);
00742     Cudd_RecursiveDeref(dd, x);
00743     Cudd_RecursiveDeref(dd, Isub1);
00744     /* sum = term0 + term1 */
00745     sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
00746     sum = Cudd_NotCond(sum, sum != NULL);
00747     if (sum == NULL) {
00748         Cudd_RecursiveDeref(dd, Id);
00749         Cudd_RecursiveDeref(dd, term0);
00750         Cudd_RecursiveDeref(dd, term1);
00751         return(NULL);
00752     }
00753     Cudd_Ref(sum);
00754     Cudd_RecursiveDeref(dd, term0);
00755     Cudd_RecursiveDeref(dd, term1);
00756     /* r = sum + Id */
00757     r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
00758     r = Cudd_NotCond(r, r != NULL);
00759     if (r == NULL) {
00760         Cudd_RecursiveDeref(dd, Id);
00761         Cudd_RecursiveDeref(dd, sum);
00762         return(NULL);
00763     }
00764     Cudd_Ref(r);
00765     Cudd_RecursiveDeref(dd, sum);
00766     Cudd_RecursiveDeref(dd, Id);
00767 
00768     cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
00769 
00770     Cudd_Deref(r);
00771     return(r);
00772 
00773 } /* end of cuddBddIsop */

DdNode* cuddBddIteRecur ( DdManager dd,
DdNode f,
DdNode g,
DdNode h 
)

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

Synopsis [Implements the recursive step of Cudd_bddIte.]

Description [Implements the recursive step of Cudd_bddIte. Returns a pointer to the resulting BDD. NULL if the intermediate result blows up or if reordering occurs.]

SideEffects [None]

SeeAlso []

Definition at line 629 of file cuddBddIte.c.

00634 {
00635     DdNode       *one, *zero, *res;
00636     DdNode       *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
00637     unsigned int topf, topg, toph, v;
00638     int          index;
00639     int          comple;
00640 
00641     statLine(dd);
00642     /* Terminal cases. */
00643 
00644     /* One variable cases. */
00645     if (f == (one = DD_ONE(dd)))        /* ITE(1,G,H) = G */
00646         return(g);
00647     
00648     if (f == (zero = Cudd_Not(one)))    /* ITE(0,G,H) = H */
00649         return(h);
00650     
00651     /* From now on, f is known not to be a constant. */
00652     if (g == one || f == g) {   /* ITE(F,F,H) = ITE(F,1,H) = F + H */
00653         if (h == zero) {        /* ITE(F,1,0) = F */
00654             return(f);
00655         } else {
00656             res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
00657             return(Cudd_NotCond(res,res != NULL));
00658         }
00659     } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
00660         if (h == one) {         /* ITE(F,0,1) = !F */
00661             return(Cudd_Not(f));
00662         } else {
00663             res = cuddBddAndRecur(dd,Cudd_Not(f),h);
00664             return(res);
00665         }
00666     }
00667     if (h == zero || f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
00668         res = cuddBddAndRecur(dd,f,g);
00669         return(res);
00670     } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
00671         res = cuddBddAndRecur(dd,f,Cudd_Not(g));
00672         return(Cudd_NotCond(res,res != NULL));
00673     }
00674 
00675     /* Check remaining one variable case. */
00676     if (g == h) {               /* ITE(F,G,G) = G */
00677         return(g);
00678     } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
00679         res = cuddBddXorRecur(dd,f,h);
00680         return(res);
00681     }
00682     
00683     /* From here, there are no constants. */
00684     comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);
00685 
00686     /* f & g are now regular pointers */
00687 
00688     v = ddMin(topg, toph);
00689 
00690     /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
00691     if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
00692         r = cuddUniqueInter(dd, (int) f->index, g, h);
00693         return(Cudd_NotCond(r,comple && r != NULL));
00694     }
00695 
00696     /* Check cache. */
00697     r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
00698     if (r != NULL) {
00699         return(Cudd_NotCond(r,comple));
00700     }
00701 
00702     /* Compute cofactors. */
00703     if (topf <= v) {
00704         v = ddMin(topf, v);     /* v = top_var(F,G,H) */
00705         index = f->index;
00706         Fv = cuddT(f); Fnv = cuddE(f);
00707     } else {
00708         Fv = Fnv = f;
00709     }
00710     if (topg == v) {
00711         index = g->index;
00712         Gv = cuddT(g); Gnv = cuddE(g);
00713     } else {
00714         Gv = Gnv = g;
00715     }
00716     if (toph == v) {
00717         H = Cudd_Regular(h);
00718         index = H->index;
00719         Hv = cuddT(H); Hnv = cuddE(H);
00720         if (Cudd_IsComplement(h)) {
00721             Hv = Cudd_Not(Hv);
00722             Hnv = Cudd_Not(Hnv);
00723         }
00724     } else {
00725         Hv = Hnv = h;
00726     }
00727 
00728     /* Recursive step. */
00729     t = cuddBddIteRecur(dd,Fv,Gv,Hv);
00730     if (t == NULL) return(NULL);
00731     cuddRef(t);
00732 
00733     e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
00734     if (e == NULL) {
00735         Cudd_IterDerefBdd(dd,t);
00736         return(NULL);
00737     }
00738     cuddRef(e);
00739 
00740     r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
00741     if (r == NULL) {
00742         Cudd_IterDerefBdd(dd,t);
00743         Cudd_IterDerefBdd(dd,e);
00744         return(NULL);
00745     }
00746     cuddDeref(t);
00747     cuddDeref(e);
00748 
00749     cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
00750     return(Cudd_NotCond(r,comple));
00751 
00752 } /* end of cuddBddIteRecur */

DdNode* cuddBddLICompaction ( DdManager dd,
DdNode f,
DdNode c 
)

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

Synopsis [Performs safe minimization of a BDD.]

Description [Performs safe minimization of a BDD. Given the BDD f of a function to be minimized and a BDD c representing the care set, Cudd_bddLICompaction produces the BDD of a function that agrees with f wherever c is 1. Safe minimization means that the size of the result is guaranteed not to exceed the size of f. This function is based on the DAC97 paper by Hong et al.. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddLICompaction]

Definition at line 1430 of file cuddGenCof.c.

01434 {
01435     st_table *marktable, *markcache, *buildcache;
01436     DdNode *res, *zero;
01437 
01438     zero = Cudd_Not(DD_ONE(dd));
01439     if (c == zero) return(zero);
01440 
01441     /* We need to use local caches for both steps of this operation.
01442     ** The results of the edge marking step are only valid as long as the
01443     ** edge markings themselves are available. However, the edge markings
01444     ** are lost at the end of one invocation of Cudd_bddLICompaction.
01445     ** Hence, the cache entries for the edge marking step must be
01446     ** invalidated at the end of this function.
01447     ** For the result of the building step we argue as follows. The result
01448     ** for a node and a given constrain depends on the BDD in which the node
01449     ** appears. Hence, the same node and constrain may give different results
01450     ** in successive invocations.
01451     */
01452     marktable = st_init_table(st_ptrcmp,st_ptrhash);
01453     if (marktable == NULL) {
01454         return(NULL);
01455     }
01456     markcache = st_init_table(MarkCacheCompare,MarkCacheHash);
01457     if (markcache == NULL) {
01458         st_free_table(marktable);
01459         return(NULL);
01460     }
01461     if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) {
01462         st_foreach(markcache, MarkCacheCleanUp, NULL);
01463         st_free_table(marktable);
01464         st_free_table(markcache);
01465         return(NULL);
01466     }
01467     st_foreach(markcache, MarkCacheCleanUp, NULL);
01468     st_free_table(markcache);
01469     buildcache = st_init_table(st_ptrcmp,st_ptrhash);
01470     if (buildcache == NULL) {
01471         st_free_table(marktable);
01472         return(NULL);
01473     }
01474     res = cuddBddLICBuildResult(dd,f,buildcache,marktable);
01475     st_free_table(buildcache);
01476     st_free_table(marktable);
01477     return(res);
01478 
01479 } /* end of cuddBddLICompaction */

DdNode* cuddBddLiteralSetIntersectionRecur ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_bddLiteralSetIntersection.]

Description [Performs the recursive step of Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, and checks whether they agree in phase. Returns a pointer to the resulting cube if successful; NULL otherwise.]

SideEffects [None]

Definition at line 149 of file cuddLiteral.c.

00153 {
00154     DdNode *res, *tmp;
00155     DdNode *F, *G;
00156     DdNode *fc, *gc;
00157     DdNode *one;
00158     DdNode *zero;
00159     unsigned int topf, topg, comple;
00160     int phasef, phaseg;
00161 
00162     statLine(dd);
00163     if (f == g) return(f);
00164 
00165     F = Cudd_Regular(f);
00166     G = Cudd_Regular(g);
00167     one = DD_ONE(dd);
00168 
00169     /* Here f != g. If F == G, then f and g are complementary.
00170     ** Since they are two cubes, this case only occurs when f == v,
00171     ** g == v', and v is a variable or its complement.
00172     */
00173     if (F == G) return(one);
00174 
00175     zero = Cudd_Not(one);
00176     topf = cuddI(dd,F->index);
00177     topg = cuddI(dd,G->index);
00178     /* Look for a variable common to both cubes. If there are none, this
00179     ** loop will stop when the constant node is reached in both cubes.
00180     */
00181     while (topf != topg) {
00182         if (topf < topg) {      /* move down on f */
00183             comple = f != F;
00184             f = cuddT(F);
00185             if (comple) f = Cudd_Not(f);
00186             if (f == zero) {
00187                 f = cuddE(F);
00188                 if (comple) f = Cudd_Not(f);
00189             }
00190             F = Cudd_Regular(f);
00191             topf = cuddI(dd,F->index);
00192         } else if (topg < topf) {
00193             comple = g != G;
00194             g = cuddT(G);
00195             if (comple) g = Cudd_Not(g);
00196             if (g == zero) {
00197                 g = cuddE(G);
00198                 if (comple) g = Cudd_Not(g);
00199             }
00200             G = Cudd_Regular(g);
00201             topg = cuddI(dd,G->index);
00202         }
00203     }
00204 
00205     /* At this point, f == one <=> g == 1. It suffices to test one of them. */
00206     if (f == one) return(one);
00207 
00208     res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g);
00209     if (res != NULL) {
00210         return(res);
00211     }
00212 
00213     /* Here f and g are both non constant and have the same top variable. */
00214     comple = f != F;
00215     fc = cuddT(F);
00216     phasef = 1;
00217     if (comple) fc = Cudd_Not(fc);
00218     if (fc == zero) {
00219         fc = cuddE(F);
00220         phasef = 0;
00221         if (comple) fc = Cudd_Not(fc);
00222     }
00223     comple = g != G;
00224     gc = cuddT(G);
00225     phaseg = 1;
00226     if (comple) gc = Cudd_Not(gc);
00227     if (gc == zero) {
00228         gc = cuddE(G);
00229         phaseg = 0;
00230         if (comple) gc = Cudd_Not(gc);
00231     }
00232 
00233     tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc);
00234     if (tmp == NULL) {
00235         return(NULL);
00236     }
00237 
00238     if (phasef != phaseg) {
00239         res = tmp;
00240     } else {
00241         cuddRef(tmp);
00242         if (phasef == 0) {
00243             res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp);
00244         } else {
00245             res = cuddBddAndRecur(dd,dd->vars[F->index],tmp);
00246         }
00247         if (res == NULL) {
00248             Cudd_RecursiveDeref(dd,tmp);
00249             return(NULL);
00250         }
00251         cuddDeref(tmp); /* Just cuddDeref, because it is included in result */
00252     }
00253 
00254     cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res);
00255 
00256     return(res);
00257 
00258 } /* end of cuddBddLiteralSetIntersectionRecur */

DdNode* cuddBddMakePrime ( DdManager dd,
DdNode cube,
DdNode f 
)

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

Synopsis [Performs the recursive step of Cudd_bddMakePrime.]

Description [Performs the recursive step of Cudd_bddMakePrime. Returns the prime if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 896 of file cuddSat.c.

00900 {
00901     DdNode *scan;
00902     DdNode *t, *e;
00903     DdNode *res = cube;
00904     DdNode *zero = Cudd_Not(DD_ONE(dd));
00905 
00906     Cudd_Ref(res);
00907     scan = cube;
00908     while (!Cudd_IsConstant(scan)) {
00909         DdNode *reg = Cudd_Regular(scan);
00910         DdNode *var = dd->vars[reg->index];
00911         DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
00912         if (expanded == NULL) {
00913             return(NULL);
00914         }
00915         Cudd_Ref(expanded);
00916         if (Cudd_bddLeq(dd,expanded,f)) {
00917             Cudd_RecursiveDeref(dd,res);
00918             res = expanded;
00919         } else {
00920             Cudd_RecursiveDeref(dd,expanded);
00921         }
00922         cuddGetBranches(scan,&t,&e);
00923         if (t == zero) {
00924             scan = e;
00925         } else if (e == zero) {
00926             scan = t;
00927         } else {
00928             Cudd_RecursiveDeref(dd,res);
00929             return(NULL);       /* cube is not a cube */
00930         }
00931     }
00932 
00933     if (scan == DD_ONE(dd)) {
00934         Cudd_Deref(res);
00935         return(res);
00936     } else {
00937         Cudd_RecursiveDeref(dd,res);
00938         return(NULL);
00939     }
00940 
00941 } /* end of cuddBddMakePrime */

DdNode* cuddBddNPAndRecur ( DdManager manager,
DdNode f,
DdNode g 
)

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

Synopsis [Implements the recursive step of Cudd_bddAnd.]

Description [Implements the recursive step of Cudd_bddNPAnd. Returns a pointer to the result is successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddNPAnd]

Definition at line 1058 of file cuddGenCof.c.

01062 {
01063     DdNode *F, *ft, *fe, *G, *gt, *ge;
01064     DdNode *one, *r, *t, *e;
01065     unsigned int topf, topg, index;
01066 
01067     statLine(manager);
01068     one = DD_ONE(manager);
01069 
01070     /* Terminal cases. */
01071     F = Cudd_Regular(f);
01072     G = Cudd_Regular(g);
01073     if (F == G) {
01074         if (f == g) return(one);
01075         else return(Cudd_Not(one));
01076     }
01077     if (G == one) {
01078         if (g == one) return(f);
01079         else return(g);
01080     }
01081     if (F == one) {
01082         return(f);
01083     }
01084 
01085     /* At this point f and g are not constant. */
01086     /* Check cache. */
01087     if (F->ref != 1 || G->ref != 1) {
01088         r = cuddCacheLookup2(manager, Cudd_bddNPAnd, f, g);
01089         if (r != NULL) return(r);
01090     }
01091 
01092     /* Here we can skip the use of cuddI, because the operands are known
01093     ** to be non-constant.
01094     */
01095     topf = manager->perm[F->index];
01096     topg = manager->perm[G->index];
01097 
01098     if (topg < topf) {  /* abstract top variable from g */
01099         DdNode *d;
01100 
01101         /* Find complements of cofactors of g. */
01102         if (Cudd_IsComplement(g)) {
01103             gt = cuddT(G);
01104             ge = cuddE(G);
01105         } else {
01106             gt = Cudd_Not(cuddT(g));
01107             ge = Cudd_Not(cuddE(g));
01108         }
01109         /* Take the OR by applying DeMorgan. */
01110         d = cuddBddAndRecur(manager, gt, ge);
01111         if (d == NULL) return(NULL);
01112         d = Cudd_Not(d);
01113         cuddRef(d);
01114         r = cuddBddNPAndRecur(manager, f, d);
01115         if (r == NULL) {
01116             Cudd_IterDerefBdd(manager, d);
01117             return(NULL);
01118         }
01119         cuddRef(r);
01120         Cudd_IterDerefBdd(manager, d);
01121         cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
01122         cuddDeref(r);
01123         return(r);
01124     }
01125 
01126     /* Compute cofactors. */
01127     index = F->index;
01128     ft = cuddT(F);
01129     fe = cuddE(F);
01130     if (Cudd_IsComplement(f)) {
01131       ft = Cudd_Not(ft);
01132       fe = Cudd_Not(fe);
01133     }
01134 
01135     if (topg == topf) {
01136         gt = cuddT(G);
01137         ge = cuddE(G);
01138         if (Cudd_IsComplement(g)) {
01139             gt = Cudd_Not(gt);
01140             ge = Cudd_Not(ge);
01141         }
01142     } else {
01143         gt = ge = g;
01144     }
01145 
01146     t = cuddBddAndRecur(manager, ft, gt);
01147     if (t == NULL) return(NULL);
01148     cuddRef(t);
01149 
01150     e = cuddBddAndRecur(manager, fe, ge);
01151     if (e == NULL) {
01152         Cudd_IterDerefBdd(manager, t);
01153         return(NULL);
01154     }
01155     cuddRef(e);
01156 
01157     if (t == e) {
01158         r = t;
01159     } else {
01160         if (Cudd_IsComplement(t)) {
01161             r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
01162             if (r == NULL) {
01163                 Cudd_IterDerefBdd(manager, t);
01164                 Cudd_IterDerefBdd(manager, e);
01165                 return(NULL);
01166             }
01167             r = Cudd_Not(r);
01168         } else {
01169             r = cuddUniqueInter(manager,(int)index,t,e);
01170             if (r == NULL) {
01171                 Cudd_IterDerefBdd(manager, t);
01172                 Cudd_IterDerefBdd(manager, e);
01173                 return(NULL);
01174             }
01175         }
01176     }
01177     cuddDeref(e);
01178     cuddDeref(t);
01179     if (F->ref != 1 || G->ref != 1)
01180         cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
01181     return(r);
01182 
01183 } /* end of cuddBddNPAndRecur */

DdNode* cuddBddRestrictRecur ( DdManager dd,
DdNode f,
DdNode c 
)

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

Synopsis [Performs the recursive step of Cudd_bddRestrict.]

Description [Performs the recursive step of Cudd_bddRestrict. Returns the restricted BDD if successful; otherwise NULL.]

SideEffects [None]

SeeAlso [Cudd_bddRestrict]

Definition at line 908 of file cuddGenCof.c.

00912 {
00913     DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
00914     unsigned int topf, topc;
00915     int          index;
00916     int          comple = 0;
00917 
00918     statLine(dd);
00919     one = DD_ONE(dd);
00920     zero = Cudd_Not(one);
00921 
00922     /* Trivial cases */
00923     if (c == one)               return(f);
00924     if (c == zero)              return(zero);
00925     if (Cudd_IsConstant(f))     return(f);
00926     if (f == c)                 return(one);
00927     if (f == Cudd_Not(c))       return(zero);
00928 
00929     /* Make canonical to increase the utilization of the cache. */
00930     if (Cudd_IsComplement(f)) {
00931         f = Cudd_Not(f);
00932         comple = 1;
00933     }
00934     /* Now f is a regular pointer to a non-constant node; c is also
00935     ** non-constant, but may be complemented.
00936     */
00937 
00938     /* Check the cache. */
00939     r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c);
00940     if (r != NULL) {
00941         return(Cudd_NotCond(r,comple));
00942     }
00943 
00944     topf = dd->perm[f->index];
00945     topc = dd->perm[Cudd_Regular(c)->index];
00946 
00947     if (topc < topf) {  /* abstract top variable from c */
00948         DdNode *d, *s1, *s2;
00949 
00950         /* Find complements of cofactors of c. */
00951         if (Cudd_IsComplement(c)) {
00952             s1 = cuddT(Cudd_Regular(c));
00953             s2 = cuddE(Cudd_Regular(c));
00954         } else {
00955             s1 = Cudd_Not(cuddT(c));
00956             s2 = Cudd_Not(cuddE(c));
00957         }
00958         /* Take the OR by applying DeMorgan. */
00959         d = cuddBddAndRecur(dd, s1, s2);
00960         if (d == NULL) return(NULL);
00961         d = Cudd_Not(d);
00962         cuddRef(d);
00963         r = cuddBddRestrictRecur(dd, f, d);
00964         if (r == NULL) {
00965             Cudd_IterDerefBdd(dd, d);
00966             return(NULL);
00967         }
00968         cuddRef(r);
00969         Cudd_IterDerefBdd(dd, d);
00970         cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
00971         cuddDeref(r);
00972         return(Cudd_NotCond(r,comple));
00973     }
00974 
00975     /* Recursive step. Here topf <= topc. */
00976     index = f->index;
00977     Fv = cuddT(f); Fnv = cuddE(f);
00978     if (topc == topf) {
00979         Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
00980         if (Cudd_IsComplement(c)) {
00981             Cv = Cudd_Not(Cv);
00982             Cnv = Cudd_Not(Cnv);
00983         }
00984     } else {
00985         Cv = Cnv = c;
00986     }
00987 
00988     if (!Cudd_IsConstant(Cv)) {
00989         t = cuddBddRestrictRecur(dd, Fv, Cv);
00990         if (t == NULL) return(NULL);
00991     } else if (Cv == one) {
00992         t = Fv;
00993     } else {            /* Cv == zero: return(Fnv @ Cnv) */
00994         if (Cnv == one) {
00995             r = Fnv;
00996         } else {
00997             r = cuddBddRestrictRecur(dd, Fnv, Cnv);
00998             if (r == NULL) return(NULL);
00999         }
01000         return(Cudd_NotCond(r,comple));
01001     }
01002     cuddRef(t);
01003 
01004     if (!Cudd_IsConstant(Cnv)) {
01005         e = cuddBddRestrictRecur(dd, Fnv, Cnv);
01006         if (e == NULL) {
01007             Cudd_IterDerefBdd(dd, t);
01008             return(NULL);
01009         }
01010     } else if (Cnv == one) {
01011         e = Fnv;
01012     } else {            /* Cnv == zero: return (Fv @ Cv) previously computed */
01013         cuddDeref(t);
01014         return(Cudd_NotCond(t,comple));
01015     }
01016     cuddRef(e);
01017 
01018     if (Cudd_IsComplement(t)) {
01019         t = Cudd_Not(t);
01020         e = Cudd_Not(e);
01021         r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
01022         if (r == NULL) {
01023             Cudd_IterDerefBdd(dd, e);
01024             Cudd_IterDerefBdd(dd, t);
01025             return(NULL);
01026         }
01027         r = Cudd_Not(r);
01028     } else {
01029         r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
01030         if (r == NULL) {
01031             Cudd_IterDerefBdd(dd, e);
01032             Cudd_IterDerefBdd(dd, t);
01033             return(NULL);
01034         }
01035     }
01036     cuddDeref(t);
01037     cuddDeref(e);
01038 
01039     cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
01040     return(Cudd_NotCond(r,comple));
01041 
01042 } /* end of cuddBddRestrictRecur */

DdNode* cuddBddTransfer ( DdManager ddS,
DdManager ddD,
DdNode f 
)

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

Synopsis [Convert a BDD from a manager to another one.]

Description [Convert a BDD from a manager to another one. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddTransfer]

Definition at line 439 of file cuddBridge.c.

00443 {
00444     DdNode *res;
00445     st_table *table = NULL;
00446     st_generator *gen = NULL;
00447     DdNode *key, *value;
00448 
00449     table = st_init_table(st_ptrcmp,st_ptrhash);
00450     if (table == NULL) goto failure;
00451     res = cuddBddTransferRecur(ddS, ddD, f, table);
00452     if (res != NULL) cuddRef(res);
00453 
00454     /* Dereference all elements in the table and dispose of the table.
00455     ** This must be done also if res is NULL to avoid leaks in case of
00456     ** reordering. */
00457     gen = st_init_gen(table);
00458     if (gen == NULL) goto failure;
00459     while (st_gen(gen, &key, &value)) {
00460         Cudd_RecursiveDeref(ddD, value);
00461     }
00462     st_free_gen(gen); gen = NULL;
00463     st_free_table(table); table = NULL;
00464 
00465     if (res != NULL) cuddDeref(res);
00466     return(res);
00467 
00468 failure:
00469     /* No need to free gen because it is always NULL here. */
00470     if (table != NULL) st_free_table(table);
00471     return(NULL);
00472 
00473 } /* end of cuddBddTransfer */

DdNode* cuddBddXorExistAbstractRecur ( DdManager manager,
DdNode f,
DdNode g,
DdNode cube 
)

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

Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube.]

Description [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddAndAbstract]

Definition at line 458 of file cuddBddAbs.c.

00463 {
00464     DdNode *F, *fv, *fnv, *G, *gv, *gnv;
00465     DdNode *one, *zero, *r, *t, *e, *Cube;
00466     unsigned int topf, topg, topcube, top, index;
00467 
00468     statLine(manager);
00469     one = DD_ONE(manager);
00470     zero = Cudd_Not(one);
00471 
00472     /* Terminal cases. */
00473     if (f == g) {
00474         return(zero);
00475     }
00476     if (f == Cudd_Not(g)) {
00477         return(one);
00478     }
00479     if (cube == one) {
00480         return(cuddBddXorRecur(manager, f, g));
00481     }
00482     if (f == one) {
00483         return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
00484     }
00485     if (g == one) {
00486         return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
00487     }
00488     if (f == zero) {
00489         return(cuddBddExistAbstractRecur(manager, g, cube));
00490     }
00491     if (g == zero) {
00492         return(cuddBddExistAbstractRecur(manager, f, cube));
00493     }
00494 
00495     /* At this point f, g, and cube are not constant. */
00496 
00497     if (f > g) { /* Try to increase cache efficiency. */
00498         DdNode *tmp = f;
00499         f = g;
00500         g = tmp;
00501     }
00502 
00503     /* Check cache. */
00504     r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
00505     if (r != NULL) {
00506         return(r);
00507     }
00508 
00509     /* Here we can skip the use of cuddI, because the operands are known
00510     ** to be non-constant.
00511     */
00512     F = Cudd_Regular(f);
00513     topf = manager->perm[F->index];
00514     G = Cudd_Regular(g);
00515     topg = manager->perm[G->index];
00516     top = ddMin(topf, topg);
00517     topcube = manager->perm[cube->index];
00518 
00519     if (topcube < top) {
00520         return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
00521     }
00522     /* Now, topcube >= top. */
00523 
00524     if (topf == top) {
00525         index = F->index;
00526         fv = cuddT(F);
00527         fnv = cuddE(F);
00528         if (Cudd_IsComplement(f)) {
00529             fv = Cudd_Not(fv);
00530             fnv = Cudd_Not(fnv);
00531         }
00532     } else {
00533         index = G->index;
00534         fv = fnv = f;
00535     }
00536 
00537     if (topg == top) {
00538         gv = cuddT(G);
00539         gnv = cuddE(G);
00540         if (Cudd_IsComplement(g)) {
00541             gv = Cudd_Not(gv);
00542             gnv = Cudd_Not(gnv);
00543         }
00544     } else {
00545         gv = gnv = g;
00546     }
00547 
00548     if (topcube == top) {
00549         Cube = cuddT(cube);
00550     } else {
00551         Cube = cube;
00552     }
00553 
00554     t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
00555     if (t == NULL) return(NULL);
00556 
00557     /* Special case: 1 OR anything = 1. Hence, no need to compute
00558     ** the else branch if t is 1.
00559     */
00560     if (t == one && topcube == top) {
00561         cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
00562         return(one);
00563     }
00564     cuddRef(t);
00565 
00566     e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
00567     if (e == NULL) {
00568         Cudd_IterDerefBdd(manager, t);
00569         return(NULL);
00570     }
00571     cuddRef(e);
00572 
00573     if (topcube == top) {       /* abstract */
00574         r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
00575         if (r == NULL) {
00576             Cudd_IterDerefBdd(manager, t);
00577             Cudd_IterDerefBdd(manager, e);
00578             return(NULL);
00579         }
00580         r = Cudd_Not(r);
00581         cuddRef(r);
00582         Cudd_IterDerefBdd(manager, t);
00583         Cudd_IterDerefBdd(manager, e);
00584         cuddDeref(r);
00585     } else if (t == e) {
00586         r = t;
00587         cuddDeref(t);
00588         cuddDeref(e);
00589     } else {
00590         if (Cudd_IsComplement(t)) {
00591             r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
00592             if (r == NULL) {
00593                 Cudd_IterDerefBdd(manager, t);
00594                 Cudd_IterDerefBdd(manager, e);
00595                 return(NULL);
00596             }
00597             r = Cudd_Not(r);
00598         } else {
00599             r = cuddUniqueInter(manager,(int)index,t,e);
00600             if (r == NULL) {
00601                 Cudd_IterDerefBdd(manager, t);
00602                 Cudd_IterDerefBdd(manager, e);
00603                 return(NULL);
00604             }
00605         }
00606         cuddDeref(e);
00607         cuddDeref(t);
00608     }
00609     cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
00610     return (r);
00611 
00612 } /* end of cuddBddXorExistAbstractRecur */

DdNode* cuddBddXorRecur ( DdManager manager,
DdNode f,
DdNode g 
)

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

Synopsis [Implements the recursive step of Cudd_bddXor.]

Description [Implements the recursive step of Cudd_bddXor by taking the exclusive OR of two BDDs. Returns a pointer to the result is successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_bddXor]

Definition at line 1010 of file cuddBddIte.c.

01014 {
01015     DdNode *fv, *fnv, *G, *gv, *gnv;
01016     DdNode *one, *zero, *r, *t, *e;
01017     unsigned int topf, topg, index;
01018 
01019     statLine(manager);
01020     one = DD_ONE(manager);
01021     zero = Cudd_Not(one);
01022 
01023     /* Terminal cases. */
01024     if (f == g) return(zero);
01025     if (f == Cudd_Not(g)) return(one);
01026     if (f > g) { /* Try to increase cache efficiency and simplify tests. */
01027         DdNode *tmp = f;
01028         f = g;
01029         g = tmp;
01030     }
01031     if (g == zero) return(f);
01032     if (g == one) return(Cudd_Not(f));
01033     if (Cudd_IsComplement(f)) {
01034         f = Cudd_Not(f);
01035         g = Cudd_Not(g);
01036     }
01037     /* Now the first argument is regular. */
01038     if (f == one) return(Cudd_Not(g));
01039 
01040     /* At this point f and g are not constant. */
01041 
01042     /* Check cache. */
01043     r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
01044     if (r != NULL) return(r);
01045 
01046     /* Here we can skip the use of cuddI, because the operands are known
01047     ** to be non-constant.
01048     */
01049     topf = manager->perm[f->index];
01050     G = Cudd_Regular(g);
01051     topg = manager->perm[G->index];
01052 
01053     /* Compute cofactors. */
01054     if (topf <= topg) {
01055         index = f->index;
01056         fv = cuddT(f);
01057         fnv = cuddE(f);
01058     } else {
01059         index = G->index;
01060         fv = fnv = f;
01061     }
01062 
01063     if (topg <= topf) {
01064         gv = cuddT(G);
01065         gnv = cuddE(G);
01066         if (Cudd_IsComplement(g)) {
01067             gv = Cudd_Not(gv);
01068             gnv = Cudd_Not(gnv);
01069         }
01070     } else {
01071         gv = gnv = g;
01072     }
01073 
01074     t = cuddBddXorRecur(manager, fv, gv);
01075     if (t == NULL) return(NULL);
01076     cuddRef(t);
01077 
01078     e = cuddBddXorRecur(manager, fnv, gnv);
01079     if (e == NULL) {
01080         Cudd_IterDerefBdd(manager, t);
01081         return(NULL);
01082     }
01083     cuddRef(e);
01084 
01085     if (t == e) {
01086         r = t;
01087     } else {
01088         if (Cudd_IsComplement(t)) {
01089             r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
01090             if (r == NULL) {
01091                 Cudd_IterDerefBdd(manager, t);
01092                 Cudd_IterDerefBdd(manager, e);
01093                 return(NULL);
01094             }
01095             r = Cudd_Not(r);
01096         } else {
01097             r = cuddUniqueInter(manager,(int)index,t,e);
01098             if (r == NULL) {
01099                 Cudd_IterDerefBdd(manager, t);
01100                 Cudd_IterDerefBdd(manager, e);
01101                 return(NULL);
01102             }
01103         }
01104     }
01105     cuddDeref(e);
01106     cuddDeref(t);
01107     cuddCacheInsert2(manager, Cudd_bddXor, f, g, r);
01108     return(r);
01109 
01110 } /* end of cuddBddXorRecur */

DdNode* cuddBiasedUnderApprox ( DdManager dd,
DdNode f,
DdNode b,
int  numVars,
int  threshold,
double  quality1,
double  quality0 
)

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

Synopsis [Applies the biased remapping underappoximation algorithm.]

Description [Applies the biased remapping underappoximation algorithm. Proceeds in three phases:

  • collect information on each node in the BDD; this is done via DFS.
  • traverse the BDD in top-down fashion and compute for each node whether remapping increases density.
  • traverse the BDD via DFS and actually perform the elimination.

Returns the approximated BDD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_BiasedUnderApprox]

Definition at line 687 of file cuddApprox.c.

00695 {
00696     ApproxInfo *info;
00697     DdNode *subset;
00698     int result;
00699     DdHashTable *cache;
00700 
00701     if (f == NULL) {
00702         fprintf(dd->err, "Cannot subset, nil object\n");
00703         dd->errorCode = CUDD_INVALID_ARG;
00704         return(NULL);
00705     }
00706 
00707     if (Cudd_IsConstant(f)) {
00708         return(f);
00709     }
00710 
00711     /* Create table where node data are accessible via a hash table. */
00712     info = gatherInfo(dd, f, numVars, TRUE);
00713     if (info == NULL) {
00714         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00715         dd->errorCode = CUDD_MEMORY_OUT;
00716         return(NULL);
00717     }
00718 
00719     cache = cuddHashTableInit(dd,2,2);
00720     result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache);
00721     if (result == CARE_ERROR) {
00722         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00723         cuddHashTableQuit(cache);
00724         FREE(info->page);
00725         st_free_table(info->table);
00726         FREE(info);
00727         dd->errorCode = CUDD_MEMORY_OUT;
00728         return(NULL);
00729     }
00730     cuddHashTableQuit(cache);
00731 
00732     /* Mark nodes that should be replaced by zero. */
00733     result = BAmarkNodes(dd, f, info, threshold, quality1, quality0);
00734     if (result == 0) {
00735         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00736         FREE(info->page);
00737         st_free_table(info->table);
00738         FREE(info);
00739         dd->errorCode = CUDD_MEMORY_OUT;
00740         return(NULL);
00741     }
00742 
00743     /* Build the result. */
00744     subset = RAbuildSubset(dd, f, info);
00745 #if 1
00746     if (subset && info->size < Cudd_DagSize(subset))
00747         (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00748                        info->size, Cudd_DagSize(subset));
00749 #endif
00750     FREE(info->page);
00751     st_free_table(info->table);
00752     FREE(info);
00753 
00754 #ifdef DD_DEBUG
00755     if (subset != NULL) {
00756         cuddRef(subset);
00757 #if 0
00758         (void) Cudd_DebugCheck(dd);
00759         (void) Cudd_CheckKeys(dd);
00760 #endif
00761         if (!Cudd_bddLeq(dd, subset, f)) {
00762             (void) fprintf(dd->err, "Wrong subset\n");
00763         }
00764         cuddDeref(subset);
00765         dd->errorCode = CUDD_INTERNAL_ERROR;
00766     }
00767 #endif
00768     return(subset);
00769 
00770 } /* end of cuddBiasedUnderApprox */

void cuddCacheFlush ( DdManager table  ) 

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

Synopsis [Flushes the cache.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 1001 of file cuddCache.c.

01003 {
01004     int i, slots;
01005     DdCache *cache;
01006 
01007     slots = table->cacheSlots;
01008     cache = table->cache;
01009     for (i = 0; i < slots; i++) {
01010         table->cachedeletions += cache[i].data != NULL;
01011         cache[i].data = NULL;
01012     }
01013     table->cacheLastInserts = table->cacheinserts;
01014 
01015     return;
01016 
01017 } /* end of cuddCacheFlush */

void cuddCacheInsert ( DdManager table,
ptruint  op,
DdNode f,
DdNode g,
DdNode h,
DdNode data 
)

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

Synopsis [Inserts a result in the cache.]

Description []

SideEffects [None]

SeeAlso [cuddCacheInsert2 cuddCacheInsert1]

Definition at line 214 of file cuddCache.c.

00221 {
00222     int posn;
00223     register DdCache *entry;
00224     ptruint uf, ug, uh;
00225 
00226     uf = (ptruint) f | (op & 0xe);
00227     ug = (ptruint) g | (op >> 4);
00228     uh = (ptruint) h;
00229 
00230     posn = ddCHash2(uh,uf,ug,table->cacheShift);
00231     entry = &table->cache[posn];
00232 
00233     table->cachecollisions += entry->data != NULL;
00234     table->cacheinserts++;
00235 
00236     entry->f    = (DdNode *) uf;
00237     entry->g    = (DdNode *) ug;
00238     entry->h    = uh;
00239     entry->data = data;
00240 #ifdef DD_CACHE_PROFILE
00241     entry->count++;
00242 #endif
00243 
00244 } /* end of cuddCacheInsert */

void cuddCacheInsert1 ( DdManager table,
DdNode *)(DdManager *, DdNode *,
DdNode f,
DdNode data 
)
void cuddCacheInsert2 ( DdManager table,
DdNode *)(DdManager *, DdNode *, DdNode *,
DdNode f,
DdNode g,
DdNode data 
)
DdNode* cuddCacheLookup ( DdManager table,
ptruint  op,
DdNode f,
DdNode g,
DdNode h 
)

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

Synopsis [Looks up in the cache for the result of op applied to f, g, and h.]

Description [Returns the result if found; it returns NULL if no result is found.]

SideEffects [None]

SeeAlso [cuddCacheLookup2 cuddCacheLookup1]

Definition at line 344 of file cuddCache.c.

00350 {
00351     int posn;
00352     DdCache *en,*cache;
00353     DdNode *data;
00354     ptruint uf, ug, uh;
00355 
00356     uf = (ptruint) f | (op & 0xe);
00357     ug = (ptruint) g | (op >> 4);
00358     uh = (ptruint) h;
00359 
00360     cache = table->cache;
00361 #ifdef DD_DEBUG
00362     if (cache == NULL) {
00363         return(NULL);
00364     }
00365 #endif
00366 
00367     posn = ddCHash2(uh,uf,ug,table->cacheShift);
00368     en = &cache[posn];
00369     if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
00370         en->h==uh) {
00371         data = Cudd_Regular(en->data);
00372         table->cacheHits++;
00373         if (data->ref == 0) {
00374             cuddReclaim(table,data);
00375         }
00376         return(en->data);
00377     }
00378 
00379     /* Cache miss: decide whether to resize. */
00380     table->cacheMisses++;
00381 
00382     if (table->cacheSlack >= 0 &&
00383         table->cacheHits > table->cacheMisses * table->minHit) {
00384         cuddCacheResize(table);
00385     }
00386 
00387     return(NULL);
00388 
00389 } /* end of cuddCacheLookup */

DdNode* cuddCacheLookup1 ( DdManager table,
DdNode *)(DdManager *, DdNode *,
DdNode f 
)
DdNode* cuddCacheLookup1Zdd ( DdManager table,
DdNode *)(DdManager *, DdNode *,
DdNode f 
)
DdNode* cuddCacheLookup2 ( DdManager table,
DdNode *)(DdManager *, DdNode *, DdNode *,
DdNode f,
DdNode g 
)
DdNode* cuddCacheLookup2Zdd ( DdManager table,
DdNode *)(DdManager *, DdNode *, DdNode *,
DdNode f,
DdNode g 
)
DdNode* cuddCacheLookupZdd ( DdManager table,
ptruint  op,
DdNode f,
DdNode g,
DdNode h 
)

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

Synopsis [Looks up in the cache for the result of op applied to f, g, and h.]

Description [Returns the result if found; it returns NULL if no result is found.]

SideEffects [None]

SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd]

Definition at line 406 of file cuddCache.c.

00412 {
00413     int posn;
00414     DdCache *en,*cache;
00415     DdNode *data;
00416     ptruint uf, ug, uh;
00417 
00418     uf = (ptruint) f | (op & 0xe);
00419     ug = (ptruint) g | (op >> 4);
00420     uh = (ptruint) h;
00421 
00422     cache = table->cache;
00423 #ifdef DD_DEBUG
00424     if (cache == NULL) {
00425         return(NULL);
00426     }
00427 #endif
00428 
00429     posn = ddCHash2(uh,uf,ug,table->cacheShift);
00430     en = &cache[posn];
00431     if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
00432         en->h==uh) {
00433         data = Cudd_Regular(en->data);
00434         table->cacheHits++;
00435         if (data->ref == 0) {
00436             cuddReclaimZdd(table,data);
00437         }
00438         return(en->data);
00439     }
00440 
00441     /* Cache miss: decide whether to resize. */
00442     table->cacheMisses++;
00443 
00444     if (table->cacheSlack >= 0 &&
00445         table->cacheHits > table->cacheMisses * table->minHit) {
00446         cuddCacheResize(table);
00447     }
00448 
00449     return(NULL);
00450 
00451 } /* end of cuddCacheLookupZdd */

int cuddCacheProfile ( DdManager table,
FILE *  fp 
)

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

Synopsis [Computes and prints a profile of the cache usage.]

Description [Computes and prints a profile of the cache usage. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 746 of file cuddCache.c.

00749 {
00750     DdCache *cache = table->cache;
00751     int slots = table->cacheSlots;
00752     int nzeroes = 0;
00753     int i, retval;
00754     double exUsed;
00755 
00756 #ifdef DD_CACHE_PROFILE
00757     double count, mean, meansq, stddev, expected;
00758     long max, min;
00759     int imax, imin;
00760     double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */
00761     int nbins = DD_HYSTO_BINS;
00762     int bin;
00763     long thiscount;
00764     double totalcount, exStddev;
00765 
00766     meansq = mean = expected = 0.0;
00767     max = min = (long) cache[0].count;
00768     imax = imin = 0;
00769     totalcount = 0.0;
00770 
00771     hystogramQ = ALLOC(double, nbins);
00772     if (hystogramQ == NULL) {
00773         table->errorCode = CUDD_MEMORY_OUT;
00774         return(0);
00775     }
00776     hystogramR = ALLOC(double, nbins);
00777     if (hystogramR == NULL) {
00778         FREE(hystogramQ);
00779         table->errorCode = CUDD_MEMORY_OUT;
00780         return(0);
00781     }
00782     for (i = 0; i < nbins; i++) {
00783         hystogramQ[i] = 0;
00784         hystogramR[i] = 0;
00785     }
00786 
00787     for (i = 0; i < slots; i++) {
00788         thiscount = (long) cache[i].count;
00789         if (thiscount > max) {
00790             max = thiscount;
00791             imax = i;
00792         }
00793         if (thiscount < min) {
00794             min = thiscount;
00795             imin = i;
00796         }
00797         if (thiscount == 0) {
00798             nzeroes++;
00799         }
00800         count = (double) thiscount;
00801         mean += count;
00802         meansq += count * count;
00803         totalcount += count;
00804         expected += count * (double) i;
00805         bin = (i * nbins) / slots;
00806         hystogramQ[bin] += (double) thiscount;
00807         bin = i % nbins;
00808         hystogramR[bin] += (double) thiscount;
00809     }
00810     mean /= (double) slots;
00811     meansq /= (double) slots;
00812 
00813     /* Compute the standard deviation from both the data and the
00814     ** theoretical model for a random distribution. */
00815     stddev = sqrt(meansq - mean*mean);
00816     exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots);
00817 
00818     retval = fprintf(fp,"Cache average accesses = %g\n",  mean);
00819     if (retval == EOF) return(0);
00820     retval = fprintf(fp,"Cache access standard deviation = %g ", stddev);
00821     if (retval == EOF) return(0);
00822     retval = fprintf(fp,"(expected = %g)\n", exStddev);
00823     if (retval == EOF) return(0);
00824     retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
00825     if (retval == EOF) return(0);
00826     retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
00827     if (retval == EOF) return(0);
00828     exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots));
00829     retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
00830                      100.0 - (double) nzeroes * 100.0 / (double) slots,
00831                      exUsed);
00832     if (retval == EOF) return(0);
00833 
00834     if (totalcount > 0) {
00835         expected /= totalcount;
00836         retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
00837         if (retval == EOF) return(0);
00838         retval = fprintf(fp," (expected bin value = %g)\nBy quotient:",
00839                          expected);
00840         if (retval == EOF) return(0);
00841         for (i = nbins - 1; i>=0; i--) {
00842             retval = fprintf(fp," %.0f", hystogramQ[i]);
00843             if (retval == EOF) return(0);
00844         }
00845         retval = fprintf(fp,"\nBy residue: ");
00846         if (retval == EOF) return(0);
00847         for (i = nbins - 1; i>=0; i--) {
00848             retval = fprintf(fp," %.0f", hystogramR[i]);
00849             if (retval == EOF) return(0);
00850         }
00851         retval = fprintf(fp,"\n");
00852         if (retval == EOF) return(0);
00853     }
00854 
00855     FREE(hystogramQ);
00856     FREE(hystogramR);
00857 #else
00858     for (i = 0; i < slots; i++) {
00859         nzeroes += cache[i].h == 0;
00860     }
00861     exUsed = 100.0 *
00862         (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) /
00863                    (double) slots));
00864     retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
00865                      100.0 - (double) nzeroes * 100.0 / (double) slots,
00866                      exUsed);
00867     if (retval == EOF) return(0);
00868 #endif
00869     return(1);
00870 
00871 } /* end of cuddCacheProfile */

void cuddCacheResize ( DdManager table  ) 

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

Synopsis [Resizes the cache.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 886 of file cuddCache.c.

00888 {
00889     DdCache *cache, *oldcache, *oldacache, *entry, *old;
00890     int i;
00891     int posn, shift;
00892     unsigned int slots, oldslots;
00893     double offset;
00894     int moved = 0;
00895     extern DD_OOMFP MMoutOfMemory;
00896     DD_OOMFP saveHandler;
00897 #ifndef DD_CACHE_PROFILE
00898     ptruint misalignment;
00899     DdNodePtr *mem;
00900 #endif
00901 
00902     oldcache = table->cache;
00903     oldacache = table->acache;
00904     oldslots = table->cacheSlots;
00905     slots = table->cacheSlots = oldslots << 1;
00906 
00907 #ifdef DD_VERBOSE
00908     (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n",
00909                    oldslots, slots);
00910     (void) fprintf(table->err,
00911                    "\thits = %g\tmisses = %g\thit ratio = %5.3f\n",
00912                    table->cacheHits, table->cacheMisses,
00913                    table->cacheHits / (table->cacheHits + table->cacheMisses));
00914 #endif
00915 
00916     saveHandler = MMoutOfMemory;
00917     MMoutOfMemory = Cudd_OutOfMem;
00918     table->acache = cache = ALLOC(DdCache,slots+1);
00919     MMoutOfMemory = saveHandler;
00920     /* If we fail to allocate the new table we just give up. */
00921     if (cache == NULL) {
00922 #ifdef DD_VERBOSE
00923         (void) fprintf(table->err,"Resizing failed. Giving up.\n");
00924 #endif
00925         table->cacheSlots = oldslots;
00926         table->acache = oldacache;
00927         /* Do not try to resize again. */
00928         table->maxCacheHard = oldslots - 1;
00929         table->cacheSlack = - (int) (oldslots + 1);
00930         return;
00931     }
00932     /* If the size of the cache entry is a power of 2, we want to
00933     ** enforce alignment to that power of two. This happens when
00934     ** DD_CACHE_PROFILE is not defined. */
00935 #ifdef DD_CACHE_PROFILE
00936     table->cache = cache;
00937 #else
00938     mem = (DdNodePtr *) cache;
00939     misalignment = (ptruint) mem & (sizeof(DdCache) - 1);
00940     mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr);
00941     table->cache = cache = (DdCache *) mem;
00942     assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0);
00943 #endif
00944     shift = --(table->cacheShift);
00945     table->memused += (slots - oldslots) * sizeof(DdCache);
00946     table->cacheSlack -= slots; /* need these many slots to double again */
00947 
00948     /* Clear new cache. */
00949     for (i = 0; (unsigned) i < slots; i++) {
00950         cache[i].data = NULL;
00951         cache[i].h = 0;
00952 #ifdef DD_CACHE_PROFILE
00953         cache[i].count = 0;
00954 #endif
00955     }
00956 
00957     /* Copy from old cache to new one. */
00958     for (i = 0; (unsigned) i < oldslots; i++) {
00959         old = &oldcache[i];
00960         if (old->data != NULL) {
00961             posn = ddCHash2(old->h,old->f,old->g,shift);
00962             entry = &cache[posn];
00963             entry->f = old->f;
00964             entry->g = old->g;
00965             entry->h = old->h;
00966             entry->data = old->data;
00967 #ifdef DD_CACHE_PROFILE
00968             entry->count = 1;
00969 #endif
00970             moved++;
00971         }
00972     }
00973 
00974     FREE(oldacache);
00975 
00976     /* Reinitialize measurements so as to avoid division by 0 and
00977     ** immediate resizing.
00978     */
00979     offset = (double) (int) (slots * table->minHit + 1);
00980     table->totCacheMisses += table->cacheMisses - offset;
00981     table->cacheMisses = offset;
00982     table->totCachehits += table->cacheHits;
00983     table->cacheHits = 0;
00984     table->cacheLastInserts = table->cacheinserts - (double) moved;
00985 
00986 } /* end of cuddCacheResize */

int cuddCheckCube ( DdManager dd,
DdNode g 
)

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

Synopsis [Checks whether g is the BDD of a cube.]

Description [Checks whether g is the BDD of a cube. Returns 1 in case of success; 0 otherwise. The constant 1 is a valid cube, but all other constant functions cause cuddCheckCube to return 0.]

SideEffects [None]

SeeAlso []

Definition at line 189 of file cuddCof.c.

00192 {
00193     DdNode *g1,*g0,*one,*zero;
00194     
00195     one = DD_ONE(dd);
00196     if (g == one) return(1);
00197     if (Cudd_IsConstant(g)) return(0);
00198 
00199     zero = Cudd_Not(one);
00200     cuddGetBranches(g,&g1,&g0);
00201 
00202     if (g0 == zero) {
00203         return(cuddCheckCube(dd, g1));
00204     }
00205     if (g1 == zero) {
00206         return(cuddCheckCube(dd, g0));
00207     }
00208     return(0);
00209 
00210 } /* end of cuddCheckCube */

void cuddClearDeathRow ( DdManager table  ) 

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

Synopsis [Clears the death row.]

Description []

SideEffects [None]

SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef cuddGarbageCollect]

Definition at line 722 of file cuddRef.c.

00724 {
00725 #ifndef DD_NO_DEATH_ROW
00726     int i;
00727 
00728     for (i = 0; i < table->deathRowDepth; i++) {
00729         if (table->deathRow[i] == NULL) break;
00730         Cudd_IterDerefBdd(table,table->deathRow[i]);
00731         table->deathRow[i] = NULL;
00732     }
00733 #ifdef DD_DEBUG
00734     for (; i < table->deathRowDepth; i++) {
00735         assert(table->deathRow[i] == NULL);
00736     }
00737 #endif
00738     table->nextDead = 0;
00739 #endif
00740 
00741 } /* end of cuddClearDeathRow */

DdNode* cuddCofactorRecur ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_Cofactor.]

Description [Performs the recursive step of Cudd_Cofactor. Returns a pointer to the cofactor if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_Cofactor]

Definition at line 226 of file cuddCof.c.

00230 {
00231     DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r;
00232     unsigned int topf,topg;
00233     int comple;
00234 
00235     statLine(dd);
00236     F = Cudd_Regular(f);
00237     if (cuddIsConstant(F)) return(f);
00238 
00239     one = DD_ONE(dd);
00240 
00241     /* The invariant g != 0 is true on entry to this procedure and is
00242     ** recursively maintained by it. Therefore it suffices to test g
00243     ** against one to make sure it is not constant.
00244     */
00245     if (g == one) return(f);
00246     /* From now on, f and g are known not to be constants. */
00247 
00248     comple = f != F;
00249     r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g);
00250     if (r != NULL) {
00251         return(Cudd_NotCond(r,comple));
00252     }
00253 
00254     topf = dd->perm[F->index];
00255     G = Cudd_Regular(g);
00256     topg = dd->perm[G->index];
00257 
00258     /* We take the cofactors of F because we are going to rely on
00259     ** the fact that the cofactors of the complement are the complements
00260     ** of the cofactors to better utilize the cache. Variable comple
00261     ** remembers whether we have to complement the result or not.
00262     */
00263     if (topf <= topg) {
00264         f1 = cuddT(F); f0 = cuddE(F);
00265     } else {
00266         f1 = f0 = F;
00267     }
00268     if (topg <= topf) {
00269         g1 = cuddT(G); g0 = cuddE(G);
00270         if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); }
00271     } else {
00272         g1 = g0 = g;
00273     }
00274 
00275     zero = Cudd_Not(one);
00276     if (topf >= topg) {
00277         if (g0 == zero || g0 == DD_ZERO(dd)) {
00278             r = cuddCofactorRecur(dd, f1, g1);
00279         } else if (g1 == zero || g1 == DD_ZERO(dd)) {
00280             r = cuddCofactorRecur(dd, f0, g0);
00281         } else {
00282             (void) fprintf(dd->out,
00283                            "Cudd_Cofactor: Invalid restriction 2\n");
00284             dd->errorCode = CUDD_INVALID_ARG;
00285             return(NULL);
00286         }
00287         if (r == NULL) return(NULL);
00288     } else /* if (topf < topg) */ {
00289         t = cuddCofactorRecur(dd, f1, g);
00290         if (t == NULL) return(NULL);
00291         cuddRef(t);
00292         e = cuddCofactorRecur(dd, f0, g);
00293         if (e == NULL) {
00294             Cudd_RecursiveDeref(dd, t);
00295             return(NULL);
00296         }
00297         cuddRef(e);
00298 
00299         if (t == e) {
00300             r = t;
00301         } else if (Cudd_IsComplement(t)) {
00302             r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e));
00303             if (r != NULL)
00304                 r = Cudd_Not(r);
00305         } else {
00306             r = cuddUniqueInter(dd,(int)F->index,t,e);
00307         }
00308         if (r == NULL) {
00309             Cudd_RecursiveDeref(dd ,e);
00310             Cudd_RecursiveDeref(dd ,t);
00311             return(NULL);
00312         }
00313         cuddDeref(t);
00314         cuddDeref(e);
00315     }
00316 
00317     cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r);
00318 
00319     return(Cudd_NotCond(r,comple));
00320 
00321 } /* end of cuddCofactorRecur */

int cuddComputeFloorLog2 ( unsigned int  value  ) 

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

Synopsis [Returns the floor of the logarithm to the base 2.]

Description [Returns the floor of the logarithm to the base 2. The input value is assumed to be greater than 0.]

SideEffects [None]

SeeAlso []

Definition at line 1033 of file cuddCache.c.

01035 {
01036     int floorLog = 0;
01037 #ifdef DD_DEBUG
01038     assert(value > 0);
01039 #endif
01040     while (value > 1) {
01041         floorLog++;
01042         value >>= 1;
01043     }
01044     return(floorLog);
01045 
01046 } /* end of cuddComputeFloorLog2 */

DdNode* cuddConstantLookup ( DdManager table,
ptruint  op,
DdNode f,
DdNode g,
DdNode h 
)

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

Synopsis [Looks up in the cache for the result of op applied to f, g, and h.]

Description [Looks up in the cache for the result of op applied to f, g, and h. Assumes that the calling procedure (e.g., Cudd_bddIteConstant) is only interested in whether the result is constant or not. Returns the result if found (possibly DD_NON_CONSTANT); otherwise it returns NULL.]

SideEffects [None]

SeeAlso [cuddCacheLookup]

Definition at line 687 of file cuddCache.c.

00693 {
00694     int posn;
00695     DdCache *en,*cache;
00696     ptruint uf, ug, uh;
00697 
00698     uf = (ptruint) f | (op & 0xe);
00699     ug = (ptruint) g | (op >> 4);
00700     uh = (ptruint) h;
00701 
00702     cache = table->cache;
00703 #ifdef DD_DEBUG
00704     if (cache == NULL) {
00705         return(NULL);
00706     }
00707 #endif
00708     posn = ddCHash2(uh,uf,ug,table->cacheShift);
00709     en = &cache[posn];
00710 
00711     /* We do not reclaim here because the result should not be
00712      * referenced, but only tested for being a constant.
00713      */
00714     if (en->data != NULL &&
00715         en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) {
00716         table->cacheHits++;
00717         return(en->data);
00718     }
00719 
00720     /* Cache miss: decide whether to resize. */
00721     table->cacheMisses++;
00722 
00723     if (table->cacheSlack >= 0 &&
00724         table->cacheHits > table->cacheMisses * table->minHit) {
00725         cuddCacheResize(table);
00726     }
00727 
00728     return(NULL);
00729 
00730 } /* end of cuddConstantLookup */

DdNode* cuddCProjectionRecur ( DdManager dd,
DdNode R,
DdNode Y,
DdNode Ysupp 
)

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

Synopsis [Performs the recursive step of Cudd_CProjection.]

Description [Performs the recursive step of Cudd_CProjection. Returns the projection if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_CProjection]

Definition at line 1421 of file cuddPriority.c.

01426 {
01427     DdNode *res, *res1, *res2, *resA;
01428     DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha;
01429     unsigned int topR, topY, top, index;
01430     DdNode *one = DD_ONE(dd);
01431 
01432     statLine(dd);
01433     if (Y == one) return(R);
01434 
01435 #ifdef DD_DEBUG
01436     assert(!Cudd_IsConstant(Y));
01437 #endif
01438 
01439     if (R == Cudd_Not(one)) return(R);
01440 
01441     res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y);
01442     if (res != NULL) return(res);
01443 
01444     r = Cudd_Regular(R);
01445     topR = cuddI(dd,r->index);
01446     y = Cudd_Regular(Y);
01447     topY = cuddI(dd,y->index);
01448 
01449     top = ddMin(topR, topY);
01450 
01451     /* Compute the cofactors of R */
01452     if (topR == top) {
01453         index = r->index;
01454         RT = cuddT(r);
01455         RE = cuddE(r);
01456         if (r != R) {
01457             RT = Cudd_Not(RT); RE = Cudd_Not(RE);
01458         }
01459     } else {
01460         RT = RE = R;
01461     }
01462 
01463     if (topY > top) {
01464         /* Y does not depend on the current top variable.
01465         ** We just need to compute the results on the two cofactors of R
01466         ** and make them the children of a node labeled r->index.
01467         */
01468         res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp);
01469         if (res1 == NULL) return(NULL);
01470         cuddRef(res1);
01471         res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp);
01472         if (res2 == NULL) {
01473             Cudd_RecursiveDeref(dd,res1);
01474             return(NULL);
01475         }
01476         cuddRef(res2);
01477         res = cuddBddIteRecur(dd, dd->vars[index], res1, res2);
01478         if (res == NULL) {
01479             Cudd_RecursiveDeref(dd,res1);
01480             Cudd_RecursiveDeref(dd,res2);
01481             return(NULL);
01482         }
01483         /* If we have reached this point, res1 and res2 are now
01484         ** incorporated in res. cuddDeref is therefore sufficient.
01485         */
01486         cuddDeref(res1);
01487         cuddDeref(res2);
01488     } else {
01489         /* Compute the cofactors of Y */
01490         index = y->index;
01491         YT = cuddT(y);
01492         YE = cuddE(y);
01493         if (y != Y) {
01494             YT = Cudd_Not(YT); YE = Cudd_Not(YE);
01495         }
01496         if (YT == Cudd_Not(one)) {
01497             Alpha  = Cudd_Not(dd->vars[index]);
01498             Yrest = YE;
01499             Ra = RE;
01500             Ran = RT;
01501         } else {
01502             Alpha = dd->vars[index];
01503             Yrest = YT;
01504             Ra = RT;
01505             Ran = RE;
01506         }
01507         Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp));
01508         if (Gamma == NULL) return(NULL);
01509         if (Gamma == one) {
01510             res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
01511             if (res1 == NULL) return(NULL);
01512             cuddRef(res1);
01513             res = cuddBddAndRecur(dd, Alpha, res1);
01514             if (res == NULL) {
01515                 Cudd_RecursiveDeref(dd,res1);
01516                 return(NULL);
01517             }
01518             cuddDeref(res1);
01519         } else if (Gamma == Cudd_Not(one)) {
01520             res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
01521             if (res1 == NULL) return(NULL);
01522             cuddRef(res1);
01523             res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1);
01524             if (res == NULL) {
01525                 Cudd_RecursiveDeref(dd,res1);
01526                 return(NULL);
01527             }
01528             cuddDeref(res1);
01529         } else {
01530             cuddRef(Gamma);
01531             resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
01532             if (resA == NULL) {
01533                 Cudd_RecursiveDeref(dd,Gamma);
01534                 return(NULL);
01535             }
01536             cuddRef(resA);
01537             res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA);
01538             if (res2 == NULL) {
01539                 Cudd_RecursiveDeref(dd,Gamma);
01540                 Cudd_RecursiveDeref(dd,resA);
01541                 return(NULL);
01542             }
01543             cuddRef(res2);
01544             Cudd_RecursiveDeref(dd,Gamma);
01545             Cudd_RecursiveDeref(dd,resA);
01546             res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
01547             if (res1 == NULL) {
01548                 Cudd_RecursiveDeref(dd,res2);
01549                 return(NULL);
01550             }
01551             cuddRef(res1);
01552             res = cuddBddIteRecur(dd, Alpha, res1, res2);
01553             if (res == NULL) {
01554                 Cudd_RecursiveDeref(dd,res1);
01555                 Cudd_RecursiveDeref(dd,res2);
01556                 return(NULL);
01557             }
01558             cuddDeref(res1);
01559             cuddDeref(res2);
01560         }
01561     }
01562 
01563     cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res);
01564 
01565     return(res);
01566 
01567 } /* end of cuddCProjectionRecur */

int cuddDestroySubtables ( DdManager unique,
int  n 
)

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

Synopsis [Destroys the n most recently created subtables in a unique table.]

Description [Destroys the n most recently created subtables in a unique table. n should be positive. The subtables should not contain any live nodes, except the (isolated) projection function. The projection functions are freed. Returns 1 if successful; 0 otherwise.]

SideEffects [The variable map used for fast variable substitution is destroyed if it exists. In this case the cache is also cleared.]

SeeAlso [cuddInsertSubtables Cudd_SetVarMap]

Definition at line 2093 of file cuddTable.c.

02096 {
02097     DdSubtable *subtables;
02098     DdNodePtr *nodelist;
02099     DdNodePtr *vars;
02100     int firstIndex, lastIndex;
02101     int index, level, newlevel;
02102     int lowestLevel;
02103     int shift;
02104     int found;
02105 
02106     /* Sanity check and set up. */
02107     if (n <= 0) return(0);
02108     if (n > unique->size) n = unique->size;
02109 
02110     subtables = unique->subtables;
02111     vars = unique->vars;
02112     firstIndex = unique->size - n;
02113     lastIndex  = unique->size;
02114 
02115     /* Check for nodes labeled by the variables being destroyed
02116     ** that may still be in use.  It is allowed to destroy a variable
02117     ** only if there are no such nodes. Also, find the lowest level
02118     ** among the variables being destroyed. This will make further
02119     ** processing more efficient.
02120     */
02121     lowestLevel = unique->size;
02122     for (index = firstIndex; index < lastIndex; index++) {
02123         level = unique->perm[index];
02124         if (level < lowestLevel) lowestLevel = level;
02125         nodelist = subtables[level].nodelist;
02126         if (subtables[level].keys - subtables[level].dead != 1) return(0);
02127         /* The projection function should be isolated. If the ref count
02128         ** is 1, everything is OK. If the ref count is saturated, then
02129         ** we need to make sure that there are no nodes pointing to it.
02130         ** As for the external references, we assume the application is
02131         ** responsible for them.
02132         */
02133         if (vars[index]->ref != 1) {
02134             if (vars[index]->ref != DD_MAXREF) return(0);
02135             found = cuddFindParent(unique,vars[index]);
02136             if (found) {
02137                 return(0);
02138             } else {
02139                 vars[index]->ref = 1;
02140             }
02141         }
02142         Cudd_RecursiveDeref(unique,vars[index]);
02143     }
02144 
02145     /* Collect garbage, because we cannot afford having dead nodes pointing
02146     ** to the dead nodes in the subtables being destroyed.
02147     */
02148     (void) cuddGarbageCollect(unique,1);
02149 
02150     /* Here we know we can destroy our subtables. */
02151     for (index = firstIndex; index < lastIndex; index++) {
02152         level = unique->perm[index];
02153         nodelist = subtables[level].nodelist;
02154 #ifdef DD_DEBUG
02155         assert(subtables[level].keys == 0);
02156 #endif
02157         FREE(nodelist);
02158         unique->memused -= sizeof(DdNodePtr) * subtables[level].slots;
02159         unique->slots -= subtables[level].slots;
02160         unique->dead -= subtables[level].dead;
02161     }
02162 
02163     /* Here all subtables to be destroyed have their keys field == 0 and
02164     ** their hash tables have been freed.
02165     ** We now scan the subtables from level lowestLevel + 1 to level size - 1,
02166     ** shifting the subtables as required. We keep a running count of
02167     ** how many subtables have been moved, so that we know by how many
02168     ** positions each subtable should be shifted.
02169     */
02170     shift = 1;
02171     for (level = lowestLevel + 1; level < unique->size; level++) {
02172         if (subtables[level].keys == 0) {
02173             shift++;
02174             continue;
02175         }
02176         newlevel = level - shift;
02177         subtables[newlevel].slots = subtables[level].slots;
02178         subtables[newlevel].shift = subtables[level].shift;
02179         subtables[newlevel].keys = subtables[level].keys;
02180         subtables[newlevel].maxKeys = subtables[level].maxKeys;
02181         subtables[newlevel].dead = subtables[level].dead;
02182         subtables[newlevel].nodelist = subtables[level].nodelist;
02183         index = unique->invperm[level];
02184         unique->perm[index] = newlevel;
02185         unique->invperm[newlevel]  = index;
02186         subtables[newlevel].bindVar = subtables[level].bindVar;
02187         subtables[newlevel].varType = subtables[level].varType;
02188         subtables[newlevel].pairIndex = subtables[level].pairIndex;
02189         subtables[newlevel].varHandled = subtables[level].varHandled;
02190         subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped;
02191     }
02192     /* Destroy the map. If a surviving variable is
02193     ** mapped to a dying variable, and the map were used again,
02194     ** an out-of-bounds access to unique->vars would result. */
02195     if (unique->map != NULL) {
02196         cuddCacheFlush(unique);
02197         FREE(unique->map);
02198         unique->map = NULL;
02199     }
02200 
02201     unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
02202     unique->size -= n;
02203 
02204     return(1);
02205 
02206 } /* end of cuddDestroySubtables */

DdNode* cuddDynamicAllocNode ( DdManager table  ) 

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

Synopsis [Dynamically allocates a Node.]

Description [Dynamically allocates a Node. This procedure is similar to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage collection, because during reordering there are no dead nodes. Returns a pointer to a new node if successful; NULL is memory is full.]

SideEffects [None]

SeeAlso [cuddAllocNode]

Definition at line 402 of file cuddReorder.c.

00404 {
00405     int     i;
00406     DdNodePtr *mem;
00407     DdNode *list, *node;
00408     extern DD_OOMFP MMoutOfMemory;
00409     DD_OOMFP saveHandler;
00410 
00411     if (table->nextFree == NULL) {        /* free list is empty */
00412         /* Try to allocate a new block. */
00413         saveHandler = MMoutOfMemory;
00414         MMoutOfMemory = Cudd_OutOfMem;
00415         mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1);
00416         MMoutOfMemory = saveHandler;
00417         if (mem == NULL && table->stash != NULL) {
00418             FREE(table->stash);
00419             table->stash = NULL;
00420             /* Inhibit resizing of tables. */
00421             table->maxCacheHard = table->cacheSlots - 1;
00422             table->cacheSlack = - (int) (table->cacheSlots + 1);
00423             for (i = 0; i < table->size; i++) {
00424                 table->subtables[i].maxKeys <<= 2;
00425             }
00426             mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
00427         }
00428         if (mem == NULL) {
00429             /* Out of luck. Call the default handler to do
00430             ** whatever it specifies for a failed malloc.  If this
00431             ** handler returns, then set error code, print
00432             ** warning, and return. */
00433             (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
00434             table->errorCode = CUDD_MEMORY_OUT;
00435 #ifdef DD_VERBOSE
00436             (void) fprintf(table->err,
00437                            "cuddDynamicAllocNode: out of memory");
00438             (void) fprintf(table->err,"Memory in use = %lu\n",
00439                            table->memused);
00440 #endif
00441             return(NULL);
00442         } else {        /* successful allocation; slice memory */
00443             unsigned long offset;
00444             table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
00445             mem[0] = (DdNode *) table->memoryList;
00446             table->memoryList = mem;
00447 
00448             /* Here we rely on the fact that the size of a DdNode is a
00449             ** power of 2 and a multiple of the size of a pointer.
00450             ** If we align one node, all the others will be aligned
00451             ** as well. */
00452             offset = (unsigned long) mem & (sizeof(DdNode) - 1);
00453             mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
00454 #ifdef DD_DEBUG
00455             assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
00456 #endif
00457             list = (DdNode *) mem;
00458 
00459             i = 1;
00460             do {
00461                 list[i - 1].ref = 0;
00462                 list[i - 1].next = &list[i];
00463             } while (++i < DD_MEM_CHUNK);
00464 
00465             list[DD_MEM_CHUNK-1].ref = 0;
00466             list[DD_MEM_CHUNK - 1].next = NULL;
00467 
00468             table->nextFree = &list[0];
00469         }
00470     } /* if free list empty */
00471 
00472     node = table->nextFree;
00473     table->nextFree = node->next;
00474     return (node);
00475 
00476 } /* end of cuddDynamicAllocNode */

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

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

Synopsis [Exact variable ordering algorithm.]

Description [Exact variable ordering algorithm. Finds an optimum order for the variables between lower and upper. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 149 of file cuddExact.c.

00153 {
00154     int k, i, j;
00155     int maxBinomial, oldSubsets, newSubsets;
00156     int subsetCost;
00157     int size;                   /* number of variables to be reordered */
00158     int unused, nvars, level, result;
00159     int upperBound, lowerBound, cost;
00160     int roots;
00161     char *mask = NULL;
00162     DdHalfWord  *symmInfo = NULL;
00163     DdHalfWord **newOrder = NULL;
00164     DdHalfWord **oldOrder = NULL;
00165     int *newCost = NULL;
00166     int *oldCost = NULL;
00167     DdHalfWord **tmpOrder;
00168     int *tmpCost;
00169     DdHalfWord *bestOrder = NULL;
00170     DdHalfWord *order;
00171 #ifdef DD_STATS
00172     int  ddTotalSubsets;
00173 #endif
00174 
00175     /* Restrict the range to be reordered by excluding unused variables
00176     ** at the two ends. */
00177     while (table->subtables[lower].keys == 1 &&
00178            table->vars[table->invperm[lower]]->ref == 1 &&
00179            lower < upper)
00180         lower++;
00181     while (table->subtables[upper].keys == 1 &&
00182            table->vars[table->invperm[upper]]->ref == 1 &&
00183            lower < upper)
00184         upper--;
00185     if (lower == upper) return(1); /* trivial problem */
00186 
00187     /* Apply symmetric sifting to get a good upper bound and to extract
00188     ** symmetry information. */
00189     result = cuddSymmSiftingConv(table,lower,upper);
00190     if (result == 0) goto cuddExactOutOfMem;
00191 
00192 #ifdef DD_STATS
00193     (void) fprintf(table->out,"\n");
00194     ddTotalShuffles = 0;
00195     ddTotalSubsets = 0;
00196 #endif
00197 
00198     /* Initialization. */
00199     nvars = table->size;
00200     size = upper - lower + 1;
00201     /* Count unused variable among those to be reordered.  This is only
00202     ** used to compute maxBinomial. */
00203     unused = 0;
00204     for (i = lower + 1; i < upper; i++) {
00205         if (table->subtables[i].keys == 1 &&
00206             table->vars[table->invperm[i]]->ref == 1)
00207             unused++;
00208     }
00209 
00210     /* Find the maximum number of subsets we may have to store. */
00211     maxBinomial = getMaxBinomial(size - unused);
00212     if (maxBinomial == -1) goto cuddExactOutOfMem;
00213 
00214     newOrder = getMatrix(maxBinomial, size);
00215     if (newOrder == NULL) goto cuddExactOutOfMem;
00216 
00217     newCost = ALLOC(int, maxBinomial);
00218     if (newCost == NULL) goto cuddExactOutOfMem;
00219 
00220     oldOrder = getMatrix(maxBinomial, size);
00221     if (oldOrder == NULL) goto cuddExactOutOfMem;
00222 
00223     oldCost = ALLOC(int, maxBinomial);
00224     if (oldCost == NULL) goto cuddExactOutOfMem;
00225 
00226     bestOrder = ALLOC(DdHalfWord, size);
00227     if (bestOrder == NULL) goto cuddExactOutOfMem;
00228 
00229     mask = ALLOC(char, nvars);
00230     if (mask == NULL) goto cuddExactOutOfMem;
00231 
00232     symmInfo = initSymmInfo(table, lower, upper);
00233     if (symmInfo == NULL) goto cuddExactOutOfMem;
00234 
00235     roots = ddCountRoots(table, lower, upper);
00236 
00237     /* Initialize the old order matrix for the empty subset and the best
00238     ** order to the current order. The cost for the empty subset includes
00239     ** the cost of the levels between upper and the constants. These levels
00240     ** are not going to change. Hence, we count them only once.
00241     */
00242     oldSubsets = 1;
00243     for (i = 0; i < size; i++) {
00244         oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower];
00245     }
00246     subsetCost = table->constants.keys;
00247     for (i = upper + 1; i < nvars; i++)
00248         subsetCost += getLevelKeys(table,i);
00249     oldCost[0] = subsetCost;
00250     /* The upper bound is initialized to the current size of the BDDs. */
00251     upperBound = table->keys - table->isolated;
00252 
00253     /* Now consider subsets of increasing size. */
00254     for (k = 1; k <= size; k++) {
00255 #ifdef DD_STATS
00256         (void) fprintf(table->out,"Processing subsets of size %d\n", k);
00257         fflush(table->out);
00258 #endif
00259         newSubsets = 0;
00260         level = size - k;               /* offset of first bottom variable */
00261 
00262         for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */
00263             order = oldOrder[i];
00264             cost = oldCost[i];
00265             lowerBound = computeLB(table, order, roots, cost, lower, upper,
00266                                    level);
00267             if (lowerBound >= upperBound)
00268                 continue;
00269             /* Impose new order. */
00270             result = ddShuffle(table, order, lower, upper);
00271             if (result == 0) goto cuddExactOutOfMem;
00272             upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
00273             /* For each top bottom variable. */
00274             for (j = level; j >= 0; j--) {
00275                 /* Skip unused variables. */
00276                 if (table->subtables[j+lower-1].keys == 1 &&
00277                     table->vars[table->invperm[j+lower-1]]->ref == 1) continue;
00278                 /* Find cost under this order. */
00279                 subsetCost = cost + getLevelKeys(table, lower + level);
00280                 newSubsets = updateEntry(table, order, level, subsetCost,
00281                                          newOrder, newCost, newSubsets, mask,
00282                                          lower, upper);
00283                 if (j == 0)
00284                     break;
00285                 if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0)
00286                     continue;
00287                 pushDown(order,j-1,level);
00288                 /* Impose new order. */
00289                 result = ddShuffle(table, order, lower, upper);
00290                 if (result == 0) goto cuddExactOutOfMem;
00291                 upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
00292             } /* for each bottom variable */
00293         } /* for each subset of size k */
00294 
00295         /* New orders become old orders in preparation for next iteration. */
00296         tmpOrder = oldOrder; tmpCost = oldCost;
00297         oldOrder = newOrder; oldCost = newCost;
00298         newOrder = tmpOrder; newCost = tmpCost;
00299 #ifdef DD_STATS
00300         ddTotalSubsets += newSubsets;
00301 #endif
00302         oldSubsets = newSubsets;
00303     }
00304     result = ddShuffle(table, bestOrder, lower, upper);
00305     if (result == 0) goto cuddExactOutOfMem;
00306 #ifdef DD_STATS
00307 #ifdef DD_VERBOSE
00308     (void) fprintf(table->out,"\n");
00309 #endif
00310     (void) fprintf(table->out,"#:S_EXACT   %8d: total subsets\n",
00311                    ddTotalSubsets);
00312     (void) fprintf(table->out,"#:H_EXACT   %8d: total shuffles",
00313                    ddTotalShuffles);
00314 #endif
00315 
00316     freeMatrix(newOrder);
00317     freeMatrix(oldOrder);
00318     FREE(bestOrder);
00319     FREE(oldCost);
00320     FREE(newCost);
00321     FREE(symmInfo);
00322     FREE(mask);
00323     return(1);
00324 
00325 cuddExactOutOfMem:
00326 
00327     if (newOrder != NULL) freeMatrix(newOrder);
00328     if (oldOrder != NULL) freeMatrix(oldOrder);
00329     if (bestOrder != NULL) FREE(bestOrder);
00330     if (oldCost != NULL) FREE(oldCost);
00331     if (newCost != NULL) FREE(newCost);
00332     if (symmInfo != NULL) FREE(symmInfo);
00333     if (mask != NULL) FREE(mask);
00334     table->errorCode = CUDD_MEMORY_OUT;
00335     return(0);
00336 
00337 } /* end of cuddExact */

void cuddFreeTable ( DdManager unique  ) 

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

Synopsis [Frees the resources associated to a unique table.]

Description []

SideEffects [None]

SeeAlso [cuddInitTable]

Definition at line 649 of file cuddTable.c.

00651 {
00652     DdNodePtr *next;
00653     DdNodePtr *memlist = unique->memoryList;
00654     int i;
00655 
00656     if (unique->univ != NULL) cuddZddFreeUniv(unique);
00657     while (memlist != NULL) {
00658         next = (DdNodePtr *) memlist[0];        /* link to next block */
00659         FREE(memlist);
00660         memlist = next;
00661     }
00662     unique->nextFree = NULL;
00663     unique->memoryList = NULL;
00664 
00665     for (i = 0; i < unique->size; i++) {
00666         FREE(unique->subtables[i].nodelist);
00667     }
00668     for (i = 0; i < unique->sizeZ; i++) {
00669         FREE(unique->subtableZ[i].nodelist);
00670     }
00671     FREE(unique->constants.nodelist);
00672     FREE(unique->subtables);
00673     FREE(unique->subtableZ);
00674     FREE(unique->acache);
00675     FREE(unique->perm);
00676     FREE(unique->permZ);
00677     FREE(unique->invperm);
00678     FREE(unique->invpermZ);
00679     FREE(unique->vars);
00680     if (unique->map != NULL) FREE(unique->map);
00681     FREE(unique->stack);
00682 #ifndef DD_NO_DEATH_ROW
00683     FREE(unique->deathRow);
00684 #endif
00685     if (unique->tree != NULL) Mtr_FreeTree(unique->tree);
00686     if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ);
00687     if (unique->linear != NULL) FREE(unique->linear);
00688     while (unique->preGCHook != NULL)
00689         Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK);
00690     while (unique->postGCHook != NULL)
00691         Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK);
00692     while (unique->preReorderingHook != NULL)
00693         Cudd_RemoveHook(unique,unique->preReorderingHook->f,
00694                         CUDD_PRE_REORDERING_HOOK);
00695     while (unique->postReorderingHook != NULL)
00696         Cudd_RemoveHook(unique,unique->postReorderingHook->f,
00697                         CUDD_POST_REORDERING_HOOK);
00698     FREE(unique);
00699 
00700 } /* end of cuddFreeTable */

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

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

Synopsis [Genetic algorithm for DD reordering.]

Description [Genetic algorithm for DD reordering. The two children of a crossover will be stored in storedd[popsize] and storedd[popsize+1] --- the last two slots in the storedd array. (This will make comparisons and replacement easy.) Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 188 of file cuddGenetic.c.

00192 {
00193     int         i,n,m;          /* dummy/loop vars */
00194     int         index;
00195 #ifdef DD_STATS
00196     double      average_fitness;
00197 #endif
00198     int         small;          /* index of smallest DD in population */
00199 
00200     /* Do an initial sifting to produce at least one reasonable individual. */
00201     if (!cuddSifting(table,lower,upper)) return(0);
00202 
00203     /* Get the initial values. */
00204     numvars = upper - lower + 1; /* number of variables to be reordered */
00205     if (table->populationSize == 0) {
00206         popsize = 3 * numvars;  /* population size is 3 times # of vars */
00207         if (popsize > 120) {
00208             popsize = 120;      /* Maximum population size is 120 */
00209         }
00210     } else {
00211         popsize = table->populationSize;  /* user specified value */
00212     }
00213     if (popsize < 4) popsize = 4;       /* enforce minimum population size */
00214 
00215     /* Allocate population table. */
00216     storedd = ALLOC(int,(popsize+2)*(numvars+1));
00217     if (storedd == NULL) {
00218         table->errorCode = CUDD_MEMORY_OUT;
00219         return(0);
00220     }
00221 
00222     /* Initialize the computed table. This table is made up of two data
00223     ** structures: A hash table with the key given by the order, which says
00224     ** if a given order is present in the population; and the repeat
00225     ** vector, which says how many copies of a given order are stored in
00226     ** the population table. If there are multiple copies of an order, only
00227     ** one has a repeat count greater than 1. This copy is the one pointed
00228     ** by the computed table.
00229     */
00230     repeat = ALLOC(int,popsize);
00231     if (repeat == NULL) {
00232         table->errorCode = CUDD_MEMORY_OUT;
00233         FREE(storedd);
00234         return(0);
00235     }
00236     for (i = 0; i < popsize; i++) {
00237         repeat[i] = 0;
00238     }
00239     computed = st_init_table(array_compare,array_hash);
00240     if (computed == NULL) {
00241         table->errorCode = CUDD_MEMORY_OUT;
00242         FREE(storedd);
00243         FREE(repeat);
00244         return(0);
00245     }
00246 
00247     /* Copy the current DD and its size to the population table. */
00248     for (i = 0; i < numvars; i++) {
00249         STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */
00250     }
00251     STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */
00252 
00253     /* Store the initial order in the computed table. */
00254     if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) {
00255         FREE(storedd);
00256         FREE(repeat);
00257         st_free_table(computed);
00258         return(0);
00259     }
00260     repeat[0]++;
00261 
00262     /* Insert the reverse order as second element of the population. */
00263     for (i = 0; i < numvars; i++) {
00264         STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */
00265     }
00266 
00267     /* Now create the random orders. make_random fills the population
00268     ** table with random permutations. The successive loop builds and sifts
00269     ** the DDs for the reverse order and each random permutation, and stores
00270     ** the results in the computed table.
00271     */
00272     if (!make_random(table,lower)) {
00273         table->errorCode = CUDD_MEMORY_OUT;
00274         FREE(storedd);
00275         FREE(repeat);
00276         st_free_table(computed);
00277         return(0);
00278     }
00279     for (i = 1; i < popsize; i++) {
00280         result = build_dd(table,i,lower,upper); /* build and sift order */
00281         if (!result) {
00282             FREE(storedd);
00283             FREE(repeat);
00284             st_free_table(computed);
00285             return(0);
00286         }
00287         if (st_lookup_int(computed,(char *)&STOREDD(i,0),&index)) {
00288             repeat[index]++;
00289         } else {
00290             if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) ==
00291             ST_OUT_OF_MEM) {
00292                 FREE(storedd);
00293                 FREE(repeat);
00294                 st_free_table(computed);
00295                 return(0);
00296             }
00297             repeat[i]++;
00298         }
00299     }
00300 
00301 #if 0
00302 #ifdef DD_STATS
00303     /* Print the initial population. */
00304     (void) fprintf(table->out,"Initial population after sifting\n");
00305     for (m = 0; m < popsize; m++) {
00306         for (i = 0; i < numvars; i++) {
00307             (void) fprintf(table->out," %2d",STOREDD(m,i));
00308         }
00309         (void) fprintf(table->out," : %3d (%d)\n",
00310                        STOREDD(m,numvars),repeat[m]);
00311     }
00312 #endif
00313 #endif
00314 
00315     small = find_best();
00316 #ifdef DD_STATS
00317     average_fitness = find_average_fitness();
00318     (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
00319 #endif
00320 
00321     /* Decide how many crossovers should be tried. */
00322     if (table->numberXovers == 0) {
00323         cross = 3*numvars;
00324         if (cross > 60) {       /* do a maximum of 50 crossovers */
00325             cross = 60;
00326         }
00327     } else {
00328         cross = table->numberXovers;      /* use user specified value */
00329     }
00330 
00331     /* Perform the crossovers to get the best order. */
00332     for (m = 0; m < cross; m++) {
00333         if (!PMX(table->size)) {        /* perform one crossover */
00334             table->errorCode = CUDD_MEMORY_OUT;
00335             FREE(storedd);
00336             FREE(repeat);
00337             st_free_table(computed);
00338             return(0);
00339         }
00340         /* The offsprings are left in the last two entries of the
00341         ** population table. These are now considered in turn.
00342         */
00343         for (i = popsize; i <= popsize+1; i++) {
00344             result = build_dd(table,i,lower,upper); /* build and sift child */
00345             if (!result) {
00346                 FREE(storedd);
00347                 FREE(repeat);
00348                 st_free_table(computed);
00349                 return(0);
00350             }
00351             large = largest();  /* find the largest DD in population */
00352 
00353             /* If the new child is smaller than the largest DD in the current
00354             ** population, enter it into the population in place of the
00355             ** largest DD.
00356             */
00357             if (STOREDD(i,numvars) < STOREDD(large,numvars)) {
00358                 /* Look up the largest DD in the computed table.
00359                 ** Decrease its repetition count. If the repetition count
00360                 ** goes to 0, remove the largest DD from the computed table.
00361                 */
00362                 result = st_lookup_int(computed,(char *)&STOREDD(large,0),
00363                                        &index);
00364                 if (!result) {
00365                     FREE(storedd);
00366                     FREE(repeat);
00367                     st_free_table(computed);
00368                     return(0);
00369                 }
00370                 repeat[index]--;
00371                 if (repeat[index] == 0) {
00372                     int *pointer = &STOREDD(index,0);
00373                     result = st_delete(computed, &pointer, NULL);
00374                     if (!result) {
00375                         FREE(storedd);
00376                         FREE(repeat);
00377                         st_free_table(computed);
00378                         return(0);
00379                     }
00380                 }
00381                 /* Copy the new individual to the entry of the
00382                 ** population table just made available and update the
00383                 ** computed table.
00384                 */
00385                 for (n = 0; n <= numvars; n++) {
00386                     STOREDD(large,n) = STOREDD(i,n);
00387                 }
00388                 if (st_lookup_int(computed,(char *)&STOREDD(large,0),
00389                                   &index)) {
00390                     repeat[index]++;
00391                 } else {
00392                     if (st_insert(computed,(char *)&STOREDD(large,0),
00393                     (char *)(long)large) == ST_OUT_OF_MEM) {
00394                         FREE(storedd);
00395                         FREE(repeat);
00396                         st_free_table(computed);
00397                         return(0);
00398                     }
00399                     repeat[large]++;
00400                 }
00401             }
00402         }
00403     }
00404 
00405     /* Find the smallest DD in the population and build it;
00406     ** that will be the result.
00407     */
00408     small = find_best();
00409 
00410     /* Print stats on the final population. */
00411 #ifdef DD_STATS
00412     average_fitness = find_average_fitness();
00413     (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
00414 #endif
00415 
00416     /* Clean up, build the result DD, and return. */
00417     st_free_table(computed);
00418     computed = NULL;
00419     result = build_dd(table,small,lower,upper);
00420     FREE(storedd);
00421     FREE(repeat);
00422     return(result);
00423 
00424 } /* end of cuddGa */

int cuddGarbageCollect ( DdManager unique,
int  clearCache 
)

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

Synopsis [Performs garbage collection on the unique tables.]

Description [Performs garbage collection on the BDD and ZDD unique tables. If clearCache is 0, the cache is not cleared. This should only be specified if the cache has been cleared right before calling cuddGarbageCollect. (As in the case of dynamic reordering.) Returns the total number of deleted nodes.]

SideEffects [None]

SeeAlso []

Definition at line 719 of file cuddTable.c.

00722 {
00723     DdHook      *hook;
00724     DdCache     *cache = unique->cache;
00725     DdNode      *sentinel = &(unique->sentinel);
00726     DdNodePtr   *nodelist;
00727     int         i, j, deleted, totalDeleted, totalDeletedZ;
00728     DdCache     *c;
00729     DdNode      *node,*next;
00730     DdNodePtr   *lastP;
00731     int         slots;
00732     long        localTime;
00733 #ifndef DD_UNSORTED_FREE_LIST
00734 #ifdef DD_RED_BLACK_FREE_LIST
00735     DdNodePtr   tree;
00736 #else
00737     DdNodePtr *memListTrav, *nxtNode;
00738     DdNode *downTrav, *sentry;
00739     int k;
00740 #endif
00741 #endif
00742 
00743 #ifndef DD_NO_DEATH_ROW
00744     cuddClearDeathRow(unique);
00745 #endif
00746 
00747     hook = unique->preGCHook;
00748     while (hook != NULL) {
00749         int res = (hook->f)(unique,"DD",NULL);
00750         if (res == 0) return(0);
00751         hook = hook->next;
00752     }
00753 
00754     if (unique->dead + unique->deadZ == 0) {
00755         hook = unique->postGCHook;
00756         while (hook != NULL) {
00757             int res = (hook->f)(unique,"DD",NULL);
00758             if (res == 0) return(0);
00759             hook = hook->next;
00760         }
00761         return(0);
00762     }
00763 
00764     /* If many nodes are being reclaimed, we want to resize the tables
00765     ** more aggressively, to reduce the frequency of garbage collection.
00766     */
00767     if (clearCache && unique->gcFrac == DD_GC_FRAC_LO &&
00768         unique->slots <= unique->looseUpTo && unique->stash != NULL) {
00769         unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
00770 #ifdef DD_VERBOSE
00771         (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI);
00772         (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
00773 #endif
00774         unique->gcFrac = DD_GC_FRAC_HI;
00775         return(0);
00776     }
00777 
00778     localTime = util_cpu_time();
00779 
00780     unique->garbageCollections++;
00781 #ifdef DD_VERBOSE
00782     (void) fprintf(unique->err,
00783                    "garbage collecting (%d dead BDD nodes out of %d, min %d)...",
00784                    unique->dead, unique->keys, unique->minDead);
00785     (void) fprintf(unique->err,
00786                    "                   (%d dead ZDD nodes out of %d)...",
00787                    unique->deadZ, unique->keysZ);
00788 #endif
00789 
00790     /* Remove references to garbage collected nodes from the cache. */
00791     if (clearCache) {
00792         slots = unique->cacheSlots;
00793         for (i = 0; i < slots; i++) {
00794             c = &cache[i];
00795             if (c->data != NULL) {
00796                 if (cuddClean(c->f)->ref == 0 ||
00797                 cuddClean(c->g)->ref == 0 ||
00798                 (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) ||
00799                 (c->data != DD_NON_CONSTANT &&
00800                 Cudd_Regular(c->data)->ref == 0)) {
00801                     c->data = NULL;
00802                     unique->cachedeletions++;
00803                 }
00804             }
00805         }
00806         cuddLocalCacheClearDead(unique);
00807     }
00808 
00809     /* Now return dead nodes to free list. Count them for sanity check. */
00810     totalDeleted = 0;
00811 #ifndef DD_UNSORTED_FREE_LIST
00812 #ifdef DD_RED_BLACK_FREE_LIST
00813     tree = NULL;
00814 #endif
00815 #endif
00816 
00817     for (i = 0; i < unique->size; i++) {
00818         if (unique->subtables[i].dead == 0) continue;
00819         nodelist = unique->subtables[i].nodelist;
00820 
00821         deleted = 0;
00822         slots = unique->subtables[i].slots;
00823         for (j = 0; j < slots; j++) {
00824             lastP = &(nodelist[j]);
00825             node = *lastP;
00826             while (node != sentinel) {
00827                 next = node->next;
00828                 if (node->ref == 0) {
00829                     deleted++;
00830 #ifndef DD_UNSORTED_FREE_LIST
00831 #ifdef DD_RED_BLACK_FREE_LIST
00832 #ifdef __osf__
00833 #pragma pointer_size save
00834 #pragma pointer_size short
00835 #endif
00836                     cuddOrderedInsert(&tree,node);
00837 #ifdef __osf__
00838 #pragma pointer_size restore
00839 #endif
00840 #endif
00841 #else
00842                     cuddDeallocNode(unique,node);
00843 #endif
00844                 } else {
00845                     *lastP = node;
00846                     lastP = &(node->next);
00847                 }
00848                 node = next;
00849             }
00850             *lastP = sentinel;
00851         }
00852         if ((unsigned) deleted != unique->subtables[i].dead) {
00853             ddReportRefMess(unique, i, "cuddGarbageCollect");
00854         }
00855         totalDeleted += deleted;
00856         unique->subtables[i].keys -= deleted;
00857         unique->subtables[i].dead = 0;
00858     }
00859     if (unique->constants.dead != 0) {
00860         nodelist = unique->constants.nodelist;
00861         deleted = 0;
00862         slots = unique->constants.slots;
00863         for (j = 0; j < slots; j++) {
00864             lastP = &(nodelist[j]);
00865             node = *lastP;
00866             while (node != NULL) {
00867                 next = node->next;
00868                 if (node->ref == 0) {
00869                     deleted++;
00870 #ifndef DD_UNSORTED_FREE_LIST
00871 #ifdef DD_RED_BLACK_FREE_LIST
00872 #ifdef __osf__
00873 #pragma pointer_size save
00874 #pragma pointer_size short
00875 #endif
00876                     cuddOrderedInsert(&tree,node);
00877 #ifdef __osf__
00878 #pragma pointer_size restore
00879 #endif
00880 #endif
00881 #else
00882                     cuddDeallocNode(unique,node);
00883 #endif
00884                 } else {
00885                     *lastP = node;
00886                     lastP = &(node->next);
00887                 }
00888                 node = next;
00889             }
00890             *lastP = NULL;
00891         }
00892         if ((unsigned) deleted != unique->constants.dead) {
00893             ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect");
00894         }
00895         totalDeleted += deleted;
00896         unique->constants.keys -= deleted;
00897         unique->constants.dead = 0;
00898     }
00899     if ((unsigned) totalDeleted != unique->dead) {
00900         ddReportRefMess(unique, -1, "cuddGarbageCollect");
00901     }
00902     unique->keys -= totalDeleted;
00903     unique->dead = 0;
00904 #ifdef DD_STATS
00905     unique->nodesFreed += (double) totalDeleted;
00906 #endif
00907 
00908     totalDeletedZ = 0;
00909 
00910     for (i = 0; i < unique->sizeZ; i++) {
00911         if (unique->subtableZ[i].dead == 0) continue;
00912         nodelist = unique->subtableZ[i].nodelist;
00913 
00914         deleted = 0;
00915         slots = unique->subtableZ[i].slots;
00916         for (j = 0; j < slots; j++) {
00917             lastP = &(nodelist[j]);
00918             node = *lastP;
00919             while (node != NULL) {
00920                 next = node->next;
00921                 if (node->ref == 0) {
00922                     deleted++;
00923 #ifndef DD_UNSORTED_FREE_LIST
00924 #ifdef DD_RED_BLACK_FREE_LIST
00925 #ifdef __osf__
00926 #pragma pointer_size save
00927 #pragma pointer_size short
00928 #endif
00929                     cuddOrderedInsert(&tree,node);
00930 #ifdef __osf__
00931 #pragma pointer_size restore
00932 #endif
00933 #endif
00934 #else
00935                     cuddDeallocNode(unique,node);
00936 #endif
00937                 } else {
00938                     *lastP = node;
00939                     lastP = &(node->next);
00940                 }
00941                 node = next;
00942             }
00943             *lastP = NULL;
00944         }
00945         if ((unsigned) deleted != unique->subtableZ[i].dead) {
00946             ddReportRefMess(unique, i, "cuddGarbageCollect");
00947         }
00948         totalDeletedZ += deleted;
00949         unique->subtableZ[i].keys -= deleted;
00950         unique->subtableZ[i].dead = 0;
00951     }
00952 
00953     /* No need to examine the constant table for ZDDs.
00954     ** If we did we should be careful not to count whatever dead
00955     ** nodes we found there among the dead ZDD nodes. */
00956     if ((unsigned) totalDeletedZ != unique->deadZ) {
00957         ddReportRefMess(unique, -1, "cuddGarbageCollect");
00958     }
00959     unique->keysZ -= totalDeletedZ;
00960     unique->deadZ = 0;
00961 #ifdef DD_STATS
00962     unique->nodesFreed += (double) totalDeletedZ;
00963 #endif
00964 
00965 
00966 #ifndef DD_UNSORTED_FREE_LIST
00967 #ifdef DD_RED_BLACK_FREE_LIST
00968     unique->nextFree = cuddOrderedThread(tree,unique->nextFree);
00969 #else
00970     memListTrav = unique->memoryList;
00971     sentry = NULL;
00972     while (memListTrav != NULL) {
00973         ptruint offset;
00974         nxtNode = (DdNodePtr *)memListTrav[0];
00975         offset = (ptruint) memListTrav & (sizeof(DdNode) - 1);
00976         memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
00977         downTrav = (DdNode *)memListTrav;
00978         k = 0;
00979         do {
00980             if (downTrav[k].ref == 0) {
00981                 if (sentry == NULL) {
00982                     unique->nextFree = sentry = &downTrav[k];
00983                 } else {
00984                     /* First hook sentry->next to the dead node and then
00985                     ** reassign sentry to the dead node. */
00986                     sentry = (sentry->next = &downTrav[k]);
00987                 }
00988             }
00989         } while (++k < DD_MEM_CHUNK);
00990         memListTrav = nxtNode;
00991     }
00992     sentry->next = NULL;
00993 #endif
00994 #endif
00995 
00996     unique->GCTime += util_cpu_time() - localTime;
00997 
00998     hook = unique->postGCHook;
00999     while (hook != NULL) {
01000         int res = (hook->f)(unique,"DD",NULL);
01001         if (res == 0) return(0);
01002         hook = hook->next;
01003     }
01004 
01005 #ifdef DD_VERBOSE
01006     (void) fprintf(unique->err," done\n");
01007 #endif
01008 
01009     return(totalDeleted+totalDeletedZ);
01010 
01011 } /* end of cuddGarbageCollect */

void cuddGetBranches ( DdNode g,
DdNode **  g1,
DdNode **  g0 
)

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

Synopsis [Computes the children of g.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 158 of file cuddCof.c.

00162 {
00163     DdNode      *G = Cudd_Regular(g);
00164 
00165     *g1 = cuddT(G);
00166     *g0 = cuddE(G);
00167     if (Cudd_IsComplement(g)) {
00168         *g1 = Cudd_Not(*g1);
00169         *g0 = Cudd_Not(*g0);
00170     }
00171 
00172 } /* end of cuddGetBranches */

DdHashTable* cuddHashTableInit ( DdManager manager,
unsigned int  keySize,
unsigned int  initSize 
)

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

Synopsis [Initializes a hash table.]

Description [Initializes a hash table. Returns a pointer to the new table if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [cuddHashTableQuit]

Definition at line 534 of file cuddLCache.c.

00538 {
00539     DdHashTable *hash;
00540     int logSize;
00541 
00542 #ifdef __osf__
00543 #pragma pointer_size save
00544 #pragma pointer_size short
00545 #endif
00546     hash = ALLOC(DdHashTable, 1);
00547     if (hash == NULL) {
00548         manager->errorCode = CUDD_MEMORY_OUT;
00549         return(NULL);
00550     }
00551     hash->keysize = keySize;
00552     hash->manager = manager;
00553     hash->memoryList = NULL;
00554     hash->nextFree = NULL;
00555     hash->itemsize = (keySize + 1) * sizeof(DdNode *) +
00556         sizeof(ptrint) + sizeof(DdHashItem *);
00557     /* We have to guarantee that the shift be < 32. */
00558     if (initSize < 2) initSize = 2;
00559     logSize = cuddComputeFloorLog2(initSize);
00560     hash->numBuckets = 1 << logSize;
00561     hash->shift = sizeof(int) * 8 - logSize;
00562     hash->bucket = ALLOC(DdHashItem *, hash->numBuckets);
00563     if (hash->bucket == NULL) {
00564         manager->errorCode = CUDD_MEMORY_OUT;
00565         FREE(hash);
00566         return(NULL);
00567     }
00568     memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *));
00569     hash->size = 0;
00570     hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY;
00571 #ifdef __osf__
00572 #pragma pointer_size restore
00573 #endif
00574     return(hash);
00575 
00576 } /* end of cuddHashTableInit */

int cuddHashTableInsert ( DdHashTable hash,
DdNodePtr key,
DdNode value,
ptrint  count 
)

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

Synopsis [Inserts an item in a hash table.]

Description [Inserts an item in a hash table when the key has more than three pointers. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3 cuddHashTableLookup]

Definition at line 644 of file cuddLCache.c.

00649 {
00650     int result;
00651     unsigned int posn;
00652     DdHashItem *item;
00653     unsigned int i;
00654 
00655 #ifdef DD_DEBUG
00656     assert(hash->keysize > 3);
00657 #endif
00658 
00659     if (hash->size > hash->maxsize) {
00660         result = cuddHashTableResize(hash);
00661         if (result == 0) return(0);
00662     }
00663     item = cuddHashTableAlloc(hash);
00664     if (item == NULL) return(0);
00665     hash->size++;
00666     item->value = value;
00667     cuddRef(value);
00668     item->count = count;
00669     for (i = 0; i < hash->keysize; i++) {
00670         item->key[i] = key[i];
00671     }
00672     posn = ddLCHash(key,hash->keysize,hash->shift);
00673     item->next = hash->bucket[posn];
00674     hash->bucket[posn] = item;
00675 
00676     return(1);
00677 
00678 } /* end of cuddHashTableInsert */

int cuddHashTableInsert1 ( DdHashTable hash,
DdNode f,
DdNode value,
ptrint  count 
)

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

Synopsis [Inserts an item in a hash table.]

Description [Inserts an item in a hash table when the key is one pointer. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3 cuddHashTableLookup1]

Definition at line 763 of file cuddLCache.c.

00768 {
00769     int result;
00770     unsigned int posn;
00771     DdHashItem *item;
00772 
00773 #ifdef DD_DEBUG
00774     assert(hash->keysize == 1);
00775 #endif
00776 
00777     if (hash->size > hash->maxsize) {
00778         result = cuddHashTableResize(hash);
00779         if (result == 0) return(0);
00780     }
00781     item = cuddHashTableAlloc(hash);
00782     if (item == NULL) return(0);
00783     hash->size++;
00784     item->value = value;
00785     cuddRef(value);
00786     item->count = count;
00787     item->key[0] = f;
00788     posn = ddLCHash2(f,f,hash->shift);
00789     item->next = hash->bucket[posn];
00790     hash->bucket[posn] = item;
00791 
00792     return(1);
00793 
00794 } /* end of cuddHashTableInsert1 */

int cuddHashTableInsert2 ( DdHashTable hash,
DdNode f,
DdNode g,
DdNode value,
ptrint  count 
)

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

Synopsis [Inserts an item in a hash table.]

Description [Inserts an item in a hash table when the key is composed of two pointers. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3 cuddHashTableLookup2]

Definition at line 870 of file cuddLCache.c.

00876 {
00877     int result;
00878     unsigned int posn;
00879     DdHashItem *item;
00880 
00881 #ifdef DD_DEBUG
00882     assert(hash->keysize == 2);
00883 #endif
00884 
00885     if (hash->size > hash->maxsize) {
00886         result = cuddHashTableResize(hash);
00887         if (result == 0) return(0);
00888     }
00889     item = cuddHashTableAlloc(hash);
00890     if (item == NULL) return(0);
00891     hash->size++;
00892     item->value = value;
00893     cuddRef(value);
00894     item->count = count;
00895     item->key[0] = f;
00896     item->key[1] = g;
00897     posn = ddLCHash2(f,g,hash->shift);
00898     item->next = hash->bucket[posn];
00899     hash->bucket[posn] = item;
00900 
00901     return(1);
00902 
00903 } /* end of cuddHashTableInsert2 */

int cuddHashTableInsert3 ( DdHashTable hash,
DdNode f,
DdNode g,
DdNode h,
DdNode value,
ptrint  count 
)

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

Synopsis [Inserts an item in a hash table.]

Description [Inserts an item in a hash table when the key is composed of three pointers. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableLookup3]

Definition at line 980 of file cuddLCache.c.

00987 {
00988     int result;
00989     unsigned int posn;
00990     DdHashItem *item;
00991 
00992 #ifdef DD_DEBUG
00993     assert(hash->keysize == 3);
00994 #endif
00995 
00996     if (hash->size > hash->maxsize) {
00997         result = cuddHashTableResize(hash);
00998         if (result == 0) return(0);
00999     }
01000     item = cuddHashTableAlloc(hash);
01001     if (item == NULL) return(0);
01002     hash->size++;
01003     item->value = value;
01004     cuddRef(value);
01005     item->count = count;
01006     item->key[0] = f;
01007     item->key[1] = g;
01008     item->key[2] = h;
01009     posn = ddLCHash3(f,g,h,hash->shift);
01010     item->next = hash->bucket[posn];
01011     hash->bucket[posn] = item;
01012 
01013     return(1);
01014 
01015 } /* end of cuddHashTableInsert3 */

DdNode* cuddHashTableLookup ( DdHashTable hash,
DdNodePtr key 
)

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

Synopsis [Looks up a key in a hash table.]

Description [Looks up a key consisting of more than three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]

SideEffects [None]

SeeAlso [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3 cuddHashTableInsert]

Definition at line 699 of file cuddLCache.c.

00702 {
00703     unsigned int posn;
00704     DdHashItem *item, *prev;
00705     unsigned int i, keysize;
00706 
00707 #ifdef DD_DEBUG
00708     assert(hash->keysize > 3);
00709 #endif
00710 
00711     posn = ddLCHash(key,hash->keysize,hash->shift);
00712     item = hash->bucket[posn];
00713     prev = NULL;
00714 
00715     keysize = hash->keysize;
00716     while (item != NULL) {
00717         DdNodePtr *key2 = item->key;
00718         int equal = 1;
00719         for (i = 0; i < keysize; i++) {
00720             if (key[i] != key2[i]) {
00721                 equal = 0;
00722                 break;
00723             }
00724         }
00725         if (equal) {
00726             DdNode *value = item->value;
00727             cuddSatDec(item->count);
00728             if (item->count == 0) {
00729                 cuddDeref(value);
00730                 if (prev == NULL) {
00731                     hash->bucket[posn] = item->next;
00732                 } else {
00733                     prev->next = item->next;
00734                 }
00735                 item->next = hash->nextFree;
00736                 hash->nextFree = item;
00737                 hash->size--;
00738             }
00739             return(value);
00740         }
00741         prev = item;
00742         item = item->next;
00743     }
00744     return(NULL);
00745 
00746 } /* end of cuddHashTableLookup */

DdNode* cuddHashTableLookup1 ( DdHashTable hash,
DdNode f 
)

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

Synopsis [Looks up a key consisting of one pointer in a hash table.]

Description [Looks up a key consisting of one pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]

SideEffects [None]

SeeAlso [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3 cuddHashTableInsert1]

Definition at line 815 of file cuddLCache.c.

00818 {
00819     unsigned int posn;
00820     DdHashItem *item, *prev;
00821 
00822 #ifdef DD_DEBUG
00823     assert(hash->keysize == 1);
00824 #endif
00825 
00826     posn = ddLCHash2(f,f,hash->shift);
00827     item = hash->bucket[posn];
00828     prev = NULL;
00829 
00830     while (item != NULL) {
00831         DdNodePtr *key = item->key;
00832         if (f == key[0]) {
00833             DdNode *value = item->value;
00834             cuddSatDec(item->count);
00835             if (item->count == 0) {
00836                 cuddDeref(value);
00837                 if (prev == NULL) {
00838                     hash->bucket[posn] = item->next;
00839                 } else {
00840                     prev->next = item->next;
00841                 }
00842                 item->next = hash->nextFree;
00843                 hash->nextFree = item;
00844                 hash->size--;
00845             }
00846             return(value);
00847         }
00848         prev = item;
00849         item = item->next;
00850     }
00851     return(NULL);
00852 
00853 } /* end of cuddHashTableLookup1 */

DdNode* cuddHashTableLookup2 ( DdHashTable hash,
DdNode f,
DdNode g 
)

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

Synopsis [Looks up a key consisting of two pointers in a hash table.]

Description [Looks up a key consisting of two pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]

SideEffects [None]

SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3 cuddHashTableInsert2]

Definition at line 924 of file cuddLCache.c.

00928 {
00929     unsigned int posn;
00930     DdHashItem *item, *prev;
00931 
00932 #ifdef DD_DEBUG
00933     assert(hash->keysize == 2);
00934 #endif
00935 
00936     posn = ddLCHash2(f,g,hash->shift);
00937     item = hash->bucket[posn];
00938     prev = NULL;
00939 
00940     while (item != NULL) {
00941         DdNodePtr *key = item->key;
00942         if ((f == key[0]) && (g == key[1])) {
00943             DdNode *value = item->value;
00944             cuddSatDec(item->count);
00945             if (item->count == 0) {
00946                 cuddDeref(value);
00947                 if (prev == NULL) {
00948                     hash->bucket[posn] = item->next;
00949                 } else {
00950                     prev->next = item->next;
00951                 }
00952                 item->next = hash->nextFree;
00953                 hash->nextFree = item;
00954                 hash->size--;
00955             }
00956             return(value);
00957         }
00958         prev = item;
00959         item = item->next;
00960     }
00961     return(NULL);
00962 
00963 } /* end of cuddHashTableLookup2 */

DdNode* cuddHashTableLookup3 ( DdHashTable hash,
DdNode f,
DdNode g,
DdNode h 
)

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

Synopsis [Looks up a key consisting of three pointers in a hash table.]

Description [Looks up a key consisting of three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.]

SideEffects [None]

SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableInsert3]

Definition at line 1036 of file cuddLCache.c.

01041 {
01042     unsigned int posn;
01043     DdHashItem *item, *prev;
01044 
01045 #ifdef DD_DEBUG
01046     assert(hash->keysize == 3);
01047 #endif
01048 
01049     posn = ddLCHash3(f,g,h,hash->shift);
01050     item = hash->bucket[posn];
01051     prev = NULL;
01052 
01053     while (item != NULL) {
01054         DdNodePtr *key = item->key;
01055         if ((f == key[0]) && (g == key[1]) && (h == key[2])) {
01056             DdNode *value = item->value;
01057             cuddSatDec(item->count);
01058             if (item->count == 0) {
01059                 cuddDeref(value);
01060                 if (prev == NULL) {
01061                     hash->bucket[posn] = item->next;
01062                 } else {
01063                     prev->next = item->next;
01064                 }
01065                 item->next = hash->nextFree;
01066                 hash->nextFree = item;
01067                 hash->size--;
01068             }
01069             return(value);
01070         }
01071         prev = item;
01072         item = item->next;
01073     }
01074     return(NULL);
01075 
01076 } /* end of cuddHashTableLookup3 */

void cuddHashTableQuit ( DdHashTable hash  ) 

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

Synopsis [Shuts down a hash table.]

Description [Shuts down a hash table, dereferencing all the values.]

SideEffects [None]

SeeAlso [cuddHashTableInit]

Definition at line 591 of file cuddLCache.c.

00593 {
00594 #ifdef __osf__
00595 #pragma pointer_size save
00596 #pragma pointer_size short
00597 #endif
00598     unsigned int i;
00599     DdManager *dd = hash->manager;
00600     DdHashItem *bucket;
00601     DdHashItem **memlist, **nextmem;
00602     unsigned int numBuckets = hash->numBuckets;
00603 
00604     for (i = 0; i < numBuckets; i++) {
00605         bucket = hash->bucket[i];
00606         while (bucket != NULL) {
00607             Cudd_RecursiveDeref(dd, bucket->value);
00608             bucket = bucket->next;
00609         }
00610     }
00611 
00612     memlist = hash->memoryList;
00613     while (memlist != NULL) {
00614         nextmem = (DdHashItem **) memlist[0];
00615         FREE(memlist);
00616         memlist = nextmem;
00617     }
00618 
00619     FREE(hash->bucket);
00620     FREE(hash);
00621 #ifdef __osf__
00622 #pragma pointer_size restore
00623 #endif
00624 
00625     return;
00626 
00627 } /* end of cuddHashTableQuit */

int cuddHeapProfile ( DdManager dd  ) 

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

Synopsis [Prints information about the heap.]

Description [Prints to the manager's stdout the number of live nodes for each level of the DD heap that contains at least one live node. It also prints a summary containing:

  • total number of tables;
  • number of tables with live nodes;
  • table with the largest number of live nodes;
  • number of nodes in that table.

If more than one table contains the maximum number of live nodes, only the one of lowest index is reported. Returns 1 in case of success and 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 635 of file cuddCheck.c.

00637 {
00638     int ntables = dd->size;
00639     DdSubtable *subtables = dd->subtables;
00640     int i,              /* loop index */
00641         nodes,          /* live nodes in i-th layer */
00642         retval,         /* return value of fprintf */
00643         largest = -1,   /* index of the table with most live nodes */
00644         maxnodes = -1,  /* maximum number of live nodes in a table */
00645         nonempty = 0;   /* number of tables with live nodes */
00646 
00647     /* Print header. */
00648 #if SIZEOF_VOID_P == 8
00649     retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n",
00650                      (ptruint) dd);
00651 #else
00652     retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n",
00653                      (ptruint) dd);
00654 #endif
00655     if (retval == EOF) return 0;
00656 
00657     /* Print number of live nodes for each nonempty table. */
00658     for (i=0; i<ntables; i++) {
00659         nodes = subtables[i].keys - subtables[i].dead;
00660         if (nodes) {
00661             nonempty++;
00662             retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes);
00663             if (retval == EOF) return 0;
00664             if (nodes > maxnodes) {
00665                 maxnodes = nodes;
00666                 largest = i;
00667             }
00668         }
00669     }
00670 
00671     nodes = dd->constants.keys - dd->constants.dead;
00672     if (nodes) {
00673         nonempty++;
00674         retval = fprintf(dd->out,"const: %5d nodes\n", nodes);
00675         if (retval == EOF) return 0;
00676         if (nodes > maxnodes) {
00677             maxnodes = nodes;
00678             largest = CUDD_CONST_INDEX;
00679         }
00680     }
00681 
00682     /* Print summary. */
00683     retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ",
00684           ntables+1, nonempty, largest);
00685     if (retval == EOF) return 0;
00686     retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes);
00687     if (retval == EOF) return 0;
00688 
00689     return(1);
00690 
00691 } /* end of cuddHeapProfile */

int cuddInitCache ( DdManager unique,
unsigned int  cacheSize,
unsigned int  maxCacheSize 
)

AutomaticStart AutomaticEnd Function********************************************************************

Synopsis [Initializes the computed table.]

Description [Initializes the computed table. It is called by Cudd_Init. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso [Cudd_Init]

Definition at line 132 of file cuddCache.c.

00136 {
00137     int i;
00138     unsigned int logSize;
00139 #ifndef DD_CACHE_PROFILE
00140     DdNodePtr *mem;
00141     ptruint offset;
00142 #endif
00143 
00144     /* Round cacheSize to largest power of 2 not greater than the requested
00145     ** initial cache size. */
00146     logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2));
00147     cacheSize = 1 << logSize;
00148     unique->acache = ALLOC(DdCache,cacheSize+1);
00149     if (unique->acache == NULL) {
00150         unique->errorCode = CUDD_MEMORY_OUT;
00151         return(0);
00152     }
00153     /* If the size of the cache entry is a power of 2, we want to
00154     ** enforce alignment to that power of two. This happens when
00155     ** DD_CACHE_PROFILE is not defined. */
00156 #ifdef DD_CACHE_PROFILE
00157     unique->cache = unique->acache;
00158     unique->memused += (cacheSize) * sizeof(DdCache);
00159 #else
00160     mem = (DdNodePtr *) unique->acache;
00161     offset = (ptruint) mem & (sizeof(DdCache) - 1);
00162     mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr);
00163     unique->cache = (DdCache *) mem;
00164     assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0);
00165     unique->memused += (cacheSize+1) * sizeof(DdCache);
00166 #endif
00167     unique->cacheSlots = cacheSize;
00168     unique->cacheShift = sizeof(int) * 8 - logSize;
00169     unique->maxCacheHard = maxCacheSize;
00170     /* If cacheSlack is non-negative, we can resize. */
00171     unique->cacheSlack = (int) ddMin(maxCacheSize,
00172         DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) -
00173         2 * (int) cacheSize;
00174     Cudd_SetMinHit(unique,DD_MIN_HIT);
00175     /* Initialize to avoid division by 0 and immediate resizing. */
00176     unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1);
00177     unique->cacheHits = 0;
00178     unique->totCachehits = 0;
00179     /* The sum of cacheMisses and totCacheMisses is always correct,
00180     ** even though cacheMisses is larger than it should for the reasons
00181     ** explained above. */
00182     unique->totCacheMisses = -unique->cacheMisses;
00183     unique->cachecollisions = 0;
00184     unique->cacheinserts = 0;
00185     unique->cacheLastInserts = 0;
00186     unique->cachedeletions = 0;
00187 
00188     /* Initialize the cache */
00189     for (i = 0; (unsigned) i < cacheSize; i++) {
00190         unique->cache[i].h = 0; /* unused slots */
00191         unique->cache[i].data = NULL; /* invalid entry */
00192 #ifdef DD_CACHE_PROFILE
00193         unique->cache[i].count = 0;
00194 #endif
00195     }
00196 
00197     return(1);
00198 
00199 } /* end of cuddInitCache */

int cuddInitInteract ( DdManager table  ) 

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

Synopsis [Initializes the interaction matrix.]

Description [Initializes the interaction matrix. The interaction matrix is implemented as a bit vector storing the upper triangle of the symmetric interaction matrix. The bit vector is kept in an array of long integers. The computation is based on a series of depth-first searches, one for each root of the DAG. Two flags are needed: The local visited flag uses the LSB of the then pointer. The global visited flag uses the LSB of the next pointer. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 233 of file cuddInteract.c.

00235 {
00236     int i,j,k;
00237     int words;
00238     long *interact;
00239     int *support;
00240     DdNode *f;
00241     DdNode *sentinel = &(table->sentinel);
00242     DdNodePtr *nodelist;
00243     int slots;
00244     int n = table->size;
00245 
00246     words = ((n * (n-1)) >> (1 + LOGBPL)) + 1;
00247     table->interact = interact = ALLOC(long,words);
00248     if (interact == NULL) {
00249         table->errorCode = CUDD_MEMORY_OUT;
00250         return(0);
00251     }
00252     for (i = 0; i < words; i++) {
00253         interact[i] = 0;
00254     }
00255 
00256     support = ALLOC(int,n);
00257     if (support == NULL) {
00258         table->errorCode = CUDD_MEMORY_OUT;
00259         FREE(interact);
00260         return(0);
00261     }
00262 
00263     for (i = 0; i < n; i++) {
00264         nodelist = table->subtables[i].nodelist;
00265         slots = table->subtables[i].slots;
00266         for (j = 0; j < slots; j++) {
00267             f = nodelist[j];
00268             while (f != sentinel) {
00269                 /* A node is a root of the DAG if it cannot be
00270                 ** reached by nodes above it. If a node was never
00271                 ** reached during the previous depth-first searches,
00272                 ** then it is a root, and we start a new depth-first
00273                 ** search from it.
00274                 */
00275                 if (!Cudd_IsComplement(f->next)) {
00276                     for (k = 0; k < n; k++) {
00277                         support[k] = 0;
00278                     }
00279                     ddSuppInteract(f,support);
00280                     ddClearLocal(f);
00281                     ddUpdateInteract(table,support);
00282                 }
00283                 f = Cudd_Regular(f->next);
00284             }
00285         }
00286     }
00287     ddClearGlobal(table);
00288 
00289     FREE(support);
00290     return(1);
00291 
00292 } /* end of cuddInitInteract */

int cuddInitLinear ( DdManager table  ) 

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

Synopsis [Initializes the linear transform matrix.]

Description [Initializes the linear transform matrix. Returns 1 if successful; 0 otherwise.]

SideEffects [none]

SeeAlso []

Definition at line 755 of file cuddLinear.c.

00757 {
00758     int words;
00759     int wordsPerRow;
00760     int nvars;
00761     int word;
00762     int bit;
00763     int i;
00764     long *linear;
00765 
00766     nvars = table->size;
00767     wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00768     words = wordsPerRow * nvars;
00769     table->linear = linear = ALLOC(long,words);
00770     if (linear == NULL) {
00771         table->errorCode = CUDD_MEMORY_OUT;
00772         return(0);
00773     }
00774     table->memused += words * sizeof(long);
00775     table->linearSize = nvars;
00776     for (i = 0; i < words; i++) linear[i] = 0;
00777     for (i = 0; i < nvars; i++) {
00778         word = wordsPerRow * i + (i >> LOGBPL);
00779         bit  = i & (BPL-1);
00780         linear[word] = 1 << bit;
00781     }
00782     return(1);
00783 
00784 } /* end of cuddInitLinear */

DdManager* cuddInitTable ( unsigned int  numVars,
unsigned int  numVarsZ,
unsigned int  numSlots,
unsigned int  looseUpTo 
)

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

Synopsis [Creates and initializes the unique table.]

Description [Creates and initializes the unique table. Returns a pointer to the table if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_Init cuddFreeTable]

Definition at line 341 of file cuddTable.c.

00346 {
00347     DdManager   *unique = ALLOC(DdManager,1);
00348     int         i, j;
00349     DdNodePtr   *nodelist;
00350     DdNode      *sentinel;
00351     unsigned int slots;
00352     int shift;
00353 
00354     if (unique == NULL) {
00355         return(NULL);
00356     }
00357     sentinel = &(unique->sentinel);
00358     sentinel->ref = 0;
00359     sentinel->index = 0;
00360     cuddT(sentinel) = NULL;
00361     cuddE(sentinel) = NULL;
00362     sentinel->next = NULL;
00363     unique->epsilon = DD_EPSILON;
00364     unique->maxGrowth = DD_MAX_REORDER_GROWTH;
00365     unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH;
00366     unique->reordCycle = 0;     /* do not use alternate threshold */
00367     unique->size = numVars;
00368     unique->sizeZ = numVarsZ;
00369     unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars);
00370     unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ);
00371 
00372     /* Adjust the requested number of slots to a power of 2. */
00373     slots = 8;
00374     while (slots < numSlots) {
00375         slots <<= 1;
00376     }
00377     unique->initSlots = slots;
00378     shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots);
00379 
00380     unique->slots = (numVars + numVarsZ + 1) * slots;
00381     unique->keys = 0;
00382     unique->maxLive = ~0;       /* very large number */
00383     unique->keysZ = 0;
00384     unique->dead = 0;
00385     unique->deadZ = 0;
00386     unique->gcFrac = DD_GC_FRAC_HI;
00387     unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
00388     unique->looseUpTo = looseUpTo;
00389     unique->gcEnabled = 1;
00390     unique->allocated = 0;
00391     unique->reclaimed = 0;
00392     unique->subtables = ALLOC(DdSubtable,unique->maxSize);
00393     if (unique->subtables == NULL) {
00394         FREE(unique);
00395         return(NULL);
00396     }
00397     unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ);
00398     if (unique->subtableZ == NULL) {
00399         FREE(unique->subtables);
00400         FREE(unique);
00401         return(NULL);
00402     }
00403     unique->perm = ALLOC(int,unique->maxSize);
00404     if (unique->perm == NULL) {
00405         FREE(unique->subtables);
00406         FREE(unique->subtableZ);
00407         FREE(unique);
00408         return(NULL);
00409     }
00410     unique->invperm = ALLOC(int,unique->maxSize);
00411     if (unique->invperm == NULL) {
00412         FREE(unique->subtables);
00413         FREE(unique->subtableZ);
00414         FREE(unique->perm);
00415         FREE(unique);
00416         return(NULL);
00417     }
00418     unique->permZ = ALLOC(int,unique->maxSizeZ);
00419     if (unique->permZ == NULL) {
00420         FREE(unique->subtables);
00421         FREE(unique->subtableZ);
00422         FREE(unique->perm);
00423         FREE(unique->invperm);
00424         FREE(unique);
00425         return(NULL);
00426     }
00427     unique->invpermZ = ALLOC(int,unique->maxSizeZ);
00428     if (unique->invpermZ == NULL) {
00429         FREE(unique->subtables);
00430         FREE(unique->subtableZ);
00431         FREE(unique->perm);
00432         FREE(unique->invperm);
00433         FREE(unique->permZ);
00434         FREE(unique);
00435         return(NULL);
00436     }
00437     unique->map = NULL;
00438     unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1);
00439     if (unique->stack == NULL) {
00440         FREE(unique->subtables);
00441         FREE(unique->subtableZ);
00442         FREE(unique->perm);
00443         FREE(unique->invperm);
00444         FREE(unique->permZ);
00445         FREE(unique->invpermZ);
00446         FREE(unique);
00447         return(NULL);
00448     }
00449     unique->stack[0] = NULL; /* to suppress harmless UMR */
00450 
00451 #ifndef DD_NO_DEATH_ROW
00452     unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2);
00453     unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth);
00454     if (unique->deathRow == NULL) {
00455         FREE(unique->subtables);
00456         FREE(unique->subtableZ);
00457         FREE(unique->perm);
00458         FREE(unique->invperm);
00459         FREE(unique->permZ);
00460         FREE(unique->invpermZ);
00461         FREE(unique->stack);
00462         FREE(unique);
00463         return(NULL);
00464     }
00465     for (i = 0; i < unique->deathRowDepth; i++) {
00466         unique->deathRow[i] = NULL;
00467     }
00468     unique->nextDead = 0;
00469     unique->deadMask = unique->deathRowDepth - 1;
00470 #endif
00471 
00472     for (i = 0; (unsigned) i < numVars; i++) {
00473         unique->subtables[i].slots = slots;
00474         unique->subtables[i].shift = shift;
00475         unique->subtables[i].keys = 0;
00476         unique->subtables[i].dead = 0;
00477         unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
00478         unique->subtables[i].bindVar = 0;
00479         unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
00480         unique->subtables[i].pairIndex = 0;
00481         unique->subtables[i].varHandled = 0;
00482         unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE;
00483 
00484         nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots);
00485         if (nodelist == NULL) {
00486             for (j = 0; j < i; j++) {
00487                 FREE(unique->subtables[j].nodelist);
00488             }
00489             FREE(unique->subtables);
00490             FREE(unique->subtableZ);
00491             FREE(unique->perm);
00492             FREE(unique->invperm);
00493             FREE(unique->permZ);
00494             FREE(unique->invpermZ);
00495             FREE(unique->stack);
00496             FREE(unique);
00497             return(NULL);
00498         }
00499         for (j = 0; (unsigned) j < slots; j++) {
00500             nodelist[j] = sentinel;
00501         }
00502         unique->perm[i] = i;
00503         unique->invperm[i] = i;
00504     }
00505     for (i = 0; (unsigned) i < numVarsZ; i++) {
00506         unique->subtableZ[i].slots = slots;
00507         unique->subtableZ[i].shift = shift;
00508         unique->subtableZ[i].keys = 0;
00509         unique->subtableZ[i].dead = 0;
00510         unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
00511         nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots);
00512         if (nodelist == NULL) {
00513             for (j = 0; (unsigned) j < numVars; j++) {
00514                 FREE(unique->subtables[j].nodelist);
00515             }
00516             FREE(unique->subtables);
00517             for (j = 0; j < i; j++) {
00518                 FREE(unique->subtableZ[j].nodelist);
00519             }
00520             FREE(unique->subtableZ);
00521             FREE(unique->perm);
00522             FREE(unique->invperm);
00523             FREE(unique->permZ);
00524             FREE(unique->invpermZ);
00525             FREE(unique->stack);
00526             FREE(unique);
00527             return(NULL);
00528         }
00529         for (j = 0; (unsigned) j < slots; j++) {
00530             nodelist[j] = NULL;
00531         }
00532         unique->permZ[i] = i;
00533         unique->invpermZ[i] = i;
00534     }
00535     unique->constants.slots = slots;
00536     unique->constants.shift = shift;
00537     unique->constants.keys = 0;
00538     unique->constants.dead = 0;
00539     unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
00540     nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots);
00541     if (nodelist == NULL) {
00542         for (j = 0; (unsigned) j < numVars; j++) {
00543             FREE(unique->subtables[j].nodelist);
00544         }
00545         FREE(unique->subtables);
00546         for (j = 0; (unsigned) j < numVarsZ; j++) {
00547             FREE(unique->subtableZ[j].nodelist);
00548         }
00549         FREE(unique->subtableZ);
00550         FREE(unique->perm);
00551         FREE(unique->invperm);
00552         FREE(unique->permZ);
00553         FREE(unique->invpermZ);
00554         FREE(unique->stack);
00555         FREE(unique);
00556         return(NULL);
00557     }
00558     for (j = 0; (unsigned) j < slots; j++) {
00559         nodelist[j] = NULL;
00560     }
00561 
00562     unique->memoryList = NULL;
00563     unique->nextFree = NULL;
00564 
00565     unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ)
00566         * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) *
00567         slots * sizeof(DdNodePtr) +
00568         (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr);
00569 #ifndef DD_NO_DEATH_ROW
00570     unique->memused += unique->deathRowDepth * sizeof(DdNodePtr);
00571 #endif
00572 
00573     /* Initialize fields concerned with automatic dynamic reordering */
00574     unique->reorderings = 0;
00575     unique->autoDyn = 0;        /* initially disabled */
00576     unique->autoDynZ = 0;       /* initially disabled */
00577     unique->realign = 0;        /* initially disabled */
00578     unique->realignZ = 0;       /* initially disabled */
00579     unique->reordered = 0;
00580     unique->autoMethod = CUDD_REORDER_SIFT;
00581     unique->autoMethodZ = CUDD_REORDER_SIFT;
00582     unique->nextDyn = DD_FIRST_REORDER;
00583     unique->countDead = ~0;
00584     unique->siftMaxVar = DD_SIFT_MAX_VAR;
00585     unique->siftMaxSwap = DD_SIFT_MAX_SWAPS;
00586     unique->tree = NULL;
00587     unique->treeZ = NULL;
00588     unique->groupcheck = CUDD_GROUP_CHECK7;
00589     unique->recomb = DD_DEFAULT_RECOMB;
00590     unique->symmviolation = 0;
00591     unique->arcviolation = 0;
00592     unique->populationSize = 0;
00593     unique->numberXovers = 0;
00594     unique->linear = NULL;
00595     unique->linearSize = 0;
00596 
00597     /* Initialize ZDD universe. */
00598     unique->univ = (DdNodePtr *)NULL;
00599 
00600     /* Initialize auxiliary fields. */
00601     unique->localCaches = NULL;
00602     unique->preGCHook = NULL;
00603     unique->postGCHook = NULL;
00604     unique->preReorderingHook = NULL;
00605     unique->postReorderingHook = NULL;
00606     unique->out = stdout;
00607     unique->err = stderr;
00608     unique->errorCode = CUDD_NO_ERROR;
00609 
00610     /* Initialize statistical counters. */
00611     unique->maxmemhard = ~ 0UL;
00612     unique->garbageCollections = 0;
00613     unique->GCTime = 0;
00614     unique->reordTime = 0;
00615 #ifdef DD_STATS
00616     unique->nodesDropped = 0;
00617     unique->nodesFreed = 0;
00618 #endif
00619     unique->peakLiveNodes = 0;
00620 #ifdef DD_UNIQUE_PROFILE
00621     unique->uniqueLookUps = 0;
00622     unique->uniqueLinks = 0;
00623 #endif
00624 #ifdef DD_COUNT
00625     unique->recursiveCalls = 0;
00626     unique->swapSteps = 0;
00627 #ifdef DD_STATS
00628     unique->nextSample = 250000;
00629 #endif
00630 #endif
00631 
00632     return(unique);
00633 
00634 } /* end of cuddInitTable */

int cuddInsertSubtables ( DdManager unique,
int  n,
int  level 
)

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

Synopsis [Inserts n new subtables in a unique table at level.]

Description [Inserts n new subtables in a unique table at level. The number n should be positive, and level should be an existing level. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddDestroySubtables]

Definition at line 1780 of file cuddTable.c.

01784 {
01785     DdSubtable *newsubtables;
01786     DdNodePtr *newnodelist;
01787     DdNodePtr *newvars;
01788     DdNode *sentinel = &(unique->sentinel);
01789     int oldsize,newsize;
01790     int i,j,index,reorderSave;
01791     unsigned int numSlots = unique->initSlots;
01792     int *newperm, *newinvperm, *newmap;
01793     DdNode *one, *zero;
01794 
01795 #ifdef DD_DEBUG
01796     assert(n > 0 && level < unique->size);
01797 #endif
01798 
01799     oldsize = unique->size;
01800     /* Easy case: there is still room in the current table. */
01801     if (oldsize + n <= unique->maxSize) {
01802         /* Shift the tables at and below level. */
01803         for (i = oldsize - 1; i >= level; i--) {
01804             unique->subtables[i+n].slots    = unique->subtables[i].slots;
01805             unique->subtables[i+n].shift    = unique->subtables[i].shift;
01806             unique->subtables[i+n].keys     = unique->subtables[i].keys;
01807             unique->subtables[i+n].maxKeys  = unique->subtables[i].maxKeys;
01808             unique->subtables[i+n].dead     = unique->subtables[i].dead;
01809             unique->subtables[i+n].nodelist = unique->subtables[i].nodelist;
01810             unique->subtables[i+n].bindVar  = unique->subtables[i].bindVar;
01811             unique->subtables[i+n].varType  = unique->subtables[i].varType;
01812             unique->subtables[i+n].pairIndex  = unique->subtables[i].pairIndex;
01813             unique->subtables[i+n].varHandled = unique->subtables[i].varHandled;
01814             unique->subtables[i+n].varToBeGrouped =
01815                 unique->subtables[i].varToBeGrouped;
01816 
01817             index                           = unique->invperm[i];
01818             unique->invperm[i+n]            = index;
01819             unique->perm[index]            += n;
01820         }
01821         /* Create new subtables. */
01822         for (i = 0; i < n; i++) {
01823             unique->subtables[level+i].slots = numSlots;
01824             unique->subtables[level+i].shift = sizeof(int) * 8 -
01825                 cuddComputeFloorLog2(numSlots);
01826             unique->subtables[level+i].keys = 0;
01827             unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
01828             unique->subtables[level+i].dead = 0;
01829             unique->subtables[level+i].bindVar = 0;
01830             unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT;
01831             unique->subtables[level+i].pairIndex = 0;
01832             unique->subtables[level+i].varHandled = 0;
01833             unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE;
01834 
01835             unique->perm[oldsize+i] = level + i;
01836             unique->invperm[level+i] = oldsize + i;
01837             newnodelist = unique->subtables[level+i].nodelist =
01838                 ALLOC(DdNodePtr, numSlots);
01839             if (newnodelist == NULL) {
01840                 unique->errorCode = CUDD_MEMORY_OUT;
01841                 return(0);
01842             }
01843             for (j = 0; (unsigned) j < numSlots; j++) {
01844                 newnodelist[j] = sentinel;
01845             }
01846         }
01847         if (unique->map != NULL) {
01848             for (i = 0; i < n; i++) {
01849                 unique->map[oldsize+i] = oldsize + i;
01850             }
01851         }
01852     } else {
01853         /* The current table is too small: we need to allocate a new,
01854         ** larger one; move all old subtables, and initialize the new
01855         ** subtables.
01856         */
01857         newsize = oldsize + n + DD_DEFAULT_RESIZE;
01858 #ifdef DD_VERBOSE
01859         (void) fprintf(unique->err,
01860                        "Increasing the table size from %d to %d\n",
01861             unique->maxSize, newsize);
01862 #endif
01863         /* Allocate memory for new arrays (except nodelists). */
01864         newsubtables = ALLOC(DdSubtable,newsize);
01865         if (newsubtables == NULL) {
01866             unique->errorCode = CUDD_MEMORY_OUT;
01867             return(0);
01868         }
01869         newvars = ALLOC(DdNodePtr,newsize);
01870         if (newvars == NULL) {
01871             unique->errorCode = CUDD_MEMORY_OUT;
01872             FREE(newsubtables);
01873             return(0);
01874         }
01875         newperm = ALLOC(int,newsize);
01876         if (newperm == NULL) {
01877             unique->errorCode = CUDD_MEMORY_OUT;
01878             FREE(newsubtables);
01879             FREE(newvars);
01880             return(0);
01881         }
01882         newinvperm = ALLOC(int,newsize);
01883         if (newinvperm == NULL) {
01884             unique->errorCode = CUDD_MEMORY_OUT;
01885             FREE(newsubtables);
01886             FREE(newvars);
01887             FREE(newperm);
01888             return(0);
01889         }
01890         if (unique->map != NULL) {
01891             newmap = ALLOC(int,newsize);
01892             if (newmap == NULL) {
01893                 unique->errorCode = CUDD_MEMORY_OUT;
01894                 FREE(newsubtables);
01895                 FREE(newvars);
01896                 FREE(newperm);
01897                 FREE(newinvperm);
01898                 return(0);
01899             }
01900             unique->memused += (newsize - unique->maxSize) * sizeof(int);
01901         }
01902         unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
01903             sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
01904         /* Copy levels before insertion points from old tables. */
01905         for (i = 0; i < level; i++) {
01906             newsubtables[i].slots = unique->subtables[i].slots;
01907             newsubtables[i].shift = unique->subtables[i].shift;
01908             newsubtables[i].keys = unique->subtables[i].keys;
01909             newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
01910             newsubtables[i].dead = unique->subtables[i].dead;
01911             newsubtables[i].nodelist = unique->subtables[i].nodelist;
01912             newsubtables[i].bindVar = unique->subtables[i].bindVar;
01913             newsubtables[i].varType = unique->subtables[i].varType;
01914             newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
01915             newsubtables[i].varHandled = unique->subtables[i].varHandled;
01916             newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
01917 
01918             newvars[i] = unique->vars[i];
01919             newperm[i] = unique->perm[i];
01920             newinvperm[i] = unique->invperm[i];
01921         }
01922         /* Finish initializing permutation for new table to old one. */
01923         for (i = level; i < oldsize; i++) {
01924             newperm[i] = unique->perm[i];
01925         }
01926         /* Initialize new levels. */
01927         for (i = level; i < level + n; i++) {
01928             newsubtables[i].slots = numSlots;
01929             newsubtables[i].shift = sizeof(int) * 8 -
01930                 cuddComputeFloorLog2(numSlots);
01931             newsubtables[i].keys = 0;
01932             newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
01933             newsubtables[i].dead = 0;
01934             newsubtables[i].bindVar = 0;
01935             newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
01936             newsubtables[i].pairIndex = 0;
01937             newsubtables[i].varHandled = 0;
01938             newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
01939 
01940             newperm[oldsize + i - level] = i;
01941             newinvperm[i] = oldsize + i - level;
01942             newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
01943             if (newnodelist == NULL) {
01944                 /* We are going to leak some memory.  We should clean up. */
01945                 unique->errorCode = CUDD_MEMORY_OUT;
01946                 return(0);
01947             }
01948             for (j = 0; (unsigned) j < numSlots; j++) {
01949                 newnodelist[j] = sentinel;
01950             }
01951         }
01952         /* Copy the old tables for levels past the insertion point. */
01953         for (i = level; i < oldsize; i++) {
01954             newsubtables[i+n].slots    = unique->subtables[i].slots;
01955             newsubtables[i+n].shift    = unique->subtables[i].shift;
01956             newsubtables[i+n].keys     = unique->subtables[i].keys;
01957             newsubtables[i+n].maxKeys  = unique->subtables[i].maxKeys;
01958             newsubtables[i+n].dead     = unique->subtables[i].dead;
01959             newsubtables[i+n].nodelist = unique->subtables[i].nodelist;
01960             newsubtables[i+n].bindVar  = unique->subtables[i].bindVar;
01961             newsubtables[i+n].varType  = unique->subtables[i].varType;
01962             newsubtables[i+n].pairIndex  = unique->subtables[i].pairIndex;
01963             newsubtables[i+n].varHandled  = unique->subtables[i].varHandled;
01964             newsubtables[i+n].varToBeGrouped  =
01965                 unique->subtables[i].varToBeGrouped;
01966 
01967             newvars[i]                 = unique->vars[i];
01968             index                      = unique->invperm[i];
01969             newinvperm[i+n]            = index;
01970             newperm[index]            += n;
01971         }
01972         /* Update the map. */
01973         if (unique->map != NULL) {
01974             for (i = 0; i < oldsize; i++) {
01975                 newmap[i] = unique->map[i];
01976             }
01977             for (i = oldsize; i < oldsize + n; i++) {
01978                 newmap[i] = i;
01979             }
01980             FREE(unique->map);
01981             unique->map = newmap;
01982         }
01983         /* Install the new tables and free the old ones. */
01984         FREE(unique->subtables);
01985         unique->subtables = newsubtables;
01986         unique->maxSize = newsize;
01987         FREE(unique->vars);
01988         unique->vars = newvars;
01989         FREE(unique->perm);
01990         unique->perm = newperm;
01991         FREE(unique->invperm);
01992         unique->invperm = newinvperm;
01993         /* Update the stack for iterative procedures. */
01994         if (newsize > unique->maxSizeZ) {
01995             FREE(unique->stack);
01996             unique->stack = ALLOC(DdNodePtr,newsize + 1);
01997             if (unique->stack == NULL) {
01998                 unique->errorCode = CUDD_MEMORY_OUT;
01999                 return(0);
02000             }
02001             unique->stack[0] = NULL; /* to suppress harmless UMR */
02002             unique->memused +=
02003                 (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
02004                 * sizeof(DdNode *);
02005         }
02006     }
02007     /* Update manager parameters to account for the new subtables. */
02008     unique->slots += n * numSlots;
02009     ddFixLimits(unique);
02010     unique->size += n;
02011 
02012     /* Now that the table is in a coherent state, create the new
02013     ** projection functions. We need to temporarily disable reordering,
02014     ** because we cannot reorder without projection functions in place.
02015     **/
02016     one = unique->one;
02017     zero = Cudd_Not(one);
02018 
02019     reorderSave = unique->autoDyn;
02020     unique->autoDyn = 0;
02021     for (i = oldsize; i < oldsize + n; i++) {
02022         unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
02023         if (unique->vars[i] == NULL) {
02024             unique->autoDyn = reorderSave;
02025             /* Shift everything back so table remains coherent. */
02026             for (j = oldsize; j < i; j++) {
02027                 Cudd_IterDerefBdd(unique,unique->vars[j]);
02028                 cuddDeallocNode(unique,unique->vars[j]);
02029                 unique->vars[j] = NULL;
02030             }
02031             for (j = level; j < oldsize; j++) {
02032                 unique->subtables[j].slots    = unique->subtables[j+n].slots;
02033                 unique->subtables[j].slots    = unique->subtables[j+n].slots;
02034                 unique->subtables[j].shift    = unique->subtables[j+n].shift;
02035                 unique->subtables[j].keys     = unique->subtables[j+n].keys;
02036                 unique->subtables[j].maxKeys  =
02037                     unique->subtables[j+n].maxKeys;
02038                 unique->subtables[j].dead     = unique->subtables[j+n].dead;
02039                 FREE(unique->subtables[j].nodelist);
02040                 unique->subtables[j].nodelist =
02041                     unique->subtables[j+n].nodelist;
02042                 unique->subtables[j+n].nodelist = NULL;
02043                 unique->subtables[j].bindVar  =
02044                     unique->subtables[j+n].bindVar;
02045                 unique->subtables[j].varType  =
02046                     unique->subtables[j+n].varType;
02047                 unique->subtables[j].pairIndex =
02048                     unique->subtables[j+n].pairIndex;
02049                 unique->subtables[j].varHandled =
02050                     unique->subtables[j+n].varHandled;
02051                 unique->subtables[j].varToBeGrouped =
02052                     unique->subtables[j+n].varToBeGrouped;
02053                 index                         = unique->invperm[j+n];
02054                 unique->invperm[j]            = index;
02055                 unique->perm[index]          -= n;
02056             }
02057             unique->size = oldsize;
02058             unique->slots -= n * numSlots;
02059             ddFixLimits(unique);
02060             (void) Cudd_DebugCheck(unique);
02061             return(0);
02062         }
02063         cuddRef(unique->vars[i]);
02064     }
02065     if (unique->tree != NULL) {
02066         unique->tree->size += n;
02067         unique->tree->index = unique->invperm[0];
02068         ddPatchTree(unique,unique->tree);
02069     }
02070     unique->autoDyn = reorderSave;
02071 
02072     return(1);
02073 
02074 } /* end of cuddInsertSubtables */

int cuddIsInDeathRow ( DdManager dd,
DdNode f 
)

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

Synopsis [Checks whether a node is in the death row.]

Description [Checks whether a node is in the death row. Returns the position of the first occurrence if the node is present; -1 otherwise.]

SideEffects [None]

SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow]

Definition at line 758 of file cuddRef.c.

00761 {
00762 #ifndef DD_NO_DEATH_ROW
00763     int i;
00764 
00765     for (i = 0; i < dd->deathRowDepth; i++) {
00766         if (f == dd->deathRow[i]) {
00767             return(i);
00768         }
00769     }
00770 #endif
00771 
00772     return(-1);
00773 
00774 } /* end of cuddIsInDeathRow */

void cuddLevelQueueDequeue ( DdLevelQueue queue,
int  level 
)

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

Synopsis [Remove an item from the front of a level queue.]

Description [Remove an item from the front of a level queue.]

SideEffects [None]

SeeAlso [cuddLevelQueueEnqueue]

Definition at line 350 of file cuddLevelQ.c.

00353 {
00354     DdQueueItem *item = (DdQueueItem *) queue->first;
00355 
00356     /* Delete from the hash table. */
00357     hashDelete(queue,item);
00358 
00359     /* Since we delete from the front, if this is the last item for
00360     ** its level, there are no other items for the same level. */
00361     if (queue->last[level] == item)
00362         queue->last[level] = NULL;
00363 
00364     queue->first = item->next;
00365     /* Put item on the free list. */
00366     item->next = queue->freelist;
00367     queue->freelist = item;
00368     /* Update stats. */
00369     queue->size--;
00370     return;
00371 
00372 } /* end of cuddLevelQueueDequeue */

void* cuddLevelQueueEnqueue ( DdLevelQueue queue,
void *  key,
int  level 
)

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

Synopsis [Inserts a new key in a level queue.]

Description [Inserts a new key in a level queue. A new entry is created in the queue only if the node is not already enqueued. Returns a pointer to the queue item if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue]

Definition at line 278 of file cuddLevelQ.c.

00282 {
00283     int plevel;
00284     DdQueueItem *item;
00285 
00286 #ifdef DD_DEBUG
00287     assert(level < queue->levels);
00288 #endif
00289     /* Check whether entry for this node exists. */
00290     item = hashLookup(queue,key);
00291     if (item != NULL) return(item);
00292 
00293     /* Get a free item from either the free list or the memory manager. */
00294     if (queue->freelist == NULL) {
00295         item = (DdQueueItem *) ALLOC(char, queue->itemsize);
00296         if (item == NULL)
00297             return(NULL);
00298     } else {
00299         item = queue->freelist;
00300         queue->freelist = item->next;
00301     }
00302     /* Initialize. */
00303     memset(item, 0, queue->itemsize);
00304     item->key = key;
00305     /* Update stats. */
00306     queue->size++;
00307 
00308     if (queue->last[level]) {
00309         /* There are already items for this level in the queue. */
00310         item->next = queue->last[level]->next;
00311         queue->last[level]->next = item;
00312     } else {
00313         /* There are no items at the current level.  Look for the first
00314         ** non-empty level preceeding this one. */
00315         plevel = level;
00316         while (plevel != 0 && queue->last[plevel] == NULL)
00317             plevel--;
00318         if (queue->last[plevel] == NULL) {
00319             /* No element precedes this one in the queue. */
00320             item->next = (DdQueueItem *) queue->first;
00321             queue->first = item;
00322         } else {
00323             item->next = queue->last[plevel]->next;
00324             queue->last[plevel]->next = item;
00325         }
00326     }
00327     queue->last[level] = item;
00328 
00329     /* Insert entry for the key in the hash table. */
00330     if (hashInsert(queue,item) == 0) {
00331         return(NULL);
00332     }
00333     return(item);
00334 
00335 } /* end of cuddLevelQueueEnqueue */

DdLevelQueue* cuddLevelQueueInit ( int  levels,
int  itemSize,
int  numBuckets 
)

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

Synopsis [Initializes a level queue.]

Description [Initializes a level queue. A level queue is a queue where inserts are based on the levels of the nodes. Within each level the policy is FIFO. Level queues are useful in traversing a BDD top-down. Queue items are kept in a free list when dequeued for efficiency. Returns a pointer to the new queue if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue]

Definition at line 165 of file cuddLevelQ.c.

00169 {
00170     DdLevelQueue *queue;
00171     int logSize;
00172 
00173     queue = ALLOC(DdLevelQueue,1);
00174     if (queue == NULL)
00175         return(NULL);
00176 #ifdef __osf__
00177 #pragma pointer_size save
00178 #pragma pointer_size short
00179 #endif
00180     /* Keep pointers to the insertion points for all levels. */
00181     queue->last = ALLOC(DdQueueItem *, levels);
00182 #ifdef __osf__
00183 #pragma pointer_size restore
00184 #endif
00185     if (queue->last == NULL) {
00186         FREE(queue);
00187         return(NULL);
00188     }
00189     /* Use a hash table to test for uniqueness. */
00190     if (numBuckets < 2) numBuckets = 2;
00191     logSize = cuddComputeFloorLog2(numBuckets);
00192     queue->numBuckets = 1 << logSize;
00193     queue->shift = sizeof(int) * 8 - logSize;
00194 #ifdef __osf__
00195 #pragma pointer_size save
00196 #pragma pointer_size short
00197 #endif
00198     queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets);
00199 #ifdef __osf__
00200 #pragma pointer_size restore
00201 #endif
00202     if (queue->buckets == NULL) {
00203         FREE(queue->last);
00204         FREE(queue);
00205         return(NULL);
00206     }
00207 #ifdef __osf__
00208 #pragma pointer_size save
00209 #pragma pointer_size short
00210 #endif
00211     memset(queue->last, 0, levels * sizeof(DdQueueItem *));
00212     memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *));
00213 #ifdef __osf__
00214 #pragma pointer_size restore
00215 #endif
00216     queue->first = NULL;
00217     queue->freelist = NULL;
00218     queue->levels = levels;
00219     queue->itemsize = itemSize;
00220     queue->size = 0;
00221     queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY;
00222     return(queue);
00223 
00224 } /* end of cuddLevelQueueInit */

void cuddLevelQueueQuit ( DdLevelQueue queue  ) 

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

Synopsis [Shuts down a level queue.]

Description [Shuts down a level queue and releases all the associated memory.]

SideEffects [None]

SeeAlso [cuddLevelQueueInit]

Definition at line 240 of file cuddLevelQ.c.

00242 {
00243     DdQueueItem *item;
00244 
00245     while (queue->freelist != NULL) {
00246         item = queue->freelist;
00247         queue->freelist = item->next;
00248         FREE(item);
00249     }
00250     while (queue->first != NULL) {
00251         item = (DdQueueItem *) queue->first;
00252         queue->first = item->next;
00253         FREE(item);
00254     }
00255     FREE(queue->buckets);
00256     FREE(queue->last);
00257     FREE(queue);
00258     return;
00259 
00260 } /* end of cuddLevelQueueQuit */

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

00240 {
00241     int         i;
00242     int         *var;
00243     int         size;
00244     int         x;
00245     int         result;
00246 #ifdef DD_STATS
00247     int         previousSize;
00248 #endif
00249 
00250 #ifdef DD_STATS
00251     ddTotalNumberLinearTr = 0;
00252 #endif
00253 
00254     size = table->size;
00255 
00256     var = NULL;
00257     entry = NULL;
00258     if (table->linear == NULL) {
00259         result = cuddInitLinear(table);
00260         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00261 #if 0
00262         (void) fprintf(table->out,"\n");
00263         result = Cudd_PrintLinear(table);
00264         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00265 #endif
00266     } else if (table->size != table->linearSize) {
00267         result = cuddResizeLinear(table);
00268         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00269 #if 0
00270         (void) fprintf(table->out,"\n");
00271         result = Cudd_PrintLinear(table);
00272         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00273 #endif
00274     }
00275 
00276     /* Find order in which to sift variables. */
00277     entry = ALLOC(int,size);
00278     if (entry == NULL) {
00279         table->errorCode = CUDD_MEMORY_OUT;
00280         goto cuddLinearAndSiftingOutOfMem;
00281     }
00282     var = ALLOC(int,size);
00283     if (var == NULL) {
00284         table->errorCode = CUDD_MEMORY_OUT;
00285         goto cuddLinearAndSiftingOutOfMem;
00286     }
00287 
00288     for (i = 0; i < size; i++) {
00289         x = table->perm[i];
00290         entry[i] = table->subtables[x].keys;
00291         var[i] = i;
00292     }
00293 
00294     qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare);
00295 
00296     /* Now sift. */
00297     for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00298         x = table->perm[var[i]];
00299         if (x < lower || x > upper) continue;
00300 #ifdef DD_STATS
00301         previousSize = table->keys - table->isolated;
00302 #endif
00303         result = ddLinearAndSiftingAux(table,x,lower,upper);
00304         if (!result) goto cuddLinearAndSiftingOutOfMem;
00305 #ifdef DD_STATS
00306         if (table->keys < (unsigned) previousSize + table->isolated) {
00307             (void) fprintf(table->out,"-");
00308         } else if (table->keys > (unsigned) previousSize + table->isolated) {
00309             (void) fprintf(table->out,"+");     /* should never happen */
00310             (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00311         } else {
00312             (void) fprintf(table->out,"=");
00313         }
00314         fflush(table->out);
00315 #endif
00316 #ifdef DD_DEBUG
00317         (void) Cudd_DebugCheck(table);
00318 #endif
00319     }
00320 
00321     FREE(var);
00322     FREE(entry);
00323 
00324 #ifdef DD_STATS
00325     (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
00326                    ddTotalNumberLinearTr);
00327 #endif
00328 
00329     return(1);
00330 
00331 cuddLinearAndSiftingOutOfMem:
00332 
00333     if (entry != NULL) FREE(entry);
00334     if (var != NULL) FREE(var);
00335 
00336     return(0);
00337 
00338 } /* end of cuddLinearAndSifting */

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

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

00364 {
00365     DdNodePtr *xlist, *ylist;
00366     int    xindex, yindex;
00367     int    xslots, yslots;
00368     int    xshift, yshift;
00369     int    oldxkeys, oldykeys;
00370     int    newxkeys, newykeys;
00371     int    comple, newcomplement;
00372     int    i;
00373     int    posn;
00374     int    isolated;
00375     DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00376     DdNode *g,*next,*last;
00377     DdNodePtr *previousP;
00378     DdNode *tmp;
00379     DdNode *sentinel = &(table->sentinel);
00380 #ifdef DD_DEBUG
00381     int    count, idcheck;
00382 #endif
00383 
00384 #ifdef DD_DEBUG
00385     assert(x < y);
00386     assert(cuddNextHigh(table,x) == y);
00387     assert(table->subtables[x].keys != 0);
00388     assert(table->subtables[y].keys != 0);
00389     assert(table->subtables[x].dead == 0);
00390     assert(table->subtables[y].dead == 0);
00391 #endif
00392 
00393     xindex = table->invperm[x];
00394     yindex = table->invperm[y];
00395 
00396     if (cuddTestInteract(table,xindex,yindex)) {
00397 #ifdef DD_STATS
00398         ddTotalNumberLinearTr++;
00399 #endif
00400         /* Get parameters of x subtable. */
00401         xlist = table->subtables[x].nodelist;
00402         oldxkeys = table->subtables[x].keys;
00403         xslots = table->subtables[x].slots;
00404         xshift = table->subtables[x].shift;
00405 
00406         /* Get parameters of y subtable. */
00407         ylist = table->subtables[y].nodelist;
00408         oldykeys = table->subtables[y].keys;
00409         yslots = table->subtables[y].slots;
00410         yshift = table->subtables[y].shift;
00411 
00412         newxkeys = 0;
00413         newykeys = oldykeys;
00414 
00415         /* Check whether the two projection functions involved in this
00416         ** swap are isolated. At the end, we'll be able to tell how many
00417         ** isolated projection functions are there by checking only these
00418         ** two functions again. This is done to eliminate the isolated
00419         ** projection functions from the node count.
00420         */
00421         isolated = - ((table->vars[xindex]->ref == 1) +
00422                      (table->vars[yindex]->ref == 1));
00423 
00424         /* The nodes in the x layer are put in a chain.
00425         ** The chain is handled as a FIFO; g points to the beginning and
00426         ** last points to the end.
00427         */
00428         g = NULL;
00429 #ifdef DD_DEBUG
00430         last = NULL;
00431 #endif
00432         for (i = 0; i < xslots; i++) {
00433             f = xlist[i];
00434             if (f == sentinel) continue;
00435             xlist[i] = sentinel;
00436             if (g == NULL) {
00437                 g = f;
00438             } else {
00439                 last->next = f;
00440             }
00441             while ((next = f->next) != sentinel) {
00442                 f = next;
00443             } /* while there are elements in the collision chain */
00444             last = f;
00445         } /* for each slot of the x subtable */
00446 #ifdef DD_DEBUG
00447         /* last is always assigned in the for loop because there is at
00448         ** least one key */
00449         assert(last != NULL);
00450 #endif
00451         last->next = NULL;
00452 
00453 #ifdef DD_COUNT
00454         table->swapSteps += oldxkeys;
00455 #endif
00456         /* Take care of the x nodes that must be re-expressed.
00457         ** They form a linked list pointed by g.
00458         */
00459         f = g;
00460         while (f != NULL) {
00461             next = f->next;
00462             /* Find f1, f0, f11, f10, f01, f00. */
00463             f1 = cuddT(f);
00464 #ifdef DD_DEBUG
00465             assert(!(Cudd_IsComplement(f1)));
00466 #endif
00467             if ((int) f1->index == yindex) {
00468                 f11 = cuddT(f1); f10 = cuddE(f1);
00469             } else {
00470                 f11 = f10 = f1;
00471             }
00472 #ifdef DD_DEBUG
00473             assert(!(Cudd_IsComplement(f11)));
00474 #endif
00475             f0 = cuddE(f);
00476             comple = Cudd_IsComplement(f0);
00477             f0 = Cudd_Regular(f0);
00478             if ((int) f0->index == yindex) {
00479                 f01 = cuddT(f0); f00 = cuddE(f0);
00480             } else {
00481                 f01 = f00 = f0;
00482             }
00483             if (comple) {
00484                 f01 = Cudd_Not(f01);
00485                 f00 = Cudd_Not(f00);
00486             }
00487             /* Decrease ref count of f1. */
00488             cuddSatDec(f1->ref);
00489             /* Create the new T child. */
00490             if (f11 == f00) {
00491                 newf1 = f11;
00492                 cuddSatInc(newf1->ref);
00493             } else {
00494                 /* Check ylist for triple (yindex,f11,f00). */
00495                 posn = ddHash(f11, f00, yshift);
00496                 /* For each element newf1 in collision list ylist[posn]. */
00497                 previousP = &(ylist[posn]);
00498                 newf1 = *previousP;
00499                 while (f11 < cuddT(newf1)) {
00500                     previousP = &(newf1->next);
00501                     newf1 = *previousP;
00502                 }
00503                 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
00504                     previousP = &(newf1->next);
00505                     newf1 = *previousP;
00506                 }
00507                 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
00508                     cuddSatInc(newf1->ref);
00509                 } else { /* no match */
00510                     newf1 = cuddDynamicAllocNode(table);
00511                     if (newf1 == NULL)
00512                         goto cuddLinearOutOfMem;
00513                     newf1->index = yindex; newf1->ref = 1;
00514                     cuddT(newf1) = f11;
00515                     cuddE(newf1) = f00;
00516                     /* Insert newf1 in the collision list ylist[posn];
00517                     ** increase the ref counts of f11 and f00.
00518                     */
00519                     newykeys++;
00520                     newf1->next = *previousP;
00521                     *previousP = newf1;
00522                     cuddSatInc(f11->ref);
00523                     tmp = Cudd_Regular(f00);
00524                     cuddSatInc(tmp->ref);
00525                 }
00526             }
00527             cuddT(f) = newf1;
00528 #ifdef DD_DEBUG
00529             assert(!(Cudd_IsComplement(newf1)));
00530 #endif
00531 
00532             /* Do the same for f0, keeping complement dots into account. */
00533             /* decrease ref count of f0 */
00534             tmp = Cudd_Regular(f0);
00535             cuddSatDec(tmp->ref);
00536             /* create the new E child */
00537             if (f01 == f10) {
00538                 newf0 = f01;
00539                 tmp = Cudd_Regular(newf0);
00540                 cuddSatInc(tmp->ref);
00541             } else {
00542                 /* make sure f01 is regular */
00543                 newcomplement = Cudd_IsComplement(f01);
00544                 if (newcomplement) {
00545                     f01 = Cudd_Not(f01);
00546                     f10 = Cudd_Not(f10);
00547                 }
00548                 /* Check ylist for triple (yindex,f01,f10). */
00549                 posn = ddHash(f01, f10, yshift);
00550                 /* For each element newf0 in collision list ylist[posn]. */
00551                 previousP = &(ylist[posn]);
00552                 newf0 = *previousP;
00553                 while (f01 < cuddT(newf0)) {
00554                     previousP = &(newf0->next);
00555                     newf0 = *previousP;
00556                 }
00557                 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
00558                     previousP = &(newf0->next);
00559                     newf0 = *previousP;
00560                 }
00561                 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
00562                     cuddSatInc(newf0->ref);
00563                 } else { /* no match */
00564                     newf0 = cuddDynamicAllocNode(table);
00565                     if (newf0 == NULL)
00566                         goto cuddLinearOutOfMem;
00567                     newf0->index = yindex; newf0->ref = 1;
00568                     cuddT(newf0) = f01;
00569                     cuddE(newf0) = f10;
00570                     /* Insert newf0 in the collision list ylist[posn];
00571                     ** increase the ref counts of f01 and f10.
00572                     */
00573                     newykeys++;
00574                     newf0->next = *previousP;
00575                     *previousP = newf0;
00576                     cuddSatInc(f01->ref);
00577                     tmp = Cudd_Regular(f10);
00578                     cuddSatInc(tmp->ref);
00579                 }
00580                 if (newcomplement) {
00581                     newf0 = Cudd_Not(newf0);
00582                 }
00583             }
00584             cuddE(f) = newf0;
00585 
00586             /* Re-insert the modified f in xlist.
00587             ** The modified f does not already exists in xlist.
00588             ** (Because of the uniqueness of the cofactors.)
00589             */
00590             posn = ddHash(newf1, newf0, xshift);
00591             newxkeys++;
00592             previousP = &(xlist[posn]);
00593             tmp = *previousP;
00594             while (newf1 < cuddT(tmp)) {
00595                 previousP = &(tmp->next);
00596                 tmp = *previousP;
00597             }
00598             while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
00599                 previousP = &(tmp->next);
00600                 tmp = *previousP;
00601             }
00602             f->next = *previousP;
00603             *previousP = f;
00604             f = next;
00605         } /* while f != NULL */
00606 
00607         /* GC the y layer. */
00608 
00609         /* For each node f in ylist. */
00610         for (i = 0; i < yslots; i++) {
00611             previousP = &(ylist[i]);
00612             f = *previousP;
00613             while (f != sentinel) {
00614                 next = f->next;
00615                 if (f->ref == 0) {
00616                     tmp = cuddT(f);
00617                     cuddSatDec(tmp->ref);
00618                     tmp = Cudd_Regular(cuddE(f));
00619                     cuddSatDec(tmp->ref);
00620                     cuddDeallocNode(table,f);
00621                     newykeys--;
00622                 } else {
00623                     *previousP = f;
00624                     previousP = &(f->next);
00625                 }
00626                 f = next;
00627             } /* while f */
00628             *previousP = sentinel;
00629         } /* for every collision list */
00630 
00631 #ifdef DD_DEBUG
00632 #if 0
00633         (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
00634 #endif
00635         count = 0;
00636         idcheck = 0;
00637         for (i = 0; i < yslots; i++) {
00638             f = ylist[i];
00639             while (f != sentinel) {
00640                 count++;
00641                 if (f->index != (DdHalfWord) yindex)
00642                     idcheck++;
00643                 f = f->next;
00644             }
00645         }
00646         if (count != newykeys) {
00647             fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
00648         }
00649         if (idcheck != 0)
00650             fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
00651         count = 0;
00652         idcheck = 0;
00653         for (i = 0; i < xslots; i++) {
00654             f = xlist[i];
00655             while (f != sentinel) {
00656                 count++;
00657                 if (f->index != (DdHalfWord) xindex)
00658                     idcheck++;
00659                 f = f->next;
00660             }
00661         }
00662         if (count != newxkeys || newxkeys != oldxkeys) {
00663             fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
00664         }
00665         if (idcheck != 0)
00666             fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
00667 #endif
00668 
00669         isolated += (table->vars[xindex]->ref == 1) +
00670                     (table->vars[yindex]->ref == 1);
00671         table->isolated += isolated;
00672 
00673         /* Set the appropriate fields in table. */
00674         table->subtables[y].keys = newykeys;
00675 
00676         /* Here we should update the linear combination table
00677         ** to record that x <- x EXNOR y. This is done by complementing
00678         ** the (x,y) entry of the table.
00679         */
00680 
00681         table->keys += newykeys - oldykeys;
00682 
00683         cuddXorLinear(table,xindex,yindex);
00684     }
00685 
00686 #ifdef DD_DEBUG
00687     if (zero) {
00688         (void) Cudd_DebugCheck(table);
00689     }
00690 #endif
00691 
00692     return(table->keys - table->isolated);
00693 
00694 cuddLinearOutOfMem:
00695     (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
00696 
00697     return (0);
00698 
00699 } /* end of cuddLinearInPlace */

void cuddLocalCacheClearAll ( DdManager manager  ) 

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

Synopsis [Clears the local caches of a manager.]

Description [Clears the local caches of a manager. Used before reordering.]

SideEffects [None]

SeeAlso []

Definition at line 400 of file cuddLCache.c.

00402 {
00403     DdLocalCache *cache = manager->localCaches;
00404 
00405     while (cache != NULL) {
00406         memset(cache->item, 0, cache->slots * cache->itemsize);
00407         cache = cache->next;
00408     }
00409     return;
00410 
00411 } /* end of cuddLocalCacheClearAll */

void cuddLocalCacheClearDead ( DdManager manager  ) 

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

Synopsis [Clears the dead entries of the local caches of a manager.]

Description [Clears the dead entries of the local caches of a manager. Used during garbage collection.]

SideEffects [None]

SeeAlso []

Definition at line 348 of file cuddLCache.c.

00350 {
00351     DdLocalCache *cache = manager->localCaches;
00352     unsigned int keysize;
00353     unsigned int itemsize;
00354     unsigned int slots;
00355     DdLocalCacheItem *item;
00356     DdNodePtr *key;
00357     unsigned int i, j;
00358 
00359     while (cache != NULL) {
00360         keysize = cache->keysize;
00361         itemsize = cache->itemsize;
00362         slots = cache->slots;
00363         item = cache->item;
00364         for (i = 0; i < slots; i++) {
00365             if (item->value != NULL) {
00366                 if (Cudd_Regular(item->value)->ref == 0) {
00367                     item->value = NULL;
00368                 } else {
00369                     key = item->key;
00370                     for (j = 0; j < keysize; j++) {
00371                         if (Cudd_Regular(key[j])->ref == 0) {
00372                             item->value = NULL;
00373                             break;
00374                         }
00375                     }
00376                 }
00377             }
00378             item = (DdLocalCacheItem *) ((char *) item + itemsize);
00379         }
00380         cache = cache->next;
00381     }
00382     return;
00383 
00384 } /* end of cuddLocalCacheClearDead */

DdLocalCache* cuddLocalCacheInit ( DdManager manager,
unsigned int  keySize,
unsigned int  cacheSize,
unsigned int  maxCacheSize 
)

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

Synopsis [Initializes a local computed table.]

Description [Initializes a computed table. Returns a pointer the the new local cache in case of success; NULL otherwise.]

SideEffects [None]

SeeAlso [cuddInitCache]

Definition at line 179 of file cuddLCache.c.

00184 {
00185     DdLocalCache *cache;
00186     int logSize;
00187 
00188     cache = ALLOC(DdLocalCache,1);
00189     if (cache == NULL) {
00190         manager->errorCode = CUDD_MEMORY_OUT;
00191         return(NULL);
00192     }
00193     cache->manager = manager;
00194     cache->keysize = keySize;
00195     cache->itemsize = (keySize + 1) * sizeof(DdNode *);
00196 #ifdef DD_CACHE_PROFILE
00197     cache->itemsize += sizeof(ptrint);
00198 #endif
00199     logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2));
00200     cacheSize = 1 << logSize;
00201     cache->item = (DdLocalCacheItem *)
00202         ALLOC(char, cacheSize * cache->itemsize);
00203     if (cache->item == NULL) {
00204         manager->errorCode = CUDD_MEMORY_OUT;
00205         FREE(cache);
00206         return(NULL);
00207     }
00208     cache->slots = cacheSize;
00209     cache->shift = sizeof(int) * 8 - logSize;
00210     cache->maxslots = ddMin(maxCacheSize,manager->slots);
00211     cache->minHit = manager->minHit;
00212     /* Initialize to avoid division by 0 and immediate resizing. */
00213     cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1);
00214     cache->hits = 0;
00215     manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache);
00216 
00217     /* Initialize the cache. */
00218     memset(cache->item, 0, cacheSize * cache->itemsize);
00219 
00220     /* Add to manager's list of local caches for GC. */
00221     cuddLocalCacheAddToList(cache);
00222 
00223     return(cache);
00224 
00225 } /* end of cuddLocalCacheInit */

void cuddLocalCacheInsert ( DdLocalCache cache,
DdNodePtr key,
DdNode value 
)

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

Synopsis [Inserts a result in a local cache.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 268 of file cuddLCache.c.

00272 {
00273     unsigned int posn;
00274     DdLocalCacheItem *entry;
00275 
00276     posn = ddLCHash(key,cache->keysize,cache->shift);
00277     entry = (DdLocalCacheItem *) ((char *) cache->item +
00278                                   posn * cache->itemsize);
00279     memcpy(entry->key,key,cache->keysize * sizeof(DdNode *));
00280     entry->value = value;
00281 #ifdef DD_CACHE_PROFILE
00282     entry->count++;
00283 #endif
00284 
00285 } /* end of cuddLocalCacheInsert */

DdNode* cuddLocalCacheLookup ( DdLocalCache cache,
DdNodePtr key 
)

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

Synopsis [Looks up in a local cache.]

Description [Looks up in a local cache. Returns the result if found; it returns NULL if no result is found.]

SideEffects [None]

SeeAlso []

Definition at line 301 of file cuddLCache.c.

00304 {
00305     unsigned int posn;
00306     DdLocalCacheItem *entry;
00307     DdNode *value;
00308 
00309     cache->lookUps++;
00310     posn = ddLCHash(key,cache->keysize,cache->shift);
00311     entry = (DdLocalCacheItem *) ((char *) cache->item +
00312                                   posn * cache->itemsize);
00313     if (entry->value != NULL &&
00314         memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) {
00315         cache->hits++;
00316         value = Cudd_Regular(entry->value);
00317         if (value->ref == 0) {
00318             cuddReclaim(cache->manager,value);
00319         }
00320         return(entry->value);
00321     }
00322 
00323     /* Cache miss: decide whether to resize */
00324 
00325     if (cache->slots < cache->maxslots &&
00326         cache->hits > cache->lookUps * cache->minHit) {
00327         cuddLocalCacheResize(cache);
00328     }
00329 
00330     return(NULL);
00331 
00332 } /* end of cuddLocalCacheLookup */

void cuddLocalCacheQuit ( DdLocalCache cache  ) 

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

Synopsis [Shuts down a local computed table.]

Description [Initializes the computed table. It is called by Cudd_Init. Returns a pointer the the new local cache in case of success; NULL otherwise.]

SideEffects [None]

SeeAlso [cuddLocalCacheInit]

Definition at line 242 of file cuddLCache.c.

00244 {
00245     cache->manager->memused -=
00246         cache->slots * cache->itemsize + sizeof(DdLocalCache);
00247     cuddLocalCacheRemoveFromList(cache);
00248     FREE(cache->item);
00249     FREE(cache);
00250 
00251     return;
00252 
00253 } /* end of cuddLocalCacheQuit */

DdNode* cuddMakeBddFromZddCover ( DdManager dd,
DdNode node 
)

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

Synopsis [Converts a ZDD cover to a BDD graph.]

Description [Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, otherwise it returns NULL. It is a recursive algorithm as the following. First computes 3 cofactors of a ZDD cover; f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd. Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v is the variable which has the index of the top node of the ZDD cover. In this case, since the index of v can be larger than either one of T or one of E, cuddUniqueInterIVO is called, here IVO stands for independent variable ordering.]

SideEffects []

SeeAlso [Cudd_MakeBddFromZddCover]

Definition at line 796 of file cuddZddIsop.c.

00799 {
00800     DdNode      *neW;
00801     int         v;
00802     DdNode      *f1, *f0, *fd;
00803     DdNode      *b1, *b0, *bd;
00804     DdNode      *T, *E;
00805 
00806     statLine(dd);
00807     if (node == dd->one)
00808         return(dd->one);
00809     if (node == dd->zero)
00810         return(Cudd_Not(dd->one));
00811 
00812     /* Check cache */
00813     neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node);
00814     if (neW)
00815         return(neW);
00816 
00817     v = Cudd_Regular(node)->index;      /* either yi or zi */
00818     if (cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd)) return(NULL);
00819     Cudd_Ref(f1);
00820     Cudd_Ref(f0);
00821     Cudd_Ref(fd);
00822 
00823     b1 = cuddMakeBddFromZddCover(dd, f1);
00824     if (!b1) {
00825         Cudd_RecursiveDerefZdd(dd, f1);
00826         Cudd_RecursiveDerefZdd(dd, f0);
00827         Cudd_RecursiveDerefZdd(dd, fd);
00828         return(NULL);
00829     }
00830     Cudd_Ref(b1);
00831     b0 = cuddMakeBddFromZddCover(dd, f0);
00832     if (!b0) {
00833         Cudd_RecursiveDerefZdd(dd, f1);
00834         Cudd_RecursiveDerefZdd(dd, f0);
00835         Cudd_RecursiveDerefZdd(dd, fd);
00836         Cudd_RecursiveDeref(dd, b1);
00837         return(NULL);
00838     }
00839     Cudd_Ref(b0);
00840     Cudd_RecursiveDerefZdd(dd, f1);
00841     Cudd_RecursiveDerefZdd(dd, f0);
00842     if (fd != dd->zero) {
00843         bd = cuddMakeBddFromZddCover(dd, fd);
00844         if (!bd) {
00845             Cudd_RecursiveDerefZdd(dd, fd);
00846             Cudd_RecursiveDeref(dd, b1);
00847             Cudd_RecursiveDeref(dd, b0);
00848             return(NULL);
00849         }
00850         Cudd_Ref(bd);
00851         Cudd_RecursiveDerefZdd(dd, fd);
00852 
00853         T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd));
00854         if (!T) {
00855             Cudd_RecursiveDeref(dd, b1);
00856             Cudd_RecursiveDeref(dd, b0);
00857             Cudd_RecursiveDeref(dd, bd);
00858             return(NULL);
00859         }
00860         T = Cudd_NotCond(T, T != NULL);
00861         Cudd_Ref(T);
00862         Cudd_RecursiveDeref(dd, b1);
00863         E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd));
00864         if (!E) {
00865             Cudd_RecursiveDeref(dd, b0);
00866             Cudd_RecursiveDeref(dd, bd);
00867             Cudd_RecursiveDeref(dd, T);
00868             return(NULL);
00869         }
00870         E = Cudd_NotCond(E, E != NULL);
00871         Cudd_Ref(E);
00872         Cudd_RecursiveDeref(dd, b0);
00873         Cudd_RecursiveDeref(dd, bd);
00874     }
00875     else {
00876         Cudd_RecursiveDerefZdd(dd, fd);
00877         T = b1;
00878         E = b0;
00879     }
00880 
00881     if (Cudd_IsComplement(T)) {
00882         neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E));
00883         if (!neW) {
00884             Cudd_RecursiveDeref(dd, T);
00885             Cudd_RecursiveDeref(dd, E);
00886             return(NULL);
00887         }
00888         neW = Cudd_Not(neW);
00889     }
00890     else {
00891         neW = cuddUniqueInterIVO(dd, v / 2, T, E);
00892         if (!neW) {
00893             Cudd_RecursiveDeref(dd, T);
00894             Cudd_RecursiveDeref(dd, E);
00895             return(NULL);
00896         }
00897     }
00898     Cudd_Ref(neW);
00899     Cudd_RecursiveDeref(dd, T);
00900     Cudd_RecursiveDeref(dd, E);
00901 
00902     cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW);
00903     Cudd_Deref(neW);
00904     return(neW);
00905 
00906 } /* end of cuddMakeBddFromZddCover */

int cuddNextHigh ( DdManager table,
int  x 
)

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

Synopsis [Finds the next subtable with a larger index.]

Description [Finds the next subtable with a larger index. Returns the index.]

SideEffects [None]

SeeAlso [cuddNextLow]

Definition at line 707 of file cuddReorder.c.

00710 {
00711     return(x+1);
00712 
00713 } /* end of cuddNextHigh */

int cuddNextLow ( DdManager table,
int  x 
)

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

Synopsis [Finds the next subtable with a smaller index.]

Description [Finds the next subtable with a smaller index. Returns the index.]

SideEffects [None]

SeeAlso [cuddNextHigh]

Definition at line 729 of file cuddReorder.c.

00732 {
00733     return(x-1);
00734 
00735 } /* end of cuddNextLow */

DdNodePtr* cuddNodeArray ( DdNode f,
int *  n 
)

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

Synopsis [Recursively collects all the nodes of a DD in an array.]

Description [Traverses the DD f and collects all its nodes in an array. The caller should free the array returned by cuddNodeArray. Returns a pointer to the array of nodes in case of success; NULL otherwise. The nodes are collected in reverse topological order, so that a node is always preceded in the array by all its descendants.]

SideEffects [The number of nodes is returned as a side effect.]

SeeAlso [Cudd_FirstNode]

Definition at line 2975 of file cuddUtil.c.

02978 {
02979     DdNodePtr *table;
02980     int size, retval;
02981 
02982     size = ddDagInt(Cudd_Regular(f));
02983     table = ALLOC(DdNodePtr, size);
02984     if (table == NULL) {
02985         ddClearFlag(Cudd_Regular(f));
02986         return(NULL);
02987     }
02988 
02989     retval = cuddNodeArrayRecur(f, table, 0);
02990     assert(retval == size);
02991 
02992     *n = size;
02993     return(table);
02994 
02995 } /* cuddNodeArray */

int cuddP ( DdManager dd,
DdNode f 
)

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

Synopsis [Prints a DD to the standard output. One line per node is printed.]

Description [Prints a DD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [Cudd_PrintDebug]

Definition at line 2862 of file cuddUtil.c.

02865 {
02866     int retval;
02867     st_table *table = st_init_table(st_ptrcmp,st_ptrhash);
02868 
02869     if (table == NULL) return(0);
02870 
02871     retval = dp2(dd,f,table);
02872     st_free_table(table);
02873     (void) fputc('\n',dd->out);
02874     return(retval);
02875 
02876 } /* end of cuddP */

void cuddPrintNode ( DdNode f,
FILE *  fp 
)

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

Synopsis [Prints out information on a node.]

Description [Prints out information on a node.]

SideEffects [None]

SeeAlso []

Definition at line 706 of file cuddCheck.c.

00709 {
00710     f = Cudd_Regular(f);
00711 #if SIZEOF_VOID_P == 8
00712     (void) fprintf(fp,"       node 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
00713 #else
00714     (void) fprintf(fp,"       node 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
00715 #endif
00716 
00717 } /* end of cuddPrintNode */

void cuddPrintVarGroups ( DdManager dd,
MtrNode root,
int  zdd,
int  silent 
)

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

Synopsis [Prints the variable groups as a parenthesized list.]

Description [Prints the variable groups as a parenthesized list. For each group the level range that it represents is printed. After each group, the group's flags are printed, preceded by a `|'. For each flag (except MTR_TERMINAL) a character is printed.

  • F: MTR_FIXED
  • N: MTR_NEWNODE
  • S: MTR_SOFT

The second argument, silent, if different from 0, causes Cudd_PrintVarGroups to only check the syntax of the group tree.]

SideEffects [None]

SeeAlso []

Definition at line 743 of file cuddCheck.c.

00746               : BDD; 1: ZDD */,
00747   int silent /* flag to check tree syntax only */)
00748 {
00749     MtrNode *node;
00750     int level;
00751 
00752     assert(root != NULL);
00753     assert(root->younger == NULL || root->younger->elder == root);
00754     assert(root->elder == NULL || root->elder->younger == root);
00755     if (zdd) {
00756         level = dd->permZ[root->index];
00757     } else {
00758         level = dd->perm[root->index];
00759     }
00760     if (!silent) (void) printf("(%d",level);
00761     if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
00762         if (!silent) (void) printf(",");
00763     } else {
00764         node = root->child;
00765         while (node != NULL) {
00766             assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
00767             assert(node->parent == root);
00768             cuddPrintVarGroups(dd,node,zdd,silent);
00769             node = node->younger;
00770         }
00771     }
00772     if (!silent) {
00773         (void) printf("%d", (int) (level + root->size - 1));
00774         if (root->flags != MTR_DEFAULT) {
00775             (void) printf("|");
00776             if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
00777             if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
00778             if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
00779         }
00780         (void) printf(")");
00781         if (root->parent == NULL) (void) printf("\n");
00782     }
00783     assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
00784     return;
00785 
00786 } /* end of cuddPrintVarGroups */

void cuddReclaim ( DdManager table,
DdNode n 
)

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

Synopsis [Brings children of a dead node back.]

Description []

SideEffects [None]

SeeAlso [cuddReclaimZdd]

Definition at line 580 of file cuddRef.c.

00583 {
00584     DdNode *N;
00585     int ord;
00586     DdNodePtr *stack = table->stack;
00587     int SP = 1;
00588     double initialDead = table->dead;
00589 
00590     N = Cudd_Regular(n);
00591 
00592 #ifdef DD_DEBUG
00593     assert(N->ref == 0);
00594 #endif
00595 
00596     do {
00597         if (N->ref == 0) {
00598             N->ref = 1;
00599             table->dead--;
00600             if (cuddIsConstant(N)) {
00601                 table->constants.dead--;
00602                 N = stack[--SP];
00603             } else {
00604                 ord = table->perm[N->index];
00605                 stack[SP++] = Cudd_Regular(cuddE(N));
00606                 table->subtables[ord].dead--;
00607                 N = cuddT(N);
00608             }
00609         } else {
00610             cuddSatInc(N->ref);
00611             N = stack[--SP];
00612         }
00613     } while (SP != 0);
00614 
00615     N = Cudd_Regular(n);
00616     cuddSatDec(N->ref);
00617     table->reclaimed += initialDead - table->dead;
00618 
00619 } /* end of cuddReclaim */

void cuddReclaimZdd ( DdManager table,
DdNode n 
)

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

Synopsis [Brings children of a dead ZDD node back.]

Description []

SideEffects [None]

SeeAlso [cuddReclaim]

Definition at line 634 of file cuddRef.c.

00637 {
00638     DdNode *N;
00639     int ord;
00640     DdNodePtr *stack = table->stack;
00641     int SP = 1;
00642 
00643     N = n;
00644 
00645 #ifdef DD_DEBUG
00646     assert(N->ref == 0);
00647 #endif
00648 
00649     do {
00650         cuddSatInc(N->ref);
00651 
00652         if (N->ref == 1) {
00653             table->deadZ--;
00654             table->reclaimed++;
00655 #ifdef DD_DEBUG
00656             assert(!cuddIsConstant(N));
00657 #endif
00658             ord = table->permZ[N->index];
00659             stack[SP++] = cuddE(N);
00660             table->subtableZ[ord].dead--;
00661             N = cuddT(N);
00662         } else {
00663             N = stack[--SP];
00664         }
00665     } while (SP != 0);
00666 
00667     cuddSatDec(n->ref);
00668 
00669 } /* end of cuddReclaimZdd */

void cuddRehash ( DdManager unique,
int  i 
)

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

Synopsis [Rehashes a unique subtable.]

Description [Doubles the size of a unique subtable and rehashes its contents.]

SideEffects [None]

SeeAlso []

Definition at line 1515 of file cuddTable.c.

01518 {
01519     unsigned int slots, oldslots;
01520     int shift, oldshift;
01521     int j, pos;
01522     DdNodePtr *nodelist, *oldnodelist;
01523     DdNode *node, *next;
01524     DdNode *sentinel = &(unique->sentinel);
01525     hack split;
01526     extern DD_OOMFP MMoutOfMemory;
01527     DD_OOMFP saveHandler;
01528 
01529     if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) {
01530         unique->gcFrac = DD_GC_FRAC_LO;
01531         unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
01532 #ifdef DD_VERBOSE
01533         (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO);
01534         (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
01535 #endif
01536     }
01537 
01538     if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) {
01539         unique->gcFrac = DD_GC_FRAC_MIN;
01540         unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
01541 #ifdef DD_VERBOSE
01542         (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN);
01543         (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
01544 #endif
01545         cuddShrinkDeathRow(unique);
01546         if (cuddGarbageCollect(unique,1) > 0) return;
01547     }
01548 
01549     if (i != CUDD_CONST_INDEX) {
01550         oldslots = unique->subtables[i].slots;
01551         oldshift = unique->subtables[i].shift;
01552         oldnodelist = unique->subtables[i].nodelist;
01553 
01554         /* Compute the new size of the subtable. */
01555         slots = oldslots << 1;
01556         shift = oldshift - 1;
01557 
01558         saveHandler = MMoutOfMemory;
01559         MMoutOfMemory = Cudd_OutOfMem;
01560         nodelist = ALLOC(DdNodePtr, slots);
01561         MMoutOfMemory = saveHandler;
01562         if (nodelist == NULL) {
01563             (void) fprintf(unique->err,
01564                            "Unable to resize subtable %d for lack of memory\n",
01565                            i);
01566             /* Prevent frequent resizing attempts. */
01567             (void) cuddGarbageCollect(unique,1);
01568             if (unique->stash != NULL) {
01569                 FREE(unique->stash);
01570                 unique->stash = NULL;
01571                 /* Inhibit resizing of tables. */
01572                 cuddSlowTableGrowth(unique);
01573             }
01574             return;
01575         }
01576         unique->subtables[i].nodelist = nodelist;
01577         unique->subtables[i].slots = slots;
01578         unique->subtables[i].shift = shift;
01579         unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
01580 
01581         /* Move the nodes from the old table to the new table.
01582         ** This code depends on the type of hash function.
01583         ** It assumes that the effect of doubling the size of the table
01584         ** is to retain one more bit of the 32-bit hash value.
01585         ** The additional bit is the LSB. */
01586         for (j = 0; (unsigned) j < oldslots; j++) {
01587             DdNodePtr *evenP, *oddP;
01588             node = oldnodelist[j];
01589             evenP = &(nodelist[j<<1]);
01590             oddP = &(nodelist[(j<<1)+1]);
01591             while (node != sentinel) {
01592                 next = node->next;
01593                 pos = ddHash(cuddT(node), cuddE(node), shift);
01594                 if (pos & 1) {
01595                     *oddP = node;
01596                     oddP = &(node->next);
01597                 } else {
01598                     *evenP = node;
01599                     evenP = &(node->next);
01600                 }
01601                 node = next;
01602             }
01603             *evenP = *oddP = sentinel;
01604         }
01605         FREE(oldnodelist);
01606 
01607 #ifdef DD_VERBOSE
01608         (void) fprintf(unique->err,
01609                        "rehashing layer %d: keys %d dead %d new size %d\n",
01610                        i, unique->subtables[i].keys,
01611                        unique->subtables[i].dead, slots);
01612 #endif
01613     } else {
01614         oldslots = unique->constants.slots;
01615         oldshift = unique->constants.shift;
01616         oldnodelist = unique->constants.nodelist;
01617 
01618         /* The constant subtable is never subjected to reordering.
01619         ** Therefore, when it is resized, it is because it has just
01620         ** reached the maximum load. We can safely just double the size,
01621         ** with no need for the loop we use for the other tables.
01622         */
01623         slots = oldslots << 1;
01624         shift = oldshift - 1;
01625         saveHandler = MMoutOfMemory;
01626         MMoutOfMemory = Cudd_OutOfMem;
01627         nodelist = ALLOC(DdNodePtr, slots);
01628         MMoutOfMemory = saveHandler;
01629         if (nodelist == NULL) {
01630             (void) fprintf(unique->err,
01631                            "Unable to resize constant subtable for lack of memory\n");
01632             (void) cuddGarbageCollect(unique,1);
01633             for (j = 0; j < unique->size; j++) {
01634                 unique->subtables[j].maxKeys <<= 1;
01635             }
01636             unique->constants.maxKeys <<= 1;
01637             return;
01638         }
01639         unique->constants.slots = slots;
01640         unique->constants.shift = shift;
01641         unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
01642         unique->constants.nodelist = nodelist;
01643         for (j = 0; (unsigned) j < slots; j++) {
01644             nodelist[j] = NULL;
01645         }
01646         for (j = 0; (unsigned) j < oldslots; j++) {
01647             node = oldnodelist[j];
01648             while (node != NULL) {
01649                 next = node->next;
01650                 split.value = cuddV(node);
01651                 pos = ddHash(split.bits[0], split.bits[1], shift);
01652                 node->next = nodelist[pos];
01653                 nodelist[pos] = node;
01654                 node = next;
01655             }
01656         }
01657         FREE(oldnodelist);
01658 
01659 #ifdef DD_VERBOSE
01660         (void) fprintf(unique->err,
01661                        "rehashing constants: keys %d dead %d new size %d\n",
01662                        unique->constants.keys,unique->constants.dead,slots);
01663 #endif
01664     }
01665 
01666     /* Update global data */
01667 
01668     unique->memused += (slots - oldslots) * sizeof(DdNodePtr);
01669     unique->slots += (slots - oldslots);
01670     ddFixLimits(unique);
01671 
01672 } /* end of cuddRehash */

DdNode* cuddRemapUnderApprox ( DdManager dd,
DdNode f,
int  numVars,
int  threshold,
double  quality 
)

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

Synopsis [Applies the remapping underappoximation algorithm.]

Description [Applies the remapping underappoximation algorithm. Proceeds in three phases:

  • collect information on each node in the BDD; this is done via DFS.
  • traverse the BDD in top-down fashion and compute for each node whether remapping increases density.
  • traverse the BDD via DFS and actually perform the elimination.

Returns the approximated BDD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_RemapUnderApprox]

Definition at line 597 of file cuddApprox.c.

00603 {
00604     ApproxInfo *info;
00605     DdNode *subset;
00606     int result;
00607 
00608     if (f == NULL) {
00609         fprintf(dd->err, "Cannot subset, nil object\n");
00610         dd->errorCode = CUDD_INVALID_ARG;
00611         return(NULL);
00612     }
00613 
00614     if (Cudd_IsConstant(f)) {
00615         return(f);
00616     }
00617 
00618     /* Create table where node data are accessible via a hash table. */
00619     info = gatherInfo(dd, f, numVars, TRUE);
00620     if (info == NULL) {
00621         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00622         dd->errorCode = CUDD_MEMORY_OUT;
00623         return(NULL);
00624     }
00625 
00626     /* Mark nodes that should be replaced by zero. */
00627     result = RAmarkNodes(dd, f, info, threshold, quality);
00628     if (result == 0) {
00629         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00630         FREE(info->page);
00631         st_free_table(info->table);
00632         FREE(info);
00633         dd->errorCode = CUDD_MEMORY_OUT;
00634         return(NULL);
00635     }
00636 
00637     /* Build the result. */
00638     subset = RAbuildSubset(dd, f, info);
00639 #if 1
00640     if (subset && info->size < Cudd_DagSize(subset))
00641         (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00642                        info->size, Cudd_DagSize(subset));
00643 #endif
00644     FREE(info->page);
00645     st_free_table(info->table);
00646     FREE(info);
00647 
00648 #ifdef DD_DEBUG
00649     if (subset != NULL) {
00650         cuddRef(subset);
00651 #if 0
00652         (void) Cudd_DebugCheck(dd);
00653         (void) Cudd_CheckKeys(dd);
00654 #endif
00655         if (!Cudd_bddLeq(dd, subset, f)) {
00656             (void) fprintf(dd->err, "Wrong subset\n");
00657         }
00658         cuddDeref(subset);
00659         dd->errorCode = CUDD_INTERNAL_ERROR;
00660     }
00661 #endif
00662     return(subset);
00663 
00664 } /* end of cuddRemapUnderApprox */

int cuddResizeLinear ( DdManager table  ) 

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

Synopsis [Resizes the linear transform matrix.]

Description [Resizes the linear transform matrix. Returns 1 if successful; 0 otherwise.]

SideEffects [none]

SeeAlso []

Definition at line 800 of file cuddLinear.c.

00802 {
00803     int words,oldWords;
00804     int wordsPerRow,oldWordsPerRow;
00805     int nvars,oldNvars;
00806     int word,oldWord;
00807     int bit;
00808     int i,j;
00809     long *linear,*oldLinear;
00810 
00811     oldNvars = table->linearSize;
00812     oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
00813     oldWords = oldWordsPerRow * oldNvars;
00814     oldLinear = table->linear;
00815 
00816     nvars = table->size;
00817     wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00818     words = wordsPerRow * nvars;
00819     table->linear = linear = ALLOC(long,words);
00820     if (linear == NULL) {
00821         table->errorCode = CUDD_MEMORY_OUT;
00822         return(0);
00823     }
00824     table->memused += (words - oldWords) * sizeof(long);
00825     for (i = 0; i < words; i++) linear[i] = 0;
00826 
00827     /* Copy old matrix. */
00828     for (i = 0; i < oldNvars; i++) {
00829         for (j = 0; j < oldWordsPerRow; j++) {
00830             oldWord = oldWordsPerRow * i + j;
00831             word = wordsPerRow * i + j;
00832             linear[word] = oldLinear[oldWord];
00833         }
00834     }
00835     FREE(oldLinear);
00836 
00837     /* Add elements to the diagonal. */
00838     for (i = oldNvars; i < nvars; i++) {
00839         word = wordsPerRow * i + (i >> LOGBPL);
00840         bit  = i & (BPL-1);
00841         linear[word] = 1 << bit;
00842     }
00843     table->linearSize = nvars;
00844 
00845     return(1);
00846 
00847 } /* end of cuddResizeLinear */

int cuddResizeTableZdd ( DdManager unique,
int  index 
)

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

Synopsis [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index.]

Description [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index. When new ZDD variables are created, it is possible to preserve the functions unchanged, or it is possible to preserve the covers unchanged, but not both. cuddResizeTableZdd preserves the covers. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [ddResizeTable]

Definition at line 2226 of file cuddTable.c.

02229 {
02230     DdSubtable *newsubtables;
02231     DdNodePtr *newnodelist;
02232     int oldsize,newsize;
02233     int i,j,reorderSave;
02234     unsigned int numSlots = unique->initSlots;
02235     int *newperm, *newinvperm;
02236 
02237     oldsize = unique->sizeZ;
02238     /* Easy case: there is still room in the current table. */
02239     if (index < unique->maxSizeZ) {
02240         for (i = oldsize; i <= index; i++) {
02241             unique->subtableZ[i].slots = numSlots;
02242             unique->subtableZ[i].shift = sizeof(int) * 8 -
02243                 cuddComputeFloorLog2(numSlots);
02244             unique->subtableZ[i].keys = 0;
02245             unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
02246             unique->subtableZ[i].dead = 0;
02247             unique->permZ[i] = i;
02248             unique->invpermZ[i] = i;
02249             newnodelist = unique->subtableZ[i].nodelist =
02250                 ALLOC(DdNodePtr, numSlots);
02251             if (newnodelist == NULL) {
02252                 unique->errorCode = CUDD_MEMORY_OUT;
02253                 return(0);
02254             }
02255             for (j = 0; (unsigned) j < numSlots; j++) {
02256                 newnodelist[j] = NULL;
02257             }
02258         }
02259     } else {
02260         /* The current table is too small: we need to allocate a new,
02261         ** larger one; move all old subtables, and initialize the new
02262         ** subtables up to index included.
02263         */
02264         newsize = index + DD_DEFAULT_RESIZE;
02265 #ifdef DD_VERBOSE
02266         (void) fprintf(unique->err,
02267                        "Increasing the ZDD table size from %d to %d\n",
02268             unique->maxSizeZ, newsize);
02269 #endif
02270         newsubtables = ALLOC(DdSubtable,newsize);
02271         if (newsubtables == NULL) {
02272             unique->errorCode = CUDD_MEMORY_OUT;
02273             return(0);
02274         }
02275         newperm = ALLOC(int,newsize);
02276         if (newperm == NULL) {
02277             unique->errorCode = CUDD_MEMORY_OUT;
02278             return(0);
02279         }
02280         newinvperm = ALLOC(int,newsize);
02281         if (newinvperm == NULL) {
02282             unique->errorCode = CUDD_MEMORY_OUT;
02283             return(0);
02284         }
02285         unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) *
02286             sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
02287         if (newsize > unique->maxSize) {
02288             FREE(unique->stack);
02289             unique->stack = ALLOC(DdNodePtr,newsize + 1);
02290             if (unique->stack == NULL) {
02291                 unique->errorCode = CUDD_MEMORY_OUT;
02292                 return(0);
02293             }
02294             unique->stack[0] = NULL; /* to suppress harmless UMR */
02295             unique->memused +=
02296                 (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
02297                 * sizeof(DdNode *);
02298         }
02299         for (i = 0; i < oldsize; i++) {
02300             newsubtables[i].slots = unique->subtableZ[i].slots;
02301             newsubtables[i].shift = unique->subtableZ[i].shift;
02302             newsubtables[i].keys = unique->subtableZ[i].keys;
02303             newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys;
02304             newsubtables[i].dead = unique->subtableZ[i].dead;
02305             newsubtables[i].nodelist = unique->subtableZ[i].nodelist;
02306             newperm[i] = unique->permZ[i];
02307             newinvperm[i] = unique->invpermZ[i];
02308         }
02309         for (i = oldsize; i <= index; i++) {
02310             newsubtables[i].slots = numSlots;
02311             newsubtables[i].shift = sizeof(int) * 8 -
02312                 cuddComputeFloorLog2(numSlots);
02313             newsubtables[i].keys = 0;
02314             newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
02315             newsubtables[i].dead = 0;
02316             newperm[i] = i;
02317             newinvperm[i] = i;
02318             newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
02319             if (newnodelist == NULL) {
02320                 unique->errorCode = CUDD_MEMORY_OUT;
02321                 return(0);
02322             }
02323             for (j = 0; (unsigned) j < numSlots; j++) {
02324                 newnodelist[j] = NULL;
02325             }
02326         }
02327         FREE(unique->subtableZ);
02328         unique->subtableZ = newsubtables;
02329         unique->maxSizeZ = newsize;
02330         FREE(unique->permZ);
02331         unique->permZ = newperm;
02332         FREE(unique->invpermZ);
02333         unique->invpermZ = newinvperm;
02334     }
02335     unique->slots += (index + 1 - unique->sizeZ) * numSlots;
02336     ddFixLimits(unique);
02337     unique->sizeZ = index + 1;
02338 
02339     /* Now that the table is in a coherent state, update the ZDD
02340     ** universe. We need to temporarily disable reordering,
02341     ** because we cannot reorder without universe in place.
02342     */
02343 
02344     reorderSave = unique->autoDynZ;
02345     unique->autoDynZ = 0;
02346     cuddZddFreeUniv(unique);
02347     if (!cuddZddInitUniv(unique)) {
02348         unique->autoDynZ = reorderSave;
02349         return(0);
02350     }
02351     unique->autoDynZ = reorderSave;
02352 
02353     return(1);
02354 
02355 } /* end of cuddResizeTableZdd */

void cuddSetInteract ( DdManager table,
int  x,
int  y 
)

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

Synopsis [Set interaction matrix entries.]

Description [Given a pair of variables 0 <= x < y < table->size, sets the corresponding bit of the interaction matrix to 1.]

SideEffects [None]

SeeAlso []

Definition at line 152 of file cuddInteract.c.

00156 {
00157     int posn, word, bit;
00158 
00159 #ifdef DD_DEBUG
00160     assert(x < y);
00161     assert(y < table->size);
00162     assert(x >= 0);
00163 #endif
00164 
00165     posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
00166     word = posn >> LOGBPL;
00167     bit = posn & (BPL-1);
00168     table->interact[word] |= 1L << bit;
00169 
00170 } /* end of cuddSetInteract */

void cuddShrinkDeathRow ( DdManager table  ) 

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

Synopsis [Shrinks the death row.]

Description [Shrinks the death row by a factor of four.]

SideEffects [None]

SeeAlso [cuddClearDeathRow]

Definition at line 684 of file cuddRef.c.

00686 {
00687 #ifndef DD_NO_DEATH_ROW
00688     int i;
00689 
00690     if (table->deathRowDepth > 3) {
00691         for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) {
00692             if (table->deathRow[i] == NULL) break;
00693             Cudd_IterDerefBdd(table,table->deathRow[i]);
00694             table->deathRow[i] = NULL;
00695         }
00696         table->deathRowDepth /= 4;
00697         table->deadMask = table->deathRowDepth - 1;
00698         if ((unsigned) table->nextDead > table->deadMask) {
00699             table->nextDead = 0;
00700         }
00701         table->deathRow = REALLOC(DdNodePtr, table->deathRow,
00702                                    table->deathRowDepth);
00703     }
00704 #endif
00705 
00706 } /* end of cuddShrinkDeathRow */

void cuddShrinkSubtable ( DdManager unique,
int  i 
)

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

Synopsis [Shrinks a subtable.]

Description [Shrinks a subtable.]

SideEffects [None]

SeeAlso [cuddRehash]

Definition at line 1687 of file cuddTable.c.

01690 {
01691     int j;
01692     int shift, posn;
01693     DdNodePtr *nodelist, *oldnodelist;
01694     DdNode *node, *next;
01695     DdNode *sentinel = &(unique->sentinel);
01696     unsigned int slots, oldslots;
01697     extern DD_OOMFP MMoutOfMemory;
01698     DD_OOMFP saveHandler;
01699 
01700     oldnodelist = unique->subtables[i].nodelist;
01701     oldslots = unique->subtables[i].slots;
01702     slots = oldslots >> 1;
01703     saveHandler = MMoutOfMemory;
01704     MMoutOfMemory = Cudd_OutOfMem;
01705     nodelist = ALLOC(DdNodePtr, slots);
01706     MMoutOfMemory = saveHandler;
01707     if (nodelist == NULL) {
01708         return;
01709     }
01710     unique->subtables[i].nodelist = nodelist;
01711     unique->subtables[i].slots = slots;
01712     unique->subtables[i].shift++;
01713     unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
01714 #ifdef DD_VERBOSE
01715     (void) fprintf(unique->err,
01716                    "shrunk layer %d (%d keys) from %d to %d slots\n",
01717                    i, unique->subtables[i].keys, oldslots, slots);
01718 #endif
01719 
01720     for (j = 0; (unsigned) j < slots; j++) {
01721         nodelist[j] = sentinel;
01722     }
01723     shift = unique->subtables[i].shift;
01724     for (j = 0; (unsigned) j < oldslots; j++) {
01725         node = oldnodelist[j];
01726         while (node != sentinel) {
01727             DdNode *looking, *T, *E;
01728             DdNodePtr *previousP;
01729             next = node->next;
01730             posn = ddHash(cuddT(node), cuddE(node), shift);
01731             previousP = &(nodelist[posn]);
01732             looking = *previousP;
01733             T = cuddT(node);
01734             E = cuddE(node);
01735             while (T < cuddT(looking)) {
01736                 previousP = &(looking->next);
01737                 looking = *previousP;
01738 #ifdef DD_UNIQUE_PROFILE
01739                 unique->uniqueLinks++;
01740 #endif
01741             }
01742             while (T == cuddT(looking) && E < cuddE(looking)) {
01743                 previousP = &(looking->next);
01744                 looking = *previousP;
01745 #ifdef DD_UNIQUE_PROFILE
01746                 unique->uniqueLinks++;
01747 #endif
01748             }
01749             node->next = *previousP;
01750             *previousP = node;
01751             node = next;
01752         }
01753     }
01754     FREE(oldnodelist);
01755 
01756     unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *);
01757     unique->slots += slots - oldslots;
01758     unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
01759     unique->cacheSlack = (int)
01760         ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots)
01761         - 2 * (int) unique->cacheSlots;
01762 
01763 } /* end of cuddShrinkSubtable */

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

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

Synopsis [Implementation of Rudell's sifting algorithm.]

Description [Implementation of Rudell's sifting algorithm. 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.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 499 of file cuddReorder.c.

00503 {
00504     int i;
00505     int *var;
00506     int size;
00507     int x;
00508     int result;
00509 #ifdef DD_STATS
00510     int previousSize;
00511 #endif
00512 
00513     size = table->size;
00514 
00515     /* Find order in which to sift variables. */
00516     var = NULL;
00517     entry = ALLOC(int,size);
00518     if (entry == NULL) {
00519         table->errorCode = CUDD_MEMORY_OUT;
00520         goto cuddSiftingOutOfMem;
00521     }
00522     var = ALLOC(int,size);
00523     if (var == NULL) {
00524         table->errorCode = CUDD_MEMORY_OUT;
00525         goto cuddSiftingOutOfMem;
00526     }
00527 
00528     for (i = 0; i < size; i++) {
00529         x = table->perm[i];
00530         entry[i] = table->subtables[x].keys;
00531         var[i] = i;
00532     }
00533 
00534     qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
00535 
00536     /* Now sift. */
00537     for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00538         if (ddTotalNumberSwapping >= table->siftMaxSwap)
00539             break;
00540         x = table->perm[var[i]];
00541 
00542         if (x < lower || x > upper || table->subtables[x].bindVar == 1)
00543             continue;
00544 #ifdef DD_STATS
00545         previousSize = table->keys - table->isolated;
00546 #endif
00547         result = ddSiftingAux(table, x, lower, upper);
00548         if (!result) goto cuddSiftingOutOfMem;
00549 #ifdef DD_STATS
00550         if (table->keys < (unsigned) previousSize + table->isolated) {
00551             (void) fprintf(table->out,"-");
00552         } else if (table->keys > (unsigned) previousSize + table->isolated) {
00553             (void) fprintf(table->out,"+");     /* should never happen */
00554             (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00555         } else {
00556             (void) fprintf(table->out,"=");
00557         }
00558         fflush(table->out);
00559 #endif
00560     }
00561 
00562     FREE(var);
00563     FREE(entry);
00564 
00565     return(1);
00566 
00567 cuddSiftingOutOfMem:
00568 
00569     if (entry != NULL) FREE(entry);
00570     if (var != NULL) FREE(var);
00571 
00572     return(0);
00573 
00574 } /* end of cuddSifting */

void cuddSlowTableGrowth ( DdManager unique  ) 

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

Synopsis [Adjusts parameters of a table to slow down its growth.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 2370 of file cuddTable.c.

02372 {
02373     int i;
02374 
02375     unique->maxCacheHard = unique->cacheSlots - 1;
02376     unique->cacheSlack = - (int) (unique->cacheSlots + 1);
02377     for (i = 0; i < unique->size; i++) {
02378         unique->subtables[i].maxKeys <<= 2;
02379     }
02380     unique->gcFrac = DD_GC_FRAC_MIN;
02381     unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
02382     cuddShrinkDeathRow(unique);
02383     (void) fprintf(unique->err,"Slowing down table growth: ");
02384     (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac);
02385     (void) fprintf(unique->err,"minDead = %u\n", unique->minDead);
02386 
02387 } /* end of cuddSlowTableGrowth */

DdNode* cuddSolveEqnRecur ( DdManager bdd,
DdNode F,
DdNode Y,
DdNode **  G,
int  n,
int *  yIndex,
int  i 
)

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

Synopsis [Implements the recursive step of Cudd_SolveEqn.]

Description [Implements the recursive step of Cudd_SolveEqn. Returns NULL if the intermediate solution blows up or reordering occurs. The parametric solutions are stored in the array G.]

SideEffects [none]

SeeAlso [Cudd_SolveEqn, Cudd_VerifySol]

Definition at line 206 of file cuddSolve.c.

00214 {
00215     DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one;
00216     DdNodePtr *variables;
00217 
00218     int j;
00219 
00220     statLine(bdd);
00221     variables = bdd->vars;
00222     one = DD_ONE(bdd);
00223 
00224     /* Base condition. */
00225     if (Y == one) {
00226         return F;
00227     }
00228 
00229     /* Cofactor of Y. */
00230     yIndex[i] = Y->index;
00231     nextY = Cudd_T(Y);
00232 
00233     /* Universal abstraction of F with respect to the top variable index. */
00234     Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]);
00235     if (Fm1) {
00236         Fm1 = Cudd_Not(Fm1);
00237         cuddRef(Fm1);
00238     } else {
00239         return(NULL);
00240     }
00241 
00242     Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1);
00243     if (Fn) {
00244         cuddRef(Fn);
00245     } else {
00246         Cudd_RecursiveDeref(bdd, Fm1);
00247         return(NULL);
00248     }
00249 
00250     Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]);
00251     if (Fv) {
00252         cuddRef(Fv);
00253     } else {
00254         Cudd_RecursiveDeref(bdd, Fm1);
00255         Cudd_RecursiveDeref(bdd, Fn);
00256         return(NULL);
00257     }
00258 
00259     Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]]));
00260     if (Fvbar) {
00261         cuddRef(Fvbar);
00262     } else {
00263         Cudd_RecursiveDeref(bdd, Fm1);
00264         Cudd_RecursiveDeref(bdd, Fn);
00265         Cudd_RecursiveDeref(bdd, Fv);
00266         return(NULL);
00267     }
00268 
00269     /* Build i-th component of the solution. */
00270     w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar);
00271     if (w) {
00272         cuddRef(w);
00273     } else {
00274         Cudd_RecursiveDeref(bdd, Fm1);
00275         Cudd_RecursiveDeref(bdd, Fn);
00276         Cudd_RecursiveDeref(bdd, Fv);
00277         Cudd_RecursiveDeref(bdd, Fvbar);
00278         return(NULL);
00279     }
00280 
00281     T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1));
00282     if(T) {
00283         cuddRef(T);
00284     } else {
00285         Cudd_RecursiveDeref(bdd, Fm1);
00286         Cudd_RecursiveDeref(bdd, Fn);
00287         Cudd_RecursiveDeref(bdd, Fv);
00288         Cudd_RecursiveDeref(bdd, Fvbar);
00289         Cudd_RecursiveDeref(bdd, w);
00290         return(NULL);
00291     }
00292 
00293     Cudd_RecursiveDeref(bdd,Fm1);
00294     Cudd_RecursiveDeref(bdd,w);
00295     Cudd_RecursiveDeref(bdd,Fv);
00296     Cudd_RecursiveDeref(bdd,Fvbar);
00297 
00298     /* Substitute components of solution already found into solution. */
00299     for (j = n-1; j > i; j--) {
00300         w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]);
00301         if(w) {
00302             cuddRef(w);
00303         } else {
00304             Cudd_RecursiveDeref(bdd, Fn);
00305             Cudd_RecursiveDeref(bdd, T);
00306             return(NULL);
00307         }
00308         Cudd_RecursiveDeref(bdd,T);
00309         T = w;
00310     }
00311     G[i] = T;
00312 
00313     Cudd_Deref(Fn);
00314 
00315     return(Fn);
00316 
00317 } /* end of cuddSolveEqnRecur */

DdNode* cuddSubsetHeavyBranch ( DdManager dd,
DdNode f,
int  numVars,
int  threshold 
)

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

Synopsis [The main procedure that returns a subset by choosing the heavier branch in the BDD.]

Description [Here a subset BDD is built by throwing away one of the children. Starting at root, annotate each node with the number of minterms (in terms of the total number of variables specified - numVars), number of nodes taken by the DAG rooted at this node and number of additional nodes taken by the child that has the lesser minterms. The child with the lower number of minterms is thrown away and a dyanmic count of the nodes of the subset is kept. Once the threshold is reached the subset is returned to the calling procedure.]

SideEffects [None]

SeeAlso [Cudd_SubsetHeavyBranch]

Definition at line 301 of file cuddSubsetHB.c.

00306 {
00307 
00308     int i, *size;
00309     st_table *visitedTable;
00310     int numNodes;
00311     NodeData_t *currNodeQual;
00312     DdNode *subset;
00313     st_table *storeTable, *approxTable;
00314     char *key, *value;
00315     st_generator *stGen;
00316 
00317     if (f == NULL) {
00318         fprintf(dd->err, "Cannot subset, nil object\n");
00319         dd->errorCode = CUDD_INVALID_ARG;
00320         return(NULL);
00321     }
00322 
00323     one  = Cudd_ReadOne(dd);
00324     zero = Cudd_Not(one);
00325 
00326     /* If user does not know numVars value, set it to the maximum
00327      * exponent that the pow function can take. The -1 is due to the
00328      * discrepancy in the value that pow takes and the value that
00329      * log gives.
00330      */
00331     if (numVars == 0) {
00332         /* set default value */
00333         numVars = DBL_MAX_EXP - 1;
00334     }
00335 
00336     if (Cudd_IsConstant(f)) {
00337         return(f);
00338     }
00339 
00340     max = pow(2.0, (double)numVars);
00341 
00342     /* Create visited table where structures for node data are allocated and
00343        stored in a st_table */
00344     visitedTable = SubsetCountMinterm(f, numVars);
00345     if ((visitedTable == NULL) || memOut) {
00346         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00347         dd->errorCode = CUDD_MEMORY_OUT;
00348         return(0);
00349     }
00350     numNodes = SubsetCountNodes(f, visitedTable, numVars);
00351     if (memOut) {
00352         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00353         dd->errorCode = CUDD_MEMORY_OUT;
00354         return(0);
00355     }
00356 
00357     if (st_lookup(visitedTable, f, &currNodeQual) == 0) {
00358         fprintf(dd->err,
00359                 "Something is wrong, ought to be node quality table\n");
00360         dd->errorCode = CUDD_INTERNAL_ERROR;
00361     }
00362 
00363     size = ALLOC(int, 1);
00364     if (size == NULL) {
00365         dd->errorCode = CUDD_MEMORY_OUT;
00366         return(NULL);
00367     }
00368     *size = numNodes;
00369 
00370 #ifdef DEBUG
00371     num_calls = 0;
00372 #endif
00373     /* table to store nodes being created. */
00374     storeTable = st_init_table(st_ptrcmp, st_ptrhash);
00375     /* insert the constant */
00376     cuddRef(one);
00377     if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) ==
00378         ST_OUT_OF_MEM) {
00379         fprintf(dd->out, "Something wrong, st_table insert failed\n");
00380     }
00381     /* table to store approximations of nodes */
00382     approxTable = st_init_table(st_ptrcmp, st_ptrhash);
00383     subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold,
00384                                       storeTable, approxTable);
00385     if (subset != NULL) {
00386         cuddRef(subset);
00387     }
00388 
00389     stGen = st_init_gen(approxTable);
00390     if (stGen == NULL) {
00391         st_free_table(approxTable);
00392         return(NULL);
00393     }
00394     while(st_gen(stGen, (char **)&key, (char **)&value)) {
00395         Cudd_RecursiveDeref(dd, (DdNode *)value);
00396     }
00397     st_free_gen(stGen); stGen = NULL;
00398     st_free_table(approxTable);
00399 
00400     stGen = st_init_gen(storeTable);
00401     if (stGen == NULL) {
00402         st_free_table(storeTable);
00403         return(NULL);
00404     }
00405     while(st_gen(stGen, (char **)&key, (char **)&value)) {
00406         Cudd_RecursiveDeref(dd, (DdNode *)key);
00407     }
00408     st_free_gen(stGen); stGen = NULL;
00409     st_free_table(storeTable);
00410 
00411     for (i = 0; i <= page; i++) {
00412         FREE(mintermPages[i]);
00413     }
00414     FREE(mintermPages);
00415     for (i = 0; i <= page; i++) {
00416         FREE(nodePages[i]);
00417     }
00418     FREE(nodePages);
00419     for (i = 0; i <= page; i++) {
00420         FREE(lightNodePages[i]);
00421     }
00422     FREE(lightNodePages);
00423     for (i = 0; i <= nodeDataPage; i++) {
00424         FREE(nodeDataPages[i]);
00425     }
00426     FREE(nodeDataPages);
00427     st_free_table(visitedTable);
00428     FREE(size);
00429 #if 0
00430     (void) Cudd_DebugCheck(dd);
00431     (void) Cudd_CheckKeys(dd);
00432 #endif
00433 
00434     if (subset != NULL) {
00435 #ifdef DD_DEBUG
00436       if (!Cudd_bddLeq(dd, subset, f)) {
00437             fprintf(dd->err, "Wrong subset\n");
00438             dd->errorCode = CUDD_INTERNAL_ERROR;
00439             return(NULL);
00440       }
00441 #endif
00442         cuddDeref(subset);
00443         return(subset);
00444     } else {
00445         return(NULL);
00446     }
00447 } /* end of cuddSubsetHeavyBranch */

DdNode* cuddSubsetShortPaths ( DdManager dd,
DdNode f,
int  numVars,
int  threshold,
int  hardlimit 
)

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

Synopsis [The outermost procedure to return a subset of the given BDD with the shortest path lengths.]

Description [The outermost procedure to return a subset of the given BDD with the largest cubes. The path lengths are calculated, the maximum allowable path length is determined and the number of nodes of this path length that can be used to build a subset. If the threshold is larger than the size of the original BDD, the original BDD is returned. ]

SideEffects [None]

SeeAlso [Cudd_SubsetShortPaths]

Definition at line 312 of file cuddSubsetSP.c.

00318 {
00319     st_table *pathTable;
00320     DdNode *N, *subset;
00321 
00322     unsigned int  *pathLengthArray;
00323     unsigned int maxpath, oddLen, evenLen, pathLength, *excess;
00324     int i;
00325     NodeDist_t  *nodeStat;
00326     struct AssortedInfo *info;
00327     st_table *subsetNodeTable;
00328 
00329     one = DD_ONE(dd);
00330     zero = Cudd_Not(one);
00331 
00332     if (numVars == 0) {
00333       /* set default value */
00334       numVars = Cudd_ReadSize(dd);
00335     }
00336 
00337     if (threshold > numVars) {
00338         threshold = threshold - numVars;
00339     }
00340     if (f == NULL) {
00341         fprintf(dd->err, "Cannot partition, nil object\n");
00342         dd->errorCode = CUDD_INVALID_ARG;
00343         return(NULL);
00344     }
00345     if (Cudd_IsConstant(f))
00346         return (f);
00347 
00348     pathLengthArray = ALLOC(unsigned int, numVars+1);
00349     for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0;
00350 
00351 
00352 #ifdef DD_DEBUG
00353     numCalls = 0;
00354 #endif
00355 
00356     pathTable = CreatePathTable(f, pathLengthArray, dd->err);
00357 
00358     if ((pathTable == NULL) || (memOut)) {
00359         if (pathTable != NULL)
00360             st_free_table(pathTable);
00361         FREE(pathLengthArray);
00362         return (NIL(DdNode));
00363     }
00364 
00365     excess = ALLOC(unsigned int, 1);
00366     *excess = 0;
00367     maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess,
00368                                dd->err);
00369 
00370     if (maxpath != (unsigned) (numVars + 1)) {
00371 
00372         info = ALLOC(struct AssortedInfo, 1);
00373         info->maxpath = maxpath;
00374         info->findShortestPath = 0;
00375         info->thresholdReached = *excess;
00376         info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash);
00377         info->threshold = threshold;
00378 
00379 #ifdef DD_DEBUG
00380         (void) fprintf(dd->out, "Path length array\n");
00381         for (i = 0; i < (numVars+1); i++) {
00382             if (pathLengthArray[i])
00383                 (void) fprintf(dd->out, "%d ",i);
00384         }
00385         (void) fprintf(dd->out, "\n");
00386         for (i = 0; i < (numVars+1); i++) {
00387             if (pathLengthArray[i])
00388                 (void) fprintf(dd->out, "%d ",pathLengthArray[i]);
00389         }
00390         (void) fprintf(dd->out, "\n");
00391         (void) fprintf(dd->out, "Maxpath  = %d, Thresholdreached = %d\n",
00392                        maxpath, info->thresholdReached);
00393 #endif
00394 
00395         N = Cudd_Regular(f);
00396         if (!st_lookup(pathTable, N, &nodeStat)) {
00397             fprintf(dd->err, "Something wrong, root node must be in table\n");
00398             dd->errorCode = CUDD_INTERNAL_ERROR;
00399             FREE(excess);
00400             FREE(info);
00401             return(NULL);
00402         } else {
00403             if ((nodeStat->oddTopDist != MAXSHORTINT) &&
00404                 (nodeStat->oddBotDist != MAXSHORTINT))
00405                 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
00406             else
00407                 oddLen = MAXSHORTINT;
00408 
00409             if ((nodeStat->evenTopDist != MAXSHORTINT) &&
00410                 (nodeStat->evenBotDist != MAXSHORTINT))
00411                 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
00412             else
00413                 evenLen = MAXSHORTINT;
00414 
00415             pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
00416             if (pathLength > maxpath) {
00417                 (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %u, %u\n", maxpath, pathLength);
00418                 dd->errorCode = CUDD_INTERNAL_ERROR;
00419                 return(NULL);
00420             }
00421         }
00422 
00423 #ifdef DD_DEBUG
00424         numCalls = 0;
00425         hits = 0;
00426         thishit = 0;
00427 #endif
00428         /* initialize a table to store computed nodes */
00429         if (hardlimit) {
00430             subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
00431         } else {
00432             subsetNodeTable = NIL(st_table);
00433         }
00434         subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable);
00435         if (subset != NULL) {
00436             cuddRef(subset);
00437         }
00438         /* record the number of times a computed result for a node is hit */
00439 
00440 #ifdef DD_DEBUG
00441         (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n",
00442                 hits, thishit, numCalls);
00443 #endif
00444 
00445         if (subsetNodeTable != NIL(st_table)) {
00446             st_free_table(subsetNodeTable);
00447         }
00448         st_free_table(info->maxpathTable);
00449         st_foreach(pathTable, stPathTableDdFree, (char *)dd);
00450 
00451         FREE(info);
00452 
00453     } else {/* if threshold larger than size of dd */
00454         subset = f;
00455         cuddRef(subset);
00456     }
00457     FREE(excess);
00458     st_free_table(pathTable);
00459     FREE(pathLengthArray);
00460     for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
00461     FREE(nodeDistPages);
00462 
00463 #ifdef DD_DEBUG
00464     /* check containment of subset in f */
00465     if (subset != NULL) {
00466         DdNode *check;
00467         check = Cudd_bddIteConstant(dd, subset, f, one);
00468         if (check != one) {
00469             (void) fprintf(dd->err, "Wrong partition\n");
00470             dd->errorCode = CUDD_INTERNAL_ERROR;
00471             return(NULL);
00472         }
00473     }
00474 #endif
00475 
00476     if (subset != NULL) {
00477         cuddDeref(subset);
00478         return(subset);
00479     } else {
00480         return(NULL);
00481     }
00482 
00483 } /* end of cuddSubsetShortPaths */

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

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

Synopsis [Swaps two adjacent variables.]

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

SideEffects [None]

Definition at line 752 of file cuddReorder.c.

00756 {
00757     DdNodePtr *xlist, *ylist;
00758     int    xindex, yindex;
00759     int    xslots, yslots;
00760     int    xshift, yshift;
00761     int    oldxkeys, oldykeys;
00762     int    newxkeys, newykeys;
00763     int    comple, newcomplement;
00764     int    i;
00765     Cudd_VariableType varType;
00766     Cudd_LazyGroupType groupType;
00767     int    posn;
00768     int    isolated;
00769     DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00770     DdNode *g,*next;
00771     DdNodePtr *previousP;
00772     DdNode *tmp;
00773     DdNode *sentinel = &(table->sentinel);
00774     extern DD_OOMFP MMoutOfMemory;
00775     DD_OOMFP saveHandler;
00776 
00777 #ifdef DD_DEBUG
00778     int    count,idcheck;
00779 #endif
00780 
00781 #ifdef DD_DEBUG
00782     assert(x < y);
00783     assert(cuddNextHigh(table,x) == y);
00784     assert(table->subtables[x].keys != 0);
00785     assert(table->subtables[y].keys != 0);
00786     assert(table->subtables[x].dead == 0);
00787     assert(table->subtables[y].dead == 0);
00788 #endif
00789 
00790     ddTotalNumberSwapping++;
00791 
00792     /* Get parameters of x subtable. */
00793     xindex = table->invperm[x];
00794     xlist = table->subtables[x].nodelist;
00795     oldxkeys = table->subtables[x].keys;
00796     xslots = table->subtables[x].slots;
00797     xshift = table->subtables[x].shift;
00798 
00799     /* Get parameters of y subtable. */
00800     yindex = table->invperm[y];
00801     ylist = table->subtables[y].nodelist;
00802     oldykeys = table->subtables[y].keys;
00803     yslots = table->subtables[y].slots;
00804     yshift = table->subtables[y].shift;
00805 
00806     if (!cuddTestInteract(table,xindex,yindex)) {
00807 #ifdef DD_STATS
00808         ddTotalNISwaps++;
00809 #endif
00810         newxkeys = oldxkeys;
00811         newykeys = oldykeys;
00812     } else {
00813         newxkeys = 0;
00814         newykeys = oldykeys;
00815 
00816         /* Check whether the two projection functions involved in this
00817         ** swap are isolated. At the end, we'll be able to tell how many
00818         ** isolated projection functions are there by checking only these
00819         ** two functions again. This is done to eliminate the isolated
00820         ** projection functions from the node count.
00821         */
00822         isolated = - ((table->vars[xindex]->ref == 1) +
00823                      (table->vars[yindex]->ref == 1));
00824 
00825         /* The nodes in the x layer that do not depend on
00826         ** y will stay there; the others are put in a chain.
00827         ** The chain is handled as a LIFO; g points to the beginning.
00828         */
00829         g = NULL;
00830         if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
00831             oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
00832             for (i = 0; i < xslots; i++) {
00833                 previousP = &(xlist[i]);
00834                 f = *previousP;
00835                 while (f != sentinel) {
00836                     next = f->next;
00837                     f1 = cuddT(f); f0 = cuddE(f);
00838                     if (f1->index != (DdHalfWord) yindex &&
00839                         Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
00840                         /* stays */
00841                         newxkeys++;
00842                         *previousP = f;
00843                         previousP = &(f->next);
00844                     } else {
00845                         f->index = yindex;
00846                         f->next = g;
00847                         g = f;
00848                     }
00849                     f = next;
00850                 } /* while there are elements in the collision chain */
00851                 *previousP = sentinel;
00852             } /* for each slot of the x subtable */
00853         } else {                /* resize xlist */
00854             DdNode *h = NULL;
00855             DdNodePtr *newxlist;
00856             unsigned int newxslots;
00857             int newxshift;
00858             /* Empty current xlist. Nodes that stay go to list h;
00859             ** nodes that move go to list g. */
00860             for (i = 0; i < xslots; i++) {
00861                 f = xlist[i];
00862                 while (f != sentinel) {
00863                     next = f->next;
00864                     f1 = cuddT(f); f0 = cuddE(f);
00865                     if (f1->index != (DdHalfWord) yindex &&
00866                         Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
00867                         /* stays */
00868                         f->next = h;
00869                         h = f;
00870                         newxkeys++;
00871                     } else {
00872                         f->index = yindex;
00873                         f->next = g;
00874                         g = f;
00875                     }
00876                     f = next;
00877                 } /* while there are elements in the collision chain */
00878             } /* for each slot of the x subtable */
00879             /* Decide size of new subtable. */
00880             newxshift = xshift;
00881             newxslots = xslots;
00882             while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
00883                 newxshift--;
00884                 newxslots <<= 1;
00885             }
00886             while ((unsigned) oldxkeys < newxslots &&
00887                    newxslots > table->initSlots) {
00888                 newxshift++;
00889                 newxslots >>= 1;
00890             }
00891             /* Try to allocate new table. Be ready to back off. */
00892             saveHandler = MMoutOfMemory;
00893             MMoutOfMemory = Cudd_OutOfMem;
00894             newxlist = ALLOC(DdNodePtr, newxslots);
00895             MMoutOfMemory = saveHandler;
00896             if (newxlist == NULL) {
00897                 (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
00898                 newxlist = xlist;
00899                 newxslots = xslots;
00900                 newxshift = xshift;
00901             } else {
00902                 table->slots += ((int) newxslots - xslots);
00903                 table->minDead = (unsigned)
00904                     (table->gcFrac * (double) table->slots);
00905                 table->cacheSlack = (int)
00906                     ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO
00907                           * table->slots) - 2 * (int) table->cacheSlots;
00908                 table->memused +=
00909                     ((int) newxslots - xslots) * sizeof(DdNodePtr);
00910                 FREE(xlist);
00911                 xslots =  newxslots;
00912                 xshift = newxshift;
00913                 xlist = newxlist;
00914             }
00915             /* Initialize new subtable. */
00916             for (i = 0; i < xslots; i++) {
00917                 xlist[i] = sentinel;
00918             }
00919             /* Move nodes that were parked in list h to their new home. */
00920             f = h;
00921             while (f != NULL) {
00922                 next = f->next;
00923                 f1 = cuddT(f);
00924                 f0 = cuddE(f);
00925                 /* Check xlist for pair (f11,f01). */
00926                 posn = ddHash(f1, f0, xshift);
00927                 /* For each element tmp in collision list xlist[posn]. */
00928                 previousP = &(xlist[posn]);
00929                 tmp = *previousP;
00930                 while (f1 < cuddT(tmp)) {
00931                     previousP = &(tmp->next);
00932                     tmp = *previousP;
00933                 }
00934                 while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
00935                     previousP = &(tmp->next);
00936                     tmp = *previousP;
00937                 }
00938                 f->next = *previousP;
00939                 *previousP = f;
00940                 f = next;
00941             }
00942         }
00943 
00944 #ifdef DD_COUNT
00945         table->swapSteps += oldxkeys - newxkeys;
00946 #endif
00947         /* Take care of the x nodes that must be re-expressed.
00948         ** They form a linked list pointed by g. Their index has been
00949         ** already changed to yindex.
00950         */
00951         f = g;
00952         while (f != NULL) {
00953             next = f->next;
00954             /* Find f1, f0, f11, f10, f01, f00. */
00955             f1 = cuddT(f);
00956 #ifdef DD_DEBUG
00957             assert(!(Cudd_IsComplement(f1)));
00958 #endif
00959             if ((int) f1->index == yindex) {
00960                 f11 = cuddT(f1); f10 = cuddE(f1);
00961             } else {
00962                 f11 = f10 = f1;
00963             }
00964 #ifdef DD_DEBUG
00965             assert(!(Cudd_IsComplement(f11)));
00966 #endif
00967             f0 = cuddE(f);
00968             comple = Cudd_IsComplement(f0);
00969             f0 = Cudd_Regular(f0);
00970             if ((int) f0->index == yindex) {
00971                 f01 = cuddT(f0); f00 = cuddE(f0);
00972             } else {
00973                 f01 = f00 = f0;
00974             }
00975             if (comple) {
00976                 f01 = Cudd_Not(f01);
00977                 f00 = Cudd_Not(f00);
00978             }
00979             /* Decrease ref count of f1. */
00980             cuddSatDec(f1->ref);
00981             /* Create the new T child. */
00982             if (f11 == f01) {
00983                 newf1 = f11;
00984                 cuddSatInc(newf1->ref);
00985             } else {
00986                 /* Check xlist for triple (xindex,f11,f01). */
00987                 posn = ddHash(f11, f01, xshift);
00988                 /* For each element newf1 in collision list xlist[posn]. */
00989                 previousP = &(xlist[posn]);
00990                 newf1 = *previousP;
00991                 while (f11 < cuddT(newf1)) {
00992                     previousP = &(newf1->next);
00993                     newf1 = *previousP;
00994                 }
00995                 while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
00996                     previousP = &(newf1->next);
00997                     newf1 = *previousP;
00998                 }
00999                 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
01000                     cuddSatInc(newf1->ref);
01001                 } else { /* no match */
01002                     newf1 = cuddDynamicAllocNode(table);
01003                     if (newf1 == NULL)
01004                         goto cuddSwapOutOfMem;
01005                     newf1->index = xindex; newf1->ref = 1;
01006                     cuddT(newf1) = f11;
01007                     cuddE(newf1) = f01;
01008                     /* Insert newf1 in the collision list xlist[posn];
01009                     ** increase the ref counts of f11 and f01.
01010                     */
01011                     newxkeys++;
01012                     newf1->next = *previousP;
01013                     *previousP = newf1;
01014                     cuddSatInc(f11->ref);
01015                     tmp = Cudd_Regular(f01);
01016                     cuddSatInc(tmp->ref);
01017                 }
01018             }
01019             cuddT(f) = newf1;
01020 #ifdef DD_DEBUG
01021             assert(!(Cudd_IsComplement(newf1)));
01022 #endif
01023 
01024             /* Do the same for f0, keeping complement dots into account. */
01025             /* Decrease ref count of f0. */
01026             tmp = Cudd_Regular(f0);
01027             cuddSatDec(tmp->ref);
01028             /* Create the new E child. */
01029             if (f10 == f00) {
01030                 newf0 = f00;
01031                 tmp = Cudd_Regular(newf0);
01032                 cuddSatInc(tmp->ref);
01033             } else {
01034                 /* make sure f10 is regular */
01035                 newcomplement = Cudd_IsComplement(f10);
01036                 if (newcomplement) {
01037                     f10 = Cudd_Not(f10);
01038                     f00 = Cudd_Not(f00);
01039                 }
01040                 /* Check xlist for triple (xindex,f10,f00). */
01041                 posn = ddHash(f10, f00, xshift);
01042                 /* For each element newf0 in collision list xlist[posn]. */
01043                 previousP = &(xlist[posn]);
01044                 newf0 = *previousP;
01045                 while (f10 < cuddT(newf0)) {
01046                     previousP = &(newf0->next);
01047                     newf0 = *previousP;
01048                 }
01049                 while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
01050                     previousP = &(newf0->next);
01051                     newf0 = *previousP;
01052                 }
01053                 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
01054                     cuddSatInc(newf0->ref);
01055                 } else { /* no match */
01056                     newf0 = cuddDynamicAllocNode(table);
01057                     if (newf0 == NULL)
01058                         goto cuddSwapOutOfMem;
01059                     newf0->index = xindex; newf0->ref = 1;
01060                     cuddT(newf0) = f10;
01061                     cuddE(newf0) = f00;
01062                     /* Insert newf0 in the collision list xlist[posn];
01063                     ** increase the ref counts of f10 and f00.
01064                     */
01065                     newxkeys++;
01066                     newf0->next = *previousP;
01067                     *previousP = newf0;
01068                     cuddSatInc(f10->ref);
01069                     tmp = Cudd_Regular(f00);
01070                     cuddSatInc(tmp->ref);
01071                 }
01072                 if (newcomplement) {
01073                     newf0 = Cudd_Not(newf0);
01074                 }
01075             }
01076             cuddE(f) = newf0;
01077 
01078             /* Insert the modified f in ylist.
01079             ** The modified f does not already exists in ylist.
01080             ** (Because of the uniqueness of the cofactors.)
01081             */
01082             posn = ddHash(newf1, newf0, yshift);
01083             newykeys++;
01084             previousP = &(ylist[posn]);
01085             tmp = *previousP;
01086             while (newf1 < cuddT(tmp)) {
01087                 previousP = &(tmp->next);
01088                 tmp = *previousP;
01089             }
01090             while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
01091                 previousP = &(tmp->next);
01092                 tmp = *previousP;
01093             }
01094             f->next = *previousP;
01095             *previousP = f;
01096             f = next;
01097         } /* while f != NULL */
01098 
01099         /* GC the y layer. */
01100 
01101         /* For each node f in ylist. */
01102         for (i = 0; i < yslots; i++) {
01103             previousP = &(ylist[i]);
01104             f = *previousP;
01105             while (f != sentinel) {
01106                 next = f->next;
01107                 if (f->ref == 0) {
01108                     tmp = cuddT(f);
01109                     cuddSatDec(tmp->ref);
01110                     tmp = Cudd_Regular(cuddE(f));
01111                     cuddSatDec(tmp->ref);
01112                     cuddDeallocNode(table,f);
01113                     newykeys--;
01114                 } else {
01115                     *previousP = f;
01116                     previousP = &(f->next);
01117                 }
01118                 f = next;
01119             } /* while f */
01120             *previousP = sentinel;
01121         } /* for i */
01122 
01123 #ifdef DD_DEBUG
01124 #if 0
01125         (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
01126 #endif
01127         count = 0;
01128         idcheck = 0;
01129         for (i = 0; i < yslots; i++) {
01130             f = ylist[i];
01131             while (f != sentinel) {
01132                 count++;
01133                 if (f->index != (DdHalfWord) yindex)
01134                     idcheck++;
01135                 f = f->next;
01136             }
01137         }
01138         if (count != newykeys) {
01139             (void) fprintf(table->out,
01140                            "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
01141                            oldykeys,newykeys,count);
01142         }
01143         if (idcheck != 0)
01144             (void) fprintf(table->out,
01145                            "Error in id's of ylist\twrong id's = %d\n",
01146                            idcheck);
01147         count = 0;
01148         idcheck = 0;
01149         for (i = 0; i < xslots; i++) {
01150             f = xlist[i];
01151             while (f != sentinel) {
01152                 count++;
01153                 if (f->index != (DdHalfWord) xindex)
01154                     idcheck++;
01155                 f = f->next;
01156             }
01157         }
01158         if (count != newxkeys) {
01159             (void) fprintf(table->out,
01160                            "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
01161                            oldxkeys,newxkeys,count);
01162         }
01163         if (idcheck != 0)
01164             (void) fprintf(table->out,
01165                            "Error in id's of xlist\twrong id's = %d\n",
01166                            idcheck);
01167 #endif
01168 
01169         isolated += (table->vars[xindex]->ref == 1) +
01170                     (table->vars[yindex]->ref == 1);
01171         table->isolated += isolated;
01172     }
01173 
01174     /* Set the appropriate fields in table. */
01175     table->subtables[x].nodelist = ylist;
01176     table->subtables[x].slots = yslots;
01177     table->subtables[x].shift = yshift;
01178     table->subtables[x].keys = newykeys;
01179     table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
01180     i = table->subtables[x].bindVar;
01181     table->subtables[x].bindVar = table->subtables[y].bindVar;
01182     table->subtables[y].bindVar = i;
01183     /* Adjust filds for lazy sifting. */
01184     varType = table->subtables[x].varType;
01185     table->subtables[x].varType = table->subtables[y].varType;
01186     table->subtables[y].varType = varType;
01187     i = table->subtables[x].pairIndex;
01188     table->subtables[x].pairIndex = table->subtables[y].pairIndex;
01189     table->subtables[y].pairIndex = i;
01190     i = table->subtables[x].varHandled;
01191     table->subtables[x].varHandled = table->subtables[y].varHandled;
01192     table->subtables[y].varHandled = i;
01193     groupType = table->subtables[x].varToBeGrouped;
01194     table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
01195     table->subtables[y].varToBeGrouped = groupType;
01196 
01197     table->subtables[y].nodelist = xlist;
01198     table->subtables[y].slots = xslots;
01199     table->subtables[y].shift = xshift;
01200     table->subtables[y].keys = newxkeys;
01201     table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
01202 
01203     table->perm[xindex] = y; table->perm[yindex] = x;
01204     table->invperm[x] = yindex; table->invperm[y] = xindex;
01205 
01206     table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
01207 
01208     return(table->keys - table->isolated);
01209 
01210 cuddSwapOutOfMem:
01211     (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
01212 
01213     return (0);
01214 
01215 } /* end of cuddSwapInPlace */

int cuddSwapping ( DdManager table,
int  lower,
int  upper,
Cudd_ReorderingType  heuristic 
)

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

Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.]

Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps.

  1. Select two variables (RANDOM or HEURISTIC).
  2. Permute these variables.
  3. If the nodes have decreased accept the permutation.
  4. Otherwise reconstruct the original heap.
  5. Loop.

Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 596 of file cuddReorder.c.

00601 {
00602     int i, j;
00603     int max, keys;
00604     int nvars;
00605     int x, y;
00606     int iterate;
00607     int previousSize;
00608     Move *moves, *move;
00609     int pivot;
00610     int modulo;
00611     int result;
00612 
00613 #ifdef DD_DEBUG
00614     /* Sanity check */
00615     assert(lower >= 0 && upper < table->size && lower <= upper);
00616 #endif
00617 
00618     nvars = upper - lower + 1;
00619     iterate = nvars;
00620 
00621     for (i = 0; i < iterate; i++) {
00622         if (ddTotalNumberSwapping >= table->siftMaxSwap)
00623             break;
00624         if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
00625             max = -1;
00626             for (j = lower; j <= upper; j++) {
00627                 if ((keys = table->subtables[j].keys) > max) {
00628                     max = keys;
00629                     pivot = j;
00630                 }
00631             }
00632 
00633             modulo = upper - pivot;
00634             if (modulo == 0) {
00635                 y = pivot;
00636             } else{
00637                 y = pivot + 1 + ((int) Cudd_Random() % modulo);
00638             }
00639 
00640             modulo = pivot - lower - 1;
00641             if (modulo < 1) {
00642                 x = lower;
00643             } else{
00644                 do {
00645                     x = (int) Cudd_Random() % modulo;
00646                 } while (x == y);
00647             }
00648         } else {
00649             x = ((int) Cudd_Random() % nvars) + lower;
00650             do {
00651                 y = ((int) Cudd_Random() % nvars) + lower;
00652             } while (x == y);
00653         }
00654         previousSize = table->keys - table->isolated;
00655         moves = ddSwapAny(table,x,y);
00656         if (moves == NULL) goto cuddSwappingOutOfMem;
00657         result = ddSiftingBackward(table,previousSize,moves);
00658         if (!result) goto cuddSwappingOutOfMem;
00659         while (moves != NULL) {
00660             move = moves->next;
00661             cuddDeallocMove(table, moves);
00662             moves = move;
00663         }
00664 #ifdef DD_STATS
00665         if (table->keys < (unsigned) previousSize + table->isolated) {
00666             (void) fprintf(table->out,"-");
00667         } else if (table->keys > (unsigned) previousSize + table->isolated) {
00668             (void) fprintf(table->out,"+");     /* should never happen */
00669         } else {
00670             (void) fprintf(table->out,"=");
00671         }
00672         fflush(table->out);
00673 #endif
00674 #if 0
00675         (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
00676                        table->keys - table->isolated);
00677 #endif
00678     }
00679 
00680     return(1);
00681 
00682 cuddSwappingOutOfMem:
00683     while (moves != NULL) {
00684         move = moves->next;
00685         cuddDeallocMove(table, moves);
00686         moves = move;
00687     }
00688 
00689     return(0);
00690 
00691 } /* end of cuddSwapping */

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

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

Synopsis [Checks for symmetry of x and y.]

Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.]

SideEffects [None]

Definition at line 188 of file cuddSymmetry.c.

00192 {
00193     DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
00194     int comple;         /* f0 is complemented */
00195     int xsymmy;         /* x and y may be positively symmetric */
00196     int xsymmyp;        /* x and y may be negatively symmetric */
00197     int arccount;       /* number of arcs from layer x to layer y */
00198     int TotalRefCount;  /* total reference count of layer y minus 1 */
00199     int yindex;
00200     int i;
00201     DdNodePtr *list;
00202     int slots;
00203     DdNode *sentinel = &(table->sentinel);
00204 #ifdef DD_DEBUG
00205     int xindex;
00206 #endif
00207 
00208     /* Checks that x and y are not the projection functions.
00209     ** For x it is sufficient to check whether there is only one
00210     ** node; indeed, if there is one node, it is the projection function
00211     ** and it cannot point to y. Hence, if y isn't just the projection
00212     ** function, it has one arc coming from a layer different from x.
00213     */
00214     if (table->subtables[x].keys == 1) {
00215         return(0);
00216     }
00217     yindex = table->invperm[y];
00218     if (table->subtables[y].keys == 1) {
00219         if (table->vars[yindex]->ref == 1)
00220             return(0);
00221     }
00222 
00223     xsymmy = xsymmyp = 1;
00224     arccount = 0;
00225     slots = table->subtables[x].slots;
00226     list = table->subtables[x].nodelist;
00227     for (i = 0; i < slots; i++) {
00228         f = list[i];
00229         while (f != sentinel) {
00230             /* Find f1, f0, f11, f10, f01, f00. */
00231             f1 = cuddT(f);
00232             f0 = Cudd_Regular(cuddE(f));
00233             comple = Cudd_IsComplement(cuddE(f));
00234             if ((int) f1->index == yindex) {
00235                 arccount++;
00236                 f11 = cuddT(f1); f10 = cuddE(f1);
00237             } else {
00238                 if ((int) f0->index != yindex) {
00239                     /* If f is an isolated projection function it is
00240                     ** allowed to bypass layer y.
00241                     */
00242                     if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
00243                         return(0); /* f bypasses layer y */
00244                 }
00245                 f11 = f10 = f1;
00246             }
00247             if ((int) f0->index == yindex) {
00248                 arccount++;
00249                 f01 = cuddT(f0); f00 = cuddE(f0);
00250             } else {
00251                 f01 = f00 = f0;
00252             }
00253             if (comple) {
00254                 f01 = Cudd_Not(f01);
00255                 f00 = Cudd_Not(f00);
00256             }
00257 
00258             if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
00259                 xsymmy &= f01 == f10;
00260                 xsymmyp &= f11 == f00;
00261                 if ((xsymmy == 0) && (xsymmyp == 0))
00262                     return(0);
00263             }
00264 
00265             f = f->next;
00266         } /* while */
00267     } /* for */
00268 
00269     /* Calculate the total reference counts of y */
00270     TotalRefCount = -1; /* -1 for projection function */
00271     slots = table->subtables[y].slots;
00272     list = table->subtables[y].nodelist;
00273     for (i = 0; i < slots; i++) {
00274         f = list[i];
00275         while (f != sentinel) {
00276             TotalRefCount += f->ref;
00277             f = f->next;
00278         }
00279     }
00280 
00281 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00282     if (arccount == TotalRefCount) {
00283         xindex = table->invperm[x];
00284         (void) fprintf(table->out,
00285                        "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00286                        xindex,yindex,x,y);
00287     }
00288 #endif
00289 
00290     return(arccount == TotalRefCount);
00291 
00292 } /* end of cuddSymmCheck */

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

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

Synopsis [Symmetric sifting algorithm.]

Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique subtable.
  2. Sift the variable up and down, remembering each time the total size of the DD heap and grouping variables that are symmetric.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddSymmSiftingConv]

Definition at line 318 of file cuddSymmetry.c.

00322 {
00323     int         i;
00324     int         *var;
00325     int         size;
00326     int         x;
00327     int         result;
00328     int         symvars;
00329     int         symgroups;
00330 #ifdef DD_STATS
00331     int         previousSize;
00332 #endif
00333 
00334     size = table->size;
00335 
00336     /* Find order in which to sift variables. */
00337     var = NULL;
00338     entry = ALLOC(int,size);
00339     if (entry == NULL) {
00340         table->errorCode = CUDD_MEMORY_OUT;
00341         goto ddSymmSiftingOutOfMem;
00342     }
00343     var = ALLOC(int,size);
00344     if (var == NULL) {
00345         table->errorCode = CUDD_MEMORY_OUT;
00346         goto ddSymmSiftingOutOfMem;
00347     }
00348 
00349     for (i = 0; i < size; i++) {
00350         x = table->perm[i];
00351         entry[i] = table->subtables[x].keys;
00352         var[i] = i;
00353     }
00354 
00355     qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00356 
00357     /* Initialize the symmetry of each subtable to itself. */
00358     for (i = lower; i <= upper; i++) {
00359         table->subtables[i].next = i;
00360     }
00361 
00362     for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00363         if (ddTotalNumberSwapping >= table->siftMaxSwap)
00364             break;
00365         x = table->perm[var[i]];
00366 #ifdef DD_STATS
00367         previousSize = table->keys - table->isolated;
00368 #endif
00369         if (x < lower || x > upper) continue;
00370         if (table->subtables[x].next == (unsigned) x) {
00371             result = ddSymmSiftingAux(table,x,lower,upper);
00372             if (!result) goto ddSymmSiftingOutOfMem;
00373 #ifdef DD_STATS
00374             if (table->keys < (unsigned) previousSize + table->isolated) {
00375                 (void) fprintf(table->out,"-");
00376             } else if (table->keys > (unsigned) previousSize +
00377                        table->isolated) {
00378                 (void) fprintf(table->out,"+"); /* should never happen */
00379             } else {
00380                 (void) fprintf(table->out,"=");
00381             }
00382             fflush(table->out);
00383 #endif
00384         }
00385     }
00386 
00387     FREE(var);
00388     FREE(entry);
00389 
00390     ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00391 
00392 #ifdef DD_STATS
00393     (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00394                    symvars);
00395     (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00396                    symgroups);
00397 #endif
00398 
00399     return(1+symvars);
00400 
00401 ddSymmSiftingOutOfMem:
00402 
00403     if (entry != NULL) FREE(entry);
00404     if (var != NULL) FREE(var);
00405 
00406     return(0);
00407 
00408 } /* end of cuddSymmSifting */

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

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

Synopsis [Symmetric sifting to convergence algorithm.]

Description [Symmetric sifting to convergence algorithm. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique subtable.
  2. Sift the variable up and down, remembering each time the total size of the DD heap and grouping variables that are symmetric.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.
  5. Repeat 1-4 until no further improvement.

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddSymmSifting]

Definition at line 435 of file cuddSymmetry.c.

00439 {
00440     int         i;
00441     int         *var;
00442     int         size;
00443     int         x;
00444     int         result;
00445     int         symvars;
00446     int         symgroups;
00447     int         classes;
00448     int         initialSize;
00449 #ifdef DD_STATS
00450     int         previousSize;
00451 #endif
00452 
00453     initialSize = table->keys - table->isolated;
00454 
00455     size = table->size;
00456 
00457     /* Find order in which to sift variables. */
00458     var = NULL;
00459     entry = ALLOC(int,size);
00460     if (entry == NULL) {
00461         table->errorCode = CUDD_MEMORY_OUT;
00462         goto ddSymmSiftingConvOutOfMem;
00463     }
00464     var = ALLOC(int,size);
00465     if (var == NULL) {
00466         table->errorCode = CUDD_MEMORY_OUT;
00467         goto ddSymmSiftingConvOutOfMem;
00468     }
00469 
00470     for (i = 0; i < size; i++) {
00471         x = table->perm[i];
00472         entry[i] = table->subtables[x].keys;
00473         var[i] = i;
00474     }
00475 
00476     qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00477 
00478     /* Initialize the symmetry of each subtable to itself
00479     ** for first pass of converging symmetric sifting.
00480     */
00481     for (i = lower; i <= upper; i++) {
00482         table->subtables[i].next = i;
00483     }
00484 
00485     for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
00486         if (ddTotalNumberSwapping >= table->siftMaxSwap)
00487             break;
00488         x = table->perm[var[i]];
00489         if (x < lower || x > upper) continue;
00490         /* Only sift if not in symmetry group already. */
00491         if (table->subtables[x].next == (unsigned) x) {
00492 #ifdef DD_STATS
00493             previousSize = table->keys - table->isolated;
00494 #endif
00495             result = ddSymmSiftingAux(table,x,lower,upper);
00496             if (!result) goto ddSymmSiftingConvOutOfMem;
00497 #ifdef DD_STATS
00498             if (table->keys < (unsigned) previousSize + table->isolated) {
00499                 (void) fprintf(table->out,"-");
00500             } else if (table->keys > (unsigned) previousSize +
00501                        table->isolated) {
00502                 (void) fprintf(table->out,"+");
00503             } else {
00504                 (void) fprintf(table->out,"=");
00505             }
00506             fflush(table->out);
00507 #endif
00508         }
00509     }
00510 
00511     /* Sifting now until convergence. */
00512     while ((unsigned) initialSize > table->keys - table->isolated) {
00513         initialSize = table->keys - table->isolated;
00514 #ifdef DD_STATS
00515         (void) fprintf(table->out,"\n");
00516 #endif
00517         /* Here we consider only one representative for each symmetry class. */
00518         for (x = lower, classes = 0; x <= upper; x++, classes++) {
00519             while ((unsigned) x < table->subtables[x].next) {
00520                 x = table->subtables[x].next;
00521             }
00522             /* Here x is the largest index in a group.
00523             ** Groups consist of adjacent variables.
00524             ** Hence, the next increment of x will move it to a new group.
00525             */
00526             i = table->invperm[x];
00527             entry[i] = table->subtables[x].keys;
00528             var[classes] = i;
00529         }
00530 
00531         qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00532 
00533         /* Now sift. */
00534         for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00535             if (ddTotalNumberSwapping >= table->siftMaxSwap)
00536                 break;
00537             x = table->perm[var[i]];
00538             if ((unsigned) x >= table->subtables[x].next) {
00539 #ifdef DD_STATS
00540                 previousSize = table->keys - table->isolated;
00541 #endif
00542                 result = ddSymmSiftingConvAux(table,x,lower,upper);
00543                 if (!result ) goto ddSymmSiftingConvOutOfMem;
00544 #ifdef DD_STATS
00545                 if (table->keys < (unsigned) previousSize + table->isolated) {
00546                     (void) fprintf(table->out,"-");
00547                 } else if (table->keys > (unsigned) previousSize +
00548                            table->isolated) {
00549                     (void) fprintf(table->out,"+");
00550                 } else {
00551                     (void) fprintf(table->out,"=");
00552                 }
00553                 fflush(table->out);
00554 #endif
00555             }
00556         } /* for */
00557     }
00558 
00559     ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00560 
00561 #ifdef DD_STATS
00562     (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00563                    symvars);
00564     (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00565                    symgroups);
00566 #endif
00567 
00568     FREE(var);
00569     FREE(entry);
00570 
00571     return(1+symvars);
00572 
00573 ddSymmSiftingConvOutOfMem:
00574 
00575     if (entry != NULL) FREE(entry);
00576     if (var != NULL) FREE(var);
00577 
00578     return(0);
00579 
00580 } /* end of cuddSymmSiftingConv */

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

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

Synopsis [Test interaction matrix entries.]

Description [Given a pair of variables 0 <= x < y < table->size, tests whether the corresponding bit of the interaction matrix is 1. Returns the value of the bit.]

SideEffects [None]

SeeAlso []

Definition at line 187 of file cuddInteract.c.

00191 {
00192     int posn, word, bit, result;
00193 
00194     if (x > y) {
00195         int tmp = x;
00196         x = y;
00197         y = tmp;
00198     }
00199 #ifdef DD_DEBUG
00200     assert(x < y);
00201     assert(y < table->size);
00202     assert(x >= 0);
00203 #endif
00204 
00205     posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
00206     word = posn >> LOGBPL;
00207     bit = posn & (BPL-1);
00208     result = (table->interact[word] >> bit) & 1L;
00209     return(result);
00210 
00211 } /* end of cuddTestInteract */

int cuddTimesInDeathRow ( DdManager dd,
DdNode f 
)

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

Synopsis [Counts how many times a node is in the death row.]

Description []

SideEffects [None]

SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow]

Definition at line 789 of file cuddRef.c.

00792 {
00793     int count = 0;
00794 #ifndef DD_NO_DEATH_ROW
00795     int i;
00796 
00797     for (i = 0; i < dd->deathRowDepth; i++) {
00798         count += f == dd->deathRow[i];
00799     }
00800 #endif
00801 
00802     return(count);
00803 
00804 } /* end of cuddTimesInDeathRow */

int cuddTreeSifting ( DdManager table,
Cudd_ReorderingType  method 
)

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

Synopsis [Tree sifting algorithm.]

Description [Tree sifting algorithm. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling ddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 270 of file cuddGroup.c.

00273 {
00274     int i;
00275     int nvars;
00276     int result;
00277     int tempTree;
00278 
00279     /* If no tree is provided we create a temporary one in which all
00280     ** variables are in a single group. After reordering this tree is
00281     ** destroyed.
00282     */
00283     tempTree = table->tree == NULL;
00284     if (tempTree) {
00285         table->tree = Mtr_InitGroupTree(0,table->size);
00286         table->tree->index = table->invperm[0];
00287     }
00288     nvars = table->size;
00289 
00290 #ifdef DD_DEBUG
00291     if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:");
00292     Mtr_PrintGroups(table->tree,pr <= 0);
00293 #endif
00294 
00295 #ifdef DD_STATS
00296     extsymmcalls = 0;
00297     extsymm = 0;
00298     secdiffcalls = 0;
00299     secdiff = 0;
00300     secdiffmisfire = 0;
00301 
00302     (void) fprintf(table->out,"\n");
00303     if (!tempTree)
00304         (void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
00305                        ddCountInternalMtrNodes(table,table->tree));
00306 #endif
00307 
00308     /* Initialize the group of each subtable to itself. Initially
00309     ** there are no groups. Groups are created according to the tree
00310     ** structure in postorder fashion.
00311     */
00312     for (i = 0; i < nvars; i++)
00313         table->subtables[i].next = i;
00314 
00315 
00316     /* Reorder. */
00317     result = ddTreeSiftingAux(table, table->tree, method);
00318 
00319 #ifdef DD_STATS         /* print stats */
00320     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00321         (table->groupcheck == CUDD_GROUP_CHECK7 ||
00322          table->groupcheck == CUDD_GROUP_CHECK5)) {
00323         (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00324         (void) fprintf(table->out,"extsymm = %d",extsymm);
00325     }
00326     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00327         table->groupcheck == CUDD_GROUP_CHECK7) {
00328         (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00329         (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00330         (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00331     }
00332 #endif
00333 
00334     if (tempTree)
00335         Cudd_FreeTree(table);
00336     return(result);
00337 
00338 } /* end of cuddTreeSifting */

DdNode* cuddUnderApprox ( DdManager dd,
DdNode f,
int  numVars,
int  threshold,
int  safe,
double  quality 
)

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

Synopsis [Applies Tom Shiple's underappoximation algorithm.]

Description [Applies Tom Shiple's underappoximation algorithm. Proceeds in three phases:

  • collect information on each node in the BDD; this is done via DFS.
  • traverse the BDD in top-down fashion and compute for each node whether its elimination increases density.
  • traverse the BDD via DFS and actually perform the elimination.

Returns the approximated BDD if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_UnderApprox]

Definition at line 507 of file cuddApprox.c.

00514 {
00515     ApproxInfo *info;
00516     DdNode *subset;
00517     int result;
00518 
00519     if (f == NULL) {
00520         fprintf(dd->err, "Cannot subset, nil object\n");
00521         return(NULL);
00522     }
00523 
00524     if (Cudd_IsConstant(f)) {
00525         return(f);
00526     }
00527 
00528     /* Create table where node data are accessible via a hash table. */
00529     info = gatherInfo(dd, f, numVars, safe);
00530     if (info == NULL) {
00531         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00532         dd->errorCode = CUDD_MEMORY_OUT;
00533         return(NULL);
00534     }
00535 
00536     /* Mark nodes that should be replaced by zero. */
00537     result = UAmarkNodes(dd, f, info, threshold, safe, quality);
00538     if (result == 0) {
00539         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00540         FREE(info->page);
00541         st_free_table(info->table);
00542         FREE(info);
00543         dd->errorCode = CUDD_MEMORY_OUT;
00544         return(NULL);
00545     }
00546 
00547     /* Build the result. */
00548     subset = UAbuildSubset(dd, f, info);
00549 #if 1
00550     if (subset && info->size < Cudd_DagSize(subset))
00551         (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00552                        info->size, Cudd_DagSize(subset));
00553 #endif
00554     FREE(info->page);
00555     st_free_table(info->table);
00556     FREE(info);
00557 
00558 #ifdef DD_DEBUG
00559     if (subset != NULL) {
00560         cuddRef(subset);
00561 #if 0
00562         (void) Cudd_DebugCheck(dd);
00563         (void) Cudd_CheckKeys(dd);
00564 #endif
00565         if (!Cudd_bddLeq(dd, subset, f)) {
00566             (void) fprintf(dd->err, "Wrong subset\n");
00567             dd->errorCode = CUDD_INTERNAL_ERROR;
00568         }
00569         cuddDeref(subset);
00570     }
00571 #endif
00572     return(subset);
00573 
00574 } /* end of cuddUnderApprox */

DdNode* cuddUniqueConst ( DdManager unique,
CUDD_VALUE_TYPE  value 
)

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

Synopsis [Checks the unique table for the existence of a constant node.]

Description [Checks the unique table for the existence of a constant node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. Returns a pointer to the new node.]

SideEffects [None]

Definition at line 1435 of file cuddTable.c.

01438 {
01439     int pos;
01440     DdNodePtr *nodelist;
01441     DdNode *looking;
01442     hack split;
01443 
01444 #ifdef DD_UNIQUE_PROFILE
01445     unique->uniqueLookUps++;
01446 #endif
01447 
01448     if (unique->constants.keys > unique->constants.maxKeys) {
01449         if (unique->gcEnabled && ((unique->dead > unique->minDead) ||
01450         (10 * unique->constants.dead > 9 * unique->constants.keys))) {  /* too many dead */
01451             (void) cuddGarbageCollect(unique,1);
01452         } else {
01453             cuddRehash(unique,CUDD_CONST_INDEX);
01454         }
01455     }
01456 
01457     cuddAdjust(value); /* for the case of crippled infinities */
01458 
01459     if (ddAbs(value) < unique->epsilon) {
01460         value = 0.0;
01461     }
01462     split.value = value;
01463 
01464     pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift);
01465     nodelist = unique->constants.nodelist;
01466     looking = nodelist[pos];
01467 
01468     /* Here we compare values both for equality and for difference less
01469      * than epsilon. The first comparison is required when values are
01470      * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for
01471      * every X.
01472      */
01473     while (looking != NULL) {
01474         if (looking->type.value == value ||
01475         ddEqualVal(looking->type.value,value,unique->epsilon)) {
01476             if (looking->ref == 0) {
01477                 cuddReclaim(unique,looking);
01478             }
01479             return(looking);
01480         }
01481         looking = looking->next;
01482 #ifdef DD_UNIQUE_PROFILE
01483         unique->uniqueLinks++;
01484 #endif
01485     }
01486 
01487     unique->keys++;
01488     unique->constants.keys++;
01489 
01490     looking = cuddAllocNode(unique);
01491     if (looking == NULL) return(NULL);
01492     looking->index = CUDD_CONST_INDEX;
01493     looking->type.value = value;
01494     looking->next = nodelist[pos];
01495     nodelist[pos] = looking;
01496 
01497     return(looking);
01498 
01499 } /* end of cuddUniqueConst */

DdNode* cuddUniqueInter ( DdManager unique,
int  index,
DdNode T,
DdNode E 
)

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

Synopsis [Checks the unique table for the existence of an internal node.]

Description [Checks the unique table for the existence of an internal node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.]

SideEffects [None]

SeeAlso [cuddUniqueInterZdd]

Definition at line 1115 of file cuddTable.c.

01120 {
01121     int pos;
01122     unsigned int level;
01123     int retval;
01124     DdNodePtr *nodelist;
01125     DdNode *looking;
01126     DdNodePtr *previousP;
01127     DdSubtable *subtable;
01128     int gcNumber;
01129 
01130 #ifdef DD_UNIQUE_PROFILE
01131     unique->uniqueLookUps++;
01132 #endif
01133 
01134     if (index >= unique->size) {
01135         if (!ddResizeTable(unique,index)) return(NULL);
01136     }
01137 
01138     level = unique->perm[index];
01139     subtable = &(unique->subtables[level]);
01140 
01141 #ifdef DD_DEBUG
01142     assert(level < (unsigned) cuddI(unique,T->index));
01143     assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
01144 #endif
01145 
01146     pos = ddHash(T, E, subtable->shift);
01147     nodelist = subtable->nodelist;
01148     previousP = &(nodelist[pos]);
01149     looking = *previousP;
01150 
01151     while (T < cuddT(looking)) {
01152         previousP = &(looking->next);
01153         looking = *previousP;
01154 #ifdef DD_UNIQUE_PROFILE
01155         unique->uniqueLinks++;
01156 #endif
01157     }
01158     while (T == cuddT(looking) && E < cuddE(looking)) {
01159         previousP = &(looking->next);
01160         looking = *previousP;
01161 #ifdef DD_UNIQUE_PROFILE
01162         unique->uniqueLinks++;
01163 #endif
01164     }
01165     if (T == cuddT(looking) && E == cuddE(looking)) {
01166         if (looking->ref == 0) {
01167             cuddReclaim(unique,looking);
01168         }
01169         return(looking);
01170     }
01171 
01172     /* countDead is 0 if deads should be counted and ~0 if they should not. */
01173     if (unique->autoDyn &&
01174     unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) {
01175 #ifdef DD_DEBUG
01176         retval = Cudd_DebugCheck(unique);
01177         if (retval != 0) return(NULL);
01178         retval = Cudd_CheckKeys(unique);
01179         if (retval != 0) return(NULL);
01180 #endif
01181         retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */
01182         if (retval == 0) unique->reordered = 2;
01183 #ifdef DD_DEBUG
01184         retval = Cudd_DebugCheck(unique);
01185         if (retval != 0) unique->reordered = 2;
01186         retval = Cudd_CheckKeys(unique);
01187         if (retval != 0) unique->reordered = 2;
01188 #endif
01189         return(NULL);
01190     }
01191 
01192     if (subtable->keys > subtable->maxKeys) {
01193         if (unique->gcEnabled &&
01194             ((unique->dead > unique->minDead) ||
01195             ((unique->dead > unique->minDead / 2) &&
01196             (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */
01197             (void) cuddGarbageCollect(unique,1);
01198         } else {
01199             cuddRehash(unique,(int)level);
01200         }
01201         /* Update pointer to insertion point. In the case of rehashing,
01202         ** the slot may have changed. In the case of garbage collection,
01203         ** the predecessor may have been dead. */
01204         pos = ddHash(T, E, subtable->shift);
01205         nodelist = subtable->nodelist;
01206         previousP = &(nodelist[pos]);
01207         looking = *previousP;
01208 
01209         while (T < cuddT(looking)) {
01210             previousP = &(looking->next);
01211             looking = *previousP;
01212 #ifdef DD_UNIQUE_PROFILE
01213             unique->uniqueLinks++;
01214 #endif
01215         }
01216         while (T == cuddT(looking) && E < cuddE(looking)) {
01217             previousP = &(looking->next);
01218             looking = *previousP;
01219 #ifdef DD_UNIQUE_PROFILE
01220             unique->uniqueLinks++;
01221 #endif
01222         }
01223     }
01224 
01225     gcNumber = unique->garbageCollections;
01226     looking = cuddAllocNode(unique);
01227     if (looking == NULL) {
01228         return(NULL);
01229     }
01230     unique->keys++;
01231     subtable->keys++;
01232 
01233     if (gcNumber != unique->garbageCollections) {
01234         DdNode *looking2;
01235         pos = ddHash(T, E, subtable->shift);
01236         nodelist = subtable->nodelist;
01237         previousP = &(nodelist[pos]);
01238         looking2 = *previousP;
01239 
01240         while (T < cuddT(looking2)) {
01241             previousP = &(looking2->next);
01242             looking2 = *previousP;
01243 #ifdef DD_UNIQUE_PROFILE
01244             unique->uniqueLinks++;
01245 #endif
01246         }
01247         while (T == cuddT(looking2) && E < cuddE(looking2)) {
01248             previousP = &(looking2->next);
01249             looking2 = *previousP;
01250 #ifdef DD_UNIQUE_PROFILE
01251             unique->uniqueLinks++;
01252 #endif
01253         }
01254     }
01255     looking->index = index;
01256     cuddT(looking) = T;
01257     cuddE(looking) = E;
01258     looking->next = *previousP;
01259     *previousP = looking;
01260     cuddSatInc(T->ref);         /* we know T is a regular pointer */
01261     cuddRef(E);
01262 
01263 #ifdef DD_DEBUG
01264     cuddCheckCollisionOrdering(unique,level,pos);
01265 #endif
01266 
01267     return(looking);
01268 
01269 } /* end of cuddUniqueInter */

DdNode* cuddUniqueInterIVO ( DdManager unique,
int  index,
DdNode T,
DdNode E 
)

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

Synopsis [Wrapper for cuddUniqueInter that is independent of variable ordering.]

Description [Wrapper for cuddUniqueInter that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of T and E in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]

SideEffects [None]

SeeAlso [cuddUniqueInter Cudd_MakeBddFromZddCover]

Definition at line 1289 of file cuddTable.c.

01294 {
01295     DdNode *result;
01296     DdNode *v;
01297 
01298     v = cuddUniqueInter(unique, index, DD_ONE(unique),
01299                         Cudd_Not(DD_ONE(unique)));
01300     if (v == NULL)
01301         return(NULL);
01302     cuddRef(v);
01303     result = cuddBddIteRecur(unique, v, T, E);
01304     Cudd_RecursiveDeref(unique, v);
01305     return(result);
01306 }

DdNode* cuddUniqueInterZdd ( DdManager unique,
int  index,
DdNode T,
DdNode E 
)

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

Synopsis [Checks the unique table for the existence of an internal ZDD node.]

Description [Checks the unique table for the existence of an internal ZDD node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.]

SideEffects [None]

SeeAlso [cuddUniqueInter]

Definition at line 1328 of file cuddTable.c.

01333 {
01334     int pos;
01335     unsigned int level;
01336     int retval;
01337     DdNodePtr *nodelist;
01338     DdNode *looking;
01339     DdSubtable *subtable;
01340 
01341 #ifdef DD_UNIQUE_PROFILE
01342     unique->uniqueLookUps++;
01343 #endif
01344 
01345     if (index >= unique->sizeZ) {
01346         if (!cuddResizeTableZdd(unique,index)) return(NULL);
01347     }
01348 
01349     level = unique->permZ[index];
01350     subtable = &(unique->subtableZ[level]);
01351 
01352 #ifdef DD_DEBUG
01353     assert(level < (unsigned) cuddIZ(unique,T->index));
01354     assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index));
01355 #endif
01356 
01357     if (subtable->keys > subtable->maxKeys) {
01358         if (unique->gcEnabled && ((unique->deadZ > unique->minDead) ||
01359         (10 * subtable->dead > 9 * subtable->keys))) {  /* too many dead */
01360             (void) cuddGarbageCollect(unique,1);
01361         } else {
01362             ddRehashZdd(unique,(int)level);
01363         }
01364     }
01365 
01366     pos = ddHash(T, E, subtable->shift);
01367     nodelist = subtable->nodelist;
01368     looking = nodelist[pos];
01369 
01370     while (looking != NULL) {
01371         if (cuddT(looking) == T && cuddE(looking) == E) {
01372             if (looking->ref == 0) {
01373                 cuddReclaimZdd(unique,looking);
01374             }
01375             return(looking);
01376         }
01377         looking = looking->next;
01378 #ifdef DD_UNIQUE_PROFILE
01379         unique->uniqueLinks++;
01380 #endif
01381     }
01382 
01383     /* countDead is 0 if deads should be counted and ~0 if they should not. */
01384     if (unique->autoDynZ &&
01385     unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) {
01386 #ifdef DD_DEBUG
01387         retval = Cudd_DebugCheck(unique);
01388         if (retval != 0) return(NULL);
01389         retval = Cudd_CheckKeys(unique);
01390         if (retval != 0) return(NULL);
01391 #endif
01392         retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */
01393         if (retval == 0) unique->reordered = 2;
01394 #ifdef DD_DEBUG
01395         retval = Cudd_DebugCheck(unique);
01396         if (retval != 0) unique->reordered = 2;
01397         retval = Cudd_CheckKeys(unique);
01398         if (retval != 0) unique->reordered = 2;
01399 #endif
01400         return(NULL);
01401     }
01402 
01403     unique->keysZ++;
01404     subtable->keys++;
01405 
01406     looking = cuddAllocNode(unique);
01407     if (looking == NULL) return(NULL);
01408     looking->index = index;
01409     cuddT(looking) = T;
01410     cuddE(looking) = E;
01411     looking->next = nodelist[pos];
01412     nodelist[pos] = looking;
01413     cuddRef(T);
01414     cuddRef(E);
01415 
01416     return(looking);
01417 
01418 } /* end of cuddUniqueInterZdd */

void cuddUpdateInteractionMatrix ( DdManager table,
int  xindex,
int  yindex 
)

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

Synopsis [Updates the interaction matrix.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 714 of file cuddLinear.c.

00718 {
00719     int i;
00720     for (i = 0; i < yindex; i++) {
00721         if (i != xindex && cuddTestInteract(table,i,yindex)) {
00722             if (i < xindex) {
00723                 cuddSetInteract(table,i,xindex);
00724             } else {
00725                 cuddSetInteract(table,xindex,i);
00726             }
00727         }
00728     }
00729     for (i = yindex+1; i < table->size; i++) {
00730         if (i != xindex && cuddTestInteract(table,yindex,i)) {
00731             if (i < xindex) {
00732                 cuddSetInteract(table,i,xindex);
00733             } else {
00734                 cuddSetInteract(table,xindex,i);
00735             }
00736         }
00737     }
00738 
00739 } /* end of cuddUpdateInteractionMatrix */

DdNode* cuddVerifySol ( DdManager bdd,
DdNode F,
DdNode **  G,
int *  yIndex,
int  n 
)

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

Synopsis [Implements the recursive step of Cudd_VerifySol. ]

Description []

SideEffects [none]

SeeAlso [Cudd_VerifySol]

Definition at line 332 of file cuddSolve.c.

00338 {
00339     DdNode *w, *R;
00340 
00341     int j;
00342 
00343     R = F;
00344     cuddRef(R);
00345     for(j = n - 1; j >= 0; j--) {
00346          w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]);
00347         if (w) {
00348             cuddRef(w);
00349         } else {
00350             return(NULL); 
00351         }
00352         Cudd_RecursiveDeref(bdd,R);
00353         R = w;
00354     }
00355 
00356     cuddDeref(R);
00357 
00358     return(R);
00359 
00360 } /* end of cuddVerifySol */

int cuddWindowReorder ( DdManager table,
int  low,
int  high,
Cudd_ReorderingType  submethod 
)

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

Synopsis [Reorders by applying the method of the sliding window.]

Description [Reorders by applying the method of the sliding window. Tries all possible permutations to the variables in a window that slides from low to high. The size of the window is determined by submethod. Assumes that no dead nodes are present. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 138 of file cuddWindow.c.

00143 {
00144 
00145     int res;
00146 #ifdef DD_DEBUG
00147     int supposedOpt;
00148 #endif
00149 
00150     switch (submethod) {
00151     case CUDD_REORDER_WINDOW2:
00152         res = ddWindow2(table,low,high);
00153         break;
00154     case CUDD_REORDER_WINDOW3:
00155         res = ddWindow3(table,low,high);
00156         break;
00157     case CUDD_REORDER_WINDOW4:
00158         res = ddWindow4(table,low,high);
00159         break;
00160     case CUDD_REORDER_WINDOW2_CONV:
00161         res = ddWindowConv2(table,low,high);
00162         break;
00163     case CUDD_REORDER_WINDOW3_CONV:
00164         res = ddWindowConv3(table,low,high);
00165 #ifdef DD_DEBUG
00166         supposedOpt = table->keys - table->isolated;
00167         res = ddWindow3(table,low,high);
00168         if (table->keys - table->isolated != (unsigned) supposedOpt) {
00169             (void) fprintf(table->err, "Convergence failed! (%d != %d)\n",
00170                            table->keys - table->isolated, supposedOpt);
00171         }
00172 #endif
00173         break;
00174     case CUDD_REORDER_WINDOW4_CONV:
00175         res = ddWindowConv4(table,low,high);
00176 #ifdef DD_DEBUG
00177         supposedOpt = table->keys - table->isolated;
00178         res = ddWindow4(table,low,high);
00179         if (table->keys - table->isolated != (unsigned) supposedOpt) {
00180             (void) fprintf(table->err,"Convergence failed! (%d != %d)\n",
00181                            table->keys - table->isolated, supposedOpt);
00182         }
00183 #endif
00184         break;
00185     default: return(0);
00186     }
00187 
00188     return(res);
00189 
00190 } /* end of cuddWindowReorder */

int cuddZddAlignToBdd ( DdManager table  ) 

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

Synopsis [Reorders ZDD variables according to the order of the BDD variables.]

Description [Reorders ZDD variables according to the order of the BDD variables. This function can be called at the end of BDD reordering to insure that the order of the ZDD variables is consistent with the order of the BDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M be the ratio of the two numbers. cuddZddAlignToBdd then considers the ZDD variables from M*i to (M+1)*i-1 as corresponding to BDD variable i. This function should be normally called from Cudd_ReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]

SideEffects [Changes the ZDD variable order for all diagrams and performs garbage collection of the ZDD unique table.]

SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap]

Definition at line 348 of file cuddZddReord.c.

00350 {
00351     int *invpermZ;              /* permutation array */
00352     int M;                      /* ratio of ZDD variables to BDD variables */
00353     int i,j;                    /* loop indices */
00354     int result;                 /* return value */
00355 
00356     /* We assume that a ratio of 0 is OK. */
00357     if (table->sizeZ == 0)
00358         return(1);
00359 
00360     empty = table->zero;
00361     M = table->sizeZ / table->size;
00362     /* Check whether the number of ZDD variables is a multiple of the
00363     ** number of BDD variables.
00364     */
00365     if (M * table->size != table->sizeZ)
00366         return(0);
00367     /* Create and initialize the inverse permutation array. */
00368     invpermZ = ALLOC(int,table->sizeZ);
00369     if (invpermZ == NULL) {
00370         table->errorCode = CUDD_MEMORY_OUT;
00371         return(0);
00372     }
00373     for (i = 0; i < table->size; i++) {
00374         int index = table->invperm[i];
00375         int indexZ = index * M;
00376         int levelZ = table->permZ[indexZ];
00377         levelZ = (levelZ / M) * M;
00378         for (j = 0; j < M; j++) {
00379             invpermZ[M * i + j] = table->invpermZ[levelZ + j];
00380         }
00381     }
00382     /* Eliminate dead nodes. Do not scan the cache again, because we
00383     ** assume that Cudd_ReduceHeap has already cleared it.
00384     */
00385     cuddGarbageCollect(table,0);
00386 
00387     result = zddShuffle(table, invpermZ);
00388     FREE(invpermZ);
00389     /* Fix the ZDD variable group tree. */
00390     zddFixTree(table,table->treeZ);
00391     return(result);
00392     
00393 } /* end of cuddZddAlignToBdd */

DdNode* cuddZddChange ( DdManager dd,
DdNode P,
int  var 
)

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

Synopsis [Substitutes a variable with its complement in a ZDD.]

Description [Substitutes a variable with its complement in a ZDD. returns a pointer to the result if successful; NULL otherwise. cuddZddChange performs the same function as Cudd_zddChange, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.]

SideEffects [None]

SeeAlso [Cudd_zddChange]

Definition at line 967 of file cuddZddSetop.c.

00971 {
00972     DdNode      *zvar, *res;
00973 
00974     zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd));
00975     if (zvar == NULL) return(NULL);
00976     cuddRef(zvar);
00977 
00978     res = cuddZddChangeAux(dd, P, zvar);
00979     if (res == NULL) {
00980         Cudd_RecursiveDerefZdd(dd,zvar);
00981         return(NULL);
00982     }
00983     cuddRef(res);
00984     Cudd_RecursiveDerefZdd(dd,zvar);
00985     cuddDeref(res);
00986     return(res);
00987 
00988 } /* end of cuddZddChange */

DdNode* cuddZddChangeAux ( DdManager zdd,
DdNode P,
DdNode zvar 
)

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

Synopsis [Performs the recursive step of Cudd_zddChange.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 795 of file cuddZddSetop.c.

00799 {
00800     int         top_var, level;
00801     DdNode      *res, *t, *e;
00802     DdNode      *base = DD_ONE(zdd);
00803     DdNode      *empty = DD_ZERO(zdd);
00804 
00805     statLine(zdd);
00806     if (P == empty)
00807         return(empty);
00808     if (P == base)
00809         return(zvar);
00810 
00811     /* Check cache. */
00812     res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar);
00813     if (res != NULL)
00814         return(res);
00815 
00816     top_var = zdd->permZ[P->index];
00817     level = zdd->permZ[zvar->index];
00818 
00819     if (top_var > level) {
00820         res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd));
00821         if (res == NULL) return(NULL);
00822     } else if (top_var == level) {
00823         res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P));
00824         if (res == NULL) return(NULL);
00825     } else {
00826         t = cuddZddChangeAux(zdd, cuddT(P), zvar);
00827         if (t == NULL) return(NULL);
00828         cuddRef(t);
00829         e = cuddZddChangeAux(zdd, cuddE(P), zvar);
00830         if (e == NULL) {
00831             Cudd_RecursiveDerefZdd(zdd, t);
00832             return(NULL);
00833         }
00834         cuddRef(e);
00835         res = cuddZddGetNode(zdd, P->index, t, e);
00836         if (res == NULL) {
00837             Cudd_RecursiveDerefZdd(zdd, t);
00838             Cudd_RecursiveDerefZdd(zdd, e);
00839             return(NULL);
00840         }
00841         cuddDeref(t);
00842         cuddDeref(e);
00843     }
00844 
00845     cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res);
00846 
00847     return(res);
00848 
00849 } /* end of cuddZddChangeAux */

DdNode* cuddZddComplement ( DdManager dd,
DdNode node 
)

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

Synopsis [Computes a complement of a ZDD node.]

Description [Computes the complement of a ZDD node. So far, since we couldn't find a direct way to get the complement of a ZDD cover, we first convert a ZDD cover to a BDD, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP.]

SideEffects [The result depends on current variable order.]

SeeAlso []

Definition at line 1518 of file cuddZddFuncs.c.

01521 {
01522     DdNode      *b, *isop, *zdd_I;
01523 
01524     /* Check cache */
01525     zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node);
01526     if (zdd_I)
01527         return(zdd_I);
01528 
01529     b = cuddMakeBddFromZddCover(dd, node);
01530     if (!b)
01531         return(NULL);
01532     cuddRef(b);
01533     isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I);
01534     if (!isop) {
01535         Cudd_RecursiveDeref(dd, b);
01536         return(NULL);
01537     }
01538     cuddRef(isop);
01539     cuddRef(zdd_I);
01540     Cudd_RecursiveDeref(dd, b);
01541     Cudd_RecursiveDeref(dd, isop);
01542 
01543     cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I);
01544     cuddDeref(zdd_I);
01545     return(zdd_I);
01546 } /* end of cuddZddComplement */

DdNode* cuddZddDiff ( DdManager zdd,
DdNode P,
DdNode Q 
)

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

Synopsis [Performs the recursive step of Cudd_zddDiff.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 713 of file cuddZddSetop.c.

00717 {
00718     int         p_top, q_top;
00719     DdNode      *empty = DD_ZERO(zdd), *t, *e, *res;
00720     DdManager   *table = zdd;
00721 
00722     statLine(zdd);
00723     if (P == empty)
00724         return(empty);
00725     if (Q == empty)
00726         return(P);
00727     if (P == Q)
00728         return(empty);
00729 
00730     /* Check cache.  The cache is shared by Cudd_zddDiffConst(). */
00731     res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
00732     if (res != NULL && res != DD_NON_CONSTANT)
00733         return(res);
00734 
00735     if (cuddIsConstant(P))
00736         p_top = P->index;
00737     else
00738         p_top = zdd->permZ[P->index];
00739     if (cuddIsConstant(Q))
00740         q_top = Q->index;
00741     else
00742         q_top = zdd->permZ[Q->index];
00743     if (p_top < q_top) {
00744         e = cuddZddDiff(zdd, cuddE(P), Q);
00745         if (e == NULL) return(NULL);
00746         cuddRef(e);
00747         res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
00748         if (res == NULL) {
00749             Cudd_RecursiveDerefZdd(table, e);
00750             return(NULL);
00751         }
00752         cuddDeref(e);
00753     } else if (p_top > q_top) {
00754         res = cuddZddDiff(zdd, P, cuddE(Q));
00755         if (res == NULL) return(NULL);
00756     } else {
00757         t = cuddZddDiff(zdd, cuddT(P), cuddT(Q));
00758         if (t == NULL) return(NULL);
00759         cuddRef(t);
00760         e = cuddZddDiff(zdd, cuddE(P), cuddE(Q));
00761         if (e == NULL) {
00762             Cudd_RecursiveDerefZdd(table, t);
00763             return(NULL);
00764         }
00765         cuddRef(e);
00766         res = cuddZddGetNode(zdd, P->index, t, e);
00767         if (res == NULL) {
00768             Cudd_RecursiveDerefZdd(table, t);
00769             Cudd_RecursiveDerefZdd(table, e);
00770             return(NULL);
00771         }
00772         cuddDeref(t);
00773         cuddDeref(e);
00774     }
00775 
00776     cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
00777 
00778     return(res);
00779 
00780 } /* end of cuddZddDiff */

DdNode* cuddZddDivide ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_zddDivide.]

Description []

SideEffects [None]

SeeAlso [Cudd_zddDivide]

Definition at line 1155 of file cuddZddFuncs.c.

01159 {
01160     int         v;
01161     DdNode      *one = DD_ONE(dd);
01162     DdNode      *zero = DD_ZERO(dd);
01163     DdNode      *f0, *f1, *g0, *g1;
01164     DdNode      *q, *r, *tmp;
01165     int         flag;
01166 
01167     statLine(dd);
01168     if (g == one)
01169         return(f);
01170     if (f == zero || f == one)
01171         return(zero);
01172     if (f == g)
01173         return(one);
01174 
01175     /* Check cache. */
01176     r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g);
01177     if (r)
01178         return(r);
01179 
01180     v = g->index;
01181 
01182     flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
01183     if (flag == 1)
01184         return(NULL);
01185     Cudd_Ref(f1);
01186     Cudd_Ref(f0);
01187     flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);    /* g1 != zero */
01188     if (flag == 1) {
01189         Cudd_RecursiveDerefZdd(dd, f1);
01190         Cudd_RecursiveDerefZdd(dd, f0);
01191         return(NULL);
01192     }
01193     Cudd_Ref(g1);
01194     Cudd_Ref(g0);
01195 
01196     r = cuddZddDivide(dd, f1, g1);
01197     if (r == NULL) {
01198         Cudd_RecursiveDerefZdd(dd, f1);
01199         Cudd_RecursiveDerefZdd(dd, f0);
01200         Cudd_RecursiveDerefZdd(dd, g1);
01201         Cudd_RecursiveDerefZdd(dd, g0);
01202         return(NULL);
01203     }
01204     Cudd_Ref(r);
01205 
01206     if (r != zero && g0 != zero) {
01207         tmp = r;
01208         q = cuddZddDivide(dd, f0, g0);
01209         if (q == NULL) {
01210             Cudd_RecursiveDerefZdd(dd, f1);
01211             Cudd_RecursiveDerefZdd(dd, f0);
01212             Cudd_RecursiveDerefZdd(dd, g1);
01213             Cudd_RecursiveDerefZdd(dd, g0);
01214             return(NULL);
01215         }
01216         Cudd_Ref(q);
01217         r = cuddZddIntersect(dd, r, q);
01218         if (r == NULL) {
01219             Cudd_RecursiveDerefZdd(dd, f1);
01220             Cudd_RecursiveDerefZdd(dd, f0);
01221             Cudd_RecursiveDerefZdd(dd, g1);
01222             Cudd_RecursiveDerefZdd(dd, g0);
01223             Cudd_RecursiveDerefZdd(dd, q);
01224             return(NULL);
01225         }
01226         Cudd_Ref(r);
01227         Cudd_RecursiveDerefZdd(dd, q);
01228         Cudd_RecursiveDerefZdd(dd, tmp);
01229     }
01230 
01231     Cudd_RecursiveDerefZdd(dd, f1);
01232     Cudd_RecursiveDerefZdd(dd, f0);
01233     Cudd_RecursiveDerefZdd(dd, g1);
01234     Cudd_RecursiveDerefZdd(dd, g0);
01235     
01236     cuddCacheInsert2(dd, cuddZddDivide, f, g, r);
01237     Cudd_Deref(r);
01238     return(r);
01239 
01240 } /* end of cuddZddDivide */

DdNode* cuddZddDivideF ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_zddDivideF.]

Description []

SideEffects [None]

SeeAlso [Cudd_zddDivideF]

Definition at line 1255 of file cuddZddFuncs.c.

01259 {
01260     int         v;
01261     DdNode      *one = DD_ONE(dd);
01262     DdNode      *zero = DD_ZERO(dd);
01263     DdNode      *f0, *f1, *g0, *g1;
01264     DdNode      *q, *r, *tmp;
01265     int         flag;
01266 
01267     statLine(dd);
01268     if (g == one)
01269         return(f);
01270     if (f == zero || f == one)
01271         return(zero);
01272     if (f == g)
01273         return(one);
01274 
01275     /* Check cache. */
01276     r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g);
01277     if (r)
01278         return(r);
01279 
01280     v = g->index;
01281 
01282     flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
01283     if (flag == 1)
01284         return(NULL);
01285     Cudd_Ref(f1);
01286     Cudd_Ref(f0);
01287     flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);    /* g1 != zero */
01288     if (flag == 1) {
01289         Cudd_RecursiveDerefZdd(dd, f1);
01290         Cudd_RecursiveDerefZdd(dd, f0);
01291         return(NULL);
01292     }
01293     Cudd_Ref(g1);
01294     Cudd_Ref(g0);
01295 
01296     r = cuddZddDivideF(dd, f1, g1);
01297     if (r == NULL) {
01298         Cudd_RecursiveDerefZdd(dd, f1);
01299         Cudd_RecursiveDerefZdd(dd, f0);
01300         Cudd_RecursiveDerefZdd(dd, g1);
01301         Cudd_RecursiveDerefZdd(dd, g0);
01302         return(NULL);
01303     }
01304     Cudd_Ref(r);
01305 
01306     if (r != zero && g0 != zero) {
01307         tmp = r;
01308         q = cuddZddDivideF(dd, f0, g0);
01309         if (q == NULL) {
01310             Cudd_RecursiveDerefZdd(dd, f1);
01311             Cudd_RecursiveDerefZdd(dd, f0);
01312             Cudd_RecursiveDerefZdd(dd, g1);
01313             Cudd_RecursiveDerefZdd(dd, g0);
01314             return(NULL);
01315         }
01316         Cudd_Ref(q);
01317         r = cuddZddIntersect(dd, r, q);
01318         if (r == NULL) {
01319             Cudd_RecursiveDerefZdd(dd, f1);
01320             Cudd_RecursiveDerefZdd(dd, f0);
01321             Cudd_RecursiveDerefZdd(dd, g1);
01322             Cudd_RecursiveDerefZdd(dd, g0);
01323             Cudd_RecursiveDerefZdd(dd, q);
01324             return(NULL);
01325         }
01326         Cudd_Ref(r);
01327         Cudd_RecursiveDerefZdd(dd, q);
01328         Cudd_RecursiveDerefZdd(dd, tmp);
01329     }
01330 
01331     Cudd_RecursiveDerefZdd(dd, f1);
01332     Cudd_RecursiveDerefZdd(dd, f0);
01333     Cudd_RecursiveDerefZdd(dd, g1);
01334     Cudd_RecursiveDerefZdd(dd, g0);
01335     
01336     cuddCacheInsert2(dd, cuddZddDivideF, f, g, r);
01337     Cudd_Deref(r);
01338     return(r);
01339 
01340 } /* end of cuddZddDivideF */

void cuddZddFreeUniv ( DdManager zdd  ) 

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

Synopsis [Frees the ZDD universe.]

Description [Frees the ZDD universe.]

SideEffects [None]

SeeAlso [cuddZddInitUniv]

Definition at line 294 of file cuddInit.c.

00296 {
00297     if (zdd->univ) {
00298         Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]);
00299         FREE(zdd->univ);
00300     }
00301 
00302 } /* end of cuddZddFreeUniv */

int cuddZddGetCofactors2 ( DdManager dd,
DdNode f,
int  v,
DdNode **  f1,
DdNode **  f0 
)

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

Synopsis [Computes the two-way decomposition of f w.r.t. v.]

Description []

SideEffects [The results are returned in f1 and f0.]

SeeAlso [cuddZddGetCofactors3]

Definition at line 1483 of file cuddZddFuncs.c.

01489 {
01490     *f1 = cuddZddSubset1(dd, f, v);
01491     if (*f1 == NULL)
01492         return(1);
01493     *f0 = cuddZddSubset0(dd, f, v);
01494     if (*f0 == NULL) {
01495         Cudd_RecursiveDerefZdd(dd, *f1);
01496         return(1);
01497     }
01498     return(0);
01499 
01500 } /* end of cuddZddGetCofactors2 */

int cuddZddGetCofactors3 ( DdManager dd,
DdNode f,
int  v,
DdNode **  f1,
DdNode **  f0,
DdNode **  fd 
)

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

Synopsis [Computes the three-way decomposition of f w.r.t. v.]

Description [Computes the three-way decomposition of function f (represented by a ZDD) wit respect to variable v. Returns 0 if successful; 1 otherwise.]

SideEffects [The results are returned in f1, f0, and fd.]

SeeAlso [cuddZddGetCofactors2]

Definition at line 1356 of file cuddZddFuncs.c.

01363 {
01364     DdNode      *pc, *nc;
01365     DdNode      *zero = DD_ZERO(dd);
01366     int         top, hv, ht, pv, nv;
01367     int         level;
01368 
01369     top = dd->permZ[f->index];
01370     level = dd->permZ[v];
01371     hv = level >> 1;
01372     ht = top >> 1;
01373 
01374     if (hv < ht) {
01375         *f1 = zero;
01376         *f0 = zero;
01377         *fd = f;
01378     }
01379     else {
01380         pv = cuddZddGetPosVarIndex(dd, v);
01381         nv = cuddZddGetNegVarIndex(dd, v);
01382 
01383         /* not to create intermediate ZDD node */
01384         if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) {
01385             pc = cuddZddSubset1(dd, f, pv);
01386             if (pc == NULL)
01387                 return(1);
01388             Cudd_Ref(pc);
01389             nc = cuddZddSubset0(dd, f, pv);
01390             if (nc == NULL) {
01391                 Cudd_RecursiveDerefZdd(dd, pc);
01392                 return(1);
01393             }
01394             Cudd_Ref(nc);
01395 
01396             *f1 = cuddZddSubset0(dd, pc, nv);
01397             if (*f1 == NULL) {
01398                 Cudd_RecursiveDerefZdd(dd, pc);
01399                 Cudd_RecursiveDerefZdd(dd, nc);
01400                 return(1);
01401             }
01402             Cudd_Ref(*f1);
01403             *f0 = cuddZddSubset1(dd, nc, nv);
01404             if (*f0 == NULL) {
01405                 Cudd_RecursiveDerefZdd(dd, pc);
01406                 Cudd_RecursiveDerefZdd(dd, nc);
01407                 Cudd_RecursiveDerefZdd(dd, *f1);
01408                 return(1);
01409             }
01410             Cudd_Ref(*f0);
01411 
01412             *fd = cuddZddSubset0(dd, nc, nv);
01413             if (*fd == NULL) {
01414                 Cudd_RecursiveDerefZdd(dd, pc);
01415                 Cudd_RecursiveDerefZdd(dd, nc);
01416                 Cudd_RecursiveDerefZdd(dd, *f1);
01417                 Cudd_RecursiveDerefZdd(dd, *f0);
01418                 return(1);
01419             }
01420             Cudd_Ref(*fd);
01421         } else {
01422             pc = cuddZddSubset1(dd, f, nv);
01423             if (pc == NULL)
01424                 return(1);
01425             Cudd_Ref(pc);
01426             nc = cuddZddSubset0(dd, f, nv);
01427             if (nc == NULL) {
01428                 Cudd_RecursiveDerefZdd(dd, pc);
01429                 return(1);
01430             }
01431             Cudd_Ref(nc);
01432 
01433             *f0 = cuddZddSubset0(dd, pc, pv);
01434             if (*f0 == NULL) {
01435                 Cudd_RecursiveDerefZdd(dd, pc);
01436                 Cudd_RecursiveDerefZdd(dd, nc);
01437                 return(1);
01438             }
01439             Cudd_Ref(*f0);
01440             *f1 = cuddZddSubset1(dd, nc, pv);
01441             if (*f1 == NULL) {
01442                 Cudd_RecursiveDerefZdd(dd, pc);
01443                 Cudd_RecursiveDerefZdd(dd, nc);
01444                 Cudd_RecursiveDerefZdd(dd, *f0);
01445                 return(1);
01446             }
01447             Cudd_Ref(*f1);
01448 
01449             *fd = cuddZddSubset0(dd, nc, pv);
01450             if (*fd == NULL) {
01451                 Cudd_RecursiveDerefZdd(dd, pc);
01452                 Cudd_RecursiveDerefZdd(dd, nc);
01453                 Cudd_RecursiveDerefZdd(dd, *f1);
01454                 Cudd_RecursiveDerefZdd(dd, *f0);
01455                 return(1);
01456             }
01457             Cudd_Ref(*fd);
01458         }
01459 
01460         Cudd_RecursiveDerefZdd(dd, pc);
01461         Cudd_RecursiveDerefZdd(dd, nc);
01462         Cudd_Deref(*f1);
01463         Cudd_Deref(*f0);
01464         Cudd_Deref(*fd);
01465     }
01466     return(0);
01467 
01468 } /* end of cuddZddGetCofactors3 */

int cuddZddGetNegVarIndex ( DdManager dd,
int  index 
)

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

Synopsis [Returns the index of negative ZDD variable.]

Description [Returns the index of negative ZDD variable.]

SideEffects []

SeeAlso []

Definition at line 1582 of file cuddZddFuncs.c.

01585 {
01586     int nv = index | 0x1;
01587     return(nv);
01588 } /* end of cuddZddGetPosVarIndex */

int cuddZddGetNegVarLevel ( DdManager dd,
int  index 
)

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

Synopsis [Returns the level of negative ZDD variable.]

Description [Returns the level of negative ZDD variable.]

SideEffects []

SeeAlso []

Definition at line 1624 of file cuddZddFuncs.c.

01627 {
01628     int nv = cuddZddGetNegVarIndex(dd, index);
01629     return(dd->permZ[nv]);
01630 } /* end of cuddZddGetNegVarLevel */

DdNode* cuddZddGetNode ( DdManager zdd,
int  id,
DdNode T,
DdNode E 
)

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

Synopsis [Wrapper for cuddUniqueInterZdd.]

Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD reduction rule. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]

SideEffects [None]

SeeAlso [cuddUniqueInterZdd]

Definition at line 1028 of file cuddTable.c.

01033 {
01034     DdNode      *node;
01035 
01036     if (T == DD_ZERO(zdd))
01037         return(E);
01038     node = cuddUniqueInterZdd(zdd, id, T, E);
01039     return(node);
01040 
01041 } /* end of cuddZddGetNode */

DdNode* cuddZddGetNodeIVO ( DdManager dd,
int  index,
DdNode g,
DdNode h 
)

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

Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable ordering.]

Description [Wrapper for cuddUniqueInterZdd that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of g and h in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]

SideEffects [None]

SeeAlso [cuddZddGetNode cuddZddIsop]

Definition at line 1061 of file cuddTable.c.

01066 {
01067     DdNode      *f, *r, *t;
01068     DdNode      *zdd_one = DD_ONE(dd);
01069     DdNode      *zdd_zero = DD_ZERO(dd);
01070 
01071     f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero);
01072     if (f == NULL) {
01073         return(NULL);
01074     }
01075     cuddRef(f);
01076     t = cuddZddProduct(dd, f, g);
01077     if (t == NULL) {
01078         Cudd_RecursiveDerefZdd(dd, f);
01079         return(NULL);
01080     }
01081     cuddRef(t);
01082     Cudd_RecursiveDerefZdd(dd, f);
01083     r = cuddZddUnion(dd, t, h);
01084     if (r == NULL) {
01085         Cudd_RecursiveDerefZdd(dd, t);
01086         return(NULL);
01087     }
01088     cuddRef(r);
01089     Cudd_RecursiveDerefZdd(dd, t);
01090 
01091     cuddDeref(r);
01092     return(r);
01093 
01094 } /* end of cuddZddGetNodeIVO */

int cuddZddGetPosVarIndex ( DdManager dd,
int  index 
)

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

Synopsis [Returns the index of positive ZDD variable.]

Description [Returns the index of positive ZDD variable.]

SideEffects []

SeeAlso []

Definition at line 1561 of file cuddZddFuncs.c.

01564 {
01565     int pv = (index >> 1) << 1;
01566     return(pv);
01567 } /* end of cuddZddGetPosVarIndex */

int cuddZddGetPosVarLevel ( DdManager dd,
int  index 
)

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

Synopsis [Returns the level of positive ZDD variable.]

Description [Returns the level of positive ZDD variable.]

SideEffects []

SeeAlso []

Definition at line 1603 of file cuddZddFuncs.c.

01606 {
01607     int pv = cuddZddGetPosVarIndex(dd, index);
01608     return(dd->permZ[pv]);
01609 } /* end of cuddZddGetPosVarLevel */

int cuddZddInitUniv ( DdManager zdd  ) 

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

Synopsis [Initializes the ZDD universe.]

Description [Initializes the ZDD universe. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddFreeUniv]

Definition at line 245 of file cuddInit.c.

00247 {
00248     DdNode      *p, *res;
00249     int         i;
00250 
00251     zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ);
00252     if (zdd->univ == NULL) {
00253         zdd->errorCode = CUDD_MEMORY_OUT;
00254         return(0);
00255     }
00256 
00257     res = DD_ONE(zdd);
00258     cuddRef(res);
00259     for (i = zdd->sizeZ - 1; i >= 0; i--) {
00260         unsigned int index = zdd->invpermZ[i];
00261         p = res;
00262         res = cuddUniqueInterZdd(zdd, index, p, p);
00263         if (res == NULL) {
00264             Cudd_RecursiveDerefZdd(zdd,p);
00265             FREE(zdd->univ);
00266             return(0);
00267         }
00268         cuddRef(res);
00269         cuddDeref(p);
00270         zdd->univ[i] = res;
00271     }
00272 
00273 #ifdef DD_VERBOSE
00274     cuddZddP(zdd, zdd->univ[0]);
00275 #endif
00276 
00277     return(1);
00278 
00279 } /* end of cuddZddInitUniv */

DdNode* cuddZddIntersect ( DdManager zdd,
DdNode P,
DdNode Q 
)

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

Synopsis [Performs the recursive step of Cudd_zddIntersect.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 638 of file cuddZddSetop.c.

00642 {
00643     int         p_top, q_top;
00644     DdNode      *empty = DD_ZERO(zdd), *t, *e, *res;
00645     DdManager   *table = zdd;
00646 
00647     statLine(zdd);
00648     if (P == empty)
00649         return(empty);
00650     if (Q == empty)
00651         return(empty);
00652     if (P == Q)
00653         return(P);
00654 
00655     /* Check cache. */
00656     res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q);
00657     if (res != NULL)
00658         return(res);
00659 
00660     if (cuddIsConstant(P))
00661         p_top = P->index;
00662     else
00663         p_top = zdd->permZ[P->index];
00664     if (cuddIsConstant(Q))
00665         q_top = Q->index;
00666     else
00667         q_top = zdd->permZ[Q->index];
00668     if (p_top < q_top) {
00669         res = cuddZddIntersect(zdd, cuddE(P), Q);
00670         if (res == NULL) return(NULL);
00671     } else if (p_top > q_top) {
00672         res = cuddZddIntersect(zdd, P, cuddE(Q));
00673         if (res == NULL) return(NULL);
00674     } else {
00675         t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q));
00676         if (t == NULL) return(NULL);
00677         cuddRef(t);
00678         e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q));
00679         if (e == NULL) {
00680             Cudd_RecursiveDerefZdd(table, t);
00681             return(NULL);
00682         }
00683         cuddRef(e);
00684         res = cuddZddGetNode(zdd, P->index, t, e);
00685         if (res == NULL) {
00686             Cudd_RecursiveDerefZdd(table, t);
00687             Cudd_RecursiveDerefZdd(table, e);
00688             return(NULL);
00689         }
00690         cuddDeref(t);
00691         cuddDeref(e);
00692     }
00693 
00694     cuddCacheInsert2(table, cuddZddIntersect, P, Q, res);
00695 
00696     return(res);
00697 
00698 } /* end of cuddZddIntersect */

DdNode* cuddZddIsop ( DdManager dd,
DdNode L,
DdNode U,
DdNode **  zdd_I 
)

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

Synopsis [Performs the recursive step of Cudd_zddIsop.]

Description []

SideEffects [None]

SeeAlso [Cudd_zddIsop]

Definition at line 230 of file cuddZddIsop.c.

00235 {
00236     DdNode      *one = DD_ONE(dd);
00237     DdNode      *zero = Cudd_Not(one);
00238     DdNode      *zdd_one = DD_ONE(dd);
00239     DdNode      *zdd_zero = DD_ZERO(dd);
00240     int         v, top_l, top_u;
00241     DdNode      *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
00242     DdNode      *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
00243     DdNode      *Isub0, *Isub1, *Id;
00244     DdNode      *zdd_Isub0, *zdd_Isub1, *zdd_Id;
00245     DdNode      *x;
00246     DdNode      *term0, *term1, *sum;
00247     DdNode      *Lv, *Uv, *Lnv, *Unv;
00248     DdNode      *r, *y, *z;
00249     int         index;
00250     DD_CTFP     cacheOp;
00251 
00252     statLine(dd);
00253     if (L == zero) {
00254         *zdd_I = zdd_zero;
00255         return(zero);
00256     }
00257     if (U == one) {
00258         *zdd_I = zdd_one;
00259         return(one);
00260     }
00261 
00262     if (U == zero || L == one) {
00263         printf("*** ERROR : illegal condition for ISOP (U < L).\n");
00264         exit(1);
00265     }
00266 
00267     /* Check the cache. We store two results for each recursive call.
00268     ** One is the BDD, and the other is the ZDD. Both are needed.
00269     ** Hence we need a double hit in the cache to terminate the
00270     ** recursion. Clearly, collisions may evict only one of the two
00271     ** results. */
00272     cacheOp = (DD_CTFP) cuddZddIsop;
00273     r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
00274     if (r) {
00275         *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
00276         if (*zdd_I)
00277             return(r);
00278         else {
00279             /* The BDD result may have been dead. In that case
00280             ** cuddCacheLookup2 would have called cuddReclaim,
00281             ** whose effects we now have to undo. */
00282             cuddRef(r);
00283             Cudd_RecursiveDeref(dd, r);
00284         }
00285     }
00286 
00287     top_l = dd->perm[Cudd_Regular(L)->index];
00288     top_u = dd->perm[Cudd_Regular(U)->index];
00289     v = ddMin(top_l, top_u);
00290 
00291     /* Compute cofactors. */
00292     if (top_l == v) {
00293         index = Cudd_Regular(L)->index;
00294         Lv = Cudd_T(L);
00295         Lnv = Cudd_E(L);
00296         if (Cudd_IsComplement(L)) {
00297             Lv = Cudd_Not(Lv);
00298             Lnv = Cudd_Not(Lnv);
00299         }
00300     }
00301     else {
00302         index = Cudd_Regular(U)->index;
00303         Lv = Lnv = L;
00304     }
00305 
00306     if (top_u == v) {
00307         Uv = Cudd_T(U);
00308         Unv = Cudd_E(U);
00309         if (Cudd_IsComplement(U)) {
00310             Uv = Cudd_Not(Uv);
00311             Unv = Cudd_Not(Unv);
00312         }
00313     }
00314     else {
00315         Uv = Unv = U;
00316     }
00317 
00318     Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
00319     if (Lsub0 == NULL)
00320         return(NULL);
00321     Cudd_Ref(Lsub0);
00322     Usub0 = Unv;
00323     Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
00324     if (Lsub1 == NULL) {
00325         Cudd_RecursiveDeref(dd, Lsub0);
00326         return(NULL);
00327     }
00328     Cudd_Ref(Lsub1);
00329     Usub1 = Uv;
00330 
00331     Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
00332     if (Isub0 == NULL) {
00333         Cudd_RecursiveDeref(dd, Lsub0);
00334         Cudd_RecursiveDeref(dd, Lsub1);
00335         return(NULL);
00336     }
00337     /*
00338     if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
00339         (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
00340         dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
00341         printf("*** ERROR : illegal permutation in ZDD. ***\n");
00342     }
00343     */
00344     Cudd_Ref(Isub0);
00345     Cudd_Ref(zdd_Isub0);
00346     Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
00347     if (Isub1 == NULL) {
00348         Cudd_RecursiveDeref(dd, Lsub0);
00349         Cudd_RecursiveDeref(dd, Lsub1);
00350         Cudd_RecursiveDeref(dd, Isub0);
00351         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00352         return(NULL);
00353     }
00354     /*
00355     if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
00356         (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
00357         dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
00358         printf("*** ERROR : illegal permutation in ZDD. ***\n");
00359     }
00360     */
00361     Cudd_Ref(Isub1);
00362     Cudd_Ref(zdd_Isub1);
00363     Cudd_RecursiveDeref(dd, Lsub0);
00364     Cudd_RecursiveDeref(dd, Lsub1);
00365 
00366     Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
00367     if (Lsuper0 == NULL) {
00368         Cudd_RecursiveDeref(dd, Isub0);
00369         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00370         Cudd_RecursiveDeref(dd, Isub1);
00371         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00372         return(NULL);
00373     }
00374     Cudd_Ref(Lsuper0);
00375     Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
00376     if (Lsuper1 == NULL) {
00377         Cudd_RecursiveDeref(dd, Isub0);
00378         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00379         Cudd_RecursiveDeref(dd, Isub1);
00380         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00381         Cudd_RecursiveDeref(dd, Lsuper0);
00382         return(NULL);
00383     }
00384     Cudd_Ref(Lsuper1);
00385     Usuper0 = Unv;
00386     Usuper1 = Uv;
00387 
00388     /* Ld = Lsuper0 + Lsuper1 */
00389     Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
00390     if (Ld == NULL) {
00391         Cudd_RecursiveDeref(dd, Isub0);
00392         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00393         Cudd_RecursiveDeref(dd, Isub1);
00394         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00395         Cudd_RecursiveDeref(dd, Lsuper0);
00396         Cudd_RecursiveDeref(dd, Lsuper1);
00397         return(NULL);
00398     }
00399     Ld = Cudd_Not(Ld);
00400     Cudd_Ref(Ld);
00401     /* Ud = Usuper0 * Usuper1 */
00402     Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
00403     if (Ud == NULL) {
00404         Cudd_RecursiveDeref(dd, Isub0);
00405         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00406         Cudd_RecursiveDeref(dd, Isub1);
00407         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00408         Cudd_RecursiveDeref(dd, Lsuper0);
00409         Cudd_RecursiveDeref(dd, Lsuper1);
00410         Cudd_RecursiveDeref(dd, Ld);
00411         return(NULL);
00412     }
00413     Cudd_Ref(Ud);
00414     Cudd_RecursiveDeref(dd, Lsuper0);
00415     Cudd_RecursiveDeref(dd, Lsuper1);
00416 
00417     Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
00418     if (Id == NULL) {
00419         Cudd_RecursiveDeref(dd, Isub0);
00420         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00421         Cudd_RecursiveDeref(dd, Isub1);
00422         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00423         Cudd_RecursiveDeref(dd, Ld);
00424         Cudd_RecursiveDeref(dd, Ud);
00425         return(NULL);
00426     }
00427     /*
00428     if ((!cuddIsConstant(Cudd_Regular(Id))) &&
00429         (Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
00430         dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
00431         printf("*** ERROR : illegal permutation in ZDD. ***\n");
00432     }
00433     */
00434     Cudd_Ref(Id);
00435     Cudd_Ref(zdd_Id);
00436     Cudd_RecursiveDeref(dd, Ld);
00437     Cudd_RecursiveDeref(dd, Ud);
00438 
00439     x = cuddUniqueInter(dd, index, one, zero);
00440     if (x == NULL) {
00441         Cudd_RecursiveDeref(dd, Isub0);
00442         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00443         Cudd_RecursiveDeref(dd, Isub1);
00444         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00445         Cudd_RecursiveDeref(dd, Id);
00446         Cudd_RecursiveDerefZdd(dd, zdd_Id);
00447         return(NULL);
00448     }
00449     Cudd_Ref(x);
00450     /* term0 = x * Isub0 */
00451     term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
00452     if (term0 == NULL) {
00453         Cudd_RecursiveDeref(dd, Isub0);
00454         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00455         Cudd_RecursiveDeref(dd, Isub1);
00456         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00457         Cudd_RecursiveDeref(dd, Id);
00458         Cudd_RecursiveDerefZdd(dd, zdd_Id);
00459         Cudd_RecursiveDeref(dd, x);
00460         return(NULL);
00461     }
00462     Cudd_Ref(term0);
00463     Cudd_RecursiveDeref(dd, Isub0);
00464     /* term1 = x * Isub1 */
00465     term1 = cuddBddAndRecur(dd, x, Isub1);
00466     if (term1 == NULL) {
00467         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00468         Cudd_RecursiveDeref(dd, Isub1);
00469         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00470         Cudd_RecursiveDeref(dd, Id);
00471         Cudd_RecursiveDerefZdd(dd, zdd_Id);
00472         Cudd_RecursiveDeref(dd, x);
00473         Cudd_RecursiveDeref(dd, term0);
00474         return(NULL);
00475     }
00476     Cudd_Ref(term1);
00477     Cudd_RecursiveDeref(dd, x);
00478     Cudd_RecursiveDeref(dd, Isub1);
00479     /* sum = term0 + term1 */
00480     sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
00481     if (sum == NULL) {
00482         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00483         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00484         Cudd_RecursiveDeref(dd, Id);
00485         Cudd_RecursiveDerefZdd(dd, zdd_Id);
00486         Cudd_RecursiveDeref(dd, term0);
00487         Cudd_RecursiveDeref(dd, term1);
00488         return(NULL);
00489     }
00490     sum = Cudd_Not(sum);
00491     Cudd_Ref(sum);
00492     Cudd_RecursiveDeref(dd, term0);
00493     Cudd_RecursiveDeref(dd, term1);
00494     /* r = sum + Id */
00495     r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
00496     r = Cudd_NotCond(r, r != NULL);
00497     if (r == NULL) {
00498         Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00499         Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00500         Cudd_RecursiveDeref(dd, Id);
00501         Cudd_RecursiveDerefZdd(dd, zdd_Id);
00502         Cudd_RecursiveDeref(dd, sum);
00503         return(NULL);
00504     }
00505     Cudd_Ref(r);
00506     Cudd_RecursiveDeref(dd, sum);
00507     Cudd_RecursiveDeref(dd, Id);
00508 
00509     if (zdd_Isub0 != zdd_zero) {
00510         z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
00511         if (z == NULL) {
00512             Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00513             Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00514             Cudd_RecursiveDerefZdd(dd, zdd_Id);
00515             Cudd_RecursiveDeref(dd, r);
00516             return(NULL);
00517         }
00518     }
00519     else {
00520         z = zdd_Id;
00521     }
00522     Cudd_Ref(z);
00523     if (zdd_Isub1 != zdd_zero) {
00524         y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
00525         if (y == NULL) {
00526             Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00527             Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00528             Cudd_RecursiveDerefZdd(dd, zdd_Id);
00529             Cudd_RecursiveDeref(dd, r);
00530             Cudd_RecursiveDerefZdd(dd, z);
00531             return(NULL);
00532         }
00533     }
00534     else
00535         y = z;
00536     Cudd_Ref(y);
00537 
00538     Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
00539     Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
00540     Cudd_RecursiveDerefZdd(dd, zdd_Id);
00541     Cudd_RecursiveDerefZdd(dd, z);
00542 
00543     cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
00544     cuddCacheInsert2(dd, cacheOp, L, U, y);
00545 
00546     Cudd_Deref(r);
00547     Cudd_Deref(y);
00548     *zdd_I = y;
00549     /*
00550     if (Cudd_Regular(r)->index != y->index / 2) {
00551         printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
00552     }
00553     */
00554     return(r);
00555 
00556 } /* end of cuddZddIsop */

DdNode* cuddZddIte ( DdManager dd,
DdNode f,
DdNode g,
DdNode h 
)

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

Synopsis [Performs the recursive step of Cudd_zddIte.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 423 of file cuddZddSetop.c.

00428 {
00429     DdNode *tautology, *empty;
00430     DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e;
00431     unsigned int topf,topg,toph,v,top;
00432     int index;
00433 
00434     statLine(dd);
00435     /* Trivial cases. */
00436     /* One variable cases. */
00437     if (f == (empty = DD_ZERO(dd))) {   /* ITE(0,G,H) = H */
00438         return(h);
00439     }
00440     topf = cuddIZ(dd,f->index);
00441     topg = cuddIZ(dd,g->index);
00442     toph = cuddIZ(dd,h->index);
00443     v = ddMin(topg,toph);
00444     top  = ddMin(topf,v);
00445 
00446     tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top];
00447     if (f == tautology) {                       /* ITE(1,G,H) = G */
00448         return(g);
00449     }
00450 
00451     /* From now on, f is known to not be a constant. */
00452     zddVarToConst(f,&g,&h,tautology,empty);
00453 
00454     /* Check remaining one variable cases. */
00455     if (g == h) {                       /* ITE(F,G,G) = G */
00456         return(g);
00457     }
00458 
00459     if (g == tautology) {                       /* ITE(F,1,0) = F */
00460         if (h == empty) return(f);
00461     }
00462 
00463     /* Check cache. */
00464     r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h);
00465     if (r != NULL) {
00466         return(r);
00467     }
00468 
00469     /* Recompute these because they may have changed in zddVarToConst. */
00470     topg = cuddIZ(dd,g->index);
00471     toph = cuddIZ(dd,h->index);
00472     v = ddMin(topg,toph);
00473 
00474     if (topf < v) {
00475         r = cuddZddIte(dd,cuddE(f),g,h);
00476         if (r == NULL) return(NULL);
00477     } else if (topf > v) {
00478         if (topg > v) {
00479             Gvn = g;
00480             index = h->index;
00481         } else {
00482             Gvn = cuddE(g);
00483             index = g->index;
00484         }
00485         if (toph > v) {
00486             Hv = empty; Hvn = h;
00487         } else {
00488             Hv = cuddT(h); Hvn = cuddE(h);
00489         }
00490         e = cuddZddIte(dd,f,Gvn,Hvn);
00491         if (e == NULL) return(NULL);
00492         cuddRef(e);
00493         r = cuddZddGetNode(dd,index,Hv,e);
00494         if (r == NULL) {
00495             Cudd_RecursiveDerefZdd(dd,e);
00496             return(NULL);
00497         }
00498         cuddDeref(e);
00499     } else {
00500         index = f->index;
00501         if (topg > v) {
00502             Gv = empty; Gvn = g;
00503         } else {
00504             Gv = cuddT(g); Gvn = cuddE(g);
00505         }
00506         if (toph > v) {
00507             Hv = empty; Hvn = h;
00508         } else {
00509             Hv = cuddT(h); Hvn = cuddE(h);
00510         }
00511         e = cuddZddIte(dd,cuddE(f),Gvn,Hvn);
00512         if (e == NULL) return(NULL);
00513         cuddRef(e);
00514         t = cuddZddIte(dd,cuddT(f),Gv,Hv);
00515         if (t == NULL) {
00516             Cudd_RecursiveDerefZdd(dd,e);
00517             return(NULL);
00518         }
00519         cuddRef(t);
00520         r = cuddZddGetNode(dd,index,t,e);
00521         if (r == NULL) {
00522             Cudd_RecursiveDerefZdd(dd,e);
00523             Cudd_RecursiveDerefZdd(dd,t);
00524             return(NULL);
00525         }
00526         cuddDeref(t);
00527         cuddDeref(e);
00528     }
00529 
00530     cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r);
00531 
00532     return(r);
00533 
00534 } /* end of cuddZddIte */

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

00156 {
00157     int i;
00158     int *var;
00159     int size;
00160     int x;
00161     int result;
00162 #ifdef DD_STATS
00163     int previousSize;
00164 #endif
00165 
00166     size = table->sizeZ;
00167     empty = table->zero;
00168 
00169     /* Find order in which to sift variables. */
00170     var = NULL;
00171     zdd_entry = ALLOC(int, size);
00172     if (zdd_entry == NULL) {
00173         table->errorCode = CUDD_MEMORY_OUT;
00174         goto cuddZddSiftingOutOfMem;
00175     }
00176     var = ALLOC(int, size);
00177     if (var == NULL) {
00178         table->errorCode = CUDD_MEMORY_OUT;
00179         goto cuddZddSiftingOutOfMem;
00180     }
00181 
00182     for (i = 0; i < size; i++) {
00183         x = table->permZ[i];
00184         zdd_entry[i] = table->subtableZ[x].keys;
00185         var[i] = i;
00186     }
00187 
00188     qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00189 
00190     /* Now sift. */
00191     for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
00192         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00193             break;
00194         x = table->permZ[var[i]];
00195         if (x < lower || x > upper) continue;
00196 #ifdef DD_STATS
00197         previousSize = table->keysZ;
00198 #endif
00199         result = cuddZddLinearAux(table, x, lower, upper);
00200         if (!result)
00201             goto cuddZddSiftingOutOfMem;
00202 #ifdef DD_STATS
00203         if (table->keysZ < (unsigned) previousSize) {
00204             (void) fprintf(table->out,"-");
00205         } else if (table->keysZ > (unsigned) previousSize) {
00206             (void) fprintf(table->out,"+");     /* should never happen */
00207             (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
00208         } else {
00209             (void) fprintf(table->out,"=");
00210         }
00211         fflush(table->out);
00212 #endif
00213     }
00214 
00215     FREE(var);
00216     FREE(zdd_entry);
00217 
00218     return(1);
00219 
00220 cuddZddSiftingOutOfMem:
00221 
00222     if (zdd_entry != NULL) FREE(zdd_entry);
00223     if (var != NULL) FREE(var);
00224 
00225     return(0);
00226 
00227 } /* end of cuddZddLinearSifting */

int cuddZddNextHigh ( DdManager table,
int  x 
)

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

Synopsis [Finds the next subtable with a larger index.]

Description [Finds the next subtable with a larger index. Returns the index.]

SideEffects [None]

SeeAlso []

Definition at line 409 of file cuddZddReord.c.

00412 {
00413     return(x + 1);
00414 
00415 } /* end of cuddZddNextHigh */

int cuddZddNextLow ( DdManager table,
int  x 
)

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

Synopsis [Finds the next subtable with a smaller index.]

Description [Finds the next subtable with a smaller index. Returns the index.]

SideEffects [None]

SeeAlso []

Definition at line 431 of file cuddZddReord.c.

00434 {
00435     return(x - 1);
00436 
00437 } /* end of cuddZddNextLow */

int cuddZddP ( DdManager zdd,
DdNode f 
)

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

Synopsis [Prints a ZDD to the standard output. One line per node is printed.]

Description [Prints a ZDD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [Cudd_zddPrintDebug]

Definition at line 818 of file cuddZddUtil.c.

00821 {
00822     int retval;
00823     st_table *table = st_init_table(st_ptrcmp, st_ptrhash);
00824 
00825     if (table == NULL) return(0);
00826 
00827     retval = zp2(zdd, f, table);
00828     st_free_table(table);
00829     (void) fputc('\n', zdd->out);
00830     return(retval);
00831 
00832 } /* end of cuddZddP */

DdNode* cuddZddProduct ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_zddProduct.]

Description []

SideEffects [None]

SeeAlso [Cudd_zddProduct]

Definition at line 376 of file cuddZddFuncs.c.

00380 {
00381     int         v, top_f, top_g;
00382     DdNode      *tmp, *term1, *term2, *term3;
00383     DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
00384     DdNode      *R0, *R1, *Rd, *N0, *N1;
00385     DdNode      *r;
00386     DdNode      *one = DD_ONE(dd);
00387     DdNode      *zero = DD_ZERO(dd);
00388     int         flag;
00389     int         pv, nv;
00390 
00391     statLine(dd);
00392     if (f == zero || g == zero)
00393         return(zero);
00394     if (f == one)
00395         return(g);
00396     if (g == one)
00397         return(f);
00398 
00399     top_f = dd->permZ[f->index];
00400     top_g = dd->permZ[g->index];
00401 
00402     if (top_f > top_g)
00403         return(cuddZddProduct(dd, g, f));
00404 
00405     /* Check cache */
00406     r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g);
00407     if (r)
00408         return(r);
00409 
00410     v = f->index;       /* either yi or zi */
00411     flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
00412     if (flag == 1)
00413         return(NULL);
00414     Cudd_Ref(f1);
00415     Cudd_Ref(f0);
00416     Cudd_Ref(fd);
00417     flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
00418     if (flag == 1) {
00419         Cudd_RecursiveDerefZdd(dd, f1);
00420         Cudd_RecursiveDerefZdd(dd, f0);
00421         Cudd_RecursiveDerefZdd(dd, fd);
00422         return(NULL);
00423     }
00424     Cudd_Ref(g1);
00425     Cudd_Ref(g0);
00426     Cudd_Ref(gd);
00427     pv = cuddZddGetPosVarIndex(dd, v);
00428     nv = cuddZddGetNegVarIndex(dd, v);
00429 
00430     Rd = cuddZddProduct(dd, fd, gd);
00431     if (Rd == NULL) {
00432         Cudd_RecursiveDerefZdd(dd, f1);
00433         Cudd_RecursiveDerefZdd(dd, f0);
00434         Cudd_RecursiveDerefZdd(dd, fd);
00435         Cudd_RecursiveDerefZdd(dd, g1);
00436         Cudd_RecursiveDerefZdd(dd, g0);
00437         Cudd_RecursiveDerefZdd(dd, gd);
00438         return(NULL);
00439     }
00440     Cudd_Ref(Rd);
00441 
00442     term1 = cuddZddProduct(dd, f0, g0);
00443     if (term1 == NULL) {
00444         Cudd_RecursiveDerefZdd(dd, f1);
00445         Cudd_RecursiveDerefZdd(dd, f0);
00446         Cudd_RecursiveDerefZdd(dd, fd);
00447         Cudd_RecursiveDerefZdd(dd, g1);
00448         Cudd_RecursiveDerefZdd(dd, g0);
00449         Cudd_RecursiveDerefZdd(dd, gd);
00450         Cudd_RecursiveDerefZdd(dd, Rd);
00451         return(NULL);
00452     }
00453     Cudd_Ref(term1);
00454     term2 = cuddZddProduct(dd, f0, gd);
00455     if (term2 == NULL) {
00456         Cudd_RecursiveDerefZdd(dd, f1);
00457         Cudd_RecursiveDerefZdd(dd, f0);
00458         Cudd_RecursiveDerefZdd(dd, fd);
00459         Cudd_RecursiveDerefZdd(dd, g1);
00460         Cudd_RecursiveDerefZdd(dd, g0);
00461         Cudd_RecursiveDerefZdd(dd, gd);
00462         Cudd_RecursiveDerefZdd(dd, Rd);
00463         Cudd_RecursiveDerefZdd(dd, term1);
00464         return(NULL);
00465     }
00466     Cudd_Ref(term2);
00467     term3 = cuddZddProduct(dd, fd, g0);
00468     if (term3 == NULL) {
00469         Cudd_RecursiveDerefZdd(dd, f1);
00470         Cudd_RecursiveDerefZdd(dd, f0);
00471         Cudd_RecursiveDerefZdd(dd, fd);
00472         Cudd_RecursiveDerefZdd(dd, g1);
00473         Cudd_RecursiveDerefZdd(dd, g0);
00474         Cudd_RecursiveDerefZdd(dd, gd);
00475         Cudd_RecursiveDerefZdd(dd, Rd);
00476         Cudd_RecursiveDerefZdd(dd, term1);
00477         Cudd_RecursiveDerefZdd(dd, term2);
00478         return(NULL);
00479     }
00480     Cudd_Ref(term3);
00481     Cudd_RecursiveDerefZdd(dd, f0);
00482     Cudd_RecursiveDerefZdd(dd, g0);
00483     tmp = cuddZddUnion(dd, term1, term2);
00484     if (tmp == NULL) {
00485         Cudd_RecursiveDerefZdd(dd, f1);
00486         Cudd_RecursiveDerefZdd(dd, fd);
00487         Cudd_RecursiveDerefZdd(dd, g1);
00488         Cudd_RecursiveDerefZdd(dd, gd);
00489         Cudd_RecursiveDerefZdd(dd, Rd);
00490         Cudd_RecursiveDerefZdd(dd, term1);
00491         Cudd_RecursiveDerefZdd(dd, term2);
00492         Cudd_RecursiveDerefZdd(dd, term3);
00493         return(NULL);
00494     }
00495     Cudd_Ref(tmp);
00496     Cudd_RecursiveDerefZdd(dd, term1);
00497     Cudd_RecursiveDerefZdd(dd, term2);
00498     R0 = cuddZddUnion(dd, tmp, term3);
00499     if (R0 == NULL) {
00500         Cudd_RecursiveDerefZdd(dd, f1);
00501         Cudd_RecursiveDerefZdd(dd, fd);
00502         Cudd_RecursiveDerefZdd(dd, g1);
00503         Cudd_RecursiveDerefZdd(dd, gd);
00504         Cudd_RecursiveDerefZdd(dd, Rd);
00505         Cudd_RecursiveDerefZdd(dd, term3);
00506         Cudd_RecursiveDerefZdd(dd, tmp);
00507         return(NULL);
00508     }
00509     Cudd_Ref(R0);
00510     Cudd_RecursiveDerefZdd(dd, tmp);
00511     Cudd_RecursiveDerefZdd(dd, term3);
00512     N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */
00513     if (N0 == NULL) {
00514         Cudd_RecursiveDerefZdd(dd, f1);
00515         Cudd_RecursiveDerefZdd(dd, fd);
00516         Cudd_RecursiveDerefZdd(dd, g1);
00517         Cudd_RecursiveDerefZdd(dd, gd);
00518         Cudd_RecursiveDerefZdd(dd, Rd);
00519         Cudd_RecursiveDerefZdd(dd, R0);
00520         return(NULL);
00521     }
00522     Cudd_Ref(N0);
00523     Cudd_RecursiveDerefZdd(dd, R0);
00524     Cudd_RecursiveDerefZdd(dd, Rd);
00525 
00526     term1 = cuddZddProduct(dd, f1, g1);
00527     if (term1 == NULL) {
00528         Cudd_RecursiveDerefZdd(dd, f1);
00529         Cudd_RecursiveDerefZdd(dd, fd);
00530         Cudd_RecursiveDerefZdd(dd, g1);
00531         Cudd_RecursiveDerefZdd(dd, gd);
00532         Cudd_RecursiveDerefZdd(dd, N0);
00533         return(NULL);
00534     }
00535     Cudd_Ref(term1);
00536     term2 = cuddZddProduct(dd, f1, gd);
00537     if (term2 == NULL) {
00538         Cudd_RecursiveDerefZdd(dd, f1);
00539         Cudd_RecursiveDerefZdd(dd, fd);
00540         Cudd_RecursiveDerefZdd(dd, g1);
00541         Cudd_RecursiveDerefZdd(dd, gd);
00542         Cudd_RecursiveDerefZdd(dd, N0);
00543         Cudd_RecursiveDerefZdd(dd, term1);
00544         return(NULL);
00545     }
00546     Cudd_Ref(term2);
00547     term3 = cuddZddProduct(dd, fd, g1);
00548     if (term3 == NULL) {
00549         Cudd_RecursiveDerefZdd(dd, f1);
00550         Cudd_RecursiveDerefZdd(dd, fd);
00551         Cudd_RecursiveDerefZdd(dd, g1);
00552         Cudd_RecursiveDerefZdd(dd, gd);
00553         Cudd_RecursiveDerefZdd(dd, N0);
00554         Cudd_RecursiveDerefZdd(dd, term1);
00555         Cudd_RecursiveDerefZdd(dd, term2);
00556         return(NULL);
00557     }
00558     Cudd_Ref(term3);
00559     Cudd_RecursiveDerefZdd(dd, f1);
00560     Cudd_RecursiveDerefZdd(dd, g1);
00561     Cudd_RecursiveDerefZdd(dd, fd);
00562     Cudd_RecursiveDerefZdd(dd, gd);
00563     tmp = cuddZddUnion(dd, term1, term2);
00564     if (tmp == NULL) {
00565         Cudd_RecursiveDerefZdd(dd, N0);
00566         Cudd_RecursiveDerefZdd(dd, term1);
00567         Cudd_RecursiveDerefZdd(dd, term2);
00568         Cudd_RecursiveDerefZdd(dd, term3);
00569         return(NULL);
00570     }
00571     Cudd_Ref(tmp);
00572     Cudd_RecursiveDerefZdd(dd, term1);
00573     Cudd_RecursiveDerefZdd(dd, term2);
00574     R1 = cuddZddUnion(dd, tmp, term3);
00575     if (R1 == NULL) {
00576         Cudd_RecursiveDerefZdd(dd, N0);
00577         Cudd_RecursiveDerefZdd(dd, term3);
00578         Cudd_RecursiveDerefZdd(dd, tmp);
00579         return(NULL);
00580     }
00581     Cudd_Ref(R1);
00582     Cudd_RecursiveDerefZdd(dd, tmp);
00583     Cudd_RecursiveDerefZdd(dd, term3);
00584     N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */
00585     if (N1 == NULL) {
00586         Cudd_RecursiveDerefZdd(dd, N0);
00587         Cudd_RecursiveDerefZdd(dd, R1);
00588         return(NULL);
00589     }
00590     Cudd_Ref(N1);
00591     Cudd_RecursiveDerefZdd(dd, R1);
00592     Cudd_RecursiveDerefZdd(dd, N0);
00593 
00594     cuddCacheInsert2(dd, cuddZddProduct, f, g, N1);
00595     Cudd_Deref(N1);
00596     return(N1);
00597 
00598 } /* end of cuddZddProduct */

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

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

Synopsis [Implementation of Rudell's sifting algorithm.]

Description [Implementation of Rudell's sifting algorithm. 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.
  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 863 of file cuddZddReord.c.

00867 {
00868     int i;
00869     int *var;
00870     int size;
00871     int x;
00872     int result;
00873 #ifdef DD_STATS
00874     int previousSize;
00875 #endif
00876 
00877     size = table->sizeZ;
00878 
00879     /* Find order in which to sift variables. */
00880     var = NULL;
00881     zdd_entry = ALLOC(int, size);
00882     if (zdd_entry == NULL) {
00883         table->errorCode = CUDD_MEMORY_OUT;
00884         goto cuddZddSiftingOutOfMem;
00885     }
00886     var = ALLOC(int, size);
00887     if (var == NULL) {
00888         table->errorCode = CUDD_MEMORY_OUT;
00889         goto cuddZddSiftingOutOfMem;
00890     }
00891 
00892     for (i = 0; i < size; i++) {
00893         x = table->permZ[i];
00894         zdd_entry[i] = table->subtableZ[x].keys;
00895         var[i] = i;
00896     }
00897 
00898     qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00899 
00900     /* Now sift. */
00901     for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
00902         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00903             break;
00904         x = table->permZ[var[i]];
00905         if (x < lower || x > upper) continue;
00906 #ifdef DD_STATS
00907         previousSize = table->keysZ;
00908 #endif
00909         result = cuddZddSiftingAux(table, x, lower, upper);
00910         if (!result)
00911             goto cuddZddSiftingOutOfMem;
00912 #ifdef DD_STATS
00913         if (table->keysZ < (unsigned) previousSize) {
00914             (void) fprintf(table->out,"-");
00915         } else if (table->keysZ > (unsigned) previousSize) {
00916             (void) fprintf(table->out,"+");     /* should never happen */
00917             (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
00918         } else {
00919             (void) fprintf(table->out,"=");
00920         }
00921         fflush(table->out);
00922 #endif
00923     }
00924 
00925     FREE(var);
00926     FREE(zdd_entry);
00927 
00928     return(1);
00929 
00930 cuddZddSiftingOutOfMem:
00931 
00932     if (zdd_entry != NULL) FREE(zdd_entry);
00933     if (var != NULL) FREE(var);
00934 
00935     return(0);
00936 
00937 } /* end of cuddZddSifting */

DdNode* cuddZddSubset0 ( DdManager dd,
DdNode P,
int  var 
)

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

Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]

Description [Computes the negative cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is negated. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset0 performs the same function as Cudd_zddSubset0, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.]

SideEffects [None]

SeeAlso [cuddZddSubset1 Cudd_zddSubset0]

Definition at line 919 of file cuddZddSetop.c.

00923 {
00924     DdNode      *zvar, *r;
00925     DdNode      *base, *empty;
00926 
00927     base = DD_ONE(dd);
00928     empty = DD_ZERO(dd);
00929 
00930     zvar = cuddUniqueInterZdd(dd, var, base, empty);
00931     if (zvar == NULL) {
00932         return(NULL);
00933     } else {
00934         cuddRef(zvar);
00935         r = zdd_subset0_aux(dd, P, zvar);
00936         if (r == NULL) {
00937             Cudd_RecursiveDerefZdd(dd, zvar);
00938             return(NULL);
00939         }
00940         cuddRef(r);
00941         Cudd_RecursiveDerefZdd(dd, zvar);
00942     }
00943 
00944     cuddDeref(r);
00945     return(r);
00946 
00947 } /* end of cuddZddSubset0 */

DdNode* cuddZddSubset1 ( DdManager dd,
DdNode P,
int  var 
)

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

Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]

Description [Computes the positive cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is asserted. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset1 performs the same function as Cudd_zddSubset1, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.]

SideEffects [None]

SeeAlso [cuddZddSubset0 Cudd_zddSubset1]

Definition at line 870 of file cuddZddSetop.c.

00874 {
00875     DdNode      *zvar, *r;
00876     DdNode      *base, *empty;
00877 
00878     base = DD_ONE(dd);
00879     empty = DD_ZERO(dd);
00880 
00881     zvar = cuddUniqueInterZdd(dd, var, base, empty);
00882     if (zvar == NULL) {
00883         return(NULL);
00884     } else {
00885         cuddRef(zvar);
00886         r = zdd_subset1_aux(dd, P, zvar);
00887         if (r == NULL) {
00888             Cudd_RecursiveDerefZdd(dd, zvar);
00889             return(NULL);
00890         }
00891         cuddRef(r);
00892         Cudd_RecursiveDerefZdd(dd, zvar);
00893     }
00894 
00895     cuddDeref(r);
00896     return(r);
00897 
00898 } /* end of cuddZddSubset1 */

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

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

Synopsis [Swaps two adjacent variables.]

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

SideEffects [None]

SeeAlso []

Definition at line 480 of file cuddZddReord.c.

00484 {
00485     DdNodePtr   *xlist, *ylist;
00486     int         xindex, yindex;
00487     int         xslots, yslots;
00488     int         xshift, yshift;
00489     int         oldxkeys, oldykeys;
00490     int         newxkeys, newykeys;
00491     int         i;
00492     int         posn;
00493     DdNode      *f, *f1, *f0, *f11, *f10, *f01, *f00;
00494     DdNode      *newf1, *newf0, *next;
00495     DdNodePtr   g, *lastP, *previousP;
00496 
00497 #ifdef DD_DEBUG
00498     assert(x < y);
00499     assert(cuddZddNextHigh(table,x) == y);
00500     assert(table->subtableZ[x].keys != 0);
00501     assert(table->subtableZ[y].keys != 0);
00502     assert(table->subtableZ[x].dead == 0);
00503     assert(table->subtableZ[y].dead == 0);
00504 #endif
00505 
00506     zddTotalNumberSwapping++;
00507 
00508     /* Get parameters of x subtable. */
00509     xindex   = table->invpermZ[x];
00510     xlist    = table->subtableZ[x].nodelist;
00511     oldxkeys = table->subtableZ[x].keys;
00512     xslots   = table->subtableZ[x].slots;
00513     xshift   = table->subtableZ[x].shift;
00514     newxkeys = 0;
00515 
00516     yindex   = table->invpermZ[y];
00517     ylist    = table->subtableZ[y].nodelist;
00518     oldykeys = table->subtableZ[y].keys;
00519     yslots   = table->subtableZ[y].slots;
00520     yshift   = table->subtableZ[y].shift;
00521     newykeys = oldykeys;
00522 
00523     /* The nodes in the x layer that don't depend on y directly
00524     ** will stay there; the others are put in a chain.
00525     ** The chain is handled as a FIFO; g points to the beginning and
00526     ** last points to the end.
00527     */
00528 
00529     g = NULL;
00530     lastP = &g;
00531     for (i = 0; i < xslots; i++) {
00532         previousP = &(xlist[i]);
00533         f = *previousP;
00534         while (f != NULL) {
00535             next = f->next;
00536             f1 = cuddT(f); f0 = cuddE(f);
00537             if ((f1->index != (DdHalfWord) yindex) &&
00538                 (f0->index != (DdHalfWord) yindex)) { /* stays */
00539                 newxkeys++;
00540                 *previousP = f;
00541                 previousP = &(f->next);
00542             } else {
00543                 f->index = yindex;
00544                 *lastP = f;
00545                 lastP = &(f->next);
00546             }
00547             f = next;
00548         } /* while there are elements in the collision chain */
00549         *previousP = NULL;
00550     } /* for each slot of the x subtable */
00551     *lastP = NULL;
00552 
00553 
00554 #ifdef DD_COUNT
00555     table->swapSteps += oldxkeys - newxkeys;
00556 #endif
00557     /* Take care of the x nodes that must be re-expressed.
00558     ** They form a linked list pointed by g. Their index has been
00559     ** changed to yindex already.
00560     */
00561     f = g;
00562     while (f != NULL) {
00563         next = f->next;
00564         /* Find f1, f0, f11, f10, f01, f00. */
00565         f1 = cuddT(f);
00566         if ((int) f1->index == yindex) {
00567             f11 = cuddT(f1); f10 = cuddE(f1);
00568         } else {
00569             f11 = empty; f10 = f1;
00570         }
00571         f0 = cuddE(f);
00572         if ((int) f0->index == yindex) {
00573             f01 = cuddT(f0); f00 = cuddE(f0);
00574         } else {
00575             f01 = empty; f00 = f0;
00576         }
00577 
00578         /* Decrease ref count of f1. */
00579         cuddSatDec(f1->ref);
00580         /* Create the new T child. */
00581         if (f11 == empty) {
00582             if (f01 != empty) {
00583                 newf1 = f01;
00584                 cuddSatInc(newf1->ref);
00585             }
00586             /* else case was already handled when finding nodes
00587             ** with both children below level y
00588             */
00589         } else {
00590             /* Check xlist for triple (xindex, f11, f01). */
00591             posn = ddHash(f11, f01, xshift);
00592             /* For each element newf1 in collision list xlist[posn]. */
00593             newf1 = xlist[posn];
00594             while (newf1 != NULL) {
00595                 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
00596                     cuddSatInc(newf1->ref);
00597                     break; /* match */
00598                 }
00599                 newf1 = newf1->next;
00600             } /* while newf1 */
00601             if (newf1 == NULL) {        /* no match */
00602                 newf1 = cuddDynamicAllocNode(table);
00603                 if (newf1 == NULL)
00604                     goto zddSwapOutOfMem;
00605                 newf1->index = xindex; newf1->ref = 1;
00606                 cuddT(newf1) = f11;
00607                 cuddE(newf1) = f01;
00608                 /* Insert newf1 in the collision list xlist[pos];
00609                 ** increase the ref counts of f11 and f01
00610                 */
00611                 newxkeys++;
00612                 newf1->next = xlist[posn];
00613                 xlist[posn] = newf1;
00614                 cuddSatInc(f11->ref);
00615                 cuddSatInc(f01->ref);
00616             }
00617         }
00618         cuddT(f) = newf1;
00619 
00620         /* Do the same for f0. */
00621         /* Decrease ref count of f0. */
00622         cuddSatDec(f0->ref);
00623         /* Create the new E child. */
00624         if (f10 == empty) {
00625             newf0 = f00;
00626             cuddSatInc(newf0->ref);
00627         } else {
00628             /* Check xlist for triple (xindex, f10, f00). */
00629             posn = ddHash(f10, f00, xshift);
00630             /* For each element newf0 in collision list xlist[posn]. */
00631             newf0 = xlist[posn];
00632             while (newf0 != NULL) {
00633                 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
00634                     cuddSatInc(newf0->ref);
00635                     break; /* match */
00636                 }
00637                 newf0 = newf0->next;
00638             } /* while newf0 */
00639             if (newf0 == NULL) {        /* no match */
00640                 newf0 = cuddDynamicAllocNode(table);
00641                 if (newf0 == NULL)
00642                     goto zddSwapOutOfMem;
00643                 newf0->index = xindex; newf0->ref = 1;
00644                 cuddT(newf0) = f10; cuddE(newf0) = f00;
00645                 /* Insert newf0 in the collision list xlist[posn];
00646                 ** increase the ref counts of f10 and f00.
00647                 */
00648                 newxkeys++;
00649                 newf0->next = xlist[posn];
00650                 xlist[posn] = newf0;
00651                 cuddSatInc(f10->ref);
00652                 cuddSatInc(f00->ref);
00653             }
00654         }
00655         cuddE(f) = newf0;
00656 
00657         /* Insert the modified f in ylist.
00658         ** The modified f does not already exists in ylist.
00659         ** (Because of the uniqueness of the cofactors.)
00660         */
00661         posn = ddHash(newf1, newf0, yshift);
00662         newykeys++;
00663         f->next = ylist[posn];
00664         ylist[posn] = f;
00665         f = next;
00666     } /* while f != NULL */
00667 
00668     /* GC the y layer. */
00669 
00670     /* For each node f in ylist. */
00671     for (i = 0; i < yslots; i++) {
00672         previousP = &(ylist[i]);
00673         f = *previousP;
00674         while (f != NULL) {
00675             next = f->next;
00676             if (f->ref == 0) {
00677                 cuddSatDec(cuddT(f)->ref);
00678                 cuddSatDec(cuddE(f)->ref);
00679                 cuddDeallocNode(table, f);
00680                 newykeys--;
00681             } else {
00682                 *previousP = f;
00683                 previousP = &(f->next);
00684             }
00685             f = next;
00686         } /* while f */
00687         *previousP = NULL;
00688     } /* for i */
00689 
00690     /* Set the appropriate fields in table. */
00691     table->subtableZ[x].nodelist = ylist;
00692     table->subtableZ[x].slots    = yslots;
00693     table->subtableZ[x].shift    = yshift;
00694     table->subtableZ[x].keys     = newykeys;
00695     table->subtableZ[x].maxKeys  = yslots * DD_MAX_SUBTABLE_DENSITY;
00696 
00697     table->subtableZ[y].nodelist = xlist;
00698     table->subtableZ[y].slots    = xslots;
00699     table->subtableZ[y].shift    = xshift;
00700     table->subtableZ[y].keys     = newxkeys;
00701     table->subtableZ[y].maxKeys  = xslots * DD_MAX_SUBTABLE_DENSITY;
00702 
00703     table->permZ[xindex] = y; table->permZ[yindex] = x;
00704     table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
00705 
00706     table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
00707 
00708     /* Update univ section; univ[x] remains the same. */
00709     table->univ[y] = cuddT(table->univ[x]);
00710 
00711     return (table->keysZ);
00712 
00713 zddSwapOutOfMem:
00714     (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
00715 
00716     return (0);
00717 
00718 } /* end of cuddZddSwapInPlace */

int cuddZddSwapping ( DdManager table,
int  lower,
int  upper,
Cudd_ReorderingType  heuristic 
)

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

Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.]

Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps.

  1. Select two variables (RANDOM or HEURISTIC).
  2. Permute these variables.
  3. If the nodes have decreased accept the permutation.
  4. Otherwise reconstruct the original heap.
  5. Loop.

Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 742 of file cuddZddReord.c.

00747 {
00748     int i, j;
00749     int max, keys;
00750     int nvars;
00751     int x, y;
00752     int iterate;
00753     int previousSize;
00754     Move *moves, *move;
00755     int pivot;
00756     int modulo;
00757     int result;
00758 
00759 #ifdef DD_DEBUG
00760     /* Sanity check */
00761     assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
00762 #endif
00763 
00764     nvars = upper - lower + 1;
00765     iterate = nvars;
00766 
00767     for (i = 0; i < iterate; i++) {
00768         if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
00769             /* Find pivot <= id with maximum keys. */
00770             for (max = -1, j = lower; j <= upper; j++) {
00771                 if ((keys = table->subtableZ[j].keys) > max) {
00772                     max = keys;
00773                     pivot = j;
00774                 }
00775             }
00776 
00777             modulo = upper - pivot;
00778             if (modulo == 0) {
00779                 y = pivot;      /* y = nvars-1 */
00780             } else {
00781                 /* y = random # from {pivot+1 .. nvars-1} */
00782                 y = pivot + 1 + (int) (Cudd_Random() % modulo);
00783             }
00784 
00785             modulo = pivot - lower - 1;
00786             if (modulo < 1) {   /* if pivot = 1 or 0 */
00787                 x = lower;
00788             } else {
00789                 do { /* x = random # from {0 .. pivot-2} */
00790                     x = (int) Cudd_Random() % modulo;
00791                 } while (x == y);
00792                   /* Is this condition really needed, since x and y
00793                      are in regions separated by pivot? */
00794             }
00795         } else {
00796             x = (int) (Cudd_Random() % nvars) + lower;
00797             do {
00798                 y = (int) (Cudd_Random() % nvars) + lower;
00799             } while (x == y);
00800         }
00801 
00802         previousSize = table->keysZ;
00803         moves = zddSwapAny(table, x, y);
00804         if (moves == NULL)
00805             goto cuddZddSwappingOutOfMem;
00806 
00807         result = cuddZddSiftingBackward(table, moves, previousSize);
00808         if (!result)
00809             goto cuddZddSwappingOutOfMem;
00810 
00811         while (moves != NULL) {
00812             move = moves->next;
00813             cuddDeallocMove(table, moves);
00814             moves = move;
00815         }
00816 #ifdef DD_STATS
00817         if (table->keysZ < (unsigned) previousSize) {
00818             (void) fprintf(table->out,"-");
00819         } else if (table->keysZ > (unsigned) previousSize) {
00820             (void) fprintf(table->out,"+");     /* should never happen */
00821         } else {
00822             (void) fprintf(table->out,"=");
00823         }
00824         fflush(table->out);
00825 #endif
00826     }
00827 
00828     return(1);
00829 
00830 cuddZddSwappingOutOfMem:
00831     while (moves != NULL) {
00832         move = moves->next;
00833         cuddDeallocMove(table, moves);
00834         moves = move;
00835     }
00836     return(0);
00837 
00838 } /* end of cuddZddSwapping */

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

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

Synopsis [Checks for symmetry of x and y.]

Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 193 of file cuddZddSymm.c.

00197 {
00198     int         i;
00199     DdNode      *f, *f0, *f1, *f01, *f00, *f11, *f10;
00200     int         yindex;
00201     int         xsymmy = 1;
00202     int         xsymmyp = 1;
00203     int         arccount = 0;
00204     int         TotalRefCount = 0;
00205     int         symm_found;
00206 
00207     empty = table->zero;
00208 
00209     yindex = table->invpermZ[y];
00210     for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
00211         f = table->subtableZ[x].nodelist[i];
00212         while (f != NULL) {
00213             /* Find f1, f0, f11, f10, f01, f00 */
00214             f1 = cuddT(f);
00215             f0 = cuddE(f);
00216             if ((int) f1->index == yindex) {
00217                 f11 = cuddT(f1);
00218                 f10 = cuddE(f1);
00219                 if (f10 != empty)
00220                     arccount++;
00221             } else {
00222                 if ((int) f0->index != yindex) {
00223                     return(0); /* f bypasses layer y */
00224                 }
00225                 f11 = empty;
00226                 f10 = f1;
00227             }
00228             if ((int) f0->index == yindex) {
00229                 f01 = cuddT(f0);
00230                 f00 = cuddE(f0);
00231                 if (f00 != empty)
00232                     arccount++;
00233             } else {
00234                 f01 = empty;
00235                 f00 = f0;
00236             }
00237             if (f01 != f10)
00238                 xsymmy = 0;
00239             if (f11 != f00)
00240                 xsymmyp = 0;
00241             if ((xsymmy == 0) && (xsymmyp == 0))
00242                 return(0);
00243 
00244             f = f->next;
00245         } /* for each element of the collision list */
00246     } /* for each slot of the subtable */
00247 
00248     /* Calculate the total reference counts of y
00249     ** whose else arc is not empty.
00250     */
00251     for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
00252         f = table->subtableZ[y].nodelist[i];
00253         while (f != NIL(DdNode)) {
00254             if (cuddE(f) != empty)
00255                 TotalRefCount += f->ref;
00256             f = f->next;
00257         }
00258     }
00259 
00260     symm_found = (arccount == TotalRefCount);
00261 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00262     if (symm_found) {
00263         int xindex = table->invpermZ[x];
00264         (void) fprintf(table->out,
00265                        "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00266                        xindex,yindex,x,y);
00267     }
00268 #endif
00269 
00270     return(symm_found);
00271 
00272 } /* end cuddZddSymmCheck */

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

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

Synopsis [Symmetric sifting algorithm for ZDDs.]

Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique subtable.
  2. Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddSymmSiftingConv]

Definition at line 298 of file cuddZddSymm.c.

00302 {
00303     int         i;
00304     int         *var;
00305     int         nvars;
00306     int         x;
00307     int         result;
00308     int         symvars;
00309     int         symgroups;
00310     int         iteration;
00311 #ifdef DD_STATS
00312     int         previousSize;
00313 #endif
00314 
00315     nvars = table->sizeZ;
00316 
00317     /* Find order in which to sift variables. */
00318     var = NULL;
00319     zdd_entry = ALLOC(int, nvars);
00320     if (zdd_entry == NULL) {
00321         table->errorCode = CUDD_MEMORY_OUT;
00322         goto cuddZddSymmSiftingOutOfMem;
00323     }
00324     var = ALLOC(int, nvars);
00325     if (var == NULL) {
00326         table->errorCode = CUDD_MEMORY_OUT;
00327         goto cuddZddSymmSiftingOutOfMem;
00328     }
00329 
00330     for (i = 0; i < nvars; i++) {
00331         x = table->permZ[i];
00332         zdd_entry[i] = table->subtableZ[x].keys;
00333         var[i] = i;
00334     }
00335 
00336     qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00337 
00338     /* Initialize the symmetry of each subtable to itself. */
00339     for (i = lower; i <= upper; i++)
00340         table->subtableZ[i].next = i;
00341 
00342     iteration = ddMin(table->siftMaxVar, nvars);
00343     for (i = 0; i < iteration; i++) {
00344         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00345             break;
00346         x = table->permZ[var[i]];
00347 #ifdef DD_STATS
00348         previousSize = table->keysZ;
00349 #endif
00350         if (x < lower || x > upper) continue;
00351         if (table->subtableZ[x].next == (unsigned) x) {
00352             result = cuddZddSymmSiftingAux(table, x, lower, upper);
00353             if (!result)
00354                 goto cuddZddSymmSiftingOutOfMem;
00355 #ifdef DD_STATS
00356             if (table->keysZ < (unsigned) previousSize) {
00357                 (void) fprintf(table->out,"-");
00358             } else if (table->keysZ > (unsigned) previousSize) {
00359                 (void) fprintf(table->out,"+");
00360 #ifdef DD_VERBOSE
00361                 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00362 #endif
00363             } else {
00364                 (void) fprintf(table->out,"=");
00365             }
00366             fflush(table->out);
00367 #endif
00368         }
00369     }
00370 
00371     FREE(var);
00372     FREE(zdd_entry);
00373 
00374     cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00375 
00376 #ifdef DD_STATS
00377     (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
00378     (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
00379 #endif
00380 
00381     return(1+symvars);
00382 
00383 cuddZddSymmSiftingOutOfMem:
00384 
00385     if (zdd_entry != NULL)
00386         FREE(zdd_entry);
00387     if (var != NULL)
00388         FREE(var);
00389 
00390     return(0);
00391 
00392 } /* end of cuddZddSymmSifting */

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

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

Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]

Description [Symmetric sifting to convergence algorithm for ZDDs. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique subtable.
  2. Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.
  5. Repeat 1-4 until no further improvement.

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddSymmSifting]

Definition at line 419 of file cuddZddSymm.c.

00423 {
00424     int         i;
00425     int         *var;
00426     int         nvars;
00427     int         initialSize;
00428     int         x;
00429     int         result;
00430     int         symvars;
00431     int         symgroups;
00432     int         classes;
00433     int         iteration;
00434 #ifdef DD_STATS
00435     int         previousSize;
00436 #endif
00437 
00438     initialSize = table->keysZ;
00439 
00440     nvars = table->sizeZ;
00441 
00442     /* Find order in which to sift variables. */
00443     var = NULL;
00444     zdd_entry = ALLOC(int, nvars);
00445     if (zdd_entry == NULL) {
00446         table->errorCode = CUDD_MEMORY_OUT;
00447         goto cuddZddSymmSiftingConvOutOfMem;
00448     }
00449     var = ALLOC(int, nvars);
00450     if (var == NULL) {
00451         table->errorCode = CUDD_MEMORY_OUT;
00452         goto cuddZddSymmSiftingConvOutOfMem;
00453     }
00454 
00455     for (i = 0; i < nvars; i++) {
00456         x = table->permZ[i];
00457         zdd_entry[i] = table->subtableZ[x].keys;
00458         var[i] = i;
00459     }
00460 
00461     qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00462 
00463     /* Initialize the symmetry of each subtable to itself
00464     ** for first pass of converging symmetric sifting.
00465     */
00466     for (i = lower; i <= upper; i++)
00467         table->subtableZ[i].next = i;
00468 
00469     iteration = ddMin(table->siftMaxVar, table->sizeZ);
00470     for (i = 0; i < iteration; i++) {
00471         if (zddTotalNumberSwapping >= table->siftMaxSwap)
00472             break;
00473         x = table->permZ[var[i]];
00474         if (x < lower || x > upper) continue;
00475         /* Only sift if not in symmetry group already. */
00476         if (table->subtableZ[x].next == (unsigned) x) {
00477 #ifdef DD_STATS
00478             previousSize = table->keysZ;
00479 #endif
00480             result = cuddZddSymmSiftingAux(table, x, lower, upper);
00481             if (!result)
00482                 goto cuddZddSymmSiftingConvOutOfMem;
00483 #ifdef DD_STATS
00484             if (table->keysZ < (unsigned) previousSize) {
00485                 (void) fprintf(table->out,"-");
00486             } else if (table->keysZ > (unsigned) previousSize) {
00487                 (void) fprintf(table->out,"+");
00488 #ifdef DD_VERBOSE
00489                 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00490 #endif
00491             } else {
00492                 (void) fprintf(table->out,"=");
00493             }
00494             fflush(table->out);
00495 #endif
00496         }
00497     }
00498 
00499     /* Sifting now until convergence. */
00500     while ((unsigned) initialSize > table->keysZ) {
00501         initialSize = table->keysZ;
00502 #ifdef DD_STATS
00503         (void) fprintf(table->out,"\n");
00504 #endif
00505         /* Here we consider only one representative for each symmetry class. */
00506         for (x = lower, classes = 0; x <= upper; x++, classes++) {
00507             while ((unsigned) x < table->subtableZ[x].next)
00508                 x = table->subtableZ[x].next;
00509             /* Here x is the largest index in a group.
00510             ** Groups consists of adjacent variables.
00511             ** Hence, the next increment of x will move it to a new group.
00512             */
00513             i = table->invpermZ[x];
00514             zdd_entry[i] = table->subtableZ[x].keys;
00515             var[classes] = i;
00516         }
00517 
00518         qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);
00519 
00520         /* Now sift. */
00521         iteration = ddMin(table->siftMaxVar, nvars);
00522         for (i = 0; i < iteration; i++) {
00523             if (zddTotalNumberSwapping >= table->siftMaxSwap)
00524                 break;
00525             x = table->permZ[var[i]];
00526             if ((unsigned) x >= table->subtableZ[x].next) {
00527 #ifdef DD_STATS
00528                 previousSize = table->keysZ;
00529 #endif
00530                 result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
00531                 if (!result)
00532                     goto cuddZddSymmSiftingConvOutOfMem;
00533 #ifdef DD_STATS
00534                 if (table->keysZ < (unsigned) previousSize) {
00535                     (void) fprintf(table->out,"-");
00536                 } else if (table->keysZ > (unsigned) previousSize) {
00537                     (void) fprintf(table->out,"+");
00538 #ifdef DD_VERBOSE
00539                 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00540 #endif
00541                 } else {
00542                     (void) fprintf(table->out,"=");
00543                 }
00544                 fflush(table->out);
00545 #endif
00546             }
00547         } /* for */
00548     }
00549 
00550     cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00551 
00552 #ifdef DD_STATS
00553     (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
00554                    symvars);
00555     (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
00556                    symgroups);
00557 #endif
00558 
00559     FREE(var);
00560     FREE(zdd_entry);
00561 
00562     return(1+symvars);
00563 
00564 cuddZddSymmSiftingConvOutOfMem:
00565 
00566     if (zdd_entry != NULL)
00567         FREE(zdd_entry);
00568     if (var != NULL)
00569         FREE(var);
00570 
00571     return(0);
00572 
00573 } /* end of cuddZddSymmSiftingConv */

int cuddZddTreeSifting ( DdManager table,
Cudd_ReorderingType  method 
)

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

Synopsis [Tree sifting algorithm for ZDDs.]

Description [Tree sifting algorithm for ZDDs. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling zddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 228 of file cuddZddGroup.c.

00231 {
00232     int i;
00233     int nvars;
00234     int result;
00235     int tempTree;
00236 
00237     /* If no tree is provided we create a temporary one in which all
00238     ** variables are in a single group. After reordering this tree is
00239     ** destroyed.
00240     */
00241     tempTree = table->treeZ == NULL;
00242     if (tempTree) {
00243         table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
00244         table->treeZ->index = table->invpermZ[0];
00245     }
00246     nvars = table->sizeZ;
00247 
00248 #ifdef DD_DEBUG
00249     if (pr > 0 && !tempTree)
00250         (void) fprintf(table->out,"cuddZddTreeSifting:");
00251     Mtr_PrintGroups(table->treeZ,pr <= 0);
00252 #endif
00253 #if 0
00254     /* Debugging code. */
00255     if (table->tree && table->treeZ) {
00256         (void) fprintf(table->out,"\n");
00257         Mtr_PrintGroups(table->tree, 0);
00258         cuddPrintVarGroups(table,table->tree,0,0);
00259         for (i = 0; i < table->size; i++) {
00260             (void) fprintf(table->out,"%s%d",
00261                            (i == 0) ? "" : ",", table->invperm[i]);
00262         }
00263         (void) fprintf(table->out,"\n");
00264         for (i = 0; i < table->size; i++) {
00265             (void) fprintf(table->out,"%s%d",
00266                            (i == 0) ? "" : ",", table->perm[i]);
00267         }
00268         (void) fprintf(table->out,"\n\n");
00269         Mtr_PrintGroups(table->treeZ,0);
00270         cuddPrintVarGroups(table,table->treeZ,1,0);
00271         for (i = 0; i < table->sizeZ; i++) {
00272             (void) fprintf(table->out,"%s%d",
00273                            (i == 0) ? "" : ",", table->invpermZ[i]);
00274         }
00275         (void) fprintf(table->out,"\n");
00276         for (i = 0; i < table->sizeZ; i++) {
00277             (void) fprintf(table->out,"%s%d",
00278                            (i == 0) ? "" : ",", table->permZ[i]);
00279         }
00280         (void) fprintf(table->out,"\n");
00281     }
00282     /* End of debugging code. */
00283 #endif
00284 #ifdef DD_STATS
00285     extsymmcalls = 0;
00286     extsymm = 0;
00287     secdiffcalls = 0;
00288     secdiff = 0;
00289     secdiffmisfire = 0;
00290 
00291     (void) fprintf(table->out,"\n");
00292     if (!tempTree)
00293         (void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
00294                        zddCountInternalMtrNodes(table,table->treeZ));
00295 #endif
00296 
00297     /* Initialize the group of each subtable to itself. Initially
00298     ** there are no groups. Groups are created according to the tree
00299     ** structure in postorder fashion.
00300     */
00301     for (i = 0; i < nvars; i++)
00302         table->subtableZ[i].next = i;
00303 
00304     /* Reorder. */
00305     result = zddTreeSiftingAux(table, table->treeZ, method);
00306 
00307 #ifdef DD_STATS         /* print stats */
00308     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00309         (table->groupcheck == CUDD_GROUP_CHECK7 ||
00310          table->groupcheck == CUDD_GROUP_CHECK5)) {
00311         (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00312         (void) fprintf(table->out,"extsymm = %d",extsymm);
00313     }
00314     if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00315         table->groupcheck == CUDD_GROUP_CHECK7) {
00316         (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00317         (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00318         (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00319     }
00320 #endif
00321 
00322     if (tempTree)
00323         Cudd_FreeZddTree(table);
00324     return(result);
00325 
00326 } /* end of cuddZddTreeSifting */

DdNode* cuddZddUnateProduct ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_zddUnateProduct.]

Description []

SideEffects [None]

SeeAlso [Cudd_zddUnateProduct]

Definition at line 613 of file cuddZddFuncs.c.

00617 {
00618     int         v, top_f, top_g;
00619     DdNode      *term1, *term2, *term3, *term4;
00620     DdNode      *sum1, *sum2;
00621     DdNode      *f0, *f1, *g0, *g1;
00622     DdNode      *r;
00623     DdNode      *one = DD_ONE(dd);
00624     DdNode      *zero = DD_ZERO(dd);
00625     int         flag;
00626 
00627     statLine(dd);
00628     if (f == zero || g == zero)
00629         return(zero);
00630     if (f == one)
00631         return(g);
00632     if (g == one)
00633         return(f);
00634 
00635     top_f = dd->permZ[f->index];
00636     top_g = dd->permZ[g->index];
00637 
00638     if (top_f > top_g)
00639         return(cuddZddUnateProduct(dd, g, f));
00640 
00641     /* Check cache */
00642     r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g);
00643     if (r)
00644         return(r);
00645 
00646     v = f->index;       /* either yi or zi */
00647     flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
00648     if (flag == 1)
00649         return(NULL);
00650     Cudd_Ref(f1);
00651     Cudd_Ref(f0);
00652     flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);
00653     if (flag == 1) {
00654         Cudd_RecursiveDerefZdd(dd, f1);
00655         Cudd_RecursiveDerefZdd(dd, f0);
00656         return(NULL);
00657     }
00658     Cudd_Ref(g1);
00659     Cudd_Ref(g0);
00660 
00661     term1 = cuddZddUnateProduct(dd, f1, g1);
00662     if (term1 == NULL) {
00663         Cudd_RecursiveDerefZdd(dd, f1);
00664         Cudd_RecursiveDerefZdd(dd, f0);
00665         Cudd_RecursiveDerefZdd(dd, g1);
00666         Cudd_RecursiveDerefZdd(dd, g0);
00667         return(NULL);
00668     }
00669     Cudd_Ref(term1);
00670     term2 = cuddZddUnateProduct(dd, f1, g0);
00671     if (term2 == NULL) {
00672         Cudd_RecursiveDerefZdd(dd, f1);
00673         Cudd_RecursiveDerefZdd(dd, f0);
00674         Cudd_RecursiveDerefZdd(dd, g1);
00675         Cudd_RecursiveDerefZdd(dd, g0);
00676         Cudd_RecursiveDerefZdd(dd, term1);
00677         return(NULL);
00678     }
00679     Cudd_Ref(term2);
00680     term3 = cuddZddUnateProduct(dd, f0, g1);
00681     if (term3 == NULL) {
00682         Cudd_RecursiveDerefZdd(dd, f1);
00683         Cudd_RecursiveDerefZdd(dd, f0);
00684         Cudd_RecursiveDerefZdd(dd, g1);
00685         Cudd_RecursiveDerefZdd(dd, g0);
00686         Cudd_RecursiveDerefZdd(dd, term1);
00687         Cudd_RecursiveDerefZdd(dd, term2);
00688         return(NULL);
00689     }
00690     Cudd_Ref(term3);
00691     term4 = cuddZddUnateProduct(dd, f0, g0);
00692     if (term4 == NULL) {
00693         Cudd_RecursiveDerefZdd(dd, f1);
00694         Cudd_RecursiveDerefZdd(dd, f0);
00695         Cudd_RecursiveDerefZdd(dd, g1);
00696         Cudd_RecursiveDerefZdd(dd, g0);
00697         Cudd_RecursiveDerefZdd(dd, term1);
00698         Cudd_RecursiveDerefZdd(dd, term2);
00699         Cudd_RecursiveDerefZdd(dd, term3);
00700         return(NULL);
00701     }
00702     Cudd_Ref(term4);
00703     Cudd_RecursiveDerefZdd(dd, f1);
00704     Cudd_RecursiveDerefZdd(dd, f0);
00705     Cudd_RecursiveDerefZdd(dd, g1);
00706     Cudd_RecursiveDerefZdd(dd, g0);
00707     sum1 = cuddZddUnion(dd, term1, term2);
00708     if (sum1 == NULL) {
00709         Cudd_RecursiveDerefZdd(dd, term1);
00710         Cudd_RecursiveDerefZdd(dd, term2);
00711         Cudd_RecursiveDerefZdd(dd, term3);
00712         Cudd_RecursiveDerefZdd(dd, term4);
00713         return(NULL);
00714     }
00715     Cudd_Ref(sum1);
00716     Cudd_RecursiveDerefZdd(dd, term1);
00717     Cudd_RecursiveDerefZdd(dd, term2);
00718     sum2 = cuddZddUnion(dd, sum1, term3);
00719     if (sum2 == NULL) {
00720         Cudd_RecursiveDerefZdd(dd, term3);
00721         Cudd_RecursiveDerefZdd(dd, term4);
00722         Cudd_RecursiveDerefZdd(dd, sum1);
00723         return(NULL);
00724     }
00725     Cudd_Ref(sum2);
00726     Cudd_RecursiveDerefZdd(dd, sum1);
00727     Cudd_RecursiveDerefZdd(dd, term3);
00728     r = cuddZddGetNode(dd, v, sum2, term4);
00729     if (r == NULL) {
00730         Cudd_RecursiveDerefZdd(dd, term4);
00731         Cudd_RecursiveDerefZdd(dd, sum2);
00732         return(NULL);
00733     }
00734     Cudd_Ref(r);
00735     Cudd_RecursiveDerefZdd(dd, sum2);
00736     Cudd_RecursiveDerefZdd(dd, term4);
00737 
00738     cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r);
00739     Cudd_Deref(r);
00740     return(r);
00741 
00742 } /* end of cuddZddUnateProduct */

DdNode* cuddZddUnion ( DdManager zdd,
DdNode P,
DdNode Q 
)

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

Synopsis [Performs the recursive step of Cudd_zddUnion.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 549 of file cuddZddSetop.c.

00553 {
00554     int         p_top, q_top;
00555     DdNode      *empty = DD_ZERO(zdd), *t, *e, *res;
00556     DdManager   *table = zdd;
00557 
00558     statLine(zdd);
00559     if (P == empty)
00560         return(Q);
00561     if (Q == empty)
00562         return(P);
00563     if (P == Q)
00564         return(P);
00565 
00566     /* Check cache */
00567     res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q);
00568     if (res != NULL)
00569         return(res);
00570 
00571     if (cuddIsConstant(P))
00572         p_top = P->index;
00573     else
00574         p_top = zdd->permZ[P->index];
00575     if (cuddIsConstant(Q))
00576         q_top = Q->index;
00577     else
00578         q_top = zdd->permZ[Q->index];
00579     if (p_top < q_top) {
00580         e = cuddZddUnion(zdd, cuddE(P), Q);
00581         if (e == NULL) return (NULL);
00582         cuddRef(e);
00583         res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
00584         if (res == NULL) {
00585             Cudd_RecursiveDerefZdd(table, e);
00586             return(NULL);
00587         }
00588         cuddDeref(e);
00589     } else if (p_top > q_top) {
00590         e = cuddZddUnion(zdd, P, cuddE(Q));
00591         if (e == NULL) return(NULL);
00592         cuddRef(e);
00593         res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e);
00594         if (res == NULL) {
00595             Cudd_RecursiveDerefZdd(table, e);
00596             return(NULL);
00597         }
00598         cuddDeref(e);
00599     } else {
00600         t = cuddZddUnion(zdd, cuddT(P), cuddT(Q));
00601         if (t == NULL) return(NULL);
00602         cuddRef(t);
00603         e = cuddZddUnion(zdd, cuddE(P), cuddE(Q));
00604         if (e == NULL) {
00605             Cudd_RecursiveDerefZdd(table, t);
00606             return(NULL);
00607         }
00608         cuddRef(e);
00609         res = cuddZddGetNode(zdd, P->index, t, e);
00610         if (res == NULL) {
00611             Cudd_RecursiveDerefZdd(table, t);
00612             Cudd_RecursiveDerefZdd(table, e);
00613             return(NULL);
00614         }
00615         cuddDeref(t);
00616         cuddDeref(e);
00617     }
00618 
00619     cuddCacheInsert2(table, cuddZddUnion, P, Q, res);
00620 
00621     return(res);
00622 
00623 } /* end of cuddZddUnion */

int cuddZddUniqueCompare ( int *  ptr_x,
int *  ptr_y 
)

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]

SeeAlso []

Definition at line 455 of file cuddZddReord.c.

00458 {
00459     return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
00460 
00461 } /* end of cuddZddUniqueCompare */

DdNode* cuddZddWeakDiv ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_zddWeakDiv.]

Description []

SideEffects [None]

SeeAlso [Cudd_zddWeakDiv]

Definition at line 757 of file cuddZddFuncs.c.

00761 {
00762     int         v;
00763     DdNode      *one = DD_ONE(dd);
00764     DdNode      *zero = DD_ZERO(dd);
00765     DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
00766     DdNode      *q, *tmp;
00767     DdNode      *r;
00768     int         flag;
00769 
00770     statLine(dd);
00771     if (g == one)
00772         return(f);
00773     if (f == zero || f == one)
00774         return(zero);
00775     if (f == g)
00776         return(one);
00777 
00778     /* Check cache. */
00779     r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g);
00780     if (r)
00781         return(r);
00782 
00783     v = g->index;
00784 
00785     flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
00786     if (flag == 1)
00787         return(NULL);
00788     Cudd_Ref(f1);
00789     Cudd_Ref(f0);
00790     Cudd_Ref(fd);
00791     flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
00792     if (flag == 1) {
00793         Cudd_RecursiveDerefZdd(dd, f1);
00794         Cudd_RecursiveDerefZdd(dd, f0);
00795         Cudd_RecursiveDerefZdd(dd, fd);
00796         return(NULL);
00797     }
00798     Cudd_Ref(g1);
00799     Cudd_Ref(g0);
00800     Cudd_Ref(gd);
00801 
00802     q = g;
00803 
00804     if (g0 != zero) {
00805         q = cuddZddWeakDiv(dd, f0, g0);
00806         if (q == NULL) {
00807             Cudd_RecursiveDerefZdd(dd, f1);
00808             Cudd_RecursiveDerefZdd(dd, f0);
00809             Cudd_RecursiveDerefZdd(dd, fd);
00810             Cudd_RecursiveDerefZdd(dd, g1);
00811             Cudd_RecursiveDerefZdd(dd, g0);
00812             Cudd_RecursiveDerefZdd(dd, gd);
00813             return(NULL);
00814         }
00815         Cudd_Ref(q);
00816     }
00817     else
00818         Cudd_Ref(q);
00819     Cudd_RecursiveDerefZdd(dd, f0);
00820     Cudd_RecursiveDerefZdd(dd, g0);
00821 
00822     if (q == zero) {
00823         Cudd_RecursiveDerefZdd(dd, f1);
00824         Cudd_RecursiveDerefZdd(dd, g1);
00825         Cudd_RecursiveDerefZdd(dd, fd);
00826         Cudd_RecursiveDerefZdd(dd, gd);
00827         cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
00828         Cudd_Deref(q);
00829         return(zero);
00830     }
00831 
00832     if (g1 != zero) {
00833         Cudd_RecursiveDerefZdd(dd, q);
00834         tmp = cuddZddWeakDiv(dd, f1, g1);
00835         if (tmp == NULL) {
00836             Cudd_RecursiveDerefZdd(dd, f1);
00837             Cudd_RecursiveDerefZdd(dd, g1);
00838             Cudd_RecursiveDerefZdd(dd, fd);
00839             Cudd_RecursiveDerefZdd(dd, gd);
00840             return(NULL);
00841         }
00842         Cudd_Ref(tmp);
00843         Cudd_RecursiveDerefZdd(dd, f1);
00844         Cudd_RecursiveDerefZdd(dd, g1);
00845         if (q == g)
00846             q = tmp;
00847         else {
00848             q = cuddZddIntersect(dd, q, tmp);
00849             if (q == NULL) {
00850                 Cudd_RecursiveDerefZdd(dd, fd);
00851                 Cudd_RecursiveDerefZdd(dd, gd);
00852                 return(NULL);
00853             }
00854             Cudd_Ref(q);
00855             Cudd_RecursiveDerefZdd(dd, tmp);
00856         }
00857     }
00858     else {
00859         Cudd_RecursiveDerefZdd(dd, f1);
00860         Cudd_RecursiveDerefZdd(dd, g1);
00861     }
00862 
00863     if (q == zero) {
00864         Cudd_RecursiveDerefZdd(dd, fd);
00865         Cudd_RecursiveDerefZdd(dd, gd);
00866         cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
00867         Cudd_Deref(q);
00868         return(zero);
00869     }
00870 
00871     if (gd != zero) {
00872         Cudd_RecursiveDerefZdd(dd, q);
00873         tmp = cuddZddWeakDiv(dd, fd, gd);
00874         if (tmp == NULL) {
00875             Cudd_RecursiveDerefZdd(dd, fd);
00876             Cudd_RecursiveDerefZdd(dd, gd);
00877             return(NULL);
00878         }
00879         Cudd_Ref(tmp);
00880         Cudd_RecursiveDerefZdd(dd, fd);
00881         Cudd_RecursiveDerefZdd(dd, gd);
00882         if (q == g)
00883             q = tmp;
00884         else {
00885             q = cuddZddIntersect(dd, q, tmp);
00886             if (q == NULL) {
00887                 Cudd_RecursiveDerefZdd(dd, tmp);
00888                 return(NULL);
00889             }
00890             Cudd_Ref(q);
00891             Cudd_RecursiveDerefZdd(dd, tmp);
00892         }
00893     }
00894     else {
00895         Cudd_RecursiveDerefZdd(dd, fd);
00896         Cudd_RecursiveDerefZdd(dd, gd);
00897     }
00898 
00899     cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q);
00900     Cudd_Deref(q);
00901     return(q);
00902 
00903 } /* end of cuddZddWeakDiv */

DdNode* cuddZddWeakDivF ( DdManager dd,
DdNode f,
DdNode g 
)

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

Synopsis [Performs the recursive step of Cudd_zddWeakDivF.]

Description []

SideEffects [None]

SeeAlso [Cudd_zddWeakDivF]

Definition at line 918 of file cuddZddFuncs.c.

00922 {
00923     int         v, top_f, top_g, vf, vg;
00924     DdNode      *one = DD_ONE(dd);
00925     DdNode      *zero = DD_ZERO(dd);
00926     DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
00927     DdNode      *q, *tmp;
00928     DdNode      *r;
00929     DdNode      *term1, *term0, *termd;
00930     int         flag;
00931     int         pv, nv;
00932 
00933     statLine(dd);
00934     if (g == one)
00935         return(f);
00936     if (f == zero || f == one)
00937         return(zero);
00938     if (f == g)
00939         return(one);
00940 
00941     /* Check cache. */
00942     r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g);
00943     if (r)
00944         return(r);
00945 
00946     top_f = dd->permZ[f->index];
00947     top_g = dd->permZ[g->index];
00948     vf = top_f >> 1;
00949     vg = top_g >> 1;
00950     v = ddMin(top_f, top_g);
00951 
00952     if (v == top_f && vf < vg) {
00953         v = f->index;
00954         flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
00955         if (flag == 1)
00956             return(NULL);
00957         Cudd_Ref(f1);
00958         Cudd_Ref(f0);
00959         Cudd_Ref(fd);
00960 
00961         pv = cuddZddGetPosVarIndex(dd, v);
00962         nv = cuddZddGetNegVarIndex(dd, v);
00963 
00964         term1 = cuddZddWeakDivF(dd, f1, g);
00965         if (term1 == NULL) {
00966             Cudd_RecursiveDerefZdd(dd, f1);
00967             Cudd_RecursiveDerefZdd(dd, f0);
00968             Cudd_RecursiveDerefZdd(dd, fd);
00969             return(NULL);
00970         }
00971         Cudd_Ref(term1);
00972         Cudd_RecursiveDerefZdd(dd, f1);
00973         term0 = cuddZddWeakDivF(dd, f0, g);
00974         if (term0 == NULL) {
00975             Cudd_RecursiveDerefZdd(dd, f0);
00976             Cudd_RecursiveDerefZdd(dd, fd);
00977             Cudd_RecursiveDerefZdd(dd, term1);
00978             return(NULL);
00979         }
00980         Cudd_Ref(term0);
00981         Cudd_RecursiveDerefZdd(dd, f0);
00982         termd = cuddZddWeakDivF(dd, fd, g);
00983         if (termd == NULL) {
00984             Cudd_RecursiveDerefZdd(dd, fd);
00985             Cudd_RecursiveDerefZdd(dd, term1);
00986             Cudd_RecursiveDerefZdd(dd, term0);
00987             return(NULL);
00988         }
00989         Cudd_Ref(termd);
00990         Cudd_RecursiveDerefZdd(dd, fd);
00991 
00992         tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */
00993         if (tmp == NULL) {
00994             Cudd_RecursiveDerefZdd(dd, term1);
00995             Cudd_RecursiveDerefZdd(dd, term0);
00996             Cudd_RecursiveDerefZdd(dd, termd);
00997             return(NULL);
00998         }
00999         Cudd_Ref(tmp);
01000         Cudd_RecursiveDerefZdd(dd, term0);
01001         Cudd_RecursiveDerefZdd(dd, termd);
01002         q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */
01003         if (q == NULL) {
01004             Cudd_RecursiveDerefZdd(dd, term1);
01005             Cudd_RecursiveDerefZdd(dd, tmp);
01006             return(NULL);
01007         }
01008         Cudd_Ref(q);
01009         Cudd_RecursiveDerefZdd(dd, term1);
01010         Cudd_RecursiveDerefZdd(dd, tmp);
01011 
01012         cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
01013         Cudd_Deref(q);
01014         return(q);
01015     }
01016 
01017     if (v == top_f)
01018         v = f->index;
01019     else
01020         v = g->index;
01021 
01022     flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
01023     if (flag == 1)
01024         return(NULL);
01025     Cudd_Ref(f1);
01026     Cudd_Ref(f0);
01027     Cudd_Ref(fd);
01028     flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
01029     if (flag == 1) {
01030         Cudd_RecursiveDerefZdd(dd, f1);
01031         Cudd_RecursiveDerefZdd(dd, f0);
01032         Cudd_RecursiveDerefZdd(dd, fd);
01033         return(NULL);
01034     }
01035     Cudd_Ref(g1);
01036     Cudd_Ref(g0);
01037     Cudd_Ref(gd);
01038 
01039     q = g;
01040 
01041     if (g0 != zero) {
01042         q = cuddZddWeakDivF(dd, f0, g0);
01043         if (q == NULL) {
01044             Cudd_RecursiveDerefZdd(dd, f1);
01045             Cudd_RecursiveDerefZdd(dd, f0);
01046             Cudd_RecursiveDerefZdd(dd, fd);
01047             Cudd_RecursiveDerefZdd(dd, g1);
01048             Cudd_RecursiveDerefZdd(dd, g0);
01049             Cudd_RecursiveDerefZdd(dd, gd);
01050             return(NULL);
01051         }
01052         Cudd_Ref(q);
01053     }
01054     else
01055         Cudd_Ref(q);
01056     Cudd_RecursiveDerefZdd(dd, f0);
01057     Cudd_RecursiveDerefZdd(dd, g0);
01058 
01059     if (q == zero) {
01060         Cudd_RecursiveDerefZdd(dd, f1);
01061         Cudd_RecursiveDerefZdd(dd, g1);
01062         Cudd_RecursiveDerefZdd(dd, fd);
01063         Cudd_RecursiveDerefZdd(dd, gd);
01064         cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
01065         Cudd_Deref(q);
01066         return(zero);
01067     }
01068 
01069     if (g1 != zero) {
01070         Cudd_RecursiveDerefZdd(dd, q);
01071         tmp = cuddZddWeakDivF(dd, f1, g1);
01072         if (tmp == NULL) {
01073             Cudd_RecursiveDerefZdd(dd, f1);
01074             Cudd_RecursiveDerefZdd(dd, g1);
01075             Cudd_RecursiveDerefZdd(dd, fd);
01076             Cudd_RecursiveDerefZdd(dd, gd);
01077             return(NULL);
01078         }
01079         Cudd_Ref(tmp);
01080         Cudd_RecursiveDerefZdd(dd, f1);
01081         Cudd_RecursiveDerefZdd(dd, g1);
01082         if (q == g)
01083             q = tmp;
01084         else {
01085             q = cuddZddIntersect(dd, q, tmp);
01086             if (q == NULL) {
01087                 Cudd_RecursiveDerefZdd(dd, fd);
01088                 Cudd_RecursiveDerefZdd(dd, gd);
01089                 return(NULL);
01090             }
01091             Cudd_Ref(q);
01092             Cudd_RecursiveDerefZdd(dd, tmp);
01093         }
01094     }
01095     else {
01096         Cudd_RecursiveDerefZdd(dd, f1);
01097         Cudd_RecursiveDerefZdd(dd, g1);
01098     }
01099 
01100     if (q == zero) {
01101         Cudd_RecursiveDerefZdd(dd, fd);
01102         Cudd_RecursiveDerefZdd(dd, gd);
01103         cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
01104         Cudd_Deref(q);
01105         return(zero);
01106     }
01107 
01108     if (gd != zero) {
01109         Cudd_RecursiveDerefZdd(dd, q);
01110         tmp = cuddZddWeakDivF(dd, fd, gd);
01111         if (tmp == NULL) {
01112             Cudd_RecursiveDerefZdd(dd, fd);
01113             Cudd_RecursiveDerefZdd(dd, gd);
01114             return(NULL);
01115         }
01116         Cudd_Ref(tmp);
01117         Cudd_RecursiveDerefZdd(dd, fd);
01118         Cudd_RecursiveDerefZdd(dd, gd);
01119         if (q == g)
01120             q = tmp;
01121         else {
01122             q = cuddZddIntersect(dd, q, tmp);
01123             if (q == NULL) {
01124                 Cudd_RecursiveDerefZdd(dd, tmp);
01125                 return(NULL);
01126             }
01127             Cudd_Ref(q);
01128             Cudd_RecursiveDerefZdd(dd, tmp);
01129         }
01130     }
01131     else {
01132         Cudd_RecursiveDerefZdd(dd, fd);
01133         Cudd_RecursiveDerefZdd(dd, gd);
01134     }
01135 
01136     cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
01137     Cudd_Deref(q);
01138     return(q);
01139 
01140 } /* end of cuddZddWeakDivF */


Generated on Tue Jan 12 13:57:20 2010 for glu-2.2 by  doxygen 1.6.1