indextranslator.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 INDEXTRANSLATOR_H_NOV_29_2005
00068 #define INDEXTRANSLATOR_H_NOV_29_2005
00069 
00070 
00071 #include "mln.h"
00072 
00073 //NOTE: "domain index" and "database index" are used interchangeably
00074 
00075 struct IdxDiv { int idx; double div; };
00076 
00077 
00078 class IndexTranslator
00079 {
00080  public:
00081   IndexTranslator(const Array<MLN*>* const & mlns, 
00082                   const Array<Domain*>* const & domains) 
00083     : mlns_(mlns), domains_(domains), cIdxToCFIdxsPerDomain_(NULL), 
00084       wtsPerDomain_(NULL), gradsPerDomain_(NULL),
00085       clauseOrdering_(NULL), existFormulaOrdering_(NULL) 
00086   { createClauseIdxToClauseFormulaIdxsMap(); }
00087 
00088 
00089   ~IndexTranslator() 
00090   {
00091     if (cIdxToCFIdxsPerDomain_) 
00092     {
00093       for (int i = 0; i < cIdxToCFIdxsPerDomain_->size(); i++)
00094         (*cIdxToCFIdxsPerDomain_)[i].deleteItemsAndClear();
00095       delete cIdxToCFIdxsPerDomain_;
00096     }
00097     if (wtsPerDomain_) delete wtsPerDomain_;
00098     if (gradsPerDomain_) delete gradsPerDomain_;
00099     if (clauseOrdering_) 
00100     { clauseOrdering_->deleteItemsAndClear(); delete clauseOrdering_; }
00101     if (existFormulaOrdering_) delete existFormulaOrdering_;
00102   }    
00103 
00104 
00105     //Returns true if there are multiple databases, and there are formulas
00106     //whose CNF contains a different number of clauses for each database;
00107     //otherwise returns false. 
00108     //ASSUMPTION: the MLNs were formed from parsing the same .mln file
00109   static bool needIndexTranslator(const Array<MLN*>& mlns,
00110                                   const Array<Domain*>& domains)
00111   {
00112     if (mlns.size() <= 1) return false;
00113 
00114     for (int i = 1; i < mlns.size(); i++)
00115       if (mlns[0]->getNumClauses() != mlns[i]->getNumClauses()) return true;
00116 
00117     //there are more than one MLN and all MLNs have the same number of clauses
00118     //now check whether all tie-able formulas have one clause in their CNF
00119 
00120     bool allTiedFormulasHaveOneClause = true;
00121     for (int i = 0; i < mlns.size(); i++)
00122     {
00123       const FormulaAndClausesArray* fnca = mlns[i]->getFormulaAndClausesArray();
00124       for (int j = 0; j < fnca->size(); j++)
00125       {
00126         if (formulaWtTiedToClauseWts((*fnca)[j]) && 
00127             (*fnca)[j]->indexClauses->size() > 1)
00128         { 
00129           allTiedFormulasHaveOneClause = false;
00130           break;
00131         }
00132       }
00133       if (!allTiedFormulasHaveOneClause) break;
00134     }
00135 
00136     if (allTiedFormulasHaveOneClause) return false;
00137 
00138     //all MLNs have the same number of clauses, and a tie-able formula
00139     //has more than one clause
00140     
00141     //now check that the tie-able clauses are exactly the same across databases
00142 
00143     for (int i = 0; i < mlns[0]->getNumClauses(); i++)
00144     {
00145         //if this is a clause whose wt can be tied to the formula wt
00146       if (tieClauseWtToFormulaWt(mlns[0], i))
00147       {
00148         ostringstream oss0;
00149         mlns[0]->getClause(i)->printWithoutWtWithStrVar(oss0, domains[0]);
00150         for (int j = 1; j < mlns.size(); j++)
00151         {
00152           ostringstream ossj;
00153           mlns[j]->getClause(i)->printWithoutWtWithStrVar(ossj, domains[j]);
00154           if (oss0.str().compare(ossj.str()) != 0) return true;          
00155         }
00156       }
00157     }
00158     
00159     return false;
00160   }
00161 
00162 
00163   const Array<Array<Array<IdxDiv>*> >* 
00164   getClauseIdxToClauseFormulaIdxsPerDomain() const 
00165   { return cIdxToCFIdxsPerDomain_; }
00166 
00167   Array<Array<double> >* getWtsPerDomain() const { return wtsPerDomain_; }
00168 
00169   Array<Array<double> >* getGradsPerDomain() const { return gradsPerDomain_; }
00170 
00171   const ClauseHashArray* getClauseOrdering() const { return clauseOrdering_; }
00172 
00173   const StringHashArray* getExistFormulaOrdering() const 
00174   { return existFormulaOrdering_; }
00175 
00176   int getNumClausesAndExistFormulas() const 
00177   { return clauseOrdering_->size() + existFormulaOrdering_->size(); }
00178 
00179   
00180     //check that the sizes of cIdxToCFIdxsPerDomain_[d], wtsPerDomain_[d], and
00181     //gradsPerDomain_[d] is equal to the num of clauses in mln_[d] + numAdded
00182   bool checkCIdxWtsGradsSize(const int& numAdded)
00183   {
00184     for (int i = 0; i < mlns_->size(); i++) // for each domain
00185     {
00186       int sz = (*mlns_)[i]->getNumClauses() + numAdded;
00187       if ((*cIdxToCFIdxsPerDomain_)[i].size() != sz) return false;
00188       if ((*wtsPerDomain_)[i].size() != sz) return false;
00189       if ((*gradsPerDomain_)[i].size() != sz) return false;
00190     }
00191     return true;
00192   }
00193 
00194 
00195     //Size of wts must be sum of the sizes of clauseOrdering_, 
00196     //existFormulaOrdering_, appendedClauses, and appendedFormulas.
00197   void updateClauseFormulaWtsInMLNs(const Array<double>& wts,
00198                                     const Array<Clause*>*const& appendedClauses,
00199                                     const Array<string>*const& appendedFormulas)
00200   {
00201     assert(appendedClauses == NULL || appendedFormulas == NULL);
00202     Domain* dom0 = (*domains_)[0];
00203     for (int i = 0; i < mlns_->size(); i++) // for each domain
00204     {
00205       MLN* mln = (*mlns_)[i];
00206       Domain* dom = (*domains_)[i];
00207 
00208       for (int j = 0; j < clauseOrdering_->size(); j++)
00209       {
00210         Clause* c = (*clauseOrdering_)[j];
00211         if (i > 0 && c->containsConstants()) c->translateConstants(dom0, dom);
00212         Clause* cc = (Clause*) mln->findClause(c);
00213         if (i > 0 && c->containsConstants()) c->translateConstants(dom, dom0);
00214         cc->setWt(wts[j]);
00215       }
00216 
00217       int offset = clauseOrdering_->size();
00218 
00219       for (int j = 0; j < existFormulaOrdering_->size(); j++)
00220         mln->setFormulaWt((*existFormulaOrdering_)[j], wts[offset+j]);
00221 
00222       offset += existFormulaOrdering_->size();
00223 
00224       if (appendedClauses)
00225       {
00226         for (int j = 0; j < appendedClauses->size(); j++)
00227         {
00228           Clause* c = (*appendedClauses)[j];
00229           if (i > 0 && c->containsConstants()) c->translateConstants(dom0, dom);
00230           Clause* cc = (Clause*) mln->findClause(c);
00231           if (i > 0 && c->containsConstants()) c->translateConstants(dom, dom0);
00232           cc->setWt(wts[offset+j]);
00233         }
00234       }
00235       else
00236       if (appendedFormulas)
00237       {
00238         for (int j = 0; j < appendedFormulas->size(); j++)
00239           mln->setFormulaWt((*appendedFormulas)[j], wts[offset+j]);
00240       }       
00241     }
00242   }
00243 
00244 
00245   void getClauseFormulaWts(Array<double>& wts) const
00246   {
00247     wts.clear();
00248     wts.growToSize(clauseOrdering_->size() + existFormulaOrdering_->size());
00249     int a = 0;
00250     for (int j = 0; j < clauseOrdering_->size(); j++)
00251       wts[a++] = (*mlns_)[0]->findClause((*clauseOrdering_)[j])->getWt();
00252 
00253     for (int j = 0; j < existFormulaOrdering_->size(); j++)
00254       wts[a++] = (*mlns_)[0]->getFormulaWt((*existFormulaOrdering_)[j]);    
00255   }
00256 
00257 
00258     //There must be more than one MLN in mlns. The size of mlns_ must be the 
00259     //same as the size of domains_.
00260   void createClauseIdxToClauseFormulaIdxsMap()
00261   {
00262     assert(mlns_->size() == domains_->size());
00263     if (mlns_->size() <= 1) return;
00264     if (cIdxToCFIdxsPerDomain_) 
00265     {
00266       for (int i = 0; i < cIdxToCFIdxsPerDomain_->size(); i++)
00267         (*cIdxToCFIdxsPerDomain_)[i].deleteItemsAndClear();
00268       delete cIdxToCFIdxsPerDomain_;
00269     }
00270     if (wtsPerDomain_) delete wtsPerDomain_;
00271     if (gradsPerDomain_) delete gradsPerDomain_;
00272     if (clauseOrdering_)     
00273     { clauseOrdering_->deleteItemsAndClear(); delete clauseOrdering_; }
00274     if (existFormulaOrdering_) delete existFormulaOrdering_;
00275 
00276     trackClauseConstants();
00277     clauseOrdering_ = new ClauseHashArray;
00278     existFormulaOrdering_ = new StringHashArray;
00279     createClausesFormulasOrdering((*mlns_)[0], clauseOrdering_, 
00280                                   existFormulaOrdering_);
00281 
00282     cIdxToCFIdxsPerDomain_ = new Array<Array<Array<IdxDiv>*> >;
00283     wtsPerDomain_ = new Array<Array<double> >;
00284     gradsPerDomain_ = new Array<Array<double> >;
00285     cIdxToCFIdxsPerDomain_->growToSize(mlns_->size());
00286     wtsPerDomain_->growToSize(mlns_->size());
00287     gradsPerDomain_->growToSize(mlns_->size());
00288 
00289     Domain* dom0 = (*domains_)[0];
00290     for (int i = 0; i < mlns_->size(); i++) // for each domain
00291     {
00292       MLN* mln = (*mlns_)[i];
00293       Domain* dom = (*domains_)[i];
00294       const FormulaAndClausesArray* fnca = mln->getFormulaAndClausesArray();
00295       Array<Array<IdxDiv>*>& cIdxToCFIdxsMap = (*cIdxToCFIdxsPerDomain_)[i];
00296       cIdxToCFIdxsMap.growToSize(mln->getNumClauses());
00297       (*wtsPerDomain_)[i].growToSize(mln->getNumClauses());
00298       (*gradsPerDomain_)[i].growToSize(mln->getNumClauses());
00299 
00300       for (int j = 0; j < mln->getNumClauses(); j++) // for each clause in MLN
00301       {
00302         Array<IdxDiv>* cfIdxs = new Array<IdxDiv>;
00303         cIdxToCFIdxsMap[j] = cfIdxs;
00304 
00305           //if we don't need to tie the clause weight to formula weight as when
00306           //this clause is in the CNF of a non-existentially quant. and
00307           //non-existentially and uniquely quant. formula.
00308         if (noTieClauseWtToFormulaWt(mln,j))
00309         {
00310           Clause* c = (Clause*) mln->getClause(j);
00311           if (i > 0 && c->containsConstants()) c->translateConstants(dom, dom0);
00312           int idx = clauseOrdering_->find(c);
00313           cfIdxs->append(IdxDiv());
00314           cfIdxs->lastItem().idx = idx;
00315           cfIdxs->lastItem().div = 1;
00316           if (i > 0 && c->containsConstants()) c->translateConstants(dom0, dom);
00317           if (idx < 0) 
00318           { 
00319             cout <<"ERROR: in IndexTranslator::"
00320                  << "createClauseIdxToClauseFormulaIdxsMap(): clause ";
00321             c->printWithoutWtWithStrVar(cout, dom); cout << "not found!"<<endl;
00322             exit(-1);
00323           }
00324         }
00325 
00326           //if we must tie the clause weight to formula weight as when
00327           //the clause is in the CNF of an existentially quantified formula,
00328           //or an existentially and uniquely quantified formula,
00329         if (tieClauseWtToFormulaWt(mln, j))
00330         {
00331           const Array<FormulaClauseIndexes*>& fciArr 
00332             = mln->getMLNClauseInfo(j)->formulaClauseIndexes;
00333 
00334           for (int k = 0; k < fciArr.size(); k++)
00335           {
00336             int fidx = *(fciArr[k]->formulaIndex);
00337             if (!formulaWtTiedToClauseWts((*fnca)[fidx])) continue;
00338             string formula = (*fnca)[fidx]->formula;
00339             int numClauses = (*fnca)[fidx]->indexClauses->size();
00340             int idx = existFormulaOrdering_->find(formula);
00341             cfIdxs->append(IdxDiv());
00342                 //exist. quant. formulas comes after 'normal' clauses
00343             cfIdxs->lastItem().idx = idx + clauseOrdering_->size();
00344 
00345             if (mln->isExistClause(j))
00346               cfIdxs->lastItem().div = numClauses;
00347             else
00348             if (mln->isExistUniqueClause(j))
00349             {
00350                 //this clause states that there is at least one true value
00351               Clause* firstClause 
00352                 = (*((*fnca)[fidx]->indexClauses))[0]->clause;
00353               int numPreds = firstClause->getNumPredicates();
00354               Clause* c = (Clause*) mln->getClause(j);
00355               if (c->same(firstClause))
00356                 cfIdxs->lastItem().div = (numPreds > 1) ? numPreds+1 : 1;
00357               else
00358                 cfIdxs->lastItem().div = (numPreds*numPreds-1)*0.5;
00359             }
00360             else
00361               assert(false);
00362 
00363 
00364             if (idx < 0)
00365             { 
00366               cout << "ERROR: in createClauseIdxToClauseFormulaIdxsMap(): "
00367                    << "formula " << formula << "not found!" << endl;
00368               exit(-1);
00369             }
00370           }
00371         }
00372 
00373         cfIdxs->compress();
00374 
00375       } // for each clause in MLN
00376     } // for each DB
00377   }
00378 
00379 
00380   void appendClauseIdxToClauseFormulaIdxs(const int& numCFIdxs,
00381                                           const int& numCIdxsPerCFIdx,
00382                                           const int& domainIdx)
00383   {
00384     if (numCFIdxs == 0) return;
00385     Array<Array<IdxDiv>*>& cidxs = (*cIdxToCFIdxsPerDomain_)[domainIdx];
00386     Array<double>& wts = (*wtsPerDomain_)[domainIdx];
00387     Array<double>& grads = (*gradsPerDomain_)[domainIdx];
00388     int numClausesFormulas = getNumClausesAndExistFormulas();
00389     
00390     for (int j = 0; j < numCFIdxs; j++)
00391     {
00392       int cfidx = numClausesFormulas + j;
00393       for (int k = 0; k < numCIdxsPerCFIdx; k++)
00394       {
00395         IdxDiv idiv;
00396         idiv.idx = cfidx;
00397         idiv.div = 1;
00398         Array<IdxDiv>* arr = new Array<IdxDiv>(1);
00399         arr->append(idiv);
00400         cidxs.append(arr);
00401         
00402         wts.append(0.0);
00403         grads.append(0.0);          
00404       }
00405     }
00406   }
00407 
00408   
00409   void appendClauseIdxToClauseFormulaIdxs(const int& numCFIdxs,
00410                                           const int& numCIdxsPerCFIdx)
00411   {
00412     if (numCFIdxs == 0) return;
00413     for (int i = 0; i < cIdxToCFIdxsPerDomain_->size(); i++)
00414       appendClauseIdxToClauseFormulaIdxs(numCFIdxs, numCIdxsPerCFIdx, i);
00415   }
00416 
00417 
00418   void removeClauseIdxToClauseFormulaIdxs(const int& numCFIdxs,
00419                                           const int& numCIdxsPerCFIdx,
00420                                           const int& domainIdx)
00421   {
00422     if (numCFIdxs == 0) return;
00423     Array<Array<IdxDiv>*>& cidxs = (*cIdxToCFIdxsPerDomain_)[domainIdx];
00424     Array<double>& wts = (*wtsPerDomain_)[domainIdx];
00425     Array<double>& grads = (*gradsPerDomain_)[domainIdx];
00426     
00427     for (int j = 0; j < numCFIdxs; j++)
00428       for (int k = 0; k < numCIdxsPerCFIdx; k++)
00429       {
00430         delete cidxs.removeLastItem();
00431         wts.removeLastItem();
00432         grads.removeLastItem();          
00433       }    
00434   }
00435 
00436 
00437   void removeClauseIdxToClauseFormulaIdxs(const int& numCFIdxs,
00438                                           const int& numCIdxsPerCFIdx)
00439   {
00440     if (numCFIdxs == 0) return;
00441     for (int i = 0; i < cIdxToCFIdxsPerDomain_->size(); i++)
00442       removeClauseIdxToClauseFormulaIdxs(numCFIdxs, numCIdxsPerCFIdx, i);
00443   }
00444 
00445 
00446   void setPriorMeans(Array<double>& priorMeans)
00447   {
00448     priorMeans.clear();
00449     priorMeans.growToSize(clauseOrdering_->size() + 
00450                           existFormulaOrdering_->size());
00451     int m = 0;
00452     MLN* mln0 = (*mlns_)[0];
00453 
00454     for (int i = 0; i < clauseOrdering_->size(); i++)
00455     {
00456       Clause* c = (*clauseOrdering_)[i]; 
00457       int cidx = mln0->findClauseIdx(c);      
00458       priorMeans[m++] = mln0->getMLNClauseInfo(cidx)->priorMean;
00459     }
00460     
00461     const FormulaAndClausesArray* fnca = mln0->getFormulaAndClausesArray();
00462     for (int i = 0; i < existFormulaOrdering_->size(); i++)
00463     {
00464       FormulaAndClauses tmp((*existFormulaOrdering_)[i], 0, false, false);
00465       int a = fnca->find(&tmp);
00466       assert(a >= 0);
00467       priorMeans[m++] = (*fnca)[a]->priorMean;
00468     }
00469   }
00470 
00471 
00472     //Maps each clause index in the array to the clause/formula index, and
00473     //replaces the former with the latter.
00474   void getClauseFormulaIndexes(Array<int>& clauseIndexes, const int& domainIdx)
00475   {
00476     for (int i = 0; i < clauseIndexes.size(); i++)
00477     {
00478       int cidx = clauseIndexes[i];
00479       Array<IdxDiv>* idxDivs = (*cIdxToCFIdxsPerDomain_)[domainIdx][cidx];
00480       for (int j = 0; j < idxDivs->size(); j++)
00481         if ((*idxDivs)[j].idx < clauseOrdering_->size())
00482         {
00483             //only get the index of clauses (and not those of exist.
00484             //quant. formulas)
00485           assert((*idxDivs)[j].div == 1);
00486           clauseIndexes[i] = (*idxDivs)[j].idx;
00487         }
00488     }
00489   }
00490 
00491 
00492     //assign the weights belonging to clauses (and none of those belonging to
00493     //existentially/exitentially and uniquely  quantified formulas) to the MLNs
00494   void assignNonTiedClauseWtsToMLNs(const double* const & wts)
00495   {
00496     for (int i = 0; i < mlns_->size(); i++)
00497     {
00498       MLN* mln = (*mlns_)[i];
00499       for (int j = 0; j < mln->getNumClauses(); j++)
00500       {
00501         if (!noTieClauseWtToFormulaWt(mln,j)) continue;
00502 
00503         Clause* c = ((Clause*) mln->getClause(j));
00504         assert(inClauseOrdering(c, i));
00505         Array<IdxDiv>* idxDivs =(*cIdxToCFIdxsPerDomain_)[i][j];
00506         double wt = 0;
00507         for (int k = 0; k < idxDivs->size(); k++)
00508         {
00509             //don't assign the weights of existential formulas to clauses
00510           if ((*idxDivs)[k].idx < clauseOrdering_->size())
00511             wt += wts[ (*idxDivs)[k].idx ] / (*idxDivs)[k].div;
00512         }
00513         c->setWt(wt);
00514       }
00515     }
00516   }
00517 
00518   
00519   void printClauseFormulaWts(ostream& out, const bool& includeIdx)
00520   {
00521     Array<double> wts;
00522     getClauseFormulaWts(wts);
00523       //print those clauses that appear in a non-exist. quant. formula
00524     Array<Clause*> tmp;
00525     for (int i = 0; i < clauseOrdering_->size(); i++) 
00526     {
00527       (*clauseOrdering_)[i]->setWt(wts[i]);
00528       tmp.append((*clauseOrdering_)[i]);
00529     }
00530     Clause::sortByLen(tmp);
00531       
00532     out.setf(ios_base::left, ios_base::adjustfield);
00533     for (int i = 0; i < tmp.size(); i++)
00534     {
00535       if (includeIdx) { out << i << ":  "; out.width(14); }
00536       else            { out.width(10); }
00537       out << tmp[i]->getWt(); out.width(0); out << " ";
00538       tmp[i]->printWithoutWtWithStrVar(out, (*domains_)[0]); out << endl; 
00539     }
00540     out.width(0);
00541 
00542     for (int i = 0; i < existFormulaOrdering_->size(); i++)
00543     {
00544       int idx = i+clauseOrdering_->size();
00545       if (includeIdx) { out << idx <<":  ";out.width(14);}
00546       else            { out.width(10); }
00547       out << wts[idx]; out.width(0); 
00548       out << " " << (*existFormulaOrdering_)[i] << endl;      
00549     }
00550     out.width(0);
00551   }
00552 
00553 
00554     //used by VotedPerceptron
00555   void setRelevantClausesFormulas(Array<bool>& relevantClausesFormulas,
00556                                   const Array<bool>& relevantClausesInMLN0)
00557   {
00558     const Array<bool>& relevantClauses = relevantClausesInMLN0;
00559 
00560     if (relevantClausesFormulas.size() < relevantClauses.size())
00561       relevantClausesFormulas.growToSize(relevantClauses.size());
00562     else
00563     if (relevantClausesFormulas.size() > relevantClauses.size())
00564       relevantClausesFormulas.shrinkToSize(relevantClauses.size());
00565       
00566     for (int i = 0; i < relevantClausesFormulas.size(); i++)
00567       relevantClausesFormulas[i] = false;
00568 
00569      
00570     for (int i = 0; i < clauseOrdering_->size(); i++)
00571     {
00572       int cidx = (*mlns_)[0]->findClauseIdx((*clauseOrdering_)[i]);
00573       relevantClausesFormulas[i] = relevantClauses[cidx];
00574     }
00575 
00576     int offset = clauseOrdering_->size();      
00577       
00578     for (int i = 0; i < existFormulaOrdering_->size(); i++)
00579     {
00580       const IndexClauseHashArray* icha 
00581         = (*mlns_)[0]->getClausesOfFormula((*existFormulaOrdering_)[i]);
00582       for (int j = 0; j < icha->size(); j++)
00583       {
00584         int cidx = (*mlns_)[0]->findClauseIdx((*icha)[j]->clause);
00585         relevantClausesFormulas[offset+i] = relevantClauses[cidx];
00586         if (relevantClausesFormulas[offset+i]) break;
00587       }
00588     }
00589   }
00590 
00591 
00592   void printRelevantClausesFormulas(ostream& out,
00593                                     const Array<bool>& relevantClausesFormulas)
00594   {
00595     for (int i = 0; i < clauseOrdering_->size(); i++)
00596     {
00597       if (relevantClausesFormulas[i])
00598       {
00599         out << i << ": ";
00600         (*clauseOrdering_)[i]->printWithoutWtWithStrVar(out, (*domains_)[0]);
00601         out << endl;
00602       }
00603     }
00604     
00605     int offset = clauseOrdering_->size();
00606 
00607     for (int i = 0; i < existFormulaOrdering_->size(); i++)
00608     {
00609       if (relevantClausesFormulas[offset+i])
00610         out << offset+i << ": " << (*existFormulaOrdering_)[i] << endl;
00611     }
00612   }
00613 
00614 
00615  private:
00616   void trackClauseConstants()
00617   {
00618     for (int i = 0; i < mlns_->size(); i++)
00619       for (int j = 0; j < (*mlns_)[i]->getNumClauses(); j++)
00620         if (noTieClauseWtToFormulaWt((*mlns_)[i], j))
00621         {
00622           Clause* c = (Clause*) (*mlns_)[i]->getClause(j);
00623           if (c->getAuxClauseData() == NULL) c->newAuxClauseData();
00624           c->trackConstants();
00625         }
00626   }
00627 
00628 
00629   void createClausesFormulasOrdering(MLN* const & mln, 
00630                                      ClauseHashArray* const & clauses,
00631                                      StringHashArray* const & existFormulas)
00632   {
00633     for (int i = 0; i < mln->getNumClauses(); i++)
00634       if (noTieClauseWtToFormulaWt(mln,i))
00635       { 
00636         Clause* c = new Clause( *((Clause*)mln->getClause(i)) );
00637         clauses->append(c);
00638       }
00639 
00640     const FormulaAndClausesArray* fnca = mln->getFormulaAndClausesArray();
00641     for (int i = 0; i < fnca->size(); i++)
00642       if (formulaWtTiedToClauseWts((*fnca)[i])) 
00643         existFormulas->append((*fnca)[i]->formula);
00644   }
00645 
00646 
00647   bool inClauseOrdering(Clause* const & c, const int& domainIdx)
00648   {
00649     assert(c->getAuxClauseData());
00650     if (domainIdx > 0 && c->containsConstants()) 
00651       c->translateConstants((*domains_)[domainIdx], (*domains_)[0]);
00652     bool in = (clauseOrdering_->find(c) >= 0);
00653     if (domainIdx > 0 && c->containsConstants()) 
00654       c->translateConstants((*domains_)[0], (*domains_)[domainIdx]);
00655     return in;
00656   }
00657   
00658 
00659     //Returns true if the clause weights must be tied to the formulas (as when
00660     //the clause belongs to the CNF of an existentially quantified or 
00661     //existentially and uniquely quantified formula
00662     //i is the clause's index in mln
00663   static bool tieClauseWtToFormulaWt(const MLN* const & mln, const int& i)
00664   { return (mln->isExistClause(i) || mln->isExistUniqueClause(i)); }
00665 
00666 
00667   static bool formulaWtTiedToClauseWts(const FormulaAndClauses* const & fnc)
00668   { return (fnc->hasExist || fnc->isExistUnique); }
00669 
00670 
00671     //Returns true if the clause weights need not be tied to the formulas 
00672     //(as when the clause belongs to the CNF of a non-existentially quantified 
00673     //and non-existentially and uniquely quantified formula
00674     //i is the clause's index in mln
00675   bool noTieClauseWtToFormulaWt(const MLN* const & mln, const int& i)
00676   { return mln->clauseInNonExistAndNonExistUniqueFormulaCNF(i); }
00677 
00678  private:
00679   const Array<MLN*>* mlns_; // not owned by this object; do not delete;
00680   const Array<Domain*>* domains_; // not owned by this object; do not delete;
00681 
00682     //cIdxToCFIdxsPerDomain_[d] maps clause indexes (cIdx) in an MLN to 
00683     //clause/formula indexes (CFIdxs) for domain d.
00684     //Used when the clauses across multiple domains do not line up perfectly
00685     //as when an existential formula has a different number of CNF clauses for
00686     //different domains. Used in PseudoLogLikelihood.
00687   Array<Array<Array<IdxDiv>*> >* cIdxToCFIdxsPerDomain_;
00688   Array<Array<double> >* wtsPerDomain_; //Used in PseudoLogLikelihood
00689   Array<Array<double> >* gradsPerDomain_; //Used in PseudoLogLikelihood
00690 
00691   ClauseHashArray* clauseOrdering_; 
00692   StringHashArray* existFormulaOrdering_;
00693 };
00694 
00695 
00696 #endif

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