diff --git a/src/math/polysat/saturation.cpp b/src/math/polysat/saturation.cpp index 65c46d19a..c6405e0c5 100644 --- a/src/math/polysat/saturation.cpp +++ b/src/math/polysat/saturation.cpp @@ -1199,6 +1199,10 @@ namespace polysat { * - then index on patterns or features of literals? */ bool saturation::has_upper_bound(pvar x, conflict& core, rational& bound, signed_constraint& x_le_bound) { + + bool found = s.m_viable.has_upper_bound(x, bound, x_le_bound); + verbose_stream() << "found " << found << "\n"; + auto& m = s.var2pdd(x); pdd y = s.var(x); for (auto const& c : core) { @@ -1223,6 +1227,10 @@ namespace polysat { } bool saturation::has_lower_bound(pvar x, conflict& core, rational& bound, signed_constraint& x_ge_bound) { + + bool found = s.m_viable.has_lower_bound(x, bound, x_ge_bound); + verbose_stream() << "found " << found << "\n"; + auto& m = s.var2pdd(x); pdd y = s.var(x); for (auto const& c : core) { @@ -1314,10 +1322,9 @@ namespace polysat { pdd b = a, c = a, y = a; rational b_val, c_val, y_val, x_bound; signed_constraint x_ge_bound, x_le_bound, b_bound, ax_bound; - if (is_AxB_l_Y(x, a_l_b, a, b, y) && y.is_val() && s.try_eval(b, b_val) && !y.is_zero() && !a.is_val()) { + if (is_AxB_l_Y(x, a_l_b, a, b, y) && s.try_eval(y, y_val) && s.try_eval(b, b_val) && !y_val.is_zero() && !a.is_val()) { verbose_stream() << a_l_b << " a " << a << " b " << b << " := " << dd::val_pp(m, b_val, false) << " y " << y << "\n"; SASSERT(!a.is_zero()); - y_val = y.val(); // define c := -b c = -b; diff --git a/src/math/polysat/viable.cpp b/src/math/polysat/viable.cpp index ebfcb81fb..66a0ac40c 100644 --- a/src/math/polysat/viable.cpp +++ b/src/math/polysat/viable.cpp @@ -643,6 +643,43 @@ namespace polysat { return query(v, hi); } + bool viable::has_upper_bound(pvar v, rational& out_hi, signed_constraint& out_c) { + entry const* first = m_units[v]; + entry const* e = first; + do { + if (!e->refined) { + verbose_stream() << "has-upper-bound " << e->src << " " << e->interval << "\n"; + auto const& lo = e->interval.lo(); + auto const& hi = e->interval.hi(); + if (lo.is_val() && hi.is_val() && lo.val() > hi.val()) { + out_c = e->src; + out_hi = lo.val() - 1; + return true; + } + } + e = e->next(); + } + while (e != first); + + return false; + } + + bool viable::has_lower_bound(pvar v, rational& out_hi, signed_constraint& out_c) { + entry const* first = m_units[v]; + entry const* e = first; + do { + if (!e->refined) { + verbose_stream() << "has-upper-bound " << e->src << " " << e->interval << "\n"; + } + e = e->next(); + } + while (e != first); + + return false; + + return false; + } + template lbool viable::query(pvar v, typename query_result::result_t& result) { // max number of interval refinements before falling back to the univariate solver diff --git a/src/math/polysat/viable.h b/src/math/polysat/viable.h index ce76eae97..cb1feb822 100644 --- a/src/math/polysat/viable.h +++ b/src/math/polysat/viable.h @@ -184,6 +184,19 @@ namespace polysat { */ lbool max_viable(pvar v, rational& out_hi); + + /** + * Query for an upper bound literal for v together with justification. + * @return true if a non-trivial upper bound is found, return justifying constraint. + */ + bool has_upper_bound(pvar v, rational& out_hi, signed_constraint& out_c); + + /** + * Query for an lower bound literal for v together with justification. + * @return true if a non-trivial lower bound is found, return justifying constraint. + */ + bool has_lower_bound(pvar v, rational& out_hi, signed_constraint& out_c); + /** * Find a next viable value for variable. */