mirror of
https://github.com/Z3Prover/z3
synced 2025-06-22 05:43:39 +00:00
port Grobner
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
c329263d63
commit
6009b738d6
3 changed files with 64 additions and 36 deletions
|
@ -590,7 +590,7 @@ bool grobner::simplify_target_monomials(equation const * source, equation * targ
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
unsigned new_target_sz = 0;
|
unsigned new_target_sz = 0;
|
||||||
unsigned target_sz = target->m_monomials.size();
|
unsigned target_sz = target->m_monomials.size();
|
||||||
monomial const * LT = source->get_monomial(0);
|
monomial const * LT = source->get_monomial(0);
|
||||||
m_tmp_monomials.reset();
|
m_tmp_monomials.reset();
|
||||||
for (; i < target_sz; i++) {
|
for (; i < target_sz; i++) {
|
||||||
monomial * targ_i = target->m_monomials[i];
|
monomial * targ_i = target->m_monomials[i];
|
||||||
|
@ -889,6 +889,9 @@ bool grobner::compute_basis_step() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
equation * new_eq = simplify_using_processed(eq);
|
equation * new_eq = simplify_using_processed(eq);
|
||||||
|
if (new_eq == nullptr || new_eq->get_num_monomials() == 0) {
|
||||||
|
TRACE("grobner",);
|
||||||
|
}
|
||||||
if (new_eq != nullptr && eq != new_eq) {
|
if (new_eq != nullptr && eq != new_eq) {
|
||||||
// equation was updated using non destructive updates
|
// equation was updated using non destructive updates
|
||||||
m_equations_to_unfreeze.push_back(eq);
|
m_equations_to_unfreeze.push_back(eq);
|
||||||
|
|
|
@ -102,18 +102,20 @@ void nla_grobner::prepare_rows_and_active_vars() {
|
||||||
c().clear_and_resize_active_var_set();
|
c().clear_and_resize_active_var_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nla_grobner::display(std::ostream & out) {
|
void nla_grobner::display_matrix(std::ostream & out) const {
|
||||||
const auto& matrix = c().m_lar_solver.A_r();
|
const auto& matrix = c().m_lar_solver.A_r();
|
||||||
out << "rows = " << m_rows.size() << "\n";
|
out << m_rows.size() << " rows" <<"\n";
|
||||||
for (unsigned k : m_rows) {
|
out << "the matrix\n";
|
||||||
c().print_term(matrix.m_rows[k], out) << "\n";
|
|
||||||
}
|
|
||||||
out << "the matrix =\n";
|
|
||||||
|
|
||||||
for (const auto & r : matrix.m_rows) {
|
for (const auto & r : matrix.m_rows) {
|
||||||
c().print_term(r, out) << std::endl;
|
c().print_term(r, out) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::ostream & nla_grobner::display(std::ostream & out) const {
|
||||||
|
display_equations(out, m_to_superpose, "m_to_superpose:");
|
||||||
|
display_equations(out, m_to_simplify, "m_to_simplify:");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
void nla_grobner::process_var(nex_mul* m, lpvar j, ci_dependency* & dep, rational & coeff) {
|
void nla_grobner::process_var(nex_mul* m, lpvar j, ci_dependency* & dep, rational & coeff) {
|
||||||
if (c().var_is_fixed(j)) {
|
if (c().var_is_fixed(j)) {
|
||||||
|
@ -145,9 +147,10 @@ void nla_grobner::add_row(unsigned i) {
|
||||||
|
|
||||||
svector<lp::constraint_index> fixed_vars_constraints;
|
svector<lp::constraint_index> fixed_vars_constraints;
|
||||||
create_sum_from_row(row, m_nex_creator, *ns, true); // true to treat fixed vars as scalars
|
create_sum_from_row(row, m_nex_creator, *ns, true); // true to treat fixed vars as scalars
|
||||||
TRACE("grobner", tout << "ns = " << *ns << "\n";);
|
nex* e = m_nex_creator.simplify(ns);
|
||||||
|
TRACE("grobner", tout << "e = " << *e << "\n";);
|
||||||
m_tmp_var_set.clear();
|
m_tmp_var_set.clear();
|
||||||
assert_eq_0(ns, get_fixed_vars_dep_from_row(row, m_dep_manager));
|
assert_eq_0(e, get_fixed_vars_dep_from_row(row, m_dep_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
void nla_grobner::simplify_equations_to_process() {
|
void nla_grobner::simplify_equations_to_process() {
|
||||||
|
@ -166,6 +169,7 @@ void nla_grobner::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nla_grobner::is_trivial(equation* eq) const {
|
bool nla_grobner::is_trivial(equation* eq) const {
|
||||||
|
SASSERT(m_nex_creator.is_simplified(eq->exp()));
|
||||||
return eq->exp()->size() == 0;
|
return eq->exp()->size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,18 +219,26 @@ nla_grobner::equation* nla_grobner::simplify_using_processed(equation* eq) {
|
||||||
do {
|
do {
|
||||||
simplified = false;
|
simplified = false;
|
||||||
for (equation * p : m_to_superpose) {
|
for (equation * p : m_to_superpose) {
|
||||||
equation * new_eq = simplify_source_target(p, eq);
|
equation * new_eq = simplify_source_target(p, eq);
|
||||||
if (new_eq) {
|
if (new_eq) {
|
||||||
result = true;
|
result = true;
|
||||||
simplified = true;
|
simplified = true;
|
||||||
eq = new_eq;
|
eq = new_eq;
|
||||||
}
|
}
|
||||||
if (canceled()) {
|
if (canceled()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
if (eq->exp()->is_scalar())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (eq->exp()->is_scalar())
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
while (simplified);
|
while (simplified);
|
||||||
|
if (result && eq->exp()->is_scalar()) {
|
||||||
|
TRACE("grobner",);
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("grobner", tout << "simplification result: "; display_equation(tout, *eq););
|
TRACE("grobner", tout << "simplification result: "; display_equation(tout, *eq););
|
||||||
return result ? eq : nullptr;
|
return result ? eq : nullptr;
|
||||||
|
|
||||||
|
@ -237,8 +249,9 @@ nex_mul* nla_grobner::get_highest_monomial(nex* e) const {
|
||||||
case expr_type::MUL:
|
case expr_type::MUL:
|
||||||
return to_mul(e);
|
return to_mul(e);
|
||||||
case expr_type::SUM:
|
case expr_type::SUM:
|
||||||
return to_mul((*to_sum(e))[0]);
|
return to_mul((*to_sum(e))[0]);
|
||||||
default:
|
default:
|
||||||
|
TRACE("grobner", tout << *e << "\n";);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,11 +284,11 @@ bool nla_grobner::simplify_target_monomials_sum_check_only(nex_sum* targ_sum,
|
||||||
for (auto t : *targ_sum) {
|
for (auto t : *targ_sum) {
|
||||||
if (!t->is_mul()) continue; // what if t->is_var()
|
if (!t->is_mul()) continue; // what if t->is_var()
|
||||||
if (divide_ignore_coeffs_check_only(to_mul(t), high_mon)) {
|
if (divide_ignore_coeffs_check_only(to_mul(t), high_mon)) {
|
||||||
TRACE("grobner", tout << "yes div: " << *targ_sum << " / " << high_mon << "\n";);
|
TRACE("grobner", tout << "yes div: " << *targ_sum << " / " << *high_mon << "\n";);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRACE("grobner", tout << "no div: " << *targ_sum << " / " << high_mon << "\n";);
|
TRACE("grobner", tout << "no div: " << *targ_sum << " / " << *high_mon << "\n";);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,6 +385,9 @@ void nla_grobner::simplify_target_monomials_sum_j(equation * source, equation *t
|
||||||
|
|
||||||
nla_grobner::equation * nla_grobner::simplify_source_target(equation * source, equation * target) {
|
nla_grobner::equation * nla_grobner::simplify_source_target(equation * source, equation * target) {
|
||||||
TRACE("grobner", tout << "simplifying: "; display_equation(tout, *target); tout << "using: "; display_equation(tout, *source););
|
TRACE("grobner", tout << "simplifying: "; display_equation(tout, *target); tout << "using: "; display_equation(tout, *source););
|
||||||
|
if (target->exp()->is_scalar()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
if (source->get_num_monomials() == 0)
|
if (source->get_num_monomials() == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
m_stats.m_simplify++;
|
m_stats.m_simplify++;
|
||||||
|
@ -389,7 +405,8 @@ nla_grobner::equation * nla_grobner::simplify_source_target(equation * source, e
|
||||||
target->dep() = m_dep_manager.mk_join(target->dep(), source->dep());
|
target->dep() = m_dep_manager.mk_join(target->dep(), source->dep());
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
return nullptr;}
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void nla_grobner::process_simplified_target(ptr_buffer<equation>& to_insert, equation* new_target, equation*& target, ptr_buffer<equation>& to_remove) {
|
void nla_grobner::process_simplified_target(ptr_buffer<equation>& to_insert, equation* new_target, equation*& target, ptr_buffer<equation>& to_remove) {
|
||||||
if (new_target != target) {
|
if (new_target != target) {
|
||||||
|
@ -488,6 +505,9 @@ nex * nla_grobner::expr_superpose(nex* e1, nex* e2, nex_mul* ab, nex_mul* ac, ne
|
||||||
add_mul_skip_first(r, beta, e1, c);
|
add_mul_skip_first(r, beta, e1, c);
|
||||||
nex * ret = m_nex_creator.simplify(r);
|
nex * ret = m_nex_creator.simplify(r);
|
||||||
TRACE("grobner", tout << "e1 = " << *e1 << "\ne2 = " << *e2 <<"\nsuperpose = " << *ret << "\n";);
|
TRACE("grobner", tout << "e1 = " << *e1 << "\ne2 = " << *e2 <<"\nsuperpose = " << *ret << "\n";);
|
||||||
|
if (ret->is_scalar()) {
|
||||||
|
TRACE("grobner",);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// let eq1: ab+q=0, and eq2: ac+e=0, then qc - eb = 0
|
// let eq1: ab+q=0, and eq2: ac+e=0, then qc - eb = 0
|
||||||
|
@ -496,7 +516,8 @@ void nla_grobner::superpose(equation * eq1, equation * eq2) {
|
||||||
nex_mul * ab = get_highest_monomial(eq1->exp());
|
nex_mul * ab = get_highest_monomial(eq1->exp());
|
||||||
nex_mul * ac = get_highest_monomial(eq2->exp());
|
nex_mul * ac = get_highest_monomial(eq2->exp());
|
||||||
nex_mul *b, *c;
|
nex_mul *b, *c;
|
||||||
TRACE("grobner", tout << "ab=" << *ab << " , " << " ac = " << *ac << "\n";);
|
TRACE("grobner", tout << "ab="; if(ab) { tout << *ab; } else { tout << "null"; };
|
||||||
|
tout << " , " << " ac="; if(ac) { tout << *ac; } else { tout << "null"; }; tout << "\n";);
|
||||||
if (!find_b_c(ab, ac, b, c)) {
|
if (!find_b_c(ab, ac, b, c)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -549,6 +570,8 @@ bool nla_grobner::find_b_c(nex_mul*ab, nex_mul* ac, nex_mul*& b, nex_mul*& c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nla_grobner::find_b_c_check_only(const nex_mul*ab, const nex_mul* ac) const {
|
bool nla_grobner::find_b_c_check_only(const nex_mul*ab, const nex_mul* ac) const {
|
||||||
|
if (ab == nullptr || ac == nullptr)
|
||||||
|
return false;
|
||||||
SASSERT(m_nex_creator.is_simplified(ab) && m_nex_creator.is_simplified(ab));
|
SASSERT(m_nex_creator.is_simplified(ab) && m_nex_creator.is_simplified(ab));
|
||||||
unsigned i = 0, j = 0; // i points to ab, j points to ac
|
unsigned i = 0, j = 0; // i points to ab, j points to ac
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -591,6 +614,7 @@ bool nla_grobner::compute_basis_step() {
|
||||||
}
|
}
|
||||||
if (canceled()) return false;
|
if (canceled()) return false;
|
||||||
if (!simplify_processed_with_eq(eq)) return false;
|
if (!simplify_processed_with_eq(eq)) return false;
|
||||||
|
TRACE("grobner", tout << "eq = "; display_equation(tout, *eq););
|
||||||
superpose(eq);
|
superpose(eq);
|
||||||
insert_to_superpose(eq);
|
insert_to_superpose(eq);
|
||||||
simplify_to_process(eq);
|
simplify_to_process(eq);
|
||||||
|
@ -645,12 +669,12 @@ bool nla_grobner::find_conflict(ptr_vector<equation>& eqs){
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nla_grobner::is_inconsistent(equation*) {
|
bool nla_grobner::is_inconsistent(equation*) {
|
||||||
NOT_IMPLEMENTED_YET();
|
// NOT_IMPLEMENTED_YET(); todo implement
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nla_grobner::is_inconsistent2(equation*) {
|
bool nla_grobner::is_inconsistent2(equation*) {
|
||||||
NOT_IMPLEMENTED_YET();
|
// NOT_IMPLEMENTED_YET(); todo implement
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,10 +711,10 @@ void nla_grobner::grobner_lemmas() {
|
||||||
unsigned next_weight =
|
unsigned next_weight =
|
||||||
(unsigned)(var_weight::MAX_DEFAULT_WEIGHT) + 1; // next weight using during perturbation phase.
|
(unsigned)(var_weight::MAX_DEFAULT_WEIGHT) + 1; // next weight using during perturbation phase.
|
||||||
do {
|
do {
|
||||||
TRACE("nla_gb", tout << "before:\n"; display(tout););
|
TRACE("grobner", tout << "before:\n"; display(tout););
|
||||||
compute_basis();
|
compute_basis();
|
||||||
update_statistics();
|
update_statistics();
|
||||||
TRACE("nla_gb", tout << "after:\n"; display(tout););
|
TRACE("grobner", tout << "after:\n"; display(tout););
|
||||||
if (find_conflict(eqs))
|
if (find_conflict(eqs))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -711,19 +735,16 @@ void nla_grobner:: del_equations(unsigned old_size) {
|
||||||
|
|
||||||
void nla_grobner::display_equations(std::ostream & out, equation_set const & v, char const * header) const {
|
void nla_grobner::display_equations(std::ostream & out, equation_set const & v, char const * header) const {
|
||||||
out << header << "\n";
|
out << header << "\n";
|
||||||
NOT_IMPLEMENTED_YET();
|
for (const equation* e : v)
|
||||||
|
display_equation(out, *e);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& nla_grobner::display_equation(std::ostream & out, const equation & eq) {
|
std::ostream& nla_grobner::display_equation(std::ostream & out, const equation & eq) const {
|
||||||
out << "m_exp = " << *eq.exp() << "\n";
|
out << "m_exp = " << *eq.exp() << "\n";
|
||||||
out << "dep = "; display_dependency(out, eq.dep()) << "\n";
|
out << "dep = "; display_dependency(out, eq.dep()) << "\n";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nla_grobner::display(std::ostream & out) const {
|
|
||||||
NOT_IMPLEMENTED_YET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void nla_grobner::assert_eq_0(nex* e, ci_dependency * dep) {
|
void nla_grobner::assert_eq_0(nex* e, ci_dependency * dep) {
|
||||||
TRACE("grobner", tout << "e = " << *e << "\n";);
|
TRACE("grobner", tout << "e = " << *e << "\n";);
|
||||||
if (e == nullptr)
|
if (e == nullptr)
|
||||||
|
@ -743,7 +764,7 @@ void nla_grobner::init_equation(equation* eq, nex*e, ci_dependency * dep) {
|
||||||
SASSERT(m_equations_to_delete[eq->m_bidx] == eq);
|
SASSERT(m_equations_to_delete[eq->m_bidx] == eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& nla_grobner::display_dependency(std::ostream& out, ci_dependency* dep) {
|
std::ostream& nla_grobner::display_dependency(std::ostream& out, ci_dependency* dep) const {
|
||||||
svector<lp::constraint_index> expl;
|
svector<lp::constraint_index> expl;
|
||||||
m_dep_manager.linearize(dep, expl);
|
m_dep_manager.linearize(dep, expl);
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,7 +46,7 @@ class nla_grobner : common {
|
||||||
public:
|
public:
|
||||||
unsigned get_num_monomials() const {
|
unsigned get_num_monomials() const {
|
||||||
switch(m_expr->type()) {
|
switch(m_expr->type()) {
|
||||||
case expr_type::VAR:
|
case expr_type::VAR: return 1;
|
||||||
case expr_type::SCALAR: return 0;
|
case expr_type::SCALAR: return 0;
|
||||||
case expr_type::MUL: return 1;
|
case expr_type::MUL: return 1;
|
||||||
case expr_type::SUM: return m_expr->size();
|
case expr_type::SUM: return m_expr->size();
|
||||||
|
@ -91,7 +91,7 @@ class nla_grobner : common {
|
||||||
lp::int_set m_tmp_var_set;
|
lp::int_set m_tmp_var_set;
|
||||||
region m_alloc;
|
region m_alloc;
|
||||||
ci_value_manager m_val_manager;
|
ci_value_manager m_val_manager;
|
||||||
ci_dependency_manager m_dep_manager;
|
mutable ci_dependency_manager m_dep_manager;
|
||||||
nex_lt m_lt;
|
nex_lt m_lt;
|
||||||
bool m_changed_leading_term;
|
bool m_changed_leading_term;
|
||||||
public:
|
public:
|
||||||
|
@ -102,7 +102,6 @@ private:
|
||||||
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);
|
||||||
void display(std::ostream&);
|
|
||||||
void init();
|
void init();
|
||||||
void compute_basis();
|
void compute_basis();
|
||||||
void update_statistics();
|
void update_statistics();
|
||||||
|
@ -131,9 +130,10 @@ bool simplify_processed_with_eq(equation*);
|
||||||
void del_equations(unsigned old_size);
|
void del_equations(unsigned old_size);
|
||||||
void del_equation(equation * eq);
|
void del_equation(equation * eq);
|
||||||
void display_equations(std::ostream & out, equation_set const & v, char const * header) const;
|
void display_equations(std::ostream & out, equation_set const & v, char const * header) const;
|
||||||
std::ostream& display_equation(std::ostream & out, const equation & eq);
|
std::ostream& display_equation(std::ostream & out, const equation & eq) const;
|
||||||
|
|
||||||
void display(std::ostream & out) const;
|
void display_matrix(std::ostream & out) const;
|
||||||
|
std::ostream& 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 try_to_modify_eqs(ptr_vector<equation>& eqs, unsigned& next_weight);
|
||||||
bool internalize_gb_eq(equation*);
|
bool internalize_gb_eq(equation*);
|
||||||
|
@ -143,9 +143,13 @@ bool simplify_processed_with_eq(equation*);
|
||||||
|
|
||||||
void init_equation(equation* eq, nex*, ci_dependency* d);
|
void init_equation(equation* eq, nex*, ci_dependency* d);
|
||||||
|
|
||||||
std::ostream& display_dependency(std::ostream& out, ci_dependency*);
|
std::ostream& display_dependency(std::ostream& out, ci_dependency*) const;
|
||||||
void insert_to_simplify(equation *eq) { m_to_simplify.insert(eq); }
|
void insert_to_simplify(equation *eq) {
|
||||||
void insert_to_superpose(equation *eq) { m_to_superpose.insert(eq); }
|
m_to_simplify.insert(eq);
|
||||||
|
}
|
||||||
|
void insert_to_superpose(equation *eq) {
|
||||||
|
m_to_superpose.insert(eq);
|
||||||
|
}
|
||||||
void simplify_equations_to_process();
|
void simplify_equations_to_process();
|
||||||
nex_mul * get_highest_monomial(nex * e) const;
|
nex_mul * get_highest_monomial(nex * e) const;
|
||||||
ci_dependency* dep_from_vector( svector<lp::constraint_index> & fixed_vars_constraints);
|
ci_dependency* dep_from_vector( svector<lp::constraint_index> & fixed_vars_constraints);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue