src/bdd/cudd/cuddSplit.c File Reference

#include "util_hack.h"
#include "cuddInt.h"
Include dependency graph for cuddSplit.c:

Go to the source code of this file.

Functions

static DdNode
*selectMintermsFromUniverse 
ARGS ((DdManager *manager, int *varSeen, double n))
static DdNode *mintermsFromUniverse ARGS ((DdManager *manager, DdNode **vars, int numVars, double n, int index))
static double
bddAnnotateMintermCount 
ARGS ((DdManager *manager, DdNode *node, double max, st_table *table))
DdNodeCudd_SplitSet (DdManager *manager, DdNode *S, DdNode **xVars, int n, double m)
DdNodecuddSplitSetRecur (DdManager *manager, st_table *mtable, int *varSeen, DdNode *p, double n, double max, int index)
static DdNodeselectMintermsFromUniverse (DdManager *manager, int *varSeen, double n)
static DdNodemintermsFromUniverse (DdManager *manager, DdNode **vars, int numVars, double n, int index)
static double bddAnnotateMintermCount (DdManager *manager, DdNode *node, double max, st_table *table)

Function Documentation

static double bddAnnotateMintermCount ARGS ( (DdManager *manager, DdNode *node, double max, st_table *table)   )  [static]
static DdNode* mintermsFromUniverse ARGS ( (DdManager *manager, DdNode **vars, int numVars, double n, int index)   )  [static]
static DdNode* selectMintermsFromUniverse ARGS ( (DdManager *manager, int *varSeen, double n)   )  [static]

CFile***********************************************************************

FileName [cuddSplit.c]

PackageName [cudd]

Synopsis [Returns a subset of minterms from a boolean function.]

Description [External functions included in this modoule:

Internal functions included in this module:

static double bddAnnotateMintermCount ( DdManager manager,
DdNode node,
double  max,
st_table table 
) [static]

Function********************************************************************

Synopsis [Annotates every node in the BDD node with its minterm count.]

Description [Annotates every node in the BDD node with its minterm count. In this function, every node and the minterm count represented by it are stored in a hash table.]

SideEffects [Fills up 'table' with the pair <node,minterm_count>.]

Definition at line 600 of file cuddSplit.c.

00605 {
00606 
00607     DdNode *N,*Nv,*Nnv;
00608     register double min_v,min_nv;
00609     register double min_N;
00610     double *pmin;
00611     double *dummy;
00612 
00613     statLine(manager);
00614     N = Cudd_Regular(node);
00615     if (cuddIsConstant(N)) {
00616         if (node == DD_ONE(manager)) {
00617             return(max);
00618         } else {
00619             return(0.0);
00620         }
00621     }
00622 
00623     if (st_lookup(table,(char *)node,(char **)&dummy)) {
00624         return(*dummy);
00625     }   
00626   
00627     Nv = cuddT(N);
00628     Nnv = cuddE(N);
00629     if (N != node) {
00630         Nv = Cudd_Not(Nv);
00631         Nnv = Cudd_Not(Nnv);
00632     }
00633 
00634     /* Recur on the two branches. */
00635     min_v  = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0;
00636     if (min_v == (double)CUDD_OUT_OF_MEM)
00637         return ((double)CUDD_OUT_OF_MEM);
00638     min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0;
00639     if (min_nv == (double)CUDD_OUT_OF_MEM)
00640         return ((double)CUDD_OUT_OF_MEM);
00641     min_N  = min_v + min_nv;
00642 
00643     pmin = ALLOC(double,1);
00644     if (pmin == NULL) {
00645         manager->errorCode = CUDD_MEMORY_OUT;
00646         return((double)CUDD_OUT_OF_MEM);
00647     }
00648     *pmin = min_N;
00649 
00650     if (st_insert(table,(char *)node, (char *)pmin) == ST_OUT_OF_MEM) {
00651         FREE(pmin);
00652         return((double)CUDD_OUT_OF_MEM);
00653     }
00654     
00655     return(min_N);
00656 
00657 } /* end of bddAnnotateMintermCount */

DdNode* Cudd_SplitSet ( DdManager manager,
DdNode S,
DdNode **  xVars,
int  n,
double  m 
)

AutomaticEnd Function********************************************************************

Synopsis [Returns m minterms from a BDD.]

Description [Returns 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 []

Definition at line 97 of file cuddSplit.c.

00103 {
00104     DdNode *result;
00105     DdNode *zero, *one;
00106     double  max, num;
00107     st_table *mtable;
00108     int *varSeen;
00109     int i,index, size;
00110 
00111     size = manager->size;
00112     one = DD_ONE(manager);
00113     zero = Cudd_Not(one);
00114 
00115     /* Trivial cases. */
00116     if (m == 0.0) {
00117         return(zero);
00118     }
00119     if (S == zero) {
00120         return(NULL);
00121     }
00122 
00123     max = pow(2.0,(double)n);
00124     if (m > max)
00125         return(NULL);
00126 
00127     do {
00128         manager->reordered = 0;
00129         /* varSeen is used to mark the variables that are encountered
00130         ** while traversing the BDD S.
00131         */
00132         varSeen = ALLOC(int, size);
00133         if (varSeen == NULL) {
00134             manager->errorCode = CUDD_MEMORY_OUT;
00135             return(NULL);
00136         }
00137         for (i = 0; i < size; i++) {
00138             varSeen[i] = -1;
00139         }
00140         for (i = 0; i < n; i++) {
00141             index = (xVars[i])->index;
00142             varSeen[manager->invperm[index]] = 0;
00143         }
00144 
00145         if (S == one) {
00146             if (m == max) 
00147                 return(S);
00148             result = selectMintermsFromUniverse(manager,varSeen,m);
00149             if (result)
00150                 cuddRef(result);
00151             FREE(varSeen);
00152         } else {
00153             mtable = st_init_table(st_ptrcmp,st_ptrhash);
00154             if (mtable == NULL) {
00155                 (void) fprintf(manager->out,
00156                                "Cudd_SplitSet: out-of-memory.\n");
00157                 FREE(varSeen);
00158                 manager->errorCode = CUDD_MEMORY_OUT;
00159                 return(NULL);
00160             }
00161             /* The nodes of BDD S are annotated by the number of minterms
00162             ** in their onset. The node and the number of minterms in its
00163             ** onset are stored in mtable.
00164             */
00165             num = bddAnnotateMintermCount(manager,S,max,mtable);
00166             if (m == num) {
00167                 st_foreach(mtable,cuddStCountfree,NIL(char));
00168                 st_free_table(mtable);
00169                 FREE(varSeen);
00170                 return(S);
00171             }
00172             
00173             result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0);
00174             if (result)
00175                 cuddRef(result);
00176             st_foreach(mtable,cuddStCountfree,NULL);
00177             st_free_table(mtable);
00178             FREE(varSeen);
00179         }
00180     } while (manager->reordered == 1);
00181 
00182     cuddDeref(result);
00183     return(result);
00184 
00185 } /* end of Cudd_SplitSet */

DdNode* cuddSplitSetRecur ( DdManager manager,
st_table mtable,
int *  varSeen,
DdNode p,
double  n,
double  max,
int  index 
)

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 []

Definition at line 214 of file cuddSplit.c.

00222 {
00223     DdNode *one, *zero, *N, *Nv;
00224     DdNode *Nnv, *q, *r, *v;
00225     DdNode *result;
00226     double *dummy, numT, numE;
00227     int variable, positive;
00228   
00229     statLine(manager);
00230     one = DD_ONE(manager);
00231     zero = Cudd_Not(one);
00232 
00233     /* If p is constant, extract n minterms from constant 1.  The procedure by
00234     ** construction guarantees that minterms will not be extracted from
00235     ** constant 0.
00236     */
00237     if (Cudd_IsConstant(p)) {
00238         q = selectMintermsFromUniverse(manager,varSeen,n);
00239         return(q);
00240     }
00241 
00242     N = Cudd_Regular(p);
00243 
00244     /* Set variable as seen. */
00245     variable = N->index;
00246     varSeen[manager->invperm[variable]] = -1;
00247 
00248     Nv = cuddT(N);
00249     Nnv = cuddE(N);
00250     if (Cudd_IsComplement(p)) {
00251         Nv = Cudd_Not(Nv);
00252         Nnv = Cudd_Not(Nnv);
00253     }
00254 
00255     /* If both the children of 'p' are constants, extract n minterms from a
00256     ** constant node.
00257     */
00258     if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
00259         q = selectMintermsFromUniverse(manager,varSeen,n);
00260         if (q == NULL) {
00261             return(NULL);
00262         }
00263         cuddRef(q);
00264         r = cuddBddAndRecur(manager,p,q);
00265         if (r == NULL) {
00266             Cudd_RecursiveDeref(manager,q);
00267             return(NULL);
00268         }
00269         cuddRef(r);
00270         Cudd_RecursiveDeref(manager,q);
00271         cuddDeref(r);
00272         return(r);
00273     }
00274   
00275     /* Lookup the # of minterms in the onset of the node from the table. */
00276     if (!Cudd_IsConstant(Nv)) {
00277         st_lookup(mtable,(char *)Nv, (char **)&dummy);
00278         numT = *dummy/(2*(1<<index));
00279     } else if (Nv == one) {
00280         numT = max/(2*(1<<index));
00281     } else {
00282         numT = 0;
00283     }
00284   
00285     if (!Cudd_IsConstant(Nnv)) {
00286         st_lookup(mtable,(char *)Nnv, (char **)&dummy);
00287         numE = *dummy/(2*(1<<index));
00288     } else if (Nnv == one) {
00289         numE = max/(2*(1<<index));
00290     } else {
00291         numE = 0;
00292     }
00293 
00294     v = cuddUniqueInter(manager,variable,one,zero);
00295     cuddRef(v);
00296 
00297     /* If perfect match. */
00298     if (numT == n) {
00299         q = cuddBddAndRecur(manager,v,Nv);
00300         if (q == NULL) {
00301             Cudd_RecursiveDeref(manager,v);
00302             return(NULL);
00303         }
00304         cuddRef(q);
00305         Cudd_RecursiveDeref(manager,v);
00306         cuddDeref(q);
00307         return(q);
00308     }
00309     if (numE == n) {
00310         q = cuddBddAndRecur(manager,Cudd_Not(v),Nnv);
00311         if (q == NULL) {
00312             Cudd_RecursiveDeref(manager,v);
00313             return(NULL);
00314         }
00315         cuddRef(q);
00316         Cudd_RecursiveDeref(manager,v);
00317         cuddDeref(q);
00318         return(q);
00319     }
00320     /* If n is greater than numT, extract the difference from the ELSE child
00321     ** and retain the function represented by the THEN branch.
00322     */
00323     if (numT < n) {
00324         q = cuddSplitSetRecur(manager,mtable,varSeen,
00325                               Nnv,(n-numT),max,index+1);
00326         if (q == NULL) {
00327             Cudd_RecursiveDeref(manager,v);
00328             return(NULL);
00329         }
00330         cuddRef(q);
00331         r = cuddBddIteRecur(manager,v,Nv,q);
00332         if (r == NULL) {
00333             Cudd_RecursiveDeref(manager,q);
00334             Cudd_RecursiveDeref(manager,v);
00335             return(NULL);
00336         }
00337         cuddRef(r);
00338         Cudd_RecursiveDeref(manager,q);
00339         Cudd_RecursiveDeref(manager,v);
00340         cuddDeref(r);
00341         return(r);
00342     }
00343     /* If n is greater than numE, extract the difference from the THEN child
00344     ** and retain the function represented by the ELSE branch.
00345     */
00346     if (numE < n) {
00347         q = cuddSplitSetRecur(manager,mtable,varSeen,
00348                               Nv, (n-numE),max,index+1);
00349         if (q == NULL) {
00350             Cudd_RecursiveDeref(manager,v);
00351             return(NULL);
00352         }
00353         cuddRef(q);
00354         r = cuddBddIteRecur(manager,v,q,Nnv);
00355         if (r == NULL) {
00356             Cudd_RecursiveDeref(manager,q);
00357             Cudd_RecursiveDeref(manager,v);
00358             return(NULL);
00359         }
00360         cuddRef(r);
00361         Cudd_RecursiveDeref(manager,q);
00362         Cudd_RecursiveDeref(manager,v);
00363         cuddDeref(r);    
00364         return(r);
00365     }
00366 
00367     /* None of the above cases; (n < numT and n < numE) and either of
00368     ** the Nv, Nnv or both are not constants. If possible extract the
00369     ** required minterms the constant branch.
00370     */
00371     if (Cudd_IsConstant(Nv) && !Cudd_IsConstant(Nnv)) {
00372         q = selectMintermsFromUniverse(manager,varSeen,n);
00373         if (q == NULL) {
00374             Cudd_RecursiveDeref(manager,v);
00375             return(NULL);
00376         }
00377         cuddRef(q);
00378         result = cuddBddAndRecur(manager,v,q);
00379         if (result == NULL) {
00380             Cudd_RecursiveDeref(manager,q);
00381             Cudd_RecursiveDeref(manager,v);
00382             return(NULL);
00383         }
00384         cuddRef(result);
00385         Cudd_RecursiveDeref(manager,q);
00386         Cudd_RecursiveDeref(manager,v);
00387         cuddDeref(result);
00388         return(result);
00389     } else if (!Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
00390         q = selectMintermsFromUniverse(manager,varSeen,n);
00391         if (q == NULL) {
00392             Cudd_RecursiveDeref(manager,v);
00393             return(NULL);
00394         }
00395         cuddRef(q);
00396         result = cuddBddAndRecur(manager,Cudd_Not(v),q);
00397         if (result == NULL) {
00398             Cudd_RecursiveDeref(manager,q);
00399             Cudd_RecursiveDeref(manager,v);
00400             return(NULL);
00401         }
00402         cuddRef(result);
00403         Cudd_RecursiveDeref(manager,q);
00404         Cudd_RecursiveDeref(manager,v);
00405         cuddDeref(result);
00406         return(result);
00407     }
00408 
00409     /* Both Nv and Nnv are not constants. So choose the one which
00410     ** has fewer minterms in its onset.
00411     */
00412     positive = 0;
00413     if (numT < numE) {
00414         q = cuddSplitSetRecur(manager,mtable,varSeen,
00415                               Nv,n,max,index+1);
00416         positive = 1;
00417     } else {
00418         q = cuddSplitSetRecur(manager,mtable,varSeen,
00419                               Nnv,n,max,index+1);
00420     }
00421 
00422     if (q == NULL) {
00423         Cudd_RecursiveDeref(manager,v);
00424         return(NULL);
00425     }
00426     cuddRef(q);
00427 
00428     if (positive) {
00429         result = cuddBddAndRecur(manager,v,q);
00430     } else {
00431         result = cuddBddAndRecur(manager,Cudd_Not(v),q);
00432     }
00433     if (result == NULL) {
00434         Cudd_RecursiveDeref(manager,q);
00435         Cudd_RecursiveDeref(manager,v);
00436         return(NULL);
00437     }
00438     cuddRef(result);
00439     Cudd_RecursiveDeref(manager,q);
00440     Cudd_RecursiveDeref(manager,v);
00441     cuddDeref(result);
00442 
00443     return(result);
00444 
00445 } /* end of cuddSplitSetRecur */

static DdNode* mintermsFromUniverse ( DdManager manager,
DdNode **  vars,
int  numVars,
double  n,
int  index 
) [static]

Function********************************************************************

Synopsis [Recursive procedure to extract n mintems from constant 1.]

Description [Recursive procedure to extract n mintems from constant 1.]

SideEffects [None]

Definition at line 529 of file cuddSplit.c.

00535 {
00536     DdNode *one, *zero;
00537     DdNode *q, *result;
00538     double max, max2;
00539     
00540     statLine(manager);
00541     one = DD_ONE(manager);
00542     zero = Cudd_Not(one);
00543 
00544     max = pow(2.0, (double)numVars);
00545     max2 = max / 2.0;
00546 
00547     if (n == max)
00548         return(one);
00549     if (n == 0.0)
00550         return(zero);
00551     /* if n == 2^(numVars-1), return a single variable */
00552     if (n == max2)
00553         return vars[index];
00554     else if (n > max2) {
00555         /* When n > 2^(numVars-1), a single variable vars[index]
00556         ** contains 2^(numVars-1) minterms. The rest are extracted
00557         ** from a constant with 1 less variable.
00558         */
00559         q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1);
00560         if (q == NULL)
00561             return(NULL);
00562         cuddRef(q);
00563         result = cuddBddIteRecur(manager,vars[index],one,q);
00564     } else {
00565         /* When n < 2^(numVars-1), a literal of variable vars[index]
00566         ** is selected. The required n minterms are extracted from a
00567         ** constant with 1 less variable.
00568         */
00569         q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1);
00570         if (q == NULL)
00571             return(NULL);
00572         cuddRef(q);
00573         result = cuddBddAndRecur(manager,vars[index],q);
00574     }
00575     
00576     if (result == NULL) {
00577         Cudd_RecursiveDeref(manager,q);
00578         return(NULL);
00579     }
00580     cuddRef(result);
00581     Cudd_RecursiveDeref(manager,q);
00582     cuddDeref(result);
00583     return(result);
00584 
00585 } /* end of mintermsFromUniverse */

static DdNode* selectMintermsFromUniverse ( DdManager manager,
int *  varSeen,
double  n 
) [static]

Function********************************************************************

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

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

SideEffects [None]

Definition at line 466 of file cuddSplit.c.

00470 {
00471     int numVars;
00472     int i, size, j;
00473      DdNode *one, *zero, *result;
00474     DdNode **vars;
00475 
00476     numVars = 0;
00477     size = manager->size;
00478     one = DD_ONE(manager);
00479     zero = Cudd_Not(one);
00480 
00481     /* Count the number of variables not encountered so far in procedure
00482     ** cuddSplitSetRecur.
00483     */
00484     for (i = size-1; i >= 0; i--) {
00485         if(varSeen[i] == 0)
00486             numVars++;
00487     }
00488     vars = ALLOC(DdNode *, numVars);
00489     if (!vars) {
00490         manager->errorCode = CUDD_MEMORY_OUT;
00491         return(NULL);
00492     }
00493 
00494     j = 0;
00495     for (i = size-1; i >= 0; i--) {
00496         if(varSeen[i] == 0) {
00497             vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero);
00498             cuddRef(vars[j]);
00499             j++;
00500         }
00501     }
00502 
00503     /* Compute a function which has n minterms and depends on at most
00504     ** numVars variables.
00505     */
00506     result = mintermsFromUniverse(manager,vars,numVars,n, 0);
00507     if (result) 
00508         cuddRef(result);
00509 
00510     for (i = 0; i < numVars; i++)
00511         Cudd_RecursiveDeref(manager,vars[i]);
00512     FREE(vars);
00513 
00514     return(result);
00515 
00516 } /* end of selectMintermsFromUniverse */


Generated on Tue Jan 5 12:18:56 2010 for abc70930 by  doxygen 1.6.1