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

  Synopsis    [Integer and floating point multiplication.]

  Description [Integer and floating point multiplication. Returns NULL
  if not a terminal case; f * g otherwise.  This function can be used also
  to take the AND of two 0-1 ADDs.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addTimes(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{
    DdNode *res;
    DdNode *F, *G;
    CUDD_VALUE_TYPE value;

    F = *f; G = *g;
    if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
    if (F == DD_ONE(dd)) return(G);
    if (G == DD_ONE(dd)) return(F);
    if (cuddIsConstant(F) && cuddIsConstant(G)) {
	value = cuddV(F)*cuddV(G);
	res = cuddUniqueConst(dd,value);
	return(res);
    }
    if (F > G) { /* swap f and g */
	*f = G;
	*g = F;
    }
    return(NULL);

} /* end of Cudd_addTimes */
Ejemplo n.º 2
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 */
Ejemplo n.º 3
0
/**Function********************************************************************

  Synopsis    [Returns plusinfinity if f=g; returns min(f,g) if f!=g.]

  Description [Returns NULL if not a terminal case; f op g otherwise,
  where f op g is plusinfinity if f=g; min(f,g) if f!=g.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addDiff(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{
    DdNode *F, *G;

    F = *f; G = *g;
    if (F == G) return(DD_PLUS_INFINITY(dd));
    if (F == DD_PLUS_INFINITY(dd)) return(G);
    if (G == DD_PLUS_INFINITY(dd)) return(F);
    if (cuddIsConstant(F) && cuddIsConstant(G)) {
	if (cuddV(F) != cuddV(G)) {
            if (cuddV(F) < cuddV(G)) {
                return(F);
            } else {
                return(G);
            }
	} else {
	    return(DD_PLUS_INFINITY(dd));
	}
    }
    return(NULL);

} /* end of Cudd_addDiff */
Ejemplo n.º 4
0
/**Function********************************************************************

  Synopsis    [Integer and floating point max.]

  Description [Integer and floating point max for Cudd_addApply.
  Returns NULL if not a terminal case; max(f,g) otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addMaximum(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{
    DdNode *F, *G;

    F = *f; G = *g;
    if (F == G) return(F);
    if (F == DD_MINUS_INFINITY(dd)) return(G);
    if (G == DD_MINUS_INFINITY(dd)) return(F);
#if 0
    /* These special cases probably do not pay off. */
    if (F == DD_PLUS_INFINITY(dd)) return(F);
    if (G == DD_PLUS_INFINITY(dd)) return(G);
#endif
    if (cuddIsConstant(F) && cuddIsConstant(G)) {
	if (cuddV(F) >= cuddV(G)) {
	    return(F);
	} else {
	    return(G);
	}
    }
    if (F > G) { /* swap f and g */
	*f = G;
	*g = F;
    }
    return(NULL);

} /* end of Cudd_addMaximum */
Ejemplo n.º 5
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 */
Ejemplo n.º 6
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 */
Ejemplo n.º 7
0
/**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 */
Ejemplo n.º 8
0
/**Function********************************************************************

  Synopsis    [Determines whether f is less than or equal to g.]

  Description [Returns 1 if f is less than or equal to g; 0 otherwise.
  No new nodes are created. This procedure works for arbitrary ADDs.
  For 0-1 ADDs Cudd_addEvalConst is more efficient.]

  SideEffects [None]

  SeeAlso     [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq]

******************************************************************************/
int
Cudd_addLeq(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *tmp, *fv, *fvn, *gv, *gvn;
    unsigned int topf, topg, res;

    /* Terminal cases. */
    if (f == g) return(1);

    statLine(dd);
    if (cuddIsConstant(f)) {
	if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g));
	if (f == DD_MINUS_INFINITY(dd)) return(1);
	if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */
    }
    if (g == DD_PLUS_INFINITY(dd)) return(1);
    if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */

    /* Check cache. */
    tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_addLeq,f,g);
    if (tmp != NULL) {
	return(tmp == DD_ONE(dd));
    }

    /* Compute cofactors. One of f and g is not constant. */
    topf = cuddI(dd,f->index);
    topg = cuddI(dd,g->index);
    if (topf <= topg) {
	fv = cuddT(f); fvn = cuddE(f);
    } else {
	fv = fvn = f;
    }
    if (topg <= topf) {
	gv = cuddT(g); gvn = cuddE(g);
    } else {
	gv = gvn = g;
    }

    res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv);

    /* Store result in cache and return. */
    cuddCacheInsert2(dd,(DD_CTFP) Cudd_addLeq,f,g,
		     Cudd_NotCond(DD_ONE(dd),res==0));
    return(res);

} /* end of Cudd_addLeq */
Ejemplo n.º 9
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 */
Ejemplo n.º 10
0
/**Function********************************************************************

  Synopsis    [f if f&gt;=g; 0 if f&lt;g.]

  Description [Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g).
  Returns NULL if not a terminal case; f op g otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addThreshold(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{
    DdNode *F, *G;

    F = *f; G = *g;
    if (cuddIsConstant(F) && cuddIsConstant(G)) {
	if (cuddV(F) >= cuddV(G)) {
	    return(F);
	} else {
	    return(DD_ZERO(dd));
	}
    }
    return(NULL);

} /* end of Cudd_addThreshold */
Ejemplo n.º 11
0
/**Function********************************************************************

  Synopsis    [Returns 1 if f &gt g and 0 otherwise.]

  Description [Returns 1 if f &gt g (both should be terminal cases) and 0 
  otherwise. Used in conjunction with Cudd_addApply. Returns NULL if not a 
  terminal case.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addOneZeroMaximum(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{

    if (*g == DD_PLUS_INFINITY(dd))
	return DD_ZERO(dd);
    if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
	if (cuddV(*f) > cuddV(*g)) {
	    return(DD_ONE(dd));
	} else {
	    return(DD_ZERO(dd));
	}
    }

    return(NULL);

} /* end of Cudd_addOneZeroMaximum */
Ejemplo n.º 12
0
/**Function********************************************************************

  Synopsis    [Integer and floating point subtraction.]

  Description [Integer and floating point subtraction. Returns NULL if
  not a terminal case; f - g otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addMinus(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{
    DdNode *res;
    DdNode *F, *G;
    CUDD_VALUE_TYPE value;

    F = *f; G = *g;
    if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G));
    if (G == DD_ZERO(dd)) return(F);
    if (cuddIsConstant(F) && cuddIsConstant(G)) {
	value = cuddV(F)-cuddV(G);
	res = cuddUniqueConst(dd,value);
	return(res);
    }
    return(NULL);

} /* end of Cudd_addMinus */
Ejemplo n.º 13
0
/**Function********************************************************************

  Synopsis    [Integer and floating point division.]

  Description [Integer and floating point division. Returns NULL if not
  a terminal case; f / g otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addDivide(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{
    DdNode *res;
    DdNode *F, *G;
    CUDD_VALUE_TYPE value;

    F = *f; G = *g;
    if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
    if (G == DD_ONE(dd)) return(F);
    if (cuddIsConstant(F) && cuddIsConstant(G)) {
	value = cuddV(F)/cuddV(G);
	res = cuddUniqueConst(dd,value);
	return(res);
    }
    return(NULL);

} /* end of Cudd_addDivide */
Ejemplo n.º 14
0
/**Function********************************************************************

  Synopsis    [Natural logarithm of an ADD.]

  Description [Natural logarithm of an ADDs. Returns NULL
  if not a terminal case; log(f) otherwise.  The discriminants of f must
  be positive double's.]

  SideEffects [None]

  SeeAlso     [Cudd_addMonadicApply]

******************************************************************************/
DdNode *
Cudd_addLog(
  DdManager * dd,
  DdNode * f)
{
    if (cuddIsConstant(f)) {
	CUDD_VALUE_TYPE value = log(cuddV(f));
	DdNode *res = cuddUniqueConst(dd,value);
	return(res);
    }
    return(NULL);

} /* end of Cudd_addLog */
Ejemplo n.º 15
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 */
Ejemplo n.º 16
0
/**Function********************************************************************

  Synopsis    [Integer and floating point division.]

  Description [Integer and floating point division. Returns NULL if not
  a terminal case; f / g otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addApply]

******************************************************************************/
DdNode *
Cudd_addDivide(
  DdManager * dd,
  DdNode ** f,
  DdNode ** g)
{
    DdNode *res;
    DdNode *F, *G;
    CUDD_VALUE_TYPE value;

    F = *f; G = *g;
    /* We would like to use F == G -> F/G == 1, but F and G may
    ** contain zeroes. */
    if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
    if (G == DD_ONE(dd)) return(F);
    if (cuddIsConstant(F) && cuddIsConstant(G)) {
	value = cuddV(F)/cuddV(G);
	res = cuddUniqueConst(dd,value);
	return(res);
    }
    return(NULL);

} /* end of Cudd_addDivide */
Ejemplo n.º 17
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 */
Ejemplo n.º 18
0
static void
I_BDD_minterms_aux (DdManager * dd, DdNode * node, char *list,
                    List * minterm_list)
{
  DdNode *N, *Nv, *Nnv;
  int i, index;
  char *new_list;

  N = Cudd_Regular (node);

  if (cuddIsConstant (N))
    {
      /* Terminal case: Print one cube based on the current recursion
         ** path, unless we have reached the background value (ADDs) or
         ** the logical zero (BDDs).
       */
      if (node != dd->background && node != Cudd_Not (dd->one))
        {
          if (!(new_list = (char *) malloc (sizeof (char) * dd->size)))
            I_punt ("I_BDD_minterms_aux: cannot allocate array");

          for (i = 0; i < dd->size; i++)
	    new_list[i] = list[i];

          if (cuddV (node) != 1)
            I_punt ("I_BDD_minterms_aux: bad BDD");

          *minterm_list = List_insert_last (*minterm_list, new_list);
        }
    }
  else
    {
      Nv = cuddT (N);
      Nnv = cuddE (N);
      if (Cudd_IsComplement (node))
        {
          Nv = Cudd_Not (Nv);
          Nnv = Cudd_Not (Nnv);
        }
      index = N->index;
      list[index] = 0;
      I_BDD_minterms_aux (dd, Nnv, list, minterm_list);
      list[index] = 1;
      I_BDD_minterms_aux (dd, Nv, list, minterm_list);
      list[index] = 2;
    }

  return;
}
Ejemplo n.º 19
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_addBddIthBit.]

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

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
addBddDoIthBit(
  DdManager * dd,
  DdNode * f,
  DdNode * index)
{
    DdNode *res, *T, *E;
    DdNode *fv, *fvn;
    /* NuSMV: add begin */
    ptrint mask, value;
      /* WAS: long mask, value; */
    /* NuSMV: add end */

    int v;

    statLine(dd);
    /* Check terminal case. */
    if (cuddIsConstant(f)) {
      /* NuSMV: add begin */
	mask = 1 << ((ptrint) cuddV(index));
	value = (ptrint) cuddV(f);
        /* WAS: mask = 1 << ((long) cuddV(index));
                value = (long) cuddV(f); */
      /* NuSMV: add end */
	return(Cudd_NotCond(DD_TRUE(dd),(value & mask) == 0));
    }

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

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

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

    E = addBddDoIthBit(dd,fvn,index);
    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,addBddDoIthBit,f,index,res);

    return(res);

} /* end of addBddDoIthBit */
Ejemplo n.º 20
0
/**Function********************************************************************

  Synopsis    [Performs the reordering-sensitive step of Extra_bddHaar().]

  Description [Generates in a bottom-up fashion an ADD for all spectral
               coefficients of the functions represented by a BDD.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode* extraBddHaar( 
  DdManager * dd,    /* the manager */
  DdNode * bFunc,    /* the function whose spectrum is being computed */
  DdNode * bVars)    /* the variables on which the function depends */
{
	DdNode * aRes;
    statLine(dd); 

	/* terminal cases */
	if ( bVars == b1 )
	{
		assert( Cudd_IsConstant(bFunc) );
		if ( bFunc == b0 )
			return a0;
		else
			return a1;
	}

    /* check cache */
//	if ( bFunc->ref != 1 )
    if ( aRes = cuddCacheLookup2(dd, extraBddHaar, bFunc, bVars) )
    	return aRes;
	else
	{
		DdNode * bFunc0, * bFunc1;   /* cofactors of the function */
		DdNode * aHaar0, * aHaar1;   /* partial solutions of the problem */
		DdNode * aNode0, * aNode1;   /* the special terminal nodes */
		DdNode * aRes0,  * aRes1;    /* partial results to be composed by ITE */
		DdNode * bFuncR = Cudd_Regular(bFunc); /* the regular pointer to the function */
		DdNode * aTemp;
		double   dValue0, dValue1;

		/* bFunc cannot depend on a variable that is not in bVars */
		assert( cuddI(dd,bFuncR->index) >= cuddI(dd,bVars->index) );


		/* cofactor the BDD */
		if ( bFuncR->index == bVars->index )
		{
			if ( bFuncR != bFunc ) /* bFunc is complemented */
			{
				bFunc0 = Cudd_Not( cuddE(bFuncR) );
				bFunc1 = Cudd_Not( cuddT(bFuncR) );
			}
			else
			{
				bFunc0 = cuddE(bFuncR);
				bFunc1 = cuddT(bFuncR);
			}
		}
		else /* bVars is higher in the variable order */
			bFunc0 = bFunc1 = bFunc;


		/* solve subproblems */
		aHaar0 = extraBddHaar( dd, bFunc0, cuddT(bVars) );
		if ( aHaar0 == NULL )
			return NULL;
		cuddRef( aHaar0 );

		aHaar1 = extraBddHaar( dd, bFunc1, cuddT(bVars) );
		if ( aHaar1 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			return NULL;
		}
		cuddRef( aHaar1 );

		/* retrieve the terminal values in aHaar0 and aHaar1 */
		for ( aTemp = aHaar0; aTemp->index != CUDD_CONST_INDEX; aTemp = cuddE(aTemp) );
		dValue0 = cuddV( aTemp );
		for ( aTemp = aHaar1; aTemp->index != CUDD_CONST_INDEX; aTemp = cuddE(aTemp) );
		dValue1 = cuddV( aTemp );

		/* get the new terminal nodes */
		aNode0 = cuddUniqueConst( dd, dValue0 + dValue1 );
		if ( aNode0 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			return NULL;
		}
		cuddRef( aNode0 );

		aNode1 = cuddUniqueConst( dd, dValue0 - dValue1 );
		if ( aNode1 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			Cudd_RecursiveDeref( dd, aNode0 );
			return NULL;
		}
		cuddRef( aNode1 );


		/* replace the terminal nodes in the cofactor ADDs */
		aRes0 = extraAddUpdateZeroCubeValue( dd, aHaar0, cuddT(bVars), aNode0  );
		if ( aRes0 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			Cudd_RecursiveDeref( dd, aNode0 );
			Cudd_RecursiveDeref( dd, aNode1 );
			return NULL;
		}
		cuddRef( aRes0 );

		aRes1 = extraAddUpdateZeroCubeValue( dd, aHaar1, cuddT(bVars), aNode1  );
		if ( aRes1 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			Cudd_RecursiveDeref( dd, aNode0 );
			Cudd_RecursiveDeref( dd, aNode1 );
			Cudd_RecursiveDeref( dd, aRes0 );
			return NULL;
		}
		cuddRef( aRes1 );

		Cudd_RecursiveDeref(dd, aHaar0);
		Cudd_RecursiveDeref(dd, aHaar1);

		Cudd_RecursiveDeref(dd, aNode0);
		Cudd_RecursiveDeref(dd, aNode1);


		/* only aRes0 and aRes1 are referenced at this point */

		/* consider the case when Res0 and Res1 are the same node */
		aRes = (aRes1 == aRes0) ? aRes1 : cuddUniqueInter( dd, bVars->index, aRes1, aRes0 );
		if (aRes == NULL) 
		{
			Cudd_RecursiveDeref(dd, aRes1);
			Cudd_RecursiveDeref(dd, aRes0);
			return NULL;
		}
		cuddDeref(aRes1);
		cuddDeref(aRes0);

		/* insert the result into cache */
//		if ( bFunc->ref != 1 )
		cuddCacheInsert2(dd, extraBddHaar, bFunc, bVars, aRes);
		return aRes;
	}
} /* end of extraBddHaar */
Ejemplo n.º 21
0
/**Function********************************************************************

  Synopsis    [Main function for testcudd.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
main(int argc, char **argv)
{
    FILE *fp;           /* pointer to input file */
    char *file = (char *) "";	/* input file name */
    FILE *dfp = NULL;	/* pointer to dump file */
    char *dfile;	/* file for DD dump */
    DdNode *dfunc[2];	/* addresses of the functions to be dumped */
    DdManager *dd;	/* pointer to DD manager */
    DdNode *_true;	/* fast access to constant function */
    DdNode *M;
    DdNode **x;		/* pointers to variables */
    DdNode **y;		/* pointers to variables */
    DdNode **xn;       	/* complements of row variables */
    DdNode **yn_;      	/* complements of column variables */
    DdNode **xvars;
    DdNode **yvars;
    DdNode *C;		/* result of converting from ADD to BDD */
    DdNode *ess;	/* cube of essential variables */
    DdNode *shortP;	/* BDD cube of shortest path */
    DdNode *largest;	/* BDD of largest cube */
    DdNode *shortA;	/* ADD cube of shortest path */
    DdNode *constN;	/* value returned by evaluation of ADD */
    DdNode *ycube;	/* cube of the negated y vars for c-proj */
    DdNode *CP;		/* C-Projection of C */
    DdNode *CPr;	/* C-Selection of C */
    int    length;	/* length of the shortest path */
    int    nx;			/* number of variables */
    int    ny;
    int    maxnx;
    int    maxny;
    int    m;
    int    n;
    int    N;
    int    cmu;			/* use CMU multiplication */
    int    pr;			/* verbose printout level */
    int    harwell;
    int    multiple;		/* read multiple matrices */
    int    ok;
    int    c;			/* variable to read in options */
    int    approach;		/* reordering approach */
    int    autodyn;		/* automatic reordering */
    int    groupcheck;		/* option for group sifting */
    int    profile;		/* print heap profile if != 0 */
    int    keepperm;		/* keep track of permutation */
    int    clearcache;		/* clear the cache after each matrix */
    int    blifOrDot;		/* dump format: 0 -> dot, 1 -> blif, ... */
    int    retval;		/* return value */
    int    i;			/* loop index */
    long   startTime;		/* initial time */
    long   lapTime;
    int    size;
    unsigned int cacheSize, maxMemory;
    unsigned int nvars,nslots;

    startTime = util_cpu_time();

    approach = CUDD_REORDER_NONE;
    autodyn = 0;
    pr = 0;
    harwell = 0;
    multiple = 0;
    profile = 0;
    keepperm = 0;
    cmu = 0;
    N = 4;
    nvars = 4;
    cacheSize = 127;
    maxMemory = 0;
    nslots = CUDD_UNIQUE_SLOTS;
    clearcache = 0;
    groupcheck = CUDD_GROUP_CHECK7;
    dfile = NULL;
    blifOrDot = 0; /* dot format */

    /* Parse command line. */
    while ((c = util_getopt(argc, argv, (char *) "CDHMPS:a:bcd:g:hkmn:p:v:x:X:"))
	   != EOF) {
	switch(c) {
	case 'C':
	    cmu = 1;
	    break;
	case 'D':
	    autodyn = 1;
	    break;
	case 'H':
	    harwell = 1;
	    break;
	case 'M':
#ifdef MNEMOSYNE
	    (void) mnem_setrecording(0);
#endif
	    break;
	case 'P':
	    profile = 1;
	    break;
	case 'S':
	    nslots = atoi(util_optarg);
	    break;
	case 'X':
	    maxMemory = atoi(util_optarg);
	    break;
	case 'a':
	    approach = atoi(util_optarg);
	    break;
	case 'b':
	    blifOrDot = 1; /* blif format */
	    break;
	case 'c':
	    clearcache = 1;
	    break;
	case 'd':
	    dfile = util_optarg;
	    break;
	case 'g':
	    groupcheck = atoi(util_optarg);
	    break;
	case 'k':
	    keepperm = 1;
	    break;
	case 'm':
	    multiple = 1;
	    break;
	case 'n':
	    N = atoi(util_optarg);
	    break;
	case 'p':
	    pr = atoi(util_optarg);
	    break;
	case 'v':
	    nvars = atoi(util_optarg);
	    break;
	case 'x':
	    cacheSize = atoi(util_optarg);
	    break;
	case 'h':
	default:
	    usage(argv[0]);
	    break;
	}
    }

    if (argc - util_optind == 0) {
	file = (char *) "-";
    } else if (argc - util_optind == 1) {
	file = argv[util_optind];
    } else {
	usage(argv[0]);
    }
    if ((approach<0) || (approach>17)) {
	(void) fprintf(stderr,"Invalid approach: %d \n",approach);
	usage(argv[0]);
    }

    if (pr >= 0) {
	(void) printf("# %s\n", TESTCUDD_VERSION);
	/* Echo command line and arguments. */
	(void) printf("#");
	for (i = 0; i < argc; i++) {
	    (void) printf(" %s", argv[i]);
	}
	(void) printf("\n");
	(void) fflush(stdout);
    }

    /* Initialize manager and provide easy reference to terminals. */
    dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory);
    _true = DD_TRUE(dd);
    dd->groupcheck = (Cudd_AggregationType) groupcheck;
    if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME);

    /* Open input file. */
    fp = open_file(file, "r");

    /* Open dump file if requested */
    if (dfile != NULL) {
	dfp = open_file(dfile, "w");
    }

    x = y = xn = yn_ = NULL;
    do {
	/* We want to start anew for every matrix. */
	maxnx = maxny = 0;
	nx = maxnx; ny = maxny;
	if (pr>0) lapTime = util_cpu_time();
	if (harwell) {
	    if (pr >= 0) (void) printf(":name: ");
	    ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
	    &m, &n, 0, 2, 1, 2, pr);
	} else {
	    ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
	    &m, &n, 0, 2, 1, 2);
	    if (pr >= 0)
		(void) printf(":name: %s: %d rows %d columns\n", file, m, n);
	}
	if (!ok) {
	    (void) fprintf(stderr, "Error reading matrix\n");
	    exit(1);
	}

	if (nx > maxnx) maxnx = nx;
	if (ny > maxny) maxny = ny;

	/* Build cube of negated y's. */
	ycube = DD_TRUE(dd);
	Cudd_Ref(ycube);
	for (i = maxny - 1; i >= 0; i--) {
	    DdNode *tmpp;
	    tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube);
	    if (tmpp == NULL) exit(2);
	    Cudd_Ref(tmpp);
	    Cudd_RecursiveDeref(dd,ycube);
	    ycube = tmpp;
	}
	/* Initialize vectors of BDD variables used by priority func. */
	xvars = ALLOC(DdNode *, nx);
	if (xvars == NULL) exit(2);
	for (i = 0; i < nx; i++) {
	    xvars[i] = dd->vars[x[i]->index];
	}
	yvars = ALLOC(DdNode *, ny);
	if (yvars == NULL) exit(2);
	for (i = 0; i < ny; i++) {
	    yvars[i] = dd->vars[y[i]->index];
	}

	/* Clean up */
	for (i=0; i < maxnx; i++) {
	    Cudd_RecursiveDeref(dd, x[i]);
	    Cudd_RecursiveDeref(dd, xn[i]);
	}
	FREE(x);
	FREE(xn);
	for (i=0; i < maxny; i++) {
	    Cudd_RecursiveDeref(dd, y[i]);
	    Cudd_RecursiveDeref(dd, yn_[i]);
	}
	FREE(y);
	FREE(yn_);

	if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}

	if (pr>0) (void) printf(":2: time to read the matrix = %s\n",
		    util_print_time(util_cpu_time() - lapTime));

	C = Cudd_addBddPattern(dd, M);
	if (C == 0) exit(2);
	Cudd_Ref(C);
	if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);}

	/* Test iterators. */
	retval = testIterators(dd,M,C,pr);
	if (retval == 0) exit(2);

	cuddCacheProfile(dd,stdout);

	/* Test XOR */
	retval = testXor(dd,C,pr,nx+ny);
	if (retval == 0) exit(2);

	/* Test Hamming distance functions. */
	retval = testHamming(dd,C,pr);
	if (retval == 0) exit(2);

	/* Test selection functions. */
	CP = Cudd_CProjection(dd,C,ycube);
	if (CP == NULL) exit(2);
	Cudd_Ref(CP);
	if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);}
	if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);}

	if (nx == ny) {
	    CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL,
		(DdNode *)NULL,ny,Cudd_Xgty);
	    if (CPr == NULL) exit(2);
	    Cudd_Ref(CPr);
	    if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);}
	    if (CP != CPr) {
		(void) printf("CP != CPr!\n");
	    }
	    Cudd_RecursiveDeref(dd, CPr);
	}
	FREE(xvars); FREE(yvars);

	Cudd_RecursiveDeref(dd, CP);
	Cudd_RecursiveDeref(dd, ycube);

	/* Test functions for essential variables. */
	ess = Cudd_FindEssential(dd,C);
	if (ess == NULL) exit(2);
	Cudd_Ref(ess);
	if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);}
	Cudd_RecursiveDeref(dd, ess);

	/* Test functions for shortest paths. */
	shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length);
	if (shortP == NULL) exit(2);
	Cudd_Ref(shortP);
	if (pr>0) {
	    (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
	}
	/* Test functions for largest cubes. */
	largest = Cudd_LargestCube(dd, Cudd_Not(C), &length);
	if (largest == NULL) exit(2);
	Cudd_Ref(largest);
	if (pr>0) {
	    (void) printf(":5b: largest");
	    Cudd_PrintDebug(dd,largest,nx+ny,pr);
	}
	Cudd_RecursiveDeref(dd, largest);

	/* Test Cudd_addEvalConst and Cudd_addIteConstant. */
	shortA = Cudd_BddToAdd(dd,shortP);
	if (shortA == NULL) exit(2);
	Cudd_Ref(shortA);
	Cudd_RecursiveDeref(dd, shortP);
	constN = Cudd_addEvalConst(dd,shortA,M);
	if (constN == DD_NON_CONSTANT) exit(2);
	if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2);
	if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));}
	Cudd_RecursiveDeref(dd, shortA);

	shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length);
	if (shortP == NULL) exit(2);
	Cudd_Ref(shortP);
	if (pr>0) {
	    (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
	}

	/* Test Cudd_bddIteConstant and Cudd_bddLeq. */
	if (!Cudd_bddLeq(dd,shortP,C)) exit(2);
	if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),_true,C) != _true) exit(2);
	Cudd_RecursiveDeref(dd, shortP);

	if (profile) {
	    retval = cuddHeapProfile(dd);
	}

	size = dd->size;

	if (pr>0) {
	    (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
	}

	/* Reorder if so requested. */
        if (approach != CUDD_REORDER_NONE) {
#ifndef DD_STATS
	    retval = Cudd_EnableReorderingReporting(dd);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n");
		exit(3);
	    }
#endif
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		exit(3);
	    }
	    retval = Cudd_CheckKeys(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
		exit(3);
	    }
#endif
	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
		exit(3);
	    }
#ifndef DD_STATS
	    retval = Cudd_DisableReorderingReporting(dd);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n");
		exit(3);
	    }
#endif
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		exit(3);
	    }
	    retval = Cudd_CheckKeys(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
		exit(3);
	    }
#endif
	    if (approach == CUDD_REORDER_SYMM_SIFT ||
	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
		Cudd_SymmProfile(dd,0,dd->size-1);
	    }

	    if (pr>0) {
		(void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
	    }

	    if (keepperm) {
		/* Print variable permutation. */
		(void) printf("Variable Permutation:");
		for (i=0; i<size; i++) {
		    if (i%20 == 0) (void) printf("\n");
		    (void) printf("%d ", dd->invperm[i]);
		}
		(void) printf("\n");
		(void) printf("Inverse Permutation:");
		for (i=0; i<size; i++) {
		    if (i%20 == 0) (void) printf("\n");
		    (void) printf("%d ", dd->perm[i]);
		}
		(void) printf("\n");
	    }

	    if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}

	    if (profile) {
		retval = cuddHeapProfile(dd);
	    }

	}

	/* Dump DDs of C and M if so requested. */
	if (dfile != NULL) {
	    dfunc[0] = C;
	    dfunc[1] = M;
	    if (blifOrDot == 1) {
		/* Only dump C because blif cannot handle ADDs */
		retval = Cudd_DumpBlif(dd,1,dfunc,NULL,(char **)onames,
				       NULL,dfp);
	    } else {
		retval = Cudd_DumpDot(dd,2,dfunc,NULL,(char **)onames,dfp);
	    }
	    if (retval != 1) {
		(void) fprintf(stderr,"abnormal termination\n");
		exit(2);
	    }
	}

	Cudd_RecursiveDeref(dd, C);
	Cudd_RecursiveDeref(dd, M);

	if (clearcache) {
	    if (pr>0) {(void) printf("Clearing the cache... ");}
	    for (i = dd->cacheSlots - 1; i>=0; i--) {
		dd->cache[i].data = NIL(DdNode);
	    }
	    if (pr>0) {(void) printf("done\n");}
	}
	if (pr>0) {
	    (void) printf("Number of variables = %6d\t",dd->size);
	    (void) printf("Number of slots     = %6d\n",dd->slots);
	    (void) printf("Number of keys      = %6d\t",dd->keys);
	    (void) printf("Number of min dead  = %6d\n",dd->minDead);
	}

    } while (multiple && !feof(fp));

    fclose(fp);
    if (dfile != NULL) {
	fclose(dfp);
    }

    /* Second phase: experiment with Walsh matrices. */
    if (!testWalsh(dd,N,cmu,approach,pr)) {
	exit(2);
    }

    /* Check variable destruction. */
    assert(cuddDestroySubtables(dd,3));
    assert(Cudd_DebugCheck(dd) == 0);
    assert(Cudd_CheckKeys(dd) == 0);

    retval = Cudd_CheckZeroRef(dd);
    ok = retval != 0;  /* ok == 0 means O.K. */
    if (retval != 0) {
	(void) fprintf(stderr,
	    "%d non-zero DD reference counts after dereferencing\n", retval);
    }

    if (pr >= 0) {
	(void) Cudd_PrintInfo(dd,stdout);
    }

    Cudd_Quit(dd);

#ifdef MNEMOSYNE
    mnem_writestats();
#endif

    if (pr>0) (void) printf("total time = %s\n",
		util_print_time(util_cpu_time() - startTime));

    if (pr >= 0) util_print_cpu_stats(stdout);
    exit(ok);
    /* NOTREACHED */

} /* end of main */
Ejemplo n.º 22
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_MinHammingDist.]

  Description [Performs the recursive step of Cudd_MinHammingDist.
  It is based on the following identity. Let H(f) be the
  minimum Hamming distance of the minterms of f from the reference
  minterm. Then:
  <xmp>
    H(f) = min(H(f0)+h0,H(f1)+h1)
  </xmp>
  where f0 and f1 are the two cofactors of f with respect to its top
  variable; h0 is 1 if the minterm assigns 1 to the top variable of f;
  h1 is 1 if the minterm assigns 0 to the top variable of f.
  The upper bound on the distance is used to bound the depth of the
  recursion.
  Returns the minimum distance unless it exceeds the upper bound or
  computation fails.]

  SideEffects [None]

  SeeAlso     [Cudd_MinHammingDist]

******************************************************************************/
static int
cuddMinHammingDistRecur(
  DdNode * f,
  int *minterm,
  DdHashTable * table,
  int upperBound)
{
    DdNode	*F, *Ft, *Fe;
    double	h, hT, hE;
    DdNode	*zero, *res;
    DdManager	*dd = table->manager;

    statLine(dd);
    if (upperBound == 0) return(0);

    F = Cudd_Regular(f);

    if (cuddIsConstant(F)) {
	zero = Cudd_Not(DD_ONE(dd));
	if (f == dd->background || f == zero) {
	    return(upperBound);
	} else {
	    return(0);
	}
    }
    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
      //Rob Apr 6 2001: might need to change this, not sure what it does.....
      h = (*cuddV(res)).get_val();
      if (res->ref == 0) {
	dd->dead++;
	dd->constants.dead++;
      }
      return((int) h);
    }

    Ft = cuddT(F); Fe = cuddE(F);
    if (Cudd_IsComplement(f)) {
	Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe);
    }
    if (minterm[F->index] == 0) {
	DdNode *temp = Ft;
	Ft = Fe; Fe = temp;
    }

    hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound);
    if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
    if (hT == 0) {
	hE = upperBound;
    } else {
	hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1);
	if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
    }
    h = ddMin(hT, hE + 1);

    if (F->ref != 1) {
	ptrint fanout = (ptrint) F->ref;
	cuddSatDec(fanout);
	Terminal hTerminal;
	hTerminal.set((double) h);
	res = cuddUniqueConst(dd,&hTerminal);
	//res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h);
	if (!cuddHashTableInsert1(table,f,res,fanout)) {
	    cuddRef(res); Cudd_RecursiveDeref(dd, res);
	    return(CUDD_OUT_OF_MEM);
	}
    }

    return((int) h);

} /* end of cuddMinHammingDistRecur */
/**Function*************************************************************

  Synopsis    [Transfers the DD into the internal reordering data structure.]

  Description [It is important that the hash table is lossless.]

  SideEffects []

  SeeAlso     []

***********************************************************************/
reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F )
{
	DdManager * dd = p->dd;
	reo_unit * pUnit;
	int HKey, fComp;
	
	fComp = Cudd_IsComplement(F);
	F = Cudd_Regular(F);

	// check the hash-table
	if ( F->ref != 1 )
	{
		// search cache - use linear probing
		for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
			if ( p->HTable[HKey].Arg1 == (reo_unit *)F )
			{
				pUnit = p->HTable[HKey].Arg2;  
				assert( pUnit );
				// increment the edge counter
				pUnit->n++;
				return Unit_NotCond( pUnit, fComp );
			}
	}
	// the entry in not found in the cache
	
	// create a new entry
	pUnit         = reoUnitsGetNextUnit( p );
	pUnit->n      = 1;
	if ( cuddIsConstant(F) )
	{
		pUnit->lev    = REO_CONST_LEVEL;
		pUnit->pE     = (reo_unit*)((int)(cuddV(F)));
		pUnit->pT     = NULL;
		// check if the diagram that is being reordering has complement edges
		if ( F != dd->one )
			p->fThisIsAdd = 1;
		// insert the unit into the corresponding plane
		reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter
	}
	else
	{
		pUnit->lev    = p->pMapToPlanes[F->index];
		pUnit->pE     = reoTransferNodesToUnits_rec( p, cuddE(F) );
		pUnit->pT     = reoTransferNodesToUnits_rec( p, cuddT(F) );
		// insert the unit into the corresponding plane
		reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter
	}

	// add to the hash table
	if ( F->ref != 1 )
	{
		// the next free entry is already found - it is pointed to by HKey
		// while we traversed the diagram, the hash entry to which HKey points,
		// might have been used. Make sure that its signature is different.
		for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
		p->HTable[HKey].Sign = p->Signature;
		p->HTable[HKey].Arg1 = (reo_unit *)F;
		p->HTable[HKey].Arg2 = pUnit;
	}

	// increment the counter of nodes
	p->nNodesCur++;
	return Unit_NotCond( pUnit, fComp );
}
Ejemplo n.º 24
0
/**Function********************************************************************

  Synopsis    [Writes a dot file representing the argument ZDDs.]

  Description [Writes a file representing the argument ZDDs in a format
  suitable for the graph drawing program dot.
  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory,
  file system full).
  Cudd_zddDumpDot does not close the file: This is the caller
  responsibility. Cudd_zddDumpDot uses a minimal unique subset of the
  hexadecimal address of a node as name for it.
  If the argument inames is non-null, it is assumed to hold the pointers
  to the names of the inputs. Similarly for onames.
  Cudd_zddDumpDot uses the following convention to draw arcs:
    <ul>
    <li> solid line: THEN arcs;
    <li> dashed line: ELSE arcs.
    </ul>
  The dot options are chosen so that the drawing fits on a letter-size
  sheet.
  ]

  SideEffects [None]

  SeeAlso     [Cudd_DumpDot Cudd_zddPrintDebug]

******************************************************************************/
int
Cudd_zddDumpDot(
  DdManager * dd /* manager */,
  int  n /* number of output nodes to be dumped */,
  DdNode ** f /* array of output nodes to be dumped */,
  char ** inames /* array of input names (or NULL) */,
  char ** onames /* array of output names (or NULL) */,
  FILE * fp /* pointer to the dump file */)
{
    DdNode	*support = NULL;
    DdNode	*scan;
    int		*sorted = NULL;
    int		nvars = dd->sizeZ;
    st_table	*visited = NULL;
    st_generator *gen;
    int		retval;
    int		i, j;
    int		slots;
    DdNodePtr	*nodelist;
    long	refAddr, diff, mask;

    /* Build a bit array with the support of f. */
    sorted = ALLOC(int,nvars);
    if (sorted == NULL) {
	dd->errorCode = CUDD_MEMORY_OUT;
	goto failure;
    }
    for (i = 0; i < nvars; i++) sorted[i] = 0;

    /* Take the union of the supports of each output function. */
    for (i = 0; i < n; i++) {
	support = Cudd_Support(dd,f[i]);
	if (support == NULL) goto failure;
	cuddRef(support);
	scan = support;
	while (!cuddIsConstant(scan)) {
	    sorted[scan->index] = 1;
	    scan = cuddT(scan);
	}
	Cudd_RecursiveDeref(dd,support);
    }
    support = NULL; /* so that we do not try to free it in case of failure */

    /* Initialize symbol table for visited nodes. */
    visited = st_init_table(st_ptrcmp, st_ptrhash);
    if (visited == NULL) goto failure;

    /* Collect all the nodes of this DD in the symbol table. */
    for (i = 0; i < n; i++) {
	retval = cuddCollectNodes(f[i],visited);
	if (retval == 0) goto failure;
    }

    /* Find how many most significant hex digits are identical
    ** in the addresses of all the nodes. Build a mask based
    ** on this knowledge, so that digits that carry no information
    ** will not be printed. This is done in two steps.
    **  1. We scan the symbol table to find the bits that differ
    **     in at least 2 addresses.
    **  2. We choose one of the possible masks. There are 8 possible
    **     masks for 32-bit integer, and 16 possible masks for 64-bit
    **     integers.
    */

    /* Find the bits that are different. */
    refAddr = (long) f[0];
    diff = 0;
    gen = st_init_gen(visited);
    while (st_gen(gen, (char **) &scan, NULL)) {
	diff |= refAddr ^ (long) scan;
    }
    st_free_gen(gen);

    /* Choose the mask. */
    for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) {
	mask = (1 << i) - 1;
	if (diff <= mask) break;
    }

    /* Write the header and the global attributes. */
    retval = fprintf(fp,"digraph \"ZDD\" {\n");
    if (retval == EOF) return(0);
    retval = fprintf(fp,
	"size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
    if (retval == EOF) return(0);

    /* Write the input name subgraph by scanning the support array. */
    retval = fprintf(fp,"{ node [shape = plaintext];\n");
    if (retval == EOF) goto failure;
    retval = fprintf(fp,"  edge [style = invis];\n");
    if (retval == EOF) goto failure;
    /* We use a name ("CONST NODES") with an embedded blank, because
    ** it is unlikely to appear as an input name.
    */
    retval = fprintf(fp,"  \"CONST NODES\" [style = invis];\n");
    if (retval == EOF) goto failure;
    for (i = 0; i < nvars; i++) {
        if (sorted[dd->invpermZ[i]]) {
	    if (inames == NULL) {
		retval = fprintf(fp,"\" %d \" -> ", dd->invpermZ[i]);
	    } else {
		retval = fprintf(fp,"\" %s \" -> ", inames[dd->invpermZ[i]]);
	    }
            if (retval == EOF) goto failure;
        }
    }
    retval = fprintf(fp,"\"CONST NODES\"; \n}\n");
    if (retval == EOF) goto failure;

    /* Write the output node subgraph. */
    retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n");
    if (retval == EOF) goto failure;
    for (i = 0; i < n; i++) {
	if (onames == NULL) {
	    retval = fprintf(fp,"\"F%d\"", i);
	} else {
	    retval = fprintf(fp,"\"  %s  \"", onames[i]);
	}
	if (retval == EOF) goto failure;
	if (i == n - 1) {
	    retval = fprintf(fp,"; }\n");
	} else {
	    retval = fprintf(fp," -> ");
	}
	if (retval == EOF) goto failure;
    }

    /* Write rank info: All nodes with the same index have the same rank. */
    for (i = 0; i < nvars; i++) {
        if (sorted[dd->invpermZ[i]]) {
	    retval = fprintf(fp,"{ rank = same; ");
	    if (retval == EOF) goto failure;
	    if (inames == NULL) {
		retval = fprintf(fp,"\" %d \";\n", dd->invpermZ[i]);
	    } else {
		retval = fprintf(fp,"\" %s \";\n", inames[dd->invpermZ[i]]);
	    }
            if (retval == EOF) goto failure;
	    nodelist = dd->subtableZ[i].nodelist;
	    slots = dd->subtableZ[i].slots;
	    for (j = 0; j < slots; j++) {
		scan = nodelist[j];
		while (scan != NULL) {
		    if (st_is_member(visited,(char *) scan)) {
			retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode));
			if (retval == EOF) goto failure;
		    }
		    scan = scan->next;
		}
	    }
	    retval = fprintf(fp,"}\n");
	    if (retval == EOF) goto failure;
	}
    }

    /* All constants have the same rank. */
    retval = fprintf(fp,
	"{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
    if (retval == EOF) goto failure;
    nodelist = dd->constants.nodelist;
    slots = dd->constants.slots;
    for (j = 0; j < slots; j++) {
	scan = nodelist[j];
	while (scan != NULL) {
	    if (st_is_member(visited,(char *) scan)) {
		retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode));
		if (retval == EOF) goto failure;
	    }
	    scan = scan->next;
	}
    }
    retval = fprintf(fp,"}\n}\n");
    if (retval == EOF) goto failure;

    /* Write edge info. */
    /* Edges from the output nodes. */
    for (i = 0; i < n; i++) {
	if (onames == NULL) {
	    retval = fprintf(fp,"\"F%d\"", i);
	} else {
	    retval = fprintf(fp,"\"  %s  \"", onames[i]);
	}
	if (retval == EOF) goto failure;
	retval = fprintf(fp," -> \"%lx\" [style = solid];\n",
			 (mask & (long) f[i]) / sizeof(DdNode));
	if (retval == EOF) goto failure;
    }

    /* Edges from internal nodes. */
    for (i = 0; i < nvars; i++) {
        if (sorted[dd->invpermZ[i]]) {
	    nodelist = dd->subtableZ[i].nodelist;
	    slots = dd->subtableZ[i].slots;
	    for (j = 0; j < slots; j++) {
		scan = nodelist[j];
		while (scan != NULL) {
		    if (st_is_member(visited,(char *) scan)) {
			retval = fprintf(fp,
			    "\"%lx\" -> \"%lx\";\n",
			    (mask & (long) scan) / sizeof(DdNode),
			    (mask & (long) cuddT(scan)) / sizeof(DdNode));
			if (retval == EOF) goto failure;
			retval = fprintf(fp,
					 "\"%lx\" -> \"%lx\" [style = dashed];\n",
					 (mask & (long) scan) / sizeof(DdNode),
					 (mask & (long) cuddE(scan)) / sizeof(DdNode));
			if (retval == EOF) goto failure;
		    }
		    scan = scan->next;
		}
	    }
	}
    }

    /* Write constant labels. */
    nodelist = dd->constants.nodelist;
    slots = dd->constants.slots;
    for (j = 0; j < slots; j++) {
	scan = nodelist[j];
	while (scan != NULL) {
	    if (st_is_member(visited,(char *) scan)) {
		retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n",
		    (mask & (long) scan) / sizeof(DdNode), cuddV(scan));
		if (retval == EOF) goto failure;
	    }
	    scan = scan->next;
	}
    }

    /* Write trailer and return. */
    retval = fprintf(fp,"}\n");
    if (retval == EOF) goto failure;

    st_free_table(visited);
    FREE(sorted);
    return(1);

failure:
    if (sorted != NULL) FREE(sorted);
    if (support != NULL) Cudd_RecursiveDeref(dd,support);
    if (visited != NULL) st_free_table(visited);
    return(0);

} /* end of Cudd_zddDumpBlif */
Ejemplo n.º 25
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddTransfer.]

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

  SideEffects [None]

  SeeAlso     [cuddauxAddTransfer]

******************************************************************************/
static DdNode *
cuddauxAddTransferRecur(
  DdManager * ddS,
  DdManager * ddD,
  DdNode * f,
  st_table * table)
{
  DdNode *ft, *fe, *t, *e, *var, *res;
  DdNode *one, *zero;
  int	   index;

  /* Trivial cases. */
  if (cuddIsConstant(f)){
    double v = cuddV(f);
    return (cuddUniqueConst(ddD,v));
  }
  /* Check the cache. */
  if(st_lookup(table, f, &res))
    return(res);
    
  /* Recursive step. */
  index = f->index;
  ft = cuddT(f); fe = cuddE(f);

  t = cuddauxAddTransferRecur(ddS, ddD, ft, table);
  if (t == NULL) {
    return(NULL);
  }
  cuddRef(t);

  e = cuddauxAddTransferRecur(ddS, ddD, fe, table);
  if (e == NULL) {
    Cudd_RecursiveDeref(ddD, t);
    return(NULL);
  }
  cuddRef(e);

  one = DD_ONE(ddD);
  zero = Cudd_Not(one);
  var = cuddUniqueInter(ddD,index,one,zero);
  if (var == NULL) {
    Cudd_RecursiveDeref(ddD, t);
    Cudd_RecursiveDeref(ddD, e);
    return(NULL);
  }
  res = cuddauxAddIteRecur(ddD,var,t,e);
  if (res == NULL) {
    Cudd_RecursiveDeref(ddD, t);
    Cudd_RecursiveDeref(ddD, e);
    return(NULL);
  }
  cuddRef(res);
  Cudd_RecursiveDeref(ddD, t);
  Cudd_RecursiveDeref(ddD, e);

  if (st_add_direct(table, (char *) f, (char *) res) == ST_OUT_OF_MEM) {
    Cudd_RecursiveDeref(ddD, res);
    return(NULL);
  }
  return(res);

} /* end of cuddauxAddTransferRecur */
Ejemplo n.º 26
0
/**Function********************************************************************

  Synopsis    [Performs the reordering-sensitive step of Extra_bddHaarInverse().]

  Description [Generates in a bottom-up fashion an ADD for the inverse Haar.]

  SideEffects [The third cached argument (bSteps) is the BDD of the elementary variable
  whose index equal to the number of lazy steps made thus far plus one. On the top-most
  level it is 0, next it is 1, etc.]

  SeeAlso     []

******************************************************************************/
DdNode * extraBddHaarInverse( 
  DdManager * dd,    /* the manager */
  DdNode * aFunc,    /* the function whose spectrum is being computed */
  DdNode * aSteps,   /* the index of this variable indicates the number of previous lazy recursive calls */
  DdNode * bVars,    /* the variables, on which the function depends */
  DdNode * bVarsAll, /* the set of all variables, which will never change through the calls */
  int      nVarsAll, /* the number of vars in the set */
  int    * InverseMap ) /* the variable map mapping the var index into its inverse var index */
{
	DdNode * aRes;
	DdNode * bCacheCube;
    statLine(dd); 

	/* terminal cases */
	if ( bVars == b1 )
	{ // return a terminal node with a value equal to cuddV(aFunc) * 2^(nSteps-1)
		if ( cuddV(aSteps) == 0.0 )
			return cuddUniqueConst( dd, cuddV(aFunc) ); 
		else
			return cuddUniqueConst( dd, cuddV(aFunc) * Extra_Power2( (int)(cuddV(aSteps)-1) ) ); 
	}

    /* check cache */
    /* the last two arguments are derivitives, therefore there are useless for caching */
	/* the other two arguments (bVars and bVarsAll) can be combined into one argument */
	bCacheCube = extraCachingCube( dd, bVarsAll, bVars );  Cudd_Ref( bCacheCube );
    if ( aRes = cuddCacheLookup(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube) )
	{
		Cudd_RecursiveDeref( dd, bCacheCube );
   		return aRes;
	}
	else
	{
		DdNode * aFunc0, * aFunc1;   /* cofactors of the function */
		DdNode * aInvH0, * aInvH1;   /* partial solutions of the problem */
		DdNode * aRes0,  * aRes1;    /* partial results to be composed by ITE */
		DdNode * aStepNext;

		/* aFunc cannot depend on a variable that is not in bVars */
		assert( cuddI(dd,aFunc->index) >= cuddI(dd,bVars->index) );

		/* cofactor the ADD */
		if ( aFunc->index == bVars->index )
		{
			aFunc0 = cuddE(aFunc);
			aFunc1 = cuddT(aFunc);
		}
		else /* bVars is higher in the variable order */
			aFunc0 = aFunc1 = aFunc;


		if ( cuddV(aSteps) > 0.0 ) /* meaning that it is a lazy call */
		{
			/* solve subproblems */
			aStepNext = cuddUniqueConst( dd, cuddV(aSteps)+1 );
			if ( aStepNext == NULL )
				return NULL;
			cuddRef( aStepNext );

			aInvH0 = extraBddHaarInverse( dd, aFunc0, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH0 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				return NULL;
			}
			cuddRef( aInvH0 );

			aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aInvH1 );
			Cudd_RecursiveDeref( dd, aStepNext );

			aRes0 = aInvH0;
			aRes1 = aInvH1;
		}
		else // if ( cuddV(aSteps) == 0.0 )
		{
			/* solve subproblems */
			aInvH0 = extraBddHaarInverse( dd, aFunc0, aSteps, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH0 == NULL )
				return NULL;
			cuddRef( aInvH0 );

			aStepNext = cuddUniqueConst( dd, 1.0 );
			if ( aStepNext == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aStepNext );

			aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aInvH1 );
			Cudd_RecursiveDeref( dd, aStepNext );


			/* compute  aRes0 = aWalsh0 + aWalsh1 */
			aRes0 = cuddAddApplyRecur( dd, Cudd_addPlus, aInvH0, aInvH1 );
			if ( aRes0 == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				Cudd_RecursiveDeref( dd, aInvH1 );
				return NULL;
			}
			cuddRef( aRes0 );

			/* compute  aRes1 = aWalsh0 - aWalsh1 */
			aRes1 = cuddAddApplyRecur( dd, Cudd_addMinus, aInvH0, aInvH1 );
			if ( aRes1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				Cudd_RecursiveDeref( dd, aInvH1 );
				Cudd_RecursiveDeref( dd, aRes0 );
				return NULL;
			}
			cuddRef( aRes1 );

			Cudd_RecursiveDeref(dd, aInvH0);
			Cudd_RecursiveDeref(dd, aInvH1);
		}

		/* only aRes0 and aRes1 are referenced at this point */

		/* consider the case when Res0 and Res1 are the same node */
		aRes = extraAddIteRecurGeneral( dd, dd->vars[ InverseMap[bVars->index] ], aRes1, aRes0 );
		if (aRes == NULL) 
		{
			Cudd_RecursiveDeref(dd, aRes1);
			Cudd_RecursiveDeref(dd, aRes0);
			return NULL;
		}
		cuddRef( aRes );
		Cudd_RecursiveDeref(dd, aRes1);
		Cudd_RecursiveDeref(dd, aRes0);
		cuddDeref( aRes );

		/* insert the result into cache */
		cuddCacheInsert(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube, aRes);
		Cudd_RecursiveDeref( dd, bCacheCube );
		return aRes;
	}
} /* end of extraBddHaarInverse */
Ejemplo n.º 27
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addMatrixMultiply.]

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

  SideEffects [None]

******************************************************************************/
static DdNode *
addMMRecur(
  DdManager * dd,
  DdNode * A,
  DdNode * B,
  int  topP,
  int * vars)
{
    DdNode *zero,
           *At,		/* positive cofactor of first operand */
	   *Ae,		/* negative cofactor of first operand */
	   *Bt,		/* positive cofactor of second operand */
	   *Be,		/* negative cofactor of second operand */
	   *t,		/* positive cofactor of result */
	   *e,		/* negative cofactor of result */
	   *scaled,	/* scaled result */
	   *add_scale,	/* ADD representing the scaling factor */
	   *res;
    int	i;		/* loop index */
    double scale;	/* scaling factor */
    int index;		/* index of the top variable */
    CUDD_VALUE_TYPE value;
    unsigned int topA, topB, topV;
    DD_CTFP cacheOp;

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

    if (A == zero || B == zero) {
        return(zero);
    }

    if (cuddIsConstant(A) && cuddIsConstant(B)) {
	/* Compute the scaling factor. It is 2^k, where k is the
	** number of summation variables below the current variable.
	** Indeed, these constants represent blocks of 2^k identical
	** constant values in both A and B.
	*/
	value = cuddV(A) * cuddV(B);
	for (i = 0; i < dd->size; i++) {
	    if (vars[i]) {
		if (dd->perm[i] > topP) {
		    value *= (CUDD_VALUE_TYPE) 2;
		}
	    }
	}
	res = cuddUniqueConst(dd, value);
	return(res);
    }

    /* Standardize to increase cache efficiency. Clearly, A*B != B*A
    ** in matrix multiplication. However, which matrix is which is
    ** determined by the variables appearing in the ADDs and not by
    ** which one is passed as first argument.
    */
    if (A > B) {
	DdNode *tmp = A;
	A = B;
	B = tmp;
    }

    topA = cuddI(dd,A->index); topB = cuddI(dd,B->index);
    topV = ddMin(topA,topB);

    cacheOp = (DD_CTFP) addMMRecur;
    res = cuddCacheLookup2(dd,cacheOp,A,B);
    if (res != NULL) {
	/* If the result is 0, there is no need to normalize.
	** Otherwise we count the number of z variables between
	** the current depth and the top of the ADDs. These are
	** the missing variables that determine the size of the
	** constant blocks.
	*/
	if (res == zero) return(res);
	scale = 1.0;
	for (i = 0; i < dd->size; i++) {
	    if (vars[i]) {
		if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
		    scale *= 2;
		}
	    }
	}
	if (scale > 1.0) {
	    cuddRef(res);
	    add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
	    if (add_scale == NULL) {
		Cudd_RecursiveDeref(dd, res);
		return(NULL);
	    }
	    cuddRef(add_scale);
	    scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
	    if (scaled == NULL) {
		Cudd_RecursiveDeref(dd, add_scale);
		Cudd_RecursiveDeref(dd, res);
		return(NULL);
	    }
	    cuddRef(scaled);
	    Cudd_RecursiveDeref(dd, add_scale);
	    Cudd_RecursiveDeref(dd, res);
	    res = scaled;
	    cuddDeref(res);
	}
        return(res);
    }

    /* compute the cofactors */
    if (topV == topA) {
	At = cuddT(A);
	Ae = cuddE(A);
    } else {
	At = Ae = A;
    }
    if (topV == topB) {
	Bt = cuddT(B);
	Be = cuddE(B);
    } else {
	Bt = Be = B;
    }

    t = addMMRecur(dd, At, Bt, (int)topV, vars);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = addMMRecur(dd, Ae, Be, (int)topV, vars);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd, t);
	return(NULL);
    }
    cuddRef(e);

    index = dd->invperm[topV];
    if (vars[index] == 0) {
	/* We have split on either the rows of A or the columns
	** of B. We just need to connect the two subresults,
	** which correspond to two submatrices of the result.
	*/
	res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddRef(res);
	cuddDeref(t);
	cuddDeref(e);
    } else {
	/* we have simultaneously split on the columns of A and
	** the rows of B. The two subresults must be added.
	*/
	res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(dd, t);
	Cudd_RecursiveDeref(dd, e);
    }

    cuddCacheInsert2(dd,cacheOp,A,B,res);

    /* We have computed (and stored in the computed table) a minimal
    ** result; that is, a result that assumes no summation variables
    ** between the current depth of the recursion and its top
    ** variable. We now take into account the z variables by properly
    ** scaling the result.
    */
    if (res != zero) {
	scale = 1.0;
	for (i = 0; i < dd->size; i++) {
	    if (vars[i]) {
		if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
		    scale *= 2;
		}
	    }
	}
	if (scale > 1.0) {
	    add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
	    if (add_scale == NULL) {
		Cudd_RecursiveDeref(dd, res);
		return(NULL);
	    }
	    cuddRef(add_scale);
	    scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
	    if (scaled == NULL) {
		Cudd_RecursiveDeref(dd, res);
		Cudd_RecursiveDeref(dd, add_scale);
		return(NULL);
	    }
	    cuddRef(scaled);
	    Cudd_RecursiveDeref(dd, add_scale);
	    Cudd_RecursiveDeref(dd, res);
	    res = scaled;
	}
    }
    cuddDeref(res);
    return(res);

} /* end of addMMRecur */
Ejemplo n.º 28
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addTriangle.]

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

  SideEffects [None]

******************************************************************************/
static DdNode *
addTriangleRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  int * vars,
  DdNode *cube)
{
    DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res;
    CUDD_VALUE_TYPE value;
    int top, topf, topg, index;

    statLine(dd);
    if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) {
	return(DD_PLUS_INFINITY(dd));
    }

    if (cuddIsConstant(f) && cuddIsConstant(g)) {
	value = cuddV(f) + cuddV(g);
	res = cuddUniqueConst(dd, value);
	return(res);
    }
    if (f < g) {
	DdNode *tmp = f;
	f = g;
	g = tmp;
    }

    if (f->ref != 1 || g->ref != 1) {
	res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube);
	if (res != NULL) {
	    return(res);
	}
    }

    topf = cuddI(dd,f->index); topg = cuddI(dd,g->index);
    top = ddMin(topf,topg);

    if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
    if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}

    t = addTriangleRecur(dd, fv, gv, vars, cube);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = addTriangleRecur(dd, fvn, gvn, vars, cube);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd, t);
	return(NULL);
    }
    cuddRef(e);

    index = dd->invperm[top];
    if (vars[index] < 0) {
	res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddDeref(t);
	cuddDeref(e);
    } else {
	res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(dd, t);
	Cudd_RecursiveDeref(dd, e);
	cuddDeref(res);
    }

    if (f->ref != 1 || g->ref != 1) {
	cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res);
    }

    return(res);

} /* end of addTriangleRecur */
Ejemplo n.º 29
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addOuterSum.]

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

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
cuddAddOuterSumRecur(
  DdManager *dd,
  DdNode *M,
  DdNode *r,
  DdNode *c)
{
    DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re;
    int topM, topc, topr;
    int v, index;

    statLine(dd);
    /* Check special cases. */
    if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); 

    if (cuddIsConstant(c) && cuddIsConstant(r)) {
	R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r));
	cuddRef(R);
	if (cuddIsConstant(M)) {
	    if (cuddV(R) <= cuddV(M)) {
		cuddDeref(R);
	        return(R);
	    } else {
	        Cudd_RecursiveDeref(dd,R);       
		return(M);
	    }
	} else {
	    P = Cudd_addApply(dd,Cudd_addMinimum,R,M);
	    cuddRef(P);
	    Cudd_RecursiveDeref(dd,R);
	    cuddDeref(P);
	    return(P);
	}
    }

    /* Check the cache. */
    R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c);
    if (R != NULL) return(R);

    topM = cuddI(dd,M->index); topr = cuddI(dd,r->index);
    topc = cuddI(dd,c->index);
    v = ddMin(topM,ddMin(topr,topc));

    /* Compute cofactors. */
    if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; }
    if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; }
    if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; }

    /* Recursively solve. */
    Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct);
    if (Rt == NULL) return(NULL);
    cuddRef(Rt);
    Re = cuddAddOuterSumRecur(dd,Me,re,ce);
    if (Re == NULL) {
	Cudd_RecursiveDeref(dd, Rt);
	return(NULL);
    }
    cuddRef(Re);
    index = dd->invperm[v];
    R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re);
    if (R == NULL) {
	Cudd_RecursiveDeref(dd, Rt);
	Cudd_RecursiveDeref(dd, Re);
	return(NULL);
    }
    cuddDeref(Rt);
    cuddDeref(Re);

    /* Store the result in the cache. */
    cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R);

    return(R);

} /* end of cuddAddOuterSumRecur */