relExpression.h

Go to the documentation of this file.
00001 /*
00002  * CrocoPat is a tool for relational programming.
00003  * This file is part of CrocoPat. 
00004  *
00005  * Copyright (C) 2002-2008  Dirk Beyer
00006  *
00007  * CrocoPat is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * CrocoPat is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with CrocoPat; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * Please find the GNU Lesser General Public License in file
00022  * License_LGPL.txt or at http://www.gnu.org/licenses/lgpl.txt
00023  *
00024  * Author:
00025  * Dirk Beyer (firstname.lastname@sfu.ca)
00026  * Simon Fraser University
00027  *
00028  * With contributions of: Andreas Noack, Michael Vogel
00029  */
00030 
00031 #ifndef _relExpression_h
00032 #define _relExpression_h
00033 
00034 #include "bddRelation.h"
00035 #include "relTerm.h"
00036 
00037 #include <string>
00038 #include <fstream>
00039 #include <iterator>
00040 #include <regex.h>
00041 
00043 extern string unsigned2string(unsigned pUnsigned);
00044 extern string double2string(double pNum);
00045 extern double elapsed();
00046 
00048 extern map<string, relDataType*> gVariables;
00049 extern const unsigned   gAttributeNum;    // Default:   1000 internal vars.
00050 extern const char       gAttributePrefix; // Prefix for internal attributes.
00051 extern bddSymTab*       gSymTab;
00052 extern bool             gPrintWarnings;
00053 
00054 
00056 class relExpression : public relObject
00057 {
00058 public:
00059   virtual set<string>
00060   collectFreeAttrs() = 0;
00061 
00062   virtual bddRelation
00063   interpret(bddSymTab* pSymTab) = 0;
00064 };
00065 
00067 class relExprRelVar : public relExpression
00068 {
00069 private:
00070   string*           mRelVar;
00071   vector<relTerm*>* mTermList;
00072 
00073 public:
00074   relExprRelVar(string* pRelVar, vector<relTerm*>* pTermList)
00075     : mRelVar(pRelVar),
00076       mTermList(pTermList)
00077   {}
00078 
00079   ~relExprRelVar()
00080   {
00081     delete mRelVar;
00082     for( vector<relTerm*>::iterator 
00083          lIt = mTermList->begin();
00084          lIt != mTermList->end();
00085          ++lIt)
00086     {
00087       delete *lIt;
00088     }
00089     delete mTermList;
00090   }
00091 
00092   virtual set<string>
00093   collectFreeAttrs()
00094   {
00095     set<string> result;
00096     for( vector<relTerm*>::iterator 
00097          lIt = mTermList->begin();
00098          lIt != mTermList->end();
00099          ++lIt)
00100     {
00101       if (dynamic_cast<relTermAttribute*>(*lIt) != NULL) {
00102         result.insert((*lIt)->interpret(gSymTab));
00103       }
00104     }
00105     return result;
00106   }
00107 
00108   virtual bddRelation
00109   interpret(bddSymTab* pSymTab)
00110   {
00111     // Add attributes to SymTab, if new.
00112     //   From top to bottom is important to get the right variable order.
00113     for(unsigned i = 0; i < mTermList->size(); ++i) {
00114       // Is it an attribute?
00115       if (dynamic_cast<relTermAttribute*>((*mTermList)[i]) != NULL)
00116       {
00117         pSymTab->addAttribute( (*mTermList)[i]->interpret(pSymTab) ); 
00118       }
00119     }
00120     
00121     // Warnings and return for unknown strings.
00122     for(unsigned i = 0; i < mTermList->size(); ++i) {
00123       if ( (dynamic_cast<relTermStrExpr*>((*mTermList)[i]) != NULL) &&
00124            (!pSymTab->isValueGood((*mTermList)[i]->interpret(pSymTab)))  ) {
00125         if (gPrintWarnings) {
00126           cerr << "Warning: String '" << (*mTermList)[i]->interpret(pSymTab)
00127                << "' is not in universe." << endl;
00128         }
00129         // Result for expression with non-existing value is always the empty set.
00130         return bddRelation(pSymTab, false);
00131       }
00132     }
00133 
00134     // Fetch result.
00135     string lRelVar = *mRelVar;                // Because we update.
00136     vector<relTerm*> lTermList = *mTermList;  // Because we update.
00137     map<string, relDataType*>::const_iterator lVarIt = gVariables.find(lRelVar);
00138     assert(lVarIt != gVariables.end());  // Must be declared.
00139     assert(lVarIt->second != NULL);
00140     if (dynamic_cast<bddRelationConst*>(lVarIt->second) != NULL) {
00141       // Predefined const relation.
00142       if (lRelVar == "="  ||  lRelVar == "!="  ||  
00143           lRelVar == "<"  ||  lRelVar == "<="   ||
00144           lRelVar == ">"  ||  lRelVar == ">=") {
00145         // These are binary relations.  If not, the parser has a problem.
00146         assert(lTermList.size() == 2);
00147         // Performance optimization: Constant always first.
00148         if (dynamic_cast<relTermStrExpr*>(lTermList[0]) == NULL &&
00149             dynamic_cast<relTermStrExpr*>(lTermList[1]) != NULL) {
00150           relTerm* lTermTmp = lTermList[0];
00151           lTermList[0] = lTermList[1];
00152           lTermList[1] = lTermTmp;
00153           if (lRelVar == "<")  { 
00154             lRelVar = ">"; 
00155           } else if (lRelVar == "<=") { 
00156             lRelVar = ">="; 
00157           } else if (lRelVar == ">")  { 
00158             lRelVar = "<"; 
00159           } else if (lRelVar == ">=") { 
00160             lRelVar = "<="; 
00161           }
00162           lVarIt = gVariables.find(lRelVar);
00163           assert(lVarIt != gVariables.end());  // Must be declared.
00164           assert(lVarIt->second != NULL);
00165         }
00166       }
00167     }
00168     bddRelation* lResult = dynamic_cast<bddRelation*>(lVarIt->second);
00169     assert(lResult != NULL);             // Must be a REL variable.
00170     // Make a copy of the relation.
00171     bddRelation result = *lResult;
00172 
00173     // Some type checking: Check arity.
00174     if (   lResult->mArity != -1 
00175         && lResult->mArity != mTermList->size() )
00176     {
00177       if (gPrintWarnings) {
00178         cerr << "Warning: Arity mismatch. '" 
00179              << *mRelVar << "' is of arity " << lResult->mArity 
00180              << " but is now used for arity " << mTermList->size() << "." << endl;
00181       }
00182     }
00183 
00184     // Quantify or intersect with value.
00185     //   Ordering: From bottom to top, for efficiency.
00186     for(int i = lTermList.size()-1; i >= 0; --i)
00187     {
00188       string lTerm = lTermList[i]->interpret(pSymTab);
00189       if (dynamic_cast<relTermExists*>(lTermList[i]) != NULL)
00190       {
00191         // Quantification.
00192         result.exists(gAttributePrefix + unsigned2string(i));
00193       }
00194       else if (dynamic_cast<relTermStrExpr*>(lTermList[i]) != NULL)
00195       {
00196         // lTerm is a string (constant) and exists in symtab (checked above).
00197         result.intersect(bddRelation::mkAttributeValue(
00198                                                        pSymTab, 
00199                                                        gAttributePrefix + unsigned2string(i), 
00200                                                        lTerm)
00201                          );
00202         result.exists(gAttributePrefix + unsigned2string(i)); 
00203       }
00204     }
00205 
00206     // Rename internal attributes to the given user attributes.
00207     //   Ordering: From bottom to top, for efficiency.
00208     for(int i = lTermList.size()-1; i >= 0; --i)
00209     {
00210       string lTerm = lTermList[i]->interpret(pSymTab);
00211       if (dynamic_cast<relTermAttribute*>(lTermList[i]) != NULL)
00212       {
00213         // lTerm is an attribute.
00214         // Rename.
00215         result.rename(gAttributePrefix + unsigned2string(i), lTerm);
00216       }
00217     }
00218     
00219     // Check if the arity of the stored relation was greater than
00220     //   the number of terms by looking for BDD nodes of internal attributes.
00221     if ( result.testVars(gAttributePrefix + unsigned2string(0),
00222                          gAttributePrefix + unsigned2string(gAttributeNum-1)) ) {
00223       cerr << "Error: The arity of relation '" << *mRelVar 
00224            << "' is greater than the number of terms." << endl;
00225       exit(EXIT_FAILURE);
00226     }
00227     
00228     return result;
00229   }
00230 };
00231 
00233 class relExprRelNumCmp : public relExpression
00234 {
00235 private:
00236   string*           mRelSym;
00237   relNumExpr*       mNumExpr1;
00238   relNumExpr*       mNumExpr2;
00239 
00240 public:
00241   relExprRelNumCmp(string* pRelSym, relNumExpr* pNumExpr1, relNumExpr* pNumExpr2)
00242     : mRelSym(pRelSym),
00243       mNumExpr1(pNumExpr1),
00244       mNumExpr2(pNumExpr2)
00245   {}
00246 
00247   ~relExprRelNumCmp()
00248   {
00249     delete mRelSym;
00250     delete mNumExpr1;
00251     delete mNumExpr2;
00252   }
00253 
00254   virtual set<string>
00255   collectFreeAttrs()
00256   {
00257     set<string> result;
00258     return result;
00259   }
00260 
00261   virtual bddRelation
00262   interpret(bddSymTab* pSymTab)
00263   {
00264     double lNum1 = mNumExpr1->interpret(pSymTab).getValue();
00265     double lNum2 = mNumExpr2->interpret(pSymTab).getValue();
00266     bool result = false;
00267     if (*mRelSym == "=")   result = (lNum1 == lNum2);
00268     else if (*mRelSym == "!=")  result = (lNum1 != lNum2);
00269     else if (*mRelSym == "<")   result = (lNum1 <  lNum2);
00270     else if (*mRelSym == "<=")  result = (lNum1 <= lNum2);
00271     else if (*mRelSym == ">")   result = (lNum1 >  lNum2);
00272     else if (*mRelSym == ">=")  result = (lNum1 >= lNum2);
00273     else { 
00274       cerr << "Internal error: Unknown operator in numerical comparison: '" 
00275            << *mRelSym << "'." << endl;
00276       abort(); 
00277     }
00278     return bddRelation(pSymTab, result);
00279   }
00280 };
00281 
00283 class relExprExists : public relExpression
00284 {
00285 private:
00286   vector<relTerm*>* mTermList;
00287   relExpression*    mExpr;
00288 
00289 public:
00290   relExprExists(vector<relTerm*>* pTermList, relExpression* pExpr)
00291     : mTermList(pTermList),
00292       mExpr(pExpr)
00293   {}
00294 
00295   ~relExprExists()
00296   {
00297     for( vector<relTerm*>::iterator 
00298          lIt = mTermList->begin();
00299          lIt != mTermList->end();
00300          ++lIt)
00301     {
00302       delete *lIt;
00303     }
00304     delete mTermList;
00305     delete mExpr;
00306   }
00307 
00308   virtual set<string>
00309   collectFreeAttrs()
00310   {
00311     set<string> result = mExpr->collectFreeAttrs();
00312     for( vector<relTerm*>::iterator 
00313          lIt = mTermList->begin();
00314          lIt != mTermList->end();
00315          ++lIt)
00316     {
00317       if (dynamic_cast<relTermAttribute*>(*lIt) != NULL) {
00318         result.erase((*lIt)->interpret(gSymTab));
00319       }
00320     }
00321     return result;
00322   }
00323 
00324   virtual bddRelation
00325   interpret(bddSymTab* pSymTab)
00326   {
00327     bddRelation result( mExpr->interpret(pSymTab) );
00328     const set<string> lFree = mExpr->collectFreeAttrs();
00329     for( vector<relTerm*>::iterator 
00330          lIt = mTermList->begin();
00331          lIt != mTermList->end();
00332          ++lIt)
00333     {
00334       const string lAttr = (*lIt)->interpret(pSymTab);
00335       if (dynamic_cast<relTermAttribute*>(*lIt) == NULL) {
00336         cerr << "Error: Only attributes allowed for quantification." << endl;
00337       } else if (lFree.find(lAttr) == lFree.end()) {
00338         cerr << "Error: Only free attributes allowed for quantification." 
00339              << endl 
00340              << "Attribute '" << lAttr 
00341              << "' does not occur free in the expression." << endl;
00342       } else {
00343         result.exists(lAttr);
00344       }
00345     }
00346     return result;
00347   }
00348 };
00349 
00351 class relExprNot : public relExpression
00352 {
00353 private:
00354   relExpression*        mExpr;
00355 
00356 public:
00357   relExprNot( relExpression* pExpr)
00358     : mExpr(pExpr)
00359   {}
00360 
00361   ~relExprNot()
00362   {
00363         delete mExpr;
00364   }
00365 
00366   virtual set<string>
00367   collectFreeAttrs()
00368   {
00369         return mExpr->collectFreeAttrs();
00370   }
00371 
00372   virtual bddRelation
00373   interpret(bddSymTab* pSymTab)
00374   {
00375         bddRelation result = mExpr->interpret(pSymTab);
00376         result.complement();
00377         return result;
00378   }
00379 };
00380 
00382 class relExprAnd : public relExpression
00383 {
00384 private:
00385   relExpression* mExpr1;
00386   relExpression* mExpr2;
00387 
00388 public:
00389   relExprAnd(relExpression* pExpr1, relExpression* pExpr2)
00390     : mExpr1(pExpr1),
00391       mExpr2(pExpr2)
00392   {}
00393 
00394   ~relExprAnd()
00395   {
00396     delete mExpr1;
00397     delete mExpr2;
00398   }
00399 
00400   virtual set<string>
00401   collectFreeAttrs()
00402   {
00403         set<string> result = mExpr1->collectFreeAttrs();
00404         set<string> tmp    = mExpr2->collectFreeAttrs();
00405         result.insert(tmp.begin(), tmp.end());
00406         return result;
00407   }
00408 
00409   virtual bddRelation
00410   interpret(bddSymTab* pSymTab)
00411   {
00412     bddRelation result( mExpr1->interpret(pSymTab) );
00413     result.intersect( mExpr2->interpret(pSymTab) );
00414     return result;
00415   }
00416 };
00417 
00419 class relExprOr : public relExpression
00420 {
00421 private:
00422   relExpression* mExpr1;
00423   relExpression* mExpr2;
00424 
00425 public:
00426   relExprOr(relExpression* pExpr1, relExpression* pExpr2)
00427     : mExpr1(pExpr1),
00428       mExpr2(pExpr2)
00429   {}
00430 
00431   ~relExprOr()
00432   {
00433     delete mExpr1;
00434     delete mExpr2;
00435   }
00436 
00437   virtual set<string>
00438   collectFreeAttrs()
00439   {
00440         set<string> result = mExpr1->collectFreeAttrs();
00441         set<string> tmp    = mExpr2->collectFreeAttrs();
00442         result.insert(tmp.begin(), tmp.end());
00443         return result;
00444   }
00445 
00446   virtual bddRelation
00447   interpret(bddSymTab* pSymTab)
00448   {
00449     bddRelation result( mExpr1->interpret(pSymTab) );
00450     result.unite( mExpr2->interpret(pSymTab) );
00451     return result;
00452   }
00453 };
00454 
00456 class relExprEquiv : public relExpression
00457 {
00458 private:
00459   relExpression* mExpr1;
00460   relExpression* mExpr2;
00461 
00462 public:
00463   relExprEquiv(relExpression* pExpr1, relExpression* pExpr2)
00464     : mExpr1(pExpr1),
00465       mExpr2(pExpr2)
00466   {}
00467 
00468   ~relExprEquiv()
00469   {
00470     delete mExpr1;
00471     delete mExpr2;
00472   }
00473 
00474   virtual set<string>
00475   collectFreeAttrs()
00476   {
00477         set<string> result = mExpr1->collectFreeAttrs();
00478         set<string> tmp    = mExpr2->collectFreeAttrs();
00479         result.insert(tmp.begin(), tmp.end());
00480         return result;
00481   }
00482 
00483   virtual bddRelation
00484   interpret(bddSymTab* pSymTab)
00485   {
00486     // (expr1 AND expr2) OR NOT(expr1 OR expr2).
00487     bddRelation lExpr1 = mExpr1->interpret(pSymTab);
00488     bddRelation lExpr2 = mExpr2->interpret(pSymTab);
00489     bddRelation lIntersect = lExpr1;
00490     lIntersect.intersect(lExpr2);
00491     bddRelation result = lExpr1;
00492     result.unite(lExpr2);
00493     result.complement();
00494     result.unite(lIntersect);
00495     return result;
00496   }
00497 };
00498 
00500 class relExprClosure : public relExpression
00501 {
00502 public:
00503   typedef enum {EXPTRAVERS, WARSHALLII} relTCAlg;
00504 
00505 private:
00506   relExpression* mExpr;
00507   relTCAlg       mAlg;
00508 
00509 public:
00510   relExprClosure(relExpression* pExpr, 
00511                  relTCAlg       pAlg)
00512     : mExpr(pExpr),
00513       mAlg(pAlg)
00514   {}
00515 
00516   ~relExprClosure()
00517   {
00518     delete mExpr;
00519   }
00520 
00521   virtual set<string>
00522   collectFreeAttrs()
00523   {
00524         return mExpr->collectFreeAttrs();
00525   }
00526 
00527   // Side effect: Adds a symbol to the symbol table.
00528   virtual bddRelation
00529   interpret(bddSymTab* pSymTab)
00530   {
00531     // First evaluate, to set variables in the variable ordering.
00532     bddRelation result( mExpr->interpret(pSymTab) );
00533 
00534     const set<string> lFree = mExpr->collectFreeAttrs();
00535     if(lFree.size() != 2) {
00536       cerr << "Error: Transitive closure requires two free attributes." << endl;
00537           exit(EXIT_FAILURE);
00538     }
00539     const map<unsigned,string> lVarOrd = pSymTab->computeVariableOrder(lFree);
00540     assert(lVarOrd.size() == 2);
00541     const string lAttributeX = lVarOrd.begin()->second;
00542     const string lAttributeY = (++lVarOrd.begin())->second;
00543 
00544     // Temporary attribute for computation of transitive closure.
00545     string tmpAttr = ".INTERNAL_TMPATTR.";
00546     // Add attribute to SymTab, if new.
00547     pSymTab->addAttribute(tmpAttr); 
00548 
00549 
00550     if (mAlg == EXPTRAVERS) {
00551     /*
00552     // Partitioning.
00553     //cerr << "0: " << elapsed() << endl;
00554     { // Part 1.
00555         bddRelation lDivider(pSymTab, false);
00556         for(reprNUMBER lValueIt = 0;
00557             lValueIt < pSymTab->getUniverseSize() * 2/3;
00558             ++lValueIt)
00559         {
00560           lDivider.unite(bddRelation::mkEqual(pSymTab, 
00561                                               pSymTab->getAttributePos(lAttributeX), 
00562                                               lValueIt));
00563         }
00564         bddRelation lFirstPart(result);
00565         lFirstPart.intersect(lDivider);
00566         
00567         // Variation 0 (for minimal time consumption)
00568         // Iteration to compute fixed point.
00569         bddRelation lPrevRel(pSymTab, false);
00570         while( ! lPrevRel.setEqual(lFirstPart) )
00571         {
00572           lPrevRel = lFirstPart;
00573           
00574           // Construct relation R(Y, TMPATTR) for one step.
00575           bddRelation lTmpRel(lFirstPart);                // R(X, Y)
00576           lTmpRel.rename(lAttributeY, tmpAttr);           // R(X, TMPATTR).
00577           lTmpRel.rename(lAttributeX, lAttributeY);       // R(Y, TMPATTR).
00578           
00579           // Step.
00580           lFirstPart.intersect(lTmpRel);                  // R(X, Y, TMPATTR).
00581           lFirstPart.exists(lAttributeY);                 // R(X, TMPATTR).
00582           lFirstPart.rename(tmpAttr, lAttributeY);        // R(X, Y).
00583           
00584           lFirstPart.unite( lPrevRel );
00585         }
00586 
00587         result.unite(lFirstPart);
00588     }
00589     //cerr << "1: " << elapsed() << endl;
00590 
00591     { // Part 2.
00592         bddRelation lDivider(pSymTab, false);
00593         for(reprNUMBER lValueIt = pSymTab->getUniverseSize() * 1/3;
00594             lValueIt < pSymTab->getUniverseSize();
00595             ++lValueIt)
00596         {
00597           lDivider.unite(bddRelation::mkEqual(pSymTab, 
00598                                               pSymTab->getAttributePos(lAttributeX), 
00599                                               lValueIt));
00600         }
00601         bddRelation lSecondPart(result);
00602         lSecondPart.intersect(lDivider);
00603 
00604         // Variation 0 (for minimal time consumption)
00605         // Iteration to compute fixed point.
00606         bddRelation lPrevRel(pSymTab, false);
00607         while( ! lPrevRel.setEqual(lSecondPart) )
00608         {
00609           lPrevRel = lSecondPart;
00610           
00611           // Construct relation R(Y, TMPATTR) for one step.
00612           bddRelation lTmpRel(lSecondPart);                // R(X, Y)
00613           lTmpRel.rename(lAttributeY, tmpAttr);       // R(X, TMPATTR).
00614           lTmpRel.rename(lAttributeX, lAttributeY);   // R(Y, TMPATTR).
00615           
00616           // Step.
00617           lSecondPart.intersect(lTmpRel);                  // R(X, Y, TMPATTR).
00618           lSecondPart.exists(lAttributeY);                 // R(X, TMPATTR).
00619           lSecondPart.rename(tmpAttr, lAttributeY);        // R(X, Y).
00620           
00621           lSecondPart.unite( lPrevRel );
00622         }
00623 
00624         result.unite(lSecondPart);
00625     }
00626     //cerr << "2: " << elapsed() << endl;
00627     */
00628 
00629     { // Main Part.
00630         // Variation 0 (for minimal time consumption)
00631         // Iteration to compute fixed point.
00632         bddRelation lPrevRel(pSymTab, false);
00633         while( ! lPrevRel.setEqual(result) )
00634         {
00635           lPrevRel = result;
00636           
00637           // Construct relation R(Y, TMPATTR) for one step.
00638           bddRelation lTmpRel(result);                // R(X, Y)
00639           lTmpRel.rename(lAttributeY, tmpAttr);       // R(X, TMPATTR).
00640           lTmpRel.rename(lAttributeX, lAttributeY);   // R(Y, TMPATTR).
00641           
00642           // Step.
00643           result.intersect(lTmpRel);                  // R(X, Y, TMPATTR).
00644           result.exists(lAttributeY);                 // R(X, TMPATTR).
00645           result.rename(tmpAttr, lAttributeY);        // R(X, Y).
00646           
00647           result.unite( lPrevRel );
00648         }
00649     }
00650     //cerr << "3: " << elapsed() << endl;
00651     }
00652 
00653 /*
00654     // Variation 1
00655     // Iteration to compute fixed point.
00656     bddRelation lPrevRel(pSymTab);
00657     // Construct relation R(Y, TMPATTR) for one step.
00658     bddRelation lTmpRel(result);                // R(X, Y)
00659     lTmpRel.rename(lAttributeY, tmpAttr);       // R(X, TMPATTR).
00660     lTmpRel.rename(lAttributeX, lAttributeY);   // R(Y, TMPATTR).
00661     while( ! lPrevRel.setEqual(result) )
00662     {
00663       lPrevRel = result;
00664 
00665       // Step.
00666       result.intersect(lTmpRel);                 // R(X, Y, TMPATTR).
00667       result.exists(lAttributeY);                // R(X, TMPATTR).
00668       result.rename(tmpAttr, lAttributeY);       // R(X, Y).
00669 
00670       result.unite( lPrevRel );
00671     }
00672 */
00673 
00674 /*
00675     // Variation 2
00676     // Iteration to compute fixed point.
00677     bddRelation lFront(result);
00678     // Construct relation R(Y, TMPATTR) for one step.
00679     bddRelation lTmpRel(result);                 // R(X, Y)
00680     lTmpRel.rename(lAttributeY, tmpAttr);        // R(X, TMPATTR).
00681     lTmpRel.rename(lAttributeX, lAttributeY);    // R(Y, TMPATTR).
00682     while( ! lFront.isEmpty() )
00683     {
00684       // Step.
00685       lFront.intersect(lTmpRel);                 // R(X, Y, TMPATTR).
00686       lFront.exists(lAttributeY);                // R(X, TMPATTR).
00687       lFront.rename(tmpAttr, lAttributeY);       // R(X, Y).
00688 
00689       bddRelation lResultComp(result);
00690       lResultComp.complement();
00691       lFront.intersect(lResultComp);
00692       result.unite( lFront );
00693     }
00694 */
00695 
00696 /*
00697     // Variation 3: Floyd-Warshall
00698     for (reprNUMBER i = 0; i < pSymTab->getUniverseSize(); ++i)
00699     {
00700       bddRelation lStartNodes(result);
00701       lStartNodes.intersect(bddRelation::mkAttributeValue(pSymTab, lAttributeY, pSymTab->getAttributeValue(i)));
00702       lStartNodes.exists(lAttributeY);
00703 
00704       bddRelation lEndNodes(result);
00705       lEndNodes.intersect(bddRelation::mkAttributeValue(pSymTab, lAttributeX, pSymTab->getAttributeValue(i)));
00706       lEndNodes.exists(lAttributeX);
00707             
00708       lStartNodes.intersect(lEndNodes);
00709 
00710       result.unite(lStartNodes);
00711     }
00712 */
00713 
00714 
00715     if (mAlg == WARSHALLII) {
00716       // Variation 4: Floyd-Warshall II (for minimal memory consumption)
00717       // For efficiency,
00718       //   mAttributeX must be before mAttributeY in the variable order.
00719       //   Given by default.
00720     
00721       // Compute lInvResult, which is result with inverse variable order.
00722       bddRelation lInvResult(result);                // R(X, Y)
00723       lInvResult.rename(lAttributeY, tmpAttr);       // R(X, TMPATTR)
00724       lInvResult.rename(lAttributeX, lAttributeY);   // R(Y, TMPATTR)
00725       lInvResult.rename(tmpAttr,     lAttributeX);   // R(Y, X)
00726     
00727 
00728       bddRelation lValuesX(result);
00729       lValuesX.exists(lAttributeY);
00730       bddRelation lValuesY(result);
00731       lValuesY.exists(lAttributeX);
00732       lValuesY.rename(lAttributeY, lAttributeX);
00733       lValuesX.intersect(lValuesY);
00734       const unsigned lVarId = pSymTab->getAttributePos(lAttributeX);
00735       // For all elements of the set lValueX.
00736       while (!lValuesX.isEmpty()) {
00737             // Get next value of the attribute.
00738             string lValue = lValuesX.getElement(lVarId);
00739             // Compute cofactor for current value in (lTmpRel).
00740             bddRelation lCurrentValue( bddRelation::mkAttributeValue(pSymTab, lAttributeX, lValue) );
00741     
00742 
00743         bddRelation lStartNodesY(lInvResult);
00744         lStartNodesY.intersect(lCurrentValue);
00745         lStartNodesY.exists(lAttributeX);
00746         bddRelation lStartNodesX(lStartNodesY);
00747         lStartNodesX.rename(lAttributeY, lAttributeX);
00748 
00749         bddRelation lEndNodesY(result);
00750         lEndNodesY.intersect(lCurrentValue);
00751         lEndNodesY.exists(lAttributeX);
00752         bddRelation lEndNodesX(lEndNodesY);
00753         lEndNodesX.rename(lAttributeY, lAttributeX);
00754             
00755         lStartNodesX.intersect(lEndNodesY);
00756         lEndNodesX.intersect(lStartNodesY);
00757 
00758         result.unite(lStartNodesX);
00759         lInvResult.unite(lEndNodesX);
00760 
00761 
00762             // Delete current element from set.
00763             lCurrentValue.complement();
00764             lValuesX.intersect(lCurrentValue);
00765       }
00766     }
00767 
00768     pSymTab->removeAttribute(tmpAttr);
00769     return result;
00770   }
00771 };
00772 
00774 class relExprRelOp : public relExpression
00775 {
00776 private:
00777   relExpression*        mExpr1;
00778   string*               mRelOp;
00779   relExpression*        mExpr2;
00780 
00781 public:
00782   relExprRelOp( relExpression* pExpr1,
00783                 string*        pRelOp, 
00784                 relExpression* pExpr2)
00785     : mExpr1(pExpr1),
00786       mRelOp(pRelOp),
00787       mExpr2(pExpr2)
00788   {}
00789 
00790   ~relExprRelOp()
00791   {
00792     delete mExpr1;
00793     delete mRelOp;
00794     delete mExpr2;
00795   }
00796 
00797   virtual set<string>
00798   collectFreeAttrs()
00799   {
00800     set<string> result;
00801     return result;
00802   }
00803 
00804   virtual bddRelation
00805   interpret(bddSymTab* pSymTab)
00806   {
00807     bool result = false;
00808         bddRelation lExpr1 = mExpr1->interpret(pSymTab);
00809         bddRelation lExpr2 = mExpr2->interpret(pSymTab);
00810 
00811         if (*mRelOp == "=")  result =   lExpr1.setEqual(lExpr2);
00812         else if (*mRelOp == "!=") result = ! lExpr1.setEqual(lExpr2);
00813         else if (*mRelOp == ">")  result = lExpr1.setContains(lExpr2) && ! lExpr1.setEqual(lExpr2);
00814         else if (*mRelOp == ">=") result = lExpr1.setContains(lExpr2);
00815         else if (*mRelOp == "<")  result = lExpr2.setContains(lExpr1) && ! lExpr1.setEqual(lExpr2);
00816         else if (*mRelOp == "<=") result = lExpr2.setContains(lExpr1);
00817         else { 
00818           cerr << "Internal error: Unknown operator (relExprRelOp)." << endl;
00819           abort(); 
00820         }
00821         return bddRelation(pSymTab, result);
00822   }
00823 };
00824 
00829 class relExprRegExTerm : public relExpression
00830 {
00831 private:
00832   relStrExpr*    mRegExString;        // The string containing the regular expression.
00833   relTerm*       mTerm;               // The term to match.
00834 
00835 public:
00836   relExprRegExTerm( relStrExpr*    pRegExString, 
00837                                     relTerm*       pTerm)
00838     : mRegExString(pRegExString),
00839       mTerm(pTerm)
00840   {}
00841 
00842   ~relExprRegExTerm()
00843   {
00844         delete mRegExString;
00845         delete mTerm;
00846   }
00847 
00848   virtual set<string>
00849   collectFreeAttrs()
00850   {
00851     set<string> result;
00852     if (dynamic_cast<relTermAttribute*>(mTerm) != NULL) {
00853       result.insert(mTerm->interpret(gSymTab));
00854     }
00855     return result;
00856   }
00857   
00859   void 
00860   errorproc(int pErrorCode, 
00861             regex_t* pRegExCompiled,
00862             const char* pRegEx,
00863             const char* pString)
00864   {
00865     size_t lLength = regerror(pErrorCode, pRegExCompiled, NULL, 0);
00866     char* lErrorMsg = (char*) malloc(lLength);
00867     if (lErrorMsg == NULL) {
00868           cerr << "Error: Virtual memory exhausted." << endl;
00869           exit(EXIT_FAILURE);
00870     }
00871     (void) regerror(pErrorCode, pRegExCompiled, lErrorMsg, lLength);
00872     cerr << "Error: Cannot apply regular expression '" << pRegEx
00873          << "' to string '" << pString << "': " << lErrorMsg << endl;
00874     delete lErrorMsg;
00875   }
00876 
00878   bool
00879   regexmatch(regex_t* pRegExCompiled,
00880              const char* pRegEx, 
00881              const char* pString)
00882   {
00883     int lErrorCode = regexec(pRegExCompiled, pString, 0, NULL, 0);
00884     if (lErrorCode == 0) {            // Matches.
00885       return true;
00886     }
00887     if (lErrorCode == REG_NOMATCH) {  // Does not match.
00888       return false;
00889     }
00890     // Error occured.
00891     errorproc(lErrorCode, pRegExCompiled, pRegEx, pString);
00892     regfree(pRegExCompiled);
00893     exit(EXIT_FAILURE);
00894   }
00895 
00896   virtual bddRelation
00897   interpret(bddSymTab* pSymTab)
00898   {
00899     const char* lTerm   = mTerm->interpret(pSymTab).c_str();
00900     const char* lRegExStr 
00901       = mRegExString->interpret(pSymTab).getValue().c_str();
00902 
00903     regex_t lRegExCompiled;        // The compiled regular expression.
00904     int lErrorCode
00905       = regcomp(&lRegExCompiled, lRegExStr, REG_EXTENDED | REG_NOSUB);
00906     if (lErrorCode != 0) {         // Compilation failed.
00907       errorproc(lErrorCode, &lRegExCompiled, lRegExStr, lTerm);
00908       regfree(&lRegExCompiled);
00909       exit(EXIT_FAILURE);
00910     }
00911     // Compilation successful.
00912 
00913     if (dynamic_cast<relTermStrExpr*>(mTerm) != NULL)
00914     {
00915       if (!pSymTab->isValueGood(string(lTerm))) {
00916         if (gPrintWarnings) {
00917           cerr << "Warning: String '" << lTerm
00918                << "' is not in universe." << endl;
00919         }
00920         // Result for expression with non-existing value is always the empty set.
00921         regfree(&lRegExCompiled);
00922         return bddRelation(pSymTab, false);
00923       }
00924       // String matching.
00925       bool result = regexmatch(&lRegExCompiled, 
00926                                lRegExStr, 
00927                                lTerm);
00928       regfree(&lRegExCompiled);
00929       return bddRelation(pSymTab, result);
00930     }
00931 
00932     if (dynamic_cast<relTermExists*>(mTerm) != NULL)
00933     {
00934       for (reprNUMBER i = 0; i < pSymTab->getUniverseSize(); ++i)
00935       {
00936         // String matching.
00937         bool result = regexmatch(&lRegExCompiled, 
00938                                  lRegExStr, 
00939                                  lTerm);
00940         if (result) {
00941           regfree(&lRegExCompiled);
00942           return bddRelation(pSymTab, true);
00943         }
00944       }
00945       regfree(&lRegExCompiled);
00946       return bddRelation(pSymTab, false);
00947     }
00948 
00949     // Nothing else left here, must be relTermAttribute.
00950     assert(dynamic_cast<relTermAttribute*>(mTerm) != NULL);
00951 
00952     // lTerm is an attribute.
00953     // Add internal attribute to SymTab, if new.
00954     pSymTab->addAttribute(mTerm->interpret(pSymTab)); 
00955 
00956     bddRelation result(pSymTab, false);
00957     const unsigned lVarId = pSymTab->getAttributePos(lTerm);
00958     for (reprNUMBER i = 0; i < pSymTab->getUniverseSize(); ++i)
00959     {
00960       const string lValue = pSymTab->getAttributeValue(i);
00961       // String matching.
00962       if (regexmatch(&lRegExCompiled,
00963                      lRegExStr, 
00964                      lValue.c_str())) {
00965         result.unite( bddRelation::mkEqual(pSymTab, lVarId, i) );
00966       }
00967     }
00968     regfree(&lRegExCompiled);
00969     return result;
00970   }
00971 };
00972 
00973 
00976 class relExprTupleOf : public relExpression
00977 {
00978 private:
00979   relExpression*        mExpr;
00980 
00981 public:
00982   relExprTupleOf(relExpression* pExpr)
00983     : mExpr(pExpr)
00984   {}
00985 
00986   ~relExprTupleOf()
00987   {
00988     delete mExpr;
00989   }
00990 
00991   virtual set<string>
00992   collectFreeAttrs()
00993   {
00994         return mExpr->collectFreeAttrs();
00995   }
00996 
00997   virtual bddRelation
00998   interpret(bddSymTab* pSymTab)
00999   {
01000     // First evaluate, to set variables in the variable ordering.
01001     bddRelation lRel = mExpr->interpret(pSymTab);
01002     const set<string> lFree = mExpr->collectFreeAttrs();
01003     const map<unsigned,string> lVarOrd = pSymTab->computeVariableOrder(lFree);
01004     if( lRel.isEmpty() ) {
01005       cerr << "Error: TUPLEOF requires a non-empty relation as parameter." 
01006                << endl;
01007       exit(EXIT_FAILURE);
01008     }
01009     return lRel.getTupleOf(lVarOrd);
01010   }
01011 };
01012 
01013 #endif
01014 

Generated on Fri Jun 6 22:21:09 2008 for CrocoPat by  doxygen 1.5.1