Esempio n. 1
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 */
Esempio n. 2
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_addBddInterval.]

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

  SideEffects [None]

  SeeAlso     [addBddDoThreshold addBddDoStrictThreshold]

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

    statLine(dd);
    /* Check terminal case. */
    if (cuddIsConstant(f)) {
	return(Cudd_NotCond(DD_TRUE(dd),cuddV(f) < cuddV(l) || cuddV(f) > cuddV(u)));
    }

    /* Check cache. */
    res = cuddCacheLookup(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u);
    if (res != NULL) return(res);

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

    T = addBddDoInterval(dd,fv,l,u);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = addBddDoInterval(dd,fvn,l,u);
    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. */
    cuddCacheInsert(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u,res);

    return(res);

} /* end of addBddDoInterval */
Esempio n. 3
0
DdNode*
cuddauxAddGuardOfNodeRecur(DdManager* manager, DdNode* f, DdNode* h)
{
  DdNode *one, *res, *T, *E;
  int topf, toph;

  /* Handle terminal cases */
  one = DD_ONE(manager);
  if (f==h){
    return(one);
  }
  topf = cuddI(manager,f->index);
  toph = cuddI(manager,h->index);
  if (topf >= toph){
    return Cudd_Not(one);
  }

  /* Look in the cache */
  res = cuddCacheLookup2(manager,Cuddaux_addGuardOfNode,f,h);
  if (res != NULL)
    return(res);

  T = cuddauxAddGuardOfNodeRecur(manager,cuddT(f),h);
  if (T == NULL)
    return(NULL);
  cuddRef(T);
  E = cuddauxAddGuardOfNodeRecur(manager,cuddE(f),h);
  if (E == NULL){
    Cudd_IterDerefBdd(manager, T);
    return(NULL);
  }
  cuddRef(E);
  if (T == E){
    res = T;
  }
  else {
    if (Cudd_IsComplement(T)){
      res = cuddUniqueInter(manager,f->index,Cudd_Not(T),Cudd_Not(E));
      if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
      }
      res = Cudd_Not(res);
    }
    else {
      res = cuddUniqueInter(manager,f->index,T,E);
      if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
      }
    }
  }
  cuddDeref(T);
  cuddDeref(E);
  cuddCacheInsert2(manager,Cuddaux_addGuardOfNode,f,h,res);
  return(res);
}
Esempio n. 4
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_addBddStrictThreshold.]

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

  SideEffects [None]

  SeeAlso     [addBddDoThreshold]

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

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

    /* Check cache. */
    res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val);
    if (res != NULL) return(res);

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

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

    E = addBddDoStrictThreshold(dd,fvn,val);
    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. */
    cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res);

    return(res);

} /* end of addBddDoStrictThreshold */
Esempio 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;
	}
}
Esempio n. 6
0
/**Function********************************************************************

  Synopsis    [Computes a caching cube.]

  Description [It is known that bVars is a cube representing a subset of bVarsAll
  this function computes the canonical representation of the pair (bVarsAll, bVars) 
  by one DD node the convention is the following: if ( bVars == bVarsAll), return bVarsAll,
  otherwise return ITE(x, cuddT(bVarsAll), bVars), where x is the topmost var in bVarsAll.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode * extraCachingCube( DdManager * dd, DdNode * bVarsAll, DdNode * bVars )
{
	if ( bVars == bVarsAll)  
		return bVarsAll;
	else
		return cuddUniqueInter( dd, bVarsAll->index, cuddT(bVarsAll), bVars );
	// because bVarsAll is positive cube, cuddT(bVarsAll) is never complemented
}
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_addIthBit.]

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

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
addDoIthBit(
  DdManager * dd,
  DdNode * f,
  DdNode * index)
{
    DdNode *res, *T, *E;
    DdNode *fv, *fvn;
    int mask, value;
    int v;

    statLine(dd);
    /* Check terminal case. */
    if (cuddIsConstant(f)) {
	mask = 1 << ((int) cuddV(index));
	value = (int) cuddV(f);
	return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd));
    }

    /* Check cache. */
    res = cuddCacheLookup2(dd,addDoIthBit,f,index);
    if (res != NULL) return(res);

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

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

    E = addDoIthBit(dd,fvn,index);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd, T);
	return(NULL);
    }
    cuddRef(E);

    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. */
    cuddCacheInsert2(dd,addDoIthBit,f,index,res);

    return(res);

} /* end of addDoIthBit */
Esempio n. 8
0
/**Function********************************************************************

  Synopsis [This function prepares an array of variables which have not been
  encountered so far when traversing the procedure cuddSplitSetRecur.]

  Description [This function prepares an array of variables which have not been
  encountered so far when traversing the procedure cuddSplitSetRecur. This
  array is then used to extract the required number of minterms from a constant
  1. The algorithm guarantees that the size of BDD will be utmost \log(n).]

  SideEffects [None]

******************************************************************************/
static DdNode *
selectMintermsFromUniverse(
  DdManager * manager,
  int * varSeen,
  double  n)
{
    int numVars;
    int i, size, j;
     DdNode *one, *zero, *result;
    DdNode **vars;

    numVars = 0;
    size = manager->size;
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Count the number of variables not encountered so far in procedure
    ** cuddSplitSetRecur.
    */
    for (i = size-1; i >= 0; i--) {
	if(varSeen[i] == 0)
	    numVars++;
    }
    vars = ALLOC(DdNode *, numVars);
    if (!vars) {
	manager->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }

    j = 0;
    for (i = size-1; i >= 0; i--) {
	if(varSeen[i] == 0) {
	    vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero);
	    cuddRef(vars[j]);
	    j++;
	}
    }

    /* Compute a function which has n minterms and depends on at most
    ** numVars variables.
    */
    result = mintermsFromUniverse(manager,vars,numVars,n, 0);
    if (result) 
	cuddRef(result);

    for (i = 0; i < numVars; i++)
	Cudd_RecursiveDeref(manager,vars[i]);
    FREE(vars);

    return(result);

} /* end of selectMintermsFromUniverse */
Esempio n. 9
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 */
Esempio n. 10
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 */
/**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 */
Esempio n. 12
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 */
Esempio n. 13
0
/**
  @brief Performs the recursive step of addScalarInverse.

  @return a pointer to the resulting %ADD in case of success. Returns
  NULL if any discriminants smaller than epsilon is encountered.

  @sideeffect None

*/
DdNode *
cuddAddScalarInverseRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * epsilon)
{
    DdNode *t, *e, *res;
    CUDD_VALUE_TYPE value;

    statLine(dd);
    if (cuddIsConstant(f)) {
	if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL);
	value = 1.0 / cuddV(f);
	res = cuddUniqueConst(dd,value);
	return(res);
    }

    res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon);
    if (res != NULL) return(res);

    checkWhetherToGiveUp(dd);

    t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon);
    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);

    cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res);

    return(res);

} /* end of cuddAddScalarInverseRecur */
Esempio n. 14
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 */
Esempio n. 15
0
/**Function********************************************************************

  Synopsis    [Selects pairs from R using a priority function.]

  Description [Selects pairs from a relation R(x,y) (given as a BDD)
  in such a way that a given x appears in one pair only. Uses a
  priority function to determine which y should be paired to a given x.
  Cudd_PrioritySelect returns a pointer to
  the selected function if successful; NULL otherwise.
  Three of the arguments--x, y, and z--are vectors of BDD variables.
  The first two are the variables on which R depends. The third vectore
  is a vector of auxiliary variables, used during the computation. This
  vector is optional. If a NULL value is passed instead,
  Cudd_PrioritySelect will create the working variables on the fly.
  The sizes of x and y (and z if it is not NULL) should equal n.
  The priority function Pi can be passed as a BDD, or can be built by
  Cudd_PrioritySelect. If NULL is passed instead of a DdNode *,
  parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the
  priority function. (Pifunc is a pointer to a C function.) If Pi is not
  NULL, then Pifunc is ignored. Pifunc should have the same interface as
  the standard priority functions (e.g., Cudd_Dxygtdxz).
  Cudd_PrioritySelect and Cudd_CProjection can sometimes be used
  interchangeably. Specifically, calling Cudd_PrioritySelect with
  Cudd_Xgty as Pifunc produces the same result as calling
  Cudd_CProjection with the all-zero minterm as reference minterm.
  However, depending on the application, one or the other may be
  preferable:
  <ul>
  <li> When extracting representatives from an equivalence relation,
  Cudd_CProjection has the advantage of nor requiring the auxiliary
  variables.
  <li> When computing matchings in general bipartite graphs,
  Cudd_PrioritySelect normally obtains better results because it can use
  more powerful matching schemes (e.g., Cudd_Dxygtdxz).
  </ul>
  ]

  SideEffects [If called with z == NULL, will create new variables in
  the manager.]

  SeeAlso     [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty
  Cudd_bddAdjPermuteX Cudd_CProjection]

******************************************************************************/
DdNode *
Cudd_PrioritySelect(
  DdManager * dd /* manager */,
  DdNode * R /* BDD of the relation */,
  DdNode ** x /* array of x variables */,
  DdNode ** y /* array of y variables */,
  DdNode ** z /* array of z variables (optional: may be NULL) */,
  DdNode * Pi /* BDD of the priority function (optional: may be NULL) */,
  int  n /* size of x, y, and z */,
  DdNode * (*Pifunc)(DdManager *, int, DdNode **, DdNode **, DdNode **) /* function used to build Pi if it is NULL */)
{
    DdNode *res = NULL;
    DdNode *zcube = NULL;
    DdNode *Rxz, *Q;
    int createdZ = 0;
    int createdPi = 0;
    int i;

    /* Create z variables if needed. */
    if (z == NULL) {
	if (Pi != NULL) return(NULL);
	z = ALLOC(DdNode *,n);
	if (z == NULL) {
	    dd->errorCode = CUDD_MEMORY_OUT;
	    return(NULL);
	}
	createdZ = 1;
	for (i = 0; i < n; i++) {
	    if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame;
	    z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one));
	    if (z[i] == NULL) goto endgame;
	}
    }

    /* Create priority function BDD if needed. */
    if (Pi == NULL) {
	Pi = Pifunc(dd,n,x,y,z);
	if (Pi == NULL) goto endgame;
	createdPi = 1;
	cuddRef(Pi);
    }

    /* Initialize abstraction cube. */
    zcube = DD_ONE(dd);
    cuddRef(zcube);
    for (i = n - 1; i >= 0; i--) {
	DdNode *tmpp;
	tmpp = Cudd_bddAnd(dd,z[i],zcube);
	if (tmpp == NULL) goto endgame;
	cuddRef(tmpp);
	Cudd_RecursiveDeref(dd,zcube);
	zcube = tmpp;
    }

    /* Compute subset of (x,y) pairs. */
    Rxz = Cudd_bddSwapVariables(dd,R,y,z,n);
    if (Rxz == NULL) goto endgame;
    cuddRef(Rxz);
    Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube);
    if (Q == NULL) {
	Cudd_RecursiveDeref(dd,Rxz);
	goto endgame;
    }
    cuddRef(Q);
    Cudd_RecursiveDeref(dd,Rxz);
    res = Cudd_bddAnd(dd,R,Cudd_Not(Q));
    if (res == NULL) {
	Cudd_RecursiveDeref(dd,Q);
	goto endgame;
    }
    cuddRef(res);
    Cudd_RecursiveDeref(dd,Q);

