diff --git a/src/math/lp/monomial_bounds.cpp b/src/math/lp/monomial_bounds.cpp index a89d27a9b..84af29d05 100644 --- a/src/math/lp/monomial_bounds.cpp +++ b/src/math/lp/monomial_bounds.cpp @@ -17,13 +17,14 @@ namespace nla { common(c), dep(c->m_intervals.get_dep_intervals()) {} - void monomial_bounds::operator()() { + void monomial_bounds::propagate() { for (lpvar v : c().m_to_refine) { monic const& m = c().emons()[v]; propagate(m); } } + bool monomial_bounds::is_too_big(mpq const& q) const { return rational(q).bitsize() > 256; } @@ -257,5 +258,76 @@ namespace nla { } } + void monomial_bounds::unit_propagate() { + for (auto const& m : c().m_emons) + unit_propagate(m); + } + + void monomial_bounds::unit_propagate(monic const& m) { + m_propagated.reserve(m.var() + 1, false); + if (m_propagated[m.var()]) + return; + + if (!is_linear(m)) + return; + + c().trail().push(set_bitvector_trail(m_propagated, m.var())); + + rational k = fixed_var_product(m); + + new_lemma lemma(c(), "fixed-values"); + if (k == 0) { + for (auto v : m) { + if (c().var_is_fixed(v) && c().val(v).is_zero()) { + lemma.explain_fixed(v); + break; + } + } + lemma |= ineq(m.var(), lp::lconstraint_kind::EQ, 0); + } + else { + for (auto v : m) + if (c().var_is_fixed(v)) + lemma.explain_fixed(v); + + lpvar w = non_fixed_var(m); + SASSERT(w != null_lpvar); + + lp::lar_term term; + term.add_monomial(-m.rat_sign(), m.var()); + term.add_monomial(k, w); + lemma |= ineq(term, lp::lconstraint_kind::EQ, 0); + } + + } + + bool monomial_bounds::is_linear(monic const& m) { + unsigned non_fixed = 0; + for (lpvar v : m) { + if (!c().var_is_fixed(v)) + ++non_fixed; + else if (c().val(v).is_zero()) + return true; + } + return non_fixed <= 1; + } + + + rational monomial_bounds::fixed_var_product(monic const& m) { + rational r(1); + for (lpvar v : m) { + if (c().var_is_fixed(v)) + r *= c().lra.get_column_value(v).x; + } + return r; + } + + lpvar monomial_bounds::non_fixed_var(monic const& m) { + for (lpvar v : m) + if (!c().var_is_fixed(v)) + return v; + return null_lpvar; + } + } diff --git a/src/math/lp/monomial_bounds.h b/src/math/lp/monomial_bounds.h index d82c4bebb..c728d1a4c 100644 --- a/src/math/lp/monomial_bounds.h +++ b/src/math/lp/monomial_bounds.h @@ -16,6 +16,8 @@ namespace nla { class core; class monomial_bounds : common { dep_intervals& dep; + + void var2interval(lpvar v, scoped_dep_interval& i); bool is_too_big(mpq const& q) const; bool propagate_down(monic const& m, lpvar u); @@ -27,8 +29,17 @@ namespace nla { void analyze_monomial(monic const& m, unsigned& num_free, lpvar& free_v, unsigned& power) const; bool is_free(lpvar v) const; bool is_zero(lpvar v) const; + + // monomial propagation + bool_vector m_propagated; + void unit_propagate(monic const& m); + bool is_linear(monic const& m); + rational fixed_var_product(monic const& m); + lpvar non_fixed_var(monic const& m); + public: monomial_bounds(core* core); - void operator()(); + void propagate(); + void unit_propagate(); }; } diff --git a/src/math/lp/nla_core.cpp b/src/math/lp/nla_core.cpp index 67c48cb8a..3ab89e012 100644 --- a/src/math/lp/nla_core.cpp +++ b/src/math/lp/nla_core.cpp @@ -1546,7 +1546,7 @@ lbool core::check(vector& lits, vector& l_vec) { auto no_effect = [&]() { return !done() && l_vec.empty() && lits.empty(); }; if (no_effect()) - m_monomial_bounds(); + m_monomial_bounds.propagate(); if (no_effect() && improve_bounds()) return l_false; @@ -1814,79 +1814,14 @@ bool core::improve_bounds() { void core::propagate(vector& lemmas) { // disable for now return; - - // propagate linear monomials + // propagate linear monomials lemmas.reset(); m_lemma_vec = &lemmas; - for (auto const& m : m_emons) - propagate(m, lemmas); + + m_monomial_bounds.unit_propagate(); + } -void core::propagate(monic const& m, vector& lemmas) { - m_propagated.reserve(m.var() + 1, false); - if (m_propagated[m.var()]) - return; - - if (!is_linear(m)) - return; - - trail().push(set_bitvector_trail(m_propagated, m.var())); - - rational k = fixed_var_product(m); - - new_lemma lemma(*this, "fixed-values"); - if (k == 0) { - for (auto v : m) { - if (var_is_fixed(v) && val(v).is_zero()) { - lemma.explain_fixed(v); - break; - } - } - lemma |= ineq(m.var(), lp::lconstraint_kind::EQ, 0); - } - else { - for (auto v : m) - if (var_is_fixed(v)) - lemma.explain_fixed(v); - - lpvar w = non_fixed_var(m); - SASSERT(w != null_lpvar); - - lp::lar_term term; - term.add_monomial(mpq(-1), m.var()); - term.add_monomial(k, w); - lemma |= ineq(term, lp::lconstraint_kind::EQ, 0); - } - -} - -bool core::is_linear(monic const& m) { - unsigned non_fixed = 0; - for (lpvar v : m) { - if (!var_is_fixed(v)) - ++non_fixed; - else if (val(v).is_zero()) - return true; - } - return non_fixed <= 1; -} - - -rational core::fixed_var_product(monic const& m) { - rational r(1); - for (lpvar v : m) { - if (var_is_fixed(v)) - r *= lra.get_column_value(v).x; - } - return r; -} - -lpvar core::non_fixed_var(monic const& m) { - for (lpvar v : m) - if (!var_is_fixed(v)) - return v; - return null_lpvar; -} } // end of nla diff --git a/src/math/lp/nla_core.h b/src/math/lp/nla_core.h index 297ad1641..9c96f2fbf 100644 --- a/src/math/lp/nla_core.h +++ b/src/math/lp/nla_core.h @@ -436,12 +436,6 @@ private: void save_tableau(); bool integrality_holds(); - // monomial propagation - bool_vector m_propagated; - void propagate(monic const& m, vector& lemmas); - bool is_linear(monic const& m); - rational fixed_var_product(monic const& m); - lpvar non_fixed_var(monic const& m); }; // end of core