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, Hoifung Poon, and Daniel Lowd.
00006  * 
00007  * Copyright [2004-07] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner, Hoifung
00009  * Poon, and Daniel Lowd. 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, Hoifung
00032  * Poon, and Daniel Lowd 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 
00122   Term* removeLastTerm()
00123   {
00124     Term* term = terms_->removeLastItem();
00125     terms_->compress();
00126     setDirty();
00127     return term;
00128   }
00129   
00130   int getNumTerms() const { return terms_->size(); }
00131 
00132   const Term* getTerm(const int& idx) const { return (*terms_)[idx]; }
00133 
00134   void setTemplate(FunctionTemplate* const & t) { template_ = t; }
00135 
00136   const FunctionTemplate* getTemplate() const { return template_; }
00137 
00138     // Caller should not delete the returned const char* 
00139   const char* getName() const { return template_->getName(); }
00140 
00141   int getId() const { return template_->getId(); }
00142 
00143 
00144     // retConstId refers to the id of the constant returned by the function
00145   void setRetConstId(const int& constId) { retConstId_ = constId; setDirty();}
00146   int getRetConstId() const { return retConstId_; }
00147 
00148   void setDirty();
00149   bool isDirty() const { return dirty_; }
00150 
00151   void setParent(Term* const parent) { parent_ = parent; setDirty(); }
00152   Term* getParent() const { return parent_; }
00153 
00154 
00155     // Caller should not delete the returned const char* nor modify its
00156     // contents. Returns NULL if idx is larger than the possible number of 
00157     // terms
00158   const char* getTermTypeAsStr(const int& idx) const 
00159   {
00160     if (idx >= template_->getNumTerms()) return NULL;
00161     return template_->getTermTypeAsStr(idx); 
00162   }
00163 
00164     // Returns -1 if idx is larger than the possible number of terms
00165   int getTermTypeAsInt(const int& idx) const 
00166   {
00167     if (idx >= template_->getNumTerms()) return -1;
00168     return template_->getTermTypeAsInt(idx); 
00169   }
00170 
00171 
00172   int getRetTypeId() const { return template_->getRetTypeId(); }
00173   
00174     // Caller should not delete the returned const char*
00175   const char* getRetTypeName() const { return template_->getRetTypeName(); }
00176 
00177   bool same(const Function* const & f) const
00178   {
00179     if (this == f) return true;
00180     //commented out: no need to check return values are the same
00181     //if (retConstId_ != f->getRetConstId()) return false;
00182     if (template_->getId() != f->getId()) return false;
00183     int numTerms = terms_->size();
00184     if (numTerms != f->getNumTerms()) return false;
00185     for (int i = 0; i < numTerms; i++)
00186       if ((*terms_)[i]->getId() != f->getTerm(i)->getId()) return false;
00187     return true;
00188   }
00189 
00190   
00191     // represent function as an Array<int> and append it to rep
00192   void appendIntArrRep(Array<int>& rep) 
00193   {
00194     if (dirty_) computeAndStoreIntArrRep();
00195     rep.append(*intArrRep_);
00196   }
00197 
00198 
00199   size_t hashCode()
00200   {
00201     if (dirty_) computeAndStoreIntArrRep();
00202     return hashCode_;
00203   }
00204 
00205 
00206   bool same(Function* const & f)
00207   {
00208     if (this==f)  return true;
00209     const Array<int>* fArr  = f->getIntArrRep();
00210     const Array<int>* myArr = getIntArrRep();
00211     if (myArr->size() != fArr->size()) return false;
00212     const int* fItems  = f->getIntArrRep()->getItems();
00213     const int* myItems = getIntArrRep()->getItems();
00214     return (memcmp(myItems, fItems, myArr->size()*sizeof(int))==0); 
00215   }
00216 
00217 
00218   ostream& printAsInt(ostream& out) const
00219   {
00220     out << template_->getId() << "(";
00221     for (int i = 0; i < terms_->size(); i++)
00222     {
00223       (*terms_)[i]->printAsInt(out); 
00224       out << ((i!=terms_->size()-1)?",":")");
00225     }
00226     return out;
00227   }
00228 
00229 
00230   ostream& printAsIntWithRetConstId(ostream& out) const
00231   {
00232     printAsInt(out);
00233     out << "=" << retConstId_ << endl;
00234     return out;
00235   }
00236 
00237 
00238   ostream& print(ostream& out, const Domain* const & domain) const
00239   {
00240     out << template_->getName() << "(";
00241     for (int i = 0; i < terms_->size(); i++)
00242     {
00243       (*terms_)[i]->print(out, domain); 
00244       out << ((i!=terms_->size()-1)?",":")");
00245     }
00246     return out;
00247   }
00248 
00249 
00250   ostream& 
00251   printWithRetConstName(ostream& out, const Domain* const & domain) const;
00252 
00253 
00254  private:
00255   void copy(const Function& f)
00256   {
00257     template_ = f.template_;
00258 
00259     terms_ = new Array<Term*>;
00260     Array<Term*>* fterms = f.terms_;
00261     for (int i = 0; i < fterms->size(); i++)
00262     {
00263       Term* t = (*fterms)[i];
00264       terms_->append(new Term(*t, (void*)this, false));
00265     }
00266     dirty_ = f.dirty_;
00267 
00268     if (!dirty_) { assert(noDirtyTerms()); }
00269 
00270     retConstId_ = f.retConstId_;
00271 
00272     if (f.intArrRep_)  intArrRep_ = new Array<int>(*(f.intArrRep_));
00273     else               intArrRep_ = NULL;
00274 
00275     hashCode_ = f.hashCode_; 
00276 
00277     if (parent_) parent_->setDirty();
00278   }
00279 
00280   
00281   bool noDirtyTerms()
00282   {
00283     for (int i = 0; i < terms_->size(); i++)
00284       if ((*terms_)[i]->isDirty()) return false;
00285     return true;
00286   }
00287 
00288 
00289   const Array<int>* getIntArrRep() 
00290   { if (dirty_) computeAndStoreIntArrRep(); return intArrRep_; }
00291 
00292 
00293   void computeAndStoreIntArrRep()
00294   {
00295       //note that retConstId_ is not used to identify a function
00296     dirty_ = false;
00297     if (intArrRep_ == NULL) intArrRep_ = new Array<int>;
00298     else                    intArrRep_->clear();
00299     intArrRep_->append(template_->getId());
00300     
00301     int numTerms = terms_->size();
00302     for (int i = 0; i < numTerms; i++)
00303       (*terms_)[i]->appendIntArrRep(*intArrRep_);
00304 
00305     intArrRep_->compress();
00306     hashCode_ = Hash::hash(*intArrRep_);
00307   }
00308 
00309 
00310  private:
00311   const FunctionTemplate* template_; // not owned by Function
00312   Array<Term*>* terms_;
00313   int retConstId_;
00314   Array<int>* intArrRep_;
00315   size_t hashCode_;
00316   bool dirty_;
00317   Term* parent_;  // not owned by Function, so do not delete in destructor
00318 };
00319 
00320 inline
00321 ostream& operator<<(ostream& out, const Function& f) {return f.printAsInt(out);}
00322 
00323 
00325 
00326 class HashFunction
00327 {
00328  public:
00329   size_t operator()(Function* const & f) const  { return f->hashCode(); }
00330 };
00331 
00332 
00333 class EqualFunction
00334 {
00335  public:
00336   bool operator()(const Function* const & f1, const Function* const & f2) const
00337   { return f1->same(f2); }
00338 };
00339 
00340 
00342 
00343 typedef hash_set<Function*, HashFunction, EqualFunction> FunctionSet;
00344 
00345 
00346 #endif

Generated on Sun Jun 7 11:55:16 2009 for Alchemy by  doxygen 1.5.1