3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-23 14:23:40 +00:00

bug fixes in tangent_lemma explanations and the strict case of monotone lemma

Signed-off-by: Lev <levnach@hotmail.com>
This commit is contained in:
Lev 2019-02-09 11:26:28 -08:00 committed by Lev Nachmanson
parent 2bab591ef3
commit 286cebd9db

View file

@ -379,11 +379,7 @@ struct solver::imp {
out << "\n"; out << "\n";
return out; return out;
} }
void mk_ineq(const lp::lar_term& t, llc cmp, const rational& rs, lemma& l) {
void mk_ineq(const rational& a, lpvar j, const rational& b, lpvar k, llc cmp, const rational& rs, lemma& l) {
lp::lar_term t;
t.add_coeff_var(a, j);
t.add_coeff_var(b, k);
if (t.is_empty() && rs.is_zero() && if (t.is_empty() && rs.is_zero() &&
(cmp == llc::LT || cmp == llc::GT || cmp == llc::NE)) (cmp == llc::LT || cmp == llc::GT || cmp == llc::NE))
return; // otherwise we get something like 0 < 0, which is always false and can be removed from the lemma return; // otherwise we get something like 0 < 0, which is always false and can be removed from the lemma
@ -392,7 +388,7 @@ struct solver::imp {
if (t.size() == 1) { if (t.size() == 1) {
const auto & p = t.coeffs().begin(); const auto & p = t.coeffs().begin();
auto r = rs/p->second; auto r = rs/p->second;
j = p->first; lpvar j = p->first;
if (vvr(j) == r && var_is_fixed_to_val(j, r)) { if (vvr(j) == r && var_is_fixed_to_val(j, r)) {
explain_fixed_var(j); // instead of adding the inequality explain_fixed_var(j); // instead of adding the inequality
return; return;
@ -403,6 +399,12 @@ struct solver::imp {
} }
l.push_back(ineq(cmp, t, rs)); l.push_back(ineq(cmp, t, rs));
} }
void mk_ineq(const rational& a, lpvar j, const rational& b, lpvar k, llc cmp, const rational& rs, lemma& l) {
lp::lar_term t;
t.add_coeff_var(a, j);
t.add_coeff_var(b, k);
mk_ineq(t, cmp, rs, l);
}
void mk_ineq(lpvar j, const rational& b, lpvar k, llc cmp, const rational& rs, lemma& l) { void mk_ineq(lpvar j, const rational& b, lpvar k, llc cmp, const rational& rs, lemma& l) {
mk_ineq(rational(1), j, b, k, cmp, rs, l); mk_ineq(rational(1), j, b, k, cmp, rs, l);
@ -425,15 +427,13 @@ struct solver::imp {
} }
void mk_ineq(lpvar j, llc cmp, const rational& rs, lemma& l) { void mk_ineq(lpvar j, llc cmp, const rational& rs, lemma& l) {
lp::lar_term t; mk_ineq(rational(1), j, cmp, rs, l);
t.add_var(j);
l.push_back(ineq(cmp, t, rs));
} }
void mk_ineq(const rational& a, lpvar j, llc cmp, const rational& rs, lemma& l) { void mk_ineq(const rational& a, lpvar j, llc cmp, const rational& rs, lemma& l) {
lp::lar_term t; lp::lar_term t;
t.add_coeff_var(a, j); t.add_coeff_var(a, j);
l.push_back(ineq(cmp, t, rs)); mk_ineq(t, cmp, rs, l);
} }
llc negate(llc cmp) { llc negate(llc cmp) {
@ -1233,6 +1233,14 @@ struct solver::imp {
return false; return false;
} }
if (not_one + 1) {
// we found the only not_one
if (vvr(rm) == vvr(not_one) * sign) {
TRACE("nla_solver", tout << "the whole equal to the factor" << std::endl;);
return false;
}
}
add_empty_lemma_and_explanation(); add_empty_lemma_and_explanation();
explain(rm, current_expl()); explain(rm, current_expl());
@ -1249,7 +1257,7 @@ struct solver::imp {
} }
TRACE("nla_solver", TRACE("nla_solver",
tout << "rm = "; print_rooted_monomial_with_vars(rm, tout); tout << "rm = "; print_rooted_monomial_with_vars(rm, tout);
print_lemma(current_lemma(), tout);); print_lemma_and_expl(tout););
return true; return true;
} }
// use the fact // use the fact
@ -1359,6 +1367,15 @@ struct solver::imp {
TRACE("nla_solver", print_lemma(current_lemma(), tout); print_explanation(current_expl(), tout);); TRACE("nla_solver", print_lemma(current_lemma(), tout); print_explanation(current_expl(), tout););
} }
template <typename T>
bool has_zero(const T& product) const {
for (const rational & t : product) {
if (t.is_zero())
return true;
}
return false;
}
// x != 0 or y = 0 => |xy| >= |y| // x != 0 or y = 0 => |xy| >= |y|
bool proportion_lemma_model_based(const rooted_mon& rm, const factorization& factorization) { bool proportion_lemma_model_based(const rooted_mon& rm, const factorization& factorization) {
rational rmv = abs(vvr(rm)); rational rmv = abs(vvr(rm));
@ -2022,7 +2039,7 @@ struct solver::imp {
} }
bool uniform_less(const std::vector<rational>& a, bool uniform_le(const std::vector<rational>& a,
const std::vector<rational>& b, const std::vector<rational>& b,
unsigned & strict_i) const { unsigned & strict_i) const {
SASSERT(a.size() == b.size()); SASSERT(a.size() == b.size());
@ -2060,16 +2077,19 @@ struct solver::imp {
return r; return r;
} }
void negate_abs_a_le_abs_b(lpvar a, lpvar b) { void negate_abs_a_le_abs_b(lpvar a, lpvar b, bool strict) {
rational av = vvr(a); rational av = vvr(a);
rational as = rational(rat_sign(av)); rational as = rational(rat_sign(av));
rational bv = vvr(b); rational bv = vvr(b);
rational bs = rational(rat_sign(bv)); rational bs = rational(rat_sign(bv));
TRACE("nla_solver", tout << "av = " << av << ", bv = " << bv << "\n";); TRACE("nla_solver", tout << "av = " << av << ", bv = " << bv << "\n";);
SASSERT(as*av <= bs*bv); SASSERT(as*av <= bs*bv);
mk_ineq(as, a, llc::LT, current_lemma()); // |aj| < 0 llc mod_s = strict? (llc::LE): (llc::LT);
mk_ineq(bs, b, llc::LT, current_lemma()); // |bj| < 0 mk_ineq(as, a, mod_s, current_lemma()); // |a| <= 0 || |a| < 0
mk_ineq(as, a, -bs, b, llc::GT, current_lemma()); // negate |aj| <= |bj| if (a != b) {
mk_ineq(bs, b, mod_s, current_lemma()); // |b| <= 0 || |b| < 0
mk_ineq(as, a, -bs, b, llc::GT, current_lemma()); // negate |aj| <= |bj|
}
} }
void negate_abs_a_lt_abs_b(lpvar a, lpvar b) { void negate_abs_a_lt_abs_b(lpvar a, lpvar b) {
@ -2110,7 +2130,7 @@ struct solver::imp {
SASSERT(akey.size() == bkey.size()); SASSERT(akey.size() == bkey.size());
for (unsigned i = 0; i < akey.size(); i++) { for (unsigned i = 0; i < akey.size(); i++) {
if (i != strict) { if (i != strict) {
negate_abs_a_le_abs_b(akey[i].second, bkey[i].second); negate_abs_a_le_abs_b(akey[i].second, bkey[i].second, true);
} else { } else {
mk_ineq(b[i], llc::EQ, current_lemma()); mk_ineq(b[i], llc::EQ, current_lemma());
negate_abs_a_lt_abs_b(akey[i].second, bkey[i].second); negate_abs_a_lt_abs_b(akey[i].second, bkey[i].second);
@ -2130,7 +2150,7 @@ struct solver::imp {
auto bkey = get_sorted_key_with_vars(b); auto bkey = get_sorted_key_with_vars(b);
SASSERT(akey.size() == bkey.size()); SASSERT(akey.size() == bkey.size());
for (unsigned i = 0; i < akey.size(); i++) { for (unsigned i = 0; i < akey.size(); i++) {
negate_abs_a_le_abs_b(akey[i].second, bkey[i].second); negate_abs_a_le_abs_b(akey[i].second, bkey[i].second, false);
} }
assert_abs_val_a_le_abs_var_b(a, b, false); assert_abs_val_a_le_abs_var_b(a, b, false);
explain(a, current_expl()); explain(a, current_expl());
@ -2153,8 +2173,8 @@ struct solver::imp {
tout << "vk = " << vk << std::endl;); tout << "vk = " << vk << std::endl;);
if (vk > v) continue; if (vk > v) continue;
unsigned strict; unsigned strict;
if (uniform_less(key, p.first, strict)) { if (uniform_le(key, p.first, strict)) {
if (static_cast<int>(strict) != -1) { if (static_cast<int>(strict) != -1 && !has_zero(key)) {
generate_monl_strict(rm, rmk, strict); generate_monl_strict(rm, rmk, strict);
return true; return true;
} else { } else {
@ -2185,7 +2205,7 @@ struct solver::imp {
tout << "vk = " << vk << std::endl;); tout << "vk = " << vk << std::endl;);
if (vk < v) continue; if (vk < v) continue;
unsigned strict; unsigned strict;
if (uniform_less(p.first, key, strict)) { if (uniform_le(p.first, key, strict)) {
TRACE("nla_solver", tout << "strict = " << strict << std::endl;); TRACE("nla_solver", tout << "strict = " << strict << std::endl;);
if (static_cast<int>(strict) != -1) { if (static_cast<int>(strict) != -1) {
generate_monl_strict(rmk, rm, strict); generate_monl_strict(rmk, rm, strict);
@ -2350,13 +2370,9 @@ struct solver::imp {
void generate_explanations_of_tang_lemma(const rooted_mon& rm, const bfc& bf) { void generate_explanations_of_tang_lemma(const rooted_mon& rm, const bfc& bf) {
// here we repeat the same explanation for each lemma // here we repeat the same explanation for each lemma
lp::explanation exp; explain(rm, current_expl());
explain(rm, exp); explain(bf.m_x, current_expl());
explain(bf.m_x, exp); explain(bf.m_y, current_expl());
explain(bf.m_y, exp);
for (auto& e : *m_expl_vec) {
e = exp;
}
} }
void tangent_lemma_bf(const bfc& bf, lpvar j, const rational& sign, const rooted_mon& rm){ void tangent_lemma_bf(const bfc& bf, lpvar j, const rational& sign, const rooted_mon& rm){
@ -2407,13 +2423,13 @@ struct solver::imp {
void generate_two_tang_lines(const bfc & bf, const point& xy, const rational& sign, lpvar j) { void generate_two_tang_lines(const bfc & bf, const point& xy, const rational& sign, lpvar j) {
add_empty_lemma_and_explanation(); add_empty_lemma_and_explanation();
mk_ineq(bf.m_x, llc::NE, xy.x, m_lemma_vec->back()); mk_ineq(bf.m_x, llc::NE, xy.x, current_lemma());
mk_ineq(sign, j, - xy.x, bf.m_y, llc::EQ, m_lemma_vec->back()); mk_ineq(sign, j, - xy.x, bf.m_y, llc::EQ, current_lemma());
TRACE("nla_solver", print_lemma(m_lemma_vec->back(), tout);); TRACE("nla_solver", print_lemma_and_expl(tout););
add_empty_lemma_and_explanation(); add_empty_lemma_and_explanation();
mk_ineq(bf.m_y, llc::NE, xy.y, m_lemma_vec->back()); mk_ineq(bf.m_y, llc::NE, xy.y, current_lemma());
mk_ineq(sign, j, - xy.y, bf.m_x, llc::EQ, m_lemma_vec->back()); mk_ineq(sign, j, - xy.y, bf.m_x, llc::EQ, current_lemma());
TRACE("nla_solver", print_lemma(m_lemma_vec->back(), tout);); TRACE("nla_solver", print_lemma_and_expl(tout););
} }
// Get two planes tangent to surface z = xy, one at point a, and another at point b. // Get two planes tangent to surface z = xy, one at point a, and another at point b.
// One can show that these planes still create a cut. // One can show that these planes still create a cut.