mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
split free vars in nla
This commit is contained in:
parent
a8c4384536
commit
610313946d
8 changed files with 165 additions and 73 deletions
|
@ -115,6 +115,7 @@ struct statistics {
|
|||
unsigned m_hnf_cutter_calls;
|
||||
unsigned m_hnf_cuts;
|
||||
unsigned m_nla_calls;
|
||||
unsigned m_nla_bounds;
|
||||
unsigned m_horner_calls;
|
||||
unsigned m_horner_conflicts;
|
||||
unsigned m_cross_nested_forms;
|
||||
|
@ -144,7 +145,7 @@ struct statistics {
|
|||
st.update("arith-grobner-conflicts", m_grobner_conflicts);
|
||||
st.update("arith-offset-eqs", m_offset_eqs);
|
||||
st.update("arith-fixed-eqs", m_fixed_eqs);
|
||||
|
||||
st.update("arith-nla-bounds", m_nla_bounds);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -811,6 +811,7 @@ void core::print_stats(std::ostream& out) {
|
|||
|
||||
void core::clear() {
|
||||
m_lemma_vec->clear();
|
||||
m_literal_vec->clear();
|
||||
}
|
||||
|
||||
void core::init_search() {
|
||||
|
@ -1504,11 +1505,62 @@ void core::check_bounded_divisions(vector<lemma>& l_vec) {
|
|||
m_divisions.check_bounded_divisions();
|
||||
}
|
||||
|
||||
lbool core::check(vector<lemma>& l_vec) {
|
||||
bool core::can_add_bound(unsigned j, u_map<unsigned>& bounds) {
|
||||
unsigned count = 1;
|
||||
if (bounds.find(j, count)) {
|
||||
if (count >= 2)
|
||||
return false;
|
||||
++count;
|
||||
}
|
||||
bounds.insert(j, count);
|
||||
struct decrement : public trail {
|
||||
u_map<unsigned>& bounds;
|
||||
unsigned j;
|
||||
decrement(u_map<unsigned>& bounds, unsigned j):
|
||||
bounds(bounds),
|
||||
j(j)
|
||||
{}
|
||||
void undo() override {
|
||||
--bounds[j];
|
||||
}
|
||||
};
|
||||
trail().push(decrement(bounds, j));
|
||||
return true;
|
||||
}
|
||||
|
||||
void core::add_bounds() {
|
||||
unsigned r = random(), sz = m_to_refine.size();
|
||||
for (unsigned k = 0; k < sz; k++) {
|
||||
lpvar i = m_to_refine[(k + r) % sz];
|
||||
auto const& m = m_emons[i];
|
||||
for (lpvar j : m.vars()) {
|
||||
//m_lar_solver.print_column_info(j, verbose_stream() << "check variable " << j << " ") << "\n";
|
||||
if (var_is_free(j))
|
||||
m_literal_vec->push_back(ineq(j, lp::lconstraint_kind::EQ, rational::zero()));
|
||||
#if 0
|
||||
else if (has_lower_bound(j) && can_add_bound(j, m_lower_bounds_added)) {
|
||||
m_literal_vec->push_back(ineq(j, lp::lconstraint_kind::LE, get_lower_bound(j)));
|
||||
std::cout << "called lower\n";
|
||||
}
|
||||
else if (has_upper_bound(j) && can_add_bound(j, m_upper_bounds_added)) {
|
||||
m_literal_vec->push_back(ineq(j, lp::lconstraint_kind::GE, get_upper_bound(j)));
|
||||
std::cout << "called upper\n";
|
||||
}
|
||||
#endif
|
||||
else
|
||||
continue;
|
||||
++lp_settings().stats().m_nla_bounds;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lbool core::check(vector<ineq>& lits, vector<lemma>& l_vec) {
|
||||
lp_settings().stats().m_nla_calls++;
|
||||
TRACE("nla_solver", tout << "calls = " << lp_settings().stats().m_nla_calls << "\n";);
|
||||
m_lar_solver.get_rid_of_inf_eps();
|
||||
m_lemma_vec = &l_vec;
|
||||
m_literal_vec = &lits;
|
||||
if (!(m_lar_solver.get_status() == lp::lp_status::OPTIMAL ||
|
||||
m_lar_solver.get_status() == lp::lp_status::FEASIBLE)) {
|
||||
TRACE("nla_solver", tout << "unknown because of the m_lar_solver.m_status = " << m_lar_solver.get_status() << "\n";);
|
||||
|
@ -1518,40 +1570,44 @@ lbool core::check(vector<lemma>& l_vec) {
|
|||
init_to_refine();
|
||||
patch_monomials();
|
||||
set_use_nra_model(false);
|
||||
if (m_to_refine.empty()) { return l_true; }
|
||||
if (m_to_refine.empty())
|
||||
return l_true;
|
||||
init_search();
|
||||
|
||||
lbool ret = l_undef;
|
||||
bool run_grobner = need_run_grobner();
|
||||
bool run_horner = need_run_horner();
|
||||
bool run_bounded_nlsat = should_run_bounded_nlsat();
|
||||
bool run_bounds = params().arith_nl_branching();
|
||||
|
||||
if (l_vec.empty() && !done())
|
||||
auto no_effect = [&]() { return !done() && l_vec.empty() && lits.empty(); };
|
||||
|
||||
if (no_effect())
|
||||
m_monomial_bounds();
|
||||
|
||||
if (l_vec.empty() && !done() && run_horner)
|
||||
m_horner.horner_lemmas();
|
||||
{
|
||||
std::function<void(void)> check1 = [&]() { if (no_effect() && run_horner) m_horner.horner_lemmas(); };
|
||||
std::function<void(void)> check2 = [&]() { if (no_effect() && run_grobner) m_grobner(); };
|
||||
std::function<void(void)> check3 = [&]() { if (no_effect() && run_bounds) add_bounds(); };
|
||||
|
||||
if (l_vec.empty() && !done() && run_grobner)
|
||||
m_grobner();
|
||||
|
||||
if (l_vec.empty() && !done())
|
||||
std::pair<unsigned, std::function<void(void)>> checks[] =
|
||||
{ {1, check1},
|
||||
{1, check2},
|
||||
{1, check3} };
|
||||
check_weighted(3, checks);
|
||||
if (!l_vec.empty() || !lits.empty())
|
||||
return l_false;
|
||||
}
|
||||
|
||||
if (no_effect())
|
||||
m_basics.basic_lemma(true);
|
||||
|
||||
if (l_vec.empty() && !done())
|
||||
if (no_effect())
|
||||
m_basics.basic_lemma(false);
|
||||
|
||||
if (l_vec.empty() && !done())
|
||||
if (no_effect())
|
||||
m_divisions.check();
|
||||
|
||||
#if 0
|
||||
if (l_vec.empty() && !done() && !run_horner)
|
||||
m_horner.horner_lemmas();
|
||||
|
||||
if (l_vec.empty() && !done() && !run_grobner)
|
||||
m_grobner();
|
||||
#endif
|
||||
|
||||
if (!conflict_found() && !done() && run_bounded_nlsat)
|
||||
ret = bounded_nlsat();
|
||||
|
||||
|
@ -1635,8 +1691,9 @@ bool core::no_lemmas_hold() const {
|
|||
}
|
||||
|
||||
lbool core::test_check(vector<lemma>& l) {
|
||||
vector<ineq> lits;
|
||||
m_lar_solver.set_status(lp::lp_status::OPTIMAL);
|
||||
return check(l);
|
||||
return check(lits, l);
|
||||
}
|
||||
|
||||
std::ostream& core::print_terms(std::ostream& out) const {
|
||||
|
|
|
@ -84,6 +84,7 @@ class core {
|
|||
smt_params_helper m_params;
|
||||
std::function<bool(lpvar)> m_relevant;
|
||||
vector<lemma> * m_lemma_vec;
|
||||
vector<ineq> * m_literal_vec = nullptr;
|
||||
indexed_uint_set m_to_refine;
|
||||
tangents m_tangents;
|
||||
basics m_basics;
|
||||
|
@ -110,6 +111,10 @@ class core {
|
|||
|
||||
void check_weighted(unsigned sz, std::pair<unsigned, std::function<void(void)>>* checks);
|
||||
|
||||
u_map<unsigned> m_lower_bounds_added, m_upper_bounds_added;
|
||||
bool can_add_bound(unsigned j, u_map<unsigned>& bounds);
|
||||
void add_bounds();
|
||||
|
||||
public:
|
||||
// constructor
|
||||
core(lp::lar_solver& s, params_ref const& p, reslimit&);
|
||||
|
@ -380,7 +385,7 @@ public:
|
|||
|
||||
bool conflict_found() const;
|
||||
|
||||
lbool check(vector<lemma>& l_vec);
|
||||
lbool check(vector<ineq>& ineqs, vector<lemma>& l_vec);
|
||||
lbool check_power(lpvar r, lpvar x, lpvar y, vector<lemma>& l_vec);
|
||||
void check_bounded_divisions(vector<lemma>&);
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ namespace nla {
|
|||
|
||||
bool solver::need_check() { return m_core->has_relevant_monomial(); }
|
||||
|
||||
lbool solver::check(vector<lemma>& l) {
|
||||
return m_core->check(l);
|
||||
lbool solver::check(vector<ineq>& lits, vector<lemma>& lemmas) {
|
||||
return m_core->check(lits, lemmas);
|
||||
}
|
||||
|
||||
void solver::push(){
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace nla {
|
|||
void push();
|
||||
void pop(unsigned scopes);
|
||||
bool need_check();
|
||||
lbool check(vector<lemma>&);
|
||||
lbool check(vector<ineq>& lits, vector<lemma>&);
|
||||
lbool check_power(lpvar r, lpvar x, lpvar y, vector<lemma>&);
|
||||
bool is_monic_var(lpvar) const;
|
||||
bool influences_nl_var(lpvar) const;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue