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 
00181 bool Clause::createAndAddActiveClause(
00182                            Array<IntClause *> * const & activeIntClauses,
00183                            Array<GroundClause *> * const & activeGroundClauses,
00184                                    IntClauseHashArray * const & uniqueClauses,
00185                                    PredicateHashArray * const & seenPreds,
00186                                    PredicateHashArray * const & uniquePreds,
00187                            GroundPredicateHashArray* const& seenGndPreds,
00188                                    const Database* const & db,
00189                            bool const & getSatisfied)
00190 {
00191   assert(!activeIntClauses || !activeGroundClauses);     
00192   bool accumulateClauses = (activeIntClauses || activeGroundClauses);
00193   Predicate *cpred;
00194   PredicateSet predSet; // used to detect duplicates
00195   PredicateSet::iterator iter;
00196  
00197   IntClause *intClause;
00198   GroundClause *groundClause;
00199   
00200   Clause* fullClause = NULL;
00201   Clause* clause = NULL;
00202   bool isEmpty = true;
00203   for (int i = 0; i < predicates_->size(); i++)
00204   {
00205     Predicate* predicate = (*predicates_)[i];
00206     assert(predicate); 
00207         assert(predicate->isGrounded());
00208     if ( (iter = predSet.find(predicate)) != predSet.end() )
00209     {
00210         // The two gnd preds are of opp sense, so clause must be satisfied
00211         // and no point in adding it 
00212           if (wt_ >= 0 && !getSatisfied &&
00213           (*iter)->getSense() !=  predicate->getSense())
00214       {
00215         if (fullClause) delete fullClause;
00216         if (clause) delete clause;
00217                 return false;
00218       }
00219 
00220         // Since the two gnd preds are identical, no point adding a dup
00221       continue;
00222         }
00223     else
00224       predSet.insert(predicate);
00225       
00226     if (uniqueClauses)
00227     {
00228           if (!fullClause) fullClause = new Clause();
00229      
00230           cpred = new Predicate(*predicate, fullClause);
00231       assert(cpred);
00232           fullClause->appendPredicate(cpred);
00233         }
00234          
00235         bool isEvidence = db->getEvidenceStatus(predicate);
00236 //cout << "isEvidence " << isEvidence << endl;
00237 //predicate->printWithStrVar(cout, db->getDomain());
00238 //cout << endl;
00239         if (!isEvidence)
00240       isEmpty = false;
00241           
00242       // True evidence in a neg. clause: Discard clause
00243     if (wt_ < 0 && isEvidence && !getSatisfied &&
00244         db->sameTruthValueAndSense(db->getValue(predicate),
00245                                    predicate->getSense()))
00246     {
00247       if (clause) delete clause;
00248       if (fullClause) delete fullClause;
00249       return false;
00250     }
00251     
00252           // Add only non-evidence prdicates
00253         if (accumulateClauses && !isEvidence)
00254         {
00255           if (!clause) clause = new Clause();
00256         
00257           cpred = new Predicate(*predicate, clause);
00258       assert(cpred);
00259           clause->appendPredicate(cpred);
00260         }
00261   }
00262 
00263     // If the clause is empty after taking evidence into account, it should 
00264     // be discarded
00265   if (isEmpty)
00266   {
00267         assert(!clause);
00268         if (fullClause)
00269           delete fullClause;
00270     return false;
00271   }
00272     // Came to this point means that the clause is active (and hence nonEmpty)
00273   else
00274   {
00275           // Check if the clause is already present
00276         if (uniqueClauses)
00277         {
00278           assert(uniquePreds);
00279           assert(fullClause);  
00280      
00281                 // Note: fullClause should not be canonicalized
00282           intClause = new IntClause(fullClause, uniquePreds);
00283           delete fullClause; 
00284          
00285                 // If the clause is already present then it should
00286                 // not be added again
00287           if (uniqueClauses->append(intClause) < 0)
00288           {
00289         intClause->deleteIntPredicates();
00290         delete intClause;
00291         if (clause)
00292               delete clause;
00293                 return false;
00294       } 
00295         } 
00296     
00297           // Add the corresponding ground clause if accumulateClauses is true
00298         if (accumulateClauses)
00299         {
00300           assert(clause);       
00301       clause->canonicalizeWithoutVariables();
00302     
00303           if (activeIntClauses)
00304           {
00305         intClause = new IntClause(clause, seenPreds);
00306    
00307         if (isHardClause_) 
00308           intClause->setWtToHardWt();
00309             activeIntClauses->append(intClause);
00310       }
00311       else
00312       {
00313         groundClause = new GroundClause(clause, seenGndPreds);
00314 /*
00315           // Check if preds in clause have been seen
00316         for (int i = 0; i < groundClause->getNumGroundPredicates(); i++)
00317         {
00318           GroundPredicate* gp =
00319             (GroundPredicate*)groundClause->getGroundPredicate(i);
00320           int index = seenGndPreds->find(gp);
00321             // Pred has been seen: Use pointer to previously seen one and tell
00322             // it that it appears in this clause
00323           if (index >= 0)
00324           {
00325             groundClause->replaceGroundPredicate(i, (*seenGndPreds)[index]);
00326             bool predSense = groundClause->getGroundPredicateSense(i);
00327             bool ok = (*seenGndPreds)[index]->appendGndClause(groundClause,
00328                                                               predSense);
00329             ok = true; // avoid compilation warning
00330           }
00331             // Pred has not been seen, so append it to seen
00332           else
00333             index = seenGndPreds->append(gp);
00334           groundClause->setGroundPredicateIndex(i, index);
00335         }
00336 */     
00337         if (isHardClause_) 
00338           groundClause->setWtToHardWt();
00339             activeGroundClauses->append(groundClause);
00340       }
00341           delete clause;
00342     }
00343     return true;
00344   } 
00345 }
00346 
00347 

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