predicate.cpp

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 #include "predicate.h"
00067 #include "clause.h"
00068 #include "groundpredicate.h"
00069 
00070 double Predicate::fixedSizeB_ = -1;
00071 
00072 
00073 void Predicate::setDirty() { dirty_ = true; if (parent_) parent_->setDirty(); }
00074 
00075 
00076 void Predicate::setParentDirty() { if (parent_) parent_->setDirty(); }
00077 
00078 
00079 bool Predicate::canBeGroundedAs(const GroundPredicate* const & gndPred)
00080 {
00081   if ( ((unsigned int) template_->getId()) != gndPred->getId()) return false;
00082   if (allTermsAreDiffVars()) return true;
00083     
00084   int varGndings[MAX_VAR];
00085   memset(varGndings, -1, MAX_VAR*sizeof(int));
00086   for (int i = 0; i < terms_->size(); i++) 
00087   {
00088     int termType = (*terms_)[i]->getType();
00089       
00090     if (termType == Term::CONSTANT) 
00091     {
00092       assert((*terms_)[i]->getId() >= 0);
00093       if ( ((unsigned int) (*terms_)[i]->getId()) != gndPred->getTermId(i)) 
00094         return false;
00095     }
00096     else 
00097     if (termType == Term::VARIABLE) 
00098     {
00099       int varId = -(*terms_)[i]->getId();
00100       assert(varId > 0);
00101       assert(varId < MAX_VAR);
00102       if (varGndings[varId] < 0) // if variable has not been grounded
00103         varGndings[varId] = gndPred->getTermId(i);
00104       else 
00105       if (varGndings[varId] != (int) gndPred->getTermId(i))
00106         return false;
00107     }
00108     else
00109     {
00110       assert(false);
00111     }
00112   }
00113   return true;
00114 }
00115 
00116   //Does not consider the sense of the predicate.
00117 bool Predicate::same(const GroundPredicate* const & gp)
00118 {
00119   if ( getId() != (int) gp->getId() ) return false;
00120   if ( terms_->size() != (int) gp->getNumTerms() ) return false;
00121   for (int i = 0; i < terms_->size(); i++)
00122     if ( (*terms_)[i]->getId() != (int) gp->getTermId(i) ) return false;
00123   return true;
00124 }
00125 
00126 double 
00127 Predicate::getNumGroundingsIfAllVarDiff(const Domain* const & domain) const
00128 { 
00129   int numGnd = 1;
00130   for (int i = 0; i < template_->getNumTerms(); i++)
00131     numGnd *= domain->getNumConstantsByType(template_->getTermTypeAsInt(i));
00132   return numGnd;
00133 }
00134 
00135     //Caller is responsible for deleting the Predicate* in returnArray
00136 void Predicate::createAllGroundings(const int& predId, 
00137                                     const Domain* const & domain,
00138                                     Array<Predicate*>& returnArray)
00139 {
00140   const PredicateTemplate* pt = domain->getPredicateTemplate(predId);
00141   if (pt == NULL)
00142   {
00143     cout << "ERROR in Predicate::createAllGroundings: no predicate with id " 
00144          << predId << " in domain" << endl;
00145     return;
00146   }
00147   if (pt->isEqualPredicateTemplate())
00148   {
00149     cout << "ERROR in Predicate::createAllGroundings: cannot create " 
00150          << "groundings for '=' predicate" << endl;
00151     return;      
00152   }
00153   
00154   ArraysAccessor<int> acc;
00155   for (int i = 0; i < pt->getNumTerms(); i++)
00156   {
00157     int typeId = pt->getTermTypeAsInt(i);
00158     assert(typeId >= 0);
00159     const Array<int>* constArr = domain->getConstantsByType(typeId);
00160     assert(constArr->size() > 0);
00161     acc.appendArray(constArr);
00162   }
00163 
00164   while (acc.hasNextCombination())
00165   {
00166     Predicate* pred = new Predicate(pt);
00167     int constId;
00168     while (acc.nextItemInCombination(constId))
00169       pred->appendTerm(new Term(constId, (void*)pred, true));
00170     returnArray.append(pred);    
00171   }
00172 }
00173 
00174 //get all the groundings unifying with the term given 
00175 //Caller is responsible for deleting the Predicate* in returnArray
00176 void Predicate::createAllGroundingsUnifyingWithTerm(const int& predId, 
00177                                     const Domain* const & domain,
00178                                     Array<Predicate*>& returnArray,
00179                                                                         int termTypeId,int termConstId)
00180 {
00181   Array<int>* tmpArr;
00182   const PredicateTemplate* pt = domain->getPredicateTemplate(predId);
00183   if (pt == NULL)
00184   {
00185     cout << "ERROR in Predicate::createAllGroundings: no predicate with id " 
00186          << predId << " in domain" << endl;
00187     return;
00188   }
00189   if (pt->isEqualPredicateTemplate())
00190   {
00191     cout << "ERROR in Predicate::createAllGroundings: cannot create " 
00192          << "groundings for '=' predicate" << endl;
00193     return;      
00194   }
00195   
00196   ArraysAccessor<int> acc;
00197   for (int i = 0; i < pt->getNumTerms(); i++)
00198   {
00199     int typeId = pt->getTermTypeAsInt(i);
00200     assert(typeId >= 0);
00201     const Array<int>* constArr;
00202     if (typeId != termTypeId)
00203     {
00204       constArr = domain->getConstantsByType(typeId);
00205         }
00206     else
00207     {
00208       tmpArr = new Array<int>;
00209       tmpArr->append(termConstId);
00210       constArr = tmpArr;
00211         }
00212     assert(constArr->size() > 0);
00213     acc.appendArray(constArr);
00214   }
00215   
00216   while (acc.hasNextCombination())
00217   {
00218     Predicate* pred = new Predicate(pt);
00219     int constId;
00220     while (acc.nextItemInCombination(constId))
00221       pred->appendTerm(new Term(constId, (void*)pred, true));
00222     returnArray.append(pred);
00223   }
00224 }
00225 
00226 
00242 void Predicate::createAllGroundings(const Domain* const & domain,
00243                                     Array<Predicate*>* const & predReturnArray,
00244                                     Array<int*>* const & constReturnArray,
00245                                     const int& grounding)
00246 {
00247   assert(predReturnArray == NULL || constReturnArray == NULL);
00248 
00249   if (isGrounded())
00250   {
00251     if (grounding >= 0) assert(grounding == 0);
00252     if (predReturnArray)
00253       predReturnArray->append(new Predicate(*this));
00254     else
00255     {
00256       assert(constReturnArray);
00257       int* constArr = new int[terms_->size()];
00258       for (int j = 0; j < terms_->size(); j++) 
00259       {
00260         constArr[j] = (*terms_)[j]->getId();
00261         assert(constArr[j] >= 0);
00262       }
00263       constReturnArray->append(constArr);
00264     }
00265     return;
00266   }
00267 
00268   Array<VarsGroundedType*> vgtArr;
00269   for (int i = 0; i < terms_->size(); i++)
00270   {
00271     const Term* t = (*terms_)[i];
00272     if (t->getType() == Term::VARIABLE)
00273     {
00274       int id = -(t->getId());
00275       assert(id > 0);
00276       if (id >= vgtArr.size()) vgtArr.growToSize(id + 1,NULL);
00277       VarsGroundedType*& vgt = vgtArr[id];
00278       if (vgt == NULL) 
00279       {
00280         vgt = new VarsGroundedType; 
00281         vgt->typeId = getTermTypeAsInt(i);
00282         assert(vgt->typeId >= 0);        
00283       }
00284       assert(getTermTypeAsInt(i) == vgt->typeId);
00285       vgt->vars.append((Term*)t);
00286     }
00287   }
00288 
00289   Array<int> negVarId; 
00290   ArraysAccessor<int> acc;
00291   for (int i = 0; i < vgtArr.size(); i++)
00292   {
00293     if (vgtArr[i] == NULL) continue;
00294     negVarId.append(i);
00295     acc.appendArray(domain->getConstantsByType(vgtArr[i]->typeId));
00296   }
00297 
00298   int combination = 0;
00299   while (acc.hasNextCombination())
00300   {
00301     int i = 0;
00302     int constId;
00303     while (acc.nextItemInCombination(constId))
00304     {
00305       Array<Term*>& vars = vgtArr[negVarId[i]]->vars;
00306       for (int j = 0; j < vars.size(); j++) vars[j]->setId(constId);
00307       i++;
00308     }
00309     
00310       // If collecting all preds or we are at the right combination
00311     if (grounding < 0 || grounding == combination)
00312     {
00313       if (predReturnArray)
00314         predReturnArray->append(new Predicate(*this));
00315       else
00316       {
00317         assert(constReturnArray);
00318         int* constArr = new int[terms_->size()];
00319         for (int j = 0; j < terms_->size(); j++) 
00320         {
00321           constArr[j] = (*terms_)[j]->getId();
00322           assert(constArr[j] >= 0);
00323         }
00324         constReturnArray->append(constArr);
00325       }
00326       if (grounding == combination) break;
00327     }
00328     combination++;
00329   }
00330   if (grounding >= 0) assert(combination == grounding);
00331   
00332     // Restore variables
00333   for (int i = 0; i < vgtArr.size(); i++) 
00334   {
00335     if (vgtArr[i] == NULL) continue;
00336     Array<Term*>& vars  = vgtArr[i]->vars;
00337     for (int j = 0; j < vars.size(); j++) vars[j]->setId(-i);
00338     delete vgtArr[i];
00339   }  
00340 }
00341 
00342 
00343 ostream& Predicate::printWithStrVar(ostream& out,
00344                                     const Domain* const & domain) const
00345 {
00346   if (isEqualPred()) return printEqualPredWithStrVar(out,domain);
00347   if (isInternalPred()) return printInternalPredWithStrVar(out,domain);
00348 
00349   if (!sense_) out << "!";
00350   out << template_->getName();
00351     // If dealing with a propositional variable
00352   if (strcmp(getTermTypeAsStr(0), Domain::PROPOSITIONAL_TYPE) == 0)
00353     return out;
00354 
00355   out << "(";
00356   for (int i = 0; i < terms_->size(); i++)
00357   {
00358     (*terms_)[i]->printWithStrVar(out, domain); 
00359     out << ((i != terms_->size() - 1) ? "," : ")");
00360   }
00361   return out;
00362 }
00363 
00364 ostream& Predicate::print(ostream& out, const Domain* const & domain) const
00365 {
00366   if (isEqualPred()) return printEqualPred(out, domain);
00367   if (isInternalPred()) return printInternalPred(out, domain);
00368 
00369   if (!sense_) out << "!";
00370   out << template_->getName();
00371     // If dealing with a propositional variable
00372   if (strcmp(getTermTypeAsStr(0), Domain::PROPOSITIONAL_TYPE) == 0)
00373     return out;
00374 
00375   out << "(";
00376   for (int i = 0; i < terms_->size(); i++)
00377   {
00378     (*terms_)[i]->print(out, domain); 
00379     out << ((i != terms_->size() - 1) ? "," : ")");
00380   }
00381   return out;
00382 }
00383 

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