00001
00045 #include "util_hack.h"
00046 #include "cuddInt.h"
00047
00048
00049
00050
00051
00052 #define DD_BIGGY 1000000
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 typedef struct cuddPathPair {
00063 int pos;
00064 int neg;
00065 } cuddPathPair;
00066
00067
00068
00069
00070
00071 #ifndef lint
00072 static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $";
00073 #endif
00074
00075 static DdNode *one, *zero;
00076
00077
00078
00079
00080
00081 #define WEIGHT(weight, col) ((weight) == NULL ? 1 : weight[col])
00082
00085
00086
00087
00088
00089 static enum st_retval freePathPair ARGS((char *key, char *value, char *arg));
00090 static cuddPathPair getShortest ARGS((DdNode *root, int *cost, int *support, st_table *visited));
00091 static DdNode * getPath ARGS((DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost));
00092 static cuddPathPair getLargest ARGS((DdNode *root, st_table *visited));
00093 static DdNode * getCube ARGS((DdManager *manager, st_table *visited, DdNode *f, int cost));
00094
00098
00099
00100
00101
00102
00118 DdNode *
00119 Cudd_Eval(
00120 DdManager * dd,
00121 DdNode * f,
00122 int * inputs)
00123 {
00124 int comple;
00125 DdNode *ptr;
00126
00127 comple = Cudd_IsComplement(f);
00128 ptr = Cudd_Regular(f);
00129
00130 while (!cuddIsConstant(ptr)) {
00131 if (inputs[ptr->index] == 1) {
00132 ptr = cuddT(ptr);
00133 } else {
00134 comple ^= Cudd_IsComplement(cuddE(ptr));
00135 ptr = Cudd_Regular(cuddE(ptr));
00136 }
00137 }
00138 return(Cudd_NotCond(ptr,comple));
00139
00140 }
00141
00142
00162 DdNode *
00163 Cudd_ShortestPath(
00164 DdManager * manager,
00165 DdNode * f,
00166 int * weight,
00167 int * support,
00168 int * length)
00169 {
00170 register DdNode *F;
00171 st_table *visited;
00172 DdNode *sol;
00173 cuddPathPair *rootPair;
00174 int complement, cost;
00175 int i;
00176
00177 one = DD_ONE(manager);
00178 zero = DD_ZERO(manager);
00179
00180
00181 if (support) {
00182 for (i = 0; i < manager->size; i++) {
00183 support[i] = 0;
00184 }
00185 }
00186
00187 if (f == Cudd_Not(one) || f == zero) {
00188 *length = DD_BIGGY;
00189 return(Cudd_Not(one));
00190 }
00191
00192
00193
00194 visited = st_init_table(st_ptrcmp, st_ptrhash);
00195
00196
00197 (void) getShortest(f, weight, support, visited);
00198
00199 complement = Cudd_IsComplement(f);
00200
00201 F = Cudd_Regular(f);
00202
00203 st_lookup(visited, (char *)F, (char **)&rootPair);
00204
00205 if (complement) {
00206 cost = rootPair->neg;
00207 } else {
00208 cost = rootPair->pos;
00209 }
00210
00211
00212 do {
00213 manager->reordered = 0;
00214 sol = getPath(manager,visited,f,weight,cost);
00215 } while (manager->reordered == 1);
00216
00217 st_foreach(visited, freePathPair, NULL);
00218 st_free_table(visited);
00219
00220 *length = cost;
00221 return(sol);
00222
00223 }
00224
00225
00242 DdNode *
00243 Cudd_LargestCube(
00244 DdManager * manager,
00245 DdNode * f,
00246 int * length)
00247 {
00248 register DdNode *F;
00249 st_table *visited;
00250 DdNode *sol;
00251 cuddPathPair *rootPair;
00252 int complement, cost;
00253
00254 one = DD_ONE(manager);
00255 zero = DD_ZERO(manager);
00256
00257 if (f == Cudd_Not(one) || f == zero) {
00258 *length = DD_BIGGY;
00259 return(Cudd_Not(one));
00260 }
00261
00262
00263
00264 visited = st_init_table(st_ptrcmp, st_ptrhash);
00265
00266
00267 (void) getLargest(f, visited);
00268
00269 complement = Cudd_IsComplement(f);
00270
00271 F = Cudd_Regular(f);
00272
00273 st_lookup(visited, (char *)F, (char **)&rootPair);
00274
00275 if (complement) {
00276 cost = rootPair->neg;
00277 } else {
00278 cost = rootPair->pos;
00279 }
00280
00281
00282 do {
00283 manager->reordered = 0;
00284 sol = getCube(manager,visited,f,cost);
00285 } while (manager->reordered == 1);
00286
00287 st_foreach(visited, freePathPair, NULL);
00288 st_free_table(visited);
00289
00290 *length = cost;
00291 return(sol);
00292
00293 }
00294
00295
00311 int
00312 Cudd_ShortestLength(
00313 DdManager * manager,
00314 DdNode * f,
00315 int * weight)
00316 {
00317 register DdNode *F;
00318 st_table *visited;
00319 cuddPathPair *my_pair;
00320 int complement, cost;
00321
00322 one = DD_ONE(manager);
00323 zero = DD_ZERO(manager);
00324
00325 if (f == Cudd_Not(one) || f == zero) {
00326 return(DD_BIGGY);
00327 }
00328
00329
00330
00331 visited = st_init_table(st_ptrcmp, st_ptrhash);
00332
00333
00334 (void) getShortest(f, weight, NULL, visited);
00335
00336 complement = Cudd_IsComplement(f);
00337
00338 F = Cudd_Regular(f);
00339
00340 st_lookup(visited, (char *)F, (char **)&my_pair);
00341
00342 if (complement) {
00343 cost = my_pair->neg;
00344 } else {
00345 cost = my_pair->pos;
00346 }
00347
00348 st_foreach(visited, freePathPair, NULL);
00349 st_free_table(visited);
00350
00351 return(cost);
00352
00353 }
00354
00355
00371 DdNode *
00372 Cudd_Decreasing(
00373 DdManager * dd,
00374 DdNode * f,
00375 int i)
00376 {
00377 unsigned int topf, level;
00378 DdNode *F, *fv, *fvn, *res;
00379 DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *);
00380
00381 statLine(dd);
00382 #ifdef DD_DEBUG
00383 assert(0 <= i && i < dd->size);
00384 #endif
00385
00386 F = Cudd_Regular(f);
00387 topf = cuddI(dd,F->index);
00388
00389
00390
00391
00392 level = (unsigned) dd->perm[i];
00393 if (topf > level) {
00394 return(DD_ONE(dd));
00395 }
00396
00397
00398
00399
00400 cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_Decreasing;
00401 res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
00402 if (res != NULL) {
00403 return(res);
00404 }
00405
00406
00407 fv = cuddT(F); fvn = cuddE(F);
00408 if (F != f) {
00409 fv = Cudd_Not(fv);
00410 fvn = Cudd_Not(fvn);
00411 }
00412
00413 if (topf == (unsigned) level) {
00414
00415
00416
00417
00418
00419 if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
00420 return(Cudd_Not(DD_ONE(dd)));
00421 }
00422 res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
00423 } else {
00424 res = Cudd_Decreasing(dd,fv,i);
00425 if (res == DD_ONE(dd)) {
00426 res = Cudd_Decreasing(dd,fvn,i);
00427 }
00428 }
00429
00430 cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
00431 return(res);
00432
00433 }
00434
00435
00451 DdNode *
00452 Cudd_Increasing(
00453 DdManager * dd,
00454 DdNode * f,
00455 int i)
00456 {
00457 return(Cudd_Decreasing(dd,Cudd_Not(f),i));
00458
00459 }
00460
00461
00476 int
00477 Cudd_EquivDC(
00478 DdManager * dd,
00479 DdNode * F,
00480 DdNode * G,
00481 DdNode * D)
00482 {
00483 DdNode *tmp, *One, *Gr, *Dr;
00484 DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
00485 int res;
00486 unsigned int flevel, glevel, dlevel, top;
00487
00488 One = DD_ONE(dd);
00489
00490 statLine(dd);
00491
00492 if (D == One || F == G) return(1);
00493 if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);
00494
00495
00496
00497
00498 if (F > G) {
00499 tmp = F;
00500 F = G;
00501 G = tmp;
00502 }
00503 if (Cudd_IsComplement(F)) {
00504 F = Cudd_Not(F);
00505 G = Cudd_Not(G);
00506 }
00507
00508
00509
00510
00511 tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
00512 if (tmp != NULL) return(tmp == One);
00513
00514
00515 flevel = cuddI(dd,F->index);
00516 Gr = Cudd_Regular(G);
00517 glevel = cuddI(dd,Gr->index);
00518 top = ddMin(flevel,glevel);
00519 Dr = Cudd_Regular(D);
00520 dlevel = dd->perm[Dr->index];
00521 top = ddMin(top,dlevel);
00522
00523
00524 if (top == flevel) {
00525 Fv = cuddT(F);
00526 Fvn = cuddE(F);
00527 } else {
00528 Fv = Fvn = F;
00529 }
00530 if (top == glevel) {
00531 Gv = cuddT(Gr);
00532 Gvn = cuddE(Gr);
00533 if (G != Gr) {
00534 Gv = Cudd_Not(Gv);
00535 Gvn = Cudd_Not(Gvn);
00536 }
00537 } else {
00538 Gv = Gvn = G;
00539 }
00540 if (top == dlevel) {
00541 Dv = cuddT(Dr);
00542 Dvn = cuddE(Dr);
00543 if (D != Dr) {
00544 Dv = Cudd_Not(Dv);
00545 Dvn = Cudd_Not(Dvn);
00546 }
00547 } else {
00548 Dv = Dvn = D;
00549 }
00550
00551
00552 res = Cudd_EquivDC(dd,Fv,Gv,Dv);
00553 if (res != 0) {
00554 res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
00555 }
00556 cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));
00557
00558 return(res);
00559
00560 }
00561
00562
00576 int
00577 Cudd_bddLeqUnless(
00578 DdManager *dd,
00579 DdNode *f,
00580 DdNode *g,
00581 DdNode *D)
00582 {
00583 DdNode *tmp, *One, *F, *G;
00584 DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
00585 int res;
00586 unsigned int flevel, glevel, dlevel, top;
00587
00588 statLine(dd);
00589
00590 One = DD_ONE(dd);
00591
00592
00593 if (f == g || g == One || f == Cudd_Not(One) || D == One ||
00594 D == f || D == Cudd_Not(g)) return(1);
00595
00596 if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
00597 return(Cudd_bddLeq(dd,f,g));
00598 if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
00599 if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 if (Cudd_IsComplement(D)) {
00612 if (Cudd_IsComplement(g)) {
00613
00614
00615
00616 if (!Cudd_IsComplement(f)) return(0);
00617
00618 tmp = D;
00619 D = Cudd_Not(f);
00620 if (g < tmp) {
00621 f = Cudd_Not(g);
00622 g = tmp;
00623 } else {
00624 f = Cudd_Not(tmp);
00625 }
00626 } else {
00627 if (Cudd_IsComplement(f)) {
00628
00629 tmp = f;
00630 f = Cudd_Not(D);
00631 if (tmp < g) {
00632 D = g;
00633 g = Cudd_Not(tmp);
00634 } else {
00635 D = Cudd_Not(tmp);
00636 }
00637 } else {
00638
00639 tmp = D;
00640 D = g;
00641 if (tmp < f) {
00642 g = Cudd_Not(f);
00643 f = Cudd_Not(tmp);
00644 } else {
00645 g = tmp;
00646 }
00647 }
00648 }
00649 } else {
00650 if (Cudd_IsComplement(g)) {
00651 if (Cudd_IsComplement(f)) {
00652
00653 tmp = f;
00654 f = Cudd_Not(g);
00655 if (D < tmp) {
00656 g = D;
00657 D = Cudd_Not(tmp);
00658 } else {
00659 g = Cudd_Not(tmp);
00660 }
00661 } else {
00662
00663 if (g < f) {
00664 tmp = g;
00665 g = Cudd_Not(f);
00666 f = Cudd_Not(tmp);
00667 }
00668 }
00669 } else {
00670
00671 if (D < g) {
00672 tmp = D;
00673 D = g;
00674 g = tmp;
00675 }
00676 }
00677 }
00678
00679
00680
00681
00682 tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
00683 if (tmp != NULL) return(tmp == One);
00684
00685
00686 F = Cudd_Regular(f);
00687 flevel = dd->perm[F->index];
00688 G = Cudd_Regular(g);
00689 glevel = dd->perm[G->index];
00690 top = ddMin(flevel,glevel);
00691 dlevel = dd->perm[D->index];
00692 top = ddMin(top,dlevel);
00693
00694
00695 if (top == flevel) {
00696 Ft = cuddT(F);
00697 Fe = cuddE(F);
00698 if (F != f) {
00699 Ft = Cudd_Not(Ft);
00700 Fe = Cudd_Not(Fe);
00701 }
00702 } else {
00703 Ft = Fe = f;
00704 }
00705 if (top == glevel) {
00706 Gt = cuddT(G);
00707 Ge = cuddE(G);
00708 if (G != g) {
00709 Gt = Cudd_Not(Gt);
00710 Ge = Cudd_Not(Ge);
00711 }
00712 } else {
00713 Gt = Ge = g;
00714 }
00715 if (top == dlevel) {
00716 Dt = cuddT(D);
00717 De = cuddE(D);
00718 } else {
00719 Dt = De = D;
00720 }
00721
00722
00723 res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
00724 if (res != 0) {
00725 res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
00726 }
00727 cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res));
00728
00729 return(res);
00730
00731 }
00732
00733
00750 int
00751 Cudd_EqualSupNorm(
00752 DdManager * dd ,
00753 DdNode * f ,
00754 DdNode * g ,
00755 CUDD_VALUE_TYPE tolerance ,
00756 int pr )
00757 {
00758 DdNode *fv, *fvn, *gv, *gvn, *r;
00759 unsigned int topf, topg;
00760
00761 statLine(dd);
00762
00763 if (f == g) return(1);
00764 if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
00765 if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
00766 return(1);
00767 } else {
00768 if (pr>0) {
00769 (void) fprintf(dd->out,"Offending nodes:\n");
00770 #if SIZEOF_VOID_P == 8
00771 (void) fprintf(dd->out,
00772 "f: address = %lx\t value = %40.30f\n",
00773 (unsigned long) f, cuddV(f));
00774 (void) fprintf(dd->out,
00775 "g: address = %lx\t value = %40.30f\n",
00776 (unsigned long) g, cuddV(g));
00777 #else
00778 (void) fprintf(dd->out,
00779 "f: address = %x\t value = %40.30f\n",
00780 (unsigned) f, cuddV(f));
00781 (void) fprintf(dd->out,
00782 "g: address = %x\t value = %40.30f\n",
00783 (unsigned) g, cuddV(g));
00784 #endif
00785 }
00786 return(0);
00787 }
00788 }
00789
00790
00791
00792 r = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g);
00793 if (r != NULL) {
00794 return(1);
00795 }
00796
00797
00798 topf = cuddI(dd,f->index);
00799 topg = cuddI(dd,g->index);
00800
00801 if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
00802 if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
00803
00804 if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
00805 if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);
00806
00807 cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g,DD_ONE(dd));
00808
00809 return(1);
00810
00811 }
00812
00813
00827 DdNode *
00828 Cudd_bddMakePrime(
00829 DdManager *dd ,
00830 DdNode *cube ,
00831 DdNode *f )
00832 {
00833 DdNode *res;
00834
00835 if (!Cudd_bddLeq(dd,cube,f)) return(NULL);
00836
00837 do {
00838 dd->reordered = 0;
00839 res = cuddBddMakePrime(dd,cube,f);
00840 } while (dd->reordered == 1);
00841 return(res);
00842
00843 }
00844
00845
00846
00847
00848
00849
00850
00863 DdNode *
00864 cuddBddMakePrime(
00865 DdManager *dd ,
00866 DdNode *cube ,
00867 DdNode *f )
00868 {
00869 DdNode *scan;
00870 DdNode *t, *e;
00871 DdNode *res = cube;
00872 DdNode *zero = Cudd_Not(DD_ONE(dd));
00873
00874 Cudd_Ref(res);
00875 scan = cube;
00876 while (!Cudd_IsConstant(scan)) {
00877 DdNode *reg = Cudd_Regular(scan);
00878 DdNode *var = dd->vars[reg->index];
00879 DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
00880 if (expanded == NULL) {
00881 return(NULL);
00882 }
00883 Cudd_Ref(expanded);
00884 if (Cudd_bddLeq(dd,expanded,f)) {
00885 Cudd_RecursiveDeref(dd,res);
00886 res = expanded;
00887 } else {
00888 Cudd_RecursiveDeref(dd,expanded);
00889 }
00890 cuddGetBranches(scan,&t,&e);
00891 if (t == zero) {
00892 scan = e;
00893 } else if (e == zero) {
00894 scan = t;
00895 } else {
00896 Cudd_RecursiveDeref(dd,res);
00897 return(NULL);
00898 }
00899 }
00900
00901 if (scan == DD_ONE(dd)) {
00902 Cudd_Deref(res);
00903 return(res);
00904 } else {
00905 Cudd_RecursiveDeref(dd,res);
00906 return(NULL);
00907 }
00908
00909 }
00910
00911
00912
00913
00914
00915
00916
00927 static enum st_retval
00928 freePathPair(
00929 char * key,
00930 char * value,
00931 char * arg)
00932 {
00933 cuddPathPair *pair;
00934
00935 pair = (cuddPathPair *) value;
00936 FREE(pair);
00937 return(ST_CONTINUE);
00938
00939 }
00940
00941
00960 static cuddPathPair
00961 getShortest(
00962 DdNode * root,
00963 int * cost,
00964 int * support,
00965 st_table * visited)
00966 {
00967 cuddPathPair *my_pair, res_pair, pair_T, pair_E;
00968 DdNode *my_root, *T, *E;
00969 int weight;
00970
00971 my_root = Cudd_Regular(root);
00972
00973 if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) {
00974 if (Cudd_IsComplement(root)) {
00975 res_pair.pos = my_pair->neg;
00976 res_pair.neg = my_pair->pos;
00977 } else {
00978 res_pair.pos = my_pair->pos;
00979 res_pair.neg = my_pair->neg;
00980 }
00981 return(res_pair);
00982 }
00983
00984
00985
00986
00987
00988
00989 if (cuddIsConstant(my_root)) {
00990 if (my_root != zero) {
00991 res_pair.pos = 0;
00992 res_pair.neg = DD_BIGGY;
00993 } else {
00994 res_pair.pos = DD_BIGGY;
00995 res_pair.neg = 0;
00996 }
00997 } else {
00998 T = cuddT(my_root);
00999 E = cuddE(my_root);
01000
01001 pair_T = getShortest(T, cost, support, visited);
01002 pair_E = getShortest(E, cost, support, visited);
01003 weight = WEIGHT(cost, my_root->index);
01004 res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
01005 res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);
01006
01007
01008 if (support != NULL) {
01009 support[my_root->index] = 1;
01010 }
01011 }
01012
01013 my_pair = ALLOC(cuddPathPair, 1);
01014 if (my_pair == NULL) {
01015 if (Cudd_IsComplement(root)) {
01016 int tmp = res_pair.pos;
01017 res_pair.pos = res_pair.neg;
01018 res_pair.neg = tmp;
01019 }
01020 return(res_pair);
01021 }
01022 my_pair->pos = res_pair.pos;
01023 my_pair->neg = res_pair.neg;
01024
01025 st_insert(visited, (char *)my_root, (char *)my_pair);
01026 if (Cudd_IsComplement(root)) {
01027 res_pair.pos = my_pair->neg;
01028 res_pair.neg = my_pair->pos;
01029 } else {
01030 res_pair.pos = my_pair->pos;
01031 res_pair.neg = my_pair->neg;
01032 }
01033 return(res_pair);
01034
01035 }
01036
01037
01056 static DdNode *
01057 getPath(
01058 DdManager * manager,
01059 st_table * visited,
01060 DdNode * f,
01061 int * weight,
01062 int cost)
01063 {
01064 DdNode *sol, *tmp;
01065 DdNode *my_dd, *T, *E;
01066 cuddPathPair *T_pair, *E_pair;
01067 int Tcost, Ecost;
01068 int complement;
01069
01070 my_dd = Cudd_Regular(f);
01071 complement = Cudd_IsComplement(f);
01072
01073 sol = one;
01074 cuddRef(sol);
01075
01076 while (!cuddIsConstant(my_dd)) {
01077 Tcost = cost - WEIGHT(weight, my_dd->index);
01078 Ecost = cost;
01079
01080 T = cuddT(my_dd);
01081 E = cuddE(my_dd);
01082
01083 if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
01084
01085 st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair);
01086 if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
01087 (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
01088 tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
01089 if (tmp == NULL) {
01090 Cudd_RecursiveDeref(manager,sol);
01091 return(NULL);
01092 }
01093 cuddRef(tmp);
01094 Cudd_RecursiveDeref(manager,sol);
01095 sol = tmp;
01096
01097 complement = Cudd_IsComplement(T);
01098 my_dd = Cudd_Regular(T);
01099 cost = Tcost;
01100 continue;
01101 }
01102 st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair);
01103 if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
01104 (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
01105 tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
01106 if (tmp == NULL) {
01107 Cudd_RecursiveDeref(manager,sol);
01108 return(NULL);
01109 }
01110 cuddRef(tmp);
01111 Cudd_RecursiveDeref(manager,sol);
01112 sol = tmp;
01113 complement = Cudd_IsComplement(E);
01114 my_dd = Cudd_Regular(E);
01115 cost = Ecost;
01116 continue;
01117 }
01118 (void) fprintf(manager->err,"We shouldn't be here!!\n");
01119 manager->errorCode = CUDD_INTERNAL_ERROR;
01120 return(NULL);
01121 }
01122
01123 cuddDeref(sol);
01124 return(sol);
01125
01126 }
01127
01128
01149 static cuddPathPair
01150 getLargest(
01151 DdNode * root,
01152 st_table * visited)
01153 {
01154 cuddPathPair *my_pair, res_pair, pair_T, pair_E;
01155 DdNode *my_root, *T, *E;
01156
01157 my_root = Cudd_Regular(root);
01158
01159 if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) {
01160 if (Cudd_IsComplement(root)) {
01161 res_pair.pos = my_pair->neg;
01162 res_pair.neg = my_pair->pos;
01163 } else {
01164 res_pair.pos = my_pair->pos;
01165 res_pair.neg = my_pair->neg;
01166 }
01167 return(res_pair);
01168 }
01169
01170
01171
01172
01173
01174
01175 if (cuddIsConstant(my_root)) {
01176 if (my_root != zero) {
01177 res_pair.pos = 0;
01178 res_pair.neg = DD_BIGGY;
01179 } else {
01180 res_pair.pos = DD_BIGGY;
01181 res_pair.neg = 0;
01182 }
01183 } else {
01184 T = cuddT(my_root);
01185 E = cuddE(my_root);
01186
01187 pair_T = getLargest(T, visited);
01188 pair_E = getLargest(E, visited);
01189 res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
01190 res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
01191 }
01192
01193 my_pair = ALLOC(cuddPathPair, 1);
01194 if (my_pair == NULL) {
01195 if (Cudd_IsComplement(root)) {
01196 int tmp = res_pair.pos;
01197 res_pair.pos = res_pair.neg;
01198 res_pair.neg = tmp;
01199 }
01200 return(res_pair);
01201 }
01202 my_pair->pos = res_pair.pos;
01203 my_pair->neg = res_pair.neg;
01204
01205 st_insert(visited, (char *)my_root, (char *)my_pair);
01206 if (Cudd_IsComplement(root)) {
01207 res_pair.pos = my_pair->neg;
01208 res_pair.neg = my_pair->pos;
01209 } else {
01210 res_pair.pos = my_pair->pos;
01211 res_pair.neg = my_pair->neg;
01212 }
01213 return(res_pair);
01214
01215 }
01216
01217
01236 static DdNode *
01237 getCube(
01238 DdManager * manager,
01239 st_table * visited,
01240 DdNode * f,
01241 int cost)
01242 {
01243 DdNode *sol, *tmp;
01244 DdNode *my_dd, *T, *E;
01245 cuddPathPair *T_pair, *E_pair;
01246 int Tcost, Ecost;
01247 int complement;
01248
01249 my_dd = Cudd_Regular(f);
01250 complement = Cudd_IsComplement(f);
01251
01252 sol = one;
01253 cuddRef(sol);
01254
01255 while (!cuddIsConstant(my_dd)) {
01256 Tcost = cost - 1;
01257 Ecost = cost - 1;
01258
01259 T = cuddT(my_dd);
01260 E = cuddE(my_dd);
01261
01262 if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
01263
01264 st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair);
01265 if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
01266 (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
01267 tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
01268 if (tmp == NULL) {
01269 Cudd_RecursiveDeref(manager,sol);
01270 return(NULL);
01271 }
01272 cuddRef(tmp);
01273 Cudd_RecursiveDeref(manager,sol);
01274 sol = tmp;
01275
01276 complement = Cudd_IsComplement(T);
01277 my_dd = Cudd_Regular(T);
01278 cost = Tcost;
01279 continue;
01280 }
01281 st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair);
01282 if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
01283 (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
01284 tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
01285 if (tmp == NULL) {
01286 Cudd_RecursiveDeref(manager,sol);
01287 return(NULL);
01288 }
01289 cuddRef(tmp);
01290 Cudd_RecursiveDeref(manager,sol);
01291 sol = tmp;
01292 complement = Cudd_IsComplement(E);
01293 my_dd = Cudd_Regular(E);
01294 cost = Ecost;
01295 continue;
01296 }
01297 (void) fprintf(manager->err,"We shouldn't be here!\n");
01298 manager->errorCode = CUDD_INTERNAL_ERROR;
01299 return(NULL);
01300 }
01301
01302 cuddDeref(sol);
01303 return(sol);
01304
01305 }