feat(HeckeRing): the twisting character of the χ-twisted Γ₀(N) Hecke ring - #4324
Conversation
…Hecke ring
delta0NebentypusChar chi := chi.comp (Delta0UpperUnit N), the coefficient the
chi-twisted double-coset operator attaches to a monoid element, together with the
lemma that makes it worth naming: on Gamma0(N) it restricts to the INVERSE of
chi . Gamma0Map, the character modFormCharSpace is defined by.
The inverse is the convention rather than a slip. The twisted operator divides by
the character -- each representative contributes chi(.)^-1 . (f |[k] .) -- so the
value attached to a monoid element is the reciprocal of the one attached to a
group element acting on forms. It is inherited from Delta0UpperUnit_mapGL, where
the inverse first appears.
The definition is a composition because Delta0UpperUnit is already a MonoidHom;
AINTLIB's delta0NebentypusDeltaChar builds the same character as a bare MonoidHom
and discharges map_one'/map_mul' by hand against its Classical.choose witness API.
Two decisions, both measured rather than assumed:
- delta0NebentypusChar_apply uses (rfl), not rfl. Bare rfl fails with "This
theorem is exported from the current module ... must be exposed": the
definition is in a public section without @[expose], so its body is sealed.
- only _mapGL carries @[simp]. It shares a left-hand side with _apply, and
tagging both would let _apply fire first and leave _mapGL unable to apply.
New file rather than an addition to UpperUnit.lean: that file is about the
(ZMod N)^x-valued unit and is concurrently modified by TauCetiProject#4319.
Four gates green: build 9070 jobs 0 diagnostics; axioms 70885; module-system 3216;
lint-env PASS x1, NEW violation x0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AI review — approvedEach rubric is judged independently by multiple review agents; the PR merges only once every rubric is green — any rubric that is not green (changes requested, blocked, errored, stale, or not yet run) blocks the merge. See the rubrics.
♻️ = approved on an earlier commit, re-run before merge. Reviewing this diff at head |
…ation
api-design asked for delta0NebentypusChar_apply to carry the normal-form
annotation, and prescribed a fallback if simpNF then found _mapGL redundant.
Measured both states with lint-env:
_apply @[simp] AND _mapGL @[simp] FAIL, 1 new violation:
delta0NebentypusChar_mapGL /- simp can prove this:
by simp only [_apply, Delta0UpperUnit_mapGL, map_inv] -/
_apply @[simp], _mapGL untagged PASS, 0 new violations
So the rubric's reading was right: simp reaches _mapGL on its own through the
already-tagged Delta0UpperUnit_mapGL and map_inv. Took the prescribed fallback.
_mapGL keeps its name and docstring as the specialization the twisted Hecke ring
cites; it just no longer needs the attribute.
Docstrings updated to match, and _apply now records why it exists at all: the
definition's body is not exposed, so downstream modules cannot recover the
equation with rfl, unfold, MonoidHom.comp_apply or simp.
documentation, round 2: "both theorem docstrings substantially describe
proof/elaboration and linter mechanics rather than the results ... move proof
and simp-linter rationale to ordinary implementation comments if it must be
retained."
Done, and retained rather than deleted:
delta0NebentypusChar_apply - the sealing account (why the lemma exists at
all, and why the proof is written (rfl) rather than rfl) moves to a comment
above the declaration. The docstring is now one line: the defining equation.
delta0NebentypusChar_mapGL - the simpNF measurement (tagging both makes the
linter report "simp can prove this") likewise moves to a comment. The
docstring keeps only the mathematics: on Gamma_0(N) the twisting character
is inverse to the nebentypus.
Both facts are load-bearing for a future reader, so neither is dropped; they
are just no longer what a consumer reads first. Same treatment TauCetiProject#4319 took for
its simp rationale.
Also merges origin/main (behind 10).
There was a problem hiding this comment.
🟡 documentation — request_changes codex/gpt-5.6-sol
The module documentation incorrectly claims downstream simp cannot recover the defining equation, although the equation is explicitly tagged @[simp].
TauCeti/NumberTheory/HeckeRing/GL2/Gamma0/NebentypusChar.lean:39— The main-results documentation sayssimpcannot recover the defining equation downstream, contradicting@[simp] lemma delta0NebentypusChar_applyat line 77. Fix: Clarify that unfolding orsimp [delta0NebentypusChar]fails downstream, while ordinarysimpsucceeds viadelta0NebentypusChar_apply.
Reply in this thread to contest a finding; that re-runs only this rubric and posts an answer here. (To fix it, just push a commit — that re-reviews on its own. To contest again after an answer, post a NEW reply rather than editing an old one.)
codex/gpt-5.6-sol · 31s · 38.7k in / 888 out tokens · reviewing this diff · rubric
AI review — changes requestedEach rubric is judged independently by multiple review agents; the PR merges only once every rubric is green — any rubric that is not green (changes requested, blocked, errored, stale, or not yet run) blocks the merge. See the rubrics.
♻️ = approved on an earlier commit, re-run before merge. Reviewing this diff at head |
documentation, round 2 on the reworked head: the module docs "incorrectly claim downstream simp cannot recover the defining equation, although the equation is explicitly tagged @[simp]". Correct, and self-inflicted. The bullet was written when delta0NebentypusChar_apply carried no attribute; api-design then required the @[simp] tag, which made the sentence false without anyone touching that line. What actually fails downstream is unfolding the sealed definition -- rfl, unfold, simp [delta0NebentypusChar], MonoidHom.comp_apply -- while plain simp succeeds precisely THROUGH this lemma. The bullet now says that. Swept the rest of the file for the same conflation: the only other mention is the comment above _apply, which already names simp [delta0NebentypusChar] rather than bare simp, so it was accurate and is unchanged. Also merges origin/main (behind 5).
Roadmap: ModularForms
The coefficient the
χ-twisted double-coset operator attaches to a monoid element:The definition is thin on purpose; the lemma is the content
Delta0UpperUnitis already aMonoidHom, so the character is a composition and needs nomultiplicativity argument. That is the whole point of having bundled it: AINTLIB's
delta0NebentypusDeltaCharbuilds the same character as a bareMonoidHomand dischargesmap_one'andmap_mul'by hand against itsClassical.choosewitness API.The lemma is what makes the definition worth naming, and it ships in the same PR rather than
being deferred. It says the character restricts on
Γ₀(N)to the inverse ofχ ∘ Gamma0Map— the character
modFormCharSpaceis defined by. That inverse is the convention, not a slip:the twisted operator divides by the character, each representative contributing
χ(·)⁻¹ • (f ∣[k] ·), so the value attached to a monoid element is the reciprocal of the oneattached to a group element acting on forms. Reading this as an extension of the nebentypus and
dropping the inverse would negate every twist downstream. It is inherited directly from
Delta0UpperUnit_mapGL, where the inverse first appears, so the proof is three rewrites.Two measured design decisions
delta0NebentypusChar_applyuses(rfl), notrfl. Barerflfails:The definition sits in a
public sectionwithout@[expose], so its body is sealed and a barerflwould opt the theorem into exporting that definitional equality. The parenthesised formelaborates against the sealed body instead.
Only one of the pair is
@[simp]._applyand_mapGLshare a left-hand side; taggingboth would let
_applyfire first and leave_mapGLunable to apply — thesimpNFfailuremode.
_mapGLis the normal form worth rewriting towards, so it carries the attribute and_applyrecords in its docstring why it does not.Absence
delta0NebentypusCharandDelta0NebentypusCharmatch zero files onmain. Checked withgit grep -w, notgit grep -E "\bfoo\b"—\bis unsupported in git grep's POSIX ERE andmatches nothing silently. Controls:
Delta0UpperUnitmatches 2 files, a nonsense name matches 0.delta0NebentypusDeltaChar— the source's name — matches one file, but with zero declarationlines: it is provenance prose in
Gamma0/UpperUnit.lean:59, not a declaration. A raw namegrep counts docstring mentions.
Placement
A new file
Gamma0/NebentypusChar.lean, importingGamma0/UpperUnit.leanforDelta0UpperUnit_mapGLandMathlib.Data.Complex.Basicforℂˣ. It is deliberately not addedto
UpperUnit.lean: that file is about the(ZMod N)ˣ-valued unit and is concurrently modifiedby #4319, and the character is a different object with a different codomain.
Provenance: github.com/CBirkbeck/AINTLIB @
2baa76f742bdb4fb8ee323fabba41203bd390e08,Apache-2.0,
projects/LeanModularForms/LeanModularForms/HeckeRIngs/GL2/Unified/TwistedHeckeRing.leanline 120, declaration
delta0NebentypusDeltaChar. Restated as a composition, since themultiplicativity obligations the source discharges by hand are already carried by
Delta0UpperUnit. The same citation is in the file's References section.Roadmap target
TauCetiRoadmap/ModularForms/README.md:1461-1462names the ring-hom layerHeckeRIngs/GL2/Unified/{Gamma0RingDn,NebentypusHeckeRingHom,RingTransport,TwistedHeckeRing}.leanwith
heckeRingDnandheckeRingHomCharSpaceas its objects;TwistedHeckeRing.leanis exactlywhere this character lives in the source.
heckeRingHomCharSpaceis README:407 (the operatorΦ_χ), whichEigenformAwayFromLevelis stated against (README:515), which README:609-617 needsfor
strongMultiplicityOne/StrongMultiplicityOne/ConstantMultiple.lean. So this isCLAUDE.md's "supplies a prerequisite that a specific target needs" — the twisting character is
what the
χ-twisted Hecke ring is built from, two rungs below the Layer-5 headline.