endgame:
    if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube);
    if (createdZ) {
	FREE(z);
    }
    if (createdPi) {
	Cudd_RecursiveDeref(dd,Pi);
    }
    if (res != NULL) cuddDeref(res);
    return(res);

} /* Cudd_PrioritySelect */
Esempio n. 16
0
/**Function********************************************************************

  Synopsis    [Tests Walsh matrix multiplication.]

  Description [Tests Walsh matrix multiplication.  Return 1 if successful;
  0 otherwise.]

  SideEffects [May create new variables in the manager.]

  SeeAlso     []

******************************************************************************/
static int
testWalsh(
  DdManager *dd /* manager */,
  int N /* number of variables */,
  int cmu /* use CMU approach to matrix multiplication */,
  int approach /* reordering approach */,
  int pr /* verbosity level */)
{
    DdNode *walsh1, *walsh2, *wtw;
    DdNode **x, **v, **z;
    int i, retval;
    DdNode *_true = DD_TRUE(dd);
    DdNode *_false = DD_FALSE(dd);

    if (N > 3) {
	x = ALLOC(DdNode *,N);
	v = ALLOC(DdNode *,N);
	z = ALLOC(DdNode *,N);

	for (i = N-1; i >= 0; i--) {
	    Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,_true,_false));
	    Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,_true,_false));
	    Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,_true,_false));
	}
	Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N));
	if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);}
	Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N));
	if (cmu) {
	    Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N));
	} else {
	    Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N));
	}
	if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);}

	if (approach != CUDD_REORDER_NONE) {
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		return(0);
	    }
#endif
	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
		return(0);
	    }
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		return(0);
	    }
#endif
	    if (approach == CUDD_REORDER_SYMM_SIFT ||
	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
		Cudd_SymmProfile(dd,0,dd->size-1);
	    }
	}
	/* Clean up. */
	Cudd_RecursiveDeref(dd, wtw);
	Cudd_RecursiveDeref(dd, walsh1);
	Cudd_RecursiveDeref(dd, walsh2);
	for (i=0; i < N; i++) {
	    Cudd_RecursiveDeref(dd, x[i]);
	    Cudd_RecursiveDeref(dd, v[i]);
	    Cudd_RecursiveDeref(dd, z[i]);
	}
	FREE(x);
	FREE(v);
	FREE(z);
    }
/**Function********************************************************************

  Synopsis    [Creates a new DD manager.]

  Description [Creates a new DD manager, initializes the table, the
  basic constants and the projection functions. If maxMemory is 0,
  Cudd_Init decides suitable values for the maximum size of the cache
  and for the limit for fast unique table growth based on the available
  memory. Returns a pointer to the manager if successful; NULL
  otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_Quit]

******************************************************************************/
DdManager *
Cudd_Init(
  unsigned int numVars /* initial number of BDD variables (i.e., subtables) */,
  unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */,
  unsigned int numSlots /* initial size of the unique tables */,
  unsigned int cacheSize /* initial size of the cache */,
  unsigned long maxMemory /* target maximum memory occupation */)
{
    DdManager *unique;
    int i,result;
    DdNode *one, *zero;
    unsigned int maxCacheSize;
    unsigned int looseUpTo;
    extern void (*MMoutOfMemory)(long);
    void (*saveHandler)(long);

    if (maxMemory == 0) {
	maxMemory = getSoftDataLimit();
    }
    looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) /
				DD_MAX_LOOSE_FRACTION);
    unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo);
    unique->maxmem = (unsigned) maxMemory / 10 * 9;
    if (unique == NULL) return(NULL);
    maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) /
				   DD_MAX_CACHE_FRACTION);
    result = cuddInitCache(unique,cacheSize,maxCacheSize);
    if (result == 0) return(NULL);

    saveHandler = MMoutOfMemory;
    MMoutOfMemory = Cudd_OutOfMem;
    unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4);
    MMoutOfMemory = saveHandler;
    if (unique->stash == NULL) {
	(void) fprintf(unique->err,"Unable to set aside memory\n");
    }

    /* Initialize constants. */
    unique->one = cuddUniqueConst(unique,1.0);
    if (unique->one == NULL) return(0);
    cuddRef(unique->one);
    unique->zero = cuddUniqueConst(unique,0.0);
    if (unique->zero == NULL) return(0);
    cuddRef(unique->zero);
