3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-29 20:05:51 +00:00

delay internalize (#4714)

* adding array solver

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* use default in model construction

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* debug delay internalization

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* bv

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* arrays

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* get rid of implied values and bounds

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* redo egraph

* remove out

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remove files

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-09-28 19:24:16 -07:00 committed by GitHub
parent 25724401cf
commit 367e5fdd52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 1343 additions and 924 deletions

View file

@ -37,11 +37,11 @@ namespace bv {
};
class solver::bit_occs_trail : public trail<euf::solver> {
bit_atom& a;
atom& a;
var_pos_occ* m_occs;
public:
bit_occs_trail(solver& s, bit_atom& a): a(a), m_occs(a.m_occs) {}
bit_occs_trail(solver& s, atom& a): a(a), m_occs(a.m_occs) {}
virtual void undo(euf::solver& euf) {
IF_VERBOSE(1, verbose_stream() << "add back occurrences " << & a << "\n");
@ -134,7 +134,7 @@ namespace bv {
/**
*\brief v[idx] = ~v'[idx], then v /= v' is a theory axiom.
*/
void solver::find_new_diseq_axioms(bit_atom& a, theory_var v, unsigned idx) {
void solver::find_new_diseq_axioms(atom& a, theory_var v, unsigned idx) {
if (!get_config().m_bv_eq_axioms)
return;
literal l = m_bits[v][idx];
@ -180,12 +180,8 @@ namespace bv {
}
}
else if (m.is_bool(e) && (a = m_bool_var2atom.get(expr2literal(e).var(), nullptr))) {
if (a->is_bit()) {
for (var_pos vp : a->to_bit())
out << " " << var2enode(vp.first)->get_expr_id() << "[" << vp.second << "]";
}
else
out << "def-atom";
for (var_pos vp : *a)
out << " " << var2enode(vp.first)->get_expr_id() << "[" << vp.second << "]";
}
else
out << " " << mk_bounded_pp(e, m, 1);
@ -269,7 +265,7 @@ namespace bv {
void solver::get_antecedents(literal l, sat::ext_justification_idx idx, literal_vector& r, bool probing) {
auto& c = bv_justification::from_index(idx);
TRACE("bv", display_constraint(tout, idx););
TRACE("bv", display_constraint(tout, idx) << "\n";);
switch (c.m_kind) {
case bv_justification::kind_t::eq2bit:
SASSERT(s().value(c.m_antecedent) == l_true);
@ -389,12 +385,10 @@ namespace bv {
void solver::asserted(literal l) {
atom* a = get_bv2a(l.var());
TRACE("bv", tout << "asserted: " << l << "\n";);
if (a && a->is_bit()) {
if (a) {
force_push();
m_prop_queue.push_back(propagation_item(&a->to_bit()));
}
else if (a && a->is_eq()) {
for (auto p : a->to_eq().m_eqs) {
m_prop_queue.push_back(propagation_item(a));
for (auto p : a->m_bit2occ) {
del_eq_occurs(p.first, p.second);
}
}
@ -422,7 +416,6 @@ namespace bv {
++num_eq_assigned;
}
}
IF_VERBOSE(20, verbose_stream() << "atoms: " << num_atoms << " eqs: " << num_eqs << " atoms-assigned:" << num_assigned << " eqs-assigned: " << num_eq_assigned << " lits: " << num_lit_assigned << "\n");
}
else
propagate_bits(p.m_vp);
@ -495,20 +488,39 @@ namespace bv {
return num_assigned > 0;
}
/**
* Check each delay internalized bit-vector operation for compliance.
*
* TBD: add model-repair attempt after cheap propagation axioms have been added
*/
sat::check_result solver::check() {
force_push();
SASSERT(m_prop_queue.size() == m_prop_queue_head);
bool ok = true;
for (auto kv : m_delay_internalize) {
if (ctx.is_relevant(kv.m_key) &&
kv.m_value == internalize_mode::init_bits_i &&
!check_delay_internalized(expr2enode(kv.m_key)))
svector<std::pair<expr*, internalize_mode>> delay;
for (auto kv : m_delay_internalize)
delay.push_back(std::make_pair(kv.m_key, kv.m_value));
flet<bool> _cheap1(m_cheap_axioms, true);
for (auto kv : delay)
if (!check_delay_internalized(kv.first))
ok = false;
}
return ok ? sat::check_result::CR_DONE : sat::check_result::CR_CONTINUE;
if (!ok)
return sat::check_result::CR_CONTINUE;
// if (repair_model()) return sat::check_result::DONE;
flet<bool> _cheap2(m_cheap_axioms, false);
for (auto kv : delay)
if (!check_delay_internalized(kv.first))
ok = false;
if (!ok)
return sat::check_result::CR_CONTINUE;
return sat::check_result::CR_DONE;
}
void solver::push_core() {
TRACE("bv", tout << "push: " << get_num_vars() << "@" << m_prop_queue_lim.size() << "\n";);
th_euf_solver::push_core();
m_prop_queue_lim.push_back(m_prop_queue.size());
}
@ -523,22 +535,18 @@ namespace bv {
m_bits.shrink(old_sz);
m_wpos.shrink(old_sz);
m_zero_one_bits.shrink(old_sz);
TRACE("bv", tout << "num vars " << old_sz << "@" << m_prop_queue_lim.size() << "\n";);
}
void solver::pre_simplify() {}
void solver::simplify() {
m_ackerman.propagate();
}
bool solver::set_root(literal l, literal r) {
atom* a = get_bv2a(l.var());
atom* b = get_bv2a(r.var());
if (!a || !a->is_bit())
if (!a)
return true;
if (b && !b->is_bit())
return false;
for (auto vp : a->to_bit()) {
for (auto vp : *a) {
sat::literal l2 = m_bits[vp.first][vp.second];
if (l2.var() == r.var())
continue;
@ -549,8 +557,8 @@ namespace bv {
m_bits[vp.first][vp.second] = r2;
set_bit_eh(vp.first, r2, vp.second);
}
ctx.push(bit_occs_trail(*this, a->to_bit()));
a->to_bit().m_occs = nullptr;
ctx.push(bit_occs_trail(*this, *a));
a->m_occs = nullptr;
// validate_atoms();
return true;
}
@ -621,8 +629,7 @@ namespace bv {
return out << "bv <- v" << v1 << "[" << cidx << "] != v" << v2 << "[" << cidx << "] " << m_bits[v1][cidx] << " != " << m_bits[v2][cidx];
}
case bv_justification::kind_t::ne2bit:
return out << "bv <- " << m_bits[v1] << " != " << m_bits[v2] << " @" << cidx;
break;
return out << "bv <- " << m_bits[v1] << " != " << m_bits[v2] << " @" << cidx;
default:
UNREACHABLE();
break;
@ -643,7 +650,7 @@ namespace bv {
sat::extension* solver::copy(sat::solver* s) { UNREACHABLE(); return nullptr; }
euf::th_solver* solver::fresh(sat::solver* s, euf::solver& ctx) {
euf::th_solver* solver::clone(sat::solver* s, euf::solver& ctx) {
bv::solver* result = alloc(bv::solver, ctx, get_id());
ast_translation tr(m, ctx.get_manager());
for (unsigned i = 0; i < get_num_vars(); ++i) {
@ -664,22 +671,18 @@ namespace bv {
if (!a)
continue;
if (a->is_bit()) {
bit_atom* new_a = new (result->get_region()) bit_atom();
m_bool_var2atom.setx(i, new_a, nullptr);
for (auto vp : a->to_bit())
new_a->m_occs = new (result->get_region()) var_pos_occ(vp.first, vp.second, new_a->m_occs);
for (auto const& occ : a->to_bit().eqs()) {
expr* e = occ.m_node->get_expr();
expr_ref e2(tr(e), tr.to());
euf::enode* n = ctx.get_enode(e2);
new_a->m_eqs = new (result->get_region()) eq_occurs(occ.m_bv1, occ.m_bv2, occ.m_idx, occ.m_v1, occ.m_v2, occ.m_literal, n, new_a->m_eqs);
}
}
else {
def_atom* new_a = new (result->get_region()) def_atom(a->to_def().m_var, a->to_def().m_def);
m_bool_var2atom.setx(i, new_a, nullptr);
atom* new_a = new (result->get_region()) atom();
m_bool_var2atom.setx(i, new_a, nullptr);
for (auto vp : *a)
new_a->m_occs = new (result->get_region()) var_pos_occ(vp.first, vp.second, new_a->m_occs);
for (auto const& occ : a->eqs()) {
expr* e = occ.m_node->get_expr();
expr_ref e2(tr(e), tr.to());
euf::enode* n = ctx.get_enode(e2);
new_a->m_eqs = new (result->get_region()) eq_occurs(occ.m_bv1, occ.m_bv2, occ.m_idx, occ.m_v1, occ.m_v2, occ.m_literal, n, new_a->m_eqs);
}
new_a->m_def = a->m_def;
new_a->m_var = a->m_var;
validate_atoms();
}
return result;
@ -783,9 +786,7 @@ namespace bv {
return sat::justification::mk_ext_justification(s().scope_lvl(), constraint->to_index());
}
bool solver::assign_bit(literal consequent, theory_var v1, theory_var v2, unsigned idx, literal antecedent, bool propagate_eqc) {
m_stats.m_num_eq2bit++;
SASSERT(ctx.s().value(antecedent) == l_true);
SASSERT(m_bits[v2][idx].var() == consequent.var());
@ -801,8 +802,8 @@ namespace bv {
find_wpos(v2);
bool_var cv = consequent.var();
atom* a = get_bv2a(cv);
if (a && a->is_bit())
for (auto curr : a->to_bit())
if (a)
for (auto curr : *a)
if (propagate_eqc || find(curr.first) != find(v2) || curr.second != idx)
m_prop_queue.push_back(propagation_item(curr));
return true;