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 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 MLN_H_JUN_26_2005
00067 #define MLN_H_JUN_26_2005
00068 
00069 #include <cfloat>
00070 #include <ext/hash_map>
00071 #include <ext/hash_set>
00072 using namespace __gnu_cxx;
00073 #include "clause.h"
00074 #include "equalstr.h"
00075 #include "mlnhelper.h"
00076 
00077 
00078 class MLN
00079 {
00080  public: 
00081   MLN() : clauses_(new ClauseHashArray),clauseInfos_(new Array<MLNClauseInfo*>),
00082           formAndClausesArray_(new FormulaAndClausesArray), 
00083           predIdToClausesMap_(new Array<Array<IndexClause*>*>) {}
00084 
00085   ~MLN()
00086   {
00087     clauses_->deleteItemsAndClear(); delete clauses_;
00088     clauseInfos_->deleteItemsAndClear(); delete clauseInfos_;
00089     formAndClausesArray_->deleteItemsAndClear(); delete formAndClausesArray_;
00090     for (int i = 0; i < predIdToClausesMap_->size(); i++)
00091       if ((*predIdToClausesMap_)[i]) 
00092       {
00093         (*predIdToClausesMap_)[i]->deleteItemsAndClear();
00094         delete (*predIdToClausesMap_)[i];
00095       }
00096     delete predIdToClausesMap_;
00097   }
00098 
00099 
00100   int getNumClauses() const { return clauses_->size(); }
00101 
00102   int getNumHardClauses() const
00103   {
00104         int numHardClauses = 0;
00105         for (int i = 0; i < clauses_->size(); i++)
00106         {
00107           if ((*clauses_)[i]->isHardClause()) numHardClauses++;
00108         }
00109         return numHardClauses;
00110   }
00111 
00112 
00113   bool containsClause(const Clause* const & c) const
00114   { return clauses_->contains((Clause*)c); }
00115 
00116 
00117     //MLN owns clause c and is responsible for its deletion.
00118     //hasExist is true if formulaString contains an existential quantifier
00119     //during the CNF conversion process.
00120     //Call setHardClausesWts() after this function to set the weights of hard
00121     //clauses to twice the maximum of soft clause wts.
00122     //Returns true of the clause is appended; otherwise returns false.
00123     //retIdx is the index of the clause in MLN's array of clauses
00124   bool appendClause(const string& formulaString, const bool& hasExist, 
00125                     Clause* const& c, const double& wt,
00126                     const bool& isHardClause, int& retClauseIdx) 
00127   {
00128     assert(c);
00129     c->canonicalize();
00130     bool isAppended;
00131     Clause* clause;
00132     if ((retClauseIdx = clauses_->find(c)) >= 0) // if clauses_ contains c
00133     {
00134       clause = (*clauses_)[retClauseIdx];
00135       delete c;
00136       isAppended = false;
00137     }
00138     else
00139     {
00140         // clause does not exist in MLN, so add it
00141       retClauseIdx = clauses_->append(c);
00142       clause = c;
00143       isAppended = true;
00144       clause->setWt(0); //start accumulating weight from 0
00145     }
00146     clause->addWt(wt);
00147     if (isHardClause) clause->setIsHardClause(isHardClause);
00148 
00149  
00150     FormulaAndClauses* fac = new FormulaAndClauses(formulaString, 
00151                                                    formAndClausesArray_->size(),
00152                                                    hasExist);
00153     int fidx;
00154       // if this is the first time we see the formulaString
00155     if ( (fidx = formAndClausesArray_->find(fac)) < 0 )
00156     {
00157       fidx = formAndClausesArray_->append(fac);
00158       assert(fac->index == fidx);
00159     }
00160     else
00161     {
00162       delete fac;
00163       fac = (*formAndClausesArray_)[fidx];
00164       assert(fac->index == fidx);
00165     }
00166     IndexClause* ic = new IndexClause(fac->indexClauses->size(), clause);
00167     int cidx = fac->indexClauses->append(ic);
00168     if (cidx < 0) { delete ic; ic = NULL; }
00169     else          assert(ic->index == cidx);
00170 
00171     if (isAppended) 
00172     {
00173         // add to predIdToClausesMap_, and append to clauseInfos_
00174       appendClauseInfo(clause, retClauseIdx, &(fac->index), &(ic->index));
00175     }
00176     else 
00177     if (cidx >= 0) 
00178     {   
00179         //a clause was appended to an entry in formAndClausesArray_, so update 
00180         //the formulaClauseIndexes of the MLNClauseInfo corresponding to clause
00181       updateClauseInfo(retClauseIdx, &(fac->index), &(ic->index));
00182     }
00183 
00184     assert(clauses_->size() == clauseInfos_->size());
00185     return isAppended;
00186   } //appendClause()
00187 
00188 
00189     // idx is the index into the clauses_ array
00190   Clause* removeClause(const int& remIdx)
00191   {
00192       //remove the clause and its corresponding MLNClauseInfo
00193     Clause* r = clauses_->removeItemFastDisorder(remIdx);
00194     MLNClauseInfo* ci = clauseInfos_->removeItemFastDisorder(remIdx);
00195     assert(ci->index == remIdx);
00196 
00197     if (clauseInfos_->size() != remIdx) //if we didn't just remove the last item
00198     {
00199         //(*clauseInfos_)[remIdx] is the last item moved to the position of the
00200         //removed IndexClause
00201       (*clauseInfos_)[remIdx]->index = remIdx;
00202     }
00203 
00204       //update MLNClauseInfo's predIdsClauseIndexes
00205     Array<PredIdClauseIndex*>& piciArr = ci->predIdsClauseIndexes;
00206     for (int i = 0; i < piciArr.size(); i++)
00207     {
00208       int predId = piciArr[i]->predId;
00209       int remIdx = *(piciArr[i]->clauseIndex);
00210 
00211       Array<IndexClause*>* indexesClauses = (*predIdToClausesMap_)[predId];
00212       IndexClause* ic = indexesClauses->removeItemFastDisorder(remIdx);
00213       assert(ic->index == remIdx && ic->clause == r);
00214       delete ic;
00215 
00216         //if pred's clause array isn't empty & we didn't just removed last item
00217       if (indexesClauses->size() != remIdx)
00218       {
00219           //(*predClauses)[remIdx] is the last item moved to the position of 
00220           //removed clause, so update its position to remIdx
00221         (*indexesClauses)[remIdx]->index = remIdx;        
00222       }
00223 
00224       if (indexesClauses->empty())
00225       {
00226         delete indexesClauses;
00227         (*predIdToClausesMap_)[predId] = NULL;
00228       }
00229     }
00230 
00231       //update MLNClauseInfo's formulaClauseIndexes
00232     Array<FormulaClauseIndexes*>& fciArr = ci->formulaClauseIndexes;
00233     for (int i = 0; i < fciArr.size(); i++)
00234     {
00235       int fidx = *(fciArr[i]->formulaIndex);
00236       int remIdx = *(fciArr[i]->clauseIndex);
00237       FormulaAndClauses* fac = (*formAndClausesArray_)[fidx];
00238       IndexClauseHashArray* indexClauses = fac->indexClauses;
00239       IndexClause* ic = indexClauses->removeItemFastDisorder(remIdx);
00240       assert(ic->index == remIdx);
00241       delete ic;
00242       if (indexClauses->size() != remIdx)
00243         (*indexClauses)[remIdx]->index = remIdx;
00244       
00245       if (indexClauses->empty())
00246       {
00247         fac = formAndClausesArray_->removeItemFastDisorder(fidx);
00248         assert(fac->index == fidx);
00249         delete fac;
00250         if (formAndClausesArray_->size() != fidx)
00251           (*formAndClausesArray_)[fidx]->index = fidx;
00252       }
00253     }
00254 
00255     delete ci;
00256     assert(clauses_->size() == clauseInfos_->size());
00257     return r;
00258   }//removeClause()
00259 
00260 
00261     // returns the removed clause or NULL if c is not in the MLN
00262   Clause* removeClause(const Clause* const & c)
00263   {
00264     int idx = findClauseIdx(c);
00265     if (idx < 0) return NULL;
00266     return removeClause(idx);
00267   }
00268 
00269 
00270   void removeAllClauses(Array<Clause*>* const & clauses)
00271   {
00272     while (!clauses_->empty()) 
00273     {
00274       Clause* c = removeClause(0);
00275       if (clauses) clauses->append(c);
00276       else delete c;
00277     }
00278   }
00279 
00280 
00281     // Clauses  are reinserted into clauses_, and the indexClauses arrays of 
00282     // each FormulaAndClauses in formAndClausesArrays_. Call this when the 
00283     // clauses' hash codes change, e.g., when constants are reordered. You have
00284     // to do this because hash_map does not register the hash values of its
00285     // contents if the values change after the contents are inserted.
00286   void rehashClauses()
00287   {
00288     ClauseHashArray* newha =  new ClauseHashArray;
00289     for (int i = 0; i < clauses_->size(); i++) 
00290     {
00291       int a = newha->append((*clauses_)[i]);
00292       assert(a >= 0); a = 0; //avoid compilation warning
00293     }
00294     delete clauses_;
00295     clauses_ = newha;
00296  
00297 
00298     for (int i = 0; i < formAndClausesArray_->size(); i++)
00299     {
00300       FormulaAndClauses* fac = (*formAndClausesArray_)[i];
00301       IndexClauseHashArray* newArr = new IndexClauseHashArray;
00302       IndexClauseHashArray* curArr = fac->indexClauses;
00303       for (int j = 0; j < curArr->size(); j++)
00304       {
00305         int a = newArr->append((*curArr)[j]);
00306         assert((*curArr)[j]->index == a); a = 0; //avoid compilation warning
00307       }
00308       curArr->clear();
00309       delete curArr;
00310       fac->indexClauses = newArr;
00311     }
00312   }
00313 
00314 
00315     //returns the maximum absolute value of soft weights (weights of clauses
00316     //that are not hard and not belonging to existentially and uniquely quant.
00317     //formulas).
00318   double getMaxAbsSoftWt()
00319   {
00320       //find the max of the (absolute) soft clause wts
00321     double maxSoftWt = 0;
00322     for (int i = 0; i < clauses_->size(); i++)
00323     {
00324       Clause* c = (*clauses_)[i];
00325       if (!c->isHardClause() && !isExistUniqueClause(c))
00326       {
00327         double abWt = fabs(c->getWt());
00328         if (abWt > maxSoftWt) maxSoftWt = abWt;
00329       }
00330     }
00331     return maxSoftWt;
00332   }
00333 
00334 
00335     // Returns the index into clauses_ where c is found
00336   int findClauseIdx(const Clause* const & c) const 
00337   { return clauses_->find((Clause*)c); }
00338 
00339 
00340   const Clause* findClause(const Clause* const & c) const 
00341   { 
00342     int i = findClauseIdx(c);
00343     if (i < 0) return NULL;
00344     return (*clauses_)[i];
00345   }
00346 
00347 
00348     //returns clause at position of clauses_ 
00349     //or NULL if i is not a valid index of clauses_     
00350   const Clause* getClause(const int& i) const
00351   {
00352     if (i < 0 || i >= clauses_->size()) return NULL;
00353     return (*clauses_)[i];
00354   }
00355 
00356 
00357     // returns true if the ith clause is in the CNF of an existentially
00358     // quantified formula
00359   bool isExistClause(const int& i) const
00360   {
00361     assert(0 <= i && i < clauses_->size());
00362     Array<FormulaClauseIndexes*>& fciArr 
00363       = (*clauseInfos_)[i]->formulaClauseIndexes;
00364     for (int i = 0; i < fciArr.size(); i++)
00365       if ((*formAndClausesArray_)[*(fciArr[i]->formulaIndex)]->hasExist) 
00366         return true;
00367     return false;
00368   }
00369 
00370 
00371     // returns true if clause c is in the CNF of an existentially
00372     // quantified formula
00373   bool isExistClause(const Clause* const & c) const
00374   {
00375     int i = findClauseIdx(c);
00376     assert(i >= 0);
00377     return isExistClause(i);
00378   }
00379 
00380 
00381     // returns true if the ith clause is in the CNF of an existentially and
00382     // uniquely quantified formula
00383   bool isExistUniqueClause(const int& i) const
00384   {
00385     assert(0 <= i && i < clauses_->size());
00386     Array<FormulaClauseIndexes*>& fciArr 
00387       = (*clauseInfos_)[i]->formulaClauseIndexes;
00388     for (int i = 0; i < fciArr.size(); i++)
00389       if ((*formAndClausesArray_)[*(fciArr[i]->formulaIndex)]->isExistUnique) 
00390         return true;
00391     return false;
00392   }
00393 
00394 
00395     // returns true if clause c is in the CNF of an existentially and
00396     // uniquely quantified formula
00397   bool isExistUniqueClause(const Clause* const & c) const
00398   {
00399     int i = findClauseIdx(c);
00400     assert(i >= 0);
00401     return isExistUniqueClause(i);
00402   }
00403 
00404 
00405     // returns true if the ith clause is in the CNF of a non-existentially
00406     // quantified formula
00407   bool clauseInNonExistAndNonExistUniqueFormulaCNF(const int& i) const
00408   {
00409     assert(0 <= i && i < clauses_->size());
00410     Array<FormulaClauseIndexes*>& fciArr 
00411       = (*clauseInfos_)[i]->formulaClauseIndexes;
00412     for (int i = 0; i < fciArr.size(); i++)
00413     {
00414       FormulaAndClauses*fnc=(*formAndClausesArray_)[*(fciArr[i]->formulaIndex)];
00415       if (!fnc->hasExist && !fnc->isExistUnique) return true;
00416     }
00417     return false;
00418   }
00419 
00420 
00421     // returns true if the ith clause is in the CNF of a non-existentially
00422     // quantified formula
00423   bool clauseInNonExistAndNonExistUniqueFormulaCNF(const Clause* const & c)
00424   const
00425   {
00426     int i = findClauseIdx(c);
00427     assert(i >= 0);
00428     return clauseInNonExistAndNonExistUniqueFormulaCNF(i);
00429   }
00430 
00431 
00432     // The list and its contents should not be modified.
00433   const ClauseHashArray* getClauses() const { return clauses_; }
00434 
00435 
00436   void getClauses(Array<Clause*>* const & clauses) const
00437   { for (int i = 0; i < clauses_->size();i++) clauses->append((*clauses_)[i]); }
00438 
00439 
00440   const MLNClauseInfo* getMLNClauseInfo(const int& i) const
00441   {
00442     if (i < 0 || i >= clauseInfos_->size()) return NULL;
00443     return (*clauseInfos_)[i];
00444   }
00445 
00446 
00447   int* getMLNClauseInfoIndexPtr(const int& i) const
00448   {
00449     assert(0 <= i && i < clauseInfos_->size());
00450     return &((*clauseInfos_)[i]->index);
00451   }
00452 
00453   const Array<MLNClauseInfo*>* getMLNClauseInfos() const
00454   { return clauseInfos_; }
00455 
00456 
00457   void setClauseInfoPriorMeansToClauseWts()
00458   {
00459     assert(clauses_->size() == clauseInfos_->size());
00460     for (int i = 0; i < clauseInfos_->size(); i++)
00461       (*clauseInfos_)[i]->priorMean = (*clauses_)[i]->getWt();
00462   }
00463 
00464 
00465   void getClauseWts(Array<double>& wts) const
00466   {
00467     wts.clear();
00468     for (int i = 0; i < clauses_->size(); i++) 
00469       wts.append((*clauses_)[i]->getWt());
00470   }
00471 
00472 
00473   void setClauseWts(Array<double>& wts) 
00474   {
00475     assert (wts.size() == clauses_->size());
00476     for (int i = 0; i < clauses_->size(); i++) 
00477       (*clauses_)[i]->setWt(wts[i]);
00478   }
00479 
00480   
00481   const IndexClauseHashArray* 
00482   getClausesOfFormula(const string& formulaStr) const
00483   {
00484     FormulaAndClauses tmp(formulaStr, 0, false);    
00485     int i = formAndClausesArray_->find(&tmp);
00486     if (i < 0) return NULL;
00487     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00488     return fnc->indexClauses;
00489   }
00490 
00491 
00492     //Returns true if formulaStr is in mln and its numPred is set; otherwise,
00493     //returns false.
00494   bool setFormulaNumPreds(const string& formulaStr, const int& numPreds)
00495   {
00496     FormulaAndClauses tmp(formulaStr, 0, false);    
00497     int i = formAndClausesArray_->find(&tmp);
00498     if (i < 0) return false;
00499     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00500     fnc->numPreds = numPreds;
00501     return true;
00502   }
00503 
00504 
00505     //Returns true if formulaStr is in mln and its isHard is set; otherwise,
00506     //returns false.
00507   bool setFormulaIsHard(const string& formulaStr, const bool& isHard)
00508   {
00509     FormulaAndClauses tmp(formulaStr, 0, false);    
00510     int i = formAndClausesArray_->find(&tmp);
00511     if (i < 0) return false;
00512     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00513     fnc->isHard = isHard;
00514     return true;
00515   }
00516 
00517 
00518     //Returns true if formulaStr is in mln and its priorMean is set; otherwise,
00519     //returns false.
00520   bool setFormulaPriorMean(const string& formulaStr, const double& priorMean)
00521   {
00522     FormulaAndClauses tmp(formulaStr, 0, false);    
00523     int i = formAndClausesArray_->find(&tmp);
00524     if (i < 0) return false;
00525     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00526     fnc->priorMean = priorMean;
00527     return true;
00528   }
00529 
00530     //Returns true if formulaStr is in mln and its wt is set; otherwise,
00531     //returns false.
00532   bool setFormulaWt(const string& formulaStr, const double& wt)
00533   {
00534     FormulaAndClauses tmp(formulaStr, 0, false);    
00535     int i = formAndClausesArray_->find(&tmp);
00536     if (i < 0) return false;
00537     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00538     fnc->wt = wt;
00539     return true;
00540   }
00541 
00542 
00543     //Returns true if formulaStr is in mln and its isExistUnique is set; 
00544     //otherwise returns false.
00545   bool setFormulaIsExistUnique(const string& formulaStr, 
00546                                const bool& isExistUnique)
00547   {
00548     FormulaAndClauses tmp(formulaStr, 0, false);    
00549     int i = formAndClausesArray_->find(&tmp);
00550     if (i < 0) return false;
00551     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00552     fnc->isExistUnique = isExistUnique;
00553     return true;
00554   }
00555 
00556 
00557     //formulaStr must be in MLN
00558   double getFormulaWt(const string& formulaStr)
00559   {
00560     FormulaAndClauses tmp(formulaStr, 0, false);    
00561     int i = formAndClausesArray_->find(&tmp);
00562     FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00563     return fnc->wt;
00564   }
00565 
00566 
00567   const FormulaAndClausesArray* getFormulaAndClausesArray() const
00568   { return formAndClausesArray_; }
00569 
00570   
00571     // Caller should not modify the returned array or its contents
00572   const Array<Array<IndexClause*>*>* getPredIdToClausesMap() const
00573   { return predIdToClausesMap_; }
00574 
00575 
00576   const Array<IndexClause*>* getClausesContainingPred(const int& predId) const
00577   { 
00578     if (predId < predIdToClausesMap_->size())
00579       return (*predIdToClausesMap_)[predId];
00580     return NULL;
00581   }
00582 
00583 
00584   void compress()
00585   {
00586     clauses_->compress();
00587     for (int i = 0; i < clauseInfos_->size(); i++) 
00588       (*clauseInfos_)[i]->compress();
00589     clauseInfos_->compress();
00590     for (int i = 0; i < formAndClausesArray_->size(); i++)
00591       (*formAndClausesArray_)[i]->indexClauses->compress();
00592     formAndClausesArray_->compress();
00593     for (int i = 0; i < predIdToClausesMap_->size(); i++)
00594       if ((*predIdToClausesMap_)[i]) (*predIdToClausesMap_)[i]->compress();
00595     predIdToClausesMap_->compress();
00596   }
00597 
00598 
00599     //print formulas (commented out) followed by the clauses in its CNF
00600   void printMLN(ostream& out, const Domain* const & domain)
00601   {
00602     int outprec = 6;
00603     out.precision(outprec);
00604     out.setf(ios_base::left, ios_base::adjustfield);
00605 
00606     const FormulaAndClausesArray* fncArr = formAndClausesArray_;
00607     
00608     Array<int> fncArrIdxs;
00609     for (int i = 0; i < fncArr->size(); i++)
00610       if (!(*fncArr)[i]->hasExist && !(*fncArr)[i]->isExistUnique) 
00611         fncArrIdxs.append(i);
00612 
00613     for (int i = 0; i < fncArr->size(); i++)
00614       if ((*fncArr)[i]->isExistUnique) 
00615         fncArrIdxs.append(i);
00616     
00617     for (int i = 0; i < fncArr->size(); i++)
00618       if ((*fncArr)[i]->hasExist) 
00619         fncArrIdxs.append(i);
00620 
00621       // for each user-specified formula
00622     for (int ii = 0; ii < fncArrIdxs.size(); ii++)  
00623     {
00624       int i = fncArrIdxs[ii];
00625       double totalWt = 0;
00626       IndexClauseHashArray* indexClauses = (*fncArr)[i]->indexClauses;
00627       for (int j = 0; j < indexClauses->size(); j++)
00628       {
00629         Clause* c = (*indexClauses)[j]->clause;
00630         totalWt += c->getWt()/getNumParentFormulas(c);
00631       }
00632         // output the original formula and its weight
00633       out.width(0); out << "// "; out.width(outprec); 
00634       out << totalWt << "  " << (*fncArr)[i]->formula << endl;
00635       
00636       if ((*fncArr)[i]->hasExist || (*fncArr)[i]->isExistUnique)
00637         out << totalWt << "  " << (*fncArr)[i]->formula <<endl;
00638       else
00639       {
00640           //output clauses derived from the original formula and their weights
00641         for (int j = 0; j < indexClauses->size(); j++)
00642         {
00643           Clause* c = (*indexClauses)[j]->clause;    
00644           out.width(outprec); 
00645           out << c->getWt()/getNumParentFormulas(c) << "  "; 
00646           c->printWithoutWtWithStrVar(out, domain);
00647           out << endl;
00648         }
00649       }
00650       out << endl;
00651     }
00652   }
00653 
00654   
00655     //Print non-existential formulas (commented out) followed by the clauses in 
00656     //its CNF. Clause weights are divided among non-existential formulas.
00657   void printMLNNonExistFormulas(ostream& out, const Domain* const & domain)
00658   {
00659     int outprec = 6;
00660     out.precision(outprec);
00661     out.setf(ios_base::left, ios_base::adjustfield);
00662 
00663       // for each user-specified formula
00664     const FormulaAndClausesArray* fncArr = formAndClausesArray_;
00665     for (int i = 0; i < fncArr->size(); i++)
00666     {
00667       if ((*fncArr)[i]->hasExist || (*fncArr)[i]->isExistUnique) continue;
00668     
00669       double totalWt = 0;
00670       IndexClauseHashArray* indexClauses = (*fncArr)[i]->indexClauses;
00671       for (int j = 0; j < indexClauses->size(); j++)
00672       {
00673         Clause* c = (*indexClauses)[j]->clause;
00674         //assert(clauseOrdering->find(c) >= 0);
00675         totalWt 
00676           += c->getWt()/getNumNonExistNonExistUniqueParentFormulas(c);
00677       }
00678         // output the original formula and its weight
00679       out.width(0); out << "// "; out.width(outprec); 
00680       out << totalWt << "  " << (*fncArr)[i]->formula << endl;
00681       
00682 
00683         //output the clauses derived from the original formula and their weights
00684       for (int j = 0; j < indexClauses->size(); j++)
00685       {
00686         Clause* c = (*indexClauses)[j]->clause;    
00687         out.width(outprec); 
00688         out << c->getWt()/getNumNonExistNonExistUniqueParentFormulas(c)
00689             << "  "; 
00690         c->printWithoutWtWithStrVar(out, domain);
00691         out << endl;
00692       }
00693       out << endl;
00694     } 
00695   }
00696 
00697 
00698     //Print each non-existential clause as a single formula, followed by
00699     //existential formulas
00700   void printMLNClausesFormulas(ostream& out, const Domain* const & domain,
00701                                const bool& includeIdx)
00702   {
00703     int idx = 0;
00704     int* startIdx = (includeIdx) ? &idx : NULL;
00705     bool includeExistClauses = false;
00706     bool divideWtAmongExistFormulas = true;
00707     bool sortByLen = true;
00708     printClausesWithWeights(out, domain, startIdx, includeExistClauses,
00709                             sortByLen, divideWtAmongExistFormulas);
00710     printExistOrExistUniqueFormulasWithWeights(out, startIdx);
00711   }
00712 
00713 
00714     //If includeExistClauses is false, we exclude clauses that ONLY appear
00715     //in the CNFs of existential formulas.
00716   void printClausesWithWeights(ostream& out, const Domain* const & domain,
00717                                int* const & startIdx = NULL,
00718                                const bool& includeExistClauses=true,
00719                                const bool& sortByLen=false,
00720                                const bool& divWtAmongExistFormulas=false) const
00721   {
00722     Array<Clause*> ca;
00723     for (int i = 0; i < clauses_->size(); i++) 
00724     {
00725       if ( !includeExistClauses && 
00726            !clauseInNonExistAndNonExistUniqueFormulaCNF(i) ) continue;
00727       ca.append((*clauses_)[i]);
00728     }
00729 
00730     if (sortByLen) Clause::sortByLen(ca);
00731     ClauseHashArray cha;
00732     for (int i = 0; i < ca.size(); i++) cha.append(ca[i]);
00733 
00734     printClausesWithWeights(out, domain, &cha,startIdx,divWtAmongExistFormulas);
00735   }
00736 
00737   
00738   void printClausePriorMeans(ostream& out, const Domain* const & domain)
00739   {
00740     out.setf(ios_base::left, ios_base::adjustfield);    
00741     out.precision(6);
00742     assert(clauseInfos_->size() == clauses_->size());
00743     for (int i = 0; i < clauses_->size(); i++)
00744     {
00745       out << i << ":  "; out.width(14); 
00746       out << (*clauseInfos_)[i]->priorMean; out.width(0); out << " "; 
00747       (*clauses_)[i]->printWithoutWtWithStrVar(out, domain); 
00748       out << endl; 
00749     }
00750     out.width(0);
00751   }
00752 
00753   
00754   void printFormulaPriorMeans(ostream& out)
00755   {
00756     out.setf(ios_base::left, ios_base::adjustfield);
00757     out.precision(6);
00758     for (int i = 0; i < formAndClausesArray_->size(); i++)
00759     {
00760       FormulaAndClauses* fnc = (*formAndClausesArray_)[i];
00761       out << i << ":  "; out.width(14); 
00762       out << fnc->priorMean; out.width(0); 
00763       out << " " << fnc->formula << endl;       
00764     }
00765     out.width(0);
00766   }
00767 
00768 
00769  private:
00770   void appendClauseInfo(const Clause* const & clause, const int& clauseIdx, 
00771                         int* const& formulaIdx, int* const& clauseIdxForFormula)
00772   {
00773     assert(clauseInfos_->size() == clauseIdx);
00774 
00775     MLNClauseInfo* ci = new MLNClauseInfo(clauseInfos_->size());
00776     clauseInfos_->append(ci);
00777 
00778       // keep track of appended clause's positions in predIdToClausesMap_
00779     Array<PredIdClauseIndex*>& piciArr = ci->predIdsClauseIndexes;
00780     hash_set<int> seenPredIds;
00781     const Array<Predicate*>* preds = clause->getPredicates();
00782     for (int i = 0; i < preds->size(); i++)
00783     {
00784       int predId = (*preds)[i]->getId();
00785         //if we have already noted that clause contains pred
00786       if (seenPredIds.find(predId) != seenPredIds.end()) continue;
00787       seenPredIds.insert(predId);
00788       
00789       if (predId >= predIdToClausesMap_->size())
00790         predIdToClausesMap_->growToSize(predId+1, NULL);
00791       Array<IndexClause*>*& icArr = (*predIdToClausesMap_)[predId];
00792       if (icArr == NULL) icArr = new Array<IndexClause*>;
00793       IndexClause* ic = new IndexClause(icArr->size(), (Clause*)clause);
00794       icArr->append(ic);
00795       
00796       piciArr.append(new PredIdClauseIndex(predId, &(ic->index)));
00797     }
00798 
00799     updateClauseInfo(clauseIdx, formulaIdx, clauseIdxForFormula);
00800   }
00801 
00802   
00803   void updateClauseInfo(const int& clauseIdx, int* const & formulaIdx, 
00804                         int* const & clauseIdxForFormula)
00805   {
00806     MLNClauseInfo* clauseInfo = (*clauseInfos_)[clauseIdx];
00807       // keep track of appendedClause's position in formAndClauseArray_    
00808     assert(*clauseIdxForFormula >= 0);
00809     Array<FormulaClauseIndexes*>& fciArr = clauseInfo->formulaClauseIndexes;
00810 
00811     fciArr.append(new FormulaClauseIndexes(formulaIdx, clauseIdxForFormula));
00812   }
00813 
00814 
00815     //Returns -1 if c is not found in MLN
00816   int getNumParentFormulas(const Clause* const & c) const 
00817   {
00818     int i = findClauseIdx(c);
00819     if (i < 0) return -1;
00820     return (*clauseInfos_)[i]->formulaClauseIndexes.size();
00821   }
00822 
00823 
00824   int getNumNonExistNonExistUniqueParentFormulas(const Clause* const & c) const 
00825   {
00826     int i = findClauseIdx(c);
00827     if (i < 0) return -1;
00828     Array<FormulaClauseIndexes*>& fciArr 
00829       = (*clauseInfos_)[i]->formulaClauseIndexes;
00830     int n = 0;
00831     for (int i = 0; i < fciArr.size(); i++)
00832     {
00833       int fidx = *(fciArr[i]->formulaIndex);
00834       FormulaAndClauses* fnc = (*formAndClausesArray_)[fidx];
00835       if (!fnc->hasExist && !fnc->isExistUnique) n++;
00836     }
00837     return n;
00838   }
00839 
00840 
00841   int getNumExistOrExistUniqueParentFormulas(const Clause* const & c) const 
00842   {
00843     int i = findClauseIdx(c);
00844     if (i < 0) return -1;
00845     Array<FormulaClauseIndexes*>& fciArr 
00846       = (*clauseInfos_)[i]->formulaClauseIndexes;
00847     int n = 0;
00848     for (int i = 0; i < fciArr.size(); i++)
00849     {
00850       int fidx = *(fciArr[i]->formulaIndex);
00851       FormulaAndClauses* fnc = (*formAndClausesArray_)[fidx];
00852       if (fnc->hasExist || fnc->isExistUnique) n++;
00853     }
00854     return n;
00855   }
00856 
00857 
00858   void printClausesWithWeights(ostream& out, const Domain* const & domain,
00859                                const ClauseHashArray* const & clauses,
00860                                int* const & startIdx,
00861                                const bool& divideWithAmongExistFormulas) const
00862   {
00863     out.setf(ios_base::left, ios_base::adjustfield);
00864     int i;
00865     for (i = 0; i < clauses->size(); i++)
00866     {      
00867       if (startIdx) { out << (*(startIdx))++ << ":  "; out.width(14); }
00868       else          { out.width(10); }
00869       
00870       double wt = (*clauses)[i]->getWt();
00871       if (divideWithAmongExistFormulas) 
00872         wt /= 1+getNumExistOrExistUniqueParentFormulas((*clauses)[i]);
00873 
00874       out << wt; out.width(0); out << " ";
00875       (*clauses)[i]->printWithoutWtWithStrVar(out, domain); 
00876       out << endl; 
00877     }
00878     out.width(0);
00879   }
00880 
00881 
00882   void printExistOrExistUniqueFormulasWithWeights(ostream& out, 
00883                                                   int* const & startIdx=NULL)
00884   {
00885     int i;
00886     for (i = 0; i < formAndClausesArray_->size(); i++)
00887     {
00888       if (!(*formAndClausesArray_)[i]->hasExist && 
00889           !(*formAndClausesArray_)[i]->isExistUnique) continue;
00890       double totalWt = 0;
00891       IndexClauseHashArray* indexClauses 
00892         = (*formAndClausesArray_)[i]->indexClauses;
00893       for (int j = 0; j < indexClauses->size(); j++)
00894       {
00895         Clause* c = (*indexClauses)[j]->clause;
00896         totalWt += c->getWt()/getNumParentFormulas(c);
00897       }
00898       
00899       if (startIdx) { out << (*(startIdx))++ << ":  "; out.width(14); }
00900       else            { out.width(10); }
00901       out << totalWt; out.width(0); out << " " 
00902           << (*formAndClausesArray_)[i]->formula <<endl;
00903     }
00904   }
00905 
00906 
00907  private:
00908   ClauseHashArray* clauses_;
00909   Array<MLNClauseInfo*>* clauseInfos_;
00910   FormulaAndClausesArray* formAndClausesArray_;
00911 
00912     //predIdToClausesMap_[p] maps pred id p to an array of IndexClause.
00913     //The clause in each IndexClause contains a pred with id p, and the 
00914     //index is the index of the IndexClause in predIdToClausesMap_[p].
00915     //predIdToClausesMap_[p] may be NULL.
00916   Array<Array<IndexClause*>*>* predIdToClausesMap_;
00917 
00918 };
00919 
00920 #endif

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