diff --git a/src/math/lp/int_solver.cpp b/src/math/lp/int_solver.cpp index 0ab7d1e40..bd1ac5313 100644 --- a/src/math/lp/int_solver.cpp +++ b/src/math/lp/int_solver.cpp @@ -31,7 +31,7 @@ namespace lp { lra.remove_fixed_vars_from_base(); lp_assert(lia.is_feasible()); for (unsigned j : lra.r_basis()) - if (!lra.get_value(j).is_int() && lra.column_is_int(j)) + if (!lra.get_value(j).is_int() && lra.column_is_int(j)&& !lia.is_fixed(j)) patch_basic_column(j); if (!lia.has_inf_int()) { lia.settings().stats().m_patches_success++; diff --git a/src/math/lp/lar_solver.cpp b/src/math/lp/lar_solver.cpp index 1bd55b9bb..5f82516ef 100644 --- a/src/math/lp/lar_solver.cpp +++ b/src/math/lp/lar_solver.cpp @@ -22,7 +22,8 @@ namespace lp { } lar_solver::lar_solver() : - m_crossed_bounds_column(-1), + m_crossed_bounds_column(null_lpvar), + m_crossed_bounds_deps(nullptr), m_mpq_lar_core_solver(m_settings, *this), m_var_register(false), m_term_register(true), @@ -213,17 +214,10 @@ namespace lp { } void lar_solver::fill_explanation_from_crossed_bounds_column(explanation& evidence) const { - lp_assert(static_cast(get_column_type(m_crossed_bounds_column)) >= static_cast(column_type::boxed)); - lp_assert(!column_is_feasible(m_crossed_bounds_column)); - // this is the case when the lower bound is in conflict with the upper one - const ul_pair& ul = m_columns_to_ul_pairs[m_crossed_bounds_column]; svector deps; - m_dependencies.linearize(ul.upper_bound_witness(), deps); - for (auto d : deps) - evidence.add_pair(d, numeric_traits::one()); - deps.reset(); - m_dependencies.linearize(ul.lower_bound_witness(), deps); + SASSERT(m_crossed_bounds_deps != nullptr); + m_dependencies.linearize(m_crossed_bounds_deps, deps); for (auto d : deps) evidence.add_pair(d, -numeric_traits::one()); } @@ -232,7 +226,8 @@ namespace lp { m_simplex_strategy = m_settings.simplex_strategy(); m_simplex_strategy.push(); m_columns_to_ul_pairs.push(); - m_crossed_bounds_column.push(); + m_crossed_bounds_column = null_lpvar; + m_crossed_bounds_deps = nullptr; m_mpq_lar_core_solver.push(); m_term_count = m_terms.size(); m_term_count.push(); @@ -262,7 +257,8 @@ namespace lp { void lar_solver::pop(unsigned k) { TRACE("lar_solver", tout << "k = " << k << std::endl;); - m_crossed_bounds_column.pop(k); + m_crossed_bounds_column = null_lpvar; + m_crossed_bounds_deps = nullptr; unsigned n = m_columns_to_ul_pairs.peek_size(k); m_var_register.shrink(n); pop_tableau(n); @@ -1021,7 +1017,7 @@ namespace lp { void lar_solver::get_infeasibility_explanation(explanation& exp) const { exp.clear(); - if (m_crossed_bounds_column != -1) { + if (m_crossed_bounds_column != null_lpvar) { fill_explanation_from_crossed_bounds_column(exp); return; } @@ -1828,7 +1824,6 @@ namespace lp { if (is_base(j) && column_is_fixed(j)) m_fixed_base_var_set.insert(j); - TRACE("lar_solver_feas", tout << "j = " << j << " became " << (this->column_is_feasible(j) ? "feas" : "non-feas") << ", and " << (this->column_is_bounded(j) ? "bounded" : "non-bounded") << std::endl;); } @@ -1924,7 +1919,6 @@ namespace lp { } } - // clang-format on void lar_solver::update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { lp_assert(column_has_lower_bound(j) && column_has_upper_bound(j)); lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed || @@ -1937,12 +1931,14 @@ namespace lp { case LE: { auto up = numeric_pair(right_side, y_of_bound); if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { - set_infeasible_column(j); + set_infeasible_column_and_witness(j, true, dep); + } + else { + if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return; + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, dep); + insert_to_columns_with_changed_bounds(j); } - if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return; - m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; - set_upper_bound_witness(j, dep); - insert_to_columns_with_changed_bounds(j); break; } case GT: @@ -1950,25 +1946,33 @@ namespace lp { case GE: { auto low = numeric_pair(right_side, y_of_bound); if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - set_infeasible_column(j); + set_infeasible_column_and_witness(j, false, dep); + } else { + if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { + return; + } + m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; + set_lower_bound_witness(j, dep); + m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed); + insert_to_columns_with_changed_bounds(j); } - if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { - return; - } - m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; - set_lower_bound_witness(j, dep); - m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed); - insert_to_columns_with_changed_bounds(j); break; + } case EQ: { auto v = numeric_pair(right_side, zero_of_type()); - if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j] || v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { - set_infeasible_column(j); + if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]){ + set_infeasible_column_and_witness(j, false, dep); + } + else if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { + set_infeasible_column_and_witness(j, true, dep); + } + else { + set_upper_bound_witness(j, dep); + set_lower_bound_witness(j, dep); + m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; + insert_to_columns_with_changed_bounds(j); } - set_upper_bound_witness(j, dep); - set_lower_bound_witness(j, dep); - m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; break; } @@ -1979,7 +1983,7 @@ namespace lp { m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; } } - // clang-format off + void lar_solver::update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { lp_assert(column_has_lower_bound(j) && !column_has_upper_bound(j)); lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::lower_bound); @@ -1991,12 +1995,14 @@ namespace lp { case LE: { auto up = numeric_pair(right_side, y_of_bound); if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { - set_infeasible_column(j); + set_infeasible_column_and_witness(j, true, dep); + } + else { + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, dep); + m_mpq_lar_core_solver.m_column_types[j] = (up == m_mpq_lar_core_solver.m_r_lower_bounds[j] ? column_type::fixed : column_type::boxed); + insert_to_columns_with_changed_bounds(j); } - m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; - set_upper_bound_witness(j, dep); - m_mpq_lar_core_solver.m_column_types[j] = (up == m_mpq_lar_core_solver.m_r_lower_bounds[j] ? column_type::fixed : column_type::boxed); - insert_to_columns_with_changed_bounds(j); break; } case GT: @@ -2014,13 +2020,15 @@ namespace lp { case EQ: { auto v = numeric_pair(right_side, zero_of_type()); if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { - set_infeasible_column(j); + set_infeasible_column_and_witness(j, true, dep); + } + else { + set_upper_bound_witness(j, dep); + set_lower_bound_witness(j, dep); + m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + insert_to_columns_with_changed_bounds(j); } - - set_upper_bound_witness(j, dep); - set_lower_bound_witness(j, dep); - m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; break; } @@ -2051,26 +2059,29 @@ namespace lp { { auto low = numeric_pair(right_side, y_of_bound); if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - set_infeasible_column(j); + set_infeasible_column_and_witness(j, false, dep); + } + else { + m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; + set_lower_bound_witness(j, dep); + m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed); + insert_to_columns_with_changed_bounds(j); } - m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; - set_lower_bound_witness(j, dep); - m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed); - insert_to_columns_with_changed_bounds(j); - } break; case EQ: { auto v = numeric_pair(right_side, zero_of_type()); if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - set_infeasible_column(j); + set_infeasible_column_and_witness(j, false, dep); + } + else { + set_upper_bound_witness(j, dep); + set_lower_bound_witness(j, dep); + m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + insert_to_columns_with_changed_bounds(j); } - - set_upper_bound_witness(j, dep); - set_lower_bound_witness(j, dep); - m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; break; } @@ -2345,7 +2356,21 @@ namespace lp { return false; return true; } + // If lower_bound is true than the new asserted upper bound is less than the existing lower bound. + // Otherwise the new asserted lower bound is is greater than the existing upper bound. + // dep is the reason for the new bound + void lar_solver::set_infeasible_column_and_witness(unsigned j, bool lower_bound, u_dependency* dep) { + bool was_feas = column_is_feasible(j); + bool in_heap = m_mpq_lar_core_solver.m_r_solver.inf_heap().contains(j); + SASSERT(m_crossed_bounds_deps == nullptr && m_crossed_bounds_deps == nullptr); + set_status(lp_status::INFEASIBLE); + m_crossed_bounds_column = j; + const auto& ul = this->m_columns_to_ul_pairs()[j]; + u_dependency* bdep = lower_bound? ul.lower_bound_witness() : ul.upper_bound_witness(); + SASSERT(bdep != nullptr); + m_crossed_bounds_deps = m_dependencies.mk_join(bdep, dep); + } } // namespace lp diff --git a/src/math/lp/lar_solver.h b/src/math/lp/lar_solver.h index fc696d4b2..a689d6665 100644 --- a/src/math/lp/lar_solver.h +++ b/src/math/lp/lar_solver.h @@ -78,7 +78,8 @@ class lar_solver : public column_namer { lp_status m_status = lp_status::UNKNOWN; stacked_value m_simplex_strategy; // such can be found at the initialization step: u < l - stacked_value m_crossed_bounds_column; + lpvar m_crossed_bounds_column; + u_dependency* m_crossed_bounds_deps; lar_core_solver m_mpq_lar_core_solver; int_solver* m_int_solver = nullptr; bool m_need_register_terms = false; @@ -139,10 +140,14 @@ class lar_solver : public column_namer { bool compare_values(impq const& lhs, lconstraint_kind k, const mpq& rhs); inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.reset(); } + public: void insert_to_columns_with_changed_bounds(unsigned j); + private: void update_column_type_and_bound_check_on_equal(unsigned j, const mpq& right_side, constraint_index ci, unsigned&); void update_column_type_and_bound(unsigned j, const mpq& right_side, constraint_index ci); + public: void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); + private: void update_column_type_and_bound_with_ub(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); void update_column_type_and_bound_with_no_ub(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); void update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); @@ -152,10 +157,7 @@ class lar_solver : public column_namer { void register_in_fixed_var_table(unsigned, unsigned&); void remove_non_fixed_from_fixed_var_table(); constraint_index add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq& right_side); - inline void set_infeasible_column(unsigned j) { - set_status(lp_status::INFEASIBLE); - m_crossed_bounds_column = j; - } + void set_infeasible_column_and_witness(unsigned j, bool lower_bound, u_dependency* dep); constraint_index add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term, lconstraint_kind kind, const mpq& right_side); unsigned row_of_basic_column(unsigned) const; diff --git a/src/math/lp/lp_core_solver_base.h b/src/math/lp/lp_core_solver_base.h index e7570d5dd..d7d1666d0 100644 --- a/src/math/lp/lp_core_solver_base.h +++ b/src/math/lp/lp_core_solver_base.h @@ -540,9 +540,9 @@ public: } void add_delta_to_x_and_track_feasibility(unsigned j, const X & del) { - TRACE("lar_solver_feas_bug", tout << "del = " << del << ", was x[" << j << "] = " << m_x[j] << "\n";); + TRACE("lar_solver_feas", tout << "del = " << del << ", was x[" << j << "] = " << m_x[j] << "\n";); m_x[j] += del; - TRACE("lar_solver_feas_bug", tout << "became x[" << j << "] = " << m_x[j] << "\n";); + TRACE("lar_solver_feas", tout << "became x[" << j << "] = " << m_x[j] << "\n";); track_column_feasibility(j); } diff --git a/src/math/lp/monomial_bounds.cpp b/src/math/lp/monomial_bounds.cpp index e21891ee4..9dd4ffa90 100644 --- a/src/math/lp/monomial_bounds.cpp +++ b/src/math/lp/monomial_bounds.cpp @@ -258,51 +258,113 @@ namespace nla { } } - void monomial_bounds::unit_propagate() { - for (auto const& m : c().m_emons) - unit_propagate(m); + bool monomial_bounds::unit_propagate() { + unsigned sz = 0; + vector monics_vars; + for (auto const& m : c().m_emons) { + monics_vars.push_back(m.var()); + sz++; + } + unsigned l = this->random(); + for (unsigned i = 0; i < sz; ++i) { + lpvar v = monics_vars[(i + l) % sz]; + if (!unit_propagate(c().m_emons[v])) { + return false; + } + } + + return true; } - void monomial_bounds::unit_propagate(monic const& m) { +// returns false if and only if there is a conflict + bool monomial_bounds::unit_propagate(monic const& m) { m_propagated.reserve(m.var() + 1, false); if (m_propagated[m.var()]) - return; + return true; if (!is_linear(m)) - return; + return true; 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); + lpvar zero_fixed = null_lpvar, non_fixed = null_lpvar; + // find a zero fixed variable and a non-fixed variable + for (lpvar v : m) { + if (c().var_is_fixed(v)) { + if (c().val(v).is_zero()) { + zero_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); - if (w != null_lpvar) { - lp::lar_term term; - term.add_var(m.var()); - term.add_monomial(-k, w); - lemma += ineq(term, lp::lconstraint_kind::EQ, 0); - } else { - lemma += ineq(m.var(), lp::lconstraint_kind::EQ, k); + else { + non_fixed = v; } } - + + if (zero_fixed != null_lpvar) { + // the m.var() has to have a zero value + u_dependency* d = this->dep.mk_join(c().lra.get_column_lower_bound_witness(zero_fixed), + c().lra.get_column_upper_bound_witness(zero_fixed)); + + c().lra.update_column_type_and_bound(m.var(), lp::lconstraint_kind::EQ, mpq(0), d); + } else if (non_fixed != null_lpvar) { + u_dependency* d = nullptr; + rational k(1); + for (auto v : m) + if (v != non_fixed) { + d = this->dep.mk_join(d, c().lra.get_column_upper_bound_witness(v)); + d = this->dep.mk_join(d, c().lra.get_column_lower_bound_witness(v)); + k *= c().val(v); + } + SASSERT(k.is_pos() || k.is_neg()); + // we have m = k* non_fixed: m.var() getting the bounds witnesses of non_fixed + if (k.is_pos()) { + d = c().lra.get_column_upper_bound_witness(non_fixed); + if (d) { + const auto& b = c().lra.get_column_value(non_fixed); + bool strict = b.y.is_neg(); + c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::LT : lp::lconstraint_kind::LE, k * b.x, d); + } + d = c().lra.get_column_lower_bound_witness(non_fixed); + if (d) { + const auto& b = c().lra.get_column_value(non_fixed); + bool strict = b.y.is_pos(); + c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::GT : lp::lconstraint_kind::GE, k * b.x, d); + } + + } else { + d = c().lra.get_column_upper_bound_witness(non_fixed); + if (d) { + const auto& b = c().lra.get_column_value(non_fixed); + bool strict = b.y.is_neg(); + c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::GT : lp::lconstraint_kind::GE, k * b.x, d); + } + d = c().lra.get_column_lower_bound_witness(non_fixed); + if (d) { + const auto& b = c().lra.get_column_value(non_fixed); + bool strict = b.y.is_pos(); + c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::LT : lp::lconstraint_kind::LE, k * b.x, d); + } + } + } else { + SASSERT(non_fixed == null_lpvar && zero_fixed == null_lpvar); + rational k(1); + u_dependency* d = nullptr; + for (auto v : m) { + SASSERT(c().var_is_fixed(v)); + d = this->dep.mk_join(d, c().lra.get_column_upper_bound_witness(v)); + d = this->dep.mk_join(d, c().lra.get_column_lower_bound_witness(v)); + k *= c().val(v); + } + SASSERT(k.is_pos() || k.is_neg()); + // we have m = k: m.var() getting the bounds witnesses of all fixed variables + c().lra.update_column_type_and_bound(m.var(), lp::lconstraint_kind::EQ, k, d); + } + if (c().lra.get_status() == lp::lp_status::INFEASIBLE) { + TRACE("nla_solver", tout << "conflict in unit_propagate\n";); + return false; + } + return true; } - bool monomial_bounds::is_linear(monic const& m) { unsigned non_fixed = 0; for (lpvar v : m) { @@ -324,12 +386,6 @@ namespace nla { 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 c728d1a4c..41aa48f6c 100644 --- a/src/math/lp/monomial_bounds.h +++ b/src/math/lp/monomial_bounds.h @@ -32,14 +32,12 @@ namespace nla { // monomial propagation bool_vector m_propagated; - void unit_propagate(monic const& m); + bool 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 propagate(); - void unit_propagate(); + bool unit_propagate(); }; } diff --git a/src/math/lp/nla_core.cpp b/src/math/lp/nla_core.cpp index 4d4fa6cbe..08a768ee5 100644 --- a/src/math/lp/nla_core.cpp +++ b/src/math/lp/nla_core.cpp @@ -1818,14 +1818,18 @@ bool core::improve_bounds() { } return bounds_improved; } - -void core::propagate(vector& lemmas) { + // returns false if and only if makes lp_solver inconsistent +bool core::propagate(vector& lemmas) { // propagate linear monomials, those that have all, or all but one, variables fixed lemmas.reset(); m_lemma_vec = &lemmas; m_monomial_bounds.unit_propagate(); - + if (lra.get_status() == lp::lp_status::INFEASIBLE) { + TRACE("nla_solver", tout << "propagation found infeasibility\n";); + return false; + } + return true; } diff --git a/src/math/lp/nla_core.h b/src/math/lp/nla_core.h index 9c96f2fbf..340b94430 100644 --- a/src/math/lp/nla_core.h +++ b/src/math/lp/nla_core.h @@ -392,7 +392,7 @@ public: bool no_lemmas_hold() const; - void propagate(vector& lemmas); + bool propagate(vector& lemmas); lbool test_check(vector& l); lpvar map_to_root(lpvar) const; diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index 470ea5f7b..ae224e3ec 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -1532,11 +1532,12 @@ namespace smt { bool max, bool maintain_integrality, bool& has_shared) { + return UNBOUNDED; + m_stats.m_max_min++; unsigned best_efforts = 0; bool inc = false; - - + SASSERT(!maintain_integrality || valid_assignment()); SASSERT(satisfy_bounds()); diff --git a/src/smt/theory_arith_nl.h b/src/smt/theory_arith_nl.h index f44516cad..77e2b25f3 100644 --- a/src/smt/theory_arith_nl.h +++ b/src/smt/theory_arith_nl.h @@ -511,6 +511,7 @@ bool theory_arith::propagate_nl_downward(expr * n, var_power_pair const& p) */ template bool theory_arith::propagate_nl_bounds(expr * m) { + return false; TRACE("non_linear", tout << "propagate several bounds using:\n"; display_monomial(tout, m); tout << "\n";); bool result = propagate_nl_upward(m); buffer vp; @@ -530,6 +531,7 @@ bool theory_arith::propagate_nl_bounds(expr * m) { */ template bool theory_arith::propagate_nl_bounds() { + return false; m_dep_manager.reset(); bool propagated = false; for (unsigned i = 0; i < m_nl_monomials.size(); i++) { @@ -1632,6 +1634,7 @@ bool theory_arith::is_cross_nested_consistent(row const & r) { */ template bool theory_arith::is_cross_nested_consistent(svector const & nl_cluster) { + return true; for (theory_var v : nl_cluster) { if (!is_base(v)) continue; diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 31882ea11..29a46db19 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -2163,8 +2163,14 @@ public: if (!m_nla) return; m_nla->propagate(m_nla_lemma_vector); - for (nla::lemma const& l : m_nla_lemma_vector) - false_case_of_check_nla(l); + if (lp().get_status() == lp::lp_status::INFEASIBLE) { + TRACE("arith", tout << "propagation conflict\n";); + get_infeasibility_explanation_and_set_conflict(); + } + else { + for (nla::lemma const& l : m_nla_lemma_vector) + false_case_of_check_nla(l); + } } bool should_propagate() const {