00001
00044 #ifdef __STDC__
00045 #include <float.h>
00046 #else
00047 #define DBL_MAX_EXP 1024
00048 #endif
00049 #include "util_hack.h"
00050 #include "cuddInt.h"
00051
00052
00053
00054
00055
00056 #define DEFAULT_PAGE_SIZE 2048
00057 #define DEFAULT_NODE_DATA_PAGE_SIZE 1024
00058 #define INITIAL_PAGES 128
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 struct NodeData {
00073 double *mintermPointer;
00074 int *nodesPointer;
00075 int *lightChildNodesPointer;
00076 };
00077
00078
00079
00080
00081
00082 typedef struct NodeData NodeData_t;
00083
00084
00085
00086
00087
00088 #ifndef lint
00089 static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $";
00090 #endif
00091
00092 static int memOut;
00093 #ifdef DEBUG
00094 static int num_calls;
00095 #endif
00096
00097 static DdNode *zero, *one;
00098 static double **mintermPages;
00099 static int **nodePages;
00100 static int **lightNodePages;
00101 static double *currentMintermPage;
00102
00103 static double max;
00104
00105
00106 static int *currentNodePage;
00107
00108 static int *currentLightNodePage;
00109
00110 static int pageIndex;
00111 static int page;
00112 static int pageSize = DEFAULT_PAGE_SIZE;
00113 static int maxPages;
00114
00115 static NodeData_t *currentNodeDataPage;
00116
00117 static int nodeDataPage;
00118 static int nodeDataPageIndex;
00119 static NodeData_t **nodeDataPages;
00120 static int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE;
00121
00122 static int maxNodeDataPages;
00123
00124
00125
00126
00127
00128
00131
00132
00133
00134
00135 static void ResizeNodeDataPages ARGS(());
00136 static void ResizeCountMintermPages ARGS(());
00137 static void ResizeCountNodePages ARGS(());
00138 static double SubsetCountMintermAux ARGS((DdNode *node, double max, st_table *table));
00139 static st_table * SubsetCountMinterm ARGS((DdNode *node, int nvars));
00140 static int SubsetCountNodesAux ARGS((DdNode *node, st_table *table, double max));
00141 static int SubsetCountNodes ARGS((DdNode *node, st_table *table, int nvars));
00142 static void StoreNodes ARGS((st_table *storeTable, DdManager *dd, DdNode *node));
00143 static DdNode * BuildSubsetBdd ARGS((DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable));
00144
00148
00149
00150
00151
00177 DdNode *
00178 Cudd_SubsetHeavyBranch(
00179 DdManager * dd ,
00180 DdNode * f ,
00181 int numVars ,
00182 int threshold )
00183 {
00184 DdNode *subset;
00185
00186 memOut = 0;
00187 do {
00188 dd->reordered = 0;
00189 subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold);
00190 } while ((dd->reordered == 1) && (!memOut));
00191
00192 return(subset);
00193
00194 }
00195
00196
00227 DdNode *
00228 Cudd_SupersetHeavyBranch(
00229 DdManager * dd ,
00230 DdNode * f ,
00231 int numVars ,
00232 int threshold )
00233 {
00234 DdNode *subset, *g;
00235
00236 g = Cudd_Not(f);
00237 memOut = 0;
00238 do {
00239 dd->reordered = 0;
00240 subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold);
00241 } while ((dd->reordered == 1) && (!memOut));
00242
00243 return(Cudd_NotCond(subset, (subset != NULL)));
00244
00245 }
00246
00247
00248
00249
00250
00251
00252
00273 DdNode *
00274 cuddSubsetHeavyBranch(
00275 DdManager * dd ,
00276 DdNode * f ,
00277 int numVars ,
00278 int threshold )
00279 {
00280
00281 int i, *size;
00282 st_table *visitedTable;
00283 int numNodes;
00284 NodeData_t *currNodeQual;
00285 DdNode *subset;
00286 double minN;
00287 st_table *storeTable, *approxTable;
00288 char *key, *value;
00289 st_generator *stGen;
00290
00291 if (f == NULL) {
00292 fprintf(dd->err, "Cannot subset, nil object\n");
00293 dd->errorCode = CUDD_INVALID_ARG;
00294 return(NULL);
00295 }
00296
00297 one = Cudd_ReadOne(dd);
00298 zero = Cudd_Not(one);
00299
00300
00301
00302
00303
00304
00305 if (numVars == 0) {
00306
00307 numVars = DBL_MAX_EXP - 1;
00308 }
00309
00310 if (Cudd_IsConstant(f)) {
00311 return(f);
00312 }
00313
00314 max = pow(2.0, (double)numVars);
00315
00316
00317
00318 visitedTable = SubsetCountMinterm(f, numVars);
00319 if ((visitedTable == NULL) || memOut) {
00320 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00321 dd->errorCode = CUDD_MEMORY_OUT;
00322 return(0);
00323 }
00324 numNodes = SubsetCountNodes(f, visitedTable, numVars);
00325 if (memOut) {
00326 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00327 dd->errorCode = CUDD_MEMORY_OUT;
00328 return(0);
00329 }
00330
00331 if (st_lookup(visitedTable, (char *)f, (char **)&currNodeQual)) {
00332 minN = *(((NodeData_t *)currNodeQual)->mintermPointer);
00333 } else {
00334 fprintf(dd->err,
00335 "Something is wrong, ought to be node quality table\n");
00336 dd->errorCode = CUDD_INTERNAL_ERROR;
00337 }
00338
00339 size = ALLOC(int, 1);
00340 if (size == NULL) {
00341 dd->errorCode = CUDD_MEMORY_OUT;
00342 return(NULL);
00343 }
00344 *size = numNodes;
00345
00346 #ifdef DEBUG
00347 num_calls = 0;
00348 #endif
00349
00350 storeTable = st_init_table(st_ptrcmp, st_ptrhash);
00351
00352 cuddRef(one);
00353 if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) ==
00354 ST_OUT_OF_MEM) {
00355 fprintf(dd->out, "Something wrong, st_table insert failed\n");
00356 }
00357
00358 approxTable = st_init_table(st_ptrcmp, st_ptrhash);
00359 subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold,
00360 storeTable, approxTable);
00361 if (subset != NULL) {
00362 cuddRef(subset);
00363 }
00364
00365 stGen = st_init_gen(approxTable);
00366 if (stGen == NULL) {
00367 st_free_table(approxTable);
00368 return(NULL);
00369 }
00370 while(st_gen(stGen, (char **)&key, (char **)&value)) {
00371 Cudd_RecursiveDeref(dd, (DdNode *)value);
00372 }
00373 st_free_gen(stGen); stGen = NULL;
00374 st_free_table(approxTable);
00375
00376 stGen = st_init_gen(storeTable);
00377 if (stGen == NULL) {
00378 st_free_table(storeTable);
00379 return(NULL);
00380 }
00381 while(st_gen(stGen, (char **)&key, (char **)&value)) {
00382 Cudd_RecursiveDeref(dd, (DdNode *)key);
00383 }
00384 st_free_gen(stGen); stGen = NULL;
00385 st_free_table(storeTable);
00386
00387 for (i = 0; i <= page; i++) {
00388 FREE(mintermPages[i]);
00389 }
00390 FREE(mintermPages);
00391 for (i = 0; i <= page; i++) {
00392 FREE(nodePages[i]);
00393 }
00394 FREE(nodePages);
00395 for (i = 0; i <= page; i++) {
00396 FREE(lightNodePages[i]);
00397 }
00398 FREE(lightNodePages);
00399 for (i = 0; i <= nodeDataPage; i++) {
00400 FREE(nodeDataPages[i]);
00401 }
00402 FREE(nodeDataPages);
00403 st_free_table(visitedTable);
00404 FREE(size);
00405 #if 0
00406 (void) Cudd_DebugCheck(dd);
00407 (void) Cudd_CheckKeys(dd);
00408 #endif
00409
00410 if (subset != NULL) {
00411 #ifdef DD_DEBUG
00412 if (!Cudd_bddLeq(dd, subset, f)) {
00413 fprintf(dd->err, "Wrong subset\n");
00414 dd->errorCode = CUDD_INTERNAL_ERROR;
00415 return(NULL);
00416 }
00417 #endif
00418 cuddDeref(subset);
00419 return(subset);
00420 } else {
00421 return(NULL);
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430
00445 static void
00446 ResizeNodeDataPages(
00447 )
00448 {
00449 int i;
00450 NodeData_t **newNodeDataPages;
00451
00452 nodeDataPage++;
00453
00454
00455
00456
00457 if (nodeDataPage == maxNodeDataPages) {
00458 newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES);
00459 if (newNodeDataPages == NULL) {
00460 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00461 FREE(nodeDataPages);
00462 memOut = 1;
00463 return;
00464 } else {
00465 for (i = 0; i < maxNodeDataPages; i++) {
00466 newNodeDataPages[i] = nodeDataPages[i];
00467 }
00468
00469 maxNodeDataPages += INITIAL_PAGES;
00470 FREE(nodeDataPages);
00471 nodeDataPages = newNodeDataPages;
00472 }
00473 }
00474
00475 currentNodeDataPage = nodeDataPages[nodeDataPage] =
00476 ALLOC(NodeData_t ,nodeDataPageSize);
00477 if (currentNodeDataPage == NULL) {
00478 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00479 FREE(nodeDataPages);
00480 memOut = 1;
00481 return;
00482 }
00483
00484 nodeDataPageIndex = 0;
00485 return;
00486
00487 }
00488
00489
00505 static void
00506 ResizeCountMintermPages(
00507 )
00508 {
00509 int i;
00510 double **newMintermPages;
00511
00512 page++;
00513
00514
00515
00516
00517 if (page == maxPages) {
00518 newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES);
00519 if (newMintermPages == NULL) {
00520 for (i = 0; i < page; i++) FREE(mintermPages[i]);
00521 FREE(mintermPages);
00522 memOut = 1;
00523 return;
00524 } else {
00525 for (i = 0; i < maxPages; i++) {
00526 newMintermPages[i] = mintermPages[i];
00527 }
00528
00529 maxPages += INITIAL_PAGES;
00530 FREE(mintermPages);
00531 mintermPages = newMintermPages;
00532 }
00533 }
00534
00535 currentMintermPage = mintermPages[page] = ALLOC(double,pageSize);
00536 if (currentMintermPage == NULL) {
00537 for (i = 0; i < page; i++) FREE(mintermPages[i]);
00538 FREE(mintermPages);
00539 memOut = 1;
00540 return;
00541 }
00542
00543 pageIndex = 0;
00544 return;
00545
00546 }
00547
00548
00563 static void
00564 ResizeCountNodePages(
00565 )
00566 {
00567 int i;
00568 int **newNodePages;
00569
00570 page++;
00571
00572
00573
00574
00575
00576 if (page == maxPages) {
00577 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00578 if (newNodePages == NULL) {
00579 for (i = 0; i < page; i++) FREE(nodePages[i]);
00580 FREE(nodePages);
00581 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00582 FREE(lightNodePages);
00583 memOut = 1;
00584 return;
00585 } else {
00586 for (i = 0; i < maxPages; i++) {
00587 newNodePages[i] = nodePages[i];
00588 }
00589 FREE(nodePages);
00590 nodePages = newNodePages;
00591 }
00592
00593 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00594 if (newNodePages == NULL) {
00595 for (i = 0; i < page; i++) FREE(nodePages[i]);
00596 FREE(nodePages);
00597 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00598 FREE(lightNodePages);
00599 memOut = 1;
00600 return;
00601 } else {
00602 for (i = 0; i < maxPages; i++) {
00603 newNodePages[i] = lightNodePages[i];
00604 }
00605 FREE(lightNodePages);
00606 lightNodePages = newNodePages;
00607 }
00608
00609 maxPages += INITIAL_PAGES;
00610 }
00611
00612 currentNodePage = nodePages[page] = ALLOC(int,pageSize);
00613 if (currentNodePage == NULL) {
00614 for (i = 0; i < page; i++) FREE(nodePages[i]);
00615 FREE(nodePages);
00616 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00617 FREE(lightNodePages);
00618 memOut = 1;
00619 return;
00620 }
00621
00622 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
00623 if (currentLightNodePage == NULL) {
00624 for (i = 0; i <= page; i++) FREE(nodePages[i]);
00625 FREE(nodePages);
00626 for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00627 FREE(lightNodePages);
00628 memOut = 1;
00629 return;
00630 }
00631
00632 pageIndex = 0;
00633 return;
00634
00635 }
00636
00637
00654 static double
00655 SubsetCountMintermAux(
00656 DdNode * node ,
00657 double max ,
00658 st_table * table )
00659 {
00660
00661 DdNode *N,*Nv,*Nnv;
00662 double min,*pmin;
00663 double min1, min2;
00664 NodeData_t *dummy;
00665 NodeData_t *newEntry;
00666 int i;
00667
00668 #ifdef DEBUG
00669 num_calls++;
00670 #endif
00671
00672
00673 if (Cudd_IsConstant(node)) {
00674 if (node == zero) {
00675 return(0.0);
00676 } else {
00677 return(max);
00678 }
00679 } else {
00680
00681
00682 if (st_lookup(table,(char *)node, (char **)&dummy)) {
00683 min = *(dummy->mintermPointer);
00684 return(min);
00685 }
00686
00687
00688 N = Cudd_Regular(node);
00689
00690
00691 Nv = Cudd_T(N);
00692 Nnv = Cudd_E(N);
00693
00694 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00695 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00696
00697 min1 = SubsetCountMintermAux(Nv, max,table)/2.0;
00698 if (memOut) return(0.0);
00699 min2 = SubsetCountMintermAux(Nnv,max,table)/2.0;
00700 if (memOut) return(0.0);
00701 min = (min1+min2);
00702
00703
00704 if (pageIndex == pageSize) ResizeCountMintermPages();
00705 if (memOut) {
00706 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00707 FREE(nodeDataPages);
00708 st_free_table(table);
00709 return(0.0);
00710 }
00711
00712
00713 pmin = currentMintermPage+pageIndex;
00714 pageIndex++;
00715
00716
00717 *pmin = min;
00718
00719
00720 if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages();
00721 if (memOut) {
00722 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00723 FREE(mintermPages);
00724 st_free_table(table);
00725 return(0.0);
00726 }
00727
00728 newEntry = currentNodeDataPage + nodeDataPageIndex;
00729 nodeDataPageIndex++;
00730
00731
00732 newEntry->mintermPointer = pmin;
00733
00734 newEntry->nodesPointer = NULL;
00735
00736
00737 if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) {
00738 memOut = 1;
00739 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00740 FREE(mintermPages);
00741 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00742 FREE(nodeDataPages);
00743 st_free_table(table);
00744 return(0.0);
00745 }
00746 return(min);
00747 }
00748
00749 }
00750
00751
00765 static st_table *
00766 SubsetCountMinterm(
00767 DdNode * node ,
00768 int nvars )
00769 {
00770 st_table *table;
00771 double num;
00772 int i;
00773
00774
00775 #ifdef DEBUG
00776 num_calls = 0;
00777 #endif
00778
00779 max = pow(2.0,(double) nvars);
00780 table = st_init_table(st_ptrcmp,st_ptrhash);
00781 if (table == NULL) goto OUT_OF_MEM;
00782 maxPages = INITIAL_PAGES;
00783 mintermPages = ALLOC(double *,maxPages);
00784 if (mintermPages == NULL) {
00785 st_free_table(table);
00786 goto OUT_OF_MEM;
00787 }
00788 page = 0;
00789 currentMintermPage = ALLOC(double,pageSize);
00790 mintermPages[page] = currentMintermPage;
00791 if (currentMintermPage == NULL) {
00792 FREE(mintermPages);
00793 st_free_table(table);
00794 goto OUT_OF_MEM;
00795 }
00796 pageIndex = 0;
00797 maxNodeDataPages = INITIAL_PAGES;
00798 nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages);
00799 if (nodeDataPages == NULL) {
00800 for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00801 FREE(mintermPages);
00802 st_free_table(table);
00803 goto OUT_OF_MEM;
00804 }
00805 nodeDataPage = 0;
00806 currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize);
00807 nodeDataPages[nodeDataPage] = currentNodeDataPage;
00808 if (currentNodeDataPage == NULL) {
00809 for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00810 FREE(mintermPages);
00811 FREE(nodeDataPages);
00812 st_free_table(table);
00813 goto OUT_OF_MEM;
00814 }
00815 nodeDataPageIndex = 0;
00816
00817 num = SubsetCountMintermAux(node,max,table);
00818 if (memOut) goto OUT_OF_MEM;
00819 return(table);
00820
00821 OUT_OF_MEM:
00822 memOut = 1;
00823 return(NULL);
00824
00825 }
00826
00827
00847 static int
00848 SubsetCountNodesAux(
00849 DdNode * node ,
00850 st_table * table ,
00851 double max )
00852 {
00853 int tval, eval, i;
00854 DdNode *N, *Nv, *Nnv;
00855 double minNv, minNnv;
00856 NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar;
00857 int *pmin, *pminBar, *val;
00858
00859 if ((node == NULL) || Cudd_IsConstant(node))
00860 return(0);
00861
00862
00863 if (st_lookup(table, (char *)node, (char **)&dummyN) == 1) {
00864 val = dummyN->nodesPointer;
00865 if (val != NULL)
00866 return(0);
00867 } else {
00868 return(0);
00869 }
00870
00871 N = Cudd_Regular(node);
00872 Nv = Cudd_T(N);
00873 Nnv = Cudd_E(N);
00874
00875 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00876 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00877
00878
00879 if (Cudd_IsConstant(Nv)) {
00880 if (Nv == zero) {
00881 minNv = 0.0;
00882 } else {
00883 minNv = max;
00884 }
00885 } else {
00886 if (st_lookup(table, (char *)Nv, (char **)&dummyNv) == 1)
00887 minNv = *(dummyNv->mintermPointer);
00888 else {
00889 return(0);
00890 }
00891 }
00892 if (Cudd_IsConstant(Nnv)) {
00893 if (Nnv == zero) {
00894 minNnv = 0.0;
00895 } else {
00896 minNnv = max;
00897 }
00898 } else {
00899 if (st_lookup(table, (char *)Nnv, (char **)&dummyNnv) == 1) {
00900 minNnv = *(dummyNnv->mintermPointer);
00901 }
00902 else {
00903 return(0);
00904 }
00905 }
00906
00907
00908
00909 if (minNv >= minNnv) {
00910 tval = SubsetCountNodesAux(Nv, table, max);
00911 if (memOut) return(0);
00912 eval = SubsetCountNodesAux(Nnv, table, max);
00913 if (memOut) return(0);
00914
00915
00916 if (pageIndex == pageSize) ResizeCountNodePages();
00917 if (memOut) {
00918 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00919 FREE(mintermPages);
00920 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00921 FREE(nodeDataPages);
00922 st_free_table(table);
00923 return(0);
00924 }
00925 pmin = currentLightNodePage + pageIndex;
00926 *pmin = eval;
00927 dummyN->lightChildNodesPointer = pmin;
00928
00929 } else {
00930 eval = SubsetCountNodesAux(Nnv, table, max);
00931 if (memOut) return(0);
00932 tval = SubsetCountNodesAux(Nv, 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 = tval;
00947 dummyN->lightChildNodesPointer = pmin;
00948
00949 }
00950
00951 pmin = currentNodePage + pageIndex;
00952 *pmin = tval + eval + 1;
00953 dummyN->nodesPointer = pmin;
00954
00955
00956 pageIndex++;
00957
00958
00959
00960
00961
00962 if (st_lookup(table, (char *)Cudd_Not(node), (char **)&dummyNBar) == 1) {
00963 if (pageIndex == pageSize) ResizeCountNodePages();
00964 if (memOut) {
00965 for (i = 0; i < page; i++) FREE(mintermPages[i]);
00966 FREE(mintermPages);
00967 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00968 FREE(nodeDataPages);
00969 st_free_table(table);
00970 return(0);
00971 }
00972 pminBar = currentLightNodePage + pageIndex;
00973 *pminBar = 0;
00974 dummyNBar->lightChildNodesPointer = pminBar;
00975
00976
00977
00978 if (pageIndex == pageSize) ResizeCountNodePages();
00979 if (memOut) {
00980 for (i = 0; i < page; i++) FREE(mintermPages[i]);
00981 FREE(mintermPages);
00982 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00983 FREE(nodeDataPages);
00984 st_free_table(table);
00985 return(0);
00986 }
00987 pminBar = currentNodePage + pageIndex;
00988 *pminBar = 0;
00989 dummyNBar->nodesPointer = pminBar ;
00990
00991 pageIndex++;
00992 }
00993 return(*pmin);
00994 }
00995
00996
01011 static int
01012 SubsetCountNodes(
01013 DdNode * node ,
01014 st_table * table ,
01015 int nvars )
01016 {
01017 int num;
01018 int i;
01019
01020 #ifdef DEBUG
01021 num_calls = 0;
01022 #endif
01023
01024 max = pow(2.0,(double) nvars);
01025 maxPages = INITIAL_PAGES;
01026 nodePages = ALLOC(int *,maxPages);
01027 if (nodePages == NULL) {
01028 goto OUT_OF_MEM;
01029 }
01030
01031 lightNodePages = ALLOC(int *,maxPages);
01032 if (lightNodePages == NULL) {
01033 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01034 FREE(mintermPages);
01035 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01036 FREE(nodeDataPages);
01037 FREE(nodePages);
01038 goto OUT_OF_MEM;
01039 }
01040
01041 page = 0;
01042 currentNodePage = nodePages[page] = ALLOC(int,pageSize);
01043 if (currentNodePage == NULL) {
01044 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01045 FREE(mintermPages);
01046 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01047 FREE(nodeDataPages);
01048 FREE(lightNodePages);
01049 FREE(nodePages);
01050 goto OUT_OF_MEM;
01051 }
01052
01053 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
01054 if (currentLightNodePage == NULL) {
01055 for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01056 FREE(mintermPages);
01057 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01058 FREE(nodeDataPages);
01059 FREE(currentNodePage);
01060 FREE(lightNodePages);
01061 FREE(nodePages);
01062 goto OUT_OF_MEM;
01063 }
01064
01065 pageIndex = 0;
01066 num = SubsetCountNodesAux(node,table,max);
01067 if (memOut) goto OUT_OF_MEM;
01068 return(num);
01069
01070 OUT_OF_MEM:
01071 memOut = 1;
01072 return(0);
01073
01074 }
01075
01076
01088 static void
01089 StoreNodes(
01090 st_table * storeTable,
01091 DdManager * dd,
01092 DdNode * node)
01093 {
01094 char *dummy;
01095 DdNode *N, *Nt, *Ne;
01096 if (Cudd_IsConstant(dd)) {
01097 return;
01098 }
01099 N = Cudd_Regular(node);
01100 if (st_lookup(storeTable, (char *)N, (char **)&dummy)) {
01101 return;
01102 }
01103 cuddRef(N);
01104 if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) {
01105 fprintf(dd->err,"Something wrong, st_table insert failed\n");
01106 }
01107
01108 Nt = Cudd_T(N);
01109 Ne = Cudd_E(N);
01110
01111 StoreNodes(storeTable, dd, Nt);
01112 StoreNodes(storeTable, dd, Ne);
01113 return;
01114
01115 }
01116
01117
01134 static DdNode *
01135 BuildSubsetBdd(
01136 DdManager * dd ,
01137 DdNode * node ,
01138 int * size ,
01139 st_table * visitedTable ,
01140 int threshold,
01141 st_table * storeTable,
01142 st_table * approxTable)
01143 {
01144
01145 DdNode *Nv, *Nnv, *N, *topv, *neW;
01146 double minNv, minNnv;
01147 NodeData_t *currNodeQual;
01148 NodeData_t *currNodeQualT;
01149 NodeData_t *currNodeQualE;
01150 DdNode *ThenBranch, *ElseBranch;
01151 unsigned int topid;
01152 char *dummy;
01153
01154 #ifdef DEBUG
01155 num_calls++;
01156 #endif
01157
01158
01159 if ((*size) <= threshold) {
01160
01161 StoreNodes(storeTable, dd, node);
01162 return(node);
01163 }
01164
01165 if (Cudd_IsConstant(node))
01166 return(node);
01167
01168
01169 if (!st_lookup(visitedTable, (char *)node, (char **)&currNodeQual)) {
01170 fprintf(dd->err,
01171 "Something is wrong, ought to be in node quality table\n");
01172 }
01173
01174
01175 N = Cudd_Regular(node);
01176 Nv = Cudd_T(N);
01177 Nnv = Cudd_E(N);
01178
01179
01180 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
01181 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
01182
01183 if (!Cudd_IsConstant(Nv)) {
01184
01185 if (!st_lookup(visitedTable, (char *)Nv,
01186 (char **)&currNodeQualT)) {
01187 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
01188 dd->errorCode = CUDD_INTERNAL_ERROR;
01189 return(NULL);
01190 }
01191 else {
01192 minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer);
01193 }
01194 } else {
01195 if (Nv == zero) {
01196 minNv = 0;
01197 } else {
01198 minNv = max;
01199 }
01200 }
01201 if (!Cudd_IsConstant(Nnv)) {
01202
01203 if (!st_lookup(visitedTable, (char *)Nnv, (char **)&currNodeQualE)) {
01204 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
01205 dd->errorCode = CUDD_INTERNAL_ERROR;
01206 return(NULL);
01207 } else {
01208 minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer);
01209 }
01210 } else {
01211 if (Nnv == zero) {
01212 minNnv = 0;
01213 } else {
01214 minNnv = max;
01215 }
01216 }
01217
01218
01219
01220
01221 *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer);
01222 if (minNv >= minNnv) {
01223
01224
01225
01226 ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size,
01227 visitedTable, threshold, storeTable, approxTable);
01228 if (ThenBranch == NULL) {
01229 return(NULL);
01230 }
01231 cuddRef(ThenBranch);
01232
01233
01234
01235
01236 if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), (char **)&dummy)) {
01237 ElseBranch = Nnv;
01238 cuddRef(ElseBranch);
01239 } else {
01240 if (st_lookup(approxTable, (char *)Nnv, (char **)&dummy)) {
01241 ElseBranch = (DdNode *)dummy;
01242 cuddRef(ElseBranch);
01243 } else {
01244 ElseBranch = zero;
01245 cuddRef(ElseBranch);
01246 }
01247 }
01248
01249 }
01250 else {
01251
01252 ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size,
01253 visitedTable, threshold, storeTable, approxTable);
01254 if (ElseBranch == NULL) {
01255 return(NULL);
01256 }
01257 cuddRef(ElseBranch);
01258
01259
01260
01261
01262 if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), (char **)&dummy)) {
01263 ThenBranch = Nv;
01264 cuddRef(ThenBranch);
01265 } else {
01266 if (st_lookup(approxTable, (char *)Nv, (char **)&dummy)) {
01267 ThenBranch = (DdNode *)dummy;
01268 cuddRef(ThenBranch);
01269 } else {
01270 ThenBranch = zero;
01271 cuddRef(ThenBranch);
01272 }
01273 }
01274 }
01275
01276
01277 topid = Cudd_NodeReadIndex(N);
01278 topv = Cudd_ReadVars(dd, topid);
01279 cuddRef(topv);
01280 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
01281 if (neW != NULL) {
01282 cuddRef(neW);
01283 }
01284 Cudd_RecursiveDeref(dd, topv);
01285 Cudd_RecursiveDeref(dd, ThenBranch);
01286 Cudd_RecursiveDeref(dd, ElseBranch);
01287
01288
01289 if (neW == NULL)
01290 return(NULL);
01291 else {
01292
01293 if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), (char **)&dummy)) {
01294 cuddRef(neW);
01295 st_insert(storeTable, (char *)Cudd_Regular(neW), (char *)NIL(char));
01296
01297 }
01298
01299 if (N != Cudd_Regular(neW)) {
01300 if (st_lookup(approxTable, (char *)node, (char **)&dummy)) {
01301 fprintf(dd->err, "This node should not be in the approximated table\n");
01302 } else {
01303 cuddRef(neW);
01304 st_insert(approxTable, (char *)node, (char *)neW);
01305 }
01306 }
01307 cuddDeref(neW);
01308 return(neW);
01309 }
01310 }
01311