3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-12-20 11:29:08 -08:00
parent 6ad55cc8f6
commit 1f9aff04df
5 changed files with 48 additions and 69 deletions

View file

@ -366,7 +366,7 @@ namespace dd {
// since x is the maximal variable, it does not occur in t or v.
// thus, both a and b are linear in x
bool pdd_manager::spoly_is_invertible(pdd const& a, pdd const& b) {
return a.is_var() && b.is_var() && a.hi().is_val() && b.hi().is_val() && a.var() == b.var();
return !a.is_val() && !b.is_val() && a.hi().is_val() && b.hi().is_val() && a.var() == b.var();
}
/*
@ -617,22 +617,8 @@ namespace dd {
}
unsigned_vector const& pdd_manager::free_vars(pdd const& p) {
return free_vars_except(p, zero());
}
unsigned_vector const& pdd_manager::free_vars_except(pdd const& p, pdd const& q) {
init_mark();
m_free_vars.reset();
m_todo.push_back(q.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);
set_mark(m_var2pdd[var(r)]);
if (!is_marked(lo(r))) m_todo.push_back(lo(r));
if (!is_marked(hi(r))) m_todo.push_back(hi(r));
}
m_todo.push_back(p.root);
while (!m_todo.empty()) {
PDD r = m_todo.back();

View file

@ -246,7 +246,6 @@ namespace dd {
double tree_size(pdd const& p);
unsigned_vector const& free_vars(pdd const& p);
unsigned_vector const& free_vars_except(pdd const& p, pdd const& q);
std::ostream& display(std::ostream& out);
std::ostream& display(std::ostream& out, pdd const& b);
@ -269,7 +268,6 @@ namespace dd {
pdd hi() const { return pdd(m->hi(root), m); }
unsigned var() const { return m->var(root); }
rational const& val() const { SASSERT(is_val()); return m->val(root); }
bool is_var() const { return !m->is_val(root); }
bool is_val() const { return m->is_val(root); }
bool is_zero() const { return m->is_zero(root); }

View file

@ -55,7 +55,7 @@ namespace dd {
For p in A:
populate watch list by maxvar(p) |-> p
For p in S:
populate watch list by vars(p) |-> p
do not occur in watch list
- the variable ordering should be chosen from a candidate model M,
in a way that is compatible with weights that draw on the number of occurrences
@ -69,7 +69,7 @@ namespace dd {
The alternative version maintains the following invariant:
- polynomials not in the watch list cannot be simplified using a
Justification:
- elements in S have all variables watched
- elements in S have no variables watched
- elements in A are always reduced modulo all variables above the current x_i.
Invertible rules:
@ -106,12 +106,7 @@ namespace dd {
bool grobner::step() {
m_stats.m_compute_steps++;
if (is_tuned()) {
return tuned_step();
}
else {
return basic_step();
}
return is_tuned() ? tuned_step() : basic_step();
}
bool grobner::basic_step() {
@ -226,20 +221,6 @@ namespace dd {
if (changed_leading_term) {
target.set_processed(false);
}
if (is_tuned()) {
if (r == t) {
// noop
}
else if (changed_leading_term) {
add_to_watch(target);
}
else if (target.is_processed()) {
add_diff_to_watch(target, t);
}
else {
add_to_watch(target);
}
}
TRACE("grobner", tout << "simplified " << target.poly() << "\n";);
return true;
@ -262,8 +243,9 @@ namespace dd {
equation* e = tuned_pick_next();
if (!e) return false;
equation& eq = *e;
SASSERT(!m_watch[eq.poly().var()].contains(e));
SASSERT(!eq.is_processed());
if (!simplify_watch(eq, true)) return false;
if (!simplify_using(eq, m_processed)) return false;
if (eliminate(eq)) return true;
if (check_conflict(eq)) return false;
if (!simplify_using(m_processed, eq)) return false;
@ -271,8 +253,7 @@ namespace dd {
superpose(eq);
eq.set_processed(true);
m_processed.push_back(e);
add_diff_to_watch(eq, m.zero());
return simplify_watch(eq, false);
return simplify_to_simplify(eq);
}
void grobner::tuned_init() {
@ -292,23 +273,13 @@ namespace dd {
}
}
// add all variables in q but not p into watch.
void grobner::add_diff_to_watch(equation& eq, pdd const& p) {
SASSERT(eq.is_processed());
pdd const& q = eq.poly();
if (is_tuned() && !q.is_val()) {
for (unsigned v : m.free_vars_except(q, p)) {
m_watch[v].push_back(&eq);
}
}
}
bool grobner::simplify_watch(equation const& eq, bool is_processed) {
bool grobner::simplify_to_simplify(equation const& eq) {
unsigned v = m_vars[m_var];
auto& watch = m_watch[v];
unsigned j = 0;
for (equation* _target : watch) {
equation& target = *_target;
if (target.is_processed()) continue;
bool changed_leading_term = false;
bool simplified = !done() && simplify_source_target(eq, target, changed_leading_term);
if (simplified && is_trivial(target)) {
@ -341,6 +312,7 @@ namespace dd {
}
if (eq) {
pop_equation(eq->idx(), m_to_simplify);
m_watch[eq->poly().var()].erase(eq);
return eq;
}
++m_var;
@ -428,16 +400,37 @@ namespace dd {
}
void grobner::invariant() const {
// equations in processed have correct indices
// they are labled as processed
unsigned i = 0;
for (auto* e : m_processed) {
SASSERT(e->is_processed());
SASSERT(e->idx() == i);
VERIFY(e->is_processed());
VERIFY(e->idx() == i);
++i;
}
// equations in to_simplify have correct indices
// they are labeled as non-processed
// their top-most variable is watched
i = 0;
for (auto* e : m_to_simplify) {
SASSERT(!e->is_processed());
SASSERT(e->idx() == i);
VERIFY(!e->is_processed());
VERIFY(e->idx() == i);
if (is_tuned()) {
pdd const& p = e->poly();
VERIFY(p.is_val() || m_watch[p.var()].contains(e));
}
++i;
}
// the watch list consists of equations in to_simplify
// they watch the top most variable in poly
i = 0;
for (auto const& w : m_watch) {
for (equation const* e : w) {
VERIFY(!e->poly().is_val());
VERIFY(e->poly().var() == i);
VERIFY(!e->is_processed());
VERIFY(m_to_simplify.contains(e));
}
++i;
}
}

View file

@ -135,14 +135,11 @@ private:
bool tuned_step();
void tuned_init();
equation* tuned_pick_next();
bool simplify_watch(equation const& eq, bool is_processed);
bool simplify_to_simplify(equation const& eq);
void add_to_watch(equation& eq);
void add_diff_to_watch(equation& eq, pdd const& p);
void del_equation(equation& eq);
void retire(equation* eq) {
if (is_tuned())
for (auto v : m.free_vars(eq->poly())) m_watch[v].erase(eq);
dealloc(eq);
}
void pop_equation(unsigned idx, equation_vector& v);

View file

@ -1080,7 +1080,6 @@ namespace qe {
return true;
}
bool is_unit() const {
return m_children.size() == 1 &&
m_branch_index.empty();
@ -1430,7 +1429,7 @@ namespace qe {
// set sub-formula
m_fml = fml;
normalize(m_fml, m_root.pos_atoms(), m_root.neg_atoms());
expr_ref f(m_fml);
expr_ref f(m_fml);
get_max_relevant(get_is_relevant(), f, m_subfml);
if (f.get() != m_subfml.get()) {
m_fml = f;
@ -1465,6 +1464,11 @@ namespace qe {
if (!is_sat) {
fml = m.mk_false();
if (m_fml.get() != m_subfml.get()) {
scoped_ptr<expr_replacer> rp = mk_default_expr_replacer(m);
rp->apply_substitution(to_app(m_subfml.get()), fml, m_fml);
fml = m_fml;
}
reset();
m_solver.pop(1);
return;
@ -2227,7 +2231,9 @@ namespace qe {
}
void expr_quant_elim::operator()(expr* assumption, expr* fml, expr_ref& result) {
TRACE("qe", tout << "elim input\n" << mk_ismt2_pp(fml, m) << "\n";);
TRACE("qe",
if (assumption) tout << "elim assumption\n" << mk_ismt2_pp(assumption, m) << "\n";
tout << "elim input\n" << mk_ismt2_pp(fml, m) << "\n";);
expr_ref_vector bound(m);
result = fml;
m_assumption = assumption;
@ -2312,14 +2318,13 @@ namespace qe {
case AST_APP: {
app* a = to_app(e);
expr_ref_vector args(m);
unsigned num_args = a->get_num_args();
bool all_visited = true;
for (unsigned i = 0; i < num_args; ++i) {
if (m_visited.find(a->get_arg(i), r)) {
for (expr* arg : *a) {
if (m_visited.find(arg, r)) {
args.push_back(r);
}
else {
todo.push_back(a->get_arg(i));
todo.push_back(arg);
all_visited = false;
}
}