3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 02:15:19 +00:00

add stubs for monomial unit propagation

This commit is contained in:
Nikolaj Bjorner 2023-08-30 17:21:38 -07:00
parent 00593609c5
commit 38b131386d
7 changed files with 84 additions and 10 deletions

View file

@ -646,7 +646,6 @@ class lar_solver : public column_namer {
inline const static_matrix<mpq, impq>& A_r() const { return m_mpq_lar_core_solver.m_r_A; }
// columns
bool column_is_int(column_index const& j) const { return column_is_int((unsigned)j); }
// const impq& get_ivalue(column_index const& j) const { return get_column_value(j); }
const impq& get_column_value(column_index const& j) const { return m_mpq_lar_core_solver.m_r_x[j]; }
inline var_index external_to_local(unsigned j) const {
var_index local_j;

View file

@ -1574,10 +1574,10 @@ lbool core::check(vector<ineq>& lits, vector<lemma>& l_vec) {
if (no_effect())
m_divisions.check();
if (!conflict_found() && !done() && run_bounded_nlsat)
if (no_effect() && run_bounded_nlsat)
ret = bounded_nlsat();
if (l_vec.empty() && !done() && ret == l_undef) {
if (no_effect() && ret == l_undef) {
std::function<void(void)> check1 = [&]() { m_order.order_lemma(); };
std::function<void(void)> check2 = [&]() { m_monotone.monotonicity_lemma(); };
std::function<void(void)> check3 = [&]() { m_tangents.tangent_lemma(); };
@ -1593,7 +1593,7 @@ lbool core::check(vector<ineq>& lits, vector<lemma>& l_vec) {
ret = bounded_nlsat();
}
if (l_vec.empty() && !done() && params().arith_nl_nra() && ret == l_undef) {
if (no_effect() && params().arith_nl_nra() && ret == l_undef) {
ret = m_nra.check();
m_stats.m_nra_calls++;
}
@ -1811,6 +1811,46 @@ bool core::improve_bounds() {
return bounds_improved;
}
void core::propagate(vector<lemma>& lemmas) {
// disable for now
return;
// propagate linear monomials
lemmas.reset();
for (auto const& m : m_emons)
if (propagate(m, lemmas))
break;
}
bool core::propagate(monic const& m, vector<lemma>& lemmas) {
m_propagated.reserve(m.var() + 1, false);
if (m_propagated[m.var()])
return false;
if (!is_linear(m))
return false;
trail().push(set_bitvector_trail(m_propagated, m.var()));
mpq k = fixed_var_product(m);
// todo
// return true if m_emons changes (so the iterator is invalid)
return false;
}
bool core::is_linear(monic const& m) {
// todo
return false;
}
mpq core::fixed_var_product(monic const& m) {
// todo
return mpq(0);
}
} // end of nla

View file

@ -59,6 +59,7 @@ class core {
friend class solver;
friend class monomial_bounds;
friend class nra::solver;
friend class divisions;
struct stats {
unsigned m_nla_explanations;
@ -390,6 +391,8 @@ public:
void check_bounded_divisions(vector<lemma>&);
bool no_lemmas_hold() const;
void propagate(vector<lemma>& lemmas);
lbool test_check(vector<lemma>& l);
lpvar map_to_root(lpvar) const;
@ -432,6 +435,13 @@ private:
void restore_tableau();
void save_tableau();
bool integrality_holds();
// monomial propagation
bool_vector m_propagated;
bool propagate(monic const& m, vector<lemma>& lemmas);
bool is_linear(monic const& m);
mpq fixed_var_product(monic const& m);
}; // end of core
struct pp_mon {

View file

@ -19,19 +19,30 @@ Description:
namespace nla {
void divisions::add_idivision(lpvar q, lpvar x, lpvar y) {
auto& lra = m_core.lra;
if (x == null_lpvar || y == null_lpvar || q == null_lpvar)
return;
if (lp::tv::is_term(x) || lp::tv::is_term(y) || lp::tv::is_term(q))
return;
if (lp::tv::is_term(x))
x = lra.map_term_index_to_column_index(x);
if (lp::tv::is_term(y))
y = lra.map_term_index_to_column_index(y);
if (lp::tv::is_term(q))
q = lra.map_term_index_to_column_index(q);
m_idivisions.push_back({q, x, y});
m_core.trail().push(push_back_vector(m_idivisions));
}
void divisions::add_rdivision(lpvar q, lpvar x, lpvar y) {
auto& lra = m_core.lra;
if (x == null_lpvar || y == null_lpvar || q == null_lpvar)
return;
if (lp::tv::is_term(x) || lp::tv::is_term(y) || lp::tv::is_term(q))
return;
if (lp::tv::is_term(x))
x = lra.map_term_index_to_column_index(x);
if (lp::tv::is_term(y))
y = lra.map_term_index_to_column_index(y);
if (lp::tv::is_term(q))
q = lra.map_term_index_to_column_index(q);
m_rdivisions.push_back({ q, x, y });
m_core.trail().push(push_back_vector(m_rdivisions));
}
@ -52,7 +63,7 @@ namespace nla {
// y2 <= y1 < 0 & x1 <= x2 <= 0 => x1/y1 >= x2/y2
void divisions::check() {
core& c = m_core;
core& c = m_core;
if (c.use_nra_model())
return;
@ -132,7 +143,7 @@ namespace nla {
auto x2val = c.val(x2);
auto y2val = c.val(y2);
auto q2val = c.val(q2);
if (monotonicity(x, xval, y, yval, r, rval, x2, x2val, y2, y2val, q2, q2val))
if (monotonicity(x, xval, y, yval, r, rval, x2, x2val, y2, y2val, q2, q2val))
return;
}
}

View file

@ -45,6 +45,10 @@ namespace nla {
lbool solver::check(vector<ineq>& lits, vector<lemma>& lemmas) {
return m_core->check(lits, lemmas);
}
void solver::propagate(vector<lemma>& lemmas) {
m_core->propagate(lemmas);
}
void solver::push(){
m_core->push();

View file

@ -37,6 +37,7 @@ namespace nla {
void pop(unsigned scopes);
bool need_check();
lbool check(vector<ineq>& lits, vector<lemma>&);
void propagate(vector<lemma>& lemmas);
lbool check_power(lpvar r, lpvar x, lpvar y, vector<lemma>&);
bool is_monic_var(lpvar) const;
bool influences_nl_var(lpvar) const;

View file

@ -2152,11 +2152,20 @@ public:
propagate_bounds_with_lp_solver();
break;
case l_undef:
propagate_nla();
break;
}
return true;
}
void propagate_nla() {
if (!m_nla)
return;
m_nla->propagate(m_nla_lemma_vector);
for (nla::lemma const& l : m_nla_lemma_vector)
false_case_of_check_nla(l);
}
bool should_propagate() const {
return bound_prop_mode::BP_NONE != propagation_mode();
}