/**CFile*********************************************************************** FileName [cuddSplit.c] PackageName [cudd] Synopsis [Returns a subset of minterms from a boolean function.] Description [External functions included in this modoule:
m
minterms from a BDD whose
support has n
variables at most. The procedure tries
to create as few extra nodes as possible. The function represented
by S
depends on at most n
of the variables
in xVars
. Returns a BDD with m
minterms
of the on-set of S if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
Cudd_SplitSet(
DdManager * manager,
DdNode * S,
DdNode ** xVars,
int n,
double m)
{
DdNode *result;
DdNode *zero, *one;
double max, num;
st_table *mtable;
int *varSeen;
int i,index, size;
size = manager->size;
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* Trivial cases. */
if (m == 0.0) {
return(zero);
}
if (S == zero) {
return(NULL);
}
max = pow(2.0,(double)n);
if (m > max)
return(NULL);
do {
manager->reordered = 0;
/* varSeen is used to mark the variables that are encountered
** while traversing the BDD S.
*/
varSeen = ALLOC(int, size);
if (varSeen == NULL) {
manager->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
for (i = 0; i < size; i++) {
varSeen[i] = -1;
}
for (i = 0; i < n; i++) {
index = (xVars[i])->index;
varSeen[manager->invperm[index]] = 0;
}
if (S == one) {
if (m == max)
return(S);
result = selectMintermsFromUniverse(manager,varSeen,m);
if (result)
cuddRef(result);
FREE(varSeen);
} else {
mtable = st_init_table(st_ptrcmp,st_ptrhash);
if (mtable == NULL) {
(void) fprintf(manager->out,
"Cudd_SplitSet: out-of-memory.\n");
FREE(varSeen);
manager->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
/* The nodes of BDD S are annotated by the number of minterms
** in their onset. The node and the number of minterms in its
** onset are stored in mtable.
*/
num = bddAnnotateMintermCount(manager,S,max,mtable);
if (m == num) {
st_foreach(mtable,cuddStCountfree,NIL(char));
st_free_table(mtable);
FREE(varSeen);
return(S);
}
result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0);
if (result)
cuddRef(result);
st_foreach(mtable,cuddStCountfree,NULL);
st_free_table(mtable);
FREE(varSeen);
}
} while (manager->reordered == 1);
cuddDeref(result);
return(result);
} /* end of Cudd_SplitSet */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**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)) {
st_lookup(mtable,(char *)Nv, (char **)&dummy);
numT = *dummy/(2*(1<