Exemplo n.º 1
0
/**Function********************************************************************

  Synopsis    [Computes a complement cover for a ZDD node.]

  Description [Computes a complement cover for a ZDD node. For lack of a
  better method, we first extract the function BDD from the ZDD cover,
  then make the complement of the ZDD cover from the complement of the
  BDD node by using ISOP. Returns a pointer to the resulting cover if
  successful; NULL otherwise. The result depends on current variable
  order.]

  SideEffects [The result depends on current variable order.]

  SeeAlso     []

******************************************************************************/
DdNode  *
Cudd_zddComplement(
  DdManager *dd,
  DdNode *node)
{
    DdNode      *b, *isop, *zdd_I;

    /* Check cache */
    zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node);
    if (zdd_I)
        return(zdd_I);

    b = Cudd_MakeBddFromZddCover(dd, node);
    if (!b)
        return(NULL);
    Cudd_Ref(b);
    isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I);
    if (!isop) {
        Cudd_RecursiveDeref(dd, b);
        return(NULL);
    }
    Cudd_Ref(isop);
    Cudd_Ref(zdd_I);
    Cudd_RecursiveDeref(dd, b);
    Cudd_RecursiveDeref(dd, isop);

    cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I);
    Cudd_Deref(zdd_I);
    return(zdd_I);
} /* end of Cudd_zddComplement */
Exemplo n.º 2
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cuddaux_Support.]

  Description [Performs the recursive step of Cuddaux_Support.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode*
cuddauxSupportRecur(DdManager* dd,
		    DdNode * f)
{
  DdNode *one, *fv, *fvn, *T,*E, *res, *res1;

  one = DD_ONE(dd);
  if (cuddIsConstant(f)) {
    return one;
  }
  fv = cuddT(f);
  fvn = Cudd_Regular(cuddE(f));
  if (cuddIsConstant(fv) && cuddIsConstant(fvn)){
    return dd->vars[f->index];
  }
  /* Look in the cache */
  res = cuddCacheLookup1(dd,Cuddaux_Support,f);
  if (res != NULL)
    return(res);

  T = cuddIsConstant(fv) ? one : cuddauxSupportRecur(dd,fv);
  if (T == NULL)
    return(NULL);
  cuddRef(T);
  E = cuddIsConstant(fvn) ? one : cuddauxSupportRecur(dd,fvn);
  if (E == NULL){
    Cudd_IterDerefBdd(dd,T);
    return(NULL);
  }
  if (T==E){
    res = cuddUniqueInter(dd,f->index,T,Cudd_Not(one));
    if (res == NULL){
      Cudd_IterDerefBdd(dd,T);
      return NULL;
    }
    cuddDeref(T);
  }
  else {
    cuddRef(E);
    res1 = cuddBddAndRecur(dd,T,E);
    if (res1 == NULL){
      Cudd_IterDerefBdd(dd,T);
      Cudd_IterDerefBdd(dd,E);
      return(NULL);
    }
    cuddRef(res1);
    Cudd_IterDerefBdd(dd,T);
    Cudd_IterDerefBdd(dd,E);
    res = cuddUniqueInter(dd,f->index,res1,Cudd_Not(one));
    if (res == NULL){
      Cudd_IterDerefBdd(dd,T);
      Cudd_IterDerefBdd(dd,E);
      Cudd_IterDerefBdd(dd,res1);
      return(NULL);
    }
    cuddDeref(res1);
  }
  cuddCacheInsert1(dd,Cuddaux_Support,f,res);
  return(res);
} /* end of cuddauxSupportRecur */
Exemplo n.º 3
0
/**Function********************************************************************

  Synopsis    [Finds the maximum discriminant of f.]

  Description [Returns a pointer to a constant ADD.]

  SideEffects [None]

******************************************************************************/
DdNode *
Cudd_addFindMax(
  DdManager * dd,
  DdNode * f)
{
    DdNode *t, *e, *res;

    statLine(dd);
    if (cuddIsConstant(f)) {
	return(f);
    }

    res = cuddCacheLookup1(dd,Cudd_addFindMax,f);
    if (res != NULL) {
	return(res);
    }

    t  = Cudd_addFindMax(dd,cuddT(f));
    if (t == DD_PLUS_INFINITY(dd)) return(t);

    e  = Cudd_addFindMax(dd,cuddE(f));

    res = (cuddV(t) >= cuddV(e)) ? t : e;

    cuddCacheInsert1(dd,Cudd_addFindMax,f,res);

    return(res);

} /* end of Cudd_addFindMax */
Exemplo n.º 4
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddVarMap.]

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

  SideEffects [None]

  SeeAlso     [Cudd_bddVarMap]

