mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 12:08:18 +00:00
add facility to check for missing propagations
This commit is contained in:
parent
cafe3acff1
commit
bdac86501d
|
@ -61,6 +61,9 @@ namespace nla {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEBUG_CODE(for (auto e : m_solver.equations()) check_missing_propagation(*e););
|
||||||
|
|
||||||
|
|
||||||
if (m_quota > 0)
|
if (m_quota > 0)
|
||||||
--m_quota;
|
--m_quota;
|
||||||
|
|
||||||
|
@ -125,11 +128,11 @@ namespace nla {
|
||||||
typedef lp::lar_term term;
|
typedef lp::lar_term term;
|
||||||
bool grobner::propagate_fixed(const dd::solver::equation& eq) {
|
bool grobner::propagate_fixed(const dd::solver::equation& eq) {
|
||||||
dd::pdd const& p = eq.poly();
|
dd::pdd const& p = eq.poly();
|
||||||
//IF_VERBOSE(0, verbose_stream() << p << "\n");
|
|
||||||
if (p.is_unary()) {
|
if (p.is_unary()) {
|
||||||
unsigned v = p.var();
|
unsigned v = p.var();
|
||||||
if (c().var_is_fixed(v))
|
if (c().var_is_fixed(v))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ineq new_eq(v, llc::EQ, rational::zero());
|
ineq new_eq(v, llc::EQ, rational::zero());
|
||||||
if (c().ineq_holds(new_eq))
|
if (c().ineq_holds(new_eq))
|
||||||
return false;
|
return false;
|
||||||
|
@ -147,12 +150,19 @@ namespace nla {
|
||||||
rational d = lcm(denominator(a), denominator(b));
|
rational d = lcm(denominator(a), denominator(b));
|
||||||
a *= d;
|
a *= d;
|
||||||
b *= d;
|
b *= d;
|
||||||
|
#if 0
|
||||||
|
c().lra.update_column_type_and_bound(v, lp::lconstraint_kind::EQ, b/a, eq.dep());
|
||||||
|
lp::explanation exp;
|
||||||
|
explain(eq, exp);
|
||||||
|
c().add_fixed_equality(c().lra.column_to_reported_index(v), b/a, exp);
|
||||||
|
#else
|
||||||
ineq new_eq(term(a, v), llc::EQ, b);
|
ineq new_eq(term(a, v), llc::EQ, b);
|
||||||
if (c().ineq_holds(new_eq))
|
if (c().ineq_holds(new_eq))
|
||||||
return false;
|
return false;
|
||||||
new_lemma lemma(c(), "pdd-eq");
|
new_lemma lemma(c(), "pdd-eq");
|
||||||
add_dependencies(lemma, eq);
|
add_dependencies(lemma, eq);
|
||||||
lemma |= new_eq;
|
lemma |= new_eq;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,15 +203,19 @@ namespace nla {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void grobner::explain(const dd::solver::equation& eq, lp::explanation& exp) {
|
||||||
void grobner::add_dependencies(new_lemma& lemma, const dd::solver::equation& eq) {
|
|
||||||
lp::explanation ex;
|
|
||||||
u_dependency_manager dm;
|
u_dependency_manager dm;
|
||||||
vector<unsigned, false> lv;
|
vector<unsigned, false> lv;
|
||||||
dm.linearize(eq.dep(), lv);
|
dm.linearize(eq.dep(), lv);
|
||||||
for (unsigned ci : lv)
|
for (unsigned ci : lv)
|
||||||
ex.push_back(ci);
|
exp.push_back(ci);
|
||||||
lemma &= ex;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void grobner::add_dependencies(new_lemma& lemma, const dd::solver::equation& eq) {
|
||||||
|
lp::explanation exp;
|
||||||
|
explain(eq, exp);
|
||||||
|
lemma &= exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void grobner::configure() {
|
void grobner::configure() {
|
||||||
|
@ -280,6 +294,10 @@ namespace nla {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool grobner::is_conflicting(const dd::solver::equation& e) {
|
bool grobner::is_conflicting(const dd::solver::equation& e) {
|
||||||
|
for (auto j : e.poly().free_vars())
|
||||||
|
if (lra.column_is_free(j))
|
||||||
|
return false;
|
||||||
|
|
||||||
auto& di = c().m_intervals.get_dep_intervals();
|
auto& di = c().m_intervals.get_dep_intervals();
|
||||||
dd::pdd_interval eval(di);
|
dd::pdd_interval eval(di);
|
||||||
eval.var2interval() = [this](lpvar j, bool deps, scoped_dep_interval& a) {
|
eval.var2interval() = [this](lpvar j, bool deps, scoped_dep_interval& a) {
|
||||||
|
@ -549,4 +567,16 @@ namespace nla {
|
||||||
tout << "\n");
|
tout << "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void grobner::check_missing_propagation(const dd::solver::equation& e) {
|
||||||
|
vector<dd::pdd> eqs;
|
||||||
|
eqs.push_back(e.poly());
|
||||||
|
lbool r = c().m_nra.check(eqs);
|
||||||
|
CTRACE("grobner", r == l_false, m_solver.display(tout << "missed conflict ", e););
|
||||||
|
if (r != l_true)
|
||||||
|
return;
|
||||||
|
r = c().m_nra.check_tight(e.poly());
|
||||||
|
CTRACE("grobner", r == l_false, m_solver.display(tout << "tight equality ", e););
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ namespace nla {
|
||||||
bool propagate_factorization(const dd::solver::equation& eq);
|
bool propagate_factorization(const dd::solver::equation& eq);
|
||||||
|
|
||||||
void add_dependencies(new_lemma& lemma, const dd::solver::equation& eq);
|
void add_dependencies(new_lemma& lemma, const dd::solver::equation& eq);
|
||||||
|
void explain(const dd::solver::equation& eq, lp::explanation& exp);
|
||||||
|
|
||||||
|
void check_missing_propagation(const dd::solver::equation& eq);
|
||||||
|
|
||||||
// setup
|
// setup
|
||||||
void configure();
|
void configure();
|
||||||
|
|
|
@ -206,14 +206,62 @@ struct solver::imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r == l_true)
|
||||||
|
return r;
|
||||||
|
|
||||||
IF_VERBOSE(0, verbose_stream() << "check-nra " << r << "\n";
|
IF_VERBOSE(0, verbose_stream() << "check-nra " << r << "\n";
|
||||||
m_nlsat->display(verbose_stream());
|
m_nlsat->display(verbose_stream());
|
||||||
for (auto const& [v, w] : m_lp2nl) {
|
for (auto const& [v, w] : m_lp2nl) {
|
||||||
auto& ls = m_nla_core.lra;
|
auto& ls = m_nla_core.lra;
|
||||||
if (ls.column_has_lower_bound(v))
|
if (ls.column_has_lower_bound(v))
|
||||||
verbose_stream() << w << " >= " << ls.get_lower_bound(v) << "\n";
|
verbose_stream() << "x" << w << " >= " << ls.get_lower_bound(v) << "\n";
|
||||||
if (ls.column_has_upper_bound(v))
|
if (ls.column_has_upper_bound(v))
|
||||||
verbose_stream() << w << " <= " << ls.get_upper_bound(v) << "\n";
|
verbose_stream() << "x" << w << " <= " << ls.get_upper_bound(v) << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbool check_tight(dd::pdd const& eq) {
|
||||||
|
m_zero = nullptr;
|
||||||
|
m_nlsat = alloc(nlsat::solver, m_limit, m_params, false);
|
||||||
|
m_zero = alloc(scoped_anum, am());
|
||||||
|
m_lp2nl.reset();
|
||||||
|
m_term_set.reset();
|
||||||
|
add_eq(eq);
|
||||||
|
for (auto const& [v, w] : m_lp2nl) {
|
||||||
|
auto& ls = m_nla_core.lra;
|
||||||
|
if (ls.column_has_lower_bound(v))
|
||||||
|
add_strict_lb(ls.get_lower_bound(v), w);
|
||||||
|
if (ls.column_has_upper_bound(v))
|
||||||
|
add_strict_ub(ls.get_upper_bound(v), w);
|
||||||
|
}
|
||||||
|
|
||||||
|
lbool r = l_undef;
|
||||||
|
try {
|
||||||
|
r = m_nlsat->check();
|
||||||
|
}
|
||||||
|
catch (z3_exception&) {
|
||||||
|
if (m_limit.is_canceled()) {
|
||||||
|
r = l_undef;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == l_true)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
IF_VERBOSE(0, verbose_stream() << "check-nra tight " << r << "\n";
|
||||||
|
m_nlsat->display(verbose_stream());
|
||||||
|
for (auto const& [v, w] : m_lp2nl) {
|
||||||
|
auto& ls = m_nla_core.lra;
|
||||||
|
if (ls.column_has_lower_bound(v))
|
||||||
|
verbose_stream() << "x" << w << " >= " << ls.get_lower_bound(v) << "\n";
|
||||||
|
if (ls.column_has_upper_bound(v))
|
||||||
|
verbose_stream() << "x" << w << " <= " << ls.get_upper_bound(v) << "\n";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,6 +283,13 @@ struct solver::imp {
|
||||||
m_nlsat->mk_clause(1, &lit, nullptr);
|
m_nlsat->mk_clause(1, &lit, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_strict_lb(lp::impq const& b, unsigned w) {
|
||||||
|
add_bound(b.x, w, false, nlsat::atom::kind::GT);
|
||||||
|
}
|
||||||
|
void add_strict_ub(lp::impq const& b, unsigned w) {
|
||||||
|
add_bound(b.x, w, false, nlsat::atom::kind::LT);
|
||||||
|
}
|
||||||
|
|
||||||
void add_lb(lp::impq const& b, unsigned w) {
|
void add_lb(lp::impq const& b, unsigned w) {
|
||||||
add_bound(b.x, w, b.y <= 0, b.y > 0 ? nlsat::atom::kind::GT : nlsat::atom::kind::LT);
|
add_bound(b.x, w, b.y <= 0, b.y > 0 ? nlsat::atom::kind::GT : nlsat::atom::kind::LT);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +324,8 @@ struct solver::imp {
|
||||||
m_lp2nl.insert(v, w);
|
m_lp2nl.insert(v, w);
|
||||||
}
|
}
|
||||||
polynomial::polynomial_ref vp(pm.mk_polynomial(w, 1), pm);
|
polynomial::polynomial_ref vp(pm.mk_polynomial(w, 1), pm);
|
||||||
return pm.add(lo, pm.mul(vp, hi));
|
polynomial::polynomial_ref mp(pm.mul(vp, hi), pm);
|
||||||
|
return pm.add(lo, mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_int(lp::var_index v) {
|
bool is_int(lp::var_index v) {
|
||||||
|
@ -361,6 +417,10 @@ lbool solver::check(vector<dd::pdd> const& eqs) {
|
||||||
return m_imp->check(eqs);
|
return m_imp->check(eqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbool solver::check_tight(dd::pdd const& eq) {
|
||||||
|
return m_imp->check_tight(eq);
|
||||||
|
}
|
||||||
|
|
||||||
bool solver::need_check() {
|
bool solver::need_check() {
|
||||||
return m_imp->need_check();
|
return m_imp->need_check();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,15 @@ namespace nra {
|
||||||
lbool check();
|
lbool check();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\breif Check feasibility of equalities modulo bounds constraints on their variables.
|
\brief Check feasibility of equalities modulo bounds constraints on their variables.
|
||||||
*/
|
*/
|
||||||
lbool check(vector<dd::pdd> const& eqs);
|
lbool check(vector<dd::pdd> const& eqs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Check if equality is tight.
|
||||||
|
*/
|
||||||
|
lbool check_tight(const dd::pdd& eq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
\brief determine whether nra check is needed.
|
\brief determine whether nra check is needed.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2158,7 +2158,6 @@ public:
|
||||||
if (m_nla) {
|
if (m_nla) {
|
||||||
m_nla->propagate();
|
m_nla->propagate();
|
||||||
add_lemmas();
|
add_lemmas();
|
||||||
add_equalities();
|
|
||||||
lp().collect_more_rows_for_lp_propagation();
|
lp().collect_more_rows_for_lp_propagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2193,6 +2192,7 @@ public:
|
||||||
assume_literal(i);
|
assume_literal(i);
|
||||||
for (const nla::lemma & l : m_nla->lemmas())
|
for (const nla::lemma & l : m_nla->lemmas())
|
||||||
false_case_of_check_nla(l);
|
false_case_of_check_nla(l);
|
||||||
|
add_equalities();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_propagate() const {
|
bool should_propagate() const {
|
||||||
|
|
Loading…
Reference in a new issue