#ifdef HAVE_IEEE_754
    if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 ||
	DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) {
	(void) fprintf(unique->err,"Warning: Crippled infinite values\n");
	(void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n");
    }
#endif
    unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL);
    if (unique->plusinfinity == NULL) return(0);
    cuddRef(unique->plusinfinity);
    unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL);
    if (unique->minusinfinity == NULL) return(0);
    cuddRef(unique->minusinfinity);
    unique->background = unique->zero;

    /* The logical zero is different from the CUDD_VALUE_TYPE zero! */
    one = unique->one;
    zero = Cudd_Not(one);
    /* Create the projection functions. */
    unique->vars = ALLOC(DdNodePtr,unique->maxSize);
    if (unique->vars == NULL) {
	unique->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    for (i = 0; i < unique->size; i++) {
	unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
	if (unique->vars[i] == NULL) return(0);
	cuddRef(unique->vars[i]);
    }

    if (unique->sizeZ)
	cuddZddInitUniv(unique);

    unique->memused += sizeof(DdNode *) * unique->maxSize;

    return(unique);

} /* end of Cudd_Init */
Esempio n. 18
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddIsop.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddIsop]

******************************************************************************/
DdNode	*
cuddZddIsop(
  DdManager * dd,
  DdNode * L,
  DdNode * U,
  DdNode ** zdd_I)
{
    DdNode	*one = DD_ONE(dd);
    DdNode	*zero = Cudd_Not(one);
    DdNode	*zdd_one = DD_ONE(dd);
    DdNode	*zdd_zero = DD_ZERO(dd);
    int		v, top_l, top_u;
    DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
    DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
    DdNode	*Isub0, *Isub1, *Id;
    DdNode	*zdd_Isub0, *zdd_Isub1, *zdd_Id;
    DdNode	*x;
    DdNode	*term0, *term1, *sum;
    DdNode	*Lv, *Uv, *Lnv, *Unv;
    DdNode	*r, *y, *z;
    int		index;
    DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *);

    statLine(dd);
    if (L == zero) {
	*zdd_I = zdd_zero;
    	return(zero);
    }
    if (U == one) {
	*zdd_I = zdd_one;
    	return(one);
    }

    if (U == zero || L == one) {
	printf("*** ERROR : illegal condition for ISOP (U < L).\n");
	exit(1);
    }

    /* Check the cache. We store two results for each recursive call.
    ** One is the BDD, and the other is the ZDD. Both are needed.
    ** Hence we need a double hit in the cache to terminate the
    ** recursion. Clearly, collisions may evict only one of the two
    ** results. */
    cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop;
    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
    if (r) {
	*zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
	if (*zdd_I)
	    return(r);
	else {
	    /* The BDD result may have been dead. In that case
	    ** cuddCacheLookup2 would have called cuddReclaim,
	    ** whose effects we now have to undo. */
	    cuddRef(r);
	    Cudd_RecursiveDeref(dd, r);
	}
    }

    top_l = dd->perm[Cudd_Regular(L)->index];
    top_u = dd->perm[Cudd_Regular(U)->index];
    v = ddMin(top_l, top_u);

    /* Compute cofactors. */
    if (top_l == v) {
	index = Cudd_Regular(L)->index;
    	Lv = Cudd_T(L);
    	Lnv = Cudd_E(L);
    	if (Cudd_IsComplement(L)) {
    	    Lv = Cudd_Not(Lv);
    	    Lnv = Cudd_Not(Lnv);
    	}
    }
    else {
	index = Cudd_Regular(U)->index;
        Lv = Lnv = L;
    }

    if (top_u == v) {
    	Uv = Cudd_T(U);
    	Unv = Cudd_E(U);
    	if (Cudd_IsComplement(U)) {
    	    Uv = Cudd_Not(Uv);
    	    Unv = Cudd_Not(Unv);
    	}
    }
    else {
        Uv = Unv = U;
    }

    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
    if (Lsub0 == NULL)
	return(NULL);
    Cudd_Ref(Lsub0);
    Usub0 = Unv;
    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
    if (Lsub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	return(NULL);
    }
    Cudd_Ref(Lsub1);
    Usub1 = Uv;

    Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
    if (Isub0 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
	(Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Isub0);
    Cudd_Ref(zdd_Isub0);
    Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
    if (Isub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
	(Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Isub1);
    Cudd_Ref(zdd_Isub1);
    Cudd_RecursiveDeref(dd, Lsub0);
    Cudd_RecursiveDeref(dd, Lsub1);

    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
    if (Lsuper0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	return(NULL);
    }
    Cudd_Ref(Lsuper0);
    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
    if (Lsuper1 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	return(NULL);
    }
    Cudd_Ref(Lsuper1);
    Usuper0 = Unv;
    Usuper1 = Uv;

    /* Ld = Lsuper0 + Lsuper1 */
    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
    if (Ld == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	return(NULL);
    }
    Ld = Cudd_Not(Ld);
    Cudd_Ref(Ld);
    /* Ud = Usuper0 * Usuper1 */
    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
    if (Ud == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	Cudd_RecursiveDeref(dd, Ld);
	return(NULL);
    }
    Cudd_Ref(Ud);
    Cudd_RecursiveDeref(dd, Lsuper0);
    Cudd_RecursiveDeref(dd, Lsuper1);

    Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
    if (Id == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Ld);
	Cudd_RecursiveDeref(dd, Ud);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Id))) &&
	(Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Id);
    Cudd_Ref(zdd_Id);
    Cudd_RecursiveDeref(dd, Ld);
    Cudd_RecursiveDeref(dd, Ud);

    x = cuddUniqueInter(dd, index, one, zero);
    if (x == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	return(NULL);
    }
    Cudd_Ref(x);
    /* term0 = x * Isub0 */
    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
    if (term0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, x);
	return(NULL);
    }
    Cudd_Ref(term0);
    Cudd_RecursiveDeref(dd, Isub0);
    /* term1 = x * Isub1 */
    term1 = cuddBddAndRecur(dd, x, Isub1);
    if (term1 == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, x);
	Cudd_RecursiveDeref(dd, term0);
	return(NULL);
    }
    Cudd_Ref(term1);
    Cudd_RecursiveDeref(dd, x);
    Cudd_RecursiveDeref(dd, Isub1);
    /* sum = term0 + term1 */
    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
    if (sum == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, term0);
	Cudd_RecursiveDeref(dd, term1);
	return(NULL);
    }
    sum = Cudd_Not(sum);
    Cudd_Ref(sum);
    Cudd_RecursiveDeref(dd, term0);
    Cudd_RecursiveDeref(dd, term1);
    /* r = sum + Id */
    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
    r = Cudd_NotCond(r, r != NULL);
    if (r == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, sum);
	return(NULL);
    }
    Cudd_Ref(r);
    Cudd_RecursiveDeref(dd, sum);
    Cudd_RecursiveDeref(dd, Id);

    if (zdd_Isub0 != zdd_zero) {
	z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
	if (z == NULL) {
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
	    Cudd_RecursiveDeref(dd, r);
	    return(NULL);
	}
    }
    else {
	z = zdd_Id;
    }
    Cudd_Ref(z);
    if (zdd_Isub1 != zdd_zero) {
	y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
	if (y == NULL) {
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
	    Cudd_RecursiveDeref(dd, r);
	    Cudd_RecursiveDerefZdd(dd, z);
	    return(NULL);
	}
    }
    else
	y = z;
    Cudd_Ref(y);

    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
    Cudd_RecursiveDerefZdd(dd, zdd_Id);
    Cudd_RecursiveDerefZdd(dd, z);

    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
    cuddCacheInsert2(dd, cacheOp, L, U, y);

    Cudd_Deref(r);
    Cudd_Deref(y);
    *zdd_I = y;
    /*
    if (Cudd_Regular(r)->index != y->index / 2) {
	printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
    }
    */
    return(r);

} /* end of cuddZddIsop */
Esempio n. 19
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_bddIsop.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_bddIsop]

******************************************************************************/
DdNode	*
cuddBddIsop(
  DdManager * dd,
  DdNode * L,
  DdNode * U)
{
    DdNode	*one = DD_ONE(dd);
    DdNode	*zero = Cudd_Not(one);
    int		v, top_l, top_u;
    DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
    DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
    DdNode	*Isub0, *Isub1, *Id;
    DdNode	*x;
    DdNode	*term0, *term1, *sum;
    DdNode	*Lv, *Uv, *Lnv, *Unv;
    DdNode	*r;
    int		index;

    statLine(dd);
    if (L == zero)
    	return(zero);
    if (U == one)
    	return(one);

    /* Check cache */
    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
    if (r)
    	return(r);

    top_l = dd->perm[Cudd_Regular(L)->index];
    top_u = dd->perm[Cudd_Regular(U)->index];
    v = ddMin(top_l, top_u);

    /* Compute cofactors */
    if (top_l == v) {
	index = Cudd_Regular(L)->index;
    	Lv = Cudd_T(L);
    	Lnv = Cudd_E(L);
    	if (Cudd_IsComplement(L)) {
    	    Lv = Cudd_Not(Lv);
    	    Lnv = Cudd_Not(Lnv);
    	}
    }
    else {
	index = Cudd_Regular(U)->index;
        Lv = Lnv = L;
    }

    if (top_u == v) {
    	Uv = Cudd_T(U);
    	Unv = Cudd_E(U);
    	if (Cudd_IsComplement(U)) {
    	    Uv = Cudd_Not(Uv);
    	    Unv = Cudd_Not(Unv);
    	}
    }
    else {
        Uv = Unv = U;
    }

    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
    if (Lsub0 == NULL)
	return(NULL);
    Cudd_Ref(Lsub0);
    Usub0 = Unv;
    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
    if (Lsub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	return(NULL);
    }
    Cudd_Ref(Lsub1);
    Usub1 = Uv;

    Isub0 = cuddBddIsop(dd, Lsub0, Usub0);
    if (Isub0 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	return(NULL);
    }
    Cudd_Ref(Isub0);
    Isub1 = cuddBddIsop(dd, Lsub1, Usub1);
    if (Isub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	Cudd_RecursiveDeref(dd, Isub0);
	return(NULL);
    }
    Cudd_Ref(Isub1);
    Cudd_RecursiveDeref(dd, Lsub0);
    Cudd_RecursiveDeref(dd, Lsub1);

    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
    if (Lsuper0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	return(NULL);
    }
    Cudd_Ref(Lsuper0);
    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
    if (Lsuper1 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	return(NULL);
    }
    Cudd_Ref(Lsuper1);
    Usuper0 = Unv;
    Usuper1 = Uv;

    /* Ld = Lsuper0 + Lsuper1 */
    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
    Ld = Cudd_NotCond(Ld, Ld != NULL);
    if (Ld == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	return(NULL);
    }
    Cudd_Ref(Ld);
    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
    if (Ud == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	Cudd_RecursiveDeref(dd, Ld);
	return(NULL);
    }
    Cudd_Ref(Ud);
    Cudd_RecursiveDeref(dd, Lsuper0);
    Cudd_RecursiveDeref(dd, Lsuper1);

    Id = cuddBddIsop(dd, Ld, Ud);
    if (Id == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDeref(dd, Ld);
	Cudd_RecursiveDeref(dd, Ud);
	return(NULL);
    }
    Cudd_Ref(Id);
    Cudd_RecursiveDeref(dd, Ld);
    Cudd_RecursiveDeref(dd, Ud);

    x = cuddUniqueInter(dd, index, one, zero);
    if (x == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDeref(dd, Id);
	return(NULL);
    }
    Cudd_Ref(x);
    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
    if (term0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDeref(dd, x);
	return(NULL);
    }
    Cudd_Ref(term0);
    Cudd_RecursiveDeref(dd, Isub0);
    term1 = cuddBddAndRecur(dd, x, Isub1);
    if (term1 == NULL) {
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDeref(dd, x);
	Cudd_RecursiveDeref(dd, term0);
	return(NULL);
    }
    Cudd_Ref(term1);
    Cudd_RecursiveDeref(dd, x);
    Cudd_RecursiveDeref(dd, Isub1);
    /* sum = term0 + term1 */
    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
    sum = Cudd_NotCond(sum, sum != NULL);
    if (sum == NULL) {
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDeref(dd, term0);
	Cudd_RecursiveDeref(dd, term1);
	return(NULL);
    }
    Cudd_Ref(sum);
    Cudd_RecursiveDeref(dd, term0);
    Cudd_RecursiveDeref(dd, term1);
    /* r = sum + Id */
    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
    r = Cudd_NotCond(r, r != NULL);
    if (r == NULL) {
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDeref(dd, sum);
	return(NULL);
    }
    Cudd_Ref(r);
    Cudd_RecursiveDeref(dd, sum);
    Cudd_RecursiveDeref(dd, Id);

    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);

    Cudd_Deref(r);
    return(r);

} /* end of cuddBddIsop */
Esempio n. 20
0
/**
  @brief Implements the recursive step of Cudd_bddClippingAnd.

  @details Takes the conjunction of two BDDs.

  @return a pointer to the result is successful; NULL otherwise.

  @sideeffect None

  @see cuddBddClippingAnd

*/
static DdNode *
cuddBddClippingAndRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  int  distance,
  int  direction)
{
    DdNode *F, *ft, *fe, *G, *gt, *ge;
    DdNode *one, *zero, *r, *t, *e;
    int topf, topg;
    unsigned int index;
    DD_CTFP cacheOp;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == g || g == one) return(f);
    if (f == one) return(g);
    if (distance == 0) {
	/* One last attempt at returning the right result. We sort of
	** cheat by calling Cudd_bddLeq. */
	if (Cudd_bddLeq(manager,f,g)) return(f);
	if (Cudd_bddLeq(manager,g,f)) return(g);
	if (direction == 1) {
	    if (Cudd_bddLeq(manager,f,Cudd_Not(g)) ||
		Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero);
	}
	return(Cudd_NotCond(one,(direction == 0)));
    }

    /* At this point f and g are not constant. */
    distance--;

    /* Check cache. Try to increase cache efficiency by sorting the
    ** pointers. */
    if (f > g) {
	DdNode *tmp = f;
	f = g; g = tmp;
    }
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    cacheOp = (DD_CTFP)
	(direction ? Cudd_bddClippingAnd : cuddBddClippingAnd);
    if (F->ref != 1 || G->ref != 1) {
	r = cuddCacheLookup2(manager, cacheOp, f, g);
	if (r != NULL) return(r);
    }

    checkWhetherToGiveUp(manager);

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
	index = F->index;
	ft = cuddT(F);
	fe = cuddE(F);
	if (Cudd_IsComplement(f)) {
	    ft = Cudd_Not(ft);
	    fe = Cudd_Not(fe);
	}
    } else {
	index = G->index;
	ft = fe = f;
    }

    if (topg <= topf) {
	gt = cuddT(G);
	ge = cuddE(G);
	if (Cudd_IsComplement(g)) {
	    gt = Cudd_Not(gt);
	    ge = Cudd_Not(ge);
	}
    } else {
	gt = ge = g;
    }

    t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction);
    if (e == NULL) {
	Cudd_RecursiveDeref(manager, t);
	return(NULL);
    }
    cuddRef(e);

    if (t == e) {
	r = t;
    } else {
	if (Cudd_IsComplement(t)) {
	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
	    if (r == NULL) {
		Cudd_RecursiveDeref(manager, t);
		Cudd_RecursiveDeref(manager, e);
		return(NULL);
	    }
	    r = Cudd_Not(r);
	} else {
	    r = cuddUniqueInter(manager,(int)index,t,e);
	    if (r == NULL) {
		Cudd_RecursiveDeref(manager, t);
		Cudd_RecursiveDeref(manager, e);
		return(NULL);
	    }
	}
    }
    cuddDeref(e);
    cuddDeref(t);
    if (F->ref != 1 || G->ref != 1)
	cuddCacheInsert2(manager, cacheOp, f, g, r);
    return(r);

} /* end of cuddBddClippingAndRecur */
Esempio n. 21
0
/**
  @brief Approximates the AND of two BDDs and simultaneously abstracts the
  variables in cube.

  @details The variables are existentially abstracted.

  @return a pointer to the result is successful; NULL otherwise.

  @sideeffect None

  @see Cudd_bddClippingAndAbstract

*/
static DdNode *
cuddBddClipAndAbsRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube,
  int  distance,
  int  direction)
{
    DdNode *F, *ft, *fe, *G, *gt, *ge;
    DdNode *one, *zero, *r, *t, *e, *Cube;
    int topf, topg, topcube, top;
    unsigned int index;
    ptruint cacheTag;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == one && g == one)	return(one);
    if (cube == one) {
	return(cuddBddClippingAndRecur(manager, f, g, distance, direction));
    }
    if (f == one || f == g) {
	return (cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == one) {
	return (cuddBddExistAbstractRecur(manager, f, cube));
    }
    if (distance == 0) return(Cudd_NotCond(one,(direction == 0)));

    /* At this point f, g, and cube are not constant. */
    distance--;

    /* Check cache. */
    if (f > g) { /* Try to increase cache efficiency. */
	DdNode *tmp = f;
	f = g; g = tmp;
    }
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG :
	DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG;
    if (F->ref != 1 || G->ref != 1) {
	r = cuddCacheLookup(manager, cacheTag,
			    f, g, cube);
	if (r != NULL) {
	    return(r);
	}
    }

    checkWhetherToGiveUp(manager);

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    if (topcube < top) {
	return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube),
				      distance, direction));
    }
    /* Now, topcube >= top. */

    if (topf == top) {
	index = F->index;
	ft = cuddT(F);
	fe = cuddE(F);
	if (Cudd_IsComplement(f)) {
	    ft = Cudd_Not(ft);
	    fe = Cudd_Not(fe);
	}
    } else {
	index = G->index;
	ft = fe = f;
    }

    if (topg == top) {
	gt = cuddT(G);
	ge = cuddE(G);
	if (Cudd_IsComplement(g)) {
	    gt = Cudd_Not(gt);
	    ge = Cudd_Not(ge);
	}
    } else {
	gt = ge = g;
    }

    if (topcube == top) {
	Cube = cuddT(cube);
    } else {
	Cube = cube;
    }

    t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction);
    if (t == NULL) return(NULL);

    /* Special case: 1 OR anything = 1. Hence, no need to compute
    ** the else branch if t is 1.
    */
    if (t == one && topcube == top) {
	if (F->ref != 1 || G->ref != 1)
	    cuddCacheInsert(manager, cacheTag, f, g, cube, one);
	return(one);
    }
    cuddRef(t);

    e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction);
    if (e == NULL) {
	Cudd_RecursiveDeref(manager, t);
	return(NULL);
    }
    cuddRef(e);

    if (topcube == top) {	/* abstract */
	r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e),
				    distance, (direction == 0));
	if (r == NULL) {
	    Cudd_RecursiveDeref(manager, t);
	    Cudd_RecursiveDeref(manager, e);
	    return(NULL);
	}
	r = Cudd_Not(r);
	cuddRef(r);
	Cudd_RecursiveDeref(manager, t);
	Cudd_RecursiveDeref(manager, e);
	cuddDeref(r);
    } else if (t == e) {
	r = t;
	cuddDeref(t);
	cuddDeref(e);
    } else {
	if (Cudd_IsComplement(t)) {
	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
	    if (r == NULL) {
		Cudd_RecursiveDeref(manager, t);
		Cudd_RecursiveDeref(manager, e);
		return(NULL);
	    }
	    r = Cudd_Not(r);
	} else {
	    r = cuddUniqueInter(manager,(int)index,t,e);
	    if (r == NULL) {
		Cudd_RecursiveDeref(manager, t);
		Cudd_RecursiveDeref(manager, e);
		return(NULL);
	    }
	}
	cuddDeref(e);
	cuddDeref(t);
    }
    if (F->ref != 1 || G->ref != 1)
	cuddCacheInsert(manager, cacheTag, f, g, cube, r);
    return (r);

} /* end of cuddBddClipAndAbsRecur */
Esempio n. 22
0
/**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     []

******************************************************************************/
DdNode *
cuddAddOrAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * cube)
{
    DdNode	*T, *E, *res, *res1, *res2, *one;

    statLine(manager);
    one = DD_ONE(manager);

    /* Cube is guaranteed to be a cube at this point. */
    if (cuddIsConstant(f) || cube == one) {  
	return(f);
    }

    /* Abstract a variable that does not appear in f. */
    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
	res = cuddAddOrAbstractRecur(manager, f, cuddT(cube));
	return(res);
    }

    if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) {
	return(res);
    }

    T = cuddT(f);
    E = cuddE(f);

    /* If the two indices are the same, so are their levels. */
    if (f->index == cube->index) {
	res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube));
	if (res1 == NULL) return(NULL);
        cuddRef(res1);
	if (res1 != one) {
	    res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube));
	    if (res2 == NULL) {
		Cudd_RecursiveDeref(manager,res1);
		return(NULL);
	    }
	    cuddRef(res2);
	    res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2);
	    if (res == NULL) {
		Cudd_RecursiveDeref(manager,res1);
		Cudd_RecursiveDeref(manager,res2);
		return(NULL);
	    }
	    cuddRef(res);
	    Cudd_RecursiveDeref(manager,res1);
	    Cudd_RecursiveDeref(manager,res2);
	} else {
	    res = res1;
	}
	cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
	cuddDeref(res);
        return(res);
    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
	res1 = cuddAddOrAbstractRecur(manager, T, cube);
	if (res1 == NULL) return(NULL);
        cuddRef(res1);
	res2 = cuddAddOrAbstractRecur(manager, E, cube);
	if (res2 == NULL) {
	    Cudd_RecursiveDeref(manager,res1);
	    return(NULL);
	}
        cuddRef(res2);
	res = (res1 == res2) ? res1 :
	    cuddUniqueInter(manager, (int) f->index, res1, res2);
	if (res == NULL) {
	    Cudd_RecursiveDeref(manager,res1);
	    Cudd_RecursiveDeref(manager,res2);
	    return(NULL);
	}
	cuddDeref(res1);
	cuddDeref(res2);
	cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
        return(res);
    }

} /* end of cuddAddOrAbstractRecur */
Esempio n. 23
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 */
Esempio n. 24
0
/**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]

******************************************************************************/
DdNode *
cuddBddAndRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g)
{
    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *r, *t, *e;
    unsigned int topf, topg, index;

    statLine(manager);
    one = DD_ONE(manager);

    /* Terminal cases. */
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    if (F == G) {
        if (f == g) return(f);
        else return(Cudd_Not(one));
    }
    if (F == one) {
        if (f == one) return(g);
        else return(f);
    }
    if (G == one) {
        if (g == one) return(f);
        else return(g);
    }

    /* At this point f and g are not constant. */
    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */
        DdNode *tmp = f;
        f = g;
        g = tmp;
        F = Cudd_Regular(f);
        G = Cudd_Regular(g);
    }

    /* Check cache. */
    if (F->ref != 1 || G->ref != 1) {
        r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
        if (r != NULL) return(r);
    }

    if ( manager->TimeStop && Abc_Clock() > manager->TimeStop )
        return NULL;

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
        index = F->index;
        fv = cuddT(F);
        fnv = cuddE(F);
        if (Cudd_IsComplement(f)) {
            fv = Cudd_Not(fv);
            fnv = Cudd_Not(fnv);
        }
    } else {
        index = G->index;
        fv = fnv = f;
    }

    if (topg <= topf) {
        gv = cuddT(G);
        gnv = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gv = Cudd_Not(gv);
            gnv = Cudd_Not(gnv);
        }
    } else {
        gv = gnv = g;
    }

    t = cuddBddAndRecur(manager, fv, gv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddAndRecur(manager, fnv, gnv);
    if (e == NULL) {
        Cudd_IterDerefBdd(manager, t);
        return(NULL);
    }
    cuddRef(e);

    if (t == e) {
        r = t;
    } else {
        if (Cudd_IsComplement(t)) {
            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
        } else {
            r = cuddUniqueInter(manager,(int)index,t,e);
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
        }
    }
    cuddDeref(e);
    cuddDeref(t);
    if (F->ref != 1 || G->ref != 1)
        cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
    return(r);

} /* end of cuddBddAndRecur */
Esempio n. 25
0
/**
  @brief Builds an %ADD for the residue modulo m of an n-bit
  number.

  @details The modulus must be at least 2, and the number of bits at
  least 1. Parameter options specifies whether the MSB should be on top
  or the LSB; and whther the number whose residue is computed is in
  two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT
  specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB
  specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's
  complement residue. To request MSB on top and two's complement residue
  simultaneously, one can OR the two macros:
  CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC.

  @return a pointer to the resulting %ADD if successful; NULL
  otherwise.

  @sideeffect None

*/
DdNode *
Cudd_addResidue(
  DdManager * dd /**< manager */,
  int  n /**< number of bits */,
  int  m /**< modulus */,
  int  options /**< options */,
  int  top /**< index of top variable */)
{
    int msbLsb;	/* MSB on top (1) or LSB on top (0) */
    int tc;	/* two's complement (1) or unsigned (0) */
    int i, j, k, t, residue, thisOne, previous, index;
    DdNode **array[2], *var, *tmp, *res;

    /* Sanity check. */
    if (n < 1 && m < 2) return(NULL);

    msbLsb = options & CUDD_RESIDUE_MSB;
    tc = options & CUDD_RESIDUE_TC;

    /* Allocate and initialize working arrays. */
    array[0] = ALLOC(DdNode *,m);
    if (array[0] == NULL) {
	dd->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    array[1] = ALLOC(DdNode *,m);
    if (array[1] == NULL) {
	FREE(array[0]);
	dd->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    for (i = 0; i < m; i++) {
	array[0][i] = array[1][i] = NULL;
    }

    /* Initialize residues. */
    for (i = 0; i < m; i++) {
	tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i);
	if (tmp == NULL) {
	    for (j = 0; j < i; j++) {
		Cudd_RecursiveDeref(dd,array[1][j]);
	    }
	    FREE(array[0]);
	    FREE(array[1]);
	    return(NULL);
	}
	cuddRef(tmp);
	array[1][i] = tmp;
    }

    /* Main iteration. */
    residue = 1;	/* residue of 2**0 */
    for (k = 0; k < n; k++) {
	/* Choose current and previous arrays. */
	thisOne = k & 1;
	previous = thisOne ^ 1;
	/* Build an ADD projection function. */
	if (msbLsb) {
	    index = top+n-k-1;
	} else {
	    index = top+k;
	}
	var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd));
	if (var == NULL) {
	    for (j = 0; j < m; j++) {
		Cudd_RecursiveDeref(dd,array[previous][j]);
	    }
	    FREE(array[0]);
	    FREE(array[1]);
	    return(NULL);
	}
	cuddRef(var);
	for (i = 0; i < m; i ++) {
	    t = (i + residue) % m;
	    tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]);
	    if (tmp == NULL) {
		for (j = 0; j < i; j++) {
		    Cudd_RecursiveDeref(dd,array[thisOne][j]);
		}
		for (j = 0; j < m; j++) {
		    Cudd_RecursiveDeref(dd,array[previous][j]);
		}
		FREE(array[0]);
		FREE(array[1]);
		return(NULL);
	    }
	    cuddRef(tmp);
	    array[thisOne][i] = tmp;
	}
	/* One layer completed. Free the other array for the next iteration. */
	for (i = 0; i < m; i++) {
	    Cudd_RecursiveDeref(dd,array[previous][i]);
	}
	Cudd_RecursiveDeref(dd,var);
	/* Update residue of 2**k. */
	residue = (2 * residue) % m;
	/* Adjust residue for MSB, if this is a two's complement number. */
	if (tc && (k == n - 1)) {
	    residue = (m - residue) % m;
	}
    }

    /* We are only interested in the 0-residue node of the top layer. */
    for (i = 1; i < m; i++) {
	Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]);
    }
    res = array[(n - 1) & 1][0];

    FREE(array[0]);
    FREE(array[1]);

    cuddDeref(res);
    return(res);

} /* end of Cudd_addResidue */
Esempio n. 26
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_SplitSet.]

  Description [Implements the recursive step of Cudd_SplitSet. The
  procedure recursively traverses the BDD and checks to see if any
  node satisfies the minterm requirements as specified by 'n'. At any
  node X, n is compared to the number of minterms in the onset of X's
  children. If either of the child nodes have exactly n minterms, then
  that node is returned; else, if n is greater than the onset of one
  of the child nodes, that node is retained and the difference in the
  number of minterms is extracted from the other child. In case n
  minterms can be extracted from constant 1, the algorithm returns the
  result with at most log(n) nodes.]

  SideEffects [The array 'varSeen' is updated at every recursive call
  to set the variables traversed by the procedure.]

  SeeAlso     []

******************************************************************************/
DdNode*
cuddSplitSetRecur(
  DdManager * manager,
  st_table * mtable,
  int * varSeen,
  DdNode * p,
  double  n,
  double  max,
  int  index)
{
    DdNode *one, *zero, *N, *Nv;
    DdNode *Nnv, *q, *r, *v;
    DdNode *result;
    double *dummy, numT, numE;
    int variable, positive;
  
    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* If p is constant, extract n minterms from constant 1.  The procedure by
    ** construction guarantees that minterms will not be extracted from
    ** constant 0.
    */
    if (Cudd_IsConstant(p)) {
	q = selectMintermsFromUniverse(manager,varSeen,n);
	return(q);
    }

    N = Cudd_Regular(p);

    /* Set variable as seen. */
    variable = N->index;
    varSeen[manager->invperm[variable]] = -1;

    Nv = cuddT(N);
    Nnv = cuddE(N);
    if (Cudd_IsComplement(p)) {
	Nv = Cudd_Not(Nv);
	Nnv = Cudd_Not(Nnv);
    }

    /* If both the children of 'p' are constants, extract n minterms from a
    ** constant node.
    */
    if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
	q = selectMintermsFromUniverse(manager,varSeen,n);
	if (q == NULL) {
	    return(NULL);
	}
	cuddRef(q);
	r = cuddBddAndRecur(manager,p,q);
	if (r == NULL) {
	    Cudd_RecursiveDeref(manager,q);
	    return(NULL);
	}
	cuddRef(r);
	Cudd_RecursiveDeref(manager,q);
	cuddDeref(r);
	return(r);
    }
  
    /* Lookup the # of minterms in the onset of the node from the table. */
    if (!Cudd_IsConstant(Nv)) {
	if (!st_lookup(mtable, Nv, &dummy)) return(NULL);
	numT = *dummy/(2*(1<<index));
    } else if (Nv == one) {
	numT = max/(2*(1<<index));
    } else {
	numT = 0;
    }
  
    if (!Cudd_IsConstant(Nnv)) {
	if (!st_lookup(mtable, Nnv, &dummy)) return(NULL);
	numE = *dummy/(2*(1<<index));
    } else if (Nnv == one) {
	numE = max/(2*(1<<index));
    } else {
	numE = 0;
    }

    v = cuddUniqueInter(manager,variable,one,zero);
    cuddRef(v);

    /* If perfect match. */
    if (numT == n) {
	q = cuddBddAndRecur(manager,v,Nv);
	if (q == NULL) {
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(q);
	Cudd_RecursiveDeref(manager,v);
	cuddDeref(q);
	return(q);
    }
    if (numE == n) {
	q = cuddBddAndRecur(manager,Cudd_Not(v),Nnv);
	if (q == NULL) {
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(q);
	Cudd_RecursiveDeref(manager,v);
	cuddDeref(q);
	return(q);
    }
    /* If n is greater than numT, extract the difference from the ELSE child
    ** and retain the function represented by the THEN branch.
    */
    if (numT < n) {
	q = cuddSplitSetRecur(manager,mtable,varSeen,
			      Nnv,(n-numT),max,index+1);
	if (q == NULL) {
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(q);
	r = cuddBddIteRecur(manager,v,Nv,q);
	if (r == NULL) {
	    Cudd_RecursiveDeref(manager,q);
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(r);
	Cudd_RecursiveDeref(manager,q);
	Cudd_RecursiveDeref(manager,v);
	cuddDeref(r);
	return(r);
    }
    /* If n is greater than numE, extract the difference from the THEN child
    ** and retain the function represented by the ELSE branch.
    */
    if (numE < n) {
	q = cuddSplitSetRecur(manager,mtable,varSeen,
			      Nv, (n-numE),max,index+1);
	if (q == NULL) {
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(q);
	r = cuddBddIteRecur(manager,v,q,Nnv);
	if (r == NULL) {
	    Cudd_RecursiveDeref(manager,q);
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(r);
	Cudd_RecursiveDeref(manager,q);
	Cudd_RecursiveDeref(manager,v);
	cuddDeref(r);    
	return(r);
    }

    /* None of the above cases; (n < numT and n < numE) and either of
    ** the Nv, Nnv or both are not constants. If possible extract the
    ** required minterms the constant branch.
    */
    if (Cudd_IsConstant(Nv) && !Cudd_IsConstant(Nnv)) {
	q = selectMintermsFromUniverse(manager,varSeen,n);
	if (q == NULL) {
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(q);
	result = cuddBddAndRecur(manager,v,q);
	if (result == NULL) {
	    Cudd_RecursiveDeref(manager,q);
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(result);
	Cudd_RecursiveDeref(manager,q);
	Cudd_RecursiveDeref(manager,v);
	cuddDeref(result);
	return(result);
    } else if (!Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
	q = selectMintermsFromUniverse(manager,varSeen,n);
	if (q == NULL) {
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(q);
	result = cuddBddAndRecur(manager,Cudd_Not(v),q);
	if (result == NULL) {
	    Cudd_RecursiveDeref(manager,q);
	    Cudd_RecursiveDeref(manager,v);
	    return(NULL);
	}
	cuddRef(result);
	Cudd_RecursiveDeref(manager,q);
	Cudd_RecursiveDeref(manager,v);
	cuddDeref(result);
	return(result);
    }

    /* Both Nv and Nnv are not constants. So choose the one which
    ** has fewer minterms in its onset.
    */
    positive = 0;
    if (numT < numE) {
	q = cuddSplitSetRecur(manager,mtable,varSeen,
			      Nv,n,max,index+1);
	positive = 1;
    } else {
	q = cuddSplitSetRecur(manager,mtable,varSeen,
			      Nnv,n,max,index+1);
    }

    if (q == NULL) {
	Cudd_RecursiveDeref(manager,v);
	return(NULL);
    }
    cuddRef(q);

    if (positive) {
	result = cuddBddAndRecur(manager,v,q);
    } else {
	result = cuddBddAndRecur(manager,Cudd_Not(v),q);
    }
    if (result == NULL) {
	Cudd_RecursiveDeref(manager,q);
	Cudd_RecursiveDeref(manager,v);
	return(NULL);
    }
    cuddRef(result);
    Cudd_RecursiveDeref(manager,q);
    Cudd_RecursiveDeref(manager,v);
    cuddDeref(result);

    return(result);

} /* end of cuddSplitSetRecur */
Esempio n. 27
0
/**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]

******************************************************************************/
DdNode *
cuddBddXorExistAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube)
{
    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *zero, *r, *t, *e, *Cube;
    unsigned int topf, topg, topcube, top, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == g) {
	return(zero);
    }
    if (f == Cudd_Not(g)) {
	return(one);
    }
    if (cube == one) {
	return(cuddBddXorRecur(manager, f, g));
    }
    if (f == one) {
	return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
    }
    if (g == one) {
	return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
    }
    if (f == zero) {
	return(cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == zero) {
	return(cuddBddExistAbstractRecur(manager, f, cube));
    }

    /* At this point f, g, and cube are not constant. */

    if (f > g) { /* Try to increase cache efficiency. */
	DdNode *tmp = f;
	f = g;
	g = tmp;
    }

    /* Check cache. */
    r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
    if (r != NULL) {
	return(r);
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    F = Cudd_Regular(f);
    topf = manager->perm[F->index];
    G = Cudd_Regular(g);
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    if (topcube < top) {
	return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
    }
    /* Now, topcube >= top. */

    if (topf == top) {
	index = F->index;
	fv = cuddT(F);
	fnv = cuddE(F);
	if (Cudd_IsComplement(f)) {
	    fv = Cudd_Not(fv);
	    fnv = Cudd_Not(fnv);
	}
    } else {
	index = G->index;
	fv = fnv = f;
    }

    if (topg == top) {
	gv = cuddT(G);
	gnv = cuddE(G);
	if (Cudd_IsComplement(g)) {
	    gv = Cudd_Not(gv);
	    gnv = Cudd_Not(gnv);
	}
    } else {
	gv = gnv = g;
    }

    if (topcube == top) {
	Cube = cuddT(cube);
    } else {
	Cube = cube;
    }

    t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
    if (t == NULL) return(NULL);

    /* Special case: 1 OR anything = 1. Hence, no need to compute
    ** the else branch if t is 1.
    */
    if (t == one && topcube == top) {
	cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
	return(one);
    }
    cuddRef(t);

    e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
    if (e == NULL) {
	Cudd_IterDerefBdd(manager, t);
	return(NULL);
    }
    cuddRef(e);

    if (topcube == top) {	/* abstract */
	r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
	if (r == NULL) {
	    Cudd_IterDerefBdd(manager, t);
	    Cudd_IterDerefBdd(manager, e);
	    return(NULL);
	}
	r = Cudd_Not(r);
	cuddRef(r);
	Cudd_IterDerefBdd(manager, t);
	Cudd_IterDerefBdd(manager, e);
	cuddDeref(r);
    } else if (t == e) {
	r = t;
	cuddDeref(t);
	cuddDeref(e);
    } else {
	if (Cudd_IsComplement(t)) {
	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
	    if (r == NULL) {
		Cudd_IterDerefBdd(manager, t);
		Cudd_IterDerefBdd(manager, e);
		return(NULL);
	    }
	    r = Cudd_Not(r);
	} else {
	    r = cuddUniqueInter(manager,(int)index,t,e);
	    if (r == NULL) {
		Cudd_IterDerefBdd(manager, t);
		Cudd_IterDerefBdd(manager, e);
		return(NULL);
	    }
	}
	cuddDeref(e);
	cuddDeref(t);
    }
    cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
    return (r);

} /* end of cuddBddXorExistAbstractRecur */
Esempio n. 28
0
/**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]

******************************************************************************/
DdNode *
cuddBddAndAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube)
{
    DdNode *F, *ft, *fe, *G, *gt, *ge;
    DdNode *one, *zero, *r, *t, *e;
    unsigned int topf, topg, topcube, top, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == one && g == one)   return(one);

    if (cube == one) {
        return(cuddBddAndRecur(manager, f, g));
    }
    if (f == one || f == g) {
        return(cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == one) {
        return(cuddBddExistAbstractRecur(manager, f, cube));
    }
    /* At this point f, g, and cube are not constant. */

    if (f > g) { /* Try to increase cache efficiency. */
        DdNode *tmp = f;
        f = g;
        g = tmp;
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    while (topcube < top) {
        cube = cuddT(cube);
        if (cube == one) {
            return(cuddBddAndRecur(manager, f, g));
        }
        topcube = manager->perm[cube->index];
    }
    /* Now, topcube >= top. */

    /* Check cache. */
    if (F->ref != 1 || G->ref != 1) {
        r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
        if (r != NULL) {
            return(r);
        }
    }

    if ( manager->TimeStop && manager->TimeStop < clock() )
        return NULL;

    if (topf == top) {
        index = F->index;
        ft = cuddT(F);
        fe = cuddE(F);
        if (Cudd_IsComplement(f)) {
            ft = Cudd_Not(ft);
            fe = Cudd_Not(fe);
        }
    } else {
        index = G->index;
        ft = fe = f;
    }

    if (topg == top) {
        gt = cuddT(G);
        ge = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gt = Cudd_Not(gt);
            ge = Cudd_Not(ge);
        }
    } else {
        gt = ge = g;
    }

    if (topcube == top) {       /* quantify */
        DdNode *Cube = cuddT(cube);
        t = cuddBddAndAbstractRecur(manager, ft, gt, Cube);
        if (t == NULL) return(NULL);
        /* Special case: 1 OR anything = 1. Hence, no need to compute
        ** the else branch if t is 1. Likewise t + t * anything == t.
        ** Notice that t == fe implies that fe does not depend on the
        ** variables in Cube. Likewise for t == ge.
        */
        if (t == one || t == fe || t == ge) {
            if (F->ref != 1 || G->ref != 1)
                cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
                                f, g, cube, t);
            return(t);
        }
        cuddRef(t);
        /* Special case: t + !t * anything == t + anything. */
        if (t == Cudd_Not(fe)) {
            e = cuddBddExistAbstractRecur(manager, ge, Cube);
        } else if (t == Cudd_Not(ge)) {
            e = cuddBddExistAbstractRecur(manager, fe, Cube);
        } else {
            e = cuddBddAndAbstractRecur(manager, fe, ge, Cube);
        }
        if (e == NULL) {
            Cudd_IterDerefBdd(manager, t);
            return(NULL);
        }
        if (t == e) {
            r = t;
            cuddDeref(t);
        } else {
            cuddRef(e);
            r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
            cuddRef(r);
            Cudd_DelayedDerefBdd(manager, t);
            Cudd_DelayedDerefBdd(manager, e);
            cuddDeref(r);
        }
    } else {
        t = cuddBddAndAbstractRecur(manager, ft, gt, cube);
        if (t == NULL) return(NULL);
        cuddRef(t);
        e = cuddBddAndAbstractRecur(manager, fe, ge, cube);
        if (e == NULL) {
            Cudd_IterDerefBdd(manager, t);
            return(NULL);
        }
        if (t == e) {
            r = t;
            cuddDeref(t);
        } else {
            cuddRef(e);
            if (Cudd_IsComplement(t)) {
                r = cuddUniqueInter(manager, (int) index,
                                    Cudd_Not(t), Cudd_Not(e));
                if (r == NULL) {
                    Cudd_IterDerefBdd(manager, t);
                    Cudd_IterDerefBdd(manager, e);
                    return(NULL);
                }
                r = Cudd_Not(r);
            } else {
                r = cuddUniqueInter(manager,(int)index,t,e);
                if (r == NULL) {
                    Cudd_IterDerefBdd(manager, t);
                    Cudd_IterDerefBdd(manager, e);
                    return(NULL);
                }
            }
            cuddDeref(e);
            cuddDeref(t);
        }
    }

    if (F->ref != 1 || G->ref != 1)
        cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
    return (r);

} /* end of cuddBddAndAbstractRecur */
Esempio n. 29
0
/**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]

******************************************************************************/
DdNode *
cuddCofactorRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r;
    unsigned int topf,topg;
    int comple;

    F = Cudd_Regular(f);
    if (cuddIsConstant(F)) return(f);

    one = DD_ONE(dd);

    /* The invariant g != 0 is true on entry to this procedure and is
    ** recursively maintained by it. Therefore it suffices to test g
    ** against one to make sure it is not constant.
    */
    if (g == one) return(f);
    /* From now on, f and g are known not to be constants. */

    comple = f != F;
    r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g);
    if (r != NULL) {
	return(Cudd_NotCond(r,comple));
    }

    topf = dd->perm[F->index];
    G = Cudd_Regular(g);
    topg = dd->perm[G->index];

    /* We take the cofactors of F because we are going to rely on
    ** the fact that the cofactors of the complement are the complements
    ** of the cofactors to better utilize the cache. Variable comple
    ** remembers whether we have to complement the result or not.
    */
    if (topf <= topg) {
	f1 = cuddT(F); f0 = cuddE(F);
    } else {
	f1 = f0 = F;
    }
    if (topg <= topf) {
	g1 = cuddT(G); g0 = cuddE(G);
	if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); }
    } else {
	g1 = g0 = g;
    }

    zero = Cudd_Not(one);
    if (topf >= topg) {
	if (g0 == zero || g0 == DD_ZERO(dd)) {
	    r = cuddCofactorRecur(dd, f1, g1);
	} else if (g1 == zero || g1 == DD_ZERO(dd)) {
	    r = cuddCofactorRecur(dd, f0, g0);
	} else {
	    (void) fprintf(stdout,"Cudd_Cofactor: Invalid restriction 2\n");
	    return(NULL);
	}
	if (r == NULL) return(NULL);
    } else /* if (topf < topg) */ {
	t = cuddCofactorRecur(dd, f1, g);
	if (t == NULL) return(NULL);
    	cuddRef(t);
    	e = cuddCofactorRecur(dd, f0, g);
	if (e == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    return(NULL);
	}
	cuddRef(e);

	if (t == e) {
	    r = t;
	} else if (Cudd_IsComplement(t)) {
	    r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e));
	    if (r != NULL)
		r = Cudd_Not(r);
	} else {
	    r = cuddUniqueInter(dd,(int)F->index,t,e);
	}
	if (r == NULL) {
	    Cudd_RecursiveDeref(dd ,e);
	    Cudd_RecursiveDeref(dd ,t);
	    return(NULL);
	}
	cuddDeref(t);
	cuddDeref(e);
    }

    cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r);

    return(Cudd_NotCond(r,comple));

} /* end of cuddCofactorRecur */
Esempio n. 30
0
/**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     []

******************************************************************************/
DdNode *
cuddAddUnivAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * cube)
{
    DdNode	*T, *E, *res, *res1, *res2, *one, *zero;

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

    /* Cube is guaranteed to be a cube at this point.
    ** zero and one are the only constatnts c such that c*c=c.
    */
    if (f == zero || f == one || cube == one) {  
	return(f);
    }

    /* Abstract a variable that does not appear in f. */
    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
	res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube));
	if (res1 == NULL) return(NULL);
	cuddRef(res1);
	/* Use the "internal" procedure to be alerted in case of
	** dynamic reordering. If dynamic reordering occurs, we
	** have to abort the entire abstraction.
	*/
	res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1);
	if (res == NULL) {
	    Cudd_RecursiveDeref(manager,res1);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(manager,res1);
	cuddDeref(res);
	return(res);
    }

    if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) {
	return(res);
    }

    T = cuddT(f);
    E = cuddE(f);

    /* If the two indices are the same, so are their levels. */
    if (f->index == cube->index) {
	res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube));
	if (res1 == NULL) return(NULL);
        cuddRef(res1);
	res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube));
	if (res2 == NULL) {
	    Cudd_RecursiveDeref(manager,res1);
	    return(NULL);
	}
        cuddRef(res2);
	res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2);
	if (res == NULL) {
	    Cudd_RecursiveDeref(manager,res1);
	    Cudd_RecursiveDeref(manager,res2);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(manager,res1);
	Cudd_RecursiveDeref(manager,res2);
	cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
	cuddDeref(res);
        return(res);
    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
	res1 = cuddAddUnivAbstractRecur(manager, T, cube);
	if (res1 == NULL) return(NULL);
        cuddRef(res1);
	res2 = cuddAddUnivAbstractRecur(manager, E, cube);
	if (res2 == NULL) {
	    Cudd_RecursiveDeref(manager,res1);
	    return(NULL);
	}
        cuddRef(res2);
	res = (res1 == res2) ? res1 :
	    cuddUniqueInter(manager, (int) f->index, res1, res2);
	if (res == NULL) {
	    Cudd_RecursiveDeref(manager,res1);
	    Cudd_RecursiveDeref(manager,res2);
	    return(NULL);
	}
	cuddDeref(res1);
	cuddDeref(res2);
	cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
        return(res);
    }

} /* end of cuddAddUnivAbstractRecur */