3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-10-08 08:51:55 +00:00

retrieve both bounds and explanations recursively

This commit is contained in:
Nikolaj Bjorner 2025-09-28 13:46:22 +03:00
parent 360de4af03
commit e684537b01
2 changed files with 56 additions and 37 deletions

View file

@ -36,7 +36,10 @@
namespace nla { namespace nla {
stellensatz::stellensatz(core* core) : common(core), m_solver(*this), m_coi(*core) {} stellensatz::stellensatz(core* core) :
common(core),
m_solver(*this),
m_coi(*core) {}
lbool stellensatz::saturate() { lbool stellensatz::saturate() {
lp::explanation ex; lp::explanation ex;
@ -55,7 +58,8 @@ namespace nla {
m_mon2vars.reset(); m_mon2vars.reset();
m_values.reset(); m_values.reset();
m_resolvents.reset(); m_resolvents.reset();
m_new_mul_constraints.reset(); m_old_constraints.reset();
m_new_bounds.reset();
m_to_refine.reset(); m_to_refine.reset();
m_coi.init(); m_coi.init();
init_vars(); init_vars();
@ -123,42 +127,53 @@ namespace nla {
auto& lra = c().lra_solver(); auto& lra = c().lra_solver();
lp::explanation ex2; lp::explanation ex2;
lemma_builder new_lemma(c(), "stellensatz"); lemma_builder new_lemma(c(), "stellensatz");
for (auto p : ex1) { m_processed_constraints.reset();
auto dep = m_ci2dep.get(p.ci(), nullptr); for (auto p : ex1)
m_solver.lra().push_explanation(dep, ex2); explain_constraint(new_lemma, p.ci(), ex2);
if (!m_new_mul_constraints.contains(p.ci()))
continue;
auto const& bounds = m_new_mul_constraints[p.ci()];
for (auto const& b : bounds) {
if (std::holds_alternative<u_dependency*>(b)) {
auto dep = *std::get_if<u_dependency*>(&b);
m_solver.lra().push_explanation(dep, ex2);
}
else {
auto [v, k, rhs] = *std::get_if<bound>(&b);
k = negate(k);
if (m_solver.lra().var_is_int(v)) {
if (k == lp::lconstraint_kind::GT) {
rhs += 1;
k = lp::lconstraint_kind::GE;
}
if (k == lp::lconstraint_kind::LT) {
rhs -= 1;
k = lp::lconstraint_kind::LE;
}
}
new_lemma |= ineq(v, k, rhs);
}
}
}
new_lemma &= ex2; new_lemma &= ex2;
IF_VERBOSE(5, verbose_stream() << "unsat \n" << new_lemma << "\n"); IF_VERBOSE(5, verbose_stream() << "unsat \n" << new_lemma << "\n");
TRACE(arith, tout << "unsat\n" << new_lemma << "\n"); TRACE(arith, tout << "unsat\n" << new_lemma << "\n");
c().lra_solver().settings().stats().m_nla_stellensatz++; c().lra_solver().settings().stats().m_nla_stellensatz++;
} }
//
// a constraint can be explained by a set of bounds used as assumptions for the constraint
// and by an original constraint.
//
void stellensatz::explain_constraint(lemma_builder& new_lemma, lp::constraint_index ci, lp::explanation& ex) {
if (m_processed_constraints.contains(ci))
return;
m_processed_constraints.insert(ci);
auto dep = m_ci2dep[ci];
m_solver.lra().push_explanation(dep, ex);
lp::constraint_index old_ci;
if (m_old_constraints.find(ci, old_ci))
explain_constraint(new_lemma, old_ci, ex);
if (!m_new_bounds.contains(ci))
return;
auto const &bounds = m_new_bounds[ci];
for (auto const &b : bounds) {
if (std::holds_alternative<u_dependency *>(b)) {
auto dep = *std::get_if<u_dependency *>(&b);
m_solver.lra().push_explanation(dep, ex);
} else {
auto [v, k, rhs] = *std::get_if<bound>(&b);
k = negate(k);
if (m_solver.lra().var_is_int(v)) {
if (k == lp::lconstraint_kind::GT) {
rhs += 1;
k = lp::lconstraint_kind::GE;
}
if (k == lp::lconstraint_kind::LT) {
rhs -= 1;
k = lp::lconstraint_kind::LE;
}
}
new_lemma |= ineq(v, k, rhs);
}
}
}
// //
// Emulate linearization within stellensatz to enforce simple axioms. // Emulate linearization within stellensatz to enforce simple axioms.
// Incremental linearization in the main procedure produces new atoms that are pushed to lemmas // Incremental linearization in the main procedure produces new atoms that are pushed to lemmas
@ -338,7 +353,7 @@ namespace nla {
m_values.push_back(value(t)); m_values.push_back(value(t));
auto new_ci = m_solver.lra().add_var_bound(ti, k, rhs); auto new_ci = m_solver.lra().add_var_bound(ti, k, rhs);
SASSERT(m_values.size() - 1 == ti); SASSERT(m_values.size() - 1 == ti);
m_new_mul_constraints.insert(new_ci, bounds); m_new_bounds.insert(new_ci, bounds);
m_ci2dep.setx(new_ci, nullptr, nullptr); m_ci2dep.setx(new_ci, nullptr, nullptr);
return new_ci; return new_ci;
} }
@ -346,7 +361,7 @@ namespace nla {
lp::constraint_index stellensatz::add_ineq(bound_justifications const& bounds, lpvar j, lp::lconstraint_kind k, lp::constraint_index stellensatz::add_ineq(bound_justifications const& bounds, lpvar j, lp::lconstraint_kind k,
rational const& rhs) { rational const& rhs) {
auto new_ci = m_solver.lra().add_var_bound(j, k, rhs); auto new_ci = m_solver.lra().add_var_bound(j, k, rhs);
m_new_mul_constraints.insert(new_ci, bounds); m_new_bounds.insert(new_ci, bounds);
m_ci2dep.setx(new_ci, nullptr, nullptr); m_ci2dep.setx(new_ci, nullptr, nullptr);
return new_ci; return new_ci;
} }
@ -454,7 +469,8 @@ namespace nla {
IF_VERBOSE(4, display_constraint(verbose_stream(), old_ci) << " -> "; IF_VERBOSE(4, display_constraint(verbose_stream(), old_ci) << " -> ";
display_constraint(verbose_stream(), new_lhs.coeffs_as_vector(), k, new_rhs) << "\n"); display_constraint(verbose_stream(), new_lhs.coeffs_as_vector(), k, new_rhs) << "\n");
insert_monomials_from_constraint(new_ci); insert_monomials_from_constraint(new_ci);
m_ci2dep.setx(new_ci, m_ci2dep.get(old_ci, nullptr), nullptr); m_ci2dep.setx(new_ci, nullptr, nullptr);
m_old_constraints.insert(new_ci, old_ci);
} }
// //
@ -541,7 +557,7 @@ namespace nla {
return; return;
auto const& con = m_solver.lra().constraints()[ci]; auto const& con = m_solver.lra().constraints()[ci];
for (auto [coeff, v] : con.coeffs()) for (auto [coeff, v] : con.coeffs())
if (c().is_monic_var(v)) if (m_mon2vars.contains(v))
m_to_refine.insert(v); m_to_refine.insert(v);
} }

View file

@ -42,7 +42,8 @@ namespace nla {
using bound_justifications = vector<bound_justification>; using bound_justifications = vector<bound_justification>;
coi m_coi; coi m_coi;
u_map<bound_justifications> m_new_mul_constraints; u_map<bound_justifications> m_new_bounds;
u_map<lp::constraint_index> m_old_constraints;
indexed_uint_set m_to_refine; indexed_uint_set m_to_refine;
ptr_vector<u_dependency> m_ci2dep; ptr_vector<u_dependency> m_ci2dep;
vector<rational> m_values; vector<rational> m_values;
@ -106,6 +107,8 @@ namespace nla {
// lemmas // lemmas
void add_lemma(lp::explanation const& ex); void add_lemma(lp::explanation const& ex);
indexed_uint_set m_processed_constraints;
void explain_constraint(lemma_builder& new_lemma, lp::constraint_index ci, lp::explanation &ex);
std::ostream& display(std::ostream& out) const; std::ostream& display(std::ostream& out) const;
std::ostream& display_product(std::ostream& out, svector<lpvar> const& vars) const; std::ostream& display_product(std::ostream& out, svector<lpvar> const& vars) const;