3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-18 02:16:40 +00:00

fix the factorization sign to be equal to the monomial sign

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2019-05-10 12:08:56 -07:00
parent df5f3f9722
commit 375027d195
13 changed files with 185 additions and 151 deletions

View file

@ -29,10 +29,22 @@ tangents::tangents(core * c) : common(c) {}
std::ostream& tangents::print_tangent_domain(const point &a, const point &b, std::ostream& out) const {
return out << "(" << a << ", " << b << ")";
}
unsigned tangents::find_binomial_to_refine() {
unsigned start = c().random();
unsigned sz = c().m_to_refine.size();
for (unsigned k = 0; k < sz; k++) {
lpvar j = c().m_to_refine[(k + start) % sz];
if (c().emons()[j].size() == 2)
return j;
}
return -1;
}
void tangents::generate_simple_tangent_lemma(const monomial& m) {
if (m.size() != 2)
return;
void tangents::generate_simple_tangent_lemma() {
lpvar j = find_binomial_to_refine();
if (!is_set(j)) return;
const monomial& m = c().emons()[j];
SASSERT(m.size() != 2);
TRACE("nla_solver", tout << "m:" << pp_mon(c(), m) << std::endl;);
c().add_empty_lemma();
const rational v = c().product_value(m.vars());
@ -66,65 +78,70 @@ void tangents::generate_simple_tangent_lemma(const monomial& m) {
}
void tangents::tangent_lemma() {
bfc bf;
lpvar j;
rational sign;
const monomial* rm = nullptr;
if (c().find_bfc_to_refine(bf, j, sign, rm)) {
tangent_lemma_bf(bf, j, sign, rm);
} else {
TRACE("nla_solver", tout << "cannot find a bfc to refine\n"; );
if (rm != nullptr)
generate_simple_tangent_lemma(*rm);
if (!c().m_settings.run_tangents()) {
TRACE("nla_solver", tout << "not generating tangent lemmas\n";);
return;
}
factorization bf(nullptr);
const monomial* m;
if (c().find_bfc_to_refine(m, bf)) {
tangent_lemma_bf(*m, bf);
}
}
void tangents::generate_explanations_of_tang_lemma(const monomial& rm, const bfc& bf, lp::explanation& exp) {
void tangents::generate_explanations_of_tang_lemma(const monomial& rm, const factorization& bf, lp::explanation& exp) {
// here we repeat the same explanation for each lemma
c().explain(rm, exp);
c().explain(bf.m_x, exp);
c().explain(bf.m_y, exp);
c().explain(bf[0], exp);
c().explain(bf[1], exp);
}
void tangents::generate_tang_plane(const rational & a, const rational& b, const factor& x, const factor& y, bool below, lpvar j, const rational& j_sign) {
void tangents::generate_tang_plane(const rational & a, const rational& b, const factor& x, const factor& y, bool below, lpvar j) {
lpvar jx = var(x);
lpvar jy = var(y);
add_empty_lemma();
c().negate_relation(jx, a);
c().negate_relation(jy, b);
bool sbelow = j_sign.is_pos()? below: !below;
#if Z3DEBUG
int mult_sign = nla::rat_sign(a - val(jx))*nla::rat_sign(b - val(jy));
SASSERT((mult_sign == 1) == sbelow);
SASSERT((mult_sign == 1) == below);
// If "mult_sign is 1" then (a - x)(b-y) > 0 and ab - bx - ay + xy > 0
// or -ab + bx + ay < xy or -ay - bx + xy > -ab
// j_sign*val(j) stands for xy. So, finally we have -ay - bx + j_sign*j > - ab
// val(j) stands for xy. So, finally we have -ay - bx + j > - ab
#endif
lp::lar_term t;
t.add_coeff_var(-a, jy);
t.add_coeff_var(-b, jx);
t.add_coeff_var( j_sign, j);
c().mk_ineq(t, sbelow? llc::GT : llc::LT, - a*b);
}
void tangents::tangent_lemma_bf(const bfc& bf, lpvar j, const rational& sign, const monomial* rm){
t.add_var(j);
c().mk_ineq(t, below? llc::GT : llc::LT, - a*b);
}
void tangents::tangent_lemma_bf(const monomial& m, const factorization& bf){
point a, b;
point xy (val(bf.m_x), val(bf.m_y));
point xy (val(bf[0]), val(bf[1]));
rational correct_mult_val = xy.x * xy.y;
rational v = val(j) * sign;
lpvar j =m.var();
// We have canonize_sign(m)*m.vars() = m.rvars()
// Let s = canonize_sign(bf). Then we have bf[1]*bf[1] = s*m.rvars()
// s*canonize_sign(m)*val(m).
// Therefore sign*val(m) = val((bf[0])*val(bf[1]), where sign = canonize_sign(bf)*canonize_sign(m)
SASSERT(canonize_sign(bf) == canonize_sign(m));
rational v = val(j);
bool below = v < correct_mult_val;
TRACE("nla_solver", tout << "rm = " << rm << ", below = " << below << std::endl; );
TRACE("nla_solver", tout << "below = " << below << std::endl; );
get_tang_points(a, b, below, v, xy);
TRACE("nla_solver", tout << "sign = " << sign << ", tang domain = "; print_tangent_domain(a, b, tout); tout << std::endl;);
TRACE("nla_solver", tout << "tang domain = "; print_tangent_domain(a, b, tout); tout << std::endl;);
unsigned lemmas_size_was = c().m_lemma_vec->size();
generate_two_tang_lines(bf, xy, sign, j);
generate_tang_plane(a.x, a.y, bf.m_x, bf.m_y, below, j, sign);
generate_tang_plane(b.x, b.y, bf.m_x, bf.m_y, below, j, sign);
// if rm == nullptr there is no need to explain equivs since we work on a monomial and not on a rooted monomial
if (rm != nullptr) {
rational sign(1);
generate_two_tang_lines(bf, xy, j);
generate_tang_plane(a.x, a.y, bf[0], bf[1], below, j);
generate_tang_plane(b.x, b.y, bf[0], bf[1], below, j);
if (!bf.is_mon()) {
lp::explanation expl;
generate_explanations_of_tang_lemma(*rm, bf, expl);
generate_explanations_of_tang_lemma(m, bf, expl);
for (unsigned i = lemmas_size_was; i < c().m_lemma_vec->size(); i++) {
auto &l = ((*c().m_lemma_vec)[i]);
l.expl().add(expl);
@ -135,14 +152,14 @@ void tangents::tangent_lemma_bf(const bfc& bf, lpvar j, const rational& sign, co
c().print_specific_lemma((*c().m_lemma_vec)[i], tout); );
}
void tangents::generate_two_tang_lines(const bfc & bf, const point& xy, const rational& sign, lpvar j) {
void tangents::generate_two_tang_lines(const factorization & bf, const point& xy, lpvar j) {
add_empty_lemma();
c().mk_ineq(var(bf.m_x), llc::NE, xy.x);
c().mk_ineq(sign, j, - xy.x, var(bf.m_y), llc::EQ);
c().mk_ineq(var(bf[0]), llc::NE, xy.x);
c().mk_ineq(j, - xy.x, var(bf[1]), llc::EQ);
add_empty_lemma();
c().mk_ineq(var(bf.m_y), llc::NE, xy.y);
c().mk_ineq(sign, j, - xy.y, var(bf.m_x), llc::EQ);
c().mk_ineq(var(bf[1]), llc::NE, xy.y);
c().mk_ineq(j, - xy.y, var(bf[0]), llc::EQ);
}
// Get two planes tangent to surface z = xy, one at point a, and another at point b.
@ -168,7 +185,7 @@ void tangents::push_tang_point(point &a, const point& xy, bool below, const rati
while (steps--) {
del *= rational(2);
point na = xy + del;
TRACE("nla_solver", tout << "del = " << del << std::endl;);
TRACE("nla_solver_tp", tout << "del = " << del << std::endl;);
if (!plane_is_correct_cut(na, xy, correct_val, val, below)) {
TRACE("nla_solver_tp", tout << "exit";tout << std::endl;);
return;