mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
338d7b3283
commit
d04807e8c3
8 changed files with 122 additions and 85 deletions
|
@ -172,7 +172,8 @@ namespace lp {
|
|||
|
||||
lia_move int_solver::check(lp::explanation * e) {
|
||||
SASSERT(lra.ax_is_correct());
|
||||
if (!has_inf_int()) return lia_move::sat;
|
||||
if (!has_inf_int())
|
||||
return lia_move::sat;
|
||||
|
||||
m_t.clear();
|
||||
m_k.reset();
|
||||
|
@ -181,7 +182,8 @@ namespace lp {
|
|||
m_upper = false;
|
||||
lia_move r = lia_move::undef;
|
||||
|
||||
if (m_gcd.should_apply()) r = m_gcd();
|
||||
if (m_gcd.should_apply())
|
||||
r = m_gcd();
|
||||
|
||||
check_return_helper pc(lra);
|
||||
|
||||
|
@ -298,7 +300,6 @@ namespace lp {
|
|||
return m_number_of_calls % settings().m_int_find_cube_period == 0;
|
||||
}
|
||||
|
||||
|
||||
bool int_solver::should_gomory_cut() {
|
||||
return m_number_of_calls % settings().m_int_gomory_cut_period == 0;
|
||||
}
|
||||
|
|
|
@ -19,34 +19,38 @@ Revision History:
|
|||
--*/
|
||||
#pragma once
|
||||
namespace lp {
|
||||
enum class lia_move {
|
||||
sat,
|
||||
branch,
|
||||
cut,
|
||||
conflict,
|
||||
continue_with_check,
|
||||
undef,
|
||||
unsat
|
||||
};
|
||||
inline std::string lia_move_to_string(lia_move m) {
|
||||
switch (m) {
|
||||
case lia_move::sat:
|
||||
return "sat";
|
||||
case lia_move::branch:
|
||||
return "branch";
|
||||
case lia_move::cut:
|
||||
return "cut";
|
||||
case lia_move::conflict:
|
||||
return "conflict";
|
||||
case lia_move::continue_with_check:
|
||||
return "continue_with_check";
|
||||
case lia_move::undef:
|
||||
return "undef";
|
||||
case lia_move::unsat:
|
||||
return "unsat";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
enum class lia_move {
|
||||
sat,
|
||||
branch,
|
||||
cut,
|
||||
conflict,
|
||||
continue_with_check,
|
||||
undef,
|
||||
unsat
|
||||
};
|
||||
return "strange";
|
||||
}
|
||||
inline std::string lia_move_to_string(lia_move m) {
|
||||
switch (m) {
|
||||
case lia_move::sat:
|
||||
return "sat";
|
||||
case lia_move::branch:
|
||||
return "branch";
|
||||
case lia_move::cut:
|
||||
return "cut";
|
||||
case lia_move::conflict:
|
||||
return "conflict";
|
||||
case lia_move::continue_with_check:
|
||||
return "continue_with_check";
|
||||
case lia_move::undef:
|
||||
return "undef";
|
||||
case lia_move::unsat:
|
||||
return "unsat";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
};
|
||||
return "strange";
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, lia_move const& m) {
|
||||
return out << lia_move_to_string(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,38 +58,42 @@ namespace nla {
|
|||
auto const& upper = dep.upper(range);
|
||||
auto cmp = dep.upper_is_open(range) ? llc::LT : llc::LE;
|
||||
++c().lra.settings().stats().m_nla_propagate_bounds;
|
||||
#if UNIT_PROPAGATE_BOUNDS
|
||||
auto* d = dep.get_upper_dep(range);
|
||||
c().lra.update_column_type_and_bound(v, cmp, upper, d);
|
||||
#else
|
||||
lp::explanation ex;
|
||||
dep.get_upper_dep(range, ex);
|
||||
if (is_too_big(upper))
|
||||
return false;
|
||||
new_lemma lemma(c(), "propagate value - upper bound of range is below value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, cmp, upper);
|
||||
TRACE("nla_solver", dep.display(tout << c().val(v) << " > ", range) << "\n" << lemma << "\n";);
|
||||
#endif
|
||||
if (c().params().arith_nl_internal_bounds()) {
|
||||
auto* d = dep.get_upper_dep(range);
|
||||
TRACE("arith", tout << "upper " << cmp << " " << upper << "\n");
|
||||
propagate_bound(v, cmp, upper, d);
|
||||
}
|
||||
else {
|
||||
lp::explanation ex;
|
||||
dep.get_upper_dep(range, ex);
|
||||
if (is_too_big(upper))
|
||||
return false;
|
||||
new_lemma lemma(c(), "propagate value - upper bound of range is below value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, cmp, upper);
|
||||
TRACE("nla_solver", dep.display(tout << c().val(v) << " > ", range) << "\n" << lemma << "\n";);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (dep.is_above(range, val)) {
|
||||
auto const& lower = dep.lower(range);
|
||||
auto cmp = dep.lower_is_open(range) ? llc::GT : llc::GE;
|
||||
++c().lra.settings().stats().m_nla_propagate_bounds;
|
||||
#if UNIT_PROPAGATE_BOUNDS
|
||||
auto* d = dep.get_lower_dep(range);
|
||||
c().lra.update_column_type_and_bound(v, cmp, lower, d);
|
||||
#else
|
||||
lp::explanation ex;
|
||||
dep.get_lower_dep(range, ex);
|
||||
if (is_too_big(lower))
|
||||
return false;
|
||||
new_lemma lemma(c(), "propagate value - lower bound of range is above value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, cmp, lower);
|
||||
TRACE("nla_solver", dep.display(tout << c().val(v) << " < ", range) << "\n" << lemma << "\n";);
|
||||
#endif
|
||||
if (c().params().arith_nl_internal_bounds()) {
|
||||
auto* d = dep.get_lower_dep(range);
|
||||
propagate_bound(v, cmp, lower, d);
|
||||
TRACE("arith", tout << v << " " << cmp << " " << lower << "\n");
|
||||
}
|
||||
else {
|
||||
lp::explanation ex;
|
||||
dep.get_lower_dep(range, ex);
|
||||
if (is_too_big(lower))
|
||||
return false;
|
||||
new_lemma lemma(c(), "propagate value - lower bound of range is above value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, cmp, lower);
|
||||
TRACE("nla_solver", dep.display(tout << c().val(v) << " < ", range) << "\n" << lemma << "\n";);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -97,6 +101,28 @@ namespace nla {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that bounds are integral when the variable is integer.
|
||||
*/
|
||||
void monomial_bounds::propagate_bound(lpvar v, lp::lconstraint_kind cmp, rational const& q, u_dependency* d) {
|
||||
SASSERT(cmp != llc::EQ && cmp != llc::NE);
|
||||
if (!c().var_is_int(v))
|
||||
c().lra.update_column_type_and_bound(v, cmp, q, d);
|
||||
else if (q.is_int()) {
|
||||
if (cmp == llc::GT)
|
||||
c().lra.update_column_type_and_bound(v, llc::GE, q + 1, d);
|
||||
else if(cmp == llc::LT)
|
||||
c().lra.update_column_type_and_bound(v, llc::LE, q - 1, d);
|
||||
else
|
||||
c().lra.update_column_type_and_bound(v, cmp, q, d);
|
||||
}
|
||||
else if (cmp == llc::GE || cmp == llc::GT)
|
||||
c().lra.update_column_type_and_bound(v, llc::GE, ceil(q), d);
|
||||
else
|
||||
c().lra.update_column_type_and_bound(v, llc::LE, floor(q), d);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* val(v)^p should be in range.
|
||||
* if val(v)^p > upper(range) add
|
||||
|
@ -129,28 +155,30 @@ namespace nla {
|
|||
if ((p % 2 == 1) || val_v.is_pos()) {
|
||||
++c().lra.settings().stats().m_nla_propagate_bounds;
|
||||
auto le = dep.upper_is_open(range) ? llc::LT : llc::LE;
|
||||
#if UNIT_PROPAGATE_BOUNDS
|
||||
auto* d = dep.get_upper_dep();
|
||||
c().lra.update_column_type_and_bound(v, le, r, d);
|
||||
#else
|
||||
new_lemma lemma(c(), "propagate value - root case - upper bound of range is below value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, le, r);
|
||||
#endif
|
||||
if (c().params().arith_nl_internal_bounds()) {
|
||||
auto* d = dep.get_upper_dep(range);
|
||||
propagate_bound(v, le, r, d);
|
||||
}
|
||||
else {
|
||||
new_lemma lemma(c(), "propagate value - root case - upper bound of range is below value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, le, r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (p % 2 == 0 && val_v.is_neg()) {
|
||||
++c().lra.settings().stats().m_nla_propagate_bounds;
|
||||
SASSERT(!r.is_neg());
|
||||
auto ge = dep.upper_is_open(range) ? llc::GT : llc::GE;
|
||||
#if UNIT_PROPAGATE_BOUNDS
|
||||
auto* d = dep.get_upper_dep();
|
||||
c().lra.update_column_type_and_bound(v, ge, -r, d);
|
||||
#else
|
||||
new_lemma lemma(c(), "propagate value - root case - upper bound of range is below negative value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, ge, -r);
|
||||
#endif
|
||||
if (c().params().arith_nl_internal_bounds()) {
|
||||
auto* d = dep.get_upper_dep(range);
|
||||
propagate_bound(v, ge, -r, d);
|
||||
}
|
||||
else {
|
||||
new_lemma lemma(c(), "propagate value - root case - upper bound of range is below negative value");
|
||||
lemma &= ex;
|
||||
lemma |= ineq(v, ge, -r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -306,10 +334,11 @@ namespace nla {
|
|||
if (m.is_propagated())
|
||||
return;
|
||||
lpvar w, fixed_to_zero;
|
||||
if (!is_linear(m, w, fixed_to_zero)) {
|
||||
#if UNIT_PROPAGATE_BOUNDS
|
||||
propagate(m);
|
||||
#endif
|
||||
|
||||
if (!is_linear(m)) {
|
||||
if (c().params().arith_nl_internal_bounds()) {
|
||||
propagate(m);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace nla {
|
|||
class monomial_bounds : common {
|
||||
dep_intervals& dep;
|
||||
|
||||
void propagate_bound(lpvar v, lp::lconstraint_kind cmp, rational const& q, u_dependency* d);
|
||||
void var2interval(lpvar v, scoped_dep_interval& i);
|
||||
bool is_too_big(mpq const& q) const;
|
||||
bool propagate_down(monic const& m, lpvar u);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue