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:
parent
25724401cf
commit
367e5fdd52
60 changed files with 1343 additions and 924 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue