← Session 29 — ii′-5e-v: circle bound (far-tail + series bounds)
thinking (5901 chars)
`Complex.digamma := logDeriv Gamma` (rfl definition). So digamma(s₀/2) = logDeriv Gamma (s₀/2) = deriv Gamma (s₀/2) / Gamma (s₀/2) by logDeriv_apply.
So the direct computation of (G) at s₀:
```
logDeriv Gammaℝ s₀ = deriv (fun z => π^(−z/2) * Γ(z/2)) s₀ / (π^(−s₀/2) * Γ(s₀/2))
```
via logDeriv_apply + Gammaℝ_def. The deriv of the product via HasDerivAt.mul. This is ~50 lines. Same cost as the continuity route but more elementary. Actually — WAIT: logDeriv (f·g) = logDeriv f + logDeriv g when f,g differentiable and nonzero at the point (`logDeriv_mul (hf : f x ≠ 0) (hg : g x ≠ 0) (hf' : DifferentiableAt f x) (hg' : DifferentiableAt g x)`? — there's `logDeriv_mul` in Mathlib ✓ I'm fairly sure: `logDeriv_mul (hx : f x ≠ 0) (hy : g x ≠ 0) : logDeriv (f * g) x = logDeriv f x + logDeriv g x` — needs differentiability hypotheses: (hf : DifferentiableAt 𝕜 f x)? The exact signature: `theorem logDeriv_mul {f g : 𝕜 → 𝕜} {x : 𝕜} (hx : f x ≠ 0) (hy : g x ≠ 0) (hf : DifferentiableAt 𝕜 f x) (hg : DifferentiableAt 𝕜 g x) : logDeriv (f * g) x = logDeriv f x + logDeriv g x` ✓.
Then:
- logDeriv (fun z => (π:ℂ)^(−z/2)) s₀ = Complex.log π · (−1/2) = −(log π)/2: logDeriv of a^f = log a · f' when a ≠ 0... via logDeriv_apply + deriv: deriv (π^{−z/2}) at s₀ = π^{−s₀/2}·(Complex.log π·(−1/2)): and divided by π^{−s₀/2} ≠ 0: = Complex.log π·(−1/2). The ofReal_log: Complex.log (π:ℂ) = (Real.log π:ℂ) ✓ (Complex.ofReal_log pi_nonneg).
- logDeriv (fun z => Γ(z/2)) s₀ = (digamma(s₀/2)·Γ(s₀/2)·(1/2)) / Γ(s₀/2) = digamma(s₀/2)/2 — via the chain rule: deriv (Γ∘(·/2)) s₀ = deriv Γ (s₀/2)·(1/2) = digamma(s₀/2)·Γ(s₀/2)·(1/2): deriv Γ (s₀/2) = digamma(s₀/2)·Γ(s₀/2): from digamma_def + logDeriv_apply: deriv Gamma w = digamma w · Gamma w: rw [digamma_def, logDeriv_apply]: deriv Γ w / Γ w — so deriv Γ w = (digamma w)·Γ w iff Γ w ≠ 0 ✓ (mul_div_cancel).
So the direct (G)-at-real-point proof:
```
theorem logDeriv_Gammaℝ_eq_of_not_neg_nat {s₀ : ℂ} (hpoles : ∀ m : ℕ, s₀ / 2 ≠ -(m : ℂ)) :
logDeriv Complex.Gammaℝ s₀
= -(Real.log Real.pi : ℂ) / 2 + (1 / 2 : ℂ) * Complex.digamma (s₀ / 2) := by
have hdef : Complex.Gammaℝ = fun z : ℂ => (Real.pi : ℂ) ^ (-z / 2) * Complex.Gamma (z / 2) :=
funext Complex.Gammaℝ_def
rw [hdef]
-- the two factors: differentiability + nonvanishing
have h1 : DifferentiableAt ℂ (fun z : ℂ => (Real.pi : ℂ) ^ (-z / 2)) s₀ := ...
have h2 : DifferentiableAt ℂ (fun z : ℂ => Complex.Gamma (z / 2)) s₀ := ...
have hne1 : (Real.pi : ℂ) ^ (-s₀ / 2) ≠ 0 := cpow_ne_zero _ (by exact_mod_cast Real.pi_ne_zero)
have hne2 : Complex.Gamma (s₀ / 2) ≠ 0 := Complex.Gamma_ne_zero hpoles -- Gamma_ne_zero (hs : ∀ m, s ≠ -m) : Gamma s ≠ 0 ✓ (from Beta.lean:514 usage)
rw [logDeriv_mul hne1 hne2 h1 h2]
-- factor 1: logDeriv (π^(−z/2)) = −(logπ)/2
have hf1 : logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (-z / 2)) s₀ = -(Real.log Real.pi : ℂ) / 2 := ...
-- factor 2: logDeriv (Γ(z/2)) = ½ψ(s₀/2)
have hf2 : logDeriv (fun z : ℂ => Complex.Gamma (z / 2)) s₀ = (1 / 2 : ℂ) * Complex.digamma (s₀ / 2) := ...
rw [hf1, hf2]
```
hf1: logDeriv_apply + deriv: deriv (π^{−z/2}) s₀: HasDerivAt: `HasDerivAt.const_cpow`: let me get the exact form. In Mathlib: `theorem HasDerivAt.const_cpow {f : ℂ → ℂ} {x : ℂ} {f' : ℂ} (hf : HasDerivAt f f' x) (h : c ≠ 0 ∨ f x ≠ 0) : HasDerivAt (fun x => c ^ f x) (c ^ f x * Complex.log c * f') x`? I think the RHS is (c ^ f x * (Complex.log c * f')). Then .deriv: deriv = that. Then logDeriv_apply: deriv/value = [π^{−s₀/2}·log π·(−1/2)]/π^{−s₀/2} = log π·(−1/2) (mul_div_cancel_left₀ hne1) = −(log π)/2·... Complex.log (π:ℂ) = (Real.log π:ℂ) (Complex.ofReal_log Real.pi_nonneg) and the form: −(Real.log π:ℂ)/2 — matches after push_cast/ring.
hf2: logDeriv_apply + deriv (Γ(z/2)) s₀ = (1/2)·deriv Γ (s₀/2): HasDerivAt.comp: `((Complex.differentiableAt_Gamma _ hpoles).hasDerivAt).comp s₀ (hasDerivAt for z/2)`: HasDerivAt (z/2) (1/2): `hasDerivAt_id' s₀ |>.div_const 2`?? or (hasDerivAt_id s₀).div_const 2. Then HasDerivAt.comp x hg hf: HasDerivAt (Γ∘(·/2)) (deriv Γ (s₀/2)·(1/2)) — the chain rule form: (hg.comp x hf): HasDerivAt (fun x => Γ (x/2)) ((deriv Γ (s₀/2)) * (1/2)) x. .deriv: deriv (fun z => Γ (z/2)) s₀ = deriv Γ (s₀/2)·(1/2) — wait the comp gives HasDerivAt (fun x => g (f x)) (g' * f') where g' = deriv g (f x) — via HasDerivAt.deriv: deriv (g∘f) x = g' * f' ✓. Then:
logDeriv (Γ∘(·/2)) s₀ = [deriv Γ (s₀/2)·(1/2)] / Γ(s₀/2) = (1/2)·[deriv Γ (s₀/2)/Γ(s₀/2)] = (1/2)·digamma(s₀/2) (digamma_def + logDeriv_apply reversed).
deriv Γ (s₀/2) — the HasDerivAt from differentiableAt_Gamma: ((Complex.differentiableAt_Gamma _ hpoles).hasDerivAt) : HasDerivAt Gamma (deriv Gamma (s₀/2)) (s₀/2) ✓.
OK — this is clean, ~60 lines, no topology. And it SUPERSEDES the im ≠ 0 case: works at ANY s₀ with s₀/2 off the poles — including im ≠ 0 points! So I could use it everywhere in case (iii) — but (G) already exists for im ≠ 0, so use (G) there and this new lemma only at s₀ = −R... Actually — hmm, since it works at im ≠ 0 too (s/2 with im ≠ 0 ⟹ off poles ✓), ONE lemma `logDeriv_Gammaℝ_eq_of_not_neg_nat` handles ALL of case (iii) uniformly! (For s with im s ≠ 0: s/2 has im ≠ 0 ⟹ hpoles ✓.) Let me just prove the one lemma and use it everywhere in case (iii). No continuity needed at all!!
WAIT — but why did 5e-ii bother with the m-shift + im ≠ 0 restriction then? Probably because the direct logDeriv_mul route has a subtlety... hmm: logDeriv_mul needs DifferentiableAt of both factors at s₀ — the cpow factor: DifferentiableAt (fun z => (π:ℂ)^(−z/2)) s₀ — via DifferentiableAt.const_cpow (differentiableAt_id.neg.div_const 2) (Or.inl pi_ne_zero) ✓ fine. And Γ(z/2) ✓. So the direct proof works generally — 5e-ii's (G) via the shift was just the route they took (maybe logDeriv_mul wasn't noticed or cpow-defeq issues). Let me just write the direct proof.
One concern: logDeriv_mul's exact name/signature in this Mathlib. Let me grep.
`digamma := logDeriv Gamma` by definition — so (G) at real non-pole points is a direct `logDeriv_mul` computation, no continuity needed. Verify `logDeriv_mul`'s signature.
tool: Bash
input
{
"command": "cd \"D:/Python/Quantum/research/lean/NguyenRH1\" && grep -rn \"theorem logDeriv_mul\\|lemma logDeriv_mul\" ../../../zeta-23-lean/.lake/packages/mathlib/Mathlib/ 2>/dev/null | head -4",
"description": "Find logDeriv_mul signature"
}
raw content_json (database row)
[{"type":"thinking","thinking":"`Complex.digamma := logDeriv Gamma` (rfl definition). So digamma(s₀/2) = logDeriv Gamma (s₀/2) = deriv Gamma (s₀/2) / Gamma (s₀/2) by logDeriv_apply.\n\nSo the direct computation of (G) at s₀:\n```\nlogDeriv Gammaℝ s₀ = deriv (fun z => π^(−z/2) * Γ(z/2)) s₀ / (π^(−s₀/2) * Γ(s₀/2))\n```\nvia logDeriv_apply + Gammaℝ_def. The deriv of the product via HasDerivAt.mul. This is ~50 lines. Same cost as the continuity route but more elementary. Actually — WAIT: logDeriv (f·g) = logDeriv f + logDeriv g when f,g differentiable and nonzero at the point (`logDeriv_mul (hf : f x ≠ 0) (hg : g x ≠ 0) (hf' : DifferentiableAt f x) (hg' : DifferentiableAt g x)`? — there's `logDeriv_mul` in Mathlib ✓ I'm fairly sure: `logDeriv_mul (hx : f x ≠ 0) (hy : g x ≠ 0) : logDeriv (f * g) x = logDeriv f x + logDeriv g x` — needs differentiability hypotheses: (hf : DifferentiableAt 𝕜 f x)? The exact signature: `theorem logDeriv_mul {f g : 𝕜 → 𝕜} {x : 𝕜} (hx : f x ≠ 0) (hy : g x ≠ 0) (hf : DifferentiableAt 𝕜 f x) (hg : DifferentiableAt 𝕜 g x) : logDeriv (f * g) x = logDeriv f x + logDeriv g x` ✓.\nThen:\n- logDeriv (fun z => (π:ℂ)^(−z/2)) s₀ = Complex.log π · (−1/2) = −(log π)/2: logDeriv of a^f = log a · f' when a ≠ 0... via logDeriv_apply + deriv: deriv (π^{−z/2}) at s₀ = π^{−s₀/2}·(Complex.log π·(−1/2)): and divided by π^{−s₀/2} ≠ 0: = Complex.log π·(−1/2). The ofReal_log: Complex.log (π:ℂ) = (Real.log π:ℂ) ✓ (Complex.ofReal_log pi_nonneg).\n- logDeriv (fun z => Γ(z/2)) s₀ = (digamma(s₀/2)·Γ(s₀/2)·(1/2)) / Γ(s₀/2) = digamma(s₀/2)/2 — via the chain rule: deriv (Γ∘(·/2)) s₀ = deriv Γ (s₀/2)·(1/2) = digamma(s₀/2)·Γ(s₀/2)·(1/2): deriv Γ (s₀/2) = digamma(s₀/2)·Γ(s₀/2): from digamma_def + logDeriv_apply: deriv Gamma w = digamma w · Gamma w: rw [digamma_def, logDeriv_apply]: deriv Γ w / Γ w — so deriv Γ w = (digamma w)·Γ w iff Γ w ≠ 0 ✓ (mul_div_cancel).\n\nSo the direct (G)-at-real-point proof:\n```\ntheorem logDeriv_Gammaℝ_eq_of_not_neg_nat {s₀ : ℂ} (hpoles : ∀ m : ℕ, s₀ / 2 ≠ -(m : ℂ)) :\n logDeriv Complex.Gammaℝ s₀\n = -(Real.log Real.pi : ℂ) / 2 + (1 / 2 : ℂ) * Complex.digamma (s₀ / 2) := by\n have hdef : Complex.Gammaℝ = fun z : ℂ => (Real.pi : ℂ) ^ (-z / 2) * Complex.Gamma (z / 2) :=\n funext Complex.Gammaℝ_def\n rw [hdef]\n -- the two factors: differentiability + nonvanishing\n have h1 : DifferentiableAt ℂ (fun z : ℂ => (Real.pi : ℂ) ^ (-z / 2)) s₀ := ...\n have h2 : DifferentiableAt ℂ (fun z : ℂ => Complex.Gamma (z / 2)) s₀ := ...\n have hne1 : (Real.pi : ℂ) ^ (-s₀ / 2) ≠ 0 := cpow_ne_zero _ (by exact_mod_cast Real.pi_ne_zero)\n have hne2 : Complex.Gamma (s₀ / 2) ≠ 0 := Complex.Gamma_ne_zero hpoles -- Gamma_ne_zero (hs : ∀ m, s ≠ -m) : Gamma s ≠ 0 ✓ (from Beta.lean:514 usage)\n rw [logDeriv_mul hne1 hne2 h1 h2]\n -- factor 1: logDeriv (π^(−z/2)) = −(logπ)/2\n have hf1 : logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (-z / 2)) s₀ = -(Real.log Real.pi : ℂ) / 2 := ...\n -- factor 2: logDeriv (Γ(z/2)) = ½ψ(s₀/2)\n have hf2 : logDeriv (fun z : ℂ => Complex.Gamma (z / 2)) s₀ = (1 / 2 : ℂ) * Complex.digamma (s₀ / 2) := ...\n rw [hf1, hf2]\n```\nhf1: logDeriv_apply + deriv: deriv (π^{−z/2}) s₀: HasDerivAt: `HasDerivAt.const_cpow`: let me get the exact form. In Mathlib: `theorem HasDerivAt.const_cpow {f : ℂ → ℂ} {x : ℂ} {f' : ℂ} (hf : HasDerivAt f f' x) (h : c ≠ 0 ∨ f x ≠ 0) : HasDerivAt (fun x => c ^ f x) (c ^ f x * Complex.log c * f') x`? I think the RHS is (c ^ f x * (Complex.log c * f')). Then .deriv: deriv = that. Then logDeriv_apply: deriv/value = [π^{−s₀/2}·log π·(−1/2)]/π^{−s₀/2} = log π·(−1/2) (mul_div_cancel_left₀ hne1) = −(log π)/2·... Complex.log (π:ℂ) = (Real.log π:ℂ) (Complex.ofReal_log Real.pi_nonneg) and the form: −(Real.log π:ℂ)/2 — matches after push_cast/ring.\nhf2: logDeriv_apply + deriv (Γ(z/2)) s₀ = (1/2)·deriv Γ (s₀/2): HasDerivAt.comp: `((Complex.differentiableAt_Gamma _ hpoles).hasDerivAt).comp s₀ (hasDerivAt for z/2)`: HasDerivAt (z/2) (1/2): `hasDerivAt_id' s₀ |>.div_const 2`?? or (hasDerivAt_id s₀).div_const 2. Then HasDerivAt.comp x hg hf: HasDerivAt (Γ∘(·/2)) (deriv Γ (s₀/2)·(1/2)) — the chain rule form: (hg.comp x hf): HasDerivAt (fun x => Γ (x/2)) ((deriv Γ (s₀/2)) * (1/2)) x. .deriv: deriv (fun z => Γ (z/2)) s₀ = deriv Γ (s₀/2)·(1/2) — wait the comp gives HasDerivAt (fun x => g (f x)) (g' * f') where g' = deriv g (f x) — via HasDerivAt.deriv: deriv (g∘f) x = g' * f' ✓. Then:\n logDeriv (Γ∘(·/2)) s₀ = [deriv Γ (s₀/2)·(1/2)] / Γ(s₀/2) = (1/2)·[deriv Γ (s₀/2)/Γ(s₀/2)] = (1/2)·digamma(s₀/2) (digamma_def + logDeriv_apply reversed).\n deriv Γ (s₀/2) — the HasDerivAt from differentiableAt_Gamma: ((Complex.differentiableAt_Gamma _ hpoles).hasDerivAt) : HasDerivAt Gamma (deriv Gamma (s₀/2)) (s₀/2) ✓.\n\nOK — this is clean, ~60 lines, no topology. And it SUPERSEDES the im ≠ 0 case: works at ANY s₀ with s₀/2 off the poles — including im ≠ 0 points! So I could use it everywhere in case (iii) — but (G) already exists for im ≠ 0, so use (G) there and this new lemma only at s₀ = −R... Actually — hmm, since it works at im ≠ 0 too (s/2 with im ≠ 0 ⟹ off poles ✓), ONE lemma `logDeriv_Gammaℝ_eq_of_not_neg_nat` handles ALL of case (iii) uniformly! (For s with im s ≠ 0: s/2 has im ≠ 0 ⟹ hpoles ✓.) Let me just prove the one lemma and use it everywhere in case (iii). No continuity needed at all!!\n\nWAIT — but why did 5e-ii bother with the m-shift + im ≠ 0 restriction then? Probably because the direct logDeriv_mul route has a subtlety... hmm: logDeriv_mul needs DifferentiableAt of both factors at s₀ — the cpow factor: DifferentiableAt (fun z => (π:ℂ)^(−z/2)) s₀ — via DifferentiableAt.const_cpow (differentiableAt_id.neg.div_const 2) (Or.inl pi_ne_zero) ✓ fine. And Γ(z/2) ✓. So the direct proof works generally — 5e-ii's (G) via the shift was just the route they took (maybe logDeriv_mul wasn't noticed or cpow-defeq issues). Let me just write the direct proof.\n\nOne concern: logDeriv_mul's exact name/signature in this Mathlib. Let me grep.","signature":""},{"type":"text","text":"`digamma := logDeriv Gamma` by definition — so (G) at real non-pole points is a direct `logDeriv_mul` computation, no continuity needed. Verify `logDeriv_mul`'s signature."},{"type":"tool_use","id":"Bash_154","name":"Bash","input":{"command":"cd \"D:/Python/Quantum/research/lean/NguyenRH1\" && grep -rn \"theorem logDeriv_mul\\|lemma logDeriv_mul\" ../../../zeta-23-lean/.lake/packages/mathlib/Mathlib/ 2>/dev/null | head -4","description":"Find logDeriv_mul signature"},"extra_content":null}]