domain.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 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 #include "clause.h"
00067 #include "domain.h"
00068 #include "database.h"
00069 #include "mln.h"
00070 #include "truefalsegroundingsstore.h"
00071 
00072 
00073 Domain::~Domain()
00074 {
00075   if (typeDualMap_) delete typeDualMap_;
00076   if (constDualMap_) delete constDualMap_;
00077   
00078   if (strToPredTemplateMap_)
00079   {
00080       // strToPredTemplateMap_'s keys (predicate names) are shared with 
00081       // predDualMap_. The latter will delete the keys.
00082     StrToPredTemplateMap::iterator it = strToPredTemplateMap_->begin(); 
00083     for (; it != strToPredTemplateMap_->end(); it++)
00084       delete (*it).second; //delete PredTemplate*;
00085     delete strToPredTemplateMap_;
00086   }
00087   if (predDualMap_) delete predDualMap_;
00088 
00089   if (strToFuncTemplateMap_)
00090   {
00091       // strToFuncTemplateMap_'s keys (function names) are shared with 
00092       // funcDualMap_. The latter will delete the keys.
00093     StrToFuncTemplateMap::iterator it2 = strToFuncTemplateMap_->begin(); 
00094     for (; it2 != strToFuncTemplateMap_->end(); it2++)
00095       delete (*it2).second; //delete FuncTemplate*;
00096     delete strToFuncTemplateMap_;
00097   }
00098   if (funcDualMap_) delete funcDualMap_;
00099   
00100   if (equalPredTemplate_) delete equalPredTemplate_;
00101   
00102   if (emptyPredTemplate_) delete emptyPredTemplate_;
00103   
00104   if (emptyFuncUnaryTemplate_) delete emptyFuncUnaryTemplate_;
00105   
00106   if (emptyFuncBinaryTemplate_) delete emptyFuncBinaryTemplate_;
00107   
00108   if (constantsByType_)
00109   {
00110     for (int i = 0; i < constantsByType_->size(); i++)
00111       delete (*constantsByType_)[i];
00112     delete constantsByType_;
00113   }
00114 
00115   if (predBlocks_) delete predBlocks_;
00116 
00117   if (blockEvidence_) delete blockEvidence_;
00118 
00119   if (db_) delete db_;
00120 
00121   if (trueFalseGroundingsStore_) delete trueFalseGroundingsStore_;
00122   
00123   if (funcSet_)
00124   {
00125     FunctionSet::iterator fit;
00126     while (!funcSet_->empty())
00127     { 
00128       fit = funcSet_->begin();
00129       funcSet_->erase(fit);
00130       delete *fit;
00131     }
00132     delete funcSet_;
00133   }
00134 }
00135 
00136 
00137 void Domain::deleteDB() { if (db_) delete db_; db_ = NULL; }
00138 
00139 
00140 void Domain::newTrueFalseGroundingsStore() 
00141 { trueFalseGroundingsStore_ = new TrueFalseGroundingsStore(this); }
00142 
00143   
00144 void Domain::compress() 
00145 {
00146   typeDualMap_->compress();
00147   constDualMap_->compress();
00148   predDualMap_->compress();
00149   funcDualMap_->compress();
00150   constantsByType_->compress();
00151   for (int i = 0; i < constantsByType_->size(); i++)
00152     (*constantsByType_)[i]->compress();
00153   db_->compress();
00154 }
00155 
00156 
00157 void Domain::changePredTermsToNewIds(Predicate* const & p,
00158                                       hash_map<int,int>& oldToNewConstIds)
00159 {
00160   for (int j = 0; j < p->getNumTerms(); j++)
00161   {
00162     Term* t = (Term*) p->getTerm(j);
00163     if (t->getType() == Term::CONSTANT)
00164     {
00165       int oldId = t->getId();
00166       assert(oldToNewConstIds.find(oldId) != oldToNewConstIds.end());
00167       t->setId(oldToNewConstIds[oldId]);
00168     }
00169   }
00170 } 
00171 
00172 
00173   // Change the constant ids so that constants of the same type are ordered 
00174   // consecutively. Ensure that the constants in the mln and map is consistent
00175   // with the new constant ids.
00176 void Domain::reorderConstants(MLN* const & mln,
00177                               hash_map<int, PredicateHashArray*>& predIdToPredsMap)
00178 {  
00179   //order the constants so that those of the same type are ordered consecutively
00180 
00181   hash_map<int,int> oldToNewConstIds;
00182 
00183   ConstDualMap* newConstDualMap = new ConstDualMap;
00184   Array<Array<int>*>* newConstantsByType = new Array<Array<int>*>;
00185 
00186   int prevNewConstId = -1;
00187   bool constChanged = false;
00188   for (int i = 0; i < constantsByType_->size(); i++)
00189   {
00190     newConstantsByType->append(new Array<int>);
00191     Array<int>* constIds = (*constantsByType_)[i];
00192     for (int j = 0; j < constIds->size(); j++)
00193     {
00194       int constId = (*constIds)[j];
00195       const char* constName = getConstantName(constId);
00196       int newConstId = newConstDualMap->insert(constName, i);
00197       assert(prevNewConstId+1==newConstId);
00198       prevNewConstId = newConstId;
00199       (*newConstantsByType)[i]->append(newConstId);
00200       oldToNewConstIds[constId] = newConstId;
00201       if (constId != newConstId) constChanged = true;
00202     }
00203   }
00204 
00205   if (!constChanged)
00206   {
00207     delete newConstDualMap;
00208     for (int i = 0; i < newConstantsByType->size(); i++)
00209       delete (*newConstantsByType)[i];
00210     delete newConstantsByType;
00211     return;
00212   }
00213 
00214   delete constDualMap_;
00215   for (int i = 0; i < constantsByType_->size(); i++)
00216     delete (*constantsByType_)[i];
00217   delete constantsByType_;
00218 
00219   constDualMap_ = newConstDualMap;
00220   constantsByType_ = newConstantsByType;
00221 
00222   constantsByType_->compress();
00223   for (int i = 0; i < constantsByType_->size(); i++)
00224     (*constantsByType_)[i]->compress();
00225   constDualMap_->compress();
00226 
00227   //ensure that the constants in MLN clauses have the new ids 
00228 
00229   const ClauseHashArray* clauses = mln->getClauses();
00230   for (int i = 0; i < clauses->size(); i++)
00231   {
00232     Clause* c = (*clauses)[i];
00233     for (int i = 0; i < c->getNumPredicates(); i++)
00234       changePredTermsToNewIds(c->getPredicate(i), oldToNewConstIds);
00235   }
00236 
00237   hash_map<int, PredicateHashArray*>::iterator mit = predIdToPredsMap.begin();
00238   for (; mit != predIdToPredsMap.end(); mit++)
00239   {
00240     PredicateHashArray* pha = (*mit).second;
00241     for (int i = 0; i < pha->size(); i++ )
00242       changePredTermsToNewIds((*pha)[i], oldToNewConstIds);
00243   }
00244 
00245     // Change the const ids in the pred blocks
00246   for (int i = 0; i < predBlocks_->size(); i++)
00247   {
00248     Array<Predicate*>* predBlock = (*predBlocks_)[i];
00249     for (int j = 0; j < predBlock->size(); j++)
00250       changePredTermsToNewIds((*predBlock)[j], oldToNewConstIds);
00251   }
00252   
00253     //clauses and hence their hash values have changed, and they need to be 
00254     //inserted into the MLN
00255   mln->rehashClauses();
00256 }
00257 
00258 
00259   //Caller is responsible for deleting returned pointer
00260 Predicate* Domain::createPredicate(const int& predId, 
00261                                    const bool& includeEqualPreds) const
00262 {
00263   const PredicateTemplate* pt = getPredicateTemplate(predId);
00264   if (!includeEqualPreds && pt->isEqualPredicateTemplate()) return NULL;
00265   Predicate* pred = new Predicate(pt);
00266   pred->setSense(true);
00267   for (int j = 0; j < pt->getNumTerms(); j++)
00268     pred->appendTerm(new Term(-(j+1), (void*)pred, true));
00269   return pred;
00270 }
00271 
00272 
00273   //Caller is responsible for deleting Array and its contents
00274 void Domain::createPredicates(Array<Predicate*>* const & preds,
00275                               const bool& includeEqualPreds) const
00276 {
00277   for (int i = 0; i < getNumPredicates(); i++)
00278   {
00279     Predicate* p = createPredicate(i, includeEqualPreds);
00280     if (p) preds->append(p);
00281   }
00282 }
00283 
00284 
00285   //Caller is responsible for deleting Array and its contents
00286 void Domain::createPredicates(Array<Predicate*>* const & preds,
00287                               const Array<string>* const & predNames)
00288 {
00289   for (int i = 0; i < predNames->size(); i++)
00290   {
00291     int predId = getPredicateId((*predNames)[i].c_str());    
00292     Predicate* p = createPredicate(predId, true);
00293     if (p) preds->append(p);
00294   }
00295 }
00296 
00297 int Domain::getNumNonEvidenceAtoms() const
00298 {
00299   int numAtoms = 0;
00300   for (int i = 0; i < getNumPredicates(); i++)
00301   {
00302     numAtoms += (db_->getNumGroundings(i) - db_->getNumEvidenceGndPreds(i));
00303   }
00304   return numAtoms;
00305 }
00306 
00307 /*
00308  * Caller is responsible for deleting returned Predicate* if necessary
00309  */
00310 Predicate* Domain::getNonEvidenceAtom(int index) const
00311 {
00312   int predId = -1;
00313   int numAtomsPerPred;
00314   int numAtoms = 0;
00315   for (int i = 0; i < getNumPredicates(); i++)
00316   {
00317     numAtomsPerPred = (db_->getNumGroundings(i) - db_->getNumEvidenceGndPreds(i));
00318     if (numAtoms + numAtomsPerPred >= index + 1)
00319     {
00320       predId = i;
00321       break;
00322     }
00323     numAtoms += numAtomsPerPred;
00324   }
00325   assert(predId >= 0);
00326   index = index - numAtoms;
00327   
00328   Array<Predicate*> preds;
00329   Predicate* gndPred = NULL;
00330   Predicate::createAllGroundings(predId, this, preds);
00331   int nePreds = 0;
00332   for (int i = 0; i < preds.size(); i++)
00333   {
00334     if (!db_->getEvidenceStatus(preds[i]) && index == nePreds++)
00335       gndPred = preds[i];
00336     else
00337       delete preds[i];
00338   }
00339   assert(gndPred);
00340   return gndPred;
00341 }
00342 
00343 int Domain::addPredBlock(Array<Predicate*>* const & predBlock) const
00344 {
00345   int idx = predBlocks_->append(predBlock);
00346   blockEvidence_->append(false);
00347   return idx;
00348 }
00349 
00350   // returns the index of the block which the ground predicate
00351   // with index predIndex is in. If not in any, returns -1
00352 int Domain::getBlock(Predicate* pred) const
00353 {
00354   for (int i = 0; i < predBlocks_->size(); i++)
00355   {
00356     Array<Predicate*>* block = (*predBlocks_)[i];
00357     for (int j = 0; j < block->size(); j++)
00358     {
00359       if (pred->same((*block)[j]))
00360         return i;
00361     }
00362   }
00363   return -1;
00364 }
00365 
00366 int Domain::getNumPredBlocks() const
00367 {
00368   return predBlocks_->size();
00369 }
00370 
00371 const Array<Array<Predicate*>*>* Domain::getPredBlocks() const
00372 {
00373   return predBlocks_;
00374 }
00375 
00376 const Array<Predicate*>* Domain::getPredBlock(const int index) const
00377 {
00378   return (*predBlocks_)[index];
00379 }
00380 
00381 const Array<bool>* Domain::getBlockEvidenceArray() const
00382 {
00383   return blockEvidence_;
00384 }
00385 
00386 const bool Domain::getBlockEvidence(const int index) const
00387 {
00388   return (*blockEvidence_)[index];
00389 }
00390 
00391 void Domain::setBlockEvidence(const int index, const bool value) const
00392 {
00393   (*blockEvidence_)[index] = value;
00394 }
00395 
00396 int Domain::getEvidenceIdxInBlock(const int index) const
00397 {
00398   Array<Predicate*>* block = (*predBlocks_)[index];
00399   for (int i = 0; i < block->size(); i++)
00400   {
00401     if (db_->getEvidenceStatus((*block)[i]))
00402       return i;
00403   }
00404   return -1;
00405 }

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