mirror of
https://github.com/Z3Prover/z3
synced 2025-04-08 18:31:49 +00:00
preparing a call to pdd_grobner
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
5e19a52772
commit
dd9935de7d
|
@ -79,7 +79,7 @@ bool horner::lemmas_on_row(const T& row) {
|
|||
SASSERT (row_is_interesting(row));
|
||||
c().clear_and_resize_active_var_set();
|
||||
create_sum_from_row(row, cn.get_nex_creator(), m_row_sum, nullptr);
|
||||
set_active_vars_weights(); // without this call the comparisons will be incorrect
|
||||
c().set_active_vars_weights(m_nex_creator); // without this call the comparisons will be incorrect
|
||||
nex* e = m_nex_creator.simplify(m_row_sum.mk());
|
||||
TRACE("nla_horner", tout << "e = " << * e << "\n";);
|
||||
if (e->get_degree() < 2)
|
||||
|
|
|
@ -111,7 +111,6 @@ struct statistics {
|
|||
unsigned m_horner_conflicts;
|
||||
unsigned m_cross_nested_forms;
|
||||
unsigned m_grobner_calls;
|
||||
unsigned m_grobner_basis_computatins;
|
||||
unsigned m_grobner_conflicts;
|
||||
statistics() { reset(); }
|
||||
void reset() { memset(this, 0, sizeof(*this)); }
|
||||
|
|
|
@ -200,40 +200,6 @@ u_dependency* common::get_fixed_vars_dep_from_row(const T& row, u_dependency_man
|
|||
return dep;
|
||||
}
|
||||
|
||||
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<unsigned>(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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -121,7 +121,5 @@ struct common {
|
|||
u_dependency* create_sum_from_row(const T&, nex_creator&, nex_creator::sum_factory&, u_dependency_manager*);
|
||||
template <typename T>
|
||||
u_dependency* get_fixed_vars_dep_from_row(const T&, u_dependency_manager& dep_manager);
|
||||
void set_active_vars_weights();
|
||||
var_weight get_var_weight(lpvar) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,7 +32,9 @@ core::core(lp::lar_solver& s, reslimit & lim) :
|
|||
m_monotone(this),
|
||||
m_intervals(this, lim),
|
||||
m_horner(this, &m_intervals),
|
||||
m_grobner(this, &m_intervals),
|
||||
m_nex_grobner(this, &m_intervals),
|
||||
m_pdd_manager(0),
|
||||
m_pdd_grobner(lim, m_pdd_manager),
|
||||
m_emons(m_evars),
|
||||
m_reslim(lim)
|
||||
{}
|
||||
|
@ -1282,9 +1284,26 @@ lbool core::incremental_linearization(bool constraint_derived) {
|
|||
lbool core::inner_check(bool constraint_derived) {
|
||||
if (constraint_derived) {
|
||||
if (need_to_call_algebraic_methods())
|
||||
if (!(m_nla_settings.run_horner() && m_horner.horner_lemmas())) {
|
||||
if (m_nla_settings.run_grobner() == nla_settings::NEX_GROBNER || m_nla_settings.run_grobner() == nla_settings::BOTH_GROBNER)
|
||||
m_grobner.grobner_lemmas();
|
||||
if (m_horner.horner_lemmas()) {
|
||||
switch( m_nla_settings.run_grobner()) {
|
||||
case nla_settings::BOTH_GROBNER:
|
||||
init_nex_grobner(m_nex_grobner.get_nex_creator());
|
||||
m_nex_grobner.grobner_lemmas();
|
||||
run_pdd_grobner();
|
||||
break;
|
||||
case nla_settings::NEX_GROBNER:
|
||||
init_nex_grobner(m_nex_grobner.get_nex_creator());
|
||||
m_nex_grobner.grobner_lemmas();
|
||||
break;
|
||||
case nla_settings::PDD_GROBNER:
|
||||
run_pdd_grobner();
|
||||
break;
|
||||
case nla_settings::NO_GROBNER:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (done()) {
|
||||
return l_false;
|
||||
|
@ -1361,42 +1380,6 @@ lbool core::test_check(
|
|||
return check(l);
|
||||
}
|
||||
|
||||
// nla_expr<rational> core::mk_expr(lpvar j) const {
|
||||
// return nla_expr<rational>::var(j);
|
||||
// }
|
||||
|
||||
// nla_expr<rational> core::mk_expr(const rational &a, lpvar j) const {
|
||||
// if (a == 1)
|
||||
// return mk_expr(j);
|
||||
// nla_expr<rational> r(expr_type::MUL);
|
||||
// r.add_child(nla_expr<rational>::scalar(a));
|
||||
// r.add_child(nla_expr<rational>::var(j));
|
||||
// return r;
|
||||
// }
|
||||
|
||||
// nla_expr<rational> core::mk_expr(const rational &a, const svector<lpvar>& vs) const {
|
||||
// nla_expr<rational> r(expr_type::MUL);
|
||||
// r.add_child(nla_expr<rational>::scalar(a));
|
||||
// for (lpvar j : vs)
|
||||
// r.add_child(nla_expr<rational>::var(j));
|
||||
// return r;
|
||||
// }
|
||||
// nla_expr<rational> core::mk_expr(const lp::lar_term& t) const {
|
||||
// auto coeffs = t.coeffs_as_vector();
|
||||
// if (coeffs.size() == 1) {
|
||||
// return mk_expr(coeffs[0].first, coeffs[0].second);
|
||||
// }
|
||||
// nla_expr<rational> r(expr_type::SUM);
|
||||
// for (const auto & p : coeffs) {
|
||||
// lpvar j = p.second;
|
||||
// if (is_monic_var(j))
|
||||
// r.add_child(mk_expr(p.first, m_emons[j].vars()));
|
||||
// else
|
||||
// r.add_child(mk_expr(p.first, j));
|
||||
// }
|
||||
// return r;
|
||||
// }
|
||||
|
||||
std::ostream& core::print_terms(std::ostream& out) const {
|
||||
for (unsigned i=0; i< m_lar_solver.m_terms.size(); i++) {
|
||||
unsigned ext = i + m_lar_solver.terms_start_index();
|
||||
|
@ -1424,4 +1407,136 @@ std::ostream& core::print_term( const lp::lar_term& t, std::ostream& out) const
|
|||
[this](lpvar j) { return var_str(j); },
|
||||
out);
|
||||
}
|
||||
|
||||
void core::run_pdd_grobner() {
|
||||
m_pdd_manager.resize(m_lar_solver.number_of_vars());
|
||||
}
|
||||
|
||||
void core::add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, svector<lpvar> & q) {
|
||||
if (active_var_set_contains(j) || var_is_fixed(j)) return;
|
||||
TRACE("grobner", tout << "j = " << j << ", "; print_var(j, tout) << "\n";);
|
||||
const auto& matrix = m_lar_solver.A_r();
|
||||
insert_to_active_var_set(j);
|
||||
for (auto & s : matrix.m_columns[j]) {
|
||||
unsigned row = s.var();
|
||||
if (m_rows.contains(row)) continue;
|
||||
if (matrix.m_rows[row].size() > m_nla_settings.grobner_row_length_limit()) {
|
||||
TRACE("grobner", tout << "ignore the row " << row << " with the size " << matrix.m_rows[row].size() << "\n";);
|
||||
continue;
|
||||
}
|
||||
m_rows.insert(row);
|
||||
for (auto& rc : matrix.m_rows[row]) {
|
||||
add_var_and_its_factors_to_q_and_collect_new_rows(rc.var(), q);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_monic_var(j))
|
||||
return;
|
||||
|
||||
const monic& m = emons()[j];
|
||||
for (auto fcn : factorization_factory_imp(m, *this)) {
|
||||
for (const factor& fc: fcn) {
|
||||
q.push_back(var(fc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void core::find_nl_cluster(nex_creator& nc) {
|
||||
prepare_rows_and_active_vars();
|
||||
svector<lpvar> q;
|
||||
for (lpvar j : m_to_refine) {
|
||||
TRACE("grobner", print_monic(emons()[j], tout) << "\n";);
|
||||
q.push_back(j);
|
||||
}
|
||||
|
||||
while (!q.empty()) {
|
||||
lpvar j = q.back();
|
||||
q.pop_back();
|
||||
add_var_and_its_factors_to_q_and_collect_new_rows(j, q);
|
||||
}
|
||||
set_active_vars_weights(nc);
|
||||
TRACE("grobner", display_matrix_of_m_rows(tout););
|
||||
}
|
||||
|
||||
void core::prepare_rows_and_active_vars() {
|
||||
m_rows.clear();
|
||||
m_rows.resize(m_lar_solver.row_count());
|
||||
clear_and_resize_active_var_set();
|
||||
}
|
||||
|
||||
|
||||
std::unordered_set<lpvar> core::get_vars_of_expr_with_opening_terms(const nex *e ) {
|
||||
auto ret = get_vars_of_expr(e);
|
||||
auto & ls = m_lar_solver;
|
||||
svector<lpvar> added;
|
||||
for (auto j : ret) {
|
||||
added.push_back(j);
|
||||
}
|
||||
for (unsigned i = 0; i < added.size(); ++i) {
|
||||
lpvar j = added[i];
|
||||
if (ls.column_corresponds_to_term(j)) {
|
||||
const auto& t = m_lar_solver.get_term(ls.local_to_external(j));
|
||||
for (auto p : t) {
|
||||
if (ret.find(p.var()) == ret.end()) {
|
||||
added.push_back(p.var());
|
||||
ret.insert(p.var());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void core::display_matrix_of_m_rows(std::ostream & out) const {
|
||||
const auto& matrix = m_lar_solver.A_r();
|
||||
out << m_rows.size() << " rows" <<"\n";
|
||||
out << "the matrix\n";
|
||||
for (const auto & r : matrix.m_rows) {
|
||||
print_term(r, out) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void core::init_nex_grobner(nex_creator & nc) {
|
||||
find_nl_cluster(nc);
|
||||
clear_and_resize_active_var_set();
|
||||
TRACE("grobner", tout << "m_rows.size() = " << m_rows.size() << "\n";);
|
||||
for (unsigned i : m_rows) {
|
||||
m_nex_grobner.add_row(m_lar_solver.A_r().m_rows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void core::set_active_vars_weights(nex_creator& nc) {
|
||||
nc.set_number_of_vars(m_lar_solver.column_count());
|
||||
for (lpvar j : active_var_set()) {
|
||||
nc.set_var_weight(j, static_cast<unsigned>(get_var_weight(j)));
|
||||
}
|
||||
}
|
||||
|
||||
var_weight core::get_var_weight(lpvar j) const {
|
||||
var_weight k;
|
||||
switch (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 (is_monic_var(j)) {
|
||||
return (var_weight)((int)k + 1);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
} // end of nla
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "math/lp/horner.h"
|
||||
#include "math/lp/nla_grobner.h"
|
||||
#include "math/lp/nla_intervals.h"
|
||||
#include "math/grobner/pdd_grobner.h"
|
||||
|
||||
|
||||
namespace nla {
|
||||
|
||||
|
@ -91,12 +93,17 @@ public:
|
|||
monotone m_monotone;
|
||||
intervals m_intervals;
|
||||
horner m_horner;
|
||||
nla_settings m_nla_settings;
|
||||
grobner m_grobner;
|
||||
nla_settings m_nla_settings;
|
||||
grobner m_nex_grobner;
|
||||
dd::pdd_manager m_pdd_manager;
|
||||
dd::grobner m_pdd_grobner;
|
||||
|
||||
private:
|
||||
emonics m_emons;
|
||||
svector<lpvar> m_add_buffer;
|
||||
mutable lp::int_set m_active_var_set;
|
||||
lp::int_set m_rows;
|
||||
|
||||
public:
|
||||
reslimit m_reslim;
|
||||
|
||||
|
@ -383,6 +390,15 @@ public:
|
|||
lpvar map_to_root(lpvar) const;
|
||||
std::ostream& print_terms(std::ostream&) const;
|
||||
std::ostream& print_term( const lp::lar_term&, std::ostream&) const;
|
||||
void run_pdd_grobner();
|
||||
void find_nl_cluster(nex_creator&);
|
||||
void prepare_rows_and_active_vars();
|
||||
void add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, svector<lpvar>& q);
|
||||
void init_nex_grobner(nex_creator&);
|
||||
std::unordered_set<lpvar> get_vars_of_expr_with_opening_terms(const nex* e);
|
||||
void display_matrix_of_m_rows(std::ostream & out) const;
|
||||
void set_active_vars_weights(nex_creator&);
|
||||
var_weight get_var_weight(lpvar) const;
|
||||
}; // end of core
|
||||
|
||||
struct pp_mon {
|
||||
|
|
|
@ -36,10 +36,13 @@ grobner::grobner(core *c, intervals *s)
|
|||
|
||||
void grobner::grobner_lemmas() {
|
||||
c().lp_settings().stats().m_grobner_calls++;
|
||||
init();
|
||||
ptr_vector<grobner_core::equation> eqs;
|
||||
m_gc.reset();
|
||||
m_reported = 0;
|
||||
TRACE("grobner", tout << "before:\n"; display(tout););
|
||||
compute_basis();
|
||||
m_gc.compute_basis_loop();
|
||||
for (grobner_core::equation* e : m_gc.equations()) {
|
||||
check_eq(e);
|
||||
}
|
||||
TRACE("grobner", tout << "after:\n"; display(tout););
|
||||
}
|
||||
|
||||
|
@ -51,125 +54,11 @@ void grobner::check_eq(grobner_core::equation* target) {
|
|||
c().print_var(j, tout);
|
||||
}
|
||||
tout << "\ntarget->expr() val = " << get_nex_val(target->expr(), [this](unsigned j) { return c().val(j); }) << "\n";);
|
||||
register_report();
|
||||
m_reported++;
|
||||
}
|
||||
}
|
||||
|
||||
void grobner::register_report() {
|
||||
m_reported++;
|
||||
}
|
||||
|
||||
void grobner::compute_basis(){
|
||||
c().lp_settings().stats().m_grobner_basis_computatins++;
|
||||
if (m_rows.size() < 2) {
|
||||
TRACE("nla_grobner", tout << "there are only " << m_rows.size() << " rows, exiting compute_basis()\n";);
|
||||
return;
|
||||
}
|
||||
m_gc.compute_basis_loop();
|
||||
|
||||
TRACE("grobner", display(tout););
|
||||
for (grobner_core::equation* e : m_gc.equations()) {
|
||||
check_eq(e);
|
||||
}
|
||||
}
|
||||
|
||||
void grobner::add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, svector<lpvar> & q) {
|
||||
if (c().active_var_set_contains(j) || c().var_is_fixed(j)) return;
|
||||
TRACE("grobner", tout << "j = " << j << ", "; c().print_var(j, tout) << "\n";);
|
||||
const auto& matrix = c().m_lar_solver.A_r();
|
||||
c().insert_to_active_var_set(j);
|
||||
for (auto & s : matrix.m_columns[j]) {
|
||||
unsigned row = s.var();
|
||||
if (m_rows.contains(row)) continue;
|
||||
if (matrix.m_rows[row].size() > c().m_nla_settings.grobner_row_length_limit()) {
|
||||
TRACE("grobner", tout << "ignore the row " << row << " with the size " << matrix.m_rows[row].size() << "\n";);
|
||||
continue;
|
||||
}
|
||||
m_rows.insert(row);
|
||||
for (auto& rc : matrix.m_rows[row]) {
|
||||
add_var_and_its_factors_to_q_and_collect_new_rows(rc.var(), q);
|
||||
}
|
||||
}
|
||||
|
||||
if (!c().is_monic_var(j))
|
||||
return;
|
||||
|
||||
const monic& m = c().emons()[j];
|
||||
for (auto fcn : factorization_factory_imp(m, c())) {
|
||||
for (const factor& fc: fcn) {
|
||||
q.push_back(var(fc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void grobner::find_nl_cluster() {
|
||||
prepare_rows_and_active_vars();
|
||||
svector<lpvar> q;
|
||||
for (lpvar j : c().m_to_refine) {
|
||||
TRACE("grobner", c().print_monic(c().emons()[j], tout) << "\n";);
|
||||
q.push_back(j);
|
||||
}
|
||||
|
||||
while (!q.empty()) {
|
||||
lpvar j = q.back();
|
||||
q.pop_back();
|
||||
add_var_and_its_factors_to_q_and_collect_new_rows(j, q);
|
||||
}
|
||||
set_active_vars_weights();
|
||||
TRACE("grobner", display(tout););
|
||||
}
|
||||
|
||||
void grobner::prepare_rows_and_active_vars() {
|
||||
m_rows.clear();
|
||||
m_rows.resize(c().m_lar_solver.row_count());
|
||||
c().clear_and_resize_active_var_set();
|
||||
}
|
||||
|
||||
|
||||
std::unordered_set<lpvar> grobner::get_vars_of_expr_with_opening_terms(const nex *e ) {
|
||||
auto ret = get_vars_of_expr(e);
|
||||
auto & ls = c().m_lar_solver;
|
||||
svector<lpvar> added;
|
||||
for (auto j : ret) {
|
||||
added.push_back(j);
|
||||
}
|
||||
for (unsigned i = 0; i < added.size(); ++i) {
|
||||
lpvar j = added[i];
|
||||
if (ls.column_corresponds_to_term(j)) {
|
||||
const auto& t = c().m_lar_solver.get_term(ls.local_to_external(j));
|
||||
for (auto p : t) {
|
||||
if (ret.find(p.var()) == ret.end()) {
|
||||
added.push_back(p.var());
|
||||
ret.insert(p.var());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void grobner::display_matrix(std::ostream & out) const {
|
||||
const auto& matrix = c().m_lar_solver.A_r();
|
||||
out << m_rows.size() << " rows" <<"\n";
|
||||
out << "the matrix\n";
|
||||
for (const auto & r : matrix.m_rows) {
|
||||
c().print_term(r, out) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void grobner::init() {
|
||||
m_gc.reset();
|
||||
m_reported = 0;
|
||||
find_nl_cluster();
|
||||
c().clear_and_resize_active_var_set();
|
||||
TRACE("grobner", tout << "m_rows.size() = " << m_rows.size() << "\n";);
|
||||
for (unsigned i : m_rows) {
|
||||
add_row(i);
|
||||
}
|
||||
}
|
||||
|
||||
void grobner::add_row(unsigned i) {
|
||||
const auto& row = c().m_lar_solver.A_r().m_rows[i];
|
||||
void grobner::add_row(const vector<lp::row_cell<rational>> & row) {
|
||||
TRACE("grobner", tout << "adding row to gb\n"; c().m_lar_solver.print_row(row, tout) << '\n';
|
||||
for (auto p : row) c().print_var(p.var(), tout) << "\n"; );
|
||||
nex_creator::sum_factory sf(m_nex_creator);
|
||||
|
|
|
@ -205,23 +205,20 @@ private:
|
|||
class grobner : common {
|
||||
grobner_core m_gc;
|
||||
unsigned m_reported;
|
||||
lp::int_set m_rows;
|
||||
public:
|
||||
grobner(core *, intervals *);
|
||||
void grobner_lemmas();
|
||||
~grobner() {}
|
||||
private:
|
||||
void find_nl_cluster();
|
||||
void prepare_rows_and_active_vars();
|
||||
void add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, svector<lpvar>& q);
|
||||
void init();
|
||||
void compute_basis();
|
||||
std::unordered_set<lpvar> get_vars_of_expr_with_opening_terms(const nex* e);
|
||||
void display_matrix(std::ostream & out) const;
|
||||
std::ostream& display(std::ostream& out) const { return m_gc.display(out); }
|
||||
void add_row(unsigned);
|
||||
public:
|
||||
void add_row(const vector<lp::row_cell<rational>> & row);
|
||||
void check_eq(grobner_core::equation*);
|
||||
void register_report();
|
||||
|
||||
nex_creator& get_nex_creator() { return m_nex_creator; }
|
||||
}; // end of grobner
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue