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:
parent
25e0e6f780
commit
8f2713bdb1
3 changed files with 49 additions and 0 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue