3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-15 07:15:26 +00:00
z3/src/tactic/portfolio/euf_completion_tactic.cpp
2025-07-08 04:50:43 +02:00

138 lines
3.9 KiB
C++

/*++
Copyright (c) 2022 Microsoft Corporation
Module Name:
euf_completion_tactic.cpp
Abstract:
Tactic for simplifying with equations.
Author:
Nikolaj Bjorner (nbjorner) 2022-10-30
--*/
#include "ast/rewriter/expr_safe_replace.h"
#include "tactic/tactic.h"
#include "tactic/portfolio/euf_completion_tactic.h"
#include "solver/solver.h"
#include "smt/smt_solver.h"
class euf_side_condition_solver : public euf::side_condition_solver {
ast_manager& m;
params_ref m_params;
scoped_ptr<solver> m_solver;
expr_ref_vector m_deps;
obj_map<expr, std::pair<proof*, expr_dependency*>> m_e2d;
expr_ref_vector m_fmls;
obj_hashtable<expr> m_seen;
trail_stack m_trail;
void init_solver() {
if (m_solver.get())
return;
m_params.set_uint("smt.max_conflicts", 100);
scoped_ptr<solver_factory> f = mk_smt_solver_factory();
m_solver = (*f)(m, m_params, false, false, true, symbol::null);
}
public:
euf_side_condition_solver(ast_manager& m, params_ref const& p) :
m(m), m_params(p), m_deps(m), m_fmls(m) {}
void push() override {
init_solver();
m_solver->push();
m_trail.pop_scope(1);
}
void pop(unsigned n) override {
m_trail.push_scope();
SASSERT(m_solver.get());
m_solver->pop(n);
}
void add_constraint(expr* f, proof* pr, expr_dependency* d) override {
if (m_seen.contains(f))
return;
m_seen.insert(f);
m_trail.push(insert_obj_trail(m_seen, f));
if (!is_ground(f))
return;
if (m.is_implies(f))
return;
init_solver();
if (d) {
expr* e_dep = m.mk_fresh_const("dep", m.mk_bool_sort());
m_deps.push_back(e_dep);
m_e2d.insert(e_dep, { pr, d });
m_trail.push(insert_obj_map(m_e2d, e_dep));
m_solver->assert_expr(f, e_dep);
}
else
m_solver->assert_expr(f);
}
bool is_true(expr* f, proof_ref& pr, expr_dependency*& d) override {
d = nullptr;
init_solver();
solver::scoped_push _sp(*m_solver);
m_fmls.reset();
m_fmls.push_back(m.mk_not(f));
expr_ref nf(m.mk_not(f), m);
lbool r = m_solver->check_sat(m_fmls);
if (r == l_false) {
expr_ref_vector core(m);
m_solver->get_unsat_core(core);
for (auto c : core) {
if (c == nf)
continue;
auto [pr, dep] = m_e2d[c];
d = m.mk_join(d, dep);
}
if (m.proofs_enabled()) {
pr = m_solver->get_proof();
SASSERT(pr);
expr_safe_replace rep(m);
for (auto c : core) {
if (c == nf)
continue;
auto [p, dep] = m_e2d[c];
rep.insert(m.mk_asserted(c), p);
}
expr_ref ppr(pr, m);
rep(ppr);
pr = to_app(ppr.get());
}
}
return r == l_false;
}
void solve_for(vector<solution>& sol) override {
init_solver();
vector<solver::solution> ss;
for (auto [v, t, g] : sol)
ss.push_back({ v, t, g });
sol.reset();
m_solver->solve_for(ss);
for (auto [v, t, g] : ss)
sol.push_back({ v, t, g });
}
};
dependent_expr_simplifier* mk_euf_completion_simplifier(ast_manager& m, dependent_expr_state& s, params_ref const& p) {
auto r = alloc(euf::completion, m, s);
auto scs = alloc(euf_side_condition_solver, m, p);
r->set_solver(scs);
return r;
}
tactic * mk_euf_completion_tactic(ast_manager& m, params_ref const& p) {
return alloc(dependent_expr_state_tactic, m, p,
[](auto& m, auto& p, auto &s) -> dependent_expr_simplifier* { return mk_euf_completion_simplifier(m, s, p); });
}