00001
00108 #include "util.h"
00109 #include "cuddInt.h"
00110
00111
00112
00113
00114
00115
00116 #define MODULUS1 2147483563
00117 #define LEQA1 40014
00118 #define LEQQ1 53668
00119 #define LEQR1 12211
00120 #define MODULUS2 2147483399
00121 #define LEQA2 40692
00122 #define LEQQ2 52774
00123 #define LEQR2 3791
00124 #define STAB_SIZE 64
00125 #define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 #ifndef lint
00141 static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.81 2009/03/08 02:49:02 fabio Exp $";
00142 #endif
00143
00144 static DdNode *background, *zero;
00145
00146 static long cuddRand = 0;
00147 static long cuddRand2;
00148 static long shuffleSelect;
00149 static long shuffleTable[STAB_SIZE];
00150
00151
00152
00153
00154
00155 #define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ')
00156
00157 #ifdef __cplusplus
00158 extern "C" {
00159 #endif
00160
00163
00164
00165
00166
00167 static int dp2 (DdManager *dd, DdNode *f, st_table *t);
00168 static void ddPrintMintermAux (DdManager *dd, DdNode *node, int *list);
00169 static int ddDagInt (DdNode *n);
00170 static int cuddNodeArrayRecur (DdNode *f, DdNodePtr *table, int index);
00171 static int cuddEstimateCofactor (DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr);
00172 static DdNode * cuddUniqueLookup (DdManager * unique, int index, DdNode * T, DdNode * E);
00173 static int cuddEstimateCofactorSimple (DdNode * node, int i);
00174 static double ddCountMintermAux (DdNode *node, double max, DdHashTable *table);
00175 static int ddEpdCountMintermAux (DdNode *node, EpDouble *max, EpDouble *epd, st_table *table);
00176 static double ddCountPathAux (DdNode *node, st_table *table);
00177 static double ddCountPathsToNonZero (DdNode * N, st_table * table);
00178 static void ddSupportStep (DdNode *f, int *support);
00179 static void ddClearFlag (DdNode *f);
00180 static int ddLeavesInt (DdNode *n);
00181 static int ddPickArbitraryMinterms (DdManager *dd, DdNode *node, int nvars, int nminterms, char **string);
00182 static int ddPickRepresentativeCube (DdManager *dd, DdNode *node, double *weight, char *string);
00183 static enum st_retval ddEpdFree (char * key, char * value, char * arg);
00184
00187 #ifdef __cplusplus
00188 }
00189 #endif
00190
00191
00192
00193
00194
00195
00211 int
00212 Cudd_PrintMinterm(
00213 DdManager * manager,
00214 DdNode * node)
00215 {
00216 int i, *list;
00217
00218 background = manager->background;
00219 zero = Cudd_Not(manager->one);
00220 list = ALLOC(int,manager->size);
00221 if (list == NULL) {
00222 manager->errorCode = CUDD_MEMORY_OUT;
00223 return(0);
00224 }
00225 for (i = 0; i < manager->size; i++) list[i] = 2;
00226 ddPrintMintermAux(manager,node,list);
00227 FREE(list);
00228 return(1);
00229
00230 }
00231
00232
00248 int
00249 Cudd_bddPrintCover(
00250 DdManager *dd,
00251 DdNode *l,
00252 DdNode *u)
00253 {
00254 int *array;
00255 int q, result;
00256 DdNode *lb;
00257 #ifdef DD_DEBUG
00258 DdNode *cover;
00259 #endif
00260
00261 array = ALLOC(int, Cudd_ReadSize(dd));
00262 if (array == NULL) return(0);
00263 lb = l;
00264 cuddRef(lb);
00265 #ifdef DD_DEBUG
00266 cover = Cudd_ReadLogicZero(dd);
00267 cuddRef(cover);
00268 #endif
00269 while (lb != Cudd_ReadLogicZero(dd)) {
00270 DdNode *implicant, *prime, *tmp;
00271 int length;
00272 implicant = Cudd_LargestCube(dd,lb,&length);
00273 if (implicant == NULL) {
00274 Cudd_RecursiveDeref(dd,lb);
00275 FREE(array);
00276 return(0);
00277 }
00278 cuddRef(implicant);
00279 prime = Cudd_bddMakePrime(dd,implicant,u);
00280 if (prime == NULL) {
00281 Cudd_RecursiveDeref(dd,lb);
00282 Cudd_RecursiveDeref(dd,implicant);
00283 FREE(array);
00284 return(0);
00285 }
00286 cuddRef(prime);
00287 Cudd_RecursiveDeref(dd,implicant);
00288 tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime));
00289 if (tmp == NULL) {
00290 Cudd_RecursiveDeref(dd,lb);
00291 Cudd_RecursiveDeref(dd,prime);
00292 FREE(array);
00293 return(0);
00294 }
00295 cuddRef(tmp);
00296 Cudd_RecursiveDeref(dd,lb);
00297 lb = tmp;
00298 result = Cudd_BddToCubeArray(dd,prime,array);
00299 if (result == 0) {
00300 Cudd_RecursiveDeref(dd,lb);
00301 Cudd_RecursiveDeref(dd,prime);
00302 FREE(array);
00303 return(0);
00304 }
00305 for (q = 0; q < dd->size; q++) {
00306 switch (array[q]) {
00307 case 0:
00308 (void) fprintf(dd->out, "0");
00309 break;
00310 case 1:
00311 (void) fprintf(dd->out, "1");
00312 break;
00313 case 2:
00314 (void) fprintf(dd->out, "-");
00315 break;
00316 default:
00317 (void) fprintf(dd->out, "?");
00318 }
00319 }
00320 (void) fprintf(dd->out, " 1\n");
00321 #ifdef DD_DEBUG
00322 tmp = Cudd_bddOr(dd,prime,cover);
00323 if (tmp == NULL) {
00324 Cudd_RecursiveDeref(dd,cover);
00325 Cudd_RecursiveDeref(dd,lb);
00326 Cudd_RecursiveDeref(dd,prime);
00327 FREE(array);
00328 return(0);
00329 }
00330 cuddRef(tmp);
00331 Cudd_RecursiveDeref(dd,cover);
00332 cover = tmp;
00333 #endif
00334 Cudd_RecursiveDeref(dd,prime);
00335 }
00336 (void) fprintf(dd->out, "\n");
00337 Cudd_RecursiveDeref(dd,lb);
00338 FREE(array);
00339 #ifdef DD_DEBUG
00340 if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) {
00341 Cudd_RecursiveDeref(dd,cover);
00342 return(0);
00343 }
00344 Cudd_RecursiveDeref(dd,cover);
00345 #endif
00346 return(1);
00347
00348 }
00349
00350
00377 int
00378 Cudd_PrintDebug(
00379 DdManager * dd,
00380 DdNode * f,
00381 int n,
00382 int pr)
00383 {
00384 DdNode *azero, *bzero;
00385 int nodes;
00386 int leaves;
00387 double minterms;
00388 int retval = 1;
00389
00390 if (f == NULL) {
00391 (void) fprintf(dd->out,": is the NULL DD\n");
00392 (void) fflush(dd->out);
00393 return(0);
00394 }
00395 azero = DD_ZERO(dd);
00396 bzero = Cudd_Not(DD_ONE(dd));
00397 if ((f == azero || f == bzero) && pr > 0){
00398 (void) fprintf(dd->out,": is the zero DD\n");
00399 (void) fflush(dd->out);
00400 return(1);
00401 }
00402 if (pr > 0) {
00403 nodes = Cudd_DagSize(f);
00404 if (nodes == CUDD_OUT_OF_MEM) retval = 0;
00405 leaves = Cudd_CountLeaves(f);
00406 if (leaves == CUDD_OUT_OF_MEM) retval = 0;
00407 minterms = Cudd_CountMinterm(dd, f, n);
00408 if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0;
00409 (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n",
00410 nodes, leaves, minterms);
00411 if (pr > 2) {
00412 if (!cuddP(dd, f)) retval = 0;
00413 }
00414 if (pr == 2 || pr > 3) {
00415 if (!Cudd_PrintMinterm(dd,f)) retval = 0;
00416 (void) fprintf(dd->out,"\n");
00417 }
00418 (void) fflush(dd->out);
00419 }
00420 return(retval);
00421
00422 }
00423
00424
00437 int
00438 Cudd_DagSize(
00439 DdNode * node)
00440 {
00441 int i;
00442
00443 i = ddDagInt(Cudd_Regular(node));
00444 ddClearFlag(Cudd_Regular(node));
00445
00446 return(i);
00447
00448 }
00449
00450
00472 int
00473 Cudd_EstimateCofactor(
00474 DdManager *dd ,
00475 DdNode * f ,
00476 int i ,
00477 int phase
00478 )
00479 {
00480 int val;
00481 DdNode *ptr;
00482 st_table *table;
00483
00484 table = st_init_table(st_ptrcmp,st_ptrhash);
00485 if (table == NULL) return(CUDD_OUT_OF_MEM);
00486 val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr);
00487 ddClearFlag(Cudd_Regular(f));
00488 st_free_table(table);
00489
00490 return(val);
00491
00492 }
00493
00494
00512 int
00513 Cudd_EstimateCofactorSimple(
00514 DdNode * node,
00515 int i)
00516 {
00517 int val;
00518
00519 val = cuddEstimateCofactorSimple(Cudd_Regular(node),i);
00520 ddClearFlag(Cudd_Regular(node));
00521
00522 return(val);
00523
00524 }
00525
00526
00539 int
00540 Cudd_SharingSize(
00541 DdNode ** nodeArray,
00542 int n)
00543 {
00544 int i,j;
00545
00546 i = 0;
00547 for (j = 0; j < n; j++) {
00548 i += ddDagInt(Cudd_Regular(nodeArray[j]));
00549 }
00550 for (j = 0; j < n; j++) {
00551 ddClearFlag(Cudd_Regular(nodeArray[j]));
00552 }
00553 return(i);
00554
00555 }
00556
00557
00573 double
00574 Cudd_CountMinterm(
00575 DdManager * manager,
00576 DdNode * node,
00577 int nvars)
00578 {
00579 double max;
00580 DdHashTable *table;
00581 double res;
00582 CUDD_VALUE_TYPE epsilon;
00583
00584 background = manager->background;
00585 zero = Cudd_Not(manager->one);
00586
00587 max = pow(2.0,(double)nvars);
00588 table = cuddHashTableInit(manager,1,2);
00589 if (table == NULL) {
00590 return((double)CUDD_OUT_OF_MEM);
00591 }
00592 epsilon = Cudd_ReadEpsilon(manager);
00593 Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0);
00594 res = ddCountMintermAux(node,max,table);
00595 cuddHashTableQuit(table);
00596 Cudd_SetEpsilon(manager,epsilon);
00597
00598 return(res);
00599
00600 }
00601
00602
00618 double
00619 Cudd_CountPath(
00620 DdNode * node)
00621 {
00622
00623 st_table *table;
00624 double i;
00625
00626 table = st_init_table(st_ptrcmp,st_ptrhash);
00627 if (table == NULL) {
00628 return((double)CUDD_OUT_OF_MEM);
00629 }
00630 i = ddCountPathAux(Cudd_Regular(node),table);
00631 st_foreach(table, cuddStCountfree, NULL);
00632 st_free_table(table);
00633 return(i);
00634
00635 }
00636
00637
00652 int
00653 Cudd_EpdCountMinterm(
00654 DdManager * manager,
00655 DdNode * node,
00656 int nvars,
00657 EpDouble * epd)
00658 {
00659 EpDouble max, tmp;
00660 st_table *table;
00661 int status;
00662
00663 background = manager->background;
00664 zero = Cudd_Not(manager->one);
00665
00666 EpdPow2(nvars, &max);
00667 table = st_init_table(EpdCmp, st_ptrhash);
00668 if (table == NULL) {
00669 EpdMakeZero(epd, 0);
00670 return(CUDD_OUT_OF_MEM);
00671 }
00672 status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table);
00673 st_foreach(table, ddEpdFree, NULL);
00674 st_free_table(table);
00675 if (status == CUDD_OUT_OF_MEM) {
00676 EpdMakeZero(epd, 0);
00677 return(CUDD_OUT_OF_MEM);
00678 }
00679 if (Cudd_IsComplement(node)) {
00680 EpdSubtract3(&max, epd, &tmp);
00681 EpdCopy(&tmp, epd);
00682 }
00683 return(0);
00684
00685 }
00686
00687
00702 double
00703 Cudd_CountPathsToNonZero(
00704 DdNode * node)
00705 {
00706
00707 st_table *table;
00708 double i;
00709
00710 table = st_init_table(st_ptrcmp,st_ptrhash);
00711 if (table == NULL) {
00712 return((double)CUDD_OUT_OF_MEM);
00713 }
00714 i = ddCountPathsToNonZero(node,table);
00715 st_foreach(table, cuddStCountfree, NULL);
00716 st_free_table(table);
00717 return(i);
00718
00719 }
00720
00721
00735 DdNode *
00736 Cudd_Support(
00737 DdManager * dd ,
00738 DdNode * f )
00739 {
00740 int *support;
00741 DdNode *res, *tmp, *var;
00742 int i,j;
00743 int size;
00744
00745
00746 size = ddMax(dd->size, dd->sizeZ);
00747 support = ALLOC(int,size);
00748 if (support == NULL) {
00749 dd->errorCode = CUDD_MEMORY_OUT;
00750 return(NULL);
00751 }
00752 for (i = 0; i < size; i++) {
00753 support[i] = 0;
00754 }
00755
00756
00757 ddSupportStep(Cudd_Regular(f),support);
00758 ddClearFlag(Cudd_Regular(f));
00759
00760
00761 do {
00762 dd->reordered = 0;
00763 res = DD_ONE(dd);
00764 cuddRef(res);
00765 for (j = size - 1; j >= 0; j--) {
00766 i = (j >= dd->size) ? j : dd->invperm[j];
00767 if (support[i] == 1) {
00768
00769
00770
00771 var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
00772 cuddRef(var);
00773 tmp = cuddBddAndRecur(dd,res,var);
00774 if (tmp == NULL) {
00775 Cudd_RecursiveDeref(dd,res);
00776 Cudd_RecursiveDeref(dd,var);
00777 res = NULL;
00778 break;
00779 }
00780 cuddRef(tmp);
00781 Cudd_RecursiveDeref(dd,res);
00782 Cudd_RecursiveDeref(dd,var);
00783 res = tmp;
00784 }
00785 }
00786 } while (dd->reordered == 1);
00787
00788 FREE(support);
00789 if (res != NULL) cuddDeref(res);
00790 return(res);
00791
00792 }
00793
00794
00810 int *
00811 Cudd_SupportIndex(
00812 DdManager * dd ,
00813 DdNode * f )
00814 {
00815 int *support;
00816 int i;
00817 int size;
00818
00819
00820 size = ddMax(dd->size, dd->sizeZ);
00821 support = ALLOC(int,size);
00822 if (support == NULL) {
00823 dd->errorCode = CUDD_MEMORY_OUT;
00824 return(NULL);
00825 }
00826 for (i = 0; i < size; i++) {
00827 support[i] = 0;
00828 }
00829
00830
00831 ddSupportStep(Cudd_Regular(f),support);
00832 ddClearFlag(Cudd_Regular(f));
00833
00834 return(support);
00835
00836 }
00837
00838
00852 int
00853 Cudd_SupportSize(
00854 DdManager * dd ,
00855 DdNode * f )
00856 {
00857 int *support;
00858 int i;
00859 int size;
00860 int count;
00861
00862
00863 size = ddMax(dd->size, dd->sizeZ);
00864 support = ALLOC(int,size);
00865 if (support == NULL) {
00866 dd->errorCode = CUDD_MEMORY_OUT;
00867 return(CUDD_OUT_OF_MEM);
00868 }
00869 for (i = 0; i < size; i++) {
00870 support[i] = 0;
00871 }
00872
00873
00874 ddSupportStep(Cudd_Regular(f),support);
00875 ddClearFlag(Cudd_Regular(f));
00876
00877
00878 count = 0;
00879 for (i = 0; i < size; i++) {
00880 if (support[i] == 1) count++;
00881 }
00882
00883 FREE(support);
00884 return(count);
00885
00886 }
00887
00888
00903 DdNode *
00904 Cudd_VectorSupport(
00905 DdManager * dd ,
00906 DdNode ** F ,
00907 int n )
00908 {
00909 int *support;
00910 DdNode *res, *tmp, *var;
00911 int i,j;
00912 int size;
00913
00914
00915 size = ddMax(dd->size, dd->sizeZ);
00916 support = ALLOC(int,size);
00917 if (support == NULL) {
00918 dd->errorCode = CUDD_MEMORY_OUT;
00919 return(NULL);
00920 }
00921 for (i = 0; i < size; i++) {
00922 support[i] = 0;
00923 }
00924
00925
00926 for (i = 0; i < n; i++) {
00927 ddSupportStep(Cudd_Regular(F[i]),support);
00928 }
00929 for (i = 0; i < n; i++) {
00930 ddClearFlag(Cudd_Regular(F[i]));
00931 }
00932
00933
00934 res = DD_ONE(dd);
00935 cuddRef(res);
00936 for (j = size - 1; j >= 0; j--) {
00937 i = (j >= dd->size) ? j : dd->invperm[j];
00938 if (support[i] == 1) {
00939 var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
00940 cuddRef(var);
00941 tmp = Cudd_bddAnd(dd,res,var);
00942 if (tmp == NULL) {
00943 Cudd_RecursiveDeref(dd,res);
00944 Cudd_RecursiveDeref(dd,var);
00945 FREE(support);
00946 return(NULL);
00947 }
00948 cuddRef(tmp);
00949 Cudd_RecursiveDeref(dd,res);
00950 Cudd_RecursiveDeref(dd,var);
00951 res = tmp;
00952 }
00953 }
00954
00955 FREE(support);
00956 cuddDeref(res);
00957 return(res);
00958
00959 }
00960
00961
00975 int *
00976 Cudd_VectorSupportIndex(
00977 DdManager * dd ,
00978 DdNode ** F ,
00979 int n )
00980 {
00981 int *support;
00982 int i;
00983 int size;
00984
00985
00986 size = ddMax(dd->size, dd->sizeZ);
00987 support = ALLOC(int,size);
00988 if (support == NULL) {
00989 dd->errorCode = CUDD_MEMORY_OUT;
00990 return(NULL);
00991 }
00992 for (i = 0; i < size; i++) {
00993 support[i] = 0;
00994 }
00995
00996
00997 for (i = 0; i < n; i++) {
00998 ddSupportStep(Cudd_Regular(F[i]),support);
00999 }
01000 for (i = 0; i < n; i++) {
01001 ddClearFlag(Cudd_Regular(F[i]));
01002 }
01003
01004 return(support);
01005
01006 }
01007
01008
01023 int
01024 Cudd_VectorSupportSize(
01025 DdManager * dd ,
01026 DdNode ** F ,
01027 int n )
01028 {
01029 int *support;
01030 int i;
01031 int size;
01032 int count;
01033
01034
01035 size = ddMax(dd->size, dd->sizeZ);
01036 support = ALLOC(int,size);
01037 if (support == NULL) {
01038 dd->errorCode = CUDD_MEMORY_OUT;
01039 return(CUDD_OUT_OF_MEM);
01040 }
01041 for (i = 0; i < size; i++) {
01042 support[i] = 0;
01043 }
01044
01045
01046 for (i = 0; i < n; i++) {
01047 ddSupportStep(Cudd_Regular(F[i]),support);
01048 }
01049 for (i = 0; i < n; i++) {
01050 ddClearFlag(Cudd_Regular(F[i]));
01051 }
01052
01053
01054 count = 0;
01055 for (i = 0; i < size; i++) {
01056 if (support[i] == 1) count++;
01057 }
01058
01059 FREE(support);
01060 return(count);
01061
01062 }
01063
01064
01080 int
01081 Cudd_ClassifySupport(
01082 DdManager * dd ,
01083 DdNode * f ,
01084 DdNode * g ,
01085 DdNode ** common ,
01086 DdNode ** onlyF ,
01087 DdNode ** onlyG )
01088 {
01089 int *supportF, *supportG;
01090 DdNode *tmp, *var;
01091 int i,j;
01092 int size;
01093
01094
01095 size = ddMax(dd->size, dd->sizeZ);
01096 supportF = ALLOC(int,size);
01097 if (supportF == NULL) {
01098 dd->errorCode = CUDD_MEMORY_OUT;
01099 return(0);
01100 }
01101 supportG = ALLOC(int,size);
01102 if (supportG == NULL) {
01103 dd->errorCode = CUDD_MEMORY_OUT;
01104 FREE(supportF);
01105 return(0);
01106 }
01107 for (i = 0; i < size; i++) {
01108 supportF[i] = 0;
01109 supportG[i] = 0;
01110 }
01111
01112
01113 ddSupportStep(Cudd_Regular(f),supportF);
01114 ddClearFlag(Cudd_Regular(f));
01115 ddSupportStep(Cudd_Regular(g),supportG);
01116 ddClearFlag(Cudd_Regular(g));
01117
01118
01119 *common = *onlyF = *onlyG = DD_ONE(dd);
01120 cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG);
01121 for (j = size - 1; j >= 0; j--) {
01122 i = (j >= dd->size) ? j : dd->invperm[j];
01123 if (supportF[i] == 0 && supportG[i] == 0) continue;
01124 var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
01125 cuddRef(var);
01126 if (supportG[i] == 0) {
01127 tmp = Cudd_bddAnd(dd,*onlyF,var);
01128 if (tmp == NULL) {
01129 Cudd_RecursiveDeref(dd,*common);
01130 Cudd_RecursiveDeref(dd,*onlyF);
01131 Cudd_RecursiveDeref(dd,*onlyG);
01132 Cudd_RecursiveDeref(dd,var);
01133 FREE(supportF); FREE(supportG);
01134 return(0);
01135 }
01136 cuddRef(tmp);
01137 Cudd_RecursiveDeref(dd,*onlyF);
01138 *onlyF = tmp;
01139 } else if (supportF[i] == 0) {
01140 tmp = Cudd_bddAnd(dd,*onlyG,var);
01141 if (tmp == NULL) {
01142 Cudd_RecursiveDeref(dd,*common);
01143 Cudd_RecursiveDeref(dd,*onlyF);
01144 Cudd_RecursiveDeref(dd,*onlyG);
01145 Cudd_RecursiveDeref(dd,var);
01146 FREE(supportF); FREE(supportG);
01147 return(0);
01148 }
01149 cuddRef(tmp);
01150 Cudd_RecursiveDeref(dd,*onlyG);
01151 *onlyG = tmp;
01152 } else {
01153 tmp = Cudd_bddAnd(dd,*common,var);
01154 if (tmp == NULL) {
01155 Cudd_RecursiveDeref(dd,*common);
01156 Cudd_RecursiveDeref(dd,*onlyF);
01157 Cudd_RecursiveDeref(dd,*onlyG);
01158 Cudd_RecursiveDeref(dd,var);
01159 FREE(supportF); FREE(supportG);
01160 return(0);
01161 }
01162 cuddRef(tmp);
01163 Cudd_RecursiveDeref(dd,*common);
01164 *common = tmp;
01165 }
01166 Cudd_RecursiveDeref(dd,var);
01167 }
01168
01169 FREE(supportF); FREE(supportG);
01170 cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG);
01171 return(1);
01172
01173 }
01174
01175
01189 int
01190 Cudd_CountLeaves(
01191 DdNode * node)
01192 {
01193 int i;
01194
01195 i = ddLeavesInt(Cudd_Regular(node));
01196 ddClearFlag(Cudd_Regular(node));
01197 return(i);
01198
01199 }
01200
01201
01216 int
01217 Cudd_bddPickOneCube(
01218 DdManager * ddm,
01219 DdNode * node,
01220 char * string)
01221 {
01222 DdNode *N, *T, *E;
01223 DdNode *one, *bzero;
01224 char dir;
01225 int i;
01226
01227 if (string == NULL || node == NULL) return(0);
01228
01229
01230 one = DD_ONE(ddm);
01231 bzero = Cudd_Not(one);
01232 if (node == bzero) return(0);
01233
01234 for (i = 0; i < ddm->size; i++) string[i] = 2;
01235
01236 for (;;) {
01237
01238 if (node == one) break;
01239
01240 N = Cudd_Regular(node);
01241
01242 T = cuddT(N); E = cuddE(N);
01243 if (Cudd_IsComplement(node)) {
01244 T = Cudd_Not(T); E = Cudd_Not(E);
01245 }
01246 if (T == bzero) {
01247 string[N->index] = 0;
01248 node = E;
01249 } else if (E == bzero) {
01250 string[N->index] = 1;
01251 node = T;
01252 } else {
01253 dir = (char) ((Cudd_Random() & 0x2000) >> 13);
01254 string[N->index] = dir;
01255 node = dir ? T : E;
01256 }
01257 }
01258 return(1);
01259
01260 }
01261
01262
01286 DdNode *
01287 Cudd_bddPickOneMinterm(
01288 DdManager * dd ,
01289 DdNode * f ,
01290 DdNode ** vars ,
01291 int n )
01292 {
01293 char *string;
01294 int i, size;
01295 int *indices;
01296 int result;
01297 DdNode *old, *neW;
01298
01299 size = dd->size;
01300 string = ALLOC(char, size);
01301 if (string == NULL) {
01302 dd->errorCode = CUDD_MEMORY_OUT;
01303 return(NULL);
01304 }
01305 indices = ALLOC(int,n);
01306 if (indices == NULL) {
01307 dd->errorCode = CUDD_MEMORY_OUT;
01308 FREE(string);
01309 return(NULL);
01310 }
01311
01312 for (i = 0; i < n; i++) {
01313 indices[i] = vars[i]->index;
01314 }
01315
01316 result = Cudd_bddPickOneCube(dd,f,string);
01317 if (result == 0) {
01318 FREE(string);
01319 FREE(indices);
01320 return(NULL);
01321 }
01322
01323
01324 for (i = 0; i < n; i++) {
01325 if (string[indices[i]] == 2)
01326 string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5);
01327 }
01328
01329
01330 old = Cudd_ReadOne(dd);
01331 cuddRef(old);
01332
01333 for (i = n-1; i >= 0; i--) {
01334 neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0));
01335 if (neW == NULL) {
01336 FREE(string);
01337 FREE(indices);
01338 Cudd_RecursiveDeref(dd,old);
01339 return(NULL);
01340 }
01341 cuddRef(neW);
01342 Cudd_RecursiveDeref(dd,old);
01343 old = neW;
01344 }
01345
01346 #ifdef DD_DEBUG
01347
01348 if (Cudd_bddLeq(dd,old,f)) {
01349 cuddDeref(old);
01350 } else {
01351 Cudd_RecursiveDeref(dd,old);
01352 old = NULL;
01353 }
01354 #else
01355 cuddDeref(old);
01356 #endif
01357
01358 FREE(string);
01359 FREE(indices);
01360 return(old);
01361
01362 }
01363
01364
01388 DdNode **
01389 Cudd_bddPickArbitraryMinterms(
01390 DdManager * dd ,
01391 DdNode * f ,
01392 DdNode ** vars ,
01393 int n ,
01394 int k )
01395 {
01396 char **string;
01397 int i, j, l, size;
01398 int *indices;
01399 int result;
01400 DdNode **old, *neW;
01401 double minterms;
01402 char *saveString;
01403 int saveFlag, savePoint, isSame;
01404
01405 minterms = Cudd_CountMinterm(dd,f,n);
01406 if ((double)k > minterms) {
01407 return(NULL);
01408 }
01409
01410 size = dd->size;
01411 string = ALLOC(char *, k);
01412 if (string == NULL) {
01413 dd->errorCode = CUDD_MEMORY_OUT;
01414 return(NULL);
01415 }
01416 for (i = 0; i < k; i++) {
01417 string[i] = ALLOC(char, size + 1);
01418 if (string[i] == NULL) {
01419 for (j = 0; j < i; j++)
01420 FREE(string[i]);
01421 FREE(string);
01422 dd->errorCode = CUDD_MEMORY_OUT;
01423 return(NULL);
01424 }
01425 for (j = 0; j < size; j++) string[i][j] = '2';
01426 string[i][size] = '\0';
01427 }
01428 indices = ALLOC(int,n);
01429 if (indices == NULL) {
01430 dd->errorCode = CUDD_MEMORY_OUT;
01431 for (i = 0; i < k; i++)
01432 FREE(string[i]);
01433 FREE(string);
01434 return(NULL);
01435 }
01436
01437 for (i = 0; i < n; i++) {
01438 indices[i] = vars[i]->index;
01439 }
01440
01441 result = ddPickArbitraryMinterms(dd,f,n,k,string);
01442 if (result == 0) {
01443 for (i = 0; i < k; i++)
01444 FREE(string[i]);
01445 FREE(string);
01446 FREE(indices);
01447 return(NULL);
01448 }
01449
01450 old = ALLOC(DdNode *, k);
01451 if (old == NULL) {
01452 dd->errorCode = CUDD_MEMORY_OUT;
01453 for (i = 0; i < k; i++)
01454 FREE(string[i]);
01455 FREE(string);
01456 FREE(indices);
01457 return(NULL);
01458 }
01459 saveString = ALLOC(char, size + 1);
01460 if (saveString == NULL) {
01461 dd->errorCode = CUDD_MEMORY_OUT;
01462 for (i = 0; i < k; i++)
01463 FREE(string[i]);
01464 FREE(string);
01465 FREE(indices);
01466 FREE(old);
01467 return(NULL);
01468 }
01469 saveFlag = 0;
01470
01471
01472 for (i = 0; i < k; i++) {
01473 isSame = 0;
01474 if (!saveFlag) {
01475 for (j = i + 1; j < k; j++) {
01476 if (strcmp(string[i], string[j]) == 0) {
01477 savePoint = i;
01478 strcpy(saveString, string[i]);
01479 saveFlag = 1;
01480 break;
01481 }
01482 }
01483 } else {
01484 if (strcmp(string[i], saveString) == 0) {
01485 isSame = 1;
01486 } else {
01487 saveFlag = 0;
01488 for (j = i + 1; j < k; j++) {
01489 if (strcmp(string[i], string[j]) == 0) {
01490 savePoint = i;
01491 strcpy(saveString, string[i]);
01492 saveFlag = 1;
01493 break;
01494 }
01495 }
01496 }
01497 }
01498
01499 for (j = 0; j < n; j++) {
01500 if (string[i][indices[j]] == '2')
01501 string[i][indices[j]] =
01502 (char) ((Cudd_Random() & 0x20) ? '1' : '0');
01503 }
01504
01505 while (isSame) {
01506 isSame = 0;
01507 for (j = savePoint; j < i; j++) {
01508 if (strcmp(string[i], string[j]) == 0) {
01509 isSame = 1;
01510 break;
01511 }
01512 }
01513 if (isSame) {
01514 strcpy(string[i], saveString);
01515
01516 for (j = 0; j < n; j++) {
01517 if (string[i][indices[j]] == '2')
01518 string[i][indices[j]] =
01519 (char) ((Cudd_Random() & 0x20) ? '1' : '0');
01520 }
01521 }
01522 }
01523
01524 old[i] = Cudd_ReadOne(dd);
01525 cuddRef(old[i]);
01526
01527 for (j = 0; j < n; j++) {
01528 if (string[i][indices[j]] == '0') {
01529 neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j]));
01530 } else {
01531 neW = Cudd_bddAnd(dd,old[i],vars[j]);
01532 }
01533 if (neW == NULL) {
01534 FREE(saveString);
01535 for (l = 0; l < k; l++)
01536 FREE(string[l]);
01537 FREE(string);
01538 FREE(indices);
01539 for (l = 0; l <= i; l++)
01540 Cudd_RecursiveDeref(dd,old[l]);
01541 FREE(old);
01542 return(NULL);
01543 }
01544 cuddRef(neW);
01545 Cudd_RecursiveDeref(dd,old[i]);
01546 old[i] = neW;
01547 }
01548
01549
01550 if (!Cudd_bddLeq(dd,old[i],f)) {
01551 FREE(saveString);
01552 for (l = 0; l < k; l++)
01553 FREE(string[l]);
01554 FREE(string);
01555 FREE(indices);
01556 for (l = 0; l <= i; l++)
01557 Cudd_RecursiveDeref(dd,old[l]);
01558 FREE(old);
01559 return(NULL);
01560 }
01561 }
01562
01563 FREE(saveString);
01564 for (i = 0; i < k; i++) {
01565 cuddDeref(old[i]);
01566 FREE(string[i]);
01567 }
01568 FREE(string);
01569 FREE(indices);
01570 return(old);
01571
01572 }
01573
01574
01597 DdNode *
01598 Cudd_SubsetWithMaskVars(
01599 DdManager * dd ,
01600 DdNode * f ,
01601 DdNode ** vars ,
01602 int nvars ,
01603 DdNode ** maskVars ,
01604 int mvars )
01605 {
01606 double *weight;
01607 char *string;
01608 int i, size;
01609 int *indices, *mask;
01610 int result;
01611 DdNode *zero, *cube, *newCube, *subset;
01612 DdNode *cof;
01613
01614 DdNode *support;
01615 support = Cudd_Support(dd,f);
01616 cuddRef(support);
01617 Cudd_RecursiveDeref(dd,support);
01618
01619 zero = Cudd_Not(dd->one);
01620 size = dd->size;
01621
01622 weight = ALLOC(double,size);
01623 if (weight == NULL) {
01624 dd->errorCode = CUDD_MEMORY_OUT;
01625 return(NULL);
01626 }
01627 for (i = 0; i < size; i++) {
01628 weight[i] = 0.0;
01629 }
01630 for (i = 0; i < mvars; i++) {
01631 cof = Cudd_Cofactor(dd, f, maskVars[i]);
01632 cuddRef(cof);
01633 weight[i] = Cudd_CountMinterm(dd, cof, nvars);
01634 Cudd_RecursiveDeref(dd,cof);
01635
01636 cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i]));
01637 cuddRef(cof);
01638 weight[i] -= Cudd_CountMinterm(dd, cof, nvars);
01639 Cudd_RecursiveDeref(dd,cof);
01640 }
01641
01642 string = ALLOC(char, size + 1);
01643 if (string == NULL) {
01644 dd->errorCode = CUDD_MEMORY_OUT;
01645 FREE(weight);
01646 return(NULL);
01647 }
01648 mask = ALLOC(int, size);
01649 if (mask == NULL) {
01650 dd->errorCode = CUDD_MEMORY_OUT;
01651 FREE(weight);
01652 FREE(string);
01653 return(NULL);
01654 }
01655 for (i = 0; i < size; i++) {
01656 string[i] = '2';
01657 mask[i] = 0;
01658 }
01659 string[size] = '\0';
01660 indices = ALLOC(int,nvars);
01661 if (indices == NULL) {
01662 dd->errorCode = CUDD_MEMORY_OUT;
01663 FREE(weight);
01664 FREE(string);
01665 FREE(mask);
01666 return(NULL);
01667 }
01668 for (i = 0; i < nvars; i++) {
01669 indices[i] = vars[i]->index;
01670 }
01671
01672 result = ddPickRepresentativeCube(dd,f,weight,string);
01673 if (result == 0) {
01674 FREE(weight);
01675 FREE(string);
01676 FREE(mask);
01677 FREE(indices);
01678 return(NULL);
01679 }
01680
01681 cube = Cudd_ReadOne(dd);
01682 cuddRef(cube);
01683 zero = Cudd_Not(Cudd_ReadOne(dd));
01684 for (i = 0; i < nvars; i++) {
01685 if (string[indices[i]] == '0') {
01686 newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
01687 } else if (string[indices[i]] == '1') {
01688 newCube = Cudd_bddIte(dd,cube,vars[i],zero);
01689 } else
01690 continue;
01691 if (newCube == NULL) {
01692 FREE(weight);
01693 FREE(string);
01694 FREE(mask);
01695 FREE(indices);
01696 Cudd_RecursiveDeref(dd,cube);
01697 return(NULL);
01698 }
01699 cuddRef(newCube);
01700 Cudd_RecursiveDeref(dd,cube);
01701 cube = newCube;
01702 }
01703 Cudd_RecursiveDeref(dd,cube);
01704
01705 for (i = 0; i < mvars; i++) {
01706 mask[maskVars[i]->index] = 1;
01707 }
01708 for (i = 0; i < nvars; i++) {
01709 if (mask[indices[i]]) {
01710 if (string[indices[i]] == '2') {
01711 if (weight[indices[i]] >= 0.0)
01712 string[indices[i]] = '1';
01713 else
01714 string[indices[i]] = '0';
01715 }
01716 } else {
01717 string[indices[i]] = '2';
01718 }
01719 }
01720
01721 cube = Cudd_ReadOne(dd);
01722 cuddRef(cube);
01723 zero = Cudd_Not(Cudd_ReadOne(dd));
01724
01725
01726 for (i = 0; i < nvars; i++) {
01727 if (string[indices[i]] == '0') {
01728 newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
01729 } else if (string[indices[i]] == '1') {
01730 newCube = Cudd_bddIte(dd,cube,vars[i],zero);
01731 } else
01732 continue;
01733 if (newCube == NULL) {
01734 FREE(weight);
01735 FREE(string);
01736 FREE(mask);
01737 FREE(indices);
01738 Cudd_RecursiveDeref(dd,cube);
01739 return(NULL);
01740 }
01741 cuddRef(newCube);
01742 Cudd_RecursiveDeref(dd,cube);
01743 cube = newCube;
01744 }
01745
01746 subset = Cudd_bddAnd(dd,f,cube);
01747 cuddRef(subset);
01748 Cudd_RecursiveDeref(dd,cube);
01749
01750
01751 if (Cudd_bddLeq(dd,subset,f)) {
01752 cuddDeref(subset);
01753 } else {
01754 Cudd_RecursiveDeref(dd,subset);
01755 subset = NULL;
01756 }
01757
01758 FREE(weight);
01759 FREE(string);
01760 FREE(mask);
01761 FREE(indices);
01762 return(subset);
01763
01764 }
01765
01766
01793 DdGen *
01794 Cudd_FirstCube(
01795 DdManager * dd,
01796 DdNode * f,
01797 int ** cube,
01798 CUDD_VALUE_TYPE * value)
01799 {
01800 DdGen *gen;
01801 DdNode *top, *treg, *next, *nreg, *prev, *preg;
01802 int i;
01803 int nvars;
01804
01805
01806 if (dd == NULL || f == NULL) return(NULL);
01807
01808
01809 gen = ALLOC(DdGen,1);
01810 if (gen == NULL) {
01811 dd->errorCode = CUDD_MEMORY_OUT;
01812 return(NULL);
01813 }
01814
01815 gen->manager = dd;
01816 gen->type = CUDD_GEN_CUBES;
01817 gen->status = CUDD_GEN_EMPTY;
01818 gen->gen.cubes.cube = NULL;
01819 gen->gen.cubes.value = DD_ZERO_VAL;
01820 gen->stack.sp = 0;
01821 gen->stack.stack = NULL;
01822 gen->node = NULL;
01823
01824 nvars = dd->size;
01825 gen->gen.cubes.cube = ALLOC(int,nvars);
01826 if (gen->gen.cubes.cube == NULL) {
01827 dd->errorCode = CUDD_MEMORY_OUT;
01828 FREE(gen);
01829 return(NULL);
01830 }
01831 for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
01832
01833
01834
01835
01836
01837 gen->stack.stack = ALLOC(DdNodePtr, nvars+1);
01838 if (gen->stack.stack == NULL) {
01839 dd->errorCode = CUDD_MEMORY_OUT;
01840 FREE(gen->gen.cubes.cube);
01841 FREE(gen);
01842 return(NULL);
01843 }
01844 for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
01845
01846
01847 gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
01848
01849 while (1) {
01850 top = gen->stack.stack[gen->stack.sp-1];
01851 treg = Cudd_Regular(top);
01852 if (!cuddIsConstant(treg)) {
01853
01854 gen->gen.cubes.cube[treg->index] = 0;
01855 next = cuddE(treg);
01856 if (top != treg) next = Cudd_Not(next);
01857 gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
01858 } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
01859
01860 while (1) {
01861 if (gen->stack.sp == 1) {
01862
01863 gen->status = CUDD_GEN_EMPTY;
01864 gen->stack.sp--;
01865 goto done;
01866 }
01867 prev = gen->stack.stack[gen->stack.sp-2];
01868 preg = Cudd_Regular(prev);
01869 nreg = cuddT(preg);
01870 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
01871 if (next != top) {
01872 gen->gen.cubes.cube[preg->index] = 1;
01873 gen->stack.stack[gen->stack.sp-1] = next;
01874 break;
01875 }
01876
01877 gen->gen.cubes.cube[preg->index] = 2;
01878 gen->stack.sp--;
01879 top = gen->stack.stack[gen->stack.sp-1];
01880 treg = Cudd_Regular(top);
01881 }
01882 } else {
01883 gen->status = CUDD_GEN_NONEMPTY;
01884 gen->gen.cubes.value = cuddV(top);
01885 goto done;
01886 }
01887 }
01888
01889 done:
01890 *cube = gen->gen.cubes.cube;
01891 *value = gen->gen.cubes.value;
01892 return(gen);
01893
01894 }
01895
01896
01912 int
01913 Cudd_NextCube(
01914 DdGen * gen,
01915 int ** cube,
01916 CUDD_VALUE_TYPE * value)
01917 {
01918 DdNode *top, *treg, *next, *nreg, *prev, *preg;
01919 DdManager *dd = gen->manager;
01920
01921
01922 while (1) {
01923 if (gen->stack.sp == 1) {
01924
01925 gen->status = CUDD_GEN_EMPTY;
01926 gen->stack.sp--;
01927 goto done;
01928 }
01929 top = gen->stack.stack[gen->stack.sp-1];
01930 treg = Cudd_Regular(top);
01931 prev = gen->stack.stack[gen->stack.sp-2];
01932 preg = Cudd_Regular(prev);
01933 nreg = cuddT(preg);
01934 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
01935 if (next != top) {
01936 gen->gen.cubes.cube[preg->index] = 1;
01937 gen->stack.stack[gen->stack.sp-1] = next;
01938 break;
01939 }
01940
01941 gen->gen.cubes.cube[preg->index] = 2;
01942 gen->stack.sp--;
01943 }
01944
01945 while (1) {
01946 top = gen->stack.stack[gen->stack.sp-1];
01947 treg = Cudd_Regular(top);
01948 if (!cuddIsConstant(treg)) {
01949
01950 gen->gen.cubes.cube[treg->index] = 0;
01951 next = cuddE(treg);
01952 if (top != treg) next = Cudd_Not(next);
01953 gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
01954 } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
01955
01956 while (1) {
01957 if (gen->stack.sp == 1) {
01958
01959 gen->status = CUDD_GEN_EMPTY;
01960 gen->stack.sp--;
01961 goto done;
01962 }
01963 prev = gen->stack.stack[gen->stack.sp-2];
01964 preg = Cudd_Regular(prev);
01965 nreg = cuddT(preg);
01966 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
01967 if (next != top) {
01968 gen->gen.cubes.cube[preg->index] = 1;
01969 gen->stack.stack[gen->stack.sp-1] = next;
01970 break;
01971 }
01972
01973 gen->gen.cubes.cube[preg->index] = 2;
01974 gen->stack.sp--;
01975 top = gen->stack.stack[gen->stack.sp-1];
01976 treg = Cudd_Regular(top);
01977 }
01978 } else {
01979 gen->status = CUDD_GEN_NONEMPTY;
01980 gen->gen.cubes.value = cuddV(top);
01981 goto done;
01982 }
01983 }
01984
01985 done:
01986 if (gen->status == CUDD_GEN_EMPTY) return(0);
01987 *cube = gen->gen.cubes.cube;
01988 *value = gen->gen.cubes.value;
01989 return(1);
01990
01991 }
01992
01993
02023 DdGen *
02024 Cudd_FirstPrime(
02025 DdManager *dd,
02026 DdNode *l,
02027 DdNode *u,
02028 int **cube)
02029 {
02030 DdGen *gen;
02031 DdNode *implicant, *prime, *tmp;
02032 int length, result;
02033
02034
02035 if (dd == NULL || l == NULL || u == NULL) return(NULL);
02036
02037
02038 gen = ALLOC(DdGen,1);
02039 if (gen == NULL) {
02040 dd->errorCode = CUDD_MEMORY_OUT;
02041 return(NULL);
02042 }
02043
02044 gen->manager = dd;
02045 gen->type = CUDD_GEN_PRIMES;
02046 gen->status = CUDD_GEN_EMPTY;
02047 gen->gen.primes.cube = NULL;
02048 gen->gen.primes.ub = u;
02049 gen->stack.sp = 0;
02050 gen->stack.stack = NULL;
02051 gen->node = l;
02052 cuddRef(l);
02053
02054 gen->gen.primes.cube = ALLOC(int,dd->size);
02055 if (gen->gen.primes.cube == NULL) {
02056 dd->errorCode = CUDD_MEMORY_OUT;
02057 FREE(gen);
02058 return(NULL);
02059 }
02060
02061 if (gen->node == Cudd_ReadLogicZero(dd)) {
02062 gen->status = CUDD_GEN_EMPTY;
02063 } else {
02064 implicant = Cudd_LargestCube(dd,gen->node,&length);
02065 if (implicant == NULL) {
02066 Cudd_RecursiveDeref(dd,gen->node);
02067 FREE(gen->gen.primes.cube);
02068 FREE(gen);
02069 return(NULL);
02070 }
02071 cuddRef(implicant);
02072 prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
02073 if (prime == NULL) {
02074 Cudd_RecursiveDeref(dd,gen->node);
02075 Cudd_RecursiveDeref(dd,implicant);
02076 FREE(gen->gen.primes.cube);
02077 FREE(gen);
02078 return(NULL);
02079 }
02080 cuddRef(prime);
02081 Cudd_RecursiveDeref(dd,implicant);
02082 tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
02083 if (tmp == NULL) {
02084 Cudd_RecursiveDeref(dd,gen->node);
02085 Cudd_RecursiveDeref(dd,prime);
02086 FREE(gen->gen.primes.cube);
02087 FREE(gen);
02088 return(NULL);
02089 }
02090 cuddRef(tmp);
02091 Cudd_RecursiveDeref(dd,gen->node);
02092 gen->node = tmp;
02093 result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
02094 if (result == 0) {
02095 Cudd_RecursiveDeref(dd,gen->node);
02096 Cudd_RecursiveDeref(dd,prime);
02097 FREE(gen->gen.primes.cube);
02098 FREE(gen);
02099 return(NULL);
02100 }
02101 Cudd_RecursiveDeref(dd,prime);
02102 gen->status = CUDD_GEN_NONEMPTY;
02103 }
02104 *cube = gen->gen.primes.cube;
02105 return(gen);
02106
02107 }
02108
02109
02125 int
02126 Cudd_NextPrime(
02127 DdGen *gen,
02128 int **cube)
02129 {
02130 DdNode *implicant, *prime, *tmp;
02131 DdManager *dd = gen->manager;
02132 int length, result;
02133
02134 if (gen->node == Cudd_ReadLogicZero(dd)) {
02135 gen->status = CUDD_GEN_EMPTY;
02136 } else {
02137 implicant = Cudd_LargestCube(dd,gen->node,&length);
02138 if (implicant == NULL) {
02139 gen->status = CUDD_GEN_EMPTY;
02140 return(0);
02141 }
02142 cuddRef(implicant);
02143 prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
02144 if (prime == NULL) {
02145 Cudd_RecursiveDeref(dd,implicant);
02146 gen->status = CUDD_GEN_EMPTY;
02147 return(0);
02148 }
02149 cuddRef(prime);
02150 Cudd_RecursiveDeref(dd,implicant);
02151 tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
02152 if (tmp == NULL) {
02153 Cudd_RecursiveDeref(dd,prime);
02154 gen->status = CUDD_GEN_EMPTY;
02155 return(0);
02156 }
02157 cuddRef(tmp);
02158 Cudd_RecursiveDeref(dd,gen->node);
02159 gen->node = tmp;
02160 result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
02161 if (result == 0) {
02162 Cudd_RecursiveDeref(dd,prime);
02163 gen->status = CUDD_GEN_EMPTY;
02164 return(0);
02165 }
02166 Cudd_RecursiveDeref(dd,prime);
02167 gen->status = CUDD_GEN_NONEMPTY;
02168 }
02169 if (gen->status == CUDD_GEN_EMPTY) return(0);
02170 *cube = gen->gen.primes.cube;
02171 return(1);
02172
02173 }
02174
02175
02191 DdNode *
02192 Cudd_bddComputeCube(
02193 DdManager * dd,
02194 DdNode ** vars,
02195 int * phase,
02196 int n)
02197 {
02198 DdNode *cube;
02199 DdNode *fn;
02200 int i;
02201
02202 cube = DD_ONE(dd);
02203 cuddRef(cube);
02204
02205 for (i = n - 1; i >= 0; i--) {
02206 if (phase == NULL || phase[i] != 0) {
02207 fn = Cudd_bddAnd(dd,vars[i],cube);
02208 } else {
02209 fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube);
02210 }
02211 if (fn == NULL) {
02212 Cudd_RecursiveDeref(dd,cube);
02213 return(NULL);
02214 }
02215 cuddRef(fn);
02216 Cudd_RecursiveDeref(dd,cube);
02217 cube = fn;
02218 }
02219 cuddDeref(cube);
02220
02221 return(cube);
02222
02223 }
02224
02225
02241 DdNode *
02242 Cudd_addComputeCube(
02243 DdManager * dd,
02244 DdNode ** vars,
02245 int * phase,
02246 int n)
02247 {
02248 DdNode *cube, *zero;
02249 DdNode *fn;
02250 int i;
02251
02252 cube = DD_ONE(dd);
02253 cuddRef(cube);
02254 zero = DD_ZERO(dd);
02255
02256 for (i = n - 1; i >= 0; i--) {
02257 if (phase == NULL || phase[i] != 0) {
02258 fn = Cudd_addIte(dd,vars[i],cube,zero);
02259 } else {
02260 fn = Cudd_addIte(dd,vars[i],zero,cube);
02261 }
02262 if (fn == NULL) {
02263 Cudd_RecursiveDeref(dd,cube);
02264 return(NULL);
02265 }
02266 cuddRef(fn);
02267 Cudd_RecursiveDeref(dd,cube);
02268 cube = fn;
02269 }
02270 cuddDeref(cube);
02271
02272 return(cube);
02273
02274 }
02275
02276
02293 DdNode *
02294 Cudd_CubeArrayToBdd(
02295 DdManager *dd,
02296 int *array)
02297 {
02298 DdNode *cube, *var, *tmp;
02299 int i;
02300 int size = Cudd_ReadSize(dd);
02301
02302 cube = DD_ONE(dd);
02303 cuddRef(cube);
02304 for (i = size - 1; i >= 0; i--) {
02305 if ((array[i] & ~1) == 0) {
02306 var = Cudd_bddIthVar(dd,i);
02307 tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0));
02308 if (tmp == NULL) {
02309 Cudd_RecursiveDeref(dd,cube);
02310 return(NULL);
02311 }
02312 cuddRef(tmp);
02313 Cudd_RecursiveDeref(dd,cube);
02314 cube = tmp;
02315 }
02316 }
02317 cuddDeref(cube);
02318 return(cube);
02319
02320 }
02321
02322
02341 int
02342 Cudd_BddToCubeArray(
02343 DdManager *dd,
02344 DdNode *cube,
02345 int *array)
02346 {
02347 DdNode *scan, *t, *e;
02348 int i;
02349 int size = Cudd_ReadSize(dd);
02350 DdNode *zero = Cudd_Not(DD_ONE(dd));
02351
02352 for (i = size-1; i >= 0; i--) {
02353 array[i] = 2;
02354 }
02355 scan = cube;
02356 while (!Cudd_IsConstant(scan)) {
02357 int index = Cudd_Regular(scan)->index;
02358 cuddGetBranches(scan,&t,&e);
02359 if (t == zero) {
02360 array[index] = 0;
02361 scan = e;
02362 } else if (e == zero) {
02363 array[index] = 1;
02364 scan = t;
02365 } else {
02366 return(0);
02367 }
02368 }
02369 if (scan == zero) {
02370 return(0);
02371 } else {
02372 return(1);
02373 }
02374
02375 }
02376
02377
02395 DdGen *
02396 Cudd_FirstNode(
02397 DdManager * dd,
02398 DdNode * f,
02399 DdNode ** node)
02400 {
02401 DdGen *gen;
02402 int size;
02403
02404
02405 if (dd == NULL || f == NULL) return(NULL);
02406
02407
02408 gen = ALLOC(DdGen,1);
02409 if (gen == NULL) {
02410 dd->errorCode = CUDD_MEMORY_OUT;
02411 return(NULL);
02412 }
02413
02414 gen->manager = dd;
02415 gen->type = CUDD_GEN_NODES;
02416 gen->status = CUDD_GEN_EMPTY;
02417 gen->stack.sp = 0;
02418 gen->node = NULL;
02419
02420
02421 gen->stack.stack = cuddNodeArray(Cudd_Regular(f), &size);
02422 if (gen->stack.stack == NULL) {
02423 FREE(gen);
02424 dd->errorCode = CUDD_MEMORY_OUT;
02425 return(NULL);
02426 }
02427 gen->gen.nodes.size = size;
02428
02429
02430 if (gen->stack.sp < gen->gen.nodes.size) {
02431 gen->status = CUDD_GEN_NONEMPTY;
02432 gen->node = gen->stack.stack[gen->stack.sp];
02433 *node = gen->node;
02434 }
02435
02436 return(gen);
02437
02438 }
02439
02440
02454 int
02455 Cudd_NextNode(
02456 DdGen * gen,
02457 DdNode ** node)
02458 {
02459
02460 gen->stack.sp++;
02461 if (gen->stack.sp < gen->gen.nodes.size) {
02462 gen->node = gen->stack.stack[gen->stack.sp];
02463 *node = gen->node;
02464 return(1);
02465 } else {
02466 gen->status = CUDD_GEN_EMPTY;
02467 return(0);
02468 }
02469
02470 }
02471
02472
02486 int
02487 Cudd_GenFree(
02488 DdGen * gen)
02489 {
02490 if (gen == NULL) return(0);
02491 switch (gen->type) {
02492 case CUDD_GEN_CUBES:
02493 case CUDD_GEN_ZDD_PATHS:
02494 FREE(gen->gen.cubes.cube);
02495 FREE(gen->stack.stack);
02496 break;
02497 case CUDD_GEN_PRIMES:
02498 FREE(gen->gen.primes.cube);
02499 Cudd_RecursiveDeref(gen->manager,gen->node);
02500 break;
02501 case CUDD_GEN_NODES:
02502 FREE(gen->stack.stack);
02503 break;
02504 default:
02505 return(0);
02506 }
02507 FREE(gen);
02508 return(0);
02509
02510 }
02511
02512
02526 int
02527 Cudd_IsGenEmpty(
02528 DdGen * gen)
02529 {
02530 if (gen == NULL) return(1);
02531 return(gen->status == CUDD_GEN_EMPTY);
02532
02533 }
02534
02535
02548 DdNode *
02549 Cudd_IndicesToCube(
02550 DdManager * dd,
02551 int * array,
02552 int n)
02553 {
02554 DdNode *cube, *tmp;
02555 int i;
02556
02557 cube = DD_ONE(dd);
02558 cuddRef(cube);
02559 for (i = n - 1; i >= 0; i--) {
02560 tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube);
02561 if (tmp == NULL) {
02562 Cudd_RecursiveDeref(dd,cube);
02563 return(NULL);
02564 }
02565 cuddRef(tmp);
02566 Cudd_RecursiveDeref(dd,cube);
02567 cube = tmp;
02568 }
02569
02570 cuddDeref(cube);
02571 return(cube);
02572
02573 }
02574
02575
02587 void
02588 Cudd_PrintVersion(
02589 FILE * fp)
02590 {
02591 (void) fprintf(fp, "%s\n", CUDD_VERSION);
02592
02593 }
02594
02595
02609 double
02610 Cudd_AverageDistance(
02611 DdManager * dd)
02612 {
02613 double tetotal, nexttotal;
02614 double tesubtotal, nextsubtotal;
02615 double temeasured, nextmeasured;
02616 int i, j;
02617 int slots, nvars;
02618 long diff;
02619 DdNode *scan;
02620 DdNodePtr *nodelist;
02621 DdNode *sentinel = &(dd->sentinel);
02622
02623 nvars = dd->size;
02624 if (nvars == 0) return(0.0);
02625
02626
02627 tetotal = 0.0;
02628 nexttotal = 0.0;
02629 temeasured = 0.0;
02630 nextmeasured = 0.0;
02631
02632
02633 for (i = 0; i < nvars; i++) {
02634 nodelist = dd->subtables[i].nodelist;
02635 tesubtotal = 0.0;
02636 nextsubtotal = 0.0;
02637 slots = dd->subtables[i].slots;
02638 for (j = 0; j < slots; j++) {
02639 scan = nodelist[j];
02640 while (scan != sentinel) {
02641 diff = (long) scan - (long) cuddT(scan);
02642 tesubtotal += (double) ddAbs(diff);
02643 diff = (long) scan - (long) Cudd_Regular(cuddE(scan));
02644 tesubtotal += (double) ddAbs(diff);
02645 temeasured += 2.0;
02646 if (scan->next != sentinel) {
02647 diff = (long) scan - (long) scan->next;
02648 nextsubtotal += (double) ddAbs(diff);
02649 nextmeasured += 1.0;
02650 }
02651 scan = scan->next;
02652 }
02653 }
02654 tetotal += tesubtotal;
02655 nexttotal += nextsubtotal;
02656 }
02657
02658
02659 nodelist = dd->constants.nodelist;
02660 nextsubtotal = 0.0;
02661 slots = dd->constants.slots;
02662 for (j = 0; j < slots; j++) {
02663 scan = nodelist[j];
02664 while (scan != NULL) {
02665 if (scan->next != NULL) {
02666 diff = (long) scan - (long) scan->next;
02667 nextsubtotal += (double) ddAbs(diff);
02668 nextmeasured += 1.0;
02669 }
02670 scan = scan->next;
02671 }
02672 }
02673 nexttotal += nextsubtotal;
02674
02675 return((tetotal + nexttotal) / (temeasured + nextmeasured));
02676
02677 }
02678
02679
02697 long
02698 Cudd_Random(void)
02699 {
02700 int i;
02701 long int w;
02702
02703
02704 if (cuddRand == 0) Cudd_Srandom(1);
02705
02706
02707
02708
02709 w = cuddRand / LEQQ1;
02710 cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
02711 cuddRand += (cuddRand < 0) * MODULUS1;
02712
02713
02714
02715
02716 w = cuddRand2 / LEQQ2;
02717 cuddRand2 = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2;
02718 cuddRand2 += (cuddRand2 < 0) * MODULUS2;
02719
02720
02721
02722
02723
02724
02725
02726
02727 i = (int) (shuffleSelect / STAB_DIV);
02728
02729
02730
02731
02732 shuffleSelect = shuffleTable[i] - cuddRand2;
02733 shuffleTable[i] = cuddRand;
02734 shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1);
02735
02736
02737
02738 return(shuffleSelect - 1);
02739
02740 }
02741
02742
02759 void
02760 Cudd_Srandom(
02761 long seed)
02762 {
02763 int i;
02764
02765 if (seed < 0) cuddRand = -seed;
02766 else if (seed == 0) cuddRand = 1;
02767 else cuddRand = seed;
02768 cuddRand2 = cuddRand;
02769
02770 for (i = 0; i < STAB_SIZE + 11; i++) {
02771 long int w;
02772 w = cuddRand / LEQQ1;
02773 cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
02774 cuddRand += (cuddRand < 0) * MODULUS1;
02775 shuffleTable[i % STAB_SIZE] = cuddRand;
02776 }
02777 shuffleSelect = shuffleTable[1 % STAB_SIZE];
02778
02779 }
02780
02781
02797 double
02798 Cudd_Density(
02799 DdManager * dd ,
02800 DdNode * f ,
02801 int nvars )
02802 {
02803 double minterms;
02804 int nodes;
02805 double density;
02806
02807 if (nvars == 0) nvars = dd->size;
02808 minterms = Cudd_CountMinterm(dd,f,nvars);
02809 if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms);
02810 nodes = Cudd_DagSize(f);
02811 density = minterms / (double) nodes;
02812 return(density);
02813
02814 }
02815
02816
02832 void
02833 Cudd_OutOfMem(
02834 long size )
02835 {
02836 (void) fflush(stdout);
02837 (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size);
02838 return;
02839
02840 }
02841
02842
02843
02844
02845
02846
02847
02861 int
02862 cuddP(
02863 DdManager * dd,
02864 DdNode * f)
02865 {
02866 int retval;
02867 st_table *table = st_init_table(st_ptrcmp,st_ptrhash);
02868
02869 if (table == NULL) return(0);
02870
02871 retval = dp2(dd,f,table);
02872 st_free_table(table);
02873 (void) fputc('\n',dd->out);
02874 return(retval);
02875
02876 }
02877
02878
02890 enum st_retval
02891 cuddStCountfree(
02892 char * key,
02893 char * value,
02894 char * arg)
02895 {
02896 double *d;
02897
02898 d = (double *)value;
02899 FREE(d);
02900 return(ST_CONTINUE);
02901
02902 }
02903
02904
02920 int
02921 cuddCollectNodes(
02922 DdNode * f,
02923 st_table * visited)
02924 {
02925 DdNode *T, *E;
02926 int retval;
02927
02928 #ifdef DD_DEBUG
02929 assert(!Cudd_IsComplement(f));
02930 #endif
02931
02932
02933 if (st_is_member(visited, (char *) f) == 1)
02934 return(1);
02935
02936
02937 if (f == NULL)
02938 return(0);
02939
02940
02941 if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
02942 return(0);
02943
02944
02945 if (cuddIsConstant(f))
02946 return(1);
02947
02948
02949 T = cuddT(f);
02950 retval = cuddCollectNodes(T,visited);
02951 if (retval != 1) return(retval);
02952 E = Cudd_Regular(cuddE(f));
02953 retval = cuddCollectNodes(E,visited);
02954 return(retval);
02955
02956 }
02957
02958
02974 DdNodePtr *
02975 cuddNodeArray(
02976 DdNode *f,
02977 int *n)
02978 {
02979 DdNodePtr *table;
02980 int size, retval;
02981
02982 size = ddDagInt(Cudd_Regular(f));
02983 table = ALLOC(DdNodePtr, size);
02984 if (table == NULL) {
02985 ddClearFlag(Cudd_Regular(f));
02986 return(NULL);
02987 }
02988
02989 retval = cuddNodeArrayRecur(f, table, 0);
02990 assert(retval == size);
02991
02992 *n = size;
02993 return(table);
02994
02995 }
02996
02997
02998
02999
03000
03001
03002
03013 static int
03014 dp2(
03015 DdManager *dd,
03016 DdNode * f,
03017 st_table * t)
03018 {
03019 DdNode *g, *n, *N;
03020 int T,E;
03021
03022 if (f == NULL) {
03023 return(0);
03024 }
03025 g = Cudd_Regular(f);
03026 if (cuddIsConstant(g)) {
03027 #if SIZEOF_VOID_P == 8
03028 (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f),
03029 (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
03030 #else
03031 (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f),
03032 (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
03033 #endif
03034 return(1);
03035 }
03036 if (st_is_member(t,(char *) g) == 1) {
03037 return(1);
03038 }
03039 if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM)
03040 return(0);
03041 #ifdef DD_STATS
03042 #if SIZEOF_VOID_P == 8
03043 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f),
03044 (ptruint) g / (ptruint) sizeof(DdNode), g->index, g->ref);
03045 #else
03046 (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f),
03047 (ptruint) g / (ptruint) sizeof(DdNode),g->index,g->ref);
03048 #endif
03049 #else
03050 #if SIZEOF_VOID_P == 8
03051 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %u\t", bang(f),
03052 (ptruint) g / (ptruint) sizeof(DdNode),g->index);
03053 #else
03054 (void) fprintf(dd->out,"ID = %c0x%x\tindex = %hu\t", bang(f),
03055 (ptruint) g / (ptruint) sizeof(DdNode),g->index);
03056 #endif
03057 #endif
03058 n = cuddT(g);
03059 if (cuddIsConstant(n)) {
03060 (void) fprintf(dd->out,"T = %-9g\t",cuddV(n));
03061 T = 1;
03062 } else {
03063 #if SIZEOF_VOID_P == 8
03064 (void) fprintf(dd->out,"T = 0x%lx\t",(ptruint) n / (ptruint) sizeof(DdNode));
03065 #else
03066 (void) fprintf(dd->out,"T = 0x%x\t",(ptruint) n / (ptruint) sizeof(DdNode));
03067 #endif
03068 T = 0;
03069 }
03070
03071 n = cuddE(g);
03072 N = Cudd_Regular(n);
03073 if (cuddIsConstant(N)) {
03074 (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N));
03075 E = 1;
03076 } else {
03077 #if SIZEOF_VOID_P == 8
03078 (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
03079 #else
03080 (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
03081 #endif
03082 E = 0;
03083 }
03084 if (E == 0) {
03085 if (dp2(dd,N,t) == 0)
03086 return(0);
03087 }
03088 if (T == 0) {
03089 if (dp2(dd,cuddT(g),t) == 0)
03090 return(0);
03091 }
03092 return(1);
03093
03094 }
03095
03096
03106 static void
03107 ddPrintMintermAux(
03108 DdManager * dd ,
03109 DdNode * node ,
03110 int * list )
03111 {
03112 DdNode *N,*Nv,*Nnv;
03113 int i,v,index;
03114
03115 N = Cudd_Regular(node);
03116
03117 if (cuddIsConstant(N)) {
03118
03119
03120
03121
03122 if (node != background && node != zero) {
03123 for (i = 0; i < dd->size; i++) {
03124 v = list[i];
03125 if (v == 0) (void) fprintf(dd->out,"0");
03126 else if (v == 1) (void) fprintf(dd->out,"1");
03127 else (void) fprintf(dd->out,"-");
03128 }
03129 (void) fprintf(dd->out," % g\n", cuddV(node));
03130 }
03131 } else {
03132 Nv = cuddT(N);
03133 Nnv = cuddE(N);
03134 if (Cudd_IsComplement(node)) {
03135 Nv = Cudd_Not(Nv);
03136 Nnv = Cudd_Not(Nnv);
03137 }
03138 index = N->index;
03139 list[index] = 0;
03140 ddPrintMintermAux(dd,Nnv,list);
03141 list[index] = 1;
03142 ddPrintMintermAux(dd,Nv,list);
03143 list[index] = 2;
03144 }
03145 return;
03146
03147 }
03148
03149
03160 static int
03161 ddDagInt(
03162 DdNode * n)
03163 {
03164 int tval, eval;
03165
03166 if (Cudd_IsComplement(n->next)) {
03167 return(0);
03168 }
03169 n->next = Cudd_Not(n->next);
03170 if (cuddIsConstant(n)) {
03171 return(1);
03172 }
03173 tval = ddDagInt(cuddT(n));
03174 eval = ddDagInt(Cudd_Regular(cuddE(n)));
03175 return(1 + tval + eval);
03176
03177 }
03178
03179
03195 static int
03196 cuddNodeArrayRecur(
03197 DdNode *f,
03198 DdNodePtr *table,
03199 int index)
03200 {
03201 int tindex, eindex;
03202
03203 if (!Cudd_IsComplement(f->next)) {
03204 return(index);
03205 }
03206
03207 f->next = Cudd_Regular(f->next);
03208 if (cuddIsConstant(f)) {
03209 table[index] = f;
03210 return(index + 1);
03211 }
03212 tindex = cuddNodeArrayRecur(cuddT(f), table, index);
03213 eindex = cuddNodeArrayRecur(Cudd_Regular(cuddE(f)), table, tindex);
03214 table[eindex] = f;
03215 return(eindex + 1);
03216
03217 }
03218
03219
03235 static int
03236 cuddEstimateCofactor(
03237 DdManager *dd,
03238 st_table *table,
03239 DdNode * node,
03240 int i,
03241 int phase,
03242 DdNode ** ptr)
03243 {
03244 int tval, eval, val;
03245 DdNode *ptrT, *ptrE;
03246
03247 if (Cudd_IsComplement(node->next)) {
03248 if (!st_lookup(table,(char *)node,(char **)ptr)) {
03249 if (st_add_direct(table,(char *)node,(char *)node) ==
03250 ST_OUT_OF_MEM)
03251 return(CUDD_OUT_OF_MEM);
03252 *ptr = node;
03253 }
03254 return(0);
03255 }
03256 node->next = Cudd_Not(node->next);
03257 if (cuddIsConstant(node)) {
03258 *ptr = node;
03259 if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM)
03260 return(CUDD_OUT_OF_MEM);
03261 return(1);
03262 }
03263 if ((int) node->index == i) {
03264 if (phase == 1) {
03265 *ptr = cuddT(node);
03266 val = ddDagInt(cuddT(node));
03267 } else {
03268 *ptr = cuddE(node);
03269 val = ddDagInt(Cudd_Regular(cuddE(node)));
03270 }
03271 if (node->ref > 1) {
03272 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
03273 ST_OUT_OF_MEM)
03274 return(CUDD_OUT_OF_MEM);
03275 }
03276 return(val);
03277 }
03278 if (dd->perm[node->index] > dd->perm[i]) {
03279 *ptr = node;
03280 tval = ddDagInt(cuddT(node));
03281 eval = ddDagInt(Cudd_Regular(cuddE(node)));
03282 if (node->ref > 1) {
03283 if (st_add_direct(table,(char *)node,(char *)node) ==
03284 ST_OUT_OF_MEM)
03285 return(CUDD_OUT_OF_MEM);
03286 }
03287 val = 1 + tval + eval;
03288 return(val);
03289 }
03290 tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT);
03291 eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i,
03292 phase,&ptrE);
03293 ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node)));
03294 if (ptrT == ptrE) {
03295 *ptr = ptrT;
03296 val = tval;
03297 if (node->ref > 1) {
03298 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
03299 ST_OUT_OF_MEM)
03300 return(CUDD_OUT_OF_MEM);
03301 }
03302 } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) &&
03303 (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) {
03304 if (Cudd_IsComplement((*ptr)->next)) {
03305 val = 0;
03306 } else {
03307 val = 1 + tval + eval;
03308 }
03309 if (node->ref > 1) {
03310 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
03311 ST_OUT_OF_MEM)
03312 return(CUDD_OUT_OF_MEM);
03313 }
03314 } else {
03315 *ptr = node;
03316 val = 1 + tval + eval;
03317 }
03318 return(val);
03319
03320 }
03321
03322
03335 static DdNode *
03336 cuddUniqueLookup(
03337 DdManager * unique,
03338 int index,
03339 DdNode * T,
03340 DdNode * E)
03341 {
03342 int posn;
03343 unsigned int level;
03344 DdNodePtr *nodelist;
03345 DdNode *looking;
03346 DdSubtable *subtable;
03347
03348 if (index >= unique->size) {
03349 return(NULL);
03350 }
03351
03352 level = unique->perm[index];
03353 subtable = &(unique->subtables[level]);
03354
03355 #ifdef DD_DEBUG
03356 assert(level < (unsigned) cuddI(unique,T->index));
03357 assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
03358 #endif
03359
03360 posn = ddHash(T, E, subtable->shift);
03361 nodelist = subtable->nodelist;
03362 looking = nodelist[posn];
03363
03364 while (T < cuddT(looking)) {
03365 looking = Cudd_Regular(looking->next);
03366 }
03367 while (T == cuddT(looking) && E < cuddE(looking)) {
03368 looking = Cudd_Regular(looking->next);
03369 }
03370 if (cuddT(looking) == T && cuddE(looking) == E) {
03371 return(looking);
03372 }
03373
03374 return(NULL);
03375
03376 }
03377
03378
03394 static int
03395 cuddEstimateCofactorSimple(
03396 DdNode * node,
03397 int i)
03398 {
03399 int tval, eval;
03400
03401 if (Cudd_IsComplement(node->next)) {
03402 return(0);
03403 }
03404 node->next = Cudd_Not(node->next);
03405 if (cuddIsConstant(node)) {
03406 return(1);
03407 }
03408 tval = cuddEstimateCofactorSimple(cuddT(node),i);
03409 if ((int) node->index == i) return(tval);
03410 eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i);
03411 return(1 + tval + eval);
03412
03413 }
03414
03415
03434 static double
03435 ddCountMintermAux(
03436 DdNode * node,
03437 double max,
03438 DdHashTable * table)
03439 {
03440 DdNode *N, *Nt, *Ne;
03441 double min, minT, minE;
03442 DdNode *res;
03443
03444 N = Cudd_Regular(node);
03445
03446 if (cuddIsConstant(N)) {
03447 if (node == background || node == zero) {
03448 return(0.0);
03449 } else {
03450 return(max);
03451 }
03452 }
03453 if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
03454 min = cuddV(res);
03455 if (res->ref == 0) {
03456 table->manager->dead++;
03457 table->manager->constants.dead++;
03458 }
03459 return(min);
03460 }
03461
03462 Nt = cuddT(N); Ne = cuddE(N);
03463 if (Cudd_IsComplement(node)) {
03464 Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
03465 }
03466
03467 minT = ddCountMintermAux(Nt,max,table);
03468 if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
03469 minT *= 0.5;
03470 minE = ddCountMintermAux(Ne,max,table);
03471 if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
03472 minE *= 0.5;
03473 min = minT + minE;
03474
03475 if (N->ref != 1) {
03476 ptrint fanout = (ptrint) N->ref;
03477 cuddSatDec(fanout);
03478 res = cuddUniqueConst(table->manager,min);
03479 if (!cuddHashTableInsert1(table,node,res,fanout)) {
03480 cuddRef(res); Cudd_RecursiveDeref(table->manager, res);
03481 return((double)CUDD_OUT_OF_MEM);
03482 }
03483 }
03484
03485 return(min);
03486
03487 }
03488
03489
03507 static double
03508 ddCountPathAux(
03509 DdNode * node,
03510 st_table * table)
03511 {
03512
03513 DdNode *Nv, *Nnv;
03514 double paths, *ppaths, paths1, paths2;
03515 double *dummy;
03516
03517
03518 if (cuddIsConstant(node)) {
03519 return(1.0);
03520 }
03521 if (st_lookup(table, node, &dummy)) {
03522 paths = *dummy;
03523 return(paths);
03524 }
03525
03526 Nv = cuddT(node); Nnv = cuddE(node);
03527
03528 paths1 = ddCountPathAux(Nv,table);
03529 if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
03530 paths2 = ddCountPathAux(Cudd_Regular(Nnv),table);
03531 if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
03532 paths = paths1 + paths2;
03533
03534 ppaths = ALLOC(double,1);
03535 if (ppaths == NULL) {
03536 return((double)CUDD_OUT_OF_MEM);
03537 }
03538
03539 *ppaths = paths;
03540
03541 if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) {
03542 FREE(ppaths);
03543 return((double)CUDD_OUT_OF_MEM);
03544 }
03545 return(paths);
03546
03547 }
03548
03549
03568 static int
03569 ddEpdCountMintermAux(
03570 DdNode * node,
03571 EpDouble * max,
03572 EpDouble * epd,
03573 st_table * table)
03574 {
03575 DdNode *Nt, *Ne;
03576 EpDouble *min, minT, minE;
03577 EpDouble *res;
03578 int status;
03579
03580
03581 if (cuddIsConstant(node)) {
03582 if (node == background || node == zero) {
03583 EpdMakeZero(epd, 0);
03584 } else {
03585 EpdCopy(max, epd);
03586 }
03587 return(0);
03588 }
03589 if (node->ref != 1 && st_lookup(table, node, &res)) {
03590 EpdCopy(res, epd);
03591 return(0);
03592 }
03593
03594 Nt = cuddT(node); Ne = cuddE(node);
03595
03596 status = ddEpdCountMintermAux(Nt,max,&minT,table);
03597 if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
03598 EpdMultiply(&minT, (double)0.5);
03599 status = ddEpdCountMintermAux(Cudd_Regular(Ne),max,&minE,table);
03600 if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
03601 if (Cudd_IsComplement(Ne)) {
03602 EpdSubtract3(max, &minE, epd);
03603 EpdCopy(epd, &minE);
03604 }
03605 EpdMultiply(&minE, (double)0.5);
03606 EpdAdd3(&minT, &minE, epd);
03607
03608 if (node->ref > 1) {
03609 min = EpdAlloc();
03610 if (!min)
03611 return(CUDD_OUT_OF_MEM);
03612 EpdCopy(epd, min);
03613 if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) {
03614 EpdFree(min);
03615 return(CUDD_OUT_OF_MEM);
03616 }
03617 }
03618
03619 return(0);
03620
03621 }
03622
03623
03640 static double
03641 ddCountPathsToNonZero(
03642 DdNode * N,
03643 st_table * table)
03644 {
03645
03646 DdNode *node, *Nt, *Ne;
03647 double paths, *ppaths, paths1, paths2;
03648 double *dummy;
03649
03650 node = Cudd_Regular(N);
03651 if (cuddIsConstant(node)) {
03652 return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL));
03653 }
03654 if (st_lookup(table, N, &dummy)) {
03655 paths = *dummy;
03656 return(paths);
03657 }
03658
03659 Nt = cuddT(node); Ne = cuddE(node);
03660 if (node != N) {
03661 Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
03662 }
03663
03664 paths1 = ddCountPathsToNonZero(Nt,table);
03665 if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
03666 paths2 = ddCountPathsToNonZero(Ne,table);
03667 if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
03668 paths = paths1 + paths2;
03669
03670 ppaths = ALLOC(double,1);
03671 if (ppaths == NULL) {
03672 return((double)CUDD_OUT_OF_MEM);
03673 }
03674
03675 *ppaths = paths;
03676
03677 if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) {
03678 FREE(ppaths);
03679 return((double)CUDD_OUT_OF_MEM);
03680 }
03681 return(paths);
03682
03683 }
03684
03685
03699 static void
03700 ddSupportStep(
03701 DdNode * f,
03702 int * support)
03703 {
03704 if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
03705 return;
03706 }
03707
03708 support[f->index] = 1;
03709 ddSupportStep(cuddT(f),support);
03710 ddSupportStep(Cudd_Regular(cuddE(f)),support);
03711
03712 f->next = Cudd_Not(f->next);
03713 return;
03714
03715 }
03716
03717
03730 static void
03731 ddClearFlag(
03732 DdNode * f)
03733 {
03734 if (!Cudd_IsComplement(f->next)) {
03735 return;
03736 }
03737
03738 f->next = Cudd_Regular(f->next);
03739 if (cuddIsConstant(f)) {
03740 return;
03741 }
03742 ddClearFlag(cuddT(f));
03743 ddClearFlag(Cudd_Regular(cuddE(f)));
03744 return;
03745
03746 }
03747
03748
03761 static int
03762 ddLeavesInt(
03763 DdNode * n)
03764 {
03765 int tval, eval;
03766
03767 if (Cudd_IsComplement(n->next)) {
03768 return(0);
03769 }
03770 n->next = Cudd_Not(n->next);
03771 if (cuddIsConstant(n)) {
03772 return(1);
03773 }
03774 tval = ddLeavesInt(cuddT(n));
03775 eval = ddLeavesInt(Cudd_Regular(cuddE(n)));
03776 return(tval + eval);
03777
03778 }
03779
03780
03793 static int
03794 ddPickArbitraryMinterms(
03795 DdManager *dd,
03796 DdNode *node,
03797 int nvars,
03798 int nminterms,
03799 char **string)
03800 {
03801 DdNode *N, *T, *E;
03802 DdNode *one, *bzero;
03803 int i, t, result;
03804 double min1, min2;
03805
03806 if (string == NULL || node == NULL) return(0);
03807
03808
03809 one = DD_ONE(dd);
03810 bzero = Cudd_Not(one);
03811 if (nminterms == 0 || node == bzero) return(1);
03812 if (node == one) {
03813 return(1);
03814 }
03815
03816 N = Cudd_Regular(node);
03817 T = cuddT(N); E = cuddE(N);
03818 if (Cudd_IsComplement(node)) {
03819 T = Cudd_Not(T); E = Cudd_Not(E);
03820 }
03821
03822 min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0;
03823 if (min1 == (double)CUDD_OUT_OF_MEM) return(0);
03824 min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0;
03825 if (min2 == (double)CUDD_OUT_OF_MEM) return(0);
03826
03827 t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5);
03828 for (i = 0; i < t; i++)
03829 string[i][N->index] = '1';
03830 for (i = t; i < nminterms; i++)
03831 string[i][N->index] = '0';
03832
03833 result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]);
03834 if (result == 0)
03835 return(0);
03836 result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]);
03837 return(result);
03838
03839 }
03840
03841
03854 static int
03855 ddPickRepresentativeCube(
03856 DdManager *dd,
03857 DdNode *node,
03858 double *weight,
03859 char *string)
03860 {
03861 DdNode *N, *T, *E;
03862 DdNode *one, *bzero;
03863
03864 if (string == NULL || node == NULL) return(0);
03865
03866
03867 one = DD_ONE(dd);
03868 bzero = Cudd_Not(one);
03869 if (node == bzero) return(0);
03870
03871 if (node == DD_ONE(dd)) return(1);
03872
03873 for (;;) {
03874 N = Cudd_Regular(node);
03875 if (N == one)
03876 break;
03877 T = cuddT(N);
03878 E = cuddE(N);
03879 if (Cudd_IsComplement(node)) {
03880 T = Cudd_Not(T);
03881 E = Cudd_Not(E);
03882 }
03883 if (weight[N->index] >= 0.0) {
03884 if (T == bzero) {
03885 node = E;
03886 string[N->index] = '0';
03887 } else {
03888 node = T;
03889 string[N->index] = '1';
03890 }
03891 } else {
03892 if (E == bzero) {
03893 node = T;
03894 string[N->index] = '1';
03895 } else {
03896 node = E;
03897 string[N->index] = '0';
03898 }
03899 }
03900 }
03901 return(1);
03902
03903 }
03904
03905
03917 static enum st_retval
03918 ddEpdFree(
03919 char * key,
03920 char * value,
03921 char * arg)
03922 {
03923 EpDouble *epd;
03924
03925 epd = (EpDouble *) value;
03926 EpdFree(epd);
03927 return(ST_CONTINUE);
03928
03929 }