Skip to content

Irrelevant Axiom Transform#635

Merged
aqjune-aws merged 13 commits intomainfrom
shilpi/irrelevant-axioms-v2
Mar 24, 2026
Merged

Irrelevant Axiom Transform#635
aqjune-aws merged 13 commits intomainfrom
shilpi/irrelevant-axioms-v2

Conversation

@shigoel
Copy link
Copy Markdown
Contributor

@shigoel shigoel commented Mar 22, 2026

Summary

Reimplements the irrelevant axiom removal feature (originally drafted in PR #524) with a cleaner architecture and proven termination of helper functions.

Key changes:

  • IrrelevantAxiomsMode enum (Options.lean): Replaces the old removeIrrelevantAxioms : Bool with .Off, .Aggressive, and .Precise modes, giving callers explicit control over the tradeoff between pruning aggressiveness and soundness risk.

  • Caching (IrrelevantAxioms.lean): A Cache struct (function call graph + axiom map) is built once per program and reused across all per-goal queries, avoiding redundant recomputation.

  • Builtin exclusion (CallGraph.lean): Builtins are excluded from the function-to-axiom map because they appear in nearly every axiom, which would otherwise collapse the relevance filter.

  • Proven termination: The fixed-point computation in computeRelevantAxioms now has a Lean-verified termination proof instead of relying on a fuel counter.

  • Precise mode correctness fix: Axiom-labeled path conditions are excluded from the antecedent function extraction. Without this, axiom bodies would seed the relevant set, making everything relevant and removing nothing.

  • Cover obligations never prune: Removing axioms from cover VCs is unsound (it weakens path conditions), so pruning is skipped for those.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

shigoel and others added 3 commits March 21, 2026 18:57
Replace the old Bool-based removeIrrelevantAxioms with a three-mode
enum (Off/Aggressive/Precise) and a cached, transitive relevance
analysis.

Key changes:

- Options.lean: IrrelevantAxiomsMode enum with soundness documentation.
  Axiom removal is sound for assert obligations but unsound for cover
  (enforced in preprocessObligation).

- CallGraph.lean: Add FuncAxMap, functionImmediateAxiomMap (excludes
  builtins to prevent collapse), and transitive fixed-point algorithm
  (computeRelevantAxioms) that discovers axioms through call graph
  neighbors.

- Transform/IrrelevantAxioms.lean: New Cache struct (call graph + axiom
  map) built once per program in verify(), reused across all goals.

- Verifier.lean: preprocessObligation uses cache and mode dispatch.
  Precise mode extracts functions from both antecedent and consequent,
  excluding axiom-labeled path conditions to avoid trivial relevance.
  Cover obligations always skip pruning.

- Test updated to match new IrrelevantAxiomsMode API and VCResult
  format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Prove termination for closureGo (lexicographic measure on
  allNodes.length - visited.length, toVisit.length) and
  computeRelevantAxioms (allAxiomNames.length - discoveredAxioms.length).
  No partial declarations remain in CallGraph.lean.
- Remove all partial from extractCallsFromStatement/extractCallsFromStatements
  via structural recursion.
- Add relevance definition docstring to computeRelevantAxioms.
- Remove old Program.getIrrelevantAxioms references; update Axioms.lean
  test to use IrrelevantAxioms.Cache API.
- Fix test_datetime: assertion now passes (old axiom removal incorrectly
  discarded a relevant axiom).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@shigoel shigoel requested a review from a team March 22, 2026 03:58
@shigoel
Copy link
Copy Markdown
Contributor Author

shigoel commented Mar 22, 2026

@aqjune-aws @keyboardDrummer It was easier to reimplement this than deal with merge issues with the older PR. I accommodated your comments in the older PR (#524), but ideas like pruning irrelevant assumptions are left out of scope.

@keyboardDrummer
Copy link
Copy Markdown
Contributor

Copying some comments from the previous PR:


Are triggers for quantifiers not used to enable ignoring the body? Boogie does this in its pruning algorithm. Explanation from Claude:

Consider:

axiom forall x, y :: {P(x, y), Q(y)} {R(x)} P(x, y) ==> R(x)

This axiom has two trigger groups: {P, Q} and {R}. The axiom becomes relevant if either all symbols in a trigger group are reachable, or if R alone is reachable. So trigger group {P, Q} becomes a "merge node" — both P and Q must be visited before the axiom is reachable through that path. Trigger group {R} is a simple single-symbol incoming edge.

For triggered forall in positive position (and exists in negative position), the axiom body's incoming edges are discarded — only the trigger-derived incoming edges are kept. This is sound because the solver can only instantiate those quantifiers via their triggers.

(Back to Remy) My gut feeling is that the above is both more precise and more accurate than what you're doing with the aggressive mode. I think the tracking of positivity is a generalization of your differentiation between antecedent and consequent.

Relevant previous PRs on this topic:


Soundness documentation is included: axiom removal is sound for deductive verification

Shouldn't it be both sound and complete? If axioms that I need for a proof are deleted, what good is the feature?

Aggressive is better for finding counterexamples (fewer axioms → solver can
negate the goal more easily);

I don't understand that. By counterexample, do you mean the model given by the solver but only when it returns sat for PathCondition ^ !AssertCondition ? Are you saying fewer axioms means it's more likely to return sat ? That surprises me. I would have thought axioms make it easier to prove sat.

@keyboardDrummer
Copy link
Copy Markdown
Contributor

keyboardDrummer commented Mar 23, 2026

It seems the new aggressive pruning feature is left untested and unused. My feeling is that it might be simpler to leave the aggressive pruning option out in this PR.

Comment thread Strata/Transform/IrrelevantAxioms.lean
@MikaelMayer MikaelMayer self-assigned this Mar 23, 2026
Comment thread Strata/Transform/IrrelevantAxioms.lean Outdated
Comment thread StrataTest/Languages/Core/Examples/RemoveIrrelevantAxioms.lean
Comment thread Strata/Transform/IrrelevantAxioms.lean
@aqjune-aws aqjune-aws added this pull request to the merge queue Mar 24, 2026
Merged via the queue into main with commit 6d710f5 Mar 24, 2026
15 checks passed
@aqjune-aws aqjune-aws deleted the shilpi/irrelevant-axioms-v2 branch March 24, 2026 20:45
olivier-aws pushed a commit that referenced this pull request Mar 30, 2026
## Summary

Reimplements the irrelevant axiom removal feature (originally drafted in
PR #524) with a cleaner architecture and proven termination of helper
functions.

**Key changes:**

- **`IrrelevantAxiomsMode` enum** (`Options.lean`): Replaces the old
`removeIrrelevantAxioms : Bool` with `.Off`, `.Aggressive`, and
`.Precise` modes, giving callers explicit control over the tradeoff
between pruning aggressiveness and soundness risk.

- **Caching** (`IrrelevantAxioms.lean`): A `Cache` struct (function call
graph + axiom map) is built once per program and reused across all
per-goal queries, avoiding redundant recomputation.

- **Builtin exclusion** (`CallGraph.lean`): Builtins are excluded from
the function-to-axiom map because they appear in nearly every axiom,
which would otherwise collapse the relevance filter.

- **Proven termination**: The fixed-point computation in
`computeRelevantAxioms` now has a Lean-verified termination proof
instead of relying on a fuel counter.

- **Precise mode correctness fix**: Axiom-labeled path conditions are
excluded from the antecedent function extraction. Without this, axiom
bodies would seed the relevant set, making everything relevant and
removing nothing.

- **Cover obligations never prune**: Removing axioms from cover VCs is
unsound (it weakens path conditions), so pruning is skipped for those.


By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Mikael Mayer <mimayere@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants