3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-08-03 04:33:28 +00:00

Add array eta-reduction rewrite: (lambda (x*) (select a x*)) -> a

Sound by array extensionality when a is independent of the bound
variables. Implemented as array_rewriter::mk_lambda_core and wired into
th_rewriter::reduce_quantifier alongside the ground-lambda case.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Nikolaj Bjorner 2026-07-14 09:24:16 -07:00
parent 25e0e6f780
commit 8f2713bdb1
3 changed files with 49 additions and 0 deletions

View file

@ -399,6 +399,40 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
return BR_FAILED;
}
br_status array_rewriter::mk_lambda_core(quantifier * q, expr * body, expr_ref & result) {
// Array eta-reduction:
// (lambda (x_0 ... x_{k-1}) (select a x_0 ... x_{k-1})) --> a
// sound by array extensionality, provided 'a' is independent of the bound
// variables x_0..x_{k-1}.
if (!m_util.is_select(body))
return BR_FAILED;
app * sel = to_app(body);
unsigned k = q->get_num_decls();
// select over a k-dimensional array takes the array plus k indices.
if (sel->get_num_args() != k + 1)
return BR_FAILED;
// The j-th index argument must be exactly the bound variable of the j-th
// declaration. With de Bruijn indexing the j-th declaration is var(k-1-j).
for (unsigned j = 0; j < k; ++j) {
expr * idx = sel->get_arg(j + 1);
if (!is_var(idx) || to_var(idx)->get_idx() != k - 1 - j)
return BR_FAILED;
}
expr * a = sel->get_arg(0);
// 'a' must not reference any of the bound variables 0..k-1.
if (!is_ground(a)) {
expr_free_vars fv(a);
for (unsigned j = 0; j < k; ++j)
if (fv.contains(j))
return BR_FAILED;
}
// Shift the remaining free variables of 'a' down by k, since they are no
// longer under the eliminated lambda binder.
inv_var_shifter sh(m());
sh(a, k, result);
return BR_DONE;
}
sort_ref array_rewriter::get_map_array_sort(func_decl* f, unsigned num_args, expr* const* args) {
sort* s0 = args[0]->get_sort();
unsigned sz = get_array_arity(s0);