← Session 24 — ii′-2…4: swaps, (4.10) design, contour + website roadmap fixes
thinking (18091 chars)
Important correction: `Gammaℝ_eq_zero_iff : Gammaℝ s = 0 ↔ ∃ n : ℕ, s = -(2 * n)` — Gammaℝ DOES have zeros?! Wait — `Gammaℝ s = π^(-s/2) * Gamma(s/2)`. Gamma(s/2) is never zero (Γ has no zeros)... unless at poles! At s = −2n, Γ(s/2) = Γ(−n) is a POLE — in Lean, `Complex.Gamma` at nonpositive integers is defined as... junk/0? Mathlib's `Complex.Gamma` is defined via an integral for re > 0 extended by Γ(s) = Γ(s+n)/(s(s+1)...(s+n−1)) — at s = 0, −1, ... the division by zero gives 0 (junk value). So in Mathlib, `Complex.Gamma (−n) = 0` (junk), hence `Gamma_eq_zero_iff : Gamma s = 0 ↔ ∃ n, s = -n`?? Hmm — `Complex.Gamma_eq_zero_iff {s : ℂ} : Gamma s = 0 ↔ ∃ n : ℕ, s = -n`. Yes — the Γ function AS IMPLEMENTED in Mathlib is zero exactly at its poles (junk-value convention). Same for Gammaℝ: zeros at −2n.
This is actually PERFECT for the trivial-zero route — Mathlib's Gammaℝ is zero at −2 (junk), and the "pole order" manifests as the zero order of 1/Gammaℝ... wait no. Hmm. In Mathlib's convention, Gammaℝ(−2) = 0. And completedRiemannZeta(−2) = Gammaℝ(−2)·ζ(−2) — hmm, is the product identity valid at −2? `completedRiemannZeta_eq_Gammaℝ_mul` needs `hG : Gammaℝ s ≠ 0` — NOT valid at −2! Because at poles of ΓR the product form fails (0 · ζ(−2) = 0 but Λ(−2) = Λ(3) ≠ 0).
So the route: ζ(s) = Λ(s)/ΓR(s) for s near −2, s ≠ −2 (ΓR(s) ≠ 0 for s ∉ {−2n}: near −2 only −2 is bad). Then (s+2)⁻¹·ζ(s)... I want the factorization ζ(s) = (s+2)·G(s):
G(s) := Λ(s)/H(s) with H(s) := 4·π^{−s/2}·Γ(s/2+2)/s (the closed form of (s+2)ΓR(s)).
For s ≠ −2 near −2 (also s ≠ 0): ζ(s) = Λ(s)/ΓR(s) [product form needs ΓR(s) ≠ 0 ✓ for s ≠ −2n]. And ΓR(s) = π^{−s/2}Γ(s/2); Γ(s/2) = 4Γ(s/2+2)/(s(s+2)) [Gamma_add_one twice, valid for s/2 ∉ {0,−1} hmm: Γ(z) = Γ(z+1)/z needs... Mathlib `Gamma_add_one (hs : s ≠ 0) : Gamma (s + 1) = s * Gamma s` — wait direction: Gamma (s+1) = s·Gamma s for s ≠ 0. So Gamma(s/2) = Gamma(s/2+1)/(s/2) needs s/2 ≠ 0 ✓ near −2; = Gamma(s/2+2)/((s/2+1)(s/2)) needs s/2+1 ≠ 0 ✓ s ≠ −2]. So for s near −2, s ∉ {−2, 0}: ΓR(s) = π^{−s/2}·4Γ(s/2+2)/(s(s+2)) = H(s)/(s+2). Then ζ(s) = Λ(s)(s+2)/H(s) = (s+2)·G(s) ✓ on punctured neighborhood.
At s = −2: ζ(−2) = 0 [riemannZeta_neg_two_mul_nat_add_one 0: ζ(−2·(0+1)) = ζ(−2) = 0 ✓] and (s+2)G(s) = 0 ✓. So equality on full neighborhood.
G analytic at −2: H analytic at −2 (composition s/2+2 analytic; Γ differentiable at s/2+2 = 1: differentiableAt_Gamma (s/2+2) (hs : ∀ m, s/2+2 ≠ −m) — at s = −2: s/2+2 = 1, 1 ≠ −m ∀m ✓; need differentiableAt in a NEIGHBORHOOD for AnalyticAt — the set {s | ∀ m : ℕ, s/2+2 ≠ −↑m} is open (complement of {−2−2m : m} = {−2, −4, ...} which is closed — discrete set, `isClosed_of_discrete`? Mathlib: a set with no limit points... There's `IsClosed` for discrete sets: in T1, a set with `DiscreteTopology`... not automatic! {−2−2m} IS closed since it's locally finite (no accumulation). There might be a cleaner way: for AnalyticAt at the single point, use `DifferentiableOn.analyticOnNhd` on a small ball around −2 avoiding {−4, −6...}: ball(−2, 1) contains only −2 hmm — s/2+2 for s ∈ ball(−2,1): s/2+2 ∈ ball(1, 1/2) — contains 0? |s/2+2 − 1| < 1/2 ⟹ s/2+2 ∈ (1/2, 3/2)-ish ball, 0 ∉ it, and −m ∉ ball(1, 1/2) for m ≥ 1 ✓ (they're ≤ −1). So on ball(−2, 1): s ↦ s/2+2 ∈ ball(1, 1/2) where Γ is differentiable everywhere ⟹ DifferentiableOn on the open ball ⟹ AnalyticOnNhd ⟹ AnalyticAt at −2 ✓. Then divide by s (analytic, s ≠ 0 on ball(−2,1) ✓), multiply by 4π^{−s/2} (analytic everywhere: (fun s => (π:ℂ)^(−s/2)) = exp(log π · (−s/2))... cpow with constant base: `AnalyticAt ℂ (fun s => (c:ℂ)^(a*s+b))` — via exp form: c^w = exp(w log c) for c ≠ 0: `Complex.cpow_eq_exp_log_mul`? hmm: c ^ w = exp (log c * w) for c ≠ 0 — `Complex.cpow_def_of_ne_zero`. So the function is s ↦ exp ((−s/2)·log π) — analytic ✓).
H(−2) ≠ 0: H(−2) = 4·π^{1}·Γ(1)/(−2) = 4π·1/(−2) = −2π ≠ 0. Needs Gamma_one: Complex.Gamma_one? there's `Complex.Gamma_one : Gamma 1 = 1` ✓ surely. And π^{−(−2)/2} = π^1 = π: cpow: (π:ℂ)^(−(−2)/2) = (π:ℂ)^((1:ℂ)): −(−2)/2 = 1 (field_simp on the exponent expression — the exponent is −s/2 as a ℂ expression; at s = −2: −(−2)/2 = 2/2 = 1). (π:ℂ)^(1:ℂ) = π (`cpow_one`).
Λ(−2) ≠ 0: Λ(−2) = Λ(1−(−2)) = Λ(3) [completedRiemannZeta_one_sub]. Λ(3) = ΓR(3)·ζ(3) [completedRiemannZeta_eq_Gammaℝ_mul (3 ≠ 0 ✓) (Gammaℝ 3 ≠ 0: Gammaℝ_eq_zero_iff: ΓR(3) = 0 ↔ ∃ n, 3 = −(2n) — false since −(2n) ≤ 0 < 3... in ℂ: 3 = −(2·n) impossible as real parts: −2n ≤ 0 ≠ 3 ✓)]. ΓR(3) ≠ 0 ✓ by same lemma; ζ(3) ≠ 0 by riemannZeta_ne_zero_of_one_lt_re (re 3 = 3 > 1 ✓). So Λ(3) ≠ 0 ⟹ Λ(−2) ≠ 0.
Λ analytic at −2: differentiableAt_completedZeta (s ≠ 0) (s ≠ 1) — differentiableAt, need AnalyticAt: DifferentiableAt → AnalyticAt for ℂ? Hmm — NOT directly in Mathlib I think. Pattern from ii′-1b: `zetaA_analyticOnNhd_univ` used... AnalyticOnNhd from DifferentiableOn univ: there's `DifferentiableOn.analyticOnNhd`? Let me check what LiSides used: line 113 `zetaA_analyticOnNhd_univ : AnalyticOnNhd ℂ zetaA Set.univ`. Let me look at how it was proved — probably `DifferentiableOn.analyticOnNhd`? In recent Mathlib: `DifferentiableOn.analyticOnNhd (h : DifferentiableOn ℂ f s) (hs : IsOpen s) : AnalyticOnNhd ℂ f s`? Hmm, actually I recall `DifferentiableOn.analyticOn` — no... For ℂ there IS: `DifferentiableOn.analyticOnNhd_of...`? The Cauchy-integral-based Goursat theorem: Mathlib has `DifferentiableOn.analyticOnNhd`?? Let me grep quickly. Actually I recall `Mathlib.Analysis.Complex.CauchyIntegral` gives `DifferentiableOn.contDiffOn`?? There's definitely something since ii′-1b used it.
Also `AnalyticAt.congr`/`AnalyticOnNhd.analyticAt`: from AnalyticOnNhd on univ/ball get analyticAt at the point: `AnalyticOnNhd.analyticAt (h : AnalyticOnNhd ℂ f s) (hs : s ∈ 𝓝 z)`. ✓.
Then G = Λ/H analytic (div, H(−2) ≠ 0), G(−2) = Λ(−2)/H(−2) ≠ 0.
Finally: analyticOrderAt riemannZeta (−2) = 1 via `AnalyticAt.analyticOrderAt_eq_natCast.mpr ⟨G, hGan, hG0, hEvEq⟩` with n = 1: (s−(−2))^1 • G s = (s+2)·G s ✓. Wait — need AnalyticAt ℂ riemannZeta (−2) for the .mp direction... the lemma signature: `AnalyticAt.analyticOrderAt_eq_natCast (hf : AnalyticAt 𝕜 f z₀) : analyticOrderAt f z₀ = ↑n ↔ ∃ g, ...`. Need AnalyticAt ζ at −2: ζ analytic off 1: Mathlib has... ii′-1b probably built it (hLi analytic etc.). There might be `analyticAt_riemannZeta`? Not in Mathlib I think; LiSides has `zeta_order_ne_top_of_ne` which needed analyticity — check how that got AnalyticAt. Actually for analyticOrderAt to be ≠ ⊤ they must have shown something. Let me check LiSides 121-142.
Hmm wait — actually I realize the eventual equality ζ = (s+2)G near −2 DIRECTLY gives AnalyticAt ζ at −2 (since RHS is analytic): `AnalyticAt.congr'` — if f =ᶠ[𝓝 z] g and g analytic at z then f analytic at z (`AnalyticAt.congr'`? direction: `AnalyticAt.congr' (hg : AnalyticAt ℂ g z) (h : f =ᶠ[𝓝 z] g) : AnalyticAt ℂ f z`? something like that exists). So order: first prove the eventuallyEq, get analyticity of ζ at −2 for free, then apply the order characterization.
Hmm wait, circularity check: the eventuallyEq ζ = (s+2)·G uses the product form Λ = ΓR·ζ away from −2 — no analyticity of ζ needed. ✓ non-circular.
Then zeroMult (−2) = (analyticOrderAt riemannZeta (−2)).toNat = (1 : ℕ∞).toNat = 1. Note: analyticOrderAt returns ℕ∞ (WithTop ℕ)? `.toNat` on ENat... `ENat`? In Mathlib now ℕ∞ = WithTop ℕ? `(analyticOrderAt riemannZeta ρ).toNat` — WithTop ℕ .toNat? There's `WithTop.toNat`? or ENat.toNat. From the def `zeroMult ρ := (analyticOrderAt riemannZeta ρ).toNat`. If analyticOrderAt = (1 : ℕ∞): toNat = 1 via `ENat.toNat_one`? or WithTop.toNat... I'll find the right simp lemma.
OK the plan is solid. Now the pigeonhole part. Let me also check `zerosIn`: `zerosIn T₁ T₂ : Set ℂ := {ρ | IsNontrivialZero ρ ∧ T₁ < ρ.im ∧ ρ.im ≤ T₂}` with `zerosIn_finite` — strict < on the left, ≤ on the right. My window [t, t+1] is closed-closed; zerosIn (t−ε) (t+1)... For the count Prop I can just use zerosIn-compatible windows or state my own set and prove Finite from zerosIn_finite by subset: {IsNontrivialZero ∧ t ≤ im ∧ im ≤ t+1} ⊆ zerosIn (t−1) (t+1). Finite subset ✓ (`Set.Finite.subset`).
Now, the pigeonhole combinatorial core. Let me design the cleanest Lean version:
```lean
/-- The k+1 candidate points pigeonhole: given a finset S of reals in [a, a+1]
with card S ≤ k, one of the k+1 equally spaced midpoints T_j = a + (2j+1)/(2(k+1))
has distance ≥ 1/(2(k+1)) from every point of S. -/
theorem exists_avoiding_midpoint {k : ℕ} (a : ℝ) (S : Finset ℝ)
(hS : ∀ x ∈ S, x ∈ Set.Icc a (a + 1)) (hcard : S.card ≤ k) :
∃ T : ℝ, T ∈ Set.Icc a (a + 1) ∧ ∀ x ∈ S, |x - T| ≥ 1 / (2 * (k + 1))
```
Proof sketch in Lean:
- classical
- w := 1/(k+1) : ℝ, w > 0. candidates c j = a + (2j+1)·w/2 for j ∈ Finset.range (k+1) — use Fin? Finset.range (k+1) with j : ℕ is easier for arithmetic.
- Bad := (Finset.range (k+1)).filter (fun j => ∃ x ∈ S, |x - c j| < w/2)
- Want card Bad ≤ card S: define φ : ∀ j ∈ Bad, ℝ via choice: φ j = the x ∈ S with |x − c j| < w/2. Show injOn φ Bad: if φ j₁ = φ j₂ = x: |c j₁ − c j₂| ≤ |c j₁ − x| + |x − c j₂| < w/2 + w/2 = w. And c j₁ − c j₂ = (j₁ − j₂)·w (2j₁+1 − (2j₂+1) = 2(j₁−j₂), over 2·w... c j₁ − c j₂ = (2(j₁−j₂))·w/2 = (j₁−j₂)·w). |c j₁ − c j₂| = |j₁ − j₂|·w (as reals, |((j₁:ℤ) − j₂)|·w). If j₁ ≠ j₂ then |j₁ − j₂| ≥ 1 ⟹ |c j₁ − c j₂| ≥ w — contradiction ⟹ j₁ = j₂.
- card Bad ≤ card S via Finset.card_le_card_of_injOn φ (maps into S, injOn).
- card Bad ≤ card S ≤ k < k+1 = card (range (k+1)) ⟹ ∃ j ∈ range(k+1), j ∉ Bad: `Finset.exists_mem_not_mem`? If Bad ⊂ range and card Bad < card range then range \ Bad nonempty: use Finset.card_lt_card → exists. `Finset.exists_mem_not_mem_of_card_lt_card`? There's `Finset.exists_mem_not_mem_of_card_lt_card (h : s.card < t.card) : ∃ x ∈ t, x ∉ s`? I think `Finset.exists_mem_not_mem_of_card_lt_card` exists or prove via card_sdiff > 0. Fine.
- For that j: ∀ x ∈ S, |x − c j| ≥ w/2 (not < ⟹ ≥, with the ∃-negation push).
- c j ∈ [a, a+1]: c j = a + (2j+1)w/2; (2j+1)w/2 ≥ 0 ✓; ≤ (2k+1)w/2 < (2k+2)w/2 = (k+1)w = 1 ✓.
Then the zeta wrapper:
```lean
/-- L3: zero-avoiding ordinate. Given the unit-window count bound (perimeter:
Trudgian 2014 N(T)/S(T), D-056 §2's Ĉ₀), every unit window [a, a+1] with
a ≥ 2 contains a T whose distance from every zero ordinate in the window is
≥ 1/(3·Ĉ₀(a+1)). -/
theorem exists_zero_avoiding_T (hZC : ZeroCountProp) {a : ℝ} (ha : 2 ≤ a) :
∃ T : ℝ, a ≤ T ∧ T ≤ a + 1 ∧
∀ ρ : ℂ, IsNontrivialZero ρ → a ≤ ρ.im → ρ.im ≤ a + 1 →
1 / (3 * C0hat (a + 1)) ≤ |ρ.im - T|
```
Proof:
- W := {ρ : ℂ // IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1} — Finite (via zerosIn_finite subset). Nat.card W =: k... wait the count Prop gives (Nat.card W : ℝ) ≤ C0hat (a+1).
- S := (Finset of W).image (fun ρ => ρ.im) — or directly: S := W.toFinset.image im... card S ≤ Nat.card W (image reduces card: `Finset.card_image_le`).
- Apply exists_avoiding_midpoint with k = Nat.card W: get T with clearance 1/(2(k+1)).
- Show 1/(3·C0hat(a+1)) ≤ 1/(2(k+1)): ⟺ 2(k+1) ≤ 3·C0hat(a+1). Have k+1 ≤ C0hat(a+1)+1; C0hat(a+1) ≥ 2.9 (need a lemma: 2 ≤ C0hat t for t ≥ ... — C0hat t = 0.433 log(t+2) + 0.886 log log(t+2) + 2.9; for t ≥ 3: log(t+2) ≥ log 5 > 0, log log(t+2) ≥ log log 5: log 5 ≈ 1.6 > 1 ⟹ log log 5 > 0. So C0hat t ≥ 2.9 for t ≥ 3 — wait need t+2 ≥ e so log log(t+2) ≥ 0: t+2 ≥ e ⟸ t ≥ 1. a ≥ 2 ⟹ a+1 ≥ 3 > 1 ✓. So C0hat(a+1) ≥ 2.9). Then 2(k+1) ≤ 2(C+1) = 2C+2 ≤ 3C ⟺ C ≥ 2 ✓.
The `ZeroCountProp` definition — should it use Nat.card of the subtype? Need Finite instance first. In Lean:
```lean
/-- The zeros in a unit ordinate window, as a subtype. Finite by Zeta23. -/
def zeroWindow (a : ℝ) : Set ℂ := {ρ | IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1}
theorem zeroWindow_finite (a : ℝ) : (zeroWindow a).Finite := ...
-- subset of zerosIn (a−1) (a+1): zerosIn T₁ T₂ = {ρ | IsNontrivialZero ρ ∧ T₁ < ρ.im ∧ ρ.im ≤ T₂}
-- zeroWindow a ⊆ zerosIn (a−1) (a+1) ✓
/-- Perimeter hypothesis (Trudgian 2014 N(T)/S(T), declared): the number of
nontrivial zeros with ordinates in the unit window [t, t+1] is at most
Ĉ₀(t+1) = 0.433 log(t+3) + 0.886 log log(t+3) + 2.9. -/
def ZeroCountProp : Prop :=
∀ t : ℝ, 2 ≤ t →
(Nat.card (zeroWindow t) : ℝ) ≤ C0hat (t + 1)
```
Hmm wait — Nat.card of a Set subtype: `Nat.card (zeroWindow t)` — needs the type `(zeroWindow t)` = {x // x ∈ zeroWindow t}, Finite instance from Set.Finite. `Set.Finite.to_subtype`? The instance: `Set.Finite.fintype`? For Nat.card just need `Finite` — instance from Set.Finite: there's `Set.Finite.to_subtype`... the standard: `instance (s : Set α) [h : Finite s] ...` — actually `Set.finite_coe_iff`? There's a `Finite` instance on the subtype from Set.Finite via `Set.Finite.to_subtype`? Hmm: `theorem Set.Finite.to_subtype`... The instance exists: `Set.finite_coe_iff : Finite s ↔ s.Finite`. So `(Set.finite_coe_iff.mpr (zeroWindow_finite a))` gives Finite (zeroWindow a) instance... it's a theorem not instance — use `haveI := ...` or `letI`. Fine.
Also — hmm, wait. Does the ZeroCountProp need a floor? (Nat.card : ℝ) ≤ C0hat — fine as real inequality, no floor needed.
Also should double check C0hat's monotonicity need: none — evaluated at t+1 directly.
For the kFun bounds — let me also confirm the horizontal bound form. D-036 (II),(IV): "|1+1/s| ≤ 1 + (σ+1)/(σ²+T²) ⟹ |k_n| ≤ (1+4/(16+n))ⁿ + 1 ≤ e⁴ + 1 (−3 ≤ σ ≤ 3)". Their (16+n) comes from σ²+T² with T ≥ √(n+16)? T ∈ [√n, √n+1]: T² ≥ n... they wrote 16+n perhaps from T² ≥ n and σ² ≥ ... with |σ| ≤ 3 hmm σ² ≥ 0. (σ+1)/(σ²+T²): for σ ∈ [−3,3]: numerator ≤ 4; denominator ≥ T² ≥ n. So ≤ 4/n; they used 4/(16+n) — maybe T² ≥ n+16?? no... whatever — I'll prove the clean form: ≤ e⁴+1 using σ ≤ 3, T² ≥ n:
‖1+1/s‖ ≤ 1 + (σ+1)/(σ²+T²) requires the steps above; ≤ 1 + 4/n (needs σ+1 ≤ 4 i.e. σ ≤ 3 and σ²+T² ≥ n; also need (σ+1)/(σ²+T²) could be negative — fine, ≤ 4/n still holds since negative ≤ 4/n). Then (1+4/n)ⁿ ≤ e⁴ for n ≥ 1.
Actually — simpler unified: since σ ≤ 3 and σ²+T² ≥ n: (σ+1)/(σ²+T²) ≤ 4/n. Even simpler: skip the 16.
Wait — one subtlety: (1 + 4/n)ⁿ ≤ e⁴. Proof: 1+4/n ≤ e^{4/n} (Real.add_one_le_exp: 1+x ≤ e^x ∀x ✓). Then pow: (1+4/n)ⁿ ≤ (e^{4/n})ⁿ = e^{(4/n)·n} = e⁴ (n ≥ 1). pow_le_pow_left needs 0 ≤ 1+4/n ✓. exp: (Real.exp (4/n))^n = Real.exp (4/n * n) — `Real.exp_nat_mul`? Real.exp (n * x) = (exp x)^n: `Real.exp_nat_mul : Real.exp (n * x) = (Real.exp x)^n`? direction... there's `Real.exp_nat_mul (x : ℝ) (n : ℕ) : Real.exp (n * x) = (Real.exp x) ^ n`? something like that exists. Fine.
The normSq expansion of ‖1+1/s‖²: doable. Mathlib has `Complex.normSq_add`? There's `Complex.normSq_add (z w : ℂ) : normSq (z + w) = normSq z + normSq w + 2 * (z * conj w).re`? something like that. Or compute via div_re/div_im directly. (1/s).re = s.re/normSq s — `Complex.div_re`? (1/s) = conj s / normSq s: `Complex.one_div_re : (1/z).re = z.re / normSq z`? Hmm: z.re/normSq z for 1/z ✓ (`Complex.div_re` with 1: (1/z).re = (1·z.re + 0·(−z.im))/normSq z... the general `Complex.div_re : (z / w).re = (z.re * w.re + z.im * w.im) / normSq w` ✓; z=1: (w.re + 0)/normSq = w.re/normSq w ✓; im: (z/w).im = (z.im·w.re − z.re·w.im)/normSq w = −w.im/normSq w ✓).
So (1 + 1/s).re = 1 + σ/D, (1+1/s).im = −T/D where D = normSq s = σ²+T².
normSq(1+1/s) = (1+σ/D)² + (T/D)² = 1 + 2σ/D + σ²/D² + T²/D² = 1 + (2σ+1)/D (using σ²+T² = D ✓).
‖1+1/s‖ = Real.sqrt (normSq ...) ≤ 1 + (σ+1)/D ⟸ square both sides: need 1+(2σ+1)/D ≤ (1+(σ+1)/D)² = 1 + 2(σ+1)/D + (σ+1)²/D² ⟺ 0 ≤ 1/D + (σ+1)²/D² = (D + (σ+1)²)/D² ✓ positive. And RHS ≥ 0 ✓ (sum of nonneg... 1 + (σ+1)/D: D ≥ 1? hmm not needed: D + (σ+1)² ≥ 0 ⟹ 1 + (σ+1)/D = (D+σ+1)/D and D+σ+1 = σ²+T²+σ+1 ≥ 3/4 > 0 ✓).
Then ‖z‖ ≤ x given ‖z‖² ≤ x² and x ≥ 0: `abs_le_of_sq_le_sq'`? or `Real.sqrt_le_sqrt` + sqrt(x²) = x: ‖z‖ = sqrt(normSq z) ≤ sqrt(x²) = |x| = x. Mathlib: `Complex.norm_eq_sqrt_normSq`? Hmm — is there `Complex.norm_def : ‖z‖ = Real.sqrt (normSq z)`? There's `Complex.norm_apply : ‖z‖ = Complex.abs z` and `Complex.abs_def : abs z = Real.sqrt (normSq z)`? `Complex.abs` is def'd as sqrt normSq? `Complex.abs_apply : abs z = Real.sqrt (normSq z)`? close enough — I'll find exact names during implementation (or use normSq_le → norm_le: `Complex.norm_le_iff_normSq_le`? hmm might not exist; there's `Complex.normSq_eq_norm_sq : normSq z = ‖z‖^2` — then ‖z‖ ≤ x ⟺ ‖z‖² ≤ x² (x≥0) via sq_le_sq... `sq_le_sq' `or `abs_le_of_sq_le_sq`).
OK. Enough design — the rest is implementation detail to be worked out in the Lean editor loop. Also `kFun_neg_two`: kFun n (−2) = ((−2)/(−2−1))^n − 1 = ((−2)/(−3))^n − 1 = (2/3)^n − 1. And ‖(2/3)^n − 1‖ ≤ 1: (2/3)ⁿ ∈ (0,1] ⟹ (2/3)ⁿ − 1 ∈ (−1, 0] ⟹ abs ≤ 1 ✓. In ℂ: (2/3 : ℂ)^n − 1 is real... norm = |...|. Straightforward with norm_num/positivity + pow bounds.
Plan of files: one new file `NguyenRH1/LiContour.lean` containing:
- §1 ZeroWindow + ZeroCountProp (perimeter Prop) + C0hat lower bound lemma (2 ≤ C0hat t for 1 ≤ t or so)
- §2 exists_avoiding_midpoint (pure pigeonhole)
- §3 exists_zero_avoiding_T (L3)
- §4 kFun bounds (L1): kFun_norm_le_two, horizontal e⁴+1, right-vertical e^{√n/2}+1, kFun_neg_two value + ≤ 1
- §5 zeroMult_neg_two = 1 (trivial-zero simplicity)
Sub-stage commits: 4a = §1–§3 (L3); 4b = §4 (L1 bounds); 4c = §5. Each build-green.
Where do I put things like `hLi`? Not needed here. Imports: LiSides (for kFun, zetaA), LiSkeleton (for C0hat), Zeta23 Statement (IsNontrivialZero, zeroMult), Mathlib.
Check the root file to see import structure. Let me read NguyenRH1.lean root + the header of LiSides for conventions.
Actually, before diving in: session protocol says skim latest journal (session-020) for Lean gotchas — STATE.md already summarized: "bare π auto-binds (use Real.pi); bare ↑(...) with no expected ℂ drops the coe; AnalyticAt.comp/ContinuousAt.comp mis-unify beta-reduced points — use the _of_eq variants; TendstoLocallyUniformlyOn.differentiableOn takes the IsOpen as third arg; iteratedDerivWithin_tsum needs SummableLocallyUniformlyOn of each derivative family". Good.
Time to start building. First check root file + one header for conventions.
All pieces confirmed. Design for ii′-4 (new file `LiContour.lean`, three sub-stages):
- **ii′-4a — L3**: `ZeroCountProp` perimeter Prop (unit-window count ≤ `C0hat (t+1)`, via Zeta23 `zerosIn_finite`) + pure pigeonhole `exists_avoiding_midpoint` (k+1 midpoints, injective-badness argument) + `exists_zero_avoiding_T` with clearance 1/(3·C0hat(a+1)).
- **ii′-4b — L1**: `‖kFun n s‖ ≤ 2` for re s ≤ 1/2; `‖kFun n (s+1)‖ ≤ e⁴+1` on horizontals (|re s| ≤ 3, n ≤ im²); `‖kFun n (s+1)‖ ≤ e^{√n/2}+1` on the right vertical; `kFun n (−2) = (2/3)ⁿ − 1`, ‖·‖ ≤ 1.
- **ii′-4c — `zeroMult (−2) = 1`**: factor ζ(s) = (s+2)·G(s) near −2 with G(s) = Λ(s)/H(s), H(s) = 4π^{−s/2}Γ(s/2+2)/s; H(−2) = −2π ≠ 0; Λ(−2) = Λ(3) = ΓR(3)ζ(3) ≠ 0 (FE + `Gammaℝ_eq_zero_iff` + `riemannZeta_ne_zero_of_one_lt_re`); then `AnalyticAt.analyticOrderAt_eq_natCast`.
Checking root file conventions, then starting.
tool: Read
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1.lean"
}
tool: Read
input
{
"file_path": "D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiSides.lean",
"limit": 55
}
raw content_json (database row)
[{"type":"thinking","thinking":"Important correction: `Gammaℝ_eq_zero_iff : Gammaℝ s = 0 ↔ ∃ n : ℕ, s = -(2 * n)` — Gammaℝ DOES have zeros?! Wait — `Gammaℝ s = π^(-s/2) * Gamma(s/2)`. Gamma(s/2) is never zero (Γ has no zeros)... unless at poles! At s = −2n, Γ(s/2) = Γ(−n) is a POLE — in Lean, `Complex.Gamma` at nonpositive integers is defined as... junk/0? Mathlib's `Complex.Gamma` is defined via an integral for re > 0 extended by Γ(s) = Γ(s+n)/(s(s+1)...(s+n−1)) — at s = 0, −1, ... the division by zero gives 0 (junk value). So in Mathlib, `Complex.Gamma (−n) = 0` (junk), hence `Gamma_eq_zero_iff : Gamma s = 0 ↔ ∃ n, s = -n`?? Hmm — `Complex.Gamma_eq_zero_iff {s : ℂ} : Gamma s = 0 ↔ ∃ n : ℕ, s = -n`. Yes — the Γ function AS IMPLEMENTED in Mathlib is zero exactly at its poles (junk-value convention). Same for Gammaℝ: zeros at −2n.\n\nThis is actually PERFECT for the trivial-zero route — Mathlib's Gammaℝ is zero at −2 (junk), and the \"pole order\" manifests as the zero order of 1/Gammaℝ... wait no. Hmm. In Mathlib's convention, Gammaℝ(−2) = 0. And completedRiemannZeta(−2) = Gammaℝ(−2)·ζ(−2) — hmm, is the product identity valid at −2? `completedRiemannZeta_eq_Gammaℝ_mul` needs `hG : Gammaℝ s ≠ 0` — NOT valid at −2! Because at poles of ΓR the product form fails (0 · ζ(−2) = 0 but Λ(−2) = Λ(3) ≠ 0).\n\nSo the route: ζ(s) = Λ(s)/ΓR(s) for s near −2, s ≠ −2 (ΓR(s) ≠ 0 for s ∉ {−2n}: near −2 only −2 is bad). Then (s+2)⁻¹·ζ(s)... I want the factorization ζ(s) = (s+2)·G(s):\n\nG(s) := Λ(s)/H(s) with H(s) := 4·π^{−s/2}·Γ(s/2+2)/s (the closed form of (s+2)ΓR(s)).\n\nFor s ≠ −2 near −2 (also s ≠ 0): ζ(s) = Λ(s)/ΓR(s) [product form needs ΓR(s) ≠ 0 ✓ for s ≠ −2n]. And ΓR(s) = π^{−s/2}Γ(s/2); Γ(s/2) = 4Γ(s/2+2)/(s(s+2)) [Gamma_add_one twice, valid for s/2 ∉ {0,−1} hmm: Γ(z) = Γ(z+1)/z needs... Mathlib `Gamma_add_one (hs : s ≠ 0) : Gamma (s + 1) = s * Gamma s` — wait direction: Gamma (s+1) = s·Gamma s for s ≠ 0. So Gamma(s/2) = Gamma(s/2+1)/(s/2) needs s/2 ≠ 0 ✓ near −2; = Gamma(s/2+2)/((s/2+1)(s/2)) needs s/2+1 ≠ 0 ✓ s ≠ −2]. So for s near −2, s ∉ {−2, 0}: ΓR(s) = π^{−s/2}·4Γ(s/2+2)/(s(s+2)) = H(s)/(s+2). Then ζ(s) = Λ(s)(s+2)/H(s) = (s+2)·G(s) ✓ on punctured neighborhood.\n\nAt s = −2: ζ(−2) = 0 [riemannZeta_neg_two_mul_nat_add_one 0: ζ(−2·(0+1)) = ζ(−2) = 0 ✓] and (s+2)G(s) = 0 ✓. So equality on full neighborhood.\n\nG analytic at −2: H analytic at −2 (composition s/2+2 analytic; Γ differentiable at s/2+2 = 1: differentiableAt_Gamma (s/2+2) (hs : ∀ m, s/2+2 ≠ −m) — at s = −2: s/2+2 = 1, 1 ≠ −m ∀m ✓; need differentiableAt in a NEIGHBORHOOD for AnalyticAt — the set {s | ∀ m : ℕ, s/2+2 ≠ −↑m} is open (complement of {−2−2m : m} = {−2, −4, ...} which is closed — discrete set, `isClosed_of_discrete`? Mathlib: a set with no limit points... There's `IsClosed` for discrete sets: in T1, a set with `DiscreteTopology`... not automatic! {−2−2m} IS closed since it's locally finite (no accumulation). There might be a cleaner way: for AnalyticAt at the single point, use `DifferentiableOn.analyticOnNhd` on a small ball around −2 avoiding {−4, −6...}: ball(−2, 1) contains only −2 hmm — s/2+2 for s ∈ ball(−2,1): s/2+2 ∈ ball(1, 1/2) — contains 0? |s/2+2 − 1| < 1/2 ⟹ s/2+2 ∈ (1/2, 3/2)-ish ball, 0 ∉ it, and −m ∉ ball(1, 1/2) for m ≥ 1 ✓ (they're ≤ −1). So on ball(−2, 1): s ↦ s/2+2 ∈ ball(1, 1/2) where Γ is differentiable everywhere ⟹ DifferentiableOn on the open ball ⟹ AnalyticOnNhd ⟹ AnalyticAt at −2 ✓. Then divide by s (analytic, s ≠ 0 on ball(−2,1) ✓), multiply by 4π^{−s/2} (analytic everywhere: (fun s => (π:ℂ)^(−s/2)) = exp(log π · (−s/2))... cpow with constant base: `AnalyticAt ℂ (fun s => (c:ℂ)^(a*s+b))` — via exp form: c^w = exp(w log c) for c ≠ 0: `Complex.cpow_eq_exp_log_mul`? hmm: c ^ w = exp (log c * w) for c ≠ 0 — `Complex.cpow_def_of_ne_zero`. So the function is s ↦ exp ((−s/2)·log π) — analytic ✓).\n\nH(−2) ≠ 0: H(−2) = 4·π^{1}·Γ(1)/(−2) = 4π·1/(−2) = −2π ≠ 0. Needs Gamma_one: Complex.Gamma_one? there's `Complex.Gamma_one : Gamma 1 = 1` ✓ surely. And π^{−(−2)/2} = π^1 = π: cpow: (π:ℂ)^(−(−2)/2) = (π:ℂ)^((1:ℂ)): −(−2)/2 = 1 (field_simp on the exponent expression — the exponent is −s/2 as a ℂ expression; at s = −2: −(−2)/2 = 2/2 = 1). (π:ℂ)^(1:ℂ) = π (`cpow_one`).\n\nΛ(−2) ≠ 0: Λ(−2) = Λ(1−(−2)) = Λ(3) [completedRiemannZeta_one_sub]. Λ(3) = ΓR(3)·ζ(3) [completedRiemannZeta_eq_Gammaℝ_mul (3 ≠ 0 ✓) (Gammaℝ 3 ≠ 0: Gammaℝ_eq_zero_iff: ΓR(3) = 0 ↔ ∃ n, 3 = −(2n) — false since −(2n) ≤ 0 < 3... in ℂ: 3 = −(2·n) impossible as real parts: −2n ≤ 0 ≠ 3 ✓)]. ΓR(3) ≠ 0 ✓ by same lemma; ζ(3) ≠ 0 by riemannZeta_ne_zero_of_one_lt_re (re 3 = 3 > 1 ✓). So Λ(3) ≠ 0 ⟹ Λ(−2) ≠ 0.\n\nΛ analytic at −2: differentiableAt_completedZeta (s ≠ 0) (s ≠ 1) — differentiableAt, need AnalyticAt: DifferentiableAt → AnalyticAt for ℂ? Hmm — NOT directly in Mathlib I think. Pattern from ii′-1b: `zetaA_analyticOnNhd_univ` used... AnalyticOnNhd from DifferentiableOn univ: there's `DifferentiableOn.analyticOnNhd`? Let me check what LiSides used: line 113 `zetaA_analyticOnNhd_univ : AnalyticOnNhd ℂ zetaA Set.univ`. Let me look at how it was proved — probably `DifferentiableOn.analyticOnNhd`? In recent Mathlib: `DifferentiableOn.analyticOnNhd (h : DifferentiableOn ℂ f s) (hs : IsOpen s) : AnalyticOnNhd ℂ f s`? Hmm, actually I recall `DifferentiableOn.analyticOn` — no... For ℂ there IS: `DifferentiableOn.analyticOnNhd_of...`? The Cauchy-integral-based Goursat theorem: Mathlib has `DifferentiableOn.analyticOnNhd`?? Let me grep quickly. Actually I recall `Mathlib.Analysis.Complex.CauchyIntegral` gives `DifferentiableOn.contDiffOn`?? There's definitely something since ii′-1b used it.\n\nAlso `AnalyticAt.congr`/`AnalyticOnNhd.analyticAt`: from AnalyticOnNhd on univ/ball get analyticAt at the point: `AnalyticOnNhd.analyticAt (h : AnalyticOnNhd ℂ f s) (hs : s ∈ 𝓝 z)`. ✓.\n\nThen G = Λ/H analytic (div, H(−2) ≠ 0), G(−2) = Λ(−2)/H(−2) ≠ 0.\n\nFinally: analyticOrderAt riemannZeta (−2) = 1 via `AnalyticAt.analyticOrderAt_eq_natCast.mpr ⟨G, hGan, hG0, hEvEq⟩` with n = 1: (s−(−2))^1 • G s = (s+2)·G s ✓. Wait — need AnalyticAt ℂ riemannZeta (−2) for the .mp direction... the lemma signature: `AnalyticAt.analyticOrderAt_eq_natCast (hf : AnalyticAt 𝕜 f z₀) : analyticOrderAt f z₀ = ↑n ↔ ∃ g, ...`. Need AnalyticAt ζ at −2: ζ analytic off 1: Mathlib has... ii′-1b probably built it (hLi analytic etc.). There might be `analyticAt_riemannZeta`? Not in Mathlib I think; LiSides has `zeta_order_ne_top_of_ne` which needed analyticity — check how that got AnalyticAt. Actually for analyticOrderAt to be ≠ ⊤ they must have shown something. Let me check LiSides 121-142.\n\nHmm wait — actually I realize the eventual equality ζ = (s+2)G near −2 DIRECTLY gives AnalyticAt ζ at −2 (since RHS is analytic): `AnalyticAt.congr'` — if f =ᶠ[𝓝 z] g and g analytic at z then f analytic at z (`AnalyticAt.congr'`? direction: `AnalyticAt.congr' (hg : AnalyticAt ℂ g z) (h : f =ᶠ[𝓝 z] g) : AnalyticAt ℂ f z`? something like that exists). So order: first prove the eventuallyEq, get analyticity of ζ at −2 for free, then apply the order characterization.\n\nHmm wait, circularity check: the eventuallyEq ζ = (s+2)·G uses the product form Λ = ΓR·ζ away from −2 — no analyticity of ζ needed. ✓ non-circular.\n\nThen zeroMult (−2) = (analyticOrderAt riemannZeta (−2)).toNat = (1 : ℕ∞).toNat = 1. Note: analyticOrderAt returns ℕ∞ (WithTop ℕ)? `.toNat` on ENat... `ENat`? In Mathlib now ℕ∞ = WithTop ℕ? `(analyticOrderAt riemannZeta ρ).toNat` — WithTop ℕ .toNat? There's `WithTop.toNat`? or ENat.toNat. From the def `zeroMult ρ := (analyticOrderAt riemannZeta ρ).toNat`. If analyticOrderAt = (1 : ℕ∞): toNat = 1 via `ENat.toNat_one`? or WithTop.toNat... I'll find the right simp lemma.\n\nOK the plan is solid. Now the pigeonhole part. Let me also check `zerosIn`: `zerosIn T₁ T₂ : Set ℂ := {ρ | IsNontrivialZero ρ ∧ T₁ < ρ.im ∧ ρ.im ≤ T₂}` with `zerosIn_finite` — strict < on the left, ≤ on the right. My window [t, t+1] is closed-closed; zerosIn (t−ε) (t+1)... For the count Prop I can just use zerosIn-compatible windows or state my own set and prove Finite from zerosIn_finite by subset: {IsNontrivialZero ∧ t ≤ im ∧ im ≤ t+1} ⊆ zerosIn (t−1) (t+1). Finite subset ✓ (`Set.Finite.subset`).\n\nNow, the pigeonhole combinatorial core. Let me design the cleanest Lean version:\n\n```lean\n/-- The k+1 candidate points pigeonhole: given a finset S of reals in [a, a+1]\nwith card S ≤ k, one of the k+1 equally spaced midpoints T_j = a + (2j+1)/(2(k+1))\nhas distance ≥ 1/(2(k+1)) from every point of S. -/\ntheorem exists_avoiding_midpoint {k : ℕ} (a : ℝ) (S : Finset ℝ)\n (hS : ∀ x ∈ S, x ∈ Set.Icc a (a + 1)) (hcard : S.card ≤ k) :\n ∃ T : ℝ, T ∈ Set.Icc a (a + 1) ∧ ∀ x ∈ S, |x - T| ≥ 1 / (2 * (k + 1))\n```\n\nProof sketch in Lean:\n- classical\n- w := 1/(k+1) : ℝ, w > 0. candidates c j = a + (2j+1)·w/2 for j ∈ Finset.range (k+1) — use Fin? Finset.range (k+1) with j : ℕ is easier for arithmetic.\n- Bad := (Finset.range (k+1)).filter (fun j => ∃ x ∈ S, |x - c j| < w/2)\n- Want card Bad ≤ card S: define φ : ∀ j ∈ Bad, ℝ via choice: φ j = the x ∈ S with |x − c j| < w/2. Show injOn φ Bad: if φ j₁ = φ j₂ = x: |c j₁ − c j₂| ≤ |c j₁ − x| + |x − c j₂| < w/2 + w/2 = w. And c j₁ − c j₂ = (j₁ − j₂)·w (2j₁+1 − (2j₂+1) = 2(j₁−j₂), over 2·w... c j₁ − c j₂ = (2(j₁−j₂))·w/2 = (j₁−j₂)·w). |c j₁ − c j₂| = |j₁ − j₂|·w (as reals, |((j₁:ℤ) − j₂)|·w). If j₁ ≠ j₂ then |j₁ − j₂| ≥ 1 ⟹ |c j₁ − c j₂| ≥ w — contradiction ⟹ j₁ = j₂.\n- card Bad ≤ card S via Finset.card_le_card_of_injOn φ (maps into S, injOn).\n- card Bad ≤ card S ≤ k < k+1 = card (range (k+1)) ⟹ ∃ j ∈ range(k+1), j ∉ Bad: `Finset.exists_mem_not_mem`? If Bad ⊂ range and card Bad < card range then range \\ Bad nonempty: use Finset.card_lt_card → exists. `Finset.exists_mem_not_mem_of_card_lt_card`? There's `Finset.exists_mem_not_mem_of_card_lt_card (h : s.card < t.card) : ∃ x ∈ t, x ∉ s`? I think `Finset.exists_mem_not_mem_of_card_lt_card` exists or prove via card_sdiff > 0. Fine.\n- For that j: ∀ x ∈ S, |x − c j| ≥ w/2 (not < ⟹ ≥, with the ∃-negation push).\n- c j ∈ [a, a+1]: c j = a + (2j+1)w/2; (2j+1)w/2 ≥ 0 ✓; ≤ (2k+1)w/2 < (2k+2)w/2 = (k+1)w = 1 ✓.\n\nThen the zeta wrapper:\n\n```lean\n/-- L3: zero-avoiding ordinate. Given the unit-window count bound (perimeter:\nTrudgian 2014 N(T)/S(T), D-056 §2's Ĉ₀), every unit window [a, a+1] with\na ≥ 2 contains a T whose distance from every zero ordinate in the window is\n≥ 1/(3·Ĉ₀(a+1)). -/\ntheorem exists_zero_avoiding_T (hZC : ZeroCountProp) {a : ℝ} (ha : 2 ≤ a) :\n ∃ T : ℝ, a ≤ T ∧ T ≤ a + 1 ∧\n ∀ ρ : ℂ, IsNontrivialZero ρ → a ≤ ρ.im → ρ.im ≤ a + 1 →\n 1 / (3 * C0hat (a + 1)) ≤ |ρ.im - T|\n```\n\nProof: \n- W := {ρ : ℂ // IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1} — Finite (via zerosIn_finite subset). Nat.card W =: k... wait the count Prop gives (Nat.card W : ℝ) ≤ C0hat (a+1).\n- S := (Finset of W).image (fun ρ => ρ.im) — or directly: S := W.toFinset.image im... card S ≤ Nat.card W (image reduces card: `Finset.card_image_le`).\n- Apply exists_avoiding_midpoint with k = Nat.card W: get T with clearance 1/(2(k+1)).\n- Show 1/(3·C0hat(a+1)) ≤ 1/(2(k+1)): ⟺ 2(k+1) ≤ 3·C0hat(a+1). Have k+1 ≤ C0hat(a+1)+1; C0hat(a+1) ≥ 2.9 (need a lemma: 2 ≤ C0hat t for t ≥ ... — C0hat t = 0.433 log(t+2) + 0.886 log log(t+2) + 2.9; for t ≥ 3: log(t+2) ≥ log 5 > 0, log log(t+2) ≥ log log 5: log 5 ≈ 1.6 > 1 ⟹ log log 5 > 0. So C0hat t ≥ 2.9 for t ≥ 3 — wait need t+2 ≥ e so log log(t+2) ≥ 0: t+2 ≥ e ⟸ t ≥ 1. a ≥ 2 ⟹ a+1 ≥ 3 > 1 ✓. So C0hat(a+1) ≥ 2.9). Then 2(k+1) ≤ 2(C+1) = 2C+2 ≤ 3C ⟺ C ≥ 2 ✓.\n\nThe `ZeroCountProp` definition — should it use Nat.card of the subtype? Need Finite instance first. In Lean:\n\n```lean\n/-- The zeros in a unit ordinate window, as a subtype. Finite by Zeta23. -/\ndef zeroWindow (a : ℝ) : Set ℂ := {ρ | IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1}\n\ntheorem zeroWindow_finite (a : ℝ) : (zeroWindow a).Finite := ...\n -- subset of zerosIn (a−1) (a+1): zerosIn T₁ T₂ = {ρ | IsNontrivialZero ρ ∧ T₁ < ρ.im ∧ ρ.im ≤ T₂}\n -- zeroWindow a ⊆ zerosIn (a−1) (a+1) ✓\n\n/-- Perimeter hypothesis (Trudgian 2014 N(T)/S(T), declared): the number of\nnontrivial zeros with ordinates in the unit window [t, t+1] is at most\nĈ₀(t+1) = 0.433 log(t+3) + 0.886 log log(t+3) + 2.9. -/\ndef ZeroCountProp : Prop :=\n ∀ t : ℝ, 2 ≤ t →\n (Nat.card (zeroWindow t) : ℝ) ≤ C0hat (t + 1)\n```\n\nHmm wait — Nat.card of a Set subtype: `Nat.card (zeroWindow t)` — needs the type `(zeroWindow t)` = {x // x ∈ zeroWindow t}, Finite instance from Set.Finite. `Set.Finite.to_subtype`? The instance: `Set.Finite.fintype`? For Nat.card just need `Finite` — instance from Set.Finite: there's `Set.Finite.to_subtype`... the standard: `instance (s : Set α) [h : Finite s] ...` — actually `Set.finite_coe_iff`? There's a `Finite` instance on the subtype from Set.Finite via `Set.Finite.to_subtype`? Hmm: `theorem Set.Finite.to_subtype`... The instance exists: `Set.finite_coe_iff : Finite s ↔ s.Finite`. So `(Set.finite_coe_iff.mpr (zeroWindow_finite a))` gives Finite (zeroWindow a) instance... it's a theorem not instance — use `haveI := ...` or `letI`. Fine.\n\nAlso — hmm, wait. Does the ZeroCountProp need a floor? (Nat.card : ℝ) ≤ C0hat — fine as real inequality, no floor needed.\n\nAlso should double check C0hat's monotonicity need: none — evaluated at t+1 directly.\n\nFor the kFun bounds — let me also confirm the horizontal bound form. D-036 (II),(IV): \"|1+1/s| ≤ 1 + (σ+1)/(σ²+T²) ⟹ |k_n| ≤ (1+4/(16+n))ⁿ + 1 ≤ e⁴ + 1 (−3 ≤ σ ≤ 3)\". Their (16+n) comes from σ²+T² with T ≥ √(n+16)? T ∈ [√n, √n+1]: T² ≥ n... they wrote 16+n perhaps from T² ≥ n and σ² ≥ ... with |σ| ≤ 3 hmm σ² ≥ 0. (σ+1)/(σ²+T²): for σ ∈ [−3,3]: numerator ≤ 4; denominator ≥ T² ≥ n. So ≤ 4/n; they used 4/(16+n) — maybe T² ≥ n+16?? no... whatever — I'll prove the clean form: ≤ e⁴+1 using σ ≤ 3, T² ≥ n:\n\n‖1+1/s‖ ≤ 1 + (σ+1)/(σ²+T²) requires the steps above; ≤ 1 + 4/n (needs σ+1 ≤ 4 i.e. σ ≤ 3 and σ²+T² ≥ n; also need (σ+1)/(σ²+T²) could be negative — fine, ≤ 4/n still holds since negative ≤ 4/n). Then (1+4/n)ⁿ ≤ e⁴ for n ≥ 1.\n\nActually — simpler unified: since σ ≤ 3 and σ²+T² ≥ n: (σ+1)/(σ²+T²) ≤ 4/n. Even simpler: skip the 16.\n\nWait — one subtlety: (1 + 4/n)ⁿ ≤ e⁴. Proof: 1+4/n ≤ e^{4/n} (Real.add_one_le_exp: 1+x ≤ e^x ∀x ✓). Then pow: (1+4/n)ⁿ ≤ (e^{4/n})ⁿ = e^{(4/n)·n} = e⁴ (n ≥ 1). pow_le_pow_left needs 0 ≤ 1+4/n ✓. exp: (Real.exp (4/n))^n = Real.exp (4/n * n) — `Real.exp_nat_mul`? Real.exp (n * x) = (exp x)^n: `Real.exp_nat_mul : Real.exp (n * x) = (Real.exp x)^n`? direction... there's `Real.exp_nat_mul (x : ℝ) (n : ℕ) : Real.exp (n * x) = (Real.exp x) ^ n`? something like that exists. Fine.\n\nThe normSq expansion of ‖1+1/s‖²: doable. Mathlib has `Complex.normSq_add`? There's `Complex.normSq_add (z w : ℂ) : normSq (z + w) = normSq z + normSq w + 2 * (z * conj w).re`? something like that. Or compute via div_re/div_im directly. (1/s).re = s.re/normSq s — `Complex.div_re`? (1/s) = conj s / normSq s: `Complex.one_div_re : (1/z).re = z.re / normSq z`? Hmm: z.re/normSq z for 1/z ✓ (`Complex.div_re` with 1: (1/z).re = (1·z.re + 0·(−z.im))/normSq z... the general `Complex.div_re : (z / w).re = (z.re * w.re + z.im * w.im) / normSq w` ✓; z=1: (w.re + 0)/normSq = w.re/normSq w ✓; im: (z/w).im = (z.im·w.re − z.re·w.im)/normSq w = −w.im/normSq w ✓).\n\nSo (1 + 1/s).re = 1 + σ/D, (1+1/s).im = −T/D where D = normSq s = σ²+T².\nnormSq(1+1/s) = (1+σ/D)² + (T/D)² = 1 + 2σ/D + σ²/D² + T²/D² = 1 + (2σ+1)/D (using σ²+T² = D ✓).\n‖1+1/s‖ = Real.sqrt (normSq ...) ≤ 1 + (σ+1)/D ⟸ square both sides: need 1+(2σ+1)/D ≤ (1+(σ+1)/D)² = 1 + 2(σ+1)/D + (σ+1)²/D² ⟺ 0 ≤ 1/D + (σ+1)²/D² = (D + (σ+1)²)/D² ✓ positive. And RHS ≥ 0 ✓ (sum of nonneg... 1 + (σ+1)/D: D ≥ 1? hmm not needed: D + (σ+1)² ≥ 0 ⟹ 1 + (σ+1)/D = (D+σ+1)/D and D+σ+1 = σ²+T²+σ+1 ≥ 3/4 > 0 ✓).\nThen ‖z‖ ≤ x given ‖z‖² ≤ x² and x ≥ 0: `abs_le_of_sq_le_sq'`? or `Real.sqrt_le_sqrt` + sqrt(x²) = x: ‖z‖ = sqrt(normSq z) ≤ sqrt(x²) = |x| = x. Mathlib: `Complex.norm_eq_sqrt_normSq`? Hmm — is there `Complex.norm_def : ‖z‖ = Real.sqrt (normSq z)`? There's `Complex.norm_apply : ‖z‖ = Complex.abs z` and `Complex.abs_def : abs z = Real.sqrt (normSq z)`? `Complex.abs` is def'd as sqrt normSq? `Complex.abs_apply : abs z = Real.sqrt (normSq z)`? close enough — I'll find exact names during implementation (or use normSq_le → norm_le: `Complex.norm_le_iff_normSq_le`? hmm might not exist; there's `Complex.normSq_eq_norm_sq : normSq z = ‖z‖^2` — then ‖z‖ ≤ x ⟺ ‖z‖² ≤ x² (x≥0) via sq_le_sq... `sq_le_sq' `or `abs_le_of_sq_le_sq`).\n\nOK. Enough design — the rest is implementation detail to be worked out in the Lean editor loop. Also `kFun_neg_two`: kFun n (−2) = ((−2)/(−2−1))^n − 1 = ((−2)/(−3))^n − 1 = (2/3)^n − 1. And ‖(2/3)^n − 1‖ ≤ 1: (2/3)ⁿ ∈ (0,1] ⟹ (2/3)ⁿ − 1 ∈ (−1, 0] ⟹ abs ≤ 1 ✓. In ℂ: (2/3 : ℂ)^n − 1 is real... norm = |...|. Straightforward with norm_num/positivity + pow bounds.\n\nPlan of files: one new file `NguyenRH1/LiContour.lean` containing:\n- §1 ZeroWindow + ZeroCountProp (perimeter Prop) + C0hat lower bound lemma (2 ≤ C0hat t for 1 ≤ t or so)\n- §2 exists_avoiding_midpoint (pure pigeonhole)\n- §3 exists_zero_avoiding_T (L3)\n- §4 kFun bounds (L1): kFun_norm_le_two, horizontal e⁴+1, right-vertical e^{√n/2}+1, kFun_neg_two value + ≤ 1\n- §5 zeroMult_neg_two = 1 (trivial-zero simplicity)\n\nSub-stage commits: 4a = §1–§3 (L3); 4b = §4 (L1 bounds); 4c = §5. Each build-green.\n\nWhere do I put things like `hLi`? Not needed here. Imports: LiSides (for kFun, zetaA), LiSkeleton (for C0hat), Zeta23 Statement (IsNontrivialZero, zeroMult), Mathlib.\n\nCheck the root file to see import structure. Let me read NguyenRH1.lean root + the header of LiSides for conventions.\n\nActually, before diving in: session protocol says skim latest journal (session-020) for Lean gotchas — STATE.md already summarized: \"bare π auto-binds (use Real.pi); bare ↑(...) with no expected ℂ drops the coe; AnalyticAt.comp/ContinuousAt.comp mis-unify beta-reduced points — use the _of_eq variants; TendstoLocallyUniformlyOn.differentiableOn takes the IsOpen as third arg; iteratedDerivWithin_tsum needs SummableLocallyUniformlyOn of each derivative family\". Good.\n\nTime to start building. First check root file + one header for conventions.","signature":""},{"type":"text","text":"All pieces confirmed. Design for ii′-4 (new file `LiContour.lean`, three sub-stages):\n\n- **ii′-4a — L3**: `ZeroCountProp` perimeter Prop (unit-window count ≤ `C0hat (t+1)`, via Zeta23 `zerosIn_finite`) + pure pigeonhole `exists_avoiding_midpoint` (k+1 midpoints, injective-badness argument) + `exists_zero_avoiding_T` with clearance 1/(3·C0hat(a+1)).\n- **ii′-4b — L1**: `‖kFun n s‖ ≤ 2` for re s ≤ 1/2; `‖kFun n (s+1)‖ ≤ e⁴+1` on horizontals (|re s| ≤ 3, n ≤ im²); `‖kFun n (s+1)‖ ≤ e^{√n/2}+1` on the right vertical; `kFun n (−2) = (2/3)ⁿ − 1`, ‖·‖ ≤ 1.\n- **ii′-4c — `zeroMult (−2) = 1`**: factor ζ(s) = (s+2)·G(s) near −2 with G(s) = Λ(s)/H(s), H(s) = 4π^{−s/2}Γ(s/2+2)/s; H(−2) = −2π ≠ 0; Λ(−2) = Λ(3) = ΓR(3)ζ(3) ≠ 0 (FE + `Gammaℝ_eq_zero_iff` + `riemannZeta_ne_zero_of_one_lt_re`); then `AnalyticAt.analyticOrderAt_eq_natCast`.\n\nChecking root file conventions, then starting."},{"type":"tool_use","id":"Read_59","name":"Read","input":{"file_path":"D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1.lean"},"extra_content":null},{"type":"tool_use","id":"Read_60","name":"Read","input":{"file_path":"D:\\Python\\Quantum\\research\\lean\\NguyenRH1\\NguyenRH1\\LiSides.lean","limit":55},"extra_content":null}]