Session 25 — ii′-5 R-bound: design + level-2 EM disc bound
08-22-2026 → 08-22-2026 · kimi-k3 · 33 messages · 485.6k tokens · $13.2938
Summary
Focus: ii′-5 design + level-2 EM disc bound (research session 022).
What happened:
- D-067 design for the R-bound: Davenport disc at 2+it + FE-reflection; Stirling-free, Hadamard-free.
- ii′-5b: the level-2 Euler–Maclaurin ζ representation and
norm_riemannZeta_le_disc(‖ζ‖ ≤ (3/4)|t|² on the disc).
Outcome: the growth input for the partial-fraction identity was proved.
let me know where we left of so we can continue
thinking (403 chars)
The user wants to know where we left off. STATE.md is comprehensive. Let me also skim the latest journal entry (session-023) briefly for any additional context, then give a concise summary.
Actually, STATE.md is quite complete. Let me just skim the journal-023 quickly to confirm gotchas, but STATE.md already summarizes them. I think I can answer directly from STATE.md. Let me give a concise summary.
Here's where we stand.
## Big picture
**Tier ii′** (Phase 5B) is in progress — closing `SfBoundProp` in Lean **before** Paper A submission (your directive; Paper A stays frozen/submittable throughout).
**Done so far:** ii′-0 (design D-064 + liCoeff defect found + crux identity `Sf = Res₁`), ii′-1a (defect repaired), ii′-1b (residue machinery, `rectInt'_Jlag`), ii′-2 (elementary swaps), ii′-3 design (D-066, route β4) + ii′-3a (pieces A+B proved), ii′-4 (L3 + L1 + `zeroMult_neg_two`), ii′-5a (D-067 design), ii′-5b (level-2 ζ representation, `‖ζ‖ ≤ (3/4)|t|²` on the disc), **ii′-5c PART 1** (LiDisc.lean: `zeroDiscFinset`, `scaledZeta`, F(0)=1, multiplicity invariance, `scaledZeta_jensen_count`).
## Next action — Session 024: ii′-5c back half (~1 session est.)
In LiDisc.lean:
1. **R-gap selection** — scale `exists_avoiding_midpoint` to window [2.3, 2.4] (ℓ-parameterized variant, reuse ii′-4's proof); k from the Jensen count.
2. **g := ζ/∏(s−ρₖ)^{mₖ}** analytic + nonvanishing on the closed ball (normal form removes each collected zero).
3. **Bounds** — |g| ≤ (3/4)|t|²·δ^{−M} on the outer circle; −log|g(s₀)| ≤ log 3 + M·log(2.4).
4. **BC assembly** — `LogOfAnalyticFunction` + `BorelCaratheodoryDeriv` ⟹ loose R-bound `‖ζ′/ζ − Σ m/(s−ρ)‖ ≤ C·(log|t|)²`, constants deliberately loose (per D-067 §6: the tight 10.5/48 come later from the partial-fraction identity in 5f, not from the disc).
**Read first:** D-067 §6 (route revision) + journal-023 gotchas (`analyticOrderNatAt = analyticOrderAt.toNat` by def; `Filter.EventuallyEq.xxx` terms not dot-notation on unfolded forms; `AnalyticAt.comp_of_eq` for beta-reduced points; `Nat.cast_analyticOrderNatAt`).
## Remaining map after 5c
ii′-5d (FE-reflection + left digamma bound) → ii′-5e (partial-fraction identity) → ii′-5f (tight analysis) → ii′-3b (moments) → ii′-3c (crux) → ii′-6 (L0 assembly) → ii′-7 (close + audit + paper Appendix B).
No blockers. Ready to start on ii′-5c back half whenever you are.
I am ready, let's do it.
thinking (194 chars)
Now let me look at StrongPNTPrefix for `LogOfAnalyticFunction`, `BorelCaratheodoryDeriv`, `ZeroFactorization`, `ZerosBound`, `SetOfZeros`, `finiteSetOfZeros_mono`. Let me grep the vendored repo.
Now the key StrongPNTPrefix lemmas I'll need.
tool: Grep
input
{
"pattern": "theorem (LogOfAnalyticFunction|BorelCaratheodoryDeriv|ZerosBound|ZeroFactorization)",
"path": "D:\\Python\\Quantum\\research\\lean\\zeta-23-lean\\Zeta23\\FromPNTPlus\\StrongPNTPrefix.lean",
"output_mode": "content",
"-A": 30
}
thinking (351 chars)
Interesting! Zeta23 already has `Cf r f` — this is exactly the "g" function: f divided by the product over zeros in the disc of radius r, with the cofactor at zeros themselves. And `CfAnalytic` gives analyticity on closedBall(0, R). Let me look at more of the Cf API — there may be lemmas about nonvanishing and norm bounds. Let me grep for Cf lemmas.
Zeta23 already has `Cf r f` — the Blaschke-quotient g built in. Let me see its full API.
tool: Grep
input
{
"pattern": "(lemma|theorem)\\s+\\w*Cf\\w*|(lemma|theorem)\\s+\\w*Blaschke\\w*",
"path": "D:\\Python\\Quantum\\zeta-23-lean\\Zeta23\\FromPNTPlus\\StrongPNTPrefix.lean",
"output_mode": "content",
"-A": 8
}
thinking (53476 chars)
Excellent — Zeta23's `Cf r f` is EXACTLY the g function (f divided by the zero-product over the radius-r zero set), with:
- `CfAnalytic` (r < R < 1): Cf r f analytic on closedBall(0, R)
- `BlaschkeB r R f z = Cf r f z * ∏ (R − z·conj ρ/R)^m` and `BlaschkeNonzero` on closedBall(0, r)
- `DiskBound`: ‖BlaschkeB r R f z‖ ≤ B on closedBall(0, R)
Hmm, but what about nonvanishing of Cf itself? On closedBall(0,r), BlaschkeB is nonzero AND the product factor ∏(R − z·conjρ/R)^m is nonzero (that's hBProd inside BlaschkeNonzero's proof) — so Cf is nonzero on closedBall(0, r) too (as a factor of a nonzero product... wait, BlaschkeB = Cf * prod, both factors... actually from the proof, BlaschkeNonzero shows Cf z ≠ 0 AND prod ≠ 0 separately — the mul_ne_zero requires both. Actually reading more carefully: in the case z ∈ zeros, it shows `ZeroFactor f z / ∏... ≠ 0` (that's Cf z) times hBProd. So yes both factors are nonzero on closedBall(0, r). But that nonvanishing of Cf is only on closedBall(0, r), not on the full closedBall(0, R).
Hmm, wait. For my application: g should be nonvanishing on the disc where we take the log. Let me re-think the geometry.
Design per STATE.md:
- Disc center s₀ = 2+it, outer radius R = 5/2.
- Zero-collection radius r_c = 2.3 (all |γ−t|<1 zeros have |ρ−s₀| ≤ √5 ≈ 2.236 < 2.3).
- R-gap: choose R ∈ [2.3, 2.4]?? Wait STATE.md says "exists_avoiding_midpoint SCALED to window [2.3, 2.4]". Hmm, but the outer radius in ii′-5b's bound is 5/2. Let me re-read.
From STATE.md NEXT ACTION:
1. R-gap selection: the distance-value finset (zeroDiscFinset).image (·−s₀‖-distances); exists_avoiding_midpoint SCALED to window [2.3, 2.4] (add an ℓ-parameterized variant — reuse ii′-4's proof); k from scaledZeta_jensen_count (distinct ≤ mult-weighted since each zeroMult ≥ 1). Collection := zeros with |ρ−s₀| ≤ R.
Hmm, so the outer radius R is chosen in [2.3, 2.4] (not 2.5!) avoiding the zero-distance values, with clearance δ = 1/(2(k+1)). The zeros are collected with |ρ − s₀| ≤ R. The collection radius r_c = R ∈ [2.3, 2.4]. Then:
- On the outer circle |s−s₀| = R: every zero of ζ in the closed disc B(s₀, 5/2)... wait no. Hmm, but we need |ζ| bounded on the outer circle. We have ‖ζ‖ ≤ (3/4)|t|² on B(s₀, 5/2) ⊇ B(s₀, R) since R ≤ 2.4 < 2.5. Good.
- g(s) := ζ(s)/∏ₖ(s−ρₖ)^{mₖ} where the product is over zeros in B(s₀, R)... The point of choosing R in a gap: on the circle |s−s₀| = R there are NO zeros, and moreover every zero ρₖ of ζ with |ρₖ−s₀| ≤ R satisfies |ρₖ−s₀| ≤ R − δ where δ = 1/(2(k+1)) — the clearance. So on the circle, |s−ρₖ| ≥ δ, giving |g| ≤ |ζ|·δ^{−M} on the circle, hence on the closed disc by maximum principle...
Wait, but is g analytic on the closed disc B(s₀, R)? g = ζ/∏(s−ρₖ)^{mₖ} where ρₖ ranges over zeros in the OPEN disc |ρ−s₀| < R (equivalently ≤ R − δ... hmm, since R avoids all distance values, {|ρ−s₀| ≤ R} = {|ρ−s₀| < R} = {|ρ−s₀| ≤ R−δ}). At each zero ρₖ of multiplicity mₖ, ζ has the local factorization ζ(s) = (s−ρₖ)^{mₖ}·hₖ(s) with hₖ analytic and nonzero at ρₖ. Since all zeros in the disc are collected, g is analytic and nonvanishing on B(s₀, R) (need care at the boundary but since no zeros on the circle and the zeros inside are removed, g is analytic on a neighborhood of the closed ball — hmm, actually ζ is analytic on B(s₀, 5/2 minus {1})... and g is analytic on the open disc B(s₀, R') for some R' slightly bigger than R? No wait — the zeros at exactly distance R don't exist, and zeros with distance in (R, R + ε) for small ε... the next zero distance is at least R + δ' for some δ' > 0? Actually the distance values form a finite set (finitely many zeros in B(s₀, 5/2)), so there's a gap around R: no zero has distance in (R−δ, R+δ') where δ' = distance to the next value. So g is in fact analytic on B(s₀, R + δ') which is a neighborhood of closedBall(s₀, R).
But careful: zeros OUTSIDE the disc but at distance < 5/2 exist possibly; g only divides by the inside zeros; outside zeros at distance > R are fine since (s − ρ) ≠ 0 on B(s₀, R) for those. So g analytic + nonvanishing on B(s₀, R + δ') ⊇ closedBall(s₀, R).
Approach in Lean: rather than building g directly via local factorizations myself, maybe I can reuse the scaled picture and Zeta23's `Cf`! In the scaled variable w (F(w) = ζ(s₀ + (5/2)w)/ζ(s₀) on unit disc), the zeros of F in {|w| ≤ r} correspond to zeros of ζ in {|s−s₀| ≤ (5/2)r}. The collection radius r_c = 2.3 → scaled 2.3/2.5 = 0.92. R-gap chosen in [2.3, 2.4] → scaled [0.92, 0.96].
Zeta23's `Cf r f` with r = R_scaled = R/2.5 ∈ [0.92, 0.96], R'(second arg) = 0.99: `CfAnalytic (r<R') (R'<1)` gives Cf analytic on closedBall(0, R'). And BlaschkeNonzero gives BlaschkeB ≠ 0 on closedBall(0, r) — and BlaschkeB = Cf · ∏(Blaschke factors); the Blaschke factors (R − z conj ρ/R) for |z| ≤ r < R... each factor has norm ≥ R − |z||ρ|/R·... For |z| ≤ r and |ρ| ≤ r: |R − z conjρ/R| ≥ R − |z||ρ|/R ≥ R − r²/R = (R²−r²)/R > 0. So Cf ≠ 0 on closedBall(0, r) as well (quotient of nonzero by nonzero... actually BlaschkeNonzero's proof itself establishes both factors nonzero — hBProd and the Cf part. But it's not split into a separate lemma. Hmm — but I can prove `Cf r f z ≠ 0` on closedBall(0,r) myself: BlaschkeB r R f z ≠ 0 (BlaschkeNonzero) and BlaschkeB = Cf * prod with prod ≠ 0 (re-derive hBProd) ⟹ Cf ≠ 0. That's easy.
Wait, actually for LogOfAnalyticFunction I need B nonvanishing on closedBall(0, R) where R is the outer radius and J_B analytic on ball(0, R), deriv identity on closedBall(0, r) with r < R. So: use B := Cf r_coll F where r_coll = the scaled collection radius (= R_gap/2.5, with R_gap ∈ [2.3,2.4] the gap radius)... hmm wait. Let me set up the scaled geometry precisely.
Unscaled: center s₀, zeros collected with |ρ−s₀| ≤ R_c where R_c ∈ [2.3, 2.4] chosen in a gap with clearance δ from all zero-distances. Application radius r_a = 3/2 (σ ∈ [1/2, 7/2] region: |s−s₀| ≤ 3/2 covers it).
Scaled by 5/2: F(w) = ζ(s₀+(5/2)w)/ζ(s₀). Collection radius in w: r_c = R_c/(5/2) ∈ [0.92, 0.96]. Clearance in w: δ_w = δ/(5/2). Application radius: r_aw = (3/2)/(5/2) = 0.6.
Plan with Zeta23 machinery:
- B := Cf r_c F — analytic on closedBall(0, R') for any R' < 1 with r_c < R', e.g. R' = 0.99 (CfAnalytic). F's zeros in {|w| ≤ r_c} = scaled zeros of ζ in {|s−s₀| ≤ R_c}... wait need F zero ⟺ ζ zero: F = ζ(aff)/ζ(s₀), ζ(s₀) ≠ 0, so yes, zeros of F in the ball correspond exactly.
Hmm wait, actually — is Cf's zero set exactly the zeros with |w| ≤ r_c? Cf r F divides by zeros in SetOfZeros r F = {‖ρ‖ ≤ r ∧ F ρ = 0}. Yes.
- B nonvanishing on closedBall(0, r_c): from BlaschkeNonzero + product nonvanishing as above. Actually hold on — I want B nonvanishing on closedBall(0, R'') for some R'' > r_c up to the next zero-distance. But since R_c was chosen in a gap: zeros of F have norms outside (r_c, r_c + δ'_w). Actually the NEXT zero beyond R_c: the finite set of distances in B(s₀, 5/2) has a gap after R_c... but zeros exactly at distance in (R_c, next) — there are none until the next distance value d_next > R_c. And d_next ≥ R_c + something? The midpoint pigeonhole gives clearance δ below R_c from the values ≤ R_c... hmm, let me think about what exists_avoiding_midpoint gives: S = finset of distances, T with |x − T| ≥ 1/(2(k+1)) for ALL x ∈ S (all distances, not just those ≤ T). So with T = R_c: every zero in B(s₀, 5/2) has |‖ρ−s₀‖ − R_c| ≥ δ where δ = 1/(2(k+1)). So zeros are all at distance ≤ R_c − δ or ≥ R_c + δ.
So in fact B = Cf r_c F is analytic AND nonvanishing on closedBall(0, r_c + δ_w)... well, on the region up to the next zero. Nonvanishing on closedBall(0, r_c): yes. Actually for LogOfAnalyticFunction I need nonvanishing on the SAME closedBall(0, R_log) where analyticity holds, with R_log being the radius where I bound Re J on the ball(0, R_log). Hmm.
Let me re-read LogOfAnalyticFunction signature:
```
theorem LogOfAnalyticFunction {r R : ℝ} {B : ℂ → ℂ}
(zero_lt_r: 0 < r) (r_lt_R : r < R)
(BanalyticOnNhdOfDR: AnalyticOnNhd ℂ B (Metric.closedBall (0 : ℂ) R))
(Bnonzero: ∀ z ∈ Metric.closedBall (0 : ℂ) R, B z ≠ 0) :
∃ (J_B: ℂ → ℂ), (AnalyticOnNhd ℂ J_B (Metric.ball 0 R)) ∧
(J_B 0 = 0) ∧
(∀ z ∈ Metric.closedBall 0 r, (deriv J_B) z = (deriv B) z / (B z)) ∧
(∀ z ∈ Metric.ball 0 R, Real.log ‖B z‖ - Real.log ‖B 0‖ = (J_B z).re)
```
So: B analytic on closedBall(0, R) and NONZERO on all of closedBall(0, R). Then J_B analytic on ball(0, R), deriv J_B = B'/B on closedBall(0, r) (the smaller radius), and Re J_B = log‖B‖ − log‖B(0)‖ on ball(0, R).
Then BorelCaratheodoryDeriv: f analytic on ball(0, R), f(0) = 0, Re f ≤ M on ball(0, R), z ∈ closedBall(0, r) ⟹ ‖deriv f z‖ ≤ 16MR²/(R−r)³.
So for the scaled picture:
- B := Cf r_c F, analytic on closedBall(0, R_out) with R_out := 0.99 (say), and NONVANISHING on closedBall(0, R_out)?? Is Cf r_c F nonvanishing on all of closedBall(0, 0.99)? NO — Cf removes only zeros with ‖ρ‖ ≤ r_c; zeros with r_c < ‖ρ‖ ≤ 0.99 remain zeros of Cf! (Cf z = F z / ∏... for z not in the zero set, which vanishes when F z = 0.)
Hmm. So Cf r_c F has zeros in the annulus r_c < ‖w‖ ≤ 0.99 potentially. So I can't apply LogOfAnalyticFunction with R = 0.99.
Resolution: apply LogOfAnalyticFunction with R = R_log where R_log is chosen such that closedBall(0, R_log) contains no zeros beyond r_c. Since the distances have a gap: all zeros satisfy ‖ρ‖ ≤ r_c − δ_w or ‖ρ‖ ≥ r_c + δ_w (in scaled units, δ_w = (2/5)·δ). Hmm wait: zeros with distance ≥ R_c + δ in unscaled ⟹ ‖ρ_w‖ ≥ r_c + δ_w. So on closedBall(0, r_c + δ_w/2) (say), the only zeros are those with ‖ρ‖ ≤ r_c − δ_w < r_c, all collected. So B = Cf r_c F is analytic + nonvanishing on closedBall(0, r_c + δ_w/2) ⊇ closedBall(0, r_c).
But hold on — is B nonvanishing at the collected zeros themselves? Yes — Cf's whole point: at z ∈ zero set, Cf z = ZeroFactor f z / ∏_{ρ ≠ z}(z−ρ)^m, nonzero by ZeroFactorization. That's what CfAnalytic's proof and BlaschkeNonzero handle.
So: apply LogOfAnalyticFunction with:
- R_log := r_c + δ_w/2 (or anything in (r_c, r_c + δ_w))
- B := Cf r_c F
- B analytic on closedBall(0, R_log): need R_log < 1 for CfAnalytic... r_c ≤ 0.96, δ_w = (2/5)·δ where δ = 1/(2(k+1)), k = zero count ~ log t². For t large δ is tiny; for small t... δ ≤ 1/2 so δ_w ≤ 0.2. r_c + δ_w/2 ≤ 0.96 + 0.1 = 1.06?? Could exceed 1!
Hmm. Problem: CfAnalytic requires R < 1 (analyticity only on closedBall(0,1) from scaledZeta_analytic). If r_c = 0.96 and δ_w/2 pushes past 1, trouble. Fix: shrink the window. Choose R_c ∈ [2.3, 2.35] maybe. Actually the scaled window: the midpoint pigeonhole works on a window [a, a+ℓ] of length ℓ with midpoints spaced ℓ/(k+1), clearance ℓ/(2(k+1)).
Generalized midpoint lemma (ℓ-parameterized): S finset of reals, card ≤ k, window [a, a+ℓ]: ∃ T ∈ [a, a+ℓ] with |x−T| ≥ ℓ/(2(k+1)) for all x ∈ S.
Take window [2.3, 2.4], ℓ = 0.1: clearance δ = 0.1/(2(k+1)) = 1/(20(k+1)). r_c = R_c/2.5 ∈ [0.92, 0.96]. δ_w = δ/2.5 = 1/(50(k+1)). R_log = r_c + δ_w/2 ≤ 0.96 + 1/(100(k+1)) ≤ 0.96 + 0.01 = 0.97 < 1.
And BorelCaratheodory: need f = J_B on ball(0, R_log), Re f ≤ M there, then deriv on closedBall(0, r_a_scaled) where r_a_scaled = 0.6. Factor: 16·R_log²/(R_log − r_a)³ ≤ 16·0.97²/(0.92−0.6)³ ≤ 16·0.941/0.0328 ≈ 459. Loose but fine (we only need SOME C·(log|t|)²).
Hmm wait, but actually I realize I should double check whether B = Cf r_c F is nonvanishing on closedBall(0, R_log): zeros of Cf r_c F = ? For z ∈ ball with ‖z‖ ≤ R_log < next zero distance: if F z ≠ 0 then Cf z = F z/prod ≠ 0 (prod nonzero since each factor (z−ρ) ≠ 0 for ‖ρ‖ ≤ r_c − δ_w... wait ‖z−ρ‖: z could equal ρ? No: if F z ≠ 0, z ≠ ρ for all zeros ρ. Fine.) If F z = 0 then z is a zero with ‖z‖ ≤ R_log, so ‖z‖ ≤ r_c − δ_w < r_c (by the gap), so z ∈ SetOfZeros r_c F, and Cf z = ZeroFactor/prod_{ρ≠z} ≠ 0 by ZeroFactorization + the product nonzero (each (z−ρ) ≠ 0 for ρ ≠ z since zeros are distinct points in the finset).
OK so the nonvanishing argument needs: for z with ‖z‖ ≤ R_log and F z = 0: z ∈ SetOfZeros r_c F, i.e. ‖z‖ ≤ r_c. From the gap: ‖z‖ is a distance value (z zero of F ⟹ ζ(s₀+(5/2)z) = 0 ⟹ ‖(5/2)z‖ = (5/2)‖z‖ is a zero-distance; if ‖z‖ > r_c then ‖z‖ ≥ r_c + δ_w > R_log contradiction). Good.
And ZeroFactor nonvanishing: ZeroFactorization gives ZeroFactor f z = h_z z with h_z z ≠ 0 (its conclusion includes `ZeroFactor f ρ = h_ρ ρ ∧ h_ρ ρ ≠ 0`). It needs RleOne : R < 1 where the zero is in SetOfZeros R f — take R = r_c < 1 ✓, hfAnalytic on closedBall(0,1) ✓ (scaledZeta_analytic), f 0 ≠ 0 ✓ (scaledZeta_zero: F 0 = 1).
Great — so actually I might not even need to construct g myself at all: `Cf r_c F` IS g (up to the constant ζ(s₀) factor... wait: F = ζ(aff)/ζ(s₀), and Cf r_c F = F/∏(w−ρ_w)^{m} off the zero set = ζ(aff)/(ζ(s₀)·∏(w−ρ_w)^m). The unscaled g(s) = ζ(s)/∏(s−ρₖ)^{mₖ} = ζ(s₀+(5/2)w)/∏((5/2)(w−ρ_w))^{m} = ζ(s₀)·F(w)·... hmm: g(s₀+(5/2)w) = ζ(s₀+(5/2)w)/∏(s₀+(5/2)w−ρₖ)^{mₖ} = ζ(s₀)·F(w)/∏((5/2)(w−ρ_{wₖ}))^{mₖ} = [ζ(s₀)/(5/2)^{Σm}]·Cf r_c F (w) (off zeros). Constants don't matter for log derivatives. I can just work with B := Cf r_c F entirely in the scaled picture, then translate back: deriv of log... Let me think about what the final statement needs.
FINAL TARGET (loose R-bound): for s = σ+it, σ ∈ [1/2, 7/2], |t| ≥ 10, ζ(s) ≠ 0:
‖logDeriv ζ s − Σ_{ρ ∈ nearZeros t} (zeroMult ρ)/(s−ρ)‖ ≤ C·(log|t|)²
where nearZeros t = zeros with |γ−t| < 1 (as a finset — from ii′-4's zeroWindow at windows [t−1, t] etc., or via zeroDiscFinset filtered).
Proof chain:
1. R-gap: R_c ∈ [2.3, 2.4] with clearance δ = 1/(20(k+1)) from all zero-distances in B(s₀, 5/2); k = card of distance finset ≤ mult-weighted Jensen count (each zeroMult ≥ 1 ⟹ distinct count ≤ weighted count). Hmm: the distance finset = image of zeroDiscFinset under (· − s₀) norm; card of image ≤ card of zeroDiscFinset ≤ Σ mult (since each mult ≥ 1) ≤ Jensen bound. So k := (zeroDiscFinset t).card works: distances image card ≤ card ≤ Σρ mult.
Wait, actually for exists_avoiding_midpoint I need card S ≤ k for S = distance finset. I can just take k := (zeroDiscFinset t).card and S := image, card S ≤ card = k. Clearance δ = 1/(20(k+1))... hmm wait, ℓ/(2(k+1)) with ℓ = 1/10: δ = (1/10)/(2(k+1)) = 1/(20(k+1)). OK.
2. Collection: zeros with |ρ−s₀| ≤ R_c (equivalently < R_c, same by gap). In scaled: SetOfZeros r_c F.
3. B := Cf r_c F: analytic on closedBall(0, R_log), R_log := r_c + δ_w/2; nonvanishing there.
4. LogOfAnalyticFunction (r := r_a' = 0.6, R := R_log): J_B analytic on ball(0, R_log), J_B 0 = 0, deriv J_B = B'/B on closedBall(0, 0.6), Re J_B = log‖B‖ − log‖B 0‖ on ball(0, R_log).
5. Bound Re J_B on ball(0, R_log): need ‖B‖ on... Re J_B(w) = log‖B w‖ − log‖B 0‖.
- Upper bound log‖B w‖ for ‖w‖ < R_log: B = F/prod (off zeros) — but at zeros use continuity... Bound via maximum modulus on the circle ‖w‖ = r' for r' slightly less than R_log? Since B analytic on closedBall(0, R_log), max on closedBall = max on boundary sphere ‖w‖ = R_log. On ‖w‖ = R_log: ‖B w‖ = ‖F w‖/∏‖w−ρ‖^m ≤ ‖F w‖·(δ_w/2)^{−M} (each ‖w−ρ‖ ≥ ‖w‖ − ‖ρ‖ ≥ R_log − (r_c − δ_w) = δ_w/2 + δ_w = 3δ_w/2... wait: ‖ρ‖ ≤ r_c − δ_w, ‖w‖ = R_log = r_c + δ_w/2 ⟹ ‖w−ρ‖ ≥ R_log − (r_c − δ_w) = 3δ_w/2.) And ‖F w‖ ≤ (9/4)|t|² (Jensen hB from ii′-5c: bound holds for ‖w‖ ≤ 99/100; R_log ≤ 0.97 ≤ 0.99 ✓).
- So log‖B w‖ ≤ log((9/4)|t|²) + M·log(2/(3δ_w)) where M = Σ mult ≤ Jensen count ≤ log((9/4)|t|²)/log(33/32).
- log‖B 0‖: B 0 = Cf r_c F 0 = F 0/∏(0−ρ)^m = 1/∏(−ρ)^m. ‖B 0‖ = 1/∏‖ρ‖^m ≥ 1 (since ‖ρ‖ ≤ r_c < 1... ∏‖ρ‖^m ≤ r_c^M ≤ 1) so −log‖B 0‖ ≤ 0... wait Re J_B = log‖B w‖ − log‖B 0‖, and log‖B 0‖ = −Σm log‖ρ‖ ≥ 0 since ‖ρ‖ < 1... hmm log‖ρ‖ < 0 so −Σm·log‖ρ‖ > 0, so log‖B 0‖ = +Σm·(−log‖ρ‖) ≥ 0. So Re J_B(w) ≤ log‖B w‖ ≤ the bound. Fine — I just need an upper bound on Re J_B.
Hmm wait, actually the maximum modulus principle for ‖B‖ on closedBall(0, R_log): `AnalyticOn.norm_le_of_norm_le_on_sphere` (used in DiskBound). B analytic on closedBall(0, R_log) needs R_log < 1 for CfAnalytic ✓ (0.97 < 1).
So M_bound := log((9/4)|t|²) + M·log(2/(3δ_w)) and Re J_B ≤ M_bound on ball(0, R_log). Note log(2/(3δ_w)) = log(2·50(k+1)/3) = log(100(k+1)/3) — grows like log k ~ log log |t|. And M ≤ log((9/4)|t|²)/log(33/32) ~ 2·log|t|/0.0308 ≈ 65·log|t|. So M_bound ≈ log((9/4)|t|²)·[1 + log(100(k+1)/3)/log(33/32)] ~ (log|t|)·(log log|t|)-ish... times BC factor 459... The final bound is C·(log|t|)·loglog|t|?? Hmm, that's worse than (log|t|)²? No wait: M·log(1/δ_w) where M ~ 65 log|t| (for large t; actually log((9/4)t²)/log(33/32)) and log(1/δ_w) = log(50(k+1)) with k ≤ M. So M_bound ~ 65·log|t| + 65·log|t|·log(50·65·log|t|)... = O(log|t| · log log|t| · ...) hmm, M·log(1/δ) = 65 log|t| · (log(50(k+1))) and k+1 ≤ M+1 ~ 65 log|t| + 1, so log(50(k+1)) ~ log(3250 log|t|) = log 3250 + log log |t|. So M_bound ~ 65·log|t|·(8.1 + log log|t|) + ... — this is O(log|t|·loglog|t|), which is o((log|t|)²).
So the final loose bound C·(log|t|)² works with room to spare. For the Lean statement I should pick something clean and provable. Options: state with an explicit constant like ‖R(s)‖ ≤ 1000·(log|t|)² for |t| ≥ 10? Need to verify the chain delivers that with all the factors. Or state it as ≤ C·(log|t|)² with C explicit-but-huge. Since it's purely existential growth input for 5e, a cleaner formulation might be:
‖logDeriv ζ s − Σ_{ρ ∈ nearZeros t} zeroMult ρ/(s−ρ)‖ ≤ C·(Real.log |t|)^2 for |t| ≥ 10, σ∈[1/2,7/2], with C := some explicit number (like 10^6) that the proof delivers.
Actually — for ii′-5e what do we actually need? |F| = o(R) on γ-gap circles where F = ζ′/ζ − (series + elementary terms). On a big circle of radius R (in the γ-gap), |ζ′/ζ(s)| ≤ C(log R)²-ish for s on the circle (via 5c on right + 5d on left — reflection). The series terms on the circle are O((log R)²). So F = O((log R)²) = o(R). Any explicit C works. So the cleanest: state the loose bound as an EXISTENTIAL: ∃ C > 0, ∀ t, |t| ≥ 10, ∀ σ ∈ [1/2, 7/2]... ‖...‖ ≤ C·(log|t|)². That avoids me having to track constants carefully!
Hmm, but honest mathematics: an existential with an uncomputated constant is fine as a growth input. But wait — D-067 §6 says "constants deliberately loose". An existential constant theorem `∃ C, ...` is cleaner and truly loose. But it does weaken auditability slightly. Let me think… For the formalization effort, tracking an explicit C through max-modulus + BC + Jensen is doable but adds ~30% work and risk. The two-stage plan only needs existence. D-067's revised ii′-5c says "the LOOSE disc R-bound (any A < ∞)". So `∃ C : ℝ, 0 < C ∧ ∀ ...` is explicitly sanctioned by the design.
Hmm, but hold on — there's a subtlety: the sum in the target is over nearZeros t = zeros with |γ − t| < 1 (im-window), but the disc collects zeros with |ρ − s₀| ≤ R_c (which includes zeros with |γ−t| up to R_c ≈ 2.4 and β ∈ [−1/2... wait β ∈ (0,1) since nontrivial; |ρ−s₀| ≤ 2.4 with s₀ = 2+it means γ−t ∈ [−2.4, 2.4]). The deriv J_B = B′/B = F′/F − Σ_{collected} mₖ/(w−ρ_wₖ). Translating back: logDeriv ζ s = (2/5)·(F′/F)(w) where s = s₀+(5/2)w... let me redo: F(w) = ζ(s₀+(5/2)w)/ζ(s₀), F′(w) = (5/2)ζ′(s₀+(5/2)w)/ζ(s₀), so F′/F = (5/2)·ζ′/ζ(s₀+(5/2)w) = (5/2) logDeriv ζ s. And B = F/∏(w−ρ_w)^m ⟹ B′/B = F′/F − Σ m/(w−ρ_w). So (5/2)·logDeriv ζ s = (B′/B)(w) + Σ m/(w−ρ_w) = (B′/B)(w) + Σ (5/2)·m/(s−ρ). So logDeriv ζ s − Σ_{collected} m/(s−ρ) = (2/5)(B′/B)(w). Then:
R(s) = logDeriv ζ s − Σ_{near} m/(s−ρ) = (2/5)(B′/B)(w) + Σ_{collected, not near} m/(s−ρ).
The collected-not-near zeros: |γ−t| ≥ 1 ⟹ |s−ρ| ≥ 1, so each term ≤ m, and total ≤ Σ m ≤ M ≤ Jensen. So ‖R(s)‖ ≤ (2/5)·‖B′/B‖(w) + M ≤ (2/5)·16·M_bound·R_log²/(R_log−0.6)³ + M.
With R_log − 0.6 ≥ 0.92 − 0.6 = 0.32 (r_c ≥ 0.92), R_log ≤ 0.97: factor 16·0.97²/0.32³ ≈ 16·0.9409/0.032768 ≈ 459. So ‖R‖ ≤ (2/5)·459·M_bound + M ≤ 184·M_bound + M.
M_bound = log((9/4)|t|²) + M·log(2/(3δ_w)) where δ_w = δ/(5/2) = (2/5)·(1/(20(k+1))) = 1/(50(k+1)), so 2/(3δ_w) = 100(k+1)/3. With k ≤ M ≤ log((9/4)|t|²)/log(33/32):
For |t| ≥ 10: log((9/4)|t|²) = 2log|t| + log(9/4) ≤ 2log|t| + 0.811. And log(33/32) = log(1.03125) ≈ 0.03077. So M ≤ (2log|t|+0.811)/0.03077 ≈ 65·log|t| + 26.4. k+1 ≤ M+1. log(100(k+1)/3) ≤ log(100(M+1)/3).
M_bound ≤ L₁ + M·log(100(M+1)/3) where L₁ = 2log|t|+0.811.
For |t| ≥ 10, log|t| ≥ 2.303. M ≤ 65L+26.4 where L = log|t|. log(100(M+1)/3) ≤ log(100(65L+27.4)/3) ≤ log(2167L + 913). For L ≥ 2.303: 2167L+913 ≤ 2167L + 396L... hmm 913/2.303 ≈ 396, so ≤ 2563L... that gives log ≤ log 2563 + log L = 7.85 + log L. So M·log(...) ≤ (65L+26.4)(7.85+log L). With log L ≤ L/e... log L ≤ L − 1 (for L ≥ 1... log L ≤ L−1 yes). So ≤ (65L+26.4)(L+6.85) = 65L² + 445L + 26.4L + 181 ≈ 65L² + 471L + 181. For L ≥ 2.303: 471L ≤ 205L², 181 ≤ 34L² ⟹ ≤ 304L². So M_bound ≤ L₁ + 304L² ≤ (L+0.811... ≤ 0.35L² + ...) let's say M_bound ≤ 305L² for L ≥ 2.303 (very loose). Then ‖R‖ ≤ 184·305L² + (65L+26.4) ≤ 56120L² + 65L + 26.4 ≤ 56120L² + 34L² ≤ 56154L². So C = 60000, say. These are silly-loose constants — fine for the growth input, and I can actually prove them in Lean with enough linarith/nlinarith slack.
Hmm, but actually proving such a chain in Lean requires many steps of real-inequality grunt work (log monotonicity, etc.). The existential formulation `∃ C : ℝ, ∀ ...` lets me... no, it doesn't help — I still need to prove the chain for SOME explicit C internally. OK whatever, it's mechanical.
Actually wait. Let me reconsider: do I even need the max-modulus detour for Re J_B? LogOfAnalyticFunction gives Re J_B(w) = log‖B w‖ − log‖B 0‖ directly on ball(0, R_log). And ‖B w‖ for w ∈ ball(0, R_log): B is continuous on the compact closedBall(0, R_log)... but I need an explicit bound. Max-modulus on sphere: AnalyticOn.norm_le_of_norm_le_on_sphere — B analytic on closedBall(0, R_log) (needs AnalyticOn on the ball + the sphere bound; DiskBound used exactly this). On the sphere ‖w‖ = R_log, no zeros (gap), so B = F/prod there pointwise, giving the norm bound. So:
∀ w ∈ closedBall(0, R_log): ‖B w‖ ≤ (9/4)|t|²·(3δ_w/2)^{−M} where the exponent M is... careful: ∏‖w−ρ‖^{m_ρ} ≥ (3δ_w/2)^{Σm} requires each factor ‖w−ρ‖ ≥ 3δ_w/2 — yes on the sphere. And Σm over the collected finset = the Jensen-counted sum. So ‖B w‖ ≤ (9/4)|t|²·(3δ_w/2)^{−M_J} where M_J := the actual sum (bounded by the Jensen RHS). To avoid real-power headaches, keep it as `(3*δ_w/2)^(-(M_J : ℤ))`? or just rpow... Better: `(2/(3δ_w))^(M_J)` with M_J : ℕ cast — natural power of a positive real, fine.
Then log‖B w‖ ≤ log((9/4)|t|²) + M_J·log(2/(3δ_w)) via Real.log_le_log, log_mul, log_pow (Nat cast). And Re J_B(w) = log‖B w‖ − log‖B 0‖ ≤ log‖B w‖ + |log‖B 0‖|... need −log‖B 0‖ bounded. B 0 = 1/∏(−ρ)^m. log‖B 0‖ = −Σm log‖ρ‖. ‖ρ‖ ≤ r_c − δ_w < 1 so log‖ρ‖ < 0, so log‖B 0‖ > 0, so Re J_B ≤ log‖B w‖ directly. Need log‖B 0‖ ≥ 0: = −Σ m_ρ log‖ρ‖ ≥ 0 since each log‖ρ‖ ≤ log(r_c−δ_w) < 0... need ‖ρ‖ ≤ r_c − δ_w for collected zeros: from the gap, collected zeros (‖ρ_w‖ ≤ r_c) actually satisfy ‖ρ_w‖ ≤ r_c − δ_w. Wait — the gap is on DISTANCES: |d − R_c| ≥ δ for all zero-distances d in B(s₀,5/2). Collected zeros: d ≤ R_c ⟹ d ≤ R_c − δ. In scaled: ‖ρ_w‖ ≤ r_c − δ_w. ✓.
Hmm wait, one more check — the zeros of F in the unit ball are EXACTLY the scaled zeros of ζ in B(s₀, 5/2) (F zero ⟺ ζ(aff w) zero since ζ(s₀) ≠ 0). And zeroDiscFinset = zeros in closedBall(s₀, 5/2). The distance finset S := (zeroDiscFinset t).image (fun ρ => ‖ρ − discCenter t‖). exists_avoiding_midpoint needs S : Finset ℝ — ✓.
But careful: SetOfZeros r_c F uses ‖ρ_w‖ ≤ r_c where ρ_w is the SCALED zero (w-coordinate). The affine map w ↦ s₀+(5/2)w: ζ-zero ρ ↔ F-zero w = (ρ−s₀)/(5/2), ‖w‖ = ‖ρ−s₀‖/(5/2). The collected set {‖w‖ ≤ r_c} = {‖ρ−s₀‖ ≤ (5/2)r_c = R_c}. ✓. And multiplicities match by analyticOrderNatAt_scaledZeta. ✓ (needed for the deriv-J_B translation: deriv of the product uses m_ρ = analyticOrderNatAt F at the scaled zero = zeroMult at the ζ-zero — actually zeroMult ρ := analyticOrderNatAt riemannZeta ρ? Let me check LiSides/LiSkeleton for zeroMult def. In LiSides: zeroMult ρ — I recall `zeroMult` is defined in LiSkeleton or LiSides as analyticOrderNatAt riemannZeta ρ. Let me check.)
Also `logDeriv` — Mathlib's logDeriv f = deriv f / f. The final statement uses logDeriv riemannZeta s. And deriv B/B... For the translation (2/5)(B′/B)(w) = logDeriv ζ s − Σ m/(s−ρ), I need:
- deriv F w = (5/2)·(deriv ζ)(s₀+(5/2)w)/ζ(s₀): deriv of comp with affine — deriv_congr / deriv.scomp / HasDerivAt. Since everything is analytic, deriv (F) w = deriv (ζ ∘ aff) w /ζ(s₀) = (deriv ζ (aff w))·(5/2)/ζ(s₀) via deriv.comp (needs differentiableAt).
- B = F/P where P(w) = ∏(w−ρ)^{m_ρ} (off the zero set; but as FUNCTIONS B = Cf — the identity B w = F w/P w holds only for w ∉ zero set. For the deriv identity I need it in a NEIGHBORHOOD of the evaluation point w. The evaluation points w (for s in the application region) have ζ(s) ≠ 0 (hypothesis) so w is not a zero, and there's a neighborhood avoiding the finite zero set where B = F/P as functions. Good: deriv B w = (F′P − FP′)/P² at w, and B′/B = F′/F − P′/P with P′/P = Σ m_ρ/(w−ρ) (logDeriv of a product of powers — need deriv of ∏(w−ρ)^{m_ρ}: deriv_prod + deriv_pow... `HasDerivAt.prod`? There's `deriv_prod` in Mathlib? There's `HasDerivAt.sum`/... For finite products: `HasDerivAt.list_prod`? I recall `deriv_prod` exists for Finset: `HasDerivAt.prod`? Hmm — in LiResidue/LiSides we did logDeriv-NF residues; there may be existing product logDeriv machinery. In Mathlib: `logDeriv_prod`? Let me check later: there's `HasStrictDerivAt.list_prod'`... I'll search at build time. Worst case: induction on the finset with deriv_mul.
Let me now also confirm the application region maps into closedBall(0, 0.6): s = σ+it with σ ∈ [1/2, 7/2]: w = (s−s₀)/(5/2) = (2/5)(σ−2), so ‖w‖ = (2/5)|σ−2| ≤ (2/5)(3/2) = 0.6 ✓ (|σ−2| ≤ 3/2 for σ∈[1/2,7/2] ✓).
And nearZeros t: I need it as a Finset ℂ with membership ⟺ IsNontrivialZero ρ ∧ |ρ.im − t| < 1. From ii′-4: zeroWindow a = {IsNontrivialZero ∧ a ≤ im ≤ a+1} finite. nearZeros t = zeroWindow-ish with open bounds. Finiteness: subset of zerosIn_finite (t−2)(t+1) or use zeroDiscFinset filtered: nearZeros t ⊆ zeroDiscFinset? |γ−t| < 1, β ∈ (0,1): ‖ρ−s₀‖ = √( (β−2)² + (γ−t)² ) ≤ √(4+1) = √5 ≈ 2.236 < 2.5 ✓. So nearZeros t ⊆ zeroDiscFinset t — finiteness free. Define nearZeros t := (zeroDiscFinset t).filter (fun ρ => |ρ.im − t| < 1). zeroDisc_isNontrivial gives IsNontrivialZero for members. ✓
The "extras" bound: collected (in the disc R_c) but not near: |γ−t| ≥ 1... wait the collected zeros in the sum from deriv J_B are zeros with ‖ρ−s₀‖ ≤ R_c, i.e. the scaled-zero finset. The final sum is over nearZeros. extras = collected ∖ near: for those, |γₖ−t| ≥ 1 hmm — careful: "not near" means |ρ.im − t| ≥ 1, and ‖s−ρ‖ ≥ |im s − im ρ| = |t − γ| ≥ 1 ✓. So each extra term ‖m/(s−ρ)‖ ≤ m, sum ≤ Σ_{collected} m = M_J ≤ Jensen RHS. ✓
But there's a subtlety: the collected finset in the scaled picture is `(finiteSetOfZeros_mono (r := r_c) ...).toFinset` — a finset of w-points. The final statement wants a sum over nearZeros t (ζ-zeros). So I need to push the sum over scaled zeros through the affine bijection w ↦ s₀+(5/2)w to a sum over ζ-zeros in closedBall(s₀, R_c), with m matching (analyticOrderNatAt_scaledZeta ✓). Finset.sum_image with InjOn (the affine map is injective globally). Let me define collectedZeros t R_c := (zeroDiscFinset t).filter (‖· − s₀‖ ≤ R_c)... and establish a bijection with the scaled finset.
Actually — alternative cleaner approach: maybe avoid Cf and the scaled picture for g, and instead directly build g on the s-side? The Cf machinery is heavily unit-disc-oriented (SetOfZeros r f requires ‖ρ‖ ≤ r ≤ R < 1, analytic on closedBall(0,1)). The scaled picture fits it perfectly and ii′-5c already built scaledZeta + its Jensen count + multiplicity invariance precisely for this. Stick with the plan: work in w, translate at the end.
Now the structure of the remaining work in LiDisc.lean:
§5 R-gap selection:
```lean
theorem exists_disc_radius_gap {t : ℝ} (ht : 10 ≤ |t|) :
∃ R_c : ℝ, 2.3 ≤ R_c ∧ R_c ≤ 2.4 ∧
∀ ρ ∈ zeroDiscFinset t, 1/(20*((zeroDiscFinset t).card + 1)) ≤ |‖ρ − discCenter t‖ − R_c|
```
via exists_avoiding_midpoint scaled. But exists_avoiding_midpoint is stated for window [a, a+1] (length 1) with clearance 1/(2(k+1)). I need length ℓ = 1/10. Options: (a) prove a generalized ℓ-version (copy-paste the proof with w := ℓ/(2(k+1))) — STATE.md explicitly suggests "add an ℓ-parameterized variant — reuse ii′-4's proof". (b) rescale S by 10: apply the length-1 lemma to S' = {10x} in window [23, 24]: get T' with |10x − T'| ≥ 1/(2(k+1)), then R_c = T'/10 ∈ [2.3, 2.4], |x − R_c| ≥ 1/(20(k+1)). Option (b) reuses the EXISTING lemma with zero new pigeonhole code — just image under (10·). Much cheaper!
k := (zeroDiscFinset t).card; S := (zeroDiscFinset t).image (fun ρ => ‖ρ − discCenter t‖); S.card ≤ k via card_image_le. S10 := S.image (· * 10)... or image (fun x => x * 10) — need InjOn for card: mul_right_injective₀. Then apply exists_avoiding_midpoint (a := 23) (S := S10) with card ≤ k. Get T' ∈ [23,24] with clearance. R_c := T'/10. |x − R_c| = |10x − T'|/10 ≥ 1/(20(k+1)). ✓
§6 g nonvanishing etc. Define in scaled coords:
- r_c := R_c/(5/2) = R_c·(2/5) ∈ [0.92, 0.96].
- δ := 1/(20(k+1)), δ_w := (2/5)·δ = 1/(50(k+1)).
- R_log := r_c + δ_w/2.
- Scaled zero finset: ZW := (finiteSetOfZeros_mono (r := r_c) (f := scaledZeta t) h_lt scaledZeta_zeros_finite).toFinset. Note: finiteSetOfZeros_mono needs r_c < 1 ✓. Wait — but the Jensen count was stated for r = 24/25 = 0.96 and the collection uses r_c ≤ 0.96. Hmm: finiteSetOfZeros_mono with r = r_c gives the finset for radius r_c; the mult-weighted sum over it ≤ sum over the 0.96-finset (monotone: r_c ≤ 0.96 ⟹ SetOfZeros r_c ⊆ SetOfZeros 0.96... need r_c ≤ 24/25: r_c ≤ 0.96 = 24/25 ✓; and both toFinsets: sum over subset ≤ sum since terms nonnegative (analyticOrderNatAt ≥ 0 ✓). And by scaledZeta_jensen_count the 0.96-sum ≤ log((9/4)|t|²)/log(33/32). So M_c := Σ_{ρ ∈ ZW} analyticOrderNatAt (scaledZeta t) ρ ≤ Jensen bound. ✓ (Need the monotonicity lemma: SetOfZeros r ⊆ SetOfZeros r' for r ≤ r' — easy; and Set.Finite.toFinset subset for the sum — Finset.sum_le_sum_of_subset_of_nonneg.)
- B := Cf r_c (scaledZeta t).
- B analytic on closedBall(0, R_log): CfAnalytic (r_lt_R : r_c < R_log) (R_log < 1) scaledZeta_analytic (F 0 ≠ 0). ✓
- B nonvanishing on closedBall(0, R_log): as argued. This is a real lemma to prove:
For w with ‖w‖ ≤ R_log: by_cases F w = 0.
- If F w = 0: then w ∈ SetOfZeros 1 F... ‖w‖ ≤ R_log ≤ 0.97 < 1 ✓ so w ∈ zeroDisc... the corresponding ζ-zero ρ = s₀+(5/2)w ∈ closedBall(s₀, 5/2·0.97) ⊂ closedBall(s₀, 5/2) hmm need (5/2)‖w‖ ≤ (5/2)R_log < 5/2 ✓. So ρ ∈ zeroDiscFinset, its distance d = ‖ρ−s₀‖ = (5/2)‖w‖ ∈ S, gap: |d − R_c| ≥ δ. If d ≥ R_c: d ≥ R_c + δ ⟹ ‖w‖ ≥ r_c + δ_w > R_log, contradiction. So d ≤ R_c − δ, ‖w‖ ≤ r_c − δ_w < r_c, so w ∈ SetOfZeros r_c F, i.e. w ∈ ZW (via mem_toFinset). Then Cf w = ZeroFactor F w / ∏_{ρ ∈ ZW\{w}} (w−ρ)^m. ZeroFactorization (needs R < 1 version: hρ ∈ SetOfZeros R F with R := r_c < 1 ✓): ZeroFactor F w = h_w w ≠ 0. Product: each (w−ρ) ≠ 0 since ρ ∈ ZW \ {w} means ρ ≠ w. So B w ≠ 0.
- If F w ≠ 0: Cf w = F w / ∏_{ρ ∈ ZW} (w−ρ)^m. Each factor: ρ ∈ ZW ⟹ ‖ρ‖ ≤ r_c and F ρ = 0; if w = ρ then F w = 0 contradiction; so w ≠ ρ, factor ≠ 0. Product ≠ 0. So B w = F w/prod ≠ 0.
Wait — the Cf definition: `if z ∈ SetOfZeros r f then ZeroFactor f z / ∏ over (toFinset \ {z}) else f z / ∏ over toFinset`. The membership condition `z ∈ SetOfZeros r f` is by `if` with Classical decidability. At w with F w = 0 and ‖w‖ ≤ r_c: dif_pos. At w with F w ≠ 0: dif_neg (need w ∉ SetOfZeros: F w ≠ 0 ⟹ not member ✓).
Also note: Cf requires `if finite_zeros_mono : (SetOfZeros r f).Finite` — dif_pos with our finiteness proof. When unfolding Cf I'll need to handle the dite with the right instance. The Zeta23 proofs do `unfold Cf; by_cases ...; simp only [finite_zeros_mono, ↓reduceDite]`. I'll mirror that. Note: our finiteness proof `scaledZeta_zeros_finite` is for SetOfZeros 1; finiteSetOfZeros_mono gives SetOfZeros r_c finite. The `if` in Cf uses a Classical instance so any proof works (proof irrelevance).
§7 bounds:
- hB0: B 0 = 1/∏(−ρ)^m, and log‖B 0‖ ≥ 0. Actually compute: Cf 0: 0 ∈ SetOfZeros r_c F? F 0 = 1 ≠ 0 so no. So B 0 = F 0/∏(0−ρ)^m = 1/∏(−ρ)^m. ‖B 0‖ = 1/∏‖ρ‖^m. Each ‖ρ‖ ≤ r_c − δ_w < 1 ⟹ log‖ρ‖ < 0 ⟹ log‖B 0‖ = −Σ m log‖ρ‖ > 0. Need: ρ ∈ ZW ⟹ ‖ρ‖ ≤ r_c − δ_w — wait, ZW = SetOfZeros r_c F, members have ‖ρ‖ ≤ r_c; the gap argument (as in §6) upgrades to ‖ρ‖ ≤ r_c − δ_w. Hmm, but the gap argument needs the corresponding ζ-zero in zeroDiscFinset — ρ ∈ ZW ⟹ F ρ = 0 ⟹ (scaledZeta_zeros_finite's hsub) ρ ∈ affine preimage of (closedBall(s₀,5/2) ∩ zeros) — I proved that subset relation already in scaledZeta_zeros_finite (hsub). Extract: ζ(s₀+(5/2)ρ) = 0 and ‖(5/2)ρ‖ ≤ 5/2 ⟹ s₀+(5/2)ρ ∈ zeroDiscFinset, distance (5/2)‖ρ‖ ∈ S, gap applies. But wait the gap argument requires |d − R_c| ≥ δ, and we know d ≤ R_c (since ‖ρ‖ ≤ r_c ⟹ d ≤ (5/2)r_c = R_c) ⟹ d ≤ R_c − δ. ✓ So a lemma: ∀ ρ ∈ ZW, ‖ρ‖ ≤ r_c − δ_w.
Hmm wait — actually I realize the gap applies to ALL members of zeroDiscFinset, including zeros at distance in (R_c, 2.5]; those have d ≥ R_c + δ. Fine.
- hBsphere: ∀ w, ‖w‖ = R_log ⟹ ‖B w‖ ≤ (9/4)*|t|² * (2/(3δ_w))^M_c... let me recompute: ‖w−ρ‖ ≥ ‖w‖ − ‖ρ‖ ≥ R_log − (r_c − δ_w) = δ_w/2 + δ_w = 3δ_w/2. So ∏‖w−ρ‖^m ≥ (3δ_w/2)^{M_c} where M_c = Σ m. So ‖B w‖ = ‖F w‖/∏ ≤ (9/4)|t|²·(2/(3δ_w))^{M_c}. Need F w ≠ 0 on the sphere for the Cf = F/prod branch: sphere ‖w‖ = R_log, if F w = 0 then w ∈ ZW (by gap, ‖w‖ ≤ r_c − δ_w < R_log) contradiction with ‖w‖ = R_log. ✓ so the else-branch applies. And ‖F w‖ ≤ (9/4)|t|² needs ‖w‖ ≤ 99/100: R_log ≤ 0.96 + δ_w/2; δ_w = 1/(50(k+1)) ≤ 1/50 ⟹ R_log ≤ 0.96 + 0.01 = 0.97 ≤ 0.99 ✓.
- hBball: ∀ w ∈ closedBall(0, R_log), ‖B w‖ ≤ that bound — via AnalyticOn.norm_le_of_norm_le_on_sphere (B analytic on closedBall(0, R_log) from CfAnalytic with R := R_log... wait CfAnalytic gives AnalyticOnNhd on closedBall(0, R) for R < 1 with r_c < R. Take R = R_log ✓ (R_log < 0.97 < 1). AnalyticOnNhd ⟹ AnalyticOn on the closed ball? norm_le_of_norm_le_on_sphere signature (from DiskBound usage): `AnalyticOn.norm_le_of_norm_le_on_sphere (le_refl R) (AnalyticOnNhd.analyticOn ...) (sphere bound) (hz ∈ closedBall)`. ✓.
§8 J_B and BC:
- obtain ⟨J_B, hJ_an, hJ0, hJderiv, hJre⟩ := LogOfAnalyticFunction (r := 3/5) (R := R_log) ... — r = 0.6 = 3/5 < R_log (R_log ≥ r_c = 0.92 > 0.6 ✓). B nonvanishing on closedBall(0, R_log) from §6. Note LogOfAnalyticFunction needs nonvanishing on closedBall(0, R) = closedBall(0, R_log) ✓ and analytic on closedBall(0, R_log) ✓.
- Re J_B bound: ∀ w ∈ ball(0, R_log), (J_B w).re ≤ M_bound where M_bound := Real.log ((9/4)*|t|²) + M_c * Real.log (2/(3δ_w)). From hJre: (J_B w).re = log‖B w‖ − log‖B 0‖ ≤ log‖B w‖ (since log‖B 0‖ ≥ 0) ≤ M_bound via hBball (ball ⊆ closedBall) + Real.log_le_log (need ‖B w‖ > 0: B w ≠ 0 ✓) + log_mul + log_pow... (9/4)|t|² > 0 ✓, (2/(3δ_w)) > 0 ✓. log((9/4)|t|² · X) = log((9/4)|t|²) + log X needs both pos ✓.
- M_bound > 0: log((9/4)|t|²) ≥ log((9/4)·100) = log 225 > 0 ✓, second term ≥ 0 (M_c ≥ 0, log(2/(3δ_w)) ≥ log(2·50/3) > 0 ✓). Actually need Mpos : 0 < M for BC — ✓.
- BC: for w ∈ closedBall(0, 3/5): ‖deriv J_B w‖ ≤ 16·M_bound·R_log²/(R_log − 3/5)³. R_log − 3/5 ≥ r_c − 3/5 ≥ 0.92 − 0.6 = 0.32. R_log ≤ 0.97. So the factor ≤ 16·0.97²/(0.32)³ — but in the proof keep symbolic then bound at the end.
§9 deriv identity + translation:
- At w with F w ≠ 0 (i.e. ζ(s) ≠ 0 for s = aff w): deriv B w / B w = deriv F w / F w − Σ_{ρ∈ZW} m_ρ/(w−ρ).
Need: B =ᶠ[𝓝 w] F/P where P = ∏(·−ρ)^m — from Cf's else-branch on the open set {F ≠ 0} ∩ ... Actually simpler: B and F/P are both analytic on a punctured neighborhood... no — get EventuallyEq: on the complement of ZW (finite, closed), if F w ≠ 0 then in a neighborhood: F z ≠ 0 (continuity) and z ∉ ZW (ZW finite ⟹ closed... ZW is a finset so its carrier is closed; w ∉ carrier ⟹ neighborhood avoiding it). On that neighborhood Cf z = F z/P z by the else-branch. So B =ᶠ[𝓝 w] F/P. Then deriv B w = deriv (F/P) w (deriv_congr of EventuallyEq — `Filter.EventuallyEq.deriv` ✓ exists). And B w = F w/P w directly. So deriv B w/B w = (F/P)′(w)/(F/P)(w) = logDeriv (F/P) w = logDeriv F w − logDeriv P w (Mathlib: logDeriv_div — needs F w ≠ 0, P w ≠ 0, differentiableAts ✓). logDeriv P w = Σ m_ρ/(w−ρ): P = ∏(·−ρ)^{m_ρ}, logDeriv of product — Mathlib has `logDeriv_prod`? Let me think... there's `logDeriv_fun_mul`, `logDeriv_fun_div`, `logDeriv_fun_pow`? I believe Mathlib has `logDeriv_mul`, `logDeriv_pow`... In recent Mathlib: `logDeriv_fun_pow : logDeriv (f ^ n) x = n * logDeriv f x`? and `logDeriv_prod`? Let me search at build time. Worst case induction.
Also deriv J_B w = deriv B w / B w (from hJderiv, needs w ∈ closedBall(0, 3/5) ✓ for application region).
And logDeriv F w = (5/2)·logDeriv ζ (aff w): F = (ζ ∘ aff)·(1/ζ(s₀)) — logDeriv (c·g) = logDeriv g (logDeriv_const_mul, c ≠ 0); logDeriv (ζ ∘ aff) w: logDeriv_comp? deriv (ζ∘aff) w = deriv ζ (aff w) · deriv aff w = deriv ζ (aff w)·(5/2) (deriv.comp w (differentiableAt ζ) (affine)). So logDeriv F w = (5/2)·deriv ζ(aff w)/ζ(aff w) = (5/2)·logDeriv ζ s. There should be a `logDeriv_comp` lemma... or do it manually with deriv.comp.
§10 assemble the R-bound:
For s with σ ∈ [1/2, 7/2], |t| ≥ 10, ζ s ≠ 0: w := (s − s₀)·(2/5), ‖w‖ = (2/5)|σ−2| ≤ 3/5 ✓. Then:
logDeriv ζ s = (2/5)·logDeriv F w = (2/5)·[deriv J_B w + Σ m_ρ/(w−ρ)].
‖logDeriv ζ s − Σ_{nearZeros} m/(s−ρ)‖ = ‖(2/5)deriv J_B w + (2/5)Σ_{ZW} m_ρ/(w−ρ) − Σ_{near} m/(s−ρ)‖.
Now (2/5)·m_ρ/(w−ρ) = m/(s−ρ_s) where ρ_s = s₀+(5/2)ρ (check: w−ρ = (2/5)(s−ρ_s) since w = (2/5)(s−s₀) and ρ_s = s₀+(5/2)ρ ⟹ s−ρ_s = (5/2)(w−ρ) ✓). So (2/5)Σ_{ZW} m/(w−ρ) = Σ_{ZW} m/(s−ρ_s) = Σ_{collected_s} m/(s−ρ) via the affine bijection (Finset.sum_image, inj). collected_s = ZW.image aff = zeros in closedBall(s₀, R_c) — I should prove collected_s = (zeroDiscFinset t).filter (‖·−s₀‖ ≤ R_c) or just work with the image directly. Then split collected_s into nearZeros and extras (Finset.sum_sdiff / sum over union): Σ_collected = Σ_near + Σ_extra (need nearZeros ⊆ collected_s: |γ−t| < 1 ⟹ ‖ρ−s₀‖ ≤ √5 ≤ 2.3 ≤ R_c ✓ — √5 ≤ 2.3: 5 ≤ 5.29 ✓, needs ‖ρ−s₀‖ computation: ‖ρ−s₀‖² = (β−2)² + (γ−t)² with β ∈ (0,1) ⟹ (β−2)² ≤ 4 (|β−2| ≤ 2 hmm β ∈ (0,1) ⟹ β−2 ∈ (−2,−1) ⟹ (β−2)² ≤ 4) and (γ−t)² ≤ 1 ⟹ ‖·‖² ≤ 5 ⟹ ‖·‖ ≤ √5. Need IsNontrivialZero for β ∈ (0,1) — nearZeros members are in zeroDiscFinset ⟹ zeroDisc_isNontrivial ✓.)
So ‖R(s)‖ ≤ (2/5)‖deriv J_B w‖ + Σ_extra m/(s−ρ) ≤ (2/5)·16·M_bound·R_log²/(R_log−3/5)³ + M_c (each extra term ≤ m since ‖s−ρ‖ ≥ |t−γ| ≥ 1, and Σ_extra m ≤ Σ_collected m = M_c).
Then the final numeric chain: show (2/5)·16·R_log²/(R_log−3/5)³·M_bound + M_c ≤ C·(log|t|)² for an explicit C with |t| ≥ 10.
Given M_bound ≤ ~305L² (L = log|t|) from my scratch estimate and the BC factor ≤ (2/5)·16·0.97²/0.32³ ≈ 183.6 ≤ 184, and M_c ≤ 65L + 27 ≤ 305L²-ish... total ≤ 184·305L² + small = 56120L² → C := 60000. In Lean, proving M_bound ≤ 305·(log|t|)² requires careful real-number estimates. Let me redo this more carefully to have a clean certifiable chain.
Let L := Real.log |t|, so L ≥ log 10 > 2.302. Facts needed:
- log((9/4)|t|²) = 2L + log(9/4). log(9/4) = 2log(3/2) ≤ 2·(1/2)·... cleanest: 9/4 ≤ e ⟹ log(9/4) ≤ 1 (since 9/4 = 2.25 < e ≈ 2.718). Is 9/4 ≤ e available? `Real.exp_one_gt_d9` : 2.718281828 < e? There are bounds e > 2.718... so 9/4 < e ✓ via norm_num + that lemma. So log((9/4)|t|²) ≤ 2L + 1.
- log(33/32) ≥ ? 33/32 = 1.03125. log(1.03125) ≥ 0.03? Use log(1+x) ≥ x/(1+x)... Real.log_le_sub_one_of_pos? The handy ones: `Real.log_le_sub_one_of_pos : 0 < x → log x ≤ x − 1` (upper). Lower: `Real.one_sub_inv_le_log_of_pos`? Hmm: log x ≥ 1 − 1/x (for x > 0)? That's `Real.one_sub_inv_le_log`... something like that exists: log x ≥ (x−1)/x. For x = 33/32: (1/32)/(33/32) = 1/33 ≈ 0.0303. So log(33/32) ≥ 1/33. Then M ≤ (2L+1)·33 = 66L + 33. (matches Jensen: log((9/4)t²)/log(33/32) ≤ 33(2L+1)).
- k+1 ≤ M_c + 1 ≤ 66L + 34. 100(k+1)/3 ≤ 100(66L+34)/3 = (6600L + 3400)/3 = 2200L + 1133.33 ≤ 2200L + 1134. For L ≥ 2.302: 2200L + 1134 ≤ 2200L + 493L = 2693L. So log(100(k+1)/3) ≤ log 2693 + log L. log 2693 ≤ 8 (e⁸ = 2981 ≥ 2693 ✓ — need e⁸ ≥ 2693: e > 2.718, 2.718⁸ = ? 2.718² = 7.387; ⁴ = 54.57; ⁸ = 2978. Hmm 2978 > 2693 ✓ but proving 2.718⁸ ≥ 2693 in Lean: norm_num with Real.exp_one_gt_d9... messy but doable; alternatively use log 2693 ≤ log e^8 = 8 via Real.log_le_log and a computed bound. Or be lazier: 2693L ≤ L⁴ for L ≥ ... L³ ≥ 2693 ⟺ L ≥ 13.9 — no, L can be 2.3. Alternative: log(2693L) = log 2693 + log L ≤ 8 + log L, and log L ≤ L/e ≤ L − 1? Actually log L ≤ L − 1 only for... log L ≤ L − 1 for all L > 0 ✓ (Real.log_le_sub_one_of_pos: log L ≤ L − 1). So log(2693L) ≤ 7 + L.
Hmm wait, I need an upper bound on log of stuff; log(2693L) ≤ log 2693 + log L requires 2693 > 0, L > 0 ✓ (Real.log_mul). log 2693 ≤ 8: 2693 ≤ e⁸: since e ≥ 2.718281828 (Real.exp_one_gt_d9 gives 2.7182818283 < e? something like that), e⁸ ≥ 2.718281828⁸. Computing 2.718281828⁸ ≥ 2693 by norm_num: 2.718281828⁸ is a specific rational... norm_num can evaluate (2.718281828 : ℝ)^8 ≈ 2980.96 > 2693 ✓. And e⁸ = (e¹)⁸ via Real.exp_nat_mul or ← Real.exp_one_pow? e⁸ = Real.exp 8 = (Real.exp 1)^8? Real.exp 8 = Real.exp (1*8) = (Real.exp 1)^8 by Real.exp_nat_mul... `Real.exp_nat_mul : exp (n * x) = (exp x)^n`? So exp 8 = exp (8*1) = (exp 1)^8 ≥ 2.718...⁸ ≥ 2693. OK.
- So log(2/(3δ_w)) = log(100(k+1)/3) ≤ 7 + L (loose). Wait let me double check δ_w: δ = 1/(20(k+1)); δ_w = (2/5)δ = 2/(100(k+1)) = 1/(50(k+1)). 3δ_w/2 = 3/(100(k+1)). 2/(3δ_w) = 200(k+1)/6·... 2/(3/(100(k+1))) = 200(k+1)/3 ≈ 66.67(k+1). Hmm I previously wrote 100(k+1)/3 — recompute: (3δ_w/2) = 3/(100(k+1)); reciprocal times... (2/(3δ_w)) = 2·100(k+1)/3 = 200(k+1)/3. OK so 200(k+1)/3 ≤ 200(66L+34)/3 = (13200L + 6800)/3 = 4400L + 2266.67 ≤ 4400L + 2267 ≤ 4400L + 985L = 5385L (for L ≥ 2.302). log(5385L) = log 5385 + log L ≤ 9 + (L−1) = 8 + L (log 5385 ≤ 9: e⁹ = 8103 ≥ 5385 ✓ via 2.71828⁹ ≈ 8100 — norm_num check).
- M_bound = log((9/4)|t|²) + M_c·log(2/(3δ_w)) ≤ (2L+1) + (66L+33)(8+L) = 2L+1 + 66L² + 528L + 33L·8... let me expand: (66L+33)(L+8) = 66L² + 528L + 33L + 264 = 66L² + 561L + 264. So M_bound ≤ 66L² + 563L + 265. For L ≥ 2.302: 563L ≤ 244.6L², 265 ≤ 50L² ⟹ M_bound ≤ 361L².
- BC factor: (2/5)·16·R_log²/(R_log−0.6)³. R_log ≤ 0.97 ⟹ R_log² ≤ 0.9409 ≤ 1. R_log − 0.6 ≥ 0.32 ⟹ (R_log−0.6)³ ≥ 0.032768 ≥ 0.03. So factor ≤ (2/5)·16·1/0.03 = (2/5)·533.33 = 213.34. Hmm: 16/0.032768 = 488.28; times 0.9409 = 459.4; times 2/5 = 183.8. With the looser 0.03: 16/0.03 = 533.3, ×(2/5) = 213.3. To be safe: factor ≤ 214. (In Lean: R_log² ≤ 1 needs R_log ≤ 1 ✓ 0.97; (R_log−3/5)³ ≥ (8/25)³: 0.32 = 8/25 ✓; 16·1/(8/25)³ = 16·15625/512 = 488.28; ·(2/5) = 195.3. Use fractions: R_log ≥ 23/25 (r_c ≥ 2.3·(2/5) = 0.92 = 23/25 ✓), R_log − 3/5 ≥ 23/25 − 15/25 = 8/25 ✓. R_log ≤ 97/100. So BC factor = 16·M·R²/(R−r)³ ≤ 16·M·(97/100)²/(8/25)³ = 16·M·(9409/10000)·(15625/512) = 16·9409·15625/(10000·512)·M = 2352250000/5120000·M ≈ 459.42·M. Times 2/5: ≈ 183.77·M ≤ 184M.)
- ‖R(s)‖ ≤ 184·M_bound + M_c ≤ 184·361L² + (66L+33) ≤ 66224L² + 66L + 33 ≤ 66224L² + 29L² + ... 66·2.302 ≈ 152; 66L ≤ 28.7L²... so ≤ 66253L² + tiny ≤ 66260L². Take C := 70000.
So the final theorem: ‖logDeriv ζ s − Σ_{nearZeros t} m/(s−ρ)‖ ≤ 70000·(Real.log|t|)². Hmm wait — (Real.log |t|)^2. Or should I state it with log(|t|+2)? For 5e the circle growth uses |t| up to R+1 on the circle... any form works. Simplest: (Real.log |t|)^2 with |t| ≥ 10. Hmm, but actually for 5d (reflection) and 5e it might be cleaner to have log(|t|+2) ≥ ... whatever — the loose form C·(log|t|)² for |t| ≥ 10 is fine; 5e can convert (log|t| ≤ log(R+1)+1 etc.).
Hmm, actually — let me reconsider whether to even keep M_c symbolic vs concrete. The final numeric fold has several irreducibly tedious steps (log(33/32) ≥ 1/33, e⁸ ≥ 2693, etc.). All doable. Total estimate: this is a LOT of Lean code — maybe 600–900 lines for §5–§10. That fits the "~1 session" estimate but it's ambitious. Let me be strategic: build in order, compile frequently with `lake env lean NguyenRH1/LiDisc.lean`.
One design decision to reduce pain: instead of tracking M_c · log(2/(3δ_w)) with δ_w defined from k = card... note 2/(3δ_w) = 200(k+1)/3. And k+1 = card+1 ≤ M_c+1 (since card ≤ Σm = M_c as each m ≥ 1). Wait — do I have card zeroDiscFinset ≤ M_c (the mult sum over the SCALED 0.96-finset)? zeroDiscFinset = zeros in closedBall(s₀, 5/2) — corresponds to scaled zeros in closedBall(0,1) — SetOfZeros 1 F. The Jensen count is over SetOfZeros (24/25) — the zeros with 0.96 < ‖w‖ ≤ 1 are NOT counted by Jensen. Hmm! So k = card(zeroDiscFinset) could exceed M(0.96-sum).
Uh oh. The clearance δ must come from a count bound on ALL zeros in the 5/2-disc (since S includes distances of all of them), but Jensen only counts those within 0.96·(5/2) = 2.4. Zeros in the annulus 2.4 < d ≤ 2.5 are not Jensen-counted.
Fix options: (a) bound card(zeroDiscFinset) via the perimeter ZeroCountProp instead (the disc B(s₀, 5/2) is covered by ~5 unit windows: γ ∈ [t−2.5, t+2.5] ⟹ 5 windows [t−3, t+2]... plus the perimeter needs a ≥ 2: t ≥ 10 ⟹ t−3 ≥ 7 ✓; for t ≤ −10 symmetric — hmm, ZeroCountProp is stated for t ≥ 2 with window [t, t+1]. For negative ordinates use the conjugate symmetry of zeros: IsNontrivialZero ρ ⟹ conj ρ also? That's a Zeta23 seam (zeros come in conjugate pairs). Might be annoying. (b) Apply Jensen with a bigger r: r = 1? SetOfZeros 1 F is finite, but ZerosBound needs r < 1. Use r = 0.995: then the sum over SetOfZeros(0.995) covers d ≤ 2.4875 — still not 2.5. Hmm r < 1 strictly, so never covers the boundary ‖w‖ = 1 exactly (d = 2.5). But zeroDiscFinset uses closedBall(s₀, 5/2) — includes the boundary.
Hmm. Option (c): shrink zeroDiscFinset to closedBall(s₀, 49/20) = 2.45 and use Jensen r = 0.98 = 24.5/25... but zeroDiscFinset was already committed in ii′-5c part 1 with 5/2 (and used in scaledZeta_zeros_finite, zeroDisc_isNontrivial). Redefining it would touch existing proved code (zeroDisc_isNontrivial used 5/2 geometry: re ∈ [−1/2, 9/2]; 49/20 gives re ≥ 2 − 2.45 = −0.45 — the re ≤ 0 exclusion argument used re ≥ −1/2 hmm: with radius 2.45, re ρ ∈ [−0.45, 4.45]; the ΓR-pole argument: re ≤ 0 ⟹ ρ = −2n with re = −2n ≤ −2 < −0.45 for n ≥ 1 ✓ still works, n = 0: ρ = 0 excluded by ζ(0) ≠ 0 ✓. So changing 5/2 → 49/20 in zeroDiscFinset would still let zeroDisc_isNontrivial go through (re ≤ 9/2 → re ≤ 4.45+... the proof structure is the same, constants change). But freeze protocol says existing proofs untouched except liCoeff fix... well, ii′-5c is THIS session's sub-stage, in progress — LiDisc.lean from session 023 is committed though. Modifying the definition would require re-proving zeroDisc_isNontrivial with new constants. Eh.
Option (d): keep S as the distances of the 0.96-disc zeros only! I.e., choose the gap R_c ∈ [2.3, 2.4] avoiding distances of zeros within 2.4 only... but then zeros with d ∈ (R_c, 2.4] could be closer than δ to R_c?? No wait — if S includes ALL zeros with d ≤ 2.4, and R_c ∈ [2.3, 2.4] avoids all of them by δ, then collected zeros (d ≤ R_c) have d ≤ R_c − δ, and zeros with d ∈ (R_c, 2.4] have d ≥ R_c + δ. Zeros with d ∈ (2.4, 2.5]: NOT in S, could be at any distance > 2.4 ≥ R_c... but they're at d > 2.4 > R_c + δ? δ = 1/(20(k+1)) could exceed 0.1 for small k... k = card of the ≤2.4-zero finset... hmm δ ≤ 1/20 = 0.05 (k ≥ 0) — wait for k=0, δ = 1/20, R_c + δ ≤ 2.4 + 0.05 = 2.45 < ... a zero at d = 2.44 exists? If k=0 there are no zeros with d ≤ 2.4 but one at 2.44 — its distance to R_c: 2.44 − 2.4 ≥ ... R_c ≤ 2.4 so d − R_c ≥ 0.04 < δ = 0.05. PROBLEM: that zero is at distance < δ above R_c. Does it matter? What do we need the gap for?
(i) Collected zeros (in ZW, ‖w‖ ≤ r_c) satisfy ‖w‖ ≤ r_c − δ_w: needs gap below R_c among... the zero at 2.44 is NOT collected (d > R_c), fine — but for ZW members, their d ≤ R_c AND they're in S (d ≤ 2.4 ✓ since R_c ≤ 2.4) so d ≤ R_c − δ ✓. Good — no problem for (i).
(ii) B nonvanishing on closedBall(0, R_log): need no zeros with r_c < ‖w‖ ≤ R_log, i.e. no ζ-zeros with d ∈ (R_c, R_c + δ/2... R_log = r_c + δ_w/2 ⟹ d ∈ (R_c, R_c + δ/2). Zeros with d ≤ 2.4: in S ⟹ d ≥ R_c + δ > R_c + δ/2 ✓. Zeros with d ∈ (2.4, 2.5]: d > 2.4 ≥ R_c; is 2.4 > R_c + δ/2? R_c ≤ 2.4 and δ/2 ≤ 1/40 = 0.025, so R_c + δ/2 could be 2.4125, and a zero at d = 2.41?? If d = 2.41 > 2.4 not in S, and R_c = 2.4, R_log·2.5 = 2.4 + δ/4 = 2.4125·... wait R_log = r_c + δ_w/2 ⟹ (5/2)R_log = R_c + (5/2)δ_w/2 = R_c + δ/2 = 2.4125. A zero at d = 2.41 ∈ (2.4, 2.4125): B would vanish at the corresponding w (‖w‖ = 0.964 ≤ R_log = 0.965)!! PROBLEM.
So option (d) breaks (ii) unless S includes the annulus zeros. Hmm.
Option (e): make R_log smaller: R_log = r_c + min(δ_w/2, (2.4 − R_c)·(2/5)/2)... ugly. Actually: the constraint is zeros with d ≤ 2.4 are δ-away; zeros with d > 2.4 are at d > 2.4. So any R_log' := min(r_c + δ_w/2, corresponding to R_c + (2.4−R_c)/2 = (R_c+2.4)/2)... i.e. choose R_c' := R_c + min(δ/2, (2.4−R_c)/2). Then no zeros in (R_c, R_c']. And R_c' − R_c could be as small as... if R_c = 2.4, min(δ/2, 0) = 0!! R_c' = R_c, no room. Ugh — if R_c = 2.4 exactly, zeros at 2.4+ε arbitrary close. But wait — do we need room above R_c at all? B = Cf r_c F is analytic on closedBall(0, R) for any R < 1 regardless (CfAnalytic) — analyticity is fine. NONVANISHING on closedBall(0, R_log) needs no zeros in the annulus. If there's no room, take R_log := r_c exactly? But then the sphere ‖w‖ = r_c... zeros ON the sphere ‖w‖ = r_c? Collected zeros satisfy ‖w‖ ≤ r_c − δ_w < r_c, and uncollected have ‖w‖ > r_c (strictly, since ‖w‖ = r_c ⟹ d = R_c ∈ S... wait d = R_c: is d ∈ S then |d − R_c| = 0 < δ contradiction — so no zero at exactly d = R_c). So on the closed ball closedBall(0, r_c): zeros w have ‖w‖ ≤ r_c − δ_w (if in S... every zero with ‖w‖ ≤ r_c has d ≤ R_c ≤ 2.4 so IS in S ⟹ ‖w‖ ≤ r_c − δ_w ✓). So B nonvanishing on closedBall(0, r_c)? At w with F w = 0 and ‖w‖ ≤ r_c: w ∈ ZW... the Cf def: at a zero w ∈ SetOfZeros r_c, Cf w = ZeroFactor/prod ≠ 0 ✓. At w with F w ≠ 0: else-branch, B w = F w/prod, prod: factors (w−ρ), ρ ∈ ZW, w ≠ ρ since F w ≠ 0 ≠ F ρ... ✓ nonzero. YES — B is nonvanishing on closedBall(0, r_c), no extra room needed!
But LogOfAnalyticFunction needs B nonvanishing on closedBall(0, R) where R > r (r = application radius 3/5) and analyticity on closedBall(0, R) — I can take R = r_c! B analytic on closedBall(0, R') for R' ∈ (r_c, 1) via CfAnalytic, hence on closedBall(0, r_c) by mono ✓. Nonvanishing on closedBall(0, r_c) ✓ as just argued. So apply LogOfAnalyticFunction with r := 3/5, R := r_c: J_B analytic on ball(0, r_c), Re J_B = log‖B‖ − log‖B 0‖ on ball(0, r_c), deriv on closedBall(0, 3/5) ✓.
Then Re J_B bound on ball(0, r_c): need ‖B‖ bound on ball(0, r_c) — via max-modulus on sphere ‖w‖ = r_c: sphere points have no zeros (shown above: no zero at ‖w‖ = r_c), else-branch: ‖B w‖ = ‖F w‖/∏‖w−ρ‖^m with ‖w−ρ‖ ≥ ‖w‖−‖ρ‖ ≥ r_c − (r_c−δ_w) = δ_w. So ‖B w‖ ≤ (9/4)|t|²·(1/δ_w)^{M_c} where 1/δ_w = 50(k+1). Slightly different constant than before (50 vs 200/3·...): log(1/δ_w) = log(50(k+1)). Even better.
Wait — is r_c ≤ 99/100 for the F bound? r_c ≤ 0.96 ≤ 0.99 ✓. And BC: R = r_c ∈ [0.92, 0.96], r = 3/5: R − r ≥ 0.32 = 8/25 ✓, R² ≤ 0.96² = 0.9216. BC factor: 16·0.9216/(8/25)³ = 16·0.9216·15625/512 = 450. Times 2/5 = 180. ✓
Also the M_c count: collected zeros = SetOfZeros r_c with r_c ≤ 0.96 = 24/25 — Jensen applies to the 24/25-finset; monotonicity: SetOfZeros r_c ⊆ SetOfZeros (24/25) (r_c ≤ 24/25 ✓), sum over toFinset subset ≤ since orders ≥ 0. ✓ And k := card of the distance finset S where S := distances of zeros with d ≤ 2.4 = image of (SetOfZeros (24/25) F).toFinset under affine+norm... Let me define S directly as image of the scaled 24/25-finset ZW96 under (5/2)·‖·‖: S := ZW96.toFinset.image (fun w => (5/2)*‖w‖)? Distances of ζ-zeros with d ≤ 2.4 = {(5/2)‖w‖ : w zero of F, ‖w‖ ≤ 24/25}. Note: (5/2)·‖w‖ = ‖s₀ + (5/2)w − s₀‖ ✓ exactly the distances. So S := (ZW96).image (fun w => (5/2) * ‖w‖), card S ≤ card ZW96 ≤ M96 ≤ Jensen. So k := (ZW96).card and card S ≤ k ✓. δ := 1/(20(k+1)) (after the ×10 rescale trick). Clearance applies to every w ∈ ZW96: |(5/2)‖w‖ − R_c| ≥ δ ⟹ |‖w‖ − r_c| ≥ δ_w (δ_w = (2/5)δ = 1/(50(k+1))).
And zeroDiscFinset stays as-is (5/2); zeroDisc_isNontrivial used for: nearZeros members are nontrivial (for β ∈ (0,1) in the nearZeros ⊆ collected argument). ✓
Hmm wait, one thing to double check: for ZW members (collected, ‖w‖ ≤ r_c): the gap argument gives ‖w‖ ≤ r_c − δ_w — this requires (5/2)‖w‖ ∈ S, i.e. w ∈ ZW96: ‖w‖ ≤ r_c ≤ 24/25 ⟹ w ∈ SetOfZeros (24/25) ✓ (F w = 0 by ZW membership). ✓
Also for §9 translation: the collected ζ-zeros finset = ZW.image (fun w => s₀ + (5/2)w). Sum over ZW of m_ρ/(s − ρ_s) via sum_image (inj: affine injective ✓). m values: analyticOrderNatAt F w = analyticOrderNatAt ζ (aff w) (analyticOrderNatAt_scaledZeta ✓ needs ‖w‖ ≤ 1 ✓ r_c < 1). zeroMult ρ := analyticOrderNatAt riemannZeta ρ? Let me check the definition of zeroMult in LiSides/LiSkeleton.
Let me check zeroMult def and nearZeros plan, then also check what logDeriv lemmas exist in Mathlib. Let me grep.
Context absorbed. Now checking `zeroMult`'s definition and the Mathlib `logDeriv` API before writing code.
tool: Grep
input
{
"pattern": "(def zeroMult|zeroMult :=|noncomputable def zeroMult)",
"path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1",
"output_mode": "content",
"-B": 3,
"-A": 3
}
tool: Grep
input
{
"pattern": "theorem logDeriv_(fun_)?(mul|prod|pow|div|comp|const_mul)",
"path": "D:\\Python\\Quantum\\zeta-23-lean\\.lake\\packages\\mathlib\\Mathlib\\Analysis\\Calculus\\LogDeriv.lean",
"output_mode": "content",
"-A": 6
}
thinking (66903 chars)
All APIs confirmed:
- `Real.one_sub_inv_le_log_of_pos : 0 < x → 1 - x⁻¹ ≤ log x` ✓ (for log(33/32) ≥ 1 − 32/33 = 1/33)
- `Set.Finite.toFinset_inj : hs.toFinset = ht.toFinset ↔ s = t` ✓
- `Real.le_log_iff_exp_le` ✓ (for log(9/4) ≤ 1 ⟺ 9/4 ≤ e, and log 4100 ≤ 9 ⟺ 4100 ≤ e⁹)
Now update todos and write the code. Plan of the file addition (append to LiDisc.lean before `end NguyenRH1`):
§5. `norm_scaledZeta_le` — the (9/4)|t|² bound (extracted, duplicated proof).
§6. `scaledZeta_order_ne_top` + `one_le_analyticOrderNatAt_of_zero`.
§7. `scaledZeroFinset` (r-parameterized) + mem lemma.
§8. Jensen count monotonicity: M_c over any r ≤ 24/25 ≤ J-bound; card ≤ M.
§9. `exists_collection_radius` — R_c gap via ×10 rescale of exists_avoiding_midpoint.
§10. With R_c chosen (use Classical choice via `choose` or just work inside the main theorem's proof with obtain) — hmm. Design decision: make r_c etc. FUNCTIONS via choice, or carry the existential into each lemma? Cleaner: one big theorem with `obtain ⟨R_c, ...⟩ := exists_collection_radius ht` at the top and everything inside. But that makes a monster proof. Better: define a structure/bundle? Standard Lean approach: noncomputable defs using Classical.choose:
```lean
def collRadius (t : ℝ) (ht : 10 ≤ |t|) : ℝ := (exists_collection_radius ht).choose
```
Then lemmas about collRadius via .choose_spec. But ht : 10 ≤ |t| as an argument to a def is fine (Prop arg).
Hmm — but then every lemma needs ht. That's OK — they all have ht anyway.
Let me define (all inside namespace, with t, ht):
- `collRadius t ht` (R_c), spec: 23/10 ≤ R_c ≤ 24/10 ∧ gap.
- `rC t ht := collRadius t ht * (2/5)` — scaled radius ∈ [23/25, 24/25].
- `collCard t : ℕ` — card of the 24/25-scaled-zero finset (no ht needed).
- `δw t := 1/(50*(collCard t + 1))`.
- `logRad t ht := rC t ht` — wait I decided R_log = r_c exactly. ✓ so no separate logRad.
- `scaledZerosRC t ht := scaledZeroFinset t (rC t ht) (r_c < 1 proof)` — hmm the def needs the proof r_c < 1 which needs ht. Messy but OK: scaledZeroFinset t r hr with hr : r < 1. For rC: rC t ht < 1 needs ht (via R_c ≤ 24/10 from choose_spec). So the def `scaledZerosRC t ht := scaledZeroFinset t (rC t ht) (rC_lt_one ht)`.
Alternatively — simplify! Note finiteSetOfZeros_mono only needs r < 1 for the FINSET to make sense, but SetOfZeros r F is finite for ANY r ≤ 1 (subset of SetOfZeros 1). Actually even simpler: scaledZeroFinset could take (hr : r ≤ 1) and use Set.Finite.subset directly of scaledZeta_zeros_finite... but finiteSetOfZeros_mono needs r < 1; for r = 1 it's scaledZeta_zeros_finite itself. Let me just define:
```lean
def scaledZeroFinset (t : ℝ) (r : ℝ) : Finset ℂ :=
if hr : r < 1 then
(finiteSetOfZeros_mono (f := scaledZeta t) hr (scaledZeta_zeros_finite)).toFinset
else (scaledZeta_zeros_finite (t := t)).toFinset
```
Ugly. Better: use subset-direct:
```lean
def scaledZeroFinset (t : ℝ) (r : ℝ) (hr : r ≤ 1) : Finset ℂ :=
(scaledZeta_zeros_finite.subset (fun w hw => ⟨hw.1.trans hr, hw.2⟩)).toFinset
```
Wait scaledZeta_zeros_finite : (SetOfZeros 1 (scaledZeta t)).Finite. SetOfZeros r ⊆ SetOfZeros 1 for r ≤ 1: `Set.Finite.subset` gives (SetOfZeros r).Finite, then toFinset. This handles all r ≤ 1 uniformly without dite. But then membership: ρ ∈ scaledZeroFinset t r hr ↔ ‖ρ‖ ≤ r ∧ scaledZeta t ρ = 0 via mem_toFinset ✓.
BUT: the Jensen count `scaledZeta_jensen_count` is stated over `(finiteSetOfZeros_mono (r := 24/25) ...).toFinset` — a DIFFERENTLY-DEFINED finset (same underlying set though). For monotonicity I need: Σ over scaledZeroFinset t (24/25) ≤ log-bound. The two finsets are equal as sets (both = SetOfZeros (24/25) F) — equal as finsets by Set.Finite.toFinset_inj (sets equal by rfl). So:
```lean
theorem scaledZeroFinset_eq_jensenFinset : scaledZeroFinset t (24/25) (by norm_num) = (finiteSetOfZeros_mono (f := scaledZeta t) (r := 24/25) (by norm_num) scaledZeta_zeros_finite).toFinset := by
apply Set.Finite.toFinset_inj.mpr ...
```
hmm toFinset_inj : hs.toFinset = ht.toFinset ↔ s = t. The sets: SetOfZeros (24/25) F = SetOfZeros (24/25) F — rfl. But wait my subset-derived finite: `scaledZeta_zeros_finite.subset (...)` : (SetOfZeros (24/25) F).Finite — the SET is SetOfZeros (24/25) F? `Set.Finite.subset hs hsub : t.Finite` where hsub : t ⊆ s — so yes the resulting .Finite is OF SetOfZeros (24/25) F. toFinset_inj.mpr rfl gives the finset equality. ✓
Hmm — but actually, for the Cf function the internal finset is `finite_zeros_mono.toFinset` where the proof is chosen by the dite's Classical decidability — I can't control which proof. But toFinset_inj.mpr rfl handles ANY proof. So the Cf-unfold lemma:
```lean
theorem Cf_eq_div_prod {t : ℝ} {r : ℝ} (hr : r ≤ 1) {w : ℂ}
(hw : w ∉ SetOfZeros r (scaledZeta t)) :
Cf r (scaledZeta t) w = scaledZeta t w / ∏ ρ ∈ scaledZeroFinset t r hr, (w - ρ) ^ analyticOrderNatAt (scaledZeta t) ρ := by
unfold Cf scaledZeroFinset
by_cases hfin : (SetOfZeros r (scaledZeta t)).Finite
· simp only [hfin, ↓reduceDIte, hw, if_true]
congr 2 -- or rw to equate finsets
exact Set.Finite.toFinset_inj.mpr rfl -- (up to the subset-derived proof)
· exact absurd (the finiteness) hfin
```
The subset-derived finiteness: `scaledZeta_zeros_finite.subset (fun w hw => ⟨hw.1.trans hr, hw.2⟩)` — as a term. OK.
And:
```lean
theorem Cf_eq_zeroFactor_div {t : ℝ} {r : ℝ} (hr : r ≤ 1) {w : ℂ}
(hw : w ∈ SetOfZeros r (scaledZeta t)) :
Cf r (scaledZeta t) w = ZeroFactor (scaledZeta t) w /
∏ ρ ∈ (scaledZeroFinset t r hr) \ {w}, (w - ρ) ^ analyticOrderNatAt (scaledZeta t) ρ
```
Now — for `B_nonzero` at a zero w: ZeroFactorization gives `ZeroFactor F w = h_w w` with `h_w w ≠ 0` — requires w ∈ SetOfZeros R F with R < 1 and F analytic on closedBall(0,1) and F 0 ≠ 0. All ✓ (r_c ≤ 24/25 < 1; scaledZeta_analytic ht; scaledZeta_zero t : F 0 = 1 ≠ 0).
And the product over ZW \ {w}: each factor (w − ρ)^m ≠ 0 ⟸ w ≠ ρ ⟸ ρ ∈ ZW\{w} ✓.
For w ∉ zeros (‖w‖ ≤ r_c): B w = F w/prod, F w ≠ 0, prod ≠ 0 (w ≠ ρ for ρ ∈ ZW: w = ρ would give w ∈ zeros). ✓
Sphere bound: w with ‖w‖ = r_c. First: w ∉ SetOfZeros r_c F: if w ∈ zeros, then w ∈ ZW96 (‖w‖ = r_c ≤ 24/25), gap: |‖w‖ − r_c| ≥ δw > 0, contradiction with ‖w‖ = r_c. ✓ So B w = F w/prod. ‖F w‖ ≤ (9/4)|t|² (norm_scaledZeta_le, r_c ≤ 24/25 ≤ 99/100). ∏: for ρ ∈ ZW: ‖ρ‖ ≤ r_c − δw (gap-below lemma) ⟹ ‖w − ρ‖ ≥ ‖w‖ − ‖ρ‖ ≥ δw ⟹ ∏ ≥ δw^{M_c} (M_c = Σ over ZW). So ‖B w‖ ≤ (9/4)|t|² / δw^{M_c} = (9/4)|t|² · (50(k+1))^{M_c} — with 1/δw = 50(k+1): (1/δw)^{M_c}: write as ((50*(k+1)):ℝ)^{M_c} nat pow. Div bound: ‖F w‖/‖P‖ ≤ B/B' with div_le_div hFtop (prod lower) (prod pos)... div_le_div (a≤b, 0<c, c≤d → a/d ≤ b/c)? The form: ‖F‖/‖P‖ ≤ ((9/4)|t|²)/(δw^{M_c}) via div_le_div_of_nonneg... `div_le_div (hac : a ≤ b) (hc : c ≤ d) (c pos) (b nonneg)??` — signature: div_le_div (h₁ : a ≤ b) (h₂ : c ≤ d) (h₃ : 0 < c) (h₄ : 0 ≤ a) : a / d ≤ b / c? I always mix up. There's `div_le_div_of_nonneg_left/right`, `div_le_div` variants. At build time, use: ‖F‖/‖P‖ ≤ ‖F‖/δw^{M_c} (div_le_div_of_nonneg_left... numerator fixed, denominator smaller (both pos) ⟹ quotient bigger: div_le_div_of_nonneg_left (h : 0 < a)?? hmm — `div_le_div_of_nonneg_left (ha : 0 ≤ a) (hb : 0 < b) (hbc : c ≤ b) : a / b ≤ a / c`. Then ≤ ((9/4)|t|²)/δw^{M_c} via div_le_div_of_nonneg_right (hFtop) hmm — `div_le_div_of_nonneg_right (h : a ≤ b) (hc : 0 < c) : a / c ≤ b / c`. These names shifted in recent Mathlib (session 023 gotcha: div_le_div_iff_of_pos_right/left renames). I'll adapt at build time. Alternatively just use `div_le_div hFtop hprod_le (pow_pos ...) (norm_nonneg _)` — the 4-arg div_le_div: `div_le_div (hbc : b ≤ c)??`. I'll sort it with exact?/apply? at build.
Max-modulus then gives the bound on closedBall(0, r_c) — note norm_le_of_norm_le_on_sphere's analytic arg: AnalyticOn ℂ B (closedBall 0 R) with r = r_c ≤ R. Take R := (1 + r_c)/2... need r_c < 1: r_c ≤ 24/25 ✓. CfAnalytic (r_lt_R : r_c < R) (R_lt_one) gives AnalyticOnNhd on closedBall(0, R); .analyticOn : AnalyticOn on closedBall(0, R). But WAIT — AnalyticOnNhd.analyticOn: AnalyticOnNhd ℂ f s → AnalyticOn ℂ f s? AnalyticOnNhd means analytic at a neighborhood of each point of s; AnalyticOn means analytic within... there's `AnalyticOnNhd.analyticOn` ✓ (used in DiskBound). ✓ And norm_le_of_norm_le_on_sphere (hyp_r : r ≤ R) (analytic : AnalyticOn ℂ f (closedBall 0 R)) (cond on sphere 0 r) (w ∈ closedBall 0 r). With r = r_c, R = (1+r_c)/2. ✓
B 0 value: 0 ∉ zeros (F 0 = 1 ≠ 0) ⟹ B 0 = F 0/∏(0−ρ)^m = 1/∏(−ρ)^m. ‖B 0‖ = 1/∏‖ρ‖^m (norm_prod, norm_pow, norm_neg... ∏‖0−ρ‖^m = ∏‖ρ‖^m). log‖B 0‖ = −Σ m log‖ρ‖... via Real.log_div (numerator 1 ≠ 0, denom ≠ 0), log_one, Real.log_prod (each factor ≠ 0: `Real.log_prod : (∀ i ∈ s, f i ≠ 0) → log (∏ i ∈ s, f i) = ∑ i ∈ s, log (f i)` ✓), Real.log_pow. Each ‖ρ‖ ≤ r_c − δw ≤ 24/25 < 1 ⟹ log‖ρ‖ ≤ log(24/25) < 0... just need log‖ρ‖ ≤ 0 (Real.log_nonpos (norm_nonneg) (‖ρ‖ ≤ 1)) ⟹ −m·log‖ρ‖ ≥ 0 ⟹ log‖B 0‖ = 0 − Σ m log‖ρ‖ ≥ 0 ✓ (Finset.sum_nonpos of m·log‖ρ‖).
Then LogOfAnalyticFunction (r := 3/5) (R := r_c) — B analytic on closedBall(0, r_c) (mono from R'), B nonzero on closedBall(0, r_c):
J_B analytic on ball(0, r_c), J_B 0 = 0, deriv J_B = B'/B on closedBall(0, 3/5), Re J_B = log‖B‖ − log‖B 0‖ on ball(0, r_c).
Re bound: w ∈ ball(0, r_c) ⟹ w ∈ closedBall ✓ ⟹ ‖B w‖ ≤ Bbound ⟹ (B w ≠ 0 ⟹ ‖B w‖ > 0) log‖B w‖ ≤ log Bbound (Real.log_le_log (norm_pos_iff.mpr (B w ≠ 0)) (ball bound)) ⟹ Re J_B(w) = log‖B w‖ − log‖B 0‖ ≤ log‖B w‖ ≤ log Bbound.
log Bbound ≤ (1 + 2L) + M_c·log(50(k+1)): Bbound = (9/4)·|t|²·(50(k+1))^{M_c}; log = log(9/4) + log(|t|²) + log((50(k+1))^{M_c}) via log_mul (positivity), log_pow: = log(9/4) + 2L + M_c·log(50(k+1)) hmm log(|t|²) = 2 log|t| via Real.log_pow (|t| ≠ 0... log (x^2) = 2 log x needs x > 0 — |t| ≥ 10 ✓). log(9/4) ≤ 1. So M_bound := 1 + 2L + M_c * log(50(k+1))... actually cleaner: define M_bound := Real.log Bbound and separately prove M_bound ≤ (1 + 2L) + M_c·log(50(k+1)) ≤ 361L². BC needs Mpos: 0 < M_bound: log Bbound ≥ log‖B w‖... hmm simpler: Bbound ≥ (9/4)·100·1 = 225 ⟹ log Bbound ≥ log 225 > 0 ✓.
BC: w₀ ∈ closedBall(0, 3/5) ⟹ ‖deriv J_B w₀‖ ≤ 16·M_bound·r_c²/(r_c−3/5)³. With r_c ∈ [23/25, 24/25]: ≤ 16·M_bound·(24/25)²/(8/25)³ = 450·M_bound.
Deriv identity at w₀ — as planned (Steps A–F).
Then the main theorem assembles. The final numeric:
‖...‖ ≤ (2/5)·450·M_bound + M_c ≤ 180·(361L²) + 35L² ≤ 66000L².
Wait: M_c ≤ J = 33 + 66L ≤ 35L² (need: 33 + 66L ≤ 35L² at L ≥ 2.302585: 35L² ≥ 35·5.3019 = 185.6 ≥ 33+66·2.302585+... hmm no: 33 + 66L ≤ 35L² ⟺ at L = 2.3026: LHS = 185.0, RHS = 185.57 ✓ barely; increasing L: derivative 66 vs 70L ≥ 161 ✓ increasing gap. For Lean: nlinarith with L ≥ 2.302585? Better: use L ≥ 23/10 = 2.3 (log 10 ≥ 2.3 ⟸ e^{2.3} ≤ 10? e^{2.3} = 9.974 ≤ 10 ✓ — provable? Real.exp 2.3 ≤ 10... hmm. Standard trick: log 10 ≥ 9/4? e^{9/4} = 9.4877 ≤ 10 ✓. e^{9/4} ≤ 10 in Lean: exp(9/4) ≤ 10... these exp bounds are painful. What do the base-point files use? LiBasePoints has exp ≤ (1−x/16)⁻¹⁶ tricks. For log 10 lower bound: `Real.log 10 ≥ 2.3`? There might be `Real.log_two_lt_d9` (log 2 < 0.6931471808) and `Real.log_two_gt_d9` (0.6931471803 < log 2). log 10 = log 2 + log 5... Alternatively just use L ≥ 2: from |t| ≥ 10 > e² = 7.389 ⟹ L ≥ 2 ✓ trivially via le_log_iff_exp_le: 2 ≤ log|t| ⟸ exp 2 ≤ 10 ⟸ exp 2 ≤ e^{2.3}-ish... exp 2 ≤ 10: `Real.exp_one_lt_d9` gives e < 2.719, so e² < 2.719² = 7.393 ≤ 10 ✓ norm_num-friendly: exp 2 = (exp 1)² via Real.exp_nat_mul (2 = 2*1: exp (2*1) = (exp 1)^2). Then 2.719² = 7.392... ≤ 10 ✓. So L ≥ 2.
Redo the fold with L ≥ 2 (slightly worse margins, recheck):
- 563L ≤ (563/2)L² = 281.5L²; 265 ≤ 66.25L²; M_bound ≤ (66 + 281.5 + 66.25)L² = 413.75L² ≤ 414L².
- 180·414 = 74520; M_c ≤ 33+66L ≤ (33/4 + 33)L² = 41.25L² ≤ 42L². Total ≤ 74562L².
- The log(50(k+1)) bound: 50(J+1) = 50(34+66L) = 1700+3300L ≤ (850+3300)L = 4150L (L ≥ 2). log(4150L) = log 4150 + log L ≤ 9 + (L − 1)?? log 4150 ≤ 9 ⟺ 4150 ≤ e⁹; e⁹ ≥ 2.718²...⁹: 2.718⁹ = 2.718·(2.718⁴)²; 2.718² = 7.387524; ⁴ = 54.57557; ⁸ = 2978.48; ⁹ = 8095.6 ≥ 4150 ✓. So log(4150L) ≤ 9 + log L. And log L ≤ L − 1 hmm that's log L ≤ L−1 (Real.log_le_sub_one_of_pos, L > 0) ✓. So ≤ L + 8 ✓ same as before.
- 66L² + 563L + 265 ≤ 414L² at L ≥ 2 ✓ (check at 2: 264+1126+265 = 1655 ≤ 1656 ✓ barely! 66·4 = 264, 563·2 = 1126, +265 = 1655 vs 414·4 = 1656 ✓ 1 unit of slack — TOO TIGHT for comfort with real-number arithmetic... use 420L²: at 2: 1680 vs 1655 ✓ margin 25. And nlinarith should prove (66L² + 563L + 265 ≤ 420L²) from L ≥ 2: 354L² − 563L − 265 ≥ 0; at 2: 1416−1126−265 = 25 ≥ 0 ✓; roots: (563 + √(563² + 4·354·265))/(2·354) = (563 + √(316969+375540))/708 = (563+832.2)/708 = 1.97 < 2 ✓ so holds for L ≥ 2. nlinarith with the product form: (L−2)(354L + 132.5)... 354L²−563L−265 = (L−2)(354L+? ): (L−2)(354L + 132.5) = 354L² + 132.5L − 708L − 265 = 354L² − 575.5L − 265 — not exact. (L−2)(354L + 281.5·...). Let me just factor: 354L² − 563L − 265; divide by (L−2): 354L² − 563L − 265 = (L − 2)(354L + 131) + ( −265 + 262)= (L−2)(354L+131) − 3. Hmm −3: not clean. (L−2)(354L+131) = 354L² + 131L − 708L − 262 = 354L² − 577L − 262. Subtract from target: (−563L + 577L) + (−265 + 262) = 14L − 3 ≥ 0 for L ≥ 2 ✓. So 354L² − 563L − 265 = (L−2)(354L+131) + (14L − 3) — nlinarith [hL] should find this. OK.)
- Total: 180·420 = 75600 + 42 = 75642 → C := 76000. Round: 80000 for headroom. Actually let me reconsider M_bound ≤ 420L²... to reduce nlinarith pain, take C := 100000? The fold: ‖R‖ ≤ (2/5)·450·M_bound + M_c = 180·M_bound + M_c ≤ 180·420L² + 42L² = 75642L² ≤ 100000L². Use 100000 for a nice round number with slack. It's a loose growth constant — bigger rounder is better for downstream manipulation. Hmm — 5e will use this as "O((log R)²)" — any constant works. 10⁵.
Actually — wait. Let me reconsider the Mpos side: BC needs 0 < M_bound where M_bound := Real.log Bbound. Bbound = (9/4)·|t|²·(50(k+1))^{M_c} ≥ (9/4)·100·1 = 225 (pow ≥ 1 since base 50(k+1) ≥ 50 > 1 and exponent... M_c could be 0! (50(k+1))^0 = 1 ✓ ≥ 1 via one_le_pow₀). So Bbound ≥ 225 > 1 ⟹ log > 0 ✓ (Real.log_pos). ✓
Also — one more subtlety in the sphere bound: ∏_{ρ∈ZW} ‖w−ρ‖^{m_ρ} ≥ δw^{M_c}: if ZW is EMPTY (M_c = 0), prod = 1 = δw^0 ✓ fine.
And in the deriv-identity Step A: w₀ ∉ ZW — w₀ = (2/5)(s−s₀); if w₀ ∈ ZW then F w₀ = 0, but F w₀ = ζ(s)/ζ(s₀) ≠ 0 ✓.
Also need: w₀ ∈ closedBall(0, 3/5) — ‖w₀‖ = (2/5)|σ−2|, σ ∈ [1/2, 7/2] ⟹ |σ−2| ≤ 3/2 ⟹ ‖w₀‖ ≤ 3/5 ✓.
Also s.im = t used in: extras ‖s−ρ‖ ≥ |im(s−ρ)| = |t − ρ.im| ≥ 1. ✓
Now — about `nearZeros`: define and prove membership + the two key properties (nontrivial ⟹ re ∈ (0,1); |im − t| < 1 ⟹ ‖ρ − s₀‖ ≤ √5 ≤ R_c for the image-subset argument).
‖ρ − s₀‖² = (β−2)² + (γ−t)² ≤ 4 + 1 = 5 ⟹ ‖ρ−s₀‖ ≤ √5. Need √5 ≤ R_c: R_c ≥ 2.3; √5 ≤ 2.3 ⟺ 5 ≤ 5.29 ✓ (Real.sqrt_le_iff / sq). In Lean: ‖ρ−s₀‖ ≤ √5 via normSq: Complex.normSq (ρ − s₀) = (β−2)² + (γ−t)² ≤ 5, then ‖x‖ = √(normSq x) (Complex.norm_eq_sqrt_normSq? there's `Complex.normSq_eq_norm_sq : normSq z = ‖z‖^2`). So ‖ρ−s₀‖² ≤ 5 ⟹ ‖ρ−s₀‖ ≤ √5 via sq_le_sq₀/Real.sqrt. Then √5 ≤ 23/10: (23/10)² = 529/100 = 5.29 ≥ 5 ✓ via Real.sqrt_le_iff... `Real.sqrt_le_iff : √x ≤ y ↔ 0 ≤ y ∧ x ≤ y^2`? something like that. Fine.
Then w := (ρ − s₀)/(5/2)... the affine inverse: w = (2/5)(ρ − s₀), aff w = ρ. ‖w‖ = (2/5)‖ρ−s₀‖ ≤ (2/5)(23/10) = 23/25 ≤ r_c ✓ (r_c = (2/5)R_c ≥ 23/25). And F w = ζ(ρ)/ζ(s₀) = 0 ✓. So w ∈ SetOfZeros r_c F ⟹ w ∈ ZW ⟹ ρ = aff w ∈ ZW.image aff ✓.
Finset.sum_image needs `Set.InjOn aff ZW`: aff w = s₀ + (5/2)w injective globally: mul_left_cancel₀ (5/2 ≠ 0) + add_left_cancel ✓ (same as scaledZeta_zeros_finite's preimage inj).
Now the sum-split: ZW.image aff ⊇ nearZeros t. Σ_{image} g = Σ_{near} g + Σ_{image\near} g (Finset.sum_sdiff (h : near ⊆ image) : ∑ in (image \ near) + ∑ in near = ∑ in image — the form `Finset.sum_sdiff : s₁ ⊆ s₂ → (∑ i in s₂ \ s₁, f i) + (∑ i in s₁, f i) = ∑ i in s₂, f i` ✓).
Extras bound: ρ ∈ image \ near ⟹ (a) ρ ∈ image: ρ = aff w, zeroMult ρ = m_w; (b) ρ ∉ near: ρ ∈ zeroDiscFinset? Need that to conclude |im−t| ≥ 1: ρ = aff w with w ∈ ZW ⟹ F w = 0 ⟹ ζ(aff w) = 0 (F w = ζ(aff w)/ζ(s₀)) and ‖ρ − s₀‖ = (5/2)‖w‖ ≤ (5/2)r_c = R_c ≤ 2.4 ≤ 2.5 ⟹ ρ ∈ zeroDiscFinset ✓ (mem_zeroDiscFinset). So ρ ∉ near ⟹ ¬|ρ.im − t| < 1 ⟹ 1 ≤ |ρ.im − t|. Then ‖(m:ℂ)/(s−ρ)‖ = m/‖s−ρ‖ ≤ m/1 = m: ‖s−ρ‖ ≥ |im(s−ρ)| = |s.im − ρ.im| = |t − ρ.im| = |ρ.im − t| ≥ 1 (abs_sub_comm). ✓
Σ_{extras} m ≤ Σ_{image} m = M_c... hmm M_c := Σ_{w ∈ ZW} analyticOrderNatAt F w. Σ_{ρ ∈ image} zeroMult ρ = M_c via sum_image + order-invariance ✓. And Σ over subset ≤ Σ over all (nonneg terms): Finset.sum_le_sum_of_subset_of_nonneg ✓ (subset: extras ⊆ image ✓). So extras ≤ M_c ≤ J.
The order-invariance: analyticOrderNatAt_scaledZeta ht (hw : ‖w‖ ≤ 1) : analyticOrderNatAt (scaledZeta t) w = analyticOrderNatAt riemannZeta (s₀ + (5/2)w). And zeroMult (aff w) = analyticOrderNatAt ζ (aff w) — def: zeroMult ρ := (analyticOrderAt riemannZeta ρ).toNat and analyticOrderNatAt f z₀ := (analyticOrderAt f z₀).toNat. So `zeroMult (aff w) = analyticOrderNatAt riemannZeta (aff w)` should be rfl after `unfold zeroMult analyticOrderNatAt`? or just `rfl`. Let me define a tiny lemma `zeroMult_eq : zeroMult ρ = analyticOrderNatAt riemannZeta ρ := rfl`. (Test at build; if not rfl, rw the defs.)
OK — also the deriv-translation for logDeriv F: F = fun w => ζ(s₀ + (5/2)w)/ζ(s₀). logDeriv F w₀ where F w₀ ≠ 0:
F = fun w => (ζ ∘ aff) w / c with c = ζ(s₀). Hmm scaledZeta def: riemannZeta (...) / riemannZeta (discCenter t). logDeriv (fun w => g w / c) w₀: logDeriv_div with g w₀ ≠ 0, c ≠ 0: = logDeriv g w₀ − logDeriv (fun _ => c) w₀ = logDeriv g − 0 (logDeriv_const: deriv const = 0, so logDeriv const = 0/c = 0 — `logDeriv_const` simp lemma exists? likely `logDeriv_const (c) : logDeriv (fun _ => c) = 0`? probably simp-able). Then logDeriv g w₀ with g = ζ ∘ aff: logDeriv_comp (diff ζ at aff w₀: analytic ⟹ differentiableAt — need aff w₀ = s ≠ 1: s ≠ 1 since s.im = t, |t| ≥ 10 ⟹ s ≠ 1 ✓; diff aff ✓): = logDeriv ζ (aff w₀) · deriv aff w₀. deriv aff w₀ = 5/2: aff = fun w => s₀ + (5/2)*w = const + const*w: deriv_const_add + deriv_const_mul (differentiableAt_id) + deriv_id''. Result: (5/2)·logDeriv ζ s ✓ (aff w₀ = s by ring-ish: s₀ + (5/2)·(2/5)(s−s₀) = s — needs field_simp/ring with ℂ... (5/2 : ℂ)*(2/5 : ℂ) = 1 by norm_num; so s₀ + 1·(s − s₀) = s by ring. Use `show` + ring? ring should handle: s₀ + (5/2)*((2/5)*(s − s₀)) = s as a ring identity in variables s₀, s ✓.)
One concern: `logDeriv_comp` needs `DifferentiableAt ℂ ζ (aff w₀)` — from analyticAt_riemannZeta_of_ne_one (s ≠ 1) .differentiableAt ✓.
Now, an important check in Step B: `Filter.EventuallyEq.deriv : f =ᶠ[𝓝 x] g → deriv f x = deriv g x` — signature `EventuallyEq.deriv (h : f₁ =ᶠ[𝓝 x] f₂) : deriv f₁ x = deriv f₂ x` ✓ exists in Mathlib.
And logDeriv (F/P) at w₀: F/P means fun w => F w / P w. logDeriv_div x (hf : f x ≠ 0) (hg : g x ≠ 0) (hdf : DifferentiableAt) (hdg) ✓.
DifferentiableAt F w₀: scaledZeta_analytic ht gives AnalyticOnNhd on closedBall(0,1); w₀ ∈ closedBall(0, 3/5) ⊆ closedBall(0,1) ⟹ AnalyticAt ⟹ differentiableAt ✓.
DifferentiableAt P w₀: analyticAt_finset_prod_sub_pow (Zeta23) ✓ .differentiableAt.
P w₀ ≠ 0: Finset.prod_ne_zero_iff; each (w₀ − ρ)^{m} ≠ 0: w₀ ≠ ρ (w₀ ∉ ZW ∋ ρ) ✓.
logDeriv P w₀ = Σ logDeriv (each) w₀ (logDeriv_prod: each factor ≠ 0 at w₀ ✓, differentiable ✓) = Σ m_ρ * logDeriv (· − ρ) w₀ (logDeriv_fun_pow (diff) m) = Σ m_ρ * (1/(w₀ − ρ))... logDeriv (fun w => w − ρ) w₀ = deriv(...)/(...) = 1/(w₀−ρ): deriv (fun w => w − ρ) w₀ = 1: `deriv_sub_const`? hmm: fun w => w − ρ = id − const: deriv_sub (differentiableAt_id) (differentiableAt_const ρ) : deriv (id − fun _ => ρ) w₀ = deriv id w₀ − deriv (fun _ => ρ) w₀ = 1 − 0. But the lambda form: (fun w => w − ρ) — simp with deriv_id'' hmm. There are simp lemmas `deriv_add_const`, `deriv_sub_const`... I think `deriv_sub_const : deriv (fun x => f x − c) x = deriv f x` requires the function form f x − c ✓ that's our form! `deriv_sub_const (c : 𝕜) : deriv (fun x => f x − c) x = deriv f x`? Hmm the actual name might be `deriv_sub_const (hc : DifferentiableAt...)`. Recent Mathlib: `deriv_sub_const (c : F) : deriv (fun x => f x - c) x = deriv f x`? not sure if needs differentiability hypothesis. And then deriv (fun w => w) w₀ = 1: `deriv_id''`? or `deriv_id'`. There's `deriv_id' : deriv id x = 1`? Hmm — `deriv_id'` might be for `deriv id = fun _ => 1`. Or `deriv_id''`. I'll use `hasDerivAt_id` + `.deriv` as fallback: (hasDerivAt_id w₀).sub (hasDerivAt_const w₀ ρ) : HasDerivAt (fun w => w − ρ) (1 − 0) w₀ → .deriv gives deriv = 1 − 0 = 1. Safe. Then logDeriv = deriv/f = 1/(w₀−ρ) (logDeriv_apply? logDeriv f x = deriv f x / f x — `logDeriv_apply` simp). So the factor's logDeriv = 1/(w₀−ρ), and after logDeriv_fun_pow: m * (1/(w₀−ρ)) = m/(w₀−ρ) (mul_one_div m _). ✓
Then: (5/2)·logDeriv ζ s = deriv J_B w₀ + Σ_{ZW} m/(w₀−ρ)?? Wait let me recompute: deriv J_B w₀ = deriv B w₀/B w₀ = logDeriv (F/P) w₀ = logDeriv F w₀ − logDeriv P w₀ = (5/2)·logDeriv ζ s − Σ m/(w₀−ρ).
So (5/2)·logDeriv ζ s = deriv J_B w₀ + Σ m/(w₀−ρ).
logDeriv ζ s = (2/5)·deriv J_B w₀ + (2/5)·Σ m/(w₀−ρ) = (2/5)·deriv J_B w₀ + Σ (2/5)·m/(w₀−ρ).
(2/5)·m/(w₀−ρ) = m/((5/2)(w₀−ρ)) = m/(s − aff ρ): (5/2)(w₀−ρ) = (5/2)w₀ − (5/2)ρ = (s−s₀) − (aff ρ − s₀) = s − aff ρ ✓. So term = (m:ℂ)/(s − aff ρ). Field manipulation: (2/5)*m/(w₀−ρ) = m/(s−affρ): mul_div_assoc + congr on denominator. In Lean: prove `(2/5 : ℂ) * (m : ℂ)/(w₀ − ρ) = (m : ℂ)/(s − aff ρ)` by `rw [mul_div_assoc]; congr 1; field_simp; ring`? (5/2)(w₀−ρ) = s − aff ρ as complex identity: (5/2)*(w₀ − ρ) = s − (s₀ + (5/2)*ρ) where w₀ = (2/5)*(s − s₀): expand: (5/2)*(2/5)*(s−s₀) − (5/2)ρ = (s−s₀) − (5/2)ρ = s − s₀ − (5/2)ρ ✓ ring proves it. Then m/(X) = m/Y via congr_arg (HDIV) — need X ≠ 0? No: congr of the denominator is just congr_arg (·) — m/X = m/Y follows from X = Y by rw. So: rw [mul_div_assoc, show (5/2:ℂ)*(w₀−ρ) = s − aff ρ from by ring]... but the LHS after mul_div_assoc is ((2/5)*m)/(w₀−ρ), and I want m/(s − aff ρ). ((2/5)*m)/(w₀−ρ) = m/((5/2)(w₀−ρ))? a/b = (c·a)/(c·b) for c ≠ 0 — mul_div_mul_right? hmm: m/Y = (2/5·m)/((2/5)·Y) hmm. Easiest: field_simp [hw₀ρ ≠ 0, hsρ ≠ 0] then ring. The identity (2/5)*m/(w₀−ρ) = m/(s−affρ) is a field identity valid when denominators ≠ 0: field_simp clears: (2/5)*m*(s−affρ) = m*(w₀−ρ) — after substituting the relations... but field_simp needs to know (s−affρ) = (5/2)(w₀−ρ) — that's a ring identity that field_simp+ring might close: goal after field_simp: (2/5)*m*(s − (s₀+(5/2)*ρ)) = m*(w₀−ρ); with w₀ := (2/5)*(s−s₀) — if w₀ is a `let`/local def, ring needs it unfolded. I'll set w₀ via `set w₀ := (2/5 : ℂ)*(s − discCenter t) with hw₀def` then the ring identity needs w₀'s def — provide `have hws : (5/2:ℂ)*(w₀ − ρ) = s − (s₀ + (5/2)*ρ) := by rw [hw₀def]; ring`. Then: (2/5)*m/(w₀−ρ) = m/(s − affρ): rw [mul_div_assoc, ← hws]?? goal: (2/5)*m/(w₀−ρ) = m/(s−affρ). Rewrite RHS denom via hws.symm: s − affρ = (5/2)(w₀−ρ). Then RHS = m/((5/2)(w₀−ρ)). And m/((5/2)(w₀−ρ)) = (2/5)·(m/(w₀−ρ)): div_mul_eq_mul_div... m/((5/2)·X) = (m/(5/2))/X = m·(2/5)/X ✓ via div_div... m/((5/2)*X) = m/(5/2)/X (div_mul_eq_div_div) = m·(2/5)/X hmm (m/(5/2) = m·(2/5) via div_eq_mul_inv + inv... (5/2)⁻¹ = 2/5 by norm_num). Then (m·(2/5))/X = (2/5·m)/X (mul_comm). OK — chain of rws; fine.
So final: logDeriv ζ s = (2/5)·deriv J_B w₀ + Σ_{w∈ZW} (m_w:ℂ)/(s − aff w) = (2/5)·deriv J_B w₀ + Σ_{ρ∈image} (zeroMult ρ:ℂ)/(s−ρ).
Then target: logDeriv ζ s − Σ_{near} ... = (2/5)·deriv J_B w₀ + Σ_{extras} ...
‖·‖ ≤ (2/5)‖deriv J_B w₀‖ + Σ_extras ‖(m:ℂ)/(s−ρ)‖ ≤ (2/5)·450·M_bound + M_c(ℝ) ≤ 180·M_bound + J ≤ 180·420L² + 42L² = 75642L² ≤ 100000L².
Hmm wait — the M_bound in BC is the SYMBOLIC one (Real.log Bbound), and I separately show M_bound ≤ 420L². And extras ≤ M_c ≤ J = 33+66L ≤ 42L² (at L ≥ 2: 33+66L ≤ 42L² ⟺ 42L²−66L−33 ≥ 0; at 2: 168−132−33 = 3 ≥ 0 ✓; (L−2)(42L+?): 42L²−66L−33 = (L−2)(42L+16.5)... 42L²+16.5L−84L−33 = 42L²−67.5L−33. remainder 1.5L ≥ 0 ✓ nlinarith).
M_c ≤ J: M_c = Σ_{ZW} order ≤ Σ_{ZW96} order (subset + nonneg) = (the Jensen finset sum) ≤ log((9/4)|t|²)/log(33/32) (scaledZeta_jensen_count) ≤ (1+2L)/(1/33) = 33(1+2L) = 33+66L = J. The last step: a/b ≤ c/d-form: log((9/4)|t|²) ≤ 1+2L ≥ 0? need 0 ≤ numerator ✓ (log((9/4)·100) ≥ log 225 > 0 ✓... log((9/4)|t|²) ≥ 0 since (9/4)|t|² ≥ 1) and log(33/32) ≥ 1/33 > 0: div_le_div (num ≤ num') (denom ≥ denom') (denom' pos) (num nonneg) — `div_le_div (hac : a ≤ b) (hbd : c ≤ d)...` the precise 4-arg: `div_le_div (h₁ : a ≤ b) (h₂ : c ≤ d) (h₃ : 0 < c) (h₄ : 0 ≤ a) : a / d ≤ b / c`? I think that's right: a/d ≤ b/c when a ≤ b, c ≤ d, 0 < c, 0 ≤ a. Let me double check direction: bigger numerator, smaller denominator ⟹ bigger. a/d vs b/c: a ≤ b and d ≥ c > 0 ⟹ a/d ≤ b/d ≤ b/c ✓. Signature in Mathlib (ordered field): `div_le_div (hab : a ≤ b) (hcd : c ≤ d) (hc : 0 < c) (ha : 0 ≤ a) : a / d ≤ b / c` ✓ yes.
And card ZW96 ≤ Σ_{ZW96} order: each order ≥ 1 (one_le for zeros — need: w ∈ ZW96 ⟹ F w = 0, ‖w‖ ≤ 24/25 ≤ 1 ⟹ order ≥ 1 via my helper). Finset.card_le_sum: card s = Σ 1 ≤ Σ order: `Finset.card_le_sum`? doesn't exist probably; do: s.card = ∑ _ ∈ s, 1 (Finset.card_eq_sum_ones) ≤ ∑ order (Finset.sum_le_sum, each 1 ≤ order) ✓.
k+1 vs J: k = card ZW96 ≤ M96 ≤ J ⟹ k+1 ≤ J+1 (real cast: (k+1 : ℝ) ≤ J+1... k ≤ J from (k:ℝ) ≤ M96 ≤ J where M96 : ℕ cast — hmm M96 = Σ of ℕ orders: (M96 : ℝ)... the Jensen bound compares Σ (nat-valued orders) with a real: `∑ ρ ∈ ..., analyticOrderNatAt F ρ ≤ Real.log ... / Real.log ...` — the LHS is ℕ ≤ ℝ?? In the committed statement: `∑ ρ ∈ ..., analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log (...) / Real.log (...)` — type: the sum is ℕ, RHS ℝ — so it's (↑sum) ≤ ℝ via Nat.cast_le. ✓. So (k:ℝ) ≤ (M96:ℝ) ≤ J. Then 50(k+1) ≤ 50(J+1): cast k+1: ((k+1:ℕ):ℝ) = k+1 ✓ push_cast.
Also for Bbound's definition, M_c appears as a NATURAL exponent: (50*(k+1))^{M_c} where M_c : ℕ. And log of it: log((50(k+1))^{M_c}) = M_c·log(50(k+1)) (Real.log_pow : log (x^n) = n*log x with n : ℕ cast ✓).
And M_c ≤ J ⟹ (50(k+1))^{M_c} ≤ ... hmm — I bound log Bbound DIRECTLY: log Bbound = log(9/4) + 2L + M_c·log(50(k+1)) ≤ 1 + 2L + J·log(50(J+1)) ≤ ... For the fold I need: M_c·log(50(k+1)) ≤ J·(L+8): M_c ≤ J ✓, log(50(k+1)) ≤ L+8 ✓ (shown: 50(k+1) ≤ 4150L ⟹ log ≤ log 4150 + log L ≤ 9 + (L−1) = L+8), both nonneg (M_c ≥ 0 nat cast ✓; log(50(k+1)) ≥ log 50 > 0 ✓) ⟹ mul_le_mul ✓. Then M_bound ≤ 1+2L + J(L+8) = 1+2L+(33+66L)(L+8) = 66L²+563L+265 ≤ 420L² ✓ (the nlinarith bit).
Wait — one more check on the (2/5)·450 factor: BC gives 16·M·r_c²/(r_c−3/5)³. r_c² ≤ (24/25)² — r_c ≤ 24/25 ✓ (r_c ≥ 0 for pow_le_pow_left₀). (r_c−3/5)³ ≥ (8/25)³: r_c−3/5 ≥ 23/25−3/5 = 23/25−15/25 = 8/25 ✓ > 0. So 16·M·r_c²/(r_c−3/5)³ ≤ 16·M·(24/25)²/(8/25)³ = 450M. Steps: div_le_div (16Mr_c² ≤ 16M(24/25)²) ((8/25)³ ≤ (r_c−3/5)³) (pos) (nonneg) ✓ then = 450M by norm_num/ring: 16·(24/25)²/(8/25)³ = 16·576/625·15625/512 = 16·576·25/512 = 16·360000/... 576·25 = 14400; 14400/512 = 28.125; ×16 = 450 ✓ exact.
Then (2/5)·450 = 180 ✓. 180·420 = 75600. 75600 + 42 = 75642 ≤ 100000 ✓.
Final statement:
```lean
theorem logDeriv_riemannZeta_sub_nearZeros_le {t : ℝ} (ht : 10 ≤ |t|) {s : ℂ}
(hsim : s.im = t) (hσlo : 1 / 2 ≤ s.re) (hσhi : s.re ≤ 7 / 2)
(hs0 : riemannZeta s ≠ 0) :
‖logDeriv riemannZeta s − ∑ ρ ∈ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)‖
≤ 100000 * (Real.log |t|) ^ 2
```
Hmm — should the constant be there or should I use ∃? D-067 says loose; explicit 100000 is honest and loose. But hmm, wait — actually let me reconsider: is there any chance 5e needs this in a different shape (e.g. on a circle of radius R with s varying)? The 5e circle argument: for s on a big circle, apply 5c at height t = im s (if |im s| ≥ 10) with the nearZeros of t... The growth bound C·(log|t|)² with |t| ≤ R+1 gives C·(log(R+1))² hmm ≤ C'·(log R)² for R ≥ ... fine, downstream can convert. The stated form is the D-067 target shape. Good.
Also — do I want `‖·‖ ≤ 100000 * (Real.log |t|)^2` or with (log(|t|))^2 vs log|t| ^ 2 — fine.
Now about proof structure size: this is big. Let me organize the new code as a sequence of lemmas appended to LiDisc.lean:
1. `norm_scaledZeta_le` (t, ht, z, ‖z‖ ≤ 99/100 → bound) — duplicated from jensen proof.
2. `scaledZeta_order_ne_top_of_norm_le` (ht, ‖w‖ ≤ 1 → analyticOrderAt F w ≠ ⊤).
3. `one_le_analyticOrderNatAt_scaledZeta` (ht, ‖w‖ ≤ 1, F w = 0 → 1 ≤ analyticOrderNatAt F w).
4. `scaledZeroFinset t r (hr : r ≤ 1)` + `mem_scaledZeroFinset`.
5. `scaledZeroFinset_mono` (r₁ ≤ r₂ → subset as finsets).
6. `card_le_sum_order` (ht: card (scaledZeroFinset t r hr) ≤ Σ order) — needs orders ≥ 1: ht for ‖w‖ ≤ 1 (r ≤ 1 ✓).
7. `sum_order_le_jensen` (ht, r ≤ 24/25: Σ order over scaledZeroFinset t r hr ≤ log((9/4)|t|²)/log(33/32)) — via mono to 24/25-finset + toFinset_inj-equality with the Jensen finset + scaledZeta_jensen_count.
8. `exists_collection_radius` (ht → ∃ R_c ∈ [23/10, 24/10], gap) via the ×10 trick on exists_avoiding_midpoint with S := (scaledZeroFinset t (24/25) _).image (fun w => (5/2)*‖w‖)... hmm wait: exists_avoiding_midpoint needs S : Finset ℝ with card S ≤ k. S := image; k := card (scaledZeroFinset 24/25). card image ≤ card ✓. Then S10 := S.image (fun x => x*10): card ≤ card S ≤ k ✓. Apply with a := 23. T ∈ [23,24], ∀ y ∈ S10, 1/(2(k+1)) ≤ |y − T|. R_c := T/10. For w ∈ ZW96: y := 10·((5/2)‖w‖) = 25‖w‖ ∈ S10 (mem_image of mem_image). |25‖w‖ − T| ≥ 1/(2(k+1)) ⟹ |(5/2)‖w‖ − R_c| = |25‖w‖ − T|/10 ≥ 1/(20(k+1)). ✓ (|25‖w‖ − T| = 10·|(5/2)‖w‖ − T/10| via abs_mul, |10| = 10.)
9. Bundle: `collRadius t ht := (exists_collection_radius ht).choose` + spec lemmas `collRadius_mem : 23/10 ≤ collRadius t ht ∧ collRadius t ht ≤ 24/10`, `collRadius_gap : ∀ w ∈ scaledZeroFinset t (24/25) _, 1/(20*(card+1)) ≤ |(5/2)*‖w‖ − collRadius t ht|`.
Hmm — with choose: `(exists_collection_radius ht).choose_spec` gives the ∃-body. ✓
10. `rC t ht := collRadius t ht * (2/5)`; `rC_mem : 23/25 ≤ rC t ht ∧ rC t ht ≤ 24/25`; `rC_gap : ∀ w ∈ ZW96, δw ≤ |‖w‖ − rC|` where δw := 1/(50*(card+1)): from gap: |(5/2)‖w‖ − R_c| = (5/2)|‖w‖ − rC| (factor: (5/2)‖w‖ − R_c = (5/2)(‖w‖ − R_c·(2/5)) = (5/2)(‖w‖ − rC) ✓ ring; abs_mul; |5/2| = 5/2) ⟹ (5/2)|‖w‖−rC| ≥ 1/(20(k+1)) ⟹ |‖w‖−rC| ≥ (2/5)·1/(20(k+1)) = 1/(50(k+1)) ✓.
11. `ZW` := scaledZeroFinset t (rC t ht) (rC ≤ 24/25 ≤ 1). `ZW_gap_below : w ∈ ZW → ‖w‖ ≤ rC − δw` (w ∈ ZW ⟹ w ∈ ZW96 (mono, rC ≤ 24/25) ⟹ gap; ‖w‖ ≤ rC + ... cases: |‖w‖ − rC| ≥ δw and ‖w‖ ≤ rC ⟹ ‖w‖ ≤ rC − δw ✓).
12. `Cf` characterizations + `B_analytic` (AnalyticOnNhd on closedBall(0, (1+rC)/2)), `B_nonzero` (on closedBall(0, rC)), `B_bound_center` (log‖B 0‖ ≥ 0), `B_sphere_bound` (‖w‖ = rC → ‖B w‖ ≤ Bbound), `B_ball_bound` (closedBall(0, rC) via max-modulus).
13. `J_B` obtain + `M_bound` def + Re-bound + BC bound: package as a lemma:
`∃ J_B : ℂ → ℂ, J_B 0 = 0 ∧ (∀ w ∈ closedBall 0 (3/5), deriv J_B w = deriv B w / B w) ∧ (∀ w ∈ ball 0 rC, (J_B w).re = log‖B w‖ − log‖B 0‖) ∧ (∀ w ∈ closedBall 0 (3/5), ‖deriv J_B w‖ ≤ 450 * M_bound) ∧ AnalyticOnNhd J_B (ball 0 rC)` — or just inline the obtain in the main theorem. Inline might be fine: obtain at the top of the main theorem, all facts local.
14. Main theorem.
Also the w₀-side deriv identity could be a standalone lemma:
`deriv_JB_eq : deriv J_B w₀ = (5/2)*logDeriv riemannZeta s − Σ_{w∈ZW} (m_w:ℂ)/(w₀−w)` — inside main proof.
Let me think about what could be painful:
(a) The Cf dite unfolding — the Classical instance: `open Classical` is at the top of StrongPNTPrefix (line 206 `open Classical`). The def Cf uses `if finite_zeros_mono : ...`. When I unfold Cf in NguyenRH1 (no `open Classical` in LiDisc?) — the instance is baked into the TERM (dite with the Classical.propDecidable instance — wait, `open Classical` makes `Classical.propDecidable` available as an instance during ELABORATION of Cf, so the dite's instance is Classical.propDecidable. When I unfold and want ↓reduceDIte to fire with my `hfin` proof, simp's ↓reduceDIte works regardless of instance (it matches `dite c ...` where c decides True-ish...). In Zeta23's own proofs they do `by_cases finite_zeros_mono : (SetOfZeros r f).Finite; simp only [finite_zeros_mono, ↓reduceDIte]` — and this works. I'll mirror exactly.
(b) `analyticOrderNatAt` vs Zeta23's `ZeroFactor` — ZeroFactorization gives the factorization at zeros; I only need ZeroFactor F w ≠ 0 (from h_ρ ρ ≠ 0 + ZeroFactor F ρ = h_ρ ρ). ✓ ZeroFactorization's hypotheses: R < 1, F analytic on closedBall(0,1), F 0 ≠ 0, ρ ∈ SetOfZeros R F. With R := rC... wait it needs RleOne : R < 1 where hρ : ρ ∈ SetOfZeros R F. w ∈ ZW ⟹ w ∈ SetOfZeros (rC) F and rC < 1 ✓ (rC ≤ 24/25). But actually ZeroFactorization's signature: (RleOne : R < 1) (hfAnalytic) (hf_neq_zero_at_zero) (hρ : ρ ∈ SetOfZeros R f). Use R := rC ✓.
(c) For B_nonzero at w with F w = 0 but ‖w‖ ∈ (rC, rC]... — wait closedBall(0, rC), F w = 0: is w ∈ SetOfZeros rC F? Need ‖w‖ ≤ rC ✓ and F w = 0 ✓ ⟹ yes! Oh nice — I don't even need the gap for nonvanishing ON closedBall(0, rC): F w = 0 ∧ ‖w‖ ≤ rC ⟹ w ∈ SetOfZeros directly. The GAP is needed only for: (i) sphere identity (no zeros ON the sphere for the else-branch... actually no — the else-branch needs w ∉ SetOfZeros rC F; on the sphere ‖w‖ = rC, if F w = 0 then w ∈ SetOfZeros (‖w‖ ≤ rC ✓). So sphere zeros ARE in the zero set, and Cf at them uses the if-branch. Hmm! So on the sphere, B w = ZeroFactor/prod_{≠w}, NOT F w/prod! Then ‖B w‖ = ‖ZeroFactor w‖/∏_{ρ≠w}‖w−ρ‖^m — the factor (w−w)^m is removed, but ZeroFactor w = h_w(w) with h_w(w) ≠ 0 — bounding ‖h_w(w)‖ above is NOT directly available!
Ugh. Wait — but the gap says: no zeros ON the sphere at all (zeros with ‖w‖ ≤ rC have ‖w‖ ≤ rC − δw). So on the sphere, F w ≠ 0, else-branch applies. ✓ The gap is exactly what kills this. Good — the sphere bound proceeds as planned: ∀ w, ‖w‖ = rC → F w ≠ 0 (via gap), hence B w = F w/prod, etc.
Hmm wait, one more: for the else-branch I need w ∉ SetOfZeros rC F — F w ≠ 0 suffices ✓.
(d) For B_nonzero's zero-case: w ∈ SetOfZeros rC F ⟹ Cf w = ZeroFactor F w / ∏_{ρ ∈ ZW\{w}} (w−ρ)^m. ZeroFactor ≠ 0 ✓; product: ρ ∈ ZW\{w} ⟹ ρ ≠ w ⟹ factor ≠ 0 ✓. ✓
(e) The max-modulus application: `AnalyticOn.norm_le_of_norm_le_on_sphere (hyp_r : r ≤ R) (analytic : AnalyticOn ℂ f (closedBall 0 R)) (cond : ∀ z ∈ sphere 0 r, ‖f z‖ ≤ C) (wInS : w ∈ closedBall 0 r)`. Take r := rC, R := (1+rC)/2 (need rC ≤ R ✓ since rC < 1), analytic: AnalyticOn on closedBall(0, R) from CfAnalytic (r_lt_R : rC < R ✓) (R < 1: (1+rC)/2 < 1 ⟸ rC < 1 ✓).analyticOn. cond: sphere(0, rC) = {‖z‖ = rC} (Metric.sphere 0 rC: dist z 0 = rC ⟺ ‖z‖ = rC via mem_sphere_iff_norm/sub_zero — diskBound used `rw[mem_sphere_iff_norm, sub_zero]`). ✓
(f) BorelCaratheodoryDeriv needs AnalyticOn ℂ J_B (ball 0 R) — from AnalyticOnNhd J_B (ball 0 rC) .analyticOn ✓.
(g) `Real.log Bbound` where Bbound := (9/4)*|t|^2*(50*(k+1))^{M_c}: log Bbound = log((9/4)*|t|²) + log((50(k+1))^{M_c}) via Real.log_mul ((9/4)|t|² ≠ 0, pow ≠ 0). log((9/4)|t|²) = log(9/4) + 2·log|t| — hmm log((9/4)·|t|²) = log(9/4) + log(|t|²) (log_mul) and log(|t|²) = 2·log|t|: Real.log_pow gives log(|t|^{2:ℕ}) = 2·log|t|... but |t|² could be written |t|^2 nat-pow ✓ (use |t|^2 with Nat pow everywhere; the Jensen bound has |t| ^ 2 — check the committed form: `Real.log ((9 / 4) * |t| ^ 2)` — |t| ^ 2 with ℕ exponent inferred ✓, and norm_riemannZeta_le_disc gives (3/4)*|t|^2. So |t|^2 nat pow ✓, Real.log_pow applies.)
Now — nearZeros def and its lemmas. And `zeroMult` cast to ℂ in sums: (zeroMult ρ : ℂ).
The final sum identity chain in the main proof:
```
logDeriv ζ s = (2/5)·deriv J_B w₀ + Σ_{w∈ZW} (m_w : ℂ)/(s − aff w) (★)
Σ_{w∈ZW} (m_w:ℂ)/(s−aff w) = Σ_{ρ∈ZW.image aff} (zeroMult ρ:ℂ)/(s−ρ) (sum_image + order-inv)
Σ_image = Σ_near + Σ_extras (sum_sdiff)
```
For (★): from deriv J_B w₀ = (5/2)·logDeriv ζ s − Σ_{w∈ZW} m_w/(w₀−w):
(5/2)·logDeriv ζ s = deriv J_B w₀ + Σ m/(w₀−w); multiply by 2/5: logDeriv ζ s = (2/5)deriv J_B + (2/5)Σ m/(w₀−w) = (2/5)deriv J_B + Σ (2/5)·m/(w₀−w) (Finset.mul_sum) and per-term (2/5)·m/(w₀−w) = m/(s−aff w) (hws identity). ✓
Then ‖logDeriv ζ s − Σ_near‖ = ‖(2/5)deriv J_B + Σ_extras‖ ≤ (2/5)‖deriv J_B‖ + ‖Σ_extras‖ ≤ (2/5)·450·M_bound + Σ_extras ‖(m:ℂ)/(s−ρ)‖ ≤ 180·M_bound + Σ_extras m.
Σ_extras m (as ℝ): Σ_{ρ∈extras} (zeroMult ρ : ℝ) ≤ Σ_{ρ∈image} (zeroMult ρ : ℝ) = (M_c : ℝ)?? hmm: Σ_{ρ∈image} zeroMult ρ = Σ_{w∈ZW} zeroMult (aff w) = Σ_{w∈ZW} m_w = M_c ✓ (sum_image with g := fun ρ => (zeroMult ρ : ℝ)). Then ≤ J. Careful with nat vs real casts: keep sums in ℝ via casts and push_cast where needed. Actually simpler: do everything with (zeroMult ρ : ℂ) terms; the extras bound: ‖(m:ℂ)/(s−ρ)‖ = m/‖s−ρ‖ ≤ m (as real: (m:ℝ)/‖s−ρ‖ ≤ m since ‖s−ρ‖ ≥ 1: div_le_of_le_mul? m/‖s−ρ‖ ≤ m/1 = m via div_le_div_of_nonneg_left (m nonneg) (‖s−ρ‖ ≥ 1 > 0) (1 ≤ ‖s−ρ‖): `div_le_div_of_nonneg_left (ha : 0 ≤ a) (hb : 0 < b) (h : b ≤ c) : a / c ≤ a / b` — with b := 1: a/‖s−ρ‖ ≤ a/1 = a ✓). Then Σ ≤ Σ m (norm cast: ‖(m:ℂ)‖ = m since m ≥ 0: Complex.norm_natCast? `Complex.norm_natCast : ‖(n : ℂ)‖ = n` ✓ (RCLike.norm_natCast)).
OK — I'm confident in the plan. One more piece: the FINAL fold nlinarith chains. To minimize pain, structure the fold as a standalone real-number lemma:
```lean
theorem loose_fold {L M k : ℝ}...
```
Hmm — variables entangled (M_c ≤ J, k ≤ J...). Let me instead do the fold stepwise with explicit haves inside the main proof. The non-linear parts:
(i) log(33/32) ≥ 1/33: from Real.one_sub_inv_le_log_of_pos (33/32 > 0): 1 − (33/32)⁻¹ = 1 − 32/33 = 1/33 ✓ (norm_num).
(ii) J := 33+66L bound: log((9/4)|t|²) ≤ 1+2L: log((9/4)|t|²) = log(9/4) + 2L; log(9/4) ≤ 1 ⟸ 9/4 ≤ exp 1 ⟸ (exp_one_gt_d9: 2.7182818283 < e?) — check the name used in LiContour: `Real.exp_one_lt_d9.le` — exp_one_lt_d9 : exp 1 < 2.7182818286? and exp_one_gt_d9 : 2.7182818283 < exp 1. LiContour used exp_one_lt_d9 for e < 2.7182818286... they wrote `Real.exp_one_lt_d9.le` in context: `he := Real.exp_one_lt_d9.le; linarith` where they needed 3 ≤ e? Their hlog needed t+2 ≥ 3 > e... they used exp_one_lt_d9.le : e ≤ 2.7182818286 then linarith with 3... wait that gives e < 3 ⟹ log 3 > ... hmm whatever — both directions exist as _gt_d9/_lt_d9. For 9/4 ≤ e: 9/4 = 2.25 ≤ 2.7182818283 ≤ e via exp_one_gt_d9. Then log(9/4) ≤ log e = 1: Real.log_le_log (0 < 9/4) (9/4 ≤ exp 1) gives log(9/4) ≤ log (exp 1) = 1 (Real.log_exp 1 hmm Real.exp_log... `Real.log_exp : log (exp x) = x` ✓).
(iii) div: M96(ℝ) ≤ log((9/4)|t|²)/log(33/32) ≤ (1+2L)/(1/33) = 33(1+2L): div_le_div (num ≤ 1+2L) (1/33 ≤ log(33/32)) (1/33 > 0) (0 ≤ num): num = log((9/4)|t|²) ≥ 0 ⟸ (9/4)|t|² ≥ 1 ⟸ |t|² ≥ 100 ≥ 4/9 ⟸ |t| ≥ 10 ✓ (Real.log_nonneg: 1 ≤ x → 0 ≤ log x ✓). (1+2L)/(1/33) = 33+66L by field_simp/ring. So J-bound: (M96:ℝ) ≤ 33+66L.
(iv) k+1 ≤ J+1: k ≤ M96 (nat ≤, cast) ⟹ (k:ℝ)+1 ≤ J+1.
(v) 50(k+1) ≤ 4150L: 50(J+1) = 50(34+66L) = 1700+3300L ≤ 4150L ⟺ 1700 ≤ 850L ⟺ L ≥ 2 ✓. nlinarith.
(vi) log(50(k+1)) ≤ L+8: 50(k+1) > 0; 50(k+1) ≤ 4150L; log(4150L) = log 4150 + log L (log_mul, L > 0); log 4150 ≤ 9: 4150 ≤ exp 9: exp 9 = (exp 1)^9 (Real.exp_nat_mul: exp (n*x) = (exp x)^n — exp 9 = exp (9*1); 9*1: norm_num; = (exp 1)^9 ≥ 2.7182818283^9 ≥ 4150: norm_num computes 2.7182818283^9 — big rational but norm_num should… 2.7182818283^9: numerator ~2.7e9...^9 — the integers involved: 27182818283^9 ≈ 10^94. norm_num can do this but might be slow. Alternative: 4150 ≤ 3^9 = 19683? No wait — need exp 9 ≥ 4150, and exp 9 ≥ (2.7)^9? 2.7^9 = 3325.3 < 4150 ✗. 2.71^9 = 7883.8 ≥ 4150 ✓ — 2.71^9: 271^9 ≈ 7.8e21 — norm_num fine. Use exp_one_gt_d9 (2.7182818283 < e): then e^9 > 2.7182818283^9 — even bigger rational (11-digit). Hmm. To be safe, derive a coarser decimal: e ≥ 2.71 via exp_one_gt_d9 (2.718... > 2.71 by norm_num) — then e^9 ≥ 2.71^9 via pow_le_pow_left₀ (2.71 ≥ 0). 2.71^9 as rational (271/100)^9 — norm_num: (271/100)^9 = 271^9/100^9; 271^9 = ? 271² = 73441; 271³ = 19,902,511; 271⁴ = 5.393e9; 271⁹ = 271·(271⁴)² = 271·2.909e19 = 7.883e21. 100^9 = 1e18. Ratio ≈ 7883.7 ≥ 4150 ✓ norm_num can verify. OK.
Then log(4150L) ≤ 9 + log L ≤ 9 + (L − 1) = L + 8 — log L ≤ L−1: Real.log_le_sub_one_of_pos (L > 0): log L ≤ L − 1 ✓.
(vii) M_bound ≤ 420L²: M_bound = log Bbound ≤ (1+2L) + J·(L+8): need J ≥ 0 (33+66L, L ≥ 2 ✓) and log(50(k+1)) ≤ L+8, M_c ≤ J... M_c·log(50(k+1)) ≤ J·(L+8) via mul_le_mul (M_c ≤ J) (log ≤ L+8) (log ≥ 0) (J ≥ 0) ✓. Then 1+2L+(33+66L)(L+8) ≤ 420L²: expand: 1+2L+33L+264+66L²+528L = 66L²+563L+265 ≤ 420L² ⟺ 354L²−563L−265 ≥ 0, at L ≥ 2. nlinarith [hL: 2 ≤ L]: witness (L−2)(354L+131) + (14L−3)... earlier computed = 354L²−577L−262+(14L−3) hmm: (L−2)(354L+131) = 354L²+131L−708L−262 = 354L²−577L−262. Target minus this: (354L²−563L−265) − (354L²−577L−262) = 14L−3 ≥ 0 since L ≥ 2 ⟹ 14·2−3 = 25 ≥ 0 ✓. So target = (L−2)(354L+131) + (14L−3) ≥ 0 + 25 > 0. nlinarith [hL] with products (L−2)(354L+131) — nlinarith multiplies hypotheses pairwise: needs (L−2) ≥ 0 and (354L+131) ≥ 0: nlinarith [hL, mul_nonneg (sub_nonneg.mpr hL) (by linarith : (0:ℝ) ≤ 354*L+131)]... provide the product as a hint. ✓
(viii) BC factor ≤ 450: 16·M·r_c²/(r_c−3/5)³ ≤ 450·M ⟸ r_c² ≤ (24/25)² (r_c ≥ 0, ≤ 24/25, pow_le_pow_left₀), (r_c−3/5)³ ≥ (8/25)³ (r_c−3/5 ≥ 8/25 > 0, pow_le_pow_left₀), M > 0: div_le_div (16·M·r_c² ≤ 16·M·(24/25)²: mul_le_mul_of_nonneg_left (pow) (16M ≥ 0)) ((8/25)³ ≤ (r_c−3/5)³) (pos (8/25)³) (nonneg 16Mr_c²) : gives 16Mr_c²/(r_c−3/5)³ ≤ 16M(24/25)²/(8/25)³ = 450M: norm_num: 16·(24/25)²/(8/25)³ = 450 ✓ then mul_assoc massaging.
(ix) final: 180·M_bound + J ≤ 100000L²: 180·420L² = 75600L²; J ≤ 42L² (33+66L ≤ 42L² ⟺ 42L²−66L−33 ≥ 0 at L ≥ 2: = (L−2)(42L+16.5)+1.5L... check: (L−2)(42L+17) = 42L²+17L−84L−34 = 42L²−67L−34; target minus = (42L²−66L−33)−(42L²−67L−34) = L+1 ≥ 0 ✓). So 75600L²+42L² = 75642L² ≤ 100000L² (L² ≥ 0: mul_le_mul_of_nonneg_right) ✓.
Alright. Also `abs_im_le_norm` : |z.im| ≤ ‖z‖ ✓ used already in file.
One more consideration: `nearZeros t` def + API:
```lean
def nearZeros (t : ℝ) : Finset ℂ := (zeroDiscFinset t).filter fun ρ => |ρ.im - t| < 1
theorem mem_nearZeros {t : ℝ} {ρ : ℂ} : ρ ∈ nearZeros t ↔ ρ ∈ zeroDiscFinset t ∧ |ρ.im − t| < 1 := Finset.mem_filter
```
✓ trivial.
And the application: ρ ∈ nearZeros t ⟹ ρ ∈ ZW.image aff: needs ‖ρ − s₀‖ ≤ √5 etc. Steps: ρ ∈ zeroDiscFinset ⟹ zeroDisc_isNontrivial ⟹ re ∈ (0,1) (IsNontrivialZero fields: ⟨ζ ρ = 0, 0 < re, re < 1⟩? check IsNontrivialZero def — from zeroDisc_isNontrivial's construction: exact ⟨h2, hpos, hnot1⟩ — three components: ζ ρ = 0, 0 < ρ.re, ρ.re < 1 ✓). ‖ρ − s₀‖² = (ρ.re−2)² + (ρ.im−t)²: compute via normSq: Complex.normSq (ρ − s₀) = (ρ.re−2)² + (ρ.im−t)² (sub_re, s₀ re = 2, im = t: discCenter t = 2 + t·I: add_re, mul_re... simp [discCenter]). Then ≤ 4+1 = 5: |ρ.re−2| ≤ 2 ⟸ ρ.re ∈ (0,1); (ρ.re−2)² ≤ 4 (sq_le_sq₀... or nlinarith with abs bounds); (ρ.im−t)² ≤ 1 ⟸ |ρ.im−t| < 1 (sq_le... abs_lt ⟹ −1 < .. < 1 ⟹ sq ≤ 1: nlinarith or sq_le_one_of_abs... use nlinarith [abs_lt.mp h]). Then ‖ρ−s₀‖ = √(normSq) ≤ √5: Complex.norm_eq_sqrt_normSq? hmm — `Complex.normSq_eq_norm_sq : normSq z = ‖z‖ ^ 2` so ‖z‖² ≤ 5 ⟹ ‖z‖ ≤ √5 via (sq_le_sq₀ nonneg (√5 ≥ 0)).mp: ‖z‖² ≤ (√5)² = 5 (Real.sq_sqrt 5 ≥ 0) ⟹ ‖z‖ ≤ √5. ✓ Then √5 ≤ 23/10: Real.sqrt_le_iff or sq: (√5)² = 5 ≤ (23/10)² = 529/100 ✓ norm_num; via Real.sqrt_le_left? `Real.sqrt_le_iff : √x ≤ y ↔ 0 ≤ y ∧ x ≤ y ^ 2`? I think `Real.sqrt_le_iff : Real.sqrt x ≤ y ↔ 0 ≤ y ∧ x ≤ y^2` exists (with hy?) — there are several variants: Real.sqrt_le_iff (hy : 0 ≤ y)? no wait. `Real.sqrt_le_iff : √x ≤ y ↔ 0 ≤ y ∧ x ≤ y ^ 2`?? Hmm, in recent Mathlib: `Real.sqrt_le_iff : √x ≤ y ↔ 0 ≤ y ∧ x ≤ y ^ 2` — I'll try; fallback `Real.sqrt_le_sqrt` + show √5 = ... no. Or: sq_le_sq₀: √5 ≤ 23/10 ⟺ (√5)² ≤ (23/10)² via (sq_le_sq₀ (Real.sqrt_nonneg) (by norm_num)).mpr? hmm sq_le_sq₀ : 0 ≤ a → 0 ≤ b → (a² ≤ b² ↔ a ≤ b)? `sq_le_sq₀ (ha : 0 ≤ a) (hb : 0 ≤ b) : a ^ 2 ≤ b ^ 2 ↔ a ≤ b` ✓ (used already in LiContour). Then 5 ≤ 529/100 by Real.sq_sqrt + norm_num. ✓
Then w_ρ := (2/5)·(ρ − s₀): aff w_ρ = ρ (ring ✓), ‖w_ρ‖ = (2/5)‖ρ−s₀‖ ≤ (2/5)(23/10) = 23/25 ≤ rC ✓. F w_ρ = ζ(ρ)/ζ(s₀) = 0 ✓ (num zero). So w_ρ ∈ SetOfZeros (rC) F ⟹ w_ρ ∈ ZW. ρ = aff w_ρ ∈ image: Finset.mem_image.mpr ⟨w_ρ, mem, aff w_ρ = ρ⟩ ✓.
Hmm wait — nearZeros ⊆ image requires ht only through... the gap/B machinery? No: nearZeros ⊆ ZW.image aff needs: ζ(ρ) = 0 (from zeroDiscFinset ✓ no ht), ζ(s₀) ≠ 0 (F w = 0 conclusion — zeta_lower_bound_two, no ht ✓), ‖w_ρ‖ ≤ rC — via √5 ≤ 23/10... wait rC ≥ 23/25 and ‖w_ρ‖ ≤ 23/25 ✓ — but rC's lower bound 23/25 comes from collRadius spec which needs... exists_collection_radius ht — hmm does the gap construction need ht? The gap exists for ANY t (combinatorial); ht only entered via... exists_avoiding_midpoint is unconditional; S/card fine. So exists_collection_radius doesn't need ht! Only the Jensen-related numeric bounds (card ≤ J etc.) need ht. But keeping ht uniformly is simpler — the final theorem has ht anyway. Fine, keep ht in the def bundle.
Wait, actually — there IS a subtlety: scaledZeroFinset t r hr uses scaledZeta_zeros_finite which needs... nothing (proved for all t ✓). Good.
But — one thing: ZW and the gap lemmas need rC > 0? For ZW ⊆ ZW96 need rC ≤ 24/25 ✓. Fine.
Also B's analyticity needs rC < R' < 1 with R' := (1+rC)/2: rC < (1+rC)/2 ⟺ rC < 1 ✓; (1+rC)/2 < 1 ✓.
Alright — also the deriv identity needs F's differentiability at w₀: from scaledZeta_analytic ht (AnalyticOnNhd on closedBall(0,1)): w₀ ∈ closedBall(0, 3/5) ⊆ closedBall(0,1) ⟹ AnalyticAt F w₀ ⟹ .differentiableAt ✓.
And logDeriv_div for F/P at w₀ needs DifferentiableAt F w₀ ✓ and DifferentiableAt P w₀ (analyticAt_finset_prod_sub_pow .differentiableAt ✓).
The EventuallyEq for B = F/P near w₀:
```lean
have hB_eq : B =ᶠ[𝓝 w₀] fun w => scaledZeta t w / P w
```
proof: w₀ ∉ SetOfZeros rC F (F w₀ ≠ 0) ⟹ complement open? SetOfZeros rC F = {‖ρ‖ ≤ rC ∧ F ρ = 0} — is it closed? F restricted to closedBall(0,1) is continuous (analytic), so {F = 0} ∩ closedBall(0, rC) is closed: isClosed (closedBall) ∩ (preimage of {0} under continuous-on...). Simpler: SetOfZeros rC F ⊆ ZW-carrier?? No — SetOfZeros rC F = ZW.carrier as SETS (ZW := finite.toFinset, mem ⟺ ∈). ZW.carrier = ↑ZW is closed (Finset carrier finite ⟹ closed: `Finite.isClosed` with (ZW : Set ℂ) finite — `Finset.finite_toSet` then `.isClosed` ✓). And SetOfZeros rC F = ↑ZW: ext: x ∈ SetOfZeros ⟺ x ∈ ZW (mem_scaledZeroFinset) ⟺ x ∈ ↑ZW (Finset.mem_coe). ✓ So complement of SetOfZeros = complement of ↑ZW is open, contains w₀: gives ∀ᶠ z, z ∉ SetOfZeros rC F (isOpen_compl.mem_nhds... `IsOpen.mem_nhds : IsOpen s → a ∈ s → s ∈ 𝓝 a` then eventually). Combined with F z ≠ 0 eventually (F.continuousAt w₀ .eventually_ne (F w₀ ≠ 0)). For z with both: Cf rC F z = F z / P z — by the else-characterization lemma (Cf_eq_div_prod) ✓. So EventuallyEq via Filter.Eventually.of_forall... wait need eventually: filter_upwards [compl_eventually, F_eventually_ne] with z hz1 hz2; exact Cf_eq_div_prod rC_le_1 hz1. ✓
where P := fun w => ∏ ρ ∈ ZW, (w − ρ) ^ analyticOrderNatAt (scaledZeta t) ρ.
Then deriv J_B w₀ = deriv B w₀ / B w₀ (hJderiv w₀ mem) — and deriv B w₀ = deriv (F/P) w₀ (hB_eq.deriv), B w₀ = (F/P) w₀ (hB_eq.eq_of_nhds — check name: `Filter.EventuallyEq.eq_of_nhds : f =ᶠ[𝓝 x] g → f x = g x`? I believe it's `Filter.EventuallyEq.eq_of_nhds` ✓).
deriv (F/P) w₀ / (F/P) w₀ = logDeriv (fun w => F w / P w) w₀ (logDeriv def: logDeriv f x = deriv f x / f x — `logDeriv_apply`? logDeriv f = fun x => deriv f x / f x by def — rfl after `rw [logDeriv_apply]`? The def: `logDeriv f := fun x ↦ deriv f x / f x` hmm might be `deriv f x / f x` directly — `logDeriv_apply : logDeriv f x = deriv f x / f x` simp lemma ✓).
So deriv J_B w₀ = logDeriv (F/P) w₀ = logDeriv F w₀ − logDeriv P w₀ (logDeriv_div w₀ (F w₀ ≠ 0) (P w₀ ≠ 0) (diffF) (diffP)) = (5/2)·logDeriv ζ s − Σ m/(w₀−·).
logDeriv F w₀: F = scaledZeta t = fun w => ζ(aff w)/c. logDeriv_div w₀ (g w₀ ≠ 0: ζ(s) ≠ 0 ✓) (c ≠ 0 ✓) (diff g: comp) (diff const): = logDeriv (ζ∘aff) w₀ − logDeriv (fun _ => c) w₀. logDeriv of const: deriv const = 0 ⟹ logDeriv = 0/c = 0: `logDeriv_const`? If exists: simp. Else: rw [logDeriv_apply, deriv_const, zero_div, sub_zero]. Then logDeriv (ζ ∘ aff) w₀: logDeriv_comp (diff ζ at aff w₀) (diff aff): logDeriv ζ (aff w₀) * deriv aff w₀. Hmm — but careful: (fun w => riemannZeta (aff w)) vs (riemannZeta ∘ aff): logDeriv_comp is stated for f ∘ g; (fun w => ζ (aff w)) is defeq to ζ ∘ aff — may need `show` conversion. deriv aff w₀ = 5/2: aff w = s₀ + (5/2)*w: deriv_const_add + deriv_const_mul (c) (hd : DifferentiableAt _ id) hmm `deriv_const_mul (c : 𝕜) (hd : DifferentiableAt 𝕜 f x) : deriv (fun x => c * f x) x = c * deriv f x` ✓ + deriv_id'' (deriv id x = 1: `deriv_id'`? Actually `deriv_id''`? I recall `deriv_id' : deriv id = fun _ => 1`... hmm deriv_id' might be `deriv id x = 1`? There are `deriv_id'` and `deriv_id''` variants. Fallback: (hasDerivAt_id x).deriv : deriv id x = 1 via HasDerivAt.deriv (hasDerivAt_id'?) — `hasDerivAt_id : HasDerivAt id 1 x`? hmm `hasDerivAt_id (x) : HasDerivAt id 1 x` hmm maybe `hasDerivAt_id'`... I know `HasDerivAt.deriv : HasDerivAt f f' x → deriv f x = f'` ✓. And (hasDerivAt_id w₀) — the name `hasDerivAt_id` exists? `hasDerivAt_id'`? Both exist in some form; simp can close `deriv (fun w : ℂ => w) w₀ = 1`? `deriv_id'` simp. I'll use simp [deriv_const_add, deriv_const_mul, deriv_id'']-style and fix at build.)
OK. This is a huge but well-understood build. Let me also decide the ordering: lemmas first, main theorem last. Also, since LiDisc.lean already ends with `end NguyenRH1 / end`, I'll append before those.
Let me also double-check `Finset.sum_image` signature: `Finset.sum_image (h : ∀ x ∈ s, ∀ y ∈ s, f x = f y → g x = g y)` : ∑ x ∈ s.image f, g x = ∑ x ∈ s, g (f x) — the hypothesis form is InjOn-style. journal-011 gotcha: "Finset.sum_image takes Set.InjOn, map = g, summand = f" — hmm that suggests this Mathlib version's sum_image takes Set.InjOn. Fine, provide Set.InjOn.
Check: does `Finset.sum_image` in current Mathlib have signature `(h : Set.InjOn f s) : ∑ x ∈ s.image f, g x = ∑ x ∈ s, g (f x)`? In recent Mathlib yes: `Finset.sum_image (h : Set.InjOn f s) : (∑ x ∈ s.image f, g x) = ∑ x ∈ s, g (f x)`. I'll adapt.
Now — one more design point for the fold: the M_c (exponent in Bbound) is Σ over ZW of analyticOrderNatAt F — a natural. In the sphere bound I'll write Bbound := (9/4)*|t|^2 * (50*(k+1))^(M_c) with M_c := ∑ ρ ∈ ZW, analyticOrderNatAt (scaledZeta t) ρ (ℕ). Then log: log(Bbound) = log(9/4) + 2L + (M_c : ℝ)·log(50(k+1)) (Real.log_pow gives ↑(M_c) * log ✓).
k := (scaledZeroFinset t (24/25) _).card. But note: scaledZeroFinset t (24/25) _ has a PROOF argument (hr : 24/25 ≤ 1) — proof irrelevance makes card independent ✓ but definitional equalities across different proof terms are fine (Subsingleton elimination — proof args are irrelevant definitionally for Prop). OK.
Wait, one issue — `scaledZeroFinset t r (hr : r ≤ 1)` with hr a proof: `scaledZeroFinset t (24/25) (by norm_num)` and inside Cf-unfolds I get `finite_zeros_mono.toFinset` where the proof is the dite-introduced one. My Cf_eq lemma will use toFinset_inj.mpr rfl to equate. Then the product over my finset. ✓
Actually hold on, let me reconsider: rather than a proof-carrying def, maybe define scaledZeroFinset via Set.Finite.toFinset of a direct finiteness proof without the r ≤ 1 hypothesis... The issue: SetOfZeros r F for r > 1 is NOT known finite (analyticity only on closedBall(0,1)). Keep the hypothesis. All my uses have r ≤ 24/25 or rC ≤ 24/25. OK.
Also `Finset.card_image_le` for card S ≤ card ZW96 — image under (fun w => (5/2)*‖w‖): card_image_le : (s.image f).card ≤ s.card ✓.
Now write the code. I'll write it in chunks and compile iteratively. Given the size, let me write §5 (norm_scaledZeta_le through the gap machinery) first, compile, then §6 (Cf char + B lemmas), compile, then §7 (main theorem).
Actually, let me reconsider ONE more time whether there's a shortcut for the whole B-nonvanishing/bound complex... The alternative "blended" approach: skip Cf entirely and use BlaschkeB?? No — BlaschkeB includes the Blaschke factors whose log-deriv is messier. The Cf approach is the Davenport one per design. Proceed.
Also — STATE.md says "g := ζ/∏(s−ρₖ)^{mₖ}" and my approach uses Cf r_c F in scaled coords. deriv log of Cf at w₀ = (5/2)logDeriv ζ(s) − Σ m/(w₀−ρ). The unscaled g's log deriv at s would be logDeriv ζ s − Σ m/(s−ρ). Consistent ✓.
Let me now also double-check the definition `SetOfZeros r f = {ρ | ‖ρ‖ ≤ r ∧ f ρ = 0}` ✓ (line 194). And `finiteSetOfZeros_mono` needs r < 1 — for ZW96 I use r = 24/25 < 1 ✓ in scaledZeta_jensen_count's statement. For my scaledZeroFinset with hr : r ≤ 1 — defined via subset of SetOfZeros 1 — fine. But for consistency with the Jensen finset equality (step 7), scaledZeroFinset t (24/25) (by norm_num) vs (finiteSetOfZeros_mono (by norm_num : (24/25:ℝ) < 1) scaledZeta_zeros_finite).toFinset — toFinset_inj.mpr rfl where the SETS: my subset-derived finite's underlying set: SetOfZeros (24/25) F (the .subset proof: `scaledZeta_zeros_finite.subset (fun w hw => ⟨hw.1.trans hr, hw.2⟩)` : (SetOfZeros (24/25) F).Finite — hmm Set.Finite.subset (hs : s.Finite) (hts : t ⊆ s) : t.Finite — so `.subset` on scaledZeta_zeros_finite : (SetOfZeros 1 F).Finite with subset proof SetOfZeros (24/25) ⊆ SetOfZeros 1 gives (SetOfZeros (24/25) F).Finite ✓ set is right. rfl : SetOfZeros (24/25) F = SetOfZeros (24/25) F ✓. toFinset_inj : hs.toFinset = ht.toFinset ↔ s = t — with s = t = SetOfZeros (24/25) F: mpr rfl : hs.toFinset = ht.toFinset ✓.
Great. Now the scaledZeta_jensen_count statement: the sum is over `(finiteSetOfZeros_mono (f := scaledZeta t) (r := 24 / 25) (by norm_num) (scaledZeta_zeros_finite)).toFinset` — note the implicit (r_lt_one : 24/25 < 1)? finiteSetOfZeros_mono {r} {f} (r_lt_one : r < 1) (finiteZeros : (SetOfZeros 1 f).Finite) : (SetOfZeros r f).Finite. In the committed code: `finiteSetOfZeros_mono (f := scaledZeta t) (r := 24 / 25) (by norm_num) (scaledZeta_zeros_finite)` ✓.
So Jensen-finset equality:
```lean
theorem scaledZeroFinset_24_25_eq (t : ℝ) :
scaledZeroFinset t (24/25) (by norm_num) =
(finiteSetOfZeros_mono (f := scaledZeta t) (r := 24/25) (by norm_num)
scaledZeta_zeros_finite).toFinset :=
Set.Finite.toFinset_inj.mpr rfl
```
✓ (probably needs the def unfolded — toFinset_inj.mpr rfl : hs.toFinset = ht.toFinset where hs, ht are the two finiteness proofs — the LHS def: (scaledZeta_zeros_finite.subset ...).toFinset — matches scaledZeroFinset t (24/25) _ by rfl of the def ✓ hopefully direct).
Now sum monotonicity: for r ≤ 24/25: scaledZeroFinset t r hr ⊆ scaledZeroFinset t (24/25) _ as finsets: Finset.subset via mem ⟹ mem: w ∈ ZW(r) ⟹ ‖w‖ ≤ r ≤ 24/25 ∧ F w = 0 ⟹ w ∈ ZW96 ✓. `Finset.sum_le_sum_of_subset_of_nonneg (hsub : s ⊆ t) (hf : ∀ i ∈ t, i ∉ s → 0 ≤ f i)` : ∑ i in s, f i ≤ ∑ i in t, f i ✓ — orders nonneg (Nat.cast_nonneg or zero_le for ℕ: the sum is in ℕ? Σ of analyticOrderNatAt is ℕ — Jensen RHS is ℝ: committed statement: `∑ ρ ∈ ..., analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log (...) / Real.log (...)` — so ℕ ≤ ℝ via Nat.cast_le? The ≤ there is... LHS : ℕ, RHS : ℝ — hmm, is there a coercion? In the committed line 352-355: `∑ ρ ∈ (...).toFinset, analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32)` — for this to typecheck, the sum must be coerced: there's likely a Nat.cast inserted (ℕ literal ≤ ℝ ⟹ Lean inserts ↑). And ZerosBound's conclusion: `∑ ... analyticOrderNatAt f ρ ≤ 1 / Real.log (R/r) * Real.log B` — same coercion. So the comparison is in ℝ with Nat.cast. ✓ So sum_le_sum_of_subset in ℕ then cast, or directly in ℝ with cast sums. I'll do ℕ-side: (Σ_{ZW} order : ℕ) ≤ (Σ_{ZW96} order : ℕ) then Nat.cast_le.trans jensen. Finset.sum_le_sum_of_subset_of_nonneg in ℕ: hf : 0 ≤ order ✓ (zero_le). ✓
Card ≤ sum: (ZW.card : ℕ) = Σ_{w∈ZW} 1 ≤ Σ order (Finset.sum_le_sum: each 1 ≤ order — needs the one_le lemma with ht and ‖w‖ ≤ r ≤ 1 ✓). Then (k:ℝ) ≤ (Σ96 : ℝ) ≤ J.
Let me now write all the code. I'll write it in one big chunk but compile in stages — actually, given the size, let me write §A–§C (through exists_collection_radius) first.
Note the file's existing header imports: `import Mathlib / import Zeta23.FromPNTPlus.StrongPNTPrefix / import NguyenRH1.LiRBound`. Need to add `import NguyenRH1.LiContour` (for exists_avoiding_midpoint + ZeroCountProp not needed... just exists_avoiding_midpoint). LiContour imports Zeta23.Statement (zeroMult) ✓ and LiSides etc. And zeroMult comes via Zeta23.Statement — LiContour re-exports? Import chain: LiContour imports Zeta23.Statement — importing LiContour gives access to its imports' decls ✓.
Also `logDeriv` needs... Mathlib's LogDeriv is in Mathlib.Analysis.Calculus.LogDeriv — included in `import Mathlib` ✓.
Write chunk 1 now: helpers + gap.
```lean
/-! ## 5. The (9/4)|t|² bound as a standalone lemma, order helpers -/
/-- The ii′-5b disc bound transferred to the scaled function (extracted
from the Jensen-count proof for reuse in the |g| outer-circle bound). -/
theorem norm_scaledZeta_le {t : ℝ} (ht : 10 ≤ |t|) {z : ℂ} (hz : ‖z‖ ≤ 99 / 100) :
‖scaledZeta t z‖ ≤ (9 / 4) * |t| ^ 2 := by
... (copy of hB body)
```
Then order helpers:
```lean
theorem scaledZeta_order_ne_top {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ} (hw : ‖w‖ ≤ 1) :
analyticOrderAt (scaledZeta t) w ≠ ⊤ := by
have hfAn := scaledZeta_analytic ht
have h0mem : (0 : ℂ) ∈ Metric.closedBall 0 1 := by
rw [Metric.mem_closedBall, dist_zero_right, norm_zero]; norm_num
have hwmem : w ∈ Metric.closedBall 0 1 := by
rwa [Metric.mem_closedBall, dist_zero_right]
have hord0 : analyticOrderAt (scaledZeta t) 0 = 0 := by
rw [analyticOrderAt_eq_zero]
exact Or.inr (Or.inr ...) -- hmm: analyticOrderAt_eq_zero : order = 0 ↔ ¬AnalyticAt ∨ f z₀ ≠ 0
```
analyticOrderAt_eq_zero : analyticOrderAt f z₀ = 0 ↔ ¬ AnalyticAt 𝕜 f z₀ ∨ f z₀ ≠ 0. F 0 = 1 ≠ 0: Or.inr (by rw [scaledZeta_zero]; exact one_ne_zero). Then:
```lean
exact hfAn.analyticOrderAt_ne_top_of_isPreconnected Metric.isPreconnected_closedBall h0mem hwmem (by rw [hord0]; exact ENat.top_pos ... )
```
ZeroFactorization used: `(lt_top_iff_ne_top.mp ?_); rw[orderAtZeroIsZero]; exact ENat.top_pos` — the arg is `analyticOrderAt f 0 < ⊤`... signature: AnalyticOnNhd.analyticOrderAt_ne_top_of_isPreconnected (hf : AnalyticOnNhd ℂ f s) (hs : IsPreconnected s) (hz₀ : z₀ ∈ s) (hz : z ∈ s) (h : analyticOrderAt f z₀ < ⊤) : analyticOrderAt f z ≠ ⊤. In ZeroFactorization they passed `(lt_top_iff_ne_top.mp ?_)` — hmm that's converting ne_top to lt_top... wait: they want to produce the hypothesis `analyticOrderAt f 0 < ⊤`: `lt_top_iff_ne_top.mp ?_` where ?_ : analyticOrderAt f 0 ≠ ⊤ — and they proved ≠ ⊤ by rw[orderAtZeroIsZero]; ENat.top_pos?? Hmm ENat.top_pos : 0 < ⊤... that's lt not ne. Confusing; probably: after rw [orderAtZeroIsZero], goal analyticOrderAt... wait they rewrote the GOAL (which was inside lt_top_iff_ne_top.mp ?_ so ?_ : analyticOrderAt f 0 ≠ ⊤)... rw turns it into (0 : ℕ∞) ≠ ⊤, and `ENat.top_pos`?? that doesn't match. Probably they used `ENat.top_pos` loosely and it elaborated via zero_ne_top or something. Let me just use: after rw [hord0]: goal (0:ℕ∞) ≠ ⊤ → `ENat.zero_ne_top`? hmm that's for... In ENat, (0 : ℕ∞) ≠ ⊤: `ENat.zero_ne_top`? exists? There's `ENat.natCast_ne_top`, `ENat.top_ne_zero`... For 0 ≠ ⊤: `ne_of_lt (ENat.top_pos ...)`? whatever — `ENat.zero_ne_top` might not exist; use `ENat.top_ne_zero.symm`? Hmm: `ENat.top_ne_zero : ⊤ ≠ 0`? then .symm? ≠ is symmetric: `Ne.symm`. Or `by simp`? At build time: try `exact ENat.natCast_ne_top 0` after showing (0:ℕ∞) = ((0:ℕ):ℕ∞) hmm. Simplest robust: `intro hcon; rw [hord0] at hcon; exact ENat.top_ne_zero ...`. I'll write `by rw [hord0]; exact fun h => ENat.zero_ne_top h`... let me check: does ENat.zero_ne_top exist? Hmm. There's `ENat.top_ne_zero : (⊤ : ℕ∞) ≠ 0`?? I don't remember. Safe: `Ne.symm ENat.top_ne_zero`? Ugh. Simplest bulletproof: after rw [hord0], `simp` should close (0 : ℕ∞) ≠ ⊤. Or `decide`? ℕ∞ has DecidableEq? Classical. `exact WithTop.zero_ne_top`? ℕ∞ = WithTop ℕ! `WithTop.zero_ne_top : (0 : WithTop ℕ) ≠ ⊤`? I believe `WithTop.zero_ne_top` exists ✓ (needs Zero). And ℕ∞ is defeq WithTop ℕ. ZeroFactorization actually used ENat.top_pos... whatever, I'll try WithTop.zero_ne_top first, fallback simp.
Then one_le:
```lean
theorem one_le_analyticOrderNatAt_scaledZeta {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : ‖w‖ ≤ 1) (hw0 : scaledZeta t w = 0) :
1 ≤ analyticOrderNatAt (scaledZeta t) w := by
have htop := scaledZeta_order_ne_top ht hw
have hne : analyticOrderAt (scaledZeta t) w ≠ 0 := by
have han : AnalyticAt ℂ (scaledZeta t) w :=
scaledZeta_analytic ht w (by rwa [Metric.mem_closedBall, dist_zero_right])
rwa [han.analyticOrderAt_ne_zero]
-- analyticOrderNatAt = (analyticOrderAt).toNat, positive
have h := ENat.toNat_pos hne htop
-- analyticOrderNatAt f w = (analyticOrderAt f w).toNat by def
exact h
```
with analyticOrderNatAt def: `analyticOrderNatAt f z₀ = (analyticOrderAt f z₀).toNat` — is it def? journal-023 says "by DEF". So the goal 1 ≤ analyticOrderNatAt F w unfolds to 1 ≤ (analyticOrderAt F w).toNat — and h : 0 < (analyticOrderAt F w).toNat ⟹ 1 ≤ it (Nat: 0 < n ↔ 1 ≤ n — same in ℕ). `exact h` might work (0 < n is 1 ≤ n definitionally in ℕ? 0 < n unfolds to 0+1 ≤ n = 1 ≤ n ✓ Nat.lt is defeq succ le). ✓
§B finsets:
```lean
/-- Zeros of the scaled function with norm ≤ r, as a finset (r ≤ 1). -/
def scaledZeroFinset (t : ℝ) (r : ℝ) (hr : r ≤ 1) : Finset ℂ :=
(scaledZeta_zeros_finite.subset (fun w hw => ⟨hw.1.trans hr, hw.2⟩)).toFinset
theorem mem_scaledZeroFinset {t : ℝ} {r : ℝ} {hr : r ≤ 1} {w : ℂ} :
w ∈ scaledZeroFinset t r hr ↔ ‖w‖ ≤ r ∧ scaledZeta t w = 0 := by
unfold scaledZeroFinset
rw [Set.Finite.mem_toFinset]
-- goal: w ∈ SetOfZeros r (scaledZeta t) ↔ ...: SetOfZeros is a setOf: mem ⟺ ∧: rfl?
exact Iff.rfl -- maybe
```
SetOfZeros r f = {ρ | ‖ρ‖ ≤ r ∧ f ρ = 0} — membership defeq ✓ (maybe needs `Set.mem_setOf_eq`... it's a def with setOf; Iff.rfl or `exact id`).
Wait — `Set.Finite.subset` signature: `Set.Finite.subset (hs : s.Finite) (hts : t ⊆ s) : t.Finite`. So `scaledZeta_zeros_finite.subset (hsub)` where hsub : SetOfZeros r F ⊆ SetOfZeros 1 F: `fun w hw => ⟨hw.1.trans hr, hw.2⟩` — hw : w ∈ SetOfZeros r F i.e. ‖w‖ ≤ r ∧ F w = 0; produces ‖w‖ ≤ 1 ∧ F w = 0 ✓. The resulting .Finite : (SetOfZeros r F).Finite ✓. toFinset membership ⟺ ∈ SetOfZeros r F ✓.
Hmm — hw.1 : ‖w‖ ≤ r — from hw : w ∈ {ρ | ‖ρ‖ ≤ r ∧ ...}, hw is the ∧ directly (setOf membership is the predicate application ✓).
§C gap:
```lean
/-- The distance finset for the gap: (5/2)-scaled norms of the 24/25-zeros. -/
def zeroNormFinset (t : ℝ) : Finset ℝ :=
(scaledZeroFinset t (24/25) (by norm_num)).image fun w => (5/2) * ‖w‖
```
exists_collection_radius:
```lean
theorem exists_collection_radius {t : ℝ} (ht : 10 ≤ |t|) :
∃ R_c : ℝ, 23 / 10 ≤ R_c ∧ R_c ≤ 24 / 10 ∧
∀ w ∈ scaledZeroFinset t (24/25) (by norm_num),
1 / (20 * (((scaledZeroFinset t (24/25) (by norm_num)).card : ℝ) + 1)) ≤
|(5 / 2) * ‖w‖ - R_c| := by
classical
set Z96 := scaledZeroFinset t (24/25) (by norm_num : (24/25:ℝ) ≤ 1) with hZ96
set S := Z96.image fun w => (5/2) * ‖w‖ with hS
set S10 := S.image fun x => x * 10 with hS10
have hcard : S10.card ≤ Z96.card := (Finset.card_image_le).trans Finset.card_image_le
obtain ⟨T, hT1, hT2, hT3⟩ := exists_avoiding_midpoint 23 S10 hcard
refine ⟨T / 10, by linarith, by linarith, fun w hw => ?_⟩
have hwS : (5/2) * ‖w‖ ∈ S := Finset.mem_image.mpr ⟨w, hw, rfl⟩
have hwS10 : (5/2) * ‖w‖ * 10 ∈ S10 := Finset.mem_image.mpr ⟨_, hwS, rfl⟩
have h := hT3 ((5/2) * ‖w‖ * 10) hwS10
-- |25‖w‖ − T| ≥ 1/(2(k+1)) ⟹ |(5/2)‖w‖ − T/10| ≥ 1/(20(k+1))
have hscale : |(5/2) * ‖w‖ * 10 - T| = 10 * |(5/2) * ‖w‖ - T / 10| := by
rw [← abs_mul]
congr 1
ring
rw [hscale] at h
-- h : 1/(2(k+1)) ≤ 10 * |(5/2)‖w‖ − T/10|
...
```
hmm the final: 1/(2(k+1)) ≤ 10·X ⟹ 1/(20(k+1)) ≤ X: div/linarith with positivity of (k:ℝ)+1: h : 1/(2*(k+1)) ≤ 10*X; want 1/(20*(k+1)) ≤ X. 1/(20(k+1)) = (1/(2(k+1)))/10 hmm: 20(k+1) = 10·(2(k+1)): 1/(20(k+1)) = (1/10)·(1/(2(k+1)))... field_simp or: have hpos : (0:ℝ) < 2*(k+1); rw [div_le_iff] ... simplest:
```
have hpos : (0:ℝ) < 20 * ((k : ℝ) + 1) := by positivity -- needs k+1 > 0: k ≥ 0 ✓ positivity handles cast+add?
have hpos2 : (0:ℝ) < 2 * ((k : ℝ) + 1) := by positivity
rw [le_div_iff₀ hpos] -- goal: 1 ≤ X * (20(k+1))
...
```
from h: 1/(2(k+1)) ≤ 10X ⟹ 1 ≤ 10X·2(k+1) (le_div_iff₀ at h) ⟹ 1 ≤ X·(20(k+1)) by ring_nf... Let me do:
```
have h1 : (1:ℝ) ≤ |(5/2)*‖w‖*10 - T| * (2 * ((k:ℝ)+1)) := (le_div_iff₀ hpos2).mp ...
```
hmm h : 1/(2*(k+1)) ≤ |...|; (le_div_iff₀ hpos2).mp? le_div_iff₀ : a ≤ b / c ↔ a * c ≤ b (c > 0). h is div ≤ abs: 1/(2(k+1)) ≤ Y: (div_le_iff₀ hpos2).mp h : 1 ≤ Y * (2(k+1)). Then 1 ≤ Y·2(k+1) = X·10·2·(k+1) = X·(20(k+1)): rw hscale already done so Y = 10X: 1 ≤ 10X·2(k+1); want 1 ≤ X·(20(k+1)): 10X·2(k+1) = X·20(k+1) ✓ ring_nf or linarith can't (nonlinear products of X·k... these are products of X (a real expr) and (k:ℝ)+1 — linarith treats X·(k+1) as nonlinear atom... provide: have h2 : 10 * |(5/2)*‖w‖ − T/10| * (2*((k:ℝ)+1)) = |(5/2)*‖w‖ − T/10| * (20*((k:ℝ)+1)) := by ring. Then linarith. Then (le_div_iff₀ hpos).mpr. ✓ manageable.
Note: `exists_avoiding_midpoint 23 S10 hcard` — signature: {k : ℕ} (a : ℝ) (S : Finset ℝ) (hcard : S.card ≤ k) — k implicit from hcard : S10.card ≤ Z96.card ⟹ k := Z96.card ✓. Returns T ∈ [23, 24] with clearance 1/(2(k+1)) where k = Z96.card ✓ matches the target form 1/(20*(card+1)).
Also `classical` needed for image decidability? Finset.image needs DecidableEq on target — ℝ has Classical. Add `classical` ✓ (done in the proof).
Then the bundle:
```lean
/-- The chosen collection radius. -/
noncomputable def collRadius (t : ℝ) (ht : 10 ≤ |t|) : ℝ := (exists_collection_radius ht).choose
theorem collRadius_ge ... := ((exists_collection_radius ht).choose_spec).1
...
```
Then rC, δw, ZW and their facts.
OK — I've spent enough planning; let me start writing. I'll write the whole addition in one go but compile after each §. Also add `import NguyenRH1.LiContour` at top.
Actually — one more API check before writing: `Finset.card_image_le`: name? `Finset.card_image_le : (s.image f).card ≤ s.card` ✓ exists. And Finset.mem_image ✓. `Set.InjOn` for sum_image.
And `Filter.EventuallyEq.eq_of_nhds`: hmm — I recall `Filter.EventuallyEq.eq_of_nhds : f =ᶠ[𝓝 x] g → f x = g x` ✓ exists.
`Filter.EventuallyEq.deriv : f =ᶠ[𝓝 x] g → deriv f x = deriv g x` ✓ (EventuallyEq.deriv).
Let me write chunk 1 now (§5–§9: helpers + gap + radius bundle + ZW facts). Then compile. Then chunk 2 (Cf characterizations + B lemmas). Then chunk 3 (main theorem + fold).
Full API picture confirmed. Marking context done and starting the build.
tool: TodoWrite
input
{
"todos": [
{
"content": "Read D-067 \u00a76 + journal-023 + LiDisc.lean + LiContour.lean (context)",
"status": "completed",
"activeForm": "Reading context files"
},
{
"content": "R-gap selection: scaled exists_avoiding_midpoint on [2.3, 2.4]",
"status": "in_progress",
"activeForm": "Building R-gap selection"
},
{
"content": "g := \u03b6/\u220f(s\u2212\u03c1\u2096)^m\u2096 analytic + nonvanishing on closed ball",
"status": "pending",
"activeForm": "Building g analytic/nonvanishing"
},
{
"content": "Bounds: |g| outer circle + \u2212log|g(s\u2080)|",
"status": "pending",
"activeForm": "Proving g bounds"
},
{
"content": "BC assembly \u2192 loose R-bound theorem",
"status": "pending",
"activeForm": "Assembling Borel\u2013Carath\u00e9odory"
},
{
"content": "Build green + axiom audit + commit sub-stage",
"status": "pending",
"activeForm": "Building and auditing"
}
]
}
thinking (9728 chars)
The last arg is `h₂x : analyticOrderAt f x ≠ ⊤`. So I need `analyticOrderAt (scaledZeta t) 0 ≠ ⊤` — with hord0 : = 0: `hord0 ▸ WithTop.zero_ne_top`? or `by rw [hord0]; exact WithTop.zero_ne_top`. The earlier failure was the metavariable — because I wrapped in lt_top_iff_ne_top.mpr unnecessarily. Fix:
```lean
exact hfAn.analyticOrderAt_ne_top_of_isPreconnected Metric.isPreconnected_closedBall
h0mem hwmem (by rw [hord0]; exact WithTop.zero_ne_top)
```
WithTop.zero_ne_top : (0 : WithTop α) ≠ ⊤ — hopefully exists for ℕ∞ (ℕ∞ = WithTop ℕ, WithTop.zero_ne_top needs [Zero α]). Might be `WithTop.zero_ne_top : 0 ≠ ⊤`. OK.
2. **Line 456** (scaledZeroFinset def): `fun w hw => ⟨hw.1.trans hr, hw.2⟩` — hw's type unknown because Set.Finite.subset's subset proof needs the sets inferred. Fix by ascribing:
```lean
(scaledZeta_zeros_finite.subset (s := SetOfZeros 1 (scaledZeta t)) (t := SetOfZeros r (scaledZeta t))
(fun w hw => ⟨hw.1.trans hr, hw.2⟩)).toFinset
```
Set.Finite.subset (hs : s.Finite) (hts : t ⊆ s) : t.Finite — named args s/t. Actually the subset arg order: `Set.Finite.subset (hs : s.Finite) (h : t ⊆ s) : t.Finite`. Provide (t := ...) explicitly. Also `hw.1.trans hr`: hw.1 : ‖w‖ ≤ r, hr : r ≤ 1 ⟹ ‖w‖ ≤ 1 ✓. But hw's type: w ∈ SetOfZeros r F — is that defeq to the ∧? SetOfZeros is a def: `SetOfZeros R f : Set ℂ := {ρ | ‖ρ‖ ≤ R ∧ f ρ = 0}`. Membership w ∈ SetOfZeros r F should unfold to the ∧ — but dot-projection needs the type known; with t ascribed, hw : w ∈ SetOfZeros r (scaledZeta t) — Lean needs to unfold the def to see it as ∧. Might fail! Safer: `fun w hw => by rw [SetOfZeros] at hw ⊢; exact ⟨hw.1.trans hr, hw.2⟩`? Hmm, the target w ∈ SetOfZeros 1 F also needs unfolding. Let me write:
```lean
def scaledZeroFinset (t : ℝ) (r : ℝ) (hr : r ≤ 1) : Finset ℂ :=
(scaledZeta_zeros_finite.subset (t := SetOfZeros r (scaledZeta t)) fun w hw => by
obtain ⟨h1, h2⟩ := hw
exact ⟨h1.trans hr, h2⟩).toFinset
```
The `obtain ⟨h1, h2⟩ := hw` — hw : w ∈ SetOfZeros r F; obtain with ∧ pattern will try whnf — anonymous constructor patterns do unfold defs ✓ usually works. And the goal w ∈ SetOfZeros 1 F: exact ⟨h1.trans hr, h2⟩ — anonymous constructor needs to see through the def — `exact` with ⟨⟩ will whnf the target ✓ typically works. And error 3 (mem lemma type mismatch): mem_toFinset's set is ?m — because the def didn't elaborate. Once the def is fixed, the mem lemma should work: w ∈ (hfin).toFinset ↔ w ∈ SetOfZeros r F, and RHS is defeq to the ∧. But the Iff's stated RHS is the ∧ — need `Iff.rfl`-level or show through: after unfold/rw, goal: w ∈ SetOfZeros r (scaledZeta t) ↔ ‖w‖ ≤ r ∧ scaledZeta t w = 0 — is w ∈ SetOfZeros r F defeq to the ∧? SetOfZeros r f = {ρ | ‖ρ‖ ≤ r ∧ f ρ = 0}, w ∈ {ρ | p ρ} ≡ p w definitionally ✓. So after `rw [Set.Finite.mem_toFinset]`, `exact Iff.rfl` should work. But the error was the unification with metavariables due to the broken def. After fixing the def, retry.
Actually for mem_scaledZeroFinset I wrote `Set.Finite.mem_toFinset _` directly as a term — that has the set as metavariable; with the def now opaque... Let me write it as:
```lean
theorem mem_scaledZeroFinset {t : ℝ} {r : ℝ} {hr : r ≤ 1} {w : ℂ} :
w ∈ scaledZeroFinset t r hr ↔ ‖w‖ ≤ r ∧ scaledZeta t w = 0 := by
show w ∈ SetOfZeros r (scaledZeta t) ↔ _
exact Iff.rfl
```
`show` needs defeq: w ∈ scaledZeroFinset t r hr ≡ w ∈ (fin).toFinset ≡ w ∈ SetOfZeros r F (mem_toFinset is a theorem not def — so show won't jump through it!). Use: `rw [scaledZeroFinset, Set.Finite.mem_toFinset]` then goal `w ∈ SetOfZeros r (scaledZeta t) ↔ ...` then `exact Iff.rfl`. But `rw [scaledZeroFinset]` — rw with a def name doesn't unfold; use `unfold scaledZeta...`? `unfold scaledZeroFinset` then `rw [Set.Finite.mem_toFinset]`; final `Iff.rfl`. The SetOfZeros membership might display as `w ∈ SetOfZeros r (scaledZeta t)`; Iff.rfl needs defeq to the ∧ — should hold. If not, add `show ‖w‖ ≤ r ∧ scaledZeta t w = 0 ↔ _` hmm. Try.
3. **Line 474** (scaledZeroFinset_24_25_eq): type mismatch — the finiteness proofs are metavariables. Fix: name the finiteness proof:
```lean
theorem scaledZeroFinset_24_25_eq (t : ℝ) :
scaledZeroFinset t (24 / 25) (by norm_num) =
(finiteSetOfZeros_mono (f := scaledZeta t) (r := 24 / 25) (by norm_num)
scaledZeta_zeros_finite).toFinset := by
apply Set.Finite.toFinset_inj.mpr
rfl
```
Same issue possibly — toFinset_inj : hs.toFinset = ht.toFinset ↔ s = t where hs : s.Finite, ht : t.Finite — the LHS/RHS of my goal determine hs, ht via the toFinset calls ✓ then mpr needs s = t: both are SetOfZeros (24/25) (scaledZeta t)... my subset-derived: (scaledZeta_zeros_finite.subset (t := SetOfZeros r ...) ...) : (SetOfZeros (24/25) F).Finite ✓ set is SetOfZeros (24/25) F; finiteSetOfZeros_mono's: (SetOfZeros (24/25) F).Finite ✓. rfl : SetOfZeros (24/25) F = SetOfZeros (24/25) F ✓. So `exact Set.Finite.toFinset_inj.mpr rfl` should now unify since goal determines both finsets. The earlier failure was probably knock-on from the broken def. Keep as term but ensure def fixed first.
4. **Line 486**: `Finset.sum_le_sum_of_subset_of_nonneg hsub (fun _ _ _ => zero_le _)` — zero_le applied to _. zero_le is `0 ≤ a` with a implicit — as a term `zero_le _` tries to apply. Use `(fun _ _ _ => zero_le (a := _))` hmm — zero_le : 0 ≤ a with {a} implicit and instance... `zero_le (α := ℕ)`? In Lean4 Mathlib: `zero_le : 0 ≤ a` — it's `zero_le (a)`? For ordered semiring: `zero_le : 0 ≤ a` with a explicit? The error says zero_le is a term 0 ≤ ?m, not a function — so no explicit arg. Use `(fun _ _ _ => Nat.zero_le _)`. ✓
5. **Line 492** (hcast): Nat.cast of sum vs sum of casts: `Nat.cast_le.mpr hle : ((Σ... : ℕ) : ℝ) ≤ ...` but goal has Σ of casts: push_cast: `Nat.cast_sum`? The goal's LHS is `∑ ρ ∈ ..., ↑(analyticOrderNatAt ...)` (sum of casts) while Nat.cast_le.mpr gives ↑(Σ ...). Need `Nat.cast_sum : ↑(∑ i in s, f i) = ∑ i in s, ↑(f i)` — push_cast [Nat.cast_sum] at hcast or exact hcast after norm_cast. Fix: after `refine (Nat.cast_le.mpr hle).trans ?_`, the ?_: ↑(Σ 24/25 sum) ≤ RHS — and scaledZeta_jensen_count's LHS: is it ↑(Σ) or Σ of ↑? The committed statement (line 352): `∑ ρ ∈ (...).toFinset, analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log ...` — elaborated with the sum coerced: ↑(Σ...) (since analyticOrderNatAt returns ℕ and no cast inside). So ?_ matches after rw [scaledZeroFinset_24_25_eq]... the error: hcast expected-type mismatch — the GOAL of the theorem (stated with `(∑ ... : ℝ)` ascription!) — I wrote `(∑ ρ ∈ scaledZeroFinset t r hr, analyticOrderNatAt (scaledZeta t) ρ : ℝ)` — the `: ℝ` ascription is INSIDE the sum?? `∑ ρ ∈ s, f ρ : ℝ` parses as `∑ ρ ∈ s, (f ρ : ℝ)`? No — `(∑ ρ ∈ s, analyticOrderNatAt (scaledZeta t) ρ : ℝ)` — the colon inside parens after the sum body... it's `(∑ ρ ∈ s, analyticOrderNatAt (scaledZeta t) ρ : ℝ)` = the whole sum ascribed ℝ — which forces f ρ : ℝ via unification — so each term is ↑(analyticOrderNatAt...). So the sum IS over casts. Meanwhile Nat.cast_le.mpr hle gives ↑(Σ nats). Bridge: Nat.cast_sum: `Nat.cast_sum : ↑(∑ i ∈ s, f i) = ∑ i ∈ s, ↑(f i)`? it's `Nat.cast_sum (s : Finset α) (f : α → ℕ) : (↑(∑ i ∈ s, f i) : β) = ∑ i ∈ s, (↑(f i) : β)` ✓. So in hcast's proof, first `rw [← Nat.cast_sum]` on the goal... the goal at `exact hcast`: Σ of casts ≤ RHS. Change the final `exact hcast` to:
```lean
rw [← Nat.cast_sum]
exact hcast
```
And inside hcast: `refine (Nat.cast_le.mpr hle).trans ?_; rw [scaledZeroFinset_24_25_eq]` — the ?_ goal: ↑(∑ 24/25-ℕ-sum) ≤ RHS; jensen's LHS: is it ↑(Σ) exactly? From the committed theorem: `∑ ρ ∈ (...).toFinset, analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log ...` — elaborates to ↑(Σ...) ≤ RHS? The ≤ unifies ℕ with ℝ? No: ≤ needs same type; Lean inserts coercion around the SUM (since body is ℕ and can't unify ℕ ≤ ℝ... actually the coercion could be inserted at the body: ∑ ρ, ↑(order ρ) ≤ RHS — elaborator tries... hmm. In committed code it compiled with `h.trans_eq` at the end where h := ZerosBound ... : ∑ ρ ∈ ..., analyticOrderNatAt f ρ ≤ 1 / Real.log (R/r) * Real.log B — so ZerosBound's own statement has this form; its proof ended with `Real.log_le_log (pow_pos ...)` after calc with `(R / r) ^ ∑ ...` — ^ with ℕ-cast exponent (the sum coerced into the exponent — that's Nat.cast inside pow: (R/r)^(↑Σ)...). Ugh — the exact elaboration form matters. In ZerosBound's statement: `∑ ρ ∈ (finiteSetOfZeros_mono r_lt_one finiteZeros).toFinset, analyticOrderNatAt f ρ ≤ 1 \ Real.log (R \ r) * Real.log B` — hmm `1 \ Real.log` — backslash is... `\` = \\ is "div"?? In Zeta23 `1 \ Real.log ...` — in Lean 4, `\` is... hmm `1 \ x` — that's not standard; maybe Zeta23 defines `\` notation? Wait — `1 / Real.log` — the grep output showed `1 \ Real.log (R \ r)` — I bet the backslashes are an artifact of the grep tool escaping? No... Actually looking at BorelCaratheodoryDeriv output: `16 * M * R ^ 2 \ (R - r) ^ 3` — that's clearly supposed to be `16 * M * R ^ 2 / (R - r) ^ 3`. So the terminal display converts `/` to `\`?? No wait — maybe Zeta23 actually uses `\`?? Hmm, in the Read output of StrongPNTPrefix lines 108-114: `‖deriv f z‖ ≤ 16 * M * R ^ 2 \ (R - r) ^ 3` — and line 457: `1 \ Real.log (R \ r) * Real.log B`. Hmm — this is the Read/Grep display. But Mathlib has `HDiv` notation `/`... Could `\` be a Zeta23 notation? If it were `/` it would just print `/`. Hmm, hold on — in Lean 4, `\` IS... no. Let me check with bash sed/grep raw.
Actually — I remember: some projects define `a \ b` as notation for `a / b`?? No. OR: it's the Euclidean... In PNT+, `1 \ x` hmm. Wait, maybe it's an escape artifact in the tool output rendering where `/` inside certain contexts got displayed as `\`. Let me check the raw file.
Fixing the chunk-1 errors. First checking a display oddity (`1 \ Real.log` in ZerosBound) in the raw file.
tool: Bash
input
{
"command": "cd \"D:/Python/Quantum/zeta-23-lean\" && sed -n '453,458p' Zeta23/FromPNTPlus/StrongPNTPrefix.lean | cat -A | head -8",
"description": "Inspect raw bytes of ZerosBound statement"
}
thinking (22691 chars)
OK — it's `1 / Real.log (R / r) * Real.log B` with plain `/`. The `\` was a tool display artifact. Good.
Now fix the errors:
1. scaledZeta_order_ne_top — fix the last arg.
2. scaledZeroFinset def — ascribe t explicitly.
3. mem_scaledZeroFinset — unfold + rw + Iff.rfl.
4. scaledZeroFinset_24_25_eq — keep term, should work once def fixed.
5. sum_le_sum_of_subset_of_nonneg — Nat.zero_le _.
6. scaledZeroFinset_sum_order_le — Nat.cast_sum bridging.
7. exists_collection_radius hscale — `rw [← abs_mul]` failed: |5/2*‖w‖*10 − T| = 10*|5/2*‖w‖ − T/10| — the rw pattern |?a|*|?b| not found since goal RHS is `10 * |...|` not `|10| * |...|`. Fix: `rw [show (10:ℝ) = |10| from (abs_of_pos (by norm_num)).symm, ← abs_mul]` then congr+ring. Or simpler:
```lean
have hscale : |(5 / 2) * ‖w‖ * 10 - T| = 10 * |(5 / 2) * ‖w‖ - T / 10| := by
have h10 : (10:ℝ) = |10| := (abs_of_pos (by norm_num)).symm
rw [h10, ← abs_mul]
congr 1
ring
```
Also in rC_gap I used the same `rw [hscale, abs_mul, abs_of_nonneg ...]` — that one: |(5/2)*(‖w‖ − rC ht)| after rw hscale: pattern |(5/2)*(...)| — abs_mul: |a*b| = |a|*|b| ✓ then rw [abs_of_nonneg (0 ≤ 5/2)] : |5/2| = 5/2 — hmm abs_of_nonneg gives |a| = a: rw makes |5/2| into 5/2 ✓. That part fine.
Let me also double-check `rC_gap`'s final calc: h2 : 1 ≤ (5/2)*|‖w‖−rC ht| * (20*(card+1)) — from h : 1/(20*(card+1)) ≤ (5/2)*|...| via le_div_iff₀ (0 < 20*(card+1)): div_le? h : a/b ≤ c with a=1: `div_le_iff₀ (hc : 0 < c) : a / c ≤ b ↔ a ≤ b * c` — so (div_le_iff₀ hpos).mp h : 1 ≤ ((5/2)*|...|) * (20*(card+1)) ✓. Then goal after rw [le_div_iff₀ hpos] : 1 ≤ |‖w‖−rC ht| * (50*(card+1)). calc step: 1 ≤ (5/2)*|...|*(20*(...)) = |...|*(50*(...)): ring: (5/2)*X*20*Y = X*50*Y ✓ (5/2)*20 = 50 ✓.
But wait — in rC_gap I wrote `(le_div_iff₀ (by positivity : (0:ℝ) < 20 * ...)).mp h` — I actually wrote `le_div_iff₀` in my draft as `(le_div_iff₀ ...)`. Let me re-check my written code... I wrote:
```lean
have h2 := (le_div_iff₀ (by positivity : (0:ℝ) <
20 * (((scaledZeroFinset t (24 / 25) (by norm_num : (24/25:ℝ) ≤ 1)).card : ℝ) + 1))).mp h
```
✓ ok.
And in exists_collection_radius, h1 : 1 ≤ 10*|...|*(2*(card+1)) — from (div_le_iff₀ hpos2).mp h where h : 1/(2*(card+1)) ≤ 10*|...|: div_le_iff₀.mp : 1 ≤ (10*|...|)*(2*(card+1)) ✓ then h2 rewrites to |...|*(20*(card+1)) — but careful: h2 as written: 10 * |...| * (2 * (card+1)) = |...| * (20*(card+1)) ✓ ring. rw [h2] at h1 ⟹ h1 : 1 ≤ |...|*(20*(card+1)) ✓ then (le_div_iff₀ hpos).mpr h1 : 1/(20*(card+1)) ≤ |...| ✓. le_div_iff₀ (hc : 0 < c) : a ≤ b / c ↔ a * c ≤ b — mpr h1 : 1 * (20*(card+1)) ≤ |...|?? h1 : 1 ≤ |...| * (20*(card+1)) — le_div_iff₀.mpr needs 1 * (20*(card+1)) ≤ |...| but h1 has the product flipped: |...|*(20*(card+1)) vs 1*(20*(card+1)) — mismatch! le_div_iff₀ : a ≤ b / c ↔ a * c ≤ b. mpr : a * c ≤ b → a ≤ b / c. Need a*c = 1*(20*(card+1)) ≤ b = |...|. h1 : 1 ≤ |...|*(20*(card+1)). So I need one more step: 1*(20*(card+1)) = |...|*(20*(card+1))?? NO — that's wrong: 1*(20(card+1)) ≠ |...|·(20(card+1)) unless |...| = 1. I messed up: div_le_iff₀.mp h : 1 ≤ (10|X|)·(2(k+1)) — wait: h : 1/(2(k+1)) ≤ Y — the div is on the LEFT: a/c ≤ b form: div_le_iff₀ : a / c ≤ b ↔ a ≤ b * c ✓ so mp h : 1 ≤ Y*(2(k+1)) where Y = 10|X| ✓. Then target 1/(20(k+1)) ≤ |X|: le_div_iff₀.mpr : 1·(20(k+1)) ≤ ... no wait: a ≤ b/c ↔ a*c ≤ b — here the div is on the RIGHT: 1 ≤ |X|/(20(k+1))?? No — my target: 1/(20*(k+1)) ≤ |X| — div on LEFT again: div_le_iff₀ : a/c ≤ b ↔ a ≤ b*c: (div_le_iff₀ hpos)... hmm that's the same lemma div_le_iff₀ (a/c ≤ b ↔ a ≤ b*c)?? No! There are two: `div_le_iff₀ : a / c ≤ b ↔ a ≤ b * c` and `le_div_iff₀ : a ≤ b / c ↔ a * c ≤ b`. Target: 1/(20(k+1)) ≤ |X| is a/c ≤ b: div_le_iff₀.mp needs... I want to CONSTRUCT it: div_le_iff₀.mpr? no wait div_le_iff₀ (hc : 0 < c) : a / c ≤ b ↔ a ≤ b * c — so .mpr : a ≤ b*c → a/c ≤ b. Need 1 ≤ |X|*(20(k+1)). h1 : 1 ≤ |X|*(20(k+1)) ✓ EXACTLY (after h2 rewrite). So the final should be `(div_le_iff₀ hpos).mpr h1` NOT le_div_iff₀! Let me recheck what I wrote in exists_collection_radius: `exact (le_div_iff₀ hpos).mpr h1` — WRONG lemma: le_div_iff₀ : a ≤ b / c ↔ a * c ≤ b; .mpr h1 with h1 : 1 ≤ |X|*(20(k+1)) would need 1*(20(k+1)) ≤ ... mismatch — elaboration error would have surfaced later. Fix to div_le_iff₀.
Similarly in rC_gap: goal after `rw [le_div_iff₀ hpos]`... I wrote `rw [le_div_iff₀ hpos]` on goal `1/(50*(card+1)) ≤ |‖w‖ − rC ht|` — that's a/c ≤ b: rw with le_div_iff₀ (a ≤ b/c form) doesn't match! Should be `rw [div_le_iff₀ hpos]`: goal becomes 1 ≤ |...|*(50*(card+1)) ✓ then calc. Fix.
Also in rC_gap, `h2` uses le_div_iff₀... h : 1/(20*(card+1)) ≤ (5/2)*|...| — a/c ≤ b: `div_le_iff₀`. I wrote le_div_iff₀ — fix to div_le_iff₀. Then h2 : 1 ≤ ((5/2)*|...|)*(20*(card+1)) ✓.
Also in exists_collection_radius: `have h1 := (div_le_iff₀ hpos2).mp h` — h : 1/(2*(k+1)) ≤ 10*|X|: div_le_iff₀.mp ✓ correct there.
Wait, I need to double check div_le_iff₀'s exact form in current Mathlib: `div_le_iff₀ (hc : 0 < c) : a / c ≤ b ↔ a ≤ b * c` ✓ (I believe; there's also div_le_iff₀' with c*b). And le_div_iff₀ (hc : 0 < c) : a ≤ b / c ↔ a * c ≤ b. OK.
Also in rC_gap the final calc first step: `calc (1:ℝ) ≤ (5/2)*|‖w‖−rC ht| * (20*(card+1)) := h2` — h2's form: 1 ≤ (5/2)*|...| * (20*(...)) — but is it grouped ((5/2)*|...|)*(20*(...))? div_le_iff₀.mp gives a ≤ b*c with b = (5/2)*|...|, c = 20*(...): b*c = (5/2)*|...| * (20*(...)) ✓.
6. Another issue: in `collZeros_norm_le`, habs := abs_le.mp hgap : −δw... wait hgap : δw' ≤ |‖w‖ − rC ht| where δw' = 1/(50*(...)) — abs_le.mp gives −δw' ≤ ... NO: abs_le : |a| ≤ b ↔ −b ≤ a ∧ a ≤ b — hgap has δw ≤ |X| (reversed!). abs_le.mp needs |X| ≤ b. I need: |‖w‖ − rC| ≥ δw and ‖w‖ ≤ rC ⟹ ‖w‖ ≤ rC − δw. From |‖w‖ − rC| ≥ δw: cases on sign: ‖w‖ − rC ≥ δw or ‖w‖ − rC ≤ −δw (abs_choice/le_abs). Since ‖w‖ ≤ rC, ‖w‖ − rC ≤ 0, so must have ‖w‖ − rC ≤ −δw?? NO — |x| ≥ δ with x ≤ 0 gives −x ≥ δ i.e. x ≤ −δ ✓. In Lean: le_abs' ? Hmm: `le_abs' : a ≤ |b| → b ≤ -a ∨ a ≤ b`? There's `le_abs : a ≤ |b| ↔ b ≤ -a ∨ a ≤ b`? hmm `le_abs : a ≤ |b| ↔ b ≤ −a ∨ a ≤ b`?? Not sure of exact form. Simplest:
```lean
have hcases := le_abs'.mp ...
```
Let me think: from hgap : δw ≤ |X| and hle : X ≤ 0 (X = ‖w‖ − rC ≤ 0 since ‖w‖ ≤ rC): want X ≤ −δw. `abs_of_nonpos hle : |X| = −X`; rw at hgap: δw ≤ −X ⟹ X ≤ −δw (linarith). So:
```lean
have hX : ‖w‖ - rC ht ≤ 0 := sub_nonpos.mpr hle
rw [abs_of_nonpos hX] at hgap
linarith
```
✓ cleaner. (My current draft used abs_le.mp hgap which is wrong-direction.) Fix.
7. Also check `collZeros_norm_le`'s statement: the δw expression uses `(by norm_num : (24/25:ℝ) ≤ 1)` proof inside — matches scaledZeroFinset t (24/25) (by norm_num) ✓ proof irrelevance handles.
8. In rC_gap/rC_ge etc., `unfold rC; linarith` — rC ht := collRadius ht * (2/5): goal 23/25 ≤ collRadius ht*(2/5) with h : 23/10 ≤ collRadius ht: linarith ✓ linear in the atom collRadius ht.
Also `rC_pos`: `(rC_ge ht).trans_lt' (by norm_num)` : trans_lt' : a ≤ b → b < c → a < c? `LE.le.trans_lt' : a ≤ b → b < c → a < c`? Hmm trans_lt' might not exist; use `(by norm_num : (0:ℝ) < 23/25).trans_le (rC_ge ht)` — (0 < 23/25).trans_le : 23/25 ≤ rC → 0 < rC ✓ `LT.lt.trans_le`. Fix.
Also scaledZeroFinset_subset: I have `{hr₁ : r₁ ≤ 1} {hr₂ : r₂ ≤ 1}` as instance-implicit? I wrote `{hr₁ : r₁ ≤ 1} {hr₂ : r₂ ≤ 1}` — plain implicit ✓ good. But in collZeros_norm_le I call `scaledZeroFinset_subset (rC_le ht) hw` — with h : r₁ ≤ r₂: rC ht ≤ 24/25 — rC_le ht : rC ht ≤ 24/25 ✓. But rC_le is `rC ht ≤ 24/25` while scaledZeroFinset_subset expects (h : r₁ ≤ r₂) with r₂ := 24/25 and hr₂ : 24/25 ≤ 1 (by norm_num — implicit, will it synthesize? NO — it's a hypothesis implicit, must be provided or inferred from the hw's type: hw : w ∈ scaledZeroFinset t (24/25) (by norm_num)?? — hw : w ∈ collZeros ht; scaledZeroFinset_subset (rC_le ht) hw — the subset lemma's conclusion: scaledZeroFinset t r₁ hr₁ ⊆ scaledZeroFinset t r₂ hr₂; applying to hw : w ∈ scaledZeroFinset t (rC ht) ?hr₁: the subset is a FUNCTION on membership — `scaledZeroFinset_subset (rC_le ht) hw` — Lean: subset arg h := rC_le ht fixes r₁ := rC ht, r₂ := 24/25; hr₁ must come from hw's type — hw : w ∈ collZeros ht which unfolds (collZeros is a def) to scaledZeroFinset t (rC ht) (rC_lt_one ht).le — unification of w ∈ scaledZeroFinset t r₁ hr₁ with w ∈ collZeros ht: needs to unfold collZeros — `@[simp]`? collZeros is a plain def; applying the subset-function to hw: the function's domain is w ∈ scaledZeroFinset t r₁ hr₁ and hw's type is w ∈ collZeros ht — defeq (unfold collZeros) — Lean's application elaboration will unify by whnf ✓ should work. hr₂ : 24/25 ≤ 1 remains a metavariable — implicit args of sort Prop... it can't be inferred ⟹ error "typeclass/implicit". Make hr₁ hr₂ instance-implicit? They're proofs of r ≤ 1 — Lean won't synthesize by norm_num automatically. So in the call I must provide hr₂: `scaledZeroFinset_subset (hr₂ := by norm_num) (rC_le ht) hw`. Hmm — or restructure: make scaledZeroFinset take hr as instance-implicit `[[hr : r ≤ 1]]`? No such thing for Props (only typeclasses). Alternative: drop the proof arg from the def entirely by using an if:
```lean
def scaledZeroFinset (t : ℝ) (r : ℝ) : Finset ℂ :=
if hr : r ≤ 1 then (scaledZeta_zeros_finite.subset (t := SetOfZeros r (scaledZeta t)) fun w hw => ⟨hw.1.trans hr, hw.2⟩).toFinset
else (scaledZeta_zeros_finite).toFinset -- garbage branch, never used
```
Ugh. Cleaner alternative: keep proof arg but always provide. In collZeros def: `scaledZeroFinset t (rC ht) (rC_lt_one ht).le` — already doing that. The subset lemma call sites provide proofs. In collZeros_norm_le I wrote `scaledZeroFinset_subset (rC_le ht) hw` — hr₁, hr₂ implicit NOT inferable ⟹ error. Fix: `scaledZeroFinset_subset (hr₁ := _) (hr₂ := by norm_num) (rC_le ht) hw`? hr₁ from hw. Hmm implicit args with { } can be inferred from later explicit args: hw's type determines hr₁ (via whnf unification w ∈ scaledZeroFinset t r₁ hr₁ ≡ w ∈ collZeros ht — the proof arg (rC_lt_one ht).le vs hr₁: Prop ⟹ proof irrelevance — unification of proof args: they're definitionally equal by Subsingleton? Unification doesn't use proof irrelevance automatically!! w ∈ scaledZeroFinset t r₁ hr₁ =?= w ∈ scaledZeroFinset t (rC ht) ((rC_lt_one ht).le): needs hr₁ =?= (rC_lt_one ht).le — proof irrelevance IS used by unification for Props? Lean 4 defeq includes proof irrelevance: two proofs of the same Prop are definitionally equal ✓ YES proof irrelevance is part of defeq. So unification works: hr₁ := (rC_lt_one ht).le up to proof irrelevance ✓. hr₂ : 24/25 ≤ 1 — NOT determined by anything ⟹ stuck metavariable. So provide hr₂ explicitly: `scaledZeroFinset_subset (hr₂ := by norm_num) (rC_le ht) hw`. Same in scaledZeroFinset_sum_order_le's hsub — I have `scaledZeroFinset_subset hr24` with hr₁ hr₂ — hr₂ stuck: provide (hr₂ := by norm_num). Hmm wait — in that lemma, the RHS finset in the statement is `scaledZeroFinset t (24/25) (by norm_num)` so hr₂ gets unified from the goal? The statement's RHS has (by norm_num) — but hsub is used in Finset.sum_le_sum_of_subset_of_nonneg hsub ... — the goal determines it ✓ probably. To be safe provide explicitly everywhere.
Actually — simplest robust fix: make the subset lemma take hr₁ hr₂ as EXPLICIT? No — let me just always write the full call with named proof args. OK.
Similarly `mem_collZeros` — `mem_scaledZeroFinset` with hr implicit — determined by... statement: w ∈ collZeros ht ↔ ... — mem_scaledZeroFinset : w ∈ scaledZeroFinset t r hr ↔ ... — unify LHS with w ∈ collZeros ht via whnf ⟹ r := rC ht, hr := (rC_lt_one ht).le (proof irrelevance) ✓ fine.
Also `collMultSum`/`card96` defs — fine.
Let me also double check `one_le_analyticOrderNatAt_scaledZeta` usage in scaledZeroFinset_card_le_sum: `one_le_analyticOrderNatAt_scaledZeta ht (hw.1.trans hr) hw.2` — hw from mem_scaledZeroFinset: ‖w‖ ≤ r ∧ F w = 0; need ‖w‖ ≤ 1: hw.1.trans hr ✓ where hr : r ≤ 1 is the lemma's implicit — card_le_sum has {hr : r ≤ 1} implicit ✓ from the finset in the statement.
Also in scaledZeroFinset_card_le_sum the final `exact_mod_cast h` — goal: ((card):ℝ) ≤ Σ of casts?? The statement I wrote: `((scaledZeroFinset t r hr).card : ℝ) ≤ ∑ ρ ∈ ..., analyticOrderNatAt (scaledZeta t) ρ` — the sum: body analyticOrderNatAt : ℕ, target comparison in ℝ ⟹ coercion: ↑(Σ) or Σ of ↑? When elaborating `((card):ℝ) ≤ ∑ ρ ∈ s, analyticOrderNatAt ... ρ`, unification: RHS must be ℝ; the sum's body is ℕ — Lean elaborates ∑ with expected type ℝ ⟹ each term coerced: Σ of casts. So goal: ↑(card) ≤ Σ of casts. h : card ≤ Σ (ℕ). exact_mod_cast h: casts through — mod_cast handles ↑(Σ) = Σ↑ via push_cast internally? exact_mod_cast should manage (it normalizes both sides). The earlier error 5 was about zero_le inside this lemma — fixed via Nat.zero_le. Let me rewrite this lemma:
```lean
theorem scaledZeroFinset_card_le_sum {t : ℝ} (ht : 10 ≤ |t|) {r : ℝ}
{hr : r ≤ 1} :
((scaledZeroFinset t r hr).card : ℝ) ≤
∑ ρ ∈ scaledZeroFinset t r hr, (analyticOrderNatAt (scaledZeta t) ρ : ℝ) := by
rw [← Nat.cast_sum] -- hmm Nat.cast_sum : ↑(∑) = ∑↑ ; ← direction turns Σ↑ into ↑Σ
exact_mod_cast (Finset.card_le_...)
```
Let me do:
```lean
have h : (scaledZeroFinset t r hr).card ≤
∑ ρ ∈ scaledZeroFinset t r hr, analyticOrderNatAt (scaledZeta t) ρ := by
rw [Finset.card_eq_sum_ones]
apply Finset.sum_le_sum
intro w hw
rw [mem_scaledZeroFinset] at hw
exact one_le_analyticOrderNatAt_scaledZeta ht (hw.1.trans hr) hw.2
calc ((scaledZeroFinset t r hr).card : ℝ)
≤ ↑(∑ ρ ∈ scaledZeroFinset t r hr, analyticOrderNatAt (scaledZeta t) ρ) :=
Nat.cast_le.mpr h
_ = ∑ ρ ∈ scaledZeroFinset t r hr, (analyticOrderNatAt (scaledZeta t) ρ : ℝ) :=
Nat.cast_sum _ _
```
Wait Finset.card_eq_sum_ones : s.card = ∑ x ∈ s, 1 ✓. Finset.sum_le_sum needs ∀ i ∈ s, f i ≤ g i where f = fun _ => 1, g = order: intro w hw; goal 1 ≤ order — the 1 is from card_eq_sum_ones's sum of 1s ✓.
Hmm — but wait, in `Finset.sum_le_sum` the goal after `apply`: ∀ i ∈ s, (fun _ => 1) i ≤ order i — beta: 1 ≤ analyticOrderNatAt ... ✓.
Nat.cast_sum signature: `Nat.cast_sum (s : Finset α) (f : α → ℕ) : ((∑ x ∈ s, f x : ℕ) : β) = ∑ x ∈ s, (f x : β)`? I think it's `Nat.cast_sum : ↑(∑ i ∈ s, f i) = ∑ i ∈ s, ↑(f i)` with (s) (f) explicit? or implicit. If implicit: `Nat.cast_sum` alone. I'll write `rw [Nat.cast_sum]`-friendly: put the calc's last step as `by rw [Nat.cast_sum]` reversed... Let me structure:
```lean
_ = ∑ ρ ∈ scaledZeroFinset t r hr, (analyticOrderNatAt (scaledZeta t) ρ : ℝ) := by
rw [Nat.cast_sum]
```
rw [Nat.cast_sum] on goal ↑(Σ) = Σ↑: Nat.cast_sum : ↑(Σ) = Σ↑ — rw would rewrite LHS→RHS making goal Σ↑ = Σ↑... rw closes it if it becomes rfl ✓ (rw closes goals that become rfl). But careful rw [Nat.cast_sum] rewrites the FIRST match of ↑(∑...) which is the LHS ✓ goal becomes Σ↑ = Σ↑ closed ✓.
Also same cast issue in scaledZeroFinset_sum_order_le: statement has `(∑ ρ ∈ ..., analyticOrderNatAt (scaledZeta t) ρ : ℝ)` — I should write it as `∑ ρ ∈ ..., (analyticOrderNatAt (scaledZeta t) ρ : ℝ)` explicitly. Then in the proof, jensen's LHS form: `scaledZeta_jensen_count ht : ∑ ρ ∈ ..., analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log ... / Real.log ...` — whatever form jensen elaborated to (probably ↑(Σ) ≤ RHS or Σ↑ ≤ RHS — since its statement writes `∑ ρ ∈ ..., analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log (...)`: same elaboration ⟹ Σ of casts (each term coerced) — because Lean sees ≤ with RHS : ℝ, elaborates LHS with expected type ℝ: ∑ ... : ℝ ⟹ terms coerced. So jensen : (↑(order))-sum ≤ RHS. And my hcast chain: Nat.cast_le.mpr hle : ↑(Σ_ℕ r-sum) ≤ ↑(Σ_ℕ 96-sum); need to match Σ↑ forms: use Nat.cast_sum. Rewrite plan:
```lean
theorem scaledZeroFinset_sum_order_le {t : ℝ} (ht : 10 ≤ |t|) {r : ℝ}
{hr : r ≤ 1} (hr24 : r ≤ 24 / 25) :
(∑ ρ ∈ scaledZeroFinset t r hr, (analyticOrderNatAt (scaledZeta t) ρ : ℝ)) ≤
Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by
have hsub : scaledZeroFinset t r hr ⊆ scaledZeroFinset t (24 / 25) (by norm_num) :=
scaledZeroFinset_subset (hr₂ := by norm_num) hr24
have hle : ∑ ρ ∈ scaledZeroFinset t r hr, analyticOrderNatAt (scaledZeta t) ρ ≤
∑ ρ ∈ scaledZeroFinset t (24 / 25) (by norm_num), analyticOrderNatAt (scaledZeta t) ρ :=
Finset.sum_le_sum_of_subset_of_nonneg hsub (fun _ _ _ => Nat.zero_le _)
rw [← Nat.cast_sum]
refine (Nat.cast_le.mpr hle).trans ?_
rw [← Nat.cast_sum, scaledZeroFinset_24_25_eq]
exact scaledZeta_jensen_count ht
```
Hmm — after `rw [← Nat.cast_sum]`, goal: ↑(Σ_ℕ) ≤ RHS. Then refine ... trans ?_: ?_ : ↑(Σ_ℕ 96) ≤ RHS. rw [← Nat.cast_sum] on ?_: ↑(Σ_ℕ 96) → Σ↑96... but scaledZeta_jensen_count's form is Σ↑ (as elaborated) — so after rw [← Nat.cast_sum] the goal becomes Σ↑... wait ← direction: Nat.cast_sum : ↑(Σ) = Σ↑; rw [← Nat.cast_sum] turns Σ↑ into ↑(Σ) — the goal ↑(Σ_ℕ 96) ≤ RHS has no Σ↑... the ↑(Σ_ℕ) IS already there. Ugh, direction confusion. Let me think again:
- Goal initially: Σ↑_r ≤ RHS.
- rw [← Nat.cast_sum]: rewrites Σ↑ patterns to ↑(Σ): goal becomes ↑(Σ_ℕ r) ≤ RHS ✓.
- Nat.cast_le.mpr hle : ↑(Σ_ℕ r) ≤ ↑(Σ_ℕ 96). trans leaves ?_ : ↑(Σ_ℕ 96) ≤ RHS.
- rw [scaledZeroFinset_24_25_eq] at the finset inside: ?_ : ↑(Σ_ℕ over jensen-finset) ≤ RHS.
- jensen : Σ↑ over jensen-finset ≤ RHS. Mismatch: ↑(Σ_ℕ) vs Σ↑. So `rw [Nat.cast_sum]`: turns ↑(Σ_ℕ) into Σ↑ ✓ goal becomes Σ↑ ≤ RHS = jensen ✓ exact.
So: `rw [scaledZeroFinset_24_25_eq, Nat.cast_sum]`? rw [Nat.cast_sum] on ↑(∑ x ∈ s, f x) — pattern LHS ✓. But — does jensen's statement actually have Σ↑ form? If instead jensen has ↑(Σ) form (coercion outside), then skip the last rw. I'll handle at compile: try with, remove if error. Actually safest: replace the last two steps by:
```lean
rw [scaledZeroFinset_24_25_eq]
exact_mod_cast scaledZeta_jensen_count ht -- hmm exact_mod_cast on a ≤ with cast normalization both sides
```
`exact_mod_cast jensen` — mod_cast normalizes ↑(Σℕ) ↔ Σ↑ via push_cast rules (Nat.cast_sum is a norm_cast lemma? probably `norm_cast` attr on Nat.cast_sum ✓ likely). So: after the trans ?_, do `exact_mod_cast scaledZeta_jensen_count ht`?? but the finset inside ?_ must first be rewritten to the jensen finset — rw [scaledZeroFinset_24_25_eq] changes ↑(Σ_ℕ over scaledZeroFinset 24/25) to over jensen-finset ✓ then exact_mod_cast (scaledZeta_jensen_count ht). mod_cast will handle ↑(Σ) vs Σ↑ mismatch ✓.
Wait — actually there's a subtlety: is `scaledZeta_jensen_count ht` applicable — its statement: `∑ ρ ∈ (finiteSetOfZeros_mono (f := scaledZeta t) (r := 24 / 25) (by norm_num) (scaledZeta_zeros_finite)).toFinset, analyticOrderNatAt (scaledZeta t) ρ ≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32)` ✓ ht : 10 ≤ |t| ✓.
9. `exists_collection_radius` uses `Finset.card_image_le.trans Finset.card_image_le` — card_image_le : (s.image f).card ≤ s.card ✓; S10.card ≤ S.card ≤ Z96.card: first card_image_le : S10.card ≤ S.card; second : S.card ≤ Z96.card ✓ .trans ✓.
10. `mem_scaledZeroFinset` as Iff term: `Set.Finite.mem_toFinset _` — the error was type mismatch because the finiteness proof's set was a metavariable. After def fix, `Set.Finite.mem_toFinset (scaledZeta_zeros_finite.subset ...)` — writing `_` for the proof: the Iff's LHS determines it ✓ maybe. Safer by-tactic:
```lean
theorem mem_scaledZeroFinset {t : ℝ} {r : ℝ} {hr : r ≤ 1} {w : ℂ} :
w ∈ scaledZeroFinset t r hr ↔ ‖w‖ ≤ r ∧ scaledZeta t w = 0 := by
unfold scaledZeroFinset
rw [Set.Finite.mem_toFinset]
```
leaves goal w ∈ SetOfZeros r (scaledZeta t) ↔ ‖w‖ ≤ r ∧ scaledZeta t w = 0 — hmm the rw closes? mem_toFinset : a ∈ hs.toFinset ↔ a ∈ s — rw rewrites LHS to w ∈ SetOfZeros r F, then goal X ↔ Y where X defeq Y — rw doesn't close non-rfl... after rw the goal is `w ∈ SetOfZeros r (scaledZeta t) ↔ ‖w‖ ≤ r ∧ scaledZeta t w = 0`. Add `exact Iff.rfl` (defeq via SetOfZeros unfold + mem_setOf ✓). Hmm does w ∈ SetOfZeros r F reduce to the ∧? SetOfZeros R f := {ρ | ‖ρ‖ ≤ R ∧ f ρ = 0} — w ∈ {ρ | p ρ} ≡ p w ✓ defeq. Iff.rfl ✓.
11. `scaledZeroFinset_subset` proof: after rw [mem_scaledZeroFinset] at hw ⊢ — hw : ‖w‖ ≤ r₁ ∧ F w = 0; goal ‖w‖ ≤ r₂ ∧ F w = 0: exact ⟨hw.1.trans h, hw.2⟩ ✓.
12. For `analyticOrderAt_eq_zero` usage in scaledZeta_order_ne_top: `rw [analyticOrderAt_eq_zero]; exact Or.inr (by rw [scaledZeta_zero]; exact one_ne_zero)` — analyticOrderAt_eq_zero : order = 0 ↔ ¬AnalyticAt ∨ f z₀ ≠ 0. Goal: analyticOrderAt F 0 = 0. rw [analyticOrderAt_eq_zero] — rw with an Iff?? rw with Iff works (rewrites the Prop goal to the Iff RHS) ✓ goal becomes ¬AnalyticAt ℂ F 0 ∨ F 0 ≠ 0. Or.inr : F 0 ≠ 0: rw [scaledZeta_zero]: goal (1:ℂ) ≠ 0: one_ne_zero ✓. Hmm — `by rw [scaledZeta_zero]; exact one_ne_zero` — scaledZeta_zero t : scaledZeta t 0 = 1; rw in goal scaledZeta t 0 ≠ 0 turns into 1 ≠ 0 ✓.
Also `WithTop.zero_ne_top` — check existence: WithTop.zero_ne_top [Zero α] : (0 : WithTop α) ≠ ⊤? I believe `WithTop.zero_ne_top` exists. ℕ∞ = WithTop ℕ ✓. If not, `ENat.top_ne_zero.symm`? or simp. Compile will tell.
Also in `one_le_analyticOrderNatAt_scaledZeta` — `han.analyticOrderAt_ne_zero : analyticOrderAt f z₀ ≠ 0 ↔ f z₀ = 0` — .mpr hw0 : analyticOrderAt F w ≠ 0 ✓. Then `ENat.toNat_pos hne htop : 0 < (analyticOrderAt F w).toNat`. Goal: 1 ≤ analyticOrderNatAt F w — analyticOrderNatAt f z₀ is a DEF = (analyticOrderAt f z₀).toNat: `exact ENat.toNat_pos hne htop` — 0 < X.toNat vs 1 ≤ analyticOrderNatAt F w: 0 < n is Nat.lt 0 n = Nat.le 1 n ✓ defeq with Nat.lt = succ≤ : 0 < n ↔ 0+1 ≤ n — Nat.lt n m := n+1 ≤ m so 0 < X.toNat is 0+1 ≤ X.toNat; and 1 ≤ analyticOrderNatAt F w: defeq needs analyticOrderNatAt F w ≡ (analyticOrderAt F w).toNat — unfold: is analyticOrderNatAt reducible? plain def — exact uses defeq up to unfolding regular defs? `exact` uses default transparency for defeq — includes delta for regular defs ✓ should work. If not: `show 1 ≤ (analyticOrderAt (scaledZeta t) w).toNat` first... Nat 0< ↔ 1≤: `Nat.lt_iff_add_one_le`? 0 < n → 1 ≤ n is `Nat.succ_le_of_lt`? In ℕ, 0 < n and 1 ≤ n: Nat.succ_le_iff : 0+1 ≤ n ↔ 0 < n?? The exact term: h : 0 < n.toNat — goal 1 ≤ analyticOrderNatAt F w. Try `exact h` — if fails `exact Nat.succ_le_of_lt h` hmm 0+1 = 1: Nat.succ_le_of_lt : n < m → n+1 ≤ m: with n := 0: 0+1 ≤ m — is 0+1 ≤ m the same as 1 ≤ m definitionally? 0+1 reduces to 1 ✓. OK options ready.
Now let me also reconsider `Finset.sum_le_sum_of_subset_of_nonneg`'s signature in current Mathlib: `Finset.sum_le_sum_of_subset_of_nonneg (h : s₁ ⊆ s₂) (hf : ∀ i ∈ s₂, i ∉ s₁ → 0 ≤ f i) : ∑ i ∈ s₁, f i ≤ ∑ i ∈ s₂, f i` ✓.
Let me apply all fixes now. I'll rewrite the whole appended block cleanly (replace what I added).
Raw file confirmed (the `\` was a display artifact of `/`). Now fixing the chunk-1 errors — rewriting the appended block.
tool: Bash
input
{
"command": "cd \"D:/Python/Quantum/research/lean/NguyenRH1\" && python3 - <<'EOF'\nimport io\np = \"NguyenRH1/LiDisc.lean\"\ns = io.open(p, encoding='utf-8').read()\nmarker = \"/-! ## 5. The scaled norm bound as a standalone lemma; order helpers -/\"\nidx = s.index(marker)\nend = s.rindex(\"end NguyenRH1\")\ns = s[:idx] + s[end:]\nio.open(p, 'w', encoding='utf-8', newline='\\n').write(s)\nprint(\"trimmed to\", idx)\nEOF",
"description": "Remove the erroneous appended block"
}
thinking (1020 chars)
Wait — `collZeros_norm_le` uses `card96 t` but `card96` is defined AFTER it in my block. Need to move card96's def before collZeros_norm_le, or not use card96 there. Let me reorder: define card96 right after rC_gap (before collZeros). Actually in rC_gap the long expression `((scaledZeroFinset t (24/25) (by norm_num)).card : ℝ)` is what card96 abbreviates. Let me restructure: define card96 earlier and use it. But rC_gap's statement uses the explicit form... If I state rC_gap with card96 t, then collRadius_gap's explicit form must be converted: card96 t = that card by def (unfold). Simpler: keep rC_gap as-is, and in collZeros_norm_le don't use card96 — use the explicit form and add `unfold card96` issue away. Let me just inline the explicit form in collZeros_norm_le and define card96 after (for later use in Bbound etc.). Also then later lemmas can have a rewrite `card96_eq : (card96 t : ℝ) = ((scaledZeroFinset t (24/25) (by norm_num)).card : ℝ) := rfl`. Let me fix collZeros_norm_le to use the explicit form.
`collZeros_norm_le` references `card96` before its definition — fixing by inlining.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": "/-- Collected zeros lie strictly inside: \u2016w\u2016 \u2264 r_c \u2212 \u03b4w. -/\ntheorem collZeros_norm_le {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102} (hw : w \u2208 collZeros ht) :\n \u2016w\u2016 \u2264 rC ht - 1 / (50 * ((card96 t : \u211d) + 1)) := by\n have hmem := (mem_collZeros ht).mp hw\n have hw96 : w \u2208 scaledZeroFinset t (24 / 25) (by norm_num) :=\n scaledZeroFinset_subset (hr\u2082 := by norm_num) (rC_le ht) hw\n have hgap := rC_gap ht hw96\n have hle : \u2016w\u2016 \u2264 rC ht := hmem.1\n have hX : \u2016w\u2016 - rC ht \u2264 0 := sub_nonpos.mpr hle\n rw [abs_of_nonpos hX] at hgap\n unfold card96\n linarith\n\n/-- The cardinality of the 24/25-finset. -/\nnoncomputable def card96 (t : \u211d) : \u2115 :=\n (scaledZeroFinset t (24 / 25) (by norm_num)).card\n\n/-- The mult-weighted count over the collected zeros, as a natural. -/\nnoncomputable def collMultSum {t : \u211d} (ht : 10 \u2264 |t|) : \u2115 :=\n \u2211 \u03c1 \u2208 collZeros ht, analyticOrderNatAt (scaledZeta t) \u03c1",
"new_string": "/-- Collected zeros lie strictly inside: \u2016w\u2016 \u2264 r_c \u2212 \u03b4w. -/\ntheorem collZeros_norm_le {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102} (hw : w \u2208 collZeros ht) :\n \u2016w\u2016 \u2264 rC ht - 1 / (50 * (((scaledZeroFinset t (24 / 25)\n (by norm_num : (24/25:\u211d) \u2264 1)).card : \u211d) + 1)) := by\n have hmem := (mem_collZeros ht).mp hw\n have hw96 : w \u2208 scaledZeroFinset t (24 / 25) (by norm_num) :=\n scaledZeroFinset_subset (hr\u2082 := by norm_num) (rC_le ht) hw\n have hgap := rC_gap ht hw96\n have hle : \u2016w\u2016 \u2264 rC ht := hmem.1\n have hX : \u2016w\u2016 - rC ht \u2264 0 := sub_nonpos.mpr hle\n rw [abs_of_nonpos hX] at hgap\n linarith\n\n/-- The cardinality of the 24/25-finset. -/\nnoncomputable def card96 (t : \u211d) : \u2115 :=\n (scaledZeroFinset t (24 / 25) (by norm_num)).card\n\n/-- The mult-weighted count over the collected zeros, as a natural. -/\nnoncomputable def collMultSum {t : \u211d} (ht : 10 \u2264 |t|) : \u2115 :=\n \u2211 \u03c1 \u2208 collZeros ht, analyticOrderNatAt (scaledZeta t) \u03c1"
}
thinking (1221 chars)
The `positivity` tactic hits maxRecDepth on `0 < 2 * ((Z96.card : ℝ) + 1)` — probably because Z96 is a `set` variable and positivity tries to unfold it recursively. Fix: use explicit term proofs instead of positivity:
0 < 2 * ((Z96.card : ℝ) + 1): (Z96.card : ℝ) ≥ 0 (Nat.cast_nonneg) ⟹ (k:ℝ)+1 ≥ 1 > 0 ⟹ 2*(k+1) > 0.
```lean
have hpos2 : (0:ℝ) < 2 * ((Z96.card : ℝ) + 1) :=
mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)
```
and similarly hpos:
```lean
have hpos : (0:ℝ) < 20 * ((Z96.card : ℝ) + 1) :=
mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)
```
Also check the other positivity uses with the same pattern — in rC_gap I have hpos20/hpos50 with the full scaledZeroFinset expression — those might also loop? They compiled past line 547/552 only failing at these two — wait, only 2 errors reported, and rC_gap is LATER in the file — if earlier errors abort? No, Lean reports all errors. So rC_gap's positivities were fine?? Odd — maybe recursion came from Z96 being a `set`-bound local (positivity tries whnf of the let). rC_gap's expression uses scaledZeroFinset t (24/25) (by norm_num) directly — apparently fine. Let me just fix these two.
`positivity` loops on the `set`-bound Z96. Replacing with explicit term proofs.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": " have hpos2 : (0:\u211d) < 2 * ((Z96.card : \u211d) + 1) := by positivity\n have h1 := (div_le_iff\u2080 hpos2).mp h\n have h2 : 10 * |(5 / 2) * \u2016w\u2016 - T / 10| * (2 * ((Z96.card : \u211d) + 1))\n = |(5 / 2) * \u2016w\u2016 - T / 10| * (20 * ((Z96.card : \u211d) + 1)) := by ring\n rw [h2] at h1\n have hpos : (0:\u211d) < 20 * ((Z96.card : \u211d) + 1) := by positivity\n exact (div_le_iff\u2080 hpos).mpr h1",
"new_string": " have hpos2 : (0:\u211d) < 2 * ((Z96.card : \u211d) + 1) :=\n mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)\n have h1 := (div_le_iff\u2080 hpos2).mp h\n have h2 : 10 * |(5 / 2) * \u2016w\u2016 - T / 10| * (2 * ((Z96.card : \u211d) + 1))\n = |(5 / 2) * \u2016w\u2016 - T / 10| * (20 * ((Z96.card : \u211d) + 1)) := by ring\n rw [h2] at h1\n have hpos : (0:\u211d) < 20 * ((Z96.card : \u211d) + 1) :=\n mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)\n exact (div_le_iff\u2080 hpos).mpr h1"
}
thinking (574 chars)
Chunk 1 compiles — only a warning (unused `ht` in scaledZeroFinset_card_le_sum? no wait, line 526 — that's in... let me check what's at 526 — probably `scaledZeroFinset_card_le_sum` doesn't use ht? It does: one_le_analyticOrderNatAt_scaledZeta ht. Line 526 might be `scaledZeroFinset_sum_order_le`'s ht — used in exact_mod_cast jensen ht... Hmm, or `scaledZeroFinset_subset` region. Actually a warning is fine, but let me see which decl. Line 526: within scaledZeroFinset_sum_order_le probably — no wait, ht IS used there (scaledZeta_jensen_count ht). Let me check line 526.
Chunk 1 compiles (one unused-var warning). Checking line 526.
tool: Read
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"offset": 520,
"limit": 12
}
thinking (22299 chars)
The warning: `exists_collection_radius`'s ht is unused (as I noted, the gap is combinatorial). But `collRadius ht` etc. take ht. Keep it (harmless warning; the API uniformity is worth it). Actually — unused variable warning only. Fine.
Chunk 1 GREEN. Now chunk 2: the Cf characterizations + B (g) lemmas. Let me write §8:
```lean
/-! ## 8. The Blaschke-quotient g := Cf r_c F: characterization, analyticity, nonvanishing -/
/-- The product over the collected zeros. -/
noncomputable def collProd {t : ℝ} (ht : 10 ≤ |t|) (w : ℂ) : ℂ :=
∏ ρ ∈ collZeros ht, (w - ρ) ^ analyticOrderNatAt (scaledZeta t) ρ
```
Cf characterizations:
```lean
theorem collZeros_toFinset_eq {t : ℝ} (ht : 10 ≤ |t|)
(hfin : (SetOfZeros (rC ht) (scaledZeta t)).Finite) :
hfin.toFinset = collZeros ht :=
Set.Finite.toFinset_inj.mpr rfl
```
Wait — collZeros = scaledZeroFinset t (rC ht) _ = (subset-derived .Finite).toFinset. hfin.toFinset vs that: toFinset_inj.mpr rfl : needs sets equal: SetOfZeros (rC ht) F = SetOfZeros (rC ht) F ✓ rfl. And toFinset_inj : hs.toFinset = ht.toFinset ↔ s = t where hs : s.Finite — hs := hfin : (SetOfZeros (rC ht) F).Finite; ht' := subset-derived : (SetOfZeros (rC ht) F).Finite ✓ rfl ✓.
```lean
theorem Cf_eq_div_collProd {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : w ∉ SetOfZeros (rC ht) (scaledZeta t)) :
Cf (rC ht) (scaledZeta t) w = scaledZeta t w / collProd ht w := by
classical
have hfin : (SetOfZeros (rC ht) (scaledZeta t)).Finite :=
scaledZeta_zeros_finite.subset (t := SetOfZeros (rC ht) (scaledZeta t)) fun x hx => by
obtain ⟨h1, h2⟩ := hx
exact ⟨h1.trans (rC_lt_one ht).le, h2⟩
unfold Cf collProd
simp only [hfin, ↓reduceDIte, hw, if_false]
congr 2
exact collZeros_toFinset_eq ht hfin
```
Hmm — after unfold Cf: the term is `if finite_zeros_mono : ... then if w ∈ ... then ... else scaledZeta t w / ∏ ρ ∈ finite_zeros_mono.toFinset, ... else 1`. simp only [hfin, ↓reduceDIte] reduces outer dite; then `hw` : w ∉ SetOfZeros — the inner if's condition is `w ∈ SetOfZeros (rC ht) (scaledZeta t)` — simp only [hw]? hw is a ¬p; simp only [hw] uses ¬p to close if_neg? Use `if_neg hw`... The inner if: `if _ : w ∈ SetOfZeros r f then ... else f w / ∏ ...` — also a dite (binder _). simp only with ↓reduceDIte needs a proof of ¬(w ∈ ...) — that's hw ✓. So `simp only [hfin, hw, ↓reduceDIte]`? ↓reduceDIte fires when the condition is decided by an instance... hmm — in Zeta23's proofs: `simp only [finite_zeros_mono, ↓reduceDIte]` where finite_zeros_mono : (SetOfZeros r f).Finite (a POSITIVE fact) — reduces dite with the proof. For the negative: hw : w ∉ ... = ¬(w ∈ ...) = (w ∈ ... → False). simp only [hw] rewrites the proposition w ∈ ... to False? simp can use ¬p as p ↔ False ✓. Then ↓reduceDIte with decidability... Let me follow the pattern from CfAnalytic's proof: they did `by_cases w_in_zeros : w ∈ SetOfZeros r f; · simp only [finite_zeros_mono, ↓reduceDIte]` — wait they had both dites... their simp only [finite_zeros_mono, ↓reduceDIte] then inside the case they `rw [dif_pos w_in_zeros]` / `rw [dif_neg z_not_in]`. So the pattern: simp only [hfin, ↓reduceDIte] for the outer, then `rw [dif_neg hw]` for the inner? But the inner if's instance: it's `if _ : z ∈ SetOfZeros r f then ... else ...` — a dite. rw [dif_neg hw]: dif_neg needs the dite's decidability instance to match — dif_neg (h : ¬c) : dite c a b = b (hmm for dite it's `dif_neg : ¬c → dite c (λ h => a) (λ h => b) = b h`...). In Lean4 Mathlib: `dif_neg (h : ¬c) : (if h : c then a h else b h) = b h` ✓ should work with any instance (instance appears in both sides uniformly).
So:
```lean
unfold Cf
simp only [hfin, ↓reduceDIte]
rw [dif_neg hw]
```
then goal: scaledZeta t w / ∏ ρ ∈ hfin.toFinset, (w − ρ) ^ analyticOrderNatAt (scaledZeta t) ρ = scaledZeta t w / collProd ht w. collProd := ∏ ρ ∈ collZeros ht, ...: congr 1 (div args): prod arg: hfin.toFinset = collZeros ht (collZeros_toFinset_eq) — rw [collZeros_toFinset_eq ht hfin]?? direction: goal has hfin.toFinset; collZeros_toFinset_eq : hfin.toFinset = collZeros ht: rw [collZeros_toFinset_eq ht hfin] makes it collZeros ht; then collProd ht w unfolds to exactly ∏ ρ ∈ collZeros ht, ... — rfl after unfold collProd. So:
```lean
rw [collZeros_toFinset_eq ht hfin]
rfl -- or unfold collProd
```
Hmm — the ∏ binder form might differ: ∏ ρ ∈ s, (w − ρ) ^ analyticOrderNatAt (scaledZeta t) ρ on both sides ✓ syntactically identical after the finset rewrite (collProd unfolds definitionally — rfl should work since collProd ht w ≡ ∏ ρ ∈ collZeros ht, (w − ρ) ^ ... ✓ delta+beta).
Wait — but there's the `classical` need: Cf's dites use Classical.propDecidable instance baked in. dif_neg hw works for any decidable instance ✓.
And the zero-case:
```lean
theorem Cf_eq_zeroFactor_div {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : w ∈ SetOfZeros (rC ht) (scaledZeta t)) :
Cf (rC ht) (scaledZeta t) w = ZeroFactor (scaledZeta t) w /
∏ ρ ∈ collZeros ht \ {w}, (w - ρ) ^ analyticOrderNatAt (scaledZeta t) ρ := by
classical
have hfin : ... := ...
unfold Cf
simp only [hfin, ↓reduceDIte]
rw [dif_pos hw, collZeros_toFinset_eq ht hfin]
```
✓.
Now — SetOfZeros membership vs collZeros membership: w ∈ SetOfZeros (rC ht) F ⟺ ‖w‖ ≤ rC ht ∧ F w = 0 (defeq) ⟺ w ∈ collZeros ht (mem_collZeros — but that goes through toFinset of the SUBSET-derived proof; the set is SetOfZeros (rC ht) F so membership in the set is direct). So `hw : w ∈ SetOfZeros (rC ht) (scaledZeta t)` directly gives ⟨hw.1, hw.2⟩? membership in a setOf-def set is the predicate — need whnf: use `have ⟨h1, h2⟩ := hw` (anonymous constructor dest unfolds ✓).
B analyticity:
```lean
theorem Cf_collZeros_analytic {t : ℝ} (ht : 10 ≤ |t|) :
AnalyticOnNhd ℂ (Cf (rC ht) (scaledZeta t)) (Metric.closedBall 0 ((1 + rC ht) / 2)) := by
apply CfAnalytic
· -- r_c < (1 + r_c)/2
have h1 := rC_lt_one ht
linarith [rC_pos ht]
· -- (1 + r_c)/2 < 1
have h1 := rC_lt_one ht
linarith
· exact scaledZeta_analytic ht
· rw [scaledZeta_zero]; exact one_ne_zero
```
CfAnalytic (r_lt_R : r < R) (R_lt_one : R < 1) (hfAnalytic : AnalyticOnNhd ℂ f (closedBall 0 1)) (hf_neq_zero_at_zero : f 0 ≠ 0) : AnalyticOnNhd ℂ (Cf r f) (closedBall 0 R). Implicit r, R, f. apply should unify. ✓
B nonvanishing:
```lean
theorem Cf_collZeros_ne_zero {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : w ∈ Metric.closedBall 0 (rC ht)) :
Cf (rC ht) (scaledZeta t) w ≠ 0 := by
rw [Metric.mem_closedBall, dist_zero_right] at hw
by_cases h0 : scaledZeta t w = 0
· -- w is a collected zero: ZeroFactor / product-of-others
have hwS : w ∈ SetOfZeros (rC ht) (scaledZeta t) := ⟨hw, h0⟩
rw [Cf_eq_zeroFactor_div ht hwS]
apply div_ne_zero
· -- ZeroFactor ≠ 0
obtain ⟨h_w, h_w_an, h_w_ne, hZF, _⟩ := ZeroFactorization (rC_lt_one ht)
(scaledZeta_analytic ht) (by rw [scaledZeta_zero]; exact one_ne_zero) hwS
rw [hZF] -- ZeroFactor F w = h_w w
exact h_w_ne
· -- product over ZW \ {w} ≠ 0
apply Finset.prod_ne_zero_iff.mpr
intro ρ hρ
have hρne : ρ ≠ w := fun h => (Finset.mem_sdiff.mp hρ).2 (Finset.mem_singleton.mpr h)
exact pow_ne_zero _ (sub_ne_zero.mpr (fun h => hρne h.symm))
· -- else-branch: F w / product
have hwS : w ∉ SetOfZeros (rC ht) (scaledZeta t) := fun h => h0 h.2
rw [Cf_eq_div_collProd ht hwS]
apply div_ne_zero h0
unfold collProd
apply Finset.prod_ne_zero_iff.mpr
intro ρ hρ
have hρ0 : scaledZeta t ρ = 0 := ((mem_collZeros ht).mp hρ).2
exact pow_ne_zero _ (sub_ne_zero.mpr (fun h => h0 (h ▸ hρ0)))
```
Wait — ZeroFactorization signature: {R : ℝ} {f} {ρ} (RleOne : R < 1) (hfAnalytic : AnalyticOnNhd ℂ f (closedBall 0 1)) (hf_neq_zero_at_zero : f 0 ≠ 0) (hρ : ρ ∈ SetOfZeros R f) : ∃ h_ρ, AnalyticAt ℂ h_ρ ρ ∧ h_ρ ρ ≠ 0 ∧ ZeroFactor f ρ = h_ρ ρ ∧ f =ᶠ[nhds ρ] fun z ↦ (z − ρ) ^ analyticOrderNatAt f ρ * h_ρ z. With R := rC ht: RleOne : rC ht < 1 ✓. Implicit R unified by hρ ✓. obtain ⟨h_w, h_w_an, h_w_ne, hZF, hfact⟩. ✓
Hmm — `fun h => hρne h.symm`: sub_ne_zero.mpr : w − ρ ≠ 0 from w ≠ ρ: sub_ne_zero.mpr (h : a ≠ b) : a − b ≠ 0 — a := w, b := ρ: need w ≠ ρ: hρne : ρ ≠ w ⟹ w ≠ ρ := hρne.symm? Ne.symm : ρ ≠ w → w ≠ ρ ✓ so `sub_ne_zero.mpr hρne.symm`... I wrote fun h => hρne h.symm — h : w = ρ ⟹ h.symm : ρ = w ⟹ hρne h.symm : False ✓ equivalent. Use `sub_ne_zero.mpr hρne.symm` cleaner — hmm Ne.symm hρne. `hρne.symm` : Ne is symmetric via Ne.symm — dot notation hρne.symm works (Ne.symm). ✓ Let me use that.
For the last: h : w = ρ ⟹ scaledZeta t w = scaledZeta t ρ = 0: `fun h => h0 (h ▸ hρ0)` — h ▸ hρ0 : rewrites w to ρ... h : w = ρ; hρ0 : scaledZeta t ρ = 0; h ▸ hρ0 rewrites ρ → w in hρ0? ▸ direction: h : w = ρ, h ▸ hρ0 rewrites w by ρ in... ugh. Clearer: `fun h => h0 (by rw [h]; exact hρ0)`. ✓
B center:
```lean
theorem Cf_collZeros_zero : Cf (rC ht) (scaledZeta t) 0 = 1 / ∏ ρ ∈ collZeros ht, (0 - ρ) ^ ...
```
Actually I need log‖B 0‖ ≥ 0. B 0 = F 0/prod = 1/prod since 0 ∉ zeros (F 0 = 1 ≠ 0).
```lean
theorem Cf_collZeros_log_norm_zero_nonneg {t : ℝ} (ht : 10 ≤ |t|) :
0 ≤ Real.log ‖Cf (rC ht) (scaledZeta t) 0‖ := by
have h0S : (0:ℂ) ∉ SetOfZeros (rC ht) (scaledZeta t) := by
intro h
have h2 := h.2
rw [scaledZeta_zero] at h2
exact one_ne_zero h2
rw [Cf_eq_div_collProd ht h0S, scaledZeta_zero]
-- ‖1 / ∏ (0 − ρ)^m‖ = 1 / ∏ ‖ρ‖^m; log ≥ 0 since ∏ ‖ρ‖^m ≤ 1
have hprod_norm : ‖collProd ht 0‖ = ∏ ρ ∈ collZeros ht, ‖ρ‖ ^ analyticOrderNatAt (scaledZeta t) ρ := by
unfold collProd
rw [norm_prod]
apply Finset.prod_congr rfl
intro ρ hρ
rw [norm_pow, norm_zero_sub... ] -- ‖0 − ρ‖ = ‖ρ‖: norm_neg? 0 − ρ = −ρ: zero_sub, norm_neg
rw [zero_sub, norm_neg]
rw [hprod_norm, norm_div, norm_one]
-- log (1 / ∏‖ρ‖^m) ≥ 0 ⟸ ∏‖ρ‖^m ≤ 1 ⟸ each ‖ρ‖ ≤ rC − δw < 1... actually ≤ rC ≤ 24/25 < 1
have hprod_le : ∏ ρ ∈ collZeros ht, ‖ρ‖ ^ analyticOrderNatAt (scaledZeta t) ρ ≤ 1 := by
apply Finset.prod_le_one ... -- each factor ≤ 1 (‖ρ‖ ≤ rC ≤ 24/25 < 1, pow_le_one₀), each ≥ 0
have hprod_pos : 0 < ∏ ... := by
apply Finset.prod_pos
intro ρ hρ
exact pow_pos (norm_pos_iff.mpr (fun h0 => ...)) _ -- ρ ≠ 0 since F ρ = 0 but F 0 = 1
rw [Real.log_div] ... -- log (1/x) = log 1 − log x = −log x ≥ 0 ⟸ log x ≤ 0 ⟸ x ≤ 1, x ≥ 0
```
Hmm — Real.log_div : log (x/y) = log x − log y (needs y ≠ 0: Real.log_div (hy : y ≠ 0)? signature: Real.log_div (hx : x ≠ 0) (hy : y ≠ 0)? hmm — for reals log (x/y) = log x − log y needs x,y ≠ 0. `Real.log_div (hx : x ≠ 0) (hy : y ≠ 0)` ✓. Then log 1 − log(prod) = −log(prod) ≥ 0 ⟸ log(prod) ≤ 0 ⟸ 0 ≤ prod ≤ 1: Real.log_nonpos (hx : 0 ≤ x) (h : x ≤ 1) : log x ≤ 0 ✓.
Wait — careful: ‖B 0‖ = ‖1/prod‖ = 1/‖prod‖ — the target is 0 ≤ log(1/‖prod‖). Let me restructure: 0 ≤ log(1/x) ⟺ log x ≤ 0 (x > 0). ✓ as above.
Finset.prod_le_one: `Finset.prod_le_one (h0 : ∀ i ∈ s, 0 ≤ f i) (h1 : ∀ i ∈ s, f i ≤ 1) : ∏ i ∈ s, f i ≤ 1` ✓ (ordered comm monoid... ℝ ✓). Each factor ‖ρ‖^m ≤ 1: ‖ρ‖ ≤ rC ≤ 24/25 ≤ 1: pow_le_one₀ (norm_nonneg) (h : ‖ρ‖ ≤ 1) ✓.
ρ ≠ 0 for ρ ∈ collZeros: F ρ = 0; if ρ = 0 then F 0 = 1 ≠ 0 contradiction: `fun h0 => by rw [← h0] at ... ` careful: h0 : ρ = 0; mem gives F ρ = 0; subst or rw h0 at it: scaledZeta t 0 = 0 vs scaledZeta_zero : = 1 ⟹ one_ne_zero. ✓
B sphere bound:
```lean
theorem Cf_collZeros_norm_le_sphere {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : ‖w‖ = rC ht) :
‖Cf (rC ht) (scaledZeta t) w‖ ≤ (9 / 4) * |t| ^ 2 *
(50 * ((card96 t : ℝ) + 1)) ^ collMultSum ht := by
-- no zeros on the sphere
have hwS : w ∉ SetOfZeros (rC ht) (scaledZeta t) := by
intro hmem
have hmemZ : w ∈ collZeros ht := (mem_collZeros ht).mpr ⟨hmem.1, hmem.2⟩
have hle := collZeros_norm_le ht hmemZ
rw [hw] at hle
-- rC ≤ rC − δw with δw > 0: contradiction
have hδ : (0:ℝ) < 1 / (50 * ((card96 t : ℝ) + 1)) := by
apply div_pos (by norm_num)
unfold card96
exact mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)
linarith
rw [Cf_eq_div_collProd ht hwS, norm_div]
-- ‖F w‖ ≤ (9/4)|t|²
have hF : ‖scaledZeta t w‖ ≤ (9 / 4) * |t| ^ 2 :=
norm_scaledZeta_le ht (hw ▸ (rC_le ht).trans (by norm_num))
-- ‖P w‖ ≥ δw^{M_c}
...
```
Hmm wait — collZeros_norm_le gives ‖w‖ ≤ rC − 1/(50*((card96... hold on — collZeros_norm_le's statement uses the explicit card expression ((scaledZeroFinset t (24/25) (by norm_num)).card : ℝ), and card96 t is DEFINED as that card. The δw in collZeros_norm_le: `1 / (50 * (((scaledZeroFinset t (24 / 25) (by norm_num)).card : ℝ) + 1))`. And card96 t unfolds to that card — `(card96 t : ℝ) = (((scaledZeroFinset ...).card : ℝ))` by unfold card96; push_cast/rfl. So in hδ I unfold card96 to match. Let me add a bridge lemma:
```lean
theorem card96_cast (t : ℝ) : (card96 t : ℝ) =
((scaledZeroFinset t (24 / 25) (by norm_num : (24/25:ℝ) ≤ 1)).card : ℝ) := rfl
```
rfl should work (card96 is a def; cast of card). Then use it to convert hgap/collZeros_norm_le forms into card96 form. In collZeros_norm_le I could just state with card96 t directly and do the conversion inside its proof via card96_cast. Cleaner! Let me restate collZeros_norm_le with card96 t and convert:
```lean
theorem collZeros_norm_le {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ} (hw : w ∈ collZeros ht) :
‖w‖ ≤ rC ht - 1 / (50 * ((card96 t : ℝ) + 1)) := by
have hmem := (mem_collZeros ht).mp hw
have hw96 : w ∈ scaledZeroFinset t (24 / 25) (by norm_num) :=
scaledZeroFinset_subset (hr₂ := by norm_num) (rC_le ht) hw
have hgap := rC_gap ht hw96 -- explicit card form
have hle : ‖w‖ ≤ rC ht := hmem.1
have hX : ‖w‖ - rC ht ≤ 0 := sub_nonpos.mpr hle
rw [abs_of_nonpos hX] at hgap
-- hgap : 1/(50*(↑(card of 24/25 finset) + 1)) ≤ −(‖w‖ − rC ht)
have hcast : (card96 t : ℝ) = ... := rfl
linarith [hgap] -- needs the atom match: ↑(card96 t) vs ↑(explicit card): linarith sees them as different atoms!
```
linarith matches atoms syntactically — ↑(card96 t) ≠ ↑((scaledZeroFinset ...).card) syntactically. So rw [card96] at ... no. Add: `have hcast : ((scaledZeroFinset t (24/25) (by norm_num : (24/25:ℝ) ≤ 1)).card : ℝ) = (card96 t : ℝ) := rfl; rw [hcast] at hgap`. Then linarith with matching atoms ✓. Let me restructure collZeros_norm_le that way. And rC_gap could ALSO be restated with card96... but rC_gap's proof goes through collRadius_gap whose statement is fixed with the explicit form — do the same hcast-rw trick there. Hmm — simpler: define card96 FIRST (before exists_collection_radius) and state everything with card96, converting at the boundaries where exists_avoiding_midpoint's k = Z96.card — in exists_collection_radius the statement uses the explicit card; I could restate with card96 t... but card96 t := (scaledZeroFinset t (24/25) (by norm_num)).card — the explicit form in exists_collection_radius IS (scaledZeroFinset t (24/25) (by norm_num)).card — syntactically same! (by norm_num proofs are proof-irrelevant-equal ✓ syntactic match of terms: (by norm_num) vs (by norm_num) — same tactic text, same elaborated term? by norm_num elaborates to some proof term — two separate elaborations might produce different proof terms?? Both prove (24/25:ℝ) ≤ 1 — norm_num produces a term like `of_reduceBool...`? could differ? They're both proofs of a Prop — for the FINSET equality scaledZeroFinset t (24/25) h1 = scaledZeroFinset t (24/25) h2: proof irrelevance gives defeq, but SYNTACTIC atom-matching (linarith) needs syntactic equality of atoms — the atoms are ↑(Finset.card (scaledZeroFinset t (24/25) ⋯)) — pretty printer shows ⋯ for the proof — the underlying terms: if elaborated differently they'd be different atoms syntactically BUT linarith compares atoms up to reducible defeq? linarith uses syntactic comparison up to instances... risky. SAFEST: use card96 everywhere and ONE conversion lemma. Let me restructure:
- Define card96 right after scaledZeroFinset (+ mem).
- State exists_collection_radius with (card96 t : ℝ) in the clearance — inside the proof, Z96 := scaledZeroFinset t (24/25) _; the pigeonhole gives clearance 1/(2*(Z96.card+1)); and Z96.card = card96 t by rfl (Z96 is `set`-bound — set replaces occurrences... hmm set with hZ96 rewrites goal occurrences. If the statement has card96 t, then after `set Z96 := scaledZeroFinset ...` the goal's card96 t is NOT syntactically scaledZeroFinset... — set only abstracts the given pattern. So statement-with-card96 + proof-with-Z96 needs unfolding card96. `unfold card96` at proof start? The goal would become the explicit form ✓. OK.
Plan: keep exists_collection_radius statement with explicit card (as now — it compiled!), and card96 defined after with `card96_cast : (card96 t : ℝ) = ↑((scaledZeroFinset t (24/25) (by norm_num)).card) := rfl`, and use hcast rewrites at use sites. Actually collZeros_norm_le's statement: I want card96 form for downstream (Bbound uses card96). Do the hcast trick inside. Fine — implement.
Actually, hmm, wait: is `(card96 t : ℝ) = ((scaledZeroFinset t (24/25) (by norm_num)).card : ℝ)` really `rfl`? card96 t := (scaledZeroFinset t (24/25) (by norm_num)).card — the (by norm_num) in the DEF is elaborated once; the one in the lemma statement elaborated separately — same tactic, same goal ⟹ same proof term (deterministic elaboration) ⟹ rfl ✓ almost surely (norm_num is deterministic). And even if proof terms differed, proof irrelevance makes them defeq so `rfl` still works (rfl checks defeq up to proof irrelevance ✓). So card96_cast := rfl is safe.
Then collZeros_norm_le with card96: inside, `rw [← card96_cast]`?? hgap comes in explicit form; convert hgap to card96 form by rw [← card96_cast] at hgap (replaces explicit cast with card96 cast). ✓ Then linarith.
Let me also double check the FINAL Bbound form: (9/4)*|t|^2 * (50*((card96 t : ℝ)+1))^(collMultSum ht). The exponent: collMultSum ht : ℕ = Σ orders over collZeros.
For the sphere bound's product estimate: ∏_{ρ ∈ ZW} ‖w−ρ‖^{m_ρ} ≥ ∏ (δw)^{m_ρ} = δw^{Σ m} (Finset.prod_pow_eq_pow_sum reversed: ∏ δw^{m} = δw^{Σ m} via Finset.prod_pow_eq_pow_sum : ∏ a^f = a^(Σ f) ✓). Each ‖w−ρ‖ ≥ δw: ‖w‖ = rC, ‖ρ‖ ≤ rC − δw ⟹ ‖w−ρ‖ ≥ ‖w‖ − ‖ρ‖ ≥ rC − (rC − δw) = δw (norm_sub_norm_le... ‖w‖ − ‖ρ‖ ≤ ‖w−ρ‖: norm_sub_norm_le w ρ : ‖w‖ − ‖ρ‖ ≤ ‖w − ρ‖? `norm_sub_norm_le : ‖a‖ − ‖b‖ ≤ ‖a − b‖` ✓). pow_le_pow_left₀ (δw ≥ 0) (δw ≤ ‖w−ρ‖) m ✓. And each factor positive for the div: ‖w−ρ‖ > 0 since ≥ δw > 0 ✓ — need δw > 0: 1/(50(k+1)) > 0 ✓.
Then ‖B w‖ = ‖F w‖/‖P w‖ ≤ ((9/4)|t|²)/δw^{M_c}: div_le_div (hF : ‖F‖ ≤ (9/4)|t|²) (hP : δw^M ≤ ‖P‖) (pow_pos δw>0) (norm_nonneg): the 4-arg div_le_div : a/d ≤ b/c?? order: `div_le_div (h₁ : a ≤ b) (h₂ : c ≤ d) (h₃ : 0 < c) (h₄ : 0 ≤ a) : a / d ≤ b / c` — so a := ‖F‖, b := (9/4)|t|², c := δw^M, d := ‖P‖: gives ‖F‖/‖P‖ ≤ (9/4)|t|²/δw^M ✓ with h₁ := hF, h₂ := hP, h₃ := pow_pos, h₄ := norm_nonneg. Then (9/4)|t|²/δw^M = (9/4)|t|² · (1/δw)^M: 1/δw = 50(k+1): δw = 1/(50(k+1)): (1/(50(k+1)))^{-...}... δw^M in denominator: X/δw^M = X·(δw^M)⁻¹ = X·(δw⁻¹)^M (inv_pow) and δw⁻¹ = 50(k+1): δw = 1/(50(k+1)) ⟹ δw⁻¹ = 50(k+1) (one_div, inv_inv... inv (1/y) = y via div_one/inv... (1/y)⁻¹ = y: `inv_inv`? hmm δw as written is `1 / (50 * (k+1))` — its inverse: (1/y)⁻¹ = y: inv_inv? no: (x⁻¹)⁻¹ = x is inv_inv; 1/y = y⁻¹ via one_div... (1/y)⁻¹ = y⁻¹⁻¹ = y: rw [one_div, inv_inv]). So X/δw^M = X·(50(k+1))^M: div_eq_mul_inv, inv_pow, one_div (δw = 1/E so δw^M = 1/E^M...). Let me just compute: δw^M = (1/E)^M = 1/E^M (one_pow_div... `div_pow`? (1/E)^M = 1^M/E^M = 1/E^M: one_div_pow? there's `one_div_pow : (1/a)^n = 1/a^n`? or div_pow + one_pow). Then X/(1/E^M) = X·E^M (div_one... X/(1/y) = X·y: `div_one_div`? X/(1/y) = X*y: field_simp or `div_div_cancel'`... simplest: `div_one_div_eq_mul`? Let me just use field_simp at the end with E ≠ 0. Or avoid: state the sphere bound as ‖B w‖ ≤ (9/4)*|t|² / δw^(M_c) and let the BALL bound (and M_bound) use the /δw^M form, converting to the (50(k+1))^M form only in the log computation... For log: log(X/δw^M) = log X + M·log(1/δw)... Real.log_div (X≠0) (δw^M≠0): log X − log(δw^M) = log X − M·log δw; log δw = log(1/E) = −log E (Real.log_one_div? `Real.log_div` with 1: log(1/E) = log 1 − log E = −log E); so −M·log δw = M·log E ✓. And log X = log(9/4)+2L ✓. So M_bound := log((9/4)|t|²) + M_c·log(50(k+1)) and ‖B w‖ ≤ X/δw^M ⟹ log‖B w‖ ≤ log X + M·log E — via Real.log_le_log (‖B w‖ > 0? need B w ≠ 0 ✓ from nonvanishing... on the sphere/closed ball ✓) then the log identities. OK — keep Bbound := (9/4)*|t|^2 / δw^(M_c) with δw := 1/(50*(card96 t + 1)) — hmm δw as a def? Let me define:
```lean
/-- The gap scale δw = 1/(50(k+1)). -/
noncomputable def δw (t : ℝ) : ℝ := 1 / (50 * ((card96 t : ℝ) + 1))
```
Greek letter names are fine in Lean but the project's convention... LiSkeleton uses C0hat etc. Let me name it `gapδ`? or `dwGap`. I'll use `gapD (t : ℝ) : ℝ := 1 / (50 * ((card96 t : ℝ) + 1))`. Noncomputable not needed (pure real expr) but fine as plain def. Positivity lemma: gapD_pos.
And collZeros_norm_le becomes: ‖w‖ ≤ rC ht − gapD t. rC_gap becomes: gapD t ≤ |‖w‖ − rC ht|. Cleaner. But rC_gap's proof concludes the explicit form — convert via card96_cast inside (gapD t unfolds to explicit after unfold gapD + card96_cast rw).
Hmm, wait — gapD def uses card96 which needs the explicit finset — all fine (defs after card96).
Let me restructure the order:
1. scaledZeroFinset + mem + subset + 24_25_eq + sum_order_le + card_le_sum (§6, as now).
2. card96 def + card96_cast + card96_pos-ish.
3. gapD def + gapD_pos.
4. exists_collection_radius (explicit form — keep), collRadius bundle, rC bundle, rC_gap (state with gapD; prove by converting collRadius_gap's explicit form), collZeros + mem + collZeros_norm_le (gapD form), collMultSum.
5. collProd, Cf characterizations, Cf_analytic, Cf_ne_zero, Cf log-norm-center ≥ 0, Cf sphere bound, Cf ball bound (max-modulus).
6. J_B + BC + main theorem.
Let me now rewrite the tail (from rC_gap on) to use gapD, and add card96/gapD defs after card_le_sum. I'll edit the file: replace from "/-! ## 7." to the end with the restructured version, and add card96+gapD into §6. Actually §6 currently ends with scaledZeroFinset_card_le_sum; §7 starts with exists_collection_radius (no card96). Let me just append card96/gapD defs at the start of §7 and rewrite rC_gap/collZeros_norm_le statements in gapD form.
Chunk 1 compiles. Now restructuring §7 to route everything through named `card96`/`gapD` (avoids syntactic-atom mismatches downstream), then §8 (the Cf/g machinery).
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": "/-! ## 7. The R-gap selection (\u00d710 rescale of the midpoint pigeonhole) -/\n\n/-- **The collection radius**: R_c \u2208 [2.3, 2.4] at distance \u2265 1/(20(k+1))",
"new_string": "/-! ## 7. The R-gap selection (\u00d710 rescale of the midpoint pigeonhole) -/\n\n/-- The cardinality of the 24/25-finset. -/\nnoncomputable def card96 (t : \u211d) : \u2115 :=\n (scaledZeroFinset t (24 / 25) (by norm_num)).card\n\ntheorem card96_cast (t : \u211d) :\n (card96 t : \u211d) = ((scaledZeroFinset t (24 / 25)\n (by norm_num : (24/25:\u211d) \u2264 1)).card : \u211d) := rfl\n\n/-- The gap scale \u03b4w = 1/(50(k+1)), k = card96. -/\nnoncomputable def gapD (t : \u211d) : \u211d := 1 / (50 * ((card96 t : \u211d) + 1))\n\ntheorem gapD_pos (t : \u211d) : 0 < gapD t := by\n unfold gapD\n apply div_pos (by norm_num)\n exact mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)\n\ntheorem gapD_le (t : \u211d) : gapD t \u2264 1 / 50 := by\n unfold gapD\n apply (div_le_div_iff_of_pos_left (by norm_num) (by norm_num : (0:\u211d) < 50 * 1)\n (mul_pos (by norm_num : (0:\u211d) < 50)\n (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos))).mpr\n rw [mul_one]\n exact mul_le_mul_of_nonneg_left (by linarith [Nat.cast_nonneg (card96 t)]) (by norm_num)\n\n/-- **The collection radius**: R_c \u2208 [2.3, 2.4] at distance \u2265 1/(20(k+1))"
}
thinking (12389 chars)
Now append §8 (Cf/g machinery): collProd, Cf characterizations, analyticity, nonvanishing, center log-norm, sphere bound, ball bound. Insert before `end NguyenRH1`.
For the sphere bound, statement:
```lean
theorem Cf_collZeros_norm_le_sphere {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : ‖w‖ = rC ht) :
‖Cf (rC ht) (scaledZeta t) w‖ ≤ (9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht
```
And ball bound:
```lean
theorem Cf_collZeros_norm_le_ball {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : w ∈ Metric.closedBall 0 (rC ht)) :
‖Cf (rC ht) (scaledZeta t) w‖ ≤ (9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht
```
via AnalyticOn.norm_le_of_norm_le_on_sphere (r := rC) (R := (1+rC)/2).
For the max-modulus I need AnalyticOn ℂ B (closedBall 0 R) — from Cf_collZeros_analytic (AnalyticOnNhd on closedBall(0, R)) .analyticOn. Sphere membership: z ∈ Metric.sphere 0 (rC ht) ⟺ ‖z‖ = rC ht (mem_sphere_iff_norm, sub_zero). ✓
Then §9 in the next chunk: J_B + BC + main theorem.
Let me write §8 now. Careful details:
collProd:
```lean
/-- The product over the collected zeros, P(w) = ∏ (w−ρ)^{m_ρ}. -/
noncomputable def collProd {t : ℝ} (ht : 10 ≤ |t|) (w : ℂ) : ℂ :=
∏ ρ ∈ collZeros ht, (w - ρ) ^ analyticOrderNatAt (scaledZeta t) ρ
```
Cf char lemmas as drafted. Note: in Cf_eq_div_collProd, after `unfold Cf`, the goal: Cf's body with dite — need `classical` for the dite instance? The Cf def was ELABORATED with Classical open in Zeta23 — the instance is Classical.propDecidable baked into the term. simp only [hfin, ↓reduceDIte] — hfin : the proposition — simp only [h : p] rewrites p to True; ↓reduceDIte reduces dite True ... ✓ this is the Zeta23 pattern. I don't need `classical` in MY proof (the instance is in the term already). But to be safe add it.
Wait — one concern: `unfold Cf` — Cf is noncomputable def with the dite inside. unfold should work.
After simp only [hfin, ↓reduceDIte]: goal `Cf r_c F w = ...` — hmm unfold replaces `Cf (rC ht) (scaledZeta t) w` by its body — but Cf has (f) (r) (z) args — `unfold Cf` unfolds all Cf occurrences ✓. Then the body: `if finite_zeros_mono : (SetOfZeros (rC ht) (scaledZeta t)).Finite then (if w ∈ SetOfZeros (rC ht) (scaledZeta t) then ZeroFactor ... / ∏ ρ ∈ finite_zeros_mono.toFinset \ {w}, ... else scaledZeta t w / ∏ ρ ∈ finite_zeros_mono.toFinset, ...) else 1`. simp only [hfin, ↓reduceDIte] reduces the outer (hfin matches `finite_zeros_mono`'s TYPE — simp only [hfin] uses it as rewrite p → True; ↓reduceDIte then needs a Decidable (True)... the Zeta23 proofs did exactly this and it worked (with `open Classical` in scope — the instance for the reduced dite True: `Classical.propDecidable`...). Hmm — ↓reduceDIte is a simproc: dite c a b with c replaced by True and a decidable instance... it produces `a (of_decide_eq_true ...)`-ish. The Zeta23 pattern worked there; mirror it. Then the inner: `rw [dif_neg hw]` / `rw [dif_pos hw]` — dif_neg (h : ¬c) : (if h : c then a else b) = b — for dite: `dif_neg (hnc : ¬c) : (if h : c then a h else b h) = b hnc`?? the RHS is `b hnc`?? no — dif_neg : ¬c → dite c ta ea = ea (hnc)? Signature: `dif_neg (h : ¬c) {u : c → Sort _} {v : ¬c → Sort _}??` no. Standard: `dif_neg (h : ¬c) : (if h : c then a h else b h) = b h` ✓ (b takes the proof). OK.
Then the product finset: finite_zeros_mono.toFinset — with finite_zeros_mono the PROOF introduced by the dite — it's an arbitrary proof of (SetOfZeros r_c F).Finite. My hfin is MY proof — after simp only [hfin, ↓reduceDIte], the dite's branch value uses the dite-BOUND proof (finite_zeros_mono), NOT my hfin!! Hmm — when simp reduces dite c (λ h => val h) ..., the result is val (proof-of-c-from-True)... i.e. the term becomes `scaledZeta t w / ∏ ρ ∈ (hproof).toFinset, ...` where hproof is some proof of the finiteness (from of_decide or from hfin's rewrite?). When simp only [hfin] rewrites the PROPOSITION to True, then ↓reduceDIte gives `val (of_decide_eq_true (decide ...))`? or with eq_true hfin: dite True (λ h => ...) — the application needs a proof of True — the simproc supplies `of_decide_eq_true rfl` or trivial. Either way the resulting toFinset uses SOME proof — and collZeros_toFinset_eq works for ANY proof (toFinset_inj.mpr rfl) — so I rewrite with `collZeros_toFinset_eq ht ⟨the proof⟩` — but I can't name the simproc-generated proof! Hmm. Alternative: `Set.Finite.toFinset_congr`? or just convert the product via Finset.prod_congr after proving the finsets equal by ext:
```lean
have hfinset : ∀ (h1 h2 : (SetOfZeros (rC ht) (scaledZeta t)).Finite),
h1.toFinset = collZeros ht := fun h1 h2 => Set.Finite.toFinset_inj.mpr rfl
```
and then in the proof after simp/rw: `rw [hfinset _ _]`? Can't reference the anonymous proof term in rw...
Alternative approach: use `Set.Finite.toFinset_eq` hmm. OR: congruence: the goal after the dite reductions: `scaledZeta t w / ∏ ρ ∈ PF.toFinset, (w − ρ)^m = scaledZeta t w / collProd ht w` where PF is the anonymous proof. `congr 1` ⟹ `PF.toFinset = collZeros ht`?? congr on HDiv: f a b = f a' b' → a = a' ∧ b = b': congr 1 gives goals scaledZeta t w = scaledZeta t w (rfl-closed) and ∏ ... = collProd ht w — then unfold collProd: ∏ ρ ∈ PF.toFinset, F₁ ρ = ∏ ρ ∈ collZeros ht, F₁ ρ — congr 1 again on Finset.prod: PF.toFinset = collZeros ht ∧ (fun ρ => ...) = (fun ρ => ...) — the first: Set.Finite.toFinset_inj.mpr rfl — but congr needs to produce the subgoal: `Finset.prod_congr rfl (fun _ _ => rfl)`? Finset.prod_congr (h₁ : s₁ = s₂) (h₂ : ∀ x ∈ s₂, f x = g x) : s₁.prod f = s₂.prod g. So:
```lean
apply Finset.prod_congr (Set.Finite.toFinset_inj.mpr rfl)
intro ρ hρ
rfl
```
Hmm but the target is `∏ ρ ∈ PF.toFinset, ... = collProd ht w` — collProd is a def: apply Finset.prod_congr needs the RHS to be a prod application syntactically — `show _ = ∏ ρ ∈ collZeros ht, (w − ρ)^analyticOrderNatAt (scaledZeta t) ρ`? collProd ht w unfolds (delta) to that — `show` with defeq ✓. Or `unfold collProd` first. OK:
```lean
theorem Cf_eq_div_collProd {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : w ∉ SetOfZeros (rC ht) (scaledZeta t)) :
Cf (rC ht) (scaledZeta t) w = scaledZeta t w / collProd ht w := by
classical
have hfin : (SetOfZeros (rC ht) (scaledZeta t)).Finite :=
scaledZeta_zeros_finite.subset (t := SetOfZeros (rC ht) (scaledZeta t)) fun x hx => by
obtain ⟨h1, h2⟩ := hx
exact ⟨h1.trans (rC_lt_one ht).le, h2⟩
unfold Cf collProd
simp only [hfin, ↓reduceDIte]
rw [dif_neg hw]
apply congrArg (fun X => scaledZeta t w / X)
exact Finset.prod_congr (Set.Finite.toFinset_inj.mpr rfl) (fun _ _ => rfl)
```
Hmm — `apply congrArg (fun X => scaledZeta t w / X)`: goal becomes PF.toFinset.prod f = collZeros... wait goal after rw: `scaledZeta t w / ∏ ρ ∈ PF.toFinset, (w-ρ)^m = scaledZeta t w / ∏ ρ ∈ collZeros ht, (w-ρ)^m` (after unfold collProd — the RHS is the unfolded prod). congrArg (fun X => F w / X) : a = b → F w / a = F w / b — apply: goal matches F w / a = F w / b with a := ∏..., b := ∏... — new goal a = b ✓ (apply congrArg with the lambda — unification of F w / ?a = F w / ?b ✓). Then Finset.prod_congr (h₁ : PF.toFinset = collZeros ht) (h₂ : ∀ x ∈ collZeros ht, f x = f x): Finset.prod_congr : s₁ = s₂ → (∀ x ∈ s₂, f x = g x) → s₁.prod f = s₂.prod g ✓. toFinset_inj.mpr rfl : PF.toFinset = collZeros ht — toFinset_inj : hs.toFinset = ht.toFinset ↔ s = t: hs := PF (the anonymous), ht := subset-derived, s = SetOfZeros (rC ht) F = t ✓ rfl ✓. But — will `Set.Finite.toFinset_inj.mpr rfl` UNIFY hs with PF? The goal a = b with a = PF.toFinset: apply/exact toFinset_inj.mpr rfl: the lemma's hs, ht metavars unified by the goal ✓.
Hmm — but actually will `simp only [hfin, ↓reduceDIte]` maybe produce `hfin.toFinset`?? When simp rewrites the Prop `(SetOfZeros ...).Finite` to True using hfin, the dite's motive... The dite value branch: `λ finite_zeros_mono => ...` — after the condition becomes True, the simproc must supply a True proof, and the value becomes `... (proof-of-True).toFinset ...`. So PF is anonymous ✓ my approach handles it.
Actually — maybe simpler: avoid the issue entirely with `Set.Finite.toFinset_congr`?? Hmm — there's `Set.Finite.toFinset_eq_toFinset` (line 78: h.toFinset = s.toFinset for [Fintype s])... Let me also prepare a fallback: prove the two prod-terms equal via `Finset.prod_congr rfl`? If the finsets are DEFINITIONALLY equal (proof irrelevance!) — PF.toFinset vs subset-derived.toFinset — both are toFinset of proofs of the same set-finiteness — proof irrelevance makes PF ≡ subset-proof definitionally (Subsingleton of Prop) ⟹ the finsets are defeq ⟹ the prods are defeq ⟹ `rfl` might just close it! Finset.prod's first arg is the finset — defeq terms ⟹ rfl works. So maybe just `rfl` after the rw [dif_neg hw] + unfold. Try rfl first, fallback congrArg+prod_congr.
Hmm — toFinset OF a proof: `Set.Finite.toFinset (hs : s.Finite) : Finset α` — its definition uses hs.fintype... Classical choice stuff — proof irrelevance: hs ≡ hs' (Subsingleton) ⟹ toFinset hs ≡ toFinset hs' by congruence of defeq ✓ rfl should work.
For the pos branch similarly.
Also — `hw : w ∉ SetOfZeros (rC ht) (scaledZeta t)` vs the dite's condition `w ∈ SetOfZeros (rC ht) (scaledZeta t)`: dif_neg hw ✓ types match.
Now — one more important check: Cf's r argument is `rC ht` — Cf (rC ht) (scaledZeta t) w — unfold Cf gives body with r := rC ht ✓.
Now §8's remaining: analyticity (as drafted), nonvanishing (as drafted), center log-norm, sphere bound, ball bound.
For the center log-norm proof I need collProd at 0: ∏ (0−ρ)^m = ∏ (−ρ)^m; norm: ∏ ‖ρ‖^m. And ρ ≠ 0 for ρ ∈ collZeros (since F 0 = 1 ≠ 0 = F ρ... wait F ρ = 0 and F 0 = 1: if ρ = 0 then F ρ = F 0 = 1 ≠ 0 contradiction with F ρ = 0 — so ρ ≠ 0 ✓).
log‖B 0‖ ≥ 0: B 0 = F 0 / collProd 0 = 1/collProd 0. ‖B 0‖ = 1/‖collProd 0‖ = 1/∏‖ρ‖^m. log(1/x) = −log x; −log x ≥ 0 ⟺ log x ≤ 0 ⟸ 0 < x ≤ 1. x = ∏‖ρ‖^m ≤ 1: each factor ≤ 1 (‖ρ‖ ≤ rC − gapD ≤ rC ≤ 24/25 ≤ 1: pow_le_one₀ (norm_nonneg) (‖ρ‖ ≤ 1)) ✓; x > 0: each factor > 0 (‖ρ‖ > 0: ρ ≠ 0; pow_pos) ✓.
Real.log identities: goal 0 ≤ Real.log ‖B 0‖; ‖B 0‖ = 1/x: rw norm-div chain then Real.log_div? log(1/x) = log 1 − log x (Real.log_div (one_ne_zero) (x ≠ 0)) = −log x. 0 ≤ −log x ⟺ log x ≤ 0: Real.log_nonpos (0 ≤ x) (x ≤ 1) ✓.
Now write the whole §8 block. Also keep in mind `norm_prod` name: `norm_prod : ‖∏ i ∈ s, f i‖ = ∏ i ∈ s, ‖f i‖` ✓ (norm_prod in Mathlib.Analysis.Normed... exists).
Also Finset.prod_pos : (∀ i ∈ s, 0 < f i) → 0 < ∏ i ∈ s, f i ✓.
For the sphere bound: after establishing ‖B w‖ ≤ X/δ^M, done. Note δ^M with M : ℕ and δ : ℝ: gapD t ^ collMultSum ht ✓ nat pow.
One catch — collMultSum ht = Σ orders over collZeros; the product lower bound: ∏ ‖w−ρ‖^m ≥ ∏ δ^m = δ^(Σ m) — Finset.prod_pow_eq_pow_sum : ∏ i ∈ s, a ^ f i = a ^ (∑ i ∈ s, f i) ✓. So ∏ ‖w−ρ‖^m ≥ δ^(collMultSum ht): Finset.prod_le_prod (each ≥ 0: pow_nonneg (norm... δ ≥ 0)) (each δ^m ≤ ‖w−ρ‖^m: pow_le_pow_left₀ δ≥0 (δ ≤ ‖w−ρ‖) m) — prod_le_prod (h0 : ∀ i ∈ s, 0 ≤ f i) (h1 : ∀ i ∈ s, f i ≤ g i) : ∏ f ≤ ∏ g ✓ with f = fun ρ => δ^(order ρ), g = fun ρ => ‖w−ρ‖^(order ρ). Then = δ^(Σ order) = δ^(collMultSum ht) via Finset.prod_pow_eq_pow_sum + collMultSum def (unfold).
div bound assembly as planned.
Then ball bound:
```lean
theorem Cf_collZeros_norm_le_ball {t : ℝ} (ht : 10 ≤ |t|) {w : ℂ}
(hw : w ∈ Metric.closedBall 0 (rC ht)) :
‖Cf (rC ht) (scaledZeta t) w‖ ≤ (9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht := by
apply AnalyticOn.norm_le_of_norm_le_on_sphere (r := rC ht) (R := (1 + rC ht) / 2)
· -- r ≤ R
have h1 := rC_lt_one ht
linarith [rC_pos ht]
· exact (Cf_collZeros_analytic ht).analyticOn
· intro z hz
rw [Metric.mem_sphere_iff_norm, sub_zero] at hz
exact Cf_collZeros_norm_le_sphere ht hz
· exact hw
```
Wait signature: AnalyticOn.norm_le_of_norm_le_on_sphere (hyp_r : r ≤ R) (analytic : AnalyticOn ℂ f (Metric.closedBall 0 R)) (cond : ∀ z ∈ Metric.sphere 0 r, ‖f z‖ ≤ C) (wInS : w ∈ Metric.closedBall 0 r) — with f, C, w implicit. `apply` with (r := rC ht) (R := ...) named — r, R are explicit-ish implicit? In the def: {C r R : ℝ} {f} {w} — all implicit. So provide via apply ... (r := rC ht) (R := (1+rC ht)/2) then 4 goals. ✓ mem_sphere_iff_norm : z ∈ Metric.sphere 0 r ↔ ‖z − 0‖ = r — rw [Metric.mem_sphere_iff_norm, sub_zero] at hz gives ‖z‖ = rC ht ✓.
AnalyticOnNhd.analyticOn — AnalyticOnNhd ℂ f s → AnalyticOn ℂ f s: `AnalyticOnNhd.analyticOn` ✓.
Write §8 now.
Now appending §8 (the Cf/g machinery) before `end NguyenRH1`.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": "/-- The mult-weighted count over the collected zeros, as a natural. -/\nnoncomputable def collMultSum {t : \u211d} (ht : 10 \u2264 |t|) : \u2115 :=\n \u2211 \u03c1 \u2208 collZeros ht, analyticOrderNatAt (scaledZeta t) \u03c1\n\nend NguyenRH1",
"new_string": "/-- The mult-weighted count over the collected zeros, as a natural. -/\nnoncomputable def collMultSum {t : \u211d} (ht : 10 \u2264 |t|) : \u2115 :=\n \u2211 \u03c1 \u2208 collZeros ht, analyticOrderNatAt (scaledZeta t) \u03c1\n\n/-! ## 8. The Blaschke quotient g = Cf r_c F -/\n\n/-- The product over the collected zeros, P(w) = \u220f (w\u2212\u03c1)^{m_\u03c1}. -/\nnoncomputable def collProd {t : \u211d} (ht : 10 \u2264 |t|) (w : \u2102) : \u2102 :=\n \u220f \u03c1 \u2208 collZeros ht, (w - \u03c1) ^ analyticOrderNatAt (scaledZeta t) \u03c1\n\n/-- Off the collected zero set, the Blaschke quotient Cf is F/P. -/\ntheorem Cf_eq_div_collProd {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102}\n (hw : w \u2209 SetOfZeros (rC ht) (scaledZeta t)) :\n Cf (rC ht) (scaledZeta t) w = scaledZeta t w / collProd ht w := by\n classical\n have hfin : (SetOfZeros (rC ht) (scaledZeta t)).Finite :=\n scaledZeta_zeros_finite.subset (t := SetOfZeros (rC ht) (scaledZeta t)) fun x hx => by\n obtain \u27e8h1, h2\u27e9 := hx\n exact \u27e8h1.trans (rC_lt_one ht).le, h2\u27e9\n unfold Cf collProd\n simp only [hfin, \u2193reduceDIte]\n rw [dif_neg hw]\n apply congrArg (fun X => scaledZeta t w / X)\n exact Finset.prod_congr (Set.Finite.toFinset_inj.mpr rfl) (fun _ _ => rfl)\n\n/-- At a collected zero, Cf is the zero-factor cofactor over the remaining\nproduct. -/\ntheorem Cf_eq_zeroFactor_div {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102}\n (hw : w \u2208 SetOfZeros (rC ht) (scaledZeta t)) :\n Cf (rC ht) (scaledZeta t) w = ZeroFactor (scaledZeta t) w /\n \u220f \u03c1 \u2208 collZeros ht \\ {w}, (w - \u03c1) ^ analyticOrderNatAt (scaledZeta t) \u03c1 := by\n classical\n have hfin : (SetOfZeros (rC ht) (scaledZeta t)).Finite :=\n scaledZeta_zeros_finite.subset (t := SetOfZeros (rC ht) (scaledZeta t)) fun x hx => by\n obtain \u27e8h1, h2\u27e9 := hx\n exact \u27e8h1.trans (rC_lt_one ht).le, h2\u27e9\n unfold Cf\n simp only [hfin, \u2193reduceDIte]\n rw [dif_pos hw]\n apply congrArg (fun X => ZeroFactor (scaledZeta t) w / X)\n exact Finset.prod_congr (Set.Finite.toFinset_inj.mpr rfl) (fun _ _ => rfl)\n\n/-- g is analytic on a closed disc slightly larger than closedBall(0, r_c). -/\ntheorem Cf_collZeros_analytic {t : \u211d} (ht : 10 \u2264 |t|) :\n AnalyticOnNhd \u2102 (Cf (rC ht) (scaledZeta t))\n (Metric.closedBall 0 ((1 + rC ht) / 2)) := by\n apply CfAnalytic\n \u00b7 have h1 := rC_lt_one ht\n linarith [rC_pos ht]\n \u00b7 have h1 := rC_lt_one ht\n linarith\n \u00b7 exact scaledZeta_analytic ht\n \u00b7 rw [scaledZeta_zero]\n exact one_ne_zero\n\n/-- g is nonvanishing on closedBall(0, r_c). -/\ntheorem Cf_collZeros_ne_zero {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102}\n (hw : w \u2208 Metric.closedBall 0 (rC ht)) :\n Cf (rC ht) (scaledZeta t) w \u2260 0 := by\n rw [Metric.mem_closedBall, dist_zero_right] at hw\n by_cases h0 : scaledZeta t w = 0\n \u00b7 have hwS : w \u2208 SetOfZeros (rC ht) (scaledZeta t) := \u27e8hw, h0\u27e9\n rw [Cf_eq_zeroFactor_div ht hwS]\n apply div_ne_zero\n \u00b7 obtain \u27e8h_w, h_w_an, h_w_ne, hZF, _\u27e9 := ZeroFactorization (rC_lt_one ht)\n (scaledZeta_analytic ht) (by rw [scaledZeta_zero]; exact one_ne_zero) hwS\n rw [hZF]\n exact h_w_ne\n \u00b7 apply Finset.prod_ne_zero_iff.mpr\n intro \u03c1 h\u03c1\n have h\u03c1ne : \u03c1 \u2260 w := fun h => (Finset.mem_sdiff.mp h\u03c1).2 (Finset.mem_singleton.mpr h)\n exact pow_ne_zero _ (sub_ne_zero.mpr h\u03c1ne.symm)\n \u00b7 have hwS : w \u2209 SetOfZeros (rC ht) (scaledZeta t) := fun h => h0 h.2\n rw [Cf_eq_div_collProd ht hwS]\n apply div_ne_zero h0\n unfold collProd\n apply Finset.prod_ne_zero_iff.mpr\n intro \u03c1 h\u03c1\n have h\u03c10 : scaledZeta t \u03c1 = 0 := ((mem_collZeros ht).mp h\u03c1).2\n exact pow_ne_zero _ (sub_ne_zero.mpr (fun h => h0 (by rw [h]; exact h\u03c10)))\n\n/-- At the center, log\u2016g(0)\u2016 \u2265 0 (since g(0) = 1/\u220f(\u2212\u03c1)^{m_\u03c1} and each\n\u2016\u03c1\u2016 \u2264 r_c < 1). -/\ntheorem Cf_collZeros_log_norm_zero_nonneg {t : \u211d} (ht : 10 \u2264 |t|) :\n 0 \u2264 Real.log \u2016Cf (rC ht) (scaledZeta t) 0\u2016 := by\n have h0S : (0:\u2102) \u2209 SetOfZeros (rC ht) (scaledZeta t) := by\n intro h\n have h2 := h.2\n rw [scaledZeta_zero] at h2\n exact one_ne_zero h2\n rw [Cf_eq_div_collProd ht h0S, scaledZeta_zero]\n have hprod_norm : \u2016collProd ht 0\u2016\n = \u220f \u03c1 \u2208 collZeros ht, \u2016\u03c1\u2016 ^ analyticOrderNatAt (scaledZeta t) \u03c1 := by\n unfold collProd\n rw [norm_prod]\n apply Finset.prod_congr rfl\n intro \u03c1 h\u03c1\n rw [zero_sub, norm_neg, norm_pow]\n have hfac : \u2200 \u03c1 \u2208 collZeros ht,\n 0 < \u2016\u03c1\u2016 ^ analyticOrderNatAt (scaledZeta t) \u03c1 := by\n intro \u03c1 h\u03c1\n have h\u03c10 : scaledZeta t \u03c1 = 0 := ((mem_collZeros ht).mp h\u03c1).2\n have hne : \u03c1 \u2260 0 := by\n intro h\n rw [h, scaledZeta_zero] at h\u03c10\n exact one_ne_zero h\u03c10\n exact pow_pos (norm_pos_iff.mpr hne) _\n have hprod_pos : 0 < \u220f \u03c1 \u2208 collZeros ht, \u2016\u03c1\u2016 ^ analyticOrderNatAt (scaledZeta t) \u03c1 :=\n Finset.prod_pos hfac\n have hprod_le : \u220f \u03c1 \u2208 collZeros ht, \u2016\u03c1\u2016 ^ analyticOrderNatAt (scaledZeta t) \u03c1 \u2264 1 := by\n apply Finset.prod_le_one (fun \u03c1 h\u03c1 => (hfac \u03c1 h\u03c1).le)\n intro \u03c1 h\u03c1\n have hnorm : \u2016\u03c1\u2016 \u2264 1 :=\n (((mem_collZeros ht).mp h\u03c1).1.trans (rC_le ht)).trans (by norm_num)\n exact pow_le_one\u2080 (norm_nonneg _) hnorm\n rw [hprod_norm, norm_div, norm_one,\n Real.log_div one_ne_zero (ne_of_gt hprod_pos), Real.log_one, zero_sub]\n exact neg_nonneg.mpr (Real.log_nonpos hprod_pos.le hprod_le)\n\n/-- **The outer-circle bound**: on the sphere \u2016w\u2016 = r_c (which carries no\nzeros, by the gap), \u2016g(w)\u2016 \u2264 (9/4)|t|\u00b2 \u00b7 gapD^{\u2212M_c}. -/\ntheorem Cf_collZeros_norm_le_sphere {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102}\n (hw : \u2016w\u2016 = rC ht) :\n \u2016Cf (rC ht) (scaledZeta t) w\u2016 \u2264\n (9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht := by\n have h\u03b4 := gapD_pos t\n have hwS : w \u2209 SetOfZeros (rC ht) (scaledZeta t) := by\n intro hmem\n have hmemZ : w \u2208 collZeros ht := (mem_collZeros ht).mpr \u27e8hmem.1, hmem.2\u27e9\n have hle := collZeros_norm_le ht hmemZ\n rw [hw] at hle\n linarith\n rw [Cf_eq_div_collProd ht hwS, norm_div]\n have hF : \u2016scaledZeta t w\u2016 \u2264 (9 / 4) * |t| ^ 2 :=\n norm_scaledZeta_le ht (by rw [hw]; exact (rC_le ht).trans (by norm_num))\n -- the product is \u2265 gapD^{M_c}\n have hP : gapD t ^ collMultSum ht \u2264 \u2016collProd ht w\u2016 := by\n have hstep : \u220f \u03c1 \u2208 collZeros ht, gapD t ^ analyticOrderNatAt (scaledZeta t) \u03c1\n \u2264 \u220f \u03c1 \u2208 collZeros ht, \u2016w - \u03c1\u2016 ^ analyticOrderNatAt (scaledZeta t) \u03c1 := by\n apply Finset.prod_le_prod (fun \u03c1 _ => pow_nonneg h\u03b4.le _)\n intro \u03c1 h\u03c1\n have h\u03c1le := collZeros_norm_le ht h\u03c1\n have hd : gapD t \u2264 \u2016w - \u03c1\u2016 := by\n have h1 : \u2016w\u2016 - \u2016\u03c1\u2016 \u2264 \u2016w - \u03c1\u2016 := norm_sub_norm_le w \u03c1\n rw [hw] at h1\n linarith\n exact pow_le_pow_left\u2080 h\u03b4.le hd _\n rw [\u2190 Finset.prod_pow_eq_pow_sum] at hstep\n calc gapD t ^ collMultSum ht\n = gapD t ^ (\u2211 \u03c1 \u2208 collZeros ht, analyticOrderNatAt (scaledZeta t) \u03c1) := rfl\n _ \u2264 \u220f \u03c1 \u2208 collZeros ht, \u2016w - \u03c1\u2016 ^ analyticOrderNatAt (scaledZeta t) \u03c1 := hstep\n _ = \u2016collProd ht w\u2016 := by\n unfold collProd\n rw [norm_prod]\n apply Finset.prod_congr rfl\n intro \u03c1 h\u03c1\n rw [norm_pow]\n have hPpos : 0 < gapD t ^ collMultSum ht := pow_pos h\u03b4 _\n calc \u2016scaledZeta t w\u2016 / \u2016collProd ht w\u2016\n \u2264 (9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht :=\n div_le_div hF hP hPpos (norm_nonneg _)\n\n/-- The bound propagates to the closed ball by the maximum principle. -/\ntheorem Cf_collZeros_norm_le_ball {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102}\n (hw : w \u2208 Metric.closedBall 0 (rC ht)) :\n \u2016Cf (rC ht) (scaledZeta t) w\u2016 \u2264\n (9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht := by\n apply AnalyticOn.norm_le_of_norm_le_on_sphere (r := rC ht) (R := (1 + rC ht) / 2)\n \u00b7 have h1 := rC_lt_one ht\n linarith [rC_pos ht]\n \u00b7 exact (Cf_collZeros_analytic ht).analyticOn\n \u00b7 intro z hz\n rw [Metric.mem_sphere_iff_norm, sub_zero] at hz\n exact Cf_collZeros_norm_le_sphere ht hz\n \u00b7 exact hw\n\nend NguyenRH1"
}
thinking (5458 chars)
Fixing these:
1. **gapD_le (line 539)**: div_le_div_iff_of_pos_left gives the wrong direction (it produced a/(50*1) ≤ a/(50*(k+1)) from 50(k+1) ≤ 50·1 — but I want the reverse since k+1 ≥ 1 means denominator bigger ⟹ fraction smaller). Let me redo: goal 1/(50(k+1)) ≤ 1/50 ⟸ 50(k+1) ≥ 50: div_le_div_iff_of_pos_left (ha : 0 < a) (hb : 0 < b) (hc : 0 < c) : a / b ≤ a / c ↔ c ≤ b. With a := 1, b := 50(k+1), c := 50: (div_le_div_iff_of_pos_left one_pos (h : 0 < 50(k+1)) (by norm_num : 0 < 50)).mpr (h : 50 ≤ 50(k+1)) : 1/(50(k+1)) ≤ 1/50 ✓. So the args: (ha) (hb : 0 < b) (hc : 0 < c), mpr : c ≤ b. Fix:
```lean
theorem gapD_le (t : ℝ) : gapD t ≤ 1 / 50 := by
unfold gapD
have hb : (0:ℝ) < 50 * ((card96 t : ℝ) + 1) :=
mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)
apply (div_le_div_iff_of_pos_left (by norm_num : (0:ℝ) < 1) hb (by norm_num : (0:ℝ) < 50)).mpr
have : (1:ℝ) ≤ (card96 t : ℝ) + 1 := by linarith [Nat.cast_nonneg (card96 t)]
calc (50:ℝ) ≤ 50 * ((card96 t : ℝ) + 1) := by
rw [← mul_one 50]; exact mul_le_mul_of_nonneg_left this (by norm_num)
_ = 50 * ((card96 t : ℝ) + 1) := rfl
```
hmm the calc is silly: 50 ≤ 50*(k+1) ⟸ 1 ≤ k+1: `mul_le_mul_of_nonneg_left this (by norm_num : (0:ℝ) ≤ 50)` : 50*1 ≤ 50*(k+1) — with ← mul_one. Let me write:
```lean
have h1 : (1:ℝ) ≤ (card96 t : ℝ) + 1 := by linarith [Nat.cast_nonneg (card96 t)]
have h2 : (50:ℝ) * 1 ≤ 50 * ((card96 t : ℝ) + 1) := mul_le_mul_of_nonneg_left h1 (by norm_num)
rwa [mul_one] at h2
```
Wait — div_le_div_iff_of_pos_left's iff direction: `div_le_div_iff_of_pos_left (ha : 0 < a) (hb : 0 < b) (hc : 0 < c) : a / b ≤ a / c ↔ c ≤ b`. Our goal: 1/(50(k+1)) ≤ 1/50 — so a/b := 1/(50(k+1)) ⟹ b := 50(k+1), c := 50. mpr needs c ≤ b: 50 ≤ 50(k+1) ✓ h2. ✓
2. **rC_gap line 631**: `rw [← hcast]` — hcast : ↑(card96 t) = ↑(explicit card). The goal has ↑(card96 t); I want to convert it TO the explicit form: rw [hcast] (forward: card96 → explicit). I wrote `rw [← hcast]` — backwards. Fix: `rw [hcast]`.
3. **Cf_eq_zeroFactor_div line 702**: the product after dif_pos is over `PF.toFinset \ {w}` and collProd-equivalent is `collZeros ht \ {w}` — prod_congr needs the whole `s₁ = s₂`: s₁ = PF.toFinset \ {w}, s₂ = collZeros ht \ {w}. So prove (PF.toFinset \ {w} = collZeros ht \ {w}) via congrArg (· \ {w}) (toFinset_inj.mpr rfl)... or: `Finset.prod_congr (by rw [Set.Finite.toFinset_inj.mpr rfl]) ...` hmm. Let me do:
```lean
apply congrArg (fun X => ZeroFactor (scaledZeta t) w / X)
apply Finset.prod_congr _ (fun _ _ => rfl)
congr 1
exact Set.Finite.toFinset_inj.mpr rfl
```
`congr 1` on goal PF.toFinset \ {w} = collZeros ht \ {w} gives PF.toFinset = collZeros ht (and {w} = {w} closed by rfl) ✓.
Actually wait — also check the FIRST char lemma (Cf_eq_div_collProd, line ~680): `Finset.prod_congr (Set.Finite.toFinset_inj.mpr rfl) (fun _ _ => rfl)` — same pattern with plain finsets (no sdiff) — that one apparently compiled (no error reported for it) ✓.
4. **Cf_collZeros_log_norm_zero_nonneg line 759**: `rw [zero_sub, norm_neg, norm_pow]` — the goal: ‖(−ρ) ^ m‖ = ‖ρ‖ ^ m — after zero_sub, the term became (−ρ)^m; norm_neg doesn't apply because the outer is ‖·^m‖ not ‖−ρ‖. Order: rw [norm_pow] FIRST: ‖(−ρ)^m‖ = ‖−ρ‖^m, then norm_neg: ‖ρ‖^m. But wait — did zero_sub even fire? The error shows the goal as ‖(−ρ)^m‖ = ‖ρ‖^m so zero_sub fired, norm_neg failed (pattern ‖−?a‖ not found — it's ‖(−ρ)^m‖, the pow is outside). Fix: `rw [zero_sub, norm_pow, norm_neg]`.
5. **Line 777**: `rw [hprod_norm, norm_div, norm_one, ...]` — after the earlier rw chain, the goal is `0 ≤ Real.log ‖1 / collProd ht 0‖` — the pattern ‖collProd ht 0‖ not found because the term is ‖1 / collProd ht 0‖ — norm_div must fire FIRST: ‖1 / collProd‖ = ‖1‖/‖collProd‖. So order: rw [norm_div, norm_one, hprod_norm, ...]. Wait the error says the rewrite of hprod_norm failed with target `0 ≤ Real.log ‖1 / collProd ht 0‖` — so norm_div/norm_one hadn't fired yet (I had order [hprod_norm, norm_div, norm_one, ...] — hprod_norm first ✗). Reorder: `rw [norm_div, norm_one, hprod_norm, Real.log_div one_ne_zero (ne_of_gt hprod_pos), Real.log_one, zero_sub]`.
Hmm wait — but also: after `rw [Cf_eq_div_collProd ht h0S, scaledZeta_zero]`, the goal is `0 ≤ Real.log ‖1 / collProd ht 0‖`. Hmm — actually the rw [scaledZeta_zero] rewrote `scaledZeta t 0` to 1 ✓. Then norm_div : ‖1 / collProd ht 0‖ = ‖1‖/‖collProd ht 0‖ ✓, norm_one, hprod_norm : ‖collProd ht 0‖ = ∏... ✓, then Real.log_div : log (1/x) = log 1 − log x ✓ (one_ne_zero : (1:ℝ) ≠ 0 ✓, x ≠ 0 ✓), Real.log_one : log 1 = 0, zero_sub : 0 − y = −y ⟹ goal 0 ≤ −log(∏) ⟹ neg_nonneg.mpr (log_nonpos ...) ✓.
Wait — Real.log_div signature: `Real.log_div (hx : x ≠ 0) (hy : y ≠ 0) : log (x / y) = log x - log y` ✓.
Let me also double check line 550 warning: ht unused in... line 550 is gapD_le or card96_cast? gapD_le doesn't use ht (no ht arg) — the warning at 550:42 — probably `collRadius_gap`'s ht? No... whatever, just a warning. Actually looking: 550 is in `exists_collection_radius`? Already known. Skip.
Now also the earlier chunk-1 `rC_gap` proof has `rw [← hcast]` — fix to `rw [hcast]`. Wait, in rC_gap I do `unfold gapD; rw [← hcast]` — goal after unfold: `1 / (50 * (↑(card96 t) + 1)) ≤ |‖w‖ − rC ht|`; hcast : ↑(card96 t) = ↑(explicit). rw [hcast] rewrites ↑(card96 t) → ↑(explicit) ✓. I wrote ← hcast which looks for ↑(explicit) in the goal — not there ✗. Fix to `rw [hcast]`.
Five fixes.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": "theorem gapD_le (t : \u211d) : gapD t \u2264 1 / 50 := by\n unfold gapD\n apply (div_le_div_iff_of_pos_left (by norm_num) (by norm_num : (0:\u211d) < 50 * 1)\n (mul_pos (by norm_num : (0:\u211d) < 50)\n (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos))).mpr\n rw [mul_one]\n exact mul_le_mul_of_nonneg_left (by linarith [Nat.cast_nonneg (card96 t)]) (by norm_num)",
"new_string": "theorem gapD_le (t : \u211d) : gapD t \u2264 1 / 50 := by\n unfold gapD\n have hb : (0:\u211d) < 50 * ((card96 t : \u211d) + 1) :=\n mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)\n apply (div_le_div_iff_of_pos_left (by norm_num : (0:\u211d) < 1) hb\n (by norm_num : (0:\u211d) < 50)).mpr\n have h1 : (1:\u211d) \u2264 (card96 t : \u211d) + 1 := by linarith [Nat.cast_nonneg (card96 t)]\n have h2 : (50:\u211d) * 1 \u2264 50 * ((card96 t : \u211d) + 1) :=\n mul_le_mul_of_nonneg_left h1 (by norm_num)\n rwa [mul_one] at h2"
}
thinking (10986 chars)
Progress. Fixing:
1. **Line 543** (gapD_le): `mul_le_mul_of_nonneg_left h1 (by norm_num)` — the (by norm_num : (0:ℝ) ≤ 50) should pin ℝ... the error is IsOrderedRing stuck at col 55 — the `mul_le_mul_of_nonneg_left h1 (by norm_num)` — h1 : 1 ≤ ↑(card96 t)+1; the lemma: mul_le_mul_of_nonneg_left (h : b ≤ c) (ha : 0 ≤ a) : a * b ≤ a * c — the `a` from h1: b=1? h1 : (1:ℝ) ≤ (card96 t : ℝ)+1 — so a*(1) ≤ a*(k+1) — the `by norm_num` for 0 ≤ a — a is a metavariable at the time norm_num runs? mul_le_mul_of_nonneg_left (h : b ≤ c) (hc : 0 ≤ a)?? actual signature: `mul_le_mul_of_nonneg_left (h : b ≤ c) (ha : 0 ≤ a) : a * b ≤ a * c` — with h := h1, b := 1, c := k+1, a is determined by... nothing! a is free — the result type a*1 ≤ a*(k+1) must unify with the goal 50*1 ≤ 50*(k+1) — but I used it inside `have h2 : (50:ℝ) * 1 ≤ ...` with ascription — the ascription should drive it. Hmm the error at col 55: which subterm? Let me count: line 543 = the `have h2 : (50:ℝ) * 1 ≤ 50 * ((card96 t : ℝ) + 1) := mul_le_mul_of_nonneg_left h1 (by norm_num)` line — col 55 ≈ the `by norm_num`. The ascribed type should fix a := 50... unless elaboration processes the term before the ascription unifies a. In `have h2 : T := term`, T is elaborated first, then term against T ✓ should work. Unless h1's type itself has metavariables: h1 : (1:ℝ) ≤ (card96 t : ℝ) + 1 — no metavars. Hmm — wait, maybe the issue: mul_le_mul_of_nonneg_left's signature in this Mathlib is `(h : b ≤ c) (a : α) (ha : 0 ≤ a)??` no... or it could be `[MulPosMono α]`-typeclass-based: mul_le_mul_of_nonneg_left (h : b ≤ c) (ha : 0 ≤ a) : a * b ≤ a * c ✓ that's standard. IsOrderedRing ?m stuck — so α wasn't determined — meaning the expected type wasn't propagated. `have h2 : TYPE := by exact ...`? Let me restructure with explicit by-block:
```lean
have h2 : (50:ℝ) * 1 ≤ 50 * ((card96 t : ℝ) + 1) := by
exact mul_le_mul_of_nonneg_left h1 (by norm_num)
```
Same thing. Alternatively use nlinarith: h2 : 50*1 ≤ 50*(k+1) from h1 : 1 ≤ k+1 — nlinarith [h1] or linarith? 50*1 ≤ 50*(k+1) ⟺ 50 ≤ 50k+50 ⟺ 0 ≤ 50k ⟸ k ≥ 0 — LINEAR in the atom (card96 t : ℝ)! linarith [Nat.cast_nonneg (card96 t)] ✓. Replace:
```lean
theorem gapD_le (t : ℝ) : gapD t ≤ 1 / 50 := by
unfold gapD
have hb : (0:ℝ) < 50 * ((card96 t : ℝ) + 1) :=
mul_pos (by norm_num) (add_pos_of_nonneg_of_pos (Nat.cast_nonneg _) one_pos)
apply (div_le_div_iff_of_pos_left (by norm_num : (0:ℝ) < 1) hb
(by norm_num : (0:ℝ) < 50)).mpr
have hk : (0:ℝ) ≤ (card96 t : ℝ) := Nat.cast_nonneg _
linarith
```
The mpr goal: 50 ≤ 50*(k+1) — linarith with hk: 50*(k+1) = 50k+50 ≥ 50 ✓ linarith handles (linear) ✓.
2. **Line 707 "No goals"**: Cf_eq_zeroFactor_div — after `apply Finset.prod_congr _ (fun _ _ => rfl)` — prod_congr's first arg (s₁ = s₂) filled by `_`?? I passed `_` as the first EXPLICIT arg — Finset.prod_congr (h₁ : s₁ = s₂) (h₂ : ∀ x ∈ s₂, f x = g x) — `apply Finset.prod_congr _ (fun _ _ => rfl)` — the `_` becomes a new goal? No — apply with `_` creates a metavariable solved by... apply creates goals for the underscores? `apply f _ x` — the `_` becomes a synthetic opaque goal... Actually apply with _ holes: they're created as new goals AFTER. Then `congr 1; exact toFinset_inj.mpr rfl` — but the error says "No goals to be solved" at 707:2 — meaning after apply, there were NO goals (the underscore got unified and the fun _ _ => rfl discharged h₂ too, and h₁ remained? confusing). The structure: `apply congrArg (fun X => ...)` leaves goal `PF.toFinset \ {w} = collZeros ht \ {w}`. Then `apply Finset.prod_congr _ (fun _ _ => rfl)` — WAIT the goal is an equality of FINSETS (PF.toFinset\{w} = collZeros\{w}), not of prods! Finset.prod_congr's conclusion is a prod equality — doesn't match finset equality ⟹ apply fails or produces weird unification... Actually the goal after congrArg: `∏ ρ ∈ PF.toFinset \ {w}, ... = ∏ ρ ∈ collZeros ht \ {w}, ...`?? Hmm no. Let me re-look: Cf_eq_zeroFactor_div's goal after congrArg: ZeroFactor.../X form — X := ∏ ρ ∈ PF.toFinset \ {w}, (w−ρ)^m vs RHS ∏ ρ ∈ collZeros ht \ {w}, (w−ρ)^m. congrArg (fun X => ZF w / X): new goal: ∏ ρ ∈ PF.toFinset\{w}, ... = ∏ ρ ∈ collZeros ht\{w}, ... — that IS a prod equality ✓. Then apply Finset.prod_congr _ (fun _ _ => rfl): prod_congr (h₁ : s₁ = s₂) (h₂ : ...) : s₁.prod f = s₂.prod g — the `_` for h₁: apply leaves it as a new goal? When applying a lemma with explicit args given as `_`, Lean creates metavariables; apply then tries to unify the conclusion — the conclusion s₁.prod f = s₂.prod g unifies with the goal fixing s₁ := PF.toFinset\{w}, s₂ := collZeros ht\{w}, f, g — then the remaining hypothesis args (h₁, h₂) become goals... but I SUPPLIED them positionally as `_` and `(fun _ _ => rfl)`. The `_` → new metavariable → new goal. (fun _ _ => rfl) might fail if f ≠ g syntactically... The error "No goals to be solved" at 707 — after `apply Finset.prod_congr _ (fun _ _ => rfl)`, then `congr 1` — if apply already closed everything?? "No goals" at the congr 1 line means the apply closed the main goal and the underscore-goal got... Hmm — actually `apply f _ x`: the `_` is elaborated as a metavariable; since h₁'s TYPE (s₁ = s₂) is a Prop, and apply with term-mode args — the `_` becomes a synthetic goal queued AFTER, and (fun _ _ => rfl) is checked against h₂'s type ∀ x ∈ s₂, f x = g x — f vs g: both are fun ρ => (w−ρ)^order ρ — same ✓ rfl works. Then remaining goal: h₁ : PF.toFinset\{w} = collZeros ht\{w}. But error says no goals at 707 — the `congr 1` line. So after apply, ZERO goals remained — meaning h₁'s metavariable got assigned?? By unification? No... OH WAIT — maybe the error line numbers shifted: 707 might be the `apply Finset.prod_congr _ ...` in the FIRST char lemma (Cf_eq_div_collProd)?? No — that one is `Finset.prod_congr (Set.Finite.toFinset_inj.mpr rfl) (fun _ _ => rfl)` with both args given. Hmm, line 707... After my edits the line numbers: the zeroFactor lemma is around line 700. "No goals to be solved" at 707:2 — that's likely the `congr 1` after the apply — meaning apply Finset.prod_congr _ (fun _ _ => rfl) CLOSED the goal with no remaining goals — how? If the `_` metavariable for h₁ : PF.toFinset\{w} = collZeros\{w} got solved by... rfl-up-to-defeq during the apply's isDefEq check! Because prod_congr's h₁ is a Prop proof of s₁ = s₂ — a metavariable proof of an equality — Lean can assign it via... no, apply doesn't prove equalities by rfl automatically. UNLESS: the `_` in `apply f _ x` isn't allowed to remain a goal when it's a Prop and apply tries `assumption`... no.
Hmm, actually — in Lean 4, `apply f _ x` — the `_` elaborates to a metavariable, and if not solved by unification it becomes a new goal — but the ORDER: new goals from explicit underscores come BEFORE remaining hypotheses?? Whatever — the observed behavior: after the apply, "no goals" when congr 1 runs — so apply produced no goals, meaning the `_` was solved: possibly by proof irrelevance defeq: h₁'s metavariable : PF.toFinset\{w} = collZeros ht\{w} — when the result type was unified... no.
OK let me stop speculating: the behavior suggests that after `apply Finset.prod_congr _ (fun _ _ => rfl)` there are no goals — i.e., the underscore got instantiated during unification — impossible unless... OH. Maybe Finset.prod_congr in this Mathlib has signature `Finset.prod_congr (h₁ : s₁ = s₂) (h₂ : ∀ x ∈ s₂, f x = g x) : ∏ x ∈ s₁, f x = ∏ x ∈ s₂, g x` — and `apply ... _ (fun _ _ => rfl)` unified the GOAL: LHS prod over PF.toFinset\{w} = RHS prod over collZeros\{w} — hmm.
Actually — maybe the issue is different: "No goals" at 707:2 could be the `exact Set.Finite.toFinset_inj.mpr rfl` line or `congr 1` — meaning the preceding tactic already closed everything. If `congr 1` at line 706 closed the goal (congr leaves no goal because the sdiff equality held by rfl up to toFinset proof-irrelevance defeq — congr tries rfl on subgoals!) then line 707's exact has no goals ✓ THAT's it. congr 1 on PF.toFinset \ {w} = collZeros ht \ {w}: components PF.toFinset = collZeros ht — defeq by proof-irrelevance ⟹ congr's rfl-check closes it! So drop the `exact` line. But wait — the error was at 707:2 — let me count lines... my edit inserted:
```
apply congrArg (fun X => ZeroFactor (scaledZeta t) w / X)
apply Finset.prod_congr _ (fun _ _ => rfl)
congr 1
exact Set.Finite.toFinset_inj.mpr rfl
```
If `apply Finset.prod_congr _ (fun _ _ => rfl)` left the h₁ goal, then congr 1 on it: PF.toFinset\{w} = collZeros\{w} → congr 1 → PF.toFinset = collZeros ht — congr tries `rfl` for the subgoal and SUCCEEDS (proof-irrelevance defeq) ⟹ no goals ⟹ exact fails with "no goals" ✓. Fix: remove the exact line (keep congr 1 which closes it). Or remove both congr 1 and exact, replacing the `_` with the proof directly:
```
apply congrArg (fun X => ZeroFactor (scaledZeta t) w / X)
refine Finset.prod_congr ?_ (fun _ _ => rfl)
congr 1
```
If congr 1 closes it — done; if not, need the exact. Safer:
```
apply congrArg (fun X => ZeroFactor (scaledZeta t) w / X)
refine Finset.prod_congr ?_ (fun _ _ => rfl)
rw [Set.Finite.toFinset_inj.mpr rfl]
```
rw with the equality rewrites PF.toFinset → collZeros in the goal PF.toFinset\{w} = collZeros\{w} ⟹ collZeros\{w} = collZeros\{w} — rfl-closed by rw ✓. Hmm but rw needs the pattern PF.toFinset — it's an anonymous proof term — rw [h : PF.toFinset = collZeros] rewrites occurrences of LHS pattern — the pattern contains the anonymous proof — rw abstracts it ✓ should work. Let me use:
```
congr 1
```
alone first (if congr closes it fully, done; the error says it does!). So: remove the exact line.
Wait, but in the FIRST char lemma (Cf_eq_div_collProd) I used `Finset.prod_congr (Set.Finite.toFinset_inj.mpr rfl) (fun _ _ => rfl)` — no error reported there?? Line 702's error was in the zeroFactor one (sdiff version). The first one compiled ✓ (toFinset_inj.mpr rfl unified fine there). OK.
3. **Line 814**: `rw [← Finset.prod_pow_eq_pow_sum] at hstep` — the pattern `?a ^ ∑ i ∈ ?s, ?f i` — Finset.prod_pow_eq_pow_sum : ∏ i ∈ s, a ^ f i = a ^ (∑ i ∈ s, f i)?? The actual: `Finset.prod_pow_eq_pow_sum (s : Finset ι) (f : ι → ℕ) (a : α) : ∏ i ∈ s, a ^ f i = a ^ ∑ i ∈ s, f i` ✓ so ← direction rewrites a^(Σ) → ∏ a^... I want the opposite: in hstep, the LHS is ∏ gapD^order — I want to convert it to gapD^(Σ). So rw [Finset.prod_pow_eq_pow_sum] at hstep (FORWARD). I wrote ←. Fix: `rw [Finset.prod_pow_eq_pow_sum] at hstep`. Then hstep : gapD^(Σ) ≤ ∏ ‖w−ρ‖^... ✓ then the calc: gapD^collMultSum = gapD^(Σ) (rfl via collMultSum def ✓) ≤ ∏... := hstep ✓.
4. **Line 827**: `div_le_div` unknown identifier — in this Mathlib the 4-arg div_le_div might be named differently (deprecated/renamed). Current: `div_le_div (hbc : b ≤ c)??`. In recent Mathlib (2024+): `div_le_div (ha : 0 ≤ a) (hab : a ≤ b) (hc : 0 < c) (hcd : c ≤ d) : a / d ≤ b / c`? There was a big rename: now it's `div_le_div (ha : 0 ≤ a) (hab : a ≤ b) (hc : 0 < c) (hcd : c ≤ d) : a / d ≤ b / c`. Let me check.
Checking the current `div_le_div` signature in this Mathlib version.
tool: Grep ok
input
{
"pattern": "theorem div_le_div \\{",
"path": "D:\\Python\\Quantum\\zeta-23-lean\\.lake\\packages\\mathlib\\Mathlib\\Algebra\\Order\\Field\\Basic.lean",
"output_mode": "content",
"-A": 4
}
result 2026-08-22 21:42:58Z → 2026-08-26 03:18:44Z
mode='content' num_files=0 filenames=[] content='research\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:736:def C0hat (t : ℝ) : ℝ :=\nresearch\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:745:def Z2hat (t : ℝ) : ℝ :=\nresearch\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:749:def Hhat (T : ℝ) : ℝ :=\nresearch\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:754:def IIMaj (n : ℝ) : ℝ :=\nresearch\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:766:def marginTilde (F : ℝ → ℝ) (n : ℝ) : ℝ :=\nresearch\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:1835:private def marginExpanded (F : ℝ → ℝ) : ℝ → ℝ := fun n =>\nresearch\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:2417:def FAlt (T : ℝ) : ℝ :=\nresearch\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean:2431:def Bn (F : ℝ → ℝ) (n : ℝ) : ℝ :=' num_lines=8 num_matches=None applied_limit=None applied_offset=None
tool: Grep
input
{
"pattern": "mem_sphere_iff_norm",
"path": "D:\\Python\\Quantum\\zeta-23-lean\\.lake\\packages\\mathlib\\Mathlib\\Topology\\MetricSpace\\ProperSpace\\Basic.lean",
"output_mode": "content",
"head_limit": 5
}
thinking (2832 chars)
Hmm — the Field/Basic.lean doesn't have the a/c ≤ a/b lemma by that grep (maybe different file). The strong toolbox: `gcongr` is the modern way — Zeta23 uses it. In the sphere bound, replace the calc step:
```lean
calc ‖scaledZeta t w‖ / ‖collProd ht w‖
≤ (9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht := by
gcongr
· exact norm_nonneg _ -- 0 ≤ ‖F‖? gcongr side conditions
· exact hF
· exact hPpos
· exact hP
```
gcongr for a/d ≤ b/c with pattern _/_ ≤ _/_: it reduces to a ≤ b and c ≤ d plus side conditions 0 ≤ a? 0 < c... gcongr discharges what it can and leaves the rest. Let me structure: `gcongr` then supply remaining goals. Uncertain about exact side goals — safer to do it in two explicit steps:
Step 1: ‖F‖/‖P‖ ≤ ‖F‖/δ^M: numerator fixed ≥ 0, 0 < δ^M ≤ ‖P‖: the lemma `div_le_div_of_nonneg_left`... not found. Current name? Let me search for `div_le_div_of_le_left` or use div_le_div_iff: ‖F‖/‖P‖ ≤ ‖F‖/δ^M ⟺ (div_le_div_iff (hb : 0 < b) (hc : 0 < c)?) `div_le_div_iff (hb : 0 < b) (hd : 0 < d) : a / b ≤ c / d ↔ a * d ≤ c * b` ✓ that exists I'm fairly sure. So:
‖F‖/‖P‖ ≤ X/δ^M ⟺ ‖F‖·δ^M ≤ X·‖P‖: from ‖F‖ ≤ X and δ^M ≤ ‖P‖ and nonneg: nlinarith [hF, hP, hPpos, norm_nonneg, ...] — products of ≤: nlinarith can do: (X − ‖F‖)·(‖P‖) + ‖F‖·(‖P‖ − δ^M) ≥ 0 etc. nlinarith [hF, hP, hPpos, hXnonneg, hnormP] with hXnonneg : 0 ≤ (9/4)|t|². Let me just do:
```lean
have hXnn : (0:ℝ) ≤ (9 / 4) * |t| ^ 2 := by positivity
have hnormP : 0 < ‖collProd ht w‖ := hPpos.trans_le hP
rw [div_le_div_iff hnormP hPpos] -- hmm: div_le_div_iff (0<b) (0<d) : a/b ≤ c/d ↔ a*d ≤ c*b
-- goal: ‖F‖ * δ^M ≤ X * ‖P‖
nlinarith [hF, hP, hPpos, hXnn, norm_nonneg (scaledZeta t w)]
```
div_le_div_iff signature: `div_le_div_iff (hb : 0 < b) (hd : 0 < d) : a / b ≤ c / d ↔ a * d ≤ c * b` ✓ (exists in Field/Basic usually). With a := ‖F‖, b := ‖P‖, c := X, d := δ^M: goal becomes ‖F‖ * δ^M ≤ X * ‖P‖. nlinarith: X·‖P‖ − ‖F‖·δ^M = X·(‖P‖ − δ^M) + (X − ‖F‖)·δ^M ≥ 0: X ≥ 0, ‖P‖−δ^M ≥ 0, X−‖F‖ ≥ 0, δ^M > 0: products needed: nlinarith [mul_nonneg hXnn (sub_nonneg.mpr hP), mul_nonneg (sub_nonneg.mpr hF) hPpos.le] — provide the product hints explicitly. ✓ robust.
5. **Metric.mem_sphere_iff_norm unknown** — the lemma is just `mem_sphere_iff_norm` (root namespace, seen in AbsMax.lean usage `mem_sphere_iff_norm.1`). Fix: `rw [mem_sphere_iff_norm, sub_zero] at hz`. In DiskBound they used `rw[mem_sphere_iff_norm, sub_zero] at hw` ✓ root namespace.
Also check: did the earlier `simp only [hfin, ↓reduceDIte]` + `rw [dif_neg hw]` + congrArg + prod_congr compile in Cf_eq_div_collProd? No error reported for it — ✓ compiled. And Cf_eq_zeroFactor_div's fix (remove trailing exact since congr 1 closes) — the error at 707 was "No goals" — let me view the current text around 700-712 to fix precisely.
Fixing: `gcongr`-free two-step div bound, root-namespace `mem_sphere_iff_norm`, forward `prod_pow_eq_pow_sum`, and the zeroFactor congr.
tool: Read ok
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"offset": 694,
"limit": 18
}
result 2026-08-22 21:45:56Z → 2026-08-26 03:24:44Z
{
"type": "text",
"file": {
"filePath": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiSkeleton.lean",
"content": " linarith\n have hsf : (4.56 * ((eA + eB) + (s + 1) * (-a * eA - b * eB))) / s =\n 4.56 * ((eA + eB) / s + (s + 1) * (-a * eA - b * eB) / s) := by\n field_simp [hs0.ne']\n rw [hsf]\n have hsf2 : (s + 1) * (-a * eA - b * eB) / s = -((s + 1) * (a * eA + b * eB) / s) := by\n field_simp [hs0.ne']\n ring\n rw [hsf2]\n linarith\n -- step 2: factor out b\u00b2 and b/s termwise\n have hstep2 :\n 4.56 * ((s + 1) * (a ^ 2 * eA + b ^ 2 * eB) +\n (s + 1) * (a * eA + b * eB) / s) \u2264\n 4.56 * (s + 1) * (b ^ 2 + b / s) * (eA + eB) := by\n have hsq : a ^ 2 \u2264 b ^ 2 := by nlinarith [hab, hapos]\n have h1 : a ^ 2 * eA + b ^ 2 * eB \u2264 b ^ 2 * (eA + eB) := by\n nlinarith [mul_le_mul_of_nonneg_right hsq heA.le]\n have h2 : (a * eA + b * eB) / s \u2264 b * (eA + eB) / s := by\n have h := add_le_add (mul_le_mul_of_nonneg_right hab heA.le) (le_refl (b * eB))\n have h' : a * eA + b * eB \u2264 b * (eA + eB) := by nlinarith [h]\n gcongr\n have m1 : (s + 1) * (a ^ 2 * eA + b ^ 2 * eB) \u2264 (s + 1) * (b ^ 2 * (eA + eB)) :=\n mul_le_mul_of_nonneg_left h1 (by linarith)\n have m2 : (s + 1) * (a * eA + b * eB) / s \u2264 (s + 1) * (b * (eA + eB)) / s := by\n have h3 := mul_le_mul_of_nonneg_left h2 (show (0 : \u211d) \u2264 s + 1 by linarith)\n rwa [\u2190 mul_div_assoc, \u2190 mul_div_assoc] at h3\n have e3 : 4.56 * (s + 1) * (b ^ 2 + b / s) * (eA + eB) =\n 4.56 * ((s + 1) * (b ^ 2 * (eA + eB)) + (s + 1) * (b * (eA + eB)) / s) := by\n field_simp [hs0.ne']\n rw [e3]\n exact mul_le_mul_of_nonneg_left (add_le_add m1 m2) (by norm_num)\n -- step 3: the three-factor split\n have hstep3 :\n 4.56 * (s + 1) * (b ^ 2 + b / s) * (eA + eB) =\n 4.56 * ((s + 1) / s) * ((b ^ 2 * s + b) * eA) * (1 + Real.exp (-s / 2)) := by\n have heB' : eB = eA * Real.exp (-s / 2) := by\n rw [heBdef, heAdef, \u2190 Real.exp_add]\n congr 1\n rw [hadef, hbdef]\n ring\n rw [heB']\n field_simp [hs0.ne']\n -- step 4: the three monotone factors at s = \u221a20\n have hu1 : (s + 1) / s \u2264 (1.2237 : \u211d) := by\n have h1 : (1 : \u211d) / s \u2264 1 / 4.4721 := one_div_le_one_div_of_le (by norm_num) hs4\n have h2 : (1 : \u211d) / 4.4721 \u2264 0.2237 := by\n rw [div_le_iff\u2080 (by norm_num : (0 : \u211d) < 4.4721)]\n norm_num\n have h3 : (s + 1) / s = 1 + 1 / s := by field_simp [hs0.ne']\n rw [h3]\n linarith\n have hu2fac : (b ^ 2 * s + b) * eA \u2264 (0.2124 : \u211d) := by\n have hAid : iimA = a := by unfold iimA; rw [\u2190 hLdef, \u2190 hadef]\n have hBid : iimB = b := by unfold iimB; rw [\u2190 hLdef, \u2190 hbdef]\n have hanti := iim_u2_antitone\n rw [hAid, hBid] at hanti\n have hu2le : (b ^ 2 * s + b) * Real.exp (-a * s) \u2264\n (b ^ 2 * Real.sqrt 20 + b) * Real.exp (-a * Real.sqrt 20) :=\n hanti (Set.mem_Ici.mpr (le_refl _)) (Set.mem_Ici.mpr hs) hs\n have hu2val : (b ^ 2 * Real.sqrt 20 + b) * Real.exp (-a * Real.sqrt 20) \u2264\n (0.2124 : \u211d) := by\n have hb2up : b ^ 2 \u2264 (1.92182 : \u211d) := by nlinarith [hb, hbpos]\n have hexp : Real.exp (-a * Real.sqrt 20) \u2264 (0.0212766 : \u211d) := by\n have ht : (3.9635 : \u211d) \u2264 a * Real.sqrt 20 := by\n calc (3.9635 : \u211d) \u2264 0.8862943606 * 4.4721 := by norm_num\n _ \u2264 a * Real.sqrt 20 :=\n mul_le_mul ha hsqrtlo (by norm_num) hapos.le\n have hsum : (47 : \u211d) \u2264 Real.exp (a * Real.sqrt 20) := by\n have h1 := Real.sum_le_exp_of_nonneg (x := (3.9635 : \u211d)) (by norm_num) 7\n have h2 : Real.exp (3.9635 : \u211d) \u2264 Real.exp (a * Real.sqrt 20) :=\n Real.exp_le_exp.mpr ht\n have h3 : (47 : \u211d) \u2264 \u2211 i \u2208 Finset.range 7,\n (3.9635 : \u211d) ^ i / (Nat.factorial i : \u211d) := by\n norm_num [Finset.sum_range_succ]\n linarith\n rw [show -a * Real.sqrt 20 = -(a * Real.sqrt 20) by ring, Real.exp_neg]\n calc (Real.exp (a * Real.sqrt 20))\u207b\u00b9 \u2264 1 / 47 := by\n rw [\u2190 one_div]\n exact one_div_le_one_div_of_le (by norm_num : (0 : \u211d) < 47) hsum\n _ \u2264 0.0212766 := by\n rw [div_le_iff\u2080 (by norm_num : (0 : \u211d) < 47)]; norm_num\n have hpoly : b ^ 2 * Real.sqrt 20 + b \u2264 (9.9811 : \u211d) := by\n have h1 : b ^ 2 * Real.sqrt 20 \u2264 1.92182 * 4.4722 :=\n mul_le_mul hb2up hsqrthi (Real.sqrt_nonneg 20) (by norm_num)\n linarith\n exact le_trans (mul_le_mul hpoly hexp (Real.exp_pos _).le (by norm_num))\n (by norm_num)\n calc (b ^ 2 * s + b) * eA = (b ^ 2 * s + b) * Real.exp (-a * s) := rfl\n _ \u2264 (b ^ 2 * Real.sqrt 20 + b) * Real.exp (-a * Real.sqrt 20) := hu2le\n _ \u2264 0.2124 := hu2val\n have hu3 : 1 + Real.exp (-s / 2) \u2264 (1.1099 : \u211d) := by\n have hexp : Real.exp (-s / 2) \u2264 (0.10982 : \u211d) := by\n have ht : (2.23605 : \u211d) \u2264 s / 2 := by linarith\n have hsum : (9.1064 : \u211d) \u2264 Real.exp (s / 2) := by\n have h1 := Real.sum_le_exp_of_nonneg (x := (2.23605 : \u211d)) (by norm_num) 6\n have h2 : Real.exp (2.23605 : \u211d) \u2264 Real.exp (s / 2) := Real.exp_le_exp.mpr ht\n have h3 : (9.1064 : \u211d) \u2264 \u2211 i \u2208 Finset.range 6,\n (2.23605 : \u211d) ^ i / (Nat.factorial i : \u211d) := by\n norm_num [Finset.sum_range_succ]\n linarith\n rw [show -s / 2 = -(s / 2) by ring, Real.exp_neg]\n calc (Real.exp (s / 2))\u207b\u00b9 \u2264 1 / 9.1064 := by\n rw [\u2190 one_div]\n exact one_div_le_one_div_of_le (by norm_num : (0 : \u211d) < 9.1064) hsum\n _ \u2264 0.10982 := by\n rw [div_le_iff\u2080 (by norm_num : (0 : \u211d) < 9.1064)]; norm_num\n linarith\n -- final assembly\n have hpos1 : (0 : \u211d) \u2264 (b ^ 2 * s + b) * eA :=\n mul_nonneg (by nlinarith [hbpos, hs0, sq_nonneg b]) heA.le\n have hpos2 : (0 : \u211d) \u2264 1 + Real.exp (-s / 2) := by positivity\n have hpos3 : (0 : \u211d) \u2264 (s + 1) / s := by positivity\n have hchain : 4.56 * ((s + 1) / s) * ((b ^ 2 * s + b) * eA) * (1 + Real.exp (-s / 2)) \u2264\n 4.56 * 1.2237 * 0.2124 * 1.1099 := by\n have h1 : ((s + 1) / s) * ((b ^ 2 * s + b) * eA) \u2264 1.2237 * 0.2124 :=\n mul_le_mul hu1 hu2fac hpos1 (by norm_num)\n have h2 : ((s + 1) / s) * ((b ^ 2 * s + b) * eA) * (1 + Real.exp (-s / 2)) \u2264\n 1.2237 * 0.2124 * 1.1099 :=\n mul_le_mul h1 hu3 hpos2 (by positivity)\n have h3 := mul_le_mul_of_nonneg_left h2 (by norm_num : (0 : \u211d) \u2264 4.56)\n have e : (4.56 : \u211d) * (((s + 1) / s) * ((b ^ 2 * s + b) * eA) *\n (1 + Real.exp (-s / 2))) =\n 4.56 * ((s + 1) / s) * ((b ^ 2 * s + b) * eA) * (1 + Real.exp (-s / 2)) := by ring\n have e' : (4.56 : \u211d) * (1.2237 * 0.2124 * 1.1099) = 4.56 * 1.2237 * 0.2124 * 1.1099 := by ring\n rwa [e, e'] at h3\n calc 4.56 * (2 * (-a * eA - b * eB) + (s + 1) * (a ^ 2 * eA + b ^ 2 * eB)) -\n (4.56 * ((eA + eB) + (s + 1) * (-a * eA - b * eB))) / s\n \u2264 4.56 * (s + 1) * (b ^ 2 + b / s) * (eA + eB) := le_trans hstep1 hstep2\n _ = 4.56 * ((s + 1) / s) * ((b ^ 2 * s + b) * eA) * (1 + Real.exp (-s / 2)) := hstep3\n _ \u2264 4.56 * 1.2237 * 0.2124 * 1.1099 := hchain\n _ < 2 := by norm_num\n\n/-! ### Assembly: regularity bundles -/\n\n/-- [PROVED session 011] The blocks are C\u00b2 on (\u22121, \u221e) (all\nL1/L2-singularities lie at T \u2264 \u22121). -/\ntheorem contDiffOn_L1 : ContDiffOn \u211d 2 (fun t => Real.log (t + 2)) (Set.Ioi (-1)) :=\n (contDiffOn_id.add contDiffOn_const).log (fun x hx => by\n have h : -1 < x := hx\n exact ne_of_gt (by linarith : (0 : \u211d) < x + 2))\n\ntheorem contDiffOn_L2 :\n ContDiffOn \u211d 2 (fun t => Real.log (Real.log (t + 2))) (Set.Ioi (-1)) :=\n contDiffOn_L1.log (fun x hx => by\n have h : -1 < x := hx\n exact ne_of_gt (Real.log_pos (by linarith : (1 : \u211d) < x + 2)))\n\ntheorem contDiffOn_L1sq :\n ContDiffOn \u211d 2 (fun t => Real.log (t + 2) ^ 2) (Set.Ioi (-1)) :=\n contDiffOn_L1.pow 2\n\ntheorem contDiffOn_L1L2 : ContDiffOn \u211d 2\n (fun t => Real.log (t + 2) * Real.log (Real.log (t + 2))) (Set.Ioi (-1)) :=\n contDiffOn_L1.mul contDiffOn_L2\n\ntheorem contDiffOn_L2sq :\n ContDiffOn \u211d 2 (fun t => Real.log (Real.log (t + 2)) ^ 2) (Set.Ioi (-1)) :=\n contDiffOn_L2.pow 2\n\ntheorem contDiffOn_TL1 :\n ContDiffOn \u211d 2 (fun t => t * Real.log (t + 2)) (Set.Ioi (-1)) :=\n contDiffOn_id.mul contDiffOn_L1\n\ntheorem contDiffOn_TL2 :\n ContDiffOn \u211d 2 (fun t => t * Real.log (Real.log (t + 2))) (Set.Ioi (-1)) :=\n contDiffOn_id.mul contDiffOn_L2\n\n/-- [PROVED session 011] T(m) = \u221am + 1 is C\u00b2 on (20, \u221e) and maps it\ninto (\u22121, \u221e). -/\ntheorem contDiffOn_sqrt_shift :\n ContDiffOn \u211d 2 (fun m => Real.sqrt m + 1) (Set.Ioi 20) :=\n (contDiffOn_id.sqrt (fun x hx => by\n have h : 20 < x := hx\n exact ne_of_gt (by linarith : (0 : \u211d) < x))).add contDiffOn_const",
"numLines": 175,
"startLine": 1547,
"totalLines": 2793
}
}
thinking (641 chars)
All fold lemmas compile. Now the main theorem. Let me write it in pieces: first nearZeros + the application-point setup + deriv identity as separate lemmas where possible, then the main theorem. Actually the deriv identity needs J_B from LogOfAnalyticFunction — an existential. Let me structure the main theorem as one big proof but I'll write it in two edits to keep each compile manageable:
Edit A: nearZeros def + mem + a lemma `nearZeros_subset_image` (nearZeros ⊆ collZeros.image aff) + `sum_image_zeroMult` (the push-forward identity) + `sum_image_le` (the Σ_img ≤ Jensen).
Edit B: the main theorem itself.
Let me write Edit A now.
All fold lemmas compile. Now §10: nearZeros + the push-forward machinery.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": " have hprod : (0:\u211d) \u2264 (Real.log |t| - 2) * (354 * Real.log |t| + 131) :=\n mul_nonneg (sub_nonneg.mpr hL) (by nlinarith [hL])\n nlinarith [hprod, hL]\n\nend NguyenRH1",
"new_string": " have hprod : (0:\u211d) \u2264 (Real.log |t| - 2) * (354 * Real.log |t| + 131) :=\n mul_nonneg (sub_nonneg.mpr hL) (by nlinarith [hL])\n nlinarith [hprod, hL]\n\n/-! ## 10. The near-zero finset and the affine push-forward -/\n\n/-- The nontrivial zeros in the open unit ordinate window about t. -/\ndef nearZeros (t : \u211d) : Finset \u2102 :=\n (zeroDiscFinset t).filter fun \u03c1 => |\u03c1.im - t| < 1\n\ntheorem mem_nearZeros {t : \u211d} {\u03c1 : \u2102} :\n \u03c1 \u2208 nearZeros t \u2194 \u03c1 \u2208 zeroDiscFinset t \u2227 |\u03c1.im - t| < 1 := Finset.mem_filter\n\n/-- The affine map is injective. -/\ntheorem affMap_injOn {t : \u211d} (s : Finset \u2102) :\n Set.InjOn (fun w : \u2102 => discCenter t + (5 / 2 : \u2102) * w) s :=\n fun a _ b _ hab => mul_left_cancel\u2080 (by norm_num : (5 / 2 : \u2102) \u2260 0) (add_left_cancel hab)\n\n/-- zeroMult at the affine image equals the scaled order. -/\ntheorem zeroMult_affMap {t : \u211d} (ht : 10 \u2264 |t|) {w : \u2102} (hw : w \u2208 collZeros ht) :\n zeroMult (discCenter t + (5 / 2 : \u2102) * w) = analyticOrderNatAt (scaledZeta t) w := by\n have h := analyticOrderNatAt_scaledZeta ht\n (((mem_collZeros ht).mp hw).1.trans (rC_lt_one ht).le)\n rw [h]\n rfl\n\n/-- The pushed-forward sum over the image equals the collected sum. -/\ntheorem sum_image_zeroMult_div {t : \u211d} (ht : 10 \u2264 |t|) (g : \u2102 \u2192 \u2102) :\n \u2211 \u03c1 \u2208 (collZeros ht).image (fun w : \u2102 => discCenter t + (5 / 2 : \u2102) * w), g \u03c1\n = \u2211 w \u2208 collZeros ht, g (discCenter t + (5 / 2 : \u2102) * w) :=\n Finset.sum_image (affMap_injOn _)\n\n/-- Every near zero lies in the affine image of the collected zeros. -/\ntheorem nearZeros_subset_image {t : \u211d} (ht : 10 \u2264 |t|) :\n nearZeros t \u2286 (collZeros ht).image (fun w : \u2102 => discCenter t + (5 / 2 : \u2102) * w) := by\n classical\n intro \u03c1 h\u03c1\n rw [mem_nearZeros] at h\u03c1\n obtain \u27e8h\u03c1disc, h\u03c1im\u27e9 := h\u03c1\n have h\u03c1nt : IsNontrivialZero \u03c1 := zeroDisc_isNontrivial h\u03c1disc\n have h\u03c10 : riemannZeta \u03c1 = 0 := h\u03c1nt.1\n have hnorm1 : \u2016\u03c1 - discCenter t\u2016 \u2264 Real.sqrt 5 := by\n have hsq : Complex.normSq (\u03c1 - discCenter t) \u2264 5 := by\n rw [Complex.normSq_apply]\n have hre : (\u03c1 - discCenter t).re = \u03c1.re - 2 := by\n simp [discCenter, sub_re, add_re, mul_re, ofReal_re, ofReal_im, I_re, I_im]\n have him : (\u03c1 - discCenter t).im = \u03c1.im - t := by\n simp [discCenter, sub_im, add_im, mul_im, ofReal_re, ofReal_im, I_re, I_im]\n have h1 : (\u03c1.re - 2) ^ 2 \u2264 4 := by\n have h2 : |\u03c1.re - 2| \u2264 2 := by\n rw [abs_le]\n constructor <;> linarith [h\u03c1nt.2.1, h\u03c1nt.2.2]\n calc (\u03c1.re - 2) ^ 2 = |\u03c1.re - 2| ^ 2 := by rw [sq_abs]\n _ \u2264 2 ^ 2 := pow_le_pow_left\u2080 (abs_nonneg _) h2 _\n _ = 4 := by norm_num\n have h2 : (\u03c1.im - t) ^ 2 \u2264 1 := by\n have h3 : |\u03c1.im - t| \u2264 1 := h\u03c1im.le\n calc (\u03c1.im - t) ^ 2 = |\u03c1.im - t| ^ 2 := by rw [sq_abs]\n _ \u2264 1 ^ 2 := pow_le_pow_left\u2080 (abs_nonneg _) h3 1\n _ = 1 := by norm_num\n rw [hre, him]\n nlinarith [h1, h2]\n have h4 : \u2016\u03c1 - discCenter t\u2016 ^ 2 \u2264 5 := by\n rw [\u2190 Complex.normSq_eq_norm_sq]\n exact hsq\n calc \u2016\u03c1 - discCenter t\u2016 = Real.sqrt (\u2016\u03c1 - discCenter t\u2016 ^ 2) :=\n (Real.sqrt_sq (norm_nonneg _)).symm\n _ \u2264 Real.sqrt 5 := Real.sqrt_le_sqrt h4\n have h52 : Real.sqrt 5 \u2264 23 / 10 := by\n have h1 : Real.sqrt 5 \u2264 Real.sqrt ((23 / 10) ^ 2) := Real.sqrt_le_sqrt (by norm_num)\n rwa [Real.sqrt_sq (by norm_num)] at h1\n have h25 : \u2016(2 / 5 : \u2102)\u2016 = 2 / 5 := by\n rw [show (2 / 5 : \u2102) = ((2 / 5 : \u211d) : \u2102) by norm_num, Complex.norm_real,\n Real.norm_eq_abs, abs_of_nonneg (by norm_num : (0:\u211d) \u2264 2 / 5)]\n refine Finset.mem_image.mpr \u27e8(2 / 5 : \u2102) * (\u03c1 - discCenter t), ?_, ?_\u27e9\n \u00b7 rw [mem_collZeros ht]\n constructor\n \u00b7 rw [norm_mul, h25]\n calc (2 / 5 : \u211d) * \u2016\u03c1 - discCenter t\u2016 \u2264 (2 / 5) * (23 / 10) :=\n mul_le_mul_of_nonneg_left (hnorm1.trans h52) (by norm_num)\n _ = 23 / 25 := by norm_num\n _ \u2264 rC ht := rC_ge ht\n \u00b7 unfold scaledZeta\n rw [show discCenter t + (5 / 2 : \u2102) * ((2 / 5 : \u2102) * (\u03c1 - discCenter t)) = \u03c1 by ring,\n h\u03c10, zero_div]\n \u00b7 ring\n\n/-- The image-sum of zeroMult is the collected mult-weighted count. -/\ntheorem sum_image_zeroMult_le {t : \u211d} (ht : 10 \u2264 |t|) :\n \u2211 \u03c1 \u2208 (collZeros ht).image (fun w : \u2102 => discCenter t + (5 / 2 : \u2102) * w),\n (zeroMult \u03c1 : \u211d)\n \u2264 Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by\n classical\n rw [Finset.sum_image (affMap_injOn _)]\n calc \u2211 w \u2208 collZeros ht, (zeroMult (discCenter t + (5 / 2 : \u2102) * w) : \u211d)\n = \u2211 w \u2208 collZeros ht, (analyticOrderNatAt (scaledZeta t) w : \u211d) :=\n Finset.sum_congr rfl fun w hw => by rw [zeroMult_affMap ht hw]\n _ = (collMultSum ht : \u211d) := by\n unfold collMultSum\n rw [Nat.cast_sum]\n _ \u2264 Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by\n exact scaledZeroFinset_sum_order_le (t := t) ht (r := rC ht)\n (hr := (rC_lt_one ht).le) (rC_le ht)\n\nend NguyenRH1"
}
thinking (8845 chars)
I see — the error is in `sum_image_zeroMult_le` (line 1063-1065): the calc step `_ ≤ ... := by exact scaledZeroFinset_sum_order_le ...` — expected type ↑(collMultSum ht) ≤ RHS — meaning the step `_ = (collMultSum ht : ℝ)` at 1060: its proof `unfold collMultSum; rw [Nat.cast_sum]` — goal was `∑ w ∈ collZeros ht, ↑(analyticOrderNatAt ...) = ↑(collMultSum ht)` — unfold collMultSum unfolds the RHS ↑(Σ...) then rw [Nat.cast_sum] rewrites ↑(Σ) → Σ↑: goal Σ↑ = Σ↑ ✓ rfl. That should work... but the error says at 1064 the expected type is ↑(collMultSum ht) ≤ RHS — meaning the calc's previous-step RHS was NOT the rewritten form — i.e. the equation at 1060 was proved but its RHS remained ↑(collMultSum ht)?? No wait — the calc structure: step2 : (∑ ...) = (collMultSum ht : ℝ). Step 3: (collMultSum ht : ℝ) ≤ RHS — the `_` is (collMultSum ht : ℝ), NOT the unfolded sum! My error: step 2 should be `= (collMultSum ht : ℝ)` but step 3's `_` is then ↑(collMultSum ht) — so h1 must be ↑(collMultSum ht) ≤ RHS. I need one more conversion: ↑(collMultSum ht) = Σ over scaledZeroFinset... Let me restructure step 3:
```lean
_ ≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by
unfold collMultSum
rw [Nat.cast_sum]
exact scaledZeroFinset_sum_order_le (t := t) ht (r := rC ht)
(hr := (rC_lt_one ht).le) (rC_le ht)
```
Here the goal is ↑(collMultSum ht) ≤ RHS; unfold collMultSum → ↑(Σ over collZeros) ≤ RHS; rw [Nat.cast_sum] → Σ↑ over collZeros ≤ RHS; then exact h1 — h1's finset: scaledZeroFinset t (rC ht) (rC_lt_one ht).le vs collZeros ht — defeq ✓ exact works (defeq check).
Same fix needed in collMultSum_le's step — it had the same structure:
```
calc (collMultSum ht : ℝ)
= ∑ ρ ∈ collZeros ht, (↑(order)) := by unfold collMultSum; rw [Nat.cast_sum]
_ ≤ RHS := h1
```
Here step 1: goal ↑(collMultSum ht) = Σ↑: unfold collMultSum → ↑(Σ) = Σ↑; rw [Nat.cast_sum] → Σ↑ = Σ↑ ✓ rfl. Step 2: `_ ≤ RHS := h1` — `_` is Σ↑ over collZeros — h1 : Σ↑ over scaledZeroFinset t (rC ht) (⋯) ≤ RHS — defeq — but the earlier error (line 1064 in the PREVIOUS compile) was at collMultSum_le's h1 line with expected ↑(collMultSum ht) ≤ RHS — meaning step 1's proof FAILED there?? no — it said "has type ∑ over scaledZeroFinset ... ≤ RHS but expected ↑(collMultSum ht) ≤ RHS" — so in collMultSum_le, the `_` at that step was ↑(collMultSum ht) — meaning the FIRST step's equation was `↑(collMultSum ht) = Σ...` and the calc `_` picked up... ugh — no: calc A = B := p1; _ ≤ C := p2 — the `_` := B. In collMultSum_le, B = `∑ ρ ∈ collZeros ht, (↑(analyticOrderNatAt ...) : ℝ)`. If p1 proved A = B correctly, then p2 must be B ≤ C = (Σ↑ over collZeros) ≤ RHS. But the error said expected ↑(collMultSum ht) ≤ RHS — so B was actually ↑(collMultSum ht)?! That means my p1 proof's stated B was... let me re-read my collMultSum_le:
```lean
calc (collMultSum ht : ℝ)
= ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℝ) := by
unfold collMultSum
rw [Nat.cast_sum]
_ ≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := h1
```
Hmm — if unfold+rw proved the step-1 equation, then `_` = the sum-form, and h1 : Σ↑(scaledZeroFinset-form) ≤ RHS — the two finset forms differ (collZeros ht vs scaledZeroFinset t (rC ht) ⋯) — syntactically different but defeq. The error "expected ↑(collMultSum ht) ≤ RHS" — that indicates step-1's proof left goal unf... no, error would've been reported at step 1.
OH WAIT. I bet the issue: `unfold collMultSum` fails silently?? No, unfold fails loudly. Hmm — let me reconsider: the error at line 1064 was in the PREVIOUS compile — which included BOTH collMultSum_le (earlier, ~line 950) and sum_image_zeroMult_le (~1060). The reported error 1064 was sum_image_zeroMult_le's last step — the type mismatch: h1 : ∑ over scaledZeroFinset ≤ RHS vs expected ↑(collMultSum ht) ≤ RHS. So in sum_image_zeroMult_le, the `_` at 1063 was ↑(collMultSum ht) — because step 2 (`_ = (collMultSum ht : ℝ)`) — the `_` in step 3 is ↑(collMultSum ht) — of course! calc A = B := ... ; _ = C := ... ; _ ≤ D := ...: the third step's `_` is C = ↑(collMultSum ht). I wrote it backwards: I have ∑-form = ↑(collMultSum ht), so the next `_` is ↑(collMultSum ht) — and I need ↑(collMultSum ht) ≤ RHS — which is exactly collMultSum... no wait — h1 is about the scaledZeroFinset sum. I need to convert ↑(collMultSum ht) back to the sum form AGAIN in step 3. My calc went: A = ∑↑ = ↑(collMultSum) ≤ RHS — the last step needs ↑(collMultSum ht) ≤ RHS. So:
```lean
_ ≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by
unfold collMultSum
rw [Nat.cast_sum]
exact scaledZeroFinset_sum_order_le (t := t) ht (r := rC ht)
(hr := (rC_lt_one ht).le) (rC_le ht)
```
goal ↑(collMultSum ht) ≤ RHS → unfold → ↑(Σ over collZeros) ≤ RHS → rw [Nat.cast_sum] → Σ↑ over collZeros ≤ RHS → exact h1 (defeq finset forms) ✓.
And collMultSum_le (the earlier one at ~line 950) — its error at 1064? no — previous compile's line 1064 error was reported once. The collMultSum_le had:
```
_ ≤ Real.log ... := h1
```
with `_` = Σ↑ over collZeros (since step 1: ↑(collMultSum) = Σ↑): `_` is the sum form ✓ h1 : scaledZeroFinset-sum ≤ RHS — defeq mismatch should be handled by exact... I used `:= h1` as a TERM — term-mode calc steps use defeq ✓ (the expected type is the `_` form; h1's type defeq to it — exact-style elaboration ✓). Hmm but the earlier error message said expected ↑(collMultSum ht) ≤ ... — that was in sum_image_zeroMult_le (this compile) not collMultSum_le (previous compile)... The previous compile's 1064 error — the file then had different line numbers (that error was ALSO in sum_image_zeroMult_le? No — sum_image_zeroMult_le didn't exist in the previous compile! The previous error at "1064" was in collMultSum_le — with expected ↑(collMultSum ht) ≤ RHS. So collMultSum_le's step-2 `_` was ↑(collMultSum ht) — meaning step-1's equation in collMultSum_le was...
```lean
calc (collMultSum ht : ℝ)
= ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℝ) := by
unfold collMultSum
rw [Nat.cast_sum]
_ ≤ ... := h1
```
Step 1: goal ↑(collMultSum ht) = Σ↑ — unfold collMultSum: ↑(Σ over collZeros) = Σ↑ — rw [Nat.cast_sum]: Nat.cast_sum : ↑(Σ) = Σ↑ — rewriting the LHS ↑(Σ over collZeros) → Σ↑: goal Σ↑ = Σ↑ — rfl-closed ✓. Then step-2 `_` = Σ↑ over collZeros. h1 : Σ↑ over scaledZeroFinset t (rC ht) (rC_lt_one ht).le ≤ RHS. collZeros ht := scaledZeroFinset t (rC ht) (rC_lt_one ht).le — same proof term! (rC_lt_one ht).le in both — defeq ✓ term-mode `:= h1` checks defeq ✓ should've worked. But the error said expected ↑(collMultSum ht) — as if the calc step-1's RHS was ↑(collMultSum ht) — OH WAIT. I see it now! In collMultSum_le I wrote:
```lean
calc (collMultSum ht : ℝ)
= ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℝ) := by
unfold collMultSum
rw [Nat.cast_sum]
```
Hmm no. Let me actually re-read what I wrote for collMultSum_le... From my edit:
```lean
calc (collMultSum ht : ℝ)
= ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℝ) := by
unfold collMultSum
rw [Nat.cast_sum]
_ ≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := h1
_ ≤ 33 + 66 * Real.log |t| := jensen_bound_elementary ht
```
That's right... and the previous error was at 1064 — which in the PREVIOUS file was... the previous compile's error was:
"1064:8: Type mismatch scaledZeroFinset_sum_order_le ht (rC_le ht) has type ∑ ... scaledZeroFinset ... ≤ ... but expected ↑(collMultSum ht) ≤ ..." — with the term `scaledZeroFinset_sum_order_le ht (rC_le ht)` — that's collMultSum_le's h1 WITHOUT the (t :=)(r :=)(hr :=) named args! In the previous compile, h1 was `scaledZeroFinset_sum_order_le (t := t) ht (r := rC ht) (hr := (rC_lt_one ht).le) (rC_le ht)`?? no — the error message shows `scaledZeroFinset_sum_order_le ht (rC_le ht)` — hmm, and expected ↑(collMultSum ht) ≤ RHS. So the `_` was ↑(collMultSum ht) — meaning step-1 failed to establish the sum form and Lean fell back?? When a calc step's proof has an error, the calc continues with the stated RHS anyway (error recovery) — and the error gets reported at BOTH steps potentially... but only one error was reported. Confusing.
Let me just look at the CURRENT line numbers: the current compile reported error at 1064 = sum_image_zeroMult_le's last step (visible in the Read above: lines 1063-1065). And collMultSum_le (earlier in the file ~line 960) did NOT error in this compile! So only two errors this round: line 1021 (pow exponent 1→2) and line 1064 (sum_image_zeroMult_le's last step needing the unfold+rw conversion).
Fixes:
1. Line 1021: `pow_le_pow_left₀ (abs_nonneg _) h3 1` → `pow_le_pow_left₀ (abs_nonneg _) h3 2`.
2. sum_image_zeroMult_le's last step: add unfold+rw before exact.
Two fixes: the pow exponent typo (line 1021) and the cast conversion in `sum_image_zeroMult_le`'s last step.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": " calc (\u03c1.im - t) ^ 2 = |\u03c1.im - t| ^ 2 := by rw [sq_abs]\n _ \u2264 1 ^ 2 := pow_le_pow_left\u2080 (abs_nonneg _) h3 1\n _ = 1 := by norm_num",
"new_string": " calc (\u03c1.im - t) ^ 2 = |\u03c1.im - t| ^ 2 := by rw [sq_abs]\n _ \u2264 1 ^ 2 := pow_le_pow_left\u2080 (abs_nonneg _) h3 2\n _ = 1 := by norm_num"
}
thinking (25084 chars)
All of §10 compiles now. Update todos and write the main theorem (§11). This is the big one. Let me write it carefully in one edit, following my detailed plan. I'll be extra careful with:
- w₀ setup
- F w₀ ≠ 0
- EventuallyEq B = F/P
- logDeriv computations
- J_B obtain + bounds
- the algebra
- the fold
Let me write it now. I'll keep `set` usage minimal (only w₀ and Mbound).
One thing to double check — hJderiv's membership condition: hJderiv : ∀ z ∈ Metric.closedBall 0 (3/5), (deriv J_B) z = (deriv B) z / B z — from LogOfAnalyticFunction's third component `(∀ z ∈ Metric.closedBall 0 r, (deriv J_B) z = (deriv B) z / (B z))` with r := 3/5 ✓.
For the extras bound I need the pieces from the plan. Let me write the extras bound as a standalone lemma to reduce the main proof's size:
```lean
theorem sdiff_sum_norm_le {t : ℝ} (ht : 10 ≤ |t|) {s : ℂ} (hsim : s.im = t) :
‖∑ ρ ∈ (collZeros ht).image (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) \ nearZeros t,
(zeroMult ρ : ℂ) / (s - ρ)‖
≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by
classical
set img := (collZeros ht).image (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) with himg
calc ‖∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)‖
≤ ∑ ρ ∈ img \ nearZeros t, ‖(zeroMult ρ : ℂ) / (s - ρ)‖ := norm_sum_le _ _
_ ≤ ∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℝ) := by
apply Finset.sum_le_sum
intro ρ hρ
have hρimg : ρ ∈ img := (Finset.mem_sdiff.mp hρ).1
have hρnotnear : ρ ∉ nearZeros t := (Finset.mem_sdiff.mp hρ).2
obtain ⟨w, hw, rfl⟩ := Finset.mem_image.mp hρimg
-- ρ = s₀ + (5/2)w, w collected
have hρdisc : discCenter t + (5 / 2 : ℂ) * w ∈ zeroDiscFinset t := by
rw [mem_zeroDiscFinset]
constructor
· rw [Metric.mem_closedBall, Complex.dist_eq, add_sub_cancel_left, norm_mul]
have h25 : ‖(5 / 2 : ℂ)‖ = 5 / 2 := by
rw [show (5 / 2 : ℂ) = ((5 / 2 : ℝ) : ℂ) by norm_num, Complex.norm_real,
Real.norm_eq_abs, abs_of_nonneg (by norm_num : (0:ℝ) ≤ 5 / 2)]
rw [h25]
have hwle := ((mem_collZeros ht).mp hw).1
calc (5 / 2 : ℝ) * ‖w‖ ≤ (5 / 2) * rC ht :=
mul_le_mul_of_nonneg_left hwle (by norm_num)
_ = collRadius ht := by unfold rC; ring
_ ≤ 5 / 2 := (collRadius_le ht).trans (by norm_num)
· have hFw : scaledZeta t w = 0 := ((mem_collZeros ht).mp hw).2
unfold scaledZeta at hFw
exact (div_eq_zero_iff.mp hFw).resolve_right (fun h0 => by
have h := RvM.zeta_lower_bound_two t
rw [← show discCenter t = 2 + t * Complex.I from rfl, h0, norm_zero] at h
norm_num at h)
have himge : 1 ≤ |(discCenter t + (5 / 2 : ℂ) * w).im - t| := by
by_contra h
push Not at h
exact hρnotnear (mem_nearZeros.mpr ⟨hρdisc, h⟩)
-- ‖s − ρ‖ ≥ |im(s−ρ)| = |t − im(aff w)| ≥ 1
have hsnorm : (1:ℝ) ≤ ‖s - (discCenter t + (5 / 2 : ℂ) * w)‖ := by
have h1 : |s.im - (discCenter t + (5 / 2 : ℂ) * w).im| ≤
‖s - (discCenter t + (5 / 2 : ℂ) * w)‖ := abs_im_le_norm _
rw [hsim, abs_sub_comm] at h1
linarith
rw [norm_div, RCLike.norm_natCast] -- hmm: ‖(m:ℂ)‖ = (m:ℝ): Complex.norm_natCast?
rw [← div_one ((zeroMult (discCenter t + (5 / 2 : ℂ) * w) : ℝ))]
rw [div_le_div_iff₀ (zero_lt_one.trans_le hsnorm) one_pos]
exact mul_le_mul_of_nonneg_left hsnorm (Nat.cast_nonneg _)
_ ≤ ∑ ρ ∈ img, (zeroMult ρ : ℝ) :=
Finset.sum_le_sum_of_subset_of_nonneg Finset.sdiff_subset (fun i _ _ => Nat.cast_nonneg _)
_ ≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := sum_image_zeroMult_le ht
```
Issues:
- After obtain ⟨w, hw, rfl⟩: ρ is replaced by the aff expression. The sum's integrand (zeroMult ρ : ℂ)/(s − ρ) becomes (zeroMult (s₀+(5/2)w) : ℂ)/(s − (s₀+(5/2)w)) ✓.
- ‖(m:ℂ)‖: norm_natCast — the name: `Complex.norm_natCast : ‖(n : ℂ)‖ = n`? or `RCLike.norm_natCast : ‖(n : 𝕜)‖ = n` ✓ RCLike.norm_natCast exists (𝕜 := ℂ via RCLike ℂ). Try Complex.norm_natCast first... In this Mathlib: `RCLike.norm_natCast` I think. Or `Complex.norm_natCast`. Use whichever; fallback `by exact_mod_cast` hmm. There's `Complex.norm_natCast (n : ℕ) : ‖(n : ℂ)‖ = n`? hmm might be `norm_natCast` via `RCLike`. I'll write `RCLike.norm_natCast` — if unknown, switch to `Complex.norm_natCast`. Actually the sum_le_sum goal: ‖(m:ℂ)/(s−ρ)‖ ≤ (m:ℝ): rw [norm_div]: ‖(m:ℂ)‖/‖s−ρ‖ ≤ m: rw [norm_natCast-something]: (m:ℝ)/‖s−ρ‖ ≤ m. Hmm — ‖(m : ℂ)‖ = |(m : ℝ)| via Complex.norm_real? (m:ℂ) = ((m:ℝ):ℂ) via Nat.cast... `Complex.norm_real : ‖(r : ℂ)‖ = |r|` — with (↑m : ℂ) = ((↑m : ℝ) : ℂ): push_cast or `Complex.norm_natCast` direct. Let me use: rw [norm_div, Complex.norm_natCast] and if that fails try RCLike.norm_natCast. Since m : ℕ cast to ℂ — there IS `RCLike.norm_natCast (n : ℕ) : ‖(n : 𝕜)‖ = n`? hmm. In Mathlib 2025: `RCLike.norm_natCast : ‖(n : 𝕜)‖ = n` ✓ I'm fairly confident. Fallback chain available.
- Wait — the target of the rw [norm_div, ...] is ‖(m:ℂ)/(s−ρ)‖ ≤ (m:ℝ) — hmm the sum's per-term: Finset.sum_le_sum's goal: ‖(m:ℂ)/(s−ρ)‖ ≤ (m:ℝ) hmm the RHS (zeroMult (s₀+(5/2)w) : ℝ) — the cast — fine.
Also — `div_le_div_iff₀ (zero_lt_one.trans_le hsnorm) one_pos` : (m:ℝ)/‖s−ρ‖ ≤ (m:ℝ)/1 ⟺ m*1 ≤ m*‖s−ρ‖: after the ← div_one rw, goal: m/‖s−ρ‖ ≤ m/1 ✓ then iff: m*1 ≤ m*‖s−ρ‖ — exact mul_le_mul_of_nonneg_left hsnorm (Nat.cast_nonneg _) : m*1 ≤ m*‖s−ρ‖ ✓ (form a*b ≤ a*c with a := m hmm: mul_le_mul_of_nonneg_left (h : b ≤ c) (ha : 0 ≤ a) : a*b ≤ a*c — b := 1, c := ‖s−ρ‖, a := m: m*1 ≤ m*‖s−ρ‖ ✓ EXACT). But the iff gives goal m*1 ≤ m*‖s−ρ‖ — exactly ✓.
Hmm — `zero_lt_one.trans_le hsnorm` : 0 < 1 → 1 ≤ ‖s−ρ‖ → 0 < ‖s−ρ‖ ✓ (LT.lt.trans_le).
- hsnorm's proof: |s.im − (aff w).im| ≤ ‖s − aff w‖: abs_im_le_norm (s − aff w) : |(s − aff w).im| ≤ ‖s − aff w‖ — (s − aff w).im = s.im − (aff w).im (sub_im) — is abs_im_le_norm's statement about z.im? `Complex.abs_im_le_norm (z : ℂ) : |z.im| ≤ ‖z‖` ✓; applied to z := s − aff w: |(s − aff w).im| — the goal-form |s.im − (aff w).im| — need sub_im rewrite: rw [sub_im] at... Let me write:
```lean
have hsnorm : (1:ℝ) ≤ ‖s - (discCenter t + (5 / 2 : ℂ) * w)‖ := by
have h1 := abs_im_le_norm (s - (discCenter t + (5 / 2 : ℂ) * w))
rw [sub_im, hsim] at h1
rw [abs_sub_comm] at h1
linarith
```
h1 : |(s − affw).im| ≤ ‖s − affw‖; rw [sub_im] at h1: |s.im − (affw).im| ≤ ...; hsim: s.im = t: |t − (affw).im| ≤ ...; abs_sub_comm : |t − (affw).im| = |(affw).im − t|: rw: |(affw).im − t| ≤ ‖...‖; linarith [h1, himge]: himge : 1 ≤ |(affw).im − t| ✓ ⟹ 1 ≤ ‖...‖ ✓ linarith ✓.
Hmm — abs_sub_comm : |a − b| = |b − a| ✓.
- hρdisc's second component: ζ(aff w) = 0: from hFw : scaledZeta t w = 0 — unfold scaledZeta at hFw: ζ(s₀+(5/2)w)/ζ(s₀) = 0 — div_eq_zero_iff.mp : a/b = 0 ↔ a = 0 ∨ b = 0 — .resolve_right (ζ(s₀) ≠ 0) : ζ(aff w) = 0 ✓. But — mem_zeroDiscFinset's second component needs `riemannZeta ρ = 0` with ρ := s₀+(5/2)w ✓ after the rfl-subst ✓.
Wait — the div_eq_zero_iff resolve: div_eq_zero_iff : a / b = 0 ↔ a = 0 ∨ b = 0 — is it `div_eq_zero_iff : a / b = 0 ↔ a = 0 ∨ b = 0` ✓ (GroupWithZero). .mp hFw : ζ(aff w) = 0 ∨ ζ(s₀) = 0; .resolve_right (h : ζ(s₀) ≠ 0) : ζ(aff w) = 0 ✓.
Also note the dist_eq: Complex.dist_eq : dist a b = ‖a − b‖ ✓; goal dist ρ s₀ ≤ 5/2 with ρ := aff w: dist (s₀+(5/2)w) s₀ = ‖(s₀+(5/2)w) − s₀‖ = ‖(5/2)w‖: add_sub_cancel_left : a + b − a = b ✓ pattern (s₀ + (5/2)w) − s₀ ✓.
Also in the calc: (5/2)*‖w‖ ≤ (5/2)*rC ht ✓; = collRadius ht: rC ht = collRadius ht * (2/5) — (5/2)*rC = (5/2)(collRadius·(2/5)) = collRadius: `unfold rC; ring` — the goal (5/2)*rC ht = collRadius ht: unfold rC: (5/2)*(collRadius ht*(2/5)) = collRadius ht: ring ✓ — wait I wrote the calc step as `_ = collRadius ht := by unfold rC; ring` — the step is (5/2)*rC ht = collRadius ht ✓. Then collRadius ht ≤ 5/2: collRadius_le : ≤ 24/10 = 2.4 ≤ 2.5 ✓ .trans (by norm_num) ✓.
Now the MAIN theorem. Let me also handle: nearZeros_subset_image gives nearZeros ⊆ img where img = (collZeros ht).image aff — with `classical` for the image decidability. Finset.sum_sdiff (h : s₁ ⊆ s₂) : (∑ i ∈ s₂ \ s₁, f i) + ∑ i ∈ s₁, f i = ∑ i ∈ s₂, f i ✓.
Main theorem statement:
```lean
/-- **The loose Davenport-disc R-bound** (ii′-5c, D-067 §6): on
σ ∈ [1/2, 7/2], |t| ≥ 10, the log-derivative of ζ minus its near-zero
sum is O((log|t|)²) with the deliberately loose constant 100000. This is
the GROWTH INPUT for the partial-fraction identity (ii′-5e); the tight
constants come from the identity's analysis (ii′-5f). -/
theorem logDeriv_riemannZeta_sub_nearZeros_le {t : ℝ} (ht : 10 ≤ |t|) {s : ℂ}
(hsim : s.im = t) (hσlo : 1 / 2 ≤ s.re) (hσhi : s.re ≤ 7 / 2)
(hs0 : riemannZeta s ≠ 0) :
‖logDeriv riemannZeta s - ∑ ρ ∈ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)‖
≤ 100000 * (Real.log |t|) ^ 2 := by
```
Now the body. Full assembly per plan. Let me write it all.
```lean
classical
-- the application point in the w-coordinate
set w₀ : ℂ := (2 / 5 : ℂ) * (s - discCenter t) with hw₀def
have haff : discCenter t + (5 / 2 : ℂ) * w₀ = s := by rw [hw₀def]; ring
have hw₀norm : ‖w₀‖ ≤ 3 / 5 := by
have hsnorm : ‖s - discCenter t‖ = |s.re - 2| := by
have heq : s - discCenter t = ((s.re - 2 : ℝ) : ℂ) := by
apply Complex.ext_iff.mpr
constructor
· simp [discCenter, sub_re, add_re, mul_re, ofReal_re, ofReal_im, I_re, I_im]
· simp [discCenter, sub_im, add_im, mul_im, ofReal_re, ofReal_im, I_re, I_im, hsim]
rw [heq, Complex.norm_real, Real.norm_eq_abs]
have h25 : ‖(2 / 5 : ℂ)‖ = 2 / 5 := by
rw [show (2 / 5 : ℂ) = ((2 / 5 : ℝ) : ℂ) by norm_num, Complex.norm_real,
Real.norm_eq_abs, abs_of_nonneg (by norm_num : (0:ℝ) ≤ 2 / 5)]
rw [hw₀def, norm_mul, h25, hsnorm]
have hσ : |s.re - 2| ≤ 3 / 2 := by
rw [abs_le]
constructor <;> linarith
calc (2 / 5 : ℝ) * |s.re - 2| ≤ (2 / 5) * (3 / 2) :=
mul_le_mul_of_nonneg_left hσ (by norm_num)
_ = 3 / 5 := by norm_num
-- F and its nonvanishing at w₀
have hζs0 : riemannZeta (discCenter t) ≠ 0 := by
have h := RvM.zeta_lower_bound_two t
intro h0
rw [← show discCenter t = 2 + t * Complex.I from rfl, h0, norm_zero] at h
norm_num at h
have hFw₀ : scaledZeta t w₀ ≠ 0 := by
unfold scaledZeta
rw [haff]
exact div_ne_zero hs0 hζs0
have hw₀notmem : w₀ ∉ SetOfZeros (rC ht) (scaledZeta t) := fun h => hFw₀ h.2
-- B =ᶠ F/P near w₀
have hZclosed : IsClosed (SetOfZeros (rC ht) (scaledZeta t)) := by
have hset : SetOfZeros (rC ht) (scaledZeta t) = ↑(collZeros ht) := by
ext x
rw [Finset.mem_coe, mem_collZeros ht]
rw [hset]
exact (collZeros ht).finite_toSet.isClosed
have hEv1 : ∀ᶠ w in 𝓝 w₀, w ∉ SetOfZeros (rC ht) (scaledZeta t) :=
hZclosed.isOpen_compl.mem_nhds hw₀notmem
have hB_eq : Cf (rC ht) (scaledZeta t) =ᶠ[𝓝 w₀]
fun w => scaledZeta t w / collProd ht w := by
filter_upwards [hEv1] with w hw1
exact Cf_eq_div_collProd ht hw1
```
Hmm — hset: x ∈ SetOfZeros ⟺ x ∈ ↑collZeros: Finset.mem_coe : a ∈ ↑s ↔ a ∈ s ✓; mem_collZeros : x ∈ collZeros ht ↔ ‖x‖ ≤ rC ∧ F x = 0; and x ∈ SetOfZeros (rC ht) F ⟺ ... defeq to the ∧ — the Iff: ext x; goal x ∈ SetOfZeros rC F ↔ x ∈ ↑(collZeros ht): rw [Finset.mem_coe, mem_collZeros ht]: goal x ∈ SetOfZeros rC F ↔ ‖x‖ ≤ rC ht ∧ scaledZeta t x = 0: exact Iff.rfl (defeq ✓ hopefully). Add `exact Iff.rfl`. Since rw leaves the goal — if it's Iff.rfl-closed, rw auto-closes? rw closes goals that become rfl — an Iff that's defeq-true: Iff.rfl — rw tries rfl after rewriting ✓ maybe. Add explicit `· exact Iff.rfl` hmm ext gives one goal. Write:
```lean
have hset : SetOfZeros (rC ht) (scaledZeta t) = ↑(collZeros ht) := by
ext x
rw [Finset.mem_coe, mem_collZeros ht]
exact Iff.rfl
```
Hmm — `Set.Finite.mem_toFinset`-based mem_collZeros... mem_collZeros ht : w ∈ collZeros ht ↔ ‖w‖ ≤ rC ht ∧ scaledZeta t w = 0 ✓. And x ∈ SetOfZeros (rC ht) (scaledZeta t) — unfolds to the same ∧ ✓ Iff.rfl should work (SetOfZeros is a def with setOf; membership reducible? `SetOfZeros R f : Set ℂ := {ρ : ℂ | ‖ρ‖ ≤ R ∧ f ρ = 0}` — x ∈ {ρ | p ρ} ≡ p x by defeq of Set membership on setOf ✓ Iff.rfl works up to defeq — Iff.rfl : Iff a a — needs the two sides defeq ✓).
IsClosed → compl open → mem_nhds: `IsOpen.mem_nhds (hs : IsOpen s) (ha : a ∈ s) : s ∈ 𝓝 a` ✓; the ∀ᶠ form: hZclosed.isOpen_compl : IsClosed S → IsOpen Sᶜ ✓ .mem_nhds (hw₀notmem : w₀ ∈ Sᶜ ⟺ w₀ ∉ S ✓ defeq) : Sᶜ ∈ 𝓝 w₀ — and ∀ᶠ w in 𝓝 w₀, w ∉ S ⟺ Sᶜ ∈ 𝓝 w₀: `Filter.Eventually` def: ∀ᶠ x in l, p x ⟺ {x | p x} ∈ l — the set {x | x ∉ S} vs Sᶜ: defeq (compl is {x | x ∉ s})... `mem_compl_iff`? The eventually predicate w ∉ S — {x | x ∉ S} = Sᶜ definitionally ✓. The term hZclosed.isOpen_compl.mem_nhds hw₀notmem : Sᶜ ∈ 𝓝 w₀; the target ∀ᶠ w in 𝓝 w₀, w ∉ SetOfZeros... — these are defeq but the elaborator needs to see it — might work directly; if not: `exact hZclosed.isOpen_compl.mem_nhds hw₀notmem` after `show SetOfZeros (rC ht) (scaledZeta t)ᶜ ∈ 𝓝 w₀`? Or use `Filter.eventually_iff_exists_mem`... Let me preemptively use a robust form:
```lean
have hEv1 : ∀ᶠ w in 𝓝 w₀, w ∉ SetOfZeros (rC ht) (scaledZeta t) := by
exact hZclosed.isOpen_compl.mem_nhds hw₀notmem
```
if that fails:
```lean
apply Filter.eventually_iff_exists_mem.mpr
exact ⟨_, hZclosed.isOpen_compl.mem_nhds hw₀notmem, fun x hx => hx⟩
```
hmm — eventually_iff_exists_mem : (∀ᶠ x in l, p x) ↔ ∃ s ∈ l, ∀ x ∈ s, p x. The set Sᶜ ∈ 𝓝 w₀ with ∀ x ∈ Sᶜ, x ∉ S ✓. I'll try the direct first.
Continuing the main proof — the logDeriv identities:
```lean
have hF_an : AnalyticAt ℂ (scaledZeta t) w₀ :=
scaledZeta_analytic ht w₀ (by
rw [Metric.mem_closedBall, dist_zero_right]
exact hw₀norm.trans (by norm_num))
have hP_an : AnalyticAt ℂ (collProd ht) w₀ := analyticAt_finset_prod_sub_pow _ _ _
have hP_ne : collProd ht w₀ ≠ 0 := by
unfold collProd
apply Finset.prod_ne_zero_iff.mpr
intro ρ hρ
have hρ0 : scaledZeta t ρ = 0 := ((mem_collZeros ht).mp hρ).2
exact pow_ne_zero _ (sub_ne_zero.mpr (fun h => hFw₀ (by rw [h]; exact hρ0)))
have hlogB : logDeriv (fun w => scaledZeta t w / collProd ht w) w₀
= logDeriv (scaledZeta t) w₀ - logDeriv (collProd ht) w₀ :=
logDeriv_div w₀ hFw₀ hP_ne hF_an.differentiableAt hP_an.differentiableAt
```
collProd ht as a function of w — collProd ht w₀: the def collProd {t} (ht) (w) — as a function `collProd ht` ✓. analyticAt_finset_prod_sub_pow (s : Finset ℂ) (g : ℂ → ℕ) (w : ℂ) : AnalyticAt ℂ (fun z => ∏ ρ ∈ s, (z − ρ) ^ g ρ) w — collProd ht w := ∏ ρ ∈ collZeros ht, (w − ρ)^analyticOrderNatAt (scaledZeta t) ρ ✓ matches with g := fun ρ => analyticOrderNatAt (scaledZeta t) ρ — `analyticAt_finset_prod_sub_pow _ _ _` unifies ✓ (maybe needs show/unfold — collProd ht is the def; AnalyticAt ℂ (collProd ht) w₀ vs AnalyticAt ℂ (fun z => ∏ ...) w₀: defeq via delta ✓ exact should accept. If not: `exact analyticAt_finset_prod_sub_pow (collZeros ht) _ w₀` with a show.)
hlogF:
```lean
have hsne1 : s ≠ 1 := by
intro h1
rw [h1, Complex.one_im] at hsim
rw [← hsim, abs_zero] at ht
norm_num at ht
have hζs_diff : DifferentiableAt ℂ riemannZeta s :=
(analyticAt_riemannZeta_of_ne_one hsne1).differentiableAt
have hζs_diff' : DifferentiableAt ℂ riemannZeta (discCenter t + (5 / 2 : ℂ) * w₀) :=
haff.symm ▸ hζs_diff
have haff_diff : DifferentiableAt ℂ (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ := by
fun_prop
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
have h1 : (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w)
= fun w => (5 / 2 : ℂ) * w + discCenter t := funext fun w => by ring
rw [h1]
have hh : HasDerivAt (fun w : ℂ => (5 / 2 : ℂ) * w + discCenter t) ((5 / 2 : ℂ) * 1) w₀ :=
((hasDerivAt_id w₀).const_mul (5 / 2 : ℂ)).add_const _
exact hh.deriv.trans (by ring)
have hlogF : logDeriv (scaledZeta t) w₀ = (5 / 2 : ℂ) * logDeriv riemannZeta s := by
have hFeq : scaledZeta t = fun w : ℂ =>
(riemannZeta ∘ (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w)) w /
riemannZeta (discCenter t) := funext fun w => rfl
rw [hFeq]
have hga : (riemannZeta ∘ (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w)) w₀ ≠ 0 := by
rw [Function.comp_apply, haff]
exact hs0
rw [logDeriv_div w₀ hga hζs0 (hζs_diff'.comp w₀ haff_diff) (differentiableAt_const _)]
have hlogconst : logDeriv (fun _ : ℂ => riemannZeta (discCenter t)) w₀ = 0 := by
rw [logDeriv_apply, deriv_const, zero_div]
have hlogcomp : logDeriv (riemannZeta ∘ (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w)) w₀
= logDeriv riemannZeta ((fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀) *
deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ :=
logDeriv_comp hζs_diff' haff_diff
rw [hlogcomp, hlogconst, sub_zero, hderiv_aff]
show logDeriv riemannZeta (discCenter t + (5 / 2 : ℂ) * w₀) * (5 / 2 : ℂ) = _
rw [haff]
ring
```
Issues:
- hlogcomp's statement — logDeriv_comp : logDeriv (f ∘ g) x = logDeriv f (g x) * deriv g x ✓ with f := riemannZeta, g := the affine lambda. hζs_diff' : DifferentiableAt ℂ riemannZeta (discCenter t + (5/2)*w₀) — needed: DifferentiableAt ℂ f (g w₀) where g w₀ = (fun w => ...) w₀ ≡ discCenter t + (5/2)*w₀ — defeq beta ✓ should unify.
- After rw [hFeq], goal: logDeriv (fun w => (ζ∘aff) w / c) w₀ = (5/2)*logDeriv ζ s. logDeriv_div w₀ hga hζs0 hdf hdg : logDeriv (fun z => f z / g z) w₀ = logDeriv f w₀ − logDeriv g w₀ with f := (ζ∘aff), g := fun _ => c ✓. rw transforms goal to logDeriv (ζ∘aff) w₀ − logDeriv (fun _ => c) w₀ = (5/2)*logDeriv ζ s ✓ then rw [hlogcomp, hlogconst, sub_zero, hderiv_aff]: goal logDeriv ζ ((fun w => ...) w₀) * (5/2) = (5/2)*logDeriv ζ s — the ((fun w => ...) w₀) is a beta-redex — `show ... (discCenter t + (5/2)*w₀) ...` via defeq ✓ then rw [haff] → logDeriv ζ s * (5/2) = (5/2)*logDeriv ζ s: ring ✓.
Wait — hderiv_aff's hh: ((hasDerivAt_id w₀).const_mul (5/2)) : HasDerivAt (fun x => (5/2)*id x) ((5/2)*1) w₀?? HasDerivAt.const_mul (c : 𝕜) (h : HasDerivAt f f' x) : HasDerivAt (fun x => c * f x) (c * f') x — signature order: `HasDerivAt.const_mul (c) (hf)` or (hf).const_mul c — dot: (hasDerivAt_id w₀).const_mul (5/2:ℂ) : HasDerivAt (fun x => (5/2) * id x) ((5/2)*1) w₀ — hmm const_mul's function: fun x => c * f x with f := id: fun x => (5/2) * id x — vs our (fun w => (5/2)*w + c')... .add_const _ : HasDerivAt (fun x => (5/2) * id x + discCenter t) ((5/2)*1) w₀ — the lambda (fun x => (5/2)*id x + c) vs goal (fun w => (5/2)*w + c): id x vs x — defeq but hh.deriv : deriv (fun x => (5/2)*id x + c) w₀ = (5/2)*1 — the goal after rw [h1]: deriv (fun w => (5/2)*w + discCenter t) w₀ = 5/2: hh.deriv's type mentions id x — exact hh.deriv.trans (by ring) — the deriv-application: deriv (fun x => (5/2)*id x + discCenter t) w₀ vs goal's deriv (fun w => (5/2)*w + discCenter t) w₀ — defeq (id x ≡ x) — .trans's unification uses defeq ✓ probably fine. If problems: `hasDerivAt_id'` variant. Let me preempt: does `hasDerivAt_id'` exist? Hmm. Alternative safe route:
```lean
have hh : HasDerivAt (fun w : ℂ => (5 / 2 : ℂ) * w + discCenter t) ((5 / 2 : ℂ) * 1) w₀ := by
apply HasDerivAt.add_const
exact HasDerivAt.const_mul (5 / 2 : ℂ) (hasDerivAt_id w₀)
```
same lambda issue. You know what — hasDerivAt_id w₀ : HasDerivAt id 1 w₀. There might also be `hasDerivAt_id'` : HasDerivAt (fun x => x) 1 x — I'm not sure. Let me just try and fix at compile.
- The hFeq funext rfl: scaledZeta t w = riemannZeta (discCenter t + (5/2)*w) / riemannZeta (discCenter t) (by def unfold) vs (ζ∘aff) w / c = ζ(aff w)/c where aff w := discCenter t + (5/2)*w ✓ defeq ✓ rfl works (funext fun w => rfl — rfl at each w: scaledZeta t w ≡ (ζ∘aff) w / c — delta scaledZeta + beta comp ✓).
hlogP:
```lean
have hlogP : logDeriv (collProd ht) w₀
= ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℂ) / (w₀ - ρ) := by
unfold collProd
rw [logDeriv_prod (fun ρ hρ => pow_ne_zero _ (sub_ne_zero.mpr (fun h => hFw₀ (by
rw [h]; exact ((mem_collZeros ht).mp hρ).2))))
(fun ρ hρ => ((analyticAt_id.sub analyticAt_const).pow _).differentiableAt)]
apply Finset.sum_congr rfl
intro ρ hρ
rw [logDeriv_fun_pow (differentiableAt_id.sub (differentiableAt_const _))]
rw [logDeriv_apply]
have hd : deriv (fun w : ℂ => w - ρ) w₀ = 1 := by
rw [deriv_sub_const]
exact deriv_id'' w₀ -- name check
rw [hd, mul_one_div]
```
Concern spots: logDeriv_prod with the function `(∏ i ∈ s, f i ·)` — after unfold collProd the goal's function: fun w => ∏ ρ ∈ collZeros ht, (w − ρ) ^ analyticOrderNatAt (scaledZeta t) ρ. The lemma LHS: logDeriv (∏ i ∈ s, f i ·) x — note `(∏ i ∈ s, f i ·)` IS `fun x => ∏ i ∈ s, f i x`?? The notation ∏ i ∈ s, f i where f i is applied to the · placeholder... `(∏ i ∈ s, f i ·)` elaborates to fun x => ∏ i ∈ s, f i x ✓. rw unification: f := fun ρ w => (w − ρ)^order_ρ — should match.
Hmm — actually wait: logDeriv_prod's hf : ∀ i ∈ s, f i x ≠ 0 — my lambda `fun ρ hρ => pow_ne_zero _ (...)` : ∀ ρ ∈ s, ((w₀ − ρ)^order_ρ) ≠ 0 ✓ with f ρ w₀ = (w₀−ρ)^order — f ρ := fun w => (w−ρ)^order_ρ ✓. And hd : ∀ i ∈ s, DifferentiableAt 𝕜 (f i) x: f ρ = fun w => (w−ρ)^order: DifferentiableAt: (analyticAt_id.sub analyticAt_const).pow _ : AnalyticAt ℂ (fun w => (w−ρ)^order) w₀ — analyticAt_id.sub analyticAt_const : AnalyticAt ℂ (id − fun _ => ρ)?? AnalyticAt.sub : AnalyticAt f → AnalyticAt g → AnalyticAt (f − g) — id − const: fun w => id w − ρ = fun w => w − ρ ✓ defeq-ish; .pow _ : AnalyticAt ((id−const)^order) hmm — AnalyticAt.pow : AnalyticAt f → (n) → AnalyticAt (f ^ n) — (f ^ n) w = (f w)^n ✓. The target DifferentiableAt ℂ (fun w => (w−ρ)^order) w₀ — from AnalyticAt ℂ ((fun w => w−ρ)^order)... — hmm (f ^ n) as function: (f^n) w = (f w)^n — Pi.pow_apply — vs fun w => (w−ρ)^order — defeq ✓ .differentiableAt ✓. Risk of mismatch — compile will tell.
deriv_sub_const: check existence — `deriv_sub_const (c : F) : deriv (fun x => f x − c) x = deriv f x`? If it exists: rw gives deriv (fun w => w) w₀... then deriv_id'' hmm — `deriv_id'' : deriv id x = 1`? hmm deriv_id' might be `deriv id = fun _ => 1`. Let me hedge: `simp [deriv_sub_const]` or use `((hasDerivAt_id w₀).sub_const ρ).deriv` — with the id-vs-lambda issue... HasDerivAt.sub_const (c) : HasDerivAt (fun x => f x − c) f' x — with f := id: (fun x => id x − ρ) — displays as (fun x => x − ρ)? `id x` — the TERM is id applied — but hasDerivAt_id w₀'s f is `id` — so sub_const gives fun x => id x − ρ. deriv of that = 1 − 0 = 1... .deriv : deriv (fun x => id x − ρ) w₀ = 1. Our goal: deriv (fun w : ℂ => w − ρ) w₀ = 1. The lambdas fun x => id x − ρ and fun w => w − ρ are defeq (id x ≡ x) but rw-matching fails. Use `show` to bridge: `show deriv (fun w : ℂ => id w - ρ) w₀ = 1` — defeq ✓ then exact ((hasDerivAt_id w₀).sub_const ρ).deriv — the value: sub_const keeps f' = 1 ✓ (HasDerivAt.sub_const : HasDerivAt f f' x → (c) → HasDerivAt (fun x => f x − c) f' x — value UNCHANGED f' = 1 ✓ so .deriv : deriv ... = 1 ✓).
Hmm wait — does HasDerivAt.sub_const exist with that exact behavior? journal-011 gotcha: "HasDerivAt.add_const adds to VALUE (use .comp for precomposition)" — that was about a DIFFERENT thing (they wanted precomposition f(x+c) but add_const gives f(x)+c). For me: `HasDerivAt.add_const (h : HasDerivAt f f' x) (c : F) : HasDerivAt (fun y => f y + c) f' y` ✓ exists. sub_const analog: `HasDerivAt.sub_const (h : HasDerivAt f f' x) (c : F) : HasDerivAt (fun y => f y − c) f' y`? hmm — maybe not existing; add_const with −c... Let me use: (hasDerivAt_id w₀).add_const (−ρ) : HasDerivAt (fun x => id x + (−ρ)) 1 w₀ — fun x => id x + (−ρ) vs fun w => w − ρ: + (−ρ) vs − ρ: defeq (sub = add neg ✓ via sub_eq_add_neg — defeq? sub_eq_add_neg is a theorem (a − b = a + −b) — in a division ring, a − b is DEFINED as a + −b ✓ defeq (SubNegMonoid: sub a b := a + -b ✓ definitional)). So:
```lean
have hd : deriv (fun w : ℂ => w - ρ) w₀ = 1 := by
show deriv (fun w : ℂ => id w + -ρ) w₀ = 1
exact ((hasDerivAt_id w₀).add_const (-ρ)).deriv
```
Hmm the show: deriv (fun w => w − ρ) w₀ vs deriv (fun w => id w + −ρ) w₀ — defeq: id w ≡ w ✓, w − ρ ≡ w + −ρ ✓ (definitional) — show should accept. If fussy: alternative `by simp [deriv_sub_const]`? — deriv_sub_const might not exist; `by fun_prop`-no that's for differentiability. Another robust: `by rw [deriv_sub_const (f := fun w : ℂ => w) (x := w₀) (c := ρ)]; exact deriv_id'' w₀`? — deriv_id'' hmm. Actually I recall clearly now: Mathlib has `deriv_id'' : deriv id = fun _ => 1`?? and `deriv_id' : deriv id x = 1`?? Let me check quickly via grep rather than guessing — I'll grep both deriv_sub_const and deriv_id names before writing. Also `hasDerivAt_id`. Let me do that grep now, plus HasDerivAt.add_const/sub_const, Real.log_le_log signature, norm_sum_le, Finset.sum_sdiff, RCLike.norm_natCast/Complex.norm_natCast.
All §10 compiles. Before writing the main theorem, verifying the exact names I'll need.
tool: Bash
input
{
"command": "cd \"D:/Python/Quantum/zeta-23-lean/.lake/packages/mathlib\" && grep -rn \"theorem deriv_sub_const\\|theorem deriv_id'\\|lemma deriv_id'\\|theorem deriv_id''\" Mathlib/Analysis/Calculus/Deriv/*.lean 2>/dev/null | head -6; echo ---; grep -rn \"theorem HasDerivAt.add_const \\|theorem HasDerivAt.sub_const \" Mathlib/Analysis/Calculus/Deriv/Add.lean Mathlib/Analysis/Calculus/FDeriv/*.lean 2>/dev/null | head -4; echo ---; grep -rn \"theorem log_le_log \\|lemma log_le_log \\|theorem Real.log_le_log \" Mathlib/Analysis/SpecialFunctions/Log/Basic.lean | head -4; echo ---; grep -rn \"theorem norm_sum_le\\b\\|lemma norm_sum_le\\b\" Mathlib/Analysis/ -r 2>/dev/null | head -3; echo ---; grep -rn \"theorem sum_sdiff\\b\" Mathlib/Algebra/BigOperators/ -r 2>/dev/null | head -3; echo ---; grep -rn \"norm_natCast\" Mathlib/Analysis/RCLike/Basic.lean | head -3",
"description": "Verify exact lemma names for the main theorem"
}
thinking (36862 chars)
Confirmed:
- `HasDerivAt.add_const : HasDerivAt (f · + c) f' x → HasDerivAt f f' x` — it's the mpr of `hasDerivAt_add_const_iff (c) : HasDerivAt (f · + c) f' x ↔ HasDerivAt f f' x` — so HasDerivAt.add_const REMOVES the const! Direction: mpr : HasDerivAt f f' x → HasDerivAt (f · + c) f' x — wait: alias ⟨_, HasDerivAt.add_const⟩ := hasDerivAt_add_const_iff — the iff's second component (mpr): Iff.mpr : RHS → LHS where LHS = HasDerivAt (f · + c) f' x, RHS = HasDerivAt f f' x. So HasDerivAt.add_const : HasDerivAt f f' x → HasDerivAt (f · + c) f' x — ADDS the const ✓ (takes h first? mpr of hasDerivAt_add_const_iff c — the (c) is the iff's explicit arg, so HasDerivAt.add_const (c)?? — alias preserves arg order: hasDerivAt_add_const_iff (c : F) : iff — .mpr applied: (hasDerivAt_add_const_iff c).mpr : HasDerivAt f f' x → HasDerivAt (f · + c) f' x. The alias HasDerivAt.add_const := fun c => (iff c).mpr — so HasDerivAt.add_const (c : F) (h : HasDerivAt f f' x)?? hmm — actually the alias ⟨_, X⟩ := thm means X := thm.2 = Iff.mpr — with c as a parameter: HasDerivAt.add_const c : HasDerivAt f f' x → HasDerivAt (f·+c) f' x. So usage: `(hasDerivAt_id' w₀).const_mul (5/2) |>.add_const??` hmm — as dot: h.add_const — if c comes first, dot-notation h.add_const puts h as the first EXPLICIT arg of matching type... Lean dot notation: h.add_const ⟨args⟩ inserts h at the first explicit arg of type HasDerivAt ... — if signature is add_const (c) (h'), then h.add_const discCenter-t would try to unify h with c : F ✗ then find h' slot ✓ (dot notation inserts into the first arg whose type matches the namespace head — HasDerivAt — so h goes to h' ✓ and c is explicit before... hmm dot notation: h.add_const X — h fills the first explicit HasDerivAt-typed arg, X fills remaining in order — if signature is (c : F) (h : HasDerivAt...) then h.add_const X: h → the HasDerivAt arg, X → c ✓ works regardless of order. So `(hasDerivAt_id' w₀).const_mul (5 / 2 : ℂ) |>.add_const (discCenter t)`? Hmm wait — const_mul first: HasDerivAt.const_mul (c) (h : HasDerivAt f f' x) : HasDerivAt (fun y => c * f y) (c * f') x? let me not verify — risk it and fix at compile. Actually simpler for hderiv_aff — use deriv_add_const/deriv_const_mul/deriv_id'' directly:
```lean
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
have h1 : (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w)
= fun w => (5 / 2 : ℂ) * w + discCenter t := funext fun w => by ring
rw [h1, deriv_add_const, deriv_const_mul (5 / 2 : ℂ) differentiableAt_id, deriv_id'']
ring
```
deriv_add_const (c) : deriv (fun y => f y + c) x = deriv f x ✓ (line ~111 in Deriv/Add). deriv_const_mul (c : 𝕜) (hd : DifferentiableAt 𝕜 f x) : deriv (fun y => c * f y) x = c * deriv f x ✓ standard. Then deriv (fun y => y)... wait after deriv_add_const: deriv (fun y => (5/2)*y) w₀; deriv_const_mul (5/2) differentiableAt_id — f := fun y => y? differentiableAt_id : DifferentiableAt 𝕜 id x — the function in deriv (fun y => (5/2)*y) is (fun y => y) — unify f := fun y => y vs id — deriv_const_mul's hd : DifferentiableAt 𝕜 f x — f from the LHS pattern deriv (fun y => c * f y) x — f := fun y => y — then hd must be DifferentiableAt ℂ (fun y => y) w₀ — differentiableAt_id : DifferentiableAt 𝕜 id x — id vs (fun y => y) — defeq ✓ elaboration of `differentiableAt_id` against the needed type — the needed type is a metavariable-directed... in rw [deriv_const_mul (5/2:ℂ) differentiableAt_id] — rw with the term: deriv_const_mul c hd : deriv (fun y => c * f y) x = c * deriv f x — f determined by hd's type: differentiableAt_id : DifferentiableAt ℂ id w₀ — f := id — so the rewrite pattern is deriv (fun y => (5/2) * id y) w₀ — goal has deriv (fun y => (5/2) * y) w₀ — id y vs y — syntactic mismatch ✗!! Use differentiableAt_id' : DifferentiableAt 𝕜 (fun x => x) x? exists: `differentiableAt_id' : DifferentiableAt 𝕜 (fun x => x) x` ✓ likely (paired with hasDerivAt_id'). Then f := fun y => y ✓ pattern deriv (fun y => (5/2)*(fun y => y) y)... — (fun y => y) applied — the LHS of deriv_const_mul is deriv (fun y => c * f y) x with f := (fun y => y): the pattern is deriv (fun y => c * (fun y => y) y) x — beta-redex vs goal's (5/2) * y — rw's matching is up to syntactic-with-some-defeq... rw uses `kabstract` which does NOT beta-reduce patterns by default... ugh.
SIMPLEST ROBUST: prove hderiv_aff via HasDerivAt with explicit construction:
```lean
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
have hh : HasDerivAt (fun w : ℂ => (5 / 2 : ℂ) * w + discCenter t) ((5 / 2 : ℂ) * 1) w₀ :=
((hasDerivAt_id' w₀).const_mul (5 / 2 : ℂ)).add_const (discCenter t)
...
```
same lambda-shape concerns. Honestly the cleanest: `fun_prop`-based HasDerivAt? There's `HasDerivAt` construction via `hasDerivAt_id'` + const_mul + add_const — the resulting function's lambda form: const_mul: HasDerivAt (fun x => c * f x)... with f := (fun x => x): fun x => c * (fun x => x) x — beta-redex AGAIN.
Alternative — bypass entirely: deriv_const_add! `deriv_const_add (c : F) (hd : DifferentiableAt F f x) : deriv (fun y => c + f y) x = deriv f y x`?? hmm — there's `deriv_const_add (c : F) : deriv (fun y => c + f y) x = deriv f x`? I recall deriv_const_add (c) (hd)... exists: `theorem deriv_const_add (c : F) (hd : DifferentiableAt F f x) : deriv (fun y ↦ c + f y) x = deriv f x`? hmm not sure about hd requirement. Our function: fun w => discCenter t + (5/2)*w = const + (fun w => (5/2)*w): deriv_const_add (discCenter t) (hd : DifferentiableAt ℂ (fun w => (5/2)*w) w₀) → deriv (fun w => (5/2)*w) w₀. Then deriv_const_mul for that: fun w => (5/2)*w = fun w => (5/2)*id w?? — the pattern issue again: deriv_const_mul (c) (hd : DifferentiableAt 𝕜 f x) : deriv (fun y => c * f y) x — with the GOAL deriv (fun w => (5/2)*w) w₀: rw [deriv_const_mul] — rw with just the name: pattern deriv (fun y => ?c * ?f y) ?x — match against deriv (fun w => (5/2)*w) w₀: ?c := 5/2, ?f y := y ⟹ ?f := fun w => w — higher-order unification: ?f y =?= y — pattern unification ✓ ?f := fun y => y ✓ rw succeeds, side goal DifferentiableAt ℂ (fun w => w) w₀ — discharged by...? rw doesn't auto-discharge hd — deriv_const_mul has hd as a hypothesis — rw [deriv_const_mul] with the hypothesis as metavariable: creates side goal? rw [thm] where thm has hypotheses: they become NEW GOALS after the main one ✓ (rw can take such lemmas; the hypotheses become goals). Hmm — actually rw [lemma-with-hypotheses] fails with "motive" issues sometimes... it usually works and leaves side goals. Then `exact differentiableAt_id'`. And the final deriv (fun w => w) w₀ after deriv_const_mul rewrite: = (5/2) * deriv (fun w => w) w₀: rw [deriv_id'']: (5/2)*(fun _ => 1) w₀ = (5/2)*1... then ring/norm_num.
Honestly, these micro-rewrites are unpredictable; the most robust is a one-liner via deriv's simp set:
```lean
have hdiff : DifferentiableAt ℂ (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ := by fun_prop
simp [deriv_const_add, deriv_const_mul, hdiff, deriv_id'']
```
Hmm — let me just try variants at compile time. I'll write with the HasDerivAt approach using hasDerivAt_id' and adjust based on the error:
attempt 1:
```lean
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
have hh : HasDerivAt (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) (5 / 2 : ℂ) w₀ := by
have h1 := (hasDerivAt_id' w₀).const_mul (5 / 2 : ℂ)
-- h1 : HasDerivAt (fun x => (5/2) * x) ((5/2) * 1) w₀?? const_mul's value c*f'
have h2 := h1.const_add (discCenter t) -- HasDerivAt.const_add? name!
...
```
HasDerivAt.const_add (c) (h) : HasDerivAt (fun y => c + f y) ... — exists as alias of hasDerivAtFilter_const_add_iff presumably (HasDerivAt.const_add). Our form is discCenter t + (5/2)*w = const + f w with f w = (5/2)*w ✓ const_add fits directly!
h1 := (hasDerivAt_id' w₀).const_mul (5/2:ℂ): HasDerivAt.const_mul (c : 𝕜) (hf : HasDerivAt f f' x) : HasDerivAt (fun y => c * f y) (c * f') y — dot: (hasDerivAt_id' w₀).const_mul (5/2:ℂ) : HasDerivAt (fun y => (5/2)*(fun x => x) y)?? — the body c * f y with f := fun x => x: c * (fun x => x) y — a redex (fun x => x) y — displayed/termed as (fun x => x) y — vs (5/2)*y target — rw/show bridging needed again. GRRR.
OK — decisive robust approach: prove the HasDerivAt by fun_prop! `fun_prop` can prove HasDerivAt? fun_prop proves DifferentiableAt/Continuous/etc — and HasDerivAt? No — fun_prop doesn't compute the derivative VALUE. But there's `deriv` computation via `simp [deriv_add, deriv_const_mul, deriv_id'', ...]` with differentiability side conditions discharged by fun_prop... Actually the CLEANEST: use `deriv_add` with explicit differentiability:
```lean
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
rw [deriv_add (differentiableAt_const _) ((differentiableAt_id).const_mul _)]
rw [deriv_const, deriv_const_mul _ differentiableAt_id]
simp
```
Hmm — deriv_add (hf : DifferentiableAt) (hg) : deriv (f + g) x = deriv f x + deriv g x — the function fun w => discCenter t + (5/2)*w = (fun _ => c) + (fun w => (5/2)*w) — the lambda (fun w => discCenter t + (5/2)*w) vs ((fun _ => c) + (fun w => (5/2)*w)) — Pi.add_apply defeq but syntactic match for rw [deriv_add ...] — deriv_add's LHS pattern: deriv (f + g) x — Hmm `deriv_add : deriv (f + g) x = ...`? statement: deriv_add (hf : DifferentiableAt 𝕜 f x) (hg : DifferentiableAt 𝕜 g x) : deriv (f + g) x = deriv f x + deriv g x — pattern deriv (f + g) x vs goal deriv (fun w => c + (5/2)*w) w₀: is (fun w => c + (5/2)*w) syntactically (?f + ?g)? The lambda body c + (5/2)*w is HAdd.hAdd application — while (f + g) is Pi.instAdd application — `fun w => c + (5/2)*w` ≡ (fun _ => c) + (fun w => (5/2)*w) up to defeq (Pi.add_apply is definitional: (f+g) w = f w + g w by rfl ✓) — but rw's kabstract won't match without syntactic alignment. Use `show` to bridge:
```lean
show deriv ((fun _ : ℂ => discCenter t) + fun w => (5 / 2 : ℂ) * w) w₀ = 5 / 2
```
defeq ✓ (Pi.add_apply rfl). Then rw [deriv_add (differentiableAt_const _) ((differentiableAt_id).const_mul _)]: gives deriv (fun _ => c) w₀ + deriv (fun w => (5/2)*w) w₀ — wait second: deriv ((fun w => (5/2)*w))... deriv_const_mul (c) (hd): deriv (fun y => c * f y) x = c * deriv f x — pattern fun y => (5/2)*w — ?f y := y: HOU ✓: rw [deriv_const_mul (5/2:ℂ) differentiableAt_id] — hmm f := id from differentiableAt_id — pattern fun y => (5/2)*id y vs fun w => (5/2)*w — id y vs y mismatch ✗ again. Use differentiableAt_id' (f := fun x => x): pattern fun y => (5/2)*(fun x => x) y — redex vs (5/2)*w ✗ STILL mismatch. The redex problem!! rw [deriv_id''] expects deriv (fun x => x)...
You know what, the way to kill ALL these lambda-matching issues: `deriv_const_mul_field`? no. USE simp with the differentiability facts — simp handles redexes up to beta-eta:
```lean
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
have hd : DifferentiableAt ℂ (fun w : ℂ => (5 / 2 : ℂ) * w) w₀ :=
differentiableAt_id'.const_mul _
rw [show (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w)
= ((fun _ : ℂ => discCenter t) + fun w => (5 / 2 : ℂ) * w) from rfl]
rw [deriv_add (differentiableAt_const _) hd, deriv_const, deriv_const_mul _ differentiableAt_id',
deriv_id'']
simp
```
- differentiableAt_id' : DifferentiableAt 𝕜 (fun x => x) x ✓ (paired with hasDerivAt_id' — assume exists).
- (differentiableAt_id').const_mul _ : DifferentiableAt ℂ (fun w => (5/2) * (fun x=>x) w)?? const_mul's result function: fun y => c * f y with f := fun x => x — the TYPE displays as DifferentiableAt ℂ (fun y => (5/2)* (fun x=>x) y) w₀ — my hd ascribes DifferentiableAt ℂ (fun w => (5/2)*w) w₀ — ascription checks defeq ✓ (beta) — `have hd : T := term` — term elaborated against T with defeq ✓ fine.
- deriv_add (differentiableAt_const _) hd : deriv ((fun _ => c) + fun w => (5/2)*w) w₀ = deriv (fun _ => c) w₀ + deriv (fun w => (5/2)*w) w₀ — the hd's type must match DifferentiableAt ℂ (fun w => (5/2)*w) w₀ ✓ by ascription ✓. rw with this instance: pattern deriv (?f + ?g) ?x ✓ matches the shown form ✓.
- deriv_const : deriv (fun _ => c) x = 0 ✓ (`deriv_const (c) : deriv (fun _ => c) x = 0` hmm — deriv_const (c : F) (x)? `deriv_const : deriv (fun _ => c) x = 0`? I think deriv_const (c : F) : deriv (fun _ => c) x = 0 with x implicit ✓).
- deriv_const_mul (5/2:ℂ) differentiableAt_id' : deriv (fun y => (5/2) * (fun x => x) y) w₀ = (5/2) * deriv (fun x => x) w₀ — the pattern has the redex — goal has deriv (fun w => (5/2)*w) w₀ — MISMATCH ✗!!
OK here's the thing — deriv_const_mul's LHS: `deriv (fun y => c * f y) x` — with f := (fun x => x), that's `fun y => c * (fun x => x) y` — when Lean PRINTS it might beta-reduce, but the TERM has the redex. rw matching: kabstract finds instances of the pattern in the goal — the pattern fun y => c * (fun x => x) y vs goal subterm fun w => (5/2)*w — kabstract with the pattern's head: lambda — compares bodies: c * ((fun x=>x) y) vs (5/2)*w — up to defeq? kabstract uses `AbstractMVars` with defeq at instances reducible-ish... actually kabstract DOES use defeq (isDefEq) for matching subterms! `rw` uses kabstract which by default matches up to reducible transparency... redexes: (fun x => x) y ≡ y by beta (reducibility-independent, always on) ✓ SO IT MATCHES. Hmm — actually I recall rw failing on beta-redex mismatches sometimes... kabstract's `AbstractMVars` abstracts occurrences found via `isDefEq` with default-ish settings in recent versions (they improved this). It MIGHT work.
Enough — I'll write it with the show+rws and a `simp` finisher, and iterate at compile. Actually the SIMPLEST of all: skip the HasDerivAt/deriv-lemma mess:
```lean
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
have : HasDerivAt (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) (5 / 2 : ℂ) w₀ := by
convert ((hasDerivAt_id' w₀).const_mul (5 / 2 : ℂ)).const_add (discCenter t) using 1
ring
exact this.deriv
```
convert ... using 1: goal HasDerivAt (fun w => c + (5/2)*w) (5/2) w₀ vs provided HasDerivAt (fun y => (5/2)*(fun x=>x) y + ...) hmm const_add's value: c * f' — ((5/2)*1) — and function fun y => C + (5/2)*(fun x=>x) y... convert using 1: reduces to function-equality and value-equality: fun-eq: (fun w => c + (5/2)*w) = (fun y => C + (5/2)*(fun x=>x) y) — convert leaves this as a goal? using 1 gives congruence goals: the two functions equal + values equal — funext+ring... messy too.
FINAL DECISION — brute force via `HasDerivAt` constructor from simpler parts using exact combinators is getting silly. Use the calculus `fun_prop`+`deriv` simp route which is designed for this:
```lean
have hderiv_aff : deriv (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) w₀ = 5 / 2 := by
rw [deriv_add_const]
rw [deriv_const_mul (5 / 2 : ℂ) differentiableAt_id']
rw [deriv_id'']
simp
```
- deriv_add_const (c) : deriv (fun y ↦ f y + c) x = deriv f x — goal's function fun w => discCenter t + (5/2)*w is NOT of the form (fun y => f y + c) (const is on the LEFT) — so first convert: our function = fun w => (5/2)*w + discCenter t (comm):
```lean
have h1 : (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w)
= fun w => (5 / 2 : ℂ) * w + discCenter t := funext fun w => by ring
rw [h1, deriv_add_const, deriv_const_mul (5 / 2 : ℂ) differentiableAt_id', deriv_id'']
simp
```
deriv_const_mul (c) (hd) : deriv (fun y => c * f y) x = c * deriv f x — with hd := differentiableAt_id' : DifferentiableAt ℂ (fun x => x) w₀ — f := fun x => x — the rw-pattern: deriv (fun y => (5/2) * (fun x => x) y) w₀ — goal (after deriv_add_const): deriv (fun w => (5/2)*w) w₀ — kabstract defeq match (beta) — SHOULD work (rw does abstract up to defeq — I've seen deriv_const_mul used in this project? journal gotchas don't mention trouble). deriv_id'' : deriv (fun x => x) = fun _ => 1 — rw: pattern `deriv fun x => x` (not applied!) — goal subterm deriv (fun x => x) w₀ — deriv_id'' as a rewrite: it's deriv (fun x => x) = fun _ => 1 — rewriting the FUNCTION — the goal contains deriv (fun x => x) applied to w₀ — rw [deriv_id''] rewrites `deriv (fun x => x)` subterm → (fun _ => 1) — then goal (fun _ => 1) w₀ = ... — beta-redex — then `simp` or the final (5/2)*((fun _ => 1) w₀) = 5/2: simp beta-reduces + ring: use `simp` then if needed. Actually after all rws the goal: (5/2) * ((fun _ : ℂ => 1) w₀) + 0 = 5/2 hmm order: deriv_add_const: deriv (f+c) = deriv f: goal deriv (fun w => (5/2)*w) w₀ = 5/2 — wait deriv_add_const (c : F) : deriv (fun y ↦ f y + c) x = deriv f x — rw replaces deriv (fun w => (5/2)*w + c) w₀ with deriv (fun w => (5/2)*w) w₀ ✓ goal: deriv (fun w => (5/2)*w) w₀ = 5/2. deriv_const_mul (5/2) differentiableAt_id': rewrites to (5/2) * deriv (fun x => x) w₀ = 5/2. deriv_id'': (5/2) * (fun _ => 1) w₀ = 5/2: simp: beta + mul_one ✓ — but the base: (fun _ => 1) w₀ — simp only [] beta? plain `simp` handles ✓. If deriv_id'' doesn't apply (form: deriv (fun x : 𝕜 => x) = fun _ => 1 — as a rewrite rule L→R on the FUNCTION deriv (fun x => x) — the goal has deriv (fun x => x) w₀ — the subterm deriv (fun x => x) appears ✓ rw works).
OK — good enough; iterate at compile. Similarly for hd in hlogP: deriv (fun w : ℂ => w - ρ) w₀ = 1:
```lean
have hd : deriv (fun w : ℂ => w - ρ) w₀ = 1 := by
rw [deriv_sub_const, deriv_id'']
```
deriv_sub_const (c) : deriv (fun y ↦ f y − c) x = deriv f x ✓ (confirmed exists line 414) — then deriv (fun w => w) w₀: deriv_id'' matches (fun w => w) ≡ (fun x => x) alpha ✓ — hmm deriv_id'' is about `fun x : 𝕜 => x` — alpha-equivalent ✓ — then (fun _ => 1) w₀ = 1 — rfl-close by rw ✓ or trailing simp. Add `; rfl` hmm rw closes if the goal becomes rfl after all rewrites — after deriv_id'' goal is (5/2)... no for hd: goal deriv (fun w => w−ρ) w₀ = 1: rw [deriv_sub_const]: deriv (fun w => w) w₀ = 1; rw [deriv_id'']: (fun _ => 1) w₀ = 1 — defeq-rfl — rw closes goals that become rfl (up to reducible defeq incl beta ✓). OK.
One more name check: differentiableAt_id' exists? and deriv_add_const's exact form `deriv_add_const (c : F) : deriv (fun y ↦ f y + c) x = deriv f x` — from the file listing above line ~111: `theorem deriv_add_const (c : F) : deriv (fun y ↦ f y + c) x = deriv f x` ✓ (I saw deriv_add_const in the sed output: "theorem deriv_add_const (c : F) : deriv (fun y ↦ f y + c) x = deriv f x" hmm the sed output showed derivWithin_add_const and deriv_add_const — yes line ~111: deriv_add_const exists ✓).
Now assemble the main theorem text fully. Remaining pieces after the deriv identities:
```lean
-- J_B from LogOfAnalyticFunction
obtain ⟨J_B, hJ_an, hJ0, hJderiv, hJre⟩ :=
LogOfAnalyticFunction (r := 3 / 5) (R := rC ht) (B := Cf (rC ht) (scaledZeta t))
(by norm_num) (by linarith [rC_ge ht])
((Cf_collZeros_analytic ht).mono (Metric.closedBall_subset_closedBall (by
have h1 := rC_lt_one ht
linarith [rC_pos ht])))
(Cf_collZeros_ne_zero ht)
set Mbound : ℝ := Real.log ((9 / 4) * |t| ^ 2 / gapD t ^ collMultSum ht) with hMdef
have hMpos : 0 < Mbound := by
rw [hMdef]
apply Real.log_pos
have hδM : gapD t ^ collMultSum ht ≤ 1 :=
pow_le_one₀ (gapD_pos t).le ((gapD_le t).trans (by norm_num))
have hδM0 : 0 < gapD t ^ collMultSum ht := pow_pos (gapD_pos t) _
have hX1 : (1:ℝ) ≤ (9 / 4) * |t| ^ 2 := by
have hsq : (10:ℝ) ^ 2 ≤ |t| ^ 2 := (sq_le_sq₀ (by norm_num) (abs_nonneg t)).mpr ht
nlinarith
rw [le_div_iff₀ hδM0, one_mul]
exact hδM.trans hX1
have hReJ : ∀ z ∈ Metric.ball 0 (rC ht), (J_B z).re ≤ Mbound := by
intro z hz
have hzC : z ∈ Metric.closedBall 0 (rC ht) := Metric.ball_subset_closedBall hz
have h1 := hJre z hz
have hBz := Cf_collZeros_norm_le_ball ht hzC
have hBz0 := Cf_collZeros_ne_zero ht hzC
have hlogle : Real.log ‖Cf (rC ht) (scaledZeta t) z‖ ≤ Mbound :=
Real.log_le_log (norm_pos_iff.mpr hBz0) hBz
have hcen := Cf_collZeros_log_norm_zero_nonneg ht
rw [hMdef] at hlogle -- Mbound def
rw [← h1]
linarith [hlogle, hcen]
```
hmm — hMdef : Mbound = Real.log(...): `set ... with hMdef` — hlogle : Real.log ‖B z‖ ≤ Mbound already (Mbound via set-folded in the statement? I wrote the have with Mbound directly ✓ since set replaced occurrences — but the RHS of hBz is the expanded form; Real.log_le_log ... hBz : Real.log ‖B z‖ ≤ Real.log((9/4)|t|²/δ^M) — with set active, does that display as Mbound? set folds occurrences in the GOAL at set-time, not in later terms. The `have hlogle : ... ≤ Mbound := Real.log_le_log ... hBz` — the ascribed type ≤ Mbound vs the term's ≤ Real.log(...) — defeq via hMdef (Mbound is a let/defined local): set introduces Mbound as a local DEFINITION (fvar with value) — defeq ✓ exact-elaboration ✓ fine.
Then h1 : Real.log ‖B z‖ − Real.log ‖B 0‖ = (J_B z).re; goal (J_B z).re ≤ Mbound: rw [← h1] — rewrites (J_B z).re → the log-diff: goal log‖B z‖ − log‖B 0‖ ≤ Mbound: linarith [hlogle (log‖B z‖ ≤ Mbound), hcen (0 ≤ log‖B 0‖)] ✓.
BC:
```lean
have hBC : ‖deriv J_B w₀‖ ≤ 16 * Mbound * (rC ht) ^ 2 / (rC ht - 3 / 5) ^ 3 :=
BorelCaratheodoryDeriv hMpos (by norm_num) (by linarith [rC_ge ht])
hJ_an.analyticOn hJ0 hReJ (by
rw [Metric.mem_closedBall, dist_zero_right]
exact hw₀norm)
have h450 : 16 * Mbound * (rC ht) ^ 2 / (rC ht - 3 / 5) ^ 3 ≤ 450 * Mbound := by
have hrc1 := rC_ge ht
have hrc2 := rC_le ht
have hrc0 := rC_pos ht
have h1 : (rC ht) ^ 2 ≤ (24 / 25 : ℝ) ^ 2 :=
(sq_le_sq₀ hrc0.le (by norm_num)).mpr hrc2
have h2 : (8 / 25 : ℝ) ^ 3 ≤ (rC ht - 3 / 5) ^ 3 :=
pow_le_pow_left₀ (by norm_num) (by linarith) 3
rw [div_le_iff₀ (pow_pos (by linarith : (0:ℝ) < rC ht - 3 / 5) 3)]
nlinarith [hMpos.le, h1, h2, mul_nonneg hMpos.le (sub_nonneg.mpr h1),
mul_nonneg hMpos.le (sub_nonneg.mpr h2)]
```
Goal after rw: 16*Mbound*rC² ≤ 450*Mbound*(rC−3/5)³: nlinarith hints as planned ✓.
deriv identity at w₀:
```lean
have hderivJ : deriv J_B w₀
= deriv (Cf (rC ht) (scaledZeta t)) w₀ / Cf (rC ht) (scaledZeta t) w₀ :=
hJderiv w₀ (by rw [Metric.mem_closedBall, dist_zero_right]; exact hw₀norm)
have hderivB : deriv (Cf (rC ht) (scaledZeta t)) w₀
= deriv (fun w => scaledZeta t w / collProd ht w) w₀ := hB_eq.deriv
have hBval : Cf (rC ht) (scaledZeta t) w₀ = scaledZeta t w₀ / collProd ht w₀ :=
hB_eq.eq_of_nhds
have hlogFP : logDeriv (fun w => scaledZeta t w / collProd ht w) w₀
= (5 / 2 : ℂ) * logDeriv riemannZeta s
- ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℂ) / (w₀ - ρ) := by
rw [hlogB, hlogF, hlogP]
have hkey : deriv J_B w₀ = (5 / 2 : ℂ) * logDeriv riemannZeta s
- ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℂ) / (w₀ - ρ) := by
rw [hderivJ, hderivB, hBval]
exact hlogFP
```
hkey's last: goal deriv (F/P) w₀ / (F/P) w₀ = ... — exact hlogFP : logDeriv (F/P) w₀ = ... — logDeriv f x ≡ deriv f x / f x definitionally ✓ exact works via defeq (delta logDeriv — logDeriv is a def `logDeriv f := fun x => deriv f x / f x`? then logDeriv (F/P) w₀ ≡ deriv (F/P) w₀/(F/P) w₀ by delta+beta ✓).
hζeq:
```lean
have hζeq : logDeriv riemannZeta s
= (2 / 5 : ℂ) * deriv J_B w₀
+ ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℂ) /
(s - (discCenter t + (5 / 2 : ℂ) * ρ)) := by
have h1 : (5 / 2 : ℂ) * logDeriv riemannZeta s
= deriv J_B w₀ + ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℂ) / (w₀ - ρ) := by
rw [hkey]
ring
calc logDeriv riemannZeta s
= (2 / 5 : ℂ) * ((5 / 2 : ℂ) * logDeriv riemannZeta s) := by ring
_ = (2 / 5 : ℂ) * (deriv J_B w₀ + ∑ ρ ∈ collZeros ht,
(analyticOrderNatAt (scaledZeta t) ρ : ℂ) / (w₀ - ρ)) := by rw [h1]
_ = (2 / 5 : ℂ) * deriv J_B w₀ + ∑ ρ ∈ collZeros ht,
(analyticOrderNatAt (scaledZeta t) ρ : ℂ) /
(s - (discCenter t + (5 / 2 : ℂ) * ρ)) := by
rw [mul_add, Finset.mul_sum]
apply congrArg ((2 / 5 : ℂ) * deriv J_B w₀ + ·)
apply Finset.sum_congr rfl
intro ρ hρ
have hX : (w₀ - ρ) ≠ 0 :=
sub_ne_zero.mpr (fun h => hFw₀ (by rw [h]; exact ((mem_collZeros ht).mp hρ).2))
have hden : s - (discCenter t + (5 / 2 : ℂ) * ρ) = (5 / 2 : ℂ) * (w₀ - ρ) := by
rw [hw₀def]; ring
rw [mul_div_assoc, hden]
field_simp [hX, (by norm_num : (5 / 2 : ℂ) ≠ 0)]
ring
```
Hmm — h1's proof: goal (5/2)·logDeriv ζ s = deriv J_B w₀ + Σ; rw [hkey] rewrites deriv J_B w₀ → (5/2)L − Σ: goal (5/2)L = ((5/2)L − Σ) + Σ: ring ✓.
The congrArg application: `apply congrArg ((2 / 5 : ℂ) * deriv J_B w₀ + ·)` — the `·` in a term — congrArg (fun X => A + X)? congrArg (f) (h : a = b) : f a = f b — apply: goal A + X = A + Y — unify f ?a = A + X... f := fun X => A + X, ?a := X ✓ new goal X = Y ✓.
Wait — after rw [mul_add, Finset.mul_sum]: goal: (2/5)*deriv J_B w₀ + ∑ ρ, (2/5)*((m_ρ:ℂ)/(w₀−ρ)) = (2/5)*deriv J_B w₀ + ∑ ρ, (m_ρ:ℂ)/(s−aff ρ). congrArg ✓ then sum_congr per-term: (2/5)*((m:ℂ)/(w₀−ρ)) = (m:ℂ)/(s−affρ). rw [mul_div_assoc]: ((2/5)*m)/(w₀−ρ) = ...; rw [hden]: RHS denominator s−affρ → (5/2)(w₀−ρ): goal ((2/5)*m)/(w₀−ρ) = m/((5/2)*(w₀−ρ)): field_simp [hX, h5]: cross-mult: ((2/5)*m)*((5/2)*(w₀−ρ)) = m*(w₀−ρ): ring ✓ — field_simp might produce a different normal form; ring closes ✓.
Push-forward and split:
```lean
set img := (collZeros ht).image (fun w : ℂ => discCenter t + (5 / 2 : ℂ) * w) with himg
have hsum_img : ∑ ρ ∈ img, (zeroMult ρ : ℂ) / (s - ρ)
= ∑ ρ ∈ collZeros ht, (analyticOrderNatAt (scaledZeta t) ρ : ℂ) /
(s - (discCenter t + (5 / 2 : ℂ) * ρ)) := by
rw [himg, Finset.sum_image (affMap_injOn _)]
apply Finset.sum_congr rfl
intro ρ hρ
rw [zeroMult_affMap ht hρ]
have hsplit : ∑ ρ ∈ img, (zeroMult ρ : ℂ) / (s - ρ)
= ∑ ρ ∈ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)
+ ∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ) := by
have hsub : nearZeros t ⊆ img := by rw [himg]; exact nearZeros_subset_image ht
rw [← Finset.sum_sdiff hsub] -- hmm sum_sdiff: does it exist as to_additive of prod_sdiff?
```
`Finset.prod_sdiff [DecidableEq ι] (h : s₁ ⊆ s₂) : (∏ x ∈ s₂ \ s₁, f x) * ∏ x ∈ s₁, f x = ∏ x ∈ s₂, f x` with @[to_additive] — so `Finset.sum_sdiff (h : s₁ ⊆ s₂) : (∑ x ∈ s₂ \ s₁, f x) + ∑ x ∈ s₁, f x = ∑ x ∈ s₂, f x` EXISTS via to_additive ✓ (my earlier grep just didn't match because it's generated). So:
```lean
have h := Finset.sum_sdiff hsub (f := fun ρ => (zeroMult ρ : ℂ) / (s - ρ))
-- h : (∑ extras) + (∑ near) = ∑ img
linarith?? no — complex sums. Use:
rw [eq_sub_iff_add_eq]...
```
Cleaner: goal Σ_img = Σ_near + Σ_extras: from h : Σ_extras + Σ_near = Σ_img: `rw [add_comm] at h; exact h.symm` ✓:
```lean
rw [add_comm] at h
exact h.symm
```
hmm h : Σ_extras + Σ_near = Σ_img; add_comm at h: hmm rw [add_comm] at h rewrites the FIRST + in h: Σ_near + Σ_extras = Σ_img ✓; .symm : Σ_img = Σ_near + Σ_extras ✓ exact.
Wait — hsub after `set img`: nearZeros_subset_image ht : nearZeros t ⊆ (collZeros ht).image aff — with img set-bound, rw [himg] at... the goal nearZeros t ⊆ img: rw [himg]: himg : img := ... — set's rewrite: himg : img = (collZeros ht).image ... — rw [himg] replaces img with the image ✓ then exact.
Final assembly:
```lean
have hfinal : logDeriv riemannZeta s - ∑ ρ ∈ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)
= (2 / 5 : ℂ) * deriv J_B w₀ + ∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ) := by
rw [hζeq, ← hsum_img, hsplit]
ring
rw [hfinal]
-- the extras norm bound
have hextras : ‖∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)‖
≤ Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by
-- from sdiff_sum machinery + sum_image_zeroMult_le
have h1 : ‖∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)‖
≤ ∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℝ) := by
refine (norm_sum_le _ _).trans (Finset.sum_le_sum fun ρ hρ => ?_)
have hρimg : ρ ∈ img := (Finset.mem_sdiff.mp hρ).1
have hρnotnear : ρ ∉ nearZeros t := (Finset.mem_sdiff.mp hρ).2
rw [himg] at hρimg
obtain ⟨w, hw, rfl⟩ := Finset.mem_image.mp hρimg
... (per-term bound as planned) ...
refine h1.trans ?_
refine (Finset.sum_le_sum_of_subset_of_nonneg Finset.sdiff_subset
(fun i _ _ => Nat.cast_nonneg _)).trans ?_
rw [himg]
exact sum_image_zeroMult_le ht
```
Wait — the per-term: after obtain rfl, goal: ‖(zeroMult (aff w) : ℂ)/(s − aff w)‖ ≤ (zeroMult (aff w) : ℝ). norm_div, norm_natCast: (m:ℝ)/‖s − aff w‖ ≤ m: need ‖s − aff w‖ ≥ 1: via himge (1 ≤ |(aff w).im − t|) — from hρnotnear: ρ = aff w ∉ nearZeros: with hρdisc (aff w ∈ zeroDiscFinset): mem_nearZeros would give |im−t| < 1 — so ¬ ⟹ 1 ≤ |im − t| ✓ (not_lt.mp). hρdisc: as planned (needs the div_eq_zero_iff resolve — ρ ∈ zeroDiscFinset: mem_zeroDiscFinset : ρ ∈ zeroDiscFinset t ↔ ρ ∈ closedBall ∧ ζ ρ = 0 ✓).
norm_natCast name: RCLike.norm_natCast — hmm in the RCLike/Basic.lean:654 it's inside `namespace RCLike`? The grep showed `theorem norm_natCast (n : ℕ) : ‖(n : K)‖ = n` — likely inside namespace RCLike ⟹ RCLike.norm_natCast ✓. Try that; fallback Complex.norm_natCast.
Then:
```lean
calc ‖(2 / 5 : ℂ) * deriv J_B w₀ + ∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)‖
≤ ‖(2 / 5 : ℂ) * deriv J_B w₀‖
+ ‖∑ ρ ∈ img \ nearZeros t, (zeroMult ρ : ℂ) / (s - ρ)‖ := norm_add_le _ _
_ ≤ (2 / 5) * (450 * Mbound) + Real.log ((9 / 4) * |t| ^ 2) / Real.log (33 / 32) := by
have h25 : ‖(2 / 5 : ℂ)‖ = 2 / 5 := by
rw [show (2 / 5 : ℂ) = ((2 / 5 : ℝ) : ℂ) by norm_num, Complex.norm_real,
Real.norm_eq_abs, abs_of_nonneg (by norm_num : (0:ℝ) ≤ 2 / 5)]
rw [norm_mul, h25]
exact add_le_add
(mul_le_mul_of_nonneg_left (hBC.trans h450) (by norm_num : (0:ℝ) ≤ 2 / 5)) hextras
_ ≤ 100000 * (Real.log |t|) ^ 2 := by
have h1 : Mbound ≤ 420 * (Real.log |t|) ^ 2 := by
rw [hMdef]
exact Mbound_le ht
have h2 := jensen_bound_elementary ht
have hL := two_le_log_abs_t ht
have h42 : 33 + 66 * Real.log |t| ≤ 42 * (Real.log |t|) ^ 2 := by
have hprod : (0:ℝ) ≤ (Real.log |t| - 2) * (42 * Real.log |t| + 17) :=
mul_nonneg (sub_nonneg.mpr hL) (by nlinarith [hL])
nlinarith [hprod, hL]
nlinarith [h1, h2, h42, hL, sq_nonneg (Real.log |t|)]
```
The last nlinarith: goal (2/5)*(450*Mbound) + Jensen ≤ 100000L² with h1 : Mbound ≤ 420L², h2 : Jensen ≤ 33+66L, h42 : 33+66L ≤ 42L²: (2/5)*450*Mbound = 180*Mbound ≤ 75600L²; Jensen ≤ 42L²; total ≤ 75642L² ≤ 100000L²: nlinarith [h1, h2, h42, sq_nonneg]: 180*h1 + h42 + 24358*L²: coefficients 180 (on h1), 1 (h42), and 24358*(L² ≥ 0): nlinarith multiplies hypotheses by positive constants: 180*h1 ✓, h42 ✓, and needs (100000−75642)L² = 24358L² ≥ 0 — from sq_nonneg L times 24358 ✓. Should find it. Hmm — (2/5)*(450*Mbound): nlinarith normalizes the numeral arithmetic ✓ (2/5)*450 = 180 exactly ✓.
Wait — h2 is used but with the chain h2.trans h42 — nlinarith gets both, fine (it can chain linearly: Jensen ≤ 33+66L ≤ 42L² — nlinarith treats 33+66L as linear in L and 42L² quadratic — with h42 providing the bridge ✓).
Also — one important check: `hw₀norm` : ‖w₀‖ ≤ 3/5 — used for closedBall(0, 3/5) membership (hJderiv/hBC) AND closedBall(0,1) (hF_an: hw₀norm.trans (by norm_num : 3/5 ≤ 1)) ✓.
And hBC's membership arg: w₀ ∈ closedBall 0 (3/5) ✓.
I think there's one more subtlety: in hlogB, logDeriv_div's f := scaledZeta t (a def!) — logDeriv_div (x) (hf : f x ≠ 0)... — the function in logDeriv (fun w => scaledZeta t w / collProd ht w) w₀: f := fun w => scaledZeta t w? The lemma: logDeriv (fun z => f z / g z) x with f z := scaledZeta t z — unification f := scaledZeta t ✓ (the lambda fun w => scaledZeta t w is eta of scaledZeta t ✓ handled by unification with eta ✓ generally OK). hlogB's conclusion: logDeriv (scaledZeta t) w₀ − logDeriv (collProd ht) w₀ — then in hlogFP I rw [hlogB, hlogF, hlogP]: hlogF : logDeriv (scaledZeta t) w₀ = ... — hlogB's RHS contains logDeriv (scaledZeta t) w₀ ✓ matches hlogF's LHS ✓.
Also hlogF's statement: logDeriv (scaledZeta t) w₀ = (5/2)*logDeriv ζ s — inside its proof, `rw [hFeq]` — hFeq : scaledZeta t = fun w => (ζ∘aff) w / c — the goal: logDeriv (scaledZeta t) w₀ = (5/2)*logDeriv ζ s — rw [hFeq]: logDeriv (fun w => (ζ∘aff) w / c) w₀ = ... ✓ then logDeriv_div with f := (ζ∘aff), g := fun _ => c... logDeriv_div (x) (hf : f x ≠ 0) — f must match: (fun w => (ζ∘aff) w / c) = (fun z => f z / g z) with f := ζ∘aff? f z := (ζ∘aff) z ✓ f := riemannZeta ∘ aff ✓. hf : (ζ∘aff) w₀ ≠ 0 = hga ✓. hg : (fun _ => c) w₀ = c ≠ 0 = hζs0 ✓. hdf : DifferentiableAt ℂ (ζ∘aff) w₀ := hζs_diff'.comp w₀ haff_diff — DifferentiableAt.comp (x) (hf : DifferentiableAt f (g x)) (hg : DifferentiableAt g x) : DifferentiableAt (f ∘ g) x — signature `DifferentiableAt.comp (x : 𝕜) (hf : DifferentiableAt 𝕜' f (g x)) (hg : DifferentiableAt 𝕜 g x) : DifferentiableAt 𝕜' (f ∘ g) x` ✓ hζs_diff' : DifferentiableAt ℂ ζ (discCenter t + (5/2)*w₀) — needed at ((fun w => discCenter t + (5/2)*w) w₀) — the applied form — defeq beta ✓ unification should manage (the g in comp unifies with aff lambda, then g w₀ ≡ aff-expr by beta ✓).
The hlogcomp: logDeriv_comp hζs_diff' haff_diff : logDeriv (ζ ∘ aff) w₀ = logDeriv ζ (aff w₀) * deriv aff w₀ ✓.
After rw [hlogcomp, hlogconst, sub_zero, hderiv_aff]: goal: logDeriv ζ (aff-applied w₀) * (5/2) = (5/2)*logDeriv ζ s — the aff-applied: ((fun w : ℂ => discCenter t + (5/2)*w) w₀) — beta-redex in the goal: `show logDeriv riemannZeta (discCenter t + (5 / 2 : ℂ) * w₀) * (5 / 2 : ℂ) = (5 / 2 : ℂ) * logDeriv riemannZeta s` — defeq beta ✓ — then rw [haff]: logDeriv ζ s * (5/2) = (5/2)*logDeriv ζ s: ring ✓. Hmm — but will `rw [hlogcomp]` work — hlogcomp's LHS: logDeriv (ζ ∘ aff) w₀ vs goal (after hFeq + logDeriv_div rw): logDeriv (ζ∘aff) w₀ − logDeriv (fun _ => c) w₀ — the term logDeriv (ζ∘aff) w₀ ✓ syntactic ✓.
OK — also `show` in hζs_diff' : haff.symm ▸ hζs_diff: haff : aff-expr = s; haff.symm : s = aff-expr; ▸ rewrites s → aff-expr in hζs_diff's type: DifferentiableAt ℂ ζ (aff-expr) ✓ — the ▸ term: `haff.symm ▸ hζs_diff` — ascribed type given ✓ should elaborate (▸ as term with explicit target type works).
One more: `Real.log_le_iff_le_exp` — check name: it's `Real.log_le_iff_le_exp (hx : 0 < x) : log x ≤ y ↔ x ≤ exp y` — I used it in log_9_4_le_one and it compiled ✓ (chunk 3 green). Good.
Now write the whole main theorem + hextras lemma. Actually — I planned hextras inline (h1 inside the final). Fine.
Also need: `Finset.mem_sdiff`, `Finset.sdiff_subset` ✓ standard. `not_lt.mp` ✓.
Let me also prepare hρdisc's proof inline (used in hextras):
```lean
have hρdisc : discCenter t + (5 / 2 : ℂ) * w ∈ zeroDiscFinset t := by
rw [mem_zeroDiscFinset]
constructor
· rw [Metric.mem_closedBall, Complex.dist_eq, add_sub_cancel_left, norm_mul]
have h25 : ‖(5 / 2 : ℂ)‖ = 5 / 2 := by
rw [show (5 / 2 : ℂ) = ((5 / 2 : ℝ) : ℂ) by norm_num, Complex.norm_real,
Real.norm_eq_abs, abs_of_nonneg (by norm_num : (0:ℝ) ≤ 5 / 2)]
rw [h25]
have hwle := ((mem_collZeros ht).mp hw).1
calc (5 / 2 : ℝ) * ‖w‖ ≤ (5 / 2) * rC ht :=
mul_le_mul_of_nonneg_left hwle (by norm_num)
_ = collRadius ht := by unfold rC; ring
_ ≤ 5 / 2 := (collRadius_le ht).trans (by norm_num)
· have hFw : scaledZeta t w = 0 := ((mem_collZeros ht).mp hw).2
unfold scaledZeta at hFw
exact (div_eq_zero_iff.mp hFw).resolve_right hζs0
```
Careful — hζs0 : riemannZeta (discCenter t) ≠ 0 — the div_eq_zero_iff.mp hFw : riemannZeta (discCenter t + (5/2)*w) = 0 ∨ riemannZeta (discCenter t) = 0 — .resolve_right hζs0 : riemannZeta (discCenter t + (5/2)*w) = 0 ✓ — and the goal (mem_zeroDiscFinset's second): riemannZeta (discCenter t + (5/2)*w) = 0 ✓ exactly. But wait — unfold scaledZeta at hFw: scaledZeta t w = riemannZeta (discCenter t + (5/2)*w) / riemannZeta (discCenter t) — the `unfold scaledZeta` — scaledZeta t w — unfold rewrites to the def body applied: (fun t w => ...) t w → after beta: the division ✓.
div_eq_zero_iff : a / b = 0 ↔ a = 0 ∨ b = 0 ✓ (in GroupWithZero — `div_eq_zero_iff : a / b = 0 ↔ a = 0 ∨ b = 0` ✓).
Metric.mem_closedBall : x ∈ closedBall c r ↔ dist x c ≤ r ✓; Complex.dist_eq : dist a b = ‖a − b‖ ✓ (or just dist_eq_norm). In the existing file they used `Metric.mem_closedBall, Complex.dist_eq` ✓ same pattern.
add_sub_cancel_left : a + b − a = b ✓ pattern (discCenter t + (5/2)*w) − discCenter t ✓.
OK — writing the final block now. It's long; I'll write it as ONE edit and compile. Also mark todos.
§10 green. Now the main theorem (§11) — the J_B/BC assembly.
tool: TodoWrite ok
input
{
"todos": [
{
"content": "Read D-067 \u00a76 + journal-023 + LiDisc.lean + LiContour.lean (context)",
"status": "completed",
"activeForm": "Reading context files"
},
{
"content": "R-gap selection: scaled exists_avoiding_midpoint on [2.3, 2.4]",
"status": "completed",
"activeForm": "Building R-gap selection"
},
{
"content": "g := \u03b6/\u220f(s\u2212\u03c1\u2096)^m\u2096 analytic + nonvanishing on closed ball",
"status": "completed",
"activeForm": "Building g analytic/nonvanishing"
},
{
"content": "Bounds: |g| outer circle + \u2212log|g(s\u2080)|",
"status": "completed",
"activeForm": "Proving g bounds"
},
{
"content": "BC assembly \u2192 loose R-bound theorem (main theorem)",
"status": "in_progress",
"activeForm": "Assembling Borel\u2013Carath\u00e9odory"
},
{
"content": "Build green + axiom audit + commit sub-stage",
"status": "pending",
"activeForm": "Building and auditing"
}
]
}
result 2026-08-22 22:23:34Z → 2026-08-22 22:23:34Z
{
"oldTodos": [
"content='Read D-067 \u00a76 + journal-023 + LiDisc.lean + LiContour.lean (context)' status='completed' active_form='Reading context files'",
"content='R-gap selection: scaled exists_avoiding_midpoint on [2.3, 2.4]' status='in_progress' active_form='Building R-gap selection'",
"content='g := \u03b6/\u220f(s\u2212\u03c1\u2096)^m\u2096 analytic + nonvanishing on closed ball' status='pending' active_form='Building g analytic/nonvanishing'",
"content='Bounds: |g| outer circle + \u2212log|g(s\u2080)|' status='pending' active_form='Proving g bounds'",
"content='BC assembly \u2192 loose R-bound theorem' status='pending' active_form='Assembling Borel\u2013Carath\u00e9odory'",
"content='Build green + axiom audit + commit sub-stage' status='pending' active_form='Building and auditing'"
],
"newTodos": [
"content='Read D-067 \u00a76 + journal-023 + LiDisc.lean + LiContour.lean (context)' status='completed' active_form='Reading context files'",
"content='R-gap selection: scaled exists_avoiding_midpoint on [2.3, 2.4]' status='completed' active_form='Building R-gap selection'",
"content='g := \u03b6/\u220f(s\u2212\u03c1\u2096)^m\u2096 analytic + nonvanishing on closed ball' status='completed' active_form='Building g analytic/nonvanishing'",
"content='Bounds: |g| outer circle + \u2212log|g(s\u2080)|' status='completed' active_form='Proving g bounds'",
"content='BC assembly \u2192 loose R-bound theorem (main theorem)' status='in_progress' active_form='Assembling Borel\u2013Carath\u00e9odory'",
"content='Build green + axiom audit + commit sub-stage' status='pending' active_form='Building and auditing'"
],
"cleared": false
}
thinking (2432 chars)
Good progress — the logDeriv chain compiled (hlogB, hlogF, hlogP, hlogcomp all fine!). Four errors:
1. **Line 1153**: `differentiableAt_id'` unknown — use `differentiableAt_id` (the id-form). The deriv_const_mul's hd : DifferentiableAt 𝕜 f x where f := id... then the rewrite pattern has id... Let me look at what's there — `deriv_const_mul (5 / 2 : ℂ) differentiableAt_id'` — differentiableAt_id' doesn't exist in this Mathlib? Then check the name: maybe `differentiableAt_id` is stated with (fun x => x) directly in this version. Let me check.
2. **Line 1193**: `Cf_collZeros_ne_zero ht` — signature mismatch: my lemma is `{w : ℂ} (hw : w ∈ Metric.closedBall 0 (rC ht)) → ... ≠ 0` — i.e. explicit arg version. LogOfAnalyticFunction wants `∀ z ∈ closedBall 0 R, B z ≠ 0` — that's `∀ z, z ∈ ball → ...` — which IS the same as my lemma's form modulo the implicit w. My lemma: Cf_collZeros_ne_zero {t} (ht) {w} (hw) : ... — the w is IMPLICIT. The target ∀ z ∈ ..., ... has z explicit-bounded. So `Cf_collZeros_ne_zero ht` doesn't syntactically match ∀ z ∈ ... — because my lemma's w is implicit. Fix: `fun z hz => Cf_collZeros_ne_zero ht hz`. ✓
3. **Line 1204** (hMpos): `rw [le_div_iff₀ hδM0, one_mul]` — the goal is `1 < X/δ^M` (Real.log_pos wants 1 < x, not 1 ≤!). I used Real.log_pos : 1 < x → 0 < log x. So the goal is 1 < X/δ^M not ≤. Fix: use lt_div_iff₀ : a < b/c ↔ a*c < b: `rw [lt_div_iff₀ hδM0, one_mul]` then need δ^M < X: have: δ^M ≤ 1 ≤ X with at least one strict: X ≥ 225 > 1 ≥ δ^M: δ^M ≤ 1 < X: (hδM.trans_lt (by nlinarith [hX1]: (1:ℝ) < (9/4)|t|^2)) — hX1 : 1 ≤ X; need 1 < X: X ≥ 225: nlinarith [hsq]. Let me restructure:
```lean
have hX1' : (1:ℝ) < (9 / 4) * |t| ^ 2 := by
have hsq : (10:ℝ) ^ 2 ≤ |t| ^ 2 := (sq_le_sq₀ (by norm_num) (abs_nonneg t)).mpr ht
nlinarith
rw [lt_div_iff₀ hδM0, one_mul]
exact hδM.trans_lt hX1'
```
✓ (drop hX1, keep hX1').
4. **Line 1237**: `hB_eq.deriv` — EventuallyEq.deriv : f =ᶠ[𝓝 x] g → deriv f =ᶠ[𝓝 x] deriv g — it's the EVENTUALLY version! I need the pointwise: `Filter.EventuallyEq.deriv_eq`? or `EventuallyEq.deriv (h)` gives =ᶠ... For pointwise deriv f x = deriv g x from f =ᶠ[𝓝 x] g: the lemma is `Filter.EventuallyEq.deriv : f₁ =ᶠ[𝓝 x] f₂ → deriv f₁ x = deriv f₂ x`?? — the error shows hB_eq.deriv has type deriv f =ᶠ[𝓝] deriv g — so .deriv is the eventually version in this Mathlib. The pointwise one: `Filter.EventuallyEq.deriv_eq`? Let me check.
Fixing four errors. Checking `differentiableAt_id'` and the pointwise EventuallyEq-deriv name.
tool: Bash
input
{
"command": "cd \"D:/Python/Quantum/zeta-23-lean/.lake/packages/mathlib\" && grep -rn \"theorem differentiableAt_id\\|lemma differentiableAt_id\" Mathlib/Analysis/Calculus/Deriv/Basic.lean Mathlib/Analysis/Calculus/FDeriv/Basic.lean 2>/dev/null | head -4; echo ---; grep -rn \"EventuallyEq.deriv_eq\\|theorem EventuallyEq.deriv\" Mathlib/Analysis/Calculus/*.lean Mathlib/Analysis/Calculus/**/*.lean 2>/dev/null | head -6",
"description": "Find differentiableAt_id and EventuallyEq.deriv variants"
}
thinking (2003 chars)
The entire LiDisc.lean compiles — only the unused-`ht` warning in `exists_collection_radius` remains. The main theorem `logDeriv_riemannZeta_sub_nearZeros_le` is proved!
Now:
1. Fix the warning (rename ht → _ht in exists_collection_radius? But then collRadius etc. use ht... The warning is for exists_collection_radius's ht being unused — the pigeonhole doesn't need ht. But collRadius ht := (exists_collection_radius ht).choose needs the hypothesis to exist. Just silence by using it... or accept the warning. Existing code has warnings tolerated? Keep clean: rename to `_ht`?? — but then callers pass ht anyway — fine: `_ht` works since nothing references it. Wait — collRadius {t} (ht : 10 ≤ |t|) := (exists_collection_radius ht).choose — the caller passes its ht to exists_collection_radius's _ht ✓ fine. Let me rename in exists_collection_radius only.
Hmm — but wait: does `exists_collection_radius` REALLY not need ht? The gap argument: midpoints in [23,24]/10 — no analytic input ✓ correct, it's combinatorial. Rename to _ht. But collRadius_ge etc. all fine.
2. Full build (`lake build`) to make sure the whole package is green including the root import — wait, is LiDisc imported by the root NguyenRH1.lean? Session 023's commits: LiDisc was committed — check the root file imports. If not imported, add it.
3. Axiom audit of the new declarations.
4. Commit the sub-stage, update journal/STATE at session end. Actually per protocol, at minimum commit now (sub-stage boundary), then write journal + STATE updates and final commit. It's ~session-end territory: ii′-5c is now COMPLETE (both halves). Let me check the time expectations — the session protocol wants journal + STATE + NGUYEN checklist updates at session end. The user hasn't asked to stop; the sub-stage is done. I'll: (a) fix warning, (b) full lake build, (c) axiom audit, (d) commit LiDisc completion, (e) then journal/STATE/NGUYEN updates + final commit, (f) report and suggest next (ii′-5d).
Let me check root imports first.
Main theorem compiles — ii′-5c is now complete. Fixing the lint warning, then full build + audit.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiDisc.lean",
"old_string": "theorem exists_collection_radius {t : \u211d} (ht : 10 \u2264 |t|) :",
"new_string": "theorem exists_collection_radius {t : \u211d} (_ht : 10 \u2264 |t|) :"
}
thinking (1309 chars)
Full build GREEN (8753 jobs, up from 8752 — LiDisc now in the root). The only sorries are the intended skeletons (ValleySkeleton + SuzukiSkeleton).
Now the axiom audit. Per session protocol, audit the new declarations. Let me write a quick PrintAxioms script for the key new decls:
- logDeriv_riemannZeta_sub_nearZeros_le (the capstone)
- scaledZeta_jensen_count (session 023)
- norm_scaledZeta_le, scaledZeta_order_ne_top, one_le_analyticOrderNatAt_scaledZeta
- scaledZeroFinset_sum_order_le, scaledZeroFinset_card_le_sum
- exists_collection_radius, collRadius_ge/le/gap, rC_ge/le/pos/lt_one, rC_gap, collZeros_norm_le
- Cf_eq_div_collProd, Cf_eq_zeroFactor_div, Cf_collZeros_analytic, Cf_collZeros_ne_zero, Cf_collZeros_log_norm_zero_nonneg, Cf_collZeros_norm_le_sphere, Cf_collZeros_norm_le_ball
- log_9_4_le_one, log_33_32_ge, two_le_log_abs_t, jensen_bound_elementary, card96_le, collMultSum_le, log_50_card_le, Mbound_le
- mem_nearZeros, affMap_injOn, zeroMult_affMap, sum_image_zeroMult_div, nearZeros_subset_image, sum_image_zeroMult_le
The pattern from previous sessions: a PrintAxioms.lean exists? There's PrintAxioms.lean and PrintAxiomsAll.lean in the package. Simplest: a scratch file with #print axioms lines, run with lake env lean. Expected: 'propext', 'Classical.choice', 'Quot.sound' only.
Build green (8753 jobs). Now the axiom audit of the new declarations.
tool: Write ok
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\AuditLiDisc.lean",
"content": "/- Session 024 axiom audit \u2014 ii\u2032-5c (LiDisc.lean). Expect the 3 standard\n axioms (propext, Classical.choice, Quot.sound) and NO sorryAx. -/\nimport NguyenRH1\n\nopen NguyenRH1\n\n#print axioms scaledZeta_jensen_count\n#print axioms norm_scaledZeta_le\n#print axioms scaledZeta_order_ne_top\n#print axioms one_le_analyticOrderNatAt_scaledZeta\n#print axioms scaledZeroFinset_sum_order_le\n#print axioms scaledZeroFinset_card_le_sum\n#print axioms exists_collection_radius\n#print axioms collRadius_gap\n#print axioms rC_gap\n#print axioms collZeros_norm_le\n#print axioms Cf_eq_div_collProd\n#print axioms Cf_eq_zeroFactor_div\n#print axioms Cf_collZeros_analytic\n#print axioms Cf_collZeros_ne_zero\n#print axioms Cf_collZeros_log_norm_zero_nonneg\n#print axioms Cf_collZeros_norm_le_sphere\n#print axioms Cf_collZeros_norm_le_ball\n#print axioms log_9_4_le_one\n#print axioms log_33_32_ge\n#print axioms two_le_log_abs_t\n#print axioms jensen_bound_elementary\n#print axioms card96_le\n#print axioms collMultSum_le\n#print axioms log_50_card_le\n#print axioms Mbound_le\n#print axioms mem_nearZeros\n#print axioms affMap_injOn\n#print axioms zeroMult_affMap\n#print axioms sum_image_zeroMult_div\n#print axioms nearZeros_subset_image\n#print axioms sum_image_zeroMult_le\n#print axioms logDeriv_riemannZeta_sub_nearZeros_le\n"
}
result 2026-08-22 22:35:47Z → 2026-08-22 22:35:47Z
{
"type": "create",
"filePath": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\AuditLiDisc.lean",
"content": "/- Session 024 axiom audit \u2014 ii\u2032-5c (LiDisc.lean). Expect the 3 standard\n axioms (propext, Classical.choice, Quot.sound) and NO sorryAx. -/\nimport NguyenRH1\n\nopen NguyenRH1\n\n#print axioms scaledZeta_jensen_count\n#print axioms norm_scaledZeta_le\n#print axioms scaledZeta_order_ne_top\n#print axioms one_le_analyticOrderNatAt_scaledZeta\n#print axioms scaledZeroFinset_sum_order_le\n#print axioms scaledZeroFinset_card_le_sum\n#print axioms exists_collection_radius\n#print axioms collRadius_gap\n#print axioms rC_gap\n#print axioms collZeros_norm_le\n#print axioms Cf_eq_div_collProd\n#print axioms Cf_eq_zeroFactor_div\n#print axioms Cf_collZeros_analytic\n#print axioms Cf_collZeros_ne_zero\n#print axioms Cf_collZeros_log_norm_zero_nonneg\n#print axioms Cf_collZeros_norm_le_sphere\n#print axioms Cf_collZeros_norm_le_ball\n#print axioms log_9_4_le_one\n#print axioms log_33_32_ge\n#print axioms two_le_log_abs_t\n#print axioms jensen_bound_elementary\n#print axioms card96_le\n#print axioms collMultSum_le\n#print axioms log_50_card_le\n#print axioms Mbound_le\n#print axioms mem_nearZeros\n#print axioms affMap_injOn\n#print axioms zeroMult_affMap\n#print axioms sum_image_zeroMult_div\n#print axioms nearZeros_subset_image\n#print axioms sum_image_zeroMult_le\n#print axioms logDeriv_riemannZeta_sub_nearZeros_le\n",
"structuredPatch": [],
"originalFile": null
}
thinking (571 chars)
All 32 declarations: 3 standard axioms only, zero sorryAx.
Cleanup: delete the audit scratch file? Previous sessions kept audit-session013-axioms.txt. I'll save the output to a text file for the record and delete the .lean scratch (or keep both? The package dir has AuditLiDisc.lean — it's not in the lakefile's lean_lib so it won't build with lake build — it's a scratch. To keep the repo tidy, remove the .lean and keep the output? Actually session 013 kept audit-session013-axioms.txt in the package dir. Let me generate the output file and remove the scratch .lean.
All 32 declarations clean (3 standard axioms, no sorryAx). Saving the audit output and removing the scratch.
tool: Bash
input
{
"command": "cd \"D:/Python/Quantum/research/lean/NguyenRH1\" && export PATH=\"$HOME/.elan/bin:$PATH\" && lake env lean AuditLiDisc.lean > audit-session024-axioms.txt 2>&1 && rm AuditLiDisc.lean && tail -3 audit-session024-axioms.txt",
"description": "Save audit output, remove scratch file",
"timeout": 300000
}
thinking (392 chars)
Committed. Now per the session-end protocol: journal entry, STATE.md update, NGUYEN.md checklist update, final commit. The sub-stage ii′-5c is fully complete. The user said "let's do it" for the session — the work is done. Per §8.4 I should write the journal + update STATE + NGUYEN and commit. Let me do that now (the session reached a clean boundary).
Let me write the journal entry first.
ii′-5c committed (c7cbae5). Now the session-end protocol: journal + STATE + NGUYEN updates.
tool: Write
input
{
"file_path": "D:\\Python\\Quantum\\research\\journal\\session-024.md",
"content": "# Session 024 \u2014 2026-08-22 \u2014 ii\u2032-5c COMPLETE: the loose Davenport-disc R-bound\n\n## Directive\nContinue tier ii\u2032-5 per STATE.md: the ii\u2032-5c back half (R-gap, g, BC\nassembly). User: \"I am ready, let's do it.\"\n\n## Outcome: ii\u2032-5c COMPLETE (commit c7cbae5)\n`logDeriv_riemannZeta_sub_nearZeros_le` PROVED: for s with s.im = t,\nre s \u2208 [1/2, 7/2], |t| \u2265 10, \u03b6 s \u2260 0:\n \u2016logDeriv \u03b6 s \u2212 \u03a3_{\u03c1 \u2208 nearZeros t} zeroMult \u03c1/(s\u2212\u03c1)\u2016 \u2264 100000\u00b7(log|t|)\u00b2.\nConstant deliberately loose (D-067 \u00a76 two-stage plan: this is the GROWTH\nINPUT for the ii\u2032-5e partial-fraction identity; the tight 10.5/48 come\nfrom the identity's analysis in ii\u2032-5f). No perimeter hypothesis needed \u2014\nthe count input is the session-023 Jensen bound, not ZeroCountProp.\n\n## Build path (~1000 new lines in LiDisc.lean)\n1. `norm_scaledZeta_le` \u2014 the (9/4)|t|\u00b2 bound extracted from the Jensen\n proof (standalone, for the outer-circle estimate).\n2. Order helpers: `scaledZeta_order_ne_top` (via\n AnalyticOnNhd.analyticOrderAt_ne_top_of_isPreconnected, F(0) = 1),\n `one_le_analyticOrderNatAt_scaledZeta`.\n3. `scaledZeroFinset t r (hr : r \u2264 1)` (subset-of-unit-disc construction,\n avoiding the dite-proof finsets of Zeta23's finiteSetOfZeros_mono) +\n `scaledZeroFinset_24_25_eq` (toFinset_inj.mpr rfl) bridging to the\n Jensen finset; `scaledZeroFinset_sum_order_le` (monotonicity + Jensen),\n `scaledZeroFinset_card_le_sum` (orders \u2265 1).\n4. R-gap: `exists_collection_radius` \u2014 the \u00d710 RESCALE TRICK: apply\n ii\u2032-4's unit-window `exists_avoiding_midpoint` at a = 23 to the \u00d710\n image of the (5/2)-scaled norm finset, divide by 10 \u27f9 R_c \u2208 [2.3, 2.4]\n with clearance 1/(20(k+1)) from every zero-norm \u2014 ZERO new pigeonhole\n code (STATE.md's suggested route). `collRadius`/`rC` bundle via\n Classical.choose; `rC_gap` (gapD t := 1/(50(k+1)) in the w-scale);\n `collZeros_norm_le` (collected zeros satisfy \u2016w\u2016 \u2264 r_c \u2212 gapD).\n5. The Blaschke quotient g := Cf r_c F entirely from Zeta23's Cf API:\n `Cf_eq_div_collProd` / `Cf_eq_zeroFactor_div` (the dite-unfold pair),\n `Cf_collZeros_analytic` (CfAnalytic at R = (1+r_c)/2),\n `Cf_collZeros_ne_zero` (ZeroFactorization at zeros; else-branch off),\n `Cf_collZeros_log_norm_zero_nonneg` (g(0) = 1/\u220f(\u2212\u03c1)^m, \u2016\u03c1\u2016 < 1),\n `Cf_collZeros_norm_le_sphere` (sphere zero-free by the gap; each\n \u2016w\u2212\u03c1\u2016 \u2265 gapD \u27f9 \u2016g\u2016 \u2264 (9/4)|t|\u00b2\u00b7gapD^{\u2212M_c}),\n `Cf_collZeros_norm_le_ball` (AnalyticOn.norm_le_of_norm_le_on_sphere).\n6. Constant fold (all real-analysis, no new input): `log_9_4_le_one`\n (9/4 \u2264 e), `log_33_32_ge` (log x \u2265 1\u22121/x at 33/32 \u27f9 \u2265 1/33),\n `two_le_log_abs_t` (e\u00b2 \u2264 2.7183\u00b2 < 10), `jensen_bound_elementary`\n (\u2264 33+66L), `card96_le`, `collMultSum_le`, `log_50_card_le`\n (50(k+1) \u2264 4150L, log 4150 \u2264 9 via e > 2.71, log L \u2264 L\u22121 \u27f9 \u2264 L+8),\n `Mbound_le` (\u2264 420L\u00b2 via (L\u22122)(354L+131) \u2265 0).\n7. Main assembly: w\u2080 = (2/5)(s\u2212s\u2080) (\u2016w\u2080\u2016 \u2264 3/5 from s.im = t,\n \u03c3 \u2208 [1/2, 7/2]); B =\u1da0[\ud835\udcdd w\u2080] F/P (zero set closed = finset carrier);\n logDeriv chain (logDeriv_div/prod/comp + per-factor\n logDeriv_fun_pow \u27f9 m/(w\u2080\u2212\u03c1)); LogOfAnalyticFunction (r = 3/5,\n R = r_c) + BorelCaratheodoryDeriv (16\u00b7M\u00b7r_c\u00b2/(r_c\u22123/5)\u00b3 \u2264 450M);\n deriv J_B w\u2080 = (5/2)logDeriv \u03b6 s \u2212 \u03a3 m/(w\u2080\u2212\u03c1); the (2/5)-rescaled\n sum pushes forward through the affine image (Finset.sum_image +\n zeroMult_affMap) and splits near/extras (Finset.sum_sdiff); extras\n \u2016s\u2212\u03c1\u2016 \u2265 |t\u2212\u03b3| \u2265 1 \u27f9 \u2264 \u03a3m \u2264 Jensen. Final: 180\u00b7420L\u00b2 + 42L\u00b2 = 75642L\u00b2\n \u2264 100000L\u00b2.\n\n## Banked gotchas (session 024 additions)\n- `Set.Finite.toFinset_inj.mpr rfl` equates toFinsets from different\n finiteness proofs of the same set \u2014 the clean way to handle Cf's\n anonymous dite-bound proof.\n- `div_le_div_iff\u2080 (hb : 0 < b) (hd : 0 < d) : a/b \u2264 c/d \u2194 a*d \u2264 c*b`\n (GroupWithZero/Basic); the 4-arg `div_le_div` does NOT exist in this\n Mathlib. `div_le_iff\u2080 (hc : 0 < c) : a/c \u2264 b \u2194 a \u2264 b*c`.\n- `EventuallyEq.deriv` is the EVENTUALLY version (deriv f =\u1da0 deriv g);\n the pointwise one is `Filter.EventuallyEq.deriv_eq`.\n- `Filter.EventuallyEq.eq_of_nhds` gives pointwise value equality.\n- `Finset.sum_sdiff` exists via to_additive (prod_sdiff) \u2014 grep for\n \"sum_sdiff\" fails since it's generated; same for Finset.sum_image\n (takes Set.InjOn in this Mathlib).\n- `positivity` maxRecDepth-loops on `set`-bound finsets' card casts \u2014\n use explicit `mul_pos`/`add_pos_of_nonneg_of_pos (Nat.cast_nonneg _)`\n terms; and `Nat.cast_nonneg _` inside compound terms needs an\n ascribed target type (IsOrderedRing metavariable stuck otherwise).\n- `Real.log_le_log (0 < x) (x \u2264 y)`, `Real.one_sub_inv_le_log_of_pos`,\n `Real.log_le_iff_le_exp`, `Real.exp_one_gt_d9`/`_lt_d9`,\n `Real.exp_nat_mul : exp (n*x) = (exp x)^n` \u2014 all as expected.\n- `norm_natCast` is `RCLike.norm_natCast` (not Complex.*).\n- `mem_sphere_iff_norm` is root-namespace (not Metric.*).\n- rw [\u2190 mul_one]/[\u2190 div_one] rewrites ALL occurrences of the pattern \u2014\n for one-sided division comparisons use div_le_iff\u2080 + explicit\n mul_nonneg hints to nlinarith instead.\n- `field_simp` sometimes closes the goal entirely (trailing `ring` then\n errors \"no goals\") \u2014 check before appending ring.\n- deriv-computation chain that worked: funext-reorder to (f + const)\n form \u2192 `deriv_add_const` \u2192 `show` with `id w` (defeq) \u2192\n `deriv_const_mul _ differentiableAt_id` \u2192 `deriv_id'` \u2192 `simp`.\n (`differentiableAt_id'`/`deriv_id''` pointwise forms do NOT exist as\n stated; deriv_id' : deriv id = fun _ => 1, deriv_id'' for (fun x=>x).)\n\n## Status / next\nii\u2032-5c COMPLETE. Next per D-067 \u00a76: **ii\u2032-5d** (FE-reflection to\n\u03c3 \u2208 [\u22125/2, 1/2] + the left-plane uniform digamma bound |\u03c8(w) \u2212 log w| \u2264 C\naway from poles), then ii\u2032-5e (partial-fraction identity; needs\nzeroMult(\u22122n) = 1 for ALL n \u2014 generalize ii\u2032-4c's zeroMult_neg_two),\nii\u2032-5f (tight analysis \u2192 10.5/48), ii\u2032-3b (moments), ii\u2032-3c (crux),\nii\u2032-6, ii\u2032-7.\n"
}
thinking (393 chars)
Also update the gotchas line in STATE.md's handoff to point at journal-024, and update NGUYEN.md's Phase 5B checklist (the ii′-5c entry). Let me also add a short line to the Lean gotchas section in STATE.md — actually the NEXT ACTION already references journal-024 gotchas. Let me add the session-024 entry to the NGUYEN.md §8.6 session log and update the ii′-5c checklist line in §5 Phase 5B.
Now the NGUYEN.md checklist updates.
tool: Edit
input
{
"file_path": "D:\\Python\\Quantum\\NGUYEN.md",
"old_string": " plan: loose disc bound as the GROWTH INPUT for the\n partial-fraction identity (5e), tight constants from D-056's\n analysis of the identity (5f). **ii\u2032-5c HALF (session 023)**:\n LiDisc.lean \u2014 zeroDiscFinset + zeroDisc_isNontrivial; scaledZeta\n (unit-disc scaling) + F(0) = 1 via Zeta23 zeta_lower_bound_two\n (\u2016\u03b6(2+it)\u2016 \u2265 1/3, no \u03bc-series build); the multiplicity-invariance\n chain (analyticOrderNatAt_riemannZeta_affine/const_mul/\n scaledZeta); scaledZeta_jensen_count (ZerosBound, \u2264\n log((9/4)|t|\u00b2)/log(33/32)). Next: 5c back half (R-gap, g, BC).",
"new_string": " plan: loose disc bound as the GROWTH INPUT for the\n partial-fraction identity (5e), tight constants from D-056's\n analysis of the identity (5f). **ii\u2032-5c COMPLETE (sessions\n 023\u2013024)**: LiDisc.lean \u2014 zeroDiscFinset + zeroDisc_isNontrivial;\n scaledZeta + F(0) = 1 (zeta_lower_bound_two); the\n multiplicity-invariance chain; scaledZeta_jensen_count\n (ZerosBound, \u2264 log((9/4)|t|\u00b2)/log(33/32)); R-gap via the\n \u00d710-rescaled midpoint pigeonhole (R_c \u2208 [2.3, 2.4], clearance\n gapD = 1/(50(k+1))); g = Cf r_c F analytic + nonvanishing\n (Zeta23 Cf/ZeroFactorization); |g| \u2264 (9/4)|t|\u00b2\u00b7gapD^{\u2212M_c} on the\n ball; LogOfAnalyticFunction + BorelCaratheodoryDeriv (450\u00b7M);\n logDeriv chain + affine push-forward + near/extras split.\n **Capstone: logDeriv_riemannZeta_sub_nearZeros_le** \u2014 the LOOSE\n R-bound \u2016\u03b6\u2032/\u03b6(s) \u2212 \u03a3_{|\u03b3\u2212t|<1} m/(s\u2212\u03c1)\u2016 \u2264 100000\u00b7(log|t|)\u00b2 on\n \u03c3 \u2208 [1/2, 7/2], |t| \u2265 10, \u03b6 s \u2260 0 (no perimeter hypothesis \u2014\n Jensen count input). Build GREEN (8753 jobs); 32 decls audited:\n 3 standard axioms only. Next: 5d (FE-reflection + left digamma)."
}
thinking (337 chars)
Now register the session in research.db (per protocol §8.4 item 2 — sessions registered via direct sqlite3 insert) and commit the closure. Let me check the db registration pattern from handoff notes: "Session registration via direct sqlite3 insert (journal_file column)." Let me look at how it was done before — check the sessions table.
Registering the session in research.db, then the closure commit.
tool: Bash
input
{
"command": "cd \"D:/Python/Quantum/research\" && ./../.venv/Scripts/python.exe -c \"\nimport sqlite3\ncon = sqlite3.connect('research.db')\ncur = con.cursor()\ncur.execute('SELECT name FROM sqlite_master WHERE type=\\\"table\\\"')\nprint([r[0] for r in cur.fetchall()])\ncur.execute('PRAGMA table_info(sessions)')\nprint(cur.fetchall())\ncur.execute('SELECT * FROM sessions ORDER BY rowid DESC LIMIT 2')\nprint(cur.fetchall())\ncon.close()\n\"",
"description": "Inspect sessions table schema and last rows"
}
**ii′-5c COMPLETE** — the loose Davenport-disc R-bound is proved in Lean.
## What was built (LiDisc.lean, +~1000 lines, 32 new decls)
**Capstone** `logDeriv_riemannZeta_sub_nearZeros_le`: for `s.im = t`, `re s ∈ [1/2, 7/2]`, `|t| ≥ 10`, `ζ s ≠ 0`:
$$\bigl\|\zeta'/\zeta(s) - \textstyle\sum_{|\gamma-t|<1} m_\rho/(s-\rho)\bigr\| \le 100000\cdot(\log|t|)^2$$
- **R-gap**: the ×10-rescale trick — applied ii′-4's unit-window pigeonhole at a = 23 to the ×10-image of the zero-norm finset, ÷10 → R_c ∈ [2.3, 2.4] with clearance `gapD = 1/(50(k+1))`. Zero new pigeonhole code.
- **g = Cf r_c F**: built entirely on Zeta23's `Cf` API (`CfAnalytic`, `ZeroFactorization`); nonvanishing on closedBall(0, r_c) — the gap makes the boundary sphere zero-free, which is what lets the else-branch norm computation run.
- **Bounds**: `|g| ≤ (9/4)|t|²·gapD^{−M_c}` (max-modulus over the sphere), `log|g(0)| ≥ 0` (free since collected ‖ρ‖ < 1).
- **BC**: `LogOfAnalyticFunction` + `BorelCaratheodoryDeriv` with the factor folded to 450·M; logDeriv chain (`logDeriv_div/prod/pow/comp`) through the affine push-forward; extras bounded by the Jensen count (each ‖s−ρ‖ ≥ |t−γ| ≥ 1).
- **Constant fold**: `log(33/32) ≥ 1/33`, `log 4150 ≤ 9` (via e > 2.71), `M_bound ≤ 420L²`, final 75642L² ≤ 100000L².
- Notably: **no perimeter hypothesis** — the count input is the session-023 Jensen bound, not `ZeroCountProp`.
Build GREEN (8753 jobs, LiDisc now root-imported); all 32 declarations audited: **3 standard axioms only, no sorryAx**. Commits c7cbae5 (build) + 0755db5 (closure: journal-024, STATE, NGUYEN, db).
## Next (Session 025): ii′-5d
FE-reflection of the loose bound to σ ∈ [−5/2, 1/2]: the zero-sums cancel exactly by FE symmetry (ρ′ = 1−ρ, `mult_reflect`), the ΓR-bracket is bounded by `digamma_stirling` after a +2 recurrence shift — plus the left-plane uniform digamma bound needed again in 5e. Also queued: `zeroMult(−2n) = 1` for all n (generalizing ii′-4c).
Update me here
thinking (557 chars)
The user says "Update me here" — they want a status update on where things stand. The session just completed ii′-5c. Let me give a concise summary of the current state. Nothing new has happened since my last message — but the user probably wants the recap of where we are now, maybe in a cleaner form. Let me check if there's anything pending... Actually the last message I gave was the completion report. "Update me here" likely means: give me the current status/where we left off (perhaps they're returning). STATE.md is updated. Just summarize concisely.
## Status: Session 024 complete — ii′-5c DONE
**Just finished (committed c7cbae5 + 0755db5):** the loose Davenport-disc R-bound in Lean.
`logDeriv_riemannZeta_sub_nearZeros_le` — for `s.im = t`, `re s ∈ [1/2, 7/2]`, `|t| ≥ 10`, `ζ s ≠ 0`:
$$\|\zeta'/\zeta(s) - \textstyle\sum_{|\gamma-t|<1} m_\rho/(s-\rho)\| \le 100000\,(\log|t|)^2$$
The full chain: R-gap selection (×10-rescaled midpoint pigeonhole, R_c ∈ [2.3, 2.4], clearance `gapD = 1/(50(k+1))`) → Blaschke quotient `g = Cf r_c F` analytic + nonvanishing (Zeta23 `Cf`/`ZeroFactorization`) → `|g| ≤ (9/4)|t|²·gapD^{−M_c}` (max-modulus over the zero-free sphere) → `LogOfAnalyticFunction` + `BorelCaratheodoryDeriv` (450·M factor) → logDeriv chain + affine push-forward + near/extras split. Constant fold landed at 75642L² ≤ 100000L². Constant is deliberately loose per D-067 §6 — it's only the growth input for the identity stage.
**Build:** green, 8753 jobs. **Axioms:** all 32 new declarations — 3 standard axioms only, no sorryAx. **Perimeter:** unchanged (and notably this theorem needed no `ZeroCountProp` — the Jensen count sufficed).
## Where we are in tier ii′
Done: ii′-0, 1a, 1b, 2, 3a, 4, 5a, 5b, **5c**.
Remaining: **ii′-5d** (FE-reflection to σ ∈ [−5/2, 1/2] + left-plane digamma bound) → ii′-5e (partial-fraction identity; needs `zeroMult(−2n) = 1` for all n) → ii′-5f (tight analysis → the baked A = 10.5, B₀ = 48) → ii′-3b (moments) → ii′-3c (crux Sf = Res₁) → ii′-6 (L0 assembly) → ii′-7 (closure + paper Appendix B).
Paper A stays frozen and submission-ready throughout (freeze protocol).
**Next action (Session 025):** ii′-5d. Say the word and I'll start.
Any update?
thinking (975 chars)
The user asks "Any update?" — this is right after I gave a status update. Nothing new has happened since; no new work has been done between messages. The previous message already covered the full status. This is likely the user checking in again, perhaps expecting me to have continued working? But I was waiting for their go-ahead ("Say the word and I'll start").
I should be brief: no new work since the last update; we're at the same clean boundary; ready to start ii′-5d on their word. Or — should I interpret "Any update?" as "continue"? The previous message ended with "Say the word and I'll start." The user's reply "Any update?" is ambiguous but most likely they're just checking state. Given the pattern (they asked "let me know where we left off" then "I am ready, let's do it"), "Any update?" after my status message probably means they want to know if anything new — answer: no, work paused awaiting your go-ahead; offer to start ii′-5d now.
Keep it very short.
No new progress — work is paused at the clean Session 024 boundary awaiting your go-ahead. State is unchanged from my last update:
- **ii′-5c complete** (loose R-bound `≤ 100000·(log|t|)²` proved in Lean, build green, axioms clean, all committed).
- **Next:** ii′-5d (FE-reflection to the left half-strip + digamma bound), designed and ready to build.
Want me to start ii′-5d now?