#pragma once
#include "ast/ast.h"
#include "ast/arith_decl_plugin.h"
#include "util/heap.h"
#include "util/obj_hashtable.h"
#include "util/region.h"
#include "util/dependency.h"
struct grobner_stats {
long m_simplify; long m_superpose; long m_compute_basis; long m_num_processed;
void reset() { memset(this, 0, sizeof(grobner_stats)); }
grobner_stats() { reset(); }
};
class grobner {
protected:
struct monomial_lt;
public:
grobner_stats m_stats;
class monomial {
rational m_coeff;
ptr_vector<expr> m_vars;
friend class grobner;
friend struct monomial_lt;
monomial() = default;
public:
rational const & get_coeff() const { return m_coeff; }
unsigned get_degree() const { return m_vars.size(); }
unsigned get_size() const { return get_degree(); }
expr * get_var(unsigned idx) const { return m_vars[idx]; }
};
class equation {
unsigned m_scope_lvl; unsigned m_bidx:31; unsigned m_lc:1; ptr_vector<monomial> m_monomials; v_dependency * m_dep; friend class grobner;
equation() = default;
public:
unsigned get_num_monomials() const { return m_monomials.size(); }
monomial const * get_monomial(unsigned idx) const { return m_monomials[idx]; }
monomial * const * get_monomials() const { return m_monomials.data(); }
v_dependency * get_dependency() const { return m_dep; }
unsigned hash() const { return m_bidx; }
bool is_linear_combination() const { return m_lc; }
};
protected:
static bool is_eq_monomial_body(monomial const * m1, monomial const * m2);
struct var_lt {
obj_map<expr, int> & m_var2weight;
var_lt(obj_map<expr, int> & m):m_var2weight(m) {}
bool operator()(expr * v1, expr * v2) const;
};
struct monomial_lt {
var_lt & m_var_lt;
monomial_lt(var_lt & lt):m_var_lt(lt) {}
bool operator()(monomial * m1, monomial * m2) const;
};
typedef obj_hashtable<equation> equation_set;
typedef ptr_vector<equation> equation_vector;
ast_manager & m_manager;
v_dependency_manager & m_dep_manager;
arith_util m_util;
obj_map<expr, int> m_var2weight;
var_lt m_var_lt;
monomial_lt m_monomial_lt;
equation_set m_processed;
equation_set m_to_process;
equation_vector m_equations_to_unfreeze;
equation_vector m_equations_to_delete;
bool m_changed_leading_term; equation * m_unsat;
struct scope {
unsigned m_equations_to_unfreeze_lim;
unsigned m_equations_to_delete_lim;
};
svector<scope> m_scopes;
ptr_vector<monomial> m_tmp_monomials;
ptr_vector<monomial> m_del_monomials;
ptr_vector<expr> m_tmp_vars1;
ptr_vector<expr> m_tmp_vars2;
unsigned m_num_new_equations;
bool is_monomial_lt(monomial const & m1, monomial const & m2) const;
void display_vars(std::ostream & out, unsigned num_vars, expr * const * vars) const;
void display_var(std::ostream & out, expr * var) const;
void display_monomials(std::ostream & out, unsigned num_monomials, monomial * const * monomials, std::function<void(std::ostream&, expr*)>& display_var) const;
void display_monomials(std::ostream & out, unsigned num_monomials, monomial * const * monomials) const {
std::function<void(std::ostream& out, expr* v)> _fn = [&](std::ostream& out, expr* v) { display_var(out, v); };
display_monomials(out, num_monomials, monomials, _fn);
}
void display_equations(std::ostream & out, equation_set const & v, char const * header, std::function<void(std::ostream&, expr*)>& display_var) const;
void del_equations(unsigned old_size);
void del_monomials(ptr_vector<monomial>& monomials);
void unfreeze_equations(unsigned old_size);
void del_equation(equation * eq);
void flush();
bool update_order(equation * eq);
void update_order(equation_set & s, bool processed);
void add_var(monomial * m, expr * v);
monomial * mk_monomial(rational const & coeff, expr * m);
void init_equation(equation * eq, v_dependency * d);
void extract_monomials(expr * lhs, ptr_buffer<expr> & monomials);
void merge_monomials(ptr_vector<monomial> & monomials);
bool is_inconsistent(equation * eq) const;
bool is_trivial(equation * eq) const;
void normalize_coeff(ptr_vector<monomial> & monomials);
void simplify(ptr_vector<monomial> & monomials);
void inc(monomial const & m);
void simplify(equation * eq);
bool is_subset(monomial const * m1, monomial const * m2, ptr_vector<expr> & rest) const;
void mul_append(unsigned start_idx, equation const * source, rational const & coeff, ptr_vector<expr> const & vars, ptr_vector<monomial> & result);
monomial * copy_monomial(monomial const * m);
equation * copy_equation(equation const * eq);
equation * simplify(equation const * source, equation * target);
equation * simplify_using_processed(equation * eq);
bool is_better_choice(equation * eq1, equation * eq2);
equation * pick_next();
bool simplify_processed(equation * eq);
void simplify_to_process(equation * eq);
bool unify(monomial const * m1, monomial const * m2, ptr_vector<expr> & rest1, ptr_vector<expr> & rest2);
void superpose(equation * eq1, equation * eq2);
void superpose(equation * eq);
void copy_to(equation_set const & s, ptr_vector<equation> & result) const;
public:
grobner(ast_manager & m, v_dependency_manager & dep_m);
~grobner();
unsigned get_scope_level() const { return m_scopes.size(); }
void set_weight(expr * n, int weight);
int get_weight(expr * n) const { int w = 0; m_var2weight.find(n, w); return w; }
void update_order();
monomial * mk_monomial(rational const & coeff, unsigned num_vars, expr * const * vars);
void del_monomial(monomial * m);
void assert_eq(expr * eq, v_dependency * ex = nullptr);
void assert_eq_0(unsigned num_monomials, expr * const * monomials, v_dependency * ex = nullptr);
void assert_eq_0(unsigned num_monomials, monomial * const * monomials, v_dependency * ex = nullptr);
void assert_eq_0(unsigned num_monomials, rational const * coeffs, expr * const * monomials, v_dependency * ex = nullptr);
void assert_monomial_tautology(expr * m);
bool compute_basis(unsigned threshold);
void compute_basis_init();
bool compute_basis_step();
unsigned get_num_new_equations() { return m_num_new_equations; }
bool inconsistent() const { return m_unsat != nullptr; }
void simplify(expr * n, expr_ref & result);
void reset();
void get_equations(ptr_vector<equation> & result) const;
void push_scope();
void pop_scope(unsigned num_scopes);
void display_equation(std::ostream & out, equation const & eq) const {
std::function<void(std::ostream& out, expr* v)> _fn = [&](std::ostream& out, expr* v) { display_var(out, v); };
display_equation(out, eq, _fn);
}
void display_monomial(std::ostream & out, monomial const & m) const {
std::function<void(std::ostream& out, expr* v)> _fn = [&](std::ostream& out, expr* v) { display_var(out, v); };
display_monomial(out, m, _fn);
}
void display_equation(std::ostream & out, equation const & eq, std::function<void(std::ostream&, expr*)>& display_var) const;
void display_monomial(std::ostream & out, monomial const & m, std::function<void(std::ostream&, expr*)>& display_var) const;
void display(std::ostream & out) const {
std::function<void(std::ostream& out, expr* v)> _fn = [&](std::ostream& out, expr* v) { display_var(out, v); };
display(out, _fn);
}
void display(std::ostream & out, std::function<void(std::ostream&, expr*)>& display_var) const;
};