#include "util_hack.h"
#include "cuddInt.h"
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)) |
DdNode * | Cudd_SplitSet (DdManager *manager, DdNode *S, DdNode **xVars, int n, double m) |
DdNode * | cuddSplitSetRecur (DdManager *manager, st_table *mtable, int *varSeen, DdNode *p, double n, double max, int index) |
static DdNode * | selectMintermsFromUniverse (DdManager *manager, int *varSeen, double n) |
static DdNode * | mintermsFromUniverse (DdManager *manager, DdNode **vars, int numVars, double n, int index) |
static double | bddAnnotateMintermCount (DdManager *manager, DdNode *node, double max, st_table *table) |
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:
cuddSplitSetRecur() </u> Static functions included in this module:
]
SeeAlso []
Author [Balakrishna Kumthekar]
Copyright [This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]AutomaticStart
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 */
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 */
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 */