mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 13:28:47 +00:00
more lemmas but return after if sign lemmas found
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
0dcebde060
commit
f9df9f48bd
|
@ -779,9 +779,17 @@ struct solver::imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
void negate_strict_sign(lpvar j) {
|
void negate_strict_sign(lpvar j) {
|
||||||
SASSERT(!vvr(j).is_zero());
|
int sign;
|
||||||
mk_ineq(j, (rat_sign(vvr(j)) == 1? llc::LE : llc::GE), current_lemma());
|
if (!vvr(j).is_zero()){
|
||||||
}
|
sign = rat_sign(vvr(j));
|
||||||
|
mk_ineq(j, (sign == 1? llc::LE : llc::GE), current_lemma());
|
||||||
|
} else {
|
||||||
|
sign = 1;
|
||||||
|
try_get_non_strict_sign_from_bounds(j, sign);
|
||||||
|
mk_ineq(j, (sign == 1? llc::LT : llc::GT), current_lemma());
|
||||||
|
SASSERT(sign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void generate_strict_case_zero_lemma(const monomial& m, unsigned zero_j, int sign_of_zj) {
|
void generate_strict_case_zero_lemma(const monomial& m, unsigned zero_j, int sign_of_zj) {
|
||||||
// we know all the signs
|
// we know all the signs
|
||||||
|
@ -796,26 +804,81 @@ struct solver::imp {
|
||||||
negate_strict_sign(m.var());
|
negate_strict_sign(m.var());
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_zero_lemma(const monomial& m) {
|
bool has_upper_bound(lpvar j) const {
|
||||||
SASSERT(!vvr(m).is_zero());
|
return m_lar_solver.column_has_upper_bound(j);
|
||||||
int sign = rat_sign(vvr(m));
|
}
|
||||||
unsigned zero_j = -1;
|
|
||||||
|
bool has_lower_bound(lpvar j) const {
|
||||||
|
return m_lar_solver.column_has_lower_bound(j);
|
||||||
|
}
|
||||||
|
const rational& get_upper_bound(unsigned j) const {
|
||||||
|
return m_lar_solver.get_upper_bound(j).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rational& get_lower_bound(unsigned j) const {
|
||||||
|
return m_lar_solver.get_lower_bound(j).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool zero_is_an_inner_point_of_bounds(lpvar j) const {
|
||||||
|
if (has_upper_bound(j) && get_upper_bound(j) <= rational(0))
|
||||||
|
return false;
|
||||||
|
if (has_lower_bound(j) && get_lower_bound(j) >= rational(0))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to find a variable j such that vvr(j) = 0
|
||||||
|
// and the bounds on j contain 0 as an inner point
|
||||||
|
lpvar find_best_zero(const monomial& m) const {
|
||||||
|
lpvar zero_j = -1;
|
||||||
for (unsigned j : m){
|
for (unsigned j : m){
|
||||||
|
if (vvr(j).is_zero()){
|
||||||
|
zero_j = j;
|
||||||
|
if (zero_is_an_inner_point_of_bounds(j))
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return zero_j;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_set(unsigned j) {
|
||||||
|
return static_cast<int>(j) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_get_non_strict_sign_from_bounds(lpvar j, int& sign) const {
|
||||||
|
SASSERT(sign);
|
||||||
|
if (has_lower_bound(j) && get_lower_bound(j) >= rational(0))
|
||||||
|
return true;
|
||||||
|
if (has_upper_bound(j) && get_upper_bound(j) <= rational(0)) {
|
||||||
|
sign = -sign;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
sign = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_non_strict_sign(lpvar j, int& sign) const {
|
||||||
const rational & v = vvr(j);
|
const rational & v = vvr(j);
|
||||||
if (v.is_zero()){
|
if (v.is_zero()) {
|
||||||
if (zero_j + 1 == 0) {
|
try_get_non_strict_sign_from_bounds(j, sign);
|
||||||
zero_j = j;
|
|
||||||
} else {
|
|
||||||
sign = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sign *= rat_sign(v);
|
sign *= rat_sign(v);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_zero_lemma(const monomial& m) {
|
||||||
|
SASSERT(!vvr(m).is_zero());
|
||||||
|
int sign = rat_sign(vvr(m));
|
||||||
|
unsigned zero_j = find_best_zero(m);
|
||||||
|
SASSERT(is_set(zero_j));
|
||||||
|
for (unsigned j : m){
|
||||||
|
if (j == zero_j) continue;
|
||||||
|
get_non_strict_sign(j, sign);
|
||||||
|
if(sign == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
TRACE("nla_solver", tout << "sign = " << sign << "\n";);
|
TRACE("nla_solver", tout << "zero_j = " << zero_j << ", sign = " << sign << "\n";);
|
||||||
|
|
||||||
SASSERT(zero_j + 1);
|
|
||||||
if (sign == 0) {
|
if (sign == 0) {
|
||||||
mk_ineq(zero_j, llc::NE, current_lemma());
|
mk_ineq(zero_j, llc::NE, current_lemma());
|
||||||
mk_ineq(m.var(), llc::EQ, current_lemma());
|
mk_ineq(m.var(), llc::EQ, current_lemma());
|
||||||
|
@ -856,10 +919,10 @@ struct solver::imp {
|
||||||
return m_vars_equivalence.eq_vars(j);
|
return m_vars_equivalence.eq_vars(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_sign_lemma_on_two_monomials(const monomial& m, const monomial& n) {
|
bool basic_sign_lemma_on_two_monomials(const monomial& m, const monomial& n, const rational& sign) {
|
||||||
TRACE("nla_solver", tout << "m = "; print_monomial_with_vars(m, tout); tout << "n= "; print_monomial_with_vars(n, tout); );
|
TRACE("nla_solver", tout << "m = "; print_monomial_with_vars(m, tout); tout << "n= "; print_monomial_with_vars(n, tout); );
|
||||||
rational sign;
|
rational contr_sign;
|
||||||
if (sign_contradiction(m, n, sign)) {
|
if (sign_contradiction(m, n, contr_sign)) {
|
||||||
generate_sign_lemma(m, n, sign);
|
generate_sign_lemma(m, n, sign);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -939,8 +1002,9 @@ struct solver::imp {
|
||||||
for (index_with_sign i_s : mons_to_explore) {
|
for (index_with_sign i_s : mons_to_explore) {
|
||||||
unsigned n = i_s.index();
|
unsigned n = i_s.index();
|
||||||
if (n == i) continue;
|
if (n == i) continue;
|
||||||
if (basic_sign_lemma_on_two_monomials(m, m_monomials[n]))
|
if (basic_sign_lemma_on_two_monomials(m, m_monomials[n], rm_i_s.sign()*i_s.sign()))
|
||||||
return true;
|
if(done())
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
TRACE("nla_solver",);
|
TRACE("nla_solver",);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1621,13 +1685,11 @@ struct solver::imp {
|
||||||
do {
|
do {
|
||||||
const rooted_mon& r = m_rm_table.vec()[rm_ref[i]];
|
const rooted_mon& r = m_rm_table.vec()[rm_ref[i]];
|
||||||
SASSERT (!check_monomial(m_monomials[r.orig_index()]));
|
SASSERT (!check_monomial(m_monomials[r.orig_index()]));
|
||||||
if (basic_lemma_for_mon(r, derived)) {
|
basic_lemma_for_mon(r, derived);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (++i == rm_ref.size()) {
|
if (++i == rm_ref.size()) {
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
} while(i != start);
|
} while(i != start && !done());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1829,6 +1891,12 @@ struct solver::imp {
|
||||||
if (!check_monomial(m_monomials[i]))
|
if (!check_monomial(m_monomials[i]))
|
||||||
m_to_refine.push_back(i);
|
m_to_refine.push_back(i);
|
||||||
}
|
}
|
||||||
|
TRACE("nla_solver",
|
||||||
|
tout << "to refine: ";
|
||||||
|
for (unsigned i: m_to_refine) {
|
||||||
|
print_monomial_with_vars(m_monomials[i], tout);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool divide(const rooted_mon& bc, const factor& c, factor & b) const {
|
bool divide(const rooted_mon& bc, const factor& c, factor & b) const {
|
||||||
|
@ -2329,6 +2397,9 @@ struct solver::imp {
|
||||||
// not a strict version
|
// not a strict version
|
||||||
void generate_monl(const rooted_mon& a,
|
void generate_monl(const rooted_mon& a,
|
||||||
const rooted_mon& b) {
|
const rooted_mon& b) {
|
||||||
|
TRACE("nla_solver", tout <<
|
||||||
|
"a = "; print_rooted_monomial_with_vars(a, tout) << "\n:";
|
||||||
|
tout << "b = "; print_rooted_monomial_with_vars(a, tout) << "\n:";);
|
||||||
add_empty_lemma();
|
add_empty_lemma();
|
||||||
auto akey = get_sorted_key_with_vars(a);
|
auto akey = get_sorted_key_with_vars(a);
|
||||||
auto bkey = get_sorted_key_with_vars(b);
|
auto bkey = get_sorted_key_with_vars(b);
|
||||||
|
@ -2500,6 +2571,7 @@ struct solver::imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool generate_simple_tangent_lemma(const rooted_mon* rm) {
|
bool generate_simple_tangent_lemma(const rooted_mon* rm) {
|
||||||
|
TRACE("nla_solver", tout << "rm:"; print_rooted_monomial_with_vars(*rm, tout) << std::endl; tout << "ls = " << m_lemma_vec->size(););
|
||||||
add_empty_lemma();
|
add_empty_lemma();
|
||||||
unsigned i_mon = rm->orig_index();
|
unsigned i_mon = rm->orig_index();
|
||||||
const monomial & m = m_monomials[i_mon];
|
const monomial & m = m_monomials[i_mon];
|
||||||
|
@ -2601,7 +2673,6 @@ struct solver::imp {
|
||||||
else {
|
else {
|
||||||
mk_ineq(j, llc::LE, a, l);
|
mk_ineq(j, llc::LE, a, l);
|
||||||
}
|
}
|
||||||
TRACE("nla_solver", print_lemma(tout););
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -2683,33 +2754,37 @@ struct solver::imp {
|
||||||
TRACE("nla_solver", tout << "pushed a = "; print_point(a, tout); tout << "\npushed b = "; print_point(b, tout); tout << std::endl;);
|
TRACE("nla_solver", tout << "pushed a = "; print_point(a, tout); tout << "\npushed b = "; print_point(b, tout); tout << std::endl;);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool conflict_found() const {
|
||||||
|
for (const auto & l : * m_lemma_vec) {
|
||||||
|
if (l.is_conflict())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool done() const {
|
||||||
|
return m_lemma_vec->size() >= 10 || conflict_found();
|
||||||
|
}
|
||||||
|
|
||||||
lbool inner_check(bool derived) {
|
lbool inner_check(bool derived) {
|
||||||
lbool ret = l_undef;
|
for (int search_level = 0; search_level < 3 && !done(); search_level++) {
|
||||||
for (int search_level = 0; search_level < 3 && ret == l_undef; search_level++) {
|
|
||||||
TRACE("nla_solver", tout << "search_level = " << search_level << "\n";);
|
TRACE("nla_solver", tout << "search_level = " << search_level << "\n";);
|
||||||
if (search_level == 0) {
|
if (search_level == 0) {
|
||||||
if (basic_lemma(derived)) {
|
basic_lemma(derived);
|
||||||
ret = l_false;
|
if (!m_lemma_vec->empty())
|
||||||
}
|
return l_false;
|
||||||
} else if (search_level == 1) {
|
} else if (search_level == 1) {
|
||||||
if (order_lemma(derived)) {
|
order_lemma(derived);
|
||||||
ret = l_false;
|
|
||||||
}
|
|
||||||
} else { // search_level == 2
|
} else { // search_level == 2
|
||||||
if (!derived && (monotonicity_lemma() || tangent_lemma())) {
|
if (!derived) {
|
||||||
ret = l_false;
|
monotonicity_lemma();
|
||||||
|
tangent_lemma();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return m_lemma_vec->empty()? l_undef : l_false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
lbool check(vector<lemma>& l_vec) {
|
lbool check(vector<lemma>& l_vec) {
|
||||||
settings().st().m_nla_calls++;
|
settings().st().m_nla_calls++;
|
||||||
TRACE("nla_solver", tout << "calls = " << settings().st().m_nla_calls << "\n";);
|
TRACE("nla_solver", tout << "calls = " << settings().st().m_nla_calls << "\n";);
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
vector<ineq>& ineqs() { return m_ineqs; }
|
vector<ineq>& ineqs() { return m_ineqs; }
|
||||||
lp::explanation& expl() { return m_expl; }
|
lp::explanation& expl() { return m_expl; }
|
||||||
const lp::explanation& expl() const { return m_expl; }
|
const lp::explanation& expl() const { return m_expl; }
|
||||||
|
bool is_conflict() const { return m_ineqs.empty() && !m_expl.empty(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef vector<monomial> polynomial;
|
typedef vector<monomial> polynomial;
|
||||||
|
|
Loading…
Reference in a new issue