00001
00044 #include "util_hack.h"
00045 #include "cuddInt.h"
00046
00047
00048
00049
00050
00051 #define DEFAULT_PAGE_SIZE 2048
00052 #define DEFAULT_NODE_DIST_PAGE_SIZE 2048
00053 #define MAXSHORTINT ((DdHalfWord) ~0)
00054
00055
00056
00057
00058 #define INITIAL_PAGES 128
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 struct NodeDist{
00070 DdHalfWord oddTopDist;
00071 DdHalfWord evenTopDist;
00072 DdHalfWord oddBotDist;
00073 DdHalfWord evenBotDist;
00074 DdNode *regResult;
00075 DdNode *compResult;
00076 };
00077
00078
00079 struct AssortedInfo {
00080 unsigned int maxpath;
00081 int findShortestPath;
00082 int thresholdReached;
00083 st_table *maxpathTable;
00084 int threshold;
00085 };
00086
00087
00088
00089
00090
00091 typedef struct NodeDist NodeDist_t;
00092
00093
00094
00095
00096
00097 #ifndef lint
00098 static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $";
00099 #endif
00100
00101 #ifdef DD_DEBUG
00102 static int numCalls;
00103 static int hits;
00104 static int thishit;
00105 #endif
00106
00107
00108 static int memOut;
00109 static DdNode *zero, *one;
00110
00111 static NodeDist_t **nodeDistPages;
00112 static int nodeDistPageIndex;
00113 static int nodeDistPage;
00114 static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE;
00115 static int maxNodeDistPages;
00116 static NodeDist_t *currentNodeDistPage;
00117
00118 static DdNode ***queuePages;
00119 static int queuePageIndex;
00120 static int queuePage;
00121 static int queuePageSize = DEFAULT_PAGE_SIZE;
00122 static int maxQueuePages;
00123 static DdNode **currentQueuePage;
00124
00125
00126
00127
00128
00129
00132
00133
00134
00135
00136 static void ResizeNodeDistPages ARGS(());
00137 static void ResizeQueuePages ARGS(());
00138 static void CreateTopDist ARGS((st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp));
00139 static int CreateBotDist ARGS((DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp));
00140 static st_table * CreatePathTable ARGS((DdNode *node, unsigned int *pathLengthArray, FILE *fp));
00141 static unsigned int AssessPathLength ARGS((unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp));
00142 static DdNode * BuildSubsetBdd ARGS((DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable));
00143 static enum st_retval stPathTableDdFree ARGS((char *key, char *value, char *arg));
00144
00148
00149
00150
00151
00152
00181 DdNode *
00182 Cudd_SubsetShortPaths(
00183 DdManager * dd ,
00184 DdNode * f ,
00185 int numVars ,
00186 int threshold ,
00187 int hardlimit )
00188 {
00189 DdNode *subset;
00190
00191 memOut = 0;
00192 do {
00193 dd->reordered = 0;
00194 subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit);
00195 } while((dd->reordered ==1) && (!memOut));
00196
00197 return(subset);
00198
00199 }
00200
00201
00233 DdNode *
00234 Cudd_SupersetShortPaths(
00235 DdManager * dd ,
00236 DdNode * f ,
00237 int numVars ,
00238 int threshold ,
00239 int hardlimit )
00240 {
00241 DdNode *subset, *g;
00242
00243 g = Cudd_Not(f);
00244 memOut = 0;
00245 do {
00246 dd->reordered = 0;
00247 subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit);
00248 } while((dd->reordered ==1) && (!memOut));
00249
00250 return(Cudd_NotCond(subset, (subset != NULL)));
00251
00252 }
00253
00254
00255
00256
00257
00258
00259
00277 DdNode *
00278 cuddSubsetShortPaths(
00279 DdManager * dd ,
00280 DdNode * f ,
00281 int numVars ,
00282 int threshold ,
00283 int hardlimit )
00284 {
00285 st_table *pathTable;
00286 DdNode *N, *subset;
00287
00288 unsigned int *pathLengthArray;
00289 unsigned int maxpath, oddLen, evenLen, pathLength, *excess;
00290 int i;
00291 NodeDist_t *nodeStat;
00292 struct AssortedInfo *info;
00293 st_table *subsetNodeTable;
00294
00295 one = DD_ONE(dd);
00296 zero = Cudd_Not(one);
00297
00298 if (numVars == 0) {
00299
00300 numVars = Cudd_ReadSize(dd);
00301 }
00302
00303 if (threshold > numVars) {
00304 threshold = threshold - numVars;
00305 }
00306 if (f == NULL) {
00307 fprintf(dd->err, "Cannot partition, nil object\n");
00308 dd->errorCode = CUDD_INVALID_ARG;
00309 return(NULL);
00310 }
00311 if (Cudd_IsConstant(f))
00312 return (f);
00313
00314 pathLengthArray = ALLOC(unsigned int, numVars+1);
00315 for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0;
00316
00317
00318 #ifdef DD_DEBUG
00319 numCalls = 0;
00320 #endif
00321
00322 pathTable = CreatePathTable(f, pathLengthArray, dd->err);
00323
00324 if ((pathTable == NULL) || (memOut)) {
00325 if (pathTable != NULL)
00326 st_free_table(pathTable);
00327 FREE(pathLengthArray);
00328 return (NIL(DdNode));
00329 }
00330
00331 excess = ALLOC(unsigned int, 1);
00332 *excess = 0;
00333 maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess,
00334 dd->err);
00335
00336 if (maxpath != (unsigned) (numVars + 1)) {
00337
00338 info = ALLOC(struct AssortedInfo, 1);
00339 info->maxpath = maxpath;
00340 info->findShortestPath = 0;
00341 info->thresholdReached = *excess;
00342 info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash);
00343 info->threshold = threshold;
00344
00345 #ifdef DD_DEBUG
00346 (void) fprintf(dd->out, "Path length array\n");
00347 for (i = 0; i < (numVars+1); i++) {
00348 if (pathLengthArray[i])
00349 (void) fprintf(dd->out, "%d ",i);
00350 }
00351 (void) fprintf(dd->out, "\n");
00352 for (i = 0; i < (numVars+1); i++) {
00353 if (pathLengthArray[i])
00354 (void) fprintf(dd->out, "%d ",pathLengthArray[i]);
00355 }
00356 (void) fprintf(dd->out, "\n");
00357 (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n",
00358 maxpath, info->thresholdReached);
00359 #endif
00360
00361 N = Cudd_Regular(f);
00362 if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) {
00363 fprintf(dd->err, "Something wrong, root node must be in table\n");
00364 dd->errorCode = CUDD_INTERNAL_ERROR;
00365 return(NULL);
00366 } else {
00367 if ((nodeStat->oddTopDist != MAXSHORTINT) &&
00368 (nodeStat->oddBotDist != MAXSHORTINT))
00369 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
00370 else
00371 oddLen = MAXSHORTINT;
00372
00373 if ((nodeStat->evenTopDist != MAXSHORTINT) &&
00374 (nodeStat->evenBotDist != MAXSHORTINT))
00375 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
00376 else
00377 evenLen = MAXSHORTINT;
00378
00379 pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
00380 if (pathLength > maxpath) {
00381 (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %d, %d\n", maxpath, pathLength);
00382 dd->errorCode = CUDD_INTERNAL_ERROR;
00383 return(NULL);
00384 }
00385 }
00386
00387 #ifdef DD_DEBUG
00388 numCalls = 0;
00389 hits = 0;
00390 thishit = 0;
00391 #endif
00392
00393 if (hardlimit) {
00394 subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
00395 } else {
00396 subsetNodeTable = NIL(st_table);
00397 }
00398 subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable);
00399 if (subset != NULL) {
00400 cuddRef(subset);
00401 }
00402
00403
00404 #ifdef DD_DEBUG
00405 (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n",
00406 hits, thishit, numCalls);
00407 #endif
00408
00409 if (subsetNodeTable != NIL(st_table)) {
00410 st_free_table(subsetNodeTable);
00411 }
00412 st_free_table(info->maxpathTable);
00413 st_foreach(pathTable, stPathTableDdFree, (char *)dd);
00414
00415 FREE(info);
00416
00417 } else {
00418 subset = f;
00419 cuddRef(subset);
00420 }
00421 FREE(excess);
00422 st_free_table(pathTable);
00423 FREE(pathLengthArray);
00424 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
00425 FREE(nodeDistPages);
00426
00427 #ifdef DD_DEBUG
00428
00429 if (subset != NULL) {
00430 DdNode *check;
00431 check = Cudd_bddIteConstant(dd, subset, f, one);
00432 if (check != one) {
00433 (void) fprintf(dd->err, "Wrong partition\n");
00434 dd->errorCode = CUDD_INTERNAL_ERROR;
00435 return(NULL);
00436 }
00437 }
00438 #endif
00439
00440 if (subset != NULL) {
00441 cuddDeref(subset);
00442 return(subset);
00443 } else {
00444 return(NULL);
00445 }
00446
00447 }
00448
00449
00450
00451
00452
00453
00454
00471 static void
00472 ResizeNodeDistPages(
00473 )
00474 {
00475 int i;
00476 NodeDist_t **newNodeDistPages;
00477
00478
00479 nodeDistPage++;
00480
00481
00482
00483
00484
00485 if (nodeDistPage == maxNodeDistPages) {
00486 newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES);
00487 if (newNodeDistPages == NULL) {
00488 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]);
00489 FREE(nodeDistPages);
00490 memOut = 1;
00491 return;
00492 } else {
00493 for (i = 0; i < maxNodeDistPages; i++) {
00494 newNodeDistPages[i] = nodeDistPages[i];
00495 }
00496
00497 maxNodeDistPages += INITIAL_PAGES;
00498 FREE(nodeDistPages);
00499 nodeDistPages = newNodeDistPages;
00500 }
00501 }
00502
00503 currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t,
00504 nodeDistPageSize);
00505 if (currentNodeDistPage == NULL) {
00506 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]);
00507 FREE(nodeDistPages);
00508 memOut = 1;
00509 return;
00510 }
00511
00512 nodeDistPageIndex = 0;
00513 return;
00514
00515 }
00516
00517
00534 static void
00535 ResizeQueuePages(
00536 )
00537 {
00538 int i;
00539 DdNode ***newQueuePages;
00540
00541 queuePage++;
00542
00543
00544
00545
00546 if (queuePage == maxQueuePages) {
00547 newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES);
00548 if (newQueuePages == NULL) {
00549 for (i = 0; i < queuePage; i++) FREE(queuePages[i]);
00550 FREE(queuePages);
00551 memOut = 1;
00552 return;
00553 } else {
00554 for (i = 0; i < maxQueuePages; i++) {
00555 newQueuePages[i] = queuePages[i];
00556 }
00557
00558 maxQueuePages += INITIAL_PAGES;
00559 FREE(queuePages);
00560 queuePages = newQueuePages;
00561 }
00562 }
00563
00564 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize);
00565 if (currentQueuePage == NULL) {
00566 for (i = 0; i < queuePage; i++) FREE(queuePages[i]);
00567 FREE(queuePages);
00568 memOut = 1;
00569 return;
00570 }
00571
00572 queuePageIndex = 0;
00573 return;
00574
00575 }
00576
00577
00596 static void
00597 CreateTopDist(
00598 st_table * pathTable ,
00599 int parentPage ,
00600 int parentQueueIndex ,
00601 int topLen ,
00602 DdNode ** childPage ,
00603 int childQueueIndex ,
00604 int numParents ,
00605 FILE *fp )
00606 {
00607 NodeDist_t *nodeStat;
00608 DdNode *N, *Nv, *Nnv, *node, *child, *regChild;
00609 int i;
00610 int processingDone, childrenCount;
00611
00612 #ifdef DD_DEBUG
00613 numCalls++;
00614
00615
00616
00617
00618 if ((queuePages[parentPage] == childPage) && (parentQueueIndex ==
00619 childQueueIndex)) {
00620 fprintf(fp, "Should not happen that they are equal\n");
00621 }
00622 assert(queuePageIndex == childQueueIndex);
00623 assert(currentQueuePage == childPage);
00624 #endif
00625
00626
00627
00628 childrenCount = 0;
00629
00630 while (numParents) {
00631 numParents--;
00632 if (parentQueueIndex == queuePageSize) {
00633 parentPage++;
00634 parentQueueIndex = 0;
00635 }
00636
00637 node = *(queuePages[parentPage] + parentQueueIndex);
00638 parentQueueIndex++;
00639
00640 N = Cudd_Regular(node);
00641 Nv = Cudd_T(N);
00642 Nnv = Cudd_E(N);
00643
00644 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00645 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00646
00647 processingDone = 2;
00648 while (processingDone) {
00649
00650
00651
00652 if (processingDone == 2) {
00653 child = Nv;
00654 } else {
00655 child = Nnv;
00656 }
00657
00658 regChild = Cudd_Regular(child);
00659
00660 if (!Cudd_IsConstant(child)) {
00661
00662
00663
00664 if (!st_lookup(pathTable, (char *)regChild, (char **)&nodeStat)) {
00665
00666
00667 if (nodeDistPageIndex == nodeDistPageSize)
00668 ResizeNodeDistPages();
00669 if (memOut) {
00670 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
00671 FREE(queuePages);
00672 st_free_table(pathTable);
00673 return;
00674 }
00675
00676 nodeStat = currentNodeDistPage + nodeDistPageIndex;
00677 nodeDistPageIndex++;
00678
00679
00680 nodeStat->oddTopDist = MAXSHORTINT;
00681 nodeStat->evenTopDist = MAXSHORTINT;
00682 nodeStat->evenBotDist = MAXSHORTINT;
00683 nodeStat->oddBotDist = MAXSHORTINT;
00684 nodeStat->regResult = NULL;
00685 nodeStat->compResult = NULL;
00686
00687
00688
00689 if (Cudd_IsComplement(child)) {
00690 nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
00691 } else {
00692 nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
00693 }
00694
00695
00696 if (st_insert(pathTable, (char *)regChild,
00697 (char *)nodeStat) == ST_OUT_OF_MEM) {
00698 memOut = 1;
00699 for (i = 0; i <= nodeDistPage; i++)
00700 FREE(nodeDistPages[i]);
00701 FREE(nodeDistPages);
00702 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
00703 FREE(queuePages);
00704 st_free_table(pathTable);
00705 return;
00706 }
00707
00708
00709
00710
00711
00712
00713
00714 if (queuePageIndex == queuePageSize) ResizeQueuePages();
00715 if (memOut) {
00716 for (i = 0; i <= nodeDistPage; i++)
00717 FREE(nodeDistPages[i]);
00718 FREE(nodeDistPages);
00719 st_free_table(pathTable);
00720 return;
00721 }
00722 *(currentQueuePage + queuePageIndex) = child;
00723 queuePageIndex++;
00724
00725 childrenCount++;
00726 } else {
00727
00728
00729 if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist ==
00730 MAXSHORTINT)) || ((!Cudd_IsComplement(child)) &&
00731 (nodeStat->evenTopDist == MAXSHORTINT))) {
00732
00733 if (queuePageIndex == queuePageSize) ResizeQueuePages();
00734 if (memOut) {
00735 for (i = 0; i <= nodeDistPage; i++)
00736 FREE(nodeDistPages[i]);
00737 FREE(nodeDistPages);
00738 st_free_table(pathTable);
00739 return;
00740
00741 }
00742 *(currentQueuePage + queuePageIndex) = child;
00743 queuePageIndex++;
00744
00745
00746 if (Cudd_IsComplement(child)) {
00747 nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
00748 } else {
00749 nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
00750 }
00751 childrenCount++;
00752 }
00753
00754 }
00755 }
00756 processingDone--;
00757 }
00758 }
00759
00760 #ifdef DD_DEBUG
00761 assert(queuePages[parentPage] == childPage);
00762 assert(parentQueueIndex == childQueueIndex);
00763 #endif
00764
00765 if (childrenCount != 0) {
00766 topLen++;
00767 childPage = currentQueuePage;
00768 childQueueIndex = queuePageIndex;
00769 CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen,
00770 childPage, childQueueIndex, childrenCount, fp);
00771 }
00772
00773 return;
00774
00775 }
00776
00777
00797 static int
00798 CreateBotDist(
00799 DdNode * node ,
00800 st_table * pathTable ,
00801 unsigned int * pathLengthArray ,
00802 FILE *fp )
00803 {
00804 DdNode *N, *Nv, *Nnv;
00805 DdNode *realChild;
00806 DdNode *child, *regChild;
00807 NodeDist_t *nodeStat, *nodeStatChild;
00808 unsigned int oddLen, evenLen, pathLength;
00809 DdHalfWord botDist;
00810 int processingDone;
00811
00812 if (Cudd_IsConstant(node))
00813 return(1);
00814 N = Cudd_Regular(node);
00815
00816
00817
00818 if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) {
00819 fprintf(fp, "Something wrong, the entry doesn't exist\n");
00820 return(0);
00821 }
00822
00823
00824 if ((nodeStat->oddTopDist != MAXSHORTINT) &&
00825 (nodeStat->oddBotDist != MAXSHORTINT))
00826 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
00827 else
00828 oddLen = MAXSHORTINT;
00829
00830
00831 if (!((nodeStat->evenTopDist == MAXSHORTINT) ||
00832 (nodeStat->evenBotDist == MAXSHORTINT)))
00833 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
00834 else
00835 evenLen = MAXSHORTINT;
00836
00837
00838 pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
00839
00840 Nv = Cudd_T(N);
00841 Nnv = Cudd_E(N);
00842
00843
00844 processingDone = 0;
00845 while (processingDone != 2) {
00846 if (!processingDone) {
00847 child = Nv;
00848 } else {
00849 child = Nnv;
00850 }
00851
00852 realChild = Cudd_NotCond(child, Cudd_IsComplement(node));
00853 regChild = Cudd_Regular(child);
00854 if (Cudd_IsConstant(realChild)) {
00855
00856
00857
00858 if (Cudd_IsComplement(child))
00859 nodeStat->oddBotDist = 1;
00860 else
00861 nodeStat->evenBotDist = 1;
00862 } else {
00863
00864 if (!st_lookup(pathTable, (char *) regChild,
00865 (char **)&nodeStatChild)) {
00866 fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n");
00867 return(0);
00868 }
00869
00870 if (nodeStatChild->oddBotDist == MAXSHORTINT) {
00871 if (nodeStatChild->evenBotDist == MAXSHORTINT) {
00872 if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp))
00873 return(0);
00874 } else {
00875 fprintf(fp, "Something wrong, both bot nodeStats should be there\n");
00876 return(0);
00877 }
00878 }
00879
00880
00881
00882
00883 if (Cudd_IsComplement(child)) {
00884
00885
00886
00887
00888
00889
00890 if (nodeStatChild->oddBotDist != MAXSHORTINT)
00891 botDist = nodeStatChild->oddBotDist + 1;
00892 else
00893 botDist = MAXSHORTINT;
00894 if (nodeStat->evenBotDist > botDist )
00895 nodeStat->evenBotDist = botDist;
00896
00897 if (nodeStatChild->evenBotDist != MAXSHORTINT)
00898 botDist = nodeStatChild->evenBotDist + 1;
00899 else
00900 botDist = MAXSHORTINT;
00901 if (nodeStat->oddBotDist > botDist)
00902 nodeStat->oddBotDist = botDist;
00903
00904 } else {
00905
00906
00907
00908
00909
00910
00911 if (nodeStatChild->evenBotDist != MAXSHORTINT)
00912 botDist = nodeStatChild->evenBotDist + 1;
00913 else
00914 botDist = MAXSHORTINT;
00915 if (nodeStat->evenBotDist > botDist)
00916 nodeStat->evenBotDist = botDist;
00917
00918 if (nodeStatChild->oddBotDist != MAXSHORTINT)
00919 botDist = nodeStatChild->oddBotDist + 1;
00920 else
00921 botDist = MAXSHORTINT;
00922 if (nodeStat->oddBotDist > botDist)
00923 nodeStat->oddBotDist = botDist;
00924 }
00925 }
00926 processingDone++;
00927 }
00928
00929
00930 if ((nodeStat->oddTopDist != MAXSHORTINT) &&
00931 (nodeStat->oddBotDist != MAXSHORTINT))
00932 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
00933 else
00934 oddLen = MAXSHORTINT;
00935
00936 if ((nodeStat->evenTopDist != MAXSHORTINT) &&
00937 (nodeStat->evenBotDist != MAXSHORTINT))
00938 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
00939 else
00940 evenLen = MAXSHORTINT;
00941
00942
00943
00944 if (oddLen < pathLength ) {
00945 if (pathLength != MAXSHORTINT)
00946 pathLengthArray[pathLength]--;
00947 if (oddLen != MAXSHORTINT)
00948 pathLengthArray[oddLen]++;
00949 pathLength = oddLen;
00950 }
00951 if (evenLen < pathLength ) {
00952 if (pathLength != MAXSHORTINT)
00953 pathLengthArray[pathLength]--;
00954 if (evenLen != MAXSHORTINT)
00955 pathLengthArray[evenLen]++;
00956 }
00957
00958 return(1);
00959
00960 }
00961
00962
00981 static st_table *
00982 CreatePathTable(
00983 DdNode * node ,
00984 unsigned int * pathLengthArray ,
00985 FILE *fp )
00986 {
00987
00988 st_table *pathTable;
00989 NodeDist_t *nodeStat;
00990 DdHalfWord topLen;
00991 DdNode *N;
00992 int i, numParents;
00993 int insertValue;
00994 DdNode **childPage;
00995 int parentPage;
00996 int childQueueIndex, parentQueueIndex;
00997
00998
00999 pathTable = st_init_table(st_ptrcmp,st_ptrhash);
01000
01001
01002 maxNodeDistPages = INITIAL_PAGES;
01003 nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages);
01004 if (nodeDistPages == NULL) {
01005 goto OUT_OF_MEM;
01006 }
01007 nodeDistPage = 0;
01008 currentNodeDistPage = nodeDistPages[nodeDistPage] =
01009 ALLOC(NodeDist_t, nodeDistPageSize);
01010 if (currentNodeDistPage == NULL) {
01011 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
01012 FREE(nodeDistPages);
01013 goto OUT_OF_MEM;
01014 }
01015 nodeDistPageIndex = 0;
01016
01017
01018 maxQueuePages = INITIAL_PAGES;
01019 queuePages = ALLOC(DdNode **, maxQueuePages);
01020 if (queuePages == NULL) {
01021 goto OUT_OF_MEM;
01022 }
01023 queuePage = 0;
01024 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize);
01025 if (currentQueuePage == NULL) {
01026 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01027 FREE(queuePages);
01028 goto OUT_OF_MEM;
01029 }
01030 queuePageIndex = 0;
01031
01032
01033 parentPage = queuePage;
01034 parentQueueIndex = queuePageIndex;
01035 topLen = 0;
01036 *(currentQueuePage + queuePageIndex) = node;
01037 queuePageIndex++;
01038 childPage = currentQueuePage;
01039 childQueueIndex = queuePageIndex;
01040
01041 N = Cudd_Regular(node);
01042
01043 if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages();
01044 if (memOut) {
01045 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
01046 FREE(nodeDistPages);
01047 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01048 FREE(queuePages);
01049 st_free_table(pathTable);
01050 goto OUT_OF_MEM;
01051 }
01052
01053 nodeStat = currentNodeDistPage + nodeDistPageIndex;
01054 nodeDistPageIndex++;
01055
01056 nodeStat->oddTopDist = MAXSHORTINT;
01057 nodeStat->evenTopDist = MAXSHORTINT;
01058 nodeStat->evenBotDist = MAXSHORTINT;
01059 nodeStat->oddBotDist = MAXSHORTINT;
01060 nodeStat->regResult = NULL;
01061 nodeStat->compResult = NULL;
01062
01063 insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat);
01064 if (insertValue == ST_OUT_OF_MEM) {
01065 memOut = 1;
01066 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
01067 FREE(nodeDistPages);
01068 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01069 FREE(queuePages);
01070 st_free_table(pathTable);
01071 goto OUT_OF_MEM;
01072 } else if (insertValue == 1) {
01073 fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n");
01074 return(NULL);
01075 }
01076
01077 if (Cudd_IsComplement(node)) {
01078 nodeStat->oddTopDist = 0;
01079 } else {
01080 nodeStat->evenTopDist = 0;
01081 }
01082 numParents = 1;
01083
01084
01085
01086 #ifdef DD_DEBUG
01087 numCalls = 0;
01088 #endif
01089 CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen,
01090 childPage, childQueueIndex, numParents, fp);
01091 if (memOut) {
01092 fprintf(fp, "Out of Memory and cant count path lengths\n");
01093 goto OUT_OF_MEM;
01094 }
01095
01096 #ifdef DD_DEBUG
01097 numCalls = 0;
01098 #endif
01099
01100
01101
01102 if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL);
01103
01104
01105 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
01106 FREE(queuePages);
01107 return(pathTable);
01108
01109 OUT_OF_MEM:
01110 (void) fprintf(fp, "Out of Memory, cannot allocate pages\n");
01111 memOut = 1;
01112 return(NULL);
01113
01114 }
01115
01116
01133 static unsigned int
01134 AssessPathLength(
01135 unsigned int * pathLengthArray ,
01136 int threshold ,
01137 int numVars ,
01138 unsigned int * excess ,
01139 FILE *fp )
01140 {
01141 unsigned int i, maxpath;
01142 int temp;
01143
01144 temp = threshold;
01145 i = 0;
01146 maxpath = 0;
01147
01148
01149
01150 while ((i < (unsigned) numVars+1) && (temp > 0)) {
01151 if (pathLengthArray[i] > 0) {
01152 maxpath = i;
01153 temp = temp - pathLengthArray[i];
01154 }
01155 i++;
01156 }
01157
01158 if (temp >= 0) {
01159 maxpath++;
01160
01161 *excess = 0;
01162 } else {
01163
01164 *excess = temp + pathLengthArray[maxpath];
01165 }
01166
01167 if (maxpath == 0) {
01168 fprintf(fp, "Path Length array seems to be all zeroes, check\n");
01169 }
01170 return(maxpath);
01171
01172 }
01173
01174
01217 static DdNode *
01218 BuildSubsetBdd(
01219 DdManager * dd ,
01220 st_table * pathTable ,
01221 DdNode * node ,
01222 struct AssortedInfo * info ,
01223 st_table * subsetNodeTable )
01224 {
01225 DdNode *N, *Nv, *Nnv;
01226 DdNode *ThenBranch, *ElseBranch, *childBranch;
01227 DdNode *child, *regChild, *regNnv, *regNv;
01228 NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv;
01229 DdNode *neW, *topv, *regNew;
01230 char *entry;
01231 unsigned int topid;
01232 unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength;
01233 unsigned int NvBotDist, NnvBotDist;
01234 int tiebreakChild;
01235 int processingDone, thenDone, elseDone;
01236
01237
01238 #ifdef DD_DEBUG
01239 numCalls++;
01240 #endif
01241 if (Cudd_IsConstant(node))
01242 return(node);
01243
01244 N = Cudd_Regular(node);
01245
01246 if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) {
01247 (void) fprintf(dd->err, "Something wrong, node must be in table \n");
01248 dd->errorCode = CUDD_INTERNAL_ERROR;
01249 return(NULL);
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 if (Cudd_IsComplement(node)) {
01261 if (nodeStat->compResult != NULL) {
01262 #ifdef DD_DEBUG
01263 hits++;
01264 #endif
01265 return(nodeStat->compResult);
01266 }
01267 } else {
01268
01269
01270
01271 if (nodeStat->regResult != NULL) {
01272 #ifdef DD_DEBUG
01273 hits++;
01274 #endif
01275 return(nodeStat->regResult);
01276 }
01277 }
01278
01279
01280
01281 Nv = Cudd_T(N);
01282 Nnv = Cudd_E(N);
01283
01284 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
01285 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
01286
01287
01288 processingDone = 0;
01289
01290 thenDone = 0;
01291 ThenBranch = NULL;
01292
01293 elseDone = 0;
01294 ElseBranch = NULL;
01295
01296 if (Cudd_IsConstant(Nv)) {
01297
01298 if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) {
01299 info->findShortestPath = 0;
01300 }
01301
01302 ThenBranch = Nv;
01303 cuddRef(ThenBranch);
01304 if (ThenBranch == NULL) {
01305 return(NULL);
01306 }
01307
01308 thenDone++;
01309 processingDone++;
01310 NvBotDist = MAXSHORTINT;
01311 } else {
01312
01313 regNv = Cudd_Regular(Nv);
01314
01315 if (!st_lookup(pathTable, (char *)regNv, (char **)&nodeStatNv) ) {
01316 (void) fprintf(dd->err, "Something wrong, node must be in table\n");
01317 dd->errorCode = CUDD_INTERNAL_ERROR;
01318 return(NULL);
01319 }
01320
01321 if ((nodeStatNv->oddTopDist != MAXSHORTINT) &&
01322 (nodeStatNv->oddBotDist != MAXSHORTINT)) {
01323 oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist);
01324 } else {
01325 oddLen = MAXSHORTINT;
01326 }
01327
01328 if ((nodeStatNv->evenTopDist != MAXSHORTINT) &&
01329 (nodeStatNv->evenBotDist != MAXSHORTINT)) {
01330 evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist);
01331 } else {
01332 evenLen = MAXSHORTINT;
01333 }
01334
01335 NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
01336 NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist:
01337 nodeStatNv->evenBotDist;
01338 }
01339
01340 if (Cudd_IsConstant(Nnv)) {
01341
01342 if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) {
01343 info->findShortestPath = 0;
01344 }
01345
01346 ElseBranch = Nnv;
01347 cuddRef(ElseBranch);
01348 if (ElseBranch == NULL) {
01349 return(NULL);
01350 }
01351
01352 elseDone++;
01353 processingDone++;
01354 NnvBotDist = MAXSHORTINT;
01355 } else {
01356
01357 regNnv = Cudd_Regular(Nnv);
01358
01359 if (!st_lookup(pathTable, (char *)regNnv, (char **)&nodeStatNnv) ) {
01360 (void) fprintf(dd->err, "Something wrong, node must be in table\n");
01361 dd->errorCode = CUDD_INTERNAL_ERROR;
01362 return(NULL);
01363 }
01364
01365 if ((nodeStatNnv->oddTopDist != MAXSHORTINT) &&
01366 (nodeStatNnv->oddBotDist != MAXSHORTINT)) {
01367 oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist);
01368 } else {
01369 oddLen = MAXSHORTINT;
01370 }
01371
01372 if ((nodeStatNnv->evenTopDist != MAXSHORTINT) &&
01373 (nodeStatNnv->evenBotDist != MAXSHORTINT)) {
01374 evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist);
01375 } else {
01376 evenLen = MAXSHORTINT;
01377 }
01378
01379 NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
01380 NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist :
01381 nodeStatNnv->evenBotDist;
01382 }
01383
01384 tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0;
01385
01386 while (processingDone != 2) {
01387 if (!processingDone) {
01388
01389
01390
01391
01392 if ((NvPathLength < NnvPathLength) ||
01393 ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) {
01394 child = Nv;
01395 regChild = regNv;
01396 thenDone = 1;
01397 childPathLength = NvPathLength;
01398 } else {
01399 child = Nnv;
01400 regChild = regNnv;
01401 elseDone = 1;
01402 childPathLength = NnvPathLength;
01403 }
01404 } else {
01405
01406 if (thenDone) {
01407 child = Nnv;
01408 regChild = regNnv;
01409 elseDone = 1;
01410 childPathLength = NnvPathLength;
01411 } else {
01412 child = Nv;
01413 regChild = regNv;
01414 thenDone = 1;
01415 childPathLength = NvPathLength;
01416 }
01417 }
01418
01419
01420
01421
01422 if (childPathLength > info->maxpath) {
01423
01424 childBranch = zero;
01425 } else {
01426 if (childPathLength < info->maxpath) {
01427 if (info->findShortestPath) {
01428 info->findShortestPath = 0;
01429 }
01430 childBranch = BuildSubsetBdd(dd, pathTable, child, info,
01431 subsetNodeTable);
01432
01433 } else {
01434
01435
01436 if (st_lookup(info->maxpathTable, (char *)regChild,
01437 (char **)&entry)) {
01438
01439
01440 if (info->findShortestPath) {
01441 info->findShortestPath = 0;
01442 }
01443 childBranch = BuildSubsetBdd(dd, pathTable, child, info,
01444 subsetNodeTable);
01445 } else {
01446
01447
01448
01449
01450 if (info->thresholdReached <= 0) {
01451 if (info->findShortestPath) {
01452 if (st_insert(info->maxpathTable, (char *)regChild,
01453 (char *)NIL(char)) == ST_OUT_OF_MEM) {
01454 memOut = 1;
01455 (void) fprintf(dd->err, "OUT of memory\n");
01456 info->thresholdReached = 0;
01457 childBranch = zero;
01458 } else {
01459 info->thresholdReached--;
01460 childBranch = BuildSubsetBdd(dd, pathTable,
01461 child, info,subsetNodeTable);
01462 }
01463 } else {
01464
01465 childBranch = zero;
01466 }
01467 } else {
01468
01469 if (st_insert(info->maxpathTable, (char *)regChild,
01470 (char *)NIL(char)) == ST_OUT_OF_MEM) {
01471 memOut = 1;
01472 (void) fprintf(dd->err, "OUT of memory\n");
01473 info->thresholdReached = 0;
01474 childBranch = zero;
01475 } else {
01476 info->thresholdReached--;
01477 if (info->thresholdReached <= 0) {
01478 info->findShortestPath = 1;
01479 }
01480 childBranch = BuildSubsetBdd(dd, pathTable,
01481 child, info, subsetNodeTable);
01482
01483 }
01484 }
01485 }
01486 }
01487 }
01488 if (childBranch == NULL) {
01489
01490 if (ThenBranch != NULL) {
01491 Cudd_RecursiveDeref(dd, ThenBranch);
01492 ThenBranch = NULL;
01493 }
01494 if (ElseBranch != NULL) {
01495 Cudd_RecursiveDeref(dd, ElseBranch);
01496 ElseBranch = NULL;
01497 }
01498 return(NULL);
01499 }
01500
01501 cuddRef(childBranch);
01502
01503 if (child == Nv) {
01504 ThenBranch = childBranch;
01505 } else {
01506 ElseBranch = childBranch;
01507 }
01508 processingDone++;
01509
01510 }
01511
01512 info->findShortestPath = 0;
01513 topid = Cudd_NodeReadIndex(N);
01514 topv = Cudd_ReadVars(dd, topid);
01515 cuddRef(topv);
01516 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
01517 if (neW != NULL) {
01518 cuddRef(neW);
01519 }
01520 Cudd_RecursiveDeref(dd, topv);
01521 Cudd_RecursiveDeref(dd, ThenBranch);
01522 Cudd_RecursiveDeref(dd, ElseBranch);
01523
01524
01525
01526 if (subsetNodeTable != NIL(st_table)) {
01527
01528 regNew = Cudd_Regular(neW);
01529
01530
01531
01532 if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) {
01533 if (!Cudd_IsConstant(regNew)) {
01534 if (st_insert(subsetNodeTable, (char *)regNew,
01535 (char *)NULL) == ST_OUT_OF_MEM) {
01536 (void) fprintf(dd->err, "Out of memory\n");
01537 return (NULL);
01538 }
01539 if (st_count(subsetNodeTable) > info->threshold) {
01540 info->thresholdReached = 0;
01541 }
01542 }
01543 }
01544 }
01545
01546
01547 if (neW == NULL) {
01548 return(NULL);
01549 } else {
01550
01551 if (Cudd_IsComplement(node)) {
01552 nodeStat->compResult = neW;
01553 cuddRef(nodeStat->compResult);
01554
01555
01556
01557
01558 if (neW == node) {
01559 #ifdef DD_DEBUG
01560 thishit++;
01561 #endif
01562
01563
01564
01565
01566 if (nodeStat->regResult != NULL) {
01567 Cudd_RecursiveDeref(dd, nodeStat->regResult);
01568 }
01569 nodeStat->regResult = Cudd_Not(neW);
01570 cuddRef(nodeStat->regResult);
01571 }
01572
01573 } else {
01574 nodeStat->regResult = neW;
01575 cuddRef(nodeStat->regResult);
01576 if (neW == node) {
01577 #ifdef DD_DEBUG
01578 thishit++;
01579 #endif
01580 if (nodeStat->compResult != NULL) {
01581 Cudd_RecursiveDeref(dd, nodeStat->compResult);
01582 }
01583 nodeStat->compResult = Cudd_Not(neW);
01584 cuddRef(nodeStat->compResult);
01585 }
01586 }
01587
01588 cuddDeref(neW);
01589 return(neW);
01590 }
01591 }
01592
01593
01605 static enum st_retval
01606 stPathTableDdFree(
01607 char * key,
01608 char * value,
01609 char * arg)
01610 {
01611 NodeDist_t *nodeStat;
01612 DdManager *dd;
01613
01614 nodeStat = (NodeDist_t *)value;
01615 dd = (DdManager *)arg;
01616 if (nodeStat->regResult != NULL) {
01617 Cudd_RecursiveDeref(dd, nodeStat->regResult);
01618 }
01619 if (nodeStat->compResult != NULL) {
01620 Cudd_RecursiveDeref(dd, nodeStat->compResult);
01621 }
01622 return(ST_CONTINUE);
01623
01624 }