3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-12 02:04:43 +00:00

for Clemens: ensure fixed values are propagated after registration

Also allow to register expressions that the rewriter changes to ensure they get picked up.
This commit is contained in:
Nikolaj Bjorner 2022-01-19 14:38:11 +01:00
parent 5b0389615b
commit 0f03ef4ab0
7 changed files with 129 additions and 45 deletions

View file

@ -40,11 +40,24 @@ void theory_user_propagator::force_push() {
unsigned theory_user_propagator::add_expr(expr* e) {
force_push();
expr_ref r(m);
ctx.get_rewriter()(e, r);
if (r != e) {
r = m.mk_fresh_const("aux-expr", e->get_sort());
expr_ref eq(m.mk_eq(r, e), m);
ctx.assert_expr(eq);
ctx.internalize_assertions();
e = r;
ctx.mark_as_relevant(eq);
}
enode* n = ensure_enode(e);
if (is_attached_to_var(n))
return n->get_th_var(get_id());
theory_var v = mk_var(n);
ctx.attach_th_var(n, this, v);
literal_vector explain;
if (ctx.is_fixed(n, r, explain))
m_prop.push_back(prop_info(explain, v, r));
return v;
}
@ -118,54 +131,66 @@ bool theory_user_propagator::can_propagate() {
return m_qhead < m_prop.size();
}
void theory_user_propagator::propagate_consequence(prop_info const& prop) {
justification* js;
m_lits.reset();
m_eqs.reset();
for (unsigned id : prop.m_ids)
m_lits.append(m_id2justification[id]);
for (auto const& p : prop.m_eqs)
m_eqs.push_back(enode_pair(get_enode(p.first), get_enode(p.second)));
DEBUG_CODE(for (auto const& p : m_eqs) VERIFY(p.first->get_root() == p.second->get_root()););
DEBUG_CODE(for (unsigned id : prop.m_ids) VERIFY(m_fixed.contains(id)););
DEBUG_CODE(for (literal lit : m_lits) VERIFY(ctx.get_assignment(lit) == l_true););
TRACE("user_propagate", tout << "propagating #" << prop.m_conseq->get_id() << ": " << prop.m_conseq << "\n");
if (m.is_false(prop.m_conseq)) {
js = ctx.mk_justification(
ext_theory_conflict_justification(
get_id(), ctx.get_region(), m_lits.size(), m_lits.data(), m_eqs.size(), m_eqs.data(), 0, nullptr));
ctx.set_conflict(js);
}
else {
for (auto& lit : m_lits)
lit.neg();
for (auto const& [a,b] : m_eqs)
m_lits.push_back(~mk_eq(a->get_expr(), b->get_expr(), false));
literal lit;
if (has_quantifiers(prop.m_conseq)) {
expr_ref fn(m.mk_fresh_const("aux-literal", m.mk_bool_sort()), m);
expr_ref eq(m.mk_eq(fn, prop.m_conseq), m);
ctx.assert_expr(eq);
ctx.internalize_assertions();
lit = mk_literal(fn);
}
else
lit = mk_literal(prop.m_conseq);
ctx.mark_as_relevant(lit);
m_lits.push_back(lit);
ctx.mk_th_lemma(get_id(), m_lits);
TRACE("user_propagate", ctx.display(tout););
}
}
void theory_user_propagator::propagate_new_fixed(prop_info const& prop) {
new_fixed_eh(prop.m_var, prop.m_conseq, prop.m_lits.size(), prop.m_lits.data());
}
void theory_user_propagator::propagate() {
TRACE("user_propagate", tout << "propagating queue head: " << m_qhead << " prop queue: " << m_prop.size() << "\n");
if (m_qhead == m_prop.size())
return;
force_push();
unsigned qhead = m_qhead;
justification* js;
while (qhead < m_prop.size() && !ctx.inconsistent()) {
auto const& prop = m_prop[qhead];
m_lits.reset();
m_eqs.reset();
for (unsigned id : prop.m_ids)
m_lits.append(m_id2justification[id]);
for (auto const& p : prop.m_eqs)
m_eqs.push_back(enode_pair(get_enode(p.first), get_enode(p.second)));
DEBUG_CODE(for (auto const& p : m_eqs) VERIFY(p.first->get_root() == p.second->get_root()););
DEBUG_CODE(for (unsigned id : prop.m_ids) VERIFY(m_fixed.contains(id)););
DEBUG_CODE(for (literal lit : m_lits) VERIFY(ctx.get_assignment(lit) == l_true););
TRACE("user_propagate", tout << "propagating #" << prop.m_conseq->get_id() << ": " << prop.m_conseq << "\n");
if (m.is_false(prop.m_conseq)) {
js = ctx.mk_justification(
ext_theory_conflict_justification(
get_id(), ctx.get_region(), m_lits.size(), m_lits.data(), m_eqs.size(), m_eqs.data(), 0, nullptr));
ctx.set_conflict(js);
}
else {
for (auto& lit : m_lits)
lit.neg();
for (auto const& [a,b] : m_eqs)
m_lits.push_back(~mk_eq(a->get_expr(), b->get_expr(), false));
literal lit;
if (has_quantifiers(prop.m_conseq)) {
expr_ref fn(m.mk_fresh_const("aux-literal", m.mk_bool_sort()), m);
expr_ref eq(m.mk_eq(fn, prop.m_conseq), m);
ctx.assert_expr(eq);
ctx.internalize_assertions();
lit = mk_literal(fn);
}
else
lit = mk_literal(prop.m_conseq);
ctx.mark_as_relevant(lit);
m_lits.push_back(lit);
ctx.mk_th_lemma(get_id(), m_lits);
TRACE("user_propagate", ctx.display(tout););
}
if (prop.m_var == null_theory_var)
propagate_consequence(prop);
else
propagate_new_fixed(prop);
++m_stats.m_num_propagations;
++qhead;
}