3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-09-09 19:21:24 +00:00

add option to reduce pseudo-linear monomials

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2025-09-04 11:03:58 -07:00
parent 6eee8688c2
commit 98a9a34f2b
5 changed files with 65 additions and 27 deletions

View file

@ -1308,6 +1308,10 @@ lbool core::check() {
if (no_effect())
m_monomial_bounds.propagate();
if (no_effect() && refine_pseudo_linear())
return l_false;
{
std::function<void(void)> check1 = [&]() { if (no_effect() && run_horner) m_horner.horner_lemmas(); };
std::function<void(void)> check2 = [&]() { if (no_effect() && run_grobner) m_grobner(); };
@ -1519,6 +1523,54 @@ void core::simplify() {
}
bool core::is_pseudo_linear(monic const& m) const {
bool has_unbounded = false;
for (auto v : m.vars()) {
if (lra.column_is_bounded(v) && lra.var_is_int(v)) {
auto lb = lra.get_lower_bound(v);
auto ub = lra.get_upper_bound(v);
if (ub - lb <= rational(4))
continue;
}
if (has_unbounded)
return false;
has_unbounded = true;
}
return true;
}
bool core::refine_pseudo_linear() {
if (!params().arith_nl_reduce_pseudo_linear())
return false;
for (lpvar j : m_to_refine) {
if (is_pseudo_linear(m_emons[j])) {
refine_pseudo_linear(m_emons[j]);
return true;
}
}
return false;
}
void core::refine_pseudo_linear(monic const& m) {
lemma_builder lemma(*this, "nla-pseudo-linear");
lpvar nlvar = null_lpvar;
rational prod(1);
for (auto v : m.vars()) {
if (lra.column_is_bounded(v) && lra.var_is_int(v)) {
auto lb = lra.get_lower_bound(v);
auto ub = lra.get_upper_bound(v);
if (ub - lb <= rational(4)) {
lemma |= ineq(v, llc::NE, val(v));
prod *= val(v);
continue;
}
}
SASSERT(nlvar == null_lpvar);
nlvar = v;
}
lemma |= ineq(lp::lar_term(m.var(), rational(-prod), nlvar), llc::EQ, rational(0));
// lemma.display(verbose_stream() << "pseudo-linear lemma\n");
}

View file

@ -111,7 +111,9 @@ class core {
void check_weighted(unsigned sz, std::pair<unsigned, std::function<void(void)>>* checks);
void add_bounds();
bool refine_pseudo_linear();
bool is_pseudo_linear(monic const& m) const;
void refine_pseudo_linear(monic const& m);
public:
// constructor

View file

@ -841,22 +841,6 @@ namespace nla {
m_solver.add(p, dep);
}
bool grobner::is_pseudo_linear(unsigned_vector const& vars) const {
bool has_unbounded = false;
for (auto v : vars) {
if (c().lra.column_is_bounded(v) && c().lra.var_is_int(v)) {
auto lb = c().lra.get_lower_bound(v);
auto ub = c().lra.get_upper_bound(v);
if (ub - lb <= rational(4))
continue;
}
if (has_unbounded)
return false;
has_unbounded = true;
}
return true;
}
void grobner::add_fixed_monic(unsigned j) {
u_dependency* dep = nullptr;
dd::pdd r = m_pdd_manager.mk_val(rational(1));
@ -882,7 +866,6 @@ namespace nla {
TRACE(grobner, for (lpvar j : c().m_to_refine) print_monic(c().emons()[j], tout) << "\n";);
for (lpvar j : c().m_to_refine)
if (!is_pseudo_linear(c().emons()[j].vars()))
q.push_back(j);
while (!q.empty()) {

View file

@ -79,7 +79,7 @@ namespace nla {
void add_fixed_monic(unsigned j);
bool is_solved(dd::pdd const& p, unsigned& v, dd::pdd& r);
void add_eq(dd::pdd& p, u_dependency* dep);
bool is_pseudo_linear(unsigned_vector const& vars) const;
bool is_pseudo_linear(monic const& m) const;
const rational& val_of_fixed_var_with_deps(lpvar j, u_dependency*& dep);
dd::pdd pdd_expr(const rational& c, lpvar j, u_dependency*& dep);
dd::pdd pdd_expr(lp::lar_term const& t, u_dependency*& dep);

View file

@ -83,6 +83,7 @@ def_module_params(module_name='smt',
('arith.nl.gr_q', UINT, 10, 'grobner\'s quota'),
('arith.nl.grobner_subs_fixed', UINT, 1, '0 - no subs, 1 - substitute, 2 - substitute fixed zeros only'),
('arith.nl.grobner_expand_terms', BOOL, False, 'expand terms before computing grobner basis'),
('arith.nl.reduce_pseudo_linear', BOOL, False, 'create incremental linearization axioms for pseudo-linear monomials'),
('arith.nl.delay', UINT, 10, 'number of calls to final check before invoking bounded nlsat check'),
('arith.nl.propagate_linear_monomials', BOOL, True, 'propagate linear monomials'),
('arith.nl.optimize_bounds', BOOL, True, 'enable bounds optimization'),