00001
00035 #include "util_hack.h"
00036 #include "cuddInt.h"
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00064
00065
00066
00067
00068 static DdNode * selectMintermsFromUniverse ARGS((DdManager *manager, int *varSeen, double n));
00069 static DdNode * mintermsFromUniverse ARGS((DdManager *manager, DdNode **vars, int numVars, double n, int index));
00070 static double bddAnnotateMintermCount ARGS((DdManager *manager, DdNode *node, double max, st_table *table));
00071
00075
00076
00077
00078
00079
00096 DdNode *
00097 Cudd_SplitSet(
00098 DdManager * manager,
00099 DdNode * S,
00100 DdNode ** xVars,
00101 int n,
00102 double m)
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
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
00130
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
00162
00163
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 }
00186
00187
00188
00189
00190
00191
00213 DdNode*
00214 cuddSplitSetRecur(
00215 DdManager * manager,
00216 st_table * mtable,
00217 int * varSeen,
00218 DdNode * p,
00219 double n,
00220 double max,
00221 int index)
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
00234
00235
00236
00237 if (Cudd_IsConstant(p)) {
00238 q = selectMintermsFromUniverse(manager,varSeen,n);
00239 return(q);
00240 }
00241
00242 N = Cudd_Regular(p);
00243
00244
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
00256
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
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
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
00321
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
00344
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
00368
00369
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
00410
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 }
00446
00447
00448
00449
00450
00451
00465 static DdNode *
00466 selectMintermsFromUniverse(
00467 DdManager * manager,
00468 int * varSeen,
00469 double n)
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
00482
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
00504
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 }
00517
00518
00528 static DdNode *
00529 mintermsFromUniverse(
00530 DdManager * manager,
00531 DdNode ** vars,
00532 int numVars,
00533 double n,
00534 int index)
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
00552 if (n == max2)
00553 return vars[index];
00554 else if (n > max2) {
00555
00556
00557
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
00566
00567
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 }
00586
00587
00599 static double
00600 bddAnnotateMintermCount(
00601 DdManager * manager,
00602 DdNode * node,
00603 double max,
00604 st_table * table)
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
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 }