mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
integrate lambda expressions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
bf4edef761
commit
520ce9a5ee
139 changed files with 2243 additions and 1506 deletions
142
src/ast/ast.cpp
142
src/ast/ast.cpp
|
@ -26,6 +26,9 @@ Revision History:
|
|||
#include "util/string_buffer.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/ast_translation.h"
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -360,13 +363,14 @@ app::app(func_decl * decl, unsigned num_args, expr * const * args):
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
quantifier::quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* s,
|
||||
int weight, symbol const & qid, symbol const & skid, unsigned num_patterns, expr * const * patterns,
|
||||
unsigned num_no_patterns, expr * const * no_patterns):
|
||||
expr(AST_QUANTIFIER),
|
||||
m_forall(forall),
|
||||
m_kind(k),
|
||||
m_num_decls(num_decls),
|
||||
m_expr(body),
|
||||
m_sort(s),
|
||||
m_depth(::get_depth(body) + 1),
|
||||
m_weight(weight),
|
||||
m_has_unused_vars(true),
|
||||
|
@ -385,6 +389,25 @@ quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sort
|
|||
memcpy(const_cast<expr **>(get_no_patterns()), no_patterns, sizeof(expr *) * num_no_patterns);
|
||||
}
|
||||
|
||||
quantifier::quantifier(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* s):
|
||||
expr(AST_QUANTIFIER),
|
||||
m_kind(lambda_k),
|
||||
m_num_decls(num_decls),
|
||||
m_expr(body),
|
||||
m_sort(s),
|
||||
m_depth(::get_depth(body) + 1),
|
||||
m_weight(0),
|
||||
m_has_unused_vars(true),
|
||||
m_has_labels(::has_labels(body)),
|
||||
m_qid(symbol()),
|
||||
m_skid(symbol()),
|
||||
m_num_patterns(0),
|
||||
m_num_no_patterns(0) {
|
||||
memcpy(const_cast<sort **>(get_decl_sorts()), decl_sorts, sizeof(sort *) * num_decls);
|
||||
memcpy(const_cast<symbol*>(get_decl_names()), decl_names, sizeof(symbol) * num_decls);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Auxiliary functions
|
||||
|
@ -392,21 +415,16 @@ quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sort
|
|||
// -----------------------------------
|
||||
|
||||
sort * get_sort(expr const * n) {
|
||||
while (true) {
|
||||
switch(n->get_kind()) {
|
||||
case AST_APP:
|
||||
return to_app(n)->get_decl()->get_range();
|
||||
case AST_VAR:
|
||||
return to_var(n)->get_sort();
|
||||
case AST_QUANTIFIER:
|
||||
// The sort of the quantifier is the sort of the nested expression.
|
||||
// This code assumes the given expression is well-sorted.
|
||||
n = to_quantifier(n)->get_expr();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
switch(n->get_kind()) {
|
||||
case AST_APP:
|
||||
return to_app(n)->get_decl()->get_range();
|
||||
case AST_VAR:
|
||||
return to_var(n)->get_sort();
|
||||
case AST_QUANTIFIER:
|
||||
return to_quantifier(n)->get_sort();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,7 +484,7 @@ bool compare_nodes(ast const * n1, ast const * n2) {
|
|||
to_var(n1)->get_sort() == to_var(n2)->get_sort();
|
||||
case AST_QUANTIFIER:
|
||||
return
|
||||
to_quantifier(n1)->is_forall() == to_quantifier(n2)->is_forall() &&
|
||||
to_quantifier(n1)->get_kind() == to_quantifier(n2)->get_kind() &&
|
||||
to_quantifier(n1)->get_num_decls() == to_quantifier(n2)->get_num_decls() &&
|
||||
compare_arrays(to_quantifier(n1)->get_decl_sorts(),
|
||||
to_quantifier(n2)->get_decl_sorts(),
|
||||
|
@ -566,7 +584,7 @@ unsigned get_node_hash(ast const * n) {
|
|||
case AST_QUANTIFIER:
|
||||
a = ast_array_hash(to_quantifier(n)->get_decl_sorts(),
|
||||
to_quantifier(n)->get_num_decls(),
|
||||
to_quantifier(n)->is_forall() ? 31 : 19);
|
||||
to_quantifier(n)->get_kind() == forall_k ? 31 : 19);
|
||||
b = to_quantifier(n)->get_num_patterns();
|
||||
c = to_quantifier(n)->get_expr()->hash();
|
||||
mix(a,b,c);
|
||||
|
@ -689,7 +707,8 @@ bool basic_decl_plugin::check_proof_sorts(basic_op_kind k, unsigned arity, sort
|
|||
for (unsigned i = 0; i < arity - 1; i++)
|
||||
if (domain[i] != m_proof_sort)
|
||||
return false;
|
||||
return domain[arity-1] == m_bool_sort || domain[arity-1] == m_proof_sort;
|
||||
#define is_array(_x_) true
|
||||
return domain[arity-1] == m_bool_sort || domain[arity-1] == m_proof_sort || is_array(domain[arity-1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,7 +723,8 @@ bool basic_decl_plugin::check_proof_args(basic_op_kind k, unsigned num_args, exp
|
|||
return false;
|
||||
return
|
||||
m_manager->get_sort(args[num_args - 1]) == m_bool_sort ||
|
||||
m_manager->get_sort(args[num_args - 1]) == m_proof_sort;
|
||||
m_manager->get_sort(args[num_args - 1]) == m_proof_sort ||
|
||||
is_lambda(args[num_args-1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -818,6 +838,7 @@ func_decl * basic_decl_plugin::mk_proof_decl(basic_op_kind k, unsigned num_paren
|
|||
case PR_TRANSITIVITY_STAR: return mk_proof_decl("trans*", k, num_parents, m_transitivity_star_decls);
|
||||
case PR_MONOTONICITY: return mk_proof_decl("monotonicity", k, num_parents, m_monotonicity_decls);
|
||||
case PR_QUANT_INTRO: return mk_proof_decl("quant-intro", k, 1, m_quant_intro_decl);
|
||||
case PR_BIND: UNREACHABLE();
|
||||
case PR_DISTRIBUTIVITY: return mk_proof_decl("distributivity", k, num_parents, m_distributivity_decls);
|
||||
case PR_AND_ELIM: return mk_proof_decl("and-elim", k, 1, m_and_elim_decl);
|
||||
case PR_NOT_OR_ELIM: return mk_proof_decl("not-or-elim", k, 1, m_not_or_elim_decl);
|
||||
|
@ -1054,6 +1075,10 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
// eq and oeq must have at least two arguments, they can have more since they are chainable
|
||||
case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, join(arity, domain), m_eq_decls) : nullptr;
|
||||
case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(arity, domain), m_oeq_decls) : nullptr;
|
||||
case PR_BIND: {
|
||||
func_decl_info info(m_family_id, PR_BIND);
|
||||
return m_manager->mk_func_decl(symbol("proof-bind"), arity, domain, m_proof_sort, info);
|
||||
}
|
||||
case OP_DISTINCT: {
|
||||
func_decl_info info(m_family_id, OP_DISTINCT);
|
||||
info.set_pairwise();
|
||||
|
@ -1097,6 +1122,11 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(num_args, args), m_oeq_decls) : nullptr;
|
||||
case OP_DISTINCT:
|
||||
return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range);
|
||||
case PR_BIND: {
|
||||
ptr_buffer<sort> sorts;
|
||||
for (unsigned i = 0; i < num_args; ++i) sorts.push_back(m_manager->get_sort(args[i]));
|
||||
return mk_func_decl(k, num_parameters, parameters, num_args, sorts.c_ptr(), range);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1218,7 +1248,6 @@ func_decl * model_value_decl_plugin::mk_func_decl(decl_kind k, unsigned num_para
|
|||
unsigned arity, sort * const * domain, sort * range) {
|
||||
SASSERT(k == OP_MODEL_VALUE);
|
||||
if (arity != 0 || num_parameters != 2 || !parameters[0].is_int() || !parameters[1].is_ast() || !is_sort(parameters[1].get_ast())) {
|
||||
UNREACHABLE();
|
||||
m_manager->raise_exception("invalid model value");
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1290,7 +1319,8 @@ ast_manager::ast_manager(proof_gen_mode m, char const * trace_file, bool is_form
|
|||
m_proof_mode(m),
|
||||
m_trace_stream(nullptr),
|
||||
m_trace_stream_owner(false),
|
||||
m_rec_fun(":rec-fun") {
|
||||
m_rec_fun(":rec-fun"),
|
||||
m_lambda_def(":lambda-def") {
|
||||
|
||||
if (trace_file) {
|
||||
m_trace_stream = alloc(std::fstream, trace_file, std::ios_base::out);
|
||||
|
@ -1312,7 +1342,8 @@ ast_manager::ast_manager(proof_gen_mode m, std::fstream * trace_stream, bool is_
|
|||
m_proof_mode(m),
|
||||
m_trace_stream(trace_stream),
|
||||
m_trace_stream_owner(false),
|
||||
m_rec_fun(":rec-fun") {
|
||||
m_rec_fun(":rec-fun"),
|
||||
m_lambda_def(":lambda-def") {
|
||||
|
||||
if (!is_format_manager)
|
||||
m_format_manager = alloc(ast_manager, PGM_DISABLED, trace_stream, true);
|
||||
|
@ -1508,7 +1539,6 @@ void ast_manager::raise_exception(char const * msg) {
|
|||
throw ast_exception(msg);
|
||||
}
|
||||
|
||||
#include "ast/ast_translation.h"
|
||||
|
||||
void ast_manager::copy_families_plugins(ast_manager const & from) {
|
||||
TRACE("copy_families_plugins",
|
||||
|
@ -1761,6 +1791,7 @@ ast * ast_manager::register_node_core(ast * n) {
|
|||
case AST_QUANTIFIER:
|
||||
inc_array_ref(to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts());
|
||||
inc_ref(to_quantifier(n)->get_expr());
|
||||
inc_ref(to_quantifier(n)->get_sort());
|
||||
inc_array_ref(to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns());
|
||||
inc_array_ref(to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns());
|
||||
break;
|
||||
|
@ -1824,6 +1855,7 @@ void ast_manager::delete_node(ast * n) {
|
|||
case AST_QUANTIFIER:
|
||||
dec_array_ref(worklist, to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts());
|
||||
dec_ref(worklist, to_quantifier(n)->get_expr());
|
||||
dec_ref(worklist, to_quantifier(n)->get_sort());
|
||||
dec_array_ref(worklist, to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns());
|
||||
dec_array_ref(worklist, to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns());
|
||||
break;
|
||||
|
@ -2338,7 +2370,7 @@ bool ast_manager::is_pattern(expr const * n, ptr_vector<expr> &args) {
|
|||
}
|
||||
|
||||
|
||||
quantifier * ast_manager::mk_quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names,
|
||||
quantifier * ast_manager::mk_quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names,
|
||||
expr * body, int weight , symbol const & qid, symbol const & skid,
|
||||
unsigned num_patterns, expr * const * patterns,
|
||||
unsigned num_no_patterns, expr * const * no_patterns) {
|
||||
|
@ -2353,7 +2385,17 @@ quantifier * ast_manager::mk_quantifier(bool forall, unsigned num_decls, sort *
|
|||
}});
|
||||
unsigned sz = quantifier::get_obj_size(num_decls, num_patterns, num_no_patterns);
|
||||
void * mem = allocate_node(sz);
|
||||
quantifier * new_node = new (mem) quantifier(forall, num_decls, decl_sorts, decl_names, body,
|
||||
|
||||
sort* s = nullptr;
|
||||
if (k == lambda_k) {
|
||||
array_util autil(*this);
|
||||
s = autil.mk_array_sort(num_decls, decl_sorts, ::get_sort(body));
|
||||
}
|
||||
else {
|
||||
s = mk_bool_sort();
|
||||
}
|
||||
|
||||
quantifier * new_node = new (mem) quantifier(k, num_decls, decl_sorts, decl_names, body, s,
|
||||
weight, qid, skid, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns);
|
||||
quantifier * r = register_node(new_node);
|
||||
|
@ -2370,6 +2412,18 @@ quantifier * ast_manager::mk_quantifier(bool forall, unsigned num_decls, sort *
|
|||
return r;
|
||||
}
|
||||
|
||||
quantifier * ast_manager::mk_lambda(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body) {
|
||||
SASSERT(body);
|
||||
unsigned sz = quantifier::get_obj_size(num_decls, 0, 0);
|
||||
void * mem = allocate_node(sz);
|
||||
array_util autil(*this);
|
||||
sort* s = autil.mk_array_sort(num_decls, decl_sorts, ::get_sort(body));
|
||||
quantifier * new_node = new (mem) quantifier(num_decls, decl_sorts, decl_names, body, s);
|
||||
quantifier * r = register_node(new_node);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// Return true if the patterns of q are the given ones.
|
||||
static bool same_patterns(quantifier * q, unsigned num_patterns, expr * const * patterns) {
|
||||
if (num_patterns != q->get_num_patterns())
|
||||
|
@ -2393,7 +2447,7 @@ static bool same_no_patterns(quantifier * q, unsigned num_no_patterns, expr * co
|
|||
quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_patterns, expr * const * patterns, expr * body) {
|
||||
if (q->get_expr() == body && same_patterns(q, num_patterns, patterns))
|
||||
return q;
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2410,7 +2464,7 @@ quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_pattern
|
|||
quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_patterns, expr * const * patterns, unsigned num_no_patterns, expr * const * no_patterns, expr * body) {
|
||||
if (q->get_expr() == body && same_patterns(q, num_patterns, patterns) && same_no_patterns(q, num_no_patterns, no_patterns))
|
||||
return q;
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2427,7 +2481,7 @@ quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_pattern
|
|||
quantifier * ast_manager::update_quantifier(quantifier * q, expr * body) {
|
||||
if (q->get_expr() == body)
|
||||
return q;
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2445,7 +2499,7 @@ quantifier * ast_manager::update_quantifier_weight(quantifier * q, int w) {
|
|||
if (q->get_weight() == w)
|
||||
return q;
|
||||
TRACE("update_quantifier_weight", tout << "#" << q->get_id() << " " << q->get_weight() << " -> " << w << "\n";);
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2459,10 +2513,10 @@ quantifier * ast_manager::update_quantifier_weight(quantifier * q, int w) {
|
|||
q->get_no_patterns());
|
||||
}
|
||||
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, bool is_forall, expr * body) {
|
||||
if (q->get_expr() == body && q->is_forall() == is_forall)
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, quantifier_kind k, expr * body) {
|
||||
if (q->get_expr() == body && q->get_kind() == k)
|
||||
return q;
|
||||
return mk_quantifier(is_forall,
|
||||
return mk_quantifier(k,
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2476,10 +2530,10 @@ quantifier * ast_manager::update_quantifier(quantifier * q, bool is_forall, expr
|
|||
q->get_no_patterns());
|
||||
}
|
||||
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, bool is_forall, unsigned num_patterns, expr * const * patterns, expr * body) {
|
||||
if (q->get_expr() == body && q->is_forall() == is_forall && same_patterns(q, num_patterns, patterns))
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, quantifier_kind k, unsigned num_patterns, expr * const * patterns, expr * body) {
|
||||
if (q->get_expr() == body && q->get_kind() == k && same_patterns(q, num_patterns, patterns))
|
||||
return q;
|
||||
return mk_quantifier(is_forall,
|
||||
return mk_quantifier(k,
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2786,11 +2840,17 @@ proof * ast_manager::mk_oeq_congruence(app * f1, app * f2, unsigned num_proofs,
|
|||
return mk_monotonicity(mk_func_decl(m_basic_family_id, OP_OEQ, 0, nullptr, 2, d), f1, f2, num_proofs, proofs);
|
||||
}
|
||||
|
||||
|
||||
proof * ast_manager::mk_bind_proof(quantifier * q, proof * p) {
|
||||
expr* b = mk_lambda(q->get_num_decls(), q->get_decl_sorts(), q->get_decl_names(), p);
|
||||
return mk_app(m_basic_family_id, PR_BIND, b);
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_quant_intro(quantifier * q1, quantifier * q2, proof * p) {
|
||||
if (!p) return nullptr;
|
||||
SASSERT(q1->get_num_decls() == q2->get_num_decls());
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_eq(get_fact(p)));
|
||||
if (!p) return nullptr;
|
||||
SASSERT(q1->get_num_decls() == q2->get_num_decls());
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_eq(get_fact(p)) || is_lambda(get_fact(p)));
|
||||
return mk_app(m_basic_family_id, PR_QUANT_INTRO, p, mk_iff(q1, q2));
|
||||
}
|
||||
|
||||
|
|
|
@ -793,11 +793,18 @@ public:
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
enum quantifier_kind {
|
||||
forall_k,
|
||||
exists_k,
|
||||
lambda_k
|
||||
};
|
||||
|
||||
class quantifier : public expr {
|
||||
friend class ast_manager;
|
||||
bool m_forall;
|
||||
quantifier_kind m_kind;
|
||||
unsigned m_num_decls;
|
||||
expr * m_expr;
|
||||
sort * m_sort;
|
||||
unsigned m_depth;
|
||||
// extra fields
|
||||
int m_weight;
|
||||
|
@ -813,12 +820,18 @@ class quantifier : public expr {
|
|||
return sizeof(quantifier) + num_decls * (sizeof(sort *) + sizeof(symbol)) + (num_patterns + num_no_patterns) * sizeof(expr*);
|
||||
}
|
||||
|
||||
quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* s,
|
||||
int weight, symbol const & qid, symbol const & skid, unsigned num_patterns, expr * const * patterns,
|
||||
unsigned num_no_patterns, expr * const * no_patterns);
|
||||
|
||||
quantifier(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* sort);
|
||||
|
||||
public:
|
||||
bool is_forall() const { return m_forall; }
|
||||
bool is_exists() const { return !m_forall; }
|
||||
quantifier_kind get_kind() const { return m_kind; }
|
||||
// bool is_forall() const { return m_kind == forall_k; }
|
||||
// bool is_exists() const { return m_kind == exists_k; }
|
||||
// bool is_lambda() const { return m_kind == lambda_k; }
|
||||
|
||||
unsigned get_num_decls() const { return m_num_decls; }
|
||||
sort * const * get_decl_sorts() const { return reinterpret_cast<sort * const *>(m_patterns_decls); }
|
||||
symbol const * get_decl_names() const { return reinterpret_cast<symbol const *>(get_decl_sorts() + m_num_decls); }
|
||||
|
@ -826,6 +839,8 @@ public:
|
|||
symbol const & get_decl_name(unsigned idx) const { return get_decl_names()[idx]; }
|
||||
expr * get_expr() const { return m_expr; }
|
||||
|
||||
sort * get_sort() const { return m_sort; }
|
||||
|
||||
unsigned get_depth() const { return m_depth; }
|
||||
|
||||
int get_weight() const { return m_weight; }
|
||||
|
@ -844,6 +859,7 @@ public:
|
|||
void set_no_unused_vars() { m_has_unused_vars = false; }
|
||||
|
||||
bool has_labels() const { return m_has_labels; }
|
||||
|
||||
|
||||
unsigned get_num_children() const { return 1 + get_num_patterns() + get_num_no_patterns(); }
|
||||
expr * get_child(unsigned idx) const {
|
||||
|
@ -871,8 +887,9 @@ inline bool is_app(ast const * n) { return n->get_kind() == AST_APP; }
|
|||
inline bool is_var(ast const * n) { return n->get_kind() == AST_VAR; }
|
||||
inline bool is_var(ast const * n, unsigned& idx) { return is_var(n) && (idx = static_cast<var const*>(n)->get_idx(), true); }
|
||||
inline bool is_quantifier(ast const * n) { return n->get_kind() == AST_QUANTIFIER; }
|
||||
inline bool is_forall(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->is_forall(); }
|
||||
inline bool is_exists(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->is_exists(); }
|
||||
inline bool is_forall(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->get_kind() == forall_k; }
|
||||
inline bool is_exists(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->get_kind() == exists_k; }
|
||||
inline bool is_lambda(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->get_kind() == lambda_k; }
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -950,7 +967,7 @@ protected:
|
|||
family_id m_family_id;
|
||||
|
||||
virtual void set_manager(ast_manager * m, family_id id) {
|
||||
SASSERT(m_manager == 0);
|
||||
SASSERT(m_manager == nullptr);
|
||||
m_manager = m;
|
||||
m_family_id = id;
|
||||
}
|
||||
|
@ -1043,7 +1060,7 @@ enum basic_sort_kind {
|
|||
enum basic_op_kind {
|
||||
OP_TRUE, OP_FALSE, OP_EQ, OP_DISTINCT, OP_ITE, OP_AND, OP_OR, OP_XOR, OP_NOT, OP_IMPLIES, OP_OEQ, LAST_BASIC_OP,
|
||||
|
||||
PR_UNDEF, PR_TRUE, PR_ASSERTED, PR_GOAL, PR_MODUS_PONENS, PR_REFLEXIVITY, PR_SYMMETRY, PR_TRANSITIVITY, PR_TRANSITIVITY_STAR, PR_MONOTONICITY, PR_QUANT_INTRO,
|
||||
PR_UNDEF, PR_TRUE, PR_ASSERTED, PR_GOAL, PR_MODUS_PONENS, PR_REFLEXIVITY, PR_SYMMETRY, PR_TRANSITIVITY, PR_TRANSITIVITY_STAR, PR_MONOTONICITY, PR_QUANT_INTRO, PR_BIND,
|
||||
PR_DISTRIBUTIVITY, PR_AND_ELIM, PR_NOT_OR_ELIM, PR_REWRITE, PR_REWRITE_STAR, PR_PULL_QUANT,
|
||||
PR_PUSH_QUANT, PR_ELIM_UNUSED_VARS, PR_DER, PR_QUANT_INST,
|
||||
|
||||
|
@ -1487,6 +1504,7 @@ protected:
|
|||
#endif
|
||||
ast_manager * m_format_manager; // hack for isolating format objects in a different manager.
|
||||
symbol m_rec_fun;
|
||||
symbol m_lambda_def;
|
||||
|
||||
void init();
|
||||
|
||||
|
@ -1594,9 +1612,12 @@ public:
|
|||
bool contains(ast * a) const { return m_ast_table.contains(a); }
|
||||
|
||||
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; }
|
||||
|
||||
symbol const& rec_fun_qid() const { return m_rec_fun; }
|
||||
|
||||
symbol const& lambda_def_qid() const { return m_lambda_def; }
|
||||
|
||||
unsigned get_num_asts() const { return m_ast_table.size(); }
|
||||
|
||||
void debug_ref_count() { m_debug_ref_count = true; }
|
||||
|
@ -1892,7 +1913,7 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
quantifier * mk_quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
quantifier * mk_quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
int weight = 0, symbol const & qid = symbol::null, symbol const & skid = symbol::null,
|
||||
unsigned num_patterns = 0, expr * const * patterns = nullptr,
|
||||
unsigned num_no_patterns = 0, expr * const * no_patterns = nullptr);
|
||||
|
@ -1901,7 +1922,7 @@ public:
|
|||
int weight = 0, symbol const & qid = symbol::null, symbol const & skid = symbol::null,
|
||||
unsigned num_patterns = 0, expr * const * patterns = nullptr,
|
||||
unsigned num_no_patterns = 0, expr * const * no_patterns = nullptr) {
|
||||
return mk_quantifier(true, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
return mk_quantifier(forall_k, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns);
|
||||
}
|
||||
|
||||
|
@ -1909,10 +1930,12 @@ public:
|
|||
int weight = 0, symbol const & qid = symbol::null, symbol const & skid = symbol::null,
|
||||
unsigned num_patterns = 0, expr * const * patterns = nullptr,
|
||||
unsigned num_no_patterns = 0, expr * const * no_patterns = nullptr) {
|
||||
return mk_quantifier(false, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
return mk_quantifier(exists_k, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns);
|
||||
}
|
||||
|
||||
quantifier * mk_lambda(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, unsigned new_num_patterns, expr * const * new_patterns, expr * new_body);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, unsigned new_num_patterns, expr * const * new_patterns, unsigned new_num_no_patterns, expr * const * new_no_patterns, expr * new_body);
|
||||
|
@ -1921,9 +1944,9 @@ public:
|
|||
|
||||
quantifier * update_quantifier_weight(quantifier * q, int new_weight);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, bool new_is_forall, expr * new_body);
|
||||
quantifier * update_quantifier(quantifier * q, quantifier_kind new_kind, expr * new_body);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, bool new_is_forall, unsigned new_num_patterns, expr * const * new_patterns, expr * new_body);
|
||||
quantifier * update_quantifier(quantifier * q, quantifier_kind new_kind, unsigned new_num_patterns, expr * const * new_patterns, expr * new_body);
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -2213,6 +2236,7 @@ public:
|
|||
proof * mk_rewrite(expr * s, expr * t);
|
||||
proof * mk_oeq_rewrite(expr * s, expr * t);
|
||||
proof * mk_rewrite_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs);
|
||||
proof * mk_bind_proof(quantifier * q, proof * p);
|
||||
proof * mk_pull_quant(expr * e, quantifier * q);
|
||||
proof * mk_push_quant(quantifier * q, expr * e);
|
||||
proof * mk_elim_unused_vars(quantifier * q, expr * r);
|
||||
|
|
|
@ -242,7 +242,7 @@ public:
|
|||
|
||||
void operator()(quantifier * n) {
|
||||
display_def_header(n);
|
||||
m_out << "(" << (n->is_forall() ? "forall" : "exists") << " ";
|
||||
m_out << "(" << (n->get_kind() == forall_k ? "forall" : (n->get_kind() == exists_k ? "exists" : "lambda")) << " ";
|
||||
unsigned num_decls = n->get_num_decls();
|
||||
m_out << "(vars ";
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
|
|
|
@ -102,7 +102,7 @@ bool lt(ast * n1, ast * n2) {
|
|||
UNREACHABLE();
|
||||
return false;
|
||||
case AST_QUANTIFIER:
|
||||
check_bool(to_quantifier(n1)->is_forall(), to_quantifier(n2)->is_forall());
|
||||
check_value(to_quantifier(n1)->get_kind(), to_quantifier(n2)->get_kind());
|
||||
check_value(to_quantifier(n1)->get_num_decls(), to_quantifier(n2)->get_num_decls());
|
||||
check_value(to_quantifier(n1)->get_num_patterns(), to_quantifier(n2)->get_num_patterns());
|
||||
check_value(to_quantifier(n1)->get_num_no_patterns(), to_quantifier(n2)->get_num_no_patterns());
|
||||
|
|
|
@ -994,7 +994,7 @@ class smt2_printer {
|
|||
}
|
||||
format * f_decls = pp_var_decls(q);
|
||||
format * fs[2] = { f_decls, f_body };
|
||||
char const * header = q->is_forall() ? "forall" : "exists";
|
||||
char const * header = q->get_kind() == forall_k ? "forall" : (q->get_kind() == exists_k ? "exists" : "lambda");
|
||||
format * f = mk_seq3<format**, f2f>(m(), fs, fs+2, f2f(), header, 1, SMALL_INDENT);
|
||||
|
||||
info f_info = m_info_stack.back();
|
||||
|
|
|
@ -495,11 +495,10 @@ class smt_printer {
|
|||
m_qlists.push_back(q);
|
||||
|
||||
m_out << "(";
|
||||
if (q->is_forall()) {
|
||||
m_out << "forall ";
|
||||
}
|
||||
else {
|
||||
m_out << "exists ";
|
||||
switch (q->get_kind()) {
|
||||
case forall_k: m_out << "forall "; break;
|
||||
case exists_k: m_out << "exists "; break;
|
||||
case lambda_k: m_out << "lambda "; break;
|
||||
}
|
||||
m_out << "(";
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
|
|
|
@ -279,7 +279,7 @@ ast * ast_translation::process(ast const * _n) {
|
|||
expr ** pats = reinterpret_cast<expr**>(m_result_stack.c_ptr() + fr.m_rpos + num_decls + 1);
|
||||
unsigned num_no_pats = to_quantifier(n)->get_num_no_patterns();
|
||||
expr ** no_pats = pats + num_pats;
|
||||
quantifier * new_q = m_to_manager.mk_quantifier(to_quantifier(n)->is_forall(),
|
||||
quantifier * new_q = m_to_manager.mk_quantifier(to_quantifier(n)->get_kind(),
|
||||
num_decls,
|
||||
dsorts,
|
||||
dnames,
|
||||
|
|
|
@ -115,7 +115,7 @@ void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* cons
|
|||
tout << result << "\n";);
|
||||
}
|
||||
|
||||
expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
expr_ref mk_quantifier(quantifier_kind k, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
expr_ref result(m);
|
||||
expr_abstract(m, 0, num_bound, (expr* const*)bound, n, result);
|
||||
if (num_bound > 0) {
|
||||
|
@ -125,7 +125,7 @@ expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app*
|
|||
sorts.push_back(m.get_sort(bound[i]));
|
||||
names.push_back(bound[i]->get_decl()->get_name());
|
||||
}
|
||||
result = m.mk_quantifier(is_forall, num_bound, sorts.c_ptr(), names.c_ptr(), result);
|
||||
result = m.mk_quantifier(k, num_bound, sorts.c_ptr(), names.c_ptr(), result);
|
||||
}
|
||||
TRACE("expr_abstract",
|
||||
tout << expr_ref(n, m) << "\n";
|
||||
|
@ -137,9 +137,9 @@ expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app*
|
|||
}
|
||||
|
||||
expr_ref mk_forall(ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
return mk_quantifier(true, m, num_bound, bound, n);
|
||||
return mk_quantifier(forall_k, m, num_bound, bound, n);
|
||||
}
|
||||
|
||||
expr_ref mk_exists(ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
return mk_quantifier(false, m, num_bound, bound, n);
|
||||
return mk_quantifier(exists_k, m, num_bound, bound, n);
|
||||
}
|
||||
|
|
|
@ -194,6 +194,9 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
|||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
if (is_lambda(old_q)) {
|
||||
return false;
|
||||
}
|
||||
unsigned curr_sz = m_bindings.size();
|
||||
SASSERT(old_q->get_num_decls() <= curr_sz);
|
||||
unsigned num_decls = old_q->get_num_decls();
|
||||
|
@ -217,7 +220,7 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
|||
new_decl_names.push_back(n);
|
||||
}
|
||||
}
|
||||
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
result = m().mk_quantifier(old_q->get_kind(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = nullptr;
|
||||
|
|
|
@ -23,7 +23,7 @@ Revision History:
|
|||
#include "ast/ast_ll_pp.h"
|
||||
|
||||
bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
TRACE("macro_finder", tout << "processing: " << mk_pp(n, m) << "\n";);
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
|
@ -46,7 +46,7 @@ bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
|
|||
For case 2 & 3, the new quantifiers are stored in new_exprs and new_prs.
|
||||
*/
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
|
@ -117,7 +117,7 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_dependency * dep, e
|
|||
}
|
||||
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, vector<justified_expr>& new_fmls) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
|
|
|
@ -283,13 +283,11 @@ struct macro_manager::macro_expander_cfg : public default_rewriter_cfg {
|
|||
subst_args[nidx] = n->get_arg(i);
|
||||
}
|
||||
var_subst s(m);
|
||||
expr_ref rr(m);
|
||||
s(def, num, subst_args.c_ptr(), rr);
|
||||
expr_ref rr = s(def, num, subst_args.c_ptr());
|
||||
m_trail.push_back(rr);
|
||||
r = rr;
|
||||
if (m.proofs_enabled()) {
|
||||
expr_ref instance(m);
|
||||
s(q->get_expr(), num, subst_args.c_ptr(), instance);
|
||||
expr_ref instance = s(q->get_expr(), num, subst_args.c_ptr());
|
||||
proof * qi_pr = m.mk_quant_inst(m.mk_or(m.mk_not(q), instance), num, subst_args.c_ptr());
|
||||
proof * q_pr = nullptr;
|
||||
mm.m_decl2macro_pr.find(d, q_pr);
|
||||
|
|
|
@ -334,7 +334,7 @@ bool macro_util::is_pseudo_head(expr * n, unsigned num_decls, app_ref & head, ap
|
|||
where t is a ground term, (f X) is the head.
|
||||
*/
|
||||
bool macro_util::is_pseudo_predicate_macro(expr * n, app_ref & head, app_ref & t, expr_ref & def) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
TRACE("macro_util", tout << "processing: " << mk_pp(n, m_manager) << "\n";);
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
|
@ -485,7 +485,7 @@ void macro_util::normalize_expr(app * head, unsigned num_decls, expr * t, expr_r
|
|||
if (var_mapping[i] != 0)
|
||||
tout << "#" << i << " -> " << mk_ll_pp(var_mapping[i], m_manager);
|
||||
});
|
||||
subst(t, var_mapping.size(), var_mapping.c_ptr(), norm_t);
|
||||
norm_t = subst(t, var_mapping.size(), var_mapping.c_ptr());
|
||||
}
|
||||
else {
|
||||
norm_t = t;
|
||||
|
|
|
@ -155,7 +155,7 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
|||
// f[X] contains all universally quantified variables, and f does not occur in T[X].
|
||||
TRACE("quasi_macros", tout << "Checking for quasi macro: " << mk_pp(e, m_manager) << std::endl;);
|
||||
|
||||
if (is_quantifier(e) && to_quantifier(e)->is_forall()) {
|
||||
if (is_forall(e)) {
|
||||
quantifier * q = to_quantifier(e);
|
||||
expr * qe = q->get_expr();
|
||||
if ((m_manager.is_eq(qe))) {
|
||||
|
@ -251,7 +251,7 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
|||
|
||||
eq = m_manager.mk_eq(appl, ite);
|
||||
|
||||
macro = m_manager.mk_quantifier(true, new_var_names_rev.size(),
|
||||
macro = m_manager.mk_quantifier(forall_k, new_var_names_rev.size(),
|
||||
new_qsorts_rev.c_ptr(), new_var_names_rev.c_ptr(), eq);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,17 +16,19 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
#include "ast/used_vars.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
|
||||
struct defined_names::impl {
|
||||
typedef obj_map<expr, app *> expr2name;
|
||||
typedef obj_map<expr, proof *> expr2proof;
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
symbol m_z3name;
|
||||
|
||||
/**
|
||||
|
@ -60,9 +62,9 @@ struct defined_names::impl {
|
|||
app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer<symbol> & var_names);
|
||||
void cache_new_name(expr * e, app * name);
|
||||
void cache_new_name_intro_proof(expr * e, proof * pr);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result);
|
||||
virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result, symbol const& qid = symbol::null);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result, symbol const& qid = symbol::null);
|
||||
virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def);
|
||||
bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
|
||||
void push_scope();
|
||||
void pop_scope(unsigned num_scopes);
|
||||
|
@ -74,12 +76,13 @@ struct defined_names::impl {
|
|||
|
||||
struct defined_names::pos_impl : public defined_names::impl {
|
||||
pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {}
|
||||
void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def) override;
|
||||
void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
defined_names::impl::impl(ast_manager & m, char const * prefix):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_exprs(m),
|
||||
m_names(m),
|
||||
m_apply_proofs(m) {
|
||||
|
@ -107,20 +110,20 @@ app * defined_names::impl::gen_name(expr * e, sort_ref_buffer & var_sorts, buffe
|
|||
sort * s = uv.get(i);
|
||||
if (s) {
|
||||
domain.push_back(s);
|
||||
new_args.push_back(m_manager.mk_var(i, s));
|
||||
new_args.push_back(m.mk_var(i, s));
|
||||
var_sorts.push_back(s);
|
||||
}
|
||||
else {
|
||||
var_sorts.push_back(m_manager.mk_bool_sort()); // could be any sort.
|
||||
var_sorts.push_back(m.mk_bool_sort()); // could be any sort.
|
||||
}
|
||||
var_names.push_back(symbol(i));
|
||||
}
|
||||
|
||||
sort * range = m_manager.get_sort(e);
|
||||
func_decl * new_skolem_decl = m_manager.mk_fresh_func_decl(m_z3name, symbol::null, domain.size(), domain.c_ptr(), range);
|
||||
app * n = m_manager.mk_app(new_skolem_decl, new_args.size(), new_args.c_ptr());
|
||||
TRACE("mk_definition_bug", tout << "gen_name: " << mk_ismt2_pp(n, m_manager) << "\n";
|
||||
for (unsigned i = 0; i < var_sorts.size(); i++) tout << mk_pp(var_sorts[i], m_manager) << " ";
|
||||
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";);
|
||||
return n;
|
||||
}
|
||||
|
@ -148,22 +151,22 @@ void defined_names::impl::cache_new_name_intro_proof(expr * e, proof * pr) {
|
|||
A quantifier is added around \c def_conjunct, if sorts and names are not empty.
|
||||
In this case, The application \c name is used as a pattern for the new quantifier.
|
||||
*/
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result) {
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result, symbol const& qid) {
|
||||
SASSERT(sorts.size() == names.size());
|
||||
if (sorts.empty())
|
||||
result = def_conjunct;
|
||||
else {
|
||||
expr * patterns[1] = { m_manager.mk_pattern(name) };
|
||||
quantifier_ref q(m_manager);
|
||||
q = m_manager.mk_forall(sorts.size(),
|
||||
expr * patterns[1] = { m.mk_pattern(name) };
|
||||
quantifier_ref q(m);
|
||||
q = m.mk_forall(sorts.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
def_conjunct,
|
||||
1, symbol::null, symbol::null,
|
||||
1, qid, symbol::null,
|
||||
1, patterns);
|
||||
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m_manager) << "\n";);
|
||||
elim_unused_vars(m_manager, q, params_ref(), result);
|
||||
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m) << "\n";);
|
||||
result = elim_unused_vars(m, q, params_ref());
|
||||
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << result << "\n";);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,44 +175,81 @@ void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbo
|
|||
A quantifier is added around \c def_conjunct, if sorts and names are not empty.
|
||||
In this case, The application \c name is used as a pattern for the new quantifier.
|
||||
*/
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result) {
|
||||
expr_ref tmp(m_manager);
|
||||
bound_vars(sorts, names, def_conjunct, name, tmp);
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result, symbol const& qid) {
|
||||
expr_ref tmp(m);
|
||||
bound_vars(sorts, names, def_conjunct, name, tmp, qid);
|
||||
result.push_back(tmp);
|
||||
}
|
||||
|
||||
#define MK_OR m_manager.mk_or
|
||||
#define MK_NOT m_manager.mk_not
|
||||
#define MK_EQ m_manager.mk_eq
|
||||
#define MK_OR m.mk_or
|
||||
#define MK_NOT m.mk_not
|
||||
#define MK_EQ m.mk_eq
|
||||
|
||||
void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def) {
|
||||
expr_ref_buffer defs(m_manager);
|
||||
if (m_manager.is_bool(e)) {
|
||||
void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def) {
|
||||
expr_ref_buffer defs(m);
|
||||
if (m.is_bool(e)) {
|
||||
bound_vars(var_sorts, var_names, MK_OR(MK_NOT(n), e), n, defs);
|
||||
bound_vars(var_sorts, var_names, MK_OR(n, MK_NOT(e)), n, defs);
|
||||
}
|
||||
else if (m_manager.is_term_ite(e)) {
|
||||
else if (m.is_term_ite(e)) {
|
||||
bound_vars(var_sorts, var_names, MK_OR(MK_NOT(to_app(e)->get_arg(0)), MK_EQ(n, to_app(e)->get_arg(1))), n, defs);
|
||||
bound_vars(var_sorts, var_names, MK_OR(to_app(e)->get_arg(0), MK_EQ(n, to_app(e)->get_arg(2))), n, defs);
|
||||
}
|
||||
else if (is_lambda(e)) {
|
||||
// n(y) = \x . M[x,y]
|
||||
// =>
|
||||
// n(y)[x] = M, forall x y
|
||||
//
|
||||
// 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] }
|
||||
// The first pattern is not included.
|
||||
// TBD use a model-based scheme for exracting instantiations instead of
|
||||
// using multi-patterns.
|
||||
//
|
||||
|
||||
quantifier* q = to_quantifier(e);
|
||||
expr_ref_vector args(m);
|
||||
expr_ref n2(m), n3(m);
|
||||
var_shifter vs(m);
|
||||
vs(n, q->get_num_decls(), n2);
|
||||
args.push_back(n2);
|
||||
var_sorts.append(q->get_num_decls(), q->get_decl_sorts());
|
||||
var_names.append(q->get_num_decls(), q->get_decl_names());
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
args.push_back(m.mk_var(q->get_num_decls() - i - 1, q->get_decl_sort(i)));
|
||||
}
|
||||
array_util autil(m);
|
||||
func_decl * f = 0;
|
||||
if (autil.is_as_array(n2, f)) {
|
||||
n3 = m.mk_app(f, args.size()-1, args.c_ptr() + 1);
|
||||
}
|
||||
else {
|
||||
n3 = autil.mk_select(args.size(), args.c_ptr());
|
||||
}
|
||||
bound_vars(var_sorts, var_names, MK_EQ(q->get_expr(), n3), to_app(n3), defs, m.lambda_def_qid());
|
||||
|
||||
}
|
||||
else {
|
||||
bound_vars(var_sorts, var_names, MK_EQ(e, n), n, defs);
|
||||
}
|
||||
new_def = defs.size() == 1 ? defs[0] : m_manager.mk_and(defs.size(), defs.c_ptr());
|
||||
new_def = mk_and(m, defs.size(), defs.c_ptr());
|
||||
}
|
||||
|
||||
void defined_names::pos_impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def) {
|
||||
|
||||
void defined_names::pos_impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def) {
|
||||
bound_vars(var_sorts, var_names, MK_OR(MK_NOT(n), e), n, new_def);
|
||||
}
|
||||
|
||||
bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) {
|
||||
TRACE("mk_definition_bug", tout << "making name for:\n" << mk_ismt2_pp(e, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "making name for:\n" << mk_ismt2_pp(e, m) << "\n";);
|
||||
|
||||
app * n_ptr;
|
||||
if (m_expr2name.find(e, n_ptr)) {
|
||||
TRACE("mk_definition_bug", tout << "name for expression is already cached..., returning false...\n";);
|
||||
n = n_ptr;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
if (m.proofs_enabled()) {
|
||||
proof * pr_ptr = nullptr;
|
||||
m_expr2proof.find(e, pr_ptr);
|
||||
SASSERT(pr_ptr);
|
||||
|
@ -218,24 +258,24 @@ bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_
|
|||
return false;
|
||||
}
|
||||
else {
|
||||
sort_ref_buffer var_sorts(m_manager);
|
||||
sort_ref_buffer var_sorts(m);
|
||||
buffer<symbol> var_names;
|
||||
|
||||
n = gen_name(e, var_sorts, var_names);
|
||||
cache_new_name(e, n);
|
||||
|
||||
TRACE("mk_definition_bug", tout << "name: " << mk_ismt2_pp(n, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "name: " << mk_ismt2_pp(n, m) << "\n";);
|
||||
// variables are in reverse order in quantifiers
|
||||
std::reverse(var_sorts.c_ptr(), var_sorts.c_ptr() + var_sorts.size());
|
||||
std::reverse(var_names.c_ptr(), var_names.c_ptr() + var_names.size());
|
||||
|
||||
mk_definition(e, n, var_sorts, var_names, new_def);
|
||||
|
||||
TRACE("mk_definition_bug", tout << "new_def:\n" << mk_ismt2_pp(new_def, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "new_def:\n" << mk_ismt2_pp(new_def, m) << "\n";);
|
||||
|
||||
if (m_manager.proofs_enabled()) {
|
||||
new_def_pr = m_manager.mk_def_intro(new_def);
|
||||
pr = m_manager.mk_apply_def(e, n, new_def_pr);
|
||||
if (m.proofs_enabled()) {
|
||||
new_def_pr = m.mk_def_intro(new_def);
|
||||
pr = m.mk_apply_def(e, n, new_def_pr);
|
||||
cache_new_name_intro_proof(e, pr);
|
||||
}
|
||||
return true;
|
||||
|
@ -257,7 +297,7 @@ void defined_names::impl::pop_scope(unsigned num_scopes) {
|
|||
SASSERT(sz == m_names.size());
|
||||
while (old_sz != sz) {
|
||||
--sz;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
if (m.proofs_enabled()) {
|
||||
m_expr2proof.erase(m_exprs.back());
|
||||
m_apply_proofs.pop_back();
|
||||
}
|
||||
|
@ -296,6 +336,15 @@ bool defined_names::mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_de
|
|||
return m_pos_impl->mk_name(e, new_def, new_def_pr, n, pr);
|
||||
}
|
||||
|
||||
expr_ref defined_names::mk_definition(expr * e, app * n) {
|
||||
ast_manager& m = m_impl->m;
|
||||
sort_ref_buffer var_sorts(m);
|
||||
expr_ref new_def(m);
|
||||
buffer<symbol> var_names;
|
||||
m_impl->mk_definition(e, n, var_sorts, var_names, new_def);
|
||||
return new_def;
|
||||
}
|
||||
|
||||
void defined_names::push() {
|
||||
m_impl->push_scope();
|
||||
m_pos_impl->push_scope();
|
||||
|
|
|
@ -77,6 +77,11 @@ public:
|
|||
*/
|
||||
bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
|
||||
|
||||
/**
|
||||
\brief Create a definition for 'n' using 'e'.
|
||||
*/
|
||||
expr_ref mk_definition(expr * e, app * n);
|
||||
|
||||
void push();
|
||||
void pop(unsigned num_scopes);
|
||||
void reset();
|
||||
|
|
|
@ -22,7 +22,7 @@ Notes:
|
|||
|
||||
class name_exprs_core : public name_exprs {
|
||||
struct cfg : public default_rewriter_cfg {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
defined_names & m_defined_names;
|
||||
expr_predicate & m_pred;
|
||||
|
||||
|
@ -33,7 +33,7 @@ class name_exprs_core : public name_exprs {
|
|||
proof_ref_vector * m_def_proofs;
|
||||
|
||||
cfg(ast_manager & m, defined_names & n, expr_predicate & pred):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_defined_names(n),
|
||||
m_pred(pred),
|
||||
m_r(m),
|
||||
|
@ -43,12 +43,12 @@ class name_exprs_core : public name_exprs {
|
|||
}
|
||||
|
||||
void gen_name_for_expr(expr * n, expr * & t, proof * & t_pr) {
|
||||
expr_ref new_def(m_manager);
|
||||
proof_ref new_def_pr(m_manager);
|
||||
expr_ref new_def(m);
|
||||
proof_ref new_def_pr(m);
|
||||
|
||||
if (m_defined_names.mk_name(n, new_def, new_def_pr, m_r, m_pr)) {
|
||||
m_def_exprs->push_back(new_def);
|
||||
if (m_manager.proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
m_def_proofs->push_back(new_def_pr);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class name_exprs_core : public name_exprs {
|
|||
}
|
||||
|
||||
bool get_subst(expr * s, expr * & t, proof * & t_pr) {
|
||||
TRACE("name_exprs", tout << "get_subst:\n" << mk_ismt2_pp(s, m_manager) << "\n";);
|
||||
TRACE("name_exprs", tout << "get_subst:\n" << mk_ismt2_pp(s, m) << "\n";);
|
||||
if (m_pred(s)) {
|
||||
gen_name_for_expr(s, t, t_pr);
|
||||
return true;
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
m_cfg.m_def_exprs = &new_defs;
|
||||
m_cfg.m_def_proofs = &new_def_proofs;
|
||||
m_rw(n, r, p);
|
||||
TRACE("name_exprs", tout << mk_ismt2_pp(n, m_rw.m()) << "\n---->\n" << mk_ismt2_pp(r, m_rw.m()) << "\n";);
|
||||
TRACE("name_exprs", tout << mk_ismt2_pp(n, m_rw.m()) << "\n---->\n" << r << "\n";);
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,11 +99,11 @@ name_exprs * mk_expr_namer(ast_manager & m, defined_names & n, expr_predicate &
|
|||
|
||||
class name_quantifier_labels : public name_exprs_core {
|
||||
class pred : public expr_predicate {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
public:
|
||||
pred(ast_manager & m):m_manager(m) {}
|
||||
pred(ast_manager & m):m(m) {}
|
||||
bool operator()(expr * t) override {
|
||||
return is_quantifier(t) || m_manager.is_label(t);
|
||||
return is_quantifier(t) || m.is_label(t);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -124,16 +124,16 @@ name_exprs * mk_quantifier_label_namer(ast_manager & m, defined_names & n) {
|
|||
|
||||
class name_nested_formulas : public name_exprs_core {
|
||||
struct pred : public expr_predicate {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
expr * m_root;
|
||||
|
||||
pred(ast_manager & m):m_manager(m), m_root(nullptr) {}
|
||||
pred(ast_manager & m):m(m), m_root(0) {}
|
||||
|
||||
bool operator()(expr * t) override {
|
||||
TRACE("name_exprs", tout << "name_nested_formulas::pred:\n" << mk_ismt2_pp(t, m_manager) << "\n";);
|
||||
TRACE("name_exprs", tout << "name_nested_formulas::pred:\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
if (is_app(t))
|
||||
return to_app(t)->get_family_id() == m_manager.get_basic_family_id() && to_app(t)->get_num_args() > 0 && t != m_root;
|
||||
return m_manager.is_label(t) || is_quantifier(t);
|
||||
return to_app(t)->get_family_id() == m.get_basic_family_id() && to_app(t)->get_num_args() > 0 && t != m_root;
|
||||
return m.is_label(t) || is_quantifier(t);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -17,16 +17,16 @@ Notes:
|
|||
Major revision on 2011-10-06
|
||||
|
||||
--*/
|
||||
|
||||
#include "util/warning.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/normal_forms/nnf.h"
|
||||
#include "ast/normal_forms/nnf_params.hpp"
|
||||
#include "util/warning.h"
|
||||
#include "ast/used_vars.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
#include "ast/normal_forms/name_exprs.h"
|
||||
#include "ast/act_cache.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/normal_forms/name_exprs.h"
|
||||
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
|
@ -67,36 +67,42 @@ enum nnf_mode {
|
|||
class skolemizer {
|
||||
typedef act_cache cache;
|
||||
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
symbol m_sk_hack;
|
||||
bool m_sk_hack_enabled;
|
||||
cache m_cache;
|
||||
cache m_cache_pr;
|
||||
|
||||
void process(quantifier * q, expr_ref & r, proof_ref & p) {
|
||||
if (q->get_kind() == lambda_k) {
|
||||
TRACE("nnf", tout << expr_ref(q, m) << "\n";);
|
||||
r = q;
|
||||
p = nullptr;
|
||||
return;
|
||||
}
|
||||
used_vars uv;
|
||||
uv(q);
|
||||
SASSERT(is_well_sorted(m(), q));
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
unsigned sz = uv.get_max_found_var_idx_plus_1();
|
||||
ptr_buffer<sort> sorts;
|
||||
expr_ref_vector args(m());
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
sort * s = uv.get(i);
|
||||
if (s != nullptr) {
|
||||
sorts.push_back(s);
|
||||
args.push_back(m().mk_var(i, s));
|
||||
args.push_back(m.mk_var(i, s));
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("skolemizer", tout << "skid: " << q->get_skid() << "\n";);
|
||||
|
||||
expr_ref_vector substitution(m());
|
||||
|
||||
expr_ref_vector substitution(m);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
for (unsigned i = num_decls; i > 0; ) {
|
||||
--i;
|
||||
sort * r = q->get_decl_sort(i);
|
||||
func_decl * sk_decl = m().mk_fresh_func_decl(q->get_decl_name(i), q->get_skid(), sorts.size(), sorts.c_ptr(), r);
|
||||
app * sk = m().mk_app(sk_decl, args.size(), args.c_ptr());
|
||||
func_decl * sk_decl = m.mk_fresh_func_decl(q->get_decl_name(i), q->get_skid(), sorts.size(), sorts.c_ptr(), r);
|
||||
app * sk = m.mk_app(sk_decl, args.size(), args.c_ptr());
|
||||
substitution.push_back(sk);
|
||||
}
|
||||
//
|
||||
|
@ -106,7 +112,7 @@ class skolemizer {
|
|||
for (unsigned i = 0; i < sz; i++) {
|
||||
sort * s = uv.get(i);
|
||||
if (s != nullptr)
|
||||
substitution.push_back(m().mk_var(i, s));
|
||||
substitution.push_back(m.mk_var(i, s));
|
||||
else
|
||||
substitution.push_back(nullptr);
|
||||
}
|
||||
|
@ -118,9 +124,9 @@ class skolemizer {
|
|||
//
|
||||
// (VAR 0) should be in the last position of substitution.
|
||||
//
|
||||
var_subst s(m());
|
||||
SASSERT(is_well_sorted(m(), q->get_expr()));
|
||||
expr_ref tmp(m());
|
||||
var_subst s(m);
|
||||
SASSERT(is_well_sorted(m, q->get_expr()));
|
||||
expr_ref tmp(m);
|
||||
expr * body = q->get_expr();
|
||||
if (m_sk_hack_enabled) {
|
||||
unsigned num_patterns = q->get_num_patterns();
|
||||
|
@ -128,27 +134,27 @@ class skolemizer {
|
|||
expr * p = q->get_pattern(i);
|
||||
if (is_sk_hack(p)) {
|
||||
expr * sk_hack = to_app(p)->get_arg(0);
|
||||
if (q->is_forall()) // check whether is in negative/positive context.
|
||||
tmp = m().mk_or(body, m().mk_not(sk_hack)); // negative context
|
||||
if (q->get_kind() == forall_k) // check whether is in negative/positive context.
|
||||
tmp = m.mk_or(body, m.mk_not(sk_hack)); // negative context
|
||||
else
|
||||
tmp = m().mk_and(body, sk_hack); // positive context
|
||||
tmp = m.mk_and(body, sk_hack); // positive context
|
||||
body = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
s(body, substitution.size(), substitution.c_ptr(), r);
|
||||
r = s(body, substitution.size(), substitution.c_ptr());
|
||||
p = nullptr;
|
||||
if (m().proofs_enabled()) {
|
||||
if (q->is_forall())
|
||||
p = m().mk_skolemization(m().mk_not(q), m().mk_not(r));
|
||||
if (m.proofs_enabled()) {
|
||||
if (q->get_kind() == forall_k)
|
||||
p = m.mk_skolemization(m.mk_not(q), m.mk_not(r));
|
||||
else
|
||||
p = m().mk_skolemization(q, r);
|
||||
p = m.mk_skolemization(q, r);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
skolemizer(ast_manager & m):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_sk_hack("sk_hack"),
|
||||
m_sk_hack_enabled(false),
|
||||
m_cache(m),
|
||||
|
@ -159,25 +165,23 @@ public:
|
|||
m_sk_hack_enabled = f;
|
||||
}
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
void operator()(quantifier * q, expr_ref & r, proof_ref & p) {
|
||||
r = m_cache.find(q);
|
||||
if (r.get() != nullptr) {
|
||||
p = nullptr;
|
||||
if (m().proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
p = static_cast<proof*>(m_cache_pr.find(q));
|
||||
}
|
||||
else {
|
||||
process(q, r, p);
|
||||
m_cache.insert(q, r);
|
||||
if (m().proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
m_cache_pr.insert(q, p);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_sk_hack(expr * p) const {
|
||||
SASSERT(m().is_pattern(p));
|
||||
SASSERT(m.is_pattern(p));
|
||||
if (to_app(p)->get_num_args() != 1)
|
||||
return false;
|
||||
expr * body = to_app(p)->get_arg(0);
|
||||
|
@ -186,7 +190,7 @@ public:
|
|||
func_decl * f = to_app(body)->get_decl();
|
||||
if (!(f->get_name() == m_sk_hack && f->get_arity() == 1))
|
||||
return false;
|
||||
if (!m().is_bool(body)) {
|
||||
if (!m.is_bool(body)) {
|
||||
warning_msg("sk_hack constant must return a Boolean");
|
||||
return false;
|
||||
}
|
||||
|
@ -233,8 +237,8 @@ struct nnf::imp {
|
|||
#define POS_NQ_CIDX 1 // positive polarity and not nested in a quantifier
|
||||
#define NEG_Q_CIDX 2 // negative polarity and nested in a quantifier
|
||||
#define POS_Q_CIDX 3 // positive polarity and nested in a quantifier
|
||||
|
||||
ast_manager & m_manager;
|
||||
|
||||
ast_manager & m;
|
||||
vector<frame> m_frame_stack;
|
||||
expr_ref_vector m_result_stack;
|
||||
|
||||
|
@ -263,7 +267,7 @@ struct nnf::imp {
|
|||
unsigned long long m_max_memory; // in bytes
|
||||
|
||||
imp(ast_manager & m, defined_names & n, params_ref const & p):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_result_stack(m),
|
||||
m_todo_defs(m),
|
||||
m_todo_proofs(m),
|
||||
|
@ -279,9 +283,9 @@ struct nnf::imp {
|
|||
m_name_quant = mk_quantifier_label_namer(m, n);
|
||||
}
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
// ast_manager & m() const { return m; }
|
||||
|
||||
bool proofs_enabled() const { return m().proofs_enabled(); }
|
||||
bool proofs_enabled() const { return m.proofs_enabled(); }
|
||||
|
||||
~imp() {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
|
@ -334,7 +338,7 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
void push_frame(expr * t, bool pol, bool in_q, bool cache_res) {
|
||||
m_frame_stack.push_back(frame(expr_ref(t, m()), pol, in_q, cache_res, m_result_stack.size()));
|
||||
m_frame_stack.push_back(frame(expr_ref(t, m), pol, in_q, cache_res, m_result_stack.size()));
|
||||
}
|
||||
|
||||
static unsigned get_cache_idx(bool pol, bool in_q) {
|
||||
|
@ -382,8 +386,8 @@ struct nnf::imp {
|
|||
cooperate("nnf");
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw nnf_exception(Z3_MAX_MEMORY_MSG);
|
||||
if (m().canceled())
|
||||
throw nnf_exception(m().limit().get_cancel_msg());
|
||||
if (m.canceled())
|
||||
throw nnf_exception(m.limit().get_cancel_msg());
|
||||
}
|
||||
|
||||
void set_new_child_flag() {
|
||||
|
@ -397,16 +401,16 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
void skip(expr * t, bool pol) {
|
||||
expr * r = pol ? t : m().mk_not(t);
|
||||
expr * r = pol ? t : m.mk_not(t);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
m_result_pr_stack.push_back(m().mk_oeq_reflexivity(r));
|
||||
m_result_pr_stack.push_back(m.mk_oeq_reflexivity(r));
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
}
|
||||
}
|
||||
|
||||
bool visit(expr * t, bool pol, bool in_q) {
|
||||
SASSERT(m().is_bool(t));
|
||||
SASSERT(m.is_bool(t));
|
||||
|
||||
if (m_mode == NNF_SKOLEM || (m_mode == NNF_QUANT && !in_q)) {
|
||||
if (!has_quantifiers(t) && !has_labels(t)) {
|
||||
|
@ -456,12 +460,12 @@ struct nnf::imp {
|
|||
proof * mk_proof(bool pol, unsigned num_parents, proof * const * parents, app * old_e, app * new_e) {
|
||||
if (pol) {
|
||||
if (old_e->get_decl() == new_e->get_decl())
|
||||
return m().mk_oeq_congruence(old_e, new_e, num_parents, parents);
|
||||
else
|
||||
return m().mk_nnf_pos(old_e, new_e, num_parents, parents);
|
||||
return m.mk_oeq_congruence(old_e, new_e, num_parents, parents);
|
||||
else
|
||||
return m.mk_nnf_pos(old_e, new_e, num_parents, parents);
|
||||
}
|
||||
else
|
||||
return m().mk_nnf_neg(old_e, new_e, num_parents, parents);
|
||||
else
|
||||
return m.mk_nnf_neg(old_e, new_e, num_parents, parents);
|
||||
}
|
||||
|
||||
bool process_and_or(app * t, frame & fr) {
|
||||
|
@ -473,11 +477,11 @@ struct nnf::imp {
|
|||
return false;
|
||||
}
|
||||
app * r;
|
||||
if (m().is_and(t) == fr.m_pol)
|
||||
r = m().mk_and(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
if (m.is_and(t) == fr.m_pol)
|
||||
r = m.mk_and(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
else
|
||||
r = m().mk_or(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
r = m.mk_or(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -500,7 +504,7 @@ struct nnf::imp {
|
|||
if (proofs_enabled()) {
|
||||
pr = m_result_pr_stack.back();
|
||||
if (!fr.m_pol) {
|
||||
pr = m().mk_nnf_neg(t, r, 1, &pr);
|
||||
pr = m.mk_nnf_neg(t, r, 1, &pr);
|
||||
m_result_pr_stack.pop_back();
|
||||
m_result_pr_stack.push_back(pr);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
|
@ -526,10 +530,10 @@ struct nnf::imp {
|
|||
|
||||
app * r;
|
||||
if (fr.m_pol)
|
||||
r = m().mk_or(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
r = m.mk_or(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
else
|
||||
r = m().mk_and(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
r = m.mk_and(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -570,7 +574,7 @@ struct nnf::imp {
|
|||
expr * _then = rs[2];
|
||||
expr * _else = rs[3];
|
||||
|
||||
app * r = m().mk_and(m().mk_or(_not_cond, _then), m().mk_or(_cond, _else));
|
||||
app * r = m.mk_and(m.mk_or(_not_cond, _then), m.mk_or(_cond, _else));
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -582,7 +586,7 @@ struct nnf::imp {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool is_eq(app * t) const { return m().is_eq(t); }
|
||||
bool is_eq(app * t) const { return m.is_eq(t); }
|
||||
|
||||
bool process_iff_xor(app * t, frame & fr) {
|
||||
SASSERT(t->get_num_args() == 2);
|
||||
|
@ -614,10 +618,10 @@ struct nnf::imp {
|
|||
expr * not_rhs = rs[3];
|
||||
|
||||
app * r;
|
||||
if (is_eq(t) == fr.m_pol)
|
||||
r = m().mk_and(m().mk_or(not_lhs, rhs), m().mk_or(lhs, not_rhs));
|
||||
if (is_eq(t) == fr.m_pol)
|
||||
r = m.mk_and(m.mk_or(not_lhs, rhs), m.mk_or(lhs, not_rhs));
|
||||
else
|
||||
r = m().mk_and(m().mk_or(lhs, rhs), m().mk_or(not_lhs, not_rhs));
|
||||
r = m.mk_and(m.mk_or(lhs, rhs), m.mk_or(not_lhs, not_rhs));
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -630,7 +634,7 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
bool process_eq(app * t, frame & fr) {
|
||||
if (m().is_iff(t))
|
||||
if (m.is_bool(t->get_arg(0)))
|
||||
return process_iff_xor(t, fr);
|
||||
else
|
||||
return process_default(t, fr);
|
||||
|
@ -639,21 +643,20 @@ struct nnf::imp {
|
|||
bool process_default(app * t, frame & fr) {
|
||||
SASSERT(fr.m_i == 0);
|
||||
if (m_mode == NNF_FULL || t->has_quantifiers() || t->has_labels()) {
|
||||
expr_ref n2(m());
|
||||
proof_ref pr2(m());
|
||||
expr_ref n2(m);
|
||||
proof_ref pr2(m);
|
||||
if (m_mode == NNF_FULL || (m_mode != NNF_SKOLEM && fr.m_in_q))
|
||||
m_name_nested_formulas->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
|
||||
else
|
||||
m_name_quant->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
|
||||
|
||||
if (!fr.m_pol)
|
||||
n2 = m().mk_not(n2);
|
||||
|
||||
n2 = m.mk_not(n2);
|
||||
m_result_stack.push_back(n2);
|
||||
if (proofs_enabled()) {
|
||||
if (!fr.m_pol) {
|
||||
proof * prs[1] = { pr2 };
|
||||
pr2 = m().mk_oeq_congruence(m().mk_not(t), static_cast<app*>(n2.get()), 1, prs);
|
||||
pr2 = m.mk_oeq_congruence(m.mk_not(t), static_cast<app*>(n2.get()), 1, prs);
|
||||
}
|
||||
m_result_pr_stack.push_back(pr2);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
|
@ -681,24 +684,24 @@ struct nnf::imp {
|
|||
|
||||
buffer<symbol> names;
|
||||
bool pos;
|
||||
m().is_label(t, pos, names);
|
||||
expr_ref r(m());
|
||||
proof_ref pr(m());
|
||||
m.is_label(t, pos, names);
|
||||
expr_ref r(m);
|
||||
proof_ref pr(m);
|
||||
if (fr.m_pol == pos) {
|
||||
expr * lbl_lit = m().mk_label_lit(names.size(), names.c_ptr());
|
||||
r = m().mk_and(arg, lbl_lit);
|
||||
expr * lbl_lit = m.mk_label_lit(names.size(), names.c_ptr());
|
||||
r = m.mk_and(arg, lbl_lit);
|
||||
if (proofs_enabled()) {
|
||||
expr_ref aux(m_manager);
|
||||
aux = m().mk_label(true, names.size(), names.c_ptr(), arg);
|
||||
pr = m().mk_transitivity(mk_proof(fr.m_pol, 1, &arg_pr, t, to_app(aux)),
|
||||
m().mk_iff_oeq(m().mk_rewrite(aux, r)));
|
||||
expr_ref aux(m);
|
||||
aux = m.mk_label(true, names.size(), names.c_ptr(), arg);
|
||||
pr = m.mk_transitivity(mk_proof(fr.m_pol, 1, &arg_pr, t, to_app(aux)),
|
||||
m.mk_iff_oeq(m.mk_rewrite(aux, r)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = arg;
|
||||
if (proofs_enabled()) {
|
||||
proof * p1 = m().mk_iff_oeq(m().mk_rewrite(t, t->get_arg(0)));
|
||||
pr = m().mk_transitivity(p1, arg_pr);
|
||||
proof * p1 = m.mk_iff_oeq(m.mk_rewrite(t, t->get_arg(0)));
|
||||
pr = m.mk_transitivity(p1, arg_pr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,9 +716,9 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
bool process_app(app * t, frame & fr) {
|
||||
TRACE("nnf", tout << mk_ismt2_pp(t, m()) << "\n";);
|
||||
SASSERT(m().is_bool(t));
|
||||
if (t->get_family_id() == m().get_basic_family_id()) {
|
||||
TRACE("nnf", tout << mk_ismt2_pp(t, m) << "\n";);
|
||||
SASSERT(m.is_bool(t));
|
||||
if (t->get_family_id() == m.get_basic_family_id()) {
|
||||
switch (static_cast<basic_op_kind>(t->get_decl_kind())) {
|
||||
case OP_AND: case OP_OR:
|
||||
return process_and_or(t, fr);
|
||||
|
@ -734,7 +737,7 @@ struct nnf::imp {
|
|||
}
|
||||
}
|
||||
|
||||
if (m().is_label(t)) {
|
||||
if (m.is_label(t)) {
|
||||
return process_label(t, fr);
|
||||
}
|
||||
|
||||
|
@ -747,28 +750,51 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
bool process_quantifier(quantifier * q, frame & fr) {
|
||||
expr_ref r(m());
|
||||
proof_ref pr(m());
|
||||
TRACE("nnf", tout << expr_ref(q, m) << "\n";);
|
||||
expr_ref r(m);
|
||||
proof_ref pr(m);
|
||||
if (fr.m_i == 0) {
|
||||
fr.m_i = 1;
|
||||
if (q->is_forall() == fr.m_pol || !m_skolemize) {
|
||||
if (is_lambda(q)) {
|
||||
if (!visit(q->get_expr(), fr.m_pol, true))
|
||||
return false;
|
||||
}
|
||||
else if (is_forall(q) == fr.m_pol || !m_skolemize) {
|
||||
if (!visit(q->get_expr(), fr.m_pol, true))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
m_skolemizer(q, r, pr);
|
||||
if (!visit(r, !q->is_forall(), fr.m_in_q))
|
||||
if (!visit(r, !is_forall(q), fr.m_in_q))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (q->is_forall() == fr.m_pol || !m_skolemize) {
|
||||
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;
|
||||
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);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (is_forall(q) == fr.m_pol || !m_skolemize) {
|
||||
expr * new_expr = m_result_stack.back();
|
||||
proof * new_expr_pr = proofs_enabled() ? m_result_pr_stack.back() : nullptr;
|
||||
|
||||
ptr_buffer<expr> new_patterns;
|
||||
|
||||
if (q->is_forall() == fr.m_pol) {
|
||||
if (is_forall(q) == fr.m_pol) {
|
||||
// collect non sk_hack patterns
|
||||
unsigned num_patterns = q->get_num_patterns();
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
|
@ -785,14 +811,19 @@ struct nnf::imp {
|
|||
quantifier * new_q = nullptr;
|
||||
proof * new_q_pr = nullptr;
|
||||
if (fr.m_pol) {
|
||||
new_q = m().update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled())
|
||||
new_q_pr = m().mk_nnf_pos(q, new_q, 1, &new_expr_pr);
|
||||
new_q = m.update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled()) {
|
||||
new_expr_pr = m.mk_bind_proof(q, new_expr_pr);
|
||||
new_q_pr = m.mk_nnf_pos(q, new_q, 1, &new_expr_pr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
new_q = m().update_quantifier(q, !q->is_forall(), new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled())
|
||||
new_q_pr = m().mk_nnf_neg(q, new_q, 1, &new_expr_pr);
|
||||
quantifier_kind k = is_forall(q)? exists_k : forall_k;
|
||||
new_q = m.update_quantifier(q, k, new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled()) {
|
||||
new_expr_pr = m.mk_bind_proof(q, new_expr_pr);
|
||||
new_q_pr = m.mk_nnf_neg(q, new_q, 1, &new_expr_pr);
|
||||
}
|
||||
}
|
||||
|
||||
m_result_stack.pop_back();
|
||||
|
@ -809,7 +840,7 @@ struct nnf::imp {
|
|||
// However, the proof must be updated
|
||||
if (proofs_enabled()) {
|
||||
m_skolemizer(q, r, pr); // retrieve the proof
|
||||
pr = m().mk_transitivity(pr, m_result_pr_stack.back());
|
||||
pr = m.mk_transitivity(pr, m_result_pr_stack.back());
|
||||
m_result_pr_stack.pop_back();
|
||||
m_result_pr_stack.push_back(pr);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
|
@ -827,14 +858,14 @@ struct nnf::imp {
|
|||
result_pr = m_result_pr_stack.back();
|
||||
m_result_pr_stack.pop_back();
|
||||
if (result_pr.get() == nullptr)
|
||||
result_pr = m().mk_reflexivity(t);
|
||||
result_pr = m.mk_reflexivity(t);
|
||||
SASSERT(m_result_pr_stack.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void process(expr * t, expr_ref & result, proof_ref & result_pr) {
|
||||
TRACE("nnf", tout << "processing:\n" << mk_ismt2_pp(t, m()) << "\n";);
|
||||
SASSERT(m().is_bool(t));
|
||||
TRACE("nnf", tout << "processing:\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
SASSERT(m.is_bool(t));
|
||||
|
||||
if (visit(t, true /* positive polarity */, false /* not nested in quantifier */)) {
|
||||
recover_result(t, result, result_pr);
|
||||
|
@ -883,13 +914,13 @@ struct nnf::imp {
|
|||
unsigned old_sz2 = new_def_proofs.size();
|
||||
|
||||
for (unsigned i = 0; i < m_todo_defs.size(); i++) {
|
||||
expr_ref dr(m());
|
||||
proof_ref dpr(m());
|
||||
expr_ref dr(m);
|
||||
proof_ref dpr(m);
|
||||
process(m_todo_defs.get(i), dr, dpr);
|
||||
new_defs.push_back(dr);
|
||||
if (proofs_enabled()) {
|
||||
proof * new_pr = m().mk_modus_ponens(m_todo_proofs.get(i), dpr);
|
||||
new_def_proofs.push_back(new_pr);
|
||||
proof * new_pr = m.mk_modus_ponens(m_todo_proofs.get(i), dpr);
|
||||
new_def_proofs.push_back(new_pr);
|
||||
}
|
||||
}
|
||||
std::reverse(new_defs.c_ptr() + old_sz1, new_defs.c_ptr() + new_defs.size());
|
||||
|
@ -909,7 +940,7 @@ nnf::~nnf() {
|
|||
|
||||
void nnf::operator()(expr * n, expr_ref_vector & new_defs, proof_ref_vector & new_def_proofs, expr_ref & r, proof_ref & p) {
|
||||
m_imp->operator()(n, new_defs, new_def_proofs, r, p);
|
||||
TRACE("nnf_result", tout << mk_ismt2_pp(n, m_imp->m()) << "\nNNF result:\n" << mk_ismt2_pp(r, m_imp->m()) << "\n";);
|
||||
TRACE("nnf_result", tout << expr_ref(n, r.get_manager()) << "\nNNF result:\n" << new_defs << "\n" << r << "\n";);
|
||||
}
|
||||
|
||||
void nnf::updt_params(params_ref const & p) {
|
||||
|
|
|
@ -49,7 +49,8 @@ struct pull_quant::imp {
|
|||
if (is_quantifier(child)) {
|
||||
quantifier * q = to_quantifier(child);
|
||||
expr * body = q->get_expr();
|
||||
result = m_manager.update_quantifier(q, !q->is_forall(), m_manager.mk_not(body));
|
||||
quantifier_kind k = q->get_kind() == forall_k ? exists_k : forall_k;
|
||||
result = m_manager.update_quantifier(q, k, m_manager.mk_not(body));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -149,7 +150,7 @@ struct pull_quant::imp {
|
|||
// 3) MBQI
|
||||
std::reverse(var_sorts.begin(), var_sorts.end());
|
||||
std::reverse(var_names.begin(), var_names.end());
|
||||
result = m_manager.mk_quantifier(forall_children,
|
||||
result = m_manager.mk_quantifier(forall_children ? forall_k : exists_k,
|
||||
var_sorts.size(),
|
||||
var_sorts.c_ptr(),
|
||||
var_names.c_ptr(),
|
||||
|
@ -220,9 +221,7 @@ struct pull_quant::imp {
|
|||
expr_ref_buffer new_args(m_manager);
|
||||
expr_ref new_arg(m_manager);
|
||||
ptr_buffer<proof> proofs;
|
||||
unsigned num = to_app(n)->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
expr * arg = to_app(n)->get_arg(i);
|
||||
for (expr * arg : *to_app(n)) {
|
||||
pull_quant1(arg , new_arg);
|
||||
new_args.push_back(new_arg);
|
||||
if (new_arg != arg)
|
||||
|
@ -277,10 +276,13 @@ struct pull_quant::imp {
|
|||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
||||
if (old_q->is_exists()) {
|
||||
if (is_exists(old_q)) {
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
if (is_lambda(old_q)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_forall(new_body))
|
||||
return false;
|
||||
|
|
|
@ -53,7 +53,7 @@ expr_pattern_match::match_quantifier(quantifier* qf, app_ref_vector& patterns, u
|
|||
m_regs[0] = qf->get_expr();
|
||||
for (unsigned i = 0; i < m_precompiled.size(); ++i) {
|
||||
quantifier* qf2 = m_precompiled[i].get();
|
||||
if (qf2->is_forall() != qf->is_forall()) {
|
||||
if (qf2->get_kind() != qf->get_kind() || is_lambda(qf)) {
|
||||
continue;
|
||||
}
|
||||
if (qf2->get_num_decls() != qf->get_num_decls()) {
|
||||
|
|
|
@ -582,7 +582,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
proof_ref & result_pr) {
|
||||
|
||||
TRACE("pattern_inference", tout << "processing:\n" << mk_pp(q, m) << "\n";);
|
||||
if (!q->is_forall()) {
|
||||
if (!is_forall(q)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -673,6 +673,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
new_q = m.update_quantifier_weight(new_q, weight);
|
||||
if (m.proofs_enabled()) {
|
||||
proof* new_body_pr = m.mk_reflexivity(new_body);
|
||||
new_body_pr = m.mk_bind_proof(new_q, new_body_pr);
|
||||
result_pr = m.mk_quant_intro(q, new_q, new_body_pr);
|
||||
}
|
||||
|
||||
|
@ -690,7 +691,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
}
|
||||
new_q = m.update_quantifier(result2, new_patterns.size(), (expr**) new_patterns.c_ptr(), result2->get_expr());
|
||||
if (m.proofs_enabled()) {
|
||||
result_pr = m.mk_transitivity(new_pr, m.mk_quant_intro(result2, new_q, m.mk_reflexivity(new_q->get_expr())));
|
||||
result_pr = m.mk_transitivity(new_pr, m.mk_quant_intro(result2, new_q, m.mk_bind_proof(new_q, m.mk_reflexivity(new_q->get_expr()))));
|
||||
}
|
||||
TRACE("pattern_inference", tout << "pulled quantifier:\n" << mk_pp(new_q, m) << "\n";);
|
||||
}
|
||||
|
|
|
@ -346,7 +346,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
to_quantifier(t1.get())->get_expr() == s1.get() &&
|
||||
to_quantifier(t2.get())->get_expr() == s2.get() &&
|
||||
to_quantifier(t1.get())->get_num_decls() == to_quantifier(t2.get())->get_num_decls() &&
|
||||
to_quantifier(t1.get())->is_forall() == to_quantifier(t2.get())->is_forall()) {
|
||||
to_quantifier(t1.get())->get_kind() == to_quantifier(t2.get())->get_kind()) {
|
||||
quantifier* q1 = to_quantifier(t1.get());
|
||||
quantifier* q2 = to_quantifier(t2.get());
|
||||
for (unsigned i = 0; i < q1->get_num_decls(); ++i) {
|
||||
|
@ -734,9 +734,10 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
is_forall = true;
|
||||
}
|
||||
if (is_quantifier(e)) {
|
||||
q = to_quantifier(e);
|
||||
SASSERT(!is_lambda(e));
|
||||
q = to_quantifier(e);
|
||||
// TBD check that quantifier is properly instantiated
|
||||
return is_forall == q->is_forall();
|
||||
return is_forall == ::is_forall(q);
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -784,7 +785,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
// SASSERT(to_quantifier(premise)->get_num_decls() == sub.size());
|
||||
premise = to_quantifier(premise)->get_expr();
|
||||
}
|
||||
vs(premise, sub.size(), sub.c_ptr(), premise);
|
||||
premise = vs(premise, sub.size(), sub.c_ptr());
|
||||
}
|
||||
fmls.push_back(premise.get());
|
||||
TRACE("proof_checker",
|
||||
|
@ -974,7 +975,7 @@ bool proof_checker::match_app(expr const* e, func_decl_ref& d, expr_ref_vector&
|
|||
bool proof_checker::match_quantifier(expr const* e, bool& is_univ, sort_ref_vector& sorts, expr_ref& body) const {
|
||||
if (is_quantifier(e)) {
|
||||
quantifier const* q = to_quantifier(e);
|
||||
is_univ = q->is_forall();
|
||||
is_univ = is_forall(q);
|
||||
body = q->get_expr();
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
sorts.push_back(q->get_decl_sort(i));
|
||||
|
|
|
@ -975,9 +975,7 @@ private:
|
|||
|
||||
void compose(expr_ref_vector& sub, expr_ref_vector const& s0) {
|
||||
for (unsigned i = 0; i < sub.size(); ++i) {
|
||||
expr_ref e(m);
|
||||
var_subst(m, false)(sub[i].get(), s0.size(), s0.c_ptr(), e);
|
||||
sub[i] = e;
|
||||
sub[i] = var_subst(m, false)(sub[i].get(), s0.size(), s0.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -995,7 +993,7 @@ private:
|
|||
tout << sub.size() << "\n";);
|
||||
return;
|
||||
}
|
||||
var_subst(m, false)(q->get_expr(), sub.size(), sub.c_ptr(), fml);
|
||||
fml = var_subst(m, false)(q->get_expr(), sub.size(), sub.c_ptr());
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
#include "ast/rewriter/array_rewriter_params.hpp"
|
||||
#include "ast/ast_lt.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
void array_rewriter::updt_params(params_ref const & _p) {
|
||||
array_rewriter_params p(_p);
|
||||
|
@ -196,6 +197,17 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
|
|||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (is_lambda(args[0])) {
|
||||
// anywhere lambda reduction as opposed to whnf
|
||||
// select(lambda(X) M, N) -> M[N/X]
|
||||
quantifier* q = to_quantifier(args[0]);
|
||||
SASSERT(q->get_num_decls() == num_args - 1);
|
||||
var_subst subst(m());
|
||||
result = subst(q->get_expr(), num_args - 1, args + 1);
|
||||
return BR_REWRITE_FULL;
|
||||
|
||||
}
|
||||
|
||||
if (m_util.is_as_array(args[0])) {
|
||||
// select(as-array[f], I) --> f(I)
|
||||
func_decl * f = m_util.get_as_array_func_decl(to_app(args[0]));
|
||||
|
|
|
@ -636,7 +636,7 @@ MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend);
|
|||
new_decl_names.push_back(n);
|
||||
}
|
||||
}
|
||||
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
result = m().mk_quantifier(old_q->get_kind(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = nullptr;
|
||||
|
|
|
@ -588,58 +588,39 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
|
|||
VERIFY(m().is_ite(ite, cond, t, e));
|
||||
SASSERT(m().is_value(val));
|
||||
|
||||
if (m().is_value(t) && m().is_value(e)) {
|
||||
if (t != val && e != val) {
|
||||
TRACE("try_ite_value", tout << mk_ismt2_pp(t, m()) << " " << mk_ismt2_pp(e, m()) << " " << mk_ismt2_pp(val, m()) << "\n";
|
||||
tout << t << " " << e << " " << val << "\n";);
|
||||
result = m().mk_false();
|
||||
}
|
||||
else if (t == val && e == val) {
|
||||
if (m().are_distinct(val, e)) {
|
||||
result = m().mk_and(m().mk_eq(t, val), cond);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_distinct(val, t)) {
|
||||
result = m().mk_and(m().mk_eq(e, val), m().mk_not(cond));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_equal(val, t)) {
|
||||
if (m().are_equal(val, e)) {
|
||||
result = m().mk_true();
|
||||
}
|
||||
else if (t == val) {
|
||||
result = cond;
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
SASSERT(e == val);
|
||||
mk_not(cond, result);
|
||||
result = m().mk_or(m().mk_eq(e, val), cond);
|
||||
}
|
||||
return BR_DONE;
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m_ite_extra_rules) {
|
||||
if (m().is_value(t)) {
|
||||
if (val == t) {
|
||||
result = m().mk_or(cond, m().mk_eq(val, e));
|
||||
}
|
||||
else {
|
||||
mk_not(cond, result);
|
||||
result = m().mk_and(result, m().mk_eq(val, e));
|
||||
}
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_value(e)) {
|
||||
if (val == e) {
|
||||
mk_not(cond, result);
|
||||
result = m().mk_or(result, m().mk_eq(val, t));
|
||||
}
|
||||
else {
|
||||
result = m().mk_and(cond, m().mk_eq(val, t));
|
||||
}
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_equal(val, e)) {
|
||||
result = m().mk_or(m().mk_eq(t, val), m().mk_not(cond));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
{
|
||||
expr* cond2, *t2, *e2;
|
||||
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(t), val, result);
|
||||
result = m().mk_ite(cond, result, m().mk_eq(e, val));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(e), val, result);
|
||||
result = m().mk_ite(cond, m().mk_eq(t, val), result);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
expr* cond2 = nullptr, *t2 = nullptr, *e2 = nullptr;
|
||||
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(t), val, result);
|
||||
result = m().mk_ite(cond, result, m().mk_eq(e, val));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(e), val, result);
|
||||
result = m().mk_ite(cond, m().mk_eq(t, val), result);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
|
|
|
@ -87,20 +87,16 @@ bool bv_elim_cfg::reduce_quantifier(quantifier * q,
|
|||
expr* const* sub = subst_map.c_ptr();
|
||||
unsigned sub_size = subst_map.size();
|
||||
|
||||
subst(old_body, sub_size, sub, new_body);
|
||||
new_body = subst(old_body, sub_size, sub);
|
||||
|
||||
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
|
||||
expr_ref pat(m);
|
||||
subst(new_patterns[j], sub_size, sub, pat);
|
||||
pats.push_back(pat);
|
||||
pats.push_back(subst(new_patterns[j], sub_size, sub));
|
||||
}
|
||||
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
|
||||
expr_ref nopat(m);
|
||||
subst(new_no_patterns[j], sub_size, sub, nopat);
|
||||
no_pats.push_back(nopat);
|
||||
no_pats.push_back(subst(new_no_patterns[j], sub_size, sub));
|
||||
}
|
||||
|
||||
result = m.mk_quantifier(true,
|
||||
result = m.mk_quantifier(forall_k,
|
||||
names.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
|
|
|
@ -133,7 +133,7 @@ void der::operator()(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
// Eliminate variables that have become unused
|
||||
if (reduced && is_forall(r)) {
|
||||
quantifier * q = to_quantifier(r);
|
||||
elim_unused_vars(m_manager, q, params_ref(), r);
|
||||
r = elim_unused_vars(m_manager, q, params_ref());
|
||||
if (m_manager.proofs_enabled()) {
|
||||
proof * p1 = m_manager.mk_elim_unused_vars(q, r);
|
||||
pr = m_manager.mk_transitivity(pr, p1);
|
||||
|
@ -343,8 +343,7 @@ void der::create_substitution(unsigned sz) {
|
|||
expr_ref cur(m_map[m_order[i]], m_manager);
|
||||
|
||||
// do all the previous substitutions before inserting
|
||||
expr_ref r(m_manager);
|
||||
m_subst(cur, m_subst_map.size(), m_subst_map.c_ptr(), r);
|
||||
expr_ref r = m_subst(cur, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
|
||||
unsigned inx = sz - m_order[i]- 1;
|
||||
SASSERT(m_subst_map[inx]==0);
|
||||
|
@ -369,21 +368,18 @@ void der::apply_substitution(quantifier * q, expr_ref & r) {
|
|||
unsigned sz = m_new_args.size();
|
||||
expr_ref t(m_manager);
|
||||
t = (sz == 1) ? m_new_args[0] : m_manager.mk_or(sz, m_new_args.c_ptr());
|
||||
expr_ref new_e(m_manager);
|
||||
m_subst(t, m_subst_map.size(), m_subst_map.c_ptr(), new_e);
|
||||
expr_ref new_e = m_subst(t, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
|
||||
// don't forget to update the quantifier patterns
|
||||
expr_ref_buffer new_patterns(m_manager);
|
||||
expr_ref_buffer new_no_patterns(m_manager);
|
||||
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
|
||||
expr_ref new_pat(m_manager);
|
||||
m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr(), new_pat);
|
||||
expr_ref new_pat = m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_patterns.push_back(new_pat);
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
|
||||
expr_ref new_nopat(m_manager);
|
||||
m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr(), new_nopat);
|
||||
expr_ref new_nopat = m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_no_patterns.push_back(new_nopat);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ void distribute_forall::reduce1_app(app * a) {
|
|||
|
||||
void distribute_forall::reduce1_quantifier(quantifier * q) {
|
||||
// This transformation is applied after skolemization/quantifier elimination. So, all quantifiers are universal.
|
||||
SASSERT(q->is_forall());
|
||||
SASSERT(q->get_kind() == forall_k);
|
||||
|
||||
// This transformation is applied after basic pre-processing steps.
|
||||
// So, we can assume that
|
||||
|
@ -126,8 +126,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
|
|||
br.mk_not(arg, not_arg);
|
||||
quantifier_ref tmp_q(m_manager);
|
||||
tmp_q = m_manager.update_quantifier(q, not_arg);
|
||||
expr_ref new_q(m_manager);
|
||||
elim_unused_vars(m_manager, tmp_q, params_ref(), new_q);
|
||||
expr_ref new_q = elim_unused_vars(m_manager, tmp_q, params_ref());
|
||||
new_args.push_back(new_q);
|
||||
}
|
||||
expr_ref result(m_manager);
|
||||
|
|
|
@ -114,7 +114,7 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q,
|
|||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
if (!q->is_forall()) {
|
||||
if (!is_forall(q)) {
|
||||
return false;
|
||||
}
|
||||
unsigned num_vars = q->get_num_decls();
|
||||
|
@ -194,7 +194,7 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q,
|
|||
}
|
||||
quantifier_ref new_q(m);
|
||||
new_q = m.update_quantifier(q, new_body);
|
||||
elim_unused_vars(m, new_q, params_ref(), result);
|
||||
result = elim_unused_vars(m, new_q, params_ref());
|
||||
result_pr = m.mk_rewrite(q, result);
|
||||
TRACE("elim_bounds", tout << mk_pp(q, m) << "\n" << result << "\n";);
|
||||
return true;
|
||||
|
|
|
@ -159,6 +159,8 @@ struct enum2bv_rewriter::imp {
|
|||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
||||
if (q->get_kind() == lambda_k) return false;
|
||||
m_sorts.reset();
|
||||
expr_ref_vector bounds(m);
|
||||
bool found = false;
|
||||
|
@ -182,15 +184,20 @@ struct enum2bv_rewriter::imp {
|
|||
}
|
||||
expr_ref new_body_ref(old_body, m), tmp(m);
|
||||
if (!bounds.empty()) {
|
||||
if (q->is_forall()) {
|
||||
switch (q->get_kind()) {
|
||||
case forall_k:
|
||||
new_body_ref = m.mk_implies(mk_and(bounds), new_body_ref);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case exists_k:
|
||||
bounds.push_back(new_body_ref);
|
||||
new_body_ref = mk_and(bounds);
|
||||
break;
|
||||
case lambda_k:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = m.mk_quantifier(q->is_forall(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref,
|
||||
result = m.mk_quantifier(q->get_kind(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref,
|
||||
q->get_weight(), q->get_qid(), q->get_skid(),
|
||||
q->get_num_patterns(), new_patterns,
|
||||
q->get_num_no_patterns(), new_no_patterns);
|
||||
|
|
|
@ -32,7 +32,7 @@ bool simplify_inj_axiom(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
expr* arg1 = nullptr, * arg2 = nullptr, *narg = nullptr;
|
||||
expr* app1 = nullptr, * app2 = nullptr;
|
||||
expr* var1 = nullptr, * var2 = nullptr;
|
||||
if (q->is_forall() && m.is_or(n, arg1, arg2)) {
|
||||
if (is_forall(q) && m.is_or(n, arg1, arg2)) {
|
||||
if (m.is_not(arg2))
|
||||
std::swap(arg1, arg2);
|
||||
if (m.is_not(arg1, narg) &&
|
||||
|
|
|
@ -79,12 +79,12 @@ public:
|
|||
vars.push_back(a);
|
||||
}
|
||||
expr * const * exprs = (expr* const*) (vars.c_ptr() + vars.size()- nd);
|
||||
instantiate(m, q, exprs, result);
|
||||
result = instantiate(m, q, exprs);
|
||||
}
|
||||
|
||||
unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names, bool use_fresh, bool rewrite_ok) {
|
||||
unsigned pull_quantifier(bool _is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names, bool use_fresh, bool rewrite_ok) {
|
||||
unsigned index = var_counter().get_next_var(fml);
|
||||
while (is_quantifier(fml) && (is_forall == to_quantifier(fml)->is_forall())) {
|
||||
while (is_quantifier(fml) && _is_forall == is_forall(fml)) {
|
||||
quantifier* q = to_quantifier(fml);
|
||||
index += q->get_num_decls();
|
||||
if (names) {
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
return index;
|
||||
}
|
||||
app_ref_vector vars(m);
|
||||
pull_quantifier(is_forall, fml, vars, use_fresh, rewrite_ok);
|
||||
pull_quantifier(_is_forall, fml, vars, use_fresh, rewrite_ok);
|
||||
if (vars.empty()) {
|
||||
return index;
|
||||
}
|
||||
|
@ -277,12 +277,16 @@ private:
|
|||
}
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier* q = to_quantifier(fml);
|
||||
expr_ref tmp(m);
|
||||
if (!is_compatible(qt, q->is_forall())) {
|
||||
if (is_lambda(q)) {
|
||||
result = fml;
|
||||
break;
|
||||
}
|
||||
set_quantifier_type(qt, q->is_forall());
|
||||
expr_ref tmp(m);
|
||||
if (!is_compatible(qt, is_forall(q))) {
|
||||
result = fml;
|
||||
break;
|
||||
}
|
||||
set_quantifier_type(qt, is_forall(q));
|
||||
extract_quantifier(q, vars, tmp, use_fresh);
|
||||
pull_quantifier(tmp, qt, vars, result, use_fresh, rewrite_ok);
|
||||
break;
|
||||
|
|
|
@ -208,12 +208,10 @@ void rewriter_core::cleanup() {
|
|||
|
||||
#ifdef _TRACE
|
||||
void rewriter_core::display_stack(std::ostream & out, unsigned pp_depth) {
|
||||
svector<frame>::iterator it = m_frame_stack.begin();
|
||||
svector<frame>::iterator end = m_frame_stack.end();
|
||||
for (; it != end; ++it) {
|
||||
out << mk_bounded_pp(it->m_curr, m(), pp_depth) << "\n";
|
||||
out << "state: " << it->m_state << "\n";
|
||||
out << "cache: " << it->m_cache_result << ", new_child: " << it->m_new_child << ", max-depth: " << it->m_max_depth << ", i: " << it->m_i << "\n";
|
||||
for (frame& f : m_frame_stack) {
|
||||
out << mk_bounded_pp(f.m_curr, m(), pp_depth) << "\n";
|
||||
out << "state: " << f.m_state << "\n";
|
||||
out << "cache: " << f.m_cache_result << ", new_child: " << f.m_new_child << ", max-depth: " << f.m_max_depth << ", i: " << f.m_i << "\n";
|
||||
out << "------------------\n";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -350,11 +350,13 @@ public:
|
|||
void update_inv_binding_at(unsigned i, expr* binding);
|
||||
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
|
||||
void operator()(expr * t, expr_ref & result) { operator()(t, result, m_pr); }
|
||||
void operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result) {
|
||||
expr_ref operator()(expr * n, unsigned num_bindings, expr * const * bindings) {
|
||||
expr_ref result(m());
|
||||
SASSERT(!m_proof_gen);
|
||||
reset();
|
||||
set_inv_bindings(num_bindings, bindings);
|
||||
operator()(n, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void resume(expr_ref & result, proof_ref & result_pr);
|
||||
|
|
|
@ -542,7 +542,7 @@ void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
|
|||
}
|
||||
result_stack().shrink(fr.m_spos);
|
||||
result_stack().push_back(m_r.get());
|
||||
SASSERT(m().is_bool(m_r));
|
||||
SASSERT(m().get_sort(q) == m().get_sort(m_r));
|
||||
if (!ProofGen) {
|
||||
SASSERT(num_decls <= m_bindings.size());
|
||||
m_bindings.shrink(m_bindings.size() - num_decls);
|
||||
|
|
|
@ -36,7 +36,7 @@ expr_ref sym_expr::accept(expr* e) {
|
|||
switch (m_ty) {
|
||||
case t_pred: {
|
||||
var_subst subst(m);
|
||||
subst(m_t, 1, &e, result);
|
||||
result = subst(m_t, 1, &e);
|
||||
break;
|
||||
}
|
||||
case t_char:
|
||||
|
|
|
@ -16,6 +16,7 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/rewriter/rewriter_params.hpp"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
|
@ -28,10 +29,9 @@ Notes:
|
|||
#include "ast/rewriter/pb_rewriter.h"
|
||||
#include "ast/rewriter/seq_rewriter.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/well_sorted.h"
|
||||
|
||||
|
@ -606,7 +606,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
quantifier_ref q1(m());
|
||||
proof * p1 = nullptr;
|
||||
if (is_quantifier(new_body) &&
|
||||
to_quantifier(new_body)->is_forall() == old_q->is_forall() &&
|
||||
to_quantifier(new_body)->get_kind() == old_q->get_kind() &&
|
||||
to_quantifier(new_body)->get_kind() != lambda_k &&
|
||||
!old_q->has_patterns() &&
|
||||
!to_quantifier(new_body)->has_patterns()) {
|
||||
|
||||
|
@ -619,7 +620,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
sorts.append(nested_q->get_num_decls(), nested_q->get_decl_sorts());
|
||||
names.append(nested_q->get_num_decls(), nested_q->get_decl_names());
|
||||
|
||||
q1 = m().mk_quantifier(old_q->is_forall(),
|
||||
q1 = m().mk_quantifier(old_q->get_kind(),
|
||||
sorts.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
|
@ -653,17 +654,19 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
SASSERT(is_well_sorted(m(), q1));
|
||||
}
|
||||
|
||||
elim_unused_vars(m(), q1, params_ref(), result);
|
||||
SASSERT(m().get_sort(old_q) == m().get_sort(q1));
|
||||
result = elim_unused_vars(m(), q1, params_ref());
|
||||
|
||||
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << result << "\n";);
|
||||
|
||||
result_pr = nullptr;
|
||||
if (m().proofs_enabled()) {
|
||||
proof * p2 = nullptr;
|
||||
if (q1.get() != result.get())
|
||||
if (q1.get() != result.get() && q1->get_kind() != lambda_k)
|
||||
p2 = m().mk_elim_unused_vars(q1, result);
|
||||
result_pr = m().mk_transitivity(p1, p2);
|
||||
}
|
||||
SASSERT(m().get_sort(old_q) == m().get_sort(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -784,8 +787,8 @@ void th_rewriter::operator()(expr * t, expr_ref & result, proof_ref & result_pr)
|
|||
m_imp->operator()(t, result, result_pr);
|
||||
}
|
||||
|
||||
void th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result) {
|
||||
m_imp->operator()(n, num_bindings, bindings, result);
|
||||
expr_ref th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings) {
|
||||
return m_imp->operator()(n, num_bindings, bindings);
|
||||
}
|
||||
|
||||
void th_rewriter::set_substitution(expr_substitution * s) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
void operator()(expr_ref& term);
|
||||
void operator()(expr * t, expr_ref & result);
|
||||
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
|
||||
void operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result);
|
||||
expr_ref operator()(expr * n, unsigned num_bindings, expr * const * bindings);
|
||||
|
||||
expr_ref mk_app(func_decl* f, unsigned num_args, expr* const* args);
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@ Notes:
|
|||
#include "ast/well_sorted.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
|
||||
void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) {
|
||||
expr_ref result(m_reducer.m());
|
||||
if (is_ground(n)) {
|
||||
result = n;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
SASSERT(is_well_sorted(result.m(), n));
|
||||
m_reducer.reset();
|
||||
|
@ -41,6 +42,7 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
|
|||
for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(args[i], m_reducer.m()) << "\n";
|
||||
tout << "\n------>\n";
|
||||
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const & params) :
|
||||
|
@ -49,16 +51,22 @@ unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const
|
|||
m_ignore_patterns_on_ground_qbody = m_params.get_bool("ignore_patterns_on_ground_qbody", true);
|
||||
}
|
||||
|
||||
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
||||
expr_ref unused_vars_eliminator::operator()(quantifier* q) {
|
||||
expr_ref result(m);
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
TRACE("elim_unused_vars", tout << expr_ref(q, m) << "\n";);
|
||||
if (is_lambda(q)) {
|
||||
result = q;
|
||||
return result;
|
||||
}
|
||||
if (m_ignore_patterns_on_ground_qbody && is_ground(q->get_expr())) {
|
||||
// Ignore patterns if the body is a ground formula.
|
||||
result = q->get_expr();
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
if (!q->may_have_unused_vars()) {
|
||||
result = q;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
m_used.reset();
|
||||
m_used.process(q->get_expr());
|
||||
|
@ -73,7 +81,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
if (m_used.uses_all_vars(num_decls)) {
|
||||
q->set_no_unused_vars();
|
||||
result = q;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
ptr_buffer<sort> used_decl_sorts;
|
||||
|
@ -120,11 +128,11 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
|
||||
expr_ref new_expr(m);
|
||||
|
||||
m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
|
||||
new_expr = m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr());
|
||||
|
||||
if (num_removed == num_decls) {
|
||||
result = new_expr;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref tmp(m);
|
||||
|
@ -132,15 +140,15 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
expr_ref_buffer new_no_patterns(m);
|
||||
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
tmp = m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr());
|
||||
new_patterns.push_back(tmp);
|
||||
}
|
||||
for (unsigned i = 0; i < num_no_patterns; i++) {
|
||||
m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
tmp = m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr());
|
||||
new_no_patterns.push_back(tmp);
|
||||
}
|
||||
|
||||
result = m.mk_quantifier(q->is_forall(),
|
||||
result = m.mk_quantifier(q->get_kind(),
|
||||
used_decl_sorts.size(),
|
||||
used_decl_sorts.c_ptr(),
|
||||
used_decl_names.c_ptr(),
|
||||
|
@ -154,24 +162,28 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
new_no_patterns.c_ptr());
|
||||
to_quantifier(result)->set_no_unused_vars();
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & result) {
|
||||
expr_ref elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params) {
|
||||
unused_vars_eliminator el(m, params);
|
||||
el(q, result);
|
||||
expr_ref result = el(q);
|
||||
TRACE("elim_unused_vars", tout << expr_ref(q, m) << " -> " << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result) {
|
||||
expr_ref instantiate(ast_manager & m, quantifier * q, expr * const * exprs) {
|
||||
var_subst subst(m);
|
||||
expr_ref new_expr(m);
|
||||
subst(q->get_expr(), q->get_num_decls(), exprs, new_expr);
|
||||
TRACE("var_subst", tout << mk_pp(q, m) << "\n" << mk_pp(new_expr, m) << "\n";);
|
||||
expr_ref new_expr(m), result(m);
|
||||
new_expr = subst(q->get_expr(), q->get_num_decls(), exprs);
|
||||
TRACE("var_subst", tout << mk_pp(q, m) << "\n" << new_expr << "\n";);
|
||||
inv_var_shifter shift(m);
|
||||
shift(new_expr, q->get_num_decls(), result);
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
TRACE("instantiate_bug", tout << mk_ismt2_pp(q, m) << "\nusing\n";
|
||||
for (unsigned i = 0; i < q->get_num_decls(); i++) tout << mk_ismt2_pp(exprs[i], m) << "\n";
|
||||
tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void get_free_vars_offset(expr_sparse_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
|
||||
Otherwise, (VAR 0) is stored in the first position, (VAR 1) in the second, and so on.
|
||||
*/
|
||||
void operator()(expr * n, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
expr_ref operator()(expr * n, unsigned num_args, expr * const * args);
|
||||
void reset() { m_reducer.reset(); }
|
||||
};
|
||||
|
||||
|
@ -63,10 +63,10 @@ class unused_vars_eliminator {
|
|||
bool m_ignore_patterns_on_ground_qbody;
|
||||
public:
|
||||
unused_vars_eliminator(ast_manager & m, params_ref const & params);
|
||||
void operator()(quantifier* q, expr_ref& r);
|
||||
expr_ref operator()(quantifier* q);
|
||||
};
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & r);
|
||||
expr_ref elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params);
|
||||
|
||||
/**
|
||||
\brief Instantiate quantifier q using the given exprs.
|
||||
|
@ -77,7 +77,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params
|
|||
...
|
||||
(VAR (q->get_num_decls() - 1)) is stored in the first position of the array.
|
||||
*/
|
||||
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result);
|
||||
expr_ref instantiate(ast_manager & m, quantifier * q, expr * const * exprs);
|
||||
|
||||
/**
|
||||
\brief Enumerate set of free variables in expression.
|
||||
|
|
|
@ -35,9 +35,10 @@ struct well_sorted_proc {
|
|||
|
||||
void operator()(quantifier * n) {
|
||||
expr const * e = n->get_expr();
|
||||
if (!m_manager.is_bool(e)) {
|
||||
if (!is_lambda(n) && !m_manager.is_bool(e)) {
|
||||
warning_msg("quantifier's body must be a boolean.");
|
||||
m_error = true;
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue