00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "bddBdd.h"
00032
00033 #include <vector>
00034 #include <iostream>
00035 #include <set>
00036
00037 #include <climits>
00038
00039 bddNode* bddBdd::mNodes = 0;
00040 unsigned bddBdd::mMaxNodeNr;
00041 unsigned bddBdd::mFree;
00042
00043 multiset<unsigned> bddBdd::mExtRefs;
00044
00045 unsigned* bddBdd::mUniqueHash = 0;
00046 unsigned bddBdd::mUniqueHBitNr;
00047 bddBinEntry* bddBdd::mBinCache = 0;
00048 unsigned bddBdd::mBinCBitNr;
00049 bddStatEntry* bddBdd::mStatCache = 0;
00050 unsigned bddBdd::mStatCBitNr;
00051
00053 unsigned bddBdd::mRenameCnt = 0;
00054
00057 inline void
00058 bddBdd::normalize(unsigned& p1, unsigned& p2)
00059 {
00060 if (p1 > p2) {
00061 unsigned tmp = p1;
00062 p1 = p2;
00063 p2 = tmp;
00064 }
00065 }
00066
00068 inline unsigned
00069 bddBdd::hash (unsigned i, unsigned hashBitNr)
00070 {
00071 unsigned mask = (1u << hashBitNr) - 1;
00072 return i & mask;
00073 }
00074
00075 inline unsigned
00076 bddBdd::hash(unsigned i, unsigned j, unsigned k, unsigned hashBitNr)
00077 {
00078 unsigned mask = (1u << hashBitNr) - 1;
00079 j ^= 0x55555555;
00080 return (i +
00081 (j<<(hashBitNr>>1)) + (j>>(hashBitNr>>1)) +
00082 (k<<(hashBitNr>>2)) + (k>>(hashBitNr>>2))) & mask;
00083 }
00084
00085
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00107 void
00108 bddBdd::mark(unsigned pRoot)
00109 {
00110 if(!mNodes[pRoot].mark)
00111 {
00112 mNodes[pRoot].mark = 1;
00113 mark(mNodes[pRoot].low);
00114 mark(mNodes[pRoot].high);
00115 }
00116 }
00117
00120 void
00121 bddBdd::unMark(unsigned pRoot)
00122 {
00123 if(mNodes[pRoot].mark && pRoot != 0 && pRoot != 1)
00124 {
00125 mNodes[pRoot].mark = 0;
00126 unMark(mNodes[pRoot].low);
00127 unMark(mNodes[pRoot].high);
00128 }
00129 }
00130
00134 void
00135 bddBdd::gc()
00136 {
00137
00138 for(multiset<unsigned>::iterator lIt = mExtRefs.begin();
00139 lIt != mExtRefs.end();
00140 lIt++)
00141 {
00142 mark(*lIt);
00143 }
00144
00145
00146 memset(mUniqueHash, 0, (1u << mUniqueHBitNr) * sizeof(unsigned));
00147 memset(mStatCache, 0, (1u << mStatCBitNr) * sizeof(bddStatEntry));
00148 memset(mBinCache, 0, (1u << mBinCBitNr) * sizeof(bddBinEntry));
00149
00150 mFree = 0;
00151 for(unsigned lCnt = mMaxNodeNr-1; lCnt >= 2; --lCnt)
00152 {
00153 if(!mNodes[lCnt].mark)
00154 {
00155
00156 mNodes[lCnt].low = mFree;
00157 mFree = lCnt;
00158 }
00159 else
00160 {
00161 mNodes[lCnt].mark = 0;
00162
00163 unsigned lHashIndex = hash(
00164 mNodes[lCnt].var, mNodes[lCnt].low, mNodes[lCnt].high, mUniqueHBitNr);
00165 mNodes[lCnt].next = mUniqueHash[lHashIndex];
00166 mUniqueHash[lHashIndex] = lCnt;
00167 }
00168 }
00169 }
00170
00171
00175 unsigned
00176 bddBdd::insert(unsigned pVar, unsigned pLow, unsigned pHigh)
00177 {
00178 unsigned lHashIndex;
00179 unsigned lResult;
00180
00181
00182 if(pHigh == pLow)
00183 {
00184 return pLow;
00185 }
00186
00187
00188 lHashIndex = hash(pVar, pLow, pHigh, mUniqueHBitNr);
00189 lResult = mUniqueHash[lHashIndex];
00190 while(lResult)
00191 {
00192 if( mNodes[lResult].var == pVar
00193 && mNodes[lResult].low == pLow
00194 && mNodes[lResult].high == pHigh)
00195 {
00196 return lResult;
00197 }
00198 lResult = mNodes[lResult].next;
00199 }
00200
00201
00202 if(mFree == 0)
00203 {
00204 throw "Error: BDD package out of memory\n";
00205 }
00206
00207 lResult = mFree;
00208 mFree = mNodes[lResult].low;
00209 mNodes[lResult].var = pVar;
00210 mNodes[lResult].low = pLow;
00211 mNodes[lResult].high = pHigh;
00212 mNodes[lResult].next = mUniqueHash[lHashIndex];
00213 mUniqueHash[lHashIndex] = lResult;
00214
00215 return lResult;
00216 }
00217
00220 bool
00221 bddBdd::testVars_(unsigned pRoot,
00222 unsigned pVarIdFirst,
00223 unsigned pVarIdLast)
00224 {
00225
00226 if(mNodes[pRoot].mark)
00227 {
00228 return false;
00229 }
00230 mNodes[pRoot].mark = 1;
00231
00232
00233 if(mNodes[pRoot].var > pVarIdLast)
00234 {
00235 return false;
00236 }
00237
00238
00239 if( mNodes[pRoot].var <= pVarIdLast
00240 && mNodes[pRoot].var >= pVarIdFirst )
00241 {
00242 return true;
00243 }
00244
00245
00246 if( testVars_(mNodes[pRoot].low, pVarIdFirst, pVarIdLast) )
00247 {
00248 return true;
00249 }
00250
00251 return testVars_(mNodes[pRoot].high, pVarIdFirst, pVarIdLast);
00252 }
00253
00257 double
00258 bddBdd::getTupleNr_(unsigned pRoot, unsigned pVar, unsigned pMaxVar)
00259 {
00260
00261 if(pVar > pMaxVar)
00262 {
00263 return (pRoot == 0 ? 0.0 : 1.0);
00264 }
00265
00266
00267
00268
00269 if(pVar < mNodes[pRoot].var)
00270 {
00271 return 2 * getTupleNr_(pRoot, pVar + 1, pMaxVar);
00272 }
00273
00274
00275 assert(pVar == mNodes[pRoot].var);
00276
00277
00278
00279 unsigned lCacheIndex = hash(pRoot, mStatCBitNr);
00280 if(mStatCache[lCacheIndex].root == pRoot)
00281 {
00282 return mStatCache[lCacheIndex].result;
00283 }
00284
00285 mStatCache[lCacheIndex].result
00286 = getTupleNr_(mNodes[pRoot].low, pVar + 1, pMaxVar)
00287 + getTupleNr_(mNodes[pRoot].high, pVar + 1, pMaxVar);
00288 mStatCache[lCacheIndex].root = pRoot;
00289
00290 return mStatCache[lCacheIndex].result;
00291 }
00292
00294 unsigned
00295 bddBdd::getTuple_(unsigned pRoot, unsigned pVar, unsigned pMaxVar)
00296 {
00297
00298 if(pVar > pMaxVar)
00299 {
00300 return 0;
00301 }
00302
00303
00304
00305
00306 if(pVar < mNodes[pRoot].var)
00307 {
00308 return getTuple_(pRoot, pVar + 1, pMaxVar);
00309 }
00310
00311 if(pVar > mNodes[pRoot].var)
00312 {
00313 if (mNodes[pRoot].low != 0) {
00314 return getTuple_(mNodes[pRoot].low, pVar, pMaxVar);
00315 } else {
00316 return getTuple_(mNodes[pRoot].high, pVar, pMaxVar);
00317 }
00318 }
00319
00320
00321
00322 if (mNodes[pRoot].low != 0) {
00323 return getTuple_(mNodes[pRoot].low, pVar + 1, pMaxVar);
00324 } else {
00325 return getTuple_(mNodes[pRoot].high, pVar + 1, pMaxVar)
00326 + (1 << (pMaxVar - pVar));
00327 }
00328 }
00329
00332 unsigned
00333 bddBdd::getNodeNr_(unsigned pRoot)
00334 {
00335
00336 if(mNodes[pRoot].mark)
00337 {
00338 return 0;
00339 }
00340 mNodes[pRoot].mark = 1;
00341
00342 return getNodeNr_(mNodes[pRoot].low) + getNodeNr_(mNodes[pRoot].high) + 1;
00343 }
00344
00346 void
00347 bddBdd::getNodesPerVarId_(unsigned pRoot,
00348 map<unsigned, unsigned>& pBddNodesPerVar)
00349 {
00350
00351 if( !mNodes[pRoot].mark )
00352 {
00353 mNodes[pRoot].mark = 1;
00354 if ( pBddNodesPerVar.find(mNodes[pRoot].var) != pBddNodesPerVar.end() ) {
00355 ++ pBddNodesPerVar[mNodes[pRoot].var];
00356 } else {
00357 pBddNodesPerVar[mNodes[pRoot].var] = 1;
00358 }
00359 getNodesPerVarId_(mNodes[pRoot].low, pBddNodesPerVar);
00360 getNodesPerVarId_(mNodes[pRoot].high, pBddNodesPerVar);
00361 }
00362 }
00363
00365 void
00366 bddBdd::getGraph_(unsigned pRoot,
00367 multimap<unsigned,bddGraphNode>& pGraph)
00368 {
00369
00370 if( !mNodes[pRoot].mark )
00371 {
00372 mNodes[pRoot].mark = 1;
00373
00374 bddGraphNode node;
00375 node.id = pRoot;
00376 node.var = mNodes[pRoot].var;
00377 node.low = mNodes[pRoot].low;
00378 node.high = mNodes[pRoot].high;
00379 pGraph.insert( pair<unsigned,bddGraphNode>(node.var, node) );
00380
00381 getGraph_(mNodes[pRoot].low, pGraph);
00382 getGraph_(mNodes[pRoot].high, pGraph);
00383 }
00384 }
00385
00387 void
00388 bddBdd::print_(ostream& pS, unsigned pRoot)
00389 {
00390 if(pRoot == 1)
00391 {
00392 cout << 'T';
00393 }
00394 else
00395 {
00396 if(pRoot == 0)
00397 {
00398 cout << 'F';
00399 }
00400 else
00401 {
00402 cout << '(';
00403 print_(pS, mNodes[pRoot].low);
00404 cout << ' ' << mNodes[pRoot].var << ' ';
00405 print_(pS, mNodes[pRoot].high);
00406 cout << ')';
00407 }
00408 }
00409 }
00410
00412 bool
00413 bddBdd::setContains_(unsigned pRoot1, unsigned pRoot2)
00414 {
00415 unsigned lCacheIndex;
00416 unsigned lResult;
00417
00418
00419 if(pRoot1 == 1)
00420 {
00421 return true;
00422 }
00423 if(pRoot2 == 0)
00424 {
00425 return true;
00426 }
00427 if(pRoot1 == pRoot2)
00428 {
00429 return true;
00430 }
00431 if(pRoot1 == 0)
00432 {
00433 return false;
00434 }
00435 if(pRoot2 == 1)
00436 {
00437 return false;
00438 }
00439
00440
00441 lCacheIndex = hash(mSetContains, pRoot1, pRoot2, mBinCBitNr);
00442 if(mBinCache[lCacheIndex].op == mSetContains
00443 && mBinCache[lCacheIndex].root1 == pRoot1
00444 && mBinCache[lCacheIndex].root2 == pRoot2)
00445 {
00446 return mBinCache[lCacheIndex].result;
00447 }
00448
00449
00450 if(mNodes[pRoot1].var < mNodes[pRoot2].var)
00451 {
00452 lResult = setContains_(mNodes[pRoot1].low, pRoot2)
00453 && setContains_(mNodes[pRoot1].high, pRoot2);
00454 }
00455 else
00456 {
00457 if(mNodes[pRoot1].var == mNodes[pRoot2].var)
00458 {
00459 lResult = setContains_(mNodes[pRoot1].low, mNodes[pRoot2].low)
00460 && setContains_(mNodes[pRoot1].high, mNodes[pRoot2].high);
00461 }
00462 else
00463 {
00464 lResult = setContains_(pRoot1, mNodes[pRoot2].low)
00465 && setContains_(pRoot1, mNodes[pRoot2].high);
00466 }
00467 }
00468
00469
00470 mBinCache[lCacheIndex].result = lResult;
00471 mBinCache[lCacheIndex].op = mSetContains;
00472 mBinCache[lCacheIndex].root1 = pRoot1;
00473 mBinCache[lCacheIndex].root2 = pRoot2;
00474
00475 return lResult;
00476 }
00477
00478 unsigned
00479 bddBdd::complement_(unsigned pRoot)
00480 {
00481 unsigned lCacheIndex;
00482 unsigned lResult;
00483
00484 if(pRoot == 0)
00485 {
00486 return 1;
00487 }
00488 if(pRoot == 1)
00489 {
00490 return 0;
00491 }
00492
00493 lCacheIndex = hash(mComplement, pRoot, pRoot, mBinCBitNr);
00494 if(mBinCache[lCacheIndex].op == mComplement
00495 && mBinCache[lCacheIndex].root1 == pRoot)
00496 {
00497 return mBinCache[lCacheIndex].result;
00498 }
00499
00500 lResult = insert(mNodes[pRoot].var,
00501 complement_(mNodes[pRoot].low),
00502 complement_(mNodes[pRoot].high));
00503
00504 mBinCache[lCacheIndex].result = lResult;
00505 mBinCache[lCacheIndex].op = mComplement;
00506 mBinCache[lCacheIndex].root1 = pRoot;
00507
00508 return lResult;
00509 }
00510
00511 unsigned
00512 bddBdd::unite_(unsigned pRoot1, unsigned pRoot2)
00513 {
00514 if(pRoot1 == 1)
00515 {
00516 return 1;
00517 }
00518 if(pRoot2 == 1)
00519 {
00520 return 1;
00521 }
00522 if(pRoot1 == 0)
00523 {
00524 return pRoot2;
00525 }
00526 if(pRoot2 == 0)
00527 {
00528 return pRoot1;
00529 }
00530 if(pRoot1 == pRoot2)
00531 {
00532 return pRoot1;
00533 }
00534
00535 normalize(pRoot1, pRoot2);
00536 unsigned lResult;
00537 unsigned lCacheIndex = hash(mUnite, pRoot1, pRoot2, mBinCBitNr);
00538 if (mBinCache[lCacheIndex].op == mUnite
00539 && mBinCache[lCacheIndex].root1 == pRoot1
00540 && mBinCache[lCacheIndex].root2 == pRoot2)
00541 {
00542 return mBinCache[lCacheIndex].result;
00543 }
00544
00545 if(mNodes[pRoot1].var < mNodes[pRoot2].var)
00546 {
00547 lResult = insert(mNodes[pRoot1].var,
00548 unite_(mNodes[pRoot1].low, pRoot2),
00549 unite_(mNodes[pRoot1].high, pRoot2));
00550 }
00551 else
00552 {
00553 if(mNodes[pRoot1].var == mNodes[pRoot2].var)
00554 {
00555 lResult = insert(mNodes[pRoot1].var,
00556 unite_(mNodes[pRoot1].low, mNodes[pRoot2].low),
00557 unite_(mNodes[pRoot1].high, mNodes[pRoot2].high));
00558 }
00559 else
00560 {
00561 lResult = insert(mNodes[pRoot2].var,
00562 unite_(pRoot1, mNodes[pRoot2].low),
00563 unite_(pRoot1, mNodes[pRoot2].high));
00564 }
00565 }
00566
00567 mBinCache[lCacheIndex].result = lResult;
00568 mBinCache[lCacheIndex].op = mUnite;
00569 mBinCache[lCacheIndex].root1 = pRoot1;
00570 mBinCache[lCacheIndex].root2 = pRoot2;
00571
00572 return lResult;
00573 }
00574
00575 unsigned
00576 bddBdd::intersect_(unsigned pRoot1, unsigned pRoot2)
00577 {
00578 if(pRoot1 == 0)
00579 {
00580 return 0;
00581 }
00582 if(pRoot2 == 0)
00583 {
00584 return 0;
00585 }
00586 if(pRoot1 == 1)
00587 {
00588 return pRoot2;
00589 }
00590 if(pRoot2 == 1)
00591 {
00592 return pRoot1;
00593 }
00594 if(pRoot1 == pRoot2)
00595 {
00596 return pRoot1;
00597 }
00598
00599 normalize(pRoot1, pRoot2);
00600 unsigned lResult;
00601 unsigned lCacheIndex = hash(mIntersect, pRoot1, pRoot2, mBinCBitNr);
00602 if(mBinCache[lCacheIndex].op == mIntersect
00603 && mBinCache[lCacheIndex].root1 == pRoot1
00604 && mBinCache[lCacheIndex].root2 == pRoot2)
00605 {
00606 return mBinCache[lCacheIndex].result;
00607 }
00608
00609 if(mNodes[pRoot1].var < mNodes[pRoot2].var)
00610 {
00611 lResult = insert(mNodes[pRoot1].var,
00612 intersect_(mNodes[pRoot1].low, pRoot2),
00613 intersect_(mNodes[pRoot1].high, pRoot2));
00614 }
00615 else
00616 {
00617 if(mNodes[pRoot1].var == mNodes[pRoot2].var)
00618 {
00619 lResult = insert(mNodes[pRoot1].var,
00620 intersect_(mNodes[pRoot1].low, mNodes[pRoot2].low),
00621 intersect_(mNodes[pRoot1].high, mNodes[pRoot2].high));
00622 }
00623 else
00624 {
00625 lResult = insert(mNodes[pRoot2].var,
00626 intersect_(pRoot1, mNodes[pRoot2].low),
00627 intersect_(pRoot1, mNodes[pRoot2].high));
00628 }
00629 }
00630
00631 mBinCache[lCacheIndex].result = lResult;
00632 mBinCache[lCacheIndex].op = mIntersect;
00633 mBinCache[lCacheIndex].root1 = pRoot1;
00634 mBinCache[lCacheIndex].root2 = pRoot2;
00635
00636 return lResult;
00637 }
00638
00639 unsigned
00640 bddBdd::exists_(unsigned pRoot, unsigned pVar)
00641 {
00642 unsigned lCacheIndex;
00643 unsigned lResult;
00644
00645 if(mNodes[pRoot].var < pVar)
00646 {
00647 lCacheIndex = hash(mExists, pRoot, pVar, mBinCBitNr);
00648 if(mBinCache[lCacheIndex].op == mExists
00649 && mBinCache[lCacheIndex].root1 == pRoot
00650 && mBinCache[lCacheIndex].root2 == pVar)
00651 {
00652 return mBinCache[lCacheIndex].result;
00653 }
00654
00655 lResult = insert(mNodes[pRoot].var,
00656 exists_(mNodes[pRoot].low, pVar),
00657 exists_(mNodes[pRoot].high, pVar));
00658
00659 mBinCache[lCacheIndex].result = lResult;
00660 mBinCache[lCacheIndex].op = mExists;
00661 mBinCache[lCacheIndex].root1 = pRoot;
00662 mBinCache[lCacheIndex].root2 = pVar;
00663 }
00664 else
00665 {
00666 if(mNodes[pRoot].var == pVar)
00667 {
00668 lResult = unite_(mNodes[pRoot].low, mNodes[pRoot].high);
00669 }
00670 else
00671 {
00672 lResult = pRoot;
00673 }
00674 }
00675
00676 return lResult;
00677 }
00678
00681 unsigned
00682 bddBdd::renameVars_ (unsigned pRoot,
00683 unsigned pFirst,
00684 unsigned pLast,
00685 int pOffset)
00686 {
00687 if(pRoot == 0 || pRoot == 1)
00688 {
00689 return pRoot;
00690 }
00691
00692 if(mNodes[pRoot].var > pLast)
00693 {
00694
00695 return pRoot;
00696 }
00697
00698
00699
00700
00701 unsigned lCacheIndex = hash(mRenameVars, pRoot, mRenameCnt, mBinCBitNr);
00702 if(mBinCache[lCacheIndex].op == mRenameVars
00703 && mBinCache[lCacheIndex].root1 == pRoot
00704 && mBinCache[lCacheIndex].root2 == mRenameCnt)
00705 {
00706 return mBinCache[lCacheIndex].result;
00707 }
00708
00709 unsigned lResult;
00710 if(mNodes[pRoot].var < pFirst)
00711 {
00712
00713 lResult = insert(mNodes[pRoot].var,
00714 renameVars_(mNodes[pRoot].low, pFirst, pLast, pOffset),
00715 renameVars_(mNodes[pRoot].high, pFirst, pLast, pOffset));
00716 }
00717 else
00718 {
00719
00720 lResult = insert(mNodes[pRoot].var + pOffset,
00721 renameVars_(mNodes[pRoot].low, pFirst, pLast, pOffset),
00722 renameVars_(mNodes[pRoot].high, pFirst, pLast, pOffset));
00723 }
00724
00725
00726
00727 mBinCache[lCacheIndex].result = lResult;
00728 mBinCache[lCacheIndex].op = mRenameVars;
00729 mBinCache[lCacheIndex].root1 = pRoot;
00730 mBinCache[lCacheIndex].root2 = mRenameCnt;
00731
00732 return lResult;
00733 }
00734
00742 void
00743 bddBdd::init (unsigned pMaxNodeNr,
00744 unsigned pUniqueHBitNr,
00745 unsigned pBinCBitNr,
00746 unsigned pStatCBitNr) {
00747
00748
00749 mMaxNodeNr = pMaxNodeNr+2;
00750 mNodes = new bddNode[mMaxNodeNr];
00751
00752 mUniqueHBitNr = pUniqueHBitNr;
00753 mUniqueHash = new unsigned[1u << mUniqueHBitNr];
00754
00755 mBinCBitNr = pBinCBitNr;
00756 mBinCache = new bddBinEntry[1u << mBinCBitNr];
00757 mStatCBitNr = pStatCBitNr;
00758 mStatCache = new bddStatEntry[1u << mStatCBitNr];
00759
00760 if(!mNodes || !mUniqueHash || !mBinCache || !mStatCache)
00761 {
00762 cerr << "Error: "
00763 << "Not enough memory for initialization of BDD package." << endl;
00764 exit(EXIT_FAILURE);
00765 }
00766
00767
00768 memset(mNodes, 0, mMaxNodeNr * sizeof(bddNode));
00769 memset(mUniqueHash, 0, (1u << mUniqueHBitNr) * sizeof(unsigned));
00770 memset(mBinCache, 0, (1u << mBinCBitNr) * sizeof(bddBinEntry));
00771 memset(mStatCache, 0, (1u << mStatCBitNr) * sizeof(bddStatEntry));
00772
00773
00774 mNodes[0].var = (unsigned)-1;
00775 mNodes[0].mark = 1;
00776 mNodes[1].var = (unsigned)-1;
00777 mNodes[1].mark = 1;
00778
00779
00780 mFree = 2;
00781 for(unsigned lCnt = 2; lCnt < mMaxNodeNr-1; lCnt++)
00782 {
00783 mNodes[lCnt].low = lCnt+1;
00784 }
00785 }
00786
00788 void
00789 bddBdd::done () {
00790 delete mNodes;
00791 delete mUniqueHash;
00792 delete mBinCache;
00793 delete mStatCache;
00794 }
00795
00797 unsigned
00798 bddBdd::getReachNodeNr()
00799 {
00800 unsigned lResult;
00801
00802 lResult = 0;
00803 for(multiset<unsigned>::iterator lIt = mExtRefs.begin();
00804 lIt != mExtRefs.end();
00805 ++lIt)
00806 {
00807 lResult += getNodeNr_(*lIt);
00808 }
00809
00810 for(multiset<unsigned>::iterator lIt = mExtRefs.begin();
00811 lIt != mExtRefs.end();
00812 ++lIt)
00813 {
00814 unMark(*lIt);
00815 }
00816
00817 return lResult;
00818 }
00819
00821 unsigned
00822 bddBdd::getExtRefNr()
00823 {
00824 return mExtRefs.size();
00825 }
00826
00828 void
00829 bddBdd::analyseUniqueHash()
00830 {
00831 vector<unsigned> lListLenCnts;
00832 unsigned lListLen;
00833 unsigned lUniqueElem;
00834
00835 for(unsigned lCnt = 0; lCnt < (1u << mUniqueHBitNr); lCnt++)
00836 {
00837 lListLen = 0;
00838 lUniqueElem = mUniqueHash[lCnt];
00839 while(lUniqueElem)
00840 {
00841 lUniqueElem = mNodes[lUniqueElem].next;
00842 ++lListLen;
00843 }
00844 ++lListLenCnts[lListLen];
00845 }
00846
00847 cout << "Size of uniqueHash: " << (1u << mUniqueHBitNr) << '\n';
00848 cout << "n | number of lists of length n in uniqueHash:\n";
00849 for(unsigned lCnt = 0; lCnt < lListLenCnts.size(); lCnt++)
00850 cout << lCnt << ' ' << lListLenCnts[lCnt] << '\n';
00851 }
00852
00854 bddBdd::bddBdd(unsigned pVarId, bool pValue)
00855 {
00856 try
00857 {
00858 mRoot = bddBdd::bddBdd_(pVarId, pValue);
00859 }
00860 catch(...)
00861 {
00862 bddBdd::gc();
00863 try
00864 {
00865 mRoot = bddBdd::bddBdd_(pVarId, pValue);
00866 }
00867 catch(...)
00868 {
00869 cerr << "Error: BDD package out of memory." << endl;
00870 exit(EXIT_FAILURE);
00871 }
00872 }
00873 incRef();
00874 }
00875
00877 unsigned
00878 bddBdd::bddBdd_(unsigned pVarId, bool pValue)
00879 {
00880 if (pValue)
00881 {
00882 return insert(pVarId, 0, 1);
00883 }
00884 else
00885 {
00886 return insert(pVarId, 1, 0);
00887 }
00888 }
00889
00892 bddBdd::bddBdd(unsigned pVarId, unsigned pBitNr, unsigned pValue)
00893 {
00894 try
00895 {
00896 mRoot = bddBdd::bddBdd_(pVarId, pBitNr, pValue);
00897 }
00898 catch(...)
00899 {
00900 bddBdd::gc();
00901 try
00902 {
00903 mRoot = bddBdd::bddBdd_(pVarId, pBitNr, pValue);
00904 }
00905 catch(...)
00906 {
00907 cerr << "Error: BDD package out of memory." << endl;
00908 exit(EXIT_FAILURE);
00909 }
00910 }
00911 incRef();
00912 }
00913
00916 unsigned
00917 bddBdd::bddBdd_(unsigned pVarId, unsigned pBitNr, unsigned pValue)
00918 {
00919 unsigned result = 1;
00920
00921
00922 for (unsigned lIt = 0;
00923 lIt < pBitNr;
00924 ++lIt)
00925 {
00926 unsigned lPosition = pVarId + (pBitNr - lIt - 1);
00927 if ( (pValue & (1<<lIt)) > 0 )
00928 {
00929 result = insert(lPosition, 0, result);
00930 }
00931 else
00932 {
00933 result = insert(lPosition, result, 0);
00934 }
00935 }
00936 return result;
00937 }
00938
00940 bddBdd::bddBdd(unsigned pVarId1, unsigned pVarId2)
00941 {
00942 try
00943 {
00944 mRoot = bddBdd::bddBdd_(pVarId1, pVarId2);
00945 }
00946 catch(...)
00947 {
00948 bddBdd::gc();
00949 try
00950 {
00951 mRoot = bddBdd::bddBdd_(pVarId1, pVarId2);
00952 }
00953 catch(...)
00954 {
00955 cerr << "Error: BDD package out of memory." << endl;
00956 exit(EXIT_FAILURE);
00957 }
00958 }
00959 incRef();
00960 }
00961
00963 unsigned
00964 bddBdd::bddBdd_(unsigned pVarId1, unsigned pVarId2)
00965 {
00966 unsigned topVarId = pVarId1;
00967 unsigned bottomVarId = pVarId2;
00968 if(pVarId1 > pVarId2)
00969 {
00970 topVarId = pVarId2;
00971 bottomVarId = pVarId1;
00972 }
00973 return insert(topVarId,
00974 insert(bottomVarId, 1, 0),
00975 insert(bottomVarId, 0, 1)
00976 );
00977 }
00978
00979 bddBdd&
00980 bddBdd::operator=(const bddBdd& pBdd)
00981 {
00982 decRef();
00983 mRoot = pBdd.mRoot;
00984 incRef();
00985 return *this;
00986 }
00987
00990 bddBdd
00991 bddBdd::mkLessEqual(unsigned pVarId, unsigned pBitNr, unsigned pValue)
00992 {
00993
00994 assert(pValue < (unsigned)(1<<pBitNr));
00995
00996 unsigned lRoot;
00997 try
00998 {
00999 lRoot = bddBdd::mkLessEqual_(pVarId, pBitNr, pValue);
01000 }
01001 catch(...)
01002 {
01003 bddBdd::gc();
01004 try
01005 {
01006 lRoot = bddBdd::mkLessEqual_(pVarId, pBitNr, pValue);
01007 }
01008 catch(...)
01009 {
01010 cerr << "Error: BDD package out of memory." << endl;
01011 exit(EXIT_FAILURE);
01012 }
01013 }
01014 return bddBdd(lRoot);
01015 }
01016
01019 unsigned
01020 bddBdd::mkLessEqual_(unsigned pVarId, unsigned pBitNr, unsigned pValue)
01021 {
01022 unsigned result = 1;
01023
01024
01025 for (unsigned lIt = 0;
01026 lIt < pBitNr;
01027 ++lIt)
01028 {
01029 unsigned lPosition = pVarId + (pBitNr - lIt - 1);
01030 if ( (pValue & (1<<lIt)) > 0 )
01031 {
01032 result = insert(lPosition, 1, result);
01033 }
01034 else
01035 {
01036 result = insert(lPosition, result, 0);
01037 }
01038 }
01039 return result;
01040 }
01041
01043 unsigned
01044 bddBdd::getNodeNr() const
01045 {
01046 unsigned lResult = getNodeNr_(mRoot);
01047 unMark(mRoot);
01048 return lResult;
01049 }
01050
01052 unsigned
01053 bddBdd::getFreeNodeNr() const
01054 {
01055
01056 bddBdd::gc();
01057
01058 unsigned result = 0;
01059 unsigned lFreePos = mFree;
01060
01061 while( lFreePos != 0 )
01062 {
01063 ++result;
01064 lFreePos = mNodes[lFreePos].low;
01065 }
01066 return result;
01067 }
01068
01069
01071 void
01072 bddBdd::complement()
01073 {
01074 unsigned lResult;
01075 try
01076 {
01077 lResult = bddBdd::complement_(mRoot);
01078 }
01079 catch(...)
01080 {
01081
01082 bddBdd::gc();
01083 try
01084 {
01085 lResult = bddBdd::complement_(mRoot);
01086 }
01087 catch(...)
01088 {
01089 cerr << "Error: BDD package out of memory." << endl;
01090 exit(EXIT_FAILURE);
01091 }
01092 }
01093 decRef();
01094 mRoot = lResult;
01095 incRef();
01096 }
01097
01099 void
01100 bddBdd::unite(const bddBdd& pBdd)
01101 {
01102 unsigned lResult;
01103 try
01104 {
01105 lResult = bddBdd::unite_(mRoot, pBdd.mRoot);
01106 }
01107 catch(...)
01108 {
01109 bddBdd::gc();
01110 try
01111 {
01112 lResult = bddBdd::unite_(mRoot, pBdd.mRoot);
01113 }
01114 catch(...)
01115 {
01116 cerr << "Error: BDD package out of memory." << endl;
01117 exit(EXIT_FAILURE);
01118 }
01119 }
01120 decRef();
01121 mRoot = lResult;
01122 incRef();
01123 }
01124
01126 void
01127 bddBdd::intersect(const bddBdd& pBdd)
01128 {
01129 unsigned lResult;
01130 try
01131 {
01132 lResult = bddBdd::intersect_(mRoot, pBdd.mRoot);
01133 }
01134 catch(...)
01135 {
01136 bddBdd::gc();
01137 try
01138 {
01139 lResult = bddBdd::intersect_(mRoot, pBdd.mRoot);
01140 }
01141 catch(...)
01142 {
01143 cerr << "Error: BDD package out of memory." << endl;
01144 exit(EXIT_FAILURE);
01145 }
01146 }
01147 decRef();
01148 mRoot = lResult;
01149 incRef();
01150 }
01151
01153 void
01154 bddBdd::exists(unsigned pVar)
01155 {
01156 unsigned lResult;
01157 try
01158 {
01159 lResult = bddBdd::exists_(mRoot, pVar);
01160 }
01161 catch(...)
01162 {
01163 bddBdd::gc();
01164 try
01165 {
01166 lResult = bddBdd::exists_(mRoot, pVar);
01167 }
01168 catch(...)
01169 {
01170 cerr << "Error: BDD package out of memory." << endl;
01171 exit(EXIT_FAILURE);
01172 }
01173 }
01174 decRef();
01175 mRoot = lResult;
01176 incRef();
01177 }
01178
01181 void
01182 bddBdd::renameVars(unsigned pFirst, unsigned pLast, int pOffset)
01183 {
01184 unsigned lResult;
01185 try
01186 {
01187 lResult = bddBdd::renameVars_(mRoot, pFirst, pLast, pOffset);
01188 }
01189 catch(...)
01190 {
01191 bddBdd::gc();
01192 try
01193 {
01194 lResult = bddBdd::renameVars_(mRoot, pFirst, pLast, pOffset);
01195 }
01196 catch(...)
01197 {
01198 cerr << "Error: BDD package out of memory." << endl;
01199 exit(EXIT_FAILURE);
01200 }
01201 }
01202 decRef();
01203 mRoot = lResult;
01204 incRef();
01205
01206
01207 if (mRenameCnt < UINT_MAX) {
01208 ++mRenameCnt;
01209 } else {
01210 mRenameCnt = 0;
01211 bddBdd::gc();
01212 }
01213 }
01214