diff --git a/src/math/lp/cross_nested.h b/src/math/lp/cross_nested.h index c5694955c..b7e897eac 100644 --- a/src/math/lp/cross_nested.h +++ b/src/math/lp/cross_nested.h @@ -34,8 +34,8 @@ class cross_nested { ptr_vector m_b_split_vec; int m_reported; bool m_random_bit; - nex_creator m_nex_creator; std::function m_mk_scalar; + nex_creator& m_nex_creator; #ifdef Z3DEBUG nex* m_e_clone; #endif @@ -45,13 +45,15 @@ public: cross_nested(std::function call_on_result, std::function var_is_fixed, - std::function random) : + std::function random, + nex_creator& nex_cr) : m_call_on_result(call_on_result), m_var_is_fixed(var_is_fixed), m_random(random), m_done(false), m_reported(0), - m_mk_scalar([this]{return m_nex_creator.mk_scalar(rational(1));}) + m_mk_scalar([this]{return m_nex_creator.mk_scalar(rational(1));}), + m_nex_creator(nex_cr) {} @@ -369,15 +371,15 @@ public: // all factors of j go to a, the rest to b void pre_split(nex_sum * e, lpvar j, nex_sum*& a, nex*& b) { TRACE("nla_cn_details", tout << "e = " << * e << ", j = " << m_nex_creator.ch(j) << std::endl;); + SASSERT(m_nex_creator.is_simplified(e)); a = m_nex_creator.mk_sum(); m_b_split_vec.clear(); for (nex * ce: *e) { + TRACE("nla_cn_details", tout << "ce = " << *ce << "\n";); if (is_divisible_by_var(ce, j)) { a->add_child(m_nex_creator.mk_div(ce , j)); } else { m_b_split_vec.push_back(ce); - TRACE("nla_cn_details", tout << "ce = " << *ce << "\n";); - } } TRACE("nla_cn_details", tout << "a = " << *a << "\n";); diff --git a/src/math/lp/horner.cpp b/src/math/lp/horner.cpp index bab09e9b2..06019990e 100644 --- a/src/math/lp/horner.cpp +++ b/src/math/lp/horner.cpp @@ -45,7 +45,7 @@ bool horner::row_is_interesting(const T& row) const { return false; } SASSERT(row_has_monomial_to_refine(row)); - c().clear_row_var_set(); + c().clear_active_var_set(); for (const auto& p : row) { lpvar j = p.var(); if (!c().is_monic_var(j)) @@ -53,19 +53,19 @@ bool horner::row_is_interesting(const T& row) const { auto & m = c().emons()[j]; for (lpvar k : m.vars()) { - if (c().row_var_set_contains(k)) + if (c().active_var_set_contains(k)) return true; } for (lpvar k : m.vars()) { - c().insert_to_row_var_set(k); + c().insert_to_active_var_set(k); } } return false; } -bool horner::lemmas_on_expr(cross_nested& cn) { - TRACE("nla_horner", tout << "m_row_sum = " << m_row_sum << "\n";); - cn.run(&m_row_sum); +bool horner::lemmas_on_expr(cross_nested& cn, nex_sum* e) { + TRACE("nla_horner", tout << "e = " << *e << "\n";); + cn.run(e); return cn.done(); } @@ -92,11 +92,15 @@ bool horner::lemmas_on_row(const T& row) { cross_nested cn( [this](const nex* n) { return check_cross_nested_expr(n); }, [this](unsigned j) { return c().var_is_fixed(j); }, - [this]() { return c().random(); }); + [this]() { return c().random(); }, m_nex_creator); SASSERT (row_is_interesting(row)); create_sum_from_row(row, cn.get_nex_creator(), m_row_sum); - return lemmas_on_expr(cn); + nex* e = m_nex_creator.simplify(&m_row_sum); + if (!e->is_sum()) + return false; + + return lemmas_on_expr(cn, to_sum(e)); } void horner::horner_lemmas() { @@ -112,7 +116,7 @@ void horner::horner_lemmas() { for (auto & s : matrix.m_columns[j]) rows_to_check.insert(s.var()); } - c().prepare_row_var_set(); + c().prepare_active_var_set(); svector rows; for (unsigned i : rows_to_check) { if (row_is_interesting(matrix.m_rows[i])) diff --git a/src/math/lp/horner.h b/src/math/lp/horner.h index d35e252a5..d636cdfaa 100644 --- a/src/math/lp/horner.h +++ b/src/math/lp/horner.h @@ -53,7 +53,7 @@ public: intervals::interval interval_of_sum_no_term_with_deps(const nex_sum*); intervals::interval interval_of_mul_with_deps(const nex_mul*); void set_var_interval_with_deps(lpvar j, intervals::interval&) const; - bool lemmas_on_expr(cross_nested&); + bool lemmas_on_expr(cross_nested&, nex_sum*); template // T has an iterator of (coeff(), var()) bool row_has_monomial_to_refine(const T&) const; diff --git a/src/math/lp/nex.h b/src/math/lp/nex.h index f7979e6a8..e09a1eeff 100644 --- a/src/math/lp/nex.h +++ b/src/math/lp/nex.h @@ -97,7 +97,8 @@ public: lpvar var() const { return m_j; } lpvar& var() { return m_j; } // the setter std::ostream & print(std::ostream& out) const { - out << (char)('a' + m_j); + // out << (char)('a' + m_j); + out << "v" << m_j; return out; } diff --git a/src/math/lp/nex_creator.cpp b/src/math/lp/nex_creator.cpp index 688af2d53..e409c8087 100644 --- a/src/math/lp/nex_creator.cpp +++ b/src/math/lp/nex_creator.cpp @@ -288,8 +288,12 @@ bool nex_creator::lt(const nex* a, const nex* b) const { bool nex_creator::is_sorted(const nex_mul* e) const { for (unsigned j = 0; j < e->size() - 1; j++) { - if (!(less_than_on_nex_pow((*e)[j], (*e)[j+1]))) + if (!(less_than_on_nex_pow((*e)[j], (*e)[j+1]))) { + TRACE("nla_cn_details", tout << "not sorted e " << * e << "\norder is incorrect " << + (*e)[j] << " >= " << (*e)[j + 1]<< "\n";); + return false; + } } return true; } @@ -298,22 +302,29 @@ bool nex_creator::is_sorted(const nex_mul* e) const { bool nex_creator::mul_is_simplified(const nex_mul* e) const { + TRACE("nla_cn_details", tout << "e = " << *e << "\n";); if (e->size() == 1 && e->begin()->pow() == 1) return false; std::set s([this](const nex* a, const nex* b) {return lt(a, b); }); for (const auto &p : *e) { const nex* ee = p.e(); - if (p.pow() == 0) + if (p.pow() == 0) { + TRACE("nla_cn_details", tout << "not simplified " << *ee << "\n";); return false; - if (ee->is_mul()) + } + if (ee->is_mul()) { + TRACE("nla_cn_details", tout << "not simplified " << *ee << "\n";); return false; - if (ee->is_scalar() && to_scalar(ee)->value().is_one()) + } + if (ee->is_scalar() && to_scalar(ee)->value().is_one()) { + TRACE("nla_cn_details", tout << "not simplified " << *ee << "\n";); return false; + } auto it = s.find(ee); if (it == s.end()) { s.insert(ee); - } else { + } else { TRACE("nla_cn_details", tout << "not simplified " << *ee << "\n";); return false; } @@ -340,20 +351,29 @@ nex* nex_creator::simplify_sum(nex_sum *e) { } bool nex_creator::sum_is_simplified(const nex_sum* e) const { - if (e->size() < 2) return false; bool scalar = false; for (nex * ee : *e) { - if (ee->is_sum()) + if (ee->is_sum()) { + TRACE("nla_cn", tout << "not simplified e = " << *e << "\n" + << " has a child which is a sum " << *ee << "\n";); return false; + } if (ee->is_scalar()) { if (scalar) { + TRACE("nla_cn", tout << "not simplified e = " << *e << "\n" + << " have more than one scalar " << *ee << "\n";); + return false; } if (to_scalar(ee)->value().is_zero()) { - return false; + if (scalar) { + TRACE("nla_cn", tout << "have a zero scalar " << *ee << "\n";); + + return false; + } + scalar = true; } - scalar = true; } if (!is_simplified(ee)) return false; diff --git a/src/math/lp/nex_creator.h b/src/math/lp/nex_creator.h index d09fd2f86..9dbce32f5 100644 --- a/src/math/lp/nex_creator.h +++ b/src/math/lp/nex_creator.h @@ -57,11 +57,11 @@ class nex_creator { svector m_active_vars_weights; public: - static char ch(unsigned j) { - // std::stringstream s; - // s << "v" << j; - // return s.str(); - return (char)('a'+j); + static std::string ch(unsigned j) { + std::stringstream s; + s << "v" << j; + return s.str(); + // return (char)('a'+j); } // assuming that every lpvar is less than this number diff --git a/src/math/lp/nla_common.cpp b/src/math/lp/nla_common.cpp index 09ec84e27..270cea2b8 100644 --- a/src/math/lp/nla_common.cpp +++ b/src/math/lp/nla_common.cpp @@ -122,26 +122,32 @@ unsigned common::random() { return c().random(); } -nex * common::nexvar(lpvar j, nex_creator& cn) const { +nex * common::nexvar(lpvar j, nex_creator& cn) { // todo: consider deepen the recursion - if (!c().is_monic_var(j)) + if (!c().is_monic_var(j)) { + c().insert_to_active_var_set(j); return cn.mk_var(j); + } const monic& m = c().emons()[j]; nex_mul * e = cn.mk_mul(); for (lpvar k : m.vars()) { + c().insert_to_active_var_set(k); e->add_child(cn.mk_var(k)); CTRACE("nla_horner", c().is_monic_var(k), c().print_var(k, tout) << "\n";); } return e; } -nex * common::nexvar(const rational & coeff, lpvar j, nex_creator& cn) const { +nex * common::nexvar(const rational & coeff, lpvar j, nex_creator& cn) { // todo: consider deepen the recursion - if (!c().is_monic_var(j)) + if (!c().is_monic_var(j)) { + c().insert_to_active_var_set(j); return cn.mk_mul(cn.mk_scalar(coeff), cn.mk_var(j)); + } const monic& m = c().emons()[j]; nex_mul * e = cn.mk_mul(cn.mk_scalar(coeff)); for (lpvar k : m.vars()) { + c().insert_to_active_var_set(j); e->add_child(cn.mk_var(k)); CTRACE("nla_horner", c().is_monic_var(k), c().print_var(k, tout) << "\n";); } @@ -151,6 +157,7 @@ nex * common::nexvar(const rational & coeff, lpvar j, nex_creator& cn) const { template void common::create_sum_from_row(const T& row, nex_creator& cn, nex_sum& sum) { TRACE("nla_horner", tout << "row="; m_core->print_term(row, tout) << "\n";); + c().prepare_active_var_set(); SASSERT(row.size() > 1); sum.children().clear(); for (const auto &p : row) { @@ -160,7 +167,43 @@ template void common::create_sum_from_row(const T& row, nex_creator sum.add_child(nexvar(p.coeff(), p.var(), cn)); } } + set_active_vars_weights(); } + +void common::set_active_vars_weights() { + m_nex_creator.set_number_of_vars(c().m_lar_solver.column_count()); + for (lpvar j : c().active_var_set()) { + m_nex_creator.set_var_weight(j, static_cast(get_var_weight(j))); + } +} + +var_weight common::get_var_weight(lpvar j) const { + var_weight k; + switch (c().m_lar_solver.get_column_type(j)) { + + case lp::column_type::fixed: + k = var_weight::FIXED; + break; + case lp::column_type::boxed: + k = var_weight::BOUNDED; + break; + case lp::column_type::lower_bound: + case lp::column_type::upper_bound: + k = var_weight::NOT_FREE; + case lp::column_type::free_column: + k = var_weight::FREE; + break; + default: + UNREACHABLE(); + break; + } + if (c().is_monic_var(j)) { + return (var_weight)((int)k + 1); + } + return k; +} + + } template void nla::common::create_sum_from_row, true, unsigned int> >(old_vector, true, unsigned int> const&, nla::nex_creator&, nla::nex_sum&); diff --git a/src/math/lp/nla_common.h b/src/math/lp/nla_common.h index 0465ab3c6..b96c15ad4 100644 --- a/src/math/lp/nla_common.h +++ b/src/math/lp/nla_common.h @@ -45,7 +45,9 @@ inline llc negate(llc cmp) { class core; struct common { - core* m_core; + core* m_core; + nex_creator m_nex_creator; + common(core* c): m_core(c) {} core& c() { return *m_core; } const core& c() const { return *m_core; } @@ -115,10 +117,11 @@ struct common { typedef dependency_manager ci_dependency_manager; typedef ci_dependency_manager::dependency ci_dependency; - nex* nexvar(lpvar j, nex_creator& ) const; - nex* nexvar(const rational& coeff, lpvar j, nex_creator&) const; + nex* nexvar(lpvar j, nex_creator& ); + nex* nexvar(const rational& coeff, lpvar j, nex_creator&); template void create_sum_from_row(const T&, nex_creator&, nex_sum&); - + void set_active_vars_weights(); + var_weight get_var_weight(lpvar) const; }; } diff --git a/src/math/lp/nla_core.h b/src/math/lp/nla_core.h index 8c514a30d..ebddfaebf 100644 --- a/src/math/lp/nla_core.h +++ b/src/math/lp/nla_core.h @@ -79,7 +79,7 @@ public: class core { public: - var_eqs m_evars; + var_eqs m_evars; lp::lar_solver& m_lar_solver; vector * m_lemma_vec; lp::int_set m_to_refine; @@ -91,25 +91,25 @@ public: nla_settings m_nla_settings; nla_grobner m_grobner; private: - emonics m_emons; + emonics m_emons; svector m_add_buffer; - mutable lp::int_set m_row_var_set; + mutable lp::int_set m_active_var_set; public: reslimit m_reslim; - const lp::int_set& row_var_set () const { return m_row_var_set;} - bool row_var_set_contains(unsigned j) const { return m_row_var_set.contains(j); } + const lp::int_set& active_var_set () const { return m_active_var_set;} + bool active_var_set_contains(unsigned j) const { return m_active_var_set.contains(j); } - void insert_to_row_var_set(unsigned j) const { m_row_var_set.insert(j); } + void insert_to_active_var_set(unsigned j) const { m_active_var_set.insert(j); } - void clear_row_var_set() const { - m_row_var_set.clear(); + void clear_active_var_set() const { + m_active_var_set.clear(); } - void prepare_row_var_set() const { - m_row_var_set.clear(); - m_row_var_set.resize(m_lar_solver.number_of_vars()); + void prepare_active_var_set() const { + m_active_var_set.clear(); + m_active_var_set.resize(m_lar_solver.number_of_vars()); } reslimit & reslim() { return m_reslim; } diff --git a/src/math/lp/nla_grobner.cpp b/src/math/lp/nla_grobner.cpp index d2df9c66c..ab3be29d1 100644 --- a/src/math/lp/nla_grobner.cpp +++ b/src/math/lp/nla_grobner.cpp @@ -75,39 +75,6 @@ void nla_grobner::add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, std } } -var_weight nla_grobner::get_var_weight(lpvar j) const { - var_weight k; - switch (c().m_lar_solver.get_column_type(j)) { - - case lp::column_type::fixed: - k = var_weight::FIXED; - break; - case lp::column_type::boxed: - k = var_weight::BOUNDED; - break; - case lp::column_type::lower_bound: - case lp::column_type::upper_bound: - k = var_weight::NOT_FREE; - case lp::column_type::free_column: - k = var_weight::FREE; - break; - default: - UNREACHABLE(); - break; - } - if (c().is_monic_var(j)) { - return (var_weight)((int)k + 1); - } - return k; -} - -void nla_grobner::set_active_vars_weights() { - m_nex_creator.set_number_of_vars(c().m_lar_solver.column_count()); - for (lpvar j : m_active_vars) { - m_nex_creator.set_var_weight(j, static_cast(get_var_weight(j))); - } -} - void nla_grobner::find_nl_cluster() { prepare_rows_and_active_vars(); std::queue q; diff --git a/src/math/lp/nla_grobner.h b/src/math/lp/nla_grobner.h index af0d63a77..6d0441150 100644 --- a/src/math/lp/nla_grobner.h +++ b/src/math/lp/nla_grobner.h @@ -89,7 +89,6 @@ class nla_grobner : common { region m_alloc; ci_value_manager m_val_manager; ci_dependency_manager m_dep_manager; - nex_creator m_nex_creator; nex_lt m_lt; public: nla_grobner(core *core); @@ -100,9 +99,7 @@ private: void prepare_rows_and_active_vars(); void add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, std::queue& q); void display(std::ostream&); - void set_active_vars_weights(); void init(); - var_weight get_var_weight(lpvar) const; void compute_basis(); void update_statistics(); bool find_conflict(ptr_vector& eqs); diff --git a/src/test/lp/lp.cpp b/src/test/lp/lp.cpp index 21e837818..56eebaa61 100644 --- a/src/test/lp/lp.cpp +++ b/src/test/lp/lp.cpp @@ -76,20 +76,20 @@ void test_cn_on_expr(nex_sum *t, cross_nested& cn) { void test_simplify() { #ifdef Z3DEBUG + nex_creator r; cross_nested cn( [](const nex* n) { TRACE("nla_cn_test", tout << *n << "\n";); return false; } , [](unsigned) { return false; }, - []() { return 1; } // for random - ); + []() { return 1; }, // for random + r); // enable_trace("nla_cn"); // enable_trace("nla_cn_details"); // enable_trace("nla_cn_details_"); enable_trace("nla_test"); - nex_creator & r = cn.get_nex_creator(); r.set_number_of_vars(3); for (unsigned j = 0; j < r.get_number_of_vars(); j++) r.set_var_weight(j, j); @@ -147,6 +147,7 @@ void test_simplify() { void test_cn_shorter() { nex_sum *clone; + nex_creator cr; cross_nested cn( [](const nex* n) { TRACE("nla_test", tout <<"cn form = " << *n << "\n"; @@ -155,13 +156,12 @@ void test_cn_shorter() { return false; } , [](unsigned) { return false; }, - []{ return 1; }); + []{ return 1; }, cr); enable_trace("nla_test"); enable_trace("nla_cn"); enable_trace("nla_cn_test"); enable_trace("nla_cn_details"); enable_trace("nla_test_details"); - auto & cr = cn.get_nex_creator(); cr.set_number_of_vars(20); for (unsigned j = 0; j < cr.get_number_of_vars(); j++) cr.set_var_weight(j,j); @@ -191,18 +191,18 @@ void test_cn_shorter() { void test_cn() { #ifdef Z3DEBUG test_cn_shorter(); + nex_creator cr; cross_nested cn( [](const nex* n) { TRACE("nla_test", tout <<"cn form = " << *n << "\n";); return false; } , [](unsigned) { return false; }, - []{ return 1; }); + []{ return 1; }, cr); enable_trace("nla_test"); enable_trace("nla_cn_test"); // enable_trace("nla_cn"); // enable_trace("nla_test_details"); - auto & cr = cn.get_nex_creator(); cr.set_number_of_vars(20); for (unsigned j = 0; j < cr.get_number_of_vars(); j++) cr.set_var_weight(j, j);