From 4d1d067d42c3ea9d2928448b39695389c0e38552 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 7 Dec 2023 13:34:35 -0800 Subject: [PATCH] fix divergence reported by Guido Martinez --- src/math/lp/emonics.cpp | 15 +++++++++++++++ src/math/lp/emonics.h | 1 + src/math/lp/monic.h | 3 +++ src/math/lp/nla_core.cpp | 3 +++ 4 files changed, 22 insertions(+) diff --git a/src/math/lp/emonics.cpp b/src/math/lp/emonics.cpp index 9a9e4566b..5d0e664f2 100644 --- a/src/math/lp/emonics.cpp +++ b/src/math/lp/emonics.cpp @@ -611,4 +611,19 @@ void emonics::set_propagated(monic const& m) { m_u_f_stack.push(set_unpropagated(*this, m.var())); } +void emonics::set_bound_propagated(monic const& m) { + struct set_bound_unpropagated : public trail { + emonics& em; + unsigned var; + public: + set_bound_unpropagated(emonics& em, unsigned var): em(em), var(var) {} + void undo() override { + em[var].set_bound_propagated(false); + } + }; + SASSERT(!m.is_bound_propagated()); + (*this)[m.var()].set_bound_propagated(true); + m_u_f_stack.push(set_bound_unpropagated(*this, m.var())); +} + } diff --git a/src/math/lp/emonics.h b/src/math/lp/emonics.h index fe0b19117..55086515d 100644 --- a/src/math/lp/emonics.h +++ b/src/math/lp/emonics.h @@ -143,6 +143,7 @@ public: void after_merge_eh(unsigned r2, unsigned r1, unsigned v2, unsigned v1) {} void set_propagated(monic const& m); + void set_bound_propagated(monic const& m); // this method is required by union_find trail_stack & get_trail_stack() { return m_u_f_stack; } diff --git a/src/math/lp/monic.h b/src/math/lp/monic.h index d981b2042..19137cd31 100644 --- a/src/math/lp/monic.h +++ b/src/math/lp/monic.h @@ -59,6 +59,7 @@ class monic: public mon_eq { bool m_rsign; mutable unsigned m_visited; bool m_propagated = false; + bool m_bound_propagated = false; public: // constructors monic(lpvar v, unsigned sz, lpvar const* vs, unsigned idx): @@ -77,6 +78,8 @@ public: void sort_rvars() { std::sort(m_rvars.begin(), m_rvars.end()); } void set_propagated(bool p) { m_propagated = p; } bool is_propagated() const { return m_propagated; } + void set_bound_propagated(bool p) { m_bound_propagated = p; } + bool is_bound_propagated() const { return m_bound_propagated; } svector::const_iterator begin() const { return vars().begin(); } svector::const_iterator end() const { return vars().end(); } diff --git a/src/math/lp/nla_core.cpp b/src/math/lp/nla_core.cpp index 96f1b4a30..f36fab52e 100644 --- a/src/math/lp/nla_core.cpp +++ b/src/math/lp/nla_core.cpp @@ -1517,6 +1517,9 @@ void core::add_bounds() { for (lpvar j : m.vars()) { if (!var_is_free(j)) continue; + if (m.is_bound_propagated()) + continue; + m_emons.set_bound_propagated(m); // split the free variable (j <= 0, or j > 0), and return m_literals.push_back(ineq(j, lp::lconstraint_kind::EQ, rational::zero())); TRACE("nla_solver", print_ineq(m_literals.back(), tout) << "\n");