Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eagerly apply-subs + rewrite bodies of define-fun #11526

Merged
merged 7 commits into from
Jan 15, 2025

Conversation

ajreynol
Copy link
Member

@ajreynol ajreynol commented Jan 15, 2025

This ensures that we apply top-level substitutions and rewrite bodies of define-fun eagerly. This is required for #11513.

In particular, currently, due to the fact that variables are not fresh, and the rewriter does not rewrite inside of operators, beta redexes could appear arbtirarily nested in APPLY_UF. As a result, we were requiring the fairly sophisticated "shadow elimination" methods for handling benchmarks such as:

(define-fun P ((x Int)) Bool false)
(define-fun Q ((x Int)) Bool (P x))
(assert (Q 0))
(check-sat)

In particular, Q would be defined to be the lambda (lambda ((x Int)) (@ (lambda ((x Int)) false) x)), which assuming the rewriter does not rewrite inside of operators, leads us to requiring shadow elimination to do beta reduction.

We previously made a nested call from within the rewriter to ensure such shadowing was resolved prior to beta reduction. The PR #11329 refactored this so that beta redexes for non-rewritten lambdas were lifted to HO terms so that the rewriter could track proofs without being self referential. However, as a downside, we now require HO reasoning in first order logics, in particular, lambdas could be rewritten and beta reduction could be done for HO applications. The PR #11513 addresses this shortcoming by allowing non-rewritten lambdas to be beta-reduced. However, proof elaboration fails since this requires arbitrarily nested shadow elimination. In particular, a proof of the above benchmark would (unintuitively) introduce shadowing elimination + alpha equivalence.

The solution is to apply top-level substitutions + rewriting to bodies of lambdas as they are defined. this prevents HO rewriting while eliminating complications due to shadowing in beta redexes.

We do not rewrite defined constants, since this complication does not arise and it better to be lazy based on some benchmarks in SMT-LIB (cpachecker in QF_UFLRA).

