3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00

add consequence finding to inc-sat-solver

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-10-16 15:43:28 -04:00
parent d8ea3023fc
commit aec59e4ff7
10 changed files with 283 additions and 41 deletions

View file

@ -3075,45 +3075,51 @@ namespace sat {
m_binary_clause_graph[l1.index()].push_back(l2);
m_binary_clause_graph[l2.index()].push_back(l1);
}
while (!ps.empty()) {
bool non_empty = true;
m_seen[0].reset();
while (non_empty) {
literal_vector mutex;
literal_set other(ps);
while (!other.empty()) {
literal_set conseq;
literal p = other.pop();
bool turn = false;
m_reachable[turn] = ps;
while (!m_reachable[turn].empty()) {
literal p = m_reachable[turn].pop();
if (m_seen[0].contains(p)) {
continue;
}
m_reachable[turn].remove(p);
m_seen[0].insert(p);
mutex.push_back(p);
if (other.empty()) {
if (m_reachable[turn].empty()) {
break;
}
get_reachable(p, other, conseq);
other = conseq;
m_reachable[!turn].reset();
get_reachable(p, m_reachable[turn], m_reachable[!turn]);
turn = !turn;
}
if (mutex.size() > 1) {
mutexes.push_back(mutex);
}
for (unsigned i = 0; i < mutex.size(); ++i) {
ps.erase(mutex[i]);
}
non_empty = !mutex.empty();
}
return l_true;
}
void solver::get_reachable(literal p, literal_set const& goal, literal_set& reachable) {
literal_set seen;
literal_vector todo;
todo.push_back(p);
while (!todo.empty()) {
p = todo.back();
todo.pop_back();
if (seen.contains(p)) {
m_seen[1].reset();
m_todo.reset();
m_todo.push_back(p);
while (!m_todo.empty()) {
p = m_todo.back();
m_todo.pop_back();
if (m_seen[1].contains(p)) {
continue;
}
seen.insert(p);
m_seen[1].insert(p);
literal np = ~p;
if (goal.contains(np)) {
reachable.insert(np);
}
todo.append(m_binary_clause_graph[np.index()]);
m_todo.append(m_binary_clause_graph[np.index()]);
}
}

View file

@ -447,6 +447,9 @@ namespace sat {
u_map<index_set> m_antecedents;
vector<literal_vector> m_binary_clause_graph;
literal_set m_reachable[2];
literal_set m_seen[2];
literal_vector m_todo;
void extract_assumptions(literal lit, index_set& s);

View file

@ -33,6 +33,7 @@ Notes:
#include "filter_model_converter.h"
#include "bit_blaster_model_converter.h"
#include "ast_translation.h"
#include "ast_util.h"
// incremental SAT solver.
class inc_sat_solver : public solver {
@ -232,6 +233,41 @@ public:
return 0;
}
virtual lbool get_consequences_core(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq) {
TRACE("sat", tout << assumptions << "\n" << vars << "\n";);
sat::literal_vector asms;
sat::bool_var_vector bvars;
vector<sat::literal_vector> lconseq;
dep2asm_t dep2asm;
m_solver.pop_to_base_level();
lbool r = internalize_formulas();
if (r != l_true) return r;
r = internalize_assumptions(assumptions.size(), assumptions.c_ptr(), dep2asm);
if (r != l_true) return r;
r = internalize_vars(vars, bvars);
r = m_solver.get_consequences(m_asms, bvars, lconseq);
if (r != l_true) return r;
// build map from bound variables to
// the consequences that cover them.
u_map<unsigned> bool_var2conseq;
for (unsigned i = 0; i < lconseq.size(); ++i) {
TRACE("sat", tout << lconseq[i] << "\n";);
bool_var2conseq.insert(lconseq[i][0].var(), i);
}
// extract original fixed variables
for (unsigned i = 0; i < vars.size(); ++i) {
expr_ref cons(m);
if (extract_fixed_variable(dep2asm, vars[i], bool_var2conseq, lconseq, cons)) {
conseq.push_back(cons);
}
}
return r;
}
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) {
sat::literal_vector ls;
u_map<expr*> lit2var;
@ -359,6 +395,106 @@ private:
return res;
}
lbool internalize_vars(expr_ref_vector const& vars, sat::bool_var_vector& bvars) {
for (unsigned i = 0; i < vars.size(); ++i) {
internalize_var(vars[i], bvars);
}
return l_true;
}
bool internalize_var(expr* v, sat::bool_var_vector& bvars) {
obj_map<func_decl, expr*> const& const2bits = m_bb_rewriter->const2bits();
expr* bv;
bv_util bvutil(m);
bool internalized = false;
if (is_uninterp_const(v) && m.is_bool(v)) {
sat::bool_var b = m_map.to_bool_var(v);
if (b != sat::null_bool_var) {
bvars.push_back(b);
internalized = true;
}
}
else if (is_uninterp_const(v) && const2bits.find(to_app(v)->get_decl(), bv)) {
SASSERT(bvutil.is_bv(bv));
app* abv = to_app(bv);
internalized = true;
unsigned sz = abv->get_num_args();
for (unsigned j = 0; j < sz; ++j) {
SASSERT(is_uninterp_const(abv->get_arg(j)));
sat::bool_var b = m_map.to_bool_var(abv->get_arg(j));
if (b == sat::null_bool_var) {
internalized = false;
}
else {
bvars.push_back(b);
}
}
CTRACE("sat", internalized, tout << "var: "; for (unsigned j = 0; j < sz; ++j) tout << bvars[bvars.size()-sz+j] << " "; tout << "\n";);
}
else if (is_uninterp_const(v) && bvutil.is_bv(v)) {
// variable does not occur in assertions, so is unconstrained.
}
CTRACE("sat", !internalized, tout << "unhandled variable " << mk_pp(v, m) << "\n";);
return internalized;
}
bool extract_fixed_variable(dep2asm_t& dep2asm, expr* v, u_map<unsigned> const& bool_var2conseq, vector<sat::literal_vector> const& lconseq, expr_ref& conseq) {
u_map<expr*> asm2dep;
extract_asm2dep(dep2asm, asm2dep);
sat::bool_var_vector bvars;
if (!internalize_var(v, bvars)) {
return false;
}
sat::literal_vector value;
sat::literal_set premises;
for (unsigned i = 0; i < bvars.size(); ++i) {
unsigned index;
if (bool_var2conseq.find(bvars[i], index)) {
value.push_back(lconseq[index][0]);
for (unsigned j = 1; j < lconseq[index].size(); ++j) {
premises.insert(lconseq[index][j]);
}
}
else {
TRACE("sat", tout << "variable is not bound " << mk_pp(v, m) << "\n";);
return false;
}
}
expr_ref val(m);
expr_ref_vector conj(m);
internalize_value(value, v, val);
while (!premises.empty()) {
expr* e = 0;
VERIFY(asm2dep.find(premises.pop().index(), e));
conj.push_back(e);
}
conseq = m.mk_implies(mk_and(conj), val);
return true;
}
void internalize_value(sat::literal_vector const& value, expr* v, expr_ref& val) {
bv_util bvutil(m);
if (is_uninterp_const(v) && m.is_bool(v)) {
SASSERT(value.size() == 1);
val = value[0].sign() ? m.mk_not(v) : v;
}
else if (is_uninterp_const(v) && bvutil.is_bv_sort(m.get_sort(v))) {
SASSERT(value.size() == bvutil.get_bv_size(v));
rational r(0);
for (unsigned i = 0; i < value.size(); ++i) {
if (!value[i].sign()) {
r += rational(2).expt(i);
}
}
val = m.mk_eq(v, bvutil.mk_numeral(r, value.size()));
}
else {
UNREACHABLE();
}
}
lbool internalize_formulas() {
if (m_fmls_head == m_fmls.size()) {
return l_true;
@ -395,13 +531,17 @@ private:
SASSERT(dep2asm.size() == m_asms.size());
}
void extract_core(dep2asm_t& dep2asm) {
u_map<expr*> asm2dep;
void extract_asm2dep(dep2asm_t const& dep2asm, u_map<expr*>& asm2dep) {
dep2asm_t::iterator it = dep2asm.begin(), end = dep2asm.end();
for (; it != end; ++it) {
expr* e = it->m_key;
asm2dep.insert(it->m_value.index(), e);
}
}
void extract_core(dep2asm_t& dep2asm) {
u_map<expr*> asm2dep;
extract_asm2dep(dep2asm, asm2dep);
sat::literal_vector const& core = m_solver.get_core();
TRACE("sat",
dep2asm_t::iterator it2 = dep2asm.begin();

View file

@ -239,6 +239,18 @@ namespace sat {
}
return result;
}
literal_set& operator=(literal_vector const& v) {
reset();
for (unsigned i = 0; i < v.size(); ++i) insert(v[i]);
return *this;
}
literal_set& operator=(literal_set const& other) {
if (this != &other) {
m_set = other.m_set;
}
return *this;
}
void insert(literal l) { m_set.insert(l.index()); }
void remove(literal l) { m_set.remove(l.index()); }
literal pop() { return to_literal(m_set.erase()); }