mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 12:08:18 +00:00
na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
179c9c2da2
commit
99043399ce
|
@ -207,11 +207,11 @@ void basics::negate_strict_sign(new_lemma& lemma, lpvar j) {
|
||||||
}
|
}
|
||||||
else { // val(j).is_zero()
|
else { // val(j).is_zero()
|
||||||
if (c().has_lower_bound(j) && c().get_lower_bound(j) >= rational(0)) {
|
if (c().has_lower_bound(j) && c().get_lower_bound(j) >= rational(0)) {
|
||||||
c().explain_existing_lower_bound(lemma, j);
|
lemma.explain_existing_lower_bound(j);
|
||||||
lemma |= ineq(j, llc::GT, 0);
|
lemma |= ineq(j, llc::GT, 0);
|
||||||
} else {
|
} else {
|
||||||
SASSERT(c().has_upper_bound(j) && c().get_upper_bound(j) <= rational(0));
|
SASSERT(c().has_upper_bound(j) && c().get_upper_bound(j) <= rational(0));
|
||||||
c().explain_existing_upper_bound(lemma, j);
|
lemma.explain_existing_upper_bound(j);
|
||||||
lemma |= ineq(j, llc::LT, 0);
|
lemma |= ineq(j, llc::LT, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,7 +302,7 @@ bool basics::basic_lemma_for_mon_non_zero_derived(const monic& rm, const factori
|
||||||
continue;
|
continue;
|
||||||
new_lemma lemma(c(), "x = 0 or y = 0 -> xy = 0");
|
new_lemma lemma(c(), "x = 0 or y = 0 -> xy = 0");
|
||||||
lemma.explain_fixed(var(fc));
|
lemma.explain_fixed(var(fc));
|
||||||
c().explain_var_separated_from_zero(lemma, var(rm));
|
lemma.explain_var_separated_from_zero(var(rm));
|
||||||
lemma &= rm;
|
lemma &= rm;
|
||||||
lemma &= f;
|
lemma &= f;
|
||||||
return true;
|
return true;
|
||||||
|
@ -328,7 +328,7 @@ bool basics::basic_lemma_for_mon_neutral_derived(const monic& rm, const factoriz
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
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 u = null_lpvar, v = null_lpvar;
|
||||||
bool all_int = true;
|
bool all_int = true;
|
||||||
for (auto fc : f) {
|
for (auto fc : f) {
|
||||||
lpvar j = var(fc);
|
lpvar j = var(fc);
|
||||||
|
@ -336,31 +336,22 @@ bool basics::basic_lemma_for_mon_neutral_derived(const monic& rm, const factoriz
|
||||||
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)))
|
||||||
jl = j;
|
u = j;
|
||||||
else if (j == jl)
|
|
||||||
return false;
|
|
||||||
else if (abs(val(j)) != rational(1))
|
else if (abs(val(j)) != rational(1))
|
||||||
not_one_j = j;
|
v = j;
|
||||||
}
|
}
|
||||||
if (jl == null_lpvar || not_one_j == null_lpvar)
|
if (u == null_lpvar || v == null_lpvar)
|
||||||
return false;
|
return false;
|
||||||
if (!all_int && f.size() > 2)
|
if (!all_int && f.size() > 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// (mon_var != 0 || u != 0) & mon_var = +/- u =>
|
||||||
|
// v = 1 or v = -1
|
||||||
new_lemma lemma(c(), "|xa| = |x| & x != 0 -> |a| = 1");
|
new_lemma lemma(c(), "|xa| = |x| & x != 0 -> |a| = 1");
|
||||||
// mon_var = 0
|
lemma.explain_var_separated_from_zero(mon_var_is_sep_from_zero ? mon_var : u);
|
||||||
if (mon_var_is_sep_from_zero)
|
lemma.explain_equiv(mon_var, u);
|
||||||
c().explain_var_separated_from_zero(lemma, mon_var);
|
lemma |= ineq(v, llc::EQ, 1);
|
||||||
else
|
lemma |= ineq(v, llc::EQ, -1);
|
||||||
c().explain_var_separated_from_zero(lemma, jl);
|
|
||||||
|
|
||||||
lemma.explain_equiv(mon_var, jl);
|
|
||||||
|
|
||||||
// not_one_j = 1
|
|
||||||
lemma |= ineq(not_one_j, llc::EQ, 1);
|
|
||||||
|
|
||||||
// not_one_j = -1
|
|
||||||
lemma |= ineq(not_one_j, llc::EQ, -1);
|
|
||||||
lemma &= rm;
|
lemma &= rm;
|
||||||
lemma &= f;
|
lemma &= f;
|
||||||
return true;
|
return true;
|
||||||
|
@ -422,9 +413,6 @@ NSB review:
|
||||||
|
|
||||||
sign_m*m < 0 or f_j = 0 or \/_{i != j} sign_m*m >= sign_i*f_i
|
sign_m*m < 0 or f_j = 0 or \/_{i != j} sign_m*m >= sign_i*f_i
|
||||||
|
|
||||||
- or even, without reference to factor index:
|
|
||||||
sign_m*m < 0 or \/_i sign_m*m >= sign_i*f_i
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void basics::generate_pl_on_mon(const monic& m, unsigned factor_index) {
|
void basics::generate_pl_on_mon(const monic& m, unsigned factor_index) {
|
||||||
SASSERT(!mon_has_real(m));
|
SASSERT(!mon_has_real(m));
|
||||||
|
@ -529,7 +517,7 @@ void basics::basic_lemma_for_mon_zero_model_based(const monic& rm, const factori
|
||||||
} else {
|
} else {
|
||||||
lemma |= ineq(var(rm), llc::NE, 0);
|
lemma |= ineq(var(rm), llc::NE, 0);
|
||||||
for (auto j : f) {
|
for (auto j : f) {
|
||||||
c().explain_separation_from_zero(lemma, var(j));
|
lemma.explain_separation_from_zero(var(j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lemma &= f;
|
lemma &= f;
|
||||||
|
@ -601,8 +589,8 @@ bool basics::basic_lemma_for_mon_neutral_from_factors_to_monic_model_based_fm(co
|
||||||
|
|
||||||
new_lemma lemma(c(), __FUNCTION__);
|
new_lemma lemma(c(), __FUNCTION__);
|
||||||
for (auto j : m.vars()) {
|
for (auto j : m.vars()) {
|
||||||
if (not_one == j) continue;
|
if (not_one != j)
|
||||||
lemma |= ineq(j, llc::NE, val(j));
|
lemma |= ineq(j, llc::NE, val(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not_one == null_lpvar)
|
if (not_one == null_lpvar)
|
||||||
|
@ -613,7 +601,7 @@ bool basics::basic_lemma_for_mon_neutral_from_factors_to_monic_model_based_fm(co
|
||||||
}
|
}
|
||||||
|
|
||||||
// use the fact that
|
// use the fact that
|
||||||
// |xabc| = |x| and x != 0 -> |a| = |b| = |c| = 1
|
// |uvw| = |u| and uvw != 0 -> |v| = 1
|
||||||
bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based(const monic& rm, const factorization& f) {
|
bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based(const monic& rm, const factorization& f) {
|
||||||
lpvar mon_var = c().emons()[rm.var()].var();
|
lpvar mon_var = c().emons()[rm.var()].var();
|
||||||
TRACE("nla_solver_bl", c().trace_print_monic_and_factorization(rm, f, tout); tout << "\nmon_var = " << mon_var << "\n";);
|
TRACE("nla_solver_bl", c().trace_print_monic_and_factorization(rm, f, tout); tout << "\nmon_var = " << mon_var << "\n";);
|
||||||
|
@ -624,36 +612,32 @@ 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, not_one_j = null_lpvar;
|
lpvar u = null_lpvar, v = null_lpvar;
|
||||||
bool all_int = true;
|
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);
|
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;
|
u = j;
|
||||||
else if (j == jl)
|
|
||||||
return false;
|
|
||||||
else if (abs(val(fc)) != rational(1))
|
else if (abs(val(fc)) != rational(1))
|
||||||
not_one_j = j;
|
v = j;
|
||||||
}
|
}
|
||||||
if (jl == null_lpvar || not_one_j == null_lpvar)
|
if (u == null_lpvar || v == null_lpvar)
|
||||||
return false;
|
return false;
|
||||||
if (!all_int && f.size() > 2)
|
if (!all_int && f.size() > 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
new_lemma lemma(c(), __FUNCTION__);
|
|
||||||
// mon_var = 0
|
// mon_var = 0
|
||||||
lemma |= ineq(mon_var, llc::EQ, 0);
|
// abs(u) != abs(mon_var)
|
||||||
|
// v = 1
|
||||||
// negate abs(jl) == abs()
|
// v = -1
|
||||||
lemma |= ineq(term(jl, rational(val(jl) == -val(mon_var) ? 1 : -1), mon_var), llc::NE, 0);
|
|
||||||
|
|
||||||
// not_one_j = 1
|
new_lemma lemma(c(), __FUNCTION__);
|
||||||
lemma |= ineq(not_one_j, llc::EQ, 1);
|
lemma |= ineq(mon_var, llc::EQ, 0);
|
||||||
|
lemma |= ineq(term(u, rational(val(u) == -val(mon_var) ? 1 : -1), mon_var), llc::NE, 0);
|
||||||
// not_one_j = -1
|
lemma |= ineq(v, llc::EQ, 1);
|
||||||
lemma |= ineq(not_one_j, llc::EQ, -1);
|
lemma |= ineq(v, llc::EQ, -1);
|
||||||
lemma &= rm;
|
lemma &= rm; // NSB review: is this dependency required?
|
||||||
lemma &= f;
|
lemma &= f;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -695,7 +679,7 @@ bool basics::basic_lemma_for_mon_neutral_from_factors_to_monic_model_based(const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v == -rational(1)) {
|
if (v == -rational(1)) {
|
||||||
sign = - sign;
|
sign = -sign;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -625,24 +625,6 @@ bool core::is_canonical_monic(lpvar j) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void core::explain_existing_lower_bound(new_lemma& lemma, lpvar j) {
|
|
||||||
SASSERT(has_lower_bound(j));
|
|
||||||
lemma &= m_lar_solver.get_column_lower_bound_witness(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
void core::explain_existing_upper_bound(new_lemma& lemma, lpvar j) {
|
|
||||||
SASSERT(has_upper_bound(j));
|
|
||||||
lemma &= m_lar_solver.get_column_upper_bound_witness(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
void core::explain_separation_from_zero(new_lemma& lemma, lpvar j) {
|
|
||||||
SASSERT(!val(j).is_zero());
|
|
||||||
if (val(j).is_pos())
|
|
||||||
explain_existing_lower_bound(lemma, j);
|
|
||||||
else
|
|
||||||
explain_existing_upper_bound(lemma, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
void core::trace_print_monic_and_factorization(const monic& rm, const factorization& f, std::ostream& out) const {
|
void core::trace_print_monic_and_factorization(const monic& rm, const factorization& f, std::ostream& out) const {
|
||||||
out << "rooted vars: ";
|
out << "rooted vars: ";
|
||||||
print_product(rm.rvars(), out) << "\n";
|
print_product(rm.rvars(), out) << "\n";
|
||||||
|
@ -651,14 +633,6 @@ void core::trace_print_monic_and_factorization(const monic& rm, const factorizat
|
||||||
print_factorization(f, out << "fact: ") << "\n";
|
print_factorization(f, out << "fact: ") << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void core::explain_var_separated_from_zero(new_lemma& lemma, lpvar j) {
|
|
||||||
SASSERT(var_is_separated_from_zero(j));
|
|
||||||
if (m_lar_solver.column_has_upper_bound(j) && (m_lar_solver.get_upper_bound(j)< lp::zero_of_type<lp::impq>()))
|
|
||||||
lemma &= m_lar_solver.get_column_upper_bound_witness(j);
|
|
||||||
else
|
|
||||||
lemma &= m_lar_solver.get_column_lower_bound_witness(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool core::var_has_positive_lower_bound(lpvar j) const {
|
bool core::var_has_positive_lower_bound(lpvar j) const {
|
||||||
return m_lar_solver.column_has_lower_bound(j) && m_lar_solver.get_lower_bound(j) > lp::zero_of_type<lp::impq>();
|
return m_lar_solver.column_has_lower_bound(j) && m_lar_solver.get_lower_bound(j) > lp::zero_of_type<lp::impq>();
|
||||||
|
@ -1187,6 +1161,38 @@ new_lemma& new_lemma::explain_equiv(lpvar a, lpvar b) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_lemma& new_lemma::explain_var_separated_from_zero(lpvar j) {
|
||||||
|
SASSERT(c.var_is_separated_from_zero(j));
|
||||||
|
if (c.m_lar_solver.column_has_upper_bound(j) &&
|
||||||
|
(c.m_lar_solver.get_upper_bound(j)< lp::zero_of_type<lp::impq>()))
|
||||||
|
*this &= c.m_lar_solver.get_column_upper_bound_witness(j);
|
||||||
|
else
|
||||||
|
*this &= c.m_lar_solver.get_column_lower_bound_witness(j);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_lemma& new_lemma::explain_existing_lower_bound(lpvar j) {
|
||||||
|
SASSERT(c.has_lower_bound(j));
|
||||||
|
*this &= c.m_lar_solver.get_column_lower_bound_witness(j);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_lemma& new_lemma::explain_existing_upper_bound(lpvar j) {
|
||||||
|
SASSERT(c.has_upper_bound(j));
|
||||||
|
*this &= c.m_lar_solver.get_column_upper_bound_witness(j);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_lemma& new_lemma::explain_separation_from_zero(lpvar j) {
|
||||||
|
SASSERT(!c.val(j).is_zero());
|
||||||
|
if (c.val(j).is_pos())
|
||||||
|
explain_existing_lower_bound(j);
|
||||||
|
else
|
||||||
|
explain_existing_upper_bound(j);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::ostream& new_lemma::display(std::ostream & out) const {
|
std::ostream& new_lemma::display(std::ostream & out) const {
|
||||||
auto const& lemma = current();
|
auto const& lemma = current();
|
||||||
|
|
|
@ -105,6 +105,11 @@ public:
|
||||||
new_lemma& operator|=(ineq const& i);
|
new_lemma& operator|=(ineq const& i);
|
||||||
new_lemma& explain_fixed(lpvar j);
|
new_lemma& explain_fixed(lpvar j);
|
||||||
new_lemma& explain_equiv(lpvar u, lpvar v);
|
new_lemma& explain_equiv(lpvar u, lpvar v);
|
||||||
|
new_lemma& explain_var_separated_from_zero(lpvar j);
|
||||||
|
new_lemma& explain_existing_lower_bound(lpvar j);
|
||||||
|
new_lemma& explain_existing_upper_bound(lpvar j);
|
||||||
|
new_lemma& explain_separation_from_zero(lpvar j);
|
||||||
|
|
||||||
unsigned num_ineqs() const { return current().ineqs().size(); }
|
unsigned num_ineqs() const { return current().ineqs().size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -245,13 +250,7 @@ public:
|
||||||
|
|
||||||
// return true iff the monic value is equal to the product of the values of the factors
|
// return true iff the monic value is equal to the product of the values of the factors
|
||||||
bool check_monic(const monic& m) const;
|
bool check_monic(const monic& m) const;
|
||||||
|
|
||||||
// NSB review: these should really be methods on new_lemma
|
|
||||||
void explain_existing_lower_bound(new_lemma& lemma, lpvar j);
|
|
||||||
void explain_existing_upper_bound(new_lemma& lemma, lpvar j);
|
|
||||||
void explain_separation_from_zero(new_lemma& lemma, lpvar j);
|
|
||||||
void explain_var_separated_from_zero(new_lemma& lemma, lpvar j);
|
|
||||||
|
|
||||||
|
|
||||||
std::ostream & print_ineq(const ineq & in, std::ostream & out) const;
|
std::ostream & print_ineq(const ineq & in, std::ostream & out) const;
|
||||||
std::ostream & print_var(lpvar j, std::ostream & out) const;
|
std::ostream & print_var(lpvar j, std::ostream & out) const;
|
||||||
|
|
Loading…
Reference in a new issue