mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
avoid patching vars in powers
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
commit
ec1f449d34
15 changed files with 160 additions and 96 deletions
|
@ -2395,9 +2395,7 @@ bool lar_solver::inside_bounds(lpvar j, const impq& val) const {
|
|||
|
||||
bool lar_solver::try_to_patch(lpvar j, const mpq& val, const std::function<bool (lpvar)>& blocker, const std::function<void (lpvar)>& report_change) {
|
||||
if (is_base(j)) {
|
||||
bool r = remove_from_basis(j);
|
||||
SASSERT(r);
|
||||
(void)r;
|
||||
VERIFY(remove_from_basis(j));
|
||||
}
|
||||
impq ival(val);
|
||||
if (!inside_bounds(j, ival))
|
||||
|
@ -2409,10 +2407,10 @@ bool lar_solver::try_to_patch(lpvar j, const mpq& val, const std::function<bool
|
|||
const mpq & a = c.coeff();
|
||||
unsigned rj = m_mpq_lar_core_solver.m_r_basis[row_index];
|
||||
impq rj_new_val = a * delta + get_column_value(rj);
|
||||
if (column_is_int(rj) && ! rj_new_val.is_int())
|
||||
return false;
|
||||
if (column_is_int(rj) && !rj_new_val.is_int())
|
||||
return false;
|
||||
if (!inside_bounds(rj, rj_new_val) || blocker(rj))
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
set_column_value(j, ival);
|
||||
|
@ -2423,6 +2421,7 @@ bool lar_solver::try_to_patch(lpvar j, const mpq& val, const std::function<bool
|
|||
m_mpq_lar_core_solver.m_r_solver.add_delta_to_x(rj, a * delta);
|
||||
report_change(rj);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "util/vector.h"
|
||||
#include "math/lp/lar_solver.h"
|
||||
#include "math/lp/nla_defs.h"
|
||||
#include <algorithm>
|
||||
namespace nla {
|
||||
|
||||
class mon_eq {
|
||||
|
@ -38,7 +39,15 @@ public:
|
|||
unsigned size() const { return m_vs.size(); }
|
||||
const svector<lp::var_index>& vars() const { return m_vs; }
|
||||
bool empty() const { return m_vs.empty(); }
|
||||
|
||||
bool is_sorted() const {
|
||||
for (unsigned i = 0; i + 1 < size(); i++)
|
||||
if (m_vs[i] > m_vs[i + 1])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool contains_var(lpvar j) const {
|
||||
return std::binary_search(m_vs.begin(), m_vs.end(), j);
|
||||
}
|
||||
protected:
|
||||
svector<lp::var_index>& vars1() { return m_vs; }
|
||||
};
|
||||
|
|
|
@ -1331,72 +1331,94 @@ bool core::elists_are_consistent(bool check_in_model) const {
|
|||
}
|
||||
|
||||
bool core::var_is_used_in_a_correct_monic(lpvar j) const {
|
||||
if (emons().is_monic_var(j)) {
|
||||
if (!m_to_refine.contains(j))
|
||||
return true;
|
||||
}
|
||||
for (const monic & m : emons().get_use_list(j)) {
|
||||
if (!m_to_refine.contains(m.var())) {
|
||||
TRACE("nla_solver", tout << "j" << j << " is used in a correct monic \n";);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void core::update_to_refine_of_var(lpvar j) {
|
||||
for (const monic & m : emons().get_use_list(j)) {
|
||||
if (val(var(m)) == mul_val(m))
|
||||
if (var_val(m) == mul_val(m))
|
||||
m_to_refine.erase(var(m));
|
||||
else
|
||||
m_to_refine.insert(var(m));
|
||||
}
|
||||
if (is_monic_var(j)) {
|
||||
const monic& m = emons()[j];
|
||||
if (val(var(m)) == mul_val(m))
|
||||
if (var_val(m) == mul_val(m))
|
||||
m_to_refine.erase(j);
|
||||
else
|
||||
m_to_refine.insert(j);
|
||||
|
||||
m_to_refine.insert(j);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool core::try_to_patch(lpvar k, const rational& v) {
|
||||
bool core::try_to_patch(lpvar k, const rational& v, const monic & m) {
|
||||
return m_lar_solver.try_to_patch(k, v,
|
||||
[this](lpvar u) { return var_is_used_in_a_correct_monic(u);},
|
||||
[this, m](lpvar u) { return
|
||||
u == m.var()
|
||||
||
|
||||
var_is_used_in_a_correct_monic(u)
|
||||
||
|
||||
m.contains_var(u);
|
||||
},
|
||||
[this](lpvar u) { update_to_refine_of_var(u); });
|
||||
}
|
||||
|
||||
bool in_power(const svector<lpvar>& vs, unsigned l) {
|
||||
unsigned k = vs[l];
|
||||
return (l != 0 && vs[l - 1] == k) || (l + 1 < vs.size() && k == vs[l + 1]);
|
||||
}
|
||||
|
||||
// looking for any real var to patch
|
||||
void core::patch_monomial_with_real_var(lpvar j) {
|
||||
const monic& m = emons()[j];
|
||||
TRACE("nla_solver", tout << "m = "; print_monic(m, tout) << "\n";);
|
||||
rational v = mul_val(m);
|
||||
if (val(j) == v || val(j).is_zero() || v.is_zero()) // correct or a lemma will catch it
|
||||
return;
|
||||
if (!var_is_int(j) &&
|
||||
!var_is_used_in_a_correct_monic(j)
|
||||
&& try_to_patch(j, v)) {
|
||||
SASSERT(v == val(j));
|
||||
SASSERT(j == var(m));
|
||||
if (var_val(m) == v) {
|
||||
m_to_refine.erase(j);
|
||||
} else {
|
||||
rational r = val(j) / v;
|
||||
for (lpvar k: m.vars()) {
|
||||
if (var_is_int(k)) continue;
|
||||
if (var_is_used_in_a_correct_monic(k))
|
||||
continue;
|
||||
if (try_to_patch(k, r * val(k))) { // r * val(k) gives the right value of k
|
||||
m_to_refine.erase(j);
|
||||
SASSERT(mul_val(m) == val(j));
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (val(j).is_zero() || v.is_zero()) // a lemma will catch it
|
||||
return;
|
||||
|
||||
if (!var_is_int(j) && !var_is_used_in_a_correct_monic(j) && try_to_patch(j, v, m)) {
|
||||
// SASSERT(mul_val(m) == var_val(m));
|
||||
m_to_refine.erase(j);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have v != abc. Let us suppose we patch b. Then b should
|
||||
// be equal to v/ac = v/(abc/b) = b(v/abc)
|
||||
rational r = val(j) / v;
|
||||
SASSERT(m.is_sorted());
|
||||
for (unsigned l = 0; l < m.size(); l++) {
|
||||
lpvar k = m.vars()[l];
|
||||
if (!in_power(m.vars(), l) &&
|
||||
var_is_int(k) &&
|
||||
!var_is_used_in_a_correct_monic(k) &&
|
||||
try_to_patch(k, r * val(k), m)) { // r * val(k) gives the right value of k
|
||||
SASSERT(mul_val(m) == var_val(m));
|
||||
m_to_refine.erase(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void core::patch_monomials_with_real_vars() {
|
||||
auto to_refine = m_to_refine.index();
|
||||
// the rest of the function might change m_to_refine, so have to copy
|
||||
// the rest of the function might change m_to_refine, so have to copy
|
||||
for (lpvar j : to_refine) {
|
||||
patch_monomial_with_real_var(j);
|
||||
}
|
||||
|
|
|
@ -419,7 +419,7 @@ public:
|
|||
void patch_monomial_with_real_var(lpvar);
|
||||
bool var_is_used_in_a_correct_monic(lpvar) const;
|
||||
void update_to_refine_of_var(lpvar j);
|
||||
bool try_to_patch(lpvar, const rational&);
|
||||
bool try_to_patch(lpvar, const rational&, const monic&);
|
||||
}; // end of core
|
||||
|
||||
struct pp_mon {
|
||||
|
|
|
@ -94,7 +94,7 @@ public:
|
|||
m_index.resize(0);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out) const {
|
||||
std::ostream& display(std::ostream& out) const {
|
||||
for (unsigned j : m_index) {
|
||||
out << j << " ";
|
||||
}
|
||||
|
@ -105,4 +105,10 @@ public:
|
|||
const unsigned * end() const { return m_index.end(); }
|
||||
const unsigned_vector& index() { return m_index; }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, lp::u_set const& s) {
|
||||
return s.display(out);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue