Ejemplo n.º 1
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;

    statLine(dd);
    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(dd->out,
			   "Cudd_Cofactor: Invalid restriction 2\n");
	    dd->errorCode = CUDD_INVALID_ARG;
	    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 */
Ejemplo n.º 2
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_addBddBooleanMap.]

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

  SideEffects [None]

  SeeAlso     [addBddDoStrictThreshold]

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

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

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

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

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

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

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

    return(res);

} /* end of addBddBooleanMap */
Ejemplo n.º 3
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.º 4
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     [cuddBddTransfer]

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

    statLine(ddD);
    one = DD_TRUE(ddD);
    comple = Cudd_IsComplement(f);

    /* Trivial cases. */
    if (Cudd_IsConstant(f)) return(Cudd_NotCond(one, comple));

    /* Make canonical to increase the utilization of the cache. */
    f = Cudd_NotCond(f,comple);
    /* Now f is a regular pointer to a non-constant node. */

    /* Check the cache. */
    if(st_lookup(table, f, &res))
	return(Cudd_NotCond(res,comple));
    
    /* Recursive step. */
    index = f->index;
    ft = cuddT(f); fe = cuddE(f);

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

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

    zero = Cudd_Not(one);
    var = cuddUniqueInter(ddD,index,one,zero);
    if (var == NULL) {
	Cudd_RecursiveDeref(ddD, t);
	Cudd_RecursiveDeref(ddD, e);
    	return(NULL);
    }
    res = cuddBddIteRecur(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(Cudd_NotCond(res,comple));

} /* end of cuddBddTransferRecur */
Ejemplo n.º 5
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_addBddPattern.]

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

  SideEffects [None]

  SeeAlso     []

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

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

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

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

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

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

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

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

    return(res);

} /* end of cuddAddBddDoPattern */
Ejemplo n.º 6
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step for Cudd_BddTo01Add.]

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

  SideEffects [None]

  SeeAlso     []

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

    statLine(dd);

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

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

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

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

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

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

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

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

    return(res);

} /* end of ddBddTo01AddRecur */
Ejemplo n.º 7
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddCompose.]

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

  SideEffects [None]

  SeeAlso     [Cudd_bddCompose]

******************************************************************************/
DdNode *
cuddBddComposeRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * proj)
{
    DdNode	*F, *G, *f1, *f0, *g1, *g0, *r, *t, *e;
    unsigned int v, topf, topg, topindex;
    int		comple;

    statLine(dd);
    v = dd->perm[proj->index];
    F = Cudd_Regular(f);
    topf = cuddI(dd,F->index);

    /* Terminal case. Subsumes the test for constant f. */
    if (topf > v) return(f);

    /* We solve the problem for a regular pointer, and then complement
    ** the result if the pointer was originally complemented.
    */
    comple = Cudd_IsComplement(f);

    /* Check cache. */
    r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj);
    if (r != NULL) {
	return(Cudd_NotCond(r,comple));
    }

    if (topf == v) {
	/* Compose. */
	f1 = cuddT(F);
	f0 = cuddE(F);
	r = cuddBddIteRecur(dd, g, f1, f0);
	if (r == NULL) return(NULL);
    } else {
	/* Compute cofactors of f and g. Remember the index of the top
	** variable.
	*/
	G = Cudd_Regular(g);
	topg = cuddI(dd,G->index);
	if (topf > topg) {
	    topindex = G->index;
	    f1 = f0 = F;
	} else {
	    topindex = F->index;
	    f1 = cuddT(F);
	    f0 = cuddE(F);
	}
	if (topg > topf) {
	    g1 = g0 = g;
	} else {
	    g1 = cuddT(G);
	    g0 = cuddE(G);
	    if (g != G) {
		g1 = Cudd_Not(g1);
		g0 = Cudd_Not(g0);
	    }
	}
	/* Recursive step. */
	t = cuddBddComposeRecur(dd, f1, g1, proj);
	if (t == NULL) return(NULL);
	cuddRef(t);
	e = cuddBddComposeRecur(dd, f0, g0, proj);
	if (e == NULL) {
	    Cudd_IterDerefBdd(dd, t);
	    return(NULL);
	}
	cuddRef(e);

	r = cuddBddIteRecur(dd, dd->vars[topindex], t, e);
	if (r == NULL) {
	    Cudd_IterDerefBdd(dd, t);
	    Cudd_IterDerefBdd(dd, e);
	    return(NULL);
	}
	cuddRef(r);
	Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */
	Cudd_IterDerefBdd(dd, e);
	cuddDeref(r);
    }

    cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r);

    return(Cudd_NotCond(r,comple));

} /* end of cuddBddComposeRecur */
Ejemplo n.º 8
0
/**
  @brief Takes the exclusive OR 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_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;
    int topf, topg, topcube, top;
    unsigned int 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);
    }

    checkWhetherToGiveUp(manager);

    /* 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 */
Ejemplo n.º 9
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, (const char *)Nv, (char **)&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, (const char *)Nnv, (char **)&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 */
Ejemplo n.º 10
0
/**Function********************************************************************

  Synopsis    [Decreases the reference count of BDD node n.]

  Description [Enqueues node n for later dereferencing. If the queue
  is full decreases the reference count of the oldest node N to make
  room for n. If N dies, recursively decreases the reference counts of
  its children.  It is used to dispose of a BDD that is currently not
  needed, but may be useful again in the near future. The dereferencing
  proper is done as in Cudd_IterDerefBdd.]

  SideEffects [None]

  SeeAlso     [Cudd_RecursiveDeref Cudd_IterDerefBdd]

******************************************************************************/
void
Cudd_DelayedDerefBdd(
  DdManager * table,
  DdNode * n)
{
    DdNode *N;
    int ord;
    DdNodePtr *stack;
    int SP;

    unsigned int live = table->keys - table->dead;
    if (live > table->peakLiveNodes) {
	table->peakLiveNodes = live;
    }

    n = Cudd_Regular(n);
#ifdef DD_DEBUG
    assert(n->ref != 0);
#endif

#ifdef DD_NO_DEATH_ROW
    N = n;
#else
    if (cuddIsConstant(n) || n->ref > 1) {
#ifdef DD_DEBUG
	assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table)));
#endif
	cuddSatDec(n->ref);
	return;
    }

    N = table->deathRow[table->nextDead];

    if (N != NULL) {
#endif
#ifdef DD_DEBUG
	assert(!Cudd_IsComplement(N));
#endif
	stack = table->stack;
	SP = 1;
	do {
#ifdef DD_DEBUG
	    assert(N->ref != 0);
#endif
	    if (N->ref == 1) {
		N->ref = 0;
		table->dead++;
#ifdef DD_STATS
		table->nodesDropped++;
#endif
		ord = table->perm[N->index];
		stack[SP++] = Cudd_Regular(cuddE(N));
		table->subtables[ord].dead++;
		N = cuddT(N);
	    } else {
		cuddSatDec(N->ref);
		N = stack[--SP];
	    }
	} while (SP != 0);
#ifndef DD_NO_DEATH_ROW
    }
    table->deathRow[table->nextDead] = n;

    /* Udate insertion point. */
    table->nextDead++;
    table->nextDead &= table->deadMask;
#if 0
    if (table->nextDead == table->deathRowDepth) {
	if (table->deathRowDepth < table->looseUpTo / 2) {
	    extern void (*MMoutOfMemory)(long);
	    void (*saveHandler)(long) = MMoutOfMemory;
	    DdNodePtr *newRow;
	    MMoutOfMemory = Cudd_OutOfMem;
	    newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth);
	    MMoutOfMemory = saveHandler;
	    if (newRow == NULL) {
		table->nextDead = 0;
	    } else {
		int i;
		table->memused += table->deathRowDepth;
		i = table->deathRowDepth;
		table->deathRowDepth <<= 1;
		for (; i < table->deathRowDepth; i++) {
		    newRow[i] = NULL;
		}
		table->deadMask = table->deathRowDepth - 1;
		table->deathRow = newRow;
	    }
	} else {
	    table->nextDead = 0;
	}
    }
#endif
#endif

} /* end of Cudd_DelayedDerefBdd */