3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-14 23:05:26 +00:00

working on ho-matcher

This commit is contained in:
Nikolaj Bjorner 2025-07-08 04:50:43 +02:00
parent 195f3c9110
commit 35b1d09425
4 changed files with 49 additions and 22 deletions

View file

@ -636,15 +636,15 @@ namespace euf {
} }
quantifier* ho_matcher::compile_ho_pattern(quantifier* q, app*& p) { std::pair<quantifier*, app*> ho_matcher::compile_ho_pattern(quantifier* q, app* p) {
app* p1 = nullptr; app* p1 = nullptr;
if (m_pat2hopat.find(p, p)) { if (m_pat2hopat.find(p, p)) {
q = m_q2hoq[q]; q = m_q2hoq[q];
return q; return { q, p };
} }
auto is_ho = any_of(subterms::all(expr_ref(p, m)), [&](expr* t) { return m_unitary.is_flex(0, t); }); auto is_ho = any_of(subterms::all(expr_ref(p, m)), [&](expr* t) { return m_unitary.is_flex(0, t); });
if (!is_ho) if (!is_ho)
return q; return { q, p };
ptr_vector<expr> todo; ptr_vector<expr> todo;
ptr_buffer<var> bound; ptr_buffer<var> bound;
expr_ref_vector cache(m); expr_ref_vector cache(m);
@ -684,7 +684,7 @@ namespace euf {
} }
if (is_quantifier(t)) { if (is_quantifier(t)) {
m_pat2abs.remove(p); m_pat2abs.remove(p);
return q; return { q, p };
} }
} }
p1 = to_app(cache.get(p->get_id())); p1 = to_app(cache.get(p->get_id()));
@ -738,9 +738,8 @@ namespace euf {
trail().push(insert_map(m_pat2abs, p)); trail().push(insert_map(m_pat2abs, p));
trail().push(insert_map(m_q2hoq, q)); trail().push(insert_map(m_q2hoq, q));
trail().push(insert_map(m_hoq2q, q1)); trail().push(insert_map(m_hoq2q, q1));
trail().push(insert_map(m_hopat2free_vars, p1)); trail().push(insert_map(m_hopat2free_vars, p1));
p = p1; return { q1, p1 };
return q1;
} }
bool ho_matcher::is_ho_pattern(app* p) { bool ho_matcher::is_ho_pattern(app* p) {

View file

@ -386,7 +386,7 @@ namespace euf {
void operator()(expr* pat, expr* t, unsigned num_bound, unsigned num_vars); void operator()(expr* pat, expr* t, unsigned num_bound, unsigned num_vars);
quantifier* compile_ho_pattern(quantifier* q, app*& p); std::pair<quantifier*, app*> compile_ho_pattern(quantifier* q, app* p);
bool is_ho_pattern(app* p); bool is_ho_pattern(app* p);

View file

@ -98,28 +98,36 @@ namespace euf {
[&](ho_subst& s) { [&](ho_subst& s) {
IF_VERBOSE(1, s.display(verbose_stream() << "on-match\n") << "\n"); IF_VERBOSE(1, s.display(verbose_stream() << "on-match\n") << "\n");
auto& b = *m_ho_binding; auto& b = *m_ho_binding;
auto* hopat = b.m_pattern;
auto* hoq = b.m_q; auto* hoq = b.m_q;
auto* q = m_matcher.hoq2q(hoq); auto* q = m_matcher.hoq2q(hoq);
// shrink binding // shrink binding
expr_ref_vector binding(m); expr_ref_vector binding(m);
for (unsigned i = 0; i < s.size(); ++i) for (unsigned i = 0; i < s.size(); ++i)
binding.push_back(s.get(i)); binding.push_back(s.get(i));
binding.reverse();
if (binding.size() > q->get_num_decls()) { if (binding.size() > q->get_num_decls()) {
bool change = true; bool change = true;
while (change) { while (change) {
change = false; change = false;
for (unsigned i = binding.size(); i-- > 0;) { for (unsigned i = 1; i < binding.size();) {
var_subst sub(m, false); var_subst sub(m);
auto r = sub(binding.get(i), binding); auto r = sub(binding.get(i), binding);
change |= r != binding.get(i); change |= r != binding.get(i);
m_rewriter(r);
binding[i] = r; binding[i] = r;
} }
} }
binding.reverse();
binding.shrink(q->get_num_decls());
binding.reverse();
}
else {
for (unsigned i = 0; i < binding.size();) {
expr_ref r(binding.get(i), m);
m_rewriter(r);
binding[i] = r;
}
} }
binding.shrink(q->get_num_decls());
binding.reverse();
IF_VERBOSE(1, verbose_stream() << binding << "\n"); IF_VERBOSE(1, verbose_stream() << binding << "\n");
apply_binding(b, q, binding); apply_binding(b, q, binding);
@ -226,7 +234,7 @@ namespace euf {
void completion::add_egraph() { void completion::add_egraph() {
m_nodes_to_canonize.reset(); m_nodes_to_canonize.reset();
unsigned sz = qtail(); unsigned sz = qtail();
for (unsigned i = qhead(); i < sz; ++i) { for (unsigned i = qhead(); i < sz; ++i) {
auto [f, p, d] = m_fmls[i](); auto [f, p, d] = m_fmls[i]();
@ -264,23 +272,36 @@ namespace euf {
}; };
expr* x, * y; expr* x, * y;
if (m.is_eq(f, x, y)) { if (m.is_eq(f, x, y)) {
enode* a = mk_enode(x); expr_ref x1(x, m);
enode* b = mk_enode(y); expr_ref y1(y, m);
m_rewriter(x1);
m_rewriter(y1);
enode* a = mk_enode(x1);
enode* b = mk_enode(y1);
if (a->get_root() == b->get_root())
return;
m_egraph.merge(a, b, to_ptr(push_pr_dep(pr, d))); m_egraph.merge(a, b, to_ptr(push_pr_dep(pr, d)));
add_children(a); add_children(a);
add_children(b); add_children(b);
m_should_propagate = true; m_should_propagate = true;
if (m_side_condition_solver)
m_side_condition_solver->add_constraint(f, pr, d);
} }
else if (m.is_not(f, f)) { else if (m.is_not(f, f)) {
enode* n = mk_enode(f); enode* n = mk_enode(f);
if (m.is_false(n->get_root()->get_expr()))
return;
auto j = to_ptr(push_pr_dep(pr, d)); auto j = to_ptr(push_pr_dep(pr, d));
m_egraph.new_diseq(n, j); m_egraph.new_diseq(n, j);
add_children(n); add_children(n);
m_should_propagate = true; m_should_propagate = true;
if (m_side_condition_solver)
m_side_condition_solver->add_constraint(f, pr, d);
} }
else { else {
enode* n = mk_enode(f); enode* n = mk_enode(f);
if (m.is_true(n->get_root()->get_expr()))
return;
m_egraph.merge(n, m_tt, to_ptr(push_pr_dep(pr, d))); m_egraph.merge(n, m_tt, to_ptr(push_pr_dep(pr, d)));
add_children(n); add_children(n);
if (is_forall(f)) { if (is_forall(f)) {
@ -296,20 +317,24 @@ namespace euf {
for (unsigned i = 0; i < q->get_num_patterns(); ++i) { for (unsigned i = 0; i < q->get_num_patterns(); ++i) {
auto p = to_app(q->get_pattern(i)); auto p = to_app(q->get_pattern(i));
auto q1 = m_matcher.compile_ho_pattern(q, p); auto [q1, p1] = m_matcher.compile_ho_pattern(q, p);
ptr_vector<app> ground; ptr_vector<app> ground;
mam::ground_subterms(p, ground); mam::ground_subterms(p, ground);
if (p1 != p)
mam::ground_subterms(p1, ground);
for (expr* g : ground) for (expr* g : ground)
mk_enode(g); mk_enode(g);
m_mam->add_pattern(q1, p); m_mam->add_pattern(q, p);
if (p != p1)
m_mam->add_pattern(q1, p1);
} }
m_q2dep.insert(q, { pr, d}); m_q2dep.insert(q, { pr, d});
get_trail().push(insert_obj_map(m_q2dep, q)); get_trail().push(insert_obj_map(m_q2dep, q));
} }
add_rule(f, pr, d); add_rule(f, pr, d);
if (!is_forall(f) && !m.is_implies(f) && m_side_condition_solver)
m_side_condition_solver->add_constraint(f, pr, d);
} }
if (m_side_condition_solver)
m_side_condition_solver->add_constraint(f, pr, d);
} }
lbool completion::eval_cond(expr* f, proof_ref& pr, expr_dependency*& d) { lbool completion::eval_cond(expr* f, proof_ref& pr, expr_dependency*& d) {
@ -357,6 +382,7 @@ namespace euf {
body.push_back(x); body.push_back(x);
flatten_and(body); flatten_and(body);
unsigned j = 0; unsigned j = 0;
flet<bool> _propagate_with_solver(m_propagate_with_solver, true);
for (auto f : body) { for (auto f : body) {
switch (eval_cond(f, pr_i, d)) { switch (eval_cond(f, pr_i, d)) {

View file

@ -79,6 +79,7 @@ public:
bool is_true(expr* f, proof_ref& pr, expr_dependency*& d) override { bool is_true(expr* f, proof_ref& pr, expr_dependency*& d) override {
d = nullptr; d = nullptr;
init_solver();
solver::scoped_push _sp(*m_solver); solver::scoped_push _sp(*m_solver);
m_fmls.reset(); m_fmls.reset();
m_fmls.push_back(m.mk_not(f)); m_fmls.push_back(m.mk_not(f));
@ -113,6 +114,7 @@ public:
} }
void solve_for(vector<solution>& sol) override { void solve_for(vector<solution>& sol) override {
init_solver();
vector<solver::solution> ss; vector<solver::solution> ss;
for (auto [v, t, g] : sol) for (auto [v, t, g] : sol)
ss.push_back({ v, t, g }); ss.push_back({ v, t, g });