mirror of
https://github.com/Z3Prover/z3
synced 2025-07-17 01:46:39 +00:00
code reviewing order lemmas (#93)
* code reviewing order lemmas Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * code review monotonity Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
1ab3957eea
commit
ed3bfcdea9
7 changed files with 233 additions and 204 deletions
|
@ -184,6 +184,8 @@ namespace nla {
|
||||||
|
|
||||||
monomial const& operator[](lpvar v) const { return var2monomial(v); }
|
monomial const& operator[](lpvar v) const { return var2monomial(v); }
|
||||||
|
|
||||||
|
monomial const& operator[](smon const& m) const { return var2monomial(m.var()); }
|
||||||
|
|
||||||
bool is_monomial_var(lpvar v) const { return m_var2index.get(v, UINT_MAX) != UINT_MAX; }
|
bool is_monomial_var(lpvar v) const { return m_var2index.get(v, UINT_MAX) != UINT_MAX; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,6 +46,9 @@ struct common {
|
||||||
common(core* c): m_core(c) {}
|
common(core* c): m_core(c) {}
|
||||||
core& c() { return *m_core; }
|
core& c() { return *m_core; }
|
||||||
const core& c() const { return *m_core; }
|
const core& c() const { return *m_core; }
|
||||||
|
core& _() { return *m_core; }
|
||||||
|
const core& _() const { return *m_core; }
|
||||||
|
|
||||||
template <typename T> rational vvr(T const& t) const;
|
template <typename T> rational vvr(T const& t) const;
|
||||||
rational vvr(lpvar) const;
|
rational vvr(lpvar) const;
|
||||||
template <typename T> lpvar var(T const& t) const;
|
template <typename T> lpvar var(T const& t) const;
|
||||||
|
|
|
@ -351,5 +351,21 @@ public:
|
||||||
|
|
||||||
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_mon const& p) { return p.c.print_monomial(p.m, out); }
|
||||||
|
|
||||||
|
struct pp_fac {
|
||||||
|
core const& c;
|
||||||
|
factor const& f;
|
||||||
|
pp_fac(core const& c, factor const& f): c(c), f(f) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, pp_fac const& f) { return f.c.print_factor(f.f, out); }
|
||||||
|
|
||||||
|
struct pp_var {
|
||||||
|
core const& c;
|
||||||
|
lpvar v;
|
||||||
|
pp_var(core const& c, lpvar v): c(c), v(v) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, pp_var const& v) { return v.c.print_var(v.v, out); }
|
||||||
|
|
||||||
} // end of namespace nla
|
} // end of namespace nla
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,19 @@
|
||||||
namespace nla {
|
namespace nla {
|
||||||
|
|
||||||
monotone::monotone(core * c) : common(c) {}
|
monotone::monotone(core * c) : common(c) {}
|
||||||
void monotone::print_monotone_array(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted,
|
|
||||||
std::ostream& out) const {
|
|
||||||
|
void monotone::monotonicity_lemma() {
|
||||||
|
unsigned shift = random();
|
||||||
|
unsigned size = c().m_to_refine.size();
|
||||||
|
for(unsigned i = 0; i < size && !done(); i++) {
|
||||||
|
lpvar v = c().m_to_refine[(i + shift) % size];
|
||||||
|
monotonicity_lemma(c().m_emons[v]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void monotone::print_monotone_array(const monotone_array_t& lex_sorted,
|
||||||
|
std::ostream& out) const {
|
||||||
out << "Monotone array :\n";
|
out << "Monotone array :\n";
|
||||||
for (const auto & t : lex_sorted ){
|
for (const auto & t : lex_sorted ){
|
||||||
out << "(";
|
out << "(";
|
||||||
|
@ -33,7 +44,8 @@ void monotone::print_monotone_array(const vector<std::pair<std::vector<rational>
|
||||||
}
|
}
|
||||||
out << "}";
|
out << "}";
|
||||||
}
|
}
|
||||||
bool monotone::monotonicity_lemma_on_lex_sorted_rm_upper(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted, unsigned i, const smon& rm) {
|
|
||||||
|
bool monotone::monotonicity_lemma_on_lex_sorted_rm_upper(const monotone_array_t& lex_sorted, unsigned i, const smon& rm) {
|
||||||
const rational v = abs(vvr(rm));
|
const rational v = abs(vvr(rm));
|
||||||
const auto& key = lex_sorted[i].first;
|
const auto& key = lex_sorted[i].first;
|
||||||
TRACE("nla_solver", tout << "rm = " << rm << "i = " << i << std::endl;);
|
TRACE("nla_solver", tout << "rm = " << rm << "i = " << i << std::endl;);
|
||||||
|
@ -49,11 +61,10 @@ bool monotone::monotonicity_lemma_on_lex_sorted_rm_upper(const vector<std::pair<
|
||||||
if (static_cast<int>(strict) != -1 && !has_zero(key)) {
|
if (static_cast<int>(strict) != -1 && !has_zero(key)) {
|
||||||
generate_monl_strict(rm, rmk, strict);
|
generate_monl_strict(rm, rmk, strict);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
if (vk < v) {
|
else if (vk < v) {
|
||||||
generate_monl(rm, rmk);
|
generate_monl(rm, rmk);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +72,7 @@ bool monotone::monotonicity_lemma_on_lex_sorted_rm_upper(const vector<std::pair<
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool monotone::monotonicity_lemma_on_lex_sorted_rm_lower(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted, unsigned i, const smon& rm) {
|
bool monotone::monotonicity_lemma_on_lex_sorted_rm_lower(const monotone_array_t& lex_sorted, unsigned i, const smon& rm) {
|
||||||
const rational v = abs(vvr(rm));
|
const rational v = abs(vvr(rm));
|
||||||
const auto& key = lex_sorted[i].first;
|
const auto& key = lex_sorted[i].first;
|
||||||
TRACE("nla_solver", tout << "rm = " << rm << "i = " << i << std::endl;);
|
TRACE("nla_solver", tout << "rm = " << rm << "i = " << i << std::endl;);
|
||||||
|
@ -92,11 +103,11 @@ bool monotone::monotonicity_lemma_on_lex_sorted_rm_lower(const vector<std::pair<
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool monotone::monotonicity_lemma_on_lex_sorted_rm(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted, unsigned i, const smon& rm) {
|
bool monotone::monotonicity_lemma_on_lex_sorted_rm(const monotone_array_t& lex_sorted, unsigned i, const smon& rm) {
|
||||||
return monotonicity_lemma_on_lex_sorted_rm_upper(lex_sorted, i, rm)
|
return monotonicity_lemma_on_lex_sorted_rm_upper(lex_sorted, i, rm)
|
||||||
|| monotonicity_lemma_on_lex_sorted_rm_lower(lex_sorted, i, rm);
|
|| monotonicity_lemma_on_lex_sorted_rm_lower(lex_sorted, i, rm);
|
||||||
}
|
}
|
||||||
bool monotone::monotonicity_lemma_on_lex_sorted(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted) {
|
bool monotone::monotonicity_lemma_on_lex_sorted(const monotone_array_t& lex_sorted) {
|
||||||
for (unsigned i = 0; i < lex_sorted.size(); i++) {
|
for (unsigned i = 0; i < lex_sorted.size(); i++) {
|
||||||
unsigned rmi = lex_sorted[i].second;
|
unsigned rmi = lex_sorted[i].second;
|
||||||
const smon& rm = c().m_emons.canonical[rmi];
|
const smon& rm = c().m_emons.canonical[rmi];
|
||||||
|
@ -121,6 +132,7 @@ vector<std::pair<rational, lpvar>> monotone::get_sorted_key_with_vars(const smon
|
||||||
});
|
});
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void monotone::negate_abs_a_le_abs_b(lpvar a, lpvar b, bool strict) {
|
void monotone::negate_abs_a_le_abs_b(lpvar a, lpvar b, bool strict) {
|
||||||
rational av = vvr(a);
|
rational av = vvr(a);
|
||||||
rational as = rational(nla::rat_sign(av));
|
rational as = rational(nla::rat_sign(av));
|
||||||
|
@ -138,8 +150,8 @@ void monotone::negate_abs_a_le_abs_b(lpvar a, lpvar b, bool strict) {
|
||||||
|
|
||||||
// strict version
|
// strict version
|
||||||
void monotone::generate_monl_strict(const smon& a,
|
void monotone::generate_monl_strict(const smon& a,
|
||||||
const smon& b,
|
const smon& b,
|
||||||
unsigned strict) {
|
unsigned strict) {
|
||||||
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);
|
||||||
|
@ -189,7 +201,7 @@ void monotone::negate_abs_a_lt_abs_b(lpvar a, lpvar b) {
|
||||||
|
|
||||||
// not a strict version
|
// not a strict version
|
||||||
void monotone::generate_monl(const smon& a,
|
void monotone::generate_monl(const smon& a,
|
||||||
const smon& b) {
|
const smon& b) {
|
||||||
TRACE("nla_solver",
|
TRACE("nla_solver",
|
||||||
tout << "a = " << a << "\n:";
|
tout << "a = " << a << "\n:";
|
||||||
tout << "b = " << b << "\n:";);
|
tout << "b = " << b << "\n:";);
|
||||||
|
@ -216,7 +228,7 @@ std::vector<rational> monotone::get_sorted_key(const smon& rm) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool monotone::monotonicity_lemma_on_rms_of_same_arity(const unsigned_vector& rms) {
|
bool monotone::monotonicity_lemma_on_rms_of_same_arity(const unsigned_vector& rms) {
|
||||||
vector<std::pair<std::vector<rational>, unsigned>> lex_sorted;
|
monotone_array_t lex_sorted;
|
||||||
for (unsigned i : rms) {
|
for (unsigned i : rms) {
|
||||||
lex_sorted.push_back(std::make_pair(get_sorted_key(c().m_emons.canonical[i]), i));
|
lex_sorted.push_back(std::make_pair(get_sorted_key(c().m_emons.canonical[i]), i));
|
||||||
}
|
}
|
||||||
|
@ -228,28 +240,6 @@ bool monotone::monotonicity_lemma_on_rms_of_same_arity(const unsigned_vector& rm
|
||||||
TRACE("nla_solver", print_monotone_array(lex_sorted, tout););
|
TRACE("nla_solver", print_monotone_array(lex_sorted, tout););
|
||||||
return monotonicity_lemma_on_lex_sorted(lex_sorted);
|
return monotonicity_lemma_on_lex_sorted(lex_sorted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void monotone::monotonicity_lemma() {
|
|
||||||
unsigned shift = random();
|
|
||||||
unsigned size = c().m_to_refine.size();
|
|
||||||
for(unsigned i = 0; i < size && !done(); i++) {
|
|
||||||
lpvar v = c().m_to_refine[(i + shift) % size];
|
|
||||||
monotonicity_lemma(c().m_emons[v]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void monotone::monotonicity_lemma() {
|
|
||||||
auto const& vars = m_rm_table.m_to_refine
|
|
||||||
unsigned sz = vars.size();
|
|
||||||
unsigned start = random();
|
|
||||||
for (unsigned j = 0; !done() && j < sz; ++j) {
|
|
||||||
unsigned i = (start + j) % sz;
|
|
||||||
monotonicity_lemma(*m_emons.var2monomial(vars[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void monotone::monotonicity_lemma(monomial const& m) {
|
void monotone::monotonicity_lemma(monomial const& m) {
|
||||||
SASSERT(!check_monomial(m));
|
SASSERT(!check_monomial(m));
|
||||||
|
@ -262,6 +252,7 @@ void monotone::monotonicity_lemma(monomial const& m) {
|
||||||
else if (m_val > prod_val)
|
else if (m_val > prod_val)
|
||||||
monotonicity_lemma_gt(m, prod_val);
|
monotonicity_lemma_gt(m, prod_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void monotone::monotonicity_lemma_gt(const monomial& m, const rational& prod_val) {
|
void monotone::monotonicity_lemma_gt(const monomial& m, const rational& prod_val) {
|
||||||
add_empty_lemma();
|
add_empty_lemma();
|
||||||
for (lpvar j : m) {
|
for (lpvar j : m) {
|
||||||
|
|
|
@ -20,16 +20,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
namespace nla {
|
namespace nla {
|
||||||
class core;
|
class core;
|
||||||
struct monotone: common {
|
class monotone : common {
|
||||||
|
public:
|
||||||
monotone(core *core);
|
monotone(core *core);
|
||||||
void print_monotone_array(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted,
|
|
||||||
std::ostream& out) const;
|
|
||||||
bool monotonicity_lemma_on_lex_sorted_rm_upper(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted, unsigned i, const smon& rm);
|
|
||||||
bool monotonicity_lemma_on_lex_sorted_rm_lower(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted, unsigned i, const smon& rm);
|
|
||||||
bool monotonicity_lemma_on_lex_sorted_rm(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted, unsigned i, const smon& rm);
|
|
||||||
bool monotonicity_lemma_on_lex_sorted(const vector<std::pair<std::vector<rational>, unsigned>>& lex_sorted);
|
|
||||||
bool monotonicity_lemma_on_rms_of_same_arity(const unsigned_vector& rms);
|
|
||||||
void monotonicity_lemma();
|
void monotonicity_lemma();
|
||||||
|
private:
|
||||||
|
typedef vector<std::pair<std::vector<rational>, unsigned>> monotone_array_t;
|
||||||
|
void print_monotone_array(const monotone_array_t& lex_sorted, std::ostream& out) const;
|
||||||
|
bool monotonicity_lemma_on_lex_sorted_rm_upper(const monotone_array_t& lex_sorted, unsigned i, const smon& rm);
|
||||||
|
bool monotonicity_lemma_on_lex_sorted_rm_lower(const monotone_array_t& lex_sorted, unsigned i, const smon& rm);
|
||||||
|
bool monotonicity_lemma_on_lex_sorted_rm(const monotone_array_t& lex_sorted, unsigned i, const smon& rm);
|
||||||
|
bool monotonicity_lemma_on_lex_sorted(const monotone_array_t& lex_sorted);
|
||||||
|
bool monotonicity_lemma_on_rms_of_same_arity(const unsigned_vector& rms);
|
||||||
void monotonicity_lemma(monomial const& m);
|
void monotonicity_lemma(monomial const& m);
|
||||||
void monotonicity_lemma_gt(const monomial& m, const rational& prod_val);
|
void monotonicity_lemma_gt(const monomial& m, const rational& prod_val);
|
||||||
void monotonicity_lemma_lt(const monomial& m, const rational& prod_val);
|
void monotonicity_lemma_lt(const monomial& m, const rational& prod_val);
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#include "util/lp/nla_order_lemmas.h"
|
#include "util/lp/nla_order_lemmas.h"
|
||||||
|
@ -25,13 +24,144 @@
|
||||||
|
|
||||||
namespace nla {
|
namespace nla {
|
||||||
|
|
||||||
// a >< b && c > 0 => ac >< bc
|
void order::order_lemma() {
|
||||||
// a >< b && c < 0 => ac <> bc
|
TRACE("nla_solver", );
|
||||||
|
const auto& rm_ref = c().m_to_refine;
|
||||||
|
unsigned start = random();
|
||||||
|
unsigned sz = rm_ref.size();
|
||||||
|
for (unsigned i = 0; i < sz && !done(); ++i) {
|
||||||
|
const smon& rm = c().m_emons.canonical[rm_ref[(i + start) % sz]];
|
||||||
|
order_lemma_on_rmonomial(rm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void order::order_lemma_on_rmonomial(const smon& rm) {
|
||||||
|
TRACE("nla_solver_details",
|
||||||
|
tout << "rm = " << rm << ", orig = " << c().m_emons[rm];);
|
||||||
|
|
||||||
|
for (auto ac : factorization_factory_imp(rm, c())) {
|
||||||
|
if (ac.size() != 2)
|
||||||
|
continue;
|
||||||
|
if (ac.is_mon())
|
||||||
|
order_lemma_on_binomial(*ac.mon());
|
||||||
|
else
|
||||||
|
order_lemma_on_factorization(rm, ac);
|
||||||
|
if (done())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void order::order_lemma_on_binomial(const monomial& ac) {
|
||||||
|
TRACE("nla_solver", tout << pp_mon(c(), ac););
|
||||||
|
SASSERT(!check_monomial(ac) && ac.size() == 2);
|
||||||
|
const rational & mult_val = vvr(ac[0]) * vvr(ac[1]);
|
||||||
|
const rational acv = vvr(ac);
|
||||||
|
bool gt = acv > mult_val;
|
||||||
|
for (unsigned k = 0; k < 2; k++) {
|
||||||
|
order_lemma_on_binomial_k(ac, k == 1, gt);
|
||||||
|
order_lemma_on_factor_binomial_explore(ac, k == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void order::order_lemma_on_binomial_k(const monomial& m, bool k, bool gt) {
|
||||||
|
SASSERT(gt == (vvr(m) > vvr(m[0]) * vvr(m[1])));
|
||||||
|
order_lemma_on_binomial_sign(m, m[k], m[!k], gt ? 1: -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief
|
||||||
|
sign = the sign of vvr(xy) - vvr(x) * vvr(y) != 0
|
||||||
|
y <= 0 or x < a or xy >= ay
|
||||||
|
y <= 0 or x > a or xy <= ay
|
||||||
|
y >= 0 or x < a or xy <= ay
|
||||||
|
y >= 0 or x > a or xy >= ay
|
||||||
|
|
||||||
|
*/
|
||||||
|
void order::order_lemma_on_binomial_sign(const monomial& xy, lpvar x, lpvar y, int sign) {
|
||||||
|
SASSERT(!_().mon_has_zero(xy));
|
||||||
|
int sy = rat_sign(vvr(y));
|
||||||
|
add_empty_lemma();
|
||||||
|
mk_ineq(y, sy == 1 ? llc::LE : llc::GE); // negate sy
|
||||||
|
mk_ineq(x, sy*sign == 1 ? llc::GT : llc::LT , vvr(x));
|
||||||
|
mk_ineq(xy.var(), - vvr(x), y, sign == 1 ? llc::LE : llc::GE);
|
||||||
|
TRACE("nla_solver", print_lemma(tout););
|
||||||
|
}
|
||||||
|
|
||||||
|
void order::order_lemma_on_factor_binomial_explore(const monomial& m1, bool k) {
|
||||||
|
SASSERT(m1.size() == 2);
|
||||||
|
lpvar c = m1[k];
|
||||||
|
for (monomial const& m2 : _().m_emons.get_factors_of(c)) {
|
||||||
|
order_lemma_on_factor_binomial_rm(m1, k, m2);
|
||||||
|
if (done()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void order::order_lemma_on_factor_binomial_rm(const monomial& ac, bool k, const monomial& bd) {
|
||||||
|
smon const& rm_bd = _().m_emons.canonical[bd];
|
||||||
|
factor d(_().m_evars.find(ac[k]).var(), factor_type::VAR);
|
||||||
|
factor b;
|
||||||
|
if (c().divide(rm_bd, d, b)) {
|
||||||
|
order_lemma_on_binomial_ac_bd(ac, k, rm_bd, b, d.var());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void order::order_lemma_on_binomial_ac_bd(const monomial& ac, bool k, const smon& bd, const factor& b, lpvar d) {
|
||||||
|
TRACE("nla_solver",
|
||||||
|
tout << "ac=" << pp_mon(c(), ac) << "\nrm= " << bd << ", b= " << pp_fac(c(), b) << ", d= " << pp_var(c(), d) << "\n";);
|
||||||
|
bool p = !k;
|
||||||
|
lpvar a = ac[p];
|
||||||
|
lpvar c = ac[k];
|
||||||
|
SASSERT(_().m_evars.find(c).var() == d);
|
||||||
|
rational acv = vvr(ac);
|
||||||
|
rational av = vvr(a);
|
||||||
|
rational c_sign = rrat_sign(vvr(c));
|
||||||
|
rational d_sign = rrat_sign(vvr(d));
|
||||||
|
rational bdv = vvr(bd);
|
||||||
|
rational bv = vvr(b);
|
||||||
|
auto av_c_s = av*c_sign; auto bv_d_s = bv*d_sign;
|
||||||
|
|
||||||
|
// suppose ac >= bd, then ac/|c| >= bd/|d|.
|
||||||
|
// Notice that ac/|c| = a*c_sign , and bd/|d| = b*d_sign
|
||||||
|
if (acv >= bdv && av_c_s < bv_d_s)
|
||||||
|
generate_mon_ol(ac, a, c_sign, c, bd, b, d_sign, d, llc::LT);
|
||||||
|
else if (acv <= bdv && av_c_s > bv_d_s)
|
||||||
|
generate_mon_ol(ac, a, c_sign, c, bd, b, d_sign, d, llc::GT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TBD: document what lemma is created here.
|
||||||
|
|
||||||
|
void order::generate_mon_ol(const monomial& ac,
|
||||||
|
lpvar a,
|
||||||
|
const rational& c_sign,
|
||||||
|
lpvar c,
|
||||||
|
const smon& bd,
|
||||||
|
const factor& b,
|
||||||
|
const rational& d_sign,
|
||||||
|
lpvar d,
|
||||||
|
llc ab_cmp) {
|
||||||
|
add_empty_lemma();
|
||||||
|
mk_ineq(c_sign, c, llc::LE);
|
||||||
|
explain(c); // this explains c == +- d
|
||||||
|
negate_var_factor_relation(c_sign, a, d_sign, b);
|
||||||
|
mk_ineq(ac.var(), -canonize_sign(bd), var(bd), ab_cmp);
|
||||||
|
explain(bd);
|
||||||
|
explain(b);
|
||||||
|
explain(d);
|
||||||
|
TRACE("nla_solver", print_lemma(tout););
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// a > b && c > 0 => ac > bc
|
||||||
|
// a >< b && c > 0 => ac >< bc
|
||||||
|
// a >< b && c < 0 => ac <> bc
|
||||||
// ac[k] plays the role of c
|
// ac[k] plays the role of c
|
||||||
|
|
||||||
bool order::order_lemma_on_ac_and_bc(const smon& rm_ac,
|
bool order::order_lemma_on_ac_and_bc(const smon& rm_ac,
|
||||||
const factorization& ac_f,
|
const factorization& ac_f,
|
||||||
unsigned k,
|
bool k,
|
||||||
const smon& rm_bd) {
|
const smon& rm_bd) {
|
||||||
TRACE("nla_solver",
|
TRACE("nla_solver",
|
||||||
tout << "rm_ac = " << rm_ac << "\n";
|
tout << "rm_ac = " << rm_ac << "\n";
|
||||||
|
@ -41,10 +171,36 @@ bool order::order_lemma_on_ac_and_bc(const smon& rm_ac,
|
||||||
factor b;
|
factor b;
|
||||||
return
|
return
|
||||||
c().divide(rm_bd, ac_f[k], b) &&
|
c().divide(rm_bd, ac_f[k], b) &&
|
||||||
order_lemma_on_ac_and_bc_and_factors(rm_ac, ac_f[(k + 1) % 2], ac_f[k], rm_bd, b);
|
order_lemma_on_ac_and_bc_and_factors(rm_ac, ac_f[!k], ac_f[k], rm_bd, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool order::order_lemma_on_ac_explore(const smon& rm, const factorization& ac, unsigned k) {
|
// TBD: document what lemma is created here.
|
||||||
|
|
||||||
|
void order::order_lemma_on_factorization(const smon& rm, const factorization& ab) {
|
||||||
|
const monomial& m = _().m_emons[rm];
|
||||||
|
TRACE("nla_solver", tout << "orig_sign = " << _().m_emons.orig_sign(rm) << "\n";);
|
||||||
|
rational sign = _().m_emons.orig_sign(rm);
|
||||||
|
for (factor f: ab)
|
||||||
|
sign *= _().canonize_sign(f);
|
||||||
|
const rational & fv = vvr(ab[0]) * vvr(ab[1]);
|
||||||
|
const rational mv = sign * vvr(m);
|
||||||
|
TRACE("nla_solver",
|
||||||
|
tout << "ab.size()=" << ab.size() << "\n";
|
||||||
|
tout << "we should have sign*vvr(m):" << mv << "=(" << sign << ")*(" << vvr(m) <<") to be equal to " << " vvr(ab[0])*vvr(ab[1]):" << fv << "\n";);
|
||||||
|
if (mv == fv)
|
||||||
|
return;
|
||||||
|
bool gt = mv > fv;
|
||||||
|
TRACE("nla_solver_f", 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);
|
||||||
|
explain(ab); explain(m);
|
||||||
|
explain(rm);
|
||||||
|
TRACE("nla_solver", _().print_lemma(tout););
|
||||||
|
order_lemma_on_ac_explore(rm, ab, j == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool order::order_lemma_on_ac_explore(const smon& rm, const factorization& ac, bool k) {
|
||||||
const factor c = ac[k];
|
const factor c = ac[k];
|
||||||
TRACE("nla_solver", tout << "c = "; _().print_factor_with_vars(c, tout); );
|
TRACE("nla_solver", tout << "c = "; _().print_factor_with_vars(c, tout); );
|
||||||
if (c.is_var()) {
|
if (c.is_var()) {
|
||||||
|
@ -65,29 +221,6 @@ bool order::order_lemma_on_ac_explore(const smon& rm, const factorization& ac, u
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void order::order_lemma_on_factorization(const smon& rm, const factorization& ab) {
|
|
||||||
const monomial& m = _().m_emons[rm.var()];
|
|
||||||
TRACE("nla_solver", tout << "orig_sign = " << _().m_emons.orig_sign(rm) << "\n";);
|
|
||||||
rational sign = _().m_emons.orig_sign(rm);
|
|
||||||
for (factor f: ab)
|
|
||||||
sign *= _().canonize_sign(f);
|
|
||||||
const rational & fv = vvr(ab[0]) * vvr(ab[1]);
|
|
||||||
const rational mv = sign * vvr(m);
|
|
||||||
TRACE("nla_solver",
|
|
||||||
tout << "ab.size()=" << ab.size() << "\n";
|
|
||||||
tout << "we should have sign*vvr(m):" << mv << "=(" << sign << ")*(" << vvr(m) <<") to be equal to " << " vvr(ab[0])*vvr(ab[1]):" << fv << "\n";);
|
|
||||||
if (mv == fv)
|
|
||||||
return;
|
|
||||||
bool gt = mv > fv;
|
|
||||||
TRACE("nla_solver_f", 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);
|
|
||||||
explain(ab); explain(m);
|
|
||||||
explain(rm);
|
|
||||||
TRACE("nla_solver", _().print_lemma(tout););
|
|
||||||
order_lemma_on_ac_explore(rm, ab, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// |c_sign| = 1, and c*c_sign > 0
|
// |c_sign| = 1, and c*c_sign > 0
|
||||||
// ac > bc => ac/|c| > bc/|c| => a*c_sign > b*c_sign
|
// ac > bc => ac/|c| > bc/|c| => a*c_sign > b*c_sign
|
||||||
void order::generate_ol(const smon& ac,
|
void order::generate_ol(const smon& ac,
|
||||||
|
@ -110,25 +243,6 @@ void order::generate_ol(const smon& ac,
|
||||||
TRACE("nla_solver", _().print_lemma(tout););
|
TRACE("nla_solver", _().print_lemma(tout););
|
||||||
}
|
}
|
||||||
|
|
||||||
void order::generate_mon_ol(const monomial& ac,
|
|
||||||
lpvar a,
|
|
||||||
const rational& c_sign,
|
|
||||||
lpvar c,
|
|
||||||
const smon& bd,
|
|
||||||
const factor& b,
|
|
||||||
const rational& d_sign,
|
|
||||||
lpvar d,
|
|
||||||
llc ab_cmp) {
|
|
||||||
add_empty_lemma();
|
|
||||||
mk_ineq(c_sign, c, llc::LE);
|
|
||||||
explain(c); // this explains c == +- d
|
|
||||||
negate_var_factor_relation(c_sign, a, d_sign, b);
|
|
||||||
mk_ineq(ac.var(), -canonize_sign(bd), var(bd), ab_cmp);
|
|
||||||
explain(bd);
|
|
||||||
explain(b);
|
|
||||||
explain(d);
|
|
||||||
TRACE("nla_solver", print_lemma(tout););
|
|
||||||
}
|
|
||||||
|
|
||||||
void order::negate_var_factor_relation(const rational& a_sign, lpvar a, const rational& b_sign, const factor& b) {
|
void order::negate_var_factor_relation(const rational& a_sign, lpvar a, const rational& b_sign, const factor& b) {
|
||||||
rational b_fs = canonize_sign(b);
|
rational b_fs = canonize_sign(b);
|
||||||
|
@ -136,16 +250,6 @@ void order::negate_var_factor_relation(const rational& a_sign, lpvar a, const ra
|
||||||
mk_ineq(a_sign, a, - b_fs*b_sign, var(b), cmp);
|
mk_ineq(a_sign, a, - b_fs*b_sign, var(b), cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void order::order_lemma() {
|
|
||||||
TRACE("nla_solver", );
|
|
||||||
const auto& rm_ref = c().m_to_refine;
|
|
||||||
unsigned start = random();
|
|
||||||
unsigned sz = rm_ref.size();
|
|
||||||
for (unsigned i = sz; i-- > 0 && !done(); ) {
|
|
||||||
const smon& rm = c().m_emons.canonical[rm_ref[(i + start) % sz]];
|
|
||||||
order_lemma_on_rmonomial(rm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool order::order_lemma_on_ac_and_bc_and_factors(const smon& ac,
|
bool order::order_lemma_on_ac_and_bc_and_factors(const smon& ac,
|
||||||
const factor& a,
|
const factor& a,
|
||||||
|
@ -231,95 +335,5 @@ void order::order_lemma_on_ab(const monomial& m, const rational& sign, lpvar a,
|
||||||
else
|
else
|
||||||
order_lemma_on_ab_lt(m, sign, a, b);
|
order_lemma_on_ab_lt(m, sign, a, b);
|
||||||
}
|
}
|
||||||
// a > b && c > 0 => ac > bc
|
|
||||||
void order::order_lemma_on_rmonomial(const smon& rm) {
|
|
||||||
TRACE("nla_solver_details",
|
|
||||||
tout << "rm = "; print_product(rm, tout);
|
|
||||||
tout << ", orig = " << pp_mon(c(), c().m_emons[rm.var()]);
|
|
||||||
);
|
|
||||||
for (auto ac : factorization_factory_imp(rm, c())) {
|
|
||||||
if (ac.size() != 2)
|
|
||||||
continue;
|
|
||||||
if (ac.is_mon())
|
|
||||||
order_lemma_on_binomial(*ac.mon());
|
|
||||||
else
|
|
||||||
order_lemma_on_factorization(rm, ac);
|
|
||||||
if (done())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void order::order_lemma_on_binomial_k(const monomial& m, lpvar k, bool gt) {
|
|
||||||
SASSERT(gt == (vvr(m) > vvr(m[0]) * vvr(m[1])));
|
|
||||||
unsigned p = (k + 1) % 2;
|
|
||||||
order_lemma_on_binomial_sign(m, m[k], m[p], gt? 1: -1);
|
|
||||||
}
|
|
||||||
// sign it the sign of vvr(m) - vvr(m[0]) * vvr(m[1])
|
|
||||||
// m = xy
|
|
||||||
// and val(m) != val(x)*val(y)
|
|
||||||
// y > 0 and x = a, then xy >= ay
|
|
||||||
void order::order_lemma_on_binomial_sign(const monomial& ac, lpvar x, lpvar y, int sign) {
|
|
||||||
SASSERT(!_().mon_has_zero(ac));
|
|
||||||
int sy = rat_sign(vvr(y));
|
|
||||||
add_empty_lemma();
|
|
||||||
mk_ineq(y, sy == 1? llc::LE : llc::GE); // negate sy
|
|
||||||
mk_ineq(x, sy*sign == 1? llc::GT:llc::LT , vvr(x)); // assert x <= vvr(x) if x > 0
|
|
||||||
mk_ineq(ac.var(), - vvr(x), y, sign == 1?llc::LE:llc::GE);
|
|
||||||
TRACE("nla_solver", print_lemma(tout););
|
|
||||||
}
|
|
||||||
void order::order_lemma_on_factor_binomial_rm(const monomial& ac, unsigned k, const monomial& bd) {
|
|
||||||
smon const& rm_bd = _().m_emons.canonical[bd];
|
|
||||||
factor d(_().m_evars.find(ac[k]).var(), factor_type::VAR);
|
|
||||||
factor b;
|
|
||||||
if (_().divide(rm_bd, d, b)) {
|
|
||||||
order_lemma_on_binomial_ac_bd(ac, k, rm_bd, b, d.var());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void order::order_lemma_on_binomial_ac_bd(const monomial& ac, unsigned k, const smon& bd, const factor& b, lpvar d) {
|
|
||||||
TRACE("nla_solver", tout << "ac=" << pp_mon(c(), ac);
|
|
||||||
tout << "\nrm=" << bd;
|
|
||||||
print_factor(b, tout << ", b="); print_var(d, tout << ", d=") << "\n";);
|
|
||||||
int p = (k + 1) % 2;
|
|
||||||
lpvar a = ac[p];
|
|
||||||
lpvar c = ac[k];
|
|
||||||
SASSERT(_().m_evars.find(c).var() == d);
|
|
||||||
rational acv = vvr(ac);
|
|
||||||
rational av = vvr(a);
|
|
||||||
rational c_sign = rrat_sign(vvr(c));
|
|
||||||
rational d_sign = rrat_sign(vvr(d));
|
|
||||||
rational bdv = vvr(bd);
|
|
||||||
rational bv = vvr(b);
|
|
||||||
auto av_c_s = av*c_sign; auto bv_d_s = bv*d_sign;
|
|
||||||
|
|
||||||
// suppose ac >= bd, then ac/|c| >= bd/|d|.
|
|
||||||
// Notice that ac/|c| = a*c_sign , and bd/|d| = b*d_sign
|
|
||||||
if (acv >= bdv && av_c_s < bv_d_s)
|
|
||||||
generate_mon_ol(ac, a, c_sign, c, bd, b, d_sign, d, llc::LT);
|
|
||||||
else if (acv <= bdv && av_c_s > bv_d_s)
|
|
||||||
generate_mon_ol(ac, a, c_sign, c, bd, b, d_sign, d, llc::GT);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void order::order_lemma_on_factor_binomial_explore(const monomial& m, unsigned k) {
|
|
||||||
SASSERT(m.size() == 2);
|
|
||||||
lpvar c = m[k];
|
|
||||||
for (monomial const& m2 : _().m_emons.get_factors_of(c)) {
|
|
||||||
order_lemma_on_factor_binomial_rm(m, k, m2);
|
|
||||||
if (done()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void order::order_lemma_on_binomial(const monomial& ac) {
|
|
||||||
TRACE("nla_solver", tout << pp_mon(c(), ac););
|
|
||||||
SASSERT(!check_monomial(ac) && ac.size() == 2);
|
|
||||||
const rational & mult_val = vvr(ac[0]) * vvr(ac[1]);
|
|
||||||
const rational acv = vvr(ac);
|
|
||||||
bool gt = acv > mult_val;
|
|
||||||
for (unsigned k = 0; k < 2; k++) {
|
|
||||||
order_lemma_on_binomial_k(ac, k, gt);
|
|
||||||
order_lemma_on_factor_binomial_explore(ac, k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // end of namespace nla
|
|
||||||
|
|
|
@ -24,11 +24,13 @@
|
||||||
|
|
||||||
namespace nla {
|
namespace nla {
|
||||||
class core;
|
class core;
|
||||||
struct order: common {
|
class order: common {
|
||||||
core& _() { return *m_core; }
|
public:
|
||||||
const core& _() const { return *m_core; }
|
|
||||||
//constructor
|
|
||||||
order(core *c) : common(c) {}
|
order(core *c) : common(c) {}
|
||||||
|
void order_lemma();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
bool order_lemma_on_ac_and_bc_and_factors(const smon& ac,
|
bool order_lemma_on_ac_and_bc_and_factors(const smon& ac,
|
||||||
const factor& a,
|
const factor& a,
|
||||||
const factor& c,
|
const factor& c,
|
||||||
|
@ -40,10 +42,10 @@ struct order: common {
|
||||||
// ac[k] plays the role of c
|
// ac[k] plays the role of c
|
||||||
bool order_lemma_on_ac_and_bc(const smon& rm_ac,
|
bool order_lemma_on_ac_and_bc(const smon& rm_ac,
|
||||||
const factorization& ac_f,
|
const factorization& ac_f,
|
||||||
unsigned k,
|
bool k,
|
||||||
const smon& rm_bd);
|
const smon& rm_bd);
|
||||||
|
|
||||||
bool order_lemma_on_ac_explore(const smon& rm, const factorization& ac, unsigned k);
|
bool order_lemma_on_ac_explore(const smon& rm, const factorization& ac, bool k);
|
||||||
|
|
||||||
void order_lemma_on_factorization(const smon& rm, const factorization& ab);
|
void order_lemma_on_factorization(const smon& rm, const factorization& ab);
|
||||||
|
|
||||||
|
@ -61,14 +63,13 @@ struct order: common {
|
||||||
*/
|
*/
|
||||||
void order_lemma_on_ab_lt(const monomial& m, const rational& sign, lpvar a, lpvar b);
|
void order_lemma_on_ab_lt(const monomial& m, const rational& sign, lpvar a, lpvar b);
|
||||||
void order_lemma_on_ab(const monomial& m, const rational& sign, lpvar a, lpvar b, bool gt);
|
void order_lemma_on_ab(const monomial& m, const rational& sign, lpvar a, lpvar b, bool gt);
|
||||||
void order_lemma_on_factor_binomial_explore(const monomial& m, unsigned k);
|
void order_lemma_on_factor_binomial_explore(const monomial& m, bool k);
|
||||||
void order_lemma_on_factor_binomial_rm(const monomial& ac, unsigned k, const monomial& bd);
|
void order_lemma_on_factor_binomial_rm(const monomial& ac, bool k, const monomial& bd);
|
||||||
void order_lemma_on_binomial_ac_bd(const monomial& ac, unsigned k, const smon& bd, const factor& b, lpvar d);
|
void order_lemma_on_binomial_ac_bd(const monomial& ac, bool k, const smon& bd, const factor& b, lpvar d);
|
||||||
void order_lemma_on_binomial_k(const monomial& m, lpvar k, bool gt);
|
void order_lemma_on_binomial_k(const monomial& m, bool k, bool gt);
|
||||||
void order_lemma_on_binomial_sign(const monomial& ac, lpvar x, lpvar y, int sign);
|
void order_lemma_on_binomial_sign(const monomial& ac, lpvar x, lpvar y, int sign);
|
||||||
void order_lemma_on_binomial(const monomial& ac);
|
void order_lemma_on_binomial(const monomial& ac);
|
||||||
void order_lemma_on_rmonomial(const smon& rm);
|
void order_lemma_on_rmonomial(const smon& rm);
|
||||||
void order_lemma();
|
|
||||||
// |c_sign| = 1, and c*c_sign > 0
|
// |c_sign| = 1, and c*c_sign > 0
|
||||||
// ac > bc => ac/|c| > bc/|c| => a*c_sign > b*c_sign
|
// ac > bc => ac/|c| > bc/|c| => a*c_sign > b*c_sign
|
||||||
void generate_ol(const smon& ac,
|
void generate_ol(const smon& ac,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue