00001
00071 #include "util.h"
00072 #include "cuddInt.h"
00073
00074
00075
00076
00077
00078 #define DEFAULT_PAGE_SIZE 2048
00079 #define DEFAULT_NODE_DIST_PAGE_SIZE 2048
00080 #define MAXSHORTINT ((DdHalfWord) ~0)
00081
00082
00083
00084
00085 #define INITIAL_PAGES 128
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 struct NodeDist{
00097 DdHalfWord oddTopDist;
00098 DdHalfWord evenTopDist;
00099 DdHalfWord oddBotDist;
00100 DdHalfWord evenBotDist;
00101 DdNode *regResult;
00102 DdNode *compResult;
00103 };
00104
00105
00106 struct AssortedInfo {
00107 unsigned int maxpath;
00108 int findShortestPath;
00109 int thresholdReached;
00110 st_table *maxpathTable;
00111 int threshold;
00112 };
00113
00114
00115
00116
00117
00118 typedef struct NodeDist NodeDist_t;
00119
00120
00121
00122
00123
00124 #ifndef lint
00125 static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.34 2009/02/19 16:23:19 fabio Exp $";
00126 #endif
00127
00128 #ifdef DD_DEBUG
00129 static int numCalls;
00130 static int hits;
00131 static int thishit;
00132 #endif
00133
00134
00135 static int memOut;
00136 static DdNode *zero, *one;
00137
00138 static NodeDist_t **nodeDistPages;
00139 static int nodeDistPageIndex;
00140 static int nodeDistPage;
00141 static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE;
00142 static int maxNodeDistPages;
00143 static NodeDist_t *currentNodeDistPage;
00144
00145 static DdNode ***queuePages;
00146 static int queuePageIndex;
00147 static int queuePage;
00148 static int queuePageSize = DEFAULT_PAGE_SIZE;
00149 static int maxQueuePages;
00150 static DdNode **currentQueuePage;
00151
00152
00153
00154
00155
00156
00157 #ifdef __cplusplus
00158 extern "C" {
00159 #endif
00160
00163
00164
00165
00166
00167 static void ResizeNodeDistPages (void);
00168 static void ResizeQueuePages (void);
00169 static void CreateTopDist (st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp);
00170 static int CreateBotDist (DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp);
00171 static st_table * CreatePathTable (DdNode *node, unsigned int *pathLengthArray, FILE *fp);
00172 static unsigned int AssessPathLength (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp);
00173 static DdNode * BuildSubsetBdd (DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable);
00174 static enum st_retval stPathTableDdFree (char *key, char *value, char *arg);
00175
00178 #ifdef __cplusplus
00179 }
00180 #endif
00181
00182
00183
00184
00185
00186
00215 DdNode *
00216 Cudd_SubsetShortPaths(
00217 DdManager * dd ,
00218 DdNode * f ,
00219 int numVars ,
00220 int threshold ,
00221 int hardlimit )
00222 {
00223 DdNode *subset;
00224
00225 memOut = 0;
00226 do {
00227 dd->reordered = 0;
00228 subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit);
00229 } while((dd->reordered ==1) && (!memOut));
00230
00231 return(subset);
00232
00233 }
00234
00235
00267 DdNode *
00268 Cudd_SupersetShortPaths(
00269 DdManager * dd ,
00270 DdNode * f ,
00271 int numVars ,
00272 int threshold ,
00273 int hardlimit )
00274 {
00275 DdNode *subset, *g;
00276
00277 g = Cudd_Not(f);
00278 memOut = 0;
00279 do {
00280 dd->reordered = 0;
00281 subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit);
00282 } while((dd->reordered ==1) && (!memOut));
00283
00284 return(Cudd_NotCond(subset, (subset != NULL)));
00285
00286 }
00287
00288
00289
00290
00291
00292
00293
00311 DdNode *
00312 cuddSubsetShortPaths(
00313 DdManager * dd ,
00314 DdNode * f ,
00315 int numVars ,
00316 int threshold ,
00317 int hardlimit )
00318 {
00319 st_table *pathTable;
00320 DdNode *N, *subset;
00321
00322 unsigned int *pathLengthArray;
00323 unsigned int maxpath, oddLen, evenLen, pathLength, *excess;
00324 int i;
00325 NodeDist_t *nodeStat;
00326 struct AssortedInfo *info;
00327 st_table *subsetNodeTable;
00328
00329 one = DD_ONE(dd);
00330 zero = Cudd_Not(one);
00331
00332 if (numVars == 0) {
00333
00334 numVars = Cudd_ReadSize(dd);
00335 }
00336
00337 if (threshold > numVars) {
00338 threshold = threshold - numVars;
00339 }
00340 if (f == NULL) {
00341 fprintf(dd->err, "Cannot partition, nil object\n");
00342 dd->errorCode = CUDD_INVALID_ARG;
00343 return(NULL);
00344 }
00345 if (Cudd_IsConstant(f))
00346 return (f);
00347
00348 pathLengthArray = ALLOC(unsigned int, numVars+1);
00349 for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0;
00350
00351
00352 #ifdef DD_DEBUG
00353 numCalls = 0;
00354 #endif
00355
00356 pathTable = CreatePathTable(f, pathLengthArray, dd->err);
00357
00358 if ((pathTable == NULL) || (memOut)) {
00359 if (pathTable != NULL)
00360 st_free_table(pathTable);
00361 FREE(pathLengthArray);
00362 return (NIL(DdNode));
00363 }
00364
00365 excess = ALLOC(unsigned int, 1);
00366 *excess = 0;
00367 maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess,
00368 dd->err);
00369
00370 if (maxpath != (unsigned) (numVars + 1)) {
00371
00372 info = ALLOC(struct AssortedInfo, 1);
00373 info->maxpath = maxpath;
00374 info->findShortestPath = 0;
00375 info->thresholdReached = *excess;
00376 info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash);
00377 info->threshold = threshold;
00378
00379 #ifdef DD_DEBUG
00380 (void) fprintf(dd->out, "Path length array\n");
00381 for (i = 0; i < (numVars+1); i++) {
00382 if (pathLengthArray[i])
00383 (void) fprintf(dd->out, "%d ",i);
00384 }
00385 (void) fprintf(dd->out, "\n");
00386 for (i = 0; i < (numVars+1); i++) {
00387 if (pathLengthArray[i])
00388 (void) fprintf(dd->out, "%d ",pathLengthArray[i]);
00389 }
00390 (void) fprintf(dd->out, "\n");
00391 (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n",
00392 maxpath, info->thresholdReached);
00393 #endif
00394
00395 N = Cudd_Regular(f);
00396 if (!st_lookup(pathTable, N, &nodeStat)) {
00397 fprintf(dd->err, "Something wrong, root node must be in table\n");
00398 dd->errorCode = CUDD_INTERNAL_ERROR;
00399 FREE(excess);
00400 FREE(info);
00401 return(NULL);
00402 } else {
00403 if ((nodeStat->oddTopDist != MAXSHORTINT) &&
00404 (nodeStat->oddBotDist != MAXSHORTINT))
00405 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
00406 else
00407 oddLen = MAXSHORTINT;
00408
00409 if ((nodeStat->evenTopDist != MAXSHORTINT) &&
00410 (nodeStat->evenBotDist != MAXSHORTINT))
00411 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
00412 else
00413 evenLen = MAXSHORTINT;
00414
00415 pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
00416 if (pathLength > maxpath) {
00417 (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %u, %u\n", maxpath, pathLength);
00418 dd->errorCode = CUDD_INTERNAL_ERROR;
00419 return(NULL);
00420 }
00421 }
00422
00423 #ifdef DD_DEBUG
00424 numCalls = 0;
00425 hits = 0;
00426 thishit = 0;
00427 #endif
00428
00429 if (hardlimit) {
00430 subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
00431 } else {
00432 subsetNodeTable = NIL(st_table);
00433 }
00434 subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable);
00435 if (subset != NULL) {
00436 cuddRef(subset);
00437 }
00438
00439
00440 #ifdef DD_DEBUG
00441 (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n",
00442 hits, thishit, numCalls);
00443 #endif
00444
00445 if (subsetNodeTable != NIL(st_table)) {
00446 st_free_table(subsetNodeTable);
00447 }
00448 st_free_table(info->maxpathTable);
00449 st_foreach(pathTable, stPathTableDdFree, (char *)dd);
00450
00451 FREE(info);
00452
00453 } else {
00454 subset = f;
00455 cuddRef(subset);
00456 }
00457 FREE(excess);
00458 st_free_table(pathTable);
00459 FREE(pathLengthArray);
00460 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
00461 FREE(nodeDistPages);
00462
00463 #ifdef DD_DEBUG
00464
00465 if (subset != NULL) {
00466 DdNode *check;
00467 check = Cudd_bddIteConstant(dd, subset, f, one);
00468 if (check != one) {
00469 (void) fprintf(dd->err, "Wrong partition\n");
00470 dd->errorCode = CUDD_INTERNAL_ERROR;
00471 return(NULL);
00472 }
00473 }
00474 #endif
00475
00476 if (subset != NULL) {
00477 cuddDeref(subset);
00478 return(subset);
00479 } else {
00480 return(NULL);
00481 }
00482
00483 }
00484
00485
00486
00487
00488
00489
00490
00507 static void
00508 ResizeNodeDistPages(void)
00509 {
00510 int i;
00511 NodeDist_t **newNodeDistPages;
00512
00513
00514 nodeDistPage++;
00515
00516
00517
00518
00519
00520 if (nodeDistPage == maxNodeDistPages) {
00521 newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES);
00522 if (newNodeDistPages == NULL) {
00523 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]);
00524 FREE(nodeDistPages);
00525 memOut = 1;
00526 return;
00527 } else {
00528 for (i = 0; i < maxNodeDistPages; i++) {
00529 newNodeDistPages[i] = nodeDistPages[i];
00530 }
00531
00532 maxNodeDistPages += INITIAL_PAGES;
00533 FREE(nodeDistPages);
00534 nodeDistPages = newNodeDistPages;
00535 }
00536 }
00537
00538 currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t,
00539 nodeDistPageSize);
00540 if (currentNodeDistPage == NULL) {
00541 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]);
00542 FREE(nodeDistPages);
00543 memOut = 1;
00544 return;
00545 }
00546
00547 nodeDistPageIndex = 0;
00548 return;
00549
00550 }
00551
00552
00569 static void
00570 ResizeQueuePages(void)
00571 {
00572 int i;
00573 DdNode ***newQueuePages;
00574
00575 queuePage++;
00576
00577
00578
00579
00580 if (queuePage == maxQueuePages) {
00581 newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES);
00582 if (newQueuePages == NULL) {
00583 for (i = 0; i < queuePage; i++) FREE(queuePages[i]);
00584 FREE(queuePages);
00585 memOut = 1;
00586 return;
00587 } else {
00588 for (i = 0; i < maxQueuePages; i++) {
00589 newQueuePages[i] = queuePages[i];
00590 }
00591
00592 maxQueuePages += INITIAL_PAGES;
00593 FREE(queuePages);
00594 queuePages = newQueuePages;
00595 }
00596 }
00597
00598 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize);
00599 if (currentQueuePage == NULL) {
00600 for (i = 0; i < queuePage; i++) FREE(queuePages[i]);
00601 FREE(queuePages);
00602 memOut = 1;
00603 return;
00604 }
00605
00606 queuePageIndex = 0;
00607 return;
00608
00609 }
00610
00611
00630 static void
00631 CreateTopDist(
00632 st_table * pathTable ,
00633 int parentPage ,
00634 int parentQueueIndex ,
00635 int topLen ,
00636 DdNode ** childPage ,
00637 int childQueueIndex ,
00638 int numParents ,
00639 FILE *fp )
00640 {
00641 NodeDist_t *nodeStat;
00642 DdNode *N, *Nv, *Nnv, *node, *child, *regChild;
00643 int i;
00644 int processingDone, childrenCount;
00645
00646 #ifdef DD_DEBUG
00647 numCalls++;
00648
00649
00650
00651
00652 if ((queuePages[parentPage] == childPage) && (parentQueueIndex ==
00653 childQueueIndex)) {
00654 fprintf(fp, "Should not happen that they are equal\n");
00655 }
00656 assert(queuePageIndex == childQueueIndex);
00657 assert(currentQueuePage == childPage);
00658 #endif
00659
00660
00661
00662 childrenCount = 0;
00663
00664 while (numParents) {
00665 numParents--;
00666 if (parentQueueIndex == queuePageSize) {
00667 parentPage++;
00668 parentQueueIndex = 0;
00669 }
00670
00671 node = *(queuePages[parentPage] + parentQueueIndex);
00672 parentQueueIndex++;
00673
00674 N = Cudd_Regular(node);
00675 Nv = Cudd_T(N);
00676 Nnv = Cudd_E(N);
00677
00678 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00679 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00680
00681 processingDone = 2;
00682 while (processingDone) {
00683
00684
00685
00686 if (processingDone == 2) {
00687 child = Nv;
00688 } else {
00689 child = Nnv;
00690 }
00691
00692 regChild = Cudd_Regular(child);
00693
00694 if (!Cudd_IsConstant(child)) {
00695
00696
00697
00698 if (!st_lookup(pathTable, regChild, &nodeStat)) {
00699
00700
00701 if (nodeDistPageIndex == nodeDistPageSize)
00702 ResizeNodeDistPages();
00703 if (memOut) {
00704 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
00705 FREE(queuePages);
00706 st_free_table(pathTable);
00707 return;
00708 }
00709
00710 nodeStat = currentNodeDistPage + nodeDistPageIndex;
00711 nodeDistPageIndex++;
00712
00713
00714 nodeStat->oddTopDist = MAXSHORTINT;
00715 nodeStat->evenTopDist = MAXSHORTINT;
00716 nodeStat->evenBotDist = MAXSHORTINT;
00717 nodeStat->oddBotDist = MAXSHORTINT;
00718 nodeStat->regResult = NULL;
00719 nodeStat->compResult = NULL;
00720
00721
00722
00723 if (Cudd_IsComplement(child)) {
00724 nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
00725 } else {
00726 nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
00727 }
00728
00729
00730 if (st_insert(pathTable, (char *)regChild,
00731 (char *)nodeStat) == ST_OUT_OF_MEM) {
00732 memOut = 1;
00733 for (i = 0; i <= nodeDistPage; i++)
00734 FREE(nodeDistPages[i]);
00735 FREE(nodeDistPages);
00736 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
00737 FREE(queuePages);
00738 st_free_table(pathTable);
00739 return;
00740 }
00741
00742
00743
00744
00745
00746
00747
00748 if (queuePageIndex == queuePageSize) ResizeQueuePages();
00749 if (memOut) {
00750 for (i = 0; i <= nodeDistPage; i++)
00751 FREE(nodeDistPages[i]);
00752 FREE(nodeDistPages);
00753 st_free_table(pathTable);
00754 return;
00755 }
00756 *(currentQueuePage + queuePageIndex) = child;
00757 queuePageIndex++;
00758
00759 childrenCount++;
00760 } else {
00761
00762
00763 if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist ==
00764 MAXSHORTINT)) || ((!Cudd_IsComplement(child)) &&
00765 (nodeStat->evenTopDist == MAXSHORTINT))) {
00766
00767 if (queuePageIndex == queuePageSize) ResizeQueuePages();
00768 if (memOut) {
00769 for (i = 0; i <= nodeDistPage; i++)
00770 FREE(nodeDistPages[i]);
00771 FREE(nodeDistPages);
00772 st_free_table(pathTable);
00773 return;
00774
00775 }
00776 *(currentQueuePage + queuePageIndex) = child;
00777 queuePageIndex++;
00778
00779
00780 if (Cudd_IsComplement(child)) {
00781 nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
00782 } else {
00783 nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
00784 }
00785 childrenCount++;
00786 }
00787
00788 }
00789 }
00790 processingDone--;
00791 }
00792 }
00793
00794 #ifdef DD_DEBUG
00795 assert(queuePages[parentPage] == childPage);
00796 assert(parentQueueIndex == childQueueIndex);
00797 #endif
00798
00799 if (childrenCount != 0) {
00800 topLen++;
00801 childPage = currentQueuePage;
00802 childQueueIndex = queuePageIndex;
00803 CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen,
00804 childPage, childQueueIndex, childrenCount, fp);
00805 }
00806
00807 return;
00808
00809 }
00810
00811
00831 static int
00832 CreateBotDist(
00833 DdNode * node ,
00834 st_table * pathTable ,
00835 unsigned int * pathLengthArray ,
00836 FILE *fp )
00837 {
00838 DdNode *N, *Nv, *Nnv;
00839 DdNode *realChild;
00840 DdNode *child, *regChild;
00841 NodeDist_t *nodeStat, *nodeStatChild;
00842 unsigned int oddLen, evenLen, pathLength;
00843 DdHalfWord botDist;
00844 int processingDone;
00845
00846 if (Cudd_IsConstant(node))
00847 return(1);
00848 N = Cudd_Regular(node);
00849
00850
00851
00852 if (!st_lookup(pathTable, N, &nodeStat)) {
00853 fprintf(fp, "Something wrong, the entry doesn't exist\n");
00854 return(0);
00855 }
00856
00857
00858 if ((nodeStat->oddTopDist != MAXSHORTINT) &&
00859 (nodeStat->oddBotDist != MAXSHORTINT))
00860 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
00861 else
00862 oddLen = MAXSHORTINT;
00863
00864
00865 if (!((nodeStat->evenTopDist == MAXSHORTINT) ||
00866 (nodeStat->evenBotDist == MAXSHORTINT)))
00867 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
00868 else
00869 evenLen = MAXSHORTINT;
00870
00871
00872 pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
00873
00874 Nv = Cudd_T(N);
00875 Nnv = Cudd_E(N);
00876
00877
00878 processingDone = 0;
00879 while (processingDone != 2) {
00880 if (!processingDone) {
00881 child = Nv;
00882 } else {
00883 child = Nnv;
00884 }
00885
00886 realChild = Cudd_NotCond(child, Cudd_IsComplement(node));
00887 regChild = Cudd_Regular(child);
00888 if (Cudd_IsConstant(realChild)) {
00889
00890
00891
00892 if (Cudd_IsComplement(child))
00893 nodeStat->oddBotDist = 1;
00894 else
00895 nodeStat->evenBotDist = 1;
00896 } else {
00897
00898 if (!st_lookup(pathTable, regChild, &nodeStatChild)) {
00899 fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n");
00900 return(0);
00901 }
00902
00903 if (nodeStatChild->oddBotDist == MAXSHORTINT) {
00904 if (nodeStatChild->evenBotDist == MAXSHORTINT) {
00905 if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp))
00906 return(0);
00907 } else {
00908 fprintf(fp, "Something wrong, both bot nodeStats should be there\n");
00909 return(0);
00910 }
00911 }
00912
00913
00914
00915
00916 if (Cudd_IsComplement(child)) {
00917
00918
00919
00920
00921
00922
00923 if (nodeStatChild->oddBotDist != MAXSHORTINT)
00924 botDist = nodeStatChild->oddBotDist + 1;
00925 else
00926 botDist = MAXSHORTINT;
00927 if (nodeStat->evenBotDist > botDist )
00928 nodeStat->evenBotDist = botDist;
00929
00930 if (nodeStatChild->evenBotDist != MAXSHORTINT)
00931 botDist = nodeStatChild->evenBotDist + 1;
00932 else
00933 botDist = MAXSHORTINT;
00934 if (nodeStat->oddBotDist > botDist)
00935 nodeStat->oddBotDist = botDist;
00936
00937 } else {
00938
00939
00940
00941
00942
00943
00944 if (nodeStatChild->evenBotDist != MAXSHORTINT)
00945 botDist = nodeStatChild->evenBotDist + 1;
00946 else
00947 botDist = MAXSHORTINT;
00948 if (nodeStat->evenBotDist > botDist)
00949 nodeStat->evenBotDist = botDist;
00950
00951 if (nodeStatChild->oddBotDist != MAXSHORTINT)
00952 botDist = nodeStatChild->oddBotDist + 1;
00953 else
00954 botDist = MAXSHORTINT;
00955 if (nodeStat->oddBotDist > botDist)
00956 nodeStat->oddBotDist = botDist;
00957 }
00958 }
00959 processingDone++;
00960 }
00961
00962
00963 if ((nodeStat->oddTopDist != MAXSHORTINT) &&
00964 (nodeStat->oddBotDist != MAXSHORTINT))
00965 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
00966 else
00967 oddLen = MAXSHORTINT;
00968
00969 if ((nodeStat->evenTopDist != MAXSHORTINT) &&
00970 (nodeStat->evenBotDist != MAXSHORTINT))
00971 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
00972 else
00973 evenLen = MAXSHORTINT;
00974
00975
00976
00977 if (oddLen < pathLength ) {
00978 if (pathLength != MAXSHORTINT)
00979 pathLengthArray[pathLength]--;
00980 if (oddLen != MAXSHORTINT)
00981 pathLengthArray[oddLen]++;
00982 pathLength = oddLen;
00983 }
00984 if (evenLen < pathLength ) {
00985 if (pathLength != MAXSHORTINT)
00986 pathLengthArray[pathLength]--;
00987 if (evenLen != MAXSHORTINT)
00988 pathLengthArray[evenLen]++;
00989 }
00990
00991 return(1);
00992
00993 }
00994
00995
01014 static st_table *
01015 CreatePathTable(
01016 DdNode * node ,
01017 unsigned int * pathLengthArray ,
01018 FILE *fp )
01019 {
01020
01021 st_table *pathTable;
01022 NodeDist_t *nodeStat;
01023 DdHalfWord topLen;
01024 DdNode *N;
01025 int i, numParents;
01026 int insertValue;
01027 DdNode **childPage;
01028 int parentPage;
01029 int childQueueIndex, parentQueueIndex;
01030
01031
01032 pathTable = st_init_table(st_ptrcmp,st_ptrhash);
01033
01034
01035 maxNodeDistPages = INITIAL_PAGES;
01036 nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages);
01037 if (nodeDistPages == NULL) {
01038 goto OUT_OF_MEM;
01039 }
01040 nodeDistPage = 0;
01041 currentNodeDistPage = nodeDistPages[nodeDistPage] =
01042 ALLOC(NodeDist_t, nodeDistPageSize);
01043 if (currentNodeDistPage == NULL) {
01044 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
01045 FREE(nodeDistPages);
01046 goto OUT_OF_MEM;
01047 }
01048 nodeDistPageIndex = 0;
01049
01050
01051 maxQueuePages = INITIAL_PAGES;
01052 queuePages = ALLOC(DdNode **, maxQueuePages);
01053 if (queuePages == NULL) {
01054 goto OUT_OF_MEM;
01055 }
01056 queuePage = 0;
01057 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize);
01058 if (currentQueuePage == NULL) {
01059 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01060 FREE(queuePages);
01061 goto OUT_OF_MEM;
01062 }
01063 queuePageIndex = 0;
01064
01065
01066 parentPage = queuePage;
01067 parentQueueIndex = queuePageIndex;
01068 topLen = 0;
01069 *(currentQueuePage + queuePageIndex) = node;
01070 queuePageIndex++;
01071 childPage = currentQueuePage;
01072 childQueueIndex = queuePageIndex;
01073
01074 N = Cudd_Regular(node);
01075
01076 if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages();
01077 if (memOut) {
01078 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
01079 FREE(nodeDistPages);
01080 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01081 FREE(queuePages);
01082 st_free_table(pathTable);
01083 goto OUT_OF_MEM;
01084 }
01085
01086 nodeStat = currentNodeDistPage + nodeDistPageIndex;
01087 nodeDistPageIndex++;
01088
01089 nodeStat->oddTopDist = MAXSHORTINT;
01090 nodeStat->evenTopDist = MAXSHORTINT;
01091 nodeStat->evenBotDist = MAXSHORTINT;
01092 nodeStat->oddBotDist = MAXSHORTINT;
01093 nodeStat->regResult = NULL;
01094 nodeStat->compResult = NULL;
01095
01096 insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat);
01097 if (insertValue == ST_OUT_OF_MEM) {
01098 memOut = 1;
01099 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
01100 FREE(nodeDistPages);
01101 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01102 FREE(queuePages);
01103 st_free_table(pathTable);
01104 goto OUT_OF_MEM;
01105 } else if (insertValue == 1) {
01106 fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n");
01107 return(NULL);
01108 }
01109
01110 if (Cudd_IsComplement(node)) {
01111 nodeStat->oddTopDist = 0;
01112 } else {
01113 nodeStat->evenTopDist = 0;
01114 }
01115 numParents = 1;
01116
01117
01118
01119 #ifdef DD_DEBUG
01120 numCalls = 0;
01121 #endif
01122 CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen,
01123 childPage, childQueueIndex, numParents, fp);
01124 if (memOut) {
01125 fprintf(fp, "Out of Memory and cant count path lengths\n");
01126 goto OUT_OF_MEM;
01127 }
01128
01129 #ifdef DD_DEBUG
01130 numCalls = 0;
01131 #endif
01132
01133
01134
01135 if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL);
01136
01137
01138 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01139 FREE(queuePages);
01140 return(pathTable);
01141
01142 OUT_OF_MEM:
01143 (void) fprintf(fp, "Out of Memory, cannot allocate pages\n");
01144 memOut = 1;
01145 return(NULL);
01146
01147 }
01148
01149
01166 static unsigned int
01167 AssessPathLength(
01168 unsigned int * pathLengthArray ,
01169 int threshold ,
01170 int numVars ,
01171 unsigned int * excess ,
01172 FILE *fp )
01173 {
01174 unsigned int i, maxpath;
01175 int temp;
01176
01177 temp = threshold;
01178 i = 0;
01179 maxpath = 0;
01180
01181
01182
01183 while ((i < (unsigned) numVars+1) && (temp > 0)) {
01184 if (pathLengthArray[i] > 0) {
01185 maxpath = i;
01186 temp = temp - pathLengthArray[i];
01187 }
01188 i++;
01189 }
01190
01191 if (temp >= 0) {
01192 maxpath++;
01193
01194 *excess = 0;
01195 } else {
01196
01197 *excess = temp + pathLengthArray[maxpath];
01198 }
01199
01200 if (maxpath == 0) {
01201 fprintf(fp, "Path Length array seems to be all zeroes, check\n");
01202 }
01203 return(maxpath);
01204
01205 }
01206
01207
01250 static DdNode *
01251 BuildSubsetBdd(
01252 DdManager * dd ,
01253 st_table * pathTable ,
01254 DdNode * node ,
01255 struct AssortedInfo * info ,
01256 st_table * subsetNodeTable )
01257 {
01258 DdNode *N, *Nv, *Nnv;
01259 DdNode *ThenBranch, *ElseBranch, *childBranch;
01260 DdNode *child, *regChild, *regNnv, *regNv;
01261 NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv;
01262 DdNode *neW, *topv, *regNew;
01263 char *entry;
01264 unsigned int topid;
01265 unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength;
01266 unsigned int NvBotDist, NnvBotDist;
01267 int tiebreakChild;
01268 int processingDone, thenDone, elseDone;
01269
01270
01271 #ifdef DD_DEBUG
01272 numCalls++;
01273 #endif
01274 if (Cudd_IsConstant(node))
01275 return(node);
01276
01277 N = Cudd_Regular(node);
01278
01279 if (!st_lookup(pathTable, N, &nodeStat)) {
01280 (void) fprintf(dd->err, "Something wrong, node must be in table \n");
01281 dd->errorCode = CUDD_INTERNAL_ERROR;
01282 return(NULL);
01283 }
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293 if (Cudd_IsComplement(node)) {
01294 if (nodeStat->compResult != NULL) {
01295 #ifdef DD_DEBUG
01296 hits++;
01297 #endif
01298 return(nodeStat->compResult);
01299 }
01300 } else {
01301
01302
01303
01304 if (nodeStat->regResult != NULL) {
01305 #ifdef DD_DEBUG
01306 hits++;
01307 #endif
01308 return(nodeStat->regResult);
01309 }
01310 }
01311
01312
01313
01314 Nv = Cudd_T(N);
01315 Nnv = Cudd_E(N);
01316
01317 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
01318 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
01319
01320
01321 processingDone = 0;
01322
01323 thenDone = 0;
01324 ThenBranch = NULL;
01325
01326 elseDone = 0;
01327 ElseBranch = NULL;
01328
01329 if (Cudd_IsConstant(Nv)) {
01330
01331 if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) {
01332 info->findShortestPath = 0;
01333 }
01334
01335 ThenBranch = Nv;
01336 cuddRef(ThenBranch);
01337 if (ThenBranch == NULL) {
01338 return(NULL);
01339 }
01340
01341 thenDone++;
01342 processingDone++;
01343 NvBotDist = MAXSHORTINT;
01344 } else {
01345
01346 regNv = Cudd_Regular(Nv);
01347
01348 if (!st_lookup(pathTable, regNv, &nodeStatNv) ) {
01349 (void) fprintf(dd->err, "Something wrong, node must be in table\n");
01350 dd->errorCode = CUDD_INTERNAL_ERROR;
01351 return(NULL);
01352 }
01353
01354 if ((nodeStatNv->oddTopDist != MAXSHORTINT) &&
01355 (nodeStatNv->oddBotDist != MAXSHORTINT)) {
01356 oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist);
01357 } else {
01358 oddLen = MAXSHORTINT;
01359 }
01360
01361 if ((nodeStatNv->evenTopDist != MAXSHORTINT) &&
01362 (nodeStatNv->evenBotDist != MAXSHORTINT)) {
01363 evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist);
01364 } else {
01365 evenLen = MAXSHORTINT;
01366 }
01367
01368 NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
01369 NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist:
01370 nodeStatNv->evenBotDist;
01371 }
01372
01373 if (Cudd_IsConstant(Nnv)) {
01374
01375 if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) {
01376 info->findShortestPath = 0;
01377 }
01378
01379 ElseBranch = Nnv;
01380 cuddRef(ElseBranch);
01381 if (ElseBranch == NULL) {
01382 return(NULL);
01383 }
01384
01385 elseDone++;
01386 processingDone++;
01387 NnvBotDist = MAXSHORTINT;
01388 } else {
01389
01390 regNnv = Cudd_Regular(Nnv);
01391
01392 if (!st_lookup(pathTable, regNnv, &nodeStatNnv) ) {
01393 (void) fprintf(dd->err, "Something wrong, node must be in table\n");
01394 dd->errorCode = CUDD_INTERNAL_ERROR;
01395 return(NULL);
01396 }
01397
01398 if ((nodeStatNnv->oddTopDist != MAXSHORTINT) &&
01399 (nodeStatNnv->oddBotDist != MAXSHORTINT)) {
01400 oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist);
01401 } else {
01402 oddLen = MAXSHORTINT;
01403 }
01404
01405 if ((nodeStatNnv->evenTopDist != MAXSHORTINT) &&
01406 (nodeStatNnv->evenBotDist != MAXSHORTINT)) {
01407 evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist);
01408 } else {
01409 evenLen = MAXSHORTINT;
01410 }
01411
01412 NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
01413 NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist :
01414 nodeStatNnv->evenBotDist;
01415 }
01416
01417 tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0;
01418
01419 while (processingDone != 2) {
01420 if (!processingDone) {
01421
01422
01423
01424
01425 if ((NvPathLength < NnvPathLength) ||
01426 ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) {
01427 child = Nv;
01428 regChild = regNv;
01429 thenDone = 1;
01430 childPathLength = NvPathLength;
01431 } else {
01432 child = Nnv;
01433 regChild = regNnv;
01434 elseDone = 1;
01435 childPathLength = NnvPathLength;
01436 }
01437 } else {
01438
01439 if (thenDone) {
01440 child = Nnv;
01441 regChild = regNnv;
01442 elseDone = 1;
01443 childPathLength = NnvPathLength;
01444 } else {
01445 child = Nv;
01446 regChild = regNv;
01447 thenDone = 1;
01448 childPathLength = NvPathLength;
01449 }
01450 }
01451
01452
01453
01454
01455 if (childPathLength > info->maxpath) {
01456
01457 childBranch = zero;
01458 } else {
01459 if (childPathLength < info->maxpath) {
01460 if (info->findShortestPath) {
01461 info->findShortestPath = 0;
01462 }
01463 childBranch = BuildSubsetBdd(dd, pathTable, child, info,
01464 subsetNodeTable);
01465
01466 } else {
01467
01468
01469 if (st_lookup(info->maxpathTable, (char *)regChild,
01470 (char **)&entry)) {
01471
01472
01473 if (info->findShortestPath) {
01474 info->findShortestPath = 0;
01475 }
01476 childBranch = BuildSubsetBdd(dd, pathTable, child, info,
01477 subsetNodeTable);
01478 } else {
01479
01480
01481
01482
01483 if (info->thresholdReached <= 0) {
01484 if (info->findShortestPath) {
01485 if (st_insert(info->maxpathTable, (char *)regChild,
01486 (char *)NIL(char)) == ST_OUT_OF_MEM) {
01487 memOut = 1;
01488 (void) fprintf(dd->err, "OUT of memory\n");
01489 info->thresholdReached = 0;
01490 childBranch = zero;
01491 } else {
01492 info->thresholdReached--;
01493 childBranch = BuildSubsetBdd(dd, pathTable,
01494 child, info,subsetNodeTable);
01495 }
01496 } else {
01497
01498 childBranch = zero;
01499 }
01500 } else {
01501
01502 if (st_insert(info->maxpathTable, (char *)regChild,
01503 (char *)NIL(char)) == ST_OUT_OF_MEM) {
01504 memOut = 1;
01505 (void) fprintf(dd->err, "OUT of memory\n");
01506 info->thresholdReached = 0;
01507 childBranch = zero;
01508 } else {
01509 info->thresholdReached--;
01510 if (info->thresholdReached <= 0) {
01511 info->findShortestPath = 1;
01512 }
01513 childBranch = BuildSubsetBdd(dd, pathTable,
01514 child, info, subsetNodeTable);
01515
01516 }
01517 }
01518 }
01519 }
01520 }
01521 if (childBranch == NULL) {
01522
01523 if (ThenBranch != NULL) {
01524 Cudd_RecursiveDeref(dd, ThenBranch);
01525 ThenBranch = NULL;
01526 }
01527 if (ElseBranch != NULL) {
01528 Cudd_RecursiveDeref(dd, ElseBranch);
01529 ElseBranch = NULL;
01530 }
01531 return(NULL);
01532 }
01533
01534 cuddRef(childBranch);
01535
01536 if (child == Nv) {
01537 ThenBranch = childBranch;
01538 } else {
01539 ElseBranch = childBranch;
01540 }
01541 processingDone++;
01542
01543 }
01544
01545 info->findShortestPath = 0;
01546 topid = Cudd_NodeReadIndex(N);
01547 topv = Cudd_ReadVars(dd, topid);
01548 cuddRef(topv);
01549 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
01550 if (neW != NULL) {
01551 cuddRef(neW);
01552 }
01553 Cudd_RecursiveDeref(dd, topv);
01554 Cudd_RecursiveDeref(dd, ThenBranch);
01555 Cudd_RecursiveDeref(dd, ElseBranch);
01556
01557
01558
01559 if (subsetNodeTable != NIL(st_table)) {
01560
01561 regNew = Cudd_Regular(neW);
01562
01563
01564
01565 if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) {
01566 if (!Cudd_IsConstant(regNew)) {
01567 if (st_insert(subsetNodeTable, (char *)regNew,
01568 (char *)NULL) == ST_OUT_OF_MEM) {
01569 (void) fprintf(dd->err, "Out of memory\n");
01570 return (NULL);
01571 }
01572 if (st_count(subsetNodeTable) > info->threshold) {
01573 info->thresholdReached = 0;
01574 }
01575 }
01576 }
01577 }
01578
01579
01580 if (neW == NULL) {
01581 return(NULL);
01582 } else {
01583
01584 if (Cudd_IsComplement(node)) {
01585 nodeStat->compResult = neW;
01586 cuddRef(nodeStat->compResult);
01587
01588
01589
01590
01591 if (neW == node) {
01592 #ifdef DD_DEBUG
01593 thishit++;
01594 #endif
01595
01596
01597
01598
01599 if (nodeStat->regResult != NULL) {
01600 Cudd_RecursiveDeref(dd, nodeStat->regResult);
01601 }
01602 nodeStat->regResult = Cudd_Not(neW);
01603 cuddRef(nodeStat->regResult);
01604 }
01605
01606 } else {
01607 nodeStat->regResult = neW;
01608 cuddRef(nodeStat->regResult);
01609 if (neW == node) {
01610 #ifdef DD_DEBUG
01611 thishit++;
01612 #endif
01613 if (nodeStat->compResult != NULL) {
01614 Cudd_RecursiveDeref(dd, nodeStat->compResult);
01615 }
01616 nodeStat->compResult = Cudd_Not(neW);
01617 cuddRef(nodeStat->compResult);
01618 }
01619 }
01620
01621 cuddDeref(neW);
01622 return(neW);
01623 }
01624 }
01625
01626
01638 static enum st_retval
01639 stPathTableDdFree(
01640 char * key,
01641 char * value,
01642 char * arg)
01643 {
01644 NodeDist_t *nodeStat;
01645 DdManager *dd;
01646
01647 nodeStat = (NodeDist_t *)value;
01648 dd = (DdManager *)arg;
01649 if (nodeStat->regResult != NULL) {
01650 Cudd_RecursiveDeref(dd, nodeStat->regResult);
01651 }
01652 if (nodeStat->compResult != NULL) {
01653 Cudd_RecursiveDeref(dd, nodeStat->compResult);
01654 }
01655 return(ST_CONTINUE);
01656
01657 }