mirror of
https://github.com/Z3Prover/z3
synced 2026-03-20 20:05:51 +00:00
Port throttle and soundness fixes from master
- Fix soundness: pop incomplete lemma from m_lemmas on add_lemma failure - Gracefully handle root atoms in add_lemma - Throttle check_assignment with failure counter (decrement on success) - Add arith.nl.nra_check_assignment parameter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
77d81de03f
commit
6c27140bc9
4 changed files with 62 additions and 41 deletions
|
|
@ -1330,10 +1330,14 @@ lbool core::check(unsigned level) {
|
|||
return l_false;
|
||||
}
|
||||
|
||||
if (no_effect()) {
|
||||
if (no_effect() && params().arith_nl_nra_check_assignment() && m_check_assignment_fail_cnt < 10) {
|
||||
scoped_limits sl(m_reslim);
|
||||
sl.push_child(&m_nra_lim);
|
||||
ret = m_nra.check_assignment();
|
||||
if (ret != l_true)
|
||||
++m_check_assignment_fail_cnt;
|
||||
else
|
||||
--m_check_assignment_fail_cnt;
|
||||
}
|
||||
|
||||
if (no_effect() && should_run_bounded_nlsat())
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ class core {
|
|||
|
||||
unsigned m_nlsat_delay = 0;
|
||||
unsigned m_nlsat_delay_bound = 0;
|
||||
unsigned m_check_assignment_fail_cnt = 0;
|
||||
|
||||
bool should_run_bounded_nlsat();
|
||||
lbool bounded_nlsat();
|
||||
|
|
|
|||
|
|
@ -448,48 +448,63 @@ struct solver::imp {
|
|||
lbool add_lemma(nlsat::literal_vector const &clause) {
|
||||
u_map<lp::lpvar> nl2lp = reverse_lp2nl();
|
||||
polynomial::manager &pm = m_nlsat->pm();
|
||||
nla::lemma_builder lemma(m_nla_core, __FUNCTION__);
|
||||
for (nlsat::literal l : clause) {
|
||||
if (m_literal2constraint.get((~l).index(), lp::null_ci) != lp::null_ci) {
|
||||
auto ci = m_literal2constraint[(~l).index()];
|
||||
lp::explanation ex;
|
||||
ex.push_back(ci);
|
||||
lemma &= ex;
|
||||
continue;
|
||||
}
|
||||
nlsat::atom *a = m_nlsat->bool_var2atom(l.var());
|
||||
SASSERT(!a->is_root_atom());
|
||||
SASSERT(a->is_ineq_atom());
|
||||
auto &ia = *to_ineq_atom(a);
|
||||
if (ia.size() != 1) {
|
||||
return l_undef; // factored polynomials not handled here
|
||||
}
|
||||
polynomial::polynomial const *p = ia.p(0);
|
||||
rational bound(0);
|
||||
lp::lar_term t;
|
||||
process_polynomial_check_assignment(p, bound, nl2lp, t);
|
||||
lbool result = l_false;
|
||||
{
|
||||
nla::lemma_builder lemma(m_nla_core, __FUNCTION__);
|
||||
for (nlsat::literal l : clause) {
|
||||
if (m_literal2constraint.get((~l).index(), lp::null_ci) != lp::null_ci) {
|
||||
auto ci = m_literal2constraint[(~l).index()];
|
||||
lp::explanation ex;
|
||||
ex.push_back(ci);
|
||||
lemma &= ex;
|
||||
continue;
|
||||
}
|
||||
nlsat::atom *a = m_nlsat->bool_var2atom(l.var());
|
||||
if (a->is_root_atom()) {
|
||||
result = l_undef;
|
||||
break;
|
||||
}
|
||||
SASSERT(a->is_ineq_atom());
|
||||
auto &ia = *to_ineq_atom(a);
|
||||
if (ia.size() != 1) {
|
||||
result = l_undef; // factored polynomials not handled here
|
||||
break;
|
||||
}
|
||||
polynomial::polynomial const *p = ia.p(0);
|
||||
rational bound(0);
|
||||
lp::lar_term t;
|
||||
process_polynomial_check_assignment(p, bound, nl2lp, t);
|
||||
|
||||
nla::ineq inq(lp::lconstraint_kind::EQ, t, bound); // initial value overwritten in cases below
|
||||
switch (a->get_kind()) {
|
||||
case nlsat::atom::EQ:
|
||||
inq = nla::ineq(l.sign() ? lp::lconstraint_kind::NE : lp::lconstraint_kind::EQ, t, bound);
|
||||
break;
|
||||
case nlsat::atom::LT:
|
||||
inq = nla::ineq(l.sign() ? lp::lconstraint_kind::GE : lp::lconstraint_kind::LT, t, bound);
|
||||
break;
|
||||
case nlsat::atom::GT:
|
||||
inq = nla::ineq(l.sign() ? lp::lconstraint_kind::LE : lp::lconstraint_kind::GT, t, bound);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return l_undef;
|
||||
nla::ineq inq(lp::lconstraint_kind::EQ, t, bound); // initial value overwritten in cases below
|
||||
switch (a->get_kind()) {
|
||||
case nlsat::atom::EQ:
|
||||
inq = nla::ineq(l.sign() ? lp::lconstraint_kind::NE : lp::lconstraint_kind::EQ, t, bound);
|
||||
break;
|
||||
case nlsat::atom::LT:
|
||||
inq = nla::ineq(l.sign() ? lp::lconstraint_kind::GE : lp::lconstraint_kind::LT, t, bound);
|
||||
break;
|
||||
case nlsat::atom::GT:
|
||||
inq = nla::ineq(l.sign() ? lp::lconstraint_kind::LE : lp::lconstraint_kind::GT, t, bound);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
result = l_undef;
|
||||
break;
|
||||
}
|
||||
if (result == l_undef)
|
||||
break;
|
||||
if (m_nla_core.ineq_holds(inq)) {
|
||||
result = l_undef;
|
||||
break;
|
||||
}
|
||||
lemma |= inq;
|
||||
}
|
||||
if (m_nla_core.ineq_holds(inq))
|
||||
return l_undef;
|
||||
lemma |= inq;
|
||||
}
|
||||
this->m_nla_core.m_check_feasible = true;
|
||||
return l_false;
|
||||
if (result == l_false)
|
||||
this->m_nla_core.m_check_feasible = true;
|
||||
} // lemma_builder destructor runs here
|
||||
if (result == l_undef)
|
||||
m_nla_core.m_lemmas.pop_back(); // discard incomplete lemma
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue