3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 05:18:44 +00:00

operate with sign as a boolean

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2019-05-06 16:44:48 -07:00
parent 6d5fd5d980
commit 495161fe5c
9 changed files with 57 additions and 65 deletions

View file

@ -280,7 +280,6 @@ void emonomials::do_canonize(monomial & m) const {
bool emonomials::is_canonized(const monomial & m) const {
monomial mm(m);
do_canonize(mm);
return mm.rvars() == m.rvars();
}

View file

@ -61,8 +61,7 @@ public:
unsigned visited() const { return m_visited; }
unsigned& visited() { return m_visited; }
svector<lpvar> const& rvars() const { return m_rvars; }
bool sign() const { return m_rsign; }
rational rsign() const { return rational(m_rsign ? -1 : 1); }
bool rsign() const { return m_rsign; }
void reset_rfields() { m_rsign = false; m_rvars.reset(); SASSERT(m_rvars.size() == 0); }
void push_rvar(signed_var sv) { m_rsign ^= sv.sign(); m_rvars.push_back(sv.var()); }
void sort_rvars() {

View file

@ -27,7 +27,7 @@ basics::basics(core * c) : common(c) {}
// Monomials m and n vars have the same values, up to "sign"
// Generate a lemma if values of m.var() and n.var() are not the same up to sign
bool basics::basic_sign_lemma_on_two_monomials(const monomial& m, const monomial& n) {
const rational& sign = m.rsign() * n.rsign();
const rational sign = sign_to_rat(m.rsign() ^ n.rsign());
if (val(m) == val(n) * sign)
return false;
TRACE("nla_solver", tout << "sign contradiction:\nm = " << pp_mon(c(), m) << "n= " << pp_mon(c(), n) << "sign: " << sign << "\n";);
@ -478,14 +478,25 @@ void basics::generate_pl(const monomial& rm, const factorization& fc, int factor
explain(rm);
}
TRACE("nla_solver", c().print_lemma(tout); );
}
}
bool basics::is_separated_from_zero(const factorization& f) const {
for (const factor& fc: f) {
lpvar j = var(fc);
if (!(c().var_has_positive_lower_bound(j) || c().var_has_negative_upper_bound(j))) {
return false;
}
}
return true;
}
// here we use the fact xy = 0 -> x = 0 or y = 0
void basics::basic_lemma_for_mon_zero_model_based(const monomial& rm, const factorization& f) {
TRACE("nla_solver", c().trace_print_monomial_and_factorization(rm, f, tout););
SASSERT(val(rm).is_zero()&& ! c().rm_check(rm));
add_empty_lemma();
int sign = c().get_derived_sign(rm, f);
if (sign == 0) {
if (is_separated_from_zero(f)) {
c().mk_ineq(var(rm), llc::NE);
for (auto j : f) {
c().mk_ineq(var(j), llc::EQ);
@ -496,7 +507,6 @@ void basics::basic_lemma_for_mon_zero_model_based(const monomial& rm, const fact
c().explain_separation_from_zero(var(j));
}
}
explain(rm);
explain(f);
TRACE("nla_solver", c().print_lemma(tout););
}
@ -692,7 +702,7 @@ void basics::basic_lemma_for_mon_neutral_model_based(const monomial& rm, const f
// use the fact
// 1 * 1 ... * 1 * x * 1 ... * 1 = x
bool basics::basic_lemma_for_mon_neutral_from_factors_to_monomial_model_based(const monomial& rm, const factorization& f) {
rational sign = rm.rsign();
rational sign = sign_to_rat(rm.rsign());
TRACE("nla_solver_bl", tout << "f = "; c().print_factorization(f, tout); tout << ", sign = " << sign << '\n'; );
lpvar not_one = -1;
for (auto j : f){

View file

@ -103,5 +103,6 @@ struct basics: common {
// none of the factors is zero and the product is not zero
// -> |fc[factor_index]| <= |rm|
void generate_pl(const monomial& rm, const factorization& fc, int factor_index);
bool is_separated_from_zero(const factorization&) const;
};
}

View file

@ -40,15 +40,14 @@ template <typename T> lpvar common::var(T const& t) const { return c().var(t); }
template lpvar common::var<factor>(factor const& t) const;
template lpvar common::var<monomial>(monomial const& t) const;
void common::add_empty_lemma() { c().add_empty_lemma(); }
template <typename T> rational common::canonize_sign(const T& t) const {
template <typename T> bool common::canonize_sign(const T& t) const {
return c().canonize_sign(t);
}
template rational common::canonize_sign<monomial>(const monomial& t) const;
template rational common::canonize_sign<factor>(const factor& t) const;
rational common::canonize_sign(lpvar j) const {
return c().canonize_sign_of_var(j);
}
template bool common::canonize_sign<monomial>(const monomial&) const;
template bool common::canonize_sign<factor>(const factor&) const;
template bool common::canonize_sign<lpvar>(const lpvar&) const;
void common::mk_ineq(lp::lar_term& t, llc cmp, const rational& rs){
c().mk_ineq(t, cmp, rs);
}
@ -68,6 +67,10 @@ void common::mk_ineq(const rational& a, lpvar j, const rational& b, lpvar k, llc
c().mk_ineq(a, j, b, k, cmp);
}
void common::mk_ineq(bool a, lpvar j, bool b, lpvar k, llc cmp) {
c().mk_ineq(sign_to_rat(a), j, sign_to_rat(b), k, cmp);
}
void common::mk_ineq(const rational& a ,lpvar j, lpvar k, llc cmp, const rational& rs) {
c().mk_ineq(a, j, k, cmp, rs);
}

View file

@ -57,8 +57,7 @@ struct common {
template <typename T> void explain(const T&);
void explain(lpvar);
void add_empty_lemma();
template <typename T> rational canonize_sign(const T&) const;
rational canonize_sign(lpvar) const;
template <typename T> bool canonize_sign(const T&) const;
void mk_ineq(lp::lar_term& t, llc cmp, const rational& rs);
void mk_ineq(const rational& a, lpvar j, const rational& b, lpvar k, llc cmp, const rational& rs);
@ -67,6 +66,7 @@ struct common {
void mk_ineq(lpvar j, const rational& b, lpvar k, llc cmp);
void mk_ineq(const rational& a, lpvar j, const rational& b, lpvar k, llc cmp);
void mk_ineq(bool a, lpvar j, bool b, lpvar k, llc cmp);
void mk_ineq(const rational& a ,lpvar j, lpvar k, llc cmp, const rational& rs);

View file

@ -92,23 +92,23 @@ svector<lpvar> core::sorted_rvars(const factor& f) const {
// the value of the factor is equal to the value of the variable multiplied
// by the canonize_sign
rational core::canonize_sign(const factor& f) const {
return f.rat_sign() * (f.is_var()? canonize_sign_of_var(f.var()) : m_emons[f.var()].rsign());
bool core::canonize_sign(const factor& f) const {
return f.sign() ^ (f.is_var()? canonize_sign(f.var()) : m_emons[f.var()].rsign());
}
rational core::canonize_sign_of_var(lpvar j) const {
return m_evars.find(j).rsign();
bool core::canonize_sign(lpvar j) const {
return m_evars.find(j).sign();
}
bool core::canonize_sign_is_correct(const monomial& m) const {
rational r(1);
bool r = false;
for (lpvar j : m.vars()) {
r *= canonize_sign_of_var(j);
r ^= canonize_sign(j);
}
return r == m.rsign();
}
rational core::canonize_sign(const monomial& m) const {
bool core::canonize_sign(const monomial& m) const {
SASSERT(canonize_sign_is_correct(m));
return m.rsign();
}
@ -811,18 +811,6 @@ void core::explain_separation_from_zero(lpvar j) {
explain_existing_upper_bound(j);
}
int core::get_derived_sign(const monomial& rm, const factorization& f) const {
rational sign = rm.rsign(); // this is the flip sign of the variable var(rm)
SASSERT(!sign.is_zero());
for (const factor& fc: f) {
lpvar j = var(fc);
if (!(var_has_positive_lower_bound(j) || var_has_negative_upper_bound(j))) {
return 0;
}
sign *= m_evars.find(j).rsign();
}
return nla::rat_sign(sign);
}
void core::trace_print_monomial_and_factorization(const monomial& rm, const factorization& f, std::ostream& out) const {
out << "rooted vars: ";
print_product(rm.rvars(), out);
@ -1390,11 +1378,7 @@ std::unordered_set<lpvar> core::collect_vars(const lemma& l) const {
// divides bc by c, so bc = b*c
bool core::divide(const monomial& bc, const factor& c, factor & b) const {
svector<lpvar> c_rvars = sorted_rvars(c);
TRACE("nla_solver",
tout << "c_rvars = ";
print_product(c_rvars, tout);
tout << "\nbc_rvars = ";
print_product(bc.rvars(), tout););
TRACE("nla_solver_div", tout << "c_rvars = "; print_product(c_rvars, tout); tout << "\nbc_rvars = "; print_product(bc.rvars(), tout););
if (!lp::is_proper_factor(c_rvars, bc.rvars()))
return false;
@ -1412,12 +1396,10 @@ bool core::divide(const monomial& bc, const factor& c, factor & b) const {
b = factor(sv->var(), factor_type::MON);
}
SASSERT(!b.sign());
// we should have bc.vars()*canonize_sign(bc) = bc.rvar() = b.rvars()*c.rvars() =
// = canonize_sign(b)*b.vars()* canonize_sign(c)*c.vars().
// so bc.vars()*canonize_sign(bc) = canonize_sign(b)*b.vars()* canonize_sign(c)*c.vars().
// but canonize_sign(b) now is canonize_sign_of_var(b.m_var) or canonize_sign(m_monomials[b.m_var])
// so we are adjusting it
b.sign() = (canonize_sign(b) * canonize_sign(c) * canonize_sign(bc) == rational(1))? false: true;
// We have bc = canonize_sign(bc)*bc.rvars() = canonize_sign(b)*b.rvars()*canonize_sign(c)*c.rvars().
// Dividing by bc.rvars() we get canonize_sign(bc) = canonize_sign(b)*canonize_sign(c)
// Currently, canonize_sign(b) is 1, we might need to adjust it
b.sign() = canonize_sign(b) ^ canonize_sign(c) ^ canonize_sign(bc);
TRACE("nla_solver", tout << "success div:"; print_factor(b, tout););
return true;
}
@ -1438,8 +1420,8 @@ void core::negate_factor_equality(const factor& c,
}
void core::negate_factor_relation(const rational& a_sign, const factor& a, const rational& b_sign, const factor& b) {
rational a_fs = canonize_sign(a);
rational b_fs = canonize_sign(b);
rational a_fs = sign_to_rat(canonize_sign(a));
rational b_fs = sign_to_rat(canonize_sign(b));
llc cmp = a_sign*val(a) < b_sign*val(b)? llc::GE : llc::LE;
mk_ineq(a_fs*a_sign, var(a), - b_fs*b_sign, var(b), cmp);
}

View file

@ -116,13 +116,13 @@ public:
void add_empty_lemma();
// the value of the factor is equal to the value of the variable multiplied
// by the canonize_sign
rational canonize_sign(const factor& f) const;
bool canonize_sign(const factor& f) const;
rational canonize_sign_of_var(lpvar j) const;
bool canonize_sign(lpvar j) const;
// the value of the rooted monomias is equal to the value of the m.var() variable multiplied
// by the canonize_sign
rational canonize_sign(const monomial& m) const;
bool canonize_sign(const monomial& m) const;
void deregister_monomial_from_monomialomials (const monomial & m, unsigned i);
@ -186,6 +186,8 @@ public:
void mk_ineq(lp::lar_term& t, llc cmp, const rational& rs);
void mk_ineq(const rational& a, lpvar j, const rational& b, lpvar k, llc cmp, const rational& rs);
void mk_ineq(bool a, lpvar j, bool b, lpvar k, llc cmp, const rational& rs);
void mk_ineq(bool a, lpvar j, bool b, lpvar k, llc cmp);
void mk_ineq(lpvar j, const rational& b, lpvar k, llc cmp, const rational& rs);
void mk_ineq(lpvar j, const rational& b, lpvar k, llc cmp);
void mk_ineq(const rational& a, lpvar j, const rational& b, lpvar k, llc cmp);
@ -240,20 +242,13 @@ public:
const monomial* find_monomial_of_vars(const svector<lpvar>& vars) const;
int get_derived_sign(const monomial& rm, const factorization& f) const;
bool var_has_positive_lower_bound(lpvar j) const;
bool var_has_negative_upper_bound(lpvar j) const;
bool var_is_separated_from_zero(lpvar j) const;
bool vars_are_equiv(lpvar a, lpvar b) const;
bool vars_are_equiv(lpvar a, lpvar b) const;
void explain_equiv_vars(lpvar a, lpvar b);
void explain(const factorization& f, lp::explanation& exp);
bool explain_upper_bound(const lp::lar_term& t, const rational& rs, lp::explanation& e) const;
@ -353,6 +348,7 @@ struct pp_rmon {
pp_rmon(core const& c, monomial const& m): c(c), m(m) {}
pp_rmon(core const& c, lpvar v): c(c), m(c.m_emons[v]) {}
};
inline rational sign_to_rat(bool s) { return rational(s? -1 : 1); }
inline std::ostream& operator<<(std::ostream& out, pp_mon const& p) { return p.c.print_monomial(p.m, out); }
inline std::ostream& operator<<(std::ostream& out, pp_rmon const& p) { return p.c.print_monomial_with_vars(p.m, out); }

View file

@ -209,12 +209,14 @@ bool order::order_lemma_on_ac_and_bc(const monomial& rm_ac,
order_lemma_on_ac_and_bc_and_factors(rm_ac, ac_f[!k], ac_f[k], rm_bd, b);
}
// TBD: document what lemma is created here.
// Here ab is a binary factorization of m.
// We try to find a monomial n = cd, such that |b| = |d|
// and get a lemma m R n & |b| = |d| => ab/|b| R cd /|d|, where R is a relation
void order::order_lemma_on_factorization(const monomial& m, const factorization& ab) {
rational sign = m.rsign();
bool sign = m.rsign();
for (factor f: ab)
sign *= _().canonize_sign(f);
sign ^= _().canonize_sign(f);
const rational fv = val(ab[0]) * val(ab[1]);
const rational mv = sign * val(m);
TRACE("nla_solver",
@ -225,7 +227,7 @@ void order::order_lemma_on_factorization(const monomial& m, const factorization&
bool gt = mv > fv;
TRACE("nla_solver", tout << "m="; _().print_monomial_with_vars(m, tout); tout << "\nfactorization="; _().print_factorization(ab, tout););
for (unsigned j = 0, k = 1; j < 2; j++, k--) {
order_lemma_on_ab(m, sign, var(ab[k]), var(ab[j]), gt);
order_lemma_on_ab(m, sign_to_rat(sign), var(ab[k]), var(ab[j]), gt);
explain(ab); explain(m);
TRACE("nla_solver", _().print_lemma(tout););
order_lemma_on_ac_explore(m, ab, j == 1);
@ -265,7 +267,7 @@ void order::generate_ol(const monomial& ac,
add_empty_lemma();
rational rc_sign = rational(c_sign);
mk_ineq(rc_sign * canonize_sign(c), var(c), llc::LE);
mk_ineq(canonize_sign(ac), var(ac), -canonize_sign(bc), var(bc), ab_cmp);
mk_ineq(canonize_sign(ac), var(ac), !canonize_sign(bc), var(bc), ab_cmp);
mk_ineq(canonize_sign(a)*rc_sign, var(a), - canonize_sign(b)*rc_sign, var(b), negate(ab_cmp));
explain(ac);
explain(a);