predicate.h

00001 /*
00002  * All of the documentation and software included in the
00003  * Alchemy Software is copyrighted by Stanley Kok, Parag
00004  * Singla, Matthew Richardson, Pedro Domingos, Marc
00005  * Sumner and Hoifung Poon.
00006  * 
00007  * Copyright [2004-07] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00009  * Poon. All rights reserved.
00010  * 
00011  * Contact: Pedro Domingos, University of Washington
00012  * (pedrod@cs.washington.edu).
00013  * 
00014  * Redistribution and use in source and binary forms, with
00015  * or without modification, are permitted provided that
00016  * the following conditions are met:
00017  * 
00018  * 1. Redistributions of source code must retain the above
00019  * copyright notice, this list of conditions and the
00020  * following disclaimer.
00021  * 
00022  * 2. Redistributions in binary form must reproduce the
00023  * above copyright notice, this list of conditions and the
00024  * following disclaimer in the documentation and/or other
00025  * materials provided with the distribution.
00026  * 
00027  * 3. All advertising materials mentioning features or use
00028  * of this software must display the following
00029  * acknowledgment: "This product includes software
00030  * developed by Stanley Kok, Parag Singla, Matthew
00031  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00032  * Poon in the Department of Computer Science and
00033  * Engineering at the University of Washington".
00034  * 
00035  * 4. Your publications acknowledge the use or
00036  * contribution made by the Software to your research
00037  * using the following citation(s): 
00038  * Stanley Kok, Parag Singla, Matthew Richardson and
00039  * Pedro Domingos (2005). "The Alchemy System for
00040  * Statistical Relational AI", Technical Report,
00041  * Department of Computer Science and Engineering,
00042  * University of Washington, Seattle, WA.
00043  * http://www.cs.washington.edu/ai/alchemy.
00044  * 
00045  * 5. Neither the name of the University of Washington nor
00046  * the names of its contributors may be used to endorse or
00047  * promote products derived from this software without
00048  * specific prior written permission.
00049  * 
00050  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
00051  * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00052  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00053  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00054  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
00055  * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00056  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00057  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00058  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00059  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00060  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00061  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00062  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00063  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00064  * 
00065  */
00066 #ifndef PREDICATE_H_JUN_26_2005
00067 #define PREDICATE_H_JUN_26_2005
00068 
00069 #include <ext/hash_set>
00070 using namespace __gnu_cxx;
00071 #include "predicatetemplate.h"
00072 #include "term.h"
00073 #include "hash.h"
00074 #include "hasharray.h"
00075 #include "function.h"
00076 
00077 const int MAX_VAR = 10;
00078 enum TruthValue { FALSE = 0, TRUE = 1, UNKNOWN = 2 };
00079 
00080 struct VarsTypeId { Array<Term*> vars; int typeId; }; 
00081 
00082 class Clause;
00083 class GroundPredicate;
00084 class Domain;
00085 
00086   //Ensure that the dirty_ bit is consistently updated.
00087 class Predicate
00088 {
00089  public:
00090   Predicate(const PredicateTemplate* const & pt) 
00091     : template_(pt), terms_(new Array<Term*>), sense_(true), 
00092       truthValue_(UNKNOWN), allTermsAreDiffVars_(false), isGrounded_(false), 
00093       intArrRep_(NULL), hashCode_(0), dirty_(true), parent_(NULL) {}
00094 
00095   Predicate(const PredicateTemplate* const & pt, Clause* const & parent)
00096     : template_(pt), terms_(new Array<Term*>), sense_(true), 
00097       truthValue_(UNKNOWN), allTermsAreDiffVars_(false), isGrounded_(false), 
00098       intArrRep_(NULL), hashCode_(0), dirty_(true), parent_(parent) {}
00099 
00100   Predicate(const Predicate& p)  { parent_ = NULL; copy(p); }
00101   Predicate(const Predicate& p,  Clause* const & par) { parent_= par; copy(p); }
00102 
00103   
00104   ~Predicate()
00105   {
00106     for (int i = 0; i < terms_->size(); i++)  delete (*terms_)[i];
00107     delete terms_;
00108     if (intArrRep_) delete intArrRep_;
00109   }
00110 
00111 
00112   double sizeMB() const
00113   {
00114     double sizeMB = (fixedSizeB_ + intArrRep_->size()*sizeof(int) +
00115                      terms_->size()*sizeof(Term*))/1000000.0;
00116     for (int i = 0; i < terms_->size(); i++) sizeMB += (*terms_)[i]->sizeMB();
00117     return sizeMB;
00118   }
00119 
00120 
00121   static void computeFixedSizeB()
00122   { fixedSizeB_ = (sizeof(Predicate)+sizeof(Array<Term*>)+sizeof(Array<int>)); }
00123 
00124 
00125   void compress() 
00126   { 
00127     for (int i = 0; i < terms_->size(); i++)  (*terms_)[i]->compress();
00128     terms_->compress(); 
00129     intArrRep_->compress(); 
00130   }
00131 
00132 
00133     //returns true if this predicate represents "="
00134   bool isEqualPred() const  { return template_->isEqualPred(); }
00135   
00136   bool isEqualPredWithType() const  { return template_->isEqualPredWithType(); }
00137 
00138     //returns true if this predicate is empty predicate
00139   bool isEmptyPred() const  { return template_->isEmptyPredicateTemplate(); }
00140  
00141      //returns true if this predicate is an internal predicate
00142   bool isInternalPred() const  { return template_->isInternalPredicateTemplate(); }
00143   
00144   bool isInternalPredWithoutType() const
00145   { return template_->isInternalPredicateTemplateWithoutType(); }
00146 
00147   void canonicalize()
00148   {
00149     Array<int> varIdToNewVarId;
00150     int newVarId = 0;
00151     for (int i = 0; i < terms_->size(); i++)
00152     {
00153       if ((*terms_)[i]->getType() == Term::VARIABLE)
00154       {
00155         int id = -((*terms_)[i]->getId());
00156         assert(id > 0);
00157         if (id >= varIdToNewVarId.size()) varIdToNewVarId.growToSize(id+1,0);
00158           //if a new var id has not been assigned to old var id
00159         if (varIdToNewVarId[id] >= 0) varIdToNewVarId[id] = --newVarId;
00160         (*terms_)[i]->setId(varIdToNewVarId[id]);
00161       }
00162       assert((*terms_)[i]->getType() != Term::FUNCTION);
00163     }
00164   }
00165 
00166 
00167     //term is owned by Predicate. Caller should not delete it
00168   void appendTerm(Term* const & term)
00169   {
00170     if (template_->getNumTerms() == terms_->size()) 
00171     {
00172       cout << "Error: In Predicate::appendTerm. Tried to add more terms than "
00173            << "the declared num of " << template_->getNumTerms() << endl;
00174       exit(-1);
00175     }
00176     terms_->append(term);
00177     setDirty();
00178   }
00179 
00180   
00181   bool getSense() const { return sense_; }
00182   void setSense(const bool& s) { sense_ = s; setDirty();}
00183   void invertSense() { sense_ = (sense_) ? false : true; setDirty(); }
00184 
00185     //get and set the definitive truth value of the predicate
00186   TruthValue getTruthValue() const { return truthValue_; }
00187   void setTruthValue(const TruthValue& tv) { truthValue_ = tv; }
00188   string getTruthValueAsStr() const 
00189   {
00190     if (truthValue_ == TRUE)    return "TRUE";
00191     if (truthValue_ == FALSE)   return "FALSE";
00192     if (truthValue_ == UNKNOWN) return "UNKNOWN";
00193     assert(false); 
00194     return "UNKNOWN"; //avoid compilation warning
00195   }
00196 
00197 
00198   double getNumGroundingsIfAllVarDiff(const Domain* const & domain) const;
00199  
00200   
00201     //Caller is responsible for deleting the Predicate* in returnArray
00202   static void createAllGroundings(const int& predId, 
00203                                   const Domain* const & domain,
00204                                   Array<Predicate*>& returnArray);
00205     
00206   
00207   //Caller is responsible for deleting the Predicate* in returnArray
00208   static void createAllGroundingsUnifyingWithTerm(const int& predId, 
00209                                   const Domain* const & domain,
00210                                   Array<Predicate*>& returnArray,
00211                                                                   int termTypeId,int termVal);
00212 
00213 
00214   void createAllGroundingsIfAllVarDiff(const Domain* const & domain,
00215                                        Array<Predicate*>& returnArray)
00216   { createAllGroundings(getId(), domain, returnArray); }
00217 
00218 
00219     //Create groundings of predicate, taking into account vars may be shared.
00220     //Exactly one of  predReturnArray or constReturnArray must be NULL.
00221     //Callers are responsible for deleting the parameters and their contents.
00222   void createAllGroundings(const Domain* const & domain,
00223                            Array<Predicate*>* const & predReturnArray,
00224                            Array<int*>* const & constReturnArray);
00225 
00226     //create groundings of predicate, taking into account vars may be shared
00227   void createAllGroundings(const Domain* const & domain,
00228                            Array<Predicate*>& returnArray)
00229   { createAllGroundings(domain, &returnArray, NULL); }
00230 
00231 
00232     //create groundings of predicate, taking into account vars may be shared
00233   void createAllGroundings(const Domain* const & domain,
00234                            Array<int*>& returnArray)
00235   { createAllGroundings(domain, NULL, &returnArray); }
00236 
00237 
00238   int getNumTerms() const { return terms_->size(); }
00239 
00240   const Term* getTerm(const int& idx) const { return (*terms_)[idx]; }
00241 
00242 
00243   void setTermToConstant(const int& termNum, const int& constId)
00244   {
00245     assert(termNum < template_->getNumTerms());
00246     assert(constId >= 0);
00247     if (termNum >= terms_->size()) terms_->growToSize(termNum+1,NULL);
00248     if ((*terms_)[termNum]) delete (*terms_)[termNum];
00249     (*terms_)[termNum] = new Term(constId, (void*)this, true);
00250     setDirty();
00251   }
00252 
00253   
00254   bool containsConstant(const int& constId) const
00255   {
00256     assert(constId >= 0);
00257     for (int i = 0; i < terms_->size(); i++)
00258     {
00259       Term* t = (*terms_)[i];
00260       if (t->getType() == Term::CONSTANT && t->getId() == constId) return true;
00261     }
00262     return false;
00263   }
00264 
00265 
00266   void setTemplate(PredicateTemplate* const & t) { template_ = t; }
00267 
00268   const PredicateTemplate* getTemplate() const { return template_; }
00269 
00270 
00271     // Caller should not delete the returned const char* 
00272   const char* getName() const { return template_->getName(); }
00273 
00274   int getId() const { return template_->getId(); }
00275   
00276 
00277     // Caller should not delete the returned const char* nor modify its
00278     // contents. Returns NULL if idx is larger than the possible number of 
00279     // terms
00280   const char* getTermTypeAsStr(const int& idx) const 
00281   {
00282     if (idx >= template_->getNumTerms()) return NULL;
00283     return template_->getTermTypeAsStr(idx); 
00284   }
00285 
00286     // Returns -1 if idx is larger than the possible number of terms
00287   int getTermTypeAsInt(const int& idx) const 
00288   {
00289     if (idx >= template_->getNumTerms()) return -1;
00290     return template_->getTermTypeAsInt(idx); 
00291   }
00292 
00293 
00294   bool allTermsAreDiffVars()
00295   {
00296     if (dirty_) computeAndStoreIntArrRep();
00297     return allTermsAreDiffVars_;
00298   }
00299   
00300 
00301   bool checkAllTermsAreDiffVars()
00302   {
00303     Array<int> vars;
00304     allTermsAreDiffVars_ = true;
00305     for (int i = 0; i < terms_->size(); i++)
00306     {
00307       if ((*terms_)[i]->getType() == Term::VARIABLE)
00308       {
00309         int tid = (*terms_)[i]->getId();
00310         if (vars.contains(tid)) { allTermsAreDiffVars_ = false; return false;}
00311         else                    vars.append(tid);
00312       }
00313       else
00314       { 
00315         assert((*terms_)[i]->getType() != Term::FUNCTION);
00316           //is a constant
00317         allTermsAreDiffVars_ = false;
00318         return false;
00319       }
00320     }
00321     return true;
00322   }
00323 
00324 
00325   bool isGrounded()
00326   {
00327     if (dirty_) computeAndStoreIntArrRep();
00328     return isGrounded_;    
00329   }
00330 
00331   
00332   bool canBeGroundedAs(Predicate* const & gndPred)
00333   {
00334     assert(gndPred->isGrounded());
00335     if (template_->getId() != gndPred->getId()) return false;
00336     if (allTermsAreDiffVars()) return true;
00337     if (isGrounded()) return same(gndPred);
00338     
00339     int varGndings[MAX_VAR];
00340     memset(varGndings, -1, MAX_VAR*sizeof(int));
00341     for (int i = 0; i < terms_->size(); i++) 
00342     {
00343       int termType = (*terms_)[i]->getType();
00344       
00345       if (termType == Term::CONSTANT) 
00346       {
00347         if ((*terms_)[i]->getId() != gndPred->getTerm(i)->getId()) 
00348           return false;
00349       }
00350       else 
00351       if (termType == Term::VARIABLE) 
00352       {
00353         int varId = -(*terms_)[i]->getId();
00354         assert(varId > 0);
00355         assert(varId < MAX_VAR);
00356         if (varGndings[varId] < 0) // if variable has not been grounded
00357           varGndings[varId] = gndPred->getTerm(i)->getId();
00358         else 
00359           if (varGndings[varId] != gndPred->getTerm(i)->getId())
00360             return false;
00361       }
00362       else
00363       {
00364         assert(false);
00365       }
00366     }
00367     return true;
00368   }
00369 
00370 
00371   bool canBeGroundedAs(const GroundPredicate* const & gndPred);
00372 
00373 
00374   void setDirty();
00375   bool isDirty() const { return dirty_; }
00376 
00377   void setParent(Clause* const & parent) { parent_ = parent; setDirty(); }
00378   Clause* getParent() const { return parent_; }
00379 
00380         // True, if the predicate can be used in the inverted index
00381     // If in pos. clause, then it must be negated and binary
00382     // If in neg. clause, then the inverted index can not be used
00383   bool isIndexable(bool posClause)
00384   {
00385           // At most one of the two terms is grounded
00386           // and equality pred is never indexed
00387         if (isGrounded() || isEqualPred()) return false;
00388     
00389     if (posClause)
00390       return (!getSense() && getNumTerms() == 2);
00391     else
00392       return false;
00393   }
00394 
00395   void createVarsTypeIdArr(Array<VarsTypeId*>*& varsTypeIdArr)
00396   {
00397     if (varsTypeIdArr == NULL) varsTypeIdArr = new Array<VarsTypeId*>;
00398 
00399       //for each variable of the predicate
00400     for (int j = 0; j < terms_->size(); j++)
00401     {
00402       Term* t = (*terms_)[j];
00403       if (t->getType() == Term::VARIABLE)
00404       {
00405         int id = -(t->getId());
00406         assert(id > 0);
00407         if (id >= varsTypeIdArr->size()) varsTypeIdArr->growToSize(id+1,NULL);
00408         VarsTypeId*& vti = (*varsTypeIdArr)[id];
00409         if (vti == NULL) 
00410         {
00411           vti = new VarsTypeId;
00412           vti->typeId = getTermTypeAsInt(j);
00413           assert(vti->typeId >= 0);
00414         }
00415         assert(getTermTypeAsInt(j) == vti->typeId);
00416         vti->vars.append(t);
00417       }
00418       assert(t->getType() != Term::FUNCTION);
00419     }// for each variable of the predicate
00420   }
00421 
00422 
00423   void deleteVarsTypeIdArr(Array<VarsTypeId*>*& varsTypeIdArr)
00424   {
00425     for (int i = 0; i < varsTypeIdArr->size(); i++)
00426       if ((*varsTypeIdArr)[i]) delete (*varsTypeIdArr)[i];
00427     delete varsTypeIdArr;
00428     varsTypeIdArr = NULL; 
00429   }
00430 
00431 
00432     //Does not consider the sense of the predicate.
00433   bool same(Predicate* const & p)
00434   {
00435     if (this == p)  return true;
00436     const Array<int>* pArr  = p->getIntArrRep();
00437     const Array<int>* myArr = getIntArrRep();
00438     if (myArr->size() != pArr->size()) return false;
00439     const int* pItems  = p->getIntArrRep()->getItems();
00440     const int* myItems = getIntArrRep()->getItems();
00441     return (memcmp(myItems, pItems, myArr->size()*sizeof(int))==0);
00442   }
00443 
00444 
00445   bool same(const GroundPredicate* const & gp);
00446 
00447   
00448     // represent function as an Array<int> and append it to rep
00449   void appendIntArrRep(Array<int>& rep) 
00450   {
00451     if (dirty_) computeAndStoreIntArrRep();
00452     rep.append(*intArrRep_);
00453   }
00454 
00455 
00456   size_t hashCode()
00457   {
00458     if (dirty_) computeAndStoreIntArrRep();
00459     return hashCode_;
00460   }
00461 
00462 
00463   ostream& printAsInt(ostream& out) const
00464   {
00465     if(isEqualPred()) return printAsIntEqualPred(out);
00466     if(isInternalPred()) return printAsIntInternalPred(out);
00467 
00468     if (!sense_) out << "!";
00469     out << template_->getId() << "(";
00470     for (int i = 0; i < terms_->size(); i++)
00471     {
00472       (*terms_)[i]->printAsInt(out); 
00473       out << ((i!=terms_->size()-1)?",":")");
00474     }
00475     return out;
00476   }
00477 
00478 
00479   ostream& printWithStrVar(ostream& out, const Domain* const & domain) const
00480   {
00481     if (isEqualPred()) return printEqualPredWithStrVar(out,domain);
00482     if (isInternalPred()) return printInternalPredWithStrVar(out,domain);
00483 
00484     if (!sense_) out << "!";
00485     out << template_->getName() << "(";
00486     for (int i = 0; i < terms_->size(); i++)
00487     {
00488       (*terms_)[i]->printWithStrVar(out, domain); 
00489       out << ((i!=terms_->size()-1)?",":")");
00490     }
00491     return out;
00492   }
00493 
00494 
00495   ostream& print(ostream& out, const Domain* const & domain) const
00496   {
00497     if (isEqualPred()) return printEqualPred(out, domain);
00498     if (isInternalPred()) return printInternalPred(out, domain);
00499 
00500     if (!sense_) out << "!";
00501     out << template_->getName() << "(";
00502     for (int i = 0; i < terms_->size(); i++)
00503     {
00504       (*terms_)[i]->print(out, domain); 
00505       out << ((i!=terms_->size()-1)?",":")");
00506     }
00507     return out;
00508   }
00509 
00510 
00511  private:
00512   void copy(const Predicate& p)
00513   {
00514     template_ = p.template_;
00515 
00516     terms_ = new Array<Term*>;
00517     Array<Term*>* tterms = p.terms_;
00518     for (int i = 0; i < tterms->size(); i++)
00519     {
00520       Term* t = (*tterms)[i];
00521       terms_->append(new Term(*t, (void*)this, true));      
00522     }
00523     dirty_ = p.dirty_;
00524 
00525     if (!dirty_) { assert(noDirtyTerms()); }
00526 
00527     sense_ = p.sense_;
00528     truthValue_ = p.truthValue_;
00529     allTermsAreDiffVars_ = p.allTermsAreDiffVars_;
00530     isGrounded_ = p.isGrounded_;
00531     
00532     if (p.intArrRep_)  intArrRep_ = new Array<int>(*(p.intArrRep_));
00533     else               intArrRep_ = NULL;    
00534 
00535     hashCode_ = p.hashCode_;
00536 
00537     setParentDirty();
00538   }
00539 
00540 
00541   void setParentDirty();
00542 
00543   bool noDirtyTerms()
00544   {
00545     for (int i = 0; i < terms_->size(); i++)
00546       if ((*terms_)[i]->isDirty()) return false;
00547     return true;
00548   }
00549 
00550 
00551   const Array<int>* getIntArrRep() 
00552   { if (dirty_) computeAndStoreIntArrRep(); return intArrRep_; }
00553 
00554 
00555     //Also finds out whether all of its terms are variables/constants.
00556   void computeAndStoreIntArrRep()
00557   {
00558     dirty_ = false;
00559     if (intArrRep_ == NULL) intArrRep_ = new Array<int>;
00560     else                    intArrRep_->clear();
00561       //commented out: predicate comparison ignores sense
00562     //intArrRep_->append(sense_?1:0);
00563     intArrRep_->append(template_->getId());
00564     int numTerms = terms_->size();
00565     Array<int> vars(numTerms);
00566     allTermsAreDiffVars_ = true;
00567     isGrounded_ = true;
00568     for (int i = 0; i < numTerms; i++)
00569     {
00570       (*terms_)[i]->appendIntArrRep(*intArrRep_);
00571       int termType = (*terms_)[i]->getType();
00572       
00573       if (termType == Term::VARIABLE)
00574       {
00575         if (allTermsAreDiffVars_)
00576         {
00577           int tid = (*terms_)[i]->getId();
00578           if (vars.contains(tid)) allTermsAreDiffVars_ = false;
00579           else                    vars.append(tid);
00580         }
00581         isGrounded_ = false;
00582       }
00583       else
00584       if (termType == Term::CONSTANT)
00585       {
00586         allTermsAreDiffVars_ = false;
00587         if ((*terms_)[i]->getType() != Term::CONSTANT) isGrounded_ = false;
00588       }
00589       else
00590       {
00591         assert(false);
00592       }
00593     }
00594     hashCode_ = Hash::hash(*intArrRep_);
00595   }
00596 
00597 
00598   ostream& printAsIntEqualPred(ostream& out) const
00599   {
00600     assert(isEqualPred());
00601     assert(terms_->size()==2);
00602     if (!sense_) out << "!(";
00603     (*terms_)[0]->printAsInt(out); 
00604     out << " = ";
00605     (*terms_)[1]->printAsInt(out); 
00606     if (!sense_) out << ")";
00607     return out;
00608   }
00609 
00610 
00611   ostream& printEqualPred(ostream& out, const Domain* const & domain) const
00612   {
00613     assert(isEqualPred());
00614     assert(terms_->size()==2);
00615     if (!sense_) out << "!(";
00616     (*terms_)[0]->print(out, domain); 
00617     out << " = ";
00618     (*terms_)[1]->print(out, domain); 
00619     if (!sense_) out << ")";
00620     return out;
00621   }
00622 
00623 
00624   ostream& 
00625   printEqualPredWithStrVar(ostream& out, const Domain* const & domain) const
00626   {
00627     assert(isEqualPred());
00628     assert(terms_->size()==2);
00629     if (!sense_) out << "!(";
00630     (*terms_)[0]->printWithStrVar(out, domain); 
00631     out << " = ";
00632     (*terms_)[1]->printWithStrVar(out, domain); 
00633     if (!sense_) out << ")";
00634     return out;
00635   }
00636     
00637     
00638   ostream& printAsIntInternalPred(ostream& out) const
00639   {
00640     assert(isInternalPred());
00641     assert(terms_->size()==2);
00642     
00643       //No infix
00644         if (strncmp(getName(), PredicateTemplate::SUBSTR_NAME,
00645                                 strlen(PredicateTemplate::SUBSTR_NAME)) == 0)
00646         {
00647           if (!sense_) out << "!";
00648       out << template_->getId() << "(";
00649       for (int i = 0; i < terms_->size(); i++)
00650       {
00651         (*terms_)[i]->printAsInt(out); 
00652         out << ((i!=terms_->size()-1)?",":")");
00653       }
00654       return out; 
00655         }
00656         else // Infix
00657         {
00658       if (!sense_) out << "!(";
00659       (*terms_)[0]->printAsInt(out); 
00660           
00661           if (strncmp(getName(), PredicateTemplate::GT_NAME,
00662                                   strlen(PredicateTemplate::GT_NAME)) == 0)
00663         out << " > ";
00664       else
00665           if (strncmp(getName(), PredicateTemplate::LT_NAME,
00666                                   strlen(PredicateTemplate::LT_NAME)) == 0)
00667         out << " < ";
00668       else
00669       if (strncmp(getName(), PredicateTemplate::GTEQ_NAME,
00670                                   strlen(PredicateTemplate::GTEQ_NAME)) == 0)
00671         out << " >= ";
00672       else
00673           if (strncmp(getName(), PredicateTemplate::LTEQ_NAME,
00674                                   strlen(PredicateTemplate::LTEQ_NAME)) == 0)
00675         out << " <= ";
00676       
00677       (*terms_)[1]->printAsInt(out); 
00678       if (!sense_) out << ")";
00679       return out;
00680         }
00681   }
00682 
00683 
00684   ostream& printInternalPred(ostream& out, const Domain* const & domain) const
00685   {
00686     assert(isInternalPred());
00687     assert(terms_->size()==2);
00688 
00689           //No infix
00690         if (strncmp(getName(), PredicateTemplate::SUBSTR_NAME,
00691                                 strlen(PredicateTemplate::SUBSTR_NAME)) == 0)
00692         {
00693       if (!sense_) out << "!";
00694       out << PredicateTemplate::SUBSTR_NAME << "(";
00695       for (int i = 0; i < terms_->size(); i++)
00696       {
00697         (*terms_)[i]->print(out, domain); 
00698         out << ((i!=terms_->size()-1)?",":")");
00699       }
00700       return out;
00701         }
00702         else // Infix
00703         {
00704           if (!sense_) out << "!(";
00705       (*terms_)[0]->print(out, domain); 
00706           
00707           if (strncmp(getName(), PredicateTemplate::GT_NAME,
00708                                   strlen(PredicateTemplate::GT_NAME)) == 0)
00709         out << " > ";
00710       else
00711           if (strncmp(getName(), PredicateTemplate::LT_NAME,
00712                                   strlen(PredicateTemplate::LT_NAME)) == 0)
00713         out << " < ";
00714       else
00715       if (strncmp(getName(), PredicateTemplate::GTEQ_NAME,
00716                                   strlen(PredicateTemplate::GTEQ_NAME)) == 0)
00717         out << " >= ";
00718       else
00719           if (strncmp(getName(), PredicateTemplate::LTEQ_NAME,
00720                                   strlen(PredicateTemplate::LTEQ_NAME)) == 0)
00721         out << " <= ";
00722       
00723       (*terms_)[1]->print(out, domain); 
00724       if (!sense_) out << ")";
00725       return out;
00726         }
00727   }
00728 
00729 
00730   ostream& 
00731   printInternalPredWithStrVar(ostream& out, const Domain* const & domain) const
00732   {
00733     assert(isInternalPred());
00734     assert(terms_->size()==2);
00735 
00736           //No infix
00737         if (strncmp(getName(), PredicateTemplate::SUBSTR_NAME,
00738                                 strlen(PredicateTemplate::SUBSTR_NAME)) == 0)
00739         {
00740       if (!sense_) out << "!";
00741       out << PredicateTemplate::SUBSTR_NAME << "(";
00742       for (int i = 0; i < terms_->size(); i++)
00743       {
00744         (*terms_)[i]->printWithStrVar(out, domain); 
00745         out << ((i!=terms_->size()-1)?",":")");
00746       }
00747       return out;
00748         }
00749         else // Infix
00750         {
00751       if (!sense_) out << "!(";
00752       (*terms_)[0]->printWithStrVar(out, domain);
00753           
00754           if (strncmp(getName(), PredicateTemplate::GT_NAME,
00755                                   strlen(PredicateTemplate::GT_NAME)) == 0)
00756         out << " > ";
00757       else
00758           if (strncmp(getName(), PredicateTemplate::LT_NAME,
00759                                   strlen(PredicateTemplate::LT_NAME)) == 0)
00760         out << " < ";
00761       else
00762       if (strncmp(getName(), PredicateTemplate::GTEQ_NAME,
00763                                   strlen(PredicateTemplate::GTEQ_NAME)) == 0)
00764         out << " >= ";
00765       else
00766           if (strncmp(getName(), PredicateTemplate::LTEQ_NAME,
00767                                   strlen(PredicateTemplate::LTEQ_NAME)) == 0)
00768         out << " <= ";
00769       
00770       (*terms_)[1]->printWithStrVar(out, domain); 
00771       if (!sense_) out << ")";
00772       return out;
00773         }
00774   }
00775   
00776    
00777  private:
00778   const PredicateTemplate* template_; // not owned by Predicate
00779   Array<Term*>* terms_;
00780   bool sense_; // indicate whether the predicate is non-negated/negated
00781   TruthValue truthValue_;
00782 
00783   bool allTermsAreDiffVars_; // all of its terms are different variables
00784   bool isGrounded_;
00785 
00786   Array<int>* intArrRep_;
00787   size_t hashCode_;
00788   bool dirty_;
00789   Clause* parent_; //not owned by Predicate, so no deleted in destructor
00790 
00791   static double fixedSizeB_;
00792 };
00793 
00794 inline
00795 ostream& operator<<(ostream& out, const Predicate& p){return p.printAsInt(out);}
00796 
00797 
00799 
00800 class HashPredicate
00801 {
00802  public:
00803   size_t operator()(Predicate* const & p) const  { return p->hashCode(); }
00804 };
00805 
00806 
00807 class EqualPredicate
00808 {
00809  public:
00810   bool operator()(Predicate* const & p1, Predicate* const & p2) 
00811     const { return p1->same(p2); }
00812 };
00813 
00815 
00816 typedef hash_set<Predicate*, HashPredicate, EqualPredicate> PredicateSet;
00817 
00818 typedef HashArray<Predicate*, HashPredicate, EqualPredicate> PredicateHashArray;
00819 
00820 #endif

Generated on Tue Jan 16 05:30:04 2007 for Alchemy by  doxygen 1.5.1