← Session 24 — ii′-2…4: swaps, (4.10) design, contour + website roadmap fixes
thinking (25073 chars)
Conventions clear: `import Mathlib` wholesale, `open Zeta23 Complex Filter Topology`, `noncomputable section`, `namespace NguyenRH1`, full module doc with archive references. Note line 36 of the LiSides doc: "The split Sz = {nontrivial zeros} ∪ {−2} on the D-064 rectangle (σ ∈ [−5/2, 2√n]) is ii′-4 territory."
Now let me start with ii′-4a. First update todos, then write LiContour.lean §1–3 (L3). I'll develop iteratively: write the file with `sorry`s first? NO — honesty policy: no sorries in new proved files (sorryAx only on intended skeletons). Better: build lemma by lemma with `lake env lean` checking.
Strategy: write the file incrementally, checking with `lake env lean NguyenRH1/LiContour.lean` from the package dir after each chunk.
Key Lean details to nail for ii′-4a:
1. `zeroWindow (a : ℝ) : Set ℂ := {ρ | IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1}`
2. `zeroWindow_finite (a : ℝ) : (zeroWindow a).Finite`:
- zerosIn T₁ T₂ = {ρ | IsNontrivialZero ρ ∧ T₁ < ρ.im ∧ ρ.im ≤ T₂}
- zeroWindow a ⊆ zerosIn (a−1) (a+1): a ≤ im ⟹ a−1 < im ✓; im ≤ a+1 ✓.
- `(zerosIn_finite (a−1) (a+1)).subset hsubset`
3. ZeroCountProp:
```lean
def ZeroCountProp : Prop :=
∀ t : ℝ, 2 ≤ t → (Nat.card (zeroWindow t) : ℝ) ≤ C0hat (t + 1)
```
Nat.card of a set coerced to a type — `Nat.card (zeroWindow t)` — zeroWindow t is a Set ℂ; Nat.card expects a Type — `Nat.card (zeroWindow t)` where the set coerces to a subtype ✓ (Set coercion to Sort). Need Finite instance for Nat.card to be the "right" value: Nat.card is defined via toFinite-independent? Nat.card α = if finite then card else 0 — actually `Nat.card` is defined for any type and equals the cardinality for finite types (0 for infinite). `Nat.card_eq_of_finite`? The pigeonhole will need: from (Nat.card W : ℝ) ≤ C, conclude things about a Finset of W. With Finite W: get `W.toFinset` (needs Fintype — `Set.Finite.fintype : s.Finite → Fintype s` — `Set.Finite.fintype (h : s.Finite) : Fintype s`).
Hmm wait — Set.Finite.fintype is noncomputable ✓ fine. card: `Set.Finite.toFinset`? With `hs : s.Finite`, `hs.toFinset : Finset α` with `hs.mem_toFinset : x ∈ hs.toFinset ↔ x ∈ s`. And card relation: `Nat.card s = (hs.toFinset).card`? There's `Set.Finite.card_toFinset`? or Nat.card_coe_set_eq: `Nat.card s = s.toFinset.card` for Fintype... `Set.Nat.card_coe_set_eq : Nat.card s = ...`? There's `Set.ncard`: `s.ncard = Nat.card s` and `Set.Finite.toFinset`... `Set.ncard_eq_toFinset_card'`? For hs : s.Finite: `hs.ncard_toFinset_eq : s.ncard = hs.toFinset.card`? Something like `Set.ncard_coe_Finset`/`Set.Finite.ncard_toFinset`. I'll find it in implementation.
4. C0hat lower bound: `two_le_C0hat {t : ℝ} (ht : 1 ≤ t) : 2 ≤ C0hat t`:
C0hat t = 0.433 log(t+2) + 0.886 log log(t+2) + 2.9. t ≥ 1: t+2 ≥ 3 > e ⟹ log(t+2) ≥ 1 ⟹ log log(t+2) ≥ 0. So C0hat t ≥ 0.433·1 + 0 + 2.9 = 3.33 ≥ 2. Wait — need log(t+2) ≥ 1 ⟸ t+2 ≥ e: t ≥ 1 ⟹ t+2 ≥ 3 ≥ e ✓ (e ≤ 3: `Real.exp_one_lt_d9`? e < 3: `Real.exp_one_lt_d9 : Real.exp 1 < 2.7182818286`? there's `Real.exp_one_lt_d9`; or Real.exp 1 < 3 via `Real.exp_one_lt_...`? nlinarith with Real.exp_one_lt_d9 hmm; or log 3 ≥ 1 ⟺ 3 ≥ e: `Real.le_log_iff_exp_le`? For implementation: Real.log 3 ≥ 1 ⟸ Real.exp 1 ≤ 3. There's `Real.exp_one_lt_d9 : exp 1 < 2.7182818286` ⟹ < 3 ✓. Or `Real.one_le_log_iff`? I'll manage.)
Then: 0.433·log(t+2) ≥ 0.433·1 = 0.433 (mul_le_mul_of_nonneg_left), 0.886·loglog ≥ 0 (mul_nonneg, log_nonneg of log(t+2) ≥ 1), + 2.9. Total ≥ 3.33 ≥ 2 ✓.
Actually for the assembly I need 2(k+1) ≤ 3C from (k+1) ≤ C+1 and C ≥ 2: 2(k+1) ≤ 2(C+1) ≤ 3C ⟺ 2 ≤ C ✓.
5. exists_avoiding_midpoint — the pure combinatorial heart. Let me write it carefully:
```lean
theorem exists_avoiding_midpoint {k : ℕ} (a : ℝ) (S : Finset ℝ)
(hS : ∀ x ∈ S, a ≤ x ∧ x ≤ a + 1) (hcard : S.card ≤ k) :
∃ T : ℝ, a ≤ T ∧ T ≤ a + 1 ∧ ∀ x ∈ S, |x - T| ≥ 1 / (2 * (k + 1)) := by
classical
set w : ℝ := 1 / (2 * (k + 1)) with hw_def
have hw : 0 < w := by positivity -- k+1 ≥ 1
-- candidate points c j = a + (2j+1)·w, j ∈ range (k+1)
-- wait: T_j = a + (2j+1)/(2(k+1)) = a + (2j+1)·w ✓ since w = 1/(2(k+1)).
set c : ℕ → ℝ := fun j => a + (2 * j + 1) * w with hc_def
-- candidates in range
have hmem : ∀ j < k + 1, a ≤ c j ∧ c j ≤ a + 1 := ...
-- |c i − c j| = |i − j| · 2w for i j
have hdist : ∀ i j : ℕ, c i - c j = (2 * (i : ℝ) - 2 * j) * w := fun i j => by ring
-- bad set
set Bad : Finset ℕ := (Finset.range (k + 1)).filter (fun j => ∃ x ∈ S, |x - c j| < w)
...
```
Wait — careful with the distance scale: clearance target is w = 1/(2(k+1)); adjacent candidates are 2w apart: c(j+1) − c j = 2w. Bad j: ∃ x ∈ S, |x − c j| < w. If j₁, j₂ both bad via same x: |c j₁ − c j₂| ≤ |c j₁ − x| + |x − c j₂| < 2w ⟹ |i−j|·2w < 2w ⟹ |i−j| < 1 ⟹ i = j ✓.
- injOn: φ : ∀ j ∈ Bad, {x // x ∈ S}... use Finset.card_le_card_of_injOn: needs f : ℕ → ℝ with ∀ j ∈ Bad, f j ∈ S and Set.InjOn f Bad. Then Bad.card ≤ S.card ≤ k.
f via choice: for j ∈ Bad, ∃ x ∈ S, |x − c j| < w — choose. `Finset.card_le_card_of_injOn : (∀ a ∈ s, f a ∈ t) → Set.InjOn f s → s.card ≤ t.card` ✓ exists.
- Then ∃ j ∈ range(k+1), j ∉ Bad: card Bad ≤ k < k+1 = card (range (k+1)):
`Finset.exists_mem_not_mem_of_card_lt_card`? hmm — there's `Finset.exists_mem_not_mem_of_card_lt_card : s.card < t.card → ∃ a ∈ t, a ∉ s`? I believe something like `Finset.exists_mem_not_mem_of_card_lt`... Let me just plan: by_contra: if range(k+1) ⊆ Bad then card(range) ≤ card Bad ≤ k < k+1 contradiction. Finset.card_le_card (subset) — simple.
- For that j: ∀ x ∈ S, |x − c j| ≥ w: from j ∉ Bad: ¬∃ x ∈ S, |x−c j| < w ⟹ ∀ x ∈ S, ¬(|x−c j| < w) ⟹ ≥ w (not_lt ⟹ ge).
- Conclusion with T = c j.
The arithmetic |c i − c j| < 2w ⟹ i = j: c i − c j = (2i − 2j)w (integers cast); |(2i−2j)w| = |2(i−j)|·w (w > 0): = 2|i−j|w. If i ≠ j: |i−j| ≥ 1 ⟹ 2|i−j|w ≥ 2w — contradiction with < 2w. In Lean: work with ((i:ℝ) − j) via Int or directly reals: (2i+1)w − (2j+1)w = (2i − 2j)w as reals: 2*((i:ℝ)−(j:ℝ))*w. |(i:ℝ)−(j:ℝ)| ≥ 1 for i ≠ j: `Nat.one_le_iff...`: |((i : ℝ) - j)| = |(i−j : ℤ)| cast: abs_of... `Nat.cast_le`: i ≠ j ⟹ i < j ∨ j < i ⟹ (i:ℝ) + 1 ≤ j or j+1 ≤ i ⟹ |(i:ℝ)−(j:ℝ)| ≥ 1 ✓. nlinarith/linarith glue.
6. exists_zero_avoiding_T:
```lean
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| := by
classical
haveI := Set.finite_coe_iff.mpr (zeroWindow_finite a) -- Finite (zeroWindow a)
-- hmm: zeroWindow_finite gives (zeroWindow a).Finite; the subtype Finite instance
set W := zeroWindow a with hW
set S : Finset ℝ := (finite toFinset).image (fun ρ => (ρ : ℂ).im)
...
```
Hmm — Set.Finite.toFinset: for hfin : (zeroWindow a).Finite: `hfin.toFinset : Finset ℂ` with membership ↔ ∈ zeroWindow a. Then S := hfin.toFinset.image (Complex.im). card S ≤ hfin.toFinset.card = Nat.card (zeroWindow a) (via Set.Finite.toFinset + Nat.card: `Set.Finite.card_toFinset : s.Finite → s.toFinset.card = s.ncard`? or ncard... `Set.ncard_eq_toFinset_card'`? hmm: `Set.Finite.toFinset` is defined for a Finite set; `Set.ncard (s) = s.toFinset.card`? There's `Set.ncard_eq_toFinset_card' (s : Finset?)`... I'll figure out: the chain I need: S.card ≤ W.toFinset.card = W.ncard = Nat.card W ≤ C0hat(a+1) (hZC).
Finset.image card: `Finset.card_image_le : (s.image f).card ≤ s.card` ✓.
Then k := W.toFinset.card... wait exists_avoiding_midpoint wants S.card ≤ k with k : ℕ. Use k := hfin.toFinset.card: hcard: S.card ≤ k ✓ (card_image_le). Get T with clearance 1/(2(k+1)). Then need 1/(3·C0hat(a+1)) ≤ 1/(2(k+1)) ⟺ 2(k+1) ≤ 3·C0hat(a+1) (both sides positive): from (k : ℝ) ≤ C0hat(a+1) (hZC a ha — the Nat.card = k needs the card-toFinset relation... hfin.toFinset.card = Nat.card (zeroWindow a): `Set.Finite.toFinset` card: `Set.Finite.card_toFinset`? Let me search mathlib during implementation: likely `Set.Finite.toFinset` + `Set.ncard_eq_toFinset_card'`: theorem Set.ncard_eq_toFinset_card' (s : Set α) [Fintype s] : s.ncard = s.toFinset.card — different toFinset (Fintype-based vs Finite-based). Ugh, two toFinset variants. For hs : s.Finite: `hs.toFinset` and `hs.mem_toFinset`; and `hs.ncard_eq_toFinset_card`? I recall `Set.Finite.ncard_toFinset (hs : s.Finite) : s.ncard = hs.toFinset.card`?? I'll check. And Nat.card vs ncard: `Set.Nat.card_coe_set_eq : Nat.card s = s.ncard` ✓ exists (Set.Nat.card_coe_set_eq). Chain: hfin.toFinset.card = s.ncard (hfin lemma) = Nat.card s (symm).
Then: 2((k:ℝ)+1) ≤ 3·C: (k:ℝ) ≤ C ⟹ k+1 ≤ C+1 ⟹ 2(k+1) ≤ 2C+2 ≤ 3C ⟺ C ≥ 2 ✓ (two_le_C0hat with a+1 ≥ 3 ≥ 1 ✓).
Division flip: 1/(3C) ≤ 1/(2(k+1)) ⟺ 2(k+1) ≤ 3C with 0 < 2(k+1), 0 < 3C: `one_div_le_one_div_of_le` : 0 < a → a ≤ b → 1/b ≤ 1/a ✓ exists (one_div_le_one_div_of_le (ha : 0 < a) (h : a ≤ b) : 1/b ≤ 1/a). ✓
Then final: for ρ with the hypotheses: ρ ∈ zeroWindow a ⟹ ρ ∈ hfin.toFinset ⟹ ρ.im ∈ S (mem_image) ⟹ |ρ.im − T| ≥ 1/(2(k+1)) ≥ 1/(3C) ✓.
OK — ready to implement ii′-4a. One more check — exact names: `Finset.card_le_card_of_injOn`, `one_div_le_one_div_of_le`, `Set.Nat.card_coe_set_eq`, `Set.Finite.toFinset` API, `Finset.filter` decidability of the ∃ (classical ✓), `Real.add_one_le_exp` (for later), `zerosIn_finite` namespace: it's in `namespace Zeta23` (end Zeta23 at line 55-ish) — so `Zeta23.zerosIn_finite`. And IsNontrivialZero is in Zeta23.Statement — opened Zeta23 in LiSides; I'll open Zeta23 too.
Also C0hat lives in LiSkeleton (namespace NguyenRH1) ✓ same namespace.
Let me now write the file's §1–§3 and iterate with the compiler. I'll create LiContour.lean with a module doc and the L3 content first (4a), get it green, commit; then 4b (kFun bounds) appended; then 4c.
Actually — for efficiency, let me write the whole skeleton of §1–3 in one go and iterate on errors. Development loop: `cd research/lean/NguyenRH1 && ~/.elan/bin/lake env lean NguyenRH1/LiContour.lean`. PATH: handoff says elan at ~/.elan/bin, export per shell: `export PATH="$HOME/.elan/bin:$PATH"`.
Let me write §1–3 now. Careful with:
- `open Zeta23 Complex Filter Topology` + `open scoped Nat`
- noncomputable section + namespace NguyenRH1
Draft §1–3:
```lean
/-
NguyenRH1/LiContour.lean — tier ii′ sub-stage ii′-4 (D-064 §5 graph L3+L1,
D-036 §2–3): the zero-avoiding ordinate T (pigeonhole on the perimeter
unit-window count bound) and the Lagarias-kernel norm bounds.
L3 (D-036 §2): in every unit ordinate window [a, a+1] (a ≥ 2) with at most
Ĉ₀(a+1) zero ordinates, one of the k+1 equally-spaced midpoints
T_j = a + (2j+1)/(2(k+1)) has distance ≥ 1/(2(k+1)) ≥ 1/(3·Ĉ₀(a+1)) from
every zero ordinate in the window (k+1 candidates, each zero kills at most
one: adjacent candidates are 2·(1/(2(k+1))) apart). The count input is the
perimeter hypothesis `ZeroCountProp` (Trudgian 2014 N(T)/S(T), D-062 §4;
Ĉ₀ = C0hat is D-056 §2's majorant, already in LiSkeleton).
L1 (D-036 §3): the kernel kFun n s = (s/(s−1))ⁿ − 1 satisfies
* ‖kFun n s‖ ≤ 2 (re s ≤ 1/2: |s/(s−1)| ≤ 1)
* ‖kFun n (s+1)‖ ≤ e⁴ + 1 (|re s| ≤ 3, n ≤ (im s)²: the
horizontals, |1+1/s| ≤ 1 + (σ+1)/(σ²+T²) ≤ 1 + 4/n)
* ‖kFun n (s+1)‖ ≤ e^{√n/2} + 1 (2√n ≤ re s: the right vertical,
|1+1/s| ≤ 1 + 1/|s| ≤ 1 + 1/(2√n))
* kFun n (−2) = (2/3)ⁿ − 1, hence ‖kFun n (−2)‖ ≤ 1 (trivial-zero term).
Also the deferred trivial-zero simplicity (ii′-1b(iii) note): zeroMult(−2) = 1,
via ζ(s) = (s+2)·G(s) near −2 with G(s) = Λ(s)/H(s),
H(s) = 4·π^{−s/2}·Γ(s/2+2)/s = (s+2)·ΓR(s) (punctured), H(−2) = −2π ≠ 0,
Λ(−2) = Λ(3) = ΓR(3)·ζ(3) ≠ 0.
Archive references: D-036 §2–3, D-056 §2, D-064 §5 (L3/L1), D-066 §6.
-/
import Mathlib
import Zeta23.Statement
import NguyenRH1.LiSides
import NguyenRH1.LiSkeleton
open Zeta23 Complex Filter Topology
open scoped Nat
noncomputable section
namespace NguyenRH1
/-! ## 1. The unit ordinate window and the perimeter count hypothesis -/
/-- The nontrivial zeros with ordinate in the unit window [a, a+1]. -/
def zeroWindow (a : ℝ) : Set ℂ :=
{ρ | IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1}
/-- Finiteness of the unit ordinate window (Zeta23 `zerosIn_finite`). -/
theorem zeroWindow_finite (a : ℝ) : (zeroWindow a).Finite := by
apply Set.Finite.subset (zerosIn_finite (a - 1) (a + 1))
intro ρ hρ
refine ⟨hρ.1, ?_, hρ.2.2⟩
linarith [hρ.2.1]
/-- [PERIMETER — Trudgian 2014 N(T)/S(T), D-062 §4] The unit-window
zero-count bound: at most Ĉ₀(t+1) nontrivial zeros have ordinates in
[t, t+1] (t ≥ 2). This is the declared counting input for the L3
pigeonhole; Ĉ₀ = `C0hat` is D-056 §2's honest majorant. -/
def ZeroCountProp : Prop :=
∀ t : ℝ, 2 ≤ t → (Nat.card (zeroWindow t) : ℝ) ≤ C0hat (t + 1)
```
Wait — zerosIn_finite is in namespace Zeta23 (the file ended `end Zeta23`) — with `open Zeta23` it's just `zerosIn_finite` ✓. Also check: `zerosIn` def is in Zeta23 namespace in Statement.lean? The grep showed `Zeta23/Statement.lean:46:def zerosIn` — need to check namespace there; SeamClosed.lean:47 `zerosIn_finite` inside `namespace Zeta23`. With open Zeta23 both accessible ✓.
C0hat lower bound:
```lean
/-- 2 ≤ Ĉ₀(t) for t ≥ 1 (indeed 3.33: log(t+2) ≥ 1 since t + 2 ≥ 3 > e). -/
theorem two_le_C0hat {t : ℝ} (ht : 1 ≤ t) : 2 ≤ C0hat t := by
have h3 : 3 ≤ t + 2 := by linarith
have hlog : 1 ≤ Real.log (t + 2) := by
-- 1 = log e ≤ log (t+2) since e ≤ 3 ≤ t+2
have he : Real.exp 1 ≤ t + 2 := by
have := Real.exp_one_lt_d9
linarith [this.le.trans ... ] hmm
```
Real.exp_one_lt_d9 : Real.exp 1 < 2.7182818286 — so exp 1 < 3 ≤ t+2: linarith with h3. Then 1 ≤ log(t+2): `Real.le_log_iff_exp_le (h : 0 < x) : 1 ≤ log x ↔ exp 1 ≤ x`? hmm the exact name: `Real.le_log_iff_exp_le (hx : 0 < x) : r ≤ log x ↔ exp r ≤ x` ✓ exists. So `(Real.le_log_iff_exp_le (by positivity)).mpr he`... wait need r ≤ Real.log x form ✓.
Then log log(t+2) ≥ 0: `Real.log_nonneg (h : 1 ≤ x)` ✓: log(t+2) ≥ 1 ⟹ log log(t+2) ≥ 0.
```lean
have hloglog : 0 ≤ Real.log (Real.log (t + 2)) := Real.log_nonneg hlog
unfold C0hat
have : (0:ℝ) ≤ 0.433 * Real.log (t + 2) := by positivity -- 0.433 > 0, log ≥ 1 > 0
have : (0:ℝ) ≤ 0.886 * Real.log (Real.log (t + 2)) := by positivity
nlinarith / linarith: 0.433·(≥1) + (≥0) + 2.9 ≥ 2 — even simpler: both terms ≥ 0 and 2.9 ≥ 2 ✓ linarith.
```
positivity for the two products: 0.433 * log(t+2): needs log(t+2) ≥ 0 — positivity knows log_nonneg? positivity extension for Real.log: yes there's one (log_nonneg for 1 ≤ x... positivity has a log extension: `Real.log` positive when 1 ≤ x? I think positivity handles 0 ≤ log x given 1 ≤ x in context? Hmm — the positivity extension for log: `0 < Real.log x` if `1 < x`... To be safe, apply mul_nonneg directly with hlog.le / hloglog.)
Now §2 pigeonhole:
```lean
/-! ## 2. The midpoint pigeonhole (pure combinatorics) -/
/-- **Midpoint pigeonhole**: a finset S ⊂ [a, a+1] with card S ≤ k avoids
one of the k+1 midpoints a + (2j+1)/(2(k+1)) by ≥ 1/(2(k+1)). (Each point
of S is within < 1/(2(k+1)) of at most one midpoint, since adjacent
midpoints are 1/(k+1) apart; so at most card S ≤ k of the k+1 midpoints
are blocked.) -/
theorem exists_avoiding_midpoint {k : ℕ} (a : ℝ) (S : Finset ℝ)
(hS : ∀ x ∈ S, a ≤ x ∧ x ≤ a + 1) (hcard : S.card ≤ k) :
∃ T : ℝ, a ≤ T ∧ T ≤ a + 1 ∧
∀ x ∈ S, 1 / (2 * (k + 1)) ≤ |x - T| := by
classical
set w : ℝ := 1 / (2 * (k + 1)) with hw_def
have hk1 : (0:ℝ) < 2 * (k + 1) := by positivity
have hw : 0 < w := one_div_pos.mpr hk1
set c : ℕ → ℝ := fun j => a + (2 * j + 1) * w with hc_def
-- candidate spread: c i − c j = 2(i − j)·w
have hcd : ∀ i j : ℕ, c i - c j = 2 * ((i : ℝ) - (j : ℝ)) * w := fun i j => by
simp only [hc_def]; push_cast; ring
-- each candidate lies in [a, a+1]
have hc_mem : ∀ j < k + 1, a ≤ c j ∧ c j ≤ a + 1 := by
intro j hj
have hjl : (0:ℝ) ≤ 2 * j + 1 := by positivity
have hju : (2:ℝ) * j + 1 ≤ 2 * (k + 1) := by
have : j ≤ k := Nat.lt_succ_iff.mp hj
nlinarith [this] hmm — (2j+1) ≤ 2k+1 < 2(k+1)? 2j+1 ≤ 2k+1 and 2(k+1) = 2k+2: 2j+1 ≤ 2(k+1) ⟺ j ≤ k + 1/2 ✓ from j ≤ k. linarith after cast.
constructor
· have : 0 ≤ (2 * j + 1) * w := mul_nonneg hjl hw.le
simp only [hc_def]; linarith
· have : (2 * j + 1) * w ≤ 1 := by
rw [hw_def]; rw [div_le_iff hk1]... (2j+1)·(1/(2(k+1))) ≤ 1 ⟺ 2j+1 ≤ 2(k+1) ✓
calc (2 * (j:ℝ) + 1) * (1 / (2 * (k + 1))) = (2*j+1)/(2*(k+1)) := by ring
_ ≤ 1 := by rw [div_le_one hk1]; exact hju
simp only [hc_def]; linarith
...
```
Then the Bad set & injection:
```lean
-- bad candidates
set Bad : Finset ℕ := (Finset.range (k + 1)).filter
(fun j => ∃ x ∈ S, |x - c j| < w) with hBad_def
-- choose, for each bad j, a witness x j ∈ S
have hbad_wit : ∀ j ∈ Bad, ∃ x ∈ S, |x - c j| < w := fun j hj =>
(Finset.mem_filter.mp hj).2
choose! f hfS hfw using hbad_wit -- classical choice on finset
```
Hmm — `choose!` on ∀ j ∈ Bad, ∃ x ∈ S, ... gives f : ℕ → ℝ with hfS : ∀ j ∈ Bad, f j ∈ S and hfw : ∀ j ∈ Bad, |f j − c j| < w. ✓ (`choose!` tactic exists in Mathlib).
```lean
-- f is injective on Bad
have hinj : Set.InjOn f Bad := by
intro i hi j hj hij
simp only [Finset.coe_sort] at * -- hmm Bad is Finset; InjOn on ↑Bad
by_contra hne
have h1 : |f i - c i| < w := hfw i hi
have h2 : |f j - c j| < w := hfw j hj
have hcc : |c i - c j| ≤ |c i - f i| + |f i - c j| := by
have := abs_sub_le (c i) (f i) (c j) -- |a−c| ≤ |a−b|+|b−c|
...
have hfi : |c i - f i| = |f i - c i| := abs_sub_comm _ _
have hfj : f i = f j := hij
rw [hfj] at ...
-- so |c i − c j| < 2w
have hlt : |c i - c j| < 2 * w := by linarith [h1, h2, ...]
-- but |c i − c j| = 2|i−j|w ≥ 2w
rw [hcd i j] at hlt
have h3 : (1:ℝ) ≤ |(i : ℝ) - (j : ℝ)| := by
rw [← Nat.cast_one, ...]
rcases lt_or_gt_of_ne hne with h | h
· have : (i:ℝ) + 1 ≤ j := by exact_mod_cast Nat.add_one_le_of_lt h -- i < j
rw [abs_of_nonpos (by linarith)]; linarith
· have : (j:ℝ) + 1 ≤ i := by exact_mod_cast Nat.add_one_le_of_lt h
rw [abs_of_nonneg (by linarith)]; linarith
have hge : 2 * w ≤ |2 * ((i:ℝ) - (j:ℝ)) * w| := by
rw [abs_mul, abs_mul, abs_of_pos hw, abs_of_pos (by norm_num : (0:ℝ) < 2)]
nlinarith [h3, hw]
linarith [hlt, hge]
-- cardinalities
have hcardBad : Bad.card ≤ S.card :=
Finset.card_le_card_of_injOn f (fun j hj => hfS j hj) hinj
-- some candidate is not bad
have hlt2 : Bad.card < (Finset.range (k + 1)).card := by
rw [Finset.card_range]
exact Nat.lt_succ_of_le (hcardBad.trans hcard)
obtain ⟨j, hj, hjB⟩ : ∃ j ∈ Finset.range (k + 1), j ∉ Bad := by
by_contra hcon
push_neg at hcon
have : (Finset.range (k + 1)).card ≤ Bad.card :=
Finset.card_le_card (fun x hx => by ... hcon x hx → x ∈ Bad)
-- hcon : ∀ j, j ∈ range → j ∈ Bad (after push_neg of ∃ j ∈ range, j ∉ Bad)
linarith [hlt2] / exact absurd (this) (by omega using hlt2)
...
```
Careful: push_neg on ¬∃ j ∈ range, j ∉ Bad gives ∀ j ∈ range, j ∈ Bad ✓ (`Finset.forall_mem_...` push_neg handles ∈ patterns ✓).
Then:
```lean
have hjk : j < k + 1 := Finset.mem_range.mp hj
refine ⟨c j, (hc_mem j hjk).1, (hc_mem j hjk).2, fun x hx => ?_⟩
have : ¬ |x - c j| < w := by
intro hlt
exact hjB (Finset.mem_filter.mpr ⟨hj, ⟨x, hx, hlt⟩⟩)
exact not_lt.mp this
```
Wait — hjB : j ∉ Bad; membership: j ∈ Bad ⟺ j ∈ range ∧ ∃ x ∈ S, ... ✓ mem_filter. ✓.
The `Set.InjOn f Bad` — InjOn expects a Set; Bad coerces ✓. `Finset.card_le_card_of_injOn (f : α → β) (hf : ∀ a ∈ s, f a ∈ t) (inj : Set.InjOn f s) : s.card ≤ t.card` ✓ exists in Mathlib (Finset.card_le_card_of_injOn).
One subtlety: `choose!` — syntax: `choose! f hfS hfw using hbad_wit` where hbad_wit : ∀ j ∈ Bad, ∃ x ∈ S, |x − c j| < w. Hmm — ∀ j ∈ Bad desugars to ∀ j, j ∈ Bad → ∃ x, x ∈ S ∧ ...; choose! should give f : ℕ → ℝ, hfS : ∀ (j : ℕ), j ∈ Bad → f j ∈ S, hfw : ∀ (j : ℕ), j ∈ Bad → |f j − c j| < w. I believe choose/choose! handles this ✓.
Then §3:
```lean
/-! ## 3. L3: the zero-avoiding ordinate -/
/-- **L3** (D-036 §2): given the perimeter count bound `ZeroCountProp`,
every unit window [a, a+1] (a ≥ 2) contains an ordinate T at distance
≥ 1/(3·Ĉ₀(a+1)) from every zero ordinate in the window. -/
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| := by
classical
have hfin := zeroWindow_finite a
haveI : Finite (zeroWindow a) := Set.finite_coe_iff.mpr hfin -- or Fintype
...
```
Hmm — for Nat.card of the subtype: `Nat.card (zeroWindow a)` — needs `Finite ↥(zeroWindow a)` instance — haveI with Set.finite_coe_iff... hmm actually Set.finite_coe_iff : ↥s.Finite ↔ Finite ↥s? It's `Set.finite_coe_iff : s.Finite ↔ Finite s` ✓.
Then:
```lean
set WF : Finset ℂ := hfin.toFinset with hWF
have hWFmem : ∀ ρ : ℂ, ρ ∈ WF ↔ ρ ∈ zeroWindow a := Set.Finite.mem_toFinset hfin
set S : Finset ℝ := WF.image Complex.im with hS_def
have hScard : S.card ≤ WF.card := Finset.card_image_le
-- WF.card = Nat.card (zeroWindow a)
have hWFcard : (WF.card : ℝ) ≤ C0hat (a + 1) := by
have h1 := hZC a ha
have h2 : Nat.card (zeroWindow a) = WF.card := by
rw [Set.Nat.card_coe_set_eq] -- Nat.card ↥s = s.ncard
rw [hWF]; exact (Set.Finite.ncard_toFinset hfin).symm?
rw [h2] at h1; exact h1
```
`Set.Finite.ncard_toFinset`? Let me think: `Set.Finite.toFinset` card relation: I believe `Set.Finite.card_toFinset : hs.toFinset.card = s.ncard`? Hmm — Mathlib: `Set.Finite.toFinset (hs : s.Finite) : Finset α`; lemmas: `Set.Finite.mem_toFinset`, `Set.Finite.toFinset_subset...` and `Set.Finite.card_toFinset : hs.toFinset.card = s.ncard`?? hmm. Hmm, actually I recall `Set.Finite.toFinset` uses `Set.ncard` in `Set.Finite.card_toFinset (hs : s.Finite) : hs.toFinset.card = s.ncard`. I'll check in implementation.
Then apply exists_avoiding_midpoint with k := WF.card, a, S:
- hS: ∀ x ∈ S, a ≤ x ∧ x ≤ a+1: x ∈ S ⟹ x = ρ.im for some ρ ∈ WF ⟹ ρ ∈ zeroWindow a ⟹ bounds ✓.
- hcard: S.card ≤ WF.card ✓ (image).
Get T, hT1, hT2, hT3 : ∀ x ∈ S, 1/(2(WF.card+1)) ≤ |x − T|.
Then final: for ρ hyp: ρ.im ∈ S: `Finset.mem_image.mpr ⟨ρ, mem, rfl⟩` ✓. So 1/(2(k+1)) ≤ |ρ.im − T|. And 1/(3C) ≤ 1/(2(k+1)): one_div_le_one_div_of_le:
- 0 < 2(k+1): positivity ✓.
- 2(k+1) ≤ 3C: (k:ℝ) ≤ C (hWFcard), C ≥ 2 (two_le_C0hat, a+1 ≥ 3 ≥ 1) ⟹ 2(k+1) ≤ 2C+2 ≤ 3C ⟺ C ≥ 2 ✓ linarith/nlinarith.
Both sides: target `1 / (3 * C0hat (a + 1)) ≤ |ρ.im - T|` via le_trans (one_div_le_one_div_of_le (show 0 < 2*((k:ℝ)+1) ...) (show 2*((k:ℝ)+1) ≤ 3*C ...)) (hT3 ρ.im (mem)) — careful direction: one_div_le_one_div_of_le (ha : 0 < a) (h : a ≤ b) : 1 / b ≤ 1 / a. With a := 2(k+1), b := 3C: gives 1/(3C) ≤ 1/(2(k+1)) ✓ then trans with hT3 ✓.
Cast care: 2 * (k+1) with k : ℕ vs the real 2*(k+1) — in exists_avoiding_midpoint the clearance is `1 / (2 * (k + 1))` with (k+1 : ℝ)? The statement writes `2 * (k + 1)` — with k : ℕ and T : ℝ, Lean elaborates 2*(k+1) in ℝ with Nat casts: 2 * (↑k + 1)? Hmm — `1 / (2 * (k + 1))`: the whole expression is ℝ (since |x − T| : ℝ and ≤ between ℝ). 2*(k+1): k : ℕ coerced... (k+1) would elaborate in ℕ then cast? `2 * (k + 1)` with expected ℝ: 2 is ℝ, so (k+1) must be ℝ: k coerced to ℝ, 1 : ℝ — so it's 2 * (↑k + 1) ✓ good (not ↑(k+1) — actually both are equal by push_cast but elaboration gives (↑k + 1): fine, push_cast/norm_cast handles).
In hcardBad/trans: Nat.lt_succ_of_le : n ≤ k → n < k+1 ✓.
OK — I'm confident in the overall shape. Time to write and compile iteratively. For iterations, single-file check: cd research/lean/NguyenRH1 && export PATH and lake env lean.
Let me write §1–3 now (L3 complete), compile, fix, commit (sub-stage 4a). Then proceed to 4b.
One more consideration on `hc_mem` upper bound: c j = a + (2j+1)w with j ≤ k: (2j+1) ≤ 2k+1; w = 1/(2(k+1)): (2j+1)w ≤ (2k+1)/(2(k+1)) ≤ 1 ✓. linarith-friendly.
Actually — do I even need the candidates' membership hS hypothesis? The pigeonhole as designed doesn't use hS (points outside [a,a+1] would still only kill one candidate each)! Interesting — the candidate argument works for ANY finite S with card ≤ k. hS is unneeded. But keeping it is harmless... no — REMOVE it: simpler statement, and the wrapper doesn't even need the window bounds for S. Wait, but then the "T ∈ [a, a+1]" conclusion is independent of S ✓ true regardless. Yes — drop hS from exists_avoiding_midpoint (simpler). Hmm — but semantically the "right" statement includes it... For Lean economy: drop it. Actually wait, let me keep it minimal: drop.
Hmm, one catch — I should double-check `Finset.card_le_card_of_injOn` signature: `theorem Finset.card_le_card_of_injOn {s : Finset α} {t : Finset β} (f : α → β) (hf : ∀ a ∈ s, f a ∈ t) (f_inj : Set.InjOn f s) : s.card ≤ t.card` ✓ that's right.
And `Set.InjOn f Bad` where Bad : Finset ℕ — coercion to Set ℕ ✓.
Alright, writing the file now. I'll write §1–§3, compile.
Conventions clear. Marking docs read and starting ii′-4a (L3).
tool: TodoWrite ok
input
{
"todos": [
{
"activeForm": "Reading design docs for ii\u2032-4 content",
"content": "Read design docs: D-036 \u00a72, D-064 \u00a74, D-066 \u00a76 (zeroMult route)",
"status": "completed"
},
{
"activeForm": "Surveying Lean package state",
"content": "Survey Lean package state (LiSkeleton perimeter, LiSides zeroMult/Jlag)",
"status": "completed"
},
{
"activeForm": "Implementing L3 zero-avoiding T",
"content": "ii\u2032-4a: L3 pigeonhole \u2014 zeroWindow/ZeroCountProp + exists_avoiding_midpoint + exists_zero_avoiding_T",
"status": "in_progress"
},
{
"activeForm": "Implementing L1 kernel bounds",
"content": "ii\u2032-4b: L1 kernel bounds (kFun \u2264 2, e\u2074+1, e^{\u221an/2}+1, kFun(\u22122))",
"status": "pending"
},
{
"activeForm": "Proving trivial-zero simplicity",
"content": "ii\u2032-4c: zeroMult(\u22122) = 1 via FE + \u0393R pole + \u03b6(3) \u2260 0",
"status": "pending"
},
{
"activeForm": "Building and auditing axioms",
"content": "Full build + axiom audit",
"status": "pending"
},
{
"activeForm": "Running session end protocol",
"content": "Session end protocol: journal-021, NGUYEN.md, STATE.md, commit",
"status": "pending"
}
]
}
result 2026-08-22 15:13:35Z → 2026-08-28 04:27:14Z
{
"oldTodos": [
"content='Audit web app for hardcoded paths / Django-6-only APIs / requirements' status='completed' active_form='Auditing web app for paths and version-sensitive APIs'",
"content='Create staging folder outside repo; copy site-needed files' status='in_progress' active_form='Staging site files outside the repo'",
"content='Vendor Django 5.2 + markdown (pure-Python) into staging' status='pending' active_form='Vendoring Django 5.2 + markdown'",
"content='Patch staged settings.py + AGENT_DB path (web/database/agent.db)' status='pending' active_form='Patching staged settings and AGENT_DB path'",
"content='Local smoke test of staged site (Django 5.2 checks + page crawl)' status='pending' active_form='Smoke-testing staged site locally'",
"content='collectstatic + write app.cgi adapter + .htaccess files' status='pending' active_form='Collecting statics and writing CGI adapter'",
"content='Upload to server via resumable parallel FTP' status='pending' active_form='Uploading to server via FTP'",
"content='Server smoke test all key routes + feedback POST' status='pending' active_form='Smoke-testing live site'",
"content='Clean up probes, final report + memory update' status='pending' active_form='Cleaning up and reporting'"
],
"newTodos": [
"content='Audit web app for hardcoded paths / Django-6-only APIs / requirements' status='completed' active_form='Auditing web app for paths and version-sensitive APIs'",
"content='Create staging folder outside repo; copy site-needed files' status='completed' active_form='Staging site files outside the repo'",
"content='Vendor Django 5.2 + markdown (pure-Python) into staging' status='completed' active_form='Vendoring Django 5.2 + markdown'",
"content='Patch staged settings.py + AGENT_DB path (web/database/agent.db)' status='completed' active_form='Patching staged settings and AGENT_DB path'",
"content='Local smoke test of staged site (Django 5.2 checks + page crawl)' status='completed' active_form='Smoke-testing staged site locally'",
"content='collectstatic + write app.cgi adapter + .htaccess files' status='completed' active_form='Collecting statics and writing CGI adapter'",
"content='Upload to server via resumable parallel FTP' status='completed' active_form='Uploading to server via FTP'",
"content='Server smoke test all key routes + feedback POST' status='in_progress' active_form='Smoke-testing live site'",
"content='Clean up probes, final report + memory update' status='pending' active_form='Cleaning up and reporting'"
],
"cleared": false
}
raw content_json (database row)
[{"type":"thinking","thinking":"Conventions clear: `import Mathlib` wholesale, `open Zeta23 Complex Filter Topology`, `noncomputable section`, `namespace NguyenRH1`, full module doc with archive references. Note line 36 of the LiSides doc: \"The split Sz = {nontrivial zeros} ∪ {−2} on the D-064 rectangle (σ ∈ [−5/2, 2√n]) is ii′-4 territory.\"\n\nNow let me start with ii′-4a. First update todos, then write LiContour.lean §1–3 (L3). I'll develop iteratively: write the file with `sorry`s first? NO — honesty policy: no sorries in new proved files (sorryAx only on intended skeletons). Better: build lemma by lemma with `lake env lean` checking.\n\nStrategy: write the file incrementally, checking with `lake env lean NguyenRH1/LiContour.lean` from the package dir after each chunk.\n\nKey Lean details to nail for ii′-4a:\n\n1. `zeroWindow (a : ℝ) : Set ℂ := {ρ | IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1}`\n2. `zeroWindow_finite (a : ℝ) : (zeroWindow a).Finite`:\n - zerosIn T₁ T₂ = {ρ | IsNontrivialZero ρ ∧ T₁ < ρ.im ∧ ρ.im ≤ T₂}\n - zeroWindow a ⊆ zerosIn (a−1) (a+1): a ≤ im ⟹ a−1 < im ✓; im ≤ a+1 ✓.\n - `(zerosIn_finite (a−1) (a+1)).subset hsubset`\n3. ZeroCountProp:\n```lean\ndef ZeroCountProp : Prop :=\n ∀ t : ℝ, 2 ≤ t → (Nat.card (zeroWindow t) : ℝ) ≤ C0hat (t + 1)\n```\n Nat.card of a set coerced to a type — `Nat.card (zeroWindow t)` — zeroWindow t is a Set ℂ; Nat.card expects a Type — `Nat.card (zeroWindow t)` where the set coerces to a subtype ✓ (Set coercion to Sort). Need Finite instance for Nat.card to be the \"right\" value: Nat.card is defined via toFinite-independent? Nat.card α = if finite then card else 0 — actually `Nat.card` is defined for any type and equals the cardinality for finite types (0 for infinite). `Nat.card_eq_of_finite`? The pigeonhole will need: from (Nat.card W : ℝ) ≤ C, conclude things about a Finset of W. With Finite W: get `W.toFinset` (needs Fintype — `Set.Finite.fintype : s.Finite → Fintype s` — `Set.Finite.fintype (h : s.Finite) : Fintype s`). \n\n Hmm wait — Set.Finite.fintype is noncomputable ✓ fine. card: `Set.Finite.toFinset`? With `hs : s.Finite`, `hs.toFinset : Finset α` with `hs.mem_toFinset : x ∈ hs.toFinset ↔ x ∈ s`. And card relation: `Nat.card s = (hs.toFinset).card`? There's `Set.Finite.card_toFinset`? or Nat.card_coe_set_eq: `Nat.card s = s.toFinset.card` for Fintype... `Set.Nat.card_coe_set_eq : Nat.card s = ...`? There's `Set.ncard`: `s.ncard = Nat.card s` and `Set.Finite.toFinset`... `Set.ncard_eq_toFinset_card'`? For hs : s.Finite: `hs.ncard_toFinset_eq : s.ncard = hs.toFinset.card`? Something like `Set.ncard_coe_Finset`/`Set.Finite.ncard_toFinset`. I'll find it in implementation.\n\n4. C0hat lower bound: `two_le_C0hat {t : ℝ} (ht : 1 ≤ t) : 2 ≤ C0hat t`:\n C0hat t = 0.433 log(t+2) + 0.886 log log(t+2) + 2.9. t ≥ 1: t+2 ≥ 3 > e ⟹ log(t+2) ≥ 1 ⟹ log log(t+2) ≥ 0. So C0hat t ≥ 0.433·1 + 0 + 2.9 = 3.33 ≥ 2. Wait — need log(t+2) ≥ 1 ⟸ t+2 ≥ e: t ≥ 1 ⟹ t+2 ≥ 3 ≥ e ✓ (e ≤ 3: `Real.exp_one_lt_d9`? e < 3: `Real.exp_one_lt_d9 : Real.exp 1 < 2.7182818286`? there's `Real.exp_one_lt_d9`; or Real.exp 1 < 3 via `Real.exp_one_lt_...`? nlinarith with Real.exp_one_lt_d9 hmm; or log 3 ≥ 1 ⟺ 3 ≥ e: `Real.le_log_iff_exp_le`? For implementation: Real.log 3 ≥ 1 ⟸ Real.exp 1 ≤ 3. There's `Real.exp_one_lt_d9 : exp 1 < 2.7182818286` ⟹ < 3 ✓. Or `Real.one_le_log_iff`? I'll manage.)\n Then: 0.433·log(t+2) ≥ 0.433·1 = 0.433 (mul_le_mul_of_nonneg_left), 0.886·loglog ≥ 0 (mul_nonneg, log_nonneg of log(t+2) ≥ 1), + 2.9. Total ≥ 3.33 ≥ 2 ✓.\n \n Actually for the assembly I need 2(k+1) ≤ 3C from (k+1) ≤ C+1 and C ≥ 2: 2(k+1) ≤ 2(C+1) ≤ 3C ⟺ 2 ≤ C ✓.\n\n5. exists_avoiding_midpoint — the pure combinatorial heart. Let me write it carefully:\n\n```lean\ntheorem exists_avoiding_midpoint {k : ℕ} (a : ℝ) (S : Finset ℝ)\n (hS : ∀ x ∈ S, a ≤ x ∧ x ≤ a + 1) (hcard : S.card ≤ k) :\n ∃ T : ℝ, a ≤ T ∧ T ≤ a + 1 ∧ ∀ x ∈ S, |x - T| ≥ 1 / (2 * (k + 1)) := by\n classical\n set w : ℝ := 1 / (2 * (k + 1)) with hw_def\n have hw : 0 < w := by positivity -- k+1 ≥ 1\n -- candidate points c j = a + (2j+1)·w, j ∈ range (k+1)\n -- wait: T_j = a + (2j+1)/(2(k+1)) = a + (2j+1)·w ✓ since w = 1/(2(k+1)).\n set c : ℕ → ℝ := fun j => a + (2 * j + 1) * w with hc_def\n -- candidates in range\n have hmem : ∀ j < k + 1, a ≤ c j ∧ c j ≤ a + 1 := ...\n -- |c i − c j| = |i − j| · 2w for i j\n have hdist : ∀ i j : ℕ, c i - c j = (2 * (i : ℝ) - 2 * j) * w := fun i j => by ring\n -- bad set\n set Bad : Finset ℕ := (Finset.range (k + 1)).filter (fun j => ∃ x ∈ S, |x - c j| < w)\n ...\n```\n\nWait — careful with the distance scale: clearance target is w = 1/(2(k+1)); adjacent candidates are 2w apart: c(j+1) − c j = 2w. Bad j: ∃ x ∈ S, |x − c j| < w. If j₁, j₂ both bad via same x: |c j₁ − c j₂| ≤ |c j₁ − x| + |x − c j₂| < 2w ⟹ |i−j|·2w < 2w ⟹ |i−j| < 1 ⟹ i = j ✓.\n\n- injOn: φ : ∀ j ∈ Bad, {x // x ∈ S}... use Finset.card_le_card_of_injOn: needs f : ℕ → ℝ with ∀ j ∈ Bad, f j ∈ S and Set.InjOn f Bad. Then Bad.card ≤ S.card ≤ k.\n f via choice: for j ∈ Bad, ∃ x ∈ S, |x − c j| < w — choose. `Finset.card_le_card_of_injOn : (∀ a ∈ s, f a ∈ t) → Set.InjOn f s → s.card ≤ t.card` ✓ exists.\n- Then ∃ j ∈ range(k+1), j ∉ Bad: card Bad ≤ k < k+1 = card (range (k+1)): \n `Finset.exists_mem_not_mem_of_card_lt_card`? hmm — there's `Finset.exists_mem_not_mem_of_card_lt_card : s.card < t.card → ∃ a ∈ t, a ∉ s`? I believe something like `Finset.exists_mem_not_mem_of_card_lt`... Let me just plan: by_contra: if range(k+1) ⊆ Bad then card(range) ≤ card Bad ≤ k < k+1 contradiction. Finset.card_le_card (subset) — simple.\n- For that j: ∀ x ∈ S, |x − c j| ≥ w: from j ∉ Bad: ¬∃ x ∈ S, |x−c j| < w ⟹ ∀ x ∈ S, ¬(|x−c j| < w) ⟹ ≥ w (not_lt ⟹ ge).\n- Conclusion with T = c j.\n\nThe arithmetic |c i − c j| < 2w ⟹ i = j: c i − c j = (2i − 2j)w (integers cast); |(2i−2j)w| = |2(i−j)|·w (w > 0): = 2|i−j|w. If i ≠ j: |i−j| ≥ 1 ⟹ 2|i−j|w ≥ 2w — contradiction with < 2w. In Lean: work with ((i:ℝ) − j) via Int or directly reals: (2i+1)w − (2j+1)w = (2i − 2j)w as reals: 2*((i:ℝ)−(j:ℝ))*w. |(i:ℝ)−(j:ℝ)| ≥ 1 for i ≠ j: `Nat.one_le_iff...`: |((i : ℝ) - j)| = |(i−j : ℤ)| cast: abs_of... `Nat.cast_le`: i ≠ j ⟹ i < j ∨ j < i ⟹ (i:ℝ) + 1 ≤ j or j+1 ≤ i ⟹ |(i:ℝ)−(j:ℝ)| ≥ 1 ✓. nlinarith/linarith glue.\n\n6. exists_zero_avoiding_T:\n```lean\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| := by\n classical\n haveI := Set.finite_coe_iff.mpr (zeroWindow_finite a) -- Finite (zeroWindow a)\n -- hmm: zeroWindow_finite gives (zeroWindow a).Finite; the subtype Finite instance\n set W := zeroWindow a with hW\n set S : Finset ℝ := (finite toFinset).image (fun ρ => (ρ : ℂ).im)\n ...\n```\n\nHmm — Set.Finite.toFinset: for hfin : (zeroWindow a).Finite: `hfin.toFinset : Finset ℂ` with membership ↔ ∈ zeroWindow a. Then S := hfin.toFinset.image (Complex.im). card S ≤ hfin.toFinset.card = Nat.card (zeroWindow a) (via Set.Finite.toFinset + Nat.card: `Set.Finite.card_toFinset : s.Finite → s.toFinset.card = s.ncard`? or ncard... `Set.ncard_eq_toFinset_card'`? hmm: `Set.Finite.toFinset` is defined for a Finite set; `Set.ncard (s) = s.toFinset.card`? There's `Set.ncard_eq_toFinset_card' (s : Finset?)`... I'll figure out: the chain I need: S.card ≤ W.toFinset.card = W.ncard = Nat.card W ≤ C0hat(a+1) (hZC). \n\nFinset.image card: `Finset.card_image_le : (s.image f).card ≤ s.card` ✓.\n\nThen k := W.toFinset.card... wait exists_avoiding_midpoint wants S.card ≤ k with k : ℕ. Use k := hfin.toFinset.card: hcard: S.card ≤ k ✓ (card_image_le). Get T with clearance 1/(2(k+1)). Then need 1/(3·C0hat(a+1)) ≤ 1/(2(k+1)) ⟺ 2(k+1) ≤ 3·C0hat(a+1) (both sides positive): from (k : ℝ) ≤ C0hat(a+1) (hZC a ha — the Nat.card = k needs the card-toFinset relation... hfin.toFinset.card = Nat.card (zeroWindow a): `Set.Finite.toFinset` card: `Set.Finite.card_toFinset`? Let me search mathlib during implementation: likely `Set.Finite.toFinset` + `Set.ncard_eq_toFinset_card'`: theorem Set.ncard_eq_toFinset_card' (s : Set α) [Fintype s] : s.ncard = s.toFinset.card — different toFinset (Fintype-based vs Finite-based). Ugh, two toFinset variants. For hs : s.Finite: `hs.toFinset` and `hs.mem_toFinset`; and `hs.ncard_eq_toFinset_card`? I recall `Set.Finite.ncard_toFinset (hs : s.Finite) : s.ncard = hs.toFinset.card`?? I'll check. And Nat.card vs ncard: `Set.Nat.card_coe_set_eq : Nat.card s = s.ncard` ✓ exists (Set.Nat.card_coe_set_eq). Chain: hfin.toFinset.card = s.ncard (hfin lemma) = Nat.card s (symm). \n\nThen: 2((k:ℝ)+1) ≤ 3·C: (k:ℝ) ≤ C ⟹ k+1 ≤ C+1 ⟹ 2(k+1) ≤ 2C+2 ≤ 3C ⟺ C ≥ 2 ✓ (two_le_C0hat with a+1 ≥ 3 ≥ 1 ✓).\n\nDivision flip: 1/(3C) ≤ 1/(2(k+1)) ⟺ 2(k+1) ≤ 3C with 0 < 2(k+1), 0 < 3C: `one_div_le_one_div_of_le` : 0 < a → a ≤ b → 1/b ≤ 1/a ✓ exists (one_div_le_one_div_of_le (ha : 0 < a) (h : a ≤ b) : 1/b ≤ 1/a). ✓\n\nThen final: for ρ with the hypotheses: ρ ∈ zeroWindow a ⟹ ρ ∈ hfin.toFinset ⟹ ρ.im ∈ S (mem_image) ⟹ |ρ.im − T| ≥ 1/(2(k+1)) ≥ 1/(3C) ✓.\n\nOK — ready to implement ii′-4a. One more check — exact names: `Finset.card_le_card_of_injOn`, `one_div_le_one_div_of_le`, `Set.Nat.card_coe_set_eq`, `Set.Finite.toFinset` API, `Finset.filter` decidability of the ∃ (classical ✓), `Real.add_one_le_exp` (for later), `zerosIn_finite` namespace: it's in `namespace Zeta23` (end Zeta23 at line 55-ish) — so `Zeta23.zerosIn_finite`. And IsNontrivialZero is in Zeta23.Statement — opened Zeta23 in LiSides; I'll open Zeta23 too.\n\nAlso C0hat lives in LiSkeleton (namespace NguyenRH1) ✓ same namespace.\n\nLet me now write the file's §1–§3 and iterate with the compiler. I'll create LiContour.lean with a module doc and the L3 content first (4a), get it green, commit; then 4b (kFun bounds) appended; then 4c.\n\nActually — for efficiency, let me write the whole skeleton of §1–3 in one go and iterate on errors. Development loop: `cd research/lean/NguyenRH1 && ~/.elan/bin/lake env lean NguyenRH1/LiContour.lean`. PATH: handoff says elan at ~/.elan/bin, export per shell: `export PATH=\"$HOME/.elan/bin:$PATH\"`.\n\nLet me write §1–3 now. Careful with:\n- `open Zeta23 Complex Filter Topology` + `open scoped Nat`\n- noncomputable section + namespace NguyenRH1\n\nDraft §1–3:\n\n```lean\n/-\nNguyenRH1/LiContour.lean — tier ii′ sub-stage ii′-4 (D-064 §5 graph L3+L1,\nD-036 §2–3): the zero-avoiding ordinate T (pigeonhole on the perimeter\nunit-window count bound) and the Lagarias-kernel norm bounds.\n\nL3 (D-036 §2): in every unit ordinate window [a, a+1] (a ≥ 2) with at most\nĈ₀(a+1) zero ordinates, one of the k+1 equally-spaced midpoints\nT_j = a + (2j+1)/(2(k+1)) has distance ≥ 1/(2(k+1)) ≥ 1/(3·Ĉ₀(a+1)) from\nevery zero ordinate in the window (k+1 candidates, each zero kills at most\none: adjacent candidates are 2·(1/(2(k+1))) apart). The count input is the\nperimeter hypothesis `ZeroCountProp` (Trudgian 2014 N(T)/S(T), D-062 §4;\nĈ₀ = C0hat is D-056 §2's majorant, already in LiSkeleton).\n\nL1 (D-036 §3): the kernel kFun n s = (s/(s−1))ⁿ − 1 satisfies\n * ‖kFun n s‖ ≤ 2 (re s ≤ 1/2: |s/(s−1)| ≤ 1)\n * ‖kFun n (s+1)‖ ≤ e⁴ + 1 (|re s| ≤ 3, n ≤ (im s)²: the\n horizontals, |1+1/s| ≤ 1 + (σ+1)/(σ²+T²) ≤ 1 + 4/n)\n * ‖kFun n (s+1)‖ ≤ e^{√n/2} + 1 (2√n ≤ re s: the right vertical,\n |1+1/s| ≤ 1 + 1/|s| ≤ 1 + 1/(2√n))\n * kFun n (−2) = (2/3)ⁿ − 1, hence ‖kFun n (−2)‖ ≤ 1 (trivial-zero term).\n\nAlso the deferred trivial-zero simplicity (ii′-1b(iii) note): zeroMult(−2) = 1,\nvia ζ(s) = (s+2)·G(s) near −2 with G(s) = Λ(s)/H(s),\nH(s) = 4·π^{−s/2}·Γ(s/2+2)/s = (s+2)·ΓR(s) (punctured), H(−2) = −2π ≠ 0,\nΛ(−2) = Λ(3) = ΓR(3)·ζ(3) ≠ 0.\n\nArchive references: D-036 §2–3, D-056 §2, D-064 §5 (L3/L1), D-066 §6.\n-/\nimport Mathlib\nimport Zeta23.Statement\nimport NguyenRH1.LiSides\nimport NguyenRH1.LiSkeleton\n\nopen Zeta23 Complex Filter Topology\nopen scoped Nat\n\nnoncomputable section\n\nnamespace NguyenRH1\n\n/-! ## 1. The unit ordinate window and the perimeter count hypothesis -/\n\n/-- The nontrivial zeros with ordinate in the unit window [a, a+1]. -/\ndef zeroWindow (a : ℝ) : Set ℂ :=\n {ρ | IsNontrivialZero ρ ∧ a ≤ ρ.im ∧ ρ.im ≤ a + 1}\n\n/-- Finiteness of the unit ordinate window (Zeta23 `zerosIn_finite`). -/\ntheorem zeroWindow_finite (a : ℝ) : (zeroWindow a).Finite := by\n apply Set.Finite.subset (zerosIn_finite (a - 1) (a + 1))\n intro ρ hρ\n refine ⟨hρ.1, ?_, hρ.2.2⟩\n linarith [hρ.2.1]\n\n/-- [PERIMETER — Trudgian 2014 N(T)/S(T), D-062 §4] The unit-window\nzero-count bound: at most Ĉ₀(t+1) nontrivial zeros have ordinates in\n[t, t+1] (t ≥ 2). This is the declared counting input for the L3\npigeonhole; Ĉ₀ = `C0hat` is D-056 §2's honest majorant. -/\ndef ZeroCountProp : Prop :=\n ∀ t : ℝ, 2 ≤ t → (Nat.card (zeroWindow t) : ℝ) ≤ C0hat (t + 1)\n```\n\nWait — zerosIn_finite is in namespace Zeta23 (the file ended `end Zeta23`) — with `open Zeta23` it's just `zerosIn_finite` ✓. Also check: `zerosIn` def is in Zeta23 namespace in Statement.lean? The grep showed `Zeta23/Statement.lean:46:def zerosIn` — need to check namespace there; SeamClosed.lean:47 `zerosIn_finite` inside `namespace Zeta23`. With open Zeta23 both accessible ✓.\n\nC0hat lower bound:\n\n```lean\n/-- 2 ≤ Ĉ₀(t) for t ≥ 1 (indeed 3.33: log(t+2) ≥ 1 since t + 2 ≥ 3 > e). -/\ntheorem two_le_C0hat {t : ℝ} (ht : 1 ≤ t) : 2 ≤ C0hat t := by\n have h3 : 3 ≤ t + 2 := by linarith\n have hlog : 1 ≤ Real.log (t + 2) := by\n -- 1 = log e ≤ log (t+2) since e ≤ 3 ≤ t+2\n have he : Real.exp 1 ≤ t + 2 := by\n have := Real.exp_one_lt_d9\n linarith [this.le.trans ... ] hmm\n```\n\nReal.exp_one_lt_d9 : Real.exp 1 < 2.7182818286 — so exp 1 < 3 ≤ t+2: linarith with h3. Then 1 ≤ log(t+2): `Real.le_log_iff_exp_le (h : 0 < x) : 1 ≤ log x ↔ exp 1 ≤ x`? hmm the exact name: `Real.le_log_iff_exp_le (hx : 0 < x) : r ≤ log x ↔ exp r ≤ x` ✓ exists. So `(Real.le_log_iff_exp_le (by positivity)).mpr he`... wait need r ≤ Real.log x form ✓.\n\nThen log log(t+2) ≥ 0: `Real.log_nonneg (h : 1 ≤ x)` ✓: log(t+2) ≥ 1 ⟹ log log(t+2) ≥ 0.\n\n```lean\n have hloglog : 0 ≤ Real.log (Real.log (t + 2)) := Real.log_nonneg hlog\n unfold C0hat\n have : (0:ℝ) ≤ 0.433 * Real.log (t + 2) := by positivity -- 0.433 > 0, log ≥ 1 > 0\n have : (0:ℝ) ≤ 0.886 * Real.log (Real.log (t + 2)) := by positivity\n nlinarith / linarith: 0.433·(≥1) + (≥0) + 2.9 ≥ 2 — even simpler: both terms ≥ 0 and 2.9 ≥ 2 ✓ linarith.\n```\n\npositivity for the two products: 0.433 * log(t+2): needs log(t+2) ≥ 0 — positivity knows log_nonneg? positivity extension for Real.log: yes there's one (log_nonneg for 1 ≤ x... positivity has a log extension: `Real.log` positive when 1 ≤ x? I think positivity handles 0 ≤ log x given 1 ≤ x in context? Hmm — the positivity extension for log: `0 < Real.log x` if `1 < x`... To be safe, apply mul_nonneg directly with hlog.le / hloglog.)\n\nNow §2 pigeonhole:\n\n```lean\n/-! ## 2. The midpoint pigeonhole (pure combinatorics) -/\n\n/-- **Midpoint pigeonhole**: a finset S ⊂ [a, a+1] with card S ≤ k avoids\none of the k+1 midpoints a + (2j+1)/(2(k+1)) by ≥ 1/(2(k+1)). (Each point\nof S is within < 1/(2(k+1)) of at most one midpoint, since adjacent\nmidpoints are 1/(k+1) apart; so at most card S ≤ k of the k+1 midpoints\nare blocked.) -/\ntheorem exists_avoiding_midpoint {k : ℕ} (a : ℝ) (S : Finset ℝ)\n (hS : ∀ x ∈ S, a ≤ x ∧ x ≤ a + 1) (hcard : S.card ≤ k) :\n ∃ T : ℝ, a ≤ T ∧ T ≤ a + 1 ∧\n ∀ x ∈ S, 1 / (2 * (k + 1)) ≤ |x - T| := by\n classical\n set w : ℝ := 1 / (2 * (k + 1)) with hw_def\n have hk1 : (0:ℝ) < 2 * (k + 1) := by positivity\n have hw : 0 < w := one_div_pos.mpr hk1\n set c : ℕ → ℝ := fun j => a + (2 * j + 1) * w with hc_def\n -- candidate spread: c i − c j = 2(i − j)·w\n have hcd : ∀ i j : ℕ, c i - c j = 2 * ((i : ℝ) - (j : ℝ)) * w := fun i j => by\n simp only [hc_def]; push_cast; ring\n -- each candidate lies in [a, a+1]\n have hc_mem : ∀ j < k + 1, a ≤ c j ∧ c j ≤ a + 1 := by\n intro j hj\n have hjl : (0:ℝ) ≤ 2 * j + 1 := by positivity\n have hju : (2:ℝ) * j + 1 ≤ 2 * (k + 1) := by\n have : j ≤ k := Nat.lt_succ_iff.mp hj\n nlinarith [this] hmm — (2j+1) ≤ 2k+1 < 2(k+1)? 2j+1 ≤ 2k+1 and 2(k+1) = 2k+2: 2j+1 ≤ 2(k+1) ⟺ j ≤ k + 1/2 ✓ from j ≤ k. linarith after cast.\n constructor\n · have : 0 ≤ (2 * j + 1) * w := mul_nonneg hjl hw.le\n simp only [hc_def]; linarith\n · have : (2 * j + 1) * w ≤ 1 := by\n rw [hw_def]; rw [div_le_iff hk1]... (2j+1)·(1/(2(k+1))) ≤ 1 ⟺ 2j+1 ≤ 2(k+1) ✓\n calc (2 * (j:ℝ) + 1) * (1 / (2 * (k + 1))) = (2*j+1)/(2*(k+1)) := by ring\n _ ≤ 1 := by rw [div_le_one hk1]; exact hju\n simp only [hc_def]; linarith\n ...\n```\n\nThen the Bad set & injection:\n\n```lean\n -- bad candidates\n set Bad : Finset ℕ := (Finset.range (k + 1)).filter\n (fun j => ∃ x ∈ S, |x - c j| < w) with hBad_def\n -- choose, for each bad j, a witness x j ∈ S\n have hbad_wit : ∀ j ∈ Bad, ∃ x ∈ S, |x - c j| < w := fun j hj =>\n (Finset.mem_filter.mp hj).2\n choose! f hfS hfw using hbad_wit -- classical choice on finset\n```\n\nHmm — `choose!` on ∀ j ∈ Bad, ∃ x ∈ S, ... gives f : ℕ → ℝ with hfS : ∀ j ∈ Bad, f j ∈ S and hfw : ∀ j ∈ Bad, |f j − c j| < w. ✓ (`choose!` tactic exists in Mathlib).\n\n```lean\n -- f is injective on Bad\n have hinj : Set.InjOn f Bad := by\n intro i hi j hj hij\n simp only [Finset.coe_sort] at * -- hmm Bad is Finset; InjOn on ↑Bad\n by_contra hne\n have h1 : |f i - c i| < w := hfw i hi\n have h2 : |f j - c j| < w := hfw j hj\n have hcc : |c i - c j| ≤ |c i - f i| + |f i - c j| := by\n have := abs_sub_le (c i) (f i) (c j) -- |a−c| ≤ |a−b|+|b−c|\n ... \n have hfi : |c i - f i| = |f i - c i| := abs_sub_comm _ _\n have hfj : f i = f j := hij\n rw [hfj] at ... \n -- so |c i − c j| < 2w\n have hlt : |c i - c j| < 2 * w := by linarith [h1, h2, ...]\n -- but |c i − c j| = 2|i−j|w ≥ 2w\n rw [hcd i j] at hlt\n have h3 : (1:ℝ) ≤ |(i : ℝ) - (j : ℝ)| := by\n rw [← Nat.cast_one, ...]\n rcases lt_or_gt_of_ne hne with h | h\n · have : (i:ℝ) + 1 ≤ j := by exact_mod_cast Nat.add_one_le_of_lt h -- i < j\n rw [abs_of_nonpos (by linarith)]; linarith\n · have : (j:ℝ) + 1 ≤ i := by exact_mod_cast Nat.add_one_le_of_lt h\n rw [abs_of_nonneg (by linarith)]; linarith\n have hge : 2 * w ≤ |2 * ((i:ℝ) - (j:ℝ)) * w| := by\n rw [abs_mul, abs_mul, abs_of_pos hw, abs_of_pos (by norm_num : (0:ℝ) < 2)]\n nlinarith [h3, hw]\n linarith [hlt, hge]\n -- cardinalities\n have hcardBad : Bad.card ≤ S.card :=\n Finset.card_le_card_of_injOn f (fun j hj => hfS j hj) hinj\n -- some candidate is not bad\n have hlt2 : Bad.card < (Finset.range (k + 1)).card := by\n rw [Finset.card_range]\n exact Nat.lt_succ_of_le (hcardBad.trans hcard)\n obtain ⟨j, hj, hjB⟩ : ∃ j ∈ Finset.range (k + 1), j ∉ Bad := by\n by_contra hcon\n push_neg at hcon\n have : (Finset.range (k + 1)).card ≤ Bad.card :=\n Finset.card_le_card (fun x hx => by ... hcon x hx → x ∈ Bad)\n -- hcon : ∀ j, j ∈ range → j ∈ Bad (after push_neg of ∃ j ∈ range, j ∉ Bad)\n linarith [hlt2] / exact absurd (this) (by omega using hlt2)\n ...\n```\n\nCareful: push_neg on ¬∃ j ∈ range, j ∉ Bad gives ∀ j ∈ range, j ∈ Bad ✓ (`Finset.forall_mem_...` push_neg handles ∈ patterns ✓).\n\n Then:\n```lean\n have hjk : j < k + 1 := Finset.mem_range.mp hj\n refine ⟨c j, (hc_mem j hjk).1, (hc_mem j hjk).2, fun x hx => ?_⟩\n have : ¬ |x - c j| < w := by\n intro hlt\n exact hjB (Finset.mem_filter.mpr ⟨hj, ⟨x, hx, hlt⟩⟩)\n exact not_lt.mp this\n```\n\nWait — hjB : j ∉ Bad; membership: j ∈ Bad ⟺ j ∈ range ∧ ∃ x ∈ S, ... ✓ mem_filter. ✓.\n\nThe `Set.InjOn f Bad` — InjOn expects a Set; Bad coerces ✓. `Finset.card_le_card_of_injOn (f : α → β) (hf : ∀ a ∈ s, f a ∈ t) (inj : Set.InjOn f s) : s.card ≤ t.card` ✓ exists in Mathlib (Finset.card_le_card_of_injOn).\n\nOne subtlety: `choose!` — syntax: `choose! f hfS hfw using hbad_wit` where hbad_wit : ∀ j ∈ Bad, ∃ x ∈ S, |x − c j| < w. Hmm — ∀ j ∈ Bad desugars to ∀ j, j ∈ Bad → ∃ x, x ∈ S ∧ ...; choose! should give f : ℕ → ℝ, hfS : ∀ (j : ℕ), j ∈ Bad → f j ∈ S, hfw : ∀ (j : ℕ), j ∈ Bad → |f j − c j| < w. I believe choose/choose! handles this ✓.\n\nThen §3:\n\n```lean\n/-! ## 3. L3: the zero-avoiding ordinate -/\n\n/-- **L3** (D-036 §2): given the perimeter count bound `ZeroCountProp`,\nevery unit window [a, a+1] (a ≥ 2) contains an ordinate T at distance\n≥ 1/(3·Ĉ₀(a+1)) from every zero ordinate in the window. -/\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| := by\n classical\n have hfin := zeroWindow_finite a\n haveI : Finite (zeroWindow a) := Set.finite_coe_iff.mpr hfin -- or Fintype\n ...\n```\n\nHmm — for Nat.card of the subtype: `Nat.card (zeroWindow a)` — needs `Finite ↥(zeroWindow a)` instance — haveI with Set.finite_coe_iff... hmm actually Set.finite_coe_iff : ↥s.Finite ↔ Finite ↥s? It's `Set.finite_coe_iff : s.Finite ↔ Finite s` ✓.\n\nThen:\n```lean\n set WF : Finset ℂ := hfin.toFinset with hWF\n have hWFmem : ∀ ρ : ℂ, ρ ∈ WF ↔ ρ ∈ zeroWindow a := Set.Finite.mem_toFinset hfin\n set S : Finset ℝ := WF.image Complex.im with hS_def\n have hScard : S.card ≤ WF.card := Finset.card_image_le\n -- WF.card = Nat.card (zeroWindow a)\n have hWFcard : (WF.card : ℝ) ≤ C0hat (a + 1) := by\n have h1 := hZC a ha\n have h2 : Nat.card (zeroWindow a) = WF.card := by\n rw [Set.Nat.card_coe_set_eq] -- Nat.card ↥s = s.ncard\n rw [hWF]; exact (Set.Finite.ncard_toFinset hfin).symm? \n rw [h2] at h1; exact h1\n```\n\n`Set.Finite.ncard_toFinset`? Let me think: `Set.Finite.toFinset` card relation: I believe `Set.Finite.card_toFinset : hs.toFinset.card = s.ncard`? Hmm — Mathlib: `Set.Finite.toFinset (hs : s.Finite) : Finset α`; lemmas: `Set.Finite.mem_toFinset`, `Set.Finite.toFinset_subset...` and `Set.Finite.card_toFinset : hs.toFinset.card = s.ncard`?? hmm. Hmm, actually I recall `Set.Finite.toFinset` uses `Set.ncard` in `Set.Finite.card_toFinset (hs : s.Finite) : hs.toFinset.card = s.ncard`. I'll check in implementation.\n\n Then apply exists_avoiding_midpoint with k := WF.card, a, S:\n - hS: ∀ x ∈ S, a ≤ x ∧ x ≤ a+1: x ∈ S ⟹ x = ρ.im for some ρ ∈ WF ⟹ ρ ∈ zeroWindow a ⟹ bounds ✓.\n - hcard: S.card ≤ WF.card ✓ (image).\n Get T, hT1, hT2, hT3 : ∀ x ∈ S, 1/(2(WF.card+1)) ≤ |x − T|.\n \n Then final: for ρ hyp: ρ.im ∈ S: `Finset.mem_image.mpr ⟨ρ, mem, rfl⟩` ✓. So 1/(2(k+1)) ≤ |ρ.im − T|. And 1/(3C) ≤ 1/(2(k+1)): one_div_le_one_div_of_le:\n - 0 < 2(k+1): positivity ✓.\n - 2(k+1) ≤ 3C: (k:ℝ) ≤ C (hWFcard), C ≥ 2 (two_le_C0hat, a+1 ≥ 3 ≥ 1) ⟹ 2(k+1) ≤ 2C+2 ≤ 3C ⟺ C ≥ 2 ✓ linarith/nlinarith.\n\n Both sides: target `1 / (3 * C0hat (a + 1)) ≤ |ρ.im - T|` via le_trans (one_div_le_one_div_of_le (show 0 < 2*((k:ℝ)+1) ...) (show 2*((k:ℝ)+1) ≤ 3*C ...)) (hT3 ρ.im (mem)) — careful direction: one_div_le_one_div_of_le (ha : 0 < a) (h : a ≤ b) : 1 / b ≤ 1 / a. With a := 2(k+1), b := 3C: gives 1/(3C) ≤ 1/(2(k+1)) ✓ then trans with hT3 ✓.\n\nCast care: 2 * (k+1) with k : ℕ vs the real 2*(k+1) — in exists_avoiding_midpoint the clearance is `1 / (2 * (k + 1))` with (k+1 : ℝ)? The statement writes `2 * (k + 1)` — with k : ℕ and T : ℝ, Lean elaborates 2*(k+1) in ℝ with Nat casts: 2 * (↑k + 1)? Hmm — `1 / (2 * (k + 1))`: the whole expression is ℝ (since |x − T| : ℝ and ≤ between ℝ). 2*(k+1): k : ℕ coerced... (k+1) would elaborate in ℕ then cast? `2 * (k + 1)` with expected ℝ: 2 is ℝ, so (k+1) must be ℝ: k coerced to ℝ, 1 : ℝ — so it's 2 * (↑k + 1) ✓ good (not ↑(k+1) — actually both are equal by push_cast but elaboration gives (↑k + 1): fine, push_cast/norm_cast handles).\n\nIn hcardBad/trans: Nat.lt_succ_of_le : n ≤ k → n < k+1 ✓.\n\nOK — I'm confident in the overall shape. Time to write and compile iteratively. For iterations, single-file check: cd research/lean/NguyenRH1 && export PATH and lake env lean.\n\nLet me write §1–3 now (L3 complete), compile, fix, commit (sub-stage 4a). Then proceed to 4b.\n\nOne more consideration on `hc_mem` upper bound: c j = a + (2j+1)w with j ≤ k: (2j+1) ≤ 2k+1; w = 1/(2(k+1)): (2j+1)w ≤ (2k+1)/(2(k+1)) ≤ 1 ✓. linarith-friendly.\n\nActually — do I even need the candidates' membership hS hypothesis? The pigeonhole as designed doesn't use hS (points outside [a,a+1] would still only kill one candidate each)! Interesting — the candidate argument works for ANY finite S with card ≤ k. hS is unneeded. But keeping it is harmless... no — REMOVE it: simpler statement, and the wrapper doesn't even need the window bounds for S. Wait, but then the \"T ∈ [a, a+1]\" conclusion is independent of S ✓ true regardless. Yes — drop hS from exists_avoiding_midpoint (simpler). Hmm — but semantically the \"right\" statement includes it... For Lean economy: drop it. Actually wait, let me keep it minimal: drop.\n\nHmm, one catch — I should double-check `Finset.card_le_card_of_injOn` signature: `theorem Finset.card_le_card_of_injOn {s : Finset α} {t : Finset β} (f : α → β) (hf : ∀ a ∈ s, f a ∈ t) (f_inj : Set.InjOn f s) : s.card ≤ t.card` ✓ that's right.\n\nAnd `Set.InjOn f Bad` where Bad : Finset ℕ — coercion to Set ℕ ✓.\n\nAlright, writing the file now. I'll write §1–§3, compile.","signature":""},{"type":"text","text":"Conventions clear. Marking docs read and starting ii′-4a (L3)."},{"type":"tool_use","id":"TodoWrite_61","name":"TodoWrite","input":{"todos":[{"activeForm":"Reading design docs for ii′-4 content","content":"Read design docs: D-036 §2, D-064 §4, D-066 §6 (zeroMult route)","status":"completed"},{"activeForm":"Surveying Lean package state","content":"Survey Lean package state (LiSkeleton perimeter, LiSides zeroMult/Jlag)","status":"completed"},{"activeForm":"Implementing L3 zero-avoiding T","content":"ii′-4a: L3 pigeonhole — zeroWindow/ZeroCountProp + exists_avoiding_midpoint + exists_zero_avoiding_T","status":"in_progress"},{"activeForm":"Implementing L1 kernel bounds","content":"ii′-4b: L1 kernel bounds (kFun ≤ 2, e⁴+1, e^{√n/2}+1, kFun(−2))","status":"pending"},{"activeForm":"Proving trivial-zero simplicity","content":"ii′-4c: zeroMult(−2) = 1 via FE + ΓR pole + ζ(3) ≠ 0","status":"pending"},{"activeForm":"Building and auditing axioms","content":"Full build + axiom audit","status":"pending"},{"activeForm":"Running session end protocol","content":"Session end protocol: journal-021, NGUYEN.md, STATE.md, commit","status":"pending"}]},"extra_content":null}]