3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 20:18:18 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-05-10 09:56:09 -07:00
parent 6c72f39142
commit d774ba9da1
2 changed files with 40 additions and 26 deletions

View file

@ -46,7 +46,7 @@ void basics::generate_zero_lemmas(const monic& m) {
} }
TRACE("nla_solver_details", tout << "zero_j = " << zero_j << ", sign = " << sign << "\n";); TRACE("nla_solver_details", tout << "zero_j = " << zero_j << ", sign = " << sign << "\n";);
if (sign == 0) { // have to generate a non-convex lemma if (sign == 0) { // have to generate a non-convex lemma
add_trival_zero_lemma(zero_j, m); add_trivial_zero_lemma(zero_j, m);
} else { // here we know the sign of zero_j } else { // here we know the sign of zero_j
generate_strict_case_zero_lemma(m, zero_j, sign); generate_strict_case_zero_lemma(m, zero_j, sign);
} }
@ -171,11 +171,13 @@ lpvar basics::find_best_zero(const monic& m, unsigned_vector & fixed_zeros) cons
} }
return zero_j; return zero_j;
} }
void basics::add_trival_zero_lemma(lpvar zero_j, const monic& m) {
new_lemma lemma(c(), "x = 0 or x != 0"); void basics::add_trivial_zero_lemma(lpvar zero_j, const monic& m) {
new_lemma lemma(c(), "x = 0 => x*y = 0");
c().mk_ineq(zero_j, llc::NE); c().mk_ineq(zero_j, llc::NE);
c().mk_ineq(m.var(), llc::EQ); c().mk_ineq(m.var(), llc::EQ);
} }
void basics::generate_strict_case_zero_lemma(const monic& m, unsigned zero_j, int sign_of_zj) { void basics::generate_strict_case_zero_lemma(const monic& m, unsigned zero_j, int sign_of_zj) {
TRACE("nla_solver_bl", tout << "sign_of_zj = " << sign_of_zj << "\n";); TRACE("nla_solver_bl", tout << "sign_of_zj = " << sign_of_zj << "\n";);
// we know all the signs // we know all the signs
@ -305,6 +307,9 @@ bool basics::basic_lemma_for_mon_non_zero_derived(const monic& rm, const factori
} }
// use the fact that // use the fact that
// |xabc| = |x| and x != 0 -> |a| = |b| = |c| = 1 // |xabc| = |x| and x != 0 -> |a| = |b| = |c| = 1
// it holds for integers, and for reals for a pair of factors
// |x*a| = |x| & x != 0 -> |a| = 1
bool basics::basic_lemma_for_mon_neutral_monic_to_factor_derived(const monic& rm, const factorization& f) { bool basics::basic_lemma_for_mon_neutral_monic_to_factor_derived(const monic& rm, const factorization& f) {
TRACE("nla_solver", c().trace_print_monic_and_factorization(rm, f, tout);); TRACE("nla_solver", c().trace_print_monic_and_factorization(rm, f, tout););
@ -319,8 +324,10 @@ bool basics::basic_lemma_for_mon_neutral_monic_to_factor_derived(const monic& rm
} }
bool mon_var_is_sep_from_zero = c().var_is_separated_from_zero(mon_var); bool mon_var_is_sep_from_zero = c().var_is_separated_from_zero(mon_var);
lpvar jl = null_lpvar, not_one_j = null_lpvar; lpvar jl = null_lpvar, not_one_j = null_lpvar;
bool all_int = true;
for (auto fc : f) { for (auto fc : f) {
lpvar j = var(fc); lpvar j = var(fc);
all_int &= c().var_is_int(j);
if (j == null_lpvar && abs(val(j)) == abs_mv && if (j == null_lpvar && abs(val(j)) == abs_mv &&
c().vars_are_equiv(j, mon_var) && c().vars_are_equiv(j, mon_var) &&
(mon_var_is_sep_from_zero || c().var_is_separated_from_zero(j))) (mon_var_is_sep_from_zero || c().var_is_separated_from_zero(j)))
@ -332,6 +339,8 @@ bool basics::basic_lemma_for_mon_neutral_monic_to_factor_derived(const monic& rm
} }
if (jl == null_lpvar || not_one_j == null_lpvar) if (jl == null_lpvar || not_one_j == null_lpvar)
return false; return false;
if (!all_int && f.size() > 2)
return false;
new_lemma lemma(c(), "|xa| = |x| & x != 0 -> |a| = 1"); new_lemma lemma(c(), "|xa| = |x| & x != 0 -> |a| = 1");
// mon_var = 0 // mon_var = 0
@ -518,9 +527,10 @@ bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based_fm(const mo
if (abs_mv == rational::zero()) { if (abs_mv == rational::zero()) {
return false; return false;
} }
lpvar jl = null_lpvar; lpvar jl = null_lpvar, not_one_j = null_lpvar;
lpvar not_one_j = null_lpvar; bool all_int = true;
for (auto j : m.vars()) { for (auto j : m.vars()) {
all_int &= c().var_is_int(j);
if (jl == null_lpvar && abs(val(j)) == abs_mv) if (jl == null_lpvar && abs(val(j)) == abs_mv)
jl = j; jl = j;
else if (jl == j) else if (jl == j)
@ -531,6 +541,9 @@ bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based_fm(const mo
if (jl == null_lpvar || not_one_j == null_lpvar) if (jl == null_lpvar || not_one_j == null_lpvar)
return false; return false;
if (!all_int && m.size() > 2)
return false;
new_lemma lemma(c(), __FUNCTION__); new_lemma lemma(c(), __FUNCTION__);
// mon_var = 0 // mon_var = 0
c().mk_ineq(mon_var, llc::EQ); c().mk_ineq(mon_var, llc::EQ);
@ -616,11 +629,11 @@ bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based(const monic
if (abs_mv == rational::zero()) { if (abs_mv == rational::zero()) {
return false; return false;
} }
lpvar jl = null_lpvar; lpvar jl = null_lpvar, not_one_j = null_lpvar;
lpvar not_one_j = null_lpvar; bool all_int = true;
for (auto fc : f) { for (auto fc : f) {
lpvar j = var(fc); lpvar j = var(fc);
all_int &= c().var_is_int(j);
if (j == null_lpvar && abs(val(fc)) == abs_mv) if (j == null_lpvar && abs(val(fc)) == abs_mv)
jl = j; jl = j;
else if (j == jl) else if (j == jl)
@ -630,6 +643,8 @@ bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based(const monic
} }
if (jl == null_lpvar || not_one_j == null_lpvar) if (jl == null_lpvar || not_one_j == null_lpvar)
return false; return false;
if (!all_int && f.size() > 2)
return false;
new_lemma lemma(c(), __FUNCTION__); new_lemma lemma(c(), __FUNCTION__);
// mon_var = 0 // mon_var = 0
@ -735,23 +750,22 @@ bool basics::basic_lemma_for_mon_neutral_from_factors_to_monic_model_based(const
void basics::basic_lemma_for_mon_non_zero_model_based_mf(const factorization& f) { void basics::basic_lemma_for_mon_non_zero_model_based_mf(const factorization& f) {
TRACE("nla_solver_bl", tout << c().pp(f);); TRACE("nla_solver_bl", tout << c().pp(f););
lpvar zero_j = null_lpvar;
for (auto j : f) { for (auto j : f) {
if (val(j).is_zero()) { if (val(j).is_zero()) {
zero_j = var(j); lpvar zero_j = var(j);
break; new_lemma lemma(c(), "x = 0 => x*... = 0");
}
}
if (zero_j == null_lpvar) { return; }
new_lemma lemma(c(), __FUNCTION__);
c().mk_ineq(zero_j, llc::NE); c().mk_ineq(zero_j, llc::NE);
c().mk_ineq(f.mon().var(), llc::EQ); c().mk_ineq(f.mon().var(), llc::EQ);
return;
}
}
} }
// x = 0 or y = 0 -> xy = 0 // x = 0 or y = 0 -> xy = 0
void basics::basic_lemma_for_mon_non_zero_model_based(const monic& rm, const factorization& f) { void basics::basic_lemma_for_mon_non_zero_model_based(const monic& rm, const factorization& f) {
TRACE("nla_solver_bl", c().trace_print_monic_and_factorization(rm, f, tout);); TRACE("nla_solver_bl", c().trace_print_monic_and_factorization(rm, f, tout););
# NSB code review:
# the two branches are the same
if (f.is_mon()) if (f.is_mon())
basic_lemma_for_mon_non_zero_model_based_mf(f); basic_lemma_for_mon_non_zero_model_based_mf(f);
else else

View file

@ -76,7 +76,7 @@ struct basics: common {
lpvar find_best_zero(const monic& m, unsigned_vector & fixed_zeros) const; lpvar find_best_zero(const monic& m, unsigned_vector & fixed_zeros) const;
bool try_get_non_strict_sign_from_bounds(lpvar j, int& sign) const; bool try_get_non_strict_sign_from_bounds(lpvar j, int& sign) const;
void get_non_strict_sign(lpvar j, int& sign) const; void get_non_strict_sign(lpvar j, int& sign) const;
void add_trival_zero_lemma(lpvar zero_j, const monic& m); void add_trivial_zero_lemma(lpvar zero_j, const monic& m);
void generate_strict_case_zero_lemma(const monic& m, unsigned zero_j, int sign_of_zj); void generate_strict_case_zero_lemma(const monic& m, unsigned zero_j, int sign_of_zj);
void add_fixed_zero_lemma(const monic& m, lpvar j); void add_fixed_zero_lemma(const monic& m, lpvar j);