There are several motivations for this change:

  1. It makes the proofs significantly simpler and resolves all open issues related to define-fun (after Add macro rule for capture avoidance in beta redexes and its elaboration #11513 is merged),
  2. It makes the output of e.g. -o post-asserts much more intuitive. In particular, prior to this commit, we'd get:
(set-logic ALL)
(define-fun Q ((x Int)) Bool (@ (lambda ((x Int)) false) x))
(define-fun P ((x Int)) Bool false)
(assert false)
(check-sat)

whereas now we get:

(set-logic ALL)
(define-fun Q ((x Int)) Bool false)
(define-fun P ((x Int)) Bool false)
(assert false)
(check-sat)

@ajreynol ajreynol changed the title Eagerly rewrite bodies of define-fun Eagerly apply-subs + rewrite bodies of define-fun Jan 15, 2025
@ajreynol ajreynol added this pull request to the merge queue Jan 15, 2025
Merged via the queue into cvc5:main with commit 32b5a54 Jan 15, 2025
11 checks passed
@ajreynol ajreynol deleted the eagerRewDefineFUn branch January 15, 2025 19:27
HanielB pushed a commit to HanielB/cvc5 that referenced this pull request Jan 21, 2025
This ensures that we apply top-level substitutions and rewrite bodies of
define-fun eagerly. This is required for
cvc5#11513.

In particular, currently, due to the fact that variables are *not*
fresh, and the rewriter does not rewrite inside of operators, beta
redexes could appear arbtirarily nested in APPLY_UF. As a result, we
were requiring the fairly sophisticated "shadow elimination" methods for
handling benchmarks such as:
```
(define-fun P ((x Int)) Bool false)
(define-fun Q ((x Int)) Bool (P x))
(assert (Q 0))
(check-sat)
```

In particular, `Q` would be defined to be the lambda `(lambda ((x Int))
(@ (lambda ((x Int)) false) x))`, which assuming the rewriter does not
rewrite inside of operators, leads us to requiring shadow elimination to
do beta reduction.

We previously made a nested call from within the rewriter to ensure such
shadowing was resolved prior to beta reduction. The PR
cvc5#11329 refactored this so that beta
redexes for non-rewritten lambdas were lifted to HO terms so that the
rewriter could track proofs without being self referential. However, as
a downside, we now require HO reasoning in first order logics, in
particular, lambdas could be rewritten and beta reduction could be done
for HO applications. The PR cvc5#11513
addresses this shortcoming by allowing non-rewritten lambdas to be
beta-reduced. However, proof elaboration fails since this requires
arbitrarily nested shadow elimination. In particular, a proof of the
above benchmark would (unintuitively) introduce shadowing elimination +
alpha equivalence.

The solution is to apply top-level substitutions + rewriting to *bodies*
of lambdas as they are defined. this prevents HO rewriting while
eliminating complications due to shadowing in beta redexes.

We do not rewrite defined constants, since this complication does not
arise and it better to be lazy based on some benchmarks in SMT-LIB
(cpachecker in QF_UFLRA).

There are several motivations for this change:
1. It makes the proofs significantly simpler and resolves all open
issues related to define-fun (after
cvc5#11513 is merged),
2. It makes the output of e.g. `-o post-asserts` much more intuitive. In
particular, prior to this commit, we'd get:
```
(set-logic ALL)
(define-fun Q ((x Int)) Bool (@ (lambda ((x Int)) false) x))
(define-fun P ((x Int)) Bool false)
(assert false)
(check-sat)
```
whereas now we get:
```
(set-logic ALL)
(define-fun Q ((x Int)) Bool false)
(define-fun P ((x Int)) Bool false)
(assert false)
(check-sat)
```
amaleewilson pushed a commit to amaleewilson/cvc5 that referenced this pull request Jan 21, 2025
This ensures that we apply top-level substitutions and rewrite bodies of
define-fun eagerly. This is required for
cvc5#11513.

In particular, currently, due to the fact that variables are *not*
fresh, and the rewriter does not rewrite inside of operators, beta
redexes could appear arbtirarily nested in APPLY_UF. As a result, we
were requiring the fairly sophisticated "shadow elimination" methods for
handling benchmarks such as:
```
(define-fun P ((x Int)) Bool false)
(define-fun Q ((x Int)) Bool (P x))
(assert (Q 0))
(check-sat)
```

In particular, `Q` would be defined to be the lambda `(lambda ((x Int))
(@ (lambda ((x Int)) false) x))`, which assuming the rewriter does not
rewrite inside of operators, leads us to requiring shadow elimination to
do beta reduction.

We previously made a nested call from within the rewriter to ensure such
shadowing was resolved prior to beta reduction. The PR
cvc5#11329 refactored this so that beta
redexes for non-rewritten lambdas were lifted to HO terms so that the
rewriter could track proofs without being self referential. However, as
a downside, we now require HO reasoning in first order logics, in
particular, lambdas could be rewritten and beta reduction could be done
for HO applications. The PR cvc5#11513
addresses this shortcoming by allowing non-rewritten lambdas to be
beta-reduced. However, proof elaboration fails since this requires
arbitrarily nested shadow elimination. In particular, a proof of the
above benchmark would (unintuitively) introduce shadowing elimination +
alpha equivalence.

The solution is to apply top-level substitutions + rewriting to *bodies*
of lambdas as they are defined. this prevents HO rewriting while
eliminating complications due to shadowing in beta redexes.

We do not rewrite defined constants, since this complication does not
arise and it better to be lazy based on some benchmarks in SMT-LIB
(cpachecker in QF_UFLRA).

There are several motivations for this change:
1. It makes the proofs significantly simpler and resolves all open
issues related to define-fun (after
cvc5#11513 is merged),
2. It makes the output of e.g. `-o post-asserts` much more intuitive. In
particular, prior to this commit, we'd get:
```
(set-logic ALL)
(define-fun Q ((x Int)) Bool (@ (lambda ((x Int)) false) x))
(define-fun P ((x Int)) Bool false)
(assert false)
(check-sat)
```
whereas now we get:
```
(set-logic ALL)
(define-fun Q ((x Int)) Bool false)
(define-fun P ((x Int)) Bool false)
(assert false)
(check-sat)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major Priority moderate Complexity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants