00001
00072 #include "util.h"
00073 #include "cuddInt.h"
00074
00075
00076
00077
00078
00079 #define DD_BIGGY 1000000
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 typedef struct cuddPathPair {
00090 int pos;
00091 int neg;
00092 } cuddPathPair;
00093
00094
00095
00096
00097
00098 #ifndef lint
00099 static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio Exp $";
00100 #endif
00101
00102 static DdNode *one, *zero;
00103
00104
00105
00106
00107
00108 #define WEIGHT(weight, col) ((weight) == NULL ? 1 : weight[col])
00109
00110 #ifdef __cplusplus
00111 extern "C" {
00112 #endif
00113
00116
00117
00118
00119
00120 static enum st_retval freePathPair (char *key, char *value, char *arg);
00121 static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st_table *visited);
00122 static DdNode * getPath (DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost);
00123 static cuddPathPair getLargest (DdNode *root, st_table *visited);
00124 static DdNode * getCube (DdManager *manager, st_table *visited, DdNode *f, int cost);
00125
00128 #ifdef __cplusplus
00129 }
00130 #endif
00131
00132
00133
00134
00135
00136
00152 DdNode *
00153 Cudd_Eval(
00154 DdManager * dd,
00155 DdNode * f,
00156 int * inputs)
00157 {
00158 int comple;
00159 DdNode *ptr;
00160
00161 comple = Cudd_IsComplement(f);
00162 ptr = Cudd_Regular(f);
00163
00164 while (!cuddIsConstant(ptr)) {
00165 if (inputs[ptr->index] == 1) {
00166 ptr = cuddT(ptr);
00167 } else {
00168 comple ^= Cudd_IsComplement(cuddE(ptr));
00169 ptr = Cudd_Regular(cuddE(ptr));
00170 }
00171 }
00172 return(Cudd_NotCond(ptr,comple));
00173
00174 }
00175
00176
00196 DdNode *
00197 Cudd_ShortestPath(
00198 DdManager * manager,
00199 DdNode * f,
00200 int * weight,
00201 int * support,
00202 int * length)
00203 {
00204 DdNode *F;
00205 st_table *visited;
00206 DdNode *sol;
00207 cuddPathPair *rootPair;
00208 int complement, cost;
00209 int i;
00210
00211 one = DD_ONE(manager);
00212 zero = DD_ZERO(manager);
00213
00214
00215
00216
00217 if (support) {
00218 for (i = 0; i < manager->size; i++) {
00219 support[i] = 0;
00220 }
00221 }
00222
00223 if (f == Cudd_Not(one) || f == zero) {
00224 *length = DD_BIGGY;
00225 return(Cudd_Not(one));
00226 }
00227
00228
00229 do {
00230 manager->reordered = 0;
00231
00232
00233 visited = st_init_table(st_ptrcmp, st_ptrhash);
00234
00235
00236 (void) getShortest(f, weight, support, visited);
00237
00238 complement = Cudd_IsComplement(f);
00239
00240 F = Cudd_Regular(f);
00241
00242 if (!st_lookup(visited, F, &rootPair)) return(NULL);
00243
00244 if (complement) {
00245 cost = rootPair->neg;
00246 } else {
00247 cost = rootPair->pos;
00248 }
00249
00250
00251 sol = getPath(manager,visited,f,weight,cost);
00252
00253 st_foreach(visited, freePathPair, NULL);
00254 st_free_table(visited);
00255
00256 } while (manager->reordered == 1);
00257
00258 *length = cost;
00259 return(sol);
00260
00261 }
00262
00263
00280 DdNode *
00281 Cudd_LargestCube(
00282 DdManager * manager,
00283 DdNode * f,
00284 int * length)
00285 {
00286 register DdNode *F;
00287 st_table *visited;
00288 DdNode *sol;
00289 cuddPathPair *rootPair;
00290 int complement, cost;
00291
00292 one = DD_ONE(manager);
00293 zero = DD_ZERO(manager);
00294
00295 if (f == Cudd_Not(one) || f == zero) {
00296 *length = DD_BIGGY;
00297 return(Cudd_Not(one));
00298 }
00299
00300
00301 do {
00302 manager->reordered = 0;
00303
00304
00305 visited = st_init_table(st_ptrcmp, st_ptrhash);
00306
00307
00308 (void) getLargest(f, visited);
00309
00310 complement = Cudd_IsComplement(f);
00311
00312 F = Cudd_Regular(f);
00313
00314 if (!st_lookup(visited, F, &rootPair)) return(NULL);
00315
00316 if (complement) {
00317 cost = rootPair->neg;
00318 } else {
00319 cost = rootPair->pos;
00320 }
00321
00322
00323 sol = getCube(manager,visited,f,cost);
00324
00325 st_foreach(visited, freePathPair, NULL);
00326 st_free_table(visited);
00327
00328 } while (manager->reordered == 1);
00329
00330 *length = cost;
00331 return(sol);
00332
00333 }
00334
00335
00352 int
00353 Cudd_ShortestLength(
00354 DdManager * manager,
00355 DdNode * f,
00356 int * weight)
00357 {
00358 register DdNode *F;
00359 st_table *visited;
00360 cuddPathPair *my_pair;
00361 int complement, cost;
00362
00363 one = DD_ONE(manager);
00364 zero = DD_ZERO(manager);
00365
00366 if (f == Cudd_Not(one) || f == zero) {
00367 return(DD_BIGGY);
00368 }
00369
00370
00371
00372 visited = st_init_table(st_ptrcmp, st_ptrhash);
00373
00374
00375 (void) getShortest(f, weight, NULL, visited);
00376
00377 complement = Cudd_IsComplement(f);
00378
00379 F = Cudd_Regular(f);
00380
00381 if (!st_lookup(visited, F, &my_pair)) return(CUDD_OUT_OF_MEM);
00382
00383 if (complement) {
00384 cost = my_pair->neg;
00385 } else {
00386 cost = my_pair->pos;
00387 }
00388
00389 st_foreach(visited, freePathPair, NULL);
00390 st_free_table(visited);
00391
00392 return(cost);
00393
00394 }
00395
00396
00412 DdNode *
00413 Cudd_Decreasing(
00414 DdManager * dd,
00415 DdNode * f,
00416 int i)
00417 {
00418 unsigned int topf, level;
00419 DdNode *F, *fv, *fvn, *res;
00420 DD_CTFP cacheOp;
00421
00422 statLine(dd);
00423 #ifdef DD_DEBUG
00424 assert(0 <= i && i < dd->size);
00425 #endif
00426
00427 F = Cudd_Regular(f);
00428 topf = cuddI(dd,F->index);
00429
00430
00431
00432
00433 level = (unsigned) dd->perm[i];
00434 if (topf > level) {
00435 return(DD_ONE(dd));
00436 }
00437
00438
00439
00440
00441 cacheOp = (DD_CTFP) Cudd_Decreasing;
00442 res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
00443 if (res != NULL) {
00444 return(res);
00445 }
00446
00447
00448 fv = cuddT(F); fvn = cuddE(F);
00449 if (F != f) {
00450 fv = Cudd_Not(fv);
00451 fvn = Cudd_Not(fvn);
00452 }
00453
00454 if (topf == (unsigned) level) {
00455
00456
00457
00458
00459
00460 if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
00461 return(Cudd_Not(DD_ONE(dd)));
00462 }
00463 res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
00464 } else {
00465 res = Cudd_Decreasing(dd,fv,i);
00466 if (res == DD_ONE(dd)) {
00467 res = Cudd_Decreasing(dd,fvn,i);
00468 }
00469 }
00470
00471 cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
00472 return(res);
00473
00474 }
00475
00476
00492 DdNode *
00493 Cudd_Increasing(
00494 DdManager * dd,
00495 DdNode * f,
00496 int i)
00497 {
00498 return(Cudd_Decreasing(dd,Cudd_Not(f),i));
00499
00500 }
00501
00502
00517 int
00518 Cudd_EquivDC(
00519 DdManager * dd,
00520 DdNode * F,
00521 DdNode * G,
00522 DdNode * D)
00523 {
00524 DdNode *tmp, *One, *Gr, *Dr;
00525 DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
00526 int res;
00527 unsigned int flevel, glevel, dlevel, top;
00528
00529 One = DD_ONE(dd);
00530
00531 statLine(dd);
00532
00533 if (D == One || F == G) return(1);
00534 if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);
00535
00536
00537
00538
00539 if (F > G) {
00540 tmp = F;
00541 F = G;
00542 G = tmp;
00543 }
00544 if (Cudd_IsComplement(F)) {
00545 F = Cudd_Not(F);
00546 G = Cudd_Not(G);
00547 }
00548
00549
00550
00551
00552 tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
00553 if (tmp != NULL) return(tmp == One);
00554
00555
00556 flevel = cuddI(dd,F->index);
00557 Gr = Cudd_Regular(G);
00558 glevel = cuddI(dd,Gr->index);
00559 top = ddMin(flevel,glevel);
00560 Dr = Cudd_Regular(D);
00561 dlevel = dd->perm[Dr->index];
00562 top = ddMin(top,dlevel);
00563
00564
00565 if (top == flevel) {
00566 Fv = cuddT(F);
00567 Fvn = cuddE(F);
00568 } else {
00569 Fv = Fvn = F;
00570 }
00571 if (top == glevel) {
00572 Gv = cuddT(Gr);
00573 Gvn = cuddE(Gr);
00574 if (G != Gr) {
00575 Gv = Cudd_Not(Gv);
00576 Gvn = Cudd_Not(Gvn);
00577 }
00578 } else {
00579 Gv = Gvn = G;
00580 }
00581 if (top == dlevel) {
00582 Dv = cuddT(Dr);
00583 Dvn = cuddE(Dr);
00584 if (D != Dr) {
00585 Dv = Cudd_Not(Dv);
00586 Dvn = Cudd_Not(Dvn);
00587 }
00588 } else {
00589 Dv = Dvn = D;
00590 }
00591
00592
00593 res = Cudd_EquivDC(dd,Fv,Gv,Dv);
00594 if (res != 0) {
00595 res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
00596 }
00597 cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));
00598
00599 return(res);
00600
00601 }
00602
00603
00617 int
00618 Cudd_bddLeqUnless(
00619 DdManager *dd,
00620 DdNode *f,
00621 DdNode *g,
00622 DdNode *D)
00623 {
00624 DdNode *tmp, *One, *F, *G;
00625 DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
00626 int res;
00627 unsigned int flevel, glevel, dlevel, top;
00628
00629 statLine(dd);
00630
00631 One = DD_ONE(dd);
00632
00633
00634 if (f == g || g == One || f == Cudd_Not(One) || D == One ||
00635 D == f || D == Cudd_Not(g)) return(1);
00636
00637 if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
00638 return(Cudd_bddLeq(dd,f,g));
00639 if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
00640 if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 if (Cudd_IsComplement(D)) {
00653 if (Cudd_IsComplement(g)) {
00654
00655
00656
00657 if (!Cudd_IsComplement(f)) return(0);
00658
00659 tmp = D;
00660 D = Cudd_Not(f);
00661 if (g < tmp) {
00662 f = Cudd_Not(g);
00663 g = tmp;
00664 } else {
00665 f = Cudd_Not(tmp);
00666 }
00667 } else {
00668 if (Cudd_IsComplement(f)) {
00669
00670 tmp = f;
00671 f = Cudd_Not(D);
00672 if (tmp < g) {
00673 D = g;
00674 g = Cudd_Not(tmp);
00675 } else {
00676 D = Cudd_Not(tmp);
00677 }
00678 } else {
00679
00680 tmp = D;
00681 D = g;
00682 if (tmp < f) {
00683 g = Cudd_Not(f);
00684 f = Cudd_Not(tmp);
00685 } else {
00686 g = tmp;
00687 }
00688 }
00689 }
00690 } else {
00691 if (Cudd_IsComplement(g)) {
00692 if (Cudd_IsComplement(f)) {
00693
00694 tmp = f;
00695 f = Cudd_Not(g);
00696 if (D < tmp) {
00697 g = D;
00698 D = Cudd_Not(tmp);
00699 } else {
00700 g = Cudd_Not(tmp);
00701 }
00702 } else {
00703
00704 if (g < f) {
00705 tmp = g;
00706 g = Cudd_Not(f);
00707 f = Cudd_Not(tmp);
00708 }
00709 }
00710 } else {
00711
00712 if (D < g) {
00713 tmp = D;
00714 D = g;
00715 g = tmp;
00716 }
00717 }
00718 }
00719
00720
00721
00722
00723 tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
00724 if (tmp != NULL) return(tmp == One);
00725
00726
00727 F = Cudd_Regular(f);
00728 flevel = dd->perm[F->index];
00729 G = Cudd_Regular(g);
00730 glevel = dd->perm[G->index];
00731 top = ddMin(flevel,glevel);
00732 dlevel = dd->perm[D->index];
00733 top = ddMin(top,dlevel);
00734
00735
00736 if (top == flevel) {
00737 Ft = cuddT(F);
00738 Fe = cuddE(F);
00739 if (F != f) {
00740 Ft = Cudd_Not(Ft);
00741 Fe = Cudd_Not(Fe);
00742 }
00743 } else {
00744 Ft = Fe = f;
00745 }
00746 if (top == glevel) {
00747 Gt = cuddT(G);
00748 Ge = cuddE(G);
00749 if (G != g) {
00750 Gt = Cudd_Not(Gt);
00751 Ge = Cudd_Not(Ge);
00752 }
00753 } else {
00754 Gt = Ge = g;
00755 }
00756 if (top == dlevel) {
00757 Dt = cuddT(D);
00758 De = cuddE(D);
00759 } else {
00760 Dt = De = D;
00761 }
00762
00763
00764 res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
00765 if (res != 0) {
00766 res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
00767 }
00768 cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res));
00769
00770 return(res);
00771
00772 }
00773
00774
00791 int
00792 Cudd_EqualSupNorm(
00793 DdManager * dd ,
00794 DdNode * f ,
00795 DdNode * g ,
00796 CUDD_VALUE_TYPE tolerance ,
00797 int pr )
00798 {
00799 DdNode *fv, *fvn, *gv, *gvn, *r;
00800 unsigned int topf, topg;
00801
00802 statLine(dd);
00803
00804 if (f == g) return(1);
00805 if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
00806 if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
00807 return(1);
00808 } else {
00809 if (pr>0) {
00810 (void) fprintf(dd->out,"Offending nodes:\n");
00811 (void) fprintf(dd->out,
00812 "f: address = %p\t value = %40.30f\n",
00813 (void *) f, cuddV(f));
00814 (void) fprintf(dd->out,
00815 "g: address = %p\t value = %40.30f\n",
00816 (void *) g, cuddV(g));
00817 }
00818 return(0);
00819 }
00820 }
00821
00822
00823
00824 r = cuddCacheLookup2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g);
00825 if (r != NULL) {
00826 return(1);
00827 }
00828
00829
00830 topf = cuddI(dd,f->index);
00831 topg = cuddI(dd,g->index);
00832
00833 if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
00834 if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
00835
00836 if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
00837 if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);
00838
00839 cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd));
00840
00841 return(1);
00842
00843 }
00844
00845
00859 DdNode *
00860 Cudd_bddMakePrime(
00861 DdManager *dd ,
00862 DdNode *cube ,
00863 DdNode *f )
00864 {
00865 DdNode *res;
00866
00867 if (!Cudd_bddLeq(dd,cube,f)) return(NULL);
00868
00869 do {
00870 dd->reordered = 0;
00871 res = cuddBddMakePrime(dd,cube,f);
00872 } while (dd->reordered == 1);
00873 return(res);
00874
00875 }
00876
00877
00878
00879
00880
00881
00882
00895 DdNode *
00896 cuddBddMakePrime(
00897 DdManager *dd ,
00898 DdNode *cube ,
00899 DdNode *f )
00900 {
00901 DdNode *scan;
00902 DdNode *t, *e;
00903 DdNode *res = cube;
00904 DdNode *zero = Cudd_Not(DD_ONE(dd));
00905
00906 Cudd_Ref(res);
00907 scan = cube;
00908 while (!Cudd_IsConstant(scan)) {
00909 DdNode *reg = Cudd_Regular(scan);
00910 DdNode *var = dd->vars[reg->index];
00911 DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
00912 if (expanded == NULL) {
00913 return(NULL);
00914 }
00915 Cudd_Ref(expanded);
00916 if (Cudd_bddLeq(dd,expanded,f)) {
00917 Cudd_RecursiveDeref(dd,res);
00918 res = expanded;
00919 } else {
00920 Cudd_RecursiveDeref(dd,expanded);
00921 }
00922 cuddGetBranches(scan,&t,&e);
00923 if (t == zero) {
00924 scan = e;
00925 } else if (e == zero) {
00926 scan = t;
00927 } else {
00928 Cudd_RecursiveDeref(dd,res);
00929 return(NULL);
00930 }
00931 }
00932
00933 if (scan == DD_ONE(dd)) {
00934 Cudd_Deref(res);
00935 return(res);
00936 } else {
00937 Cudd_RecursiveDeref(dd,res);
00938 return(NULL);
00939 }
00940
00941 }
00942
00943
00944
00945
00946
00947
00948
00959 static enum st_retval
00960 freePathPair(
00961 char * key,
00962 char * value,
00963 char * arg)
00964 {
00965 cuddPathPair *pair;
00966
00967 pair = (cuddPathPair *) value;
00968 FREE(pair);
00969 return(ST_CONTINUE);
00970
00971 }
00972
00973
00992 static cuddPathPair
00993 getShortest(
00994 DdNode * root,
00995 int * cost,
00996 int * support,
00997 st_table * visited)
00998 {
00999 cuddPathPair *my_pair, res_pair, pair_T, pair_E;
01000 DdNode *my_root, *T, *E;
01001 int weight;
01002
01003 my_root = Cudd_Regular(root);
01004
01005 if (st_lookup(visited, my_root, &my_pair)) {
01006 if (Cudd_IsComplement(root)) {
01007 res_pair.pos = my_pair->neg;
01008 res_pair.neg = my_pair->pos;
01009 } else {
01010 res_pair.pos = my_pair->pos;
01011 res_pair.neg = my_pair->neg;
01012 }
01013 return(res_pair);
01014 }
01015
01016
01017
01018
01019
01020
01021 if (cuddIsConstant(my_root)) {
01022 if (my_root != zero) {
01023 res_pair.pos = 0;
01024 res_pair.neg = DD_BIGGY;
01025 } else {
01026 res_pair.pos = DD_BIGGY;
01027 res_pair.neg = 0;
01028 }
01029 } else {
01030 T = cuddT(my_root);
01031 E = cuddE(my_root);
01032
01033 pair_T = getShortest(T, cost, support, visited);
01034 pair_E = getShortest(E, cost, support, visited);
01035 weight = WEIGHT(cost, my_root->index);
01036 res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
01037 res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);
01038
01039
01040 if (support != NULL) {
01041 support[my_root->index] = 1;
01042 }
01043 }
01044
01045 my_pair = ALLOC(cuddPathPair, 1);
01046 if (my_pair == NULL) {
01047 if (Cudd_IsComplement(root)) {
01048 int tmp = res_pair.pos;
01049 res_pair.pos = res_pair.neg;
01050 res_pair.neg = tmp;
01051 }
01052 return(res_pair);
01053 }
01054 my_pair->pos = res_pair.pos;
01055 my_pair->neg = res_pair.neg;
01056
01057 st_insert(visited, (char *)my_root, (char *)my_pair);
01058 if (Cudd_IsComplement(root)) {
01059 res_pair.pos = my_pair->neg;
01060 res_pair.neg = my_pair->pos;
01061 } else {
01062 res_pair.pos = my_pair->pos;
01063 res_pair.neg = my_pair->neg;
01064 }
01065 return(res_pair);
01066
01067 }
01068
01069
01088 static DdNode *
01089 getPath(
01090 DdManager * manager,
01091 st_table * visited,
01092 DdNode * f,
01093 int * weight,
01094 int cost)
01095 {
01096 DdNode *sol, *tmp;
01097 DdNode *my_dd, *T, *E;
01098 cuddPathPair *T_pair, *E_pair;
01099 int Tcost, Ecost;
01100 int complement;
01101
01102 my_dd = Cudd_Regular(f);
01103 complement = Cudd_IsComplement(f);
01104
01105 sol = one;
01106 cuddRef(sol);
01107
01108 while (!cuddIsConstant(my_dd)) {
01109 Tcost = cost - WEIGHT(weight, my_dd->index);
01110 Ecost = cost;
01111
01112 T = cuddT(my_dd);
01113 E = cuddE(my_dd);
01114
01115 if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
01116
01117 st_lookup(visited, Cudd_Regular(T), &T_pair);
01118 if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
01119 (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
01120 tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
01121 if (tmp == NULL) {
01122 Cudd_RecursiveDeref(manager,sol);
01123 return(NULL);
01124 }
01125 cuddRef(tmp);
01126 Cudd_RecursiveDeref(manager,sol);
01127 sol = tmp;
01128
01129 complement = Cudd_IsComplement(T);
01130 my_dd = Cudd_Regular(T);
01131 cost = Tcost;
01132 continue;
01133 }
01134 st_lookup(visited, Cudd_Regular(E), &E_pair);
01135 if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
01136 (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
01137 tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
01138 if (tmp == NULL) {
01139 Cudd_RecursiveDeref(manager,sol);
01140 return(NULL);
01141 }
01142 cuddRef(tmp);
01143 Cudd_RecursiveDeref(manager,sol);
01144 sol = tmp;
01145 complement = Cudd_IsComplement(E);
01146 my_dd = Cudd_Regular(E);
01147 cost = Ecost;
01148 continue;
01149 }
01150 (void) fprintf(manager->err,"We shouldn't be here!!\n");
01151 manager->errorCode = CUDD_INTERNAL_ERROR;
01152 return(NULL);
01153 }
01154
01155 cuddDeref(sol);
01156 return(sol);
01157
01158 }
01159
01160
01181 static cuddPathPair
01182 getLargest(
01183 DdNode * root,
01184 st_table * visited)
01185 {
01186 cuddPathPair *my_pair, res_pair, pair_T, pair_E;
01187 DdNode *my_root, *T, *E;
01188
01189 my_root = Cudd_Regular(root);
01190
01191 if (st_lookup(visited, my_root, &my_pair)) {
01192 if (Cudd_IsComplement(root)) {
01193 res_pair.pos = my_pair->neg;
01194 res_pair.neg = my_pair->pos;
01195 } else {
01196 res_pair.pos = my_pair->pos;
01197 res_pair.neg = my_pair->neg;
01198 }
01199 return(res_pair);
01200 }
01201
01202
01203
01204
01205
01206
01207 if (cuddIsConstant(my_root)) {
01208 if (my_root != zero) {
01209 res_pair.pos = 0;
01210 res_pair.neg = DD_BIGGY;
01211 } else {
01212 res_pair.pos = DD_BIGGY;
01213 res_pair.neg = 0;
01214 }
01215 } else {
01216 T = cuddT(my_root);
01217 E = cuddE(my_root);
01218
01219 pair_T = getLargest(T, visited);
01220 pair_E = getLargest(E, visited);
01221 res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
01222 res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
01223 }
01224
01225 my_pair = ALLOC(cuddPathPair, 1);
01226 if (my_pair == NULL) {
01227 if (Cudd_IsComplement(root)) {
01228 int tmp = res_pair.pos;
01229 res_pair.pos = res_pair.neg;
01230 res_pair.neg = tmp;
01231 }
01232 return(res_pair);
01233 }
01234 my_pair->pos = res_pair.pos;
01235 my_pair->neg = res_pair.neg;
01236
01237
01238 st_insert(visited, (char *)my_root, (char *)my_pair);
01239 if (Cudd_IsComplement(root)) {
01240 res_pair.pos = my_pair->neg;
01241 res_pair.neg = my_pair->pos;
01242 } else {
01243 res_pair.pos = my_pair->pos;
01244 res_pair.neg = my_pair->neg;
01245 }
01246 return(res_pair);
01247
01248 }
01249
01250
01269 static DdNode *
01270 getCube(
01271 DdManager * manager,
01272 st_table * visited,
01273 DdNode * f,
01274 int cost)
01275 {
01276 DdNode *sol, *tmp;
01277 DdNode *my_dd, *T, *E;
01278 cuddPathPair *T_pair, *E_pair;
01279 int Tcost, Ecost;
01280 int complement;
01281
01282 my_dd = Cudd_Regular(f);
01283 complement = Cudd_IsComplement(f);
01284
01285 sol = one;
01286 cuddRef(sol);
01287
01288 while (!cuddIsConstant(my_dd)) {
01289 Tcost = cost - 1;
01290 Ecost = cost - 1;
01291
01292 T = cuddT(my_dd);
01293 E = cuddE(my_dd);
01294
01295 if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
01296
01297 if (!st_lookup(visited, Cudd_Regular(T), &T_pair)) return(NULL);
01298 if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
01299 (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
01300 tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
01301 if (tmp == NULL) {
01302 Cudd_RecursiveDeref(manager,sol);
01303 return(NULL);
01304 }
01305 cuddRef(tmp);
01306 Cudd_RecursiveDeref(manager,sol);
01307 sol = tmp;
01308
01309 complement = Cudd_IsComplement(T);
01310 my_dd = Cudd_Regular(T);
01311 cost = Tcost;
01312 continue;
01313 }
01314 if (!st_lookup(visited, Cudd_Regular(E), &E_pair)) return(NULL);
01315 if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
01316 (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
01317 tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
01318 if (tmp == NULL) {
01319 Cudd_RecursiveDeref(manager,sol);
01320 return(NULL);
01321 }
01322 cuddRef(tmp);
01323 Cudd_RecursiveDeref(manager,sol);
01324 sol = tmp;
01325 complement = Cudd_IsComplement(E);
01326 my_dd = Cudd_Regular(E);
01327 cost = Ecost;
01328 continue;
01329 }
01330 (void) fprintf(manager->err,"We shouldn't be here!\n");
01331 manager->errorCode = CUDD_INTERNAL_ERROR;
01332 return(NULL);
01333 }
01334
01335 cuddDeref(sol);
01336 return(sol);
01337
01338 }