variable.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file variable.cpp
00004  * \brief Implementation of class Variable; see variable.h for detail.
00005  * 
00006  * Author: Sergey Berezin
00007  * 
00008  * Created: Fri Apr 25 12:30:17 2003
00009  *
00010  * <hr>
00011  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00012  * Junior University and by New York University. 
00013  *
00014  * License to use, copy, modify, sell and/or distribute this software
00015  * and its documentation for any purpose is hereby granted without
00016  * royalty, subject to the terms and conditions defined in the \ref
00017  * LICENSE file provided with this distribution.  In particular:
00018  *
00019  * - The above copyright notice and this permission notice must appear
00020  * in all copies of the software and related documentation.
00021  *
00022  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00023  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00024  * 
00025  * <hr>
00026  * 
00027  */
00028 /*****************************************************************************/
00029 
00030 #include <sstream>
00031 #include "variable.h"
00032 #include "search_rules.h"
00033 #include "memory_manager_chunks.h"
00034 #include "memory_manager_malloc.h"
00035 
00036 using namespace std;
00037 
00038 namespace CVCL {
00039 
00040 ///////////////////////////////////////////////////////////////////////
00041 // class Variable methods
00042 ///////////////////////////////////////////////////////////////////////
00043 
00044 // Constructors
00045 Variable::Variable(VariableManager* vm, const Expr& e)
00046   : d_val(vm->newVariableValue(e))
00047 {
00048   d_val->d_refcount++;
00049 }
00050 
00051 Variable::Variable(const Variable& l): d_val(l.d_val) {
00052   if(!isNull()) d_val->d_refcount++;
00053 }
00054 
00055   // Destructor
00056 Variable::~Variable() {
00057   if(!isNull()) {
00058     if(--(d_val->d_refcount) == 0)
00059       d_val->d_vm->gc(d_val);
00060   }
00061 }
00062 
00063   // Assignment
00064 Variable&
00065 Variable::operator=(const Variable& l) {
00066   if(&l == this) return *this; // Self-assignment
00067   if(!isNull()) {
00068     if(--(d_val->d_refcount) == 0) d_val->d_vm->gc(d_val);
00069   }
00070   d_val = l.d_val;
00071   if(!isNull()) d_val->d_refcount++;
00072   return *this;
00073 }
00074 
00075 const Expr&
00076 Variable::getExpr() const {
00077   static Expr null;
00078   if(isNull()) return null;
00079   return d_val->getExpr();
00080 }
00081 
00082 const Expr&
00083 Variable::getNegExpr() const {
00084   static Expr null;
00085   if(isNull()) return null;
00086   return d_val->getNegExpr();
00087 }
00088 
00089 // IMPORTANT: Value can be -1 (false), 1 (true), or 0 (unresolved)
00090 int
00091 Variable::getValue() const {
00092   if(isNull()) return 0;
00093   return d_val->getValue();
00094 }
00095 
00096 
00097 int
00098 Variable::getScope() const {
00099   if(isNull()) return 0;
00100   return d_val->getScope();
00101 }
00102 
00103 const Theorem&
00104 Variable::getTheorem() const {
00105   static Theorem null;
00106   if(isNull()) return null;
00107   return d_val->getTheorem();
00108 }
00109 
00110 const Clause&
00111 Variable::getAntecedent() const {
00112   static Clause null;
00113   if(isNull()) return null;
00114   return d_val->getAntecedent();
00115 }
00116 
00117 int
00118 Variable::getAntecedentIdx() const {
00119   if(isNull()) return 0;
00120   return d_val->getAntecedentIdx();
00121 }
00122 
00123 const Theorem&
00124 Variable::getAssumpThm() const {
00125   static Theorem null;
00126   if(isNull()) return null;
00127   return d_val->getAssumpThm();
00128 }
00129 
00130 // Setting the attributes: it can be either derived from the
00131 // antecedent clause, or by a theorem.  The scope level is set to
00132 // the current scope.
00133 void
00134 Variable::setValue(int val, const Clause& c, int idx) {
00135   DebugAssert(!isNull(), "Variable::setValue(antecedent): var is NULL");
00136   d_val->setValue(val, c, idx);
00137 }
00138 
00139 // The theorem's expr must be the same as the variable's expr or
00140 // its negation
00141 void
00142 Variable::setValue(const Theorem& thm) {
00143   DebugAssert(!isNull(), "Variable::setValue(Theorem): var is NULL");
00144   d_val->setValue(thm, thm.getScope());
00145 }
00146 
00147 void
00148 Variable::setValue(const Theorem& thm, int scope) {
00149   DebugAssert(!isNull(), "Variable::setValue(Theorem,scope): var is NULL");
00150   d_val->setValue(thm, scope);
00151 }
00152 
00153 void
00154 Variable::setAssumpThm(const Theorem& a, int scope) {
00155   DebugAssert(!isNull(), "Variable::setAssumpThm(): var is NULL");
00156   d_val->setAssumpThm(a, scope);
00157 }
00158   
00159   // Derive the theorem for either the variable or its negation.  If
00160   // the value is set by a theorem, that theorem is returned;
00161   // otherwise a unit propagation rule is applied to the antecedent
00162   // clause, and the theorem is cached for a quick access later.
00163 Theorem
00164 Variable::deriveTheorem() const {
00165   return deriveThmRec(false);
00166 }
00167 
00168 
00169 Theorem
00170 Variable::deriveThmRec(bool checkAssump) const {
00171   DebugAssert(!isNull(), "Variable::deriveTheorem(): called on Null");
00172   DebugAssert(getValue() != 0, "Variable::deriveTheorem(): value is not set: "
00173               + toString());
00174   if(!getTheorem().isNull()) return getTheorem();
00175   if(checkAssump && !getAssumpThm().isNull()) return getAssumpThm();
00176   // Have to derive the theorem
00177   Clause c(getAntecedent());
00178   int idx(getAntecedentIdx());
00179   const vector<Literal>& lits = c.getLiterals();
00180   // Theorems for the other literals in the antecedent clause
00181   vector<Theorem> thms;
00182   int size(lits.size());
00183   // Derive theorems recursively
00184   for(int i=0; i<size; ++i)
00185     if(i!=idx) thms.push_back(lits[i].getVar().deriveThmRec(true));
00186   Theorem thm;
00187   if(idx!=-1)
00188     thm = d_val->d_vm->getRules()->unitProp(thms, c.getTheorem(), idx);
00189   else
00190     thm = d_val->d_vm->getRules()->conflictRule(thms, c.getTheorem());
00191   
00192   IF_DEBUG(Expr e(thm.getExpr()));
00193   DebugAssert(e == getExpr()
00194               || (e.isNot() && e[0] == getExpr()),
00195               "Variable::deriveTheorem: bad theorem derived: expr ="
00196               + toString() + ", thm = " + thm.toString());
00197   // Cache the result
00198   d_val->setValue(thm, getScope());
00199   return thm;
00200 }
00201 
00202 string
00203 Variable::toString() const {
00204   ostringstream ss;
00205   ss << *this;
00206   return ss.str();
00207 }
00208 
00209 // Friend methods
00210 ostream& operator<<(ostream& os, const Variable& l) {
00211   return os << (*l.d_val);
00212 }
00213 
00214 ///////////////////////////////////////////////////////////////////////
00215 // class Literal methods
00216 ///////////////////////////////////////////////////////////////////////
00217 
00218 string
00219 Literal::toString() const {
00220   ostringstream ss;
00221   ss << *this;
00222   return ss.str();
00223 }
00224 
00225 ostream& operator<<(ostream& os, const Literal& l) {
00226   os << "Lit(" << (l.isNegative()? "!" : "")
00227      << l.getVar();
00228   // Attributes
00229   os << ", count=" << l.count() << ", score=" << l.score();
00230   return os << ")";
00231 }
00232 
00233 ///////////////////////////////////////////////////////////////////////
00234 // class VariableValue methods
00235 ///////////////////////////////////////////////////////////////////////
00236 
00237 // Destructor
00238 VariableValue::~VariableValue() {
00239   if(d_val!=NULL) { delete d_val; d_val = NULL; }
00240   if(d_scope!=NULL) { delete d_scope; d_scope = NULL; }
00241   if(d_thm!=NULL) { delete d_thm; d_thm = NULL; }
00242   if(d_ante!=NULL) { delete d_ante; d_ante = NULL; }
00243   if(d_anteIdx!=NULL) { delete d_anteIdx; d_anteIdx = NULL; }
00244   if(d_assump!=NULL) { delete d_assump; d_assump = NULL; }
00245 }
00246 
00247   // Setting the attributes: it can be either derived from the
00248   // antecedent clause, or by a theorem
00249 void
00250 VariableValue::setValue(int val, const Clause& c, int idx) {
00251   if(d_val==NULL) {
00252     // Make sure d_val==0 all the way to scope 0
00253     d_val = new CDO<int>(d_vm->getCM()->getCurrentContext(), 0, 0);
00254     IF_DEBUG(d_val->setName("CDO[VariableValue::d_val]"));
00255   }
00256   if(d_scope==NULL) {
00257     d_scope = new CDO<int>(d_vm->getCM()->getCurrentContext());
00258     IF_DEBUG(d_scope->setName("CDO[VariableValue::d_scope]"));
00259   }
00260   if(d_ante==NULL) {
00261     d_ante = new CDO<Clause>(d_vm->getCM()->getCurrentContext());
00262     IF_DEBUG(d_ante->setName("CDO[VariableValue::d_ante]"));
00263   }
00264   if(d_anteIdx==NULL) {
00265     d_anteIdx = new CDO<int>(d_vm->getCM()->getCurrentContext());
00266     IF_DEBUG(d_anteIdx->setName("CDO[VariableValue::d_anteIdx]"));
00267   }
00268 
00269   // Compute the scope from the antecedent clause
00270   // Assume the clause is valid exactly at the bottom scope
00271   int scope(c.getScope());
00272   for(int i=0, iend=c.size(); i!=iend; ++i) {
00273     if(i!=idx) {
00274       int s(c[i].getScope());
00275       if(s > scope) scope = s;
00276       DebugAssert(c[i].getValue() != 0,
00277                   "VariableValue::setValue(ante): literal has no value: "
00278                   "i="+int2string(i)+" in\n clause = "
00279                   +c.toString());
00280     }
00281   }
00282 
00283   d_val->set(val, scope);
00284   d_scope->set(scope, scope); // d_vm->getCM()->scopeLevel();
00285   d_ante->set(c, scope);
00286   d_anteIdx->set(idx, scope);
00287   // Set the theorem to null, to clean up the old value
00288   if(!getTheorem().isNull()) d_thm->set(Theorem(), scope);
00289 
00290   IF_DEBUG(Expr l((idx == -1)? getExpr().getEM()->falseExpr()
00291                   : c[idx].getExpr()));
00292   DebugAssert((val > 0 && l == getExpr())
00293               || (val < 0 && l.isNot() && l[0] == getExpr()),
00294               "VariableValue::setValue(val = " + int2string(val)
00295               + ", c = " + c.toString() + ", idx = " + int2string(idx)
00296               + "):\n expr = " + getExpr().toString()
00297               + "\n literal = " + l.toString());
00298 }
00299 
00300 // The theorem's expr must be the same as the variable's expr or
00301 // its negation
00302 void
00303 VariableValue::setValue(const Theorem& thm, int scope) {
00304   if(d_val==NULL) {
00305     // Make sure d_val==0 all the way to scope 0
00306     d_val = new CDO<int>(d_vm->getCM()->getCurrentContext(),0,0);
00307     IF_DEBUG(d_val->setName("CDO[VariableValue::d_val]"));
00308   }
00309   if(d_scope==NULL) {
00310     d_scope = new CDO<int>(d_vm->getCM()->getCurrentContext());
00311     IF_DEBUG(d_scope->setName("CDO[VariableValue::d_scope]"));
00312   }
00313   if(d_thm==NULL) {
00314     d_thm = new CDO<Theorem>(d_vm->getCM()->getCurrentContext());
00315     IF_DEBUG(d_thm->setName("CDO[VariableValue::d_thm]"));
00316   }
00317 
00318   Expr e(thm.getExpr());
00319   int val(0);
00320   if(e == d_expr) val = 1;
00321   else {
00322     DebugAssert(e.isNot() && e[0] == d_expr,
00323                 "VariableValue::setValue(thm = "
00324                 + thm.toString() + "): expr = " + d_expr.toString());
00325     val = -1;
00326   }
00327   // Set the values on that scope
00328   d_val->set(val, scope);
00329   d_scope->set(scope, scope); // d_vm->getCM()->scopeLevel();
00330   d_thm->set(thm, scope);
00331   // Set clause to null, to clean up the old value
00332   if(!getAntecedent().isNull()) d_ante->set(Clause(), scope);
00333 }
00334 
00335 void
00336 VariableValue::setAssumpThm(const Theorem& thm, int scope) {
00337   if(d_assump==NULL) {
00338     // Make sure d_val==0 all the way to scope 0
00339     d_assump = new CDO<Theorem>(d_vm->getCM()->getCurrentContext());
00340     IF_DEBUG(d_val->setName("CDO[VariableValue::d_val]"));
00341   }
00342   d_assump->set(thm, scope);
00343 }
00344 
00345 ostream& operator<<(ostream& os, const VariableValue& v) {
00346   os << "Var(" << v.getExpr() << " = " << v.getValue();
00347   if(v.getValue() != 0) {
00348     os << " @ " << v.getScope();
00349     if(!v.getTheorem().isNull())
00350       os << "; " << v.getTheorem();
00351     else if(!v.getAntecedent().isNull()) {
00352       os << "; #" << v.getAntecedentIdx()
00353          << " in " << CompactClause(v.getAntecedent());
00354     }
00355   }
00356   return os << ")";
00357 }
00358 
00359 ///////////////////////////////////////////////////////////////////////
00360 // class VariableManager methods
00361 ///////////////////////////////////////////////////////////////////////
00362 
00363 // Creating unique VariableValue
00364 VariableValue*
00365 VariableManager::newVariableValue(const Expr& e) {
00366   VariableValue vv(this, e);
00367   VariableValueSet::iterator i(d_varSet.find(&vv)), iend(d_varSet.end());
00368   if(i != iend) return (*i);
00369   // No such variable, create and insert one
00370   VariableValue* p_vv(new(d_mm) VariableValue(this, e));
00371   d_varSet.insert(p_vv);
00372   return p_vv;
00373 }
00374 
00375 // Constructor
00376 VariableManager::VariableManager(ContextManager* cm, SearchEngineRules* rules,
00377                                  const string& mmFlag)
00378   : d_cm(cm), d_rules(rules), d_disableGC(false), d_postponeGC(false) {
00379   if(mmFlag == "chunks")
00380     d_mm = new MemoryManagerChunks(sizeof(VariableValue));
00381   else
00382     d_mm = new MemoryManagerMalloc();
00383 
00384   d_notifyObj = new VariableManagerNotifyObj(this, d_cm->getCurrentContext());
00385 }
00386 
00387 // Destructor
00388 VariableManager::~VariableManager() {
00389   delete d_notifyObj;
00390   // Delete the remaining variables
00391   d_disableGC = true;
00392   vector<VariableValue*> vars;
00393   for(VariableValueSet::iterator i=d_varSet.begin(), iend=d_varSet.end();
00394       i!=iend; ++i) {
00395     vars.push_back(*i);
00396     // delete(*i);
00397     // No need to free memory; we'll delete the entire d_mm
00398     // d_mm->deleteData(*i);
00399   }
00400   d_varSet.clear();
00401   for(vector<VariableValue*>::iterator i=vars.begin(), iend=vars.end();
00402       i!=iend; ++i) delete *i;
00403   delete d_mm;
00404 }
00405 
00406 // Garbage collect VariableValue pointer
00407 void
00408 VariableManager::gc(VariableValue* v) {
00409   if(!d_disableGC) {
00410     d_varSet.erase(v);
00411     if(d_postponeGC) d_deleted.push_back(v);
00412     else {
00413       delete v;
00414       d_mm->deleteData(v);
00415     }
00416   }
00417 }
00418 
00419 
00420 void
00421 VariableManager::resumeGC() {
00422   d_postponeGC = false;
00423   while(d_deleted.size() > 0) {
00424     VariableValue* v = d_deleted.back();
00425     d_deleted.pop_back();
00426     delete v;
00427     d_mm->deleteData(v);
00428   }
00429 }
00430 
00431 } // end of namespace CVCL

Generated on Thu Apr 13 16:57:36 2006 for CVC Lite by  doxygen 1.4.4