00001
00071 #ifdef __STDC__
00072 #include <float.h>
00073 #else
00074 #define DBL_MAX_EXP 1024
00075 #endif
00076 #include "util.h"
00077 #include "cuddInt.h"
00078
00079
00080
00081
00082
00083 #define DEFAULT_PAGE_SIZE 2048
00084 #define DEFAULT_NODE_DATA_PAGE_SIZE 1024
00085 #define INITIAL_PAGES 128
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 struct NodeData {
00100 double *mintermPointer;
00101 int *nodesPointer;
00102 int *lightChildNodesPointer;
00103 };
00104
00105
00106
00107
00108
00109 typedef struct NodeData NodeData_t;
00110
00111
00112
00113
00114
00115 #ifndef lint
00116 static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.37 2009/02/20 02:14:58 fabio Exp $";
00117 #endif
00118
00119 static int memOut;
00120 #ifdef DEBUG
00121 static int num_calls;
00122 #endif
00123
00124 static DdNode *zero, *one;
00125 static double **mintermPages;
00126 static int **nodePages;
00127 static int **lightNodePages;
00128 static double *currentMintermPage;
00129
00130 static double max;
00131
00132
00133 static int *currentNodePage;
00134
00135 static int *currentLightNodePage;
00136
00137 static int pageIndex;
00138 static int page;
00139 static int pageSize = DEFAULT_PAGE_SIZE;
00140 static int maxPages;
00141
00142 static NodeData_t *currentNodeDataPage;
00143
00144 static int nodeDataPage;
00145 static int nodeDataPageIndex;
00146 static NodeData_t **nodeDataPages;
00147 static int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE;
00148
00149 static int maxNodeDataPages;
00150
00151
00152
00153
00154
00155
00158
00159
00160
00161
00162 static void ResizeNodeDataPages (void);
00163 static void ResizeCountMintermPages (void);
00164 static void ResizeCountNodePages (void);
00165 static double SubsetCountMintermAux (DdNode *node, double max, st_table *table);
00166 static st_table * SubsetCountMinterm (DdNode *node, int nvars);
00167 static int SubsetCountNodesAux (DdNode *node, st_table *table, double max);
00168 static int SubsetCountNodes (DdNode *node, st_table *table, int nvars);
00169 static void StoreNodes (st_table *storeTable, DdManager *dd, DdNode *node);
00170 static DdNode * BuildSubsetBdd (DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable);
00171
00175
00176
00177
00178
00204 DdNode *
00205 Cudd_SubsetHeavyBranch(
00206 DdManager * dd ,
00207 DdNode * f ,
00208 int numVars ,
00209 int threshold )
00210 {
00211 DdNode *subset;
00212
00213 memOut = 0;
00214 do {
00215 dd->reordered = 0;
00216 subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold);
00217 } while ((dd->reordered == 1) && (!memOut));
00218
00219 return(subset);
00220
00221 }
00222
00223
00254 DdNode *
00255 Cudd_SupersetHeavyBranch(
00256 DdManager * dd ,
00257 DdNode * f ,
00258 int numVars ,
00259 int threshold )
00260 {
00261 DdNode *subset, *g;
00262
00263 g = Cudd_Not(f);
00264 memOut = 0;
00265 do {
00266 dd->reordered = 0;
00267 subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold);
00268 } while ((dd->reordered == 1) && (!memOut));
00269
00270 return(Cudd_NotCond(subset, (subset != NULL)));
00271
00272 }
00273
00274
00275
00276
00277
00278
00279
00300 DdNode *
00301 cuddSubsetHeavyBranch(
00302 DdManager * dd ,
00303 DdNode * f ,
00304 int numVars ,
00305 int threshold )
00306 {
00307
00308 int i, *size;
00309 st_table *visitedTable;
00310 int numNodes;
00311 NodeData_t *currNodeQual;
00312 DdNode *subset;
00313 st_table *storeTable, *approxTable;
00314 char *key, *value;
00315 st_generator *stGen;
00316
00317 if (f == NULL) {
00318 fprintf(dd->err, "Cannot subset, nil object\n");
00319 dd->errorCode = CUDD_INVALID_ARG;
00320 return(NULL);
00321 }
00322
00323 one = Cudd_ReadOne(dd);
00324 zero = Cudd_Not(one);
00325
00326
00327
00328
00329
00330
00331 if (numVars == 0) {
00332
00333 numVars = DBL_MAX_EXP - 1;
00334 }
00335
00336 if (Cudd_IsConstant(f)) {
00337 return(f);
00338 }
00339
00340 max = pow(2.0, (double)numVars);
00341
00342
00343
00344 visitedTable = SubsetCountMinterm(f, numVars);
00345 if ((visitedTable == NULL) || memOut) {
00346 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00347 dd->errorCode = CUDD_MEMORY_OUT;
00348 return(0);
00349 }
00350 numNodes = SubsetCountNodes(f, visitedTable, numVars);
00351 if (memOut) {
00352 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00353 dd->errorCode = CUDD_MEMORY_OUT;
00354 return(0);
00355 }
00356
00357 if (st_lookup(visitedTable, f, &currNodeQual) == 0) {
00358 fprintf(dd->err,
00359 "Something is wrong, ought to be node quality table\n");
00360 dd->errorCode = CUDD_INTERNAL_ERROR;
00361 }
00362
00363 size = ALLOC(int, 1);
00364 if (size == NULL) {
00365 dd->errorCode = CUDD_MEMORY_OUT;
00366 return(NULL);
00367 }
00368 *size = numNodes;
00369
00370 #ifdef DEBUG
00371 num_calls = 0;
00372 #endif
00373
00374 storeTable = st_init_table(st_ptrcmp, st_ptrhash);
00375
00376 cuddRef(one);
00377 if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) ==
00378 ST_OUT_OF_MEM) {
00379 fprintf(dd->out, "Something wrong, st_table insert failed\n");
00380 }
00381
00382 approxTable = st_init_table(st_ptrcmp, st_ptrhash);
00383 subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold,
00384 storeTable, approxTable);
00385 if (subset != NULL) {
00386 cuddRef(subset);
00387 }
00388
00389 stGen = st_init_gen(approxTable);
00390 if (stGen == NULL) {
00391 st_free_table(approxTable);
00392 return(NULL);
00393 }
00394 while(st_gen(stGen, (char **)&key, (char **)&value)) {
00395 Cudd_RecursiveDeref(dd, (DdNode *)value);
00396 }
00397 st_free_gen(stGen); stGen = NULL;
00398 st_free_table(approxTable);
00399
00400 stGen = st_init_gen(storeTable);
00401 if (stGen == NULL) {
00402 st_free_table(storeTable);
00403 return(NULL);
00404 }
00405 while(st_gen(stGen, (char **)&key, (char **)&value)) {
00406 Cudd_RecursiveDeref(dd, (DdNode *)key);
00407 }
00408 st_free_gen(stGen); stGen = NULL;
00409 st_free_table(storeTable);
00410
00411 for (i = 0; i <= page; i++) {
00412 FREE(mintermPages[i]);
00413 }
00414 FREE(mintermPages);
00415 for (i = 0; i <= page; i++) {
00416 FREE(nodePages[i]);
00417 }
00418 FREE(nodePages);
00419 for (i = 0; i <= page; i++) {
00420 FREE(lightNodePages[i]);
00421 }
00422 FREE(lightNodePages);
00423 for (i = 0; i <= nodeDataPage; i++) {
00424 FREE(nodeDataPages[i]);
00425 }
00426 FREE(nodeDataPages);
00427 st_free_table(visitedTable);
00428 FREE(size);
00429 #if 0
00430 (void) Cudd_DebugCheck(dd);
00431 (void) Cudd_CheckKeys(dd);
00432 #endif
00433
00434 if (subset != NULL) {
00435 #ifdef DD_DEBUG
00436 if (!Cudd_bddLeq(dd, subset, f)) {
00437 fprintf(dd->err, "Wrong subset\n");
00438 dd->errorCode = CUDD_INTERNAL_ERROR;
00439 return(NULL);
00440 }
00441 #endif
00442 cuddDeref(subset);
00443 return(subset);
00444 } else {
00445 return(NULL);
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454
00469 static void
00470 ResizeNodeDataPages(void)
00471 {
00472 int i;
00473 NodeData_t **newNodeDataPages;
00474
00475 nodeDataPage++;
00476
00477
00478
00479
00480 if (nodeDataPage == maxNodeDataPages) {
00481 newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES);
00482 if (newNodeDataPages == NULL) {
00483 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00484 FREE(nodeDataPages);
00485 memOut = 1;
00486 return;
00487 } else {
00488 for (i = 0; i < maxNodeDataPages; i++) {
00489 newNodeDataPages[i] = nodeDataPages[i];
00490 }
00491
00492 maxNodeDataPages += INITIAL_PAGES;
00493 FREE(nodeDataPages);
00494 nodeDataPages = newNodeDataPages;
00495 }
00496 }
00497
00498 currentNodeDataPage = nodeDataPages[nodeDataPage] =
00499 ALLOC(NodeData_t ,nodeDataPageSize);
00500 if (currentNodeDataPage == NULL) {
00501 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00502 FREE(nodeDataPages);
00503 memOut = 1;
00504 return;
00505 }
00506
00507 nodeDataPageIndex = 0;
00508 return;
00509
00510 }
00511
00512
00528 static void
00529 ResizeCountMintermPages(void)
00530 {
00531 int i;
00532 double **newMintermPages;
00533
00534 page++;
00535
00536
00537
00538
00539 if (page == maxPages) {
00540 newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES);
00541 if (newMintermPages == NULL) {
00542 for (i = 0; i < page; i++) FREE(mintermPages[i]);
00543 FREE(mintermPages);
00544 memOut = 1;
00545 return;
00546 } else {
00547 for (i = 0; i < maxPages; i++) {
00548 newMintermPages[i] = mintermPages[i];
00549 }
00550
00551 maxPages += INITIAL_PAGES;
00552 FREE(mintermPages);
00553 mintermPages = newMintermPages;
00554 }
00555 }
00556
00557 currentMintermPage = mintermPages[page] = ALLOC(double,pageSize);
00558 if (currentMintermPage == NULL) {
00559 for (i = 0; i < page; i++) FREE(mintermPages[i]);
00560 FREE(mintermPages);
00561 memOut = 1;
00562 return;
00563 }
00564
00565 pageIndex = 0;
00566 return;
00567
00568 }
00569
00570
00585 static void
00586 ResizeCountNodePages(void)
00587 {
00588 int i;
00589 int **newNodePages;
00590
00591 page++;
00592
00593
00594
00595
00596
00597 if (page == maxPages) {
00598 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00599 if (newNodePages == NULL) {
00600 for (i = 0; i < page; i++) FREE(nodePages[i]);
00601 FREE(nodePages);
00602 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00603 FREE(lightNodePages);
00604 memOut = 1;
00605 return;
00606 } else {
00607 for (i = 0; i < maxPages; i++) {
00608 newNodePages[i] = nodePages[i];
00609 }
00610 FREE(nodePages);
00611 nodePages = newNodePages;
00612 }
00613
00614 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00615 if (newNodePages == NULL) {
00616 for (i = 0; i < page; i++) FREE(nodePages[i]);
00617 FREE(nodePages);
00618 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00619 FREE(lightNodePages);
00620 memOut = 1;
00621 return;
00622 } else {
00623 for (i = 0; i < maxPages; i++) {
00624 newNodePages[i] = lightNodePages[i];
00625 }
00626 FREE(lightNodePages);
00627 lightNodePages = newNodePages;
00628 }
00629
00630 maxPages += INITIAL_PAGES;
00631 }
00632
00633 currentNodePage = nodePages[page] = ALLOC(int,pageSize);
00634 if (currentNodePage == NULL) {
00635 for (i = 0; i < page; i++) FREE(nodePages[i]);
00636 FREE(nodePages);
00637 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00638 FREE(lightNodePages);
00639 memOut = 1;
00640 return;
00641 }
00642
00643 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
00644 if (currentLightNodePage == NULL) {
00645 for (i = 0; i <= page; i++) FREE(nodePages[i]);
00646 FREE(nodePages);
00647 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00648 FREE(lightNodePages);
00649 memOut = 1;
00650 return;
00651 }
00652
00653 pageIndex = 0;
00654 return;
00655
00656 }
00657
00658
00675 static double
00676 SubsetCountMintermAux(
00677 DdNode * node ,
00678 double max ,
00679 st_table * table )
00680 {
00681
00682 DdNode *N,*Nv,*Nnv;
00683 double min,*pmin;
00684 double min1, min2;
00685 NodeData_t *dummy;
00686 NodeData_t *newEntry;
00687 int i;
00688
00689 #ifdef DEBUG
00690 num_calls++;
00691 #endif
00692
00693
00694 if (Cudd_IsConstant(node)) {
00695 if (node == zero) {
00696 return(0.0);
00697 } else {
00698 return(max);
00699 }
00700 } else {
00701
00702
00703 if (st_lookup(table, node, &dummy)) {
00704 min = *(dummy->mintermPointer);
00705 return(min);
00706 }
00707
00708
00709 N = Cudd_Regular(node);
00710
00711
00712 Nv = Cudd_T(N);
00713 Nnv = Cudd_E(N);
00714
00715 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00716 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00717
00718 min1 = SubsetCountMintermAux(Nv, max,table)/2.0;
00719 if (memOut) return(0.0);
00720 min2 = SubsetCountMintermAux(Nnv,max,table)/2.0;
00721 if (memOut) return(0.0);
00722 min = (min1+min2);
00723
00724
00725 if (pageIndex == pageSize) ResizeCountMintermPages();
00726 if (memOut) {
00727 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00728 FREE(nodeDataPages);
00729 st_free_table(table);
00730 return(0.0);
00731 }
00732
00733
00734 pmin = currentMintermPage+pageIndex;
00735 pageIndex++;
00736
00737
00738 *pmin = min;
00739
00740
00741 if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages();
00742 if (memOut) {
00743 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00744 FREE(mintermPages);
00745 st_free_table(table);
00746 return(0.0);
00747 }
00748
00749 newEntry = currentNodeDataPage + nodeDataPageIndex;
00750 nodeDataPageIndex++;
00751
00752
00753 newEntry->mintermPointer = pmin;
00754
00755 newEntry->nodesPointer = NULL;
00756
00757
00758 if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) {
00759 memOut = 1;
00760 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00761 FREE(mintermPages);
00762 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00763 FREE(nodeDataPages);
00764 st_free_table(table);
00765 return(0.0);
00766 }
00767 return(min);
00768 }
00769
00770 }
00771
00772
00786 static st_table *
00787 SubsetCountMinterm(
00788 DdNode * node ,
00789 int nvars )
00790 {
00791 st_table *table;
00792 int i;
00793
00794
00795 #ifdef DEBUG
00796 num_calls = 0;
00797 #endif
00798
00799 max = pow(2.0,(double) nvars);
00800 table = st_init_table(st_ptrcmp,st_ptrhash);
00801 if (table == NULL) goto OUT_OF_MEM;
00802 maxPages = INITIAL_PAGES;
00803 mintermPages = ALLOC(double *,maxPages);
00804 if (mintermPages == NULL) {
00805 st_free_table(table);
00806 goto OUT_OF_MEM;
00807 }
00808 page = 0;
00809 currentMintermPage = ALLOC(double,pageSize);
00810 mintermPages[page] = currentMintermPage;
00811 if (currentMintermPage == NULL) {
00812 FREE(mintermPages);
00813 st_free_table(table);
00814 goto OUT_OF_MEM;
00815 }
00816 pageIndex = 0;
00817 maxNodeDataPages = INITIAL_PAGES;
00818 nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages);
00819 if (nodeDataPages == NULL) {
00820 for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00821 FREE(mintermPages);
00822 st_free_table(table);
00823 goto OUT_OF_MEM;
00824 }
00825 nodeDataPage = 0;
00826 currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize);
00827 nodeDataPages[nodeDataPage] = currentNodeDataPage;
00828 if (currentNodeDataPage == NULL) {
00829 for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00830 FREE(mintermPages);
00831 FREE(nodeDataPages);
00832 st_free_table(table);
00833 goto OUT_OF_MEM;
00834 }
00835 nodeDataPageIndex = 0;
00836
00837 (void) SubsetCountMintermAux(node,max,table);
00838 if (memOut) goto OUT_OF_MEM;
00839 return(table);
00840
00841 OUT_OF_MEM:
00842 memOut = 1;
00843 return(NULL);
00844
00845 }
00846
00847
00867 static int
00868 SubsetCountNodesAux(
00869 DdNode * node ,
00870 st_table * table ,
00871 double max )
00872 {
00873 int tval, eval, i;
00874 DdNode *N, *Nv, *Nnv;
00875 double minNv, minNnv;
00876 NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar;
00877 int *pmin, *pminBar, *val;
00878
00879 if ((node == NULL) || Cudd_IsConstant(node))
00880 return(0);
00881
00882
00883 if (st_lookup(table, node, &dummyN) == 1) {
00884 val = dummyN->nodesPointer;
00885 if (val != NULL)
00886 return(0);
00887 } else {
00888 return(0);
00889 }
00890
00891 N = Cudd_Regular(node);
00892 Nv = Cudd_T(N);
00893 Nnv = Cudd_E(N);
00894
00895 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00896 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00897
00898
00899 if (Cudd_IsConstant(Nv)) {
00900 if (Nv == zero) {
00901 minNv = 0.0;
00902 } else {
00903 minNv = max;
00904 }
00905 } else {
00906 if (st_lookup(table, Nv, &dummyNv) == 1)
00907 minNv = *(dummyNv->mintermPointer);
00908 else {
00909 return(0);
00910 }
00911 }
00912 if (Cudd_IsConstant(Nnv)) {
00913 if (Nnv == zero) {
00914 minNnv = 0.0;
00915 } else {
00916 minNnv = max;
00917 }
00918 } else {
00919 if (st_lookup(table, Nnv, &dummyNnv) == 1) {
00920 minNnv = *(dummyNnv->mintermPointer);
00921 }
00922 else {
00923 return(0);
00924 }
00925 }
00926
00927
00928
00929 if (minNv >= minNnv) {
00930 tval = SubsetCountNodesAux(Nv, table, max);
00931 if (memOut) return(0);
00932 eval = SubsetCountNodesAux(Nnv, table, max);
00933 if (memOut) return(0);
00934
00935
00936 if (pageIndex == pageSize) ResizeCountNodePages();
00937 if (memOut) {
00938 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00939 FREE(mintermPages);
00940 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00941 FREE(nodeDataPages);
00942 st_free_table(table);
00943 return(0);
00944 }
00945 pmin = currentLightNodePage + pageIndex;
00946 *pmin = eval;
00947 dummyN->lightChildNodesPointer = pmin;
00948
00949 } else {
00950 eval = SubsetCountNodesAux(Nnv, table, max);
00951 if (memOut) return(0);
00952 tval = SubsetCountNodesAux(Nv, table, max);
00953 if (memOut) return(0);
00954
00955
00956 if (pageIndex == pageSize) ResizeCountNodePages();
00957 if (memOut) {
00958 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00959 FREE(mintermPages);
00960 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00961 FREE(nodeDataPages);
00962 st_free_table(table);
00963 return(0);
00964 }
00965 pmin = currentLightNodePage + pageIndex;
00966 *pmin = tval;
00967 dummyN->lightChildNodesPointer = pmin;
00968
00969 }
00970
00971 pmin = currentNodePage + pageIndex;
00972 *pmin = tval + eval + 1;
00973 dummyN->nodesPointer = pmin;
00974
00975
00976 pageIndex++;
00977
00978
00979
00980
00981
00982 if (st_lookup(table, Cudd_Not(node), &dummyNBar) == 1) {
00983 if (pageIndex == pageSize) ResizeCountNodePages();
00984 if (memOut) {
00985 for (i = 0; i < page; i++) FREE(mintermPages[i]);
00986 FREE(mintermPages);
00987 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00988 FREE(nodeDataPages);
00989 st_free_table(table);
00990 return(0);
00991 }
00992 pminBar = currentLightNodePage + pageIndex;
00993 *pminBar = 0;
00994 dummyNBar->lightChildNodesPointer = pminBar;
00995
00996
00997
00998 if (pageIndex == pageSize) ResizeCountNodePages();
00999 if (memOut) {
01000 for (i = 0; i < page; i++) FREE(mintermPages[i]);
01001 FREE(mintermPages);
01002 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
01003 FREE(nodeDataPages);
01004 st_free_table(table);
01005 return(0);
01006 }
01007 pminBar = currentNodePage + pageIndex;
01008 *pminBar = 0;
01009 dummyNBar->nodesPointer = pminBar ;
01010
01011 pageIndex++;
01012 }
01013 return(*pmin);
01014 }
01015
01016
01031 static int
01032 SubsetCountNodes(
01033 DdNode * node ,
01034 st_table * table ,
01035 int nvars )
01036 {
01037 int num;
01038 int i;
01039
01040 #ifdef DEBUG
01041 num_calls = 0;
01042 #endif
01043
01044 max = pow(2.0,(double) nvars);
01045 maxPages = INITIAL_PAGES;
01046 nodePages = ALLOC(int *,maxPages);
01047 if (nodePages == NULL) {
01048 goto OUT_OF_MEM;
01049 }
01050
01051 lightNodePages = ALLOC(int *,maxPages);
01052 if (lightNodePages == NULL) {
01053 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01054 FREE(mintermPages);
01055 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01056 FREE(nodeDataPages);
01057 FREE(nodePages);
01058 goto OUT_OF_MEM;
01059 }
01060
01061 page = 0;
01062 currentNodePage = nodePages[page] = ALLOC(int,pageSize);
01063 if (currentNodePage == NULL) {
01064 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01065 FREE(mintermPages);
01066 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01067 FREE(nodeDataPages);
01068 FREE(lightNodePages);
01069 FREE(nodePages);
01070 goto OUT_OF_MEM;
01071 }
01072
01073 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
01074 if (currentLightNodePage == NULL) {
01075 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01076 FREE(mintermPages);
01077 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01078 FREE(nodeDataPages);
01079 FREE(currentNodePage);
01080 FREE(lightNodePages);
01081 FREE(nodePages);
01082 goto OUT_OF_MEM;
01083 }
01084
01085 pageIndex = 0;
01086 num = SubsetCountNodesAux(node,table,max);
01087 if (memOut) goto OUT_OF_MEM;
01088 return(num);
01089
01090 OUT_OF_MEM:
01091 memOut = 1;
01092 return(0);
01093
01094 }
01095
01096
01108 static void
01109 StoreNodes(
01110 st_table * storeTable,
01111 DdManager * dd,
01112 DdNode * node)
01113 {
01114 DdNode *N, *Nt, *Ne;
01115 if (Cudd_IsConstant(dd)) {
01116 return;
01117 }
01118 N = Cudd_Regular(node);
01119 if (st_lookup(storeTable, (char *)N, NIL(char *))) {
01120 return;
01121 }
01122 cuddRef(N);
01123 if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) {
01124 fprintf(dd->err,"Something wrong, st_table insert failed\n");
01125 }
01126
01127 Nt = Cudd_T(N);
01128 Ne = Cudd_E(N);
01129
01130 StoreNodes(storeTable, dd, Nt);
01131 StoreNodes(storeTable, dd, Ne);
01132 return;
01133
01134 }
01135
01136
01153 static DdNode *
01154 BuildSubsetBdd(
01155 DdManager * dd ,
01156 DdNode * node ,
01157 int * size ,
01158 st_table * visitedTable ,
01159 int threshold,
01160 st_table * storeTable,
01161 st_table * approxTable)
01162 {
01163
01164 DdNode *Nv, *Nnv, *N, *topv, *neW;
01165 double minNv, minNnv;
01166 NodeData_t *currNodeQual;
01167 NodeData_t *currNodeQualT;
01168 NodeData_t *currNodeQualE;
01169 DdNode *ThenBranch, *ElseBranch;
01170 unsigned int topid;
01171 char *dummy;
01172
01173 #ifdef DEBUG
01174 num_calls++;
01175 #endif
01176
01177
01178 if ((*size) <= threshold) {
01179
01180 StoreNodes(storeTable, dd, node);
01181 return(node);
01182 }
01183
01184 if (Cudd_IsConstant(node))
01185 return(node);
01186
01187
01188 if (!st_lookup(visitedTable, node, &currNodeQual)) {
01189 fprintf(dd->err,
01190 "Something is wrong, ought to be in node quality table\n");
01191 }
01192
01193
01194 N = Cudd_Regular(node);
01195 Nv = Cudd_T(N);
01196 Nnv = Cudd_E(N);
01197
01198
01199 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
01200 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
01201
01202 if (!Cudd_IsConstant(Nv)) {
01203
01204 if (!st_lookup(visitedTable, Nv, &currNodeQualT)) {
01205 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
01206 dd->errorCode = CUDD_INTERNAL_ERROR;
01207 return(NULL);
01208 }
01209 else {
01210 minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer);
01211 }
01212 } else {
01213 if (Nv == zero) {
01214 minNv = 0;
01215 } else {
01216 minNv = max;
01217 }
01218 }
01219 if (!Cudd_IsConstant(Nnv)) {
01220
01221 if (!st_lookup(visitedTable, Nnv, &currNodeQualE)) {
01222 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
01223 dd->errorCode = CUDD_INTERNAL_ERROR;
01224 return(NULL);
01225 } else {
01226 minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer);
01227 }
01228 } else {
01229 if (Nnv == zero) {
01230 minNnv = 0;
01231 } else {
01232 minNnv = max;
01233 }
01234 }
01235
01236
01237
01238
01239 *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer);
01240 if (minNv >= minNnv) {
01241
01242
01243
01244 ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size,
01245 visitedTable, threshold, storeTable, approxTable);
01246 if (ThenBranch == NULL) {
01247 return(NULL);
01248 }
01249 cuddRef(ThenBranch);
01250
01251
01252
01253
01254 if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), &dummy)) {
01255 ElseBranch = Nnv;
01256 cuddRef(ElseBranch);
01257 } else {
01258 if (st_lookup(approxTable, (char *)Nnv, &dummy)) {
01259 ElseBranch = (DdNode *)dummy;
01260 cuddRef(ElseBranch);
01261 } else {
01262 ElseBranch = zero;
01263 cuddRef(ElseBranch);
01264 }
01265 }
01266
01267 }
01268 else {
01269
01270 ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size,
01271 visitedTable, threshold, storeTable, approxTable);
01272 if (ElseBranch == NULL) {
01273 return(NULL);
01274 }
01275 cuddRef(ElseBranch);
01276
01277
01278
01279
01280 if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), &dummy)) {
01281 ThenBranch = Nv;
01282 cuddRef(ThenBranch);
01283 } else {
01284 if (st_lookup(approxTable, (char *)Nv, &dummy)) {
01285 ThenBranch = (DdNode *)dummy;
01286 cuddRef(ThenBranch);
01287 } else {
01288 ThenBranch = zero;
01289 cuddRef(ThenBranch);
01290 }
01291 }
01292 }
01293
01294
01295 topid = Cudd_NodeReadIndex(N);
01296 topv = Cudd_ReadVars(dd, topid);
01297 cuddRef(topv);
01298 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
01299 if (neW != NULL) {
01300 cuddRef(neW);
01301 }
01302 Cudd_RecursiveDeref(dd, topv);
01303 Cudd_RecursiveDeref(dd, ThenBranch);
01304 Cudd_RecursiveDeref(dd, ElseBranch);
01305
01306
01307 if (neW == NULL)
01308 return(NULL);
01309 else {
01310
01311 if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), &dummy)) {
01312 cuddRef(neW);
01313 if (!st_insert(storeTable, (char *)Cudd_Regular(neW), NIL(char)))
01314 return (NULL);
01315 }
01316
01317 if (N != Cudd_Regular(neW)) {
01318 if (st_lookup(approxTable, (char *)node, &dummy)) {
01319 fprintf(dd->err, "This node should not be in the approximated table\n");
01320 } else {
01321 cuddRef(neW);
01322 if (!st_insert(approxTable, (char *)node, (char *)neW))
01323 return(NULL);
01324 }
01325 }
01326 cuddDeref(neW);
01327 return(neW);
01328 }
01329 }