mirror of
https://github.com/Z3Prover/z3
synced 2025-08-20 18:20:22 +00:00
turn on ho-matcher for completion
This commit is contained in:
parent
1b3c3c2716
commit
0c5b0c3724
10 changed files with 166 additions and 63 deletions
|
@ -70,7 +70,8 @@ namespace euf {
|
|||
m_canonical_proofs(m),
|
||||
// m_infer_patterns(m, m_smt_params),
|
||||
m_deps(m),
|
||||
m_rewriter(m) {
|
||||
m_rewriter(m),
|
||||
m_matcher(m, m_trail) {
|
||||
m_tt = m_egraph.mk(m.mk_true(), 0, 0, nullptr);
|
||||
m_ff = m_egraph.mk(m.mk_false(), 0, 0, nullptr);
|
||||
m_rewriter.set_order_eq(true);
|
||||
|
@ -92,6 +93,39 @@ namespace euf {
|
|||
|
||||
m_egraph.add_plugin(alloc(arith_plugin, m_egraph));
|
||||
m_egraph.add_plugin(alloc(bv_plugin, m_egraph));
|
||||
|
||||
std::function<void(ho_subst&)> on_match =
|
||||
[&](ho_subst& s) {
|
||||
IF_VERBOSE(1, s.display(verbose_stream() << "on-match\n") << "\n");
|
||||
auto& b = *m_ho_binding;
|
||||
auto* hopat = b.m_pattern;
|
||||
auto* hoq = b.m_q;
|
||||
auto* q = m_matcher.hoq2q(hoq);
|
||||
// shrink binding
|
||||
expr_ref_vector binding(m);
|
||||
for (unsigned i = 0; i < s.size(); ++i)
|
||||
binding.push_back(s.get(i));
|
||||
binding.reverse();
|
||||
if (binding.size() > q->get_num_decls()) {
|
||||
bool change = true;
|
||||
while (change) {
|
||||
change = false;
|
||||
for (unsigned i = binding.size(); i-- > 0;) {
|
||||
var_subst sub(m, false);
|
||||
auto r = sub(binding.get(i), binding);
|
||||
change |= r != binding.get(i);
|
||||
binding[i] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.shrink(q->get_num_decls());
|
||||
binding.reverse();
|
||||
|
||||
IF_VERBOSE(1, verbose_stream() << binding << "\n");
|
||||
apply_binding(b, q, binding);
|
||||
};
|
||||
|
||||
m_matcher.set_on_match(on_match);
|
||||
}
|
||||
|
||||
completion::~completion() {
|
||||
|
@ -108,6 +142,7 @@ namespace euf {
|
|||
void completion::updt_params(params_ref const& p) {
|
||||
smt_params_helper sp(p);
|
||||
m_max_instantiations = sp.qi_max_instances();
|
||||
// m_max_generation = sp.qi_max_generation();
|
||||
}
|
||||
|
||||
struct completion::push_watch_rule : public trail {
|
||||
|
@ -222,6 +257,7 @@ namespace euf {
|
|||
void completion::add_constraint(expr* f, proof* pr, expr_dependency* d) {
|
||||
if (m_egraph.inconsistent())
|
||||
return;
|
||||
TRACE(euf_completion, tout << mk_pp(f, m) << "\n");
|
||||
auto add_children = [&](enode* n) {
|
||||
for (auto* ch : enode_args(n))
|
||||
m_nodes_to_canonize.push_back(ch);
|
||||
|
@ -234,12 +270,14 @@ namespace euf {
|
|||
m_egraph.merge(a, b, to_ptr(push_pr_dep(pr, d)));
|
||||
add_children(a);
|
||||
add_children(b);
|
||||
m_should_propagate = true;
|
||||
}
|
||||
else if (m.is_not(f, f)) {
|
||||
enode* n = mk_enode(f);
|
||||
auto j = to_ptr(push_pr_dep(pr, d));
|
||||
m_egraph.new_diseq(n, j);
|
||||
add_children(n);
|
||||
m_should_propagate = true;
|
||||
}
|
||||
else {
|
||||
enode* n = mk_enode(f);
|
||||
|
@ -255,13 +293,15 @@ namespace euf {
|
|||
q = to_quantifier(tmp);
|
||||
}
|
||||
#endif
|
||||
ptr_vector<app> ground;
|
||||
|
||||
for (unsigned i = 0; i < q->get_num_patterns(); ++i) {
|
||||
auto p = to_app(q->get_pattern(i));
|
||||
auto q1 = m_matcher.compile_ho_pattern(q, p);
|
||||
ptr_vector<app> ground;
|
||||
mam::ground_subterms(p, ground);
|
||||
for (expr* g : ground)
|
||||
mk_enode(g);
|
||||
m_mam->add_pattern(q, p);
|
||||
m_mam->add_pattern(q1, p);
|
||||
}
|
||||
m_q2dep.insert(q, { pr, d});
|
||||
get_trail().push(insert_obj_map(m_q2dep, q));
|
||||
|
@ -295,7 +335,7 @@ namespace euf {
|
|||
if (m.is_true(n->get_root()->get_expr()))
|
||||
return l_false;
|
||||
}
|
||||
if (m_side_condition_solver) {
|
||||
if (m_side_condition_solver && m_propagate_with_solver) {
|
||||
expr_dependency* sd = nullptr;
|
||||
if (m_side_condition_solver->is_true(f, pr, sd)) {
|
||||
add_constraint(f, pr, sd);
|
||||
|
@ -363,6 +403,7 @@ namespace euf {
|
|||
}
|
||||
|
||||
void completion::propagate_all_rules() {
|
||||
flet<bool> _propagate_with_solver(m_propagate_with_solver, true);
|
||||
for (auto* r : m_rules)
|
||||
if (!r->m_in_queue)
|
||||
r->m_in_queue = true,
|
||||
|
@ -456,6 +497,8 @@ namespace euf {
|
|||
void completion::on_binding(quantifier* q, app* pat, enode* const* binding, unsigned max_global, unsigned min_top, unsigned max_top) {
|
||||
if (should_stop())
|
||||
return;
|
||||
if (max_top >= m_max_generation)
|
||||
return;
|
||||
auto* b = alloc_binding(q, pat, binding, max_global, min_top, max_top);
|
||||
if (!b)
|
||||
return;
|
||||
|
@ -487,23 +530,21 @@ namespace euf {
|
|||
void completion::apply_binding(binding& b) {
|
||||
if (should_stop())
|
||||
return;
|
||||
#if 0
|
||||
if (is_ho_binding(b))
|
||||
apply_ho_binding(b);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
expr_ref_vector _binding(m);
|
||||
quantifier* q = b.m_q;
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i)
|
||||
_binding.push_back(b.m_nodes[i]->get_expr());
|
||||
apply_binding(b, _binding);
|
||||
expr_ref_vector _binding(m);
|
||||
quantifier* q = b.m_q;
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i)
|
||||
_binding.push_back(b.m_nodes[i]->get_expr());
|
||||
if (m_matcher.is_ho_pattern(b.m_pattern)) {
|
||||
flet<binding*> set_binding(m_ho_binding, &b);
|
||||
m_matcher.refine_ho_match(b.m_pattern, _binding);
|
||||
}
|
||||
else
|
||||
apply_binding(b, q, _binding);
|
||||
|
||||
}
|
||||
|
||||
void completion::apply_binding(binding& b, expr_ref_vector const& s) {
|
||||
void completion::apply_binding(binding& b, quantifier* q, expr_ref_vector const& s) {
|
||||
var_subst subst(m);
|
||||
quantifier* q = b.m_q;
|
||||
expr_ref r = subst(q->get_expr(), s);
|
||||
scoped_generation sg(*this, b.m_max_top_generation + 1);
|
||||
auto [pr, d] = get_dependency(q);
|
||||
|
@ -512,10 +553,8 @@ namespace euf {
|
|||
add_constraint(r, pr, d);
|
||||
propagate_rules();
|
||||
m_egraph.propagate();
|
||||
m_should_propagate = true;
|
||||
}
|
||||
|
||||
|
||||
void completion::read_egraph() {
|
||||
if (m_egraph.inconsistent()) {
|
||||
auto* d = explain_conflict();
|
||||
|
|
|
@ -25,6 +25,7 @@ Author:
|
|||
#include "ast/simplifiers/dependent_expr_state.h"
|
||||
#include "ast/euf/euf_egraph.h"
|
||||
#include "ast/euf/euf_mam.h"
|
||||
#include "ast/euf/ho_matcher.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
// include "ast/pattern/pattern_inference.h"
|
||||
#include "params/smt_params.h"
|
||||
|
@ -133,18 +134,22 @@ namespace euf {
|
|||
bindings m_bindings;
|
||||
scoped_ptr<binding> m_tmp_binding;
|
||||
unsigned m_tmp_binding_capacity = 0;
|
||||
binding* m_ho_binding = nullptr;
|
||||
expr_dependency_ref_vector m_deps;
|
||||
obj_map<quantifier, std::pair<proof*, expr_dependency*>> m_q2dep;
|
||||
vector<std::pair<proof_ref, expr_dependency*>> m_pr_dep;
|
||||
unsigned m_epoch = 0;
|
||||
unsigned_vector m_epochs;
|
||||
th_rewriter m_rewriter;
|
||||
ho_matcher m_matcher;
|
||||
stats m_stats;
|
||||
scoped_ptr<side_condition_solver> m_side_condition_solver;
|
||||
ptr_vector<conditional_rule> m_rules;
|
||||
bool m_has_new_eq = false;
|
||||
bool m_should_propagate = false;
|
||||
bool m_propagate_with_solver = false;
|
||||
unsigned m_max_instantiations = std::numeric_limits<unsigned>::max();
|
||||
unsigned m_max_generation = 10;
|
||||
unsigned m_generation = 0;
|
||||
vector<ptr_vector<conditional_rule>> m_rule_watch;
|
||||
|
||||
|
@ -176,7 +181,7 @@ namespace euf {
|
|||
binding* alloc_binding(quantifier* q, app* pat, euf::enode* const* _binding, unsigned max_generation, unsigned min_top, unsigned max_top);
|
||||
void insert_binding(binding* b);
|
||||
void apply_binding(binding& b);
|
||||
void apply_binding(binding& b, expr_ref_vector const& s);
|
||||
void apply_binding(binding& b, quantifier* q, expr_ref_vector const& s);
|
||||
void flush_binding_queue();
|
||||
vector<ptr_vector<binding>> m_queue;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue