3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-22 05:43:39 +00:00

port grobner basis functionality

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2019-09-18 11:53:17 -07:00
parent 29cc2c5976
commit e8b6b870ac
4 changed files with 81 additions and 34 deletions

View file

@ -21,7 +21,27 @@
#include "math/lp/nla_core.h" #include "math/lp/nla_core.h"
#include "math/lp/factorization_factory_imp.h" #include "math/lp/factorization_factory_imp.h"
namespace nla { namespace nla {
nla_grobner::nla_grobner(core *c) : common(c) {} nla_grobner::nla_grobner(core *c) : common(c), m_nl_gb_exhausted(false) {}
// Scan the grobner basis eqs for equations of the form x - k = 0 or x = 0 is found, and x is not fixed,
// then assert bounds for x, and continue
bool nla_grobner::scan_for_linear(ptr_vector<equation>& eqs) {
bool result = false;
for (nla_grobner::equation* eq : eqs) {
if (!eq->is_linear_combination()) {
TRACE("non_linear", tout << "processing new equality:\n"; display_equation(tout, *eq););
TRACE("non_linear_bug", tout << "processing new equality:\n"; display_equation(tout, *eq););
if (internalize_gb_eq(eq))
result = true;
}
}
return result;
}
bool nla_grobner::internalize_gb_eq(equation* ) {
NOT_IMPLEMENTED_YET();
return false;
}
void nla_grobner::add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, std::queue<lpvar> & q) { void nla_grobner::add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, std::queue<lpvar> & q) {
SASSERT(m_active_vars.contains(j) == false); SASSERT(m_active_vars.contains(j) == false);
@ -122,9 +142,20 @@ void nla_grobner::display(std::ostream & out) {
c().print_term(r, out) << std::endl; c().print_term(r, out) << std::endl;
} }
} }
void nla_grobner::add_row_to_gb(unsigned) {
NOT_IMPLEMENTED_YET();
}
void nla_grobner::add_monomial_def(lpvar) {
NOT_IMPLEMENTED_YET();
}
void nla_grobner::init() { void nla_grobner::init() {
find_nl_cluster(); find_nl_cluster();
for (unsigned i : m_rows) {
add_row_to_gb(i);
}
for (lpvar j : m_active_vars) {
add_monomial_def(j);
}
} }
bool nla_grobner::is_trivial(equation* eq) const { bool nla_grobner::is_trivial(equation* eq) const {
@ -158,7 +189,7 @@ void nla_grobner::del_equation(equation * eq) {
*/ */
} }
equation* nla_grobner::pick_next() { nla_grobner::equation* nla_grobner::pick_next() {
equation * r = nullptr; equation * r = nullptr;
ptr_buffer<equation> to_delete; ptr_buffer<equation> to_delete;
for (equation * curr : m_to_process) { for (equation * curr : m_to_process) {
@ -175,18 +206,18 @@ equation* nla_grobner::pick_next() {
return r; return r;
} }
equation* nla_grobner::simplify_using_processed(equation* eq) { nla_grobner::equation* nla_grobner::simplify_using_processed(equation* eq) {
SASSERT(false); NOT_IMPLEMENTED_YET();
return nullptr; return nullptr;
} }
equation* nla_grobner::simplify_processed(equation* eq) { nla_grobner::equation* nla_grobner::simplify_processed(equation* eq) {
SASSERT(false); NOT_IMPLEMENTED_YET();
return nullptr; return nullptr;
} }
equation* nla_grobner::simplify_to_process(equation*) { nla_grobner::equation* nla_grobner::simplify_to_process(equation*) {
SASSERT(false); NOT_IMPLEMENTED_YET();
return nullptr; return nullptr;
} }
@ -241,7 +272,7 @@ bool nla_grobner::compute_basis_loop(){
} }
void nla_grobner::set_gb_exhausted(){ void nla_grobner::set_gb_exhausted(){
NOT_IMPLEMENTED_YET(); m_nl_gb_exhausted = true;
} }
void nla_grobner::update_statistics(){ void nla_grobner::update_statistics(){
@ -288,17 +319,26 @@ void nla_grobner::get_equations(ptr_vector<equation>& result) {
} }
bool nla_grobner::push_calculation_forward(){ bool nla_grobner::push_calculation_forward(ptr_vector<equation>& eqs, unsigned & next_weight) {
return scan_for_linear(eqs)
&&
(!m_nl_gb_exhausted) &&
try_to_modify_eqs(eqs, next_weight);
}
bool nla_grobner::try_to_modify_eqs(ptr_vector<equation>& eqs, unsigned& next_weight) {
NOT_IMPLEMENTED_YET(); NOT_IMPLEMENTED_YET();
return false; return false;
} }
void nla_grobner::grobner_lemmas() { void nla_grobner::grobner_lemmas() {
c().lp_settings().stats().m_grobner_calls++; c().lp_settings().stats().m_grobner_calls++;
init(); init();
ptr_vector<equation> eqs; ptr_vector<equation> eqs;
unsigned next_weight =
(unsigned)(var_weight::MAX_DEFAULT_WEIGHT) + 1; // next weight using during perturbation phase.
do { do {
TRACE("nla_gb", tout << "before:\n"; display(tout);); TRACE("nla_gb", tout << "before:\n"; display(tout););
compute_basis(); compute_basis();
@ -307,7 +347,7 @@ void nla_grobner::grobner_lemmas() {
if (find_conflict(eqs)) if (find_conflict(eqs))
return; return;
} }
while(push_calculation_forward()); while(push_calculation_forward(eqs, next_weight));
} }
void nla_grobner:: del_equations(unsigned old_size) { void nla_grobner:: del_equations(unsigned old_size) {
SASSERT(m_equations_to_delete.size() >= old_size); SASSERT(m_equations_to_delete.size() >= old_size);

View file

@ -50,6 +50,20 @@ public:
lpvar get_var(unsigned idx) const { return m_vars[idx]; } lpvar get_var(unsigned idx) const { return m_vars[idx]; }
}; };
enum class var_weight {
FIXED = 0,
QUOTED_FIXED = 1,
BOUNDED = 2,
QUOTED_BOUNDED = 3,
NOT_FREE = 4,
QUOTED_NOT_FREE = 5,
FREE = 6,
QUOTED_FREE = 7,
MAX_DEFAULT_WEIGHT = 7
};
class nla_grobner : common {
class equation { class equation {
unsigned m_scope_lvl; //!< scope level when this equation was created. unsigned m_scope_lvl; //!< scope level when this equation was created.
unsigned m_bidx:31; //!< position at m_equations_to_delete unsigned m_bidx:31; //!< position at m_equations_to_delete
@ -67,19 +81,6 @@ public:
bool is_linear_combination() const { return m_lc; } bool is_linear_combination() const { return m_lc; }
}; };
enum class var_weight {
FIXED = 0,
QUOTED_FIXED = 1,
BOUNDED = 2,
QUOTED_BOUNDED = 3,
NOT_FREE = 4,
QUOTED_NOT_FREE = 5,
FREE = 6,
QUOTED_FREE = 7,
MAX_DEFAULT_WEIGHT = 7
};
class nla_grobner : common {
typedef obj_hashtable<equation> equation_set; typedef obj_hashtable<equation> equation_set;
typedef ptr_vector<equation> equation_vector; typedef ptr_vector<equation> equation_vector;
@ -93,10 +94,12 @@ class nla_grobner : common {
grobner_stats m_stats; grobner_stats m_stats;
equation_set m_processed; equation_set m_processed;
equation_set m_to_process; equation_set m_to_process;
bool m_nl_gb_exhausted;
public: public:
nla_grobner(core *core); nla_grobner(core *core);
void grobner_lemmas(); void grobner_lemmas();
private: private:
bool scan_for_linear(ptr_vector<equation>& eqs);
void find_nl_cluster(); void find_nl_cluster();
void prepare_rows_and_active_vars(); void prepare_rows_and_active_vars();
void add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, std::queue<lpvar>& q); void add_var_and_its_factors_to_q_and_collect_new_rows(lpvar j, std::queue<lpvar>& q);
@ -109,7 +112,7 @@ private:
bool find_conflict(ptr_vector<equation>& eqs); bool find_conflict(ptr_vector<equation>& eqs);
bool is_inconsistent(equation*); bool is_inconsistent(equation*);
bool is_inconsistent2(equation*); bool is_inconsistent2(equation*);
bool push_calculation_forward(); bool push_calculation_forward(ptr_vector<equation>& eqs, unsigned&);
void compute_basis_init(); void compute_basis_init();
bool compute_basis_loop(); bool compute_basis_loop();
bool compute_basis_step(); bool compute_basis_step();
@ -132,5 +135,9 @@ private:
void display(std::ostream & out) const; void display(std::ostream & out) const;
void get_equations(ptr_vector<equation>& eqs); void get_equations(ptr_vector<equation>& eqs);
bool try_to_modify_eqs(ptr_vector<equation>& eqs, unsigned& next_weight);
bool internalize_gb_eq(equation*);
void add_row_to_gb(unsigned);
void add_monomial_def(lpvar);
}; // end of grobner }; // end of grobner
} }

View file

@ -1043,7 +1043,7 @@ namespace smt {
void compute_basis(grobner&, bool&); void compute_basis(grobner&, bool&);
void update_statistics(grobner&); void update_statistics(grobner&);
void set_gb_exhausted(); void set_gb_exhausted();
bool pass_over_gb_eqs_for_conflict(ptr_vector<grobner::equation>& eqs, grobner&); bool get_gb_eqs_and_look_for_conflict(ptr_vector<grobner::equation>& eqs, grobner&);
bool scan_for_linear(ptr_vector<grobner::equation>& eqs, grobner&); bool scan_for_linear(ptr_vector<grobner::equation>& eqs, grobner&);
bool try_to_modify_eqs(ptr_vector<grobner::equation>& eqs, grobner&, unsigned &); bool try_to_modify_eqs(ptr_vector<grobner::equation>& eqs, grobner&, unsigned &);
bool max_min_nl_vars(); bool max_min_nl_vars();

View file

@ -2241,7 +2241,7 @@ void theory_arith<Ext>::set_gb_exhausted() {
// Scan the grobner basis eqs, and look for inconsistencies. // Scan the grobner basis eqs, and look for inconsistencies.
template<typename Ext> template<typename Ext>
bool theory_arith<Ext>::pass_over_gb_eqs_for_conflict(ptr_vector<grobner::equation>& eqs, grobner& gb) { bool theory_arith<Ext>::get_gb_eqs_and_look_for_conflict(ptr_vector<grobner::equation>& eqs, grobner& gb) {
eqs.reset(); eqs.reset();
gb.get_equations(eqs); gb.get_equations(eqs);
TRACE("grobner_bug", tout << "after gb\n";); TRACE("grobner_bug", tout << "after gb\n";);
@ -2346,7 +2346,7 @@ typename theory_arith<Ext>::gb_result theory_arith<Ext>::compute_grobner(svector
TRACE("non_linear_gb", tout << "after:\n"; gb.display(tout);); TRACE("non_linear_gb", tout << "after:\n"; gb.display(tout););
if (get_context().get_cancel_flag()) if (get_context().get_cancel_flag())
return GB_FAIL; return GB_FAIL;
if (pass_over_gb_eqs_for_conflict(eqs, gb)) if (get_gb_eqs_and_look_for_conflict(eqs, gb))
return GB_PROGRESS; return GB_PROGRESS;
} }
while(scan_for_linear(eqs, gb) && m_params.m_nl_arith_gb_perturbate && while(scan_for_linear(eqs, gb) && m_params.m_nl_arith_gb_perturbate &&