function.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 FUNCTION_H_JUN_26_2005
00067 #define FUNCTION_H_JUN_26_2005
00068 
00069 #include <ext/hash_set>
00070 using namespace __gnu_cxx;
00071 #include "functiontemplate.h"
00072 #include "hash.h"
00073 #include "term.h"
00074 
00075 
00076   //Ensure that the dirty_ bit is consistently updated.
00077 class Function
00078 {
00079  public:
00080 
00081   Function(const FunctionTemplate* const & ft) 
00082     : template_(ft), terms_(new Array<Term*>), retConstId_(-1), 
00083       intArrRep_(NULL), hashCode_(0), dirty_(true), parent_(NULL) {}
00084 
00085 
00086   Function(const FunctionTemplate* const & ft, Term* const & parent) 
00087     : template_(ft), terms_(new Array<Term*>), retConstId_(-1), 
00088     intArrRep_(NULL), hashCode_(0), dirty_(true), parent_(NULL) {}
00089     
00090 
00091   Function(const Function& f) { parent_ = NULL;  copy(f); }
00092   Function(const Function& f, Term* const & parent) { parent_=parent; copy(f); }
00093   
00094 
00095   ~Function() 
00096   {
00097     for (int i = 0; i < terms_->size(); i++)
00098       delete (*terms_)[i];
00099     delete terms_;
00100     if (intArrRep_) delete intArrRep_;
00101   }
00102 
00103 
00104     //term is owned by Function. Caller should not delete it.
00105   void appendTerm(Term* const & term)
00106   {
00107     if (template_->getNumTerms() == terms_->size()) 
00108     {
00109       cout << "Error: In Function::appendTerm. Tried to add more terms than "
00110            << "the declared num of " << template_->getNumTerms() << endl;
00111       exit(-1);
00112     }
00113     terms_->append(term);
00114     setDirty();
00115   }
00116 
00117   
00118   int getNumTerms() const { return terms_->size(); }
00119 
00120   const Term* getTerm(const int& idx) const { return (*terms_)[idx]; }
00121 
00122   void setTemplate(FunctionTemplate* const & t) { template_ = t; }
00123 
00124   const FunctionTemplate* getTemplate() const { return template_; }
00125 
00126     // Caller should not delete the returned const char* 
00127   const char* getName() const { return template_->getName(); }
00128 
00129   int getId() const { return template_->getId(); }
00130 
00131 
00132     // retConstId refers to the id of the constant returned by the function
00133   void setRetConstId(const int& constId) { retConstId_ = constId; setDirty();}
00134   int getRetConstId() const { return retConstId_; }
00135 
00136   void setDirty();
00137   bool isDirty() const { return dirty_; }
00138 
00139   void setParent(Term* const parent) { parent_ = parent; setDirty(); }
00140   Term* getParent() const { return parent_; }
00141 
00142 
00143     // Caller should not delete the returned const char* nor modify its
00144     // contents. Returns NULL if idx is larger than the possible number of 
00145     // terms
00146   const char* getTermTypeAsStr(const int& idx) const 
00147   {
00148     if (idx >= template_->getNumTerms()) return NULL;
00149     return template_->getTermTypeAsStr(idx); 
00150   }
00151 
00152     // Returns -1 if idx is larger than the possible number of terms
00153   int getTermTypeAsInt(const int& idx) const 
00154   {
00155     if (idx >= template_->getNumTerms()) return -1;
00156     return template_->getTermTypeAsInt(idx); 
00157   }
00158 
00159 
00160   int getRetTypeId() const { return template_->getRetTypeId(); }
00161   
00162     // Caller should not delete the returned const char*
00163   const char* getRetTypeName() const { return template_->getRetTypeName(); }
00164 
00165   bool same(const Function* const & f) const
00166   {
00167     if (this == f) return true;
00168     //commented out: no need to check return values are the same
00169     //if (retConstId_ != f->getRetConstId()) return false;
00170     if (template_->getId() != f->getId()) return false;
00171     int numTerms = terms_->size();
00172     if (numTerms != f->getNumTerms()) return false;
00173     for (int i = 0; i < numTerms; i++)
00174       if ((*terms_)[i]->getId() != f->getTerm(i)->getId()) return false;
00175     return true;
00176   }
00177 
00178   
00179     // represent function as an Array<int> and append it to rep
00180   void appendIntArrRep(Array<int>& rep) 
00181   {
00182     if (dirty_) computeAndStoreIntArrRep();
00183     rep.append(*intArrRep_);
00184   }
00185 
00186 
00187   size_t hashCode()
00188   {
00189     if (dirty_) computeAndStoreIntArrRep();
00190     return hashCode_;
00191   }
00192 
00193 
00194   bool same(Function* const & f)
00195   {
00196     if (this==f)  return true;
00197     const Array<int>* fArr  = f->getIntArrRep();
00198     const Array<int>* myArr = getIntArrRep();
00199     if (myArr->size() != fArr->size()) return false;
00200     const int* fItems  = f->getIntArrRep()->getItems();
00201     const int* myItems = getIntArrRep()->getItems();
00202     return (memcmp(myItems, fItems, myArr->size()*sizeof(int))==0); 
00203   }
00204 
00205 
00206   ostream& printAsInt(ostream& out) const
00207   {
00208     out << template_->getId() << "(";
00209     for (int i = 0; i < terms_->size(); i++)
00210     {
00211       (*terms_)[i]->printAsInt(out); 
00212       out << ((i!=terms_->size()-1)?",":")");
00213     }
00214     return out;
00215   }
00216 
00217 
00218   ostream& printAsIntWithRetConstId(ostream& out) const
00219   {
00220     printAsInt(out);
00221     out << "=" << retConstId_ << endl;
00222     return out;
00223   }
00224 
00225 
00226   ostream& print(ostream& out, const Domain* const & domain) const
00227   {
00228     out << template_->getName() << "(";
00229     for (int i = 0; i < terms_->size(); i++)
00230     {
00231       (*terms_)[i]->print(out, domain); 
00232       out << ((i!=terms_->size()-1)?",":")");
00233     }
00234     return out;
00235   }
00236 
00237 
00238   ostream& 
00239   printWithRetConstName(ostream& out, const Domain* const & domain) const;
00240 
00241 
00242  private:
00243   void copy(const Function& f)
00244   {
00245     template_ = f.template_;
00246 
00247     terms_ = new Array<Term*>;
00248     Array<Term*>* fterms = f.terms_;
00249     for (int i = 0; i < fterms->size(); i++)
00250     {
00251       Term* t = (*fterms)[i];
00252       terms_->append(new Term(*t, (void*)this, false));
00253     }
00254     dirty_ = f.dirty_;
00255 
00256     if (!dirty_) { assert(noDirtyTerms()); }
00257 
00258     retConstId_ = f.retConstId_;
00259 
00260     if (f.intArrRep_)  intArrRep_ = new Array<int>(*(f.intArrRep_));
00261     else               intArrRep_ = NULL;
00262 
00263     hashCode_ = f.hashCode_; 
00264 
00265     if (parent_) parent_->setDirty();
00266   }
00267 
00268   
00269   bool noDirtyTerms()
00270   {
00271     for (int i = 0; i < terms_->size(); i++)
00272       if ((*terms_)[i]->isDirty()) return false;
00273     return true;
00274   }
00275 
00276 
00277   const Array<int>* getIntArrRep() 
00278   { if (dirty_) computeAndStoreIntArrRep(); return intArrRep_; }
00279 
00280 
00281   void computeAndStoreIntArrRep()
00282   {
00283       //note that retConstId_ is not used to identify a function
00284     dirty_ = false;
00285     if (intArrRep_ == NULL) intArrRep_ = new Array<int>;
00286     else                    intArrRep_->clear();
00287     intArrRep_->append(template_->getId());
00288     
00289     int numTerms = terms_->size();
00290     for (int i = 0; i < numTerms; i++)
00291       (*terms_)[i]->appendIntArrRep(*intArrRep_);
00292 
00293     intArrRep_->compress();
00294     hashCode_ = Hash::hash(*intArrRep_);
00295   }
00296 
00297 
00298  private:
00299   const FunctionTemplate* template_; // not owned by Function
00300   Array<Term*>* terms_;
00301   int retConstId_;
00302   Array<int>* intArrRep_;
00303   size_t hashCode_;
00304   bool dirty_;
00305   Term* parent_;  // not owned by Function, so do not delete in destructor
00306 };
00307 
00308 inline
00309 ostream& operator<<(ostream& out, const Function& f) {return f.printAsInt(out);}
00310 
00311 
00313 
00314 class HashFunction
00315 {
00316  public:
00317   size_t operator()(Function* const & f) const  { return f->hashCode(); }
00318 };
00319 
00320 
00321 class EqualFunction
00322 {
00323  public:
00324   bool operator()(const Function* const & f1, const Function* const & f2) const
00325   { return f1->same(f2); }
00326 };
00327 
00328 
00330 
00331 typedef hash_set<Function*, HashFunction, EqualFunction> FunctionSet;
00332 
00333 
00334 #endif

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