/*****************************************************************************/
/*!
*\file cnf.h
*\brief Basic classes for reasoning about formulas in CNF
*
* Author: Clark Barrett
*
* Created: Mon Dec 12 20:32:33 2005
*
*
*
* 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.
*
*
*/
/*****************************************************************************/
#ifndef _cvc3__include__cnf_h_
#define _cvc3__include__cnf_h_
#include
#include "compat_hash_map.h"
#include "cvc_util.h"
#include "cdo.h"
#include "cdlist.h"
namespace SAT {
class Var {
int d_index;
public:
enum Val { UNKNOWN = -1, FALSE_VAL, TRUE_VAL};
static Val invertValue(Val);
Var() : d_index(-1) {}
Var(int index) :d_index(index) {}
operator int() { return d_index; }
bool isNull() const { return d_index == -1; }
void reset() { d_index = -1; }
int getIndex() const { return d_index; }
bool operator==(const Var& var) const { return (d_index == var.d_index); }
};
inline Var::Val Var::invertValue(Var::Val v)
{ return v == Var::UNKNOWN ? Var::UNKNOWN : Var::Val(1-v); }
class Lit {
int d_index;
static Lit mkLit(int index) { Lit l; l.d_index = index; return l; }
public:
Lit() : d_index(0) {}
explicit Lit(Var v, bool positive=true) {
if (v.isNull()) d_index = 0;
else d_index = positive ? v+1 : -v-1;
}
static Lit getTrue() { return mkLit(1); }
static Lit getFalse() { return mkLit(-1); }
bool isNull() const { return d_index == 0; }
bool isPositive() const { return d_index > 1; }
bool isInverted() const { return d_index < -1; }
bool isFalse() const { return d_index == -1; }
bool isTrue() const { return d_index == 1; }
bool isVar() const { return abs(d_index) > 1; }
int getID() const { return d_index; }
Var getVar() const {
DebugAssert(isVar(),"Bad call to Lit::getVar");
return abs(d_index)-1;
}
void reset() { d_index = 0; }
friend Lit operator!(const Lit& lit) { return mkLit(-lit.d_index); }
};
class Clause {
/*! If d_id is 0 then the clause is a translation clause and its theorem
* can be figured out lazily. Otherwise, d_id gives the index into
* d_theorems for the theorem justifying this clause. */
int d_id:30;
int d_satisfied:1;
int d_unit:1;
std::vector d_lits;
public:
Clause() : d_id(0), d_satisfied(0), d_unit(0) {}
typedef std::vector::const_iterator const_iterator;
const_iterator begin() const { return d_lits.begin(); }
const_iterator end() const { return d_lits.end(); }
void clear() { d_id = d_satisfied = d_unit = 0; d_lits.clear(); }
unsigned size() const { return d_lits.size(); }
void addLiteral(Lit l) { if (!d_satisfied) d_lits.push_back(l); }
unsigned getMaxVar() const;
int getId() const { return d_id; }
bool isSatisfied() const { return d_satisfied != 0; }
bool isUnit() const { return d_unit != 0; }
bool isNull() const { return d_lits.size() == 0; }
void setId(int id)
{ d_id = id; FatalAssert(int(d_id) == id, "clause id overflow"); }
void setSatisfied() { d_satisfied = 1; }
void setUnit() { d_unit = 1; }
void print() const;
};
class CNF_Formula {
protected:
Clause* d_current;
virtual void setNumVars(unsigned numVars) = 0;
void copy(const CNF_Formula& cnf);
public:
CNF_Formula() : d_current(NULL) {}
virtual ~CNF_Formula() {}
typedef std::deque::const_iterator const_iterator;
virtual bool empty() const = 0;
virtual const Clause& operator[](int i) const = 0;
virtual const_iterator begin() const = 0;
virtual const_iterator end() const = 0;
virtual unsigned numVars() const = 0;
virtual unsigned numClauses() const = 0;
virtual void newClause() = 0;
virtual void registerUnit() = 0;
void addLiteral(Lit l, bool invert=false)
{ if (l.isVar() && unsigned(l.getVar()) > numVars())
setNumVars(l.getVar());
d_current->addLiteral(invert ? !l : l); }
Clause& getCurrentClause() { return *d_current; }
void print() const;
const CNF_Formula& operator+=(const CNF_Formula& cnf);
const CNF_Formula& operator+=(const Clause& c);
};
class CNF_Formula_Impl :public CNF_Formula {
std::hash_map d_lits;
std::deque d_formula;
unsigned d_numVars;
private:
void setNumVars(unsigned numVars) { d_numVars = numVars; }
public:
CNF_Formula_Impl() : CNF_Formula(), d_numVars(0) {}
CNF_Formula_Impl(const CNF_Formula& cnf) : CNF_Formula() { copy(cnf); }
~CNF_Formula_Impl() {};
bool empty() const { return d_formula.empty(); }
const Clause& operator[](int i) const { return d_formula[i]; }
const_iterator begin() const { return d_formula.begin(); }
const_iterator end() const { return d_formula.end(); }
unsigned numVars() const { return d_numVars; }
unsigned numClauses() const { return d_formula.size(); }
void deleteLast() { DebugAssert(d_formula.size() > 0, "size == 0"); d_formula.pop_back(); }
void newClause();
void registerUnit();
void simplify();
void reset();
};
class CD_CNF_Formula :public CNF_Formula {
CVC3::CDList d_formula;
CVC3::CDO d_numVars;
private:
void setNumVars(unsigned numVars) { d_numVars = numVars; }
public:
CD_CNF_Formula(CVC3::Context* context)
: CNF_Formula(), d_formula(context), d_numVars(context, 0, 0) {}
~CD_CNF_Formula() {}
bool empty() const { return d_formula.empty(); }
const Clause& operator[](int i) const { return d_formula[i]; }
const_iterator begin() const { return d_formula.begin(); }
const_iterator end() const { return d_formula.end(); }
unsigned numVars() const { return d_numVars.get(); }
unsigned numClauses() const { return d_formula.size(); }
void deleteLast() { d_formula.pop_back(); }
void newClause();
void registerUnit();
};
}
#endif