Conversation
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>
|
@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. |
|
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: This axiom has two trigger groups: 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:
Shouldn't it be both sound and complete? If axioms that I need for a proof are deleted, what good is the feature?
I don't understand that. By counterexample, do you mean the model given by the solver but only when it returns |
|
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. |
Add a high-level `run` function that removes irrelevant axiom declarations from a program, following the CoreTransformM pattern used by other transforms like FilterProcedures.
# Conflicts: # Strata/Languages/Core/Verifier.lean
## 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>
Summary
Reimplements the irrelevant axiom removal feature (originally drafted in PR #524) with a cleaner architecture and proven termination of helper functions.
Key changes:
IrrelevantAxiomsModeenum (Options.lean): Replaces the oldremoveIrrelevantAxioms : Boolwith.Off,.Aggressive, and.Precisemodes, giving callers explicit control over the tradeoff between pruning aggressiveness and soundness risk.Caching (
IrrelevantAxioms.lean): ACachestruct (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
computeRelevantAxiomsnow 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.