mln.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, Daniel Lowd, and Jue Wang.
00006  * 
00007  * Copyright [2004-09] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner, Hoifung
00009  * Poon, Daniel Lowd, and Jue Wang. 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, Daniel Lowd, and Jue Wang in the Department of
00033  * Computer Science and Engineering at the University of
00034  * Washington".
00035  * 
00036  * 4. Your publications acknowledge the use or
00037  * contribution made by the Software to your research
00038  * using the following citation(s): 
00039  * Stanley Kok, Parag Singla, Matthew Richardson and
00040  * Pedro Domingos (2005). "The Alchemy System for
00041  * Statistical Relational AI", Technical Report,
00042  * Department of Computer Science and Engineering,
00043  * University of Washington, Seattle, WA.
00044  * http://alchemy.cs.washington.edu.
00045  * 
00046  * 5. Neither the name of the University of Washington nor
00047  * the names of its contributors may be used to endorse or
00048  * promote products derived from this software without
00049  * specific prior written permission.
00050  * 
00051  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
00052  * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00053  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00054  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00055  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
00056  * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00057  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00058  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00059  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00060  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00061  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00062  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00063  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00064  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00065  * 
00066  */
00067 #ifndef MLN_H_JUN_26_2005
00068 #define MLN_H_JUN_26_2005
00069 
00070 #include <cfloat>
00071 #include <ext/hash_map>
00072 #include <ext/hash_set>
00073 using namespace __gnu_cxx;
00074 #include "clause.h"
00075 #include "equalstr.h"
00076 #include "mlnhelper.h"
00077 
00078 
00079 class MLN
00080 {
00081  public: 
00082   MLN() : clauses_(new ClauseHashArray),clauseInfos_(new Array<MLNClauseInfo*>),
00083           formAndClausesArray_(new FormulaAndClausesArray), 
00084           predIdToClausesMap_(new Array<Array<IndexClause*>*>),
00085           externalClause_(new Array<bool>) {}
00086 
00087   ~MLN()
00088   {
00089     if (clauses_)
00090     {
00091       clauses_->deleteItemsAndClear();
00092       delete clauses_;
00093     }
00094     
00095     if (clauseInfos_)
00096     {
00097       clauseInfos_->deleteItemsAndClear();
00098       delete clauseInfos_;
00099     }
00100     
00101     if (formAndClausesArray_)
00102     {
00103       formAndClausesArray_->deleteItemsAndClear();
00104       delete formAndClausesArray_;
00105     }
00106     
00107     if (predIdToClausesMap_)
00108     {
00109       for (int i = 0; i < predIdToClausesMap_->size(); i++)
00110         if ((*predIdToClausesMap_)[i]) 
00111         {
00112           (*predIdToClausesMap_)[i]->deleteItemsAndClear();
00113           delete (*predIdToClausesMap_)[i];
00114         }
00115       delete predIdToClausesMap_;
00116     }
00117 
00118     if (externalClause_) delete externalClause_;
00119   }
00120 
00121   int getNumClauses() const { return clauses_->size(); }
00122 
00123   int getNumHardClauses() const
00124   {
00125         int numHardClauses = 0;
00126         for (int i = 0; i < clauses_->size(); i++)
00127         {
00128           if ((*clauses_)[i]->isHardClause()) numHardClauses++;
00129         }
00130         return numHardClauses;
00131   }
00132 
00133 
00134   bool containsClause(const Clause* const & c) const
00135   { return clauses_->contains((Clause*)c); }
00136 
00141   bool appendExternalClause(const string& formulaString, const bool& hasExist,
00142                             Clause* const& c, const Domain* const & domain,
00143                             const bool& tiedClauses)
00144   {
00145     int idx;
00146     bool app = appendClause(formulaString, hasExist, c, c->getWt(),
00147                             c->isHardClause(), idx, tiedClauses);
00148     if (app)
00149     {
00150       setFormulaNumPreds(formulaString, c->getNumPredicates());
00151       setFormulaIsHard(formulaString, c->isHardClause());
00152       setFormulaPriorMean(formulaString, c->getWt());
00153       (*externalClause_)[idx] = true;
00154     }
00155     return app;   
00156   }
00157 
00158     //MLN owns clause c and is responsible for its deletion.
00159     //hasExist is true if formulaString contains an existential quantifier
00160     //during the CNF conversion process.
00161     //Call setHardClausesWts() after this function to set the weights of hard
00162     //clauses to twice the maximum of soft clause wts.
00163     //Returns true of the clause is appended; otherwise returns false.
00164     //retIdx is the index of the clause in MLN's array of clauses
00165   bool appendClause(const string& formulaString, const bool& hasExist, 
00166                     Clause* const& c, const double& wt,
00167                     const bool& isHardClause, int& retClauseIdx,
00168                     const bool& tiedClauses) 
00169   {
00170     assert(c);
00171     c->canonicalize();
00172     bool isAppended;
00173     Clause* clause;
00174     if ((retClauseIdx = clauses_->find(c)) >= 0) // if clauses_ contains c
00175     {
00176       clause = (*clauses_)[retClauseIdx];
00177       delete c;
00178       isAppended = false;
00179     }
00180     else
00181     {
00182         // clause does not exist in MLN, so add it
00183       retClauseIdx = clauses_->append(c);
00184       clause = c;
00185       isAppended = true;
00186       clause->setWt(0); //start accumulating weight from 0
00187       externalClause_->append(false);
00188     }
00189     clause->addWt(wt);
00190     if (isHardClause) clause->setIsHardClause(isHardClause);
00191 
00192  
00193     FormulaAndClauses* fac = new FormulaAndClauses(formulaString, 
00194                                                    formAndClausesArray_->size(),
00195                                                    hasExist, tiedClauses);
00196     int fidx;
00197       // if this is the first time we see the formulaString
00198     if ( (fidx = formAndClausesArray_->find(fac)) < 0 )
00199     {
00200       fidx = formAndClausesArray_->append(fac);
00201       assert(fac->index == fidx);
00202     }
00203     else
00204     {
00205       delete fac;
00206       fac = (*formAndClausesArray_)[fidx];
00207       assert(fac->index == fidx);
00208     }
00209     IndexClause* ic = new IndexClause(fac->indexClauses->size(), clause);
00210     int cidx = fac->indexClauses->append(ic);
00211     if (cidx < 0) { delete ic; ic = NULL; }
00212     else          assert(ic->index == cidx);
00213 
00214     if (isAppended) 
00215     {
00216         // add to predIdToClausesMap_, and append to clauseInfos_
00217       appendClauseInfo(clause, retClauseIdx, &(fac->index), &(ic->index));
00218     }
00219     else 
00220     if (cidx >= 0) 
00221     {   
00222         //a clause was appended to an entry in formAndClausesArray_, so update 
00223         //the formulaClauseIndexes of the MLNClauseInfo corresponding to clause
00224       updateClauseInfo(retClauseIdx, &(fac->index), &(ic->index));
00225     }
00226 
00227     assert(clauses_->size() == clauseInfos_->size());
00228     return isAppended;
00229   } //appendClause()
00230 
00231 
00232     // idx is the index into the clauses_ array
00233   Clause* removeClause(const int& remIdx)
00234   {
00235       //remove the clause and its corresponding MLNClauseInfo
00236     Clause* r = clauses_->removeItemFastDisorder(remIdx);
00237     MLNClauseInfo* ci = clauseInfos_->removeItemFastDisorder(remIdx);
00238     assert(ci->index == remIdx);
00239 
00240     externalClause_->removeItemFastDisorder(remIdx);
00241 
00242     if (clauseInfos_->size() != remIdx) //if we didn't just remove the last item
00243     {
00244         //(*clauseInfos_)[remIdx] is the last item moved to the position of the
00245         //removed IndexClause
00246       (*clauseInfos_)[remIdx]->index = remIdx;
00247     }
00248 
00249       //update MLNClauseInfo's predIdsClauseIndexes
00250     Array<PredIdClauseIndex*>& piciArr = ci->predIdsClauseIndexes;
00251     for (int i = 0; i < piciArr.size(); i++)
00252     {
00253       int predId = piciArr[i]->predId;
00254       int remIdx = *(piciArr[i]->clauseIndex);
00255 
00256       Array<IndexClause*>* indexesClauses = (*predIdToClausesMap_)[predId];
00257       IndexClause* ic = indexesClauses->removeItemFastDisorder(remIdx);
00258       assert(ic->index == remIdx && ic->clause == r);
00259       delete ic;
00260 
00261         //if pred's clause array isn't empty & we didn't just removed last item
00262       if (indexesClauses->size() != remIdx)
00263       {
00264           //(*predClauses)[remIdx] is the last item moved to the position of 
00265           //removed clause, so update its position to remIdx
00266         (*indexesClauses)[remIdx]->index = remIdx;        
00267       }
00268 
00269       if (indexesClauses->empty())
00270       {
00271         delete indexesClauses;
00272         (*predIdToClausesMap_)[predId] = NULL;
00273       }
00274     }
00275 
00276       //update MLNClauseInfo's formulaClauseIndexes
00277     Array<FormulaClauseIndexes*>& fciArr = ci->formulaClauseIndexes;
00278     for (int i = 0; i < fciArr.size(); i++)
00279     {
00280       int fidx = *(fciArr[i]->formulaIndex);
00281       int remIdx = *(fciArr[i]->clauseIndex);
00282       FormulaAndClauses* fac = (*formAndClausesArray_)[fidx];
00283       IndexClauseHashArray* indexClauses = fac->indexClauses;
00284       IndexClause* ic = indexClauses->removeItemFastDisorder(remIdx);
00285       assert(ic->index == remIdx);
00286       delete ic;
00287       if (indexClauses->size() != remIdx)
00288         (*indexClauses)[remIdx]->index = remIdx;
00289       
00290       if (indexClauses->empty())
00291       {
00292         fac = formAndClausesArray_->removeItemFastDisorder(fidx);
00293         assert(fac->index == fidx);
00294         delete fac;
00295         if (formAndClausesArray_->size() != fidx)
00296           (*formAndClausesArray_)[fidx]->index = fidx;
00297       }
00298     }
00299 
00300     delete ci;
00301     assert(clauses_->size() == clauseInfos_->size());
00302     return r;
00303   }//removeClause()
00304 
00305 
00306     // returns the removed clause or NULL if c is not in the MLN
00307   Clause* removeClause(const Clause* const & c)
00308   {
00309     int idx = findClauseIdx(c);
00310     if (idx < 0) return NULL;
00311     return removeClause(idx);
00312   }
00313 
00314 
00315   void removeAllClauses(Array<Clause*>* const & clauses)
00316   {
00317     while (!clauses_->empty()) 
00318     {
00319       Clause* c = removeClause(0);
00320       if (clauses) clauses->append(c);
00321       else delete c;
00322     }
00323   }
00324 
00325 
00326     // Clauses  are reinserted into clauses_, and the indexClauses arrays of 
00327     // each FormulaAndClauses in formAndClausesArrays_. Call this when the 
00328     // clauses' hash codes change, e.g., when constants are reordered. You have
00329     // to do this because hash_map does not register the hash values of its
00330     // contents if the values change after the contents are inserted.
00331   void rehashClauses()
00332   {
00333     ClauseHashArray* newha =  new ClauseHashArray;
00334     for (int i = 0; i < clauses_->size(); i++) 
00335     {
00336       int a = newha->append((*clauses_)[i]);
00337       assert(a >= 0); a = 0; //avoid compilation warning
00338     }
00339     delete clauses_;
00340     clauses_ = newha;
00341  
00342 
00343     for (int i = 0; i < formAndClausesArray_->size(); i++)
00344     {
00345       FormulaAndClauses* fac = (*formAndClausesArray_)[i];
00346       IndexClauseHashArray* newArr = new IndexClauseHashArray;
00347       IndexClauseHashArray* curArr = fac->indexClauses;
00348       for (int j = 0; j < curArr->size(); j++)
00349       {
00350         int a = newArr->append((*curArr)[j]);
00351         assert((*curArr)[j]->index == a); a = 0; //avoid compilation warning
00352       }
00353       curArr->clear();
00354       delete curArr;
00355       fac->indexClauses = newArr;
00356     }
00357   }
00358 
00359 
00360     //returns the maximum absolute value of soft weights (weights of clauses
00361     //that are not hard and not belonging to existentially and uniquely quant.
00362     //formulas).
00363   double getMaxAbsSoftWt()
00364   {
00365       //find the max of the (absolute) soft clause wts
00366     double maxSoftWt = 0;
00367     for (int i = 0; i < clauses_->size(); i++)
00368     {
00369       Clause* c = (*clauses_)[i];
00370       if (!c->isHardClause() && !isExistUniqueClause(c))
00371       {
00372         double abWt = fabs(c->getWt());
00373         if (abWt > maxSoftWt) maxSoftWt = abWt;
00374       }
00375     }
00376     return maxSoftWt;
00377   }
00378 
00379 
00380     // Returns the index into clauses_ where c is found
00381   int findClauseIdx(const Clause* const & c) const 
00382   { return clauses_->find((Clause*)c); }
00383 
00384 
00385   const Clause* findClause(const Clause* const & c) const 
00386   { 
00387     int i = findClauseIdx(c);
00388     if (i < 0) return NULL;
00389     return (*clauses_)[i];
00390   }
00391 
00392 
00393     //returns clause at position of clauses_ 
00394     //or NULL if i is not a valid index of clauses_     
00395   const Clause* getClause(const int& i) const
00396   {
00397     if (i < 0 || i >= clauses_->size()) return NULL;
00398     return (*clauses_)[i];
00399   }
00400 
00401   bool isExternalClause(const int& i) const
00402   {
00403     assert(0 <= i && i < clauses_->size());
00404     return (*externalClause_)[i];
00405   }
00406 
00407   bool isExternalClause(const Clause* const & c) const
00408   {
00409     int i = findClauseIdx(c);
00410     assert(i >= 0);
00411     return isExternalClause(i);
00412   }
00413 
00414     // returns true if the ith clause is in the CNF of an existentially
00415     // quantified formula
00416   bool isExistClause(const int& i) const
00417   {
00418     assert(0 <= i && i < clauses_->size());
00419     Array<FormulaClauseIndexes*>& fciArr 
00420       = (*clauseInfos_)[i]->formulaClauseIndexes;
00421     for (int i = 0; i < fciArr.size(); i++)
00422       if ((*formAndClausesArray_)[*(fciArr[i]->formulaIndex)]->hasExist) 
00423         return true;
00424     return false;
00425   }
00426 
00427 
00428     // returns true if clause c is in the CNF of an existentially
00429     // quantified formula
00430   bool isExistClause(const Clause* const & c) const
00431   {
00432     int i = findClauseIdx(c);
00433     assert(i >= 0);
00434     return isExistClause(i);
00435   }
00436 
00437 
00438     // returns true if the ith clause is in the CNF of an existentially and
00439     // uniquely quantified formula
00440   bool isExistUniqueClause(const int& i) const
00441   {
00442     assert(0 <= i && i < clauses_->size());
00443     Array<FormulaClauseIndexes*>& fciArr 
00444       = (*clauseInfos_)[i]->formulaClauseIndexes;
00445     for (int i = 0; i < fciArr.size(); i++)
00446       if ((*formAndClausesArray_)[*(fciArr[i]->formulaIndex)]->isExistUnique) 
00447         return true;
00448     return false;
00449   }
00450 
00451 
00452     // returns true if clause c is in the CNF of an existentially and
00453     // uniquely quantified formula
00454   bool isExistUniqueClause(const Clause* const & c) const
00455   {
00456     int i = findClauseIdx(c);
00457     assert(i >= 0);
00458     return isExistUniqueClause(i);
00459   }
00460 
00461 
00462     // returns true if the ith clause is in the CNF of a non-existentially
00463     // quantified formula
00464   bool clauseInNonExistAndNonExistUniqueFormulaCNF(const int& i) const
00465   {
00466     assert(0 <= i && i < clauses_->size());
00467     Array<FormulaClauseIndexes*>& fciArr 
00468       = (*clauseInfos_)[i]->formulaClauseIndexes;
00469     for (int i = 0; i < fciArr.size(); i++)
00470     {
00471       FormulaAndClauses*fnc=(*formAndClausesArray_)[*(fciArr[i]->formulaIndex)];
00472       if (!fnc->hasExist && !fnc->isExistUnique) return true;
00473     }
00474     return false;
00475   }
00476 
00477 
00478     // returns true if the ith clause is in the CNF of a non-existentially
00479     // quantified formula
00480   bool clauseInNonExistAndNonExistUniqueFormulaCNF(const Clause* const & c)
00481   const
00482   {
00483     int i = findClauseIdx(c);
00484     assert(i >= 0);
00485     return clauseInNonExistAndNonExistUniqueFormulaCNF(i);
00486   }
00487 
00488 
00489     // The list and its contents should not be modified.
00490   const ClauseHashArray* getClauses() const { return clauses_; }
00491 
00492   int getSoftClauseSize()
00493   {
00494         int clauseNum = clauses_->size();
00495         for (int i = 0; i < clauseNum; i++)
00496     {
00497       Clause* clause = (*clauses_)[i];
00498       if (clause->isHardClause())
00499       {
00500         clauseNum --;   
00501       }
00502     }
00503     return clauseNum;
00504   }
00505 
00506   void getClauses(Array<Clause*>* const & clauses) const
00507   { for (int i = 0; i < clauses_->size();i++) clauses->append((*clauses_)[i]); }
00508 
00509   void setClauses(ClauseHashArray* const & clauses)
00510   { clauses_ = clauses; }
00511 
00512   void replaceClauses(ClauseHashArray* const & clauses)
00513   {
00514     if (clauses_)
00515     {
00516       clauses_->deleteItemsAndClear();
00517       delete clauses_;
00518     }
00519     clauses_ = clauses;
00520   }
00521 
00522   const MLNClauseInfo* getMLNClauseInfo(const int& i) const
00523   {
00524     if (i < 0 || i >= clauseInfos_->size()) return NULL;
00525     return (*clauseInfos_)[i];
00526   }
00527 
00528 
00529   int* getMLNClauseInfoIndexPtr(const int& i) const
00530   {
00531     assert(0 <= i && i < clauseInfos_->size());
00532     return &((*clauseInfos_)[i]->index);
00533   }
00534 
00535   const Array<MLNClauseInfo*>* getMLNClauseInfos() const
00536   { return clauseInfos_; }
00537 
00538   void setMLNClauseInfos(Array<MLNClauseInfo*>* const & clauseInfos)
00539   { clauseInfos_ = clauseInfos; }
00540 
00541   void replaceMLNClauseInfos(Array<MLNClauseInfo*>* const & clauseInfos)
00542   {
00543     if (clauseInfos_)
00544     {
00545       clauseInfos_->deleteItemsAndClear();
00546       delete clauseInfos_;
00547     }
00548     clauseInfos_ = clauseInfos;
00549   }
00550 
00551   
00552     // Caller should not modify the returned array or its contents
00553   const Array<Array<IndexClause*>*>* getPredIdToClausesMap() const
00554   { return predIdToClausesMap_; }
00555   
00556   void setPredIdToClausesMap(Array<Array<IndexClause*>*>* const & predIdToClausesMap)
00557   { predIdToClausesMap_ = predIdToClausesMap; }
00558 
00559   void replacePredIdToClausesMap(Array<Array<IndexClause*>*>* const & predIdToClausesMap)
00560   {
00561     if (predIdToClausesMap_)
00562     {
00563       for (int i = 0; i < predIdToClausesMap_->size(); i++)
00564         if ((*predIdToClausesMap_)[i]) 
00565         {
00566           (*predIdToClausesMap_)[i]->deleteItemsAndClear();
00567           delete (*predIdToClausesMap_)[i];
00568         }
00569       
00570       delete predIdToClausesMap_;
00571     }
00572     
00573     predIdToClausesMap_ = predIdToClausesMap;
00574   }
00575   
00576   const FormulaAndClausesArray* getFormulaAndClausesArray() const
00577   { return formAndClausesArray_; }
00578   
00579   void setFormulaAndClausesArray(FormulaAndClausesArray* const & formAndClausesArray)
00580   { formAndClausesArray_ = formAndClausesArray; }
00581 
00582   void replaceFormulaAndClausesArray(FormulaAndClausesArray* const & formAndClausesArray)
00583   {
00584     if (formAndClausesArray_)
00585     {
00586       formAndClausesArray_->deleteItemsAndClear();
00587       delete formAndClausesArray_;
00588     }
00589     formAndClausesArray_ = formAndClausesArray;
00590   }
00591   
00592   const Array<bool>* getExternalClause() const
00593   { return externalClause_; }
00594 
00595   void setExternalClause(Array<bool>* const & externalClause)
00596   {
00597     externalClause_ = externalClause;
00598   }
00599 
00600   void replaceExternalClause(Array<bool>* const & externalClause)
00601   {
00602     if (externalClause_)
00603     {
00604       delete externalClause_;
00605     }
00606     externalClause_ = externalClause;
00607   }
00608 
00609 
00610   void setClauseInfoPriorMeansToClauseWts()
00611   {
00612     assert(clauses_->size() == clauseInfos_->size());
00613     for (int i = 0; i < clauseInfos_->size(); i++)
00614       (*clauseInfos_)[i]->priorMean = (*clauses_)[i]->getWt();
00615   }
00616 
00617 
00618   void getClauseWts(Array<double>& wts) const
00619   {
00620     wts.clear();
00621     for (int i = 0; i < clauses_->size(); i++) 
00622       wts.append((*clauses_)[i]->getWt());
00623   }
00624 
00625 
00626   void setClauseWts(Array<double>& wts) 
00627   {
00628     assert (wts.size() == clauses_->size());
00629     for (int i = 0; i < clauses_->size(); i++) 
00630       (*clauses_)[i]->setWt(wts[i]);
00631   }
00632 
00633   
00634   const IndexClauseHashArray* 
00635   getClausesOfFormula(const string& formulaStr) const
00636   {
00637     FormulaAndClauses tmp(formulaStr, 0, false, false);    
00638     int i = formAndClausesArray_->find(&tmp);
00639     if (i < 0) return NULL;
00640     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00641     return fnc->indexClauses;
00642   }
00643 
00644 
00645     //Returns true if formulaStr is in mln and its numPred is set; otherwise,
00646     //returns false.
00647   bool setFormulaNumPreds(const string& formulaStr, const int& numPreds)
00648   {
00649     FormulaAndClauses tmp(formulaStr, 0, false, false);    
00650     int i = formAndClausesArray_->find(&tmp);
00651     if (i < 0) return false;
00652     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00653     fnc->numPreds = numPreds;
00654     return true;
00655   }
00656 
00657 
00658     //Returns true if formulaStr is in mln and its isHard is set; otherwise,
00659     //returns false.
00660   bool setFormulaIsHard(const string& formulaStr, const bool& isHard)
00661   {
00662     FormulaAndClauses tmp(formulaStr, 0, false, false);    
00663     int i = formAndClausesArray_->find(&tmp);
00664     if (i < 0) return false;
00665     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00666     fnc->isHard = isHard;
00667     return true;
00668   }
00669 
00670 
00671     //Returns true if formulaStr is in mln and its priorMean is set; otherwise,
00672     //returns false.
00673   bool setFormulaPriorMean(const string& formulaStr, const double& priorMean)
00674   {
00675     FormulaAndClauses tmp(formulaStr, 0, false, false);    
00676     int i = formAndClausesArray_->find(&tmp);
00677     if (i < 0) return false;
00678     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00679     fnc->priorMean = priorMean;
00680     return true;
00681   }
00682 
00683     //Returns true if formulaStr is in mln and its wt is set; otherwise,
00684     //returns false.
00685   bool setFormulaWt(const string& formulaStr, const double& wt)
00686   {
00687     FormulaAndClauses tmp(formulaStr, 0, false, false);    
00688     int i = formAndClausesArray_->find(&tmp);
00689     if (i < 0) return false;
00690     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00691     fnc->wt = wt;
00692     return true;
00693   }
00694 
00695 
00696     //Returns true if formulaStr is in mln and its isExistUnique is set; 
00697     //otherwise returns false.
00698   bool setFormulaIsExistUnique(const string& formulaStr, 
00699                                const bool& isExistUnique)
00700   {
00701     FormulaAndClauses tmp(formulaStr, 0, false, false);    
00702     int i = formAndClausesArray_->find(&tmp);
00703     if (i < 0) return false;
00704     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00705     fnc->isExistUnique = isExistUnique;
00706     return true;
00707   }
00708 
00709 
00710     //formulaStr must be in MLN
00711   double getFormulaWt(const string& formulaStr)
00712   {
00713     FormulaAndClauses tmp(formulaStr, 0, false, false);    
00714     int i = formAndClausesArray_->find(&tmp);
00715     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00716     return fnc->wt;
00717   }
00718 
00719 
00720   const Array<IndexClause*>* getClausesContainingPred(const int& predId) const
00721   { 
00722     if (predId < predIdToClausesMap_->size())
00723       return (*predIdToClausesMap_)[predId];
00724     return NULL;
00725   }
00726 
00735   const string getParentFormula(const int& clauseIdx, const int& formulaIdx) const 
00736   {
00737     FormulaClauseIndexes* fcIdxs =
00738       (*clauseInfos_)[clauseIdx]->formulaClauseIndexes[formulaIdx];
00739     return (*formAndClausesArray_)[*fcIdxs->formulaIndex]->formula;
00740   }
00741 
00750   const string getParentFormula(const Clause* const & c, const int& formulaIdx) const 
00751   {
00752     int i = findClauseIdx(c);
00753     if (i < 0) return NULL;
00754     return getParentFormula(i, formulaIdx);
00755   }
00756 
00757 
00758   void compress()
00759   {
00760     clauses_->compress();
00761     for (int i = 0; i < clauseInfos_->size(); i++) 
00762       (*clauseInfos_)[i]->compress();
00763     clauseInfos_->compress();
00764     for (int i = 0; i < formAndClausesArray_->size(); i++)
00765       (*formAndClausesArray_)[i]->indexClauses->compress();
00766     formAndClausesArray_->compress();
00767     for (int i = 0; i < predIdToClausesMap_->size(); i++)
00768       if ((*predIdToClausesMap_)[i]) (*predIdToClausesMap_)[i]->compress();
00769     predIdToClausesMap_->compress();
00770   }
00771 
00772 
00773     //print formulas (commented out) followed by the clauses in its CNF
00774   void printMLN(ostream& out, const Domain* const & domain)
00775   {
00776     int outprec = 6;
00777     out.precision(outprec);
00778     out.setf(ios_base::left, ios_base::adjustfield);
00779 
00780     const FormulaAndClausesArray* fncArr = formAndClausesArray_;
00781     
00782     Array<int> fncArrIdxs;
00783     for (int i = 0; i < fncArr->size(); i++)
00784       if (!(*fncArr)[i]->hasExist && !(*fncArr)[i]->isExistUnique) 
00785         fncArrIdxs.append(i);
00786 
00787     for (int i = 0; i < fncArr->size(); i++)
00788       if ((*fncArr)[i]->isExistUnique) 
00789         fncArrIdxs.append(i);
00790     
00791     for (int i = 0; i < fncArr->size(); i++)
00792       if ((*fncArr)[i]->hasExist) 
00793         fncArrIdxs.append(i);
00794 
00795       // for each user-specified formula
00796     for (int ii = 0; ii < fncArrIdxs.size(); ii++)  
00797     {
00798       int i = fncArrIdxs[ii];
00799       double totalWt = 0;
00800       IndexClauseHashArray* indexClauses = (*fncArr)[i]->indexClauses;
00801       for (int j = 0; j < indexClauses->size(); j++)
00802       {
00803         Clause* c = (*indexClauses)[j]->clause;
00804         totalWt += c->getWt()/getNumParentFormulas(c);
00805       }
00806         // output the original formula and its weight
00807       out.width(0); out << "// "; out.width(outprec); 
00808       out << totalWt << "  " << (*fncArr)[i]->formula << endl;
00809       
00810       if ((*fncArr)[i]->hasExist || (*fncArr)[i]->isExistUnique)
00811       {
00812         out << totalWt << "  " << (*fncArr)[i]->formula <<endl;
00813       }
00814       else
00815       {
00816         if ((*fncArr)[i]->tiedClauses)
00817         {
00818           out.width(outprec); 
00819           out << totalWt << "  " << (*fncArr)[i]->formula << endl;
00820         }
00821         else
00822         {
00823             // output clauses derived from the original formula and their
00824             // weights
00825           for (int j = 0; j < indexClauses->size(); j++)
00826           {
00827             Clause* c = (*indexClauses)[j]->clause;    
00828             out.width(outprec); 
00829             out << c->getWt()/getNumParentFormulas(c) << "  "; 
00830             c->printWithoutWtWithStrVar(out, domain);
00831             out << endl;
00832           }
00833         }
00834       }
00835       out << endl;
00836     }
00837   }
00838 
00839   
00840     //Print non-existential formulas (commented out) followed by the clauses in 
00841     //its CNF. Clause weights are divided among non-existential formulas.
00842   void printMLNNonExistFormulas(ostream& out, const Domain* const & domain)
00843   {
00844     int outprec = 6;
00845     out.precision(outprec);
00846     out.setf(ios_base::left, ios_base::adjustfield);
00847 
00848       // for each user-specified formula
00849     const FormulaAndClausesArray* fncArr = formAndClausesArray_;
00850     for (int i = 0; i < fncArr->size(); i++)
00851     {
00852       if ((*fncArr)[i]->hasExist || (*fncArr)[i]->isExistUnique) continue;
00853     
00854       double totalWt = 0;
00855       IndexClauseHashArray* indexClauses = (*fncArr)[i]->indexClauses;
00856       for (int j = 0; j < indexClauses->size(); j++)
00857       {
00858         Clause* c = (*indexClauses)[j]->clause;
00859         //assert(clauseOrdering->find(c) >= 0);
00860         totalWt 
00861           += c->getWt()/getNumNonExistNonExistUniqueParentFormulas(c);
00862       }
00863         // output the original formula and its weight
00864       out.width(0); out << "// "; out.width(outprec); 
00865       out << totalWt << "  " << (*fncArr)[i]->formula << endl;
00866       
00867 
00868       if ((*fncArr)[i]->tiedClauses)
00869       {
00870         out.width(outprec); 
00871         out << totalWt << "  " << (*fncArr)[i]->formula << endl;
00872       }
00873       else
00874       {
00875           // output the clauses derived from the original formula and their
00876           // weights
00877         for (int j = 0; j < indexClauses->size(); j++)
00878         {
00879           Clause* c = (*indexClauses)[j]->clause;    
00880           out.width(outprec); 
00881           out << c->getWt()/getNumNonExistNonExistUniqueParentFormulas(c)
00882               << "  "; 
00883           c->printWithoutWtWithStrVar(out, domain);
00884           out << endl;
00885         }
00886       }
00887       out << endl;
00888     } 
00889   }
00890 
00891 
00892     //Print each non-existential clause as a single formula, followed by
00893     //existential formulas
00894   void printMLNClausesFormulas(ostream& out, const Domain* const & domain,
00895                                const bool& includeIdx)
00896   {
00897     int idx = 0;
00898     int* startIdx = (includeIdx) ? &idx : NULL;
00899     bool includeExistClauses = false;
00900     bool divideWtAmongExistFormulas = true;
00901     bool sortByLen = true;
00902     printClausesWithWeights(out, domain, startIdx, includeExistClauses,
00903                             sortByLen, divideWtAmongExistFormulas);
00904     printExistOrExistUniqueFormulasWithWeights(out, startIdx);
00905   }
00906 
00907 
00908     //If includeExistClauses is false, we exclude clauses that ONLY appear
00909     //in the CNFs of existential formulas.
00910   void printClausesWithWeights(ostream& out, const Domain* const & domain,
00911                                int* const & startIdx = NULL,
00912                                const bool& includeExistClauses=true,
00913                                const bool& sortByLen=false,
00914                                const bool& divWtAmongExistFormulas=false) const
00915   {
00916     Array<Clause*> ca;
00917     for (int i = 0; i < clauses_->size(); i++) 
00918     {
00919       if ( !includeExistClauses && 
00920            !clauseInNonExistAndNonExistUniqueFormulaCNF(i) ) continue;
00921       ca.append((*clauses_)[i]);
00922     }
00923 
00924     if (sortByLen) Clause::sortByLen(ca);
00925     ClauseHashArray cha;
00926     for (int i = 0; i < ca.size(); i++) cha.append(ca[i]);
00927 
00928     printClausesWithWeights(out, domain, &cha,startIdx,divWtAmongExistFormulas);
00929   }
00930 
00931   
00932   void printClausePriorMeans(ostream& out, const Domain* const & domain)
00933   {
00934     out.setf(ios_base::left, ios_base::adjustfield);    
00935     out.precision(6);
00936     assert(clauseInfos_->size() == clauses_->size());
00937     for (int i = 0; i < clauses_->size(); i++)
00938     {
00939       out << i << ":  "; out.width(14); 
00940       out << (*clauseInfos_)[i]->priorMean; out.width(0); out << " "; 
00941       (*clauses_)[i]->printWithoutWtWithStrVar(out, domain); 
00942       out << endl; 
00943     }
00944     out.width(0);
00945   }
00946 
00947   
00948   void printFormulaPriorMeans(ostream& out)
00949   {
00950     out.setf(ios_base::left, ios_base::adjustfield);
00951     out.precision(6);
00952     for (int i = 0; i < formAndClausesArray_->size(); i++)
00953     {
00954       FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00955       out << i << ":  "; out.width(14); 
00956       out << fnc->priorMean; out.width(0); 
00957       out << " " << fnc->formula << endl;       
00958     }
00959     out.width(0);
00960   }
00961 
00962 
00963  private:
00964   void appendClauseInfo(const Clause* const & clause, const int& clauseIdx, 
00965                         int* const& formulaIdx, int* const& clauseIdxForFormula)
00966   {
00967     assert(clauseInfos_->size() == clauseIdx);
00968 
00969     MLNClauseInfo* ci = new MLNClauseInfo(clauseInfos_->size());
00970     clauseInfos_->append(ci);
00971 
00972       // keep track of appended clause's positions in predIdToClausesMap_
00973     Array<PredIdClauseIndex*>& piciArr = ci->predIdsClauseIndexes;
00974     hash_set<int> seenPredIds;
00975     const Array<Predicate*>* preds = clause->getPredicates();
00976     for (int i = 0; i < preds->size(); i++)
00977     {
00978       int predId = (*preds)[i]->getId();
00979         //if we have already noted that clause contains pred
00980       if (seenPredIds.find(predId) != seenPredIds.end()) continue;
00981       seenPredIds.insert(predId);
00982       
00983       if (predId >= predIdToClausesMap_->size())
00984         predIdToClausesMap_->growToSize(predId+1, NULL);
00985       Array<IndexClause*>*& icArr = (*predIdToClausesMap_)[predId];
00986       if (icArr == NULL) icArr = new Array<IndexClause*>;
00987       IndexClause* ic = new IndexClause(icArr->size(), (Clause*)clause);
00988       icArr->append(ic);
00989       
00990       piciArr.append(new PredIdClauseIndex(predId, &(ic->index)));
00991     }
00992 
00993     updateClauseInfo(clauseIdx, formulaIdx, clauseIdxForFormula);
00994   }
00995 
00996   
00997   void updateClauseInfo(const int& clauseIdx, int* const & formulaIdx, 
00998                         int* const & clauseIdxForFormula)
00999   {
01000     MLNClauseInfo* clauseInfo = (*clauseInfos_)[clauseIdx];
01001       // keep track of appendedClause's position in formAndClauseArray_    
01002     assert(*clauseIdxForFormula >= 0);
01003     Array<FormulaClauseIndexes*>& fciArr = clauseInfo->formulaClauseIndexes;
01004 
01005     fciArr.append(new FormulaClauseIndexes(formulaIdx, clauseIdxForFormula));
01006   }
01007 
01008 
01009     //Returns -1 if c is not found in MLN
01010   int getNumParentFormulas(const Clause* const & c) const 
01011   {
01012     int i = findClauseIdx(c);
01013     if (i < 0) return -1;
01014     return (*clauseInfos_)[i]->formulaClauseIndexes.size();
01015   }
01016 
01017 
01018   int getNumNonExistNonExistUniqueParentFormulas(const Clause* const & c) const 
01019   {
01020     int i = findClauseIdx(c);
01021     if (i < 0) return -1;
01022     Array<FormulaClauseIndexes*>& fciArr 
01023       = (*clauseInfos_)[i]->formulaClauseIndexes;
01024     int n = 0;
01025     for (int i = 0; i < fciArr.size(); i++)
01026     {
01027       int fidx = *(fciArr[i]->formulaIndex);
01028       FormulaAndClauses* fnc = (*formAndClausesArray_)[fidx];
01029       if (!fnc->hasExist && !fnc->isExistUnique) n++;
01030     }
01031     return n;
01032   }
01033 
01034 
01035   int getNumExistOrExistUniqueParentFormulas(const Clause* const & c) const 
01036   {
01037     int i = findClauseIdx(c);
01038     if (i < 0) return -1;
01039     Array<FormulaClauseIndexes*>& fciArr 
01040       = (*clauseInfos_)[i]->formulaClauseIndexes;
01041     int n = 0;
01042     for (int i = 0; i < fciArr.size(); i++)
01043     {
01044       int fidx = *(fciArr[i]->formulaIndex);
01045       FormulaAndClauses* fnc = (*formAndClausesArray_)[fidx];
01046       if (fnc->hasExist || fnc->isExistUnique) n++;
01047     }
01048     return n;
01049   }
01050 
01051 
01052   void printClausesWithWeights(ostream& out, const Domain* const & domain,
01053                                const ClauseHashArray* const & clauses,
01054                                int* const & startIdx,
01055                                const bool& divideWithAmongExistFormulas) const
01056   {
01057     out.setf(ios_base::left, ios_base::adjustfield);
01058     int i;
01059     for (i = 0; i < clauses->size(); i++)
01060     {      
01061       if (startIdx) { out << (*(startIdx))++ << ":  "; out.width(14); }
01062       else          { out.width(10); }
01063       
01064       double wt = (*clauses)[i]->getWt();
01065       if (divideWithAmongExistFormulas) 
01066         wt /= 1+getNumExistOrExistUniqueParentFormulas((*clauses)[i]);
01067 
01068       out << wt; out.width(0); out << " ";
01069       (*clauses)[i]->printWithoutWtWithStrVar(out, domain); 
01070       out << endl; 
01071     }
01072     out.width(0);
01073   }
01074 
01075 
01076   void printExistOrExistUniqueFormulasWithWeights(ostream& out, 
01077                                                   int* const & startIdx=NULL)
01078   {
01079     int i;
01080     for (i = 0; i < formAndClausesArray_->size(); i++)
01081     {
01082       if (!(*formAndClausesArray_)[i]->hasExist && 
01083           !(*formAndClausesArray_)[i]->isExistUnique) continue;
01084       double totalWt = 0;
01085       IndexClauseHashArray* indexClauses 
01086         = (*formAndClausesArray_)[i]->indexClauses;
01087       for (int j = 0; j < indexClauses->size(); j++)
01088       {
01089         Clause* c = (*indexClauses)[j]->clause;
01090         totalWt += c->getWt()/getNumParentFormulas(c);
01091       }
01092       
01093       if (startIdx) { out << (*(startIdx))++ << ":  "; out.width(14); }
01094       else            { out.width(10); }
01095       out << totalWt; out.width(0); out << " " 
01096           << (*formAndClausesArray_)[i]->formula <<endl;
01097     }
01098   }
01099 
01100 
01101  private:
01102   ClauseHashArray* clauses_;
01103   Array<MLNClauseInfo*>* clauseInfos_;
01104   FormulaAndClausesArray* formAndClausesArray_;
01105 
01106     //predIdToClausesMap_[p] maps pred id p to an array of IndexClause.
01107     //The clause in each IndexClause contains a pred with id p, and the 
01108     //index is the index of the IndexClause in predIdToClausesMap_[p].
01109     //predIdToClausesMap_[p] may be NULL.
01110   Array<Array<IndexClause*>*>* predIdToClausesMap_;
01111 
01112     // externalClause_[c] indicates if clause c is external, i.e. it contains
01113     // constants not present in this mln (can occur when per-constant rules are
01114     // used with multiple dbs).
01115   Array<bool>* externalClause_;
01116 };
01117 
01118 #endif

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