mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
ccc170a06e
commit
3ee5c0e7d9
11 changed files with 120 additions and 107 deletions
|
@ -576,6 +576,10 @@ func_decl * array_recognizers::get_as_array_func_decl(func_decl * f) const {
|
|||
return to_func_decl(f->get_parameter(0).get_ast());
|
||||
}
|
||||
|
||||
bool array_recognizers::is_const(expr* e, expr*& v) const {
|
||||
return is_const(e) && (v = to_app(e)->get_arg(0), true);
|
||||
}
|
||||
|
||||
array_util::array_util(ast_manager& m):
|
||||
array_recognizers(m.mk_family_id("array")),
|
||||
m_manager(m) {
|
||||
|
|
|
@ -152,6 +152,8 @@ public:
|
|||
bool is_as_array(func_decl* f, func_decl*& g) const { return is_decl_of(f, m_fid, OP_AS_ARRAY) && (g = get_as_array_func_decl(f), true); }
|
||||
func_decl * get_as_array_func_decl(expr * n) const;
|
||||
func_decl * get_as_array_func_decl(func_decl* f) const;
|
||||
|
||||
bool is_const(expr* e, expr*& v) const;
|
||||
};
|
||||
|
||||
class array_util : public array_recognizers {
|
||||
|
@ -178,6 +180,11 @@ public:
|
|||
parameter param(s);
|
||||
return m_manager.mk_app(m_fid, OP_CONST_ARRAY, 1, ¶m, 1, &v);
|
||||
}
|
||||
app * mk_const_array(unsigned n, sort * const* s, expr * v) {
|
||||
vector<parameter> ps;
|
||||
for (unsigned i = 0; i < n; ++i) ps.push_back(parameter(s[i]));
|
||||
return m_manager.mk_app(m_fid, OP_CONST_ARRAY, n, ps.c_ptr(), 1, &v);
|
||||
}
|
||||
app * mk_empty_set(sort * s) {
|
||||
return mk_const_array(s, m_manager.mk_false());
|
||||
}
|
||||
|
|
|
@ -230,105 +230,92 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
|
|||
}
|
||||
|
||||
br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args >= 0);
|
||||
bool is_store0 = m_util.is_store(args[0]);
|
||||
bool is_const0 = m_util.is_const(args[0]);
|
||||
if (num_args == 1) {
|
||||
//
|
||||
// map_f (store a j v) = (store (map_f a) j (f v))
|
||||
//
|
||||
if (is_store0) {
|
||||
app * store_expr = to_app(args[0]);
|
||||
unsigned num_args = store_expr->get_num_args();
|
||||
SASSERT(num_args >= 3);
|
||||
expr * a = store_expr->get_arg(0);
|
||||
expr * v = store_expr->get_arg(num_args-1);
|
||||
|
||||
ptr_buffer<expr> new_args;
|
||||
|
||||
new_args.push_back(m_util.mk_map(f, 1, &a)); // (map_f a)
|
||||
new_args.append(num_args - 2, store_expr->get_args() + 1); // j
|
||||
new_args.push_back(m().mk_app(f, v)); // (f v)
|
||||
|
||||
result = m().mk_app(get_fid(), OP_STORE, new_args.size(), new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
//
|
||||
// map_f (const v) = (const (f v))
|
||||
//
|
||||
if (is_const0) {
|
||||
expr * fv = m().mk_app(f, to_app(args[0])->get_arg(0));
|
||||
result = m_util.mk_const_array(m().get_sort(args[0]), fv);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
SASSERT(num_args > 1);
|
||||
|
||||
if (is_store0) {
|
||||
unsigned num_indices = to_app(args[0])->get_num_args() - 2;
|
||||
unsigned i;
|
||||
for (i = 1; i < num_args; i++) {
|
||||
if (!m_util.is_store(args[i]))
|
||||
break;
|
||||
unsigned j;
|
||||
for (j = 1; j < num_indices+1; j++) {
|
||||
if (to_app(args[0])->get_arg(j) != to_app(args[i])->get_arg(j))
|
||||
break;
|
||||
}
|
||||
if (j < num_indices+1)
|
||||
break;
|
||||
app* store_expr = nullptr;
|
||||
unsigned num_indices = 0;
|
||||
bool same_store = true;
|
||||
for (unsigned i = 0; same_store && i < num_args; i++) {
|
||||
expr* a = args[i];
|
||||
if (m_util.is_const(a)) {
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// map_f (store a_1 j v_1) ... (store a_n j v_n) --> (store (map_f a_1 ... a_n) j (f v_1 ... v_n))
|
||||
//
|
||||
if (i == num_args) {
|
||||
ptr_buffer<expr> arrays;
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
arrays.push_back(to_app(args[i])->get_arg(0));
|
||||
values.push_back(to_app(args[i])->get_arg(num_indices+1));
|
||||
else if (!m_util.is_store(a)) {
|
||||
same_store = false;
|
||||
}
|
||||
else if (!store_expr) {
|
||||
num_indices = to_app(a)->get_num_args() - 2;
|
||||
store_expr = to_app(a);
|
||||
}
|
||||
else {
|
||||
for (unsigned j = 1; same_store && j < num_indices + 1; j++) {
|
||||
same_store = (store_expr->get_arg(j) == to_app(a)->get_arg(j));
|
||||
}
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(m_util.mk_map(f, arrays.size(), arrays.c_ptr()));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// map_f (store a_1 j v_1) ... (store a_n j v_n) --> (store (map_f a_1 ... a_n) j (f v_1 ... v_n))
|
||||
//
|
||||
if (same_store) {
|
||||
ptr_buffer<expr> arrays;
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr* a = args[i];
|
||||
if (m_util.is_const(a)) {
|
||||
arrays.push_back(a);
|
||||
values.push_back(to_app(a)->get_arg(0));
|
||||
}
|
||||
else {
|
||||
arrays.push_back(to_app(a)->get_arg(0));
|
||||
values.push_back(to_app(a)->get_arg(num_indices+1));
|
||||
}
|
||||
}
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(m_util.mk_map(f, arrays.size(), arrays.c_ptr()));
|
||||
if (store_expr) {
|
||||
new_args.append(num_indices, to_app(args[0])->get_args() + 1);
|
||||
new_args.push_back(m().mk_app(f, values.size(), values.c_ptr()));
|
||||
result = m().mk_app(get_fid(), OP_STORE, new_args.size(), new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
else {
|
||||
result = m_util.mk_const_array(m().get_sort(args[0]), new_args.back());
|
||||
}
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
if (is_const0) {
|
||||
unsigned i;
|
||||
for (i = 1; i < num_args; i++) {
|
||||
if (!m_util.is_const(args[i]))
|
||||
break;
|
||||
//
|
||||
// map_f (lambda x1 b1) ... (lambda x1 bn) -> lambda x1 (f b1 .. bn)
|
||||
//
|
||||
quantifier* lam = nullptr;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
if (is_lambda(args[i])) {
|
||||
lam = to_quantifier(args[i]);
|
||||
}
|
||||
if (i == num_args) {
|
||||
//
|
||||
// map_f (const v_1) ... (const v_n) = (const (f v_1 ... v_n))
|
||||
//
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
values.push_back(to_app(args[i])->get_arg(0));
|
||||
}
|
||||
if (lam) {
|
||||
expr_ref_vector args1(m());
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
expr* a = args[i];
|
||||
if (m_util.is_const(a)) {
|
||||
args1.push_back(to_app(a)->get_arg(0));
|
||||
}
|
||||
else if (is_lambda(a)) {
|
||||
lam = to_quantifier(a);
|
||||
args1.push_back(lam->get_expr());
|
||||
}
|
||||
else {
|
||||
expr_ref_vector sel(m());
|
||||
sel.push_back(a);
|
||||
unsigned n = lam->get_num_decls();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
sel.push_back(m().mk_var(n - i - 1, lam->get_decl_sort(i)));
|
||||
}
|
||||
args1.push_back(m_util.mk_select(sel.size(), sel.c_ptr()));
|
||||
}
|
||||
|
||||
expr * fv = m().mk_app(f, values.size(), values.c_ptr());
|
||||
sort * in_s = get_sort(args[0]);
|
||||
ptr_vector<sort> domain;
|
||||
unsigned domain_sz = get_array_arity(in_s);
|
||||
for (unsigned i = 0; i < domain_sz; i++)
|
||||
domain.push_back(get_array_domain(in_s, i));
|
||||
sort_ref out_s(m());
|
||||
out_s = m_util.mk_array_sort(domain_sz, domain.c_ptr(), f->get_range());
|
||||
parameter p(out_s.get());
|
||||
result = m().mk_app(get_fid(), OP_CONST_ARRAY, 1, &p, 1, &fv);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
result = m().mk_app(f, args1.size(), args1.c_ptr());
|
||||
result = m().update_quantifier(lam, result);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue