/*****************************************************************************/
/*!
* \file variable.cpp
* \brief Implementation of class Variable; see variable.h for detail.
*
* Author: Sergey Berezin
*
* Created: Fri Apr 25 12:30:17 2003
*
* <hr>
*
* License to use, copy, modify, sell and/or distribute this software
* and its documentation for any purpose is hereby granted without
* royalty, subject to the terms and conditions defined in the \ref
* LICENSE file provided with this distribution.
*
* <hr>
*
*/
/*****************************************************************************/
#include <sstream>
#include "variable.h"
#include "search_rules.h"
#include "memory_manager_chunks.h"
#include "memory_manager_malloc.h"
using namespace std;
namespace CVC3 {
///////////////////////////////////////////////////////////////////////
// class Variable methods
///////////////////////////////////////////////////////////////////////
// Constructors
Variable::Variable(VariableManager* vm, const Expr& e)
: d_val(vm->newVariableValue(e))
{
d_val->d_refcount++;
}
Variable::Variable(const Variable& l): d_val(l.d_val) {
if(!isNull()) d_val->d_refcount++;
}
// Destructor
Variable::~Variable() {
if(!isNull()) {
if(--(d_val->d_refcount) == 0)
d_val->d_vm->gc(d_val);
}
}
// Assignment
Variable&
Variable::operator=(const Variable& l) {
if(&l == this) return *this; // Self-assignment
if(!isNull()) {
if(--(d_val->d_refcount) == 0) d_val->d_vm->gc(d_val);
}
d_val = l.d_val;
if(!isNull()) d_val->d_refcount++;
return *this;
}
const Expr&
Variable::getExpr() const {
static Expr null;
if(isNull()) return null;
return d_val->getExpr();
}
const Expr&
Variable::getNegExpr() const {
static Expr null;
if(isNull()) return null;
return d_val->getNegExpr();
}
// IMPORTANT: Value can be -1 (false), 1 (true), or 0 (unresolved)
int
Variable::getValue() const {
if(isNull()) return 0;
return d_val->getValue();
}
int
Variable::getScope() const {
if(isNull()) return 0;
return d_val->getScope();
}
const Theorem&
Variable::getTheorem() const {
static Theorem null;
if(isNull()) return null;
return d_val->getTheorem();
}
const Clause&
Variable::getAntecedent() const {
static Clause null;
if(isNull()) return null;
return d_val->getAntecedent();
}
int
Variable::getAntecedentIdx() const {
if(isNull()) return 0;
return d_val->getAntecedentIdx();
}
const Theorem&
Variable::getAssumpThm() const {
static Theorem null;
if(isNull()) return null;
return d_val->getAssumpThm();
}
// Setting the attributes: it can be either derived from the
// antecedent clause, or by a theorem. The scope level is set to
// the current scope.
void
Variable::setValue(int val, const Clause& c, int idx) {
DebugAssert(!isNull(), "Variable::setValue(antecedent): var is NULL");
d_val->setValue(val, c, idx);
}
// The theorem's expr must be the same as the variable's expr or
// its negation
void
Variable::setValue(const Theorem& thm) {
DebugAssert(!isNull(), "Variable::setValue(Theorem): var is NULL");
d_val->setValue(thm, thm.getScope());
}
void
Variable::setValue(const Theorem& thm, int scope) {
DebugAssert(!isNull(), "Variable::setValue(Theorem,scope): var is NULL");
d_val->setValue(thm, scope);
}
void
Variable::setAssumpThm(const Theorem& a, int scope) {
DebugAssert(!isNull(), "Variable::setAssumpThm(): var is NULL");
d_val->setAssumpThm(a, scope);
}
// Derive the theorem for either the variable or its negation. If
// the value is set by a theorem, that theorem is returned;
// otherwise a unit propagation rule is applied to the antecedent
// clause, and the theorem is cached for a quick access later.
Theorem
Variable::deriveTheorem() const {
return deriveThmRec(false);
}
Theorem
Variable::deriveThmRec(bool checkAssump) const {
DebugAssert(!isNull(), "Variable::deriveTheorem(): called on Null");
DebugAssert(getValue() != 0, "Variable::deriveTheorem(): value is not set: "
+ toString());
if(!getTheorem().isNull()) return getTheorem();
if(checkAssump && !getAssumpThm().isNull()) return getAssumpThm();
// Have to derive the theorem
Clause c(getAntecedent());
int idx(getAntecedentIdx());
const vector<Literal>& lits = c.getLiterals();
// Theorems for the other literals in the antecedent clause
vector<Theorem> thms;
int size(lits.size());
// Derive theorems recursively
for(int i=0; i<size; ++i)
if(i!=idx) thms.push_back(lits[i].getVar().deriveThmRec(true));
Theorem thm;
if(idx!=-1)
thm = d_val->d_vm->getRules()->unitProp(thms, c.getTheorem(), idx);
else
thm = d_val->d_vm->getRules()->conflictRule(thms, c.getTheorem());
IF_DEBUG(Expr e(thm.getExpr()));
DebugAssert(e == getExpr()
|| (e.isNot() && e[0] == getExpr()),
"Variable::deriveTheorem: bad theorem derived: expr ="
+ toString() + ", thm = " + thm.toString());
// Cache the result
d_val->setValue(thm, getScope());
return thm;
}
string
Variable::toString() const {
ostringstream ss;
ss << *this;
return ss.str();
}
// Friend methods
ostream& operator<<(ostream& os, const Variable& l) {
return os << (*l.d_val);
}
///////////////////////////////////////////////////////////////////////
// class Literal methods
///////////////////////////////////////////////////////////////////////
string
Literal::toString() const {
ostringstream ss;
ss << *this;
return ss.str();
}
ostream& operator<<(ostream& os, const Literal& l) {
os << "Lit(" << (l.isNegative()? "!" : "")
<< l.getVar();
// Attributes
os << ", count=" << l.count() << ", score=" << l.score();
return os << ")";
}
///////////////////////////////////////////////////////////////////////
// class VariableValue methods
///////////////////////////////////////////////////////////////////////
// Destructor
VariableValue::~VariableValue() {
if(d_val!=NULL) { delete d_val; free(d_val); d_val = NULL; }
if(d_scope!=NULL) { delete d_scope; free(d_scope); d_scope = NULL; }
if(d_thm!=NULL) { delete d_thm; free(d_thm); d_thm = NULL; }
if(d_ante!=NULL) { delete d_ante; free(d_ante); d_ante = NULL; }
if(d_anteIdx!=NULL) { delete d_anteIdx; free(d_anteIdx); d_anteIdx = NULL; }
if(d_assump!=NULL) { delete d_assump; free(d_assump); d_assump = NULL; }
}
// Setting the attributes: it can be either derived from the
// antecedent clause, or by a theorem
void
VariableValue::setValue(int val, const Clause& c, int idx) {
if(d_val==NULL) {
// Make sure d_val==0 all the way to scope 0
d_val = new(true) CDO<int>(d_vm->getCM()->getCurrentContext(), 0, 0);
IF_DEBUG(d_val->setName("CDO[VariableValue::d_val]"));
}
if(d_scope==NULL) {
d_scope = new(true) CDO<int>(d_vm->getCM()->getCurrentContext());
IF_DEBUG(d_scope->setName("CDO[VariableValue::d_scope]"));
}
if(d_ante==NULL) {
d_ante = new(true) CDO<Clause>(d_vm->getCM()->getCurrentContext());
IF_DEBUG(d_ante->setName("CDO[VariableValue::d_ante]"));
}
if(d_anteIdx==NULL) {
d_anteIdx = new(true) CDO<int>(d_vm->getCM()->getCurrentContext());
IF_DEBUG(d_anteIdx->setName("CDO[VariableValue::d_anteIdx]"));
}
// Compute the scope from the antecedent clause
// Assume the clause is valid exactly at the bottom scope
int scope(c.getScope());
for(int i=0, iend=c.size(); i!=iend; ++i) {
if(i!=idx) {
int s(c[i].getScope());
if(s > scope) scope = s;
DebugAssert(c[i].getValue() != 0,
"VariableValue::setValue(ante): literal has no value: "
"i="+int2string(i)+" in\n clause = "
+c.toString());
}
}
d_val->set(val, scope);
d_scope->set(scope, scope); // d_vm->getCM()->scopeLevel();
d_ante->set(c, scope);
d_anteIdx->set(idx, scope);
// Set the theorem to null, to clean up the old value
if(!getTheorem().isNull()) d_thm->set(Theorem(), scope);
IF_DEBUG(Expr l((idx == -1)? getExpr().getEM()->falseExpr()
: c[idx].getExpr()));
DebugAssert((val > 0 && l == getExpr())
|| (val < 0 && l.isNot() && l[0] == getExpr()),
"VariableValue::setValue(val = " + int2string(val)
+ ", c = " + c.toString() + ", idx = " + int2string(idx)
+ "):\n expr = " + getExpr().toString()
+ "\n literal = " + l.toString());
}
// The theorem's expr must be the same as the variable's expr or
// its negation
void
VariableValue::setValue(const Theorem& thm, int scope) {
if(d_val==NULL) {
// Make sure d_val==0 all the way to scope 0
d_val = new(true) CDO<int>(d_vm->getCM()->getCurrentContext(),0,0);
IF_DEBUG(d_val->setName("CDO[VariableValue::d_val]"));
}
if(d_scope==NULL) {
d_scope = new(true) CDO<int>(d_vm->getCM()->getCurrentContext());
IF_DEBUG(d_scope->setName("CDO[VariableValue::d_scope]"));
}
if(d_thm==NULL) {
d_thm = new(true) CDO<Theorem>(d_vm->getCM()->getCurrentContext());
IF_DEBUG(d_thm->setName("CDO[VariableValue::d_thm]"));
}
Expr e(thm.getExpr());
int val(0);
if(e == d_expr) val = 1;
else {
DebugAssert(e.isNot() && e[0] == d_expr,
"VariableValue::setValue(thm = "
+ thm.toString() + "): expr = " + d_expr.toString());
val = -1;
}
// Set the values on that scope
d_val->set(val, scope);
d_scope->set(scope, scope); // d_vm->getCM()->scopeLevel();
d_thm->set(thm, scope);
// Set clause to null, to clean up the old value
if(!getAntecedent().isNull()) d_ante->set(Clause(), scope);
}
void
VariableValue::setAssumpThm(const Theorem& thm, int scope) {
if(d_assump==NULL) {
// Make sure d_val==0 all the way to scope 0
d_assump = new(true) CDO<Theorem>(d_vm->getCM()->getCurrentContext());
IF_DEBUG(d_val->setName("CDO[VariableValue::d_val]"));
}
d_assump->set(thm, scope);
}
ostream& operator<<(ostream& os, const VariableValue& v) {
os << "Var(" << v.getExpr() << " = " << v.getValue();
if(v.getValue() != 0) {
os << " @ " << v.getScope();
if(!v.getTheorem().isNull())
os << "; " << v.getTheorem();
else if(!v.getAntecedent().isNull()) {
os << "; #" << v.getAntecedentIdx()
<< " in " << CompactClause(v.getAntecedent());
}
}
return os << ")";
}
///////////////////////////////////////////////////////////////////////
// class VariableManager methods
///////////////////////////////////////////////////////////////////////
// Creating unique VariableValue
VariableValue*
VariableManager::newVariableValue(const Expr& e) {
VariableValue vv(this, e);
VariableValueSet::iterator i(d_varSet.find(&vv)), iend(d_varSet.end());
if(i != iend) return (*i);
// No such variable, create and insert one
VariableValue* p_vv(new(d_mm) VariableValue(this, e));
d_varSet.insert(p_vv);
return p_vv;
}
// Constructor
VariableManager::VariableManager(ContextManager* cm, SearchEngineRules* rules,
const string& mmFlag)
: d_cm(cm), d_rules(rules), d_disableGC(false), d_postponeGC(false) {
if(mmFlag == "chunks")
d_mm = new MemoryManagerChunks(sizeof(VariableValue));
else
d_mm = new MemoryManagerMalloc();
d_notifyObj = new VariableManagerNotifyObj(this, d_cm->getCurrentContext());
}
// Destructor
VariableManager::~VariableManager() {
delete d_notifyObj;
// Delete the remaining variables
d_disableGC = true;
vector<VariableValue*> vars;
for(VariableValueSet::iterator i=d_varSet.begin(), iend=d_varSet.end();
i!=iend; ++i) {
vars.push_back(*i);
// delete(*i);
// No need to free memory; we'll delete the entire d_mm
// d_mm->deleteData(*i);
}
d_varSet.clear();
for(vector<VariableValue*>::iterator i=vars.begin(), iend=vars.end();
i!=iend; ++i) delete *i;
delete d_mm;
}
// Garbage collect VariableValue pointer
void
VariableManager::gc(VariableValue* v) {
if(!d_disableGC) {
d_varSet.erase(v);
if(d_postponeGC) d_deleted.push_back(v);
else {
delete v;
d_mm->deleteData(v);
}
}
}
void
VariableManager::resumeGC() {
d_postponeGC = false;
while(d_deleted.size() > 0) {
VariableValue* v = d_deleted.back();
d_deleted.pop_back();
delete v;
d_mm->deleteData(v);
}
}
} // end of namespace CVC3
syntax highlighted by Code2HTML, v. 0.9.1