mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 12:08:18 +00:00
consolidate freeze functionality into dependent_expr_state
rename size() to qtail() and introduce shortcuts ensure tactic goals are not updated if they are in inconsistent state (because indices could be invalidated)
This commit is contained in:
parent
73a652cf4b
commit
bec3acd146
|
@ -3,6 +3,7 @@ z3_add_component(simplifiers
|
||||||
bit_blaster.cpp
|
bit_blaster.cpp
|
||||||
bv_slice.cpp
|
bv_slice.cpp
|
||||||
card2bv.cpp
|
card2bv.cpp
|
||||||
|
dependent_expr_state.cpp
|
||||||
elim_unconstrained.cpp
|
elim_unconstrained.cpp
|
||||||
eliminate_predicates.cpp
|
eliminate_predicates.cpp
|
||||||
euf_completion.cpp
|
euf_completion.cpp
|
||||||
|
|
|
@ -37,7 +37,7 @@ void bit_blaster::reduce() {
|
||||||
expr_ref new_curr(m);
|
expr_ref new_curr(m);
|
||||||
proof_ref new_pr(m);
|
proof_ref new_pr(m);
|
||||||
bool change = false;
|
bool change = false;
|
||||||
for (unsigned idx = m_fmls.qhead(); idx < m_fmls.size(); idx++) {
|
for (unsigned idx = qhead(); idx < qtail(); idx++) {
|
||||||
if (m_fmls.inconsistent())
|
if (m_fmls.inconsistent())
|
||||||
break;
|
break;
|
||||||
auto [curr, d] = m_fmls[idx]();
|
auto [curr, d] = m_fmls[idx]();
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace bv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void slice::process_eqs() {
|
void slice::process_eqs() {
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size(); ++i) {
|
for (unsigned i = qhead(); i < qtail(); ++i) {
|
||||||
auto const [f, d] = m_fmls[i]();
|
auto const [f, d] = m_fmls[i]();
|
||||||
process_eq(f);
|
process_eq(f);
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ namespace bv {
|
||||||
expr_ref_vector cache(m), pin(m);
|
expr_ref_vector cache(m), pin(m);
|
||||||
ptr_vector<expr> todo, args;
|
ptr_vector<expr> todo, args;
|
||||||
expr* c;
|
expr* c;
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size(); ++i) {
|
for (unsigned i = qhead(); i < qtail(); ++i) {
|
||||||
auto const [f, d] = m_fmls[i]();
|
auto const [f, d] = m_fmls[i]();
|
||||||
todo.push_back(f);
|
todo.push_back(f);
|
||||||
pin.push_back(f);
|
pin.push_back(f);
|
||||||
|
|
|
@ -29,7 +29,7 @@ void card2bv::reduce() {
|
||||||
|
|
||||||
expr_ref new_f1(m), new_f2(m);
|
expr_ref new_f1(m), new_f2(m);
|
||||||
proof_ref new_pr(m);
|
proof_ref new_pr(m);
|
||||||
for (unsigned idx = m_fmls.qhead(); !m_fmls.inconsistent() && idx < m_fmls.size(); idx++) {
|
for (unsigned idx = qhead(); !m_fmls.inconsistent() && idx < qtail(); idx++) {
|
||||||
auto [f, d] = m_fmls[idx]();
|
auto [f, d] = m_fmls[idx]();
|
||||||
rw1(f, new_f1);
|
rw1(f, new_f1);
|
||||||
rw2(false, new_f1, new_f2, new_pr);
|
rw2(false, new_f1, new_f2, new_pr);
|
||||||
|
|
109
src/ast/simplifiers/dependent_expr_state.cpp
Normal file
109
src/ast/simplifiers/dependent_expr_state.cpp
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2022 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
dependent_expr_state.cpp
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Nikolaj Bjorner (nbjorner) 2022-11-2.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "ast/simplifiers/dependent_expr_state.h"
|
||||||
|
#include "ast/recfun_decl_plugin.h"
|
||||||
|
#include "ast/for_each_ast.h"
|
||||||
|
|
||||||
|
unsigned dependent_expr_state::num_exprs() {
|
||||||
|
expr_fast_mark1 visited;
|
||||||
|
unsigned r = 0;
|
||||||
|
for (unsigned i = 0; i < qtail(); i++)
|
||||||
|
r += get_num_exprs((*this)[i].fml(), visited);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dependent_expr_state::freeze(func_decl* f) {
|
||||||
|
if (m_frozen.is_marked(f))
|
||||||
|
return;
|
||||||
|
m_frozen_trail.push_back(f);
|
||||||
|
m_frozen.mark(f, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dependent_expr_state::freeze(expr* term) {
|
||||||
|
if (is_app(term))
|
||||||
|
freeze(to_app(term)->get_decl());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Freeze functions appearing as sub-expressions of 'e'.
|
||||||
|
* The only_as_array flag indicates whether to only freeze occurrences of as-array
|
||||||
|
* from elimination.
|
||||||
|
*/
|
||||||
|
void dependent_expr_state::freeze_terms(expr* e, bool only_as_array, ast_mark& visited) {
|
||||||
|
auto& m = m_frozen_trail.get_manager();
|
||||||
|
struct proc {
|
||||||
|
bool only_as_array;
|
||||||
|
array_util a;
|
||||||
|
dependent_expr_state& st;
|
||||||
|
proc(ast_manager& m, bool o, dependent_expr_state& d) :
|
||||||
|
only_as_array(o), a(m), st(d) {}
|
||||||
|
void operator()(func_decl* f) {
|
||||||
|
if (!only_as_array)
|
||||||
|
st.freeze(f);
|
||||||
|
if (a.is_as_array(f, f) && is_uninterp(f))
|
||||||
|
st.freeze(f);
|
||||||
|
}
|
||||||
|
void operator()(ast* s) {}
|
||||||
|
};
|
||||||
|
proc proc(m, only_as_array, *this);
|
||||||
|
for_each_ast(proc, visited, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Freeze all functions used in recursive definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dependent_expr_state::freeze_recfun() {
|
||||||
|
if (m_recfun_frozen)
|
||||||
|
return;
|
||||||
|
m_recfun_frozen = true;
|
||||||
|
auto& m = m_frozen_trail.get_manager();
|
||||||
|
recfun::util rec(m);
|
||||||
|
ast_mark visited;
|
||||||
|
for (func_decl* f : rec.get_rec_funs())
|
||||||
|
freeze_terms(rec.get_def(f).get_rhs(), false, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current qhead is to be updated to qtail.
|
||||||
|
* Before this update, freeze all functions appearing in formulas.
|
||||||
|
*/
|
||||||
|
void dependent_expr_state::freeze_prefix() {
|
||||||
|
ast_mark visited;
|
||||||
|
for (unsigned i = qhead(); i < qtail(); ++i)
|
||||||
|
freeze_terms((*this)[i].fml(), false, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Freeze functions in the unprocessed suffix that appear in dependencies and in as-array.
|
||||||
|
*/
|
||||||
|
void dependent_expr_state::freeze_suffix() {
|
||||||
|
if (m_suffix_frozen)
|
||||||
|
return;
|
||||||
|
m_suffix_frozen = true;
|
||||||
|
auto& m = m_frozen_trail.get_manager();
|
||||||
|
freeze_recfun();
|
||||||
|
ast_mark visited;
|
||||||
|
ptr_vector<expr> es;
|
||||||
|
for (unsigned i = qhead(); i < qtail(); ++i) {
|
||||||
|
auto d = (*this)[i];
|
||||||
|
if (d.dep()) {
|
||||||
|
es.reset();
|
||||||
|
m.linearize(d.dep(), es);
|
||||||
|
for (expr* e : es)
|
||||||
|
freeze_terms(e, false, visited);
|
||||||
|
}
|
||||||
|
freeze_terms(d.fml(), true, visited);
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,27 +42,54 @@ Author:
|
||||||
*/
|
*/
|
||||||
class dependent_expr_state {
|
class dependent_expr_state {
|
||||||
unsigned m_qhead = 0;
|
unsigned m_qhead = 0;
|
||||||
|
bool m_suffix_frozen = false;
|
||||||
|
bool m_recfun_frozen = false;
|
||||||
|
ast_mark m_frozen;
|
||||||
|
func_decl_ref_vector m_frozen_trail;
|
||||||
|
void freeze_prefix();
|
||||||
|
void freeze_recfun();
|
||||||
|
void freeze_terms(expr* term, bool only_as_array, ast_mark& visited);
|
||||||
|
void freeze(expr* term);
|
||||||
|
void freeze(func_decl* f);
|
||||||
|
struct thaw : public trail {
|
||||||
|
unsigned sz;
|
||||||
|
dependent_expr_state& st;
|
||||||
|
thaw(dependent_expr_state& st) : sz(st.m_frozen_trail.size()), st(st) {}
|
||||||
|
void undo() override {
|
||||||
|
for (unsigned i = st.m_frozen_trail.size(); i-- > sz; )
|
||||||
|
st.m_frozen.mark(st.m_frozen_trail.get(i), false);
|
||||||
|
st.m_frozen_trail.shrink(sz);
|
||||||
|
}
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
|
dependent_expr_state(ast_manager& m) : m_frozen_trail(m) {}
|
||||||
virtual ~dependent_expr_state() {}
|
virtual ~dependent_expr_state() {}
|
||||||
virtual unsigned size() const = 0;
|
unsigned qhead() const { return m_qhead; }
|
||||||
|
virtual unsigned qtail() const = 0;
|
||||||
virtual dependent_expr const& operator[](unsigned i) = 0;
|
virtual dependent_expr const& operator[](unsigned i) = 0;
|
||||||
virtual void update(unsigned i, dependent_expr const& j) = 0;
|
virtual void update(unsigned i, dependent_expr const& j) = 0;
|
||||||
virtual void add(dependent_expr const& j) = 0;
|
virtual void add(dependent_expr const& j) = 0;
|
||||||
virtual bool inconsistent() = 0;
|
virtual bool inconsistent() = 0;
|
||||||
virtual model_reconstruction_trail& model_trail() = 0;
|
virtual model_reconstruction_trail& model_trail() = 0;
|
||||||
|
virtual void flatten_suffix() {}
|
||||||
|
|
||||||
trail_stack m_trail;
|
trail_stack m_trail;
|
||||||
void push() { m_trail.push_scope(); }
|
void push() {
|
||||||
void pop(unsigned n) { m_trail.pop_scope(n); }
|
m_trail.push_scope();
|
||||||
unsigned qhead() const { return m_qhead; }
|
m_trail.push(value_trail(m_qhead));
|
||||||
void advance_qhead() { if (m_trail.get_num_scopes() > 0) m_trail.push(value_trail(m_qhead)); m_qhead = size(); }
|
m_trail.push(thaw(*this));
|
||||||
unsigned num_exprs() {
|
|
||||||
expr_fast_mark1 visited;
|
|
||||||
unsigned r = 0;
|
|
||||||
for (unsigned i = 0; i < size(); i++)
|
|
||||||
r += get_num_exprs((*this)[i].fml(), visited);
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
void pop(unsigned n) { m_trail.pop_scope(n); }
|
||||||
|
|
||||||
|
void advance_qhead() { freeze_prefix(); m_suffix_frozen = false; m_qhead = qtail(); }
|
||||||
|
unsigned num_exprs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Freeze internal functions
|
||||||
|
*/
|
||||||
|
bool frozen(func_decl* f) const { return m_frozen.is_marked(f); }
|
||||||
|
bool frozen(expr* f) const { return is_app(f) && m_frozen.is_marked(to_app(f)->get_decl()); }
|
||||||
|
void freeze_suffix();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,6 +103,9 @@ protected:
|
||||||
|
|
||||||
unsigned num_scopes() const { return m_trail.get_num_scopes(); }
|
unsigned num_scopes() const { return m_trail.get_num_scopes(); }
|
||||||
|
|
||||||
|
unsigned qhead() const { return m_fmls.qhead(); }
|
||||||
|
unsigned qtail() const { return m_fmls.qtail(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
dependent_expr_simplifier(ast_manager& m, dependent_expr_state& s) : m(m), m_fmls(s), m_trail(s.m_trail) {}
|
dependent_expr_simplifier(ast_manager& m, dependent_expr_state& s) : m(m), m_fmls(s), m_trail(s.m_trail) {}
|
||||||
virtual ~dependent_expr_simplifier() {}
|
virtual ~dependent_expr_simplifier() {}
|
||||||
|
|
|
@ -48,7 +48,7 @@ Author:
|
||||||
elim_unconstrained::elim_unconstrained(ast_manager& m, dependent_expr_state& fmls) :
|
elim_unconstrained::elim_unconstrained(ast_manager& m, dependent_expr_state& fmls) :
|
||||||
dependent_expr_simplifier(m, fmls), m_inverter(m), m_lt(*this), m_heap(1024, m_lt), m_trail(m) {
|
dependent_expr_simplifier(m, fmls), m_inverter(m), m_lt(*this), m_heap(1024, m_lt), m_trail(m) {
|
||||||
std::function<bool(expr*)> is_var = [&](expr* e) {
|
std::function<bool(expr*)> is_var = [&](expr* e) {
|
||||||
return is_uninterp_const(e) && !m_frozen.is_marked(e) && get_node(e).m_refcount <= 1;
|
return is_uninterp_const(e) && !m_fmls.frozen(e) && get_node(e).m_refcount <= 1;
|
||||||
};
|
};
|
||||||
m_inverter.set_is_var(is_var);
|
m_inverter.set_is_var(is_var);
|
||||||
}
|
}
|
||||||
|
@ -121,12 +121,14 @@ expr* elim_unconstrained::get_parent(unsigned n) const {
|
||||||
* initialize node structure
|
* initialize node structure
|
||||||
*/
|
*/
|
||||||
void elim_unconstrained::init_nodes() {
|
void elim_unconstrained::init_nodes() {
|
||||||
|
|
||||||
|
m_fmls.freeze_suffix();
|
||||||
|
|
||||||
expr_ref_vector terms(m);
|
expr_ref_vector terms(m);
|
||||||
for (unsigned i = 0; i < m_fmls.size(); ++i)
|
for (unsigned i = qhead(); i < qtail(); ++i)
|
||||||
terms.push_back(m_fmls[i].fml());
|
terms.push_back(m_fmls[i].fml());
|
||||||
m_trail.append(terms);
|
m_trail.append(terms);
|
||||||
m_heap.reset();
|
m_heap.reset();
|
||||||
m_frozen.reset();
|
|
||||||
m_root.reset();
|
m_root.reset();
|
||||||
|
|
||||||
// initialize nodes for terms in the original goal
|
// initialize nodes for terms in the original goal
|
||||||
|
@ -135,23 +137,6 @@ void elim_unconstrained::init_nodes() {
|
||||||
// top-level terms have reference count > 0
|
// top-level terms have reference count > 0
|
||||||
for (expr* e : terms)
|
for (expr* e : terms)
|
||||||
inc_ref(e);
|
inc_ref(e);
|
||||||
|
|
||||||
// freeze subterms before the already processed head
|
|
||||||
terms.reset();
|
|
||||||
for (unsigned i = 0; i < m_fmls.qhead(); ++i)
|
|
||||||
terms.push_back(m_fmls[i].fml());
|
|
||||||
for (expr* e : subterms::all(terms))
|
|
||||||
m_frozen.mark(e, true);
|
|
||||||
|
|
||||||
// freeze subterms that occur with recursive function definitions
|
|
||||||
recfun::util rec(m);
|
|
||||||
if (rec.has_rec_defs()) {
|
|
||||||
for (func_decl* f : rec.get_rec_funs()) {
|
|
||||||
expr* rhs = rec.get_def(f).get_rhs();
|
|
||||||
for (expr* t : subterms::all(expr_ref(rhs, m)))
|
|
||||||
m_frozen.mark(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,7 +201,7 @@ void elim_unconstrained::gc(expr* t) {
|
||||||
*/
|
*/
|
||||||
void elim_unconstrained::reconstruct_terms() {
|
void elim_unconstrained::reconstruct_terms() {
|
||||||
expr_ref_vector terms(m);
|
expr_ref_vector terms(m);
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size(); ++i)
|
for (unsigned i = qhead(); i < qtail(); ++i)
|
||||||
terms.push_back(m_fmls[i].fml());
|
terms.push_back(m_fmls[i].fml());
|
||||||
|
|
||||||
for (expr* e : subterms_postorder::all(terms)) {
|
for (expr* e : subterms_postorder::all(terms)) {
|
||||||
|
@ -249,8 +234,8 @@ void elim_unconstrained::reconstruct_terms() {
|
||||||
|
|
||||||
void elim_unconstrained::assert_normalized(vector<dependent_expr>& old_fmls) {
|
void elim_unconstrained::assert_normalized(vector<dependent_expr>& old_fmls) {
|
||||||
|
|
||||||
unsigned sz = m_fmls.size();
|
unsigned sz = qtail();
|
||||||
for (unsigned i = m_fmls.qhead(); i < sz; ++i) {
|
for (unsigned i = qhead(); i < sz; ++i) {
|
||||||
auto [f, d] = m_fmls[i]();
|
auto [f, d] = m_fmls[i]();
|
||||||
node& n = get_node(f);
|
node& n = get_node(f);
|
||||||
expr* g = n.m_term;
|
expr* g = n.m_term;
|
||||||
|
|
|
@ -45,7 +45,6 @@ class elim_unconstrained : public dependent_expr_simplifier {
|
||||||
heap<var_lt> m_heap;
|
heap<var_lt> m_heap;
|
||||||
expr_ref_vector m_trail;
|
expr_ref_vector m_trail;
|
||||||
ptr_vector<expr> m_args;
|
ptr_vector<expr> m_args;
|
||||||
expr_mark m_frozen;
|
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
unsigned_vector m_root;
|
unsigned_vector m_root;
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ bool eliminate_predicates::can_be_macro_head(expr* _head, unsigned num_bound) {
|
||||||
return false;
|
return false;
|
||||||
app* head = to_app(_head);
|
app* head = to_app(_head);
|
||||||
func_decl* f = head->get_decl();
|
func_decl* f = head->get_decl();
|
||||||
if (m_disable_macro.is_marked(f))
|
if (m_fmls.frozen(f))
|
||||||
return false;
|
return false;
|
||||||
if (m_is_macro.is_marked(f))
|
if (m_is_macro.is_marked(f))
|
||||||
return false;
|
return false;
|
||||||
|
@ -157,7 +157,7 @@ expr_ref eliminate_predicates::bind_free_variables_in_def(clause& cl, app* head,
|
||||||
* (or (not (head x)) (def x))
|
* (or (not (head x)) (def x))
|
||||||
*/
|
*/
|
||||||
bool eliminate_predicates::try_find_binary_definition(func_decl* p, app_ref& head, expr_ref& def, expr_dependency_ref& dep) {
|
bool eliminate_predicates::try_find_binary_definition(func_decl* p, app_ref& head, expr_ref& def, expr_dependency_ref& dep) {
|
||||||
if (m_disable_macro.is_marked(p))
|
if (m_fmls.frozen(p))
|
||||||
return false;
|
return false;
|
||||||
expr_mark binary_pos, binary_neg;
|
expr_mark binary_pos, binary_neg;
|
||||||
obj_map<expr, expr_dependency*> deps;
|
obj_map<expr, expr_dependency*> deps;
|
||||||
|
@ -501,7 +501,7 @@ void eliminate_predicates::reduce_definitions() {
|
||||||
for (auto const& [k, v] : m_macros)
|
for (auto const& [k, v] : m_macros)
|
||||||
macro_expander.insert(v->m_head, v->m_def, v->m_dep);
|
macro_expander.insert(v->m_head, v->m_def, v->m_dep);
|
||||||
|
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size(); ++i) {
|
for (unsigned i = qhead(); i < qtail(); ++i) {
|
||||||
auto [f, d] = m_fmls[i]();
|
auto [f, d] = m_fmls[i]();
|
||||||
expr_ref fml(f, m), new_fml(m);
|
expr_ref fml(f, m), new_fml(m);
|
||||||
expr_dependency_ref dep(m);
|
expr_dependency_ref dep(m);
|
||||||
|
@ -524,7 +524,7 @@ void eliminate_predicates::reduce_definitions() {
|
||||||
void eliminate_predicates::try_resolve(func_decl* p) {
|
void eliminate_predicates::try_resolve(func_decl* p) {
|
||||||
if (m_disable_elimination.is_marked(p))
|
if (m_disable_elimination.is_marked(p))
|
||||||
return;
|
return;
|
||||||
if (m_disable_macro.is_marked(p))
|
if (m_fmls.frozen(p))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned num_pos = 0, num_neg = 0;
|
unsigned num_pos = 0, num_neg = 0;
|
||||||
|
@ -717,30 +717,20 @@ void eliminate_predicates::try_resolve() {
|
||||||
/**
|
/**
|
||||||
* Process the terms m_to_exclude, walk all subterms.
|
* Process the terms m_to_exclude, walk all subterms.
|
||||||
* Uninterpreted function declarations in these terms are added to 'exclude_set'
|
* Uninterpreted function declarations in these terms are added to 'exclude_set'
|
||||||
* Uninterpreted function declarations from as-array terms are added to 'm_disable_macro'
|
|
||||||
*/
|
*/
|
||||||
void eliminate_predicates::process_to_exclude(ast_mark& exclude_set) {
|
void eliminate_predicates::process_to_exclude(ast_mark& exclude_set) {
|
||||||
ast_mark visited;
|
ast_mark visited;
|
||||||
array_util a(m);
|
|
||||||
|
|
||||||
struct proc {
|
struct proc {
|
||||||
array_util& a;
|
|
||||||
ast_mark& to_exclude;
|
ast_mark& to_exclude;
|
||||||
ast_mark& to_disable;
|
proc(ast_mark& f) :
|
||||||
proc(array_util& a, ast_mark& f, ast_mark& d) :
|
to_exclude(f) {}
|
||||||
a(a), to_exclude(f), to_disable(d) {}
|
|
||||||
void operator()(func_decl* f) {
|
void operator()(func_decl* f) {
|
||||||
if (is_uninterp(f))
|
if (is_uninterp(f))
|
||||||
to_exclude.mark(f, true);
|
to_exclude.mark(f, true);
|
||||||
}
|
}
|
||||||
void operator()(app* e) {
|
|
||||||
func_decl* f;
|
|
||||||
if (a.is_as_array(e, f) && is_uninterp(f))
|
|
||||||
to_disable.mark(f, true);
|
|
||||||
}
|
|
||||||
void operator()(ast* s) {}
|
void operator()(ast* s) {}
|
||||||
};
|
};
|
||||||
proc proc(a, exclude_set, m_disable_macro);
|
proc proc(exclude_set);
|
||||||
|
|
||||||
for (expr* e : m_to_exclude)
|
for (expr* e : m_to_exclude)
|
||||||
for_each_ast(proc, visited, e);
|
for_each_ast(proc, visited, e);
|
||||||
|
@ -779,16 +769,10 @@ eliminate_predicates::clause* eliminate_predicates::init_clause(expr* f, expr_de
|
||||||
* eliminations.
|
* eliminations.
|
||||||
*/
|
*/
|
||||||
void eliminate_predicates::init_clauses() {
|
void eliminate_predicates::init_clauses() {
|
||||||
for (unsigned i = 0; i < m_fmls.qhead(); ++i)
|
|
||||||
m_to_exclude.push_back(m_fmls[i].fml());
|
|
||||||
recfun::util rec(m);
|
|
||||||
if (rec.has_rec_defs())
|
|
||||||
for (auto& d : rec.get_rec_funs())
|
|
||||||
m_to_exclude.push_back(rec.get_def(d).get_rhs());
|
|
||||||
|
|
||||||
process_to_exclude(m_disable_macro);
|
|
||||||
|
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size(); ++i) {
|
m_fmls.freeze_suffix();
|
||||||
|
|
||||||
|
for (unsigned i = qhead(); i < qtail(); ++i) {
|
||||||
clause* cl = init_clause(i);
|
clause* cl = init_clause(i);
|
||||||
add_use_list(*cl);
|
add_use_list(*cl);
|
||||||
m_clauses.push_back(cl);
|
m_clauses.push_back(cl);
|
||||||
|
@ -821,7 +805,6 @@ void eliminate_predicates::reset() {
|
||||||
m_predicates.reset();
|
m_predicates.reset();
|
||||||
m_predicate_decls.reset();
|
m_predicate_decls.reset();
|
||||||
m_to_exclude.reset();
|
m_to_exclude.reset();
|
||||||
m_disable_macro.reset();
|
|
||||||
m_disable_elimination.reset();
|
m_disable_elimination.reset();
|
||||||
m_is_macro.reset();
|
m_is_macro.reset();
|
||||||
for (auto const& [k, v] : m_macros)
|
for (auto const& [k, v] : m_macros)
|
||||||
|
|
|
@ -88,7 +88,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
scoped_ptr_vector<clause> m_clauses;
|
scoped_ptr_vector<clause> m_clauses;
|
||||||
ast_mark m_disable_elimination, m_disable_macro, m_predicate_decls, m_is_macro;
|
ast_mark m_disable_elimination, m_predicate_decls, m_is_macro;
|
||||||
ptr_vector<func_decl> m_predicates;
|
ptr_vector<func_decl> m_predicates;
|
||||||
ptr_vector<expr> m_to_exclude;
|
ptr_vector<expr> m_to_exclude;
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
|
|
|
@ -74,13 +74,13 @@ namespace euf {
|
||||||
|
|
||||||
void completion::add_egraph() {
|
void completion::add_egraph() {
|
||||||
m_nodes_to_canonize.reset();
|
m_nodes_to_canonize.reset();
|
||||||
unsigned sz = m_fmls.size();
|
unsigned sz = qtail();
|
||||||
auto add_children = [&](enode* n) {
|
auto add_children = [&](enode* n) {
|
||||||
for (auto* ch : enode_args(n))
|
for (auto* ch : enode_args(n))
|
||||||
m_nodes_to_canonize.push_back(ch);
|
m_nodes_to_canonize.push_back(ch);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (unsigned i = m_fmls.qhead(); i < sz; ++i) {
|
for (unsigned i = qhead(); i < sz; ++i) {
|
||||||
expr* x, * y;
|
expr* x, * y;
|
||||||
auto [f, d] = m_fmls[i]();
|
auto [f, d] = m_fmls[i]();
|
||||||
if (m.is_eq(f, x, y)) {
|
if (m.is_eq(f, x, y)) {
|
||||||
|
@ -113,8 +113,8 @@ namespace euf {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned sz = m_fmls.size();
|
unsigned sz = qtail();
|
||||||
for (unsigned i = m_fmls.qhead(); i < sz; ++i) {
|
for (unsigned i = qhead(); i < sz; ++i) {
|
||||||
auto [f, d] = m_fmls[i]();
|
auto [f, d] = m_fmls[i]();
|
||||||
|
|
||||||
expr_dependency_ref dep(d, m);
|
expr_dependency_ref dep(d, m);
|
||||||
|
|
|
@ -258,7 +258,7 @@ namespace euf {
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
m_nonzero.reset();
|
m_nonzero.reset();
|
||||||
for (unsigned i = 0; i < fmls.size(); ++i)
|
for (unsigned i = 0; i < fmls.qtail(); ++i)
|
||||||
add_pos(fmls[i].fml());
|
add_pos(fmls[i].fml());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,7 +255,7 @@ public:
|
||||||
void reduce() override {
|
void reduce() override {
|
||||||
expr_ref new_curr(m);
|
expr_ref new_curr(m);
|
||||||
proof_ref new_pr(m);
|
proof_ref new_pr(m);
|
||||||
for (unsigned idx = m_fmls.qhead(); idx < m_fmls.size() && !m_fmls.inconsistent(); idx++) {
|
for (unsigned idx = qhead(); idx < qtail() && !m_fmls.inconsistent(); idx++) {
|
||||||
auto [curr, d] = m_fmls[idx]();
|
auto [curr, d] = m_fmls[idx]();
|
||||||
m_rw(curr, new_curr, new_pr);
|
m_rw(curr, new_curr, new_pr);
|
||||||
// Proof reconstruction: new_pr = m.mk_modus_ponens(old_pr, new_pr);
|
// Proof reconstruction: new_pr = m.mk_modus_ponens(old_pr, new_pr);
|
||||||
|
|
|
@ -26,7 +26,7 @@ Author:
|
||||||
void model_reconstruction_trail::replay(unsigned qhead, dependent_expr_state& st) {
|
void model_reconstruction_trail::replay(unsigned qhead, dependent_expr_state& st) {
|
||||||
ast_mark free_vars;
|
ast_mark free_vars;
|
||||||
scoped_ptr<expr_replacer> rp = mk_default_expr_replacer(m, false);
|
scoped_ptr<expr_replacer> rp = mk_default_expr_replacer(m, false);
|
||||||
for (unsigned i = qhead; i < st.size(); ++i)
|
for (unsigned i = qhead; i < st.qtail(); ++i)
|
||||||
add_vars(st[i], free_vars);
|
add_vars(st[i], free_vars);
|
||||||
|
|
||||||
for (auto& t : m_trail) {
|
for (auto& t : m_trail) {
|
||||||
|
@ -64,7 +64,7 @@ void model_reconstruction_trail::replay(unsigned qhead, dependent_expr_state& st
|
||||||
dependent_expr de(m, t->m_def, t->m_dep);
|
dependent_expr de(m, t->m_def, t->m_dep);
|
||||||
add_vars(de, free_vars);
|
add_vars(de, free_vars);
|
||||||
|
|
||||||
for (unsigned i = qhead; i < st.size(); ++i) {
|
for (unsigned i = qhead; i < st.qtail(); ++i) {
|
||||||
auto [f, dep1] = st[i]();
|
auto [f, dep1] = st[i]();
|
||||||
expr_ref g(m);
|
expr_ref g(m);
|
||||||
expr_dependency_ref dep2(m);
|
expr_dependency_ref dep2(m);
|
||||||
|
@ -77,7 +77,7 @@ void model_reconstruction_trail::replay(unsigned qhead, dependent_expr_state& st
|
||||||
rp->set_substitution(t->m_subst.get());
|
rp->set_substitution(t->m_subst.get());
|
||||||
// rigid entries:
|
// rigid entries:
|
||||||
// apply substitution to added in case of rigid model convertions
|
// apply substitution to added in case of rigid model convertions
|
||||||
for (unsigned i = qhead; i < st.size(); ++i) {
|
for (unsigned i = qhead; i < st.qtail(); ++i) {
|
||||||
auto [f, dep1] = st[i]();
|
auto [f, dep1] = st[i]();
|
||||||
auto [g, dep2] = rp->replace_with_dep(f);
|
auto [g, dep2] = rp->replace_with_dep(f);
|
||||||
dependent_expr d(m, g, m.mk_join(dep1, dep2));
|
dependent_expr d(m, g, m.mk_join(dep1, dep2));
|
||||||
|
|
|
@ -41,7 +41,7 @@ void propagate_values::reduce() {
|
||||||
auto add_shared = [&]() {
|
auto add_shared = [&]() {
|
||||||
shared_occs_mark visited;
|
shared_occs_mark visited;
|
||||||
shared.reset();
|
shared.reset();
|
||||||
for (unsigned i = 0; i < m_fmls.size(); ++i)
|
for (unsigned i = 0; i < qtail(); ++i)
|
||||||
shared(m_fmls[i].fml(), visited);
|
shared(m_fmls[i].fml(), visited);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ void propagate_values::reduce() {
|
||||||
subst.reset();
|
subst.reset();
|
||||||
m_rewriter.reset();
|
m_rewriter.reset();
|
||||||
m_rewriter.set_substitution(&subst);
|
m_rewriter.set_substitution(&subst);
|
||||||
for (unsigned i = 0; i < m_fmls.qhead(); ++i)
|
for (unsigned i = 0; i < qhead(); ++i)
|
||||||
add_sub(m_fmls[i]);
|
add_sub(m_fmls[i]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,10 +86,10 @@ void propagate_values::reduce() {
|
||||||
for (unsigned r = 0; r < m_max_rounds && rw != m_stats.m_num_rewrites; ++r) {
|
for (unsigned r = 0; r < m_max_rounds && rw != m_stats.m_num_rewrites; ++r) {
|
||||||
rw = m_stats.m_num_rewrites;
|
rw = m_stats.m_num_rewrites;
|
||||||
init_sub();
|
init_sub();
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size() && !m_fmls.inconsistent(); ++i)
|
for (unsigned i = qhead(); i < qtail() && !m_fmls.inconsistent(); ++i)
|
||||||
process_fml(i);
|
process_fml(i);
|
||||||
init_sub();
|
init_sub();
|
||||||
for (unsigned i = m_fmls.size(); i-- > m_fmls.qhead() && !m_fmls.inconsistent();)
|
for (unsigned i = qtail(); i-- > qhead() && !m_fmls.inconsistent();)
|
||||||
process_fml(i);
|
process_fml(i);
|
||||||
if (subst.empty())
|
if (subst.empty())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
m_num_steps = 0;
|
m_num_steps = 0;
|
||||||
expr_ref new_curr(m);
|
expr_ref new_curr(m);
|
||||||
proof_ref new_pr(m);
|
proof_ref new_pr(m);
|
||||||
for (unsigned idx = m_fmls.qhead(); idx < m_fmls.size(); idx++) {
|
for (unsigned idx = qhead(); idx < qtail(); idx++) {
|
||||||
if (m_fmls.inconsistent())
|
if (m_fmls.inconsistent())
|
||||||
break;
|
break;
|
||||||
auto d = m_fmls[idx];
|
auto d = m_fmls[idx];
|
||||||
|
|
|
@ -70,6 +70,7 @@ public:
|
||||||
break;
|
break;
|
||||||
collect_stats _cs(*s);
|
collect_stats _cs(*s);
|
||||||
s->reduce();
|
s->reduce();
|
||||||
|
m_fmls.flatten_suffix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace euf {
|
||||||
|
|
||||||
bool solve_context_eqs::is_safe_eq(expr* e) {
|
bool solve_context_eqs::is_safe_eq(expr* e) {
|
||||||
m_and_pos.reset(); m_and_neg.reset(); m_or_pos.reset(); m_or_neg.reset();
|
m_and_pos.reset(); m_and_neg.reset(); m_or_pos.reset(); m_or_neg.reset();
|
||||||
for (unsigned i = 0; i < m_fmls.size(); ++i)
|
for (unsigned i = 0; i < m_fmls.qtail(); ++i)
|
||||||
if (!is_safe_eq(m_fmls[i].fml(), e))
|
if (!is_safe_eq(m_fmls[i].fml(), e))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -147,7 +147,7 @@ namespace euf {
|
||||||
|
|
||||||
void solve_context_eqs::collect_nested_equalities(dep_eq_vector& eqs) {
|
void solve_context_eqs::collect_nested_equalities(dep_eq_vector& eqs) {
|
||||||
expr_mark visited;
|
expr_mark visited;
|
||||||
unsigned sz = m_fmls.size();
|
unsigned sz = m_fmls.qtail();
|
||||||
for (unsigned i = m_fmls.qhead(); i < sz; ++i)
|
for (unsigned i = m_fmls.qhead(); i < sz; ++i)
|
||||||
collect_nested_equalities(m_fmls[i], visited, eqs);
|
collect_nested_equalities(m_fmls[i], visited, eqs);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace euf {
|
||||||
|
|
||||||
void solve_eqs::get_eqs(dep_eq_vector& eqs) {
|
void solve_eqs::get_eqs(dep_eq_vector& eqs) {
|
||||||
for (extract_eq* ex : m_extract_plugins)
|
for (extract_eq* ex : m_extract_plugins)
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size(); ++i)
|
for (unsigned i = qhead(); i < qtail(); ++i)
|
||||||
ex->get_eqs(m_fmls[i], eqs);
|
ex->get_eqs(m_fmls[i], eqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ namespace euf {
|
||||||
scoped_ptr<expr_replacer> rp = mk_default_expr_replacer(m, false);
|
scoped_ptr<expr_replacer> rp = mk_default_expr_replacer(m, false);
|
||||||
rp->set_substitution(m_subst.get());
|
rp->set_substitution(m_subst.get());
|
||||||
|
|
||||||
for (unsigned i = m_fmls.qhead(); i < m_fmls.size() && !m_fmls.inconsistent(); ++i) {
|
for (unsigned i = qhead(); i < qtail() && !m_fmls.inconsistent(); ++i) {
|
||||||
auto [f, d] = m_fmls[i]();
|
auto [f, d] = m_fmls[i]();
|
||||||
auto [new_f, new_dep] = rp->replace_with_dep(f);
|
auto [new_f, new_dep] = rp->replace_with_dep(f);
|
||||||
m_rewriter(new_f);
|
m_rewriter(new_f);
|
||||||
|
|
|
@ -17,9 +17,6 @@ Author:
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- proper handling of dependencies + pre-processing
|
|
||||||
- literals used in dependencies should not be eliminated by pre-processing routines
|
|
||||||
This has to be enforced.
|
|
||||||
- add translation for preprocess state.
|
- add translation for preprocess state.
|
||||||
- If the pre-processors are stateful, they need to be properly translated.
|
- If the pre-processors are stateful, they need to be properly translated.
|
||||||
- add back get_consequences, maybe or just have them handled by inc_sat_solver
|
- add back get_consequences, maybe or just have them handled by inc_sat_solver
|
||||||
|
@ -55,9 +52,9 @@ class sat_smt_solver : public solver {
|
||||||
struct dep_expr_state : public dependent_expr_state {
|
struct dep_expr_state : public dependent_expr_state {
|
||||||
sat_smt_solver& s;
|
sat_smt_solver& s;
|
||||||
model_reconstruction_trail m_reconstruction_trail;
|
model_reconstruction_trail m_reconstruction_trail;
|
||||||
dep_expr_state(sat_smt_solver& s):s(s), m_reconstruction_trail(s.m, m_trail) {}
|
dep_expr_state(sat_smt_solver& s):dependent_expr_state(s.m), s(s), m_reconstruction_trail(s.m, m_trail) {}
|
||||||
~dep_expr_state() override {}
|
~dep_expr_state() override {}
|
||||||
virtual unsigned size() const override { return s.m_fmls.size(); }
|
virtual unsigned qtail() const override { return s.m_fmls.size(); }
|
||||||
dependent_expr const& operator[](unsigned i) override { return s.m_fmls[i]; }
|
dependent_expr const& operator[](unsigned i) override { return s.m_fmls[i]; }
|
||||||
void update(unsigned i, dependent_expr const& j) override { s.m_fmls[i] = j; }
|
void update(unsigned i, dependent_expr const& j) override { s.m_fmls[i] = j; }
|
||||||
void add(dependent_expr const& j) override { s.m_fmls.push_back(j); }
|
void add(dependent_expr const& j) override { s.m_fmls.push_back(j); }
|
||||||
|
@ -65,6 +62,28 @@ class sat_smt_solver : public solver {
|
||||||
model_reconstruction_trail& model_trail() override { return m_reconstruction_trail; }
|
model_reconstruction_trail& model_trail() override { return m_reconstruction_trail; }
|
||||||
void append(generic_model_converter& mc) { model_trail().append(mc); }
|
void append(generic_model_converter& mc) { model_trail().append(mc); }
|
||||||
void replay(unsigned qhead) { m_reconstruction_trail.replay(qhead, *this); }
|
void replay(unsigned qhead) { m_reconstruction_trail.replay(qhead, *this); }
|
||||||
|
void flatten_suffix() override {
|
||||||
|
expr_mark seen;
|
||||||
|
unsigned j = qhead();
|
||||||
|
for (unsigned i = qhead(); i < qtail(); ++i) {
|
||||||
|
expr* f = s.m_fmls[i].fml();
|
||||||
|
if (seen.is_marked(f))
|
||||||
|
continue;
|
||||||
|
seen.mark(f, true);
|
||||||
|
if (s.m.is_true(f))
|
||||||
|
continue;
|
||||||
|
if (s.m.is_and(f)) {
|
||||||
|
auto* d = s.m_fmls[i].dep();
|
||||||
|
for (expr* arg : *to_app(f))
|
||||||
|
s.m_fmls.push_back(dependent_expr(s.m, arg, d));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i != j)
|
||||||
|
s.m_fmls[j] = s.m_fmls[i];
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
s.m_fmls.shrink(j);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dependency2assumptions {
|
struct dependency2assumptions {
|
||||||
|
@ -253,7 +272,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_internal() {
|
void push_internal() {
|
||||||
m_trail.push_scope();
|
|
||||||
m_solver.user_push();
|
m_solver.user_push();
|
||||||
m_goal2sat.user_push();
|
m_goal2sat.user_push();
|
||||||
m_map.push();
|
m_map.push();
|
||||||
|
@ -272,7 +290,6 @@ public:
|
||||||
m_map.pop(n);
|
m_map.pop(n);
|
||||||
m_goal2sat.user_pop(n);
|
m_goal2sat.user_pop(n);
|
||||||
m_solver.user_pop(n);
|
m_solver.user_pop(n);
|
||||||
m_trail.pop_scope(n);
|
|
||||||
m_mc->shrink(m_mc_size);
|
m_mc->shrink(m_mc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ class dependent_expr_state_tactic : public tactic, public dependent_expr_state {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
dependent_expr_state_tactic(ast_manager& m, params_ref const& p, dependent_expr_simplifier_factory* f):
|
dependent_expr_state_tactic(ast_manager& m, params_ref const& p, dependent_expr_simplifier_factory* f):
|
||||||
|
dependent_expr_state(m),
|
||||||
m(m),
|
m(m),
|
||||||
m_params(p),
|
m_params(p),
|
||||||
m_factory(f),
|
m_factory(f),
|
||||||
|
@ -52,7 +53,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* size(), [](), update() and inconsisent() implement the abstract interface of dependent_expr_state
|
* size(), [](), update() and inconsisent() implement the abstract interface of dependent_expr_state
|
||||||
*/
|
*/
|
||||||
unsigned size() const override { return m_goal->size(); }
|
unsigned qtail() const override { return m_goal->size(); }
|
||||||
|
|
||||||
dependent_expr const& operator[](unsigned i) override {
|
dependent_expr const& operator[](unsigned i) override {
|
||||||
m_dep = dependent_expr(m, m_goal->form(i), m_goal->dep(i));
|
m_dep = dependent_expr(m, m_goal->form(i), m_goal->dep(i));
|
||||||
|
@ -60,11 +61,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(unsigned i, dependent_expr const& j) override {
|
void update(unsigned i, dependent_expr const& j) override {
|
||||||
|
if (inconsistent())
|
||||||
|
return;
|
||||||
auto [f, d] = j();
|
auto [f, d] = j();
|
||||||
m_goal->update(i, f, nullptr, d);
|
m_goal->update(i, f, nullptr, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(dependent_expr const& j) override {
|
void add(dependent_expr const& j) override {
|
||||||
|
if (inconsistent())
|
||||||
|
return;
|
||||||
auto [f, d] = j();
|
auto [f, d] = j();
|
||||||
m_goal->assert_expr(f, nullptr, d);
|
m_goal->assert_expr(f, nullptr, d);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue