feat(CategoryTheory): add a grind propagator that normalizes morphism composition#39622
Draft
kim-em wants to merge 5 commits into
Draft
feat(CategoryTheory): add a grind propagator that normalizes morphism composition#39622kim-em wants to merge 5 commits into
kim-em wants to merge 5 commits into
Conversation
PR summary 998032a1c1Import changes for modified filesNo significant changes to the import graph Import changes for all files
|
… composition This PR adds a `grind` upward propagator on `CategoryTheory.CategoryStruct.comp` that, every time `grind` internalizes a composition `f ≫ g`, pushes the equality `f ≫ g = (right-associated form with syntactic identity factors removed)` back into the e-graph. The motivation is the Catalan blow-up of e-matching on `Category.assoc`: a chain of length `n` lets e-matching generate all Catalan(n − 1) parenthesizations as e-graph terms. Mathlib already has the runaway documented at `CategoryTheory/Iso.lean:146`. The propagator commits to a single canonical representative per fresh composition; the normalized form is a fixed point, so it never re-fires on the form it produces — the e-graph grows by O(1) terms per user-visible composition instead. Notes: - The `@[grind =]` / `@[grind _=_]` attributes are removed from `Category.id_comp`, `Category.comp_id`, `Category.assoc` because the propagator subsumes them and they would re-introduce the blow-up. - `uliftCategory` in `Category/Basic.lean` now provides its three category axioms explicitly, since the `cat_disch` autoparam used to rely on the e-matching tags above and `Category/Basic.lean` runs before the propagator file is loaded. - The propagator is registered via `initialize` calling `registerBuiltinUpwardPropagator` directly. The `builtin_grind_propagator` macro can't be used downstream in `module`-mode mathlib (see leanprover/lean4#13805) and `grind_propagator` (the user-facing form) is not yet implemented in lean4 v4.30.0-rc2. - The normalizer is hand-written rather than reusing `Meta.Simp.main`, which has no IR body and crashes the interpreter when invoked from a `module`-mode downstream file. Tests in `MathlibTest/CategoryTheory/GrindCatNorm.lean` cover associativity, identity removal, mixed cases, hypotheses flowing through the normalizer, reducible-alias morphism types, and a long-chain heart-beat guard. 🤖 Prepared with Claude Code Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace explicit `id_comp/comp_id/assoc` fields on `uliftCategory` with `attribute [local grind =] / [local grind _=_]` on the three lemmas. The `cat_disch` autoparam can use the e-matching tags locally without leaking them to downstream files. - Drop the implementation note about `Simp.main` from the `GrindCatNorm.lean` module docstring. 🤖 Prepared with Claude Code Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the hand-written `normalizeComp` recursion (and supporting `mkCompFromShell` / `extractHomEndpoints` helpers) with a single call to `simpOnlyNames` on `Category.id_comp`, `Category.comp_id`, `Category.assoc`. Simp already handles congruence, transitivity, and maximal sharing, so the file shrinks from ~190 to ~110 lines. The propagator still keeps the cheap `isNormalizedComp` structural guard so that already-normal compositions don't pay the cost of invoking simp. When simp fails (e.g. composition under a bare `CategoryStruct` instance with no synthesizable `Category`), the propagator silently skips that term rather than aborting `grind`. Suggested by a second-opinion code review. 🤖 Prepared with Claude Code Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop helper `mkCompFromShell`/`extractHomEndpoints`/`combineProofs` bookkeeping; everything is one `simpOnlyNames` call. - Inline `isIdMorphism` into the single structural check. - Trim the docstring and remove the now-stale caveats section. No behavioural change. 112 → 81 lines. 🤖 Prepared with Claude Code Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Second-opinion review nits:
- `isNormal` now uses `match_expr` rather than `isAppOfArity` + positional
`appFn!.appArg!`/`appArg!` accesses.
- The `catch _` around the `simp` call now logs the exception under
`trace.grind.catNorm` so future failures aren't silently swallowed.
- Stale comment on the reducible-alias test ("reduces the inferred type
until it hits Quiver.Hom" — that path no longer exists) replaced with
a concise one-liner.
🤖 Prepared with Claude Code
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a
grindupward propagator onCategoryTheory.CategoryStruct.compthat, every timegrindinternalizes a compositionf ≫ g, pushes the equalityf ≫ g = (right-associated form with syntactic identity factors removed)back into the e-graph.The motivation is the Catalan blow-up of e-matching on
Category.assoc: a chain of lengthnlets e-matching generate all Catalan(n − 1) parenthesizations as e-graph terms. Mathlib already has the runaway documented atMathlib/CategoryTheory/Iso.lean:146. The propagator commits to a single canonical representative per fresh composition; the normalized form is a fixed point, so it never re-fires on the form it produces — the e-graph grows by O(1) terms per user-visible composition instead of Catalan-many.Notes:
@[grind =]/@[grind _=_]attributes are removed fromCategory.id_comp,Category.comp_id,Category.assocbecause the propagator subsumes them and they would re-introduce the blow-up.uliftCategoryinCategory/Basic.leannow provides its three category axioms explicitly, since thecat_dischautoparam used to rely on the e-matching tags above andCategory/Basic.leanruns before the propagator file is loaded.initializecallingregisterBuiltinUpwardPropagatordirectly. Thebuiltin_grind_propagatormacro can't be used downstream inmodule-mode mathlib (see Implementgrind_propagatorfor downstream / mathlib use leanprover/lean4#13805) andgrind_propagator(the user-facing form) is not yet implemented in lean4.Meta.Simp.main, which has no IR body and crashes the interpreter when invoked from amodule-mode downstream file.Tests in
MathlibTest/CategoryTheory/GrindCatNorm.leancover associativity, identity removal, mixed cases, hypotheses flowing through the normalizer, reducible-alias morphism types, and a long-chain heart-beat guard.Filed upstream tracking issue: leanprover/lean4#13805
🤖 Prepared with Claude Code