******************************************************************************/
static DdNode *
cuddBddVarMapRecur(
  DdManager *manager /* DD manager */,
  DdNode *f /* BDD to be remapped */)
{
    DdNode	*F, *T, *E;
    DdNode	*res;
    int		index;

    statLine(manager);
    F = Cudd_Regular(f);

    /* Check for terminal case of constant node. */
    if (cuddIsConstant(F)) {
	return(f);
    }

    /* If problem already solved, look up answer and return. */
    if (F->ref != 1 &&
	(res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) {
	return(Cudd_NotCond(res,F != f));
    }

    /* Split and recur on children of this node. */
    T = cuddBddVarMapRecur(manager,cuddT(F));
    if (T == NULL) return(NULL);
    cuddRef(T);
    E = cuddBddVarMapRecur(manager,cuddE(F));
    if (E == NULL) {
	Cudd_IterDerefBdd(manager, T);
	return(NULL);
    }
    cuddRef(E);

    /* Move variable that should be in this position to this position
    ** by retrieving the single var BDD for that variable, and calling
    ** cuddBddIteRecur with the T and E we just created.
    */
    index = manager->map[F->index];
    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
    if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_IterDerefBdd(manager, T);
    Cudd_IterDerefBdd(manager, E);

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again.
    */
    if (F->ref != 1) {
	cuddCacheInsert1(manager,Cudd_bddVarMap,F,res);
    }
    cuddDeref(res);
    return(Cudd_NotCond(res,F != f));

} /* end of cuddBddVarMapRecur */
Exemplo n.º 5
0
/**Function*************************************************************

  Synopsis    [Performs the recursive step of Extra_bddSpaceCanonVars().]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF )
{
	DdNode * bRes, * bFR;
	statLine( dd );

	bFR = Cudd_Regular(bF);
	if ( cuddIsConstant(bFR) )
		return bF;

    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF)) )
    	return bRes;
	else
	{
		DdNode * bF0,  * bF1;
		DdNode * bRes, * bRes0; 

		if ( bFR != bF ) // bF is complemented 
		{
			bF0 = Cudd_Not( cuddE(bFR) );
			bF1 = Cudd_Not( cuddT(bFR) );
		}
		else
		{
			bF0 = cuddE(bFR);
			bF1 = cuddT(bFR);
		}

		if ( bF0 == b0 )
		{
			bRes = extraBddSpaceCanonVars( dd, bF1 );
			if ( bRes == NULL )
				return NULL;
		}
		else if ( bF1 == b0 )
		{
			bRes = extraBddSpaceCanonVars( dd, bF0 );
			if ( bRes == NULL )
				return NULL;
		}
		else
		{
			bRes0 = extraBddSpaceCanonVars( dd, bF0 );
			if ( bRes0 == NULL )
				return NULL;
			cuddRef( bRes0 );

			bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 );
			if ( bRes == NULL ) 
			{
				Cudd_RecursiveDeref( dd,bRes0 );
				return NULL;
			}
			cuddDeref( bRes0 );
		}

		cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes );
		return bRes;
	}
}
Exemplo n.º 6
0
/**
  @brief Implements the recursive step of Cudd_addRoundOff.

  @return a pointer to the result.

  @sideeffect None

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

    DdNode *res, *fv, *fvn, *T, *E;
    double n;
    DD_CTFP1 cacheOp;

    statLine(dd);
    if (cuddIsConstant(f)) {
	n = ceil(cuddV(f)*trunc)/trunc;
	res = cuddUniqueConst(dd,n);
	return(res);
    }
    cacheOp = (DD_CTFP1) Cudd_addRoundOff;
    res = cuddCacheLookup1(dd,cacheOp,f);
    if (res != NULL) {
	return(res);
    }
    checkWhetherToGiveUp(dd);
    /* Recursive Step */
    fv = cuddT(f);
    fvn = cuddE(f);
    T = cuddAddRoundOffRecur(dd,fv,trunc);
    if (T == NULL) {
       return(NULL);
    }
    cuddRef(T);
    E = cuddAddRoundOffRecur(dd,fvn,trunc);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);
    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd,T);
	Cudd_RecursiveDeref(dd,E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,cacheOp,f,res);
    return(res);

} /* end of cuddAddRoundOffRecur */
Exemplo n.º 7
0
DdNode *
cuddAddMonadicApplyWithDataRecur(
  DdManager * dd,
  DD_MAOPD op,
  DdNode * f,
	void * data)
{
    DdNode *res, *ft, *fe, *T, *E;
    unsigned int index;

    /* Check terminal cases. */
    statLine(dd);
    res = (*op)(dd,f, data);
    if (res != NULL) return(res);


    /* Check cache. */
    res = cuddCacheLookup1(dd,(DD_MAOP)global_bloody_counter_unary,f);
    if (res != NULL) return(res);

    /* Recursive step. */
    index = f->index;
    ft = cuddT(f);
    fe = cuddE(f);

    T = cuddAddMonadicApplyWithDataRecur(dd,op,ft, data);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = cuddAddMonadicApplyWithDataRecur(dd,op,fe, data);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);

    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd, T);
	Cudd_RecursiveDeref(dd, E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,(DD_MAOP)global_bloody_counter_unary,f,res);

    return(res);

} /* end of cuddAddMonadicApplyWithDataRecur */
Exemplo n.º 8
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addMonadicApply.]

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

  SideEffects [None]

  SeeAlso     [cuddAddApplyRecur]

******************************************************************************/
DdNode *
cuddAddMonadicApplyRecur(
  DdManager * dd,
  DdNode * (*op)(DdManager *, DdNode *),
  DdNode * f)
{
    DdNode *res, *ft, *fe, *T, *E;
    unsigned int ford;
    unsigned int index;

    /* Check terminal cases. */
    statLine(dd);
    res = (*op)(dd,f);
    if (res != NULL) return(res);

    /* Check cache. */
    res = cuddCacheLookup1(dd,op,f);
    if (res != NULL) return(res);

    /* Recursive step. */
    ford = cuddI(dd,f->index);
    index = f->index;
    ft = cuddT(f);
    fe = cuddE(f);

    T = cuddAddMonadicApplyRecur(dd,op,ft);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = cuddAddMonadicApplyRecur(dd,op,fe);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);

    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd, T);
	Cudd_RecursiveDeref(dd, E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,op,f,res);

    return(res);

} /* end of cuddAddMonadicApplyRecur */
Exemplo n.º 9
0
/**
  @brief Implements the recursive step of Cudd_addNegate.

  @return a pointer to the result.

  @sideeffect None

*/
DdNode *
cuddAddNegateRecur(
  DdManager * dd,
  DdNode * f)
{
    DdNode *res,
	    *fv, *fvn,
	    *T, *E;

    statLine(dd);
    /* Check terminal cases. */
    if (cuddIsConstant(f)) {
	res = cuddUniqueConst(dd,-cuddV(f));
	return(res);
    }

    /* Check cache */
    res = cuddCacheLookup1(dd,Cudd_addNegate,f);
    if (res != NULL) return(res);

    checkWhetherToGiveUp(dd);

    /* Recursive Step */
    fv = cuddT(f);
    fvn = cuddE(f);
    T = cuddAddNegateRecur(dd,fv);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = cuddAddNegateRecur(dd,fvn);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);
    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd, T);
	Cudd_RecursiveDeref(dd, E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,Cudd_addNegate,f,res);

    return(res);

} /* end of cuddAddNegateRecur */
Exemplo n.º 10
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Extra_zddSelectOneSubset.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode * extraZddSelectOneSubset( 
  DdManager * dd, 
  DdNode * zS )
// selects one subset from the ZDD zS
// returns z0 if and only if zS is an empty set of cubes
{
    DdNode * zRes;

    if ( zS == z0 )    return z0;
    if ( zS == z1 )    return z1;
    
    // check cache
    if ( (zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS )) )
        return zRes;
    else
    {
        DdNode * zS0, * zS1, * zTemp; 

        zS0 = cuddE(zS);
        zS1 = cuddT(zS);

        if ( zS0 != z0 )
        {
            zRes = extraZddSelectOneSubset( dd, zS0 );
            if ( zRes == NULL )
                return NULL;
        }
        else // if ( zS0 == z0 )
        {
            assert( zS1 != z0 );
            zRes = extraZddSelectOneSubset( dd, zS1 );
            if ( zRes == NULL )
                return NULL;
            cuddRef( zRes );

            zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 );
            if ( zRes == NULL ) 
            {
                Cudd_RecursiveDerefZdd( dd, zTemp );
                return NULL;
            }
            cuddDeref( zTemp );
        }

        // insert the result into cache
        cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes );
        return zRes;
    }       
} /* end of extraZddSelectOneSubset */
Exemplo n.º 11
0
/**Function********************************************************************

  Synopsis    [Performs a recursive step of Extra_zddGetSingletons.]

  Description [Returns the set of ZDD singletons, containing those positive 
  polarity ZDD variables that correspond to the BDD variables in bVars.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode * extraZddGetSingletons( 
  DdManager * dd,    /* the DD manager */
  DdNode * bVars)    /* the set of variables */
{
    DdNode * zRes;

    if ( bVars == b1 )
//    if ( bVars == b0 )  // bug fixed by Jin Zhang, Jan 23, 2004
        return z1;

    if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars)) )
        return zRes;
    else
    {
        DdNode * zTemp, * zPlus;          

        // solve subproblem
        zRes = extraZddGetSingletons( dd, cuddT(bVars) );
        if ( zRes == NULL ) 
            return NULL;
        cuddRef( zRes );
        
        zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
        if ( zPlus == NULL ) 
        {
            Cudd_RecursiveDerefZdd( dd, zRes );
            return NULL;
        }
        cuddRef( zPlus );

        // add these to the result
        zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
        if ( zRes == NULL )
        {
            Cudd_RecursiveDerefZdd( dd, zTemp );
            Cudd_RecursiveDerefZdd( dd, zPlus );
            return NULL;
        }
        cuddRef( zRes );
        Cudd_RecursiveDerefZdd( dd, zTemp );
        Cudd_RecursiveDerefZdd( dd, zPlus );
        cuddDeref( zRes );

        cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes );
        return zRes;
    }
}   /* end of extraZddGetSingletons */
Exemplo n.º 12
0
/**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]

******************************************************************************/
DdNode *
cuddAddCmplRecur(
  DdManager * dd,
  DdNode * f)
{
    DdNode *one,*zero;
    DdNode *r,*Fv,*Fnv,*t,*e;

    statLine(dd);
    one = DD_ONE(dd);
    zero = DD_ZERO(dd); 

    if (cuddIsConstant(f)) {
        if (f == zero) {
	    return(one);
	} else {
	    return(zero);
	}
    }
    r = cuddCacheLookup1(dd,Cudd_addCmpl,f);
    if (r != NULL) {
	return(r);
    }
    Fv = cuddT(f);
    Fnv = cuddE(f);
    t = cuddAddCmplRecur(dd,Fv);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = cuddAddCmplRecur(dd,Fnv);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd,t);
	return(NULL);
    }
    cuddRef(e);
    r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
    if (r == NULL) {
	Cudd_RecursiveDeref(dd, t);
	Cudd_RecursiveDeref(dd, e);
	return(NULL);
    }
    cuddDeref(t);
    cuddDeref(e);
    cuddCacheInsert1(dd,Cudd_addCmpl,f,r);
    return(r);

} /* end of cuddAddCmplRecur */
Exemplo n.º 13
0
/**Function*************************************************************

  Synopsis    [Performs the recursive step of Extra_bddSpaceEquationsNev().]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF )
{
	DdNode * zRes;
	statLine( dd );

	if ( bF == b0 )
		return z1;
	if ( bF == b1 )
		return z0;
	
    if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF)) )
    	return zRes;
	else
	{
		DdNode * bFR, * bF0,  * bF1;
		DdNode * zPos0, * zPos1, * zNeg1; 
		DdNode * zRes, * zRes0, * zRes1;

		bFR = Cudd_Regular(bF);
		if ( bFR != bF ) // bF is complemented 
		{
			bF0 = Cudd_Not( cuddE(bFR) );
			bF1 = Cudd_Not( cuddT(bFR) );
		}
		else
		{
			bF0 = cuddE(bFR);
			bF1 = cuddT(bFR);
		}

		if ( bF0 == b0 )
		{
			zRes = extraBddSpaceEquationsNeg( dd, bF1 );
			if ( zRes == NULL )
				return NULL;
		}
		else if ( bF1 == b0 )
		{
			zRes0 = extraBddSpaceEquationsNeg( dd, bF0 );
			if ( zRes0 == NULL )
				return NULL;
			cuddRef( zRes0 );

			// add the current element to the set
			zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 );
			if ( zRes == NULL ) 
			{
				Cudd_RecursiveDerefZdd(dd, zRes0);
				return NULL;
			}
			cuddDeref( zRes0 );
		}
		else
		{
			zPos0 = extraBddSpaceEquationsNeg( dd, bF0 );
			if ( zPos0 == NULL )
				return NULL;
			cuddRef( zPos0 );

			zPos1 = extraBddSpaceEquationsNeg( dd, bF1 );
			if ( zPos1 == NULL )
			{
				Cudd_RecursiveDerefZdd(dd, zPos0);
				return NULL;
			}
			cuddRef( zPos1 );

			zNeg1 = extraBddSpaceEquationsPos( dd, bF1 );
			if ( zNeg1 == NULL )
			{
				Cudd_RecursiveDerefZdd(dd, zPos0);
				Cudd_RecursiveDerefZdd(dd, zPos1);
				return NULL;
			}
			cuddRef( zNeg1 );


			zRes0 = cuddZddIntersect( dd, zPos0, zPos1 );
			if ( zRes0 == NULL )
			{
				Cudd_RecursiveDerefZdd(dd, zNeg1);
				Cudd_RecursiveDerefZdd(dd, zPos0);
				Cudd_RecursiveDerefZdd(dd, zPos1);
				return NULL;
			}
			cuddRef( zRes0 );

			zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 );
			if ( zRes1 == NULL )
			{
				Cudd_RecursiveDerefZdd(dd, zRes0);
				Cudd_RecursiveDerefZdd(dd, zNeg1);
				Cudd_RecursiveDerefZdd(dd, zPos0);
				Cudd_RecursiveDerefZdd(dd, zPos1);
				return NULL;
			}
			cuddRef( zRes1 );
			Cudd_RecursiveDerefZdd(dd, zNeg1);
			Cudd_RecursiveDerefZdd(dd, zPos0);
			Cudd_RecursiveDerefZdd(dd, zPos1);
			// only zRes0 and zRes1 are refed at this point

			zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 );
			if ( zRes == NULL ) 
			{
				Cudd_RecursiveDerefZdd(dd, zRes0);
				Cudd_RecursiveDerefZdd(dd, zRes1);
				return NULL;
			}
			cuddDeref( zRes0 );
			cuddDeref( zRes1 );
		}

		cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes );
		return zRes;
	}
}
Exemplo n.º 14
0
/**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]

******************************************************************************/
DdNode	*
cuddMakeBddFromZddCover(
  DdManager * dd,
  DdNode * node)
{
    DdNode	*neW;
    int		v;
    DdNode	*f1, *f0, *fd;
    DdNode	*b1, *b0, *bd;
    DdNode	*T, *E;

    statLine(dd);
    if (node == dd->one)
	return(dd->one);
    if (node == dd->zero)
	return(Cudd_Not(dd->one));

    /* Check cache */
    neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node);
    if (neW)
	return(neW);

    v = Cudd_Regular(node)->index;	/* either yi or zi */
    cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);

    b1 = cuddMakeBddFromZddCover(dd, f1);
    if (!b1) {
	Cudd_RecursiveDerefZdd(dd, f1);
	Cudd_RecursiveDerefZdd(dd, f0);
	Cudd_RecursiveDerefZdd(dd, fd);
	return(NULL);
    }
    Cudd_Ref(b1);
    b0 = cuddMakeBddFromZddCover(dd, f0);
    if (!b1) {
	Cudd_RecursiveDerefZdd(dd, f1);
	Cudd_RecursiveDerefZdd(dd, f0);
	Cudd_RecursiveDerefZdd(dd, fd);
	Cudd_RecursiveDeref(dd, b1);
	return(NULL);
    }
    Cudd_Ref(b0);
    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, f0);
    if (fd != dd->zero) {
	bd = cuddMakeBddFromZddCover(dd, fd);
	if (!bd) {
	    Cudd_RecursiveDerefZdd(dd, fd);
	    Cudd_RecursiveDeref(dd, b1);
	    Cudd_RecursiveDeref(dd, b0);
	    return(NULL);
	}
	Cudd_Ref(bd);
	Cudd_RecursiveDerefZdd(dd, fd);

	T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd));
	if (!T) {
	    Cudd_RecursiveDeref(dd, b1);
	    Cudd_RecursiveDeref(dd, b0);
	    Cudd_RecursiveDeref(dd, bd);
	    return(NULL);
	}
	T = Cudd_NotCond(T, T != NULL);
	Cudd_Ref(T);
	Cudd_RecursiveDeref(dd, b1);
	E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd));
	if (!E) {
	    Cudd_RecursiveDeref(dd, b0);
	    Cudd_RecursiveDeref(dd, bd);
	    Cudd_RecursiveDeref(dd, T);
	    return(NULL);
	}
	E = Cudd_NotCond(E, E != NULL);
	Cudd_Ref(E);
	Cudd_RecursiveDeref(dd, b0);
	Cudd_RecursiveDeref(dd, bd);
    }
    else {
	Cudd_RecursiveDerefZdd(dd, fd);
	T = b1;
	E = b0;
    }

    if (Cudd_IsComplement(T)) {
	neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E));
	if (!neW) {
	    Cudd_RecursiveDeref(dd, T);
	    Cudd_RecursiveDeref(dd, E);
	    return(NULL);
	}
	neW = Cudd_Not(neW);
    }
    else {
	neW = cuddUniqueInterIVO(dd, v / 2, T, E);
	if (!neW) {
	    Cudd_RecursiveDeref(dd, T);
	    Cudd_RecursiveDeref(dd, E);
	    return(NULL);
	}
    }
    Cudd_Ref(neW);
    Cudd_RecursiveDeref(dd, T);
    Cudd_RecursiveDeref(dd, E);

    cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW);
    Cudd_Deref(neW);
    return(neW);

} /* end of cuddMakeBddFromZddCover */
Exemplo n.º 15
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddPortToBdd.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
zddPortToBddStep(
  DdManager * dd /* manager */,
  DdNode * f /* ZDD to be converted */,
  int  depth /* recursion depth */)
{
    DdNode *one, *zero, *T, *E, *res, *var;
    unsigned int index;
    unsigned int level;

    statLine(dd);
    one = DD_ONE(dd);
    zero = DD_ZERO(dd);
    if (f == zero) return(Cudd_Not(one));

    if (depth == dd->sizeZ) return(one);

    index = dd->invpermZ[depth];
    level = cuddIZ(dd,f->index);
    var = cuddUniqueInter(dd,index,one,Cudd_Not(one));
    if (var == NULL) return(NULL);
    cuddRef(var);

    if (level > (unsigned) depth) {
	E = zddPortToBddStep(dd,f,depth+1);
	if (E == NULL) {
	    Cudd_RecursiveDeref(dd,var);
	    return(NULL);
	}
	cuddRef(E);
	res = cuddBddIteRecur(dd,var,Cudd_Not(one),E);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd,var);
	    Cudd_RecursiveDeref(dd,E);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(dd,var);
	Cudd_RecursiveDeref(dd,E);
	cuddDeref(res);
	return(res);
    }

    res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f);
    if (res != NULL) {
	Cudd_RecursiveDeref(dd,var);
	return(res);
    }

    T = zddPortToBddStep(dd,cuddT(f),depth+1);
    if (T == NULL) {
	Cudd_RecursiveDeref(dd,var);
	return(NULL);
    }
    cuddRef(T);
    E = zddPortToBddStep(dd,cuddE(f),depth+1);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,var);
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);

    res = cuddBddIteRecur(dd,var,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd,var);
	Cudd_RecursiveDeref(dd,T);
	Cudd_RecursiveDeref(dd,E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(dd,var);
    Cudd_RecursiveDeref(dd,T);
    Cudd_RecursiveDeref(dd,E);
    cuddDeref(res);

    cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res);

    return(res);

} /* end of zddPortToBddStep */
Exemplo n.º 16
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
zddPortFromBddStep(
  DdManager * dd,
  DdNode * B,
  int  expected)
{
    DdNode	*res, *prevZdd, *t, *e;
    DdNode	*Breg, *Bt, *Be;
    int		id, level;

    statLine(dd);
    /* Terminal cases. */
    if (B == Cudd_Not(DD_ONE(dd)))
	return(DD_ZERO(dd));
    if (B == DD_ONE(dd)) {
	if (expected >= dd->sizeZ) {
	    return(DD_ONE(dd));
	} else {
	    return(dd->univ[expected]);
	}
    }

    Breg = Cudd_Regular(B);

    /* Computed table look-up. */
    res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B);
    if (res != NULL) {
	level = cuddI(dd,Breg->index);
	/* Adding DC vars. */
	if (expected < level) {
	    /* Add suppressed variables. */
	    cuddRef(res);
	    for (level--; level >= expected; level--) {
		prevZdd = res;
		id = dd->invperm[level];
		res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
		if (res == NULL) {
		    Cudd_RecursiveDerefZdd(dd, prevZdd);
		    return(NULL);
		}
		cuddRef(res);
		Cudd_RecursiveDerefZdd(dd, prevZdd);
	    }
	    cuddDeref(res);
	}
	return(res);
    }	/* end of cache look-up */

    if (Cudd_IsComplement(B)) {
	Bt = Cudd_Not(cuddT(Breg));
	Be = Cudd_Not(cuddE(Breg));
    } else {
	Bt = cuddT(Breg);
	Be = cuddE(Breg);
    }

    id = Breg->index;
    level = cuddI(dd,id);
    t = zddPortFromBddStep(dd, Bt, level+1);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = zddPortFromBddStep(dd, Be, level+1);
    if (e == NULL) {
	Cudd_RecursiveDerefZdd(dd, t);
	return(NULL);
    }
    cuddRef(e);
    res = cuddZddGetNode(dd, id, t, e);
    if (res == NULL) {
	Cudd_RecursiveDerefZdd(dd, t);
	Cudd_RecursiveDerefZdd(dd, e);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDerefZdd(dd, t);
    Cudd_RecursiveDerefZdd(dd, e);

    cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res);

    for (level--; level >= expected; level--) {
	prevZdd = res;
	id = dd->invperm[level];
	res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
	if (res == NULL) {
	    Cudd_RecursiveDerefZdd(dd, prevZdd);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDerefZdd(dd, prevZdd);
    }

    cuddDeref(res);
    return(res);

} /* end of zddPortFromBddStep */
Exemplo n.º 17
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_addBddBooleanMap.]

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

  SideEffects [None]

  SeeAlso     [addBddDoStrictThreshold]

******************************************************************************/
static DdNode *
addBddBooleanMap(
  DdManager * dd,
  DdNode * f)
{
    DdNode *res, *T, *E;
    DdNode *fv, *fvn;
    int v;

    statLine(dd);
    /* Check terminal case. */
    if (cuddIsConstant(f)) {
      if ((f != DD_TRUE(dd)) && (f != DD_FALSE(dd))) {
        (void)fprintf(dd->err, "Error: Can only convert Add with FALSE or TRUE leaves to Bdd.");
        return(NULL);
      }
      return(Cudd_NotCond(DD_TRUE(dd), f == DD_FALSE(dd)));
    }

    /* Check cache. */
    res = cuddCacheLookup1(dd,addBddBooleanMap,f);
    if (res != NULL) return(res);

    /* Recursive step. */
    v = f->index;
    fv = cuddT(f); fvn = cuddE(f);

    T = addBddBooleanMap(dd,fv);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = addBddBooleanMap(dd,fvn);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd, T);
	return(NULL);
    }
    cuddRef(E);
    if (Cudd_IsComplement(T)) {
	res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, T);
	    Cudd_RecursiveDeref(dd, E);
	    return(NULL);
	}
	res = Cudd_Not(res);
    } else {
	res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, T);
	    Cudd_RecursiveDeref(dd, E);
	    return(NULL);
	}
    }
    cuddDeref(T);    
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,addBddBooleanMap,f,res);

    return(res);

} /* end of addBddBooleanMap */
Exemplo n.º 18
0
/**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     []

******************************************************************************/
DdNode *
cuddAddBddDoPattern(
  DdManager * dd,
  DdNode * f)
{
    DdNode *res, *T, *E;
    DdNode *fv, *fvn;
    int v;

    /* NuSMV: begin add */
    abort(); /* NOT USED BY NUSMV */
    /* NuSMV: begin end */

    statLine(dd);
    /* Check terminal case. */
    if (cuddIsConstant(f)) {
	return(Cudd_NotCond(DD_TRUE(dd),f == DD_FALSE(dd)));
    }

    /* Check cache. */
    res = cuddCacheLookup1(dd,Cudd_addBddPattern,f);
    if (res != NULL) return(res);

    /* Recursive step. */
    v = f->index;
    fv = cuddT(f); fvn = cuddE(f);

    T = cuddAddBddDoPattern(dd,fv);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = cuddAddBddDoPattern(dd,fvn);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd, T);
	return(NULL);
    }
    cuddRef(E);
    if (Cudd_IsComplement(T)) {
	res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, T);
	    Cudd_RecursiveDeref(dd, E);
	    return(NULL);
	}
	res = Cudd_Not(res);
    } else {
	res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, T);
	    Cudd_RecursiveDeref(dd, E);
	    return(NULL);
	}
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,Cudd_addBddPattern,f,res);

    return(res);

} /* end of cuddAddBddDoPattern */
Exemplo n.º 19
0
/**Function*************************************************************

  Synopsis    [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF )
{
	DdNode * bRes, * bFR;
	statLine( dd );

	bFR = Cudd_Regular(bF);
	if ( cuddIsConstant(bFR) )
		return b0;

    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF)) )
    	return bRes;
	else
	{
		DdNode * bF0,   * bF1;
		DdNode * bPos0, * bPos1;
		DdNode * bNeg0, * bNeg1;
		DdNode * bRes0, * bRes1; 

		if ( bFR != bF ) // bF is complemented 
		{
			bF0 = Cudd_Not( cuddE(bFR) );
			bF1 = Cudd_Not( cuddT(bFR) );
		}
		else
		{
			bF0 = cuddE(bFR);
			bF1 = cuddT(bFR);
		}


		bPos0  = extraBddSpaceFromFunctionNeg( dd, bF0 );
		if ( bPos0 == NULL )
			return NULL;
		cuddRef( bPos0 );

		bPos1  = extraBddSpaceFromFunctionNeg( dd, bF1 );
		if ( bPos1 == NULL )
		{
			Cudd_RecursiveDeref( dd, bPos0 );
			return NULL;
		}
		cuddRef( bPos1 );

		bRes0  = cuddBddAndRecur( dd, bPos0, bPos1 );
		if ( bRes0 == NULL )
		{
			Cudd_RecursiveDeref( dd, bPos0 );
			Cudd_RecursiveDeref( dd, bPos1 );
			return NULL;
		}
		cuddRef( bRes0 );
		Cudd_RecursiveDeref( dd, bPos0 );
		Cudd_RecursiveDeref( dd, bPos1 );


		bNeg0  = extraBddSpaceFromFunctionPos( dd, bF0 );
		if ( bNeg0 == NULL )
		{
			Cudd_RecursiveDeref( dd, bRes0 );
			return NULL;
		}
		cuddRef( bNeg0 );

		bNeg1  = extraBddSpaceFromFunctionPos( dd, bF1 );
		if ( bNeg1 == NULL )
		{
			Cudd_RecursiveDeref( dd, bRes0 );
			Cudd_RecursiveDeref( dd, bNeg0 );
			return NULL;
		}
		cuddRef( bNeg1 );

		bRes1  = cuddBddAndRecur( dd, bNeg0, bNeg1 );
		if ( bRes1 == NULL )
		{
			Cudd_RecursiveDeref( dd, bRes0 );
			Cudd_RecursiveDeref( dd, bNeg0 );
			Cudd_RecursiveDeref( dd, bNeg1 );
			return NULL;
		}
		cuddRef( bRes1 );
		Cudd_RecursiveDeref( dd, bNeg0 );
		Cudd_RecursiveDeref( dd, bNeg1 );


		// consider the case when Res0 and Res1 are the same node 
		if ( bRes0 == bRes1 )
			bRes = bRes1;
		// consider the case when Res1 is complemented 
		else if ( Cudd_IsComplement(bRes1) ) 
		{
			bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) );
			if ( bRes == NULL ) 
			{
				Cudd_RecursiveDeref(dd,bRes0);
				Cudd_RecursiveDeref(dd,bRes1);
				return NULL;
			}
			bRes = Cudd_Not(bRes);
		} 
		else 
		{
			bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
			if ( bRes == NULL ) 
			{
				Cudd_RecursiveDeref(dd,bRes0);
				Cudd_RecursiveDeref(dd,bRes1);
				return NULL;
			}
		}
		cuddDeref( bRes0 );
		cuddDeref( bRes1 );

		cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes );
		return bRes;
	}
}
Exemplo n.º 20
0
/**Function*************************************************************

  Synopsis    [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA )
{
	DdNode * bRes;
	statLine( dd );

	if ( zA == z0 )
		return b1;
	if ( zA == z1 )
		return b0;

    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA)) )
    	return bRes;
	else
	{
		DdNode * bP0, * bP1;
		DdNode * bN0, * bN1;
		DdNode * bRes0, * bRes1; 

		bP0  = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
		if ( bP0 == NULL )
			return NULL;
		cuddRef( bP0 );

		bP1  = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) );
		if ( bP1 == NULL )
		{
			Cudd_RecursiveDeref( dd, bP0 );
			return NULL;
		}
		cuddRef( bP1 );

		bRes0  = cuddBddAndRecur( dd, bP0, bP1 );
		if ( bRes0 == NULL )
		{
			Cudd_RecursiveDeref( dd, bP0 );
			Cudd_RecursiveDeref( dd, bP1 );
			return NULL;
		}
		cuddRef( bRes0 );
		Cudd_RecursiveDeref( dd, bP0 );
		Cudd_RecursiveDeref( dd, bP1 );


		bN0  = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
		if ( bN0 == NULL )
		{
			Cudd_RecursiveDeref( dd, bRes0 );
			return NULL;
		}
		cuddRef( bN0 );

		bN1  = extraBddSpaceFromMatrixPos( dd, cuddT(zA) );
		if ( bN1 == NULL )
		{
			Cudd_RecursiveDeref( dd, bRes0 );
			Cudd_RecursiveDeref( dd, bN0 );
			return NULL;
		}
		cuddRef( bN1 );

		bRes1  = cuddBddAndRecur( dd, bN0, bN1 );
		if ( bRes1 == NULL )
		{
			Cudd_RecursiveDeref( dd, bRes0 );
			Cudd_RecursiveDeref( dd, bN0 );
			Cudd_RecursiveDeref( dd, bN1 );
			return NULL;
		}
		cuddRef( bRes1 );
		Cudd_RecursiveDeref( dd, bN0 );
		Cudd_RecursiveDeref( dd, bN1 );


		// consider the case when Res0 and Res1 are the same node 
		if ( bRes0 == bRes1 )
			bRes = bRes1;
		// consider the case when Res1 is complemented 
		else if ( Cudd_IsComplement(bRes1) ) 
		{
			bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) );
			if ( bRes == NULL ) 
			{
				Cudd_RecursiveDeref(dd,bRes0);
				Cudd_RecursiveDeref(dd,bRes1);
				return NULL;
			}
			bRes = Cudd_Not(bRes);
		} 
		else 
		{
			bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 );
			if ( bRes == NULL ) 
			{
				Cudd_RecursiveDeref(dd,bRes0);
				Cudd_RecursiveDeref(dd,bRes1);
				return NULL;
			}
		}
		cuddDeref( bRes0 );
		cuddDeref( bRes1 );

		cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes );
		return bRes;
	}
}
Exemplo n.º 21
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_BddTo01Add.]

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

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
ddBddTo01AddRecur(
  DdManager * dd,
  DdNode * B)
{
    DdNode *res, *res1, *T, *E, *Bt, *Be;
    int complement = 0;

    statLine(dd);

    if (B == DD_TRUE(dd)) {
      return DD_ONE(dd);
    } else if (B == Cudd_Not(DD_TRUE(dd))) {
      return DD_ZERO(dd);
    }

    /* Check visited table */
    res = cuddCacheLookup1(dd,ddBddTo01AddRecur,B);
    if (res != NULL) return(res);

    if (Cudd_IsComplement(B)) {
	complement = 1;
	Bt = cuddT(Cudd_Regular(B));
	Be = cuddE(Cudd_Regular(B));
    } else {
	Bt = cuddT(B);
	Be = cuddE(B);
    }

    T = ddBddTo01AddRecur(dd, Bt);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = ddBddTo01AddRecur(dd, Be);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd, T);
	return(NULL);
    }
    cuddRef(E);

    /* No need to check for T == E, because it is guaranteed not to happen. */
    res = cuddUniqueInter(dd, (int) Cudd_Regular(B)->index, T, E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd ,T);
	Cudd_RecursiveDeref(dd ,E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    if (complement) {
	cuddRef(res);
	res1 = cuddAddCmpl01Recur(dd, res);
	if (res1 == NULL) {
	    Cudd_RecursiveDeref(dd, res);
	    return(NULL);
	}
	cuddRef(res1);
	Cudd_RecursiveDeref(dd, res);
	res = res1;
	cuddDeref(res);
    }

    /* Store result. */
    cuddCacheInsert1(dd,ddBddTo01AddRecur,B,res);

    return(res);

} /* end of ddBddTo01AddRecur */