mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 03:45:51 +00:00
Tune Grobner equations
\brief convert p == 0 into a solved form v == r, such that v has bounds [lo, oo) iff r has bounds [lo', oo) v has bounds (oo,hi] iff r has bounds (oo,hi'] The solved form allows the Grobner solver identify more bounds conflicts. A bad leading term can miss bounds conflicts. For example for x + y + z == 0 where x, y : [0, oo) and z : (oo,0] we prefer to solve z == -x - y instead of x == -z - y because the solution -z - y has neither an upper, nor a lower bound. The Grobner solver is augmented with a notion of a substitution that is applied before the solver is run.
This commit is contained in:
parent
f33c933241
commit
316ed778e0
5 changed files with 127 additions and 13 deletions
|
@ -342,6 +342,7 @@ namespace dd {
|
|||
for (equation* e : m_solved) dealloc(e);
|
||||
for (equation* e : m_to_simplify) dealloc(e);
|
||||
for (equation* e : m_processed) dealloc(e);
|
||||
m_subst.reset();
|
||||
m_solved.reset();
|
||||
m_processed.reset();
|
||||
m_to_simplify.reset();
|
||||
|
@ -354,16 +355,39 @@ namespace dd {
|
|||
void solver::add(pdd const& p, u_dependency * dep) {
|
||||
if (p.is_zero()) return;
|
||||
equation * eq = alloc(equation, p, dep);
|
||||
if (check_conflict(*eq)) {
|
||||
if (check_conflict(*eq))
|
||||
return;
|
||||
}
|
||||
push_equation(to_simplify, eq);
|
||||
|
||||
if (!m_var2level.empty()) {
|
||||
if (!m_var2level.empty())
|
||||
m_levelp1 = std::max(m_var2level[p.var()]+1, m_levelp1);
|
||||
}
|
||||
update_stats_max_degree_and_size(*eq);
|
||||
}
|
||||
}
|
||||
|
||||
void solver::add_subst(unsigned v, pdd const& p, u_dependency* dep) {
|
||||
SASSERT(m_processed.empty());
|
||||
SASSERT(m_solved.empty());
|
||||
|
||||
m_subst.push_back({v, p, dep});
|
||||
|
||||
for (auto* e : m_to_simplify) {
|
||||
auto r = e->poly().subst_pdd(v, p);
|
||||
if (r == e->poly())
|
||||
continue;
|
||||
*e = m_dep_manager.mk_join(dep, e->dep());
|
||||
*e = r;
|
||||
}
|
||||
}
|
||||
|
||||
void solver::simplify(pdd& p, u_dependency*& d) {
|
||||
for (auto const& [v, q, d2] : m_subst) {
|
||||
pdd r = p.subst_pdd(v, q);
|
||||
if (r != p) {
|
||||
p = r;
|
||||
d = m_dep_manager.mk_join(d, d2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool solver::canceled() {
|
||||
return m_limit.is_canceled();
|
||||
|
@ -446,9 +470,24 @@ namespace dd {
|
|||
}
|
||||
|
||||
std::ostream& solver::display(std::ostream& out) const {
|
||||
out << "solved\n"; for (auto e : m_solved) display(out, *e);
|
||||
out << "processed\n"; for (auto e : m_processed) display(out, *e);
|
||||
out << "to_simplify\n"; for (auto e : m_to_simplify) display(out, *e);
|
||||
if (!m_solved.empty()) {
|
||||
out << "solved\n"; for (auto e : m_solved) display(out, *e);
|
||||
}
|
||||
if (!m_processed.empty()) {
|
||||
out << "processed\n"; for (auto e : m_processed) display(out, *e);
|
||||
}
|
||||
if (!m_to_simplify.empty()) {
|
||||
out << "to_simplify\n"; for (auto e : m_to_simplify) display(out, *e);
|
||||
}
|
||||
if (!m_subst.empty()) {
|
||||
out << "subst\n";
|
||||
for (auto const& [v, p, d] : m_subst) {
|
||||
out << "v" << v << " := " << p;
|
||||
if (m_print_dep)
|
||||
m_print_dep(d, out);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
return display_statistics(out);
|
||||
}
|
||||
|
||||
|
|
|
@ -118,6 +118,7 @@ private:
|
|||
equation_vector m_solved; // equations with solved variables, triangular
|
||||
equation_vector m_processed;
|
||||
equation_vector m_to_simplify;
|
||||
vector<std::tuple<unsigned, pdd, u_dependency*>> m_subst;
|
||||
mutable u_dependency_manager m_dep_manager;
|
||||
equation_vector m_all_eqs;
|
||||
equation* m_conflict;
|
||||
|
@ -136,6 +137,9 @@ public:
|
|||
void add(pdd const& p) { add(p, nullptr); }
|
||||
void add(pdd const& p, u_dependency * dep);
|
||||
|
||||
void simplify(pdd& p, u_dependency*& dep);
|
||||
void add_subst(unsigned v, pdd const& p, u_dependency* dep);
|
||||
|
||||
void simplify();
|
||||
void saturate();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue