diff --git a/src/util/lp/nla_solver.cpp b/src/util/lp/nla_solver.cpp index 323d7c00c..73bc26085 100644 --- a/src/util/lp/nla_solver.cpp +++ b/src/util/lp/nla_solver.cpp @@ -1107,7 +1107,7 @@ struct solver::imp { } }; - // we derive a lemma from |x| >= 1 || |y| = 0 => |xy| >= |y| + // we derive a lemma from |x| >= 1 || y = 0 => |xy| >= |y| bool lemma_for_proportional_factors_on_vars_ge(lpvar i, lpvar j, lpvar k) { if (!(abs(vvr(j)) >= rational(1) || vvr(k).is_zero())) return false; @@ -1118,25 +1118,51 @@ struct solver::imp { } return false; } - - // we derive a lemma from |x| <= 1 || |y| = 0 => |xy| <= |y| - bool lemma_for_proportional_factors_on_vars_le(lpvar i, lpvar j, lpvar k) { + // here xy + // we derive a lemma from |x| <= 1 || y = 0 => |xy| <= |y| + bool lemma_for_proportional_factors_on_vars_le(lpvar xy, lpvar x, lpvar y) { TRACE("nla_solver", - tout << "i="; - print_var(i, tout); - tout << "j="; - print_var(j, tout); - tout << "k="; - print_var(k, tout);); - - if (!(abs(vvr(j)) <= rational(1) || vvr(k).is_zero())) + tout << "xy="; + print_var(xy, tout); + tout << "x="; + print_var(x, tout); + tout << "y="; + print_var(y, tout);); + const rational & _x = vvr(x); + const rational & _y = vvr(y); + + if (!(abs(_x) <= rational(1) || _y.is_zero())) return false; // the precondition holds - if (! (abs(vvr(i)) <= abs(vvr(k)))) { - SASSERT(false); // create here - return true; - } - return false; + const rational & _xy = vvr(xy); + if (abs(_xy) <= abs(_y)) + return false; + // adding x != val(x); + lp::lar_term t; + t.add_coeff_var(rational(1), x); + m_lemma->push_back(ineq(lp::lconstraint_kind::NE, t, _x)); + + t.clear(); + t.add_coeff_var(rational(1), y); + int y_sign; + if (_y.is_pos()) { + y_sign = 1; + m_lemma->push_back(ineq(lp::lconstraint_kind::LE, t, rational::zero())); + } else if (_y.is_neg()) { + y_sign = -1; + m_lemma->push_back(ineq(lp::lconstraint_kind::GE, t, rational::zero())); + } else { + SASSERT(_y.is_zero()); + y_sign = 1; + m_lemma->push_back(ineq(lp::lconstraint_kind::NE, t, rational::zero())); + } + int xy_sign = _xy.is_pos()? 1: -1; + t.clear(); // abs(xy) - abs(y) <= 0 + t.add_coeff_var(rational(xy_sign), xy); + t.add_coeff_var(rational(-y_sign), y); + m_lemma->push_back(ineq(lp::lconstraint_kind::LE, t, rational::zero())); + TRACE("nla_solver", tout<< "lemma: ";print_lemma(*m_lemma, tout);); + return true; } @@ -1153,13 +1179,10 @@ struct solver::imp { tout << "*"; print_var(f.m_k, tout); ); - if (lemma_for_proportional_factors_on_vars_ge(var_of_mon, f.m_j, f.m_k) - || lemma_for_proportional_factors_on_vars_ge(var_of_mon, f.m_k, f.m_j)) - return true; - if (lemma_for_proportional_factors_on_vars_le(var_of_mon, f.m_j, f.m_k) - || lemma_for_proportional_factors_on_vars_le(var_of_mon, f.m_k, f.m_j)) - return true; - return false; + return lemma_for_proportional_factors_on_vars_ge(var_of_mon, f.m_j, f.m_k) + || lemma_for_proportional_factors_on_vars_ge(var_of_mon, f.m_k, f.m_j) + || lemma_for_proportional_factors_on_vars_le(var_of_mon, f.m_j, f.m_k) + || lemma_for_proportional_factors_on_vars_le(var_of_mon, f.m_k, f.m_j); } // we derive a lemma from |xy| >= |y| => |x| >= 1 || |y| = 0 bool basic_lemma_for_mon_proportionality_from_product_to_factors(unsigned i_mon) {