clause.cpp

00001 /*
00002  * All of the documentation and software included in the
00003  * Alchemy Software is copyrighted by Stanley Kok, Parag
00004  * Singla, Matthew Richardson, Pedro Domingos, Marc
00005  * Sumner and Hoifung Poon.
00006  * 
00007  * Copyright [2004-07] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00009  * Poon. All rights reserved.
00010  * 
00011  * Contact: Pedro Domingos, University of Washington
00012  * (pedrod@cs.washington.edu).
00013  * 
00014  * Redistribution and use in source and binary forms, with
00015  * or without modification, are permitted provided that
00016  * the following conditions are met:
00017  * 
00018  * 1. Redistributions of source code must retain the above
00019  * copyright notice, this list of conditions and the
00020  * following disclaimer.
00021  * 
00022  * 2. Redistributions in binary form must reproduce the
00023  * above copyright notice, this list of conditions and the
00024  * following disclaimer in the documentation and/or other
00025  * materials provided with the distribution.
00026  * 
00027  * 3. All advertising materials mentioning features or use
00028  * of this software must display the following
00029  * acknowledgment: "This product includes software
00030  * developed by Stanley Kok, Parag Singla, Matthew
00031  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00032  * Poon in the Department of Computer Science and
00033  * Engineering at the University of Washington".
00034  * 
00035  * 4. Your publications acknowledge the use or
00036  * contribution made by the Software to your research
00037  * using the following citation(s): 
00038  * Stanley Kok, Parag Singla, Matthew Richardson and
00039  * Pedro Domingos (2005). "The Alchemy System for
00040  * Statistical Relational AI", Technical Report,
00041  * Department of Computer Science and Engineering,
00042  * University of Washington, Seattle, WA.
00043  * http://www.cs.washington.edu/ai/alchemy.
00044  * 
00045  * 5. Neither the name of the University of Washington nor
00046  * the names of its contributors may be used to endorse or
00047  * promote products derived from this software without
00048  * specific prior written permission.
00049  * 
00050  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
00051  * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00052  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00053  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00054  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
00055  * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00056  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00057  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00058  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00059  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00060  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00061  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00062  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00063  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00064  * 
00065  */
00066 #include "clause.h"
00067 #include "mrf.h"
00068 
00069 
00070 ClauseSampler* Clause::clauseSampler_ = NULL;
00071 double Clause::fixedSizeB_ = -1;
00072 double AuxClauseData::fixedSizeB_ = -1;
00073 
00074 
00075   //returns true if the (ground) clause has two literals with opposite sense
00076   //i.e. the clause is satisfied; otherwise returns false
00077 bool Clause::createAndAddUnknownClause(
00078                                 Array<GroundClause*>* const& unknownGndClauses,
00079                                 Array<Clause*>* const& unknownClauses,
00080                                 double* const & numUnknownClauses,
00081                                 const AddGroundClauseStruct* const & agcs)
00082 { 
00083   PredicateSet predSet; // used to detect duplicates
00084   PredicateSet::iterator iter;
00085   
00086   Clause* clause = NULL;
00087   for (int i = 0; i < predicates_->size(); i++)
00088   {
00089         Predicate* predicate = (*predicates_)[i];
00090     assert(predicate->isGrounded());
00091 //cout << "Pred: ";
00092 //cout << " " << predicate->getTruthValueAsStr();
00093 //cout << endl;
00094     if (predicate->getTruthValue() == UNKNOWN)
00095     {
00096       if ( (iter=predSet.find(predicate)) != predSet.end() )
00097       {
00098           // the two gnd preds are of opp sense, so clause must be satisfied
00099         if ((*iter)->getSense() !=  predicate->getSense())
00100         {
00101           if (clause) delete clause;
00102           return true;
00103         }
00104         // since the two gnd preds are identical, no point adding a dup
00105         continue;
00106       }
00107       else
00108         predSet.insert(predicate);
00109       
00110       if (clause == NULL) clause = new Clause();
00111       Predicate* pred = new Predicate(*predicate, clause);
00112       clause->appendPredicate(pred);
00113     }
00114   }
00115   
00116   if (clause) 
00117   {
00118     if (numUnknownClauses) (*numUnknownClauses)++;
00119 
00120     clause->setWt(wt_);
00121     clause->canonicalizeWithoutVariables();
00122     
00123     if (agcs) MRF::addUnknownGndClause(agcs, this, clause, isHardClause_);
00124     
00125     // MARC: The case with unknownGndClauses appears to be obsolete!
00126         if (unknownGndClauses)
00127     {
00128       unknownGndClauses->append(new GroundClause(clause, agcs->gndPreds));
00129           if (isHardClause_) unknownGndClauses->lastItem()->setWtToHardWt();
00130     }
00131     else
00132     if (unknownClauses)
00133     {
00134       unknownClauses->append(clause);
00135       if (isHardClause_) clause->setIsHardClause(true);
00136     }
00137     if (unknownClauses == NULL) delete clause;
00138   }
00139   return false;
00140 }
00141 
00142 void addPredicateToHash(const Clause* const & c,
00143                         PredicateHashArray* const & predHashArray)
00144 {
00145   int numPreds = c->getNumPredicates();
00146   // for each predicate in clause c
00147   for (int i = 0; i < numPreds; i++)
00148   {
00149     Predicate* pred = new Predicate(*(c->getPredicate(i)));
00150         int index = predHashArray->find(pred);
00151         if(index < 0 )
00152         {
00153           index = predHashArray->append(pred) + 1;
00154         }
00155         else
00156         {
00157           delete pred;
00158           index++;
00159         }
00160   }      
00161 }
00162 
00163 
00175 bool Clause::createAndAddActiveClause(
00176                            Array<GroundClause *> * const & activeGroundClauses,
00177                            GroundPredicateHashArray* const& seenGndPreds,
00178                                    const Database* const & db,
00179                            bool const & getSatisfied)
00180 {
00181   bool accumulateClauses = activeGroundClauses;
00182   Predicate *cpred;
00183   PredicateSet predSet; // used to detect duplicates
00184   PredicateSet::iterator iter;
00185  
00186   GroundClause *groundClause;
00187   
00188   Clause* clause = NULL;
00189   bool isEmpty = true;
00190   for (int i = 0; i < predicates_->size(); i++)
00191   {
00192     Predicate* predicate = (*predicates_)[i];
00193     assert(predicate); 
00194         assert(predicate->isGrounded());
00195     if ( (iter = predSet.find(predicate)) != predSet.end() )
00196     {
00197         // The two gnd preds are of opp sense, so clause must be satisfied
00198         // and no point in adding it 
00199           if (wt_ >= 0 && !getSatisfied &&
00200           (*iter)->getSense() !=  predicate->getSense())
00201       {
00202         if (clause) delete clause;
00203                 return false;
00204       }
00205 
00206         // Since the two gnd preds are identical, no point adding a dup
00207       continue;
00208         }
00209     else
00210       predSet.insert(predicate);
00211       
00212         bool isEvidence = db->getEvidenceStatus(predicate);
00213 //cout << "isEvidence " << isEvidence << endl;
00214 //predicate->printWithStrVar(cout, db->getDomain());
00215 //cout << endl;
00216         if (!isEvidence)
00217       isEmpty = false;
00218           
00219       // True evidence in a neg. clause: Discard clause
00220     if (wt_ < 0 && isEvidence && !getSatisfied &&
00221         db->sameTruthValueAndSense(db->getValue(predicate),
00222                                    predicate->getSense()))
00223     {
00224       if (clause) delete clause;
00225       return false;
00226     }
00227     
00228           // Add only non-evidence prdicates
00229         if (accumulateClauses && !isEvidence)
00230         {
00231           if (!clause) clause = new Clause();
00232         
00233           cpred = new Predicate(*predicate, clause);
00234       assert(cpred);
00235           clause->appendPredicate(cpred);
00236         }
00237   }
00238 
00239     // If the clause is empty after taking evidence into account, it should 
00240     // be discarded
00241   if (isEmpty)
00242   {
00243         assert(!clause);
00244     return false;
00245   }
00246     // Came to this point means that the clause is active (and hence nonEmpty)
00247   else
00248   {
00249           // Add the corresponding ground clause if accumulateClauses is true
00250         if (accumulateClauses)
00251         {
00252       assert(clause);   
00253       clause->canonicalizeWithoutVariables();
00254       
00255       groundClause = new GroundClause(clause, seenGndPreds);
00256       if (isHardClause_)
00257         groundClause->setWtToHardWt();
00258       activeGroundClauses->append(groundClause);
00259       delete clause;
00260     }
00261     return true;
00262   } 
00263 }
00264 
00265 

Generated on Wed Feb 14 15:15:18 2007 for Alchemy by  doxygen 1.5.1