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 #ifndef _bddRelation_h_
00032 #define _bddRelation_h_
00033
00034 #include "bddBdd.h"
00035 #include "bddSymTab.h"
00036 #include "relDataType.h"
00037
00039 extern string unsigned2string(unsigned pUnsigned);
00040
00054 class bddRelation : public relDataType
00055 {
00056
00057 private:
00058
00060 static bddRelation
00061 mkEqualPure(const bddSymTab* pSymTab,
00062 unsigned pVarId,
00063 reprNUMBER pConst)
00064 {
00065 return bddRelation(pSymTab,
00066 bddBdd(pVarId, pSymTab->getBitNr(), pConst) );
00067 }
00068
00069 public:
00070
00076 static bddRelation
00077 mkEqual(const bddSymTab* pSymTab,
00078 unsigned pVarId,
00079 reprNUMBER pConst)
00080 {
00081
00082 assert(pConst < pSymTab->getUniverseSize());
00083
00084 bddRelation result = mkEqualPure(pSymTab, pVarId, pConst);
00085
00086 if( pConst+1 == pSymTab->getUniverseSize() )
00087 {
00088
00089
00090
00091
00092
00093
00094 bddRelation lTmp = mkRange(pSymTab, pVarId);
00095 lTmp.complement();
00096 result.unite(lTmp);
00097 }
00098 return result;
00099 }
00100
00103 static bddRelation
00104 mkRange(const bddSymTab* pSymTab,
00105 unsigned pVarId)
00106 {
00107 return bddRelation(pSymTab,
00108 bddBdd::mkLessEqual(pVarId,
00109 pSymTab->getBitNr(),
00110 pSymTab->getUniverseSize() - 1 )
00111 );
00112 }
00113
00115 static bddRelation
00116 mkEqual(const bddSymTab* pSymTab,
00117 const string& pVar1,
00118 const string& pVar2)
00119 {
00120 bddRelation result(pSymTab, false);
00121 unsigned lVarId1 = pSymTab->getAttributePos(pVar1);
00122 unsigned lVarId2 = pSymTab->getAttributePos(pVar2);
00123
00124 for(reprNUMBER lValueIt = 0;
00125 lValueIt < pSymTab->getUniverseSize();
00126 ++lValueIt)
00127 {
00128 bddRelation lValuePair = mkEqual(pSymTab, lVarId1, lValueIt);
00129 lValuePair.intersect( mkEqual(pSymTab, lVarId2, lValueIt));
00130 result.unite(lValuePair);
00131 }
00132 return result;
00133 }
00134
00137 static bddRelation
00138 mkLess(const bddSymTab* pSymTab,
00139 const string& pVar1,
00140 const string& pVar2)
00141 {
00142 bddRelation result(pSymTab, false);
00143 unsigned lVarId1 = pSymTab->getAttributePos(pVar1);
00144 unsigned lVarId2 = pSymTab->getAttributePos(pVar2);
00145 assert(lVarId1 <= lVarId2);
00146
00147 bddRelation lVar2Values(pSymTab, false);
00148 for(int lValueIt = pSymTab->getUniverseSize()-1;
00149 lValueIt > 0 ;
00150 --lValueIt)
00151 {
00152
00153 lVar2Values.unite( mkEqual(pSymTab, lVarId2, lValueIt) );
00154
00155
00156 bddRelation lRel(lVar2Values);
00157 lRel.intersect( mkEqual(pSymTab, lVarId1, lValueIt-1) );
00158 result.unite(lRel);
00159 }
00160 return result;
00161 }
00162
00165 static bddRelation
00166 mkAttributeValue(const bddSymTab* pSymTab,
00167 const string& pAttributeName,
00168 const string& pAttributeValue)
00169 {
00170 return mkEqual(pSymTab,
00171 pSymTab->getAttributePos(pAttributeName),
00172 pSymTab->getValueNum(pAttributeValue));
00173 }
00174
00175 private:
00176
00178 const bddSymTab* mSymTab;
00180 bddBdd mBdd;
00181
00182 public:
00183
00189 int mArity;
00190
00191 public:
00192
00193 bddRelation(const bddSymTab* pSymTab, bool full)
00194 : mSymTab(pSymTab),
00195 mBdd(full),
00196 mArity(-1)
00197 {}
00198
00199
00200
00201
00202 private:
00203
00204 bddRelation(const bddSymTab* pSymTab, const bddBdd& pBdd)
00205 : mSymTab(pSymTab),
00206 mBdd(pBdd),
00207 mArity(-1)
00208 {}
00210 bddRelation(void*);
00212 void operator,(const bddRelation&);
00213
00214 private:
00215
00218 void
00219 renameSafe(unsigned pVarIdOld, unsigned pVarIdNew, unsigned pBitNr)
00220 {
00221
00222
00223
00224 if( pVarIdOld > pVarIdNew )
00225 {
00226 for (unsigned lIt = 0;
00227 lIt < pBitNr;
00228 ++lIt)
00229 {
00230 unsigned lPosOld = pVarIdOld + lIt;
00231 unsigned lPosNew = pVarIdNew + lIt;
00232
00233 mBdd.intersect(bddBdd(lPosOld, lPosNew));
00234 mBdd.exists(lPosOld);
00235 }
00236 }
00237 else
00238 {
00239 for (int lIt = pBitNr-1;
00240 lIt >= 0;
00241 --lIt)
00242 {
00243 unsigned lPosOld = pVarIdOld + lIt;
00244 unsigned lPosNew = pVarIdNew + lIt;
00245
00246 mBdd.intersect(bddBdd(lPosOld, lPosNew));
00247 mBdd.exists(lPosOld);
00248 }
00249 }
00250 }
00251
00252
00253 public:
00254
00257 double
00258 getTupleNr(const set<string>& pFree) const
00259 {
00260 if (pFree.size() == 0) {
00261 return isEmpty() ? 0 : 1;
00262 }
00263
00264 map<unsigned,string> lVarOrd = mSymTab->computeVariableOrder(pFree);
00265 unsigned lFirstVar = lVarOrd.begin()->first;
00266 unsigned lLastVar = (--lVarOrd.end())->first;
00267 assert(lFirstVar <= lLastVar);
00268
00269
00270
00271 bddRelation lTmp = *this;
00272 {
00273 for (unsigned lVarId = lFirstVar;
00274 lVarId <= lLastVar;
00275 lVarId += mSymTab->getBitNr() )
00276 {
00277 bddRelation lRange(mSymTab, false);
00278 if (lVarOrd.find(lVarId) == lVarOrd.end()) {
00279 lRange.unite(mkEqualPure(mSymTab, lVarId, 0));
00280 } else {
00281 lRange.unite(mkRange(mSymTab, lVarId));
00282 }
00283 lTmp.intersect(lRange);
00284 }
00285 }
00286
00287
00288 assert( !lTmp.mBdd.testVars(0, lFirstVar - 1) );
00289 return lTmp.mBdd.getTupleNr(lFirstVar, lLastVar + mSymTab->getBitNr() - 1);
00290 }
00291
00294 string
00295 getElement(unsigned pVarId)
00296 {
00297 unsigned lNumValue = mBdd.getTuple(pVarId, pVarId + mSymTab->getBitNr()-1);
00298 return mSymTab->getAttributeValue(lNumValue);
00299 }
00300
00301
00302 public:
00303
00304 bool
00305 setEqual(const bddRelation& p) const {
00306 return mBdd.setEqual( p.mBdd );
00307 }
00308
00310 bool
00311 setContains(const bddRelation& p) const {
00312 return mBdd.setContains( p.mBdd );
00313 }
00314
00315 bool
00316 isEmpty() const {
00317 return mBdd.isEmpty();
00318 }
00319
00320 void
00321 complement() {
00322 mBdd.complement();
00323 }
00324
00325 void
00326 unite(const bddRelation& p) {
00327 mBdd.unite(p.mBdd);
00328 }
00329
00330 void
00331 intersect(const bddRelation& p) {
00332 mBdd.intersect(p.mBdd);
00333 }
00334
00336 void
00337 exists(const string pAttribute) {
00338 unsigned lVarId = mSymTab->getAttributePos(pAttribute);
00339
00340
00341 for (int i = mSymTab->getBitNr() - 1; i >= 0; --i)
00342 {
00343 mBdd.exists(lVarId + i);
00344 }
00345 }
00346
00349 bool
00350 testVars(string pVarFirst, string pVarLast)
00351 {
00352 unsigned lVarIdFirst = mSymTab->getAttributePos(pVarFirst);
00353 unsigned lVarIdLast = mSymTab->getAttributePos(pVarLast) + mSymTab->getBitNr()-1;
00354 assert(lVarIdFirst <= lVarIdLast);
00355 return mBdd.testVars(lVarIdFirst, lVarIdLast);
00356 }
00357
00359 void
00360 rename(const string pAttributeOld, const string pAttributeNew) {
00361 unsigned lVarIdOld = mSymTab->getAttributePos(pAttributeOld);
00362 unsigned lVarIdNew = mSymTab->getAttributePos(pAttributeNew);
00363
00364
00365
00366
00367
00368
00369 unsigned lVarIdFirst = lVarIdOld + mSymTab->getBitNr();
00370 unsigned lVarIdLast = lVarIdNew + mSymTab->getBitNr()-1;
00371
00372 if( lVarIdOld > lVarIdNew )
00373 {
00374 lVarIdFirst = lVarIdNew;
00375 lVarIdLast = lVarIdOld - 1;
00376 }
00377
00378
00379
00380 if( mBdd.testVars(lVarIdFirst, lVarIdLast) )
00381 {
00382
00383 renameSafe(lVarIdOld, lVarIdNew, mSymTab->getBitNr());
00384 }
00385 else
00386 {
00387
00388
00389
00390
00391
00392 mBdd.renameVars(lVarIdOld,
00393 lVarIdOld + (mSymTab->getBitNr() - 1),
00394 lVarIdNew - lVarIdOld
00395 );
00396 }
00397 }
00398
00399
00400 public:
00401
00402 void
00403 printBddInfo(ostream& pS) const {
00404
00405 unsigned lFreeNodes = mBdd.getFreeNodeNr();
00406 unsigned lMaxNodes = mBdd.getMaxNodeNr();
00407
00408
00409 pS << "Number of BDD nodes: " << mBdd.getNodeNr() << endl
00410 << "Percentage of free nodes in BDD package: "
00411 << lFreeNodes << " / " << lMaxNodes << " = "
00412 << (unsigned)(((double)lFreeNodes / (double)lMaxNodes) * 100)
00413 << " %" << endl;
00414 }
00415
00418 void
00419 printNodesPerVarId(ostream& pS, const set<string>& pFree) const {
00420 map<unsigned, string> lVarOrd = mSymTab->computeVariableOrder(pFree);
00421 map<unsigned, unsigned> lBddNodesPerVar = mBdd.getNodesPerVarId();
00422 if (lVarOrd.empty() || lBddNodesPerVar.empty()) {
00423 pS << 0 << endl;
00424 return;
00425 }
00426
00427
00428
00429
00430
00431 unsigned lPos = lVarOrd.begin()->first;
00432 unsigned lLastId = (--lVarOrd.end())->first + mSymTab->getBitNr() - 1;
00433 assert( lBddNodesPerVar.begin()->first >= lPos );
00434 assert( (--lBddNodesPerVar.end())->first <= lLastId );
00435
00436 while (lPos <= lLastId) {
00437 unsigned lPosFirst = (lPos / mSymTab->getBitNr()) * mSymTab->getBitNr();
00438
00439 if (lVarOrd.find(lPosFirst) != lVarOrd.end()) {
00440 pS << lVarOrd[lPosFirst] << '_' << lPos - lPosFirst
00441 << '(' << lPos << ')'
00442 << endl;
00443 }
00444
00445 if ( lBddNodesPerVar.find(lPos) != lBddNodesPerVar.end() ) {
00446 pS << lBddNodesPerVar[lPos] << endl;
00447 } else {
00448 pS << 0 << endl;
00449 }
00450 ++lPos;
00451 }
00452 }
00453
00456 void
00457 printRelation(ostream& pS,
00458 const string pTuple,
00459 vector<string> pAttributeList) const
00460 {
00461
00462 if( isEmpty() ) {
00463 return;
00464 }
00465
00466
00467 if( pAttributeList.empty() ) {
00468 pS << pTuple << endl;
00469 return;
00470 }
00471
00472
00473
00474 bddRelation lRel(*this);
00475
00476
00477
00478 unsigned lVarId = mSymTab->getAttributePos( * pAttributeList.begin() );
00479 pAttributeList.erase(pAttributeList.begin());
00480
00481
00482 while (!lRel.isEmpty()) {
00483
00484 unsigned lNumValue = lRel.mBdd.getTuple(lVarId,
00485 lVarId + mSymTab->getBitNr()-1);
00486
00487
00488 bddRelation lTmpRel(lRel);
00489 lTmpRel.intersect( mkEqual(mSymTab, lVarId, lNumValue) );
00490
00491 string lStringValue( mSymTab->getAttributeValue(lNumValue) );
00492 if( mSymTab->isQuoted(lStringValue) )
00493 {
00494 lStringValue = '"' + lStringValue + '"';
00495 }
00496
00497 lTmpRel.printRelation(pS, pTuple + lStringValue + '\t', pAttributeList);
00498
00499
00500 lTmpRel.complement();
00501 lRel.intersect( lTmpRel );
00502 }
00503 }
00504
00506 void
00507 printGraph(ostream& pS, const set<string>& pFree) const {
00508
00509 map<unsigned,string> lVarOrd = mSymTab->computeVariableOrder(pFree);
00510
00511 bool need1Terminal = true;
00512 bool need0Terminal = true;
00513 if (setEqual(bddRelation(mSymTab, true))) {
00514 need0Terminal = false;
00515 }
00516 if (setEqual(bddRelation(mSymTab, false))) {
00517 need1Terminal = false;
00518 }
00519
00520
00521 multimap<unsigned,bddGraphNode> lGraph;
00522 mBdd.getGraph(lGraph);
00523
00524 string lEdgeStyle = " [arrowsize=\"1.0\",fontname=\"Helvetica\",fontsize=\"8\",";
00525 string lNodeStyle = " [fontname=\"Helvetica\",fontsize=\"16\",height=\"0.3\",width=\"0.5\",color=black,style=unfilled,";
00526
00527 pS << "digraph BDD {" << endl;
00528 pS << "size=\"7.5,10\";" << endl << endl;
00529
00530
00531 if (lGraph.size() > 0) {
00532 pS << "{ rank=same;" << endl;
00533 }
00534 multimap<unsigned,bddGraphNode>::const_iterator lItPrev = lGraph.begin();
00535 for (multimap<unsigned,bddGraphNode>::const_iterator lIt = lGraph.begin();
00536 lIt != lGraph.end();
00537 ++lIt) {
00538
00539 if (lIt->first != lItPrev->first) {
00540 pS << "}" << endl << endl
00541 << "{ rank=same;" << endl;
00542 }
00543 lItPrev = lIt;
00544
00545 pS << lIt->second.id << lNodeStyle;
00546 unsigned lPos = lIt->second.var;
00547 unsigned lPosFirst = (lPos / mSymTab->getBitNr()) * mSymTab->getBitNr();
00548 assert(lVarOrd.find(lPosFirst) != lVarOrd.end());
00549 pS << "label=\"" << lVarOrd[lPosFirst] << '_' << lPos - lPosFirst << "\"];" << endl;
00550 }
00551 if (lGraph.size() > 0) {
00552 pS << "}" << endl << endl;
00553 }
00554
00555
00556 pS << endl
00557 << "{ rank=same;" << endl;
00558 if (need1Terminal) {
00559 pS << 1 << lNodeStyle << "shape=box,label=\"1\"];" << endl << endl;
00560 }
00561 if (need0Terminal) {
00562 pS << 0 << lNodeStyle << "shape=box,label=\"0\"];" << endl << endl;
00563 }
00564 pS << "}" << endl << endl << endl;
00565
00566
00567 for (multimap<unsigned,bddGraphNode>::const_iterator lIt = lGraph.begin();
00568 lIt != lGraph.end();
00569 ++lIt) {
00570
00571 pS << lIt->second.id << " -> " << lIt->second.low
00572 << lEdgeStyle << "label=\"0\"," << "style=dotted]" << endl;
00573
00574 pS << lIt->second.id << " -> " << lIt->second.high
00575 << lEdgeStyle << "label=\"1\"," << "style=solid]" << endl;
00576 pS << endl;
00577 }
00578
00579 pS << "}" << endl;
00580 }
00581
00583 void
00584 printBDT(ostream& pS) const {
00585 mBdd.print(pS);
00586 }
00587
00590 bddRelation
00591 getTupleOf(const map<unsigned, string>& pAttributeList) const
00592 {
00593 assert(!isEmpty());
00594
00595 bddRelation lRel(*this);
00596 for(map<unsigned, string>::const_iterator lIt = pAttributeList.begin();
00597 lIt != pAttributeList.end();
00598 ++lIt)
00599 {
00600 unsigned lVarId = mSymTab->getAttributePos( lIt->second );
00601
00602
00603 unsigned lNumValue = lRel.mBdd.getTuple(lVarId,
00604 lVarId + mSymTab->getBitNr()-1);
00605 lRel.intersect( mkEqual(mSymTab, lVarId, lNumValue) );
00606 }
00607 return lRel;
00608 }
00609
00610 };
00611
00612 class bddRelationConst : public bddRelation
00613 {
00614 public:
00615 bddRelationConst(bddRelation pRel)
00616 : bddRelation(pRel)
00617 {}
00618 };
00619
00620 #endif // _bddRelation_h_