3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-11 19:34:32 +00:00

add option for gcd-test to grobner

This commit is contained in:
Nikolaj Bjorner 2025-09-01 16:37:21 -07:00
parent 49703f8bba
commit e2235d81d3
6 changed files with 224 additions and 32 deletions

View file

@ -1208,6 +1208,35 @@ namespace dd {
return is_binary(p.root);
}
/*
* Retrieve variables that occur as powers.
*/
void pdd_manager::get_powers(pdd const& p, svector<std::pair<unsigned, unsigned>>& powers) {
powers.reset();
init_mark();
m_todo.push_back(p.root);
while (!m_todo.empty()) {
PDD r = m_todo.back();
m_todo.pop_back();
if (is_val(r) || is_marked(r))
continue;
set_mark(r);
unsigned v = var(r);
unsigned d = 1;
while (!is_val(r) && var(hi(r)) == v) {
d++;
m_todo.push_back(lo(r));
r = hi(r);
}
if (d > 1)
powers.push_back({ v, d });
if (!is_val(r)) {
m_todo.push_back(hi(r));
m_todo.push_back(lo(r));
}
}
}
/**
Determine if p is a monomial.
*/
@ -1986,6 +2015,42 @@ namespace dd {
pdd_iterator pdd::begin() const { return pdd_iterator(*this, true); }
pdd_iterator pdd::end() const { return pdd_iterator(*this, false); }
pdd_coeff_iterator pdd::pdd_coeffients::begin() const { return m_pdd.begin_coeff(); }
pdd_coeff_iterator pdd::pdd_coeffients::end() const { return m_pdd.end_coeff(); }
void pdd_coeff_iterator::next() {
auto& m = m_pdd.manager();
while (!m_nodes.empty()) {
auto p = m_nodes.back();
m_nodes.pop_back();
SASSERT(!m.is_val(p));
unsigned n = m.lo(p);
if (m.is_val(n) && m.val(n).is_zero())
continue;
while (!m.is_val(n)) {
m_nodes.push_back(n);
n = m.hi(n);
}
m_value = { m.val(n), m_nodes.empty()};
return;
}
at_end = true;
}
void pdd_coeff_iterator::first() {
unsigned n = m_pdd.root;
auto& m = m_pdd.manager();
while (!m.is_val(n)) {
m_nodes.push_back(n);
n = m.hi(n);
}
at_end = false;
m_value = { m.val(n), m_nodes.empty() };
}
pdd_coeff_iterator pdd::begin_coeff() const { return pdd_coeff_iterator(*this, true); }
pdd_coeff_iterator pdd::end_coeff() const { return pdd_coeff_iterator(*this, false); }
std::ostream& operator<<(std::ostream& out, pdd_monomial const& m) {
if (!m.coeff.is_one()) {
out << m.coeff;

View file

@ -46,6 +46,7 @@ namespace dd {
class pdd_manager;
class pdd_iterator;
class pdd_linear_iterator;
class pdd_coeff_iterator;
class pdd_manager {
public:
@ -55,6 +56,7 @@ namespace dd {
friend pdd;
friend pdd_iterator;
friend pdd_linear_iterator;
friend pdd_coeff_iterator;
typedef unsigned PDD;
typedef vector<std::pair<rational,unsigned_vector>> monomials_t;
@ -366,6 +368,8 @@ namespace dd {
bool is_binary(PDD p);
bool is_binary(pdd const& p);
void get_powers(pdd const& p, svector<std::pair<unsigned, unsigned>>& powers);
bool is_monomial(PDD p);
bool is_univariate(PDD p);
@ -406,6 +410,7 @@ namespace dd {
friend class pdd_manager;
friend class pdd_iterator;
friend class pdd_linear_iterator;
friend class pdd_coeff_iterator;
unsigned root;
pdd_manager* m;
pdd(unsigned root, pdd_manager& pm): root(root), m(&pm) { m->inc_ref(root); }
@ -440,6 +445,7 @@ namespace dd {
bool is_unary() const { return !is_val() && lo().is_zero() && hi().is_val(); }
bool is_offset() const { return !is_val() && lo().is_val() && hi().is_one(); }
bool is_binary() const { return m->is_binary(root); }
void get_powers(svector<std::pair<unsigned, unsigned>>& powers) const { m->get_powers(*this, powers); }
bool is_monomial() const { return m->is_monomial(root); }
bool is_univariate() const { return m->is_univariate(root); }
bool is_univariate_in(unsigned v) const { return m->is_univariate_in(root, v); }
@ -508,6 +514,20 @@ namespace dd {
pdd_iterator begin() const;
pdd_iterator end() const;
pdd_coeff_iterator begin_coeff() const;
pdd_coeff_iterator end_coeff() const;
class pdd_coeffients {
friend class pdd;
pdd const& m_pdd;
pdd_coeffients(pdd const& p) : m_pdd(p) {}
public:
pdd_coeff_iterator begin() const;
pdd_coeff_iterator end() const;
};
pdd_coeffients coefficients() const { return pdd_coeffients(*this); }
class pdd_linear_monomials {
friend class pdd;
pdd const& m_pdd;
@ -593,6 +613,31 @@ namespace dd {
bool operator!=(pdd_linear_iterator const& other) const { return m_next != other.m_next; }
};
// iterator class that visits each coefficient with information
// if it is a constant or is used as a coefficient to a monomial.
struct coeff_value {
rational coeff;
bool is_constant; // true if it is a constant term.
};
class pdd_coeff_iterator {
friend class pdd;
pdd m_pdd;
unsigned_vector m_nodes;
coeff_value m_value;
bool at_end = true;
pdd_coeff_iterator(pdd const& p, bool at_start): m_pdd(p) { if (at_start) first(); }
void first();
void next();
public:
coeff_value operator*() const { return m_value; }
coeff_value const* operator->() const { return &m_value; }
pdd_coeff_iterator& operator++() { next(); return *this; }
pdd_coeff_iterator operator++(int) { auto tmp = *this; next(); return tmp; }
bool operator!=(pdd_coeff_iterator const& other) const { return at_end != other.at_end; }
};
class val_pp {
pdd_manager const& m;
rational const& val;