3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-05-14 19:05:40 +02:00
parent 4d05a11144
commit 4fcc4d07ae
12 changed files with 139 additions and 49 deletions

View file

@ -269,7 +269,8 @@ func_decl_info::func_decl_info(family_id family_id, decl_kind k, unsigned num_pa
m_pairwise(false),
m_injective(false),
m_idempotent(false),
m_skolem(false) {
m_skolem(false),
m_lambda(false) {
}
bool func_decl_info::operator==(func_decl_info const & info) const {
@ -281,20 +282,22 @@ bool func_decl_info::operator==(func_decl_info const & info) const {
m_chainable == info.m_chainable &&
m_pairwise == info.m_pairwise &&
m_injective == info.m_injective &&
m_skolem == info.m_skolem;
m_skolem == info.m_skolem &&
m_lambda == info.m_lambda;
}
std::ostream & operator<<(std::ostream & out, func_decl_info const & info) {
operator<<(out, static_cast<decl_info const&>(info));
out << " :left-assoc " << info.is_left_associative();
out << " :right-assoc " << info.is_right_associative();
out << " :flat-associative " << info.is_flat_associative();
out << " :commutative " << info.is_commutative();
out << " :chainable " << info.is_chainable();
out << " :pairwise " << info.is_pairwise();
out << " :injective " << info.is_injective();
out << " :idempotent " << info.is_idempotent();
out << " :skolem " << info.is_skolem();
if (info.is_left_associative()) out << " :left-assoc ";
if (info.is_right_associative()) out << " :right-assoc ";
if (info.is_flat_associative()) out << " :flat-associative ";
if (info.is_commutative()) out << " :commutative ";
if (info.is_chainable()) out << " :chainable ";
if (info.is_pairwise()) out << " :pairwise ";
if (info.is_injective()) out << " :injective ";
if (info.is_idempotent()) out << " :idempotent ";
if (info.is_skolem()) out << " :skolem ";
if (info.is_lambda()) out << " :lambda ";
return out;
}
@ -1713,6 +1716,20 @@ bool ast_manager::are_distinct(expr* a, expr* b) const {
return false;
}
void ast_manager::add_lambda_def(func_decl* f, quantifier* q) {
m_lambda_defs.insert(f, q);
f->get_info()->set_lambda(true);
inc_ref(q);
}
quantifier* ast_manager::is_lambda_def(func_decl* f) {
if (f->get_info() && f->get_info()->is_lambda()) {
return m_lambda_defs[f];
}
return nullptr;
}
func_decl* ast_manager::get_rec_fun_decl(quantifier* q) const {
SASSERT(is_rec_fun_def(q));
return to_app(to_app(q->get_pattern(0))->get_arg(0))->get_decl();
@ -1901,6 +1918,10 @@ void ast_manager::delete_node(ast * n) {
func_decl* f = to_func_decl(n);
if (f->m_info != nullptr && !m_debug_ref_count) {
func_decl_info * info = f->get_info();
if (info->is_lambda()) {
push_dec_ref(m_lambda_defs[f]);
m_lambda_defs.remove(f);
}
info->del_eh(*this);
dealloc(info);
}

View file

@ -398,6 +398,7 @@ struct func_decl_info : public decl_info {
bool m_injective:1;
bool m_idempotent:1;
bool m_skolem:1;
bool m_lambda:1;
func_decl_info(family_id family_id = null_family_id, decl_kind k = null_decl_kind, unsigned num_parameters = 0, parameter const * parameters = nullptr);
~func_decl_info() {}
@ -412,6 +413,7 @@ struct func_decl_info : public decl_info {
bool is_injective() const { return m_injective; }
bool is_idempotent() const { return m_idempotent; }
bool is_skolem() const { return m_skolem; }
bool is_lambda() const { return m_lambda; }
void set_associative(bool flag = true) { m_left_assoc = flag; m_right_assoc = flag; }
void set_left_associative(bool flag = true) { m_left_assoc = flag; }
@ -423,6 +425,7 @@ struct func_decl_info : public decl_info {
void set_injective(bool flag = true) { m_injective = flag; }
void set_idempotent(bool flag = true) { m_idempotent = flag; }
void set_skolem(bool flag = true) { m_skolem = flag; }
void set_lambda(bool flag = true) { m_lambda = flag; }
bool operator==(func_decl_info const & info) const;
@ -641,6 +644,7 @@ public:
bool is_pairwise() const { return get_info() != nullptr && get_info()->is_pairwise(); }
bool is_injective() const { return get_info() != nullptr && get_info()->is_injective(); }
bool is_skolem() const { return get_info() != nullptr && get_info()->is_skolem(); }
bool is_lambda() const { return get_info() != nullptr && get_info()->is_lambda(); }
bool is_idempotent() const { return get_info() != nullptr && get_info()->is_idempotent(); }
unsigned get_arity() const { return m_arity; }
sort * get_domain(unsigned idx) const { SASSERT(idx < get_arity()); return m_domain[idx]; }
@ -1522,6 +1526,7 @@ protected:
family_id m_user_sort_family_id;
family_id m_arith_family_id;
ast_table m_ast_table;
obj_map<func_decl, quantifier*> m_lambda_defs;
id_gen m_expr_id_gen;
id_gen m_decl_id_gen;
sort * m_bool_sort;
@ -1651,6 +1656,8 @@ public:
bool is_rec_fun_def(quantifier* q) const { return q->get_qid() == m_rec_fun; }
bool is_lambda_def(quantifier* q) const { return q->get_qid() == m_lambda_def; }
void add_lambda_def(func_decl* f, quantifier* q);
quantifier* is_lambda_def(func_decl* f);
func_decl* get_rec_fun_decl(quantifier* q) const;
symbol const& rec_fun_qid() const { return m_rec_fun; }

View file

@ -122,9 +122,9 @@ app * defined_names::impl::gen_name(expr * e, sort_ref_buffer & var_sorts, buffe
sort * range = m.get_sort(e);
func_decl * new_skolem_decl = m.mk_fresh_func_decl(m_z3name, symbol::null, domain.size(), domain.c_ptr(), range);
app * n = m.mk_app(new_skolem_decl, new_args.size(), new_args.c_ptr());
TRACE("mk_definition_bug", tout << "gen_name: " << mk_ismt2_pp(n, m) << "\n";
for (unsigned i = 0; i < var_sorts.size(); i++) tout << mk_pp(var_sorts[i], m) << " ";
tout << "\n";);
if (is_lambda(e)) {
m.add_lambda_def(new_skolem_decl, to_quantifier(e));
}
return n;
}
@ -203,7 +203,7 @@ void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var
// NB. The pattern is incomplete.
// consider store(a, i, v) == \lambda j . if i = j then v else a[j]
// the instantiation rules for store(a, i, v) are:
// sotre(a, i, v)[j] = if i = j then v else a[j] with patterns {a[j], store(a, i, v)} { store(a, i, v)[j] }
// store(a, i, v)[j] = if i = j then v else a[j] with patterns {a[j], store(a, i, v)} { store(a, i, v)[j] }
// The first pattern is not included.
// TBD use a model-based scheme for exracting instantiations instead of
// using multi-patterns.

View file

@ -27,7 +27,6 @@ Notes:
#include "ast/act_cache.h"
#include "ast/rewriter/var_subst.h"
#include "ast/normal_forms/name_exprs.h"
#include "ast/ast_smt2_pp.h"
/**
@ -754,8 +753,7 @@ struct nnf::imp {
if (fr.m_i == 0) {
fr.m_i = 1;
if (is_lambda(q)) {
if (!visit(q->get_expr(), fr.m_pol, true))
return false;
// skip
}
else if (is_forall(q) == fr.m_pol) {
if (!visit(q->get_expr(), fr.m_pol, true))
@ -769,19 +767,9 @@ struct nnf::imp {
}
if (is_lambda(q)) {
expr * new_expr = m_result_stack.back();
quantifier * new_q = m.update_quantifier(q, new_expr);
proof * new_q_pr = nullptr;
m_result_stack.push_back(q);
if (proofs_enabled()) {
// proof * new_expr_pr = m_result_pr_stack.back();
new_q_pr = m.mk_rewrite(q, new_q); // TBD use new_expr_pr
}
m_result_stack.pop_back();
m_result_stack.push_back(new_q);
if (proofs_enabled()) {
m_result_pr_stack.pop_back();
m_result_pr_stack.push_back(new_q_pr);
m_result_pr_stack.push_back(nullptr);
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
}
return true;
@ -949,7 +937,6 @@ void nnf::get_param_descrs(param_descrs & r) {
imp::get_param_descrs(r);
}
void nnf::reset() {
m_imp->reset();
}