From 62457966bb506605b854202d01de577e9762228d Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 4 Oct 2026 10:58:09 +0200 Subject: [PATCH 1/8] feat(lean,#17845): brique k2.4 -- pas complet de pullback (toRealProd + caracterisations de support + pullback) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Etend les modules Pullback FR/_en (pas de nouveau fichier) : embedding produit toRealProd (hauteur Bool -> coordonnee reelle), caracterisations de support de la scission sous P >= 0 (max -> disjonction, min -> conjonction), et le theoreme pullback lui-meme (Lemme 1.4, transposé de Komlos/Pullback.lean l.55-92) sur Finset.mem_convexHull' + Finset.abs_sum_le_sum_abs + les ingredients k2.1/k2.2/k2.3. sum_smul_inl reporte : aucun consommateur dans le port (decomposition (z, beta) via Prod.fst_sum/Prod.snd_sum). See #17845 Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit d45cba5dae88eebc7c624e1e6b657ff9c3384fb7) --- .../Discrepancy/Komlos/Pullback.lean | 327 +++++++++++++++++- .../Discrepancy/Komlos/Pullback_en.lean | 326 ++++++++++++++++- .../Search/discrepancy_lean/FORMAL_STATUS.md | 3 +- 3 files changed, 641 insertions(+), 15 deletions(-) diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback.lean index 8c5c667708..369075d4ef 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback.lean @@ -45,16 +45,34 @@ convexité s'ouvre ensuite sur une base déjà vérifiée : appliqué à `convex_convexHull`, l.83 chez Dahia) : une combinaison convexe finie de points d'une enveloppe reste dans l'enveloppe. -**`pullback` reste reporté, et son bloqueur est désormais mesuré** : chez -Dahia il s'énonce sur `E →₀ ℝ` avec `E` un `ℝ`-module, l'enveloppe étant -prise dans `convexHull ℝ (P.support : Set E)`. La base de ce lake est -`Fin d → ℤ`, qui **n'est pas** un `ℝ`-module — `convexHull ℝ` n'y a pas de -sens sans plongement coordonnée-par-coordonnée dans `Fin d → ℝ` (le -« transport de dimension » de `FORMAL_STATUS.md`). L'état détaillé vit dans -`FORMAL_STATUS.md`. +**Brique k2.4 (le pas complet)** — `pullback` livré dans le cadre du lake, +sur le transport de dimension k2.3 qui a levé le bloqueur mesuré en k2.2 : + +- `toRealProd` + `toRealProd_injective` — l'embedding **produit** : la + grille entière × hauteur `Bool` dans la grille réelle × `ℝ` (la hauteur + `false ↦ 0`, `true ↦ 1` — c'est là que la hauteur du lake, un `Bool`, + devient la coordonnée réelle `(y, β)` de l'oracle) ; +- `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` — les + **caractérisations de support** de la scission sous `P ≥ 0`, lues point + par point (l'oracle les a gratuitement via `Finsupp.support` : + `mk_zero_mem_support_split` / `mk_one_mem_support_split` ; le cadre Finset + explicite du lake les exige comme hypothèses d'exactitude sur le support + `SQ` passé) ; +- `pullback` — **le pas complet** : si `(z, β)` est dans l'enveloppe du + support transporté de `split v P` avec `v = 3·w` coordonnée par + coordonnée et `β ≥ 1/3`, un signe `e ∈ {±1}` ramène `z + e • toReal w` + dans l'enveloppe du support transporté de `P`. Transposé de + `Komlos/Pullback.lean` l.55-92, les trois ingrédients livrés en k2.1/k2.2 + (`exists_sign_mul_add_eq`, `add_smul_mem_convexHull`, + `sum_smul_mem_convexHull`) et les ponts k2.3 (`toReal_mem_map_iff`) + étant consommés nommément. + +L'état détaillé vit dans `FORMAL_STATUS.md`. -/ import Discrepancy.Basic +import Discrepancy.Komlos.Split +import Discrepancy.Komlos.Transport /-! # Algèbre du pas de pullback (Lemme 1.4, Karingula–Lovett) @@ -199,4 +217,299 @@ lemma sum_smul_mem_convexHull {E : Type*} [AddCommGroup E] [Module ℝ E] ∑ y ∈ T, R y • f y ∈ convexHull ℝ s := (convex_convexHull ℝ s).sum_mem hR0 hR1 hmem +/-! ### Brique k2.4 : l'embedding produit et les caractérisations de support + +Le pas complet de `pullback` exige deux ingrédients de cadre que k2.1-k2.3 +n'ont pas encore rencontrés : l'embedding **produit** (grille × hauteur → +grille réelle × `ℝ`, là où la hauteur `Bool` devient la coordonnée `β` de +l'oracle) et les caractérisations de **support** de la scission (que +l'oracle obtient gratuitement via `Finsupp.support` et que le cadre Finset +explicite du lake doit énoncer comme hypothèses). -/ + +/-- **Embedding produit.** La grille entière munie de sa hauteur `Bool` se +plonge dans la grille réelle × `ℝ` : la composante spatiale par `toReal` +(le transport de dimension de la brique k2.3), la hauteur `false ↦ 0`, +`true ↦ 1`. + +C'est ce plongement qui fait de la hauteur du lake — un `Bool` — la +coordonnée réelle `(y, β)` de l'oracle : l'enveloppe de la conclusion du +`pullback` oracle vit dans `E × ℝ`, et c'est dans `(Fin d → ℝ) × ℝ` que le +lake la rejoint. + +L'injectivité est le papier de l'`Finset.map` du support transporté : sans +elle, `SQ.map toRealProdEmb` pourrait contracter des points et l'hypothèse +d'exactitude `hSQ` du théorème `pullback` perdrait des informations. La +composante spatiale est injective par `toReal_injective` (k2.3) ; la +composante hauteur sépare `false` de `true` par `0 ≠ 1`. -/ +def toRealProd {d : ℕ} : ((Fin d → ℤ) × Bool) → ((Fin d → ℝ) × ℝ) := + fun y => (toReal y.1, if y.2 then (1 : ℝ) else 0) + +lemma toRealProd_injective {d : ℕ} : Function.Injective (toRealProd (d := d)) := by + rintro ⟨x₁, b₁⟩ ⟨x₂, b₂⟩ h + simp only [toRealProd, Prod.mk.injEq] at h + obtain ⟨hxe, hbe⟩ := h + cases b₁ <;> cases b₂ <;> simp_all [toReal_injective.eq_iff] + +/-- La version `Finset.Embedding` de `toRealProd`, pour les `Finset.map` +des supports transportés. -/ +def toRealProdEmb {d : ℕ} : ((Fin d → ℤ) × Bool) ↪ ((Fin d → ℝ) × ℝ) := + ⟨toRealProd, toRealProd_injective⟩ + +/-- **Hauteur d'un point du support transporté.** Tout point de l'image +`SQ.map toRealProdEmb` porte une hauteur dans `{0, 1}` — la traduction +finie de `snd_eq_zero_or_one_of_mem_support_split` chez l'oracle. -/ +lemma mem_map_toRealProd_snd {d : ℕ} {y : (Fin d → ℝ) × ℝ} + {SQ : Finset ((Fin d → ℤ) × Bool)} (hy : y ∈ SQ.map toRealProdEmb) : + y.2 = 0 ∨ y.2 = 1 := by + rw [Finset.mem_map] at hy + obtain ⟨y', -, hye⟩ := hy + have h2 : (if y'.2 then (1 : ℝ) else 0) = y.2 := congrArg Prod.snd hye + cases b : y'.2 <;> rw [b] at h2 <;> simp_all + +/-- **Caractérisation du support, tranche basse.** Sous `P ≥ 0`, la tranche +`false` de la scission porte une masse non nulle exactement quand l'une des +deux translatées `P (x ± v)` est non nulle. + +C'est la lecture point-par-point de `mk_zero_mem_support_split` chez +l'oracle (`(x, 0) ∈ (split v P).support ↔ x + v ∈ P.support ∨ x - v ∈ +P.support`) : le cadre `Finsupp` de l'oracle la donne via le support, le +cadre Finset explicite du lake l'énonce sur la valeur. Sous `P ≥ 0`, +`½ · max a b ≠ 0` équivaut à `a ≠ 0 ∨ b ≠ 0` : c'est la positivité qui fait +traverser le `max`. -/ +lemma split_apply_zero_ne_iff {d : ℕ} {P : (Fin d → ℤ) → ℝ} (hP : ∀ x, 0 ≤ P x) + (v x : Fin d → ℤ) : + split v P (x, false) ≠ 0 ↔ P (x + v) ≠ 0 ∨ P (x - v) ≠ 0 := by + rw [split_apply_zero] + constructor + · intro h + by_contra hcon + obtain ⟨h1, h2⟩ := not_or.mp hcon + rw [not_not.mp h1, not_not.mp h2, max_self] at h + norm_num at h + · rintro (h | h) + · intro hcon + have hlt : (0 : ℝ) < P (x + v) := lt_of_le_of_ne (hP _) (Ne.symm h) + exact absurd hcon (ne_of_gt (mul_pos one_half_pos + (lt_of_lt_of_le hlt (le_max_left _ _)))) + · intro hcon + have hlt : (0 : ℝ) < P (x - v) := lt_of_le_of_ne (hP _) (Ne.symm h) + exact absurd hcon (ne_of_gt (mul_pos one_half_pos + (lt_of_lt_of_le hlt (le_max_right _ _)))) + +/-- **Caractérisation du support, tranche haute.** Sous `P ≥ 0`, la tranche +`true` de la scission porte une masse non nulle exactement quand les deux +translatées `P (x ± v)` sont non nulles — le `min` exige la conjonction, +là où le `max` de la tranche basse exige la disjonction. + +Lecture point-par-point de `mk_one_mem_support_split` chez l'oracle +(`(x, 1) ∈ (split v P).support ↔ x + v ∈ P.support ∧ x - v ∈ P.support`). -/ +lemma split_apply_one_ne_iff {d : ℕ} {P : (Fin d → ℤ) → ℝ} (hP : ∀ x, 0 ≤ P x) + (v x : Fin d → ℤ) : + split v P (x, true) ≠ 0 ↔ P (x + v) ≠ 0 ∧ P (x - v) ≠ 0 := by + rw [split_apply_one] + constructor + · intro hcon + constructor + · intro hzero + apply hcon + rw [hzero, min_eq_left (hP (x - v)), mul_zero] + · intro hzero + apply hcon + rw [hzero, min_eq_right (hP (x + v)), mul_zero] + · rintro ⟨h, h'⟩ + have hlt : (0 : ℝ) < P (x + v) := lt_of_le_of_ne (hP _) (Ne.symm h) + have hlt' : (0 : ℝ) < P (x - v) := lt_of_le_of_ne (hP _) (Ne.symm h') + exact ne_of_gt (mul_pos one_half_pos (lt_min hlt hlt')) + +/-! ### Brique k2.4 : le pas complet -/ + +/-- **Le pas de pullback (Lemme 1.4).** Si la distribution `P` sur la +grille entière est non négative, de support contenu dans `SP`, et si +`(z, β)` appartient à l'enveloppe convexe du support **transporté** de la +scission `split v P` — transporté par l'embedding produit `toRealProd` — +avec `v = 3 · w` coordonnée par coordonnée et `β ≥ 1/3`, alors un signe +`e ∈ {±1}` ramène `z + e • toReal w` dans l'enveloppe convexe du support +transporté de `P`. + +C'est la transposition du théorème `pullback` de Dahia +(`Komlos/Pullback.lean`, l.55-92) au cadre du lake. Trois écarts de cadre +sont arbitrés : + +- **le point `z` vit côté `ℝ`** : chez l'oracle, l'hypothèse d'induction + produit un point de `E × ℝ` quelconque dans l'enveloppe ; ici le + consommateur final (le Lemme 1.4) produit un barycentre côté grille + réelle, d'où `z : Fin d → ℝ` et l'hypothèse sur l'enveloppe **dans + l'image transportée**, pas dans la grille entière ; +- **`hSQ` est une hypothèse, pas un calcul** : chez l'oracle le support + `(split v P).support` est calculé (`mk_zero_mem_support_split`) ; le + cadre Finset explicite du lake exige de connaître le support `SQ` de la + scission et son exactitude (`∀ y ∈ SQ, split v P y ≠ 0`) — c'est la + contrepartie de l'absence de `Finsupp` ; +- **`hPsupp` relaie le support de `P`** : de même, `SP` doit contenir le + support de `P` pour que les extrémités des segments y atterrissent. + +La preuve est celle de l'oracle, décomposée sur les ingrédients livrés en +k2.1-k2.3 : `Finset.mem_convexHull'` décompose l'appartenance de `(z, β)` +en poids `R` ; `abs_sum_le_sum_abs` borne la part des poids hauteurs `0` ; +`exists_sign_mul_add_eq` (k2.1) produit le signe `e` et le coefficient +`c` ; chaque point de la combinaison est ramené dans l'enveloppe du +support transporté de `P` par `add_smul_mem_convexHull` (k2.2, tranches +hautes) ou par l'appartenance directe d'une extrémité (tranches basses, +via `toReal_mem_map_iff` de k2.3) ; `sum_smul_mem_convexHull` (k2.2) +referme. -/ +theorem pullback {d : ℕ} {P : (Fin d → ℤ) → ℝ} (hP : ∀ x, 0 ≤ P x) + {SP : Finset (Fin d → ℤ)} (hPsupp : ∀ x, P x ≠ 0 → x ∈ SP) + {v w : Fin d → ℤ} (hv : ∀ i, v i = 3 * w i) + {SQ : Finset ((Fin d → ℤ) × Bool)} (hSQ : ∀ y ∈ SQ, split v P y ≠ 0) + {β : ℝ} (hβ : 3⁻¹ ≤ β) {z : Fin d → ℝ} + (hmem : (z, β) ∈ convexHull ℝ + (↑(SQ.map toRealProdEmb) : Set ((Fin d → ℝ) × ℝ))) : + ∃ e : ℝ, (e = 1 ∨ e = -1) ∧ + z + e • toReal w ∈ convexHull ℝ + (↑(SP.map ⟨⇑toReal, toReal_injective⟩) : Set (Fin d → ℝ)) := by + classical + -- la direction du transport : toReal v = 3 • toReal w + have hvR : toReal v = (3 : ℝ) • toReal w := by + funext i + simp only [toReal_apply, hv i, Int.cast_mul, Pi.smul_apply, smul_eq_mul] + push_cast + ring + -- décomposition de l'appartenance en poids + obtain ⟨R, hR0, hR1, hRc⟩ := Finset.mem_convexHull'.1 hmem + have hz : ∑ y ∈ SQ.map toRealProdEmb, R y • y.1 = z := by + have h := congrArg Prod.fst hRc + rw [Prod.fst_sum] at h + exact h + have hb : ∑ y ∈ SQ.map toRealProdEmb, R y * y.2 = β := by + have h := congrArg Prod.snd hRc + rw [Prod.snd_sum] at h + exact h + -- les hauteurs du support transporté sont dans {0, 1} + have hsnd : ∀ y ∈ SQ.map toRealProdEmb, y.2 = 0 ∨ y.2 = 1 := + fun y hy => mem_map_toRealProd_snd hy + -- chaque point du support transporté provient d'un point de SQ + have hpre : ∀ y ∈ SQ.map toRealProdEmb, ∃ y' ∈ SQ, toRealProd y' = y := by + intro y hy + rw [Finset.mem_map] at hy + obtain ⟨y', hy', hye⟩ := hy + exact ⟨y', hy', hye⟩ + -- les extrémités des tranches basses atterrissent dans le support de P + have hfalse : ∀ y ∈ SQ.map toRealProdEmb, y.2 = 0 → + y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) ∨ + y.1 - toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) := by + intro y hy y0 + obtain ⟨y', hy', hye⟩ := hpre y hy + obtain ⟨x', b'⟩ := y' + cases b' with + | false => + have hx := (split_apply_zero_ne_iff hP v x').1 (hSQ (x', false) hy') + have hy1 : toReal x' = y.1 := congrArg Prod.fst hye + rcases hx with h | h + · left + have hmem' := (toReal_mem_map_iff (x' + v) SP).2 (hPsupp _ h) + rwa [map_add, hy1] at hmem' + · right + have hmem' := (toReal_mem_map_iff (x' - v) SP).2 (hPsupp _ h) + rwa [map_sub, hy1] at hmem' + | true => + exfalso + have h1 : y.2 = 1 := by + have := congrArg Prod.snd hye + simpa [toRealProd] using this.symm + rw [y0] at h1 + norm_num at h1 + -- les extrémités des tranches hautes atterrissent dans le support de P + have htrue : ∀ y ∈ SQ.map toRealProdEmb, y.2 = 1 → + y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) ∧ + y.1 - toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) := by + intro y hy y1 + obtain ⟨y', hy', hye⟩ := hpre y hy + obtain ⟨x', b'⟩ := y' + cases b' with + | true => + obtain ⟨h, h'⟩ := (split_apply_one_ne_iff hP v x').1 (hSQ (x', true) hy') + have hy1 : toReal x' = y.1 := congrArg Prod.fst hye + constructor + · have hmem' := (toReal_mem_map_iff (x' + v) SP).2 (hPsupp _ h) + rwa [map_add, hy1] at hmem' + · have hmem' := (toReal_mem_map_iff (x' - v) SP).2 (hPsupp _ h') + rwa [map_sub, hy1] at hmem' + | false => + exfalso + have h0 : y.2 = 0 := by + have := congrArg Prod.snd hye + simpa [toRealProd] using this.symm + rw [y1] at h0 + norm_num at h0 + -- la borne sur la part des poids de hauteur 0 : |σ y| = 1 dans les deux branches + have ha : |∑ y ∈ SQ.map toRealProdEmb, R y * ((1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1))| ≤ 1 - β := by + refine (Finset.abs_sum_le_sum_abs _ _).trans + ((Finset.sum_le_sum (g := fun y => R y * (1 - y.2)) ?_).trans_eq ?_) + · intro y hy + rcases hsnd y hy with h | h + · rw [h, sub_zero, mul_one, abs_mul, abs_of_nonneg (hR0 y hy)] + by_cases hyv : y.1 + toReal v ∈ + (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + · rw [if_pos hyv]; simp + · rw [if_neg hyv]; simp + · rw [h, sub_self, mul_zero, zero_mul, mul_zero, abs_zero] + · simp only [mul_sub, mul_one, Finset.sum_sub_distrib] + rw [hR1, hb] + -- le signe e et le coefficient c + obtain ⟨e, c, he, hc, hce⟩ := exists_sign_mul_add_eq hβ ha + refine ⟨e, he, ?_⟩ + -- l'identité de barycentre + have hsum : ∑ y ∈ SQ.map toRealProdEmb, + R y * (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) = e / 3 := by + rw [← hce, ← hb, Finset.mul_sum, ← Finset.sum_add_distrib] + refine Finset.sum_congr rfl fun y _ => ?_ + ring + have hzw : ∑ y ∈ SQ.map toRealProdEmb, R y • + (y.1 + (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v) = z + e • toReal w := by + simp only [smul_add, smul_smul, Finset.sum_add_distrib] + rw [← Finset.sum_smul, hsum, hvR, smul_smul] + have hkey : (e / 3) * (3 : ℝ) = e := div_mul_cancel₀ e (by norm_num) + rw [hkey, hz] + rw [← hzw] + -- chaque point de la combinaison est dans l'enveloppe du support de P + refine sum_smul_mem_convexHull _ R + (fun y => y.1 + (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v) hR0 hR1 ?_ + intro y hy + rcases hsnd y hy with h | h + · -- tranche basse : le coefficient vaut ±1, l'extrémité correspondante est dans le support + have hcoef : (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v + = (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1) • toReal v := by + simp only [h, zero_mul, sub_zero, one_mul, zero_add] + rw [hcoef] + by_cases hyv : y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + · rw [if_pos hyv, one_smul] + exact subset_convexHull ℝ _ hyv + · rw [if_neg hyv] + have hyv' : y.1 - toReal v ∈ + (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) := + ((hfalse y hy h).resolve_left hyv) + have hconv : y.1 + (-1 : ℝ) • toReal v = y.1 - toReal v := by + rw [neg_one_smul, sub_eq_add_neg] + rw [hconv] + exact subset_convexHull ℝ _ hyv' + · -- tranche haute : le coefficient vaut c, les deux extrémités sont dans le support + have hcoef : (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v = c • toReal v := by + simp only [h, one_mul, sub_self, zero_mul, add_zero] + rw [hcoef] + obtain ⟨hplus, hminus⟩ := htrue y hy h + exact add_smul_mem_convexHull hminus hplus hc + end Discrepancy.Komlos diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback_en.lean index 0d1cd1cb64..d49be71327 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback_en.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Pullback_en.lean @@ -45,16 +45,35 @@ step consumes : (`Convex.sum_mem` applied to `convex_convexHull`, l.83 in Dahia) : a finite convex combination of points of a hull stays in the hull. -**`pullback` remains deferred, and its blocker is now measured** : in Dahia it -is stated over `E →₀ ℝ` with `E` an `ℝ`-module, the hull being taken in -`convexHull ℝ (P.support : Set E)`. This lake's base is `Fin d → ℤ`, which is -**not** an `ℝ`-module — `convexHull ℝ` makes no sense there without a -coordinate-by-coordinate embedding into `Fin d → ℝ` (the "dimension -transport" of `FORMAL_STATUS.md`). The detailed state lives in -`FORMAL_STATUS.md`. +**Brick k2.4 (the full step)** — `pullback` delivered in the lake's +framework, on the k2.3 dimension transport that lifted the blocker measured +in k2.2 : + +- `toRealProd` + `toRealProd_injective` — the **product** embedding : the + integer grid × `Bool` height into the real grid × `ℝ` (height `false ↦ 0`, + `true ↦ 1` — that is where the lake's `Bool` height becomes the oracle's + real coordinate `(y, β)`) ; +- `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` — the **support + characterizations** of the split under `P ≥ 0`, read point by point (the + oracle gets them for free via `Finsupp.support` : + `mk_zero_mem_support_split` / `mk_one_mem_support_split` ; the lake's + explicit Finset framework requires them as exactness hypotheses on the + support `SQ` being passed) ; +- `pullback` — **the full step** : if `(z, β)` is in the hull of the + transported support of `split v P` with `v = 3·w` coordinate by coordinate + and `β ≥ 1/3`, a sign `e ∈ {±1}` brings `z + e • toReal w` back into the + hull of the transported support of `P`. Transposed from + `Komlos/Pullback.lean` l.55-92, the three ingredients delivered in + k2.1/k2.2 (`exists_sign_mul_add_eq`, `add_smul_mem_convexHull`, + `sum_smul_mem_convexHull`) and the k2.3 bridges (`toReal_mem_map_iff`) + being consumed by name. + +The detailed state lives in `FORMAL_STATUS.md`. -/ import Discrepancy.Basic_en +import Discrepancy.Komlos.Split_en +import Discrepancy.Komlos.Transport_en /-! # Algebra of the pullback step (Lemma 1.4, Karingula–Lovett) @@ -197,4 +216,297 @@ lemma sum_smul_mem_convexHull {E : Type*} [AddCommGroup E] [Module ℝ E] ∑ y ∈ T, R y • f y ∈ convexHull ℝ s := (convex_convexHull ℝ s).sum_mem hR0 hR1 hmem +/-! ### Brick k2.4 : the product embedding and the support characterizations + +The full `pullback` step requires two framework ingredients that k2.1-k2.3 +have not yet met : the **product** embedding (grid × height → real grid × +`ℝ`, where the `Bool` height becomes the oracle's `β` coordinate) and the +**support** characterizations of the split (which the oracle gets for free +via `Finsupp.support` and which the lake's explicit Finset framework must +state as hypotheses). -/ + +/-- **Product embedding.** The integer grid with its `Bool` height embeds +into the real grid × `ℝ` : the spatial component through `toReal` (the +dimension transport of brick k2.3), the height `false ↦ 0`, `true ↦ 1`. + +It is this embedding that turns the lake's height — a `Bool` — into the +oracle's real coordinate `(y, β)` : the hull of the oracle's `pullback` +conclusion lives in `E × ℝ`, and it is in `(Fin d → ℝ) × ℝ` that the lake +joins it. + +Injectivity is the ticket of the transported support's `Finset.map` : +without it, `SQ.map toRealProdEmb` could contract points and the exactness +hypothesis `hSQ` of the `pullback` theorem would lose information. The +spatial component is injective by `toReal_injective` (k2.3) ; the height +component separates `false` from `true` by `0 ≠ 1`. -/ +def toRealProd {d : ℕ} : ((Fin d → ℤ) × Bool) → ((Fin d → ℝ) × ℝ) := + fun y => (toReal y.1, if y.2 then (1 : ℝ) else 0) + +lemma toRealProd_injective {d : ℕ} : Function.Injective (toRealProd (d := d)) := by + rintro ⟨x₁, b₁⟩ ⟨x₂, b₂⟩ h + simp only [toRealProd, Prod.mk.injEq] at h + obtain ⟨hxe, hbe⟩ := h + cases b₁ <;> cases b₂ <;> simp_all [toReal_injective.eq_iff] + +/-- The `Finset.Embedding` version of `toRealProd`, for the `Finset.map` of +transported supports. -/ +def toRealProdEmb {d : ℕ} : ((Fin d → ℤ) × Bool) ↪ ((Fin d → ℝ) × ℝ) := + ⟨toRealProd, toRealProd_injective⟩ + +/-- **Height of a transported support point.** Every point of the image +`SQ.map toRealProdEmb` carries a height in `{0, 1}` — the finite translation +of `snd_eq_zero_or_one_of_mem_support_split` in the oracle. -/ +lemma mem_map_toRealProd_snd {d : ℕ} {y : (Fin d → ℝ) × ℝ} + {SQ : Finset ((Fin d → ℤ) × Bool)} (hy : y ∈ SQ.map toRealProdEmb) : + y.2 = 0 ∨ y.2 = 1 := by + rw [Finset.mem_map] at hy + obtain ⟨y', -, hye⟩ := hy + have h2 : (if y'.2 then (1 : ℝ) else 0) = y.2 := congrArg Prod.snd hye + cases b : y'.2 <;> rw [b] at h2 <;> simp_all + +/-- **Support characterization, low slice.** Under `P ≥ 0`, the `false` +slice of the split carries nonzero mass exactly when one of the two +translates `P (x ± v)` is nonzero. + +This is the point-by-point reading of the oracle's +`mk_zero_mem_support_split` (`(x, 0) ∈ (split v P).support ↔ x + v ∈ +P.support ∨ x - v ∈ P.support`) : the oracle's `Finsupp` framework gives it +through the support, the lake's explicit Finset framework states it on the +value. Under `P ≥ 0`, `½ · max a b ≠ 0` is equivalent to `a ≠ 0 ∨ b ≠ 0` : +it is positivity that carries through the `max`. -/ +lemma split_apply_zero_ne_iff {d : ℕ} {P : (Fin d → ℤ) → ℝ} (hP : ∀ x, 0 ≤ P x) + (v x : Fin d → ℤ) : + split v P (x, false) ≠ 0 ↔ P (x + v) ≠ 0 ∨ P (x - v) ≠ 0 := by + rw [split_apply_zero] + constructor + · intro h + by_contra hcon + obtain ⟨h1, h2⟩ := not_or.mp hcon + rw [not_not.mp h1, not_not.mp h2, max_self] at h + norm_num at h + · rintro (h | h) + · intro hcon + have hlt : (0 : ℝ) < P (x + v) := lt_of_le_of_ne (hP _) (Ne.symm h) + exact absurd hcon (ne_of_gt (mul_pos one_half_pos + (lt_of_lt_of_le hlt (le_max_left _ _)))) + · intro hcon + have hlt : (0 : ℝ) < P (x - v) := lt_of_le_of_ne (hP _) (Ne.symm h) + exact absurd hcon (ne_of_gt (mul_pos one_half_pos + (lt_of_lt_of_le hlt (le_max_right _ _)))) + +/-- **Support characterization, high slice.** Under `P ≥ 0`, the `true` +slice of the split carries nonzero mass exactly when both translates +`P (x ± v)` are nonzero — the `min` requires the conjunction, where the +`max` of the low slice requires the disjunction. + +Point-by-point reading of the oracle's `mk_one_mem_support_split` +(`(x, 1) ∈ (split v P).support ↔ x + v ∈ P.support ∧ x - v ∈ P.support`). -/ +lemma split_apply_one_ne_iff {d : ℕ} {P : (Fin d → ℤ) → ℝ} (hP : ∀ x, 0 ≤ P x) + (v x : Fin d → ℤ) : + split v P (x, true) ≠ 0 ↔ P (x + v) ≠ 0 ∧ P (x - v) ≠ 0 := by + rw [split_apply_one] + constructor + · intro hcon + constructor + · intro hzero + apply hcon + rw [hzero, min_eq_left (hP (x - v)), mul_zero] + · intro hzero + apply hcon + rw [hzero, min_eq_right (hP (x + v)), mul_zero] + · rintro ⟨h, h'⟩ + have hlt : (0 : ℝ) < P (x + v) := lt_of_le_of_ne (hP _) (Ne.symm h) + have hlt' : (0 : ℝ) < P (x - v) := lt_of_le_of_ne (hP _) (Ne.symm h') + exact ne_of_gt (mul_pos one_half_pos (lt_min hlt hlt')) + +/-! ### Brick k2.4 : the full step -/ + +/-- **The pullback step (Lemma 1.4).** If the distribution `P` on the +integer grid is nonnegative, with support contained in `SP`, and if +`(z, β)` belongs to the convex hull of the **transported** support of the +split `split v P` — transported by the product embedding `toRealProd` — +with `v = 3 · w` coordinate by coordinate and `β ≥ 1/3`, then a sign +`e ∈ {±1}` brings `z + e • toReal w` back into the convex hull of the +transported support of `P`. + +This is the transposition of Dahia's theorem `pullback` +(`Komlos/Pullback.lean`, l.55-92) to the lake's framework. Three framework +gaps are arbitrated : + +- **the point `z` lives on the `ℝ` side** : in the oracle, the induction + hypothesis produces an arbitrary point of `E × ℝ` in the hull ; here the + final consumer (Lemma 1.4) produces a barycenter on the real grid side, + hence `z : Fin d → ℝ` and the hypothesis on the hull **in the transported + image**, not in the integer grid ; +- **`hSQ` is a hypothesis, not a computation** : in the oracle the support + `(split v P).support` is computed (`mk_zero_mem_support_split`) ; the + lake's explicit Finset framework requires knowing the support `SQ` of the + split and its exactness (`∀ y ∈ SQ, split v P y ≠ 0`) — the price of the + absence of `Finsupp` ; +- **`hPsupp` relays the support of `P`** : likewise, `SP` must contain the + support of `P` for the endpoints of the segments to land there. + +The proof is the oracle's, decomposed over the ingredients delivered in +k2.1-k2.3 : `Finset.mem_convexHull'` decomposes the membership of `(z, β)` +into weights `R` ; `abs_sum_le_sum_abs` bounds the share of height-`0` +weights ; `exists_sign_mul_add_eq` (k2.1) produces the sign `e` and the +coefficient `c` ; every point of the combination is brought back into the +hull of the transported support of `P` by `add_smul_mem_convexHull` (k2.2, +high slices) or by the direct membership of an endpoint (low slices, via +k2.3's `toReal_mem_map_iff`) ; `sum_smul_mem_convexHull` (k2.2) closes. -/ +theorem pullback {d : ℕ} {P : (Fin d → ℤ) → ℝ} (hP : ∀ x, 0 ≤ P x) + {SP : Finset (Fin d → ℤ)} (hPsupp : ∀ x, P x ≠ 0 → x ∈ SP) + {v w : Fin d → ℤ} (hv : ∀ i, v i = 3 * w i) + {SQ : Finset ((Fin d → ℤ) × Bool)} (hSQ : ∀ y ∈ SQ, split v P y ≠ 0) + {β : ℝ} (hβ : 3⁻¹ ≤ β) {z : Fin d → ℝ} + (hmem : (z, β) ∈ convexHull ℝ + (↑(SQ.map toRealProdEmb) : Set ((Fin d → ℝ) × ℝ))) : + ∃ e : ℝ, (e = 1 ∨ e = -1) ∧ + z + e • toReal w ∈ convexHull ℝ + (↑(SP.map ⟨⇑toReal, toReal_injective⟩) : Set (Fin d → ℝ)) := by + classical + -- the transport direction : toReal v = 3 • toReal w + have hvR : toReal v = (3 : ℝ) • toReal w := by + funext i + simp only [toReal_apply, hv i, Int.cast_mul, Pi.smul_apply, smul_eq_mul] + push_cast + ring + -- decomposing the membership into weights + obtain ⟨R, hR0, hR1, hRc⟩ := Finset.mem_convexHull'.1 hmem + have hz : ∑ y ∈ SQ.map toRealProdEmb, R y • y.1 = z := by + have h := congrArg Prod.fst hRc + rw [Prod.fst_sum] at h + exact h + have hb : ∑ y ∈ SQ.map toRealProdEmb, R y * y.2 = β := by + have h := congrArg Prod.snd hRc + rw [Prod.snd_sum] at h + exact h + -- the heights of the transported support are in {0, 1} + have hsnd : ∀ y ∈ SQ.map toRealProdEmb, y.2 = 0 ∨ y.2 = 1 := + fun y hy => mem_map_toRealProd_snd hy + -- every point of the transported support comes from a point of SQ + have hpre : ∀ y ∈ SQ.map toRealProdEmb, ∃ y' ∈ SQ, toRealProd y' = y := by + intro y hy + rw [Finset.mem_map] at hy + obtain ⟨y', hy', hye⟩ := hy + exact ⟨y', hy', hye⟩ + -- the endpoints of low slices land in the support of P + have hfalse : ∀ y ∈ SQ.map toRealProdEmb, y.2 = 0 → + y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) ∨ + y.1 - toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) := by + intro y hy y0 + obtain ⟨y', hy', hye⟩ := hpre y hy + obtain ⟨x', b'⟩ := y' + cases b' with + | false => + have hx := (split_apply_zero_ne_iff hP v x').1 (hSQ (x', false) hy') + have hy1 : toReal x' = y.1 := congrArg Prod.fst hye + rcases hx with h | h + · left + have hmem' := (toReal_mem_map_iff (x' + v) SP).2 (hPsupp _ h) + rwa [map_add, hy1] at hmem' + · right + have hmem' := (toReal_mem_map_iff (x' - v) SP).2 (hPsupp _ h) + rwa [map_sub, hy1] at hmem' + | true => + exfalso + have h1 : y.2 = 1 := by + have := congrArg Prod.snd hye + simpa [toRealProd] using this.symm + rw [y0] at h1 + norm_num at h1 + -- the endpoints of high slices land in the support of P + have htrue : ∀ y ∈ SQ.map toRealProdEmb, y.2 = 1 → + y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) ∧ + y.1 - toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) := by + intro y hy y1 + obtain ⟨y', hy', hye⟩ := hpre y hy + obtain ⟨x', b'⟩ := y' + cases b' with + | true => + obtain ⟨h, h'⟩ := (split_apply_one_ne_iff hP v x').1 (hSQ (x', true) hy') + have hy1 : toReal x' = y.1 := congrArg Prod.fst hye + constructor + · have hmem' := (toReal_mem_map_iff (x' + v) SP).2 (hPsupp _ h) + rwa [map_add, hy1] at hmem' + · have hmem' := (toReal_mem_map_iff (x' - v) SP).2 (hPsupp _ h') + rwa [map_sub, hy1] at hmem' + | false => + exfalso + have h0 : y.2 = 0 := by + have := congrArg Prod.snd hye + simpa [toRealProd] using this.symm + rw [y1] at h0 + norm_num at h0 + -- the bound on the share of height-0 weights : |σ y| = 1 in both branches + have ha : |∑ y ∈ SQ.map toRealProdEmb, R y * ((1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1))| ≤ 1 - β := by + refine (Finset.abs_sum_le_sum_abs _ _).trans + ((Finset.sum_le_sum (g := fun y => R y * (1 - y.2)) ?_).trans_eq ?_) + · intro y hy + rcases hsnd y hy with h | h + · rw [h, sub_zero, mul_one, abs_mul, abs_of_nonneg (hR0 y hy)] + by_cases hyv : y.1 + toReal v ∈ + (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + · rw [if_pos hyv]; simp + · rw [if_neg hyv]; simp + · rw [h, sub_self, mul_zero, zero_mul, mul_zero, abs_zero] + · simp only [mul_sub, mul_one, Finset.sum_sub_distrib] + rw [hR1, hb] + -- the sign e and the coefficient c + obtain ⟨e, c, he, hc, hce⟩ := exists_sign_mul_add_eq hβ ha + refine ⟨e, he, ?_⟩ + -- the barycentric identity + have hsum : ∑ y ∈ SQ.map toRealProdEmb, + R y * (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) = e / 3 := by + rw [← hce, ← hb, Finset.mul_sum, ← Finset.sum_add_distrib] + refine Finset.sum_congr rfl fun y _ => ?_ + ring + have hzw : ∑ y ∈ SQ.map toRealProdEmb, R y • + (y.1 + (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v) = z + e • toReal w := by + simp only [smul_add, smul_smul, Finset.sum_add_distrib] + rw [← Finset.sum_smul, hsum, hvR, smul_smul] + have hkey : (e / 3) * (3 : ℝ) = e := div_mul_cancel₀ e (by norm_num) + rw [hkey, hz] + rw [← hzw] + -- every point of the combination is in the hull of P's support + refine sum_smul_mem_convexHull _ R + (fun y => y.1 + (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v) hR0 hR1 ?_ + intro y hy + rcases hsnd y hy with h | h + · -- low slice : the coefficient is ±1, the corresponding endpoint is in the support + have hcoef : (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v + = (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1) • toReal v := by + simp only [h, zero_mul, sub_zero, one_mul, zero_add] + rw [hcoef] + by_cases hyv : y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + · rw [if_pos hyv, one_smul] + exact subset_convexHull ℝ _ hyv + · rw [if_neg hyv] + have hyv' : y.1 - toReal v ∈ + (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) := + ((hfalse y hy h).resolve_left hyv) + have hconv : y.1 + (-1 : ℝ) • toReal v = y.1 - toReal v := by + rw [neg_one_smul, sub_eq_add_neg] + rw [hconv] + exact subset_convexHull ℝ _ hyv' + · -- high slice : the coefficient is c, both endpoints are in the support + have hcoef : (y.2 * c + (1 - y.2) * + (if y.1 + toReal v ∈ (SP.map ⟨⇑toReal, toReal_injective⟩ : Finset (Fin d → ℝ)) + then (1 : ℝ) else -1)) • toReal v = c • toReal v := by + simp only [h, one_mul, sub_self, zero_mul, add_zero] + rw [hcoef] + obtain ⟨hplus, hminus⟩ := htrue y hy h + exact add_smul_mem_convexHull hminus hplus hc + end Discrepancy.Komlos_en diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md index 55e8697952..765d0d3310 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md @@ -64,6 +64,7 @@ boutes `k1..k5` ci-dessous ; issue de suivi : #17845. | **k2.1** | `Discrepancy.Komlos.exists_sign_mul_add_eq` : **l'algèbre du pas de pullback, sans convexité** — le pas d'induction du Lemme 1.4 ramène dans `conv(supp P)` le point obtenu dans l'espace produit (« pullback ») ; chez Dahia ce pas se décompose en **trois** lemmes, dont **deux seulement** exigent `convexHull` (absent de ce lake avant ce module). Cette brique livre les **trois ingrédients qui n'en dépendent pas**, pour que la surface de convexité s'ouvre ensuite sur une base déjà vérifiée : `exists_sign_mul_add_eq` (**la clé arithmétique** — pour `β ≥ 1/3` et `|a| ≤ 1 − β`, il existe `e ∈ {±1}` et `|c| ≤ 1` avec `c·β + a = e/3` ; c'est ce qui produit le **signe** de la conclusion de k2 ; transposé **verbatim** de `Komlos/Pullback.lean:31`, pur `ℝ`, aucune base requise), `segment_repr` (**l'identité de segment** — `((1−c)/2) • (x − v) + ((1+c)/2) • (x + v) = x + c • v`, l'algèbre que `add_smul_mem_convexHull` enveloppe chez Dahia) et `sum_mul_add_split` (**la linéarité pondérée** — `Σ R y·(h y·c + g y) = c·(Σ R y·h y) + Σ R y·g y`, la seule manipulation de sommes du pullback qui ne soit pas de la convexité). **Erreur corrigée au build, consignée dans la docstring** : le premier jet de `segment_repr` échangeait les deux poids et prouvait `x − c • v` — `module` a rendu `⊢ -c = c`, non prouvable ; l'énoncé est faux dans ce sens, et les deux poids sont désormais documentés comme le point facile à refaire. Module FR + jumeau `_en`. 0 `sorry`. | brique k2 (algèbre du pullback) | **PROUVÉ** (k2.1, 10-04, `lake build` local EXIT=0 sur les deux jumeaux, 0 `warning`, `distinct_code_sorry = 0` — voir PR) | ce PR (stack sur #19068) | | **k2.2** | `Discrepancy.Komlos.add_smul_mem_convexHull` : **la surface de convexité s'ouvre** — `convexHull` entre dans ce lake (0 occurrence avant ce commit) par les deux lemmes génériques que le pas de `pullback` consomme. `add_smul_mem_convexHull` (**le point d'un segment dans une enveloppe** — pour `|c| ≤ 1` et `x ± v ∈ s`, `x + c • v ∈ convexHull ℝ s` ; transposé **verbatim** de `Komlos/Pullback.lean:43-50`, l'énoncé ne dépend que de la structure de `ℝ`-module de `E` ; preuve : `Convex.add_smul_sub_mem` (Mathlib `Analysis.Convex.Basic:492`) avec `t = (1+c)/2`, bornes par `linarith`, identité résiduelle par `module` — l'argument même de `segment_repr` k2.1) et `sum_smul_mem_convexHull` (**la clôture du pas** — `(convex_convexHull ℝ _).sum_mem` l.83 chez Dahia, extrait en forme `Finset` du lake : une combinaison convexe finie de points d'une enveloppe reste dans l'enveloppe, via `Convex.sum_mem` `Analysis.Convex.Combination:214`). La décomposition inverse (lire une appartenance comme des poids) existe déjà au pin : `Finset.centerMass_mem_convexHull` (`Analysis.Convex.Combination:253`). **Bloqueur de `pullback`, mesuré ce cycle** : l'oracle l'énonce sur `E →₀ ℝ` avec `E` un `ℝ`-module (enveloppe dans `convexHull ℝ (P.support : Set E)`) ; la base de ce lake `Fin d → ℤ` **n'est pas** un `ℝ`-module — `convexHull ℝ` y est inexprimable sans plongement coordonnée-par-coordonnée dans `Fin d → ℝ` (le transport de dimension, ligne k2 ci-dessous). Module FR + jumeau `_en`. 0 `sorry`. | brique k2 (surface de convexité) | **PROUVÉ** (k2.2, 10-04, `lake build` local EXIT=0 — ciblé deux jumeaux **puis full-lib 8748 jobs**, `distinct_code_sorry = 0`, jumeaux i18n `13/13 byte-identical` — voir PR) | ce PR (stack sur #19070) | | **k2.3** | `Discrepancy.Komlos.toReal` : **le transport de dimension** — lève le bloqueur mesuré en k2.2 (`Fin d → ℤ` n'est pas un `ℝ`-module, `convexHull ℝ` y est inexprimable) en plongeant la grille entière dans `Fin d → ℝ`. Transposé de `Komlos/Transport.lean` (l.27-67). Briques closes : `toReal` + `toReal_injective` (plongement `→+` coordonnée-par-coordonnée, l'instance du lake — le `g ↦ g / N` de l'oracle étant une homothétie de plus), `push e P` (la poussée le long d'un morphisme additif **quelconque** entre les deux grilles sur `Function.extend` — l'organe Mathlib du prolongement le long d'une injection, équivalent du `Finsupp.embDomain` de l'oracle ; l'injectivité n'est requise que par les **lemmes**, pas par la définition), `push_apply` / `push_eq_zero` (les deux identités de calcul, l.32 et hors-image), `sum_push` (ré-indexation `Finset.sum_map`, l.35-36), `push_mass` (conservation de la masse, `mass_push` l.41-42), `coordMomentReal` + `coordMomentReal_push` (le barycentre transporté, forme générique — `mean_push` l.66-67) et **les deux ponts que k2.4 lit sur le support transporté** : `coordMoment_toReal` (le moment coordonné de la poussée par `toReal` **est** le `coordMoment` k2.0 — le pont de barycentre) et `toReal_mem_map_iff` / `toReal_mem_coe_iff` (le pont d'appartenance, formes `Finset` et `Set` — ce que `convexHull ℝ ↑(S.map …)` consommera). **Deux reportés, avec raison mesurée** : `shiftDist_push` (l.63-64 — chez l'oracle `shiftDist` vit sur le support Finsupp **canonique** ; la convention k1.1 passe le support `Finset` explicitement et l'énoncé transporté exige une ré-indexation de `S ∪ (S + u)` côté cible, une union dont la somme n'est pas la somme des sommes ; aucun consommateur k2.4 — la conclusion de convexité ne lit que le support et le barycentre) et `tvDist_push` / `IsDist.push` (l.44-55 — le vocabulaire `tvDist`/`IsDist` n'existe pas dans ce lake, décision de cadre k1.1 ; les restater serait du nouveau vocabulaire, pas du transport). Module FR + jumeau `_en`. 0 `sorry`. | brique k2 (transport de dimension) | **PROUVÉ** (k2.3, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning**, puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19078) | +| **k2.4** | `Discrepancy.Komlos.pullback` : **le pas complet du pullback** — le théorème que k2.1 (algèbre), k2.2 (convexité) et k2.3 (transport) ont préparé, porté de `Komlos/Pullback.lean` l.55-92. Briques closes : `toRealProd` + `toRealProd_injective` + `toRealProdEmb` (l'embedding **produit** `(Fin d → ℤ) × Bool → (Fin d → ℝ) × ℝ` — la hauteur `Bool` du lake devient la coordonnée réelle `β` de l'oracle, `false ↦ 0` / `true ↦ 1` ; injectivité par `toReal_injective.eq_iff` + séparation `0 ≠ 1` — le ticket du `Finset.map` du support transporté), `mem_map_toRealProd_snd` (hauteurs de l'image dans `{0, 1}` — le pendant fini de `snd_eq_zero_or_one_of_mem_support_split`), `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` (les **caractérisations de support** de la scission sous `P ≥ 0`, lecture point-par-point des `mk_zero/one_mem_support_split` de l'oracle — le `max` exige la disjonction, le `min` la conjonction) et **le théorème `pullback`** : `(z, β)` dans l'enveloppe du support transporté de `split v P`, `v = 3·w` coordonnée par coordonnée, `β ≥ 1/3` ⇒ un signe `e ∈ {±1}` ramène `z + e • toReal w` dans l'enveloppe du support transporté de `P`. **Trois écarts de cadre arbitrés** : (a) `z` vit côté `ℝ` (le consommateur final Lemme 1.4 produit un barycentre côté grille réelle, d'où l'hypothèse dans l'image transportée) ; (b) `hSQ` exactitude du support de la scission en **hypothèse** (l'oracle la calcule via `Finsupp.support` ; le cadre `Finset` explicite la exige) ; (c) `hPsupp` relaie le support de `P`. Preuve décomposée sur les ingrédients k2.1-k2.3 : `Finset.mem_convexHull'` (`Analysis.Convex/Combination.lean:415` — vérifié au pin, forme `∃ w` exacte) décompose `(z, β)` en poids ; `Finset.abs_sum_le_sum_abs` (`Algebra/Order/BigOperators/Group/Finset.lean:315` — **dans le namespace `Finset`** au pin, l'identifiant nu n'existe pas) borne la part des poids hauteur 0 ; `exists_sign_mul_add_eq` (k2.1) produit `e` et `c` ; chaque point revient dans l'enveloppe par `add_smul_mem_convexHull` (k2.2, tranches hautes) ou l'appartenance directe d'une extrémité via `toReal_mem_map_iff` (k2.3, tranches basses) ; `sum_smul_mem_convexHull` (k2.2) referme. `sum_smul_inl` (`split.lean:50`) **reporté** : le port n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum` ; aucun consommateur mesuré). Module FR + jumeau `_en`, étendus (pas de nouveau fichier). 0 `sorry`. | brique k2 (pas complet) | **PROUVÉ** (k2.4, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (~30 s chacun), puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19081) | | **k3.1** | `Discrepancy.Komlos.tent` (`Komlos/Tent.lean` + jumeau `_en`) : **la tente discrète, port complet du module de l'oracle** — les 13 preuves reportées en c.885 (delivery #17918) sont closes, chacune adaptée du `grind` v4.34 vers le pin v4.33.0 / `db584cd6` (détail par preuve dans la note de fin de fichier). Sommes closes : `sum_tent` (Σ tent = M²), `sum_tent_sq` (3·Σ tent² = M(2M²+1)) ; Lipschitz `abs_tent_sub_le` (1-Lipschitz) ; pas `step`/`abs_step_le_one`/`step_eq_zero`/`sum_step_sq_le` (≤ 2M) ; télescopage `tent_sub_tent_eq_sum_step` ; **résultat porteur `sum_tent_sub_sq_le`** (Σ (tent M j − tent M (j−m))² ≤ 2·M·m²) — la borne `L²` **discrète** du Lemme 4.1. Adaptations mesurées : `abs_add`/`neg_le_abs_self` **absents au pin** (sondés — la triangulaire inverse passe par `abs_max_sub_max_le_abs` + `abs_abs_sub_abs_le_abs_sub`) ; `omega` ne splitte pas `\|j\|` sur ℤ (atome opaque) → composites `le_abs_self`+`abs_neg` ; l'énoncé `support_tent_subset` force `Set.Icc` (le `Icc` nu sous `open Finset` s'élabore en coercion Finset) ; bornes en cast entier global `((M+1:ℕ):ℤ)` ; `sum_range_sub'` absent → induction manuelle ; `rw` avec `f := id` échoue → normalisation `simp only [id]`. **Réaudit k3 contre l'oracle** : la voie Dahia est **totalement discrète** — `Grid.lean` consomme `sum_tent_sq` + `sum_tent_sub_sq_le` pour construire le poids normalisé `gridF N` (distance `L²` de translation ≤ \|m\|/(N·√12)) ; le « FTC sur segments » du papier est remplacé par la discrétisation sur grille (`intervalIntegral` absent de l'oracle) — la ligne de planification k3 est réécrite en conséquence. 0 `sorry`. | brique k3 (tente + L² discret) | **PROUVÉ** (k3.1, 10-06, `lake build` local EXIT=0 sur les deux jumeaux — 8708 jobs, `distinct_code_sorry = 0`, jumeaux i18n `1/1 byte-identical` — voir PR) | ce PR (branche `feature/komlos-k3-tent`) | | **k3.2** | `Discrepancy.Komlos.gridF` (`Komlos/Grid.lean` + jumeau `_en`) : **le poids normalisé unidimensionnel et sa borne `L²` de translation — port complet du `Komlos/Grid.lean` de l'oracle** (la voie k3 de l'oracle est désormais complète). Briques closes : `gridM` (demi-largeur `6·N`), `gridZ` (constante de normalisation = `∑ tent²`), `gridF` (`tent (gridM N) j / √(gridZ N)`), `cast_gridM`, `gridZ_eq` (**`gridZ N = 144·N³ + 2·N`**), `gridZ_pos`, `gridF_nonneg`, `support_gridF_subset`, `finsum_gridF_sq` (**masse totale `1`**), `sum_gridF_sub_sq`/`sum_gridF_sq` (formes `Finset` consommables), **résultat porteur `sum_gridF_sub_sq_le`** : distance `L²` au carré entre `gridF N` et son translaté par `m` ≤ `m²/(12·N²)` — l'analogue discret du Lemme 4.1, entrée directe de la discrétisation k4 (Lemme 1.5). Adaptations mesurées : le `positivity` de l'oracle sur `gridZ_pos` échoue au pin (stricte positivité dépend de `hN : 0 < N`) → cast + `linarith` ; le `linarith` final de `gridZ_eq` échoue sur le produit non-linéaire → normalisation `ring` explicite avant `linarith` ; `support_tent_subset` de ce lake étant typé `Set.Icc` (l'oracle : `Finset.Icc`), `support_gridF_subset` est prouvé directement (`Finset.mem_coe` + composite `le_abs_self`) ; l'API `finsum` (**existe au pin**, à la racine — sondée) permet le port quasi verbatim des énoncés de masse. **Correctif i18n embarqué** : `Tent_en.lean` passait en `namespace Discrepancy.Komlos` (seul `_en` du lake non suffixé — défaut #17918) ; il repasse en `Discrepancy.Komlos_en`, condition de l'import propre `Grid_en → Tent_en`. 0 `sorry`. | brique k3 (poids normalisé + L²) | **PROUVÉ** (k3.2, 10-06, `lake build` local EXIT=0 sur les trois cibles — 8710 jobs : `Grid`, `Grid_en`, `Tent_en` recompilé ; `distinct_code_sorry = 0`, jumeaux i18n `2/2 byte-identical` — voir PR) | ce PR (stack sur #19563) | | P3 | Banaszczyk 1998 / formes fortes des papiers 2025 **et 2026** | aspiration | **NON ENGAGÉ** — exige SDP + dualité, indépendance spectrale affine, brownien discret guidé, concentration matricielle : **aucun de cet étage n'existe dans Mathlib** (vérifié 2026-08-24). **Réaudité 2026-09-13** contre le Mathlib pinné (`520045ab`, v4.32.1) : le contournement proposé par arXiv:2609.11189 ne supprime pas l'obstruction, il la **déplace** — sa route exige la *variation totale directionnelle* d'une densité sur convexe ouvert et la *transformée de Banaszczyk* préservée sous translation, deux notions **absentes du même Mathlib** (`Banaszczyk` : 0 occurrence ; `totalVariation` n'existe que pour les mesures signées ; la théorie BV de Mathlib concerne la dérivabilité a.e. des fonctions de `ℝ`). Ce que ce papier rapproche, ce sont les *socles* : gaussiennes (`Probability/Distributions/Gaussian/*`) et `ConvexBody` (`Analysis/Convex/Body.lean`) sont présents ; le **pont** manque. Documenté, jamais promis. **Réaudité 2026-09-25** : la voie **élémentaire** de Karingula–Lovett (arXiv:2609.20979, constante `36`) **supprime** cet étage au lieu de le déplacer — sa mécanique est discrète (distance de décalage `Δ`, opérateur de scission `T_v`, induction sur `n` et `d`) à une seule exception, l'estimation de la densité-tente, qui se fait par FTC sur segments + Cauchy–Schwarz `L²` et **non** par de la théorie BV. Balayage des prérequis sur le checkout Mathlib local (`v4.32.0`) : famille **`norm_image_sub_le` présente** (dont `Analysis/Calculus/IntervalIntegral/DistLEIntegral.lean`), `totalVariation` toujours cantonné aux mesures vectorielles (`VectorMeasure/Decomposition/*`) — mais le papier n'en a plus besoin. Réserve de portée : ce balayage porte sur un checkout **voisin** (`v4.32.0`), pas sur le pin du lake (`520045ab`) — à re-vérifier avant la première boute `.lean`. Une formalisation Lean 4 tierce de cette preuve existe déjà (mise à jour du 2026-09-25 ci-dessous). | — | @@ -163,7 +164,7 @@ branche, jamais `main`. Issue de suivi : #17845. | **k1.7** | Correctif d'hypothèse **avant** k2 : l'invariance du support des briques k1 est insatisfiable aux décalages non nuls (mesuré, `eq_zero_of_image_add_eq_self`) → formes consommables sous **contention** `SupportContained` | fini | k1 | | **k2.0** | **Moments de la scission** (`mean_split`) — décomposition par composante du `mean_split` de Dahia (base `Fin d → ℤ` sans structure de `ℝ`-module : `coordMoment`/`prodMoment`, `heightMoment`), moment de hauteur = `splitBit` (`heightMoment_split`), **conservation du barycentre** par la scission (`prodMoment_split`) — l'item reporté par k1.6 | fini | k1, k1.6 | | **k2.0 — correctif de support** | **Formes consommables des moments** — `prodMoment_split_of_support` + `mean_split_of_support` sous `SupportContained S P {0, v, -v}` : k1.7 appliqué à k2.0 (`heightMoment_split` réutilisé inchangé), + contrôle positif `exists_supportContained_nonzero_shift` (`d = 1`, `v = 1`, `P` Dirac, `S = {-1, 0, 1}` via `supportContained_biUnion`) | fini | k1.7, k2.0 | -| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé** (Fin d → ℤ n’est pas un ℝ-module ; l’oracle énonce pullback sur E →₀ ℝ — le transport plonge la grille dans Fin d → ℝ où convexHull ℝ parle). **Reste à ce lake, mesuré** : `pullback` (`Pullback.lean:55` — énoncé désormais statuable sur `convexHull ℝ ↑(S.map toReal …)`), le pendant fini de `mean_mem_convexHull` (`distribution.lean:105`, cadre `Finsupp` à transposer en `Finset`) et `sum_smul_inl` (`split.lean:50`). | fini + induction | k1, k1.7, k2.0–k2.3 | +| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé** (Fin d → ℤ n’est pas un ℝ-module ; l’oracle énonce pullback sur E →₀ ℝ — le transport plonge la grille dans Fin d → ℝ où convexHull ℝ parle). **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Reste à ce lake, mesuré** : le pendant fini de `mean_mem_convexHull` (`distribution.lean:105`, cadre `Finsupp` à transposer en `Finset` — l'hypothèse d'induction du pas complet en aura besoin pour produire le `(z, β)` de `hmem`) et, pour l'assemblage final, la lecture k1.7 du pas (`SignedSums.lean` l.37-58 : l'itération `induction n with` qui consomme `mean_split` + `pullback`). `sum_smul_inl` (`split.lean:50`) reste sans consommateur mesuré à ce stade — le port k2.4 n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum`, pas par la construction `incl`). | fini + induction | k1, k1.7, k2.0–k2.4 | | **k3** | Lemme 4.1 — densité-tente. **Réauditée contre l'oracle au pin (k3.1)** : la voie Dahia est **totalement discrète** — le « FTC sur segments » du papier est remplacé par la discrétisation sur grille, `intervalIntegral` **absent de l'oracle** — la dépendance `norm_image_sub_le` est sans objet. **LIVRÉE EN INTÉGRALITÉ** : k3.1 (`Tent.lean` complet, lignes k3.1/k3.2) puis k3.2 (`Grid.lean` complet — `gridF` normalisé, `gridZ_eq : gridZ N = 144·N³ + 2·N`, masse `1`, **`sum_gridF_sub_sq_le` : distance `L²` de translation ≤ m²/(12·N²)**, l'analogue discret du Lemme 4.1). **Reste** : k4 (Lemme 1.5, discrétisation). | fini (oracle discret, complet) | k3.1, k3.2 | | **k4** | Lemme 1.5 — discrétisation sur la grille, cas rationnel | fini | k3 | | **k5** | Assemblage Thm 1.2 sur `ℚ` (témoin `36`) + corollaires (`KomlosBansalJiangWeak`, Beck–Fiala régulier `72√k`) + notebooks `Search-09c`/`Search-09e` (ligne « course aux bornes » du 22/09/2026) | assemblage | k2, k4 | From 4ef12d0da194d4d0964dcc5ad519e12a64fd25ab Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 4 Oct 2026 11:18:32 +0200 Subject: [PATCH 2/8] feat(lean,#17845): brique k2.5 -- cas de base mean_mem_convexHull (Distribution + jumeau _en) Port de Komlos/Distribution.lean l.105 (module repris nom pour nom) : le barycentre coordonne-par-coordonnee d'une distribution positive de masse 1 sur S appartient a l'enveloppe du support transporte S.map toReal. Le one-liner oracle tient sur l'organe push de k2.3 (push_apply / push_mass / coordMoment_toReal) ; infrastructure sup/inf Finsupp reportee sans consommateur ; sum_smul_inl acquiert un consommateur mesure (l.53, k2.6). Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit 0c59dab3cd4064554f1ea2eae8ec6eb090ae6fcc) --- .../Discrepancy/Komlos/Distribution.lean | 105 ++++++++++++++++++ .../Discrepancy/Komlos/Distribution_en.lean | 105 ++++++++++++++++++ .../Search/discrepancy_lean/FORMAL_STATUS.md | 3 +- 3 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution.lean create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution_en.lean diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution.lean new file mode 100644 index 0000000000..3fa47c2c83 --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapté à `discrepancy_lean` (issue #17845, Karingula–Lovett distillation +arXiv:2609.20979) : toolchain v4.33.0, Mathlib `db584cd6`, convention i18n #4980. + +Le source Dahia original vit dans le dépôt `gdahia/Komlos` (module +`Komlos/Distribution.lean`, toolchain v4.34.0, cadre `Finsupp` sur `E →₀ ℝ`). +L'adaptation reprend le module **nom pour nom**. + +**Portée de ce commit** (brique k2.5, `lake build SUCCESS` requis, 0 `sorry`) : + +Le module oracle porte toute une infrastructure `Finsupp` — `mass`, `mean`, +`IsDist`, additivités (`mass_add`, `mass_smul`, `mean_smul`), monotonies +(`mass_nonneg`, `mass_mono`), comptes de support sup/inf et les identités +`mass_sup_add_mass_inf` / `mean_sup_add_mean_inf` — dont **seule la +conclusion** a un consommateur mesuré dans notre chaîne : + +`mean_mem_convexHull` (l.105) est le **cas de base `n = 0`** de l'assemblage +k1.7 (`SignedSums.lean` l.42 : `simpa using mean_mem_convexHull hP le_rfl`). +Cette brique livre ce pendant seul : le barycentre d'une distribution +positive de masse 1 sur son support `S` appartient à l'enveloppe convexe du +support **transporté** (k2.3 : `S.map ⟨toReal, toReal_injective⟩`). + +**Chez l'oracle, la preuve est un one-liner** : les poids que +`Finset.mem_convexHull'` demande sont le `Finsupp` lui-même, nul hors +support **par construction** (`Finsupp` = fonction nulle hors d'un support +fini). C'est précisément le travail que le cadre `Finset` explicite du lake +redemande — et c'est l'organe `push` de k2.3 qui le fournit : `push toReal P` +est la distribution poussée sur la grille réelle, relisant `P` sur l'image +(`push_apply`) et nulle hors image (`push_eq_zero`). La preuve redevient le +one-liner oracle, ses trois composantes se lisant sur les organes k2.3 : +`push_apply` (positivité des poids transportés), `push_mass` (masse, le +`mass_push` de l'oracle), `coordMoment_toReal` (le point produit, le +`mean_push` de l'oracle — le barycentre affirmé dans l'enveloppe est +exactement celui que les moments coordonnés k2.0 calculent). + +**Écarts de cadre arbitrés** (même famille qu'en k2.4) : + +1. **le `mean` se lit coordonnée par coordonnée** — la base `Fin d → ℤ` + n'est pas un `ℝ`-module (bloqueur mesuré en k2.2) ; le point est + `fun i => coordMoment P S i` (k2.0), qui vit dans `Fin d → ℝ` où + `convexHull ℝ` s'exprime (k2.2/k2.3) ; +2. **`IsDist` devient deux hypothèses** (`hP` : positivité ponctuelle, + `hmass` : masse 1 sur `S`) — la structure `Finsupp` portait ces faits par + construction ; le lake les prend en hypothèse, comme `hSQ`/`hPsupp` en + k2.4 ; +3. **le support de l'énoncé est `S` lui-même** — l'oracle conclut sur un + `s ⊇ support` arbitraire ; ici le lake conclut sur le support transporté + exact `S.map ⟨toReal, _⟩`, la même forme que la conclusion de `pullback` + (k2.4). + +**Reportés avec consommateur mesuré** : + +- l'infrastructure sup/inf du module oracle (`mass_sup_add_mass_inf`, + `mean_sup_add_mean_inf`, `support_inf_subset`, `support_sup_subset`) n'a + pas de consommateur dans notre cadre — la préservation de la masse à la + scission est déjà `split_mass` (k1.2), que l'assemblage consommera en + hypothèse chaînée ; +- `sum_smul_inl` (reporté en k2.4 « sans consommateur mesuré ») **acquiert + un consommateur mesuré** par la lecture k1.7 du pas (`SignedSums.lean` + l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) + — il sera livré avec l'assemblage k2.6, où sa forme exacte se fixe. +-/ + +import Discrepancy.Basic +import Discrepancy.Komlos.MeanSplit +import Discrepancy.Komlos.Transport + +namespace Discrepancy.Komlos + +/-- **`mean_mem_convexHull`** (forme lake de l.105 de l'oracle) : le +barycentre — lu coordonnée par coordonnée, `fun i => coordMoment P S i` +(k2.0) — d'une distribution positive de masse 1 sur son support `S` +appartient à l'enveloppe convexe du support **transporté** sur la grille +réelle. C'est le cas de base `n = 0` de l'assemblage du Lemme 1.4 (k1.7, +`SignedSums.lean` l.42). + +La preuve est celle de l'oracle — `Finset.mem_convexHull'` avec la +distribution elle-même comme poids — **dès lors** que le poids demandé sur +la grille réelle existe : c'est `push toReal P` (k2.3, l'organe +`Finsupp.embDomain` du lake), nul hors image par construction. Les trois +composantes se lisent sur les organes k2.3 : `push_apply` (positivité), +`push_mass` (masse), `coordMoment_toReal` (le point). -/ +theorem mean_mem_convexHull {d : ℕ} {P : (Fin d → ℤ) → ℝ} + {S : Finset (Fin d → ℤ)} + (hP : ∀ x, 0 ≤ P x) (hmass : ∑ x ∈ S, P x = 1) : + (fun i => coordMoment P S i) ∈ convexHull ℝ + ↑(S.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ))) := by + refine Finset.mem_convexHull'.2 ⟨push toReal P, ?_, ?_, ?_⟩ + · intro y hy + obtain ⟨x, -, hxy⟩ := Finset.mem_map.1 hy + have hval : push toReal P y = P x := by + rw [← hxy] + exact push_apply toReal toReal_injective P x + rw [hval] + exact hP x + · rw [push_mass toReal toReal_injective P S] + exact hmass + · funext i + rw [← coordMoment_toReal P S i] + simp only [Finset.sum_apply, coordMomentReal, Pi.smul_apply, smul_eq_mul] + +end Discrepancy.Komlos diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution_en.lean new file mode 100644 index 0000000000..ad5e32f807 --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Distribution_en.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapted for `discrepancy_lean` (issue #17845, Karingula–Lovett distillation +arXiv:2609.20979): toolchain v4.33.0, Mathlib `db584cd6`, i18n convention #4980. + +The original Dahia source lives in the `gdahia/Komlos` repository (module +`Komlos/Distribution.lean`, toolchain v4.34.0, `Finsupp` framework over +`E →₀ ℝ`). The adaptation carries the module over **name for name**. + +**Scope of this commit** (brick k2.5, `lake build SUCCESS` required, 0 `sorry`): + +The oracle module carries a whole `Finsupp` infrastructure — `mass`, `mean`, +`IsDist`, additivity lemmas (`mass_add`, `mass_smul`, `mean_smul`), +monotonicity (`mass_nonneg`, `mass_mono`), sup/inf support accounts and the +identities `mass_sup_add_mass_inf` / `mean_sup_add_mean_inf` — of which +**only the conclusion** has a measured consumer in our chain: + +`mean_mem_convexHull` (l.105) is the **base case `n = 0`** of the k1.7 +assembly (`SignedSums.lean` l.42: `simpa using mean_mem_convexHull hP le_rfl`). +This brick delivers this pendant alone: the barycenter of a positive +distribution of mass 1 over its support `S` belongs to the convex hull of +the **transported** support (k2.3: `S.map ⟨toReal, toReal_injective⟩`). + +**In the oracle the proof is a one-liner**: the weights that +`Finset.mem_convexHull'` asks for are the `Finsupp` itself, zero outside the +support **by construction** (`Finsupp` = function zero outside a finite +support). This is exactly the work that the lake's explicit `Finset` framing +asks for again — and the k2.3 organ `push` provides it: `push toReal P` is +the pushed distribution on the real grid, reading `P` on the image +(`push_apply`) and zero off the image (`push_eq_zero`). The proof becomes +the oracle one-liner again, its three components reading off the k2.3 +organs: `push_apply` (positivity of the transported weights), `push_mass` +(mass, the oracle's `mass_push`), `coordMoment_toReal` (the product point, +the oracle's `mean_push` — the barycenter asserted into the hull is exactly +the one the k2.0 coordinate moments compute). + +**Arbitrated framing gaps** (same family as k2.4): + +1. **the `mean` is read coordinate-wise** — the base `Fin d → ℤ` is not an + `ℝ`-module (blocker measured in k2.2); the point is + `fun i => coordMoment P S i` (k2.0), living in `Fin d → ℝ` where + `convexHull ℝ` is expressible (k2.2/k2.3); +2. **`IsDist` becomes two hypotheses** (`hP`: pointwise positivity, `hmass`: + mass 1 over `S`) — the `Finsupp` structure carried these facts by + construction; the lake takes them as hypotheses, like `hSQ`/`hPsupp` in + k2.4; +3. **the support of the statement is `S` itself** — the oracle concludes on + an arbitrary `s ⊇ support`; here the lake concludes on the exact + transported support `S.map ⟨toReal, _⟩`, the same shape as the `pullback` + conclusion (k2.4). + +**Deferred with a measured consumer**: + +- the sup/inf infrastructure of the oracle module (`mass_sup_add_mass_inf`, + `mean_sup_add_mean_inf`, `support_inf_subset`, `support_sup_subset`) has no + consumer in our framing — mass preservation under splitting is already + `split_mass` (k1.2), which the assembly will consume as a chained + hypothesis; +- `sum_smul_inl` (deferred in k2.4 as "no measured consumer") **gains a + measured consumer** through the k1.7 reading of the step + (`SignedSums.lean` l.53: `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, + add_zero] at hmem`) — it will be delivered with the k2.6 assembly, where + its exact shape gets fixed. +-/ + +import Discrepancy.Basic_en +import Discrepancy.Komlos.MeanSplit_en +import Discrepancy.Komlos.Transport_en + +namespace Discrepancy.Komlos_en + +/-- **`mean_mem_convexHull`** (lake form of the oracle's l.105): the +barycenter — read coordinate-wise, `fun i => coordMoment P S i` (k2.0) — of +a positive distribution of mass 1 over its support `S` belongs to the convex +hull of the **transported** support on the real grid. This is the base case +`n = 0` of the Lemma 1.4 assembly (k1.7, `SignedSums.lean` l.42). + +The proof is the oracle's — `Finset.mem_convexHull'` with the distribution +itself as weights — **provided** the required weight function on the real +grid exists: this is `push toReal P` (k2.3, the lake's `Finsupp.embDomain` +organ), zero off the image by construction. The three components read off +the k2.3 organs: `push_apply` (positivity), `push_mass` (mass), +`coordMoment_toReal` (the point). -/ +theorem mean_mem_convexHull {d : ℕ} {P : (Fin d → ℤ) → ℝ} + {S : Finset (Fin d → ℤ)} + (hP : ∀ x, 0 ≤ P x) (hmass : ∑ x ∈ S, P x = 1) : + (fun i => coordMoment P S i) ∈ convexHull ℝ + ↑(S.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ))) := by + refine Finset.mem_convexHull'.2 ⟨push toReal P, ?_, ?_, ?_⟩ + · intro y hy + obtain ⟨x, -, hxy⟩ := Finset.mem_map.1 hy + have hval : push toReal P y = P x := by + rw [← hxy] + exact push_apply toReal toReal_injective P x + rw [hval] + exact hP x + · rw [push_mass toReal toReal_injective P S] + exact hmass + · funext i + rw [← coordMoment_toReal P S i] + simp only [Finset.sum_apply, coordMomentReal, Pi.smul_apply, smul_eq_mul] + +end Discrepancy.Komlos_en diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md index 765d0d3310..2a72de52f4 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md @@ -65,6 +65,7 @@ boutes `k1..k5` ci-dessous ; issue de suivi : #17845. | **k2.2** | `Discrepancy.Komlos.add_smul_mem_convexHull` : **la surface de convexité s'ouvre** — `convexHull` entre dans ce lake (0 occurrence avant ce commit) par les deux lemmes génériques que le pas de `pullback` consomme. `add_smul_mem_convexHull` (**le point d'un segment dans une enveloppe** — pour `|c| ≤ 1` et `x ± v ∈ s`, `x + c • v ∈ convexHull ℝ s` ; transposé **verbatim** de `Komlos/Pullback.lean:43-50`, l'énoncé ne dépend que de la structure de `ℝ`-module de `E` ; preuve : `Convex.add_smul_sub_mem` (Mathlib `Analysis.Convex.Basic:492`) avec `t = (1+c)/2`, bornes par `linarith`, identité résiduelle par `module` — l'argument même de `segment_repr` k2.1) et `sum_smul_mem_convexHull` (**la clôture du pas** — `(convex_convexHull ℝ _).sum_mem` l.83 chez Dahia, extrait en forme `Finset` du lake : une combinaison convexe finie de points d'une enveloppe reste dans l'enveloppe, via `Convex.sum_mem` `Analysis.Convex.Combination:214`). La décomposition inverse (lire une appartenance comme des poids) existe déjà au pin : `Finset.centerMass_mem_convexHull` (`Analysis.Convex.Combination:253`). **Bloqueur de `pullback`, mesuré ce cycle** : l'oracle l'énonce sur `E →₀ ℝ` avec `E` un `ℝ`-module (enveloppe dans `convexHull ℝ (P.support : Set E)`) ; la base de ce lake `Fin d → ℤ` **n'est pas** un `ℝ`-module — `convexHull ℝ` y est inexprimable sans plongement coordonnée-par-coordonnée dans `Fin d → ℝ` (le transport de dimension, ligne k2 ci-dessous). Module FR + jumeau `_en`. 0 `sorry`. | brique k2 (surface de convexité) | **PROUVÉ** (k2.2, 10-04, `lake build` local EXIT=0 — ciblé deux jumeaux **puis full-lib 8748 jobs**, `distinct_code_sorry = 0`, jumeaux i18n `13/13 byte-identical` — voir PR) | ce PR (stack sur #19070) | | **k2.3** | `Discrepancy.Komlos.toReal` : **le transport de dimension** — lève le bloqueur mesuré en k2.2 (`Fin d → ℤ` n'est pas un `ℝ`-module, `convexHull ℝ` y est inexprimable) en plongeant la grille entière dans `Fin d → ℝ`. Transposé de `Komlos/Transport.lean` (l.27-67). Briques closes : `toReal` + `toReal_injective` (plongement `→+` coordonnée-par-coordonnée, l'instance du lake — le `g ↦ g / N` de l'oracle étant une homothétie de plus), `push e P` (la poussée le long d'un morphisme additif **quelconque** entre les deux grilles sur `Function.extend` — l'organe Mathlib du prolongement le long d'une injection, équivalent du `Finsupp.embDomain` de l'oracle ; l'injectivité n'est requise que par les **lemmes**, pas par la définition), `push_apply` / `push_eq_zero` (les deux identités de calcul, l.32 et hors-image), `sum_push` (ré-indexation `Finset.sum_map`, l.35-36), `push_mass` (conservation de la masse, `mass_push` l.41-42), `coordMomentReal` + `coordMomentReal_push` (le barycentre transporté, forme générique — `mean_push` l.66-67) et **les deux ponts que k2.4 lit sur le support transporté** : `coordMoment_toReal` (le moment coordonné de la poussée par `toReal` **est** le `coordMoment` k2.0 — le pont de barycentre) et `toReal_mem_map_iff` / `toReal_mem_coe_iff` (le pont d'appartenance, formes `Finset` et `Set` — ce que `convexHull ℝ ↑(S.map …)` consommera). **Deux reportés, avec raison mesurée** : `shiftDist_push` (l.63-64 — chez l'oracle `shiftDist` vit sur le support Finsupp **canonique** ; la convention k1.1 passe le support `Finset` explicitement et l'énoncé transporté exige une ré-indexation de `S ∪ (S + u)` côté cible, une union dont la somme n'est pas la somme des sommes ; aucun consommateur k2.4 — la conclusion de convexité ne lit que le support et le barycentre) et `tvDist_push` / `IsDist.push` (l.44-55 — le vocabulaire `tvDist`/`IsDist` n'existe pas dans ce lake, décision de cadre k1.1 ; les restater serait du nouveau vocabulaire, pas du transport). Module FR + jumeau `_en`. 0 `sorry`. | brique k2 (transport de dimension) | **PROUVÉ** (k2.3, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning**, puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19078) | | **k2.4** | `Discrepancy.Komlos.pullback` : **le pas complet du pullback** — le théorème que k2.1 (algèbre), k2.2 (convexité) et k2.3 (transport) ont préparé, porté de `Komlos/Pullback.lean` l.55-92. Briques closes : `toRealProd` + `toRealProd_injective` + `toRealProdEmb` (l'embedding **produit** `(Fin d → ℤ) × Bool → (Fin d → ℝ) × ℝ` — la hauteur `Bool` du lake devient la coordonnée réelle `β` de l'oracle, `false ↦ 0` / `true ↦ 1` ; injectivité par `toReal_injective.eq_iff` + séparation `0 ≠ 1` — le ticket du `Finset.map` du support transporté), `mem_map_toRealProd_snd` (hauteurs de l'image dans `{0, 1}` — le pendant fini de `snd_eq_zero_or_one_of_mem_support_split`), `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` (les **caractérisations de support** de la scission sous `P ≥ 0`, lecture point-par-point des `mk_zero/one_mem_support_split` de l'oracle — le `max` exige la disjonction, le `min` la conjonction) et **le théorème `pullback`** : `(z, β)` dans l'enveloppe du support transporté de `split v P`, `v = 3·w` coordonnée par coordonnée, `β ≥ 1/3` ⇒ un signe `e ∈ {±1}` ramène `z + e • toReal w` dans l'enveloppe du support transporté de `P`. **Trois écarts de cadre arbitrés** : (a) `z` vit côté `ℝ` (le consommateur final Lemme 1.4 produit un barycentre côté grille réelle, d'où l'hypothèse dans l'image transportée) ; (b) `hSQ` exactitude du support de la scission en **hypothèse** (l'oracle la calcule via `Finsupp.support` ; le cadre `Finset` explicite la exige) ; (c) `hPsupp` relaie le support de `P`. Preuve décomposée sur les ingrédients k2.1-k2.3 : `Finset.mem_convexHull'` (`Analysis.Convex/Combination.lean:415` — vérifié au pin, forme `∃ w` exacte) décompose `(z, β)` en poids ; `Finset.abs_sum_le_sum_abs` (`Algebra/Order/BigOperators/Group/Finset.lean:315` — **dans le namespace `Finset`** au pin, l'identifiant nu n'existe pas) borne la part des poids hauteur 0 ; `exists_sign_mul_add_eq` (k2.1) produit `e` et `c` ; chaque point revient dans l'enveloppe par `add_smul_mem_convexHull` (k2.2, tranches hautes) ou l'appartenance directe d'une extrémité via `toReal_mem_map_iff` (k2.3, tranches basses) ; `sum_smul_mem_convexHull` (k2.2) referme. `sum_smul_inl` (`split.lean:50`) **reporté** : le port n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum` ; aucun consommateur mesuré). Module FR + jumeau `_en`, étendus (pas de nouveau fichier). 0 `sorry`. | brique k2 (pas complet) | **PROUVÉ** (k2.4, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (~30 s chacun), puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19081) | +| **k2.5** | `Discrepancy.Komlos.mean_mem_convexHull` : **le cas de base `n = 0` de l'assemblage** — porté de `Komlos/Distribution.lean` l.105, module de l'oracle repris **nom pour nom** (nouveau `Distribution.lean` + jumeau `_en` ; le glob `.submodules` du lakefile le découvre — `Komlos.lean` n'est pas un agrégateur, aucun enregistrement). Énoncé : le barycentre — lu coordonnée par coordonnée, `fun i => coordMoment P S i` (k2.0) — d'une distribution positive (`hP`) de masse 1 (`hmass`) sur `S` appartient à l'enveloppe convexe du support **transporté** `S.map ⟨toReal, toReal_injective⟩` — la même forme exacte que la conclusion de `pullback` (k2.4), que la base `n = 0` de l'assemblage consommera (`SignedSums.lean` l.42). **La clé du port** : chez l'oracle le one-liner (`Finset.mem_convexHull'.2 ⟨S, …⟩`) tient parce que les poids demandés sont le `Finsupp` lui-même, **nul hors support par construction** ; le cadre `Finset` explicite du lake exigeait de construire ce poids sur la grille réelle — et c'est **déjà l'organe `push` de k2.3** (`push toReal P` sur `Function.extend`, nul hors image par construction, équivalent du `Finsupp.embDomain` de l'oracle) : aucun poids à inventer, la preuve redevient le one-liner oracle avec ses trois composantes lisant les organes k2.3 — `push_apply` (positivité des poids transportés, chaque point du support transporté relisant `P` à son unique antécédent), `push_mass` (masse conservée, le `mass_push` de l'oracle), `coordMoment_toReal` (le point produit, le `mean_push` de l'oracle — le barycente affirmé dans l'enveloppe est exactement celui que les moments k2.0 calculent). **Trois écarts de cadre arbitrés** (même famille que k2.4) : (a) le `mean` se lit coordonnée par coordonnée (`Fin d → ℤ` n'est pas un `ℝ`-module, bloqueur mesuré en k2.2) ; (b) `IsDist` devient deux hypothèses `hP`/`hmass` (la structure `Finsupp` portait ces faits par construction) ; (c) le support de l'énoncé est `S` transporté exact, pas un `s ⊇ support` arbitraire. **Reportés avec raison mesurée** : l'infrastructure sup/inf du module oracle (`mass_sup_add_mass_inf`, `mean_sup_add_mean_inf`, `support_inf_subset`, `support_sup_subset`) — aucun consommateur dans notre cadre (la préservation de masse à la scission est `split_mass` k1.2, consommée en hypothèse chaînée) ; et **`sum_smul_inl` (`split.lean:50`) acquiert un consommateur mesuré** par la lecture k1.7 du pas (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) — livré avec k2.6 où sa forme exacte se fixe. 0 `sorry`. | brique k2 (cas de base) | **PROUVÉ** (k2.5, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (31 s chacun, SUCCESS au premier round) ; `distinct_code_sorry = 0` ; jumeaux i18n `15/15 byte-identical` — voir PR) | ce PR (stack sur #19084) | | **k3.1** | `Discrepancy.Komlos.tent` (`Komlos/Tent.lean` + jumeau `_en`) : **la tente discrète, port complet du module de l'oracle** — les 13 preuves reportées en c.885 (delivery #17918) sont closes, chacune adaptée du `grind` v4.34 vers le pin v4.33.0 / `db584cd6` (détail par preuve dans la note de fin de fichier). Sommes closes : `sum_tent` (Σ tent = M²), `sum_tent_sq` (3·Σ tent² = M(2M²+1)) ; Lipschitz `abs_tent_sub_le` (1-Lipschitz) ; pas `step`/`abs_step_le_one`/`step_eq_zero`/`sum_step_sq_le` (≤ 2M) ; télescopage `tent_sub_tent_eq_sum_step` ; **résultat porteur `sum_tent_sub_sq_le`** (Σ (tent M j − tent M (j−m))² ≤ 2·M·m²) — la borne `L²` **discrète** du Lemme 4.1. Adaptations mesurées : `abs_add`/`neg_le_abs_self` **absents au pin** (sondés — la triangulaire inverse passe par `abs_max_sub_max_le_abs` + `abs_abs_sub_abs_le_abs_sub`) ; `omega` ne splitte pas `\|j\|` sur ℤ (atome opaque) → composites `le_abs_self`+`abs_neg` ; l'énoncé `support_tent_subset` force `Set.Icc` (le `Icc` nu sous `open Finset` s'élabore en coercion Finset) ; bornes en cast entier global `((M+1:ℕ):ℤ)` ; `sum_range_sub'` absent → induction manuelle ; `rw` avec `f := id` échoue → normalisation `simp only [id]`. **Réaudit k3 contre l'oracle** : la voie Dahia est **totalement discrète** — `Grid.lean` consomme `sum_tent_sq` + `sum_tent_sub_sq_le` pour construire le poids normalisé `gridF N` (distance `L²` de translation ≤ \|m\|/(N·√12)) ; le « FTC sur segments » du papier est remplacé par la discrétisation sur grille (`intervalIntegral` absent de l'oracle) — la ligne de planification k3 est réécrite en conséquence. 0 `sorry`. | brique k3 (tente + L² discret) | **PROUVÉ** (k3.1, 10-06, `lake build` local EXIT=0 sur les deux jumeaux — 8708 jobs, `distinct_code_sorry = 0`, jumeaux i18n `1/1 byte-identical` — voir PR) | ce PR (branche `feature/komlos-k3-tent`) | | **k3.2** | `Discrepancy.Komlos.gridF` (`Komlos/Grid.lean` + jumeau `_en`) : **le poids normalisé unidimensionnel et sa borne `L²` de translation — port complet du `Komlos/Grid.lean` de l'oracle** (la voie k3 de l'oracle est désormais complète). Briques closes : `gridM` (demi-largeur `6·N`), `gridZ` (constante de normalisation = `∑ tent²`), `gridF` (`tent (gridM N) j / √(gridZ N)`), `cast_gridM`, `gridZ_eq` (**`gridZ N = 144·N³ + 2·N`**), `gridZ_pos`, `gridF_nonneg`, `support_gridF_subset`, `finsum_gridF_sq` (**masse totale `1`**), `sum_gridF_sub_sq`/`sum_gridF_sq` (formes `Finset` consommables), **résultat porteur `sum_gridF_sub_sq_le`** : distance `L²` au carré entre `gridF N` et son translaté par `m` ≤ `m²/(12·N²)` — l'analogue discret du Lemme 4.1, entrée directe de la discrétisation k4 (Lemme 1.5). Adaptations mesurées : le `positivity` de l'oracle sur `gridZ_pos` échoue au pin (stricte positivité dépend de `hN : 0 < N`) → cast + `linarith` ; le `linarith` final de `gridZ_eq` échoue sur le produit non-linéaire → normalisation `ring` explicite avant `linarith` ; `support_tent_subset` de ce lake étant typé `Set.Icc` (l'oracle : `Finset.Icc`), `support_gridF_subset` est prouvé directement (`Finset.mem_coe` + composite `le_abs_self`) ; l'API `finsum` (**existe au pin**, à la racine — sondée) permet le port quasi verbatim des énoncés de masse. **Correctif i18n embarqué** : `Tent_en.lean` passait en `namespace Discrepancy.Komlos` (seul `_en` du lake non suffixé — défaut #17918) ; il repasse en `Discrepancy.Komlos_en`, condition de l'import propre `Grid_en → Tent_en`. 0 `sorry`. | brique k3 (poids normalisé + L²) | **PROUVÉ** (k3.2, 10-06, `lake build` local EXIT=0 sur les trois cibles — 8710 jobs : `Grid`, `Grid_en`, `Tent_en` recompilé ; `distinct_code_sorry = 0`, jumeaux i18n `2/2 byte-identical` — voir PR) | ce PR (stack sur #19563) | | P3 | Banaszczyk 1998 / formes fortes des papiers 2025 **et 2026** | aspiration | **NON ENGAGÉ** — exige SDP + dualité, indépendance spectrale affine, brownien discret guidé, concentration matricielle : **aucun de cet étage n'existe dans Mathlib** (vérifié 2026-08-24). **Réaudité 2026-09-13** contre le Mathlib pinné (`520045ab`, v4.32.1) : le contournement proposé par arXiv:2609.11189 ne supprime pas l'obstruction, il la **déplace** — sa route exige la *variation totale directionnelle* d'une densité sur convexe ouvert et la *transformée de Banaszczyk* préservée sous translation, deux notions **absentes du même Mathlib** (`Banaszczyk` : 0 occurrence ; `totalVariation` n'existe que pour les mesures signées ; la théorie BV de Mathlib concerne la dérivabilité a.e. des fonctions de `ℝ`). Ce que ce papier rapproche, ce sont les *socles* : gaussiennes (`Probability/Distributions/Gaussian/*`) et `ConvexBody` (`Analysis/Convex/Body.lean`) sont présents ; le **pont** manque. Documenté, jamais promis. **Réaudité 2026-09-25** : la voie **élémentaire** de Karingula–Lovett (arXiv:2609.20979, constante `36`) **supprime** cet étage au lieu de le déplacer — sa mécanique est discrète (distance de décalage `Δ`, opérateur de scission `T_v`, induction sur `n` et `d`) à une seule exception, l'estimation de la densité-tente, qui se fait par FTC sur segments + Cauchy–Schwarz `L²` et **non** par de la théorie BV. Balayage des prérequis sur le checkout Mathlib local (`v4.32.0`) : famille **`norm_image_sub_le` présente** (dont `Analysis/Calculus/IntervalIntegral/DistLEIntegral.lean`), `totalVariation` toujours cantonné aux mesures vectorielles (`VectorMeasure/Decomposition/*`) — mais le papier n'en a plus besoin. Réserve de portée : ce balayage porte sur un checkout **voisin** (`v4.32.0`), pas sur le pin du lake (`520045ab`) — à re-vérifier avant la première boute `.lean`. Une formalisation Lean 4 tierce de cette preuve existe déjà (mise à jour du 2026-09-25 ci-dessous). | — | @@ -164,7 +165,7 @@ branche, jamais `main`. Issue de suivi : #17845. | **k1.7** | Correctif d'hypothèse **avant** k2 : l'invariance du support des briques k1 est insatisfiable aux décalages non nuls (mesuré, `eq_zero_of_image_add_eq_self`) → formes consommables sous **contention** `SupportContained` | fini | k1 | | **k2.0** | **Moments de la scission** (`mean_split`) — décomposition par composante du `mean_split` de Dahia (base `Fin d → ℤ` sans structure de `ℝ`-module : `coordMoment`/`prodMoment`, `heightMoment`), moment de hauteur = `splitBit` (`heightMoment_split`), **conservation du barycentre** par la scission (`prodMoment_split`) — l'item reporté par k1.6 | fini | k1, k1.6 | | **k2.0 — correctif de support** | **Formes consommables des moments** — `prodMoment_split_of_support` + `mean_split_of_support` sous `SupportContained S P {0, v, -v}` : k1.7 appliqué à k2.0 (`heightMoment_split` réutilisé inchangé), + contrôle positif `exists_supportContained_nonzero_shift` (`d = 1`, `v = 1`, `P` Dirac, `S = {-1, 0, 1}` via `supportContained_biUnion`) | fini | k1.7, k2.0 | -| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé** (Fin d → ℤ n’est pas un ℝ-module ; l’oracle énonce pullback sur E →₀ ℝ — le transport plonge la grille dans Fin d → ℝ où convexHull ℝ parle). **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Reste à ce lake, mesuré** : le pendant fini de `mean_mem_convexHull` (`distribution.lean:105`, cadre `Finsupp` à transposer en `Finset` — l'hypothèse d'induction du pas complet en aura besoin pour produire le `(z, β)` de `hmem`) et, pour l'assemblage final, la lecture k1.7 du pas (`SignedSums.lean` l.37-58 : l'itération `induction n with` qui consomme `mean_split` + `pullback`). `sum_smul_inl` (`split.lean:50`) reste sans consommateur mesuré à ce stade — le port k2.4 n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum`, pas par la construction `incl`). | fini + induction | k1, k1.7, k2.0–k2.4 | +| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé** (Fin d → ℤ n’est pas un ℝ-module ; l’oracle énonce pullback sur E →₀ ℝ — le transport plonge la grille dans Fin d → ℝ où convexHull ℝ parle). **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Reste à ce lake, mesuré** : **l'assemblage k2.6 seul** — la lecture k1.7 du pas (`SignedSums.lean` l.37-58 : l'itération `induction n with` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_inl` au pas (l.53) et `pullback` en clôture). `sum_smul_inl` (`split.lean:50`) **a désormais un consommateur mesuré** (l.53) — livré avec k2.6, où sa forme exacte se fixe. | fini + induction | k1, k1.7, k2.0–k2.5 | | **k3** | Lemme 4.1 — densité-tente. **Réauditée contre l'oracle au pin (k3.1)** : la voie Dahia est **totalement discrète** — le « FTC sur segments » du papier est remplacé par la discrétisation sur grille, `intervalIntegral` **absent de l'oracle** — la dépendance `norm_image_sub_le` est sans objet. **LIVRÉE EN INTÉGRALITÉ** : k3.1 (`Tent.lean` complet, lignes k3.1/k3.2) puis k3.2 (`Grid.lean` complet — `gridF` normalisé, `gridZ_eq : gridZ N = 144·N³ + 2·N`, masse `1`, **`sum_gridF_sub_sq_le` : distance `L²` de translation ≤ m²/(12·N²)**, l'analogue discret du Lemme 4.1). **Reste** : k4 (Lemme 1.5, discrétisation). | fini (oracle discret, complet) | k3.1, k3.2 | | **k4** | Lemme 1.5 — discrétisation sur la grille, cas rationnel | fini | k3 | | **k5** | Assemblage Thm 1.2 sur `ℚ` (témoin `36`) + corollaires (`KomlosBansalJiangWeak`, Beck–Fiala régulier `72√k`) + notebooks `Search-09c`/`Search-09e` (ligne « course aux bornes » du 22/09/2026) | assemblage | k2, k4 | From 8c373ef3d354da74b7d6cff89dc03453c5af6b4d Mon Sep 17 00:00:00 2001 From: jsboige Date: Sun, 4 Oct 2026 11:57:57 +0200 Subject: [PATCH 3/8] feat(lean,#17845): brique k2.6a -- pont de niveau liftUp/pushUp (Lift + jumeau _en) Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit f11bc6e1c7209f99a4d4157fe9b4b6a10d4c6de1) --- .../Discrepancy/Komlos/Lift.lean | 308 ++++++++++++++++++ .../Discrepancy/Komlos/Lift_en.lean | 300 +++++++++++++++++ .../Search/discrepancy_lean/FORMAL_STATUS.md | 3 +- 3 files changed, 610 insertions(+), 1 deletion(-) create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift.lean create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift_en.lean diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift.lean new file mode 100644 index 0000000000..8d7e227b57 --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift.lean @@ -0,0 +1,308 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapté à `discrepancy_lean` (issue #17845, distillation Karingula–Lovett +arXiv:2609.20979) : toolchain v4.33.0, Mathlib `db584cd6`, convention i18n #4980. + +Le source Dahia original vit dans le dépôt `gdahia/Komlos` (toolchain +v4.34.0, cadre `Finsupp` sur `E →₀ ℝ`). Ce module n'a **pas de contrepartie +oracle nom pour nom** : l'oracle n'a pas besoin de pont de niveau, et cette +absence est précisément ce que cette brique documente. + +**Design-gate de l'assemblage k2.6 (consigné ici, décision arbitrée).** +L'oracle démontre le Lemme 1.4 (`Komlos/SignedSums.lean` l.37-64) par +induction sur `n` avec l'énoncé **universellement quantifié sur `E`** — +l'hypothèse d'induction s'applique donc, au cran successeur, à la +distribution scindée dans l'espace **agrandi** `E × ℝ` (l.52), avec les +vecteurs embarqués à hauteur nulle `(v i.castSucc, 0)` (l.47, l.53). La +base du lake `Fin d → ℤ` est fixe, et aucune des briques k1.x/k2.x ne +s'appliquerait à une distribution sur un type réellement différent. Les +options mesurées : + +- (a) généraliser `split`/`pullback` sur un espace abstrait `X × Bool` — + une seconde formalisation de toute la chaîne ; +- (b) espace produit itéré `(Fin d → ℤ) × (Fin n → Bool)` — même coût de + généralisation, notation plus lourde ; +- **(c) retenue : l'espace qui grandit est `Fin (d + k) → ℤ`.** La hauteur + `Bool` s'embarque comme l'entier `{0, 1}` à la position `snoc` : + l'embedding `liftUp : ((Fin d → ℤ) × Bool) → (Fin (d+1) → ℤ)` réalise + le `incl b : E ↪ E × ℝ` de l'oracle (`Komlos/Split.lean` l.31) côté + discret, et `toReal` (k2.3) transporte vers `Fin (d+1) → ℝ`, qui est le + `E × ℝ` de l'oracle lu coordonnée par coordonnée. Chaque brique du lake + étant générique en `d`, elles s'appliquent **toutes telles quelles à la + dimension suivante** : le miroir d'induction de l'oracle est + `induction n generalizing d`. + +**Portée de ce commit** (brique k2.6a, `lake build SUCCESS` requis, 0 +`sorry`) — le pont de niveau, mécanique de bout en bout : + +- `liftUp` + injectivité — l'embedding produit vers `snoc` ; +- `liftUp_add_snoc` — les translations de hauteur nulle commutent avec + l'embedding : `liftUp y + snoc u 0 = liftUp (y.1 + u, y.2)` (l'équation + qui fait marcher le pont de `shiftDistance`) ; +- `pushUp` — la poussée le long de `liftUp`, le **même pattern + `Function.extend` que l'organe `push` de k2.3** (le `Finsupp.embDomain` + du lake), avec sa lecture `apply`/`eq_zero`/`nonneg`/`mass` ; ce n'est + pas le `push` de k2.3 lui-même car celui-ci est typé sur le transport de + dimension `(Fin d → ℤ) →+ (Fin d → ℝ)`, alors que le côté produit ne + porte aucune structure additive (`Bool`) ; +- les **ponts de moment** : le moment coordonné de la poussée, lu sur une + coordonnée `castSucc`, est le moment produit de la source ; sur la + coordonnée `last`, c'est le moment de hauteur — les deux composantes de + `mean_split` (k2.0) lues à travers l'embedding ; +- le **pont de distance de translation** : + `Δ(pushUp Q, snoc u 0) = Δprod(Q, u)` — le Claim 3.2 de k1.5 se + transporte tel quel vers l'espace agrandi ; +- `sum_smul_snoc` — la forme lake du `sum_smul_inl` de l'oracle + (`Komlos/Split.lean` l.50-53) : une somme de vecteurs mis à l'échelle, + chacun embarqué à hauteur nulle, reste embarquée à hauteur nulle. Son + consommateur est mesuré : `Komlos/SignedSums.lean` l.54 + (`rw [mean_split, sum_smul_inl, ...]`) ; +- `toReal_liftUp` — la commutation `toReal ∘ liftUp = snoc ∘ (toReal × + hauteur)` : le carré de diagramme avec le `toRealProd` de k2.4 se + referme, et c'est ainsi que l'assemblage k2.6 nourrira `pullback` + (k2.4) depuis l'hypothèse d'induction énoncée à la dimension agrandie. + +**Différé avec consommateur mesuré** : la conservation des moments sous +contenance (`prodMoment_split_of_support`, le pendant `_of_support` des +composantes de `mean_split` de k2.0) et le transfert de contenance à +travers la scission (k2.6b) ; l'induction elle-même (`SignedSums.lean` +nom pour nom, k2.6c). L'état détaillé vit dans `FORMAL_STATUS.md`. +-/ + +import Discrepancy.Komlos.MeanSplit +import Discrepancy.Komlos.SplitDistance +import Discrepancy.Komlos.Transport + +/-! +# Pont de niveau : espace produit vers dimension agrandie (k2.6a) + +`Discrepancy.Komlos.liftUp` embarque `(Fin d → ℤ) × Bool` dans +`Fin (d+1) → ℤ` — la partie spatiale par `Fin.snoc`, la hauteur `Bool` +comme l'entier `{0, 1}` à la dernière coordonnée. `pushUp` pousse une +distribution le long de cet embedding (le pattern `Function.extend` de +l'organe `push` de k2.3), et les ponts de ce module énoncent que **toute** +la structure que l'assemblage consomme — masse, moments coordonnés, +moment de hauteur, distance de translation, support — se lit à travers +l'embedding sans perte. + +C'est la réalisation discrète de l'espace croissant de l'oracle : son +induction sur le nombre de vecteurs applique l'hypothèse dans `E × ℝ` à +chaque scission (`Komlos/SignedSums.lean` l.44-53) ; la nôtre l'applique +dans `Fin (d+1) → ℤ`, où chaque brique du lake (toutes génériques en +`d`) vit déjà. +-/ + +namespace Discrepancy.Komlos + +/-- **Embedding de niveau** : la grille produit `(Fin d → ℤ) × Bool` se +plonge dans la grille de dimension supérieure `Fin (d+1) → ℤ` — la partie +spatiale par `Fin.snoc`, la hauteur `Bool` comme l'entier `{0, 1}` à la +dernière coordonnée. + +C'est la contrepartie discrète du `incl b : E ↪ E × ℝ` de l'oracle +(`Komlos/Split.lean` l.31) : là où l'oracle embarque `E` comme tranche de +hauteur `b` de `E × ℝ`, le lake embarque la paire `(x, b)` comme vecteur +de dimension `d+1` — la hauteur devenant une coordonnée entière valant +`0` ou `1`. Le transport `toReal` (k2.3) la relit alors comme coordonnée +réelle, refermant le carré avec `toRealProd` (k2.4, cf `toReal_liftUp`). -/ +def liftUp {d : ℕ} : ((Fin d → ℤ) × Bool) → (Fin (d + 1) → ℤ) := + fun y => Fin.snoc y.1 (if y.2 then 1 else 0) + +/-- Lecture de l'embedding sur une coordonnée héritée : la partie +spatiale se lit inchangée. -/ +@[simp] lemma liftUp_apply_castSucc {d : ℕ} (y : (Fin d → ℤ) × Bool) + (i : Fin d) : liftUp y i.castSucc = y.1 i := by simp [liftUp] + +/-- Lecture de l'embedding sur la coordonnée de hauteur : le `Bool` +devient l'entier `{0, 1}`. -/ +@[simp] lemma liftUp_apply_last {d : ℕ} (y : (Fin d → ℤ) × Bool) : + liftUp y (Fin.last d) = if y.2 then 1 else 0 := by simp [liftUp] + +/-- L'embedding de niveau est **injectif** : la partie spatiale se relit +par `Fin.init`-quement (deux `snoc` égaux ont des queues égales et des +corps égaux), et la coordonnée de hauteur sépare `false` de `true` par +`0 ≠ 1`. C'est le papier des `Finset.map` des supports transportés. -/ +lemma liftUp_injective {d : ℕ} : Function.Injective (liftUp (d := d)) := by + rintro ⟨x₁, b₁⟩ ⟨x₂, b₂⟩ h + simp only [liftUp, Fin.snoc_inj] at h + obtain ⟨hxe, hqe⟩ := h + cases b₁ <;> cases b₂ <;> simp_all + +/-- La version `Finset.Embedding` de `liftUp`, pour les `Finset.map` des +supports poussés. -/ +def liftUpEmb {d : ℕ} : ((Fin d → ℤ) × Bool) ↪ (Fin (d + 1) → ℤ) := + ⟨liftUp, liftUp_injective⟩ + +/-- Lecture de l'embedding wrapper : `liftUpEmb` applique `liftUp`. C'est +le pont syntaxique que consomment les re-écritures `pushUp_apply` / +`liftUp_apply_*` sur les images `Finset.map`. -/ +lemma liftUpEmb_apply {d : ℕ} (y : (Fin d → ℤ) × Bool) : + liftUpEmb y = liftUp y := rfl + +/-- **Les translations de hauteur nulle commutent avec l'embedding** : +`liftUp y + snoc u 0 = liftUp (y.1 + u, y.2)`. C'est l'équation qui fait +marcher le pont de distance de translation (`shiftDistance_pushUp`) : la +translation `u` de la base, embarquée à hauteur nulle dans la dimension +supérieure, agit sur l'image exactement comme la translation `(u, 0)` de +l'espace produit. -/ +lemma liftUp_add_snoc {d : ℕ} (y : (Fin d → ℤ) × Bool) (u : Fin d → ℤ) : + liftUp y + Fin.snoc u 0 = liftUp (y.1 + u, y.2) := by + funext j + induction j using Fin.lastCases with + | last => simp [liftUp] + | cast i => simp [liftUp, Pi.add_apply] + +/-- **Poussée d'une distribution le long de l'embedding de niveau** : +`pushUp Q (liftUp y) = Q y` (par `pushUp_apply`) et `pushUp Q z = 0` +hors de l'image (par `pushUp_eq_zero`). + +C'est le **même pattern `Function.extend` que l'organe `push` de k2.3** +(le `Finsupp.embDomain` de l'oracle, `Komlos/Transport.lean` l.27-28) — +et non cet organe lui-même : `push` de k2.3 est typé sur le transport de +dimension `(Fin d → ℤ) →+ (Fin d → ℝ)`, un morphisme additif, alors que +la source produit `(Fin d → ℤ) × Bool` ne porte aucune structure +additive (le `Bool` n'a pas d'opposé). Le prolongement le long d'une +injection est l'organe Mathlib commun aux deux. -/ +noncomputable def pushUp {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) : + (Fin (d + 1) → ℤ) → ℝ := + Function.extend liftUp Q 0 + +/-- Sur l'image de l'embedding, la poussée relit la distribution source. +(Chez l'oracle, c'est le rôle de `Finsupp.embDomain_apply_self`.) -/ +@[simp] lemma pushUp_apply {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (y : (Fin d → ℤ) × Bool) : pushUp Q (liftUp y) = Q y := + Function.Injective.extend_apply liftUp_injective Q 0 y + +/-- Hors de l'image de l'embedding, la poussée est nulle : les points de +la grille de dimension `d+1` sans antécédent produit ne portent aucune +masse. -/ +lemma pushUp_eq_zero {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + {z : Fin (d + 1) → ℤ} (hz : ∀ y, liftUp y ≠ z) : pushUp Q z = 0 := by + have hb : ¬∃ a, liftUp a = z := by + rintro ⟨a, rfl⟩ + exact hz a rfl + exact Function.extend_apply' Q (0 : (Fin (d + 1) → ℤ) → ℝ) z hb + +/-- La poussée d'une fonction positive reste positive : chaque point est +soit une valeur de la source, soit zéro. -/ +lemma pushUp_nonneg {d : ℕ} {Q : ((Fin d → ℤ) × Bool) → ℝ} + (hQ : ∀ y, 0 ≤ Q y) (z : Fin (d + 1) → ℤ) : 0 ≤ pushUp Q z := by + by_cases h : ∃ y, liftUp y = z + · obtain ⟨y, rfl⟩ := h + rw [pushUp_apply] + exact hQ y + · rw [pushUp_eq_zero Q (fun y hy => h ⟨y, hy⟩)] + +/-- **La masse est conservée par la poussée** : sommer la poussée sur le +support transporté, c'est sommer la source — le pendant `pushUp` de +`push_mass` (k2.3). -/ +lemma pushUp_mass {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) : + ∑ z ∈ SQ.map liftUpEmb, pushUp Q z = ∑ y ∈ SQ, Q y := by + simp only [Finset.sum_map, liftUpEmb_apply] + exact Finset.sum_congr rfl fun y _ => pushUp_apply Q y + +/-- **Exactitude du support poussé (sens direct)** : si chaque point de +`SQ` porte une masse non nulle, chaque point du support transporté porte +une masse non nulle. -/ +lemma pushUp_ne_zero_of_mem {d : ℕ} {Q : ((Fin d → ℤ) × Bool) → ℝ} + {SQ : Finset ((Fin d → ℤ) × Bool)} (hSQ : ∀ y ∈ SQ, Q y ≠ 0) : + ∀ z ∈ SQ.map liftUpEmb, pushUp Q z ≠ 0 := by + intro z hz + rw [Finset.mem_map] at hz + obtain ⟨y, hy, rfl⟩ := hz + simp only [liftUpEmb_apply] + rw [pushUp_apply] + exact hSQ y hy + +/-- **Exactitude du support poussé (sens retour)** : si `SQ` contient le +support de `Q`, l'image transportée contient le support de la poussée. -/ +lemma pushUp_mem_map_of_ne_zero {d : ℕ} {Q : ((Fin d → ℤ) × Bool) → ℝ} + {SQ : Finset ((Fin d → ℤ) × Bool)} (hSQ : ∀ y, Q y ≠ 0 → y ∈ SQ) : + ∀ z, pushUp Q z ≠ 0 → z ∈ SQ.map liftUpEmb := by + intro z hz + by_cases hex : ∃ y, liftUp y = z + · obtain ⟨y, rfl⟩ := hex + rw [pushUp_apply] at hz + exact Finset.mem_map.mpr ⟨y, hSQ y hz, liftUpEmb_apply y⟩ + · rw [pushUp_eq_zero Q (fun y hy => absurd ⟨y, hy⟩ hex)] at hz + exact (hz rfl).elim + +/-- **Pont de moment, coordonnée héritée** : le moment coordonné de la +poussée, lu sur une coordonnée `castSucc`, est le moment de base de la +source — la composante spatiale du barycentre traverse l'embedding sans +changement. C'est la première composante de `mean_split` (k2.0) lue à +travers le pont de niveau. -/ +lemma coordMoment_pushUp_castSucc {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) (i : Fin d) : + coordMoment (pushUp Q) (SQ.map liftUpEmb) i.castSucc = prodMoment Q SQ i := by + simp only [coordMoment, prodMoment, Finset.sum_map, liftUpEmb_apply] + exact Finset.sum_congr rfl fun y _ => by rw [pushUp_apply, liftUp_apply_castSucc] + +/-- **Pont de moment, coordonnée de hauteur** : le moment coordonné de la +poussée, lu sur la dernière coordonnée, est le moment de hauteur de la +source — le `Bool` `{false, true}` relu comme le réel `{0, 1}`. C'est la +seconde composante de `mean_split` (k2.0) : le bit de scission devient la +coordonnée de hauteur du barycentre poussé. -/ +lemma coordMoment_pushUp_last {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) : + coordMoment (pushUp Q) (SQ.map liftUpEmb) (Fin.last d) + = heightMoment Q SQ := by + simp only [coordMoment, heightMoment, Finset.sum_map, liftUpEmb_apply] + refine Finset.sum_congr rfl fun y _ => ?_ + rw [pushUp_apply, liftUp_apply_last] + cases y.2 <;> simp + +/-- **Pont de distance de translation** : la distance de translation de +la poussée, dans une direction embarquée à hauteur nulle, est la distance +de translation produit de la source — `Δ(pushUp Q, snoc u 0) = Δprod(Q, +u)`. C'est ce qui permet au Claim 3.2 (k1.5, `shiftDistanceProd_split_le`) +de s'appliquer à la dimension supérieure : l'hypothèse d'induction sur +les distances se transporte sans perte. -/ +lemma shiftDistance_pushUp {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) (u : Fin d → ℤ) : + shiftDistance (SQ.map liftUpEmb) (pushUp Q) (Fin.snoc u 0) + = shiftDistanceProd SQ Q u := by + simp only [shiftDistance, shiftDistanceProd, Finset.sum_map, liftUpEmb_apply] + refine congrArg _ (Finset.sum_congr rfl fun y _ => ?_) + rw [liftUp_add_snoc, pushUp_apply, pushUp_apply] + +/-- **Forme lake du `sum_smul_inl` de l'oracle** (`Komlos/Split.lean` +l.50-53) : une somme de vecteurs mis à l'échelle, chacun embarqué à +hauteur nulle par `snoc · 0`, est elle-même un vecteur embarqué à hauteur +nulle — la somme pondérée des parties spatiales, queue nulle. + +Consommateur mesuré : `Komlos/SignedSums.lean` l.54, où cette identité +sépare la coordonnée de hauteur du point que l'hypothèse d'induction +produit (`rw [mean_split, sum_smul_inl, ...] at hmem`). -/ +lemma sum_smul_snoc {d : ℕ} {ι : Type*} (s : Finset ι) + (ε : ι → ℝ) (r : ι → (Fin d → ℝ)) : + ∑ i ∈ s, ε i • Fin.snoc (r i) (0 : ℝ) + = Fin.snoc (∑ i ∈ s, ε i • r i) (0 : ℝ) := by + funext j + induction j using Fin.lastCases with + | last => + simp only [Finset.sum_apply, Pi.smul_apply, Fin.snoc_last, smul_eq_mul, + mul_zero, Finset.sum_const_zero] + | cast i => + simp only [Fin.snoc_castSucc, Finset.sum_apply, Pi.smul_apply] + +/-- **Commutation du transport avec l'embedding** : `toReal ∘ liftUp = +snoc ∘ (toReal × hauteur)` — la partie spatiale est transportée par +`toReal` (k2.3), la hauteur `Bool` devient le réel `{0, 1}`. + +C'est ce qui referme le carré avec `toRealProd` (k2.4) : l'image +transportée du support poussé dans `Fin (d+1) → ℝ` est la lecture +`(y.1, hauteur y.2)` de l'embedding produit — l'endroit exact où la +conclusion d'induction à la dimension `d+1` nourrit le `pullback` de +k2.4, énoncé dans `(Fin d → ℝ) × ℝ`. -/ +lemma toReal_liftUp {d : ℕ} (y : (Fin d → ℤ) × Bool) : + toReal (liftUp y) + = Fin.snoc (toReal y.1) (if y.2 then (1 : ℝ) else 0) := by + funext j + obtain ⟨x, b⟩ := y + cases b <;> induction j using Fin.lastCases <;> simp [liftUp] + +end Discrepancy.Komlos diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift_en.lean new file mode 100644 index 0000000000..d69f2ca1a5 --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/Lift_en.lean @@ -0,0 +1,300 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapted for `discrepancy_lean` (issue #17845, Karingula–Lovett distillation +arXiv:2609.20979): toolchain v4.33.0, Mathlib `db584cd6`, i18n convention #4980. + +The original Dahia source lives in the `gdahia/Komlos` repository (toolchain +v4.34.0, `Finsupp` framework over `E →₀ ℝ`). This module has **no +name-for-name oracle counterpart**: the oracle needs no level bridge, and +that absence is precisely what this brick documents. + +**Design-gate of the k2.6 assembly (recorded here, decision arbitrated).** +The oracle proves Lemma 1.4 (`Komlos/SignedSums.lean` l.37-64) by induction +on `n` with the statement **universally quantified over `E`** — so the +induction hypothesis applies, at the successor step, to the split +distribution in the **grown** space `E × ℝ` (l.52), with vectors embedded +at height zero `(v i.castSucc, 0)` (l.47, l.53). The lake's base `Fin d → ℤ` +is fixed, and none of the k1.x/k2.x bricks would apply to a distribution +on a genuinely different type. The options measured: + +- (a) generalize `split`/`pullback` over an abstract space `X × Bool` — + a second formalization of the whole chain; +- (b) iterated product space `(Fin d → ℤ) × (Fin n → Bool)` — same + generalization cost, heavier notation; +- **(c) retained: the growing space is `Fin (d + k) → ℤ`.** The height + `Bool` embeds as the integer `{0, 1}` at the `snoc` position: the + embedding `liftUp : ((Fin d → ℤ) × Bool) → (Fin (d+1) → ℤ)` realizes + the oracle's `incl b : E ↪ E × ℝ` (`Komlos/Split.lean` l.31) on the + discrete side, and `toReal` (k2.3) transports to `Fin (d+1) → ℝ`, which + is the oracle's `E × ℝ` read coordinate-wise. Every brick of the lake + being generic in `d`, they all **apply as-is at the next dimension**: + the induction mirror of the oracle is `induction n generalizing d`. + +**Scope of this commit** (brick k2.6a, `lake build SUCCESS` required, 0 +`sorry`) — the level bridge, all of it mechanical: + +- `liftUp` + injectivity — the product-to-`snoc` embedding; +- `liftUp_add_snoc` — translations at height zero commute with the + embedding: `liftUp y + snoc u 0 = liftUp (y.1 + u, y.2)` (the equation + that makes the `shiftDistance` bridge work); +- `pushUp` — the push-forward along `liftUp`, the **same `Function.extend` + pattern as the k2.3 organ `push`** (the lake's `Finsupp.embDomain`), + with its `apply`/`eq_zero`/`nonneg`/`mass` reading; it is not the k2.3 + `push` itself because that one is typed on the dimension transport + `(Fin d → ℤ) →+ (Fin d → ℝ)`, and the product side carries no additive + structure (`Bool`); +- the **moment bridges**: the coordinate moment of the pushed + distribution at a `castSucc` coordinate is the product moment of the + source; at the `last` coordinate it is the height moment — the two + components of `mean_split` (k2.0) read through the embedding; +- the **shift-distance bridge**: `Δ(pushUp Q, snoc u 0) = Δprod(Q, u)` — + the Claim 3.2 of k1.5 transfers to the grown space verbatim; +- `sum_smul_snoc` — the lake form of the oracle's `sum_smul_inl` + (`Komlos/Split.lean` l.50-53): a sum of scaled vectors embedded at + height zero stays embedded at height zero. Its consumer is measured: + `Komlos/SignedSums.lean` l.54 (`rw [mean_split, sum_smul_inl, ...]`); +- `toReal_liftUp` — the commutation `toReal ∘ liftUp = snoc ∘ (toReal × + height)`: the diagram square with k2.4's `toRealProd` closes, which is + how the k2.6 assembly will feed `pullback` (k2.4) from the induction + hypothesis stated at the grown dimension. + +**Deferred with a measured consumer**: the moment conservation under +containment (`prodMoment_split_of_support`, the `_of_support` pendant of +k2.0's `mean_split` components) and the containment transfer through the +split (k2.6b); the induction itself (`SignedSums.lean` name for name, +k2.6c). The detailed state lives in `FORMAL_STATUS.md`. +-/ + +import Discrepancy.Komlos.MeanSplit_en +import Discrepancy.Komlos.SplitDistance_en +import Discrepancy.Komlos.Transport_en + +/-! +# Level bridge: product space to grown dimension (k2.6a) + +`Discrepancy.Komlos_en.liftUp` embeds `(Fin d → ℤ) × Bool` into +`Fin (d+1) → ℤ` — the spatial part by `Fin.snoc`, the height `Bool` as the +integer `{0, 1}` at the last coordinate. `pushUp` pushes a distribution +along it (the `Function.extend` pattern of the k2.3 organ `push`), and the +bridges of this module state that **every** structure the assembly +consumes — mass, coordinate moments, height moment, shift distance, +support — is read through the embedding without loss. + +This is the discrete realization of the oracle's growing space: its +induction on the number of vectors applies the hypothesis in `E × ℝ` at +each split (`Komlos/SignedSums.lean` l.44-53); ours applies it at +`Fin (d+1) → ℤ`, where every brick of the lake (all generic in `d`) +already lives. +-/ + +namespace Discrepancy.Komlos_en + +/-- **Level embedding**: the product grid `(Fin d → ℤ) × Bool` embeds into +the next-dimension grid `Fin (d+1) → ℤ` — the spatial part by `Fin.snoc`, +the `Bool` height as the integer `{0, 1}` at the last coordinate. + +This is the discrete counterpart of the oracle's `incl b : E ↪ E × ℝ` +(`Komlos/Split.lean` l.31): where the oracle embeds `E` as the slice at +height `b` of `E × ℝ`, the lake embeds the pair `(x, b)` as a +dimension-`d+1` vector — the height becoming an integer coordinate valued +`0` or `1`. The transport `toReal` (k2.3) then reads it back as a real +coordinate, closing the square with `toRealProd` (k2.4, cf `toReal_liftUp`). -/ +def liftUp {d : ℕ} : ((Fin d → ℤ) × Bool) → (Fin (d + 1) → ℤ) := + fun y => Fin.snoc y.1 (if y.2 then 1 else 0) + +/-- Reading of the embedding on an inherited coordinate: the spatial part +is read unchanged. -/ +@[simp] lemma liftUp_apply_castSucc {d : ℕ} (y : (Fin d → ℤ) × Bool) + (i : Fin d) : liftUp y i.castSucc = y.1 i := by simp [liftUp] + +/-- Reading of the embedding on the height coordinate: the `Bool` becomes +the integer `{0, 1}`. -/ +@[simp] lemma liftUp_apply_last {d : ℕ} (y : (Fin d → ℤ) × Bool) : + liftUp y (Fin.last d) = if y.2 then 1 else 0 := by simp [liftUp] + +/-- The level embedding is **injective**: equal `snoc`s have equal tails +and equal bodies, and the height coordinate separates `false` from `true` +by `0 ≠ 1`. This is the glue of the `Finset.map`s of pushed supports. -/ +lemma liftUp_injective {d : ℕ} : Function.Injective (liftUp (d := d)) := by + rintro ⟨x₁, b₁⟩ ⟨x₂, b₂⟩ h + simp only [liftUp, Fin.snoc_inj] at h + obtain ⟨hxe, hqe⟩ := h + cases b₁ <;> cases b₂ <;> simp_all + +/-- The `Finset.Embedding` version of `liftUp`, for the `Finset.map`s of +pushed supports. -/ +def liftUpEmb {d : ℕ} : ((Fin d → ℤ) × Bool) ↪ (Fin (d + 1) → ℤ) := + ⟨liftUp, liftUp_injective⟩ + +/-- Reading of the wrapper embedding: `liftUpEmb` applies `liftUp`. This +is the syntactic bridge consumed by the `pushUp_apply` / `liftUp_apply_*` +rewrites on `Finset.map` images. -/ +lemma liftUpEmb_apply {d : ℕ} (y : (Fin d → ℤ) × Bool) : + liftUpEmb y = liftUp y := rfl + +/-- **Translations at height zero commute with the embedding**: +`liftUp y + snoc u 0 = liftUp (y.1 + u, y.2)`. This is the equation that +makes the shift-distance bridge (`shiftDistance_pushUp`) work: a base +translation `u`, embedded at height zero in the grown dimension, acts on +the image exactly as the product-space translation `(u, 0)`. -/ +lemma liftUp_add_snoc {d : ℕ} (y : (Fin d → ℤ) × Bool) (u : Fin d → ℤ) : + liftUp y + Fin.snoc u 0 = liftUp (y.1 + u, y.2) := by + funext j + induction j using Fin.lastCases with + | last => simp [liftUp] + | cast i => simp [liftUp, Pi.add_apply] + +/-- **Push-forward of a distribution along the level embedding**: +`pushUp Q (liftUp y) = Q y` (by `pushUp_apply`) and `pushUp Q z = 0` +off the image (by `pushUp_eq_zero`). + +This is the **same `Function.extend` pattern as the k2.3 organ `push`** +(the oracle's `Finsupp.embDomain`, `Komlos/Transport.lean` l.27-28) — and +not that organ itself: the k2.3 `push` is typed on the dimension +transport `(Fin d → ℤ) →+ (Fin d → ℝ)`, an additive morphism, whereas the +product source `(Fin d → ℤ) × Bool` carries no additive structure (`Bool` +has no inverse). The extension along an injection is the Mathlib organ +common to both. -/ +noncomputable def pushUp {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) : + (Fin (d + 1) → ℤ) → ℝ := + Function.extend liftUp Q 0 + +/-- On the image of the embedding, the push-forward reads the source +distribution. (In the oracle, this is the role of +`Finsupp.embDomain_apply_self`.) -/ +@[simp] lemma pushUp_apply {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (y : (Fin d → ℤ) × Bool) : pushUp Q (liftUp y) = Q y := + Function.Injective.extend_apply liftUp_injective Q 0 y + +/-- Off the image of the embedding, the push-forward is zero: points of +the dimension-`d+1` grid with no product preimage carry no mass. -/ +lemma pushUp_eq_zero {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + {z : Fin (d + 1) → ℤ} (hz : ∀ y, liftUp y ≠ z) : pushUp Q z = 0 := by + have hb : ¬∃ a, liftUp a = z := by + rintro ⟨a, rfl⟩ + exact hz a rfl + exact Function.extend_apply' Q (0 : (Fin (d + 1) → ℤ) → ℝ) z hb + +/-- The push-forward of a nonnegative function is nonnegative: every +point is either a value of the source, or zero. -/ +lemma pushUp_nonneg {d : ℕ} {Q : ((Fin d → ℤ) × Bool) → ℝ} + (hQ : ∀ y, 0 ≤ Q y) (z : Fin (d + 1) → ℤ) : 0 ≤ pushUp Q z := by + by_cases h : ∃ y, liftUp y = z + · obtain ⟨y, rfl⟩ := h + rw [pushUp_apply] + exact hQ y + · rw [pushUp_eq_zero Q (fun y hy => h ⟨y, hy⟩)] + +/-- **Mass is preserved by the push-forward**: summing the push-forward +over the transported support is summing the source — the `pushUp` +counterpart of `push_mass` (k2.3). -/ +lemma pushUp_mass {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) : + ∑ z ∈ SQ.map liftUpEmb, pushUp Q z = ∑ y ∈ SQ, Q y := by + simp only [Finset.sum_map, liftUpEmb_apply] + exact Finset.sum_congr rfl fun y _ => pushUp_apply Q y + +/-- **Exactness of the pushed support (forward direction)**: if every +point of `SQ` carries nonzero mass, so does every point of the +transported support. -/ +lemma pushUp_ne_zero_of_mem {d : ℕ} {Q : ((Fin d → ℤ) × Bool) → ℝ} + {SQ : Finset ((Fin d → ℤ) × Bool)} (hSQ : ∀ y ∈ SQ, Q y ≠ 0) : + ∀ z ∈ SQ.map liftUpEmb, pushUp Q z ≠ 0 := by + intro z hz + rw [Finset.mem_map] at hz + obtain ⟨y, hy, rfl⟩ := hz + simp only [liftUpEmb_apply] + rw [pushUp_apply] + exact hSQ y hy + +/-- **Exactness of the pushed support (return direction)**: if `SQ` +contains the support of `Q`, the transported image contains the support +of the push-forward. -/ +lemma pushUp_mem_map_of_ne_zero {d : ℕ} {Q : ((Fin d → ℤ) × Bool) → ℝ} + {SQ : Finset ((Fin d → ℤ) × Bool)} (hSQ : ∀ y, Q y ≠ 0 → y ∈ SQ) : + ∀ z, pushUp Q z ≠ 0 → z ∈ SQ.map liftUpEmb := by + intro z hz + by_cases hex : ∃ y, liftUp y = z + · obtain ⟨y, rfl⟩ := hex + rw [pushUp_apply] at hz + exact Finset.mem_map.mpr ⟨y, hSQ y hz, liftUpEmb_apply y⟩ + · rw [pushUp_eq_zero Q (fun y hy => absurd ⟨y, hy⟩ hex)] at hz + exact (hz rfl).elim + +/-- **Moment bridge, inherited coordinate**: the coordinate moment of the +push-forward, read at a `castSucc` coordinate, is the base moment of the +source — the spatial component of the barycenter crosses the embedding +unchanged. This is the first component of `mean_split` (k2.0) read +through the level bridge. -/ +lemma coordMoment_pushUp_castSucc {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) (i : Fin d) : + coordMoment (pushUp Q) (SQ.map liftUpEmb) i.castSucc = prodMoment Q SQ i := by + simp only [coordMoment, prodMoment, Finset.sum_map, liftUpEmb_apply] + exact Finset.sum_congr rfl fun y _ => by rw [pushUp_apply, liftUp_apply_castSucc] + +/-- **Moment bridge, height coordinate**: the coordinate moment of the +push-forward, read at the last coordinate, is the height moment of the +source — the `Bool` `{false, true}` read back as the real `{0, 1}`. This +is the second component of `mean_split` (k2.0): the split bit becomes the +height coordinate of the pushed barycenter. -/ +lemma coordMoment_pushUp_last {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) : + coordMoment (pushUp Q) (SQ.map liftUpEmb) (Fin.last d) + = heightMoment Q SQ := by + simp only [coordMoment, heightMoment, Finset.sum_map, liftUpEmb_apply] + refine Finset.sum_congr rfl fun y _ => ?_ + rw [pushUp_apply, liftUp_apply_last] + cases y.2 <;> simp + +/-- **Shift-distance bridge**: the shift distance of the push-forward, in +a direction embedded at height zero, is the product shift distance of the +source — `Δ(pushUp Q, snoc u 0) = Δprod(Q, u)`. This is what lets Claim +3.2 (k1.5, `shiftDistanceProd_split_le`) apply at the grown dimension: +the induction hypothesis on distances transports without loss. -/ +lemma shiftDistance_pushUp {d : ℕ} (Q : ((Fin d → ℤ) × Bool) → ℝ) + (SQ : Finset ((Fin d → ℤ) × Bool)) (u : Fin d → ℤ) : + shiftDistance (SQ.map liftUpEmb) (pushUp Q) (Fin.snoc u 0) + = shiftDistanceProd SQ Q u := by + simp only [shiftDistance, shiftDistanceProd, Finset.sum_map, liftUpEmb_apply] + refine congrArg _ (Finset.sum_congr rfl fun y _ => ?_) + rw [liftUp_add_snoc, pushUp_apply, pushUp_apply] + +/-- **Lake form of the oracle's `sum_smul_inl`** (`Komlos/Split.lean` +l.50-53): a sum of scaled vectors, each embedded at height zero by +`snoc · 0`, is itself a vector embedded at height zero — the weighted sum +of the spatial parts, with zero tail. + +Measured consumer: `Komlos/SignedSums.lean` l.54, where this identity +separates the height coordinate of the point produced by the induction +hypothesis (`rw [mean_split, sum_smul_inl, ...] at hmem`). -/ +lemma sum_smul_snoc {d : ℕ} {ι : Type*} (s : Finset ι) + (ε : ι → ℝ) (r : ι → (Fin d → ℝ)) : + ∑ i ∈ s, ε i • Fin.snoc (r i) (0 : ℝ) + = Fin.snoc (∑ i ∈ s, ε i • r i) (0 : ℝ) := by + funext j + induction j using Fin.lastCases with + | last => + simp only [Finset.sum_apply, Pi.smul_apply, Fin.snoc_last, smul_eq_mul, + mul_zero, Finset.sum_const_zero] + | cast i => + simp only [Fin.snoc_castSucc, Finset.sum_apply, Pi.smul_apply] + +/-- **Commutation of the transport with the embedding**: `toReal ∘ liftUp += snoc ∘ (toReal × height)` — the spatial part is transported by `toReal` +(k2.3), the `Bool` height becomes the real `{0, 1}`. + +This closes the square with `toRealProd` (k2.4): the transported image of +the pushed support in `Fin (d+1) → ℝ` is the `(y.1, height y.2)` reading +of the product embedding — the exact place where the dimension-`d+1` +induction conclusion feeds k2.4's `pullback`, stated in +`(Fin d → ℝ) × ℝ`. -/ +lemma toReal_liftUp {d : ℕ} (y : (Fin d → ℤ) × Bool) : + toReal (liftUp y) + = Fin.snoc (toReal y.1) (if y.2 then (1 : ℝ) else 0) := by + funext j + obtain ⟨x, b⟩ := y + cases b <;> induction j using Fin.lastCases <;> simp [liftUp] + +end Discrepancy.Komlos_en diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md index 2a72de52f4..09a6fe3e7c 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md @@ -66,6 +66,7 @@ boutes `k1..k5` ci-dessous ; issue de suivi : #17845. | **k2.3** | `Discrepancy.Komlos.toReal` : **le transport de dimension** — lève le bloqueur mesuré en k2.2 (`Fin d → ℤ` n'est pas un `ℝ`-module, `convexHull ℝ` y est inexprimable) en plongeant la grille entière dans `Fin d → ℝ`. Transposé de `Komlos/Transport.lean` (l.27-67). Briques closes : `toReal` + `toReal_injective` (plongement `→+` coordonnée-par-coordonnée, l'instance du lake — le `g ↦ g / N` de l'oracle étant une homothétie de plus), `push e P` (la poussée le long d'un morphisme additif **quelconque** entre les deux grilles sur `Function.extend` — l'organe Mathlib du prolongement le long d'une injection, équivalent du `Finsupp.embDomain` de l'oracle ; l'injectivité n'est requise que par les **lemmes**, pas par la définition), `push_apply` / `push_eq_zero` (les deux identités de calcul, l.32 et hors-image), `sum_push` (ré-indexation `Finset.sum_map`, l.35-36), `push_mass` (conservation de la masse, `mass_push` l.41-42), `coordMomentReal` + `coordMomentReal_push` (le barycentre transporté, forme générique — `mean_push` l.66-67) et **les deux ponts que k2.4 lit sur le support transporté** : `coordMoment_toReal` (le moment coordonné de la poussée par `toReal` **est** le `coordMoment` k2.0 — le pont de barycentre) et `toReal_mem_map_iff` / `toReal_mem_coe_iff` (le pont d'appartenance, formes `Finset` et `Set` — ce que `convexHull ℝ ↑(S.map …)` consommera). **Deux reportés, avec raison mesurée** : `shiftDist_push` (l.63-64 — chez l'oracle `shiftDist` vit sur le support Finsupp **canonique** ; la convention k1.1 passe le support `Finset` explicitement et l'énoncé transporté exige une ré-indexation de `S ∪ (S + u)` côté cible, une union dont la somme n'est pas la somme des sommes ; aucun consommateur k2.4 — la conclusion de convexité ne lit que le support et le barycentre) et `tvDist_push` / `IsDist.push` (l.44-55 — le vocabulaire `tvDist`/`IsDist` n'existe pas dans ce lake, décision de cadre k1.1 ; les restater serait du nouveau vocabulaire, pas du transport). Module FR + jumeau `_en`. 0 `sorry`. | brique k2 (transport de dimension) | **PROUVÉ** (k2.3, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning**, puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19078) | | **k2.4** | `Discrepancy.Komlos.pullback` : **le pas complet du pullback** — le théorème que k2.1 (algèbre), k2.2 (convexité) et k2.3 (transport) ont préparé, porté de `Komlos/Pullback.lean` l.55-92. Briques closes : `toRealProd` + `toRealProd_injective` + `toRealProdEmb` (l'embedding **produit** `(Fin d → ℤ) × Bool → (Fin d → ℝ) × ℝ` — la hauteur `Bool` du lake devient la coordonnée réelle `β` de l'oracle, `false ↦ 0` / `true ↦ 1` ; injectivité par `toReal_injective.eq_iff` + séparation `0 ≠ 1` — le ticket du `Finset.map` du support transporté), `mem_map_toRealProd_snd` (hauteurs de l'image dans `{0, 1}` — le pendant fini de `snd_eq_zero_or_one_of_mem_support_split`), `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` (les **caractérisations de support** de la scission sous `P ≥ 0`, lecture point-par-point des `mk_zero/one_mem_support_split` de l'oracle — le `max` exige la disjonction, le `min` la conjonction) et **le théorème `pullback`** : `(z, β)` dans l'enveloppe du support transporté de `split v P`, `v = 3·w` coordonnée par coordonnée, `β ≥ 1/3` ⇒ un signe `e ∈ {±1}` ramène `z + e • toReal w` dans l'enveloppe du support transporté de `P`. **Trois écarts de cadre arbitrés** : (a) `z` vit côté `ℝ` (le consommateur final Lemme 1.4 produit un barycentre côté grille réelle, d'où l'hypothèse dans l'image transportée) ; (b) `hSQ` exactitude du support de la scission en **hypothèse** (l'oracle la calcule via `Finsupp.support` ; le cadre `Finset` explicite la exige) ; (c) `hPsupp` relaie le support de `P`. Preuve décomposée sur les ingrédients k2.1-k2.3 : `Finset.mem_convexHull'` (`Analysis.Convex/Combination.lean:415` — vérifié au pin, forme `∃ w` exacte) décompose `(z, β)` en poids ; `Finset.abs_sum_le_sum_abs` (`Algebra/Order/BigOperators/Group/Finset.lean:315` — **dans le namespace `Finset`** au pin, l'identifiant nu n'existe pas) borne la part des poids hauteur 0 ; `exists_sign_mul_add_eq` (k2.1) produit `e` et `c` ; chaque point revient dans l'enveloppe par `add_smul_mem_convexHull` (k2.2, tranches hautes) ou l'appartenance directe d'une extrémité via `toReal_mem_map_iff` (k2.3, tranches basses) ; `sum_smul_mem_convexHull` (k2.2) referme. `sum_smul_inl` (`split.lean:50`) **reporté** : le port n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum` ; aucun consommateur mesuré). Module FR + jumeau `_en`, étendus (pas de nouveau fichier). 0 `sorry`. | brique k2 (pas complet) | **PROUVÉ** (k2.4, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (~30 s chacun), puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19081) | | **k2.5** | `Discrepancy.Komlos.mean_mem_convexHull` : **le cas de base `n = 0` de l'assemblage** — porté de `Komlos/Distribution.lean` l.105, module de l'oracle repris **nom pour nom** (nouveau `Distribution.lean` + jumeau `_en` ; le glob `.submodules` du lakefile le découvre — `Komlos.lean` n'est pas un agrégateur, aucun enregistrement). Énoncé : le barycentre — lu coordonnée par coordonnée, `fun i => coordMoment P S i` (k2.0) — d'une distribution positive (`hP`) de masse 1 (`hmass`) sur `S` appartient à l'enveloppe convexe du support **transporté** `S.map ⟨toReal, toReal_injective⟩` — la même forme exacte que la conclusion de `pullback` (k2.4), que la base `n = 0` de l'assemblage consommera (`SignedSums.lean` l.42). **La clé du port** : chez l'oracle le one-liner (`Finset.mem_convexHull'.2 ⟨S, …⟩`) tient parce que les poids demandés sont le `Finsupp` lui-même, **nul hors support par construction** ; le cadre `Finset` explicite du lake exigeait de construire ce poids sur la grille réelle — et c'est **déjà l'organe `push` de k2.3** (`push toReal P` sur `Function.extend`, nul hors image par construction, équivalent du `Finsupp.embDomain` de l'oracle) : aucun poids à inventer, la preuve redevient le one-liner oracle avec ses trois composantes lisant les organes k2.3 — `push_apply` (positivité des poids transportés, chaque point du support transporté relisant `P` à son unique antécédent), `push_mass` (masse conservée, le `mass_push` de l'oracle), `coordMoment_toReal` (le point produit, le `mean_push` de l'oracle — le barycente affirmé dans l'enveloppe est exactement celui que les moments k2.0 calculent). **Trois écarts de cadre arbitrés** (même famille que k2.4) : (a) le `mean` se lit coordonnée par coordonnée (`Fin d → ℤ` n'est pas un `ℝ`-module, bloqueur mesuré en k2.2) ; (b) `IsDist` devient deux hypothèses `hP`/`hmass` (la structure `Finsupp` portait ces faits par construction) ; (c) le support de l'énoncé est `S` transporté exact, pas un `s ⊇ support` arbitraire. **Reportés avec raison mesurée** : l'infrastructure sup/inf du module oracle (`mass_sup_add_mass_inf`, `mean_sup_add_mean_inf`, `support_inf_subset`, `support_sup_subset`) — aucun consommateur dans notre cadre (la préservation de masse à la scission est `split_mass` k1.2, consommée en hypothèse chaînée) ; et **`sum_smul_inl` (`split.lean:50`) acquiert un consommateur mesuré** par la lecture k1.7 du pas (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) — livré avec k2.6 où sa forme exacte se fixe. 0 `sorry`. | brique k2 (cas de base) | **PROUVÉ** (k2.5, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (31 s chacun, SUCCESS au premier round) ; `distinct_code_sorry = 0` ; jumeaux i18n `15/15 byte-identical` — voir PR) | ce PR (stack sur #19084) | +| **k2.6a** | `Discrepancy.Komlos.liftUp` : **le pont de niveau — premier préalable mécanique de l'assemblage k2.6**. Ce module n'a **pas de contrepartie oracle**, et cette absence est le fait technique que la brique documente : le Lemme 1.4 de l'oracle est quantifié sur `E` **variable** (`induction n with`, `SignedSums.lean` l.37), son hypothèse d'induction s'applique donc dans l'espace grandi `E × ℝ` (l.52) sans rien construire ; la base du lake `Fin d → ℤ` est **fixe**, et aucun organe k1.x/k2.x ne s'applique à une distribution sur un type réellement différent. **Design-gate arbitré et consigné dans le header du module** : (a) généralisation abstraite `X × Bool` et (b) espace produit itéré `(Fin d → ℤ) × (Fin n → Bool)` **rejetées** — toutes deux une seconde formalisation de la chaîne entière ; **(c) retenue : l'espace qui grandit est `Fin (d + k) → ℤ`**, réalisé par `liftUp : ((Fin d → ℤ) × Bool) → (Fin (d+1) → ℤ)` (partie spatiale par `Fin.snoc`, hauteur `Bool` comme l'entier `{0,1}` à la dernière coordonnée — la contrepartie discrète du `incl b : E ↪ E × ℝ` de l'oracle, `Split.lean` l.31), le miroir d'induction étant `induction n generalizing d` : chaque brique du lake étant générique en `d`, elles s'appliquent **telles quelles à la dimension suivante**. **Livré** : `liftUp` + `liftUp_injective` + `liftUpEmb`/`liftUpEmb_apply` (le pont syntaxique que les rewrites sur les images `Finset.map` exigent — mesuré au round 1 : `rw` ne voit pas `liftUpEmb y` comme `liftUp ?y`) ; `liftUp_add_snoc` (les translations de hauteur nulle commutent avec l'embedding — l'équation qui fait marcher le pont de distance) ; `pushUp` — la poussée le long de `liftUp` sur le **même pattern `Function.extend` que l'organe `push` de k2.3** (et non cet organe : celui-ci est typé sur un morphisme additif, le côté produit n'a pas d'opposé), avec sa lecture `apply`/`eq_zero`/`nonneg`/`mass` ; les **deux ponts de moment** (`coordMoment_pushUp_castSucc` = `prodMoment`, `coordMoment_pushUp_last` = `heightMoment` — les deux composantes de `mean_split` k2.0 lues à travers l'embedding) ; le **pont de distance** `shiftDistance_pushUp` (`Δ(pushUp Q, snoc u 0) = Δprod(Q, u)` — le Claim 3.2 de k1.5 s'applique à la dimension agrandie sans perte) ; l'**exactitude du support** dans les deux sens (`pushUp_ne_zero_of_mem` / `pushUp_mem_map_of_ne_zero`) ; `sum_smul_snoc` — **la forme lake du `sum_smul_inl` de l'oracle dont k2.5 annonçait le consommateur mesuré** (`Split.lean` l.50-53, consommé à `SignedSums.lean` l.54 : une somme pondérée de vecteurs embarqués à hauteur nulle reste à hauteur nulle) ; et `toReal_liftUp` (commutation `toReal ∘ liftUp = snoc ∘ (toReal × hauteur)` — le carré avec `toRealProd` k2.4 se referme : c'est par là que la conclusion d'induction à la dimension `d+1` nourrira `pullback`). **Reportés avec consommateur mesuré** : la conservation des moments sous contenance (`prodMoment_split_of_support`) et le transfert de contenance à travers la scission (k2.6b) ; l'induction elle-même, `SignedSums.lean` nom pour nom (k2.6c). **Trois classes d'erreur mesurées aux rounds 1-2** (consignées pour les portages suivants) : `rfl` échoue sur les lemmes de lecture de `Fin.snoc` au pin (version Tuple hétérogène via `dite`+cast, `Tuple/Basic.lean` l.515 — remplacé par `simp [liftUp]` sur `Fin.snoc_castSucc` l.526 / `Fin.snoc_last` l.539) ; `rw` est syntaxique et exige le pont `liftUpEmb_apply` sur les images `Finset.map` ; `cases` sur un terme non-variable (`y.2`) ne substitue pas dans le but — déstructurer la paire d'abord. Module FR + jumeau `_en` (header et docstring de module en français côté FR, convention du lake — advisory HALF-DONE de l'organe i18n levé). 0 `sorry`. | brique k2 (assemblage) | **PROUVÉ** (k2.6a, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (28 s chacun, SUCCESS au 3ᵉ round : 6 classes d'erreur des rounds 1-2 diagnostiquées contre le source Mathlib du pin) ; full-lib **8754 jobs** *Build completed successfully*, **37 warnings — identique à k2.5**, 0 sur les modules nouveaux ; `distinct_code_sorry = 0` (lake discrepancy) ; jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19087) | | **k3.1** | `Discrepancy.Komlos.tent` (`Komlos/Tent.lean` + jumeau `_en`) : **la tente discrète, port complet du module de l'oracle** — les 13 preuves reportées en c.885 (delivery #17918) sont closes, chacune adaptée du `grind` v4.34 vers le pin v4.33.0 / `db584cd6` (détail par preuve dans la note de fin de fichier). Sommes closes : `sum_tent` (Σ tent = M²), `sum_tent_sq` (3·Σ tent² = M(2M²+1)) ; Lipschitz `abs_tent_sub_le` (1-Lipschitz) ; pas `step`/`abs_step_le_one`/`step_eq_zero`/`sum_step_sq_le` (≤ 2M) ; télescopage `tent_sub_tent_eq_sum_step` ; **résultat porteur `sum_tent_sub_sq_le`** (Σ (tent M j − tent M (j−m))² ≤ 2·M·m²) — la borne `L²` **discrète** du Lemme 4.1. Adaptations mesurées : `abs_add`/`neg_le_abs_self` **absents au pin** (sondés — la triangulaire inverse passe par `abs_max_sub_max_le_abs` + `abs_abs_sub_abs_le_abs_sub`) ; `omega` ne splitte pas `\|j\|` sur ℤ (atome opaque) → composites `le_abs_self`+`abs_neg` ; l'énoncé `support_tent_subset` force `Set.Icc` (le `Icc` nu sous `open Finset` s'élabore en coercion Finset) ; bornes en cast entier global `((M+1:ℕ):ℤ)` ; `sum_range_sub'` absent → induction manuelle ; `rw` avec `f := id` échoue → normalisation `simp only [id]`. **Réaudit k3 contre l'oracle** : la voie Dahia est **totalement discrète** — `Grid.lean` consomme `sum_tent_sq` + `sum_tent_sub_sq_le` pour construire le poids normalisé `gridF N` (distance `L²` de translation ≤ \|m\|/(N·√12)) ; le « FTC sur segments » du papier est remplacé par la discrétisation sur grille (`intervalIntegral` absent de l'oracle) — la ligne de planification k3 est réécrite en conséquence. 0 `sorry`. | brique k3 (tente + L² discret) | **PROUVÉ** (k3.1, 10-06, `lake build` local EXIT=0 sur les deux jumeaux — 8708 jobs, `distinct_code_sorry = 0`, jumeaux i18n `1/1 byte-identical` — voir PR) | ce PR (branche `feature/komlos-k3-tent`) | | **k3.2** | `Discrepancy.Komlos.gridF` (`Komlos/Grid.lean` + jumeau `_en`) : **le poids normalisé unidimensionnel et sa borne `L²` de translation — port complet du `Komlos/Grid.lean` de l'oracle** (la voie k3 de l'oracle est désormais complète). Briques closes : `gridM` (demi-largeur `6·N`), `gridZ` (constante de normalisation = `∑ tent²`), `gridF` (`tent (gridM N) j / √(gridZ N)`), `cast_gridM`, `gridZ_eq` (**`gridZ N = 144·N³ + 2·N`**), `gridZ_pos`, `gridF_nonneg`, `support_gridF_subset`, `finsum_gridF_sq` (**masse totale `1`**), `sum_gridF_sub_sq`/`sum_gridF_sq` (formes `Finset` consommables), **résultat porteur `sum_gridF_sub_sq_le`** : distance `L²` au carré entre `gridF N` et son translaté par `m` ≤ `m²/(12·N²)` — l'analogue discret du Lemme 4.1, entrée directe de la discrétisation k4 (Lemme 1.5). Adaptations mesurées : le `positivity` de l'oracle sur `gridZ_pos` échoue au pin (stricte positivité dépend de `hN : 0 < N`) → cast + `linarith` ; le `linarith` final de `gridZ_eq` échoue sur le produit non-linéaire → normalisation `ring` explicite avant `linarith` ; `support_tent_subset` de ce lake étant typé `Set.Icc` (l'oracle : `Finset.Icc`), `support_gridF_subset` est prouvé directement (`Finset.mem_coe` + composite `le_abs_self`) ; l'API `finsum` (**existe au pin**, à la racine — sondée) permet le port quasi verbatim des énoncés de masse. **Correctif i18n embarqué** : `Tent_en.lean` passait en `namespace Discrepancy.Komlos` (seul `_en` du lake non suffixé — défaut #17918) ; il repasse en `Discrepancy.Komlos_en`, condition de l'import propre `Grid_en → Tent_en`. 0 `sorry`. | brique k3 (poids normalisé + L²) | **PROUVÉ** (k3.2, 10-06, `lake build` local EXIT=0 sur les trois cibles — 8710 jobs : `Grid`, `Grid_en`, `Tent_en` recompilé ; `distinct_code_sorry = 0`, jumeaux i18n `2/2 byte-identical` — voir PR) | ce PR (stack sur #19563) | | P3 | Banaszczyk 1998 / formes fortes des papiers 2025 **et 2026** | aspiration | **NON ENGAGÉ** — exige SDP + dualité, indépendance spectrale affine, brownien discret guidé, concentration matricielle : **aucun de cet étage n'existe dans Mathlib** (vérifié 2026-08-24). **Réaudité 2026-09-13** contre le Mathlib pinné (`520045ab`, v4.32.1) : le contournement proposé par arXiv:2609.11189 ne supprime pas l'obstruction, il la **déplace** — sa route exige la *variation totale directionnelle* d'une densité sur convexe ouvert et la *transformée de Banaszczyk* préservée sous translation, deux notions **absentes du même Mathlib** (`Banaszczyk` : 0 occurrence ; `totalVariation` n'existe que pour les mesures signées ; la théorie BV de Mathlib concerne la dérivabilité a.e. des fonctions de `ℝ`). Ce que ce papier rapproche, ce sont les *socles* : gaussiennes (`Probability/Distributions/Gaussian/*`) et `ConvexBody` (`Analysis/Convex/Body.lean`) sont présents ; le **pont** manque. Documenté, jamais promis. **Réaudité 2026-09-25** : la voie **élémentaire** de Karingula–Lovett (arXiv:2609.20979, constante `36`) **supprime** cet étage au lieu de le déplacer — sa mécanique est discrète (distance de décalage `Δ`, opérateur de scission `T_v`, induction sur `n` et `d`) à une seule exception, l'estimation de la densité-tente, qui se fait par FTC sur segments + Cauchy–Schwarz `L²` et **non** par de la théorie BV. Balayage des prérequis sur le checkout Mathlib local (`v4.32.0`) : famille **`norm_image_sub_le` présente** (dont `Analysis/Calculus/IntervalIntegral/DistLEIntegral.lean`), `totalVariation` toujours cantonné aux mesures vectorielles (`VectorMeasure/Decomposition/*`) — mais le papier n'en a plus besoin. Réserve de portée : ce balayage porte sur un checkout **voisin** (`v4.32.0`), pas sur le pin du lake (`520045ab`) — à re-vérifier avant la première boute `.lean`. Une formalisation Lean 4 tierce de cette preuve existe déjà (mise à jour du 2026-09-25 ci-dessous). | — | @@ -165,7 +166,7 @@ branche, jamais `main`. Issue de suivi : #17845. | **k1.7** | Correctif d'hypothèse **avant** k2 : l'invariance du support des briques k1 est insatisfiable aux décalages non nuls (mesuré, `eq_zero_of_image_add_eq_self`) → formes consommables sous **contention** `SupportContained` | fini | k1 | | **k2.0** | **Moments de la scission** (`mean_split`) — décomposition par composante du `mean_split` de Dahia (base `Fin d → ℤ` sans structure de `ℝ`-module : `coordMoment`/`prodMoment`, `heightMoment`), moment de hauteur = `splitBit` (`heightMoment_split`), **conservation du barycentre** par la scission (`prodMoment_split`) — l'item reporté par k1.6 | fini | k1, k1.6 | | **k2.0 — correctif de support** | **Formes consommables des moments** — `prodMoment_split_of_support` + `mean_split_of_support` sous `SupportContained S P {0, v, -v}` : k1.7 appliqué à k2.0 (`heightMoment_split` réutilisé inchangé), + contrôle positif `exists_supportContained_nonzero_shift` (`d = 1`, `v = 1`, `P` Dirac, `S = {-1, 0, 1}` via `supportContained_biUnion`) | fini | k1.7, k2.0 | -| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé** (Fin d → ℤ n’est pas un ℝ-module ; l’oracle énonce pullback sur E →₀ ℝ — le transport plonge la grille dans Fin d → ℝ où convexHull ℝ parle). **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Reste à ce lake, mesuré** : **l'assemblage k2.6 seul** — la lecture k1.7 du pas (`SignedSums.lean` l.37-58 : l'itération `induction n with` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_inl` au pas (l.53) et `pullback` en clôture). `sum_smul_inl` (`split.lean:50`) **a désormais un consommateur mesuré** (l.53) — livré avec k2.6, où sa forme exacte se fixe. | fini + induction | k1, k1.7, k2.0–k2.5 | +| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé** (Fin d → ℤ n’est pas un ℝ-module ; l’oracle énonce pullback sur E →₀ ℝ — le transport plonge la grille dans Fin d → ℝ où convexHull ℝ parle). **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Livré en k2.6a** : **le pont de niveau** (`Lift.lean` + jumeau `_en`, sans contrepartie oracle — l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, design-gate arbitré option (c) consigné dans le header du module ; `pushUp` sur le pattern `Function.extend` de k2.3, les ponts de moment / de distance / de support, et `sum_smul_snoc` — **la forme lake du `sum_smul_inl` dont k2.5 annonçait le consommateur mesuré**, désormais livrée, cf ligne k2.6a). **Reste à ce lake, mesuré** : **k2.6b** (la conservation des moments sous contenance `prodMoment_split_of_support` + le transfert de contenance à travers la scission) puis **k2.6c** — la lecture k1.7 du pas elle-même (`SignedSums.lean` l.37-58 nom pour nom : l'itération `induction n generalizing d` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_snoc` au pas (l.53-54) et `pullback` en clôture). | fini + induction | k1, k1.7, k2.0–k2.6a | | **k3** | Lemme 4.1 — densité-tente. **Réauditée contre l'oracle au pin (k3.1)** : la voie Dahia est **totalement discrète** — le « FTC sur segments » du papier est remplacé par la discrétisation sur grille, `intervalIntegral` **absent de l'oracle** — la dépendance `norm_image_sub_le` est sans objet. **LIVRÉE EN INTÉGRALITÉ** : k3.1 (`Tent.lean` complet, lignes k3.1/k3.2) puis k3.2 (`Grid.lean` complet — `gridF` normalisé, `gridZ_eq : gridZ N = 144·N³ + 2·N`, masse `1`, **`sum_gridF_sub_sq_le` : distance `L²` de translation ≤ m²/(12·N²)**, l'analogue discret du Lemme 4.1). **Reste** : k4 (Lemme 1.5, discrétisation). | fini (oracle discret, complet) | k3.1, k3.2 | | **k4** | Lemme 1.5 — discrétisation sur la grille, cas rationnel | fini | k3 | | **k5** | Assemblage Thm 1.2 sur `ℚ` (témoin `36`) + corollaires (`KomlosBansalJiangWeak`, Beck–Fiala régulier `72√k`) + notebooks `Search-09c`/`Search-09e` (ligne « course aux bornes » du 22/09/2026) | assemblage | k2, k4 | From ab45a625741a82490b218c34381806fabafb0ced Mon Sep 17 00:00:00 2001 From: jsboige Date: Tue, 6 Oct 2026 05:38:15 +0200 Subject: [PATCH 4/8] feat(lean,#17845): brique k2.6 -- sum_smul_inl generique (SignedSums + jumeau _en) Premiere brique de l'assemblage du Lemme 1.4 : nouveau module Komlos/SignedSums.lean repris nom pour nom de l'oracle gdahia/Komlos. sum_smul_inl generique en E (l'assistant du pas inductif, l.53) ; carte de genericite des organes mesuree en tete de module, voie beta close par la mesure, decision de cadre (voie alpha) consignee ouverte. lake build local deux jumeaux EXIT=0 (WSL v4.33.0, Mathlib db584cd6) ; distinct_code_sorry = 0 ; i18n 1/1 byte-identical ; FORMAL_STATUS.md rangee k2.6 + agregateur k2 (deps k2.0-k2.6). Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit bf7378c3824bb5a4fce7eb96650158ac3a2161f3) --- .../Discrepancy/Komlos/SignedSums.lean | 65 ++++++++++++++++++ .../Discrepancy/Komlos/SignedSums_en.lean | 67 +++++++++++++++++++ .../Search/discrepancy_lean/FORMAL_STATUS.md | 3 +- 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean new file mode 100644 index 0000000000..fba43ea3a3 --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean @@ -0,0 +1,65 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapté à `discrepancy_lean` (issue #17845, Karingula–Lovett distillation +arXiv:2609.20979) : toolchain v4.33.0, Mathlib `db584cd6`, convention i18n #4980. + +Le source Dahia original vit dans le dépôt `gdahia/Komlos` (module +`Komlos/SignedSums.lean`, toolchain v4.34.0, cadre `Finsupp` sur `E →₀ ℝ`). +L'assemblage final — l'itération `induction n with` du Lemme 1.4 — s'y lit +l.37-58. Ce module du lake ouvre la distillation : la première brique +`sum_smul_inl` y est livrée générique, la carte de consommation des organes +est mesurée en tête de module, la décision de cadre (voie α) est consignée. +-/ + +import Discrepancy.Basic + +/-! +# Sommes signées — assemblage du Lemme 1.4 (brique k2.6) + +L'objectif de ce module est l'assemblage final de la voie élémentaire +(Karingula–Lovett) : l'itération `induction n with` de l'oracle +`gdahia/Komlos` (`SignedSums.lean` l.37-58) qui consomme +`mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_inl` +au pas (l.53) et `pullback` en clôture (l.55). + +## Carte de généricité (mesurée au 2026-10-06, k2.5 tip 87b4f35871) + +L'induction de l'oracle ré-instancie ses organes à chaque niveau sur un +ambiant croissant `E → E × ℝ → (E × ℝ) × ℝ → …` — c'est la généralité de +`E` qui absorbe la croissance. Les organes k2.0–k2.5 du lake sont +monomorphes (`Fin d → ℤ`, hauteur `Bool`) : + +| Organe oracle | Notre lake | État | +|---|---|---| +| `split : (E →₀ ℝ) → (E × ℝ →₀ ℝ)` | `Split.split` (`Fin d → ℤ`, `× Bool`) | monomorphe | +| `mean_split` (barycentre conservé) | `MeanSplit.mean_split_of_support` | monomorphe | +| `shiftDist_split_le` | acquis k1.6 | monomorphe | +| `splitBit_eq` | `SplitBit` | monomorphe | +| `pullback` (générique) | `Pullback.pullback` (`toReal`/`toRealProd`) | monomorphe | +| `mean_mem_convexHull` | `Distribution.mean_mem_convexHull` (k2.5) | monomorphe | +| `sum_smul_inl` | **absent — livré ci-dessous, générique** | ✓ k2.6 | +| convexHull (`add_smul`/`sum_smul`/`mem_convexHull'`) | `Pullback` l.150/189/213 | ✓ génériques | + +L'écart d'architecture est ouvert : la mise au générique des organes +monomorphes (voie α) redémontrerait k2.0–k2.4 en forme générique ; la +voie β (ping-pong deux espaces) est close par la mesure — le pullback +ramène au hull de l'ambiant courant mais le split suivant s'applique à la +distribution scindée, l'ambiant croît à chaque niveau de toute façon. +Décision de cadre à consigner à la livraison. +-/ + +namespace Discrepancy.Komlos + +/-- La composante gauche d'une somme de vecteurs `ε i • (v i, 0)` est la +somme des composantes gauches — le pendant `Finset` du `sum_smul_inl` de +l'oracle (`split.lean` l.50), utilisé par la réécriture `rw [mean_split, +sum_smul_inl, …]` du pas inductif. Générique en `E` : c'est le seul +organe du pas que le lake n'avait pas, et il ne dépend pas de la grille. -/ +lemma sum_smul_inl {n : ℕ} {E : Type*} [AddCommGroup E] [Module ℝ E] + (ε : Fin n → ℝ) (v : Fin n → E) : + (∑ i, ε i • (v i, (0 : ℝ))) = (∑ i, ε i • v i, (0 : ℝ)) := by + refine Prod.ext ?_ ?_ <;> simp [Prod.smul_mk, Prod.fst_sum, Prod.snd_sum] + +end Discrepancy.Komlos diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean new file mode 100644 index 0000000000..801a628b6b --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean @@ -0,0 +1,67 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapted for `discrepancy_lean` (issue #17845, Karingula–Lovett distillation +arXiv:2609.20979): toolchain v4.33.0, Mathlib `db584cd6`, i18n convention #4980. + +The original Dahia source lives in the `gdahia/Komlos` repository (module +`Komlos/SignedSums.lean`, toolchain v4.34.0, `Finsupp` framework over +`E →₀ ℝ`). The final assembly — the `induction n with` iteration of +Lemma 1.4 — reads there at l.37-58. This lake module opens the +distillation: the first brick `sum_smul_inl` ships here in generic form, +the consumption map of the organs is measured at the top of the module, +and the framework decision (route α) is recorded. +-/ + +import Discrepancy.Basic_en + +/-! +# Signed sums — assembly of Lemma 1.4 (brick k2.6) + +The goal of this module is the final assembly of the elementary route +(Karingula–Lovett): the `induction n with` iteration of the +`gdahia/Komlos` oracle (`SignedSums.lean` l.37-58), which consumes +`mean_mem_convexHull` in the base case (l.42), `mean_split` + +`sum_smul_inl` in the step (l.53), and `pullback` in the closing (l.55). + +## Genericity map (measured on 2026-10-06, k2.5 tip 87b4f35871) + +The oracle's induction re-instantiates its organs at every level on a +growing ambient `E → E × ℝ → (E × ℝ) × ℝ → …` — it is the generality of +`E` that absorbs the growth. The lake's k2.0–k2.5 organs are monomorphic +(`Fin d → ℤ`, height `Bool`): + +| Oracle organ | Our lake | Status | +|---|---|---| +| `split : (E →₀ ℝ) → (E × ℝ →₀ ℝ)` | `Split.split` (`Fin d → ℤ`, `× Bool`) | monomorphic | +| `mean_split` (barycenter preserved) | `MeanSplit.mean_split_of_support` | monomorphic | +| `shiftDist_split_le` | acquired k1.6 | monomorphic | +| `splitBit_eq` | `SplitBit` | monomorphic | +| `pullback` (generic) | `Pullback.pullback` (`toReal`/`toRealProd`) | monomorphic | +| `mean_mem_convexHull` | `Distribution.mean_mem_convexHull` (k2.5) | monomorphic | +| `sum_smul_inl` | **missing — shipped below, generic** | ✓ k2.6 | +| convexHull (`add_smul`/`sum_smul`/`mem_convexHull'`) | `Pullback` l.150/189/213 | ✓ generic | + +The architectural gap stays open: moving the monomorphic organs to the +generic setting (route α) would re-prove k2.0–k2.4 in generic form; +route β (two-space ping-pong) is closed by measurement — the pullback +returns to the hull of the current ambient but the next split applies to +the split distribution, the ambient grows at every level anyway. +Framework decision to be recorded at delivery. +-/ + +namespace Discrepancy.Komlos_en + +/-- The left component of a sum of vectors `ε i • (v i, 0)` is the sum +of the left components — the `Finset` counterpart of the oracle's +`sum_smul_inl` (`split.lean` l.50), used by the rewrite `rw [mean_split, +sum_smul_inl, …]` of the inductive step. Generic in `E`: it is the only +organ of the step the lake did not have, and it does not depend on the +grid. -/ +lemma sum_smul_inl {n : ℕ} {E : Type*} [AddCommGroup E] [Module ℝ E] + (ε : Fin n → ℝ) (v : Fin n → E) : + (∑ i, ε i • (v i, (0 : ℝ))) = (∑ i, ε i • v i, (0 : ℝ)) := by + refine Prod.ext ?_ ?_ <;> simp [Prod.smul_mk, Prod.fst_sum, Prod.snd_sum] + +end Discrepancy.Komlos_en diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md index 09a6fe3e7c..8a8f8a2d25 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md @@ -67,6 +67,7 @@ boutes `k1..k5` ci-dessous ; issue de suivi : #17845. | **k2.4** | `Discrepancy.Komlos.pullback` : **le pas complet du pullback** — le théorème que k2.1 (algèbre), k2.2 (convexité) et k2.3 (transport) ont préparé, porté de `Komlos/Pullback.lean` l.55-92. Briques closes : `toRealProd` + `toRealProd_injective` + `toRealProdEmb` (l'embedding **produit** `(Fin d → ℤ) × Bool → (Fin d → ℝ) × ℝ` — la hauteur `Bool` du lake devient la coordonnée réelle `β` de l'oracle, `false ↦ 0` / `true ↦ 1` ; injectivité par `toReal_injective.eq_iff` + séparation `0 ≠ 1` — le ticket du `Finset.map` du support transporté), `mem_map_toRealProd_snd` (hauteurs de l'image dans `{0, 1}` — le pendant fini de `snd_eq_zero_or_one_of_mem_support_split`), `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` (les **caractérisations de support** de la scission sous `P ≥ 0`, lecture point-par-point des `mk_zero/one_mem_support_split` de l'oracle — le `max` exige la disjonction, le `min` la conjonction) et **le théorème `pullback`** : `(z, β)` dans l'enveloppe du support transporté de `split v P`, `v = 3·w` coordonnée par coordonnée, `β ≥ 1/3` ⇒ un signe `e ∈ {±1}` ramène `z + e • toReal w` dans l'enveloppe du support transporté de `P`. **Trois écarts de cadre arbitrés** : (a) `z` vit côté `ℝ` (le consommateur final Lemme 1.4 produit un barycentre côté grille réelle, d'où l'hypothèse dans l'image transportée) ; (b) `hSQ` exactitude du support de la scission en **hypothèse** (l'oracle la calcule via `Finsupp.support` ; le cadre `Finset` explicite la exige) ; (c) `hPsupp` relaie le support de `P`. Preuve décomposée sur les ingrédients k2.1-k2.3 : `Finset.mem_convexHull'` (`Analysis.Convex/Combination.lean:415` — vérifié au pin, forme `∃ w` exacte) décompose `(z, β)` en poids ; `Finset.abs_sum_le_sum_abs` (`Algebra/Order/BigOperators/Group/Finset.lean:315` — **dans le namespace `Finset`** au pin, l'identifiant nu n'existe pas) borne la part des poids hauteur 0 ; `exists_sign_mul_add_eq` (k2.1) produit `e` et `c` ; chaque point revient dans l'enveloppe par `add_smul_mem_convexHull` (k2.2, tranches hautes) ou l'appartenance directe d'une extrémité via `toReal_mem_map_iff` (k2.3, tranches basses) ; `sum_smul_mem_convexHull` (k2.2) referme. `sum_smul_inl` (`split.lean:50`) **reporté** : le port n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum` ; aucun consommateur mesuré). Module FR + jumeau `_en`, étendus (pas de nouveau fichier). 0 `sorry`. | brique k2 (pas complet) | **PROUVÉ** (k2.4, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (~30 s chacun), puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19081) | | **k2.5** | `Discrepancy.Komlos.mean_mem_convexHull` : **le cas de base `n = 0` de l'assemblage** — porté de `Komlos/Distribution.lean` l.105, module de l'oracle repris **nom pour nom** (nouveau `Distribution.lean` + jumeau `_en` ; le glob `.submodules` du lakefile le découvre — `Komlos.lean` n'est pas un agrégateur, aucun enregistrement). Énoncé : le barycentre — lu coordonnée par coordonnée, `fun i => coordMoment P S i` (k2.0) — d'une distribution positive (`hP`) de masse 1 (`hmass`) sur `S` appartient à l'enveloppe convexe du support **transporté** `S.map ⟨toReal, toReal_injective⟩` — la même forme exacte que la conclusion de `pullback` (k2.4), que la base `n = 0` de l'assemblage consommera (`SignedSums.lean` l.42). **La clé du port** : chez l'oracle le one-liner (`Finset.mem_convexHull'.2 ⟨S, …⟩`) tient parce que les poids demandés sont le `Finsupp` lui-même, **nul hors support par construction** ; le cadre `Finset` explicite du lake exigeait de construire ce poids sur la grille réelle — et c'est **déjà l'organe `push` de k2.3** (`push toReal P` sur `Function.extend`, nul hors image par construction, équivalent du `Finsupp.embDomain` de l'oracle) : aucun poids à inventer, la preuve redevient le one-liner oracle avec ses trois composantes lisant les organes k2.3 — `push_apply` (positivité des poids transportés, chaque point du support transporté relisant `P` à son unique antécédent), `push_mass` (masse conservée, le `mass_push` de l'oracle), `coordMoment_toReal` (le point produit, le `mean_push` de l'oracle — le barycente affirmé dans l'enveloppe est exactement celui que les moments k2.0 calculent). **Trois écarts de cadre arbitrés** (même famille que k2.4) : (a) le `mean` se lit coordonnée par coordonnée (`Fin d → ℤ` n'est pas un `ℝ`-module, bloqueur mesuré en k2.2) ; (b) `IsDist` devient deux hypothèses `hP`/`hmass` (la structure `Finsupp` portait ces faits par construction) ; (c) le support de l'énoncé est `S` transporté exact, pas un `s ⊇ support` arbitraire. **Reportés avec raison mesurée** : l'infrastructure sup/inf du module oracle (`mass_sup_add_mass_inf`, `mean_sup_add_mean_inf`, `support_inf_subset`, `support_sup_subset`) — aucun consommateur dans notre cadre (la préservation de masse à la scission est `split_mass` k1.2, consommée en hypothèse chaînée) ; et **`sum_smul_inl` (`split.lean:50`) acquiert un consommateur mesuré** par la lecture k1.7 du pas (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) — livré avec k2.6 où sa forme exacte se fixe. 0 `sorry`. | brique k2 (cas de base) | **PROUVÉ** (k2.5, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (31 s chacun, SUCCESS au premier round) ; `distinct_code_sorry = 0` ; jumeaux i18n `15/15 byte-identical` — voir PR) | ce PR (stack sur #19084) | | **k2.6a** | `Discrepancy.Komlos.liftUp` : **le pont de niveau — premier préalable mécanique de l'assemblage k2.6**. Ce module n'a **pas de contrepartie oracle**, et cette absence est le fait technique que la brique documente : le Lemme 1.4 de l'oracle est quantifié sur `E` **variable** (`induction n with`, `SignedSums.lean` l.37), son hypothèse d'induction s'applique donc dans l'espace grandi `E × ℝ` (l.52) sans rien construire ; la base du lake `Fin d → ℤ` est **fixe**, et aucun organe k1.x/k2.x ne s'applique à une distribution sur un type réellement différent. **Design-gate arbitré et consigné dans le header du module** : (a) généralisation abstraite `X × Bool` et (b) espace produit itéré `(Fin d → ℤ) × (Fin n → Bool)` **rejetées** — toutes deux une seconde formalisation de la chaîne entière ; **(c) retenue : l'espace qui grandit est `Fin (d + k) → ℤ`**, réalisé par `liftUp : ((Fin d → ℤ) × Bool) → (Fin (d+1) → ℤ)` (partie spatiale par `Fin.snoc`, hauteur `Bool` comme l'entier `{0,1}` à la dernière coordonnée — la contrepartie discrète du `incl b : E ↪ E × ℝ` de l'oracle, `Split.lean` l.31), le miroir d'induction étant `induction n generalizing d` : chaque brique du lake étant générique en `d`, elles s'appliquent **telles quelles à la dimension suivante**. **Livré** : `liftUp` + `liftUp_injective` + `liftUpEmb`/`liftUpEmb_apply` (le pont syntaxique que les rewrites sur les images `Finset.map` exigent — mesuré au round 1 : `rw` ne voit pas `liftUpEmb y` comme `liftUp ?y`) ; `liftUp_add_snoc` (les translations de hauteur nulle commutent avec l'embedding — l'équation qui fait marcher le pont de distance) ; `pushUp` — la poussée le long de `liftUp` sur le **même pattern `Function.extend` que l'organe `push` de k2.3** (et non cet organe : celui-ci est typé sur un morphisme additif, le côté produit n'a pas d'opposé), avec sa lecture `apply`/`eq_zero`/`nonneg`/`mass` ; les **deux ponts de moment** (`coordMoment_pushUp_castSucc` = `prodMoment`, `coordMoment_pushUp_last` = `heightMoment` — les deux composantes de `mean_split` k2.0 lues à travers l'embedding) ; le **pont de distance** `shiftDistance_pushUp` (`Δ(pushUp Q, snoc u 0) = Δprod(Q, u)` — le Claim 3.2 de k1.5 s'applique à la dimension agrandie sans perte) ; l'**exactitude du support** dans les deux sens (`pushUp_ne_zero_of_mem` / `pushUp_mem_map_of_ne_zero`) ; `sum_smul_snoc` — **la forme lake du `sum_smul_inl` de l'oracle dont k2.5 annonçait le consommateur mesuré** (`Split.lean` l.50-53, consommé à `SignedSums.lean` l.54 : une somme pondérée de vecteurs embarqués à hauteur nulle reste à hauteur nulle) ; et `toReal_liftUp` (commutation `toReal ∘ liftUp = snoc ∘ (toReal × hauteur)` — le carré avec `toRealProd` k2.4 se referme : c'est par là que la conclusion d'induction à la dimension `d+1` nourrira `pullback`). **Reportés avec consommateur mesuré** : la conservation des moments sous contenance (`prodMoment_split_of_support`) et le transfert de contenance à travers la scission (k2.6b) ; l'induction elle-même, `SignedSums.lean` nom pour nom (k2.6c). **Trois classes d'erreur mesurées aux rounds 1-2** (consignées pour les portages suivants) : `rfl` échoue sur les lemmes de lecture de `Fin.snoc` au pin (version Tuple hétérogène via `dite`+cast, `Tuple/Basic.lean` l.515 — remplacé par `simp [liftUp]` sur `Fin.snoc_castSucc` l.526 / `Fin.snoc_last` l.539) ; `rw` est syntaxique et exige le pont `liftUpEmb_apply` sur les images `Finset.map` ; `cases` sur un terme non-variable (`y.2`) ne substitue pas dans le but — déstructurer la paire d'abord. Module FR + jumeau `_en` (header et docstring de module en français côté FR, convention du lake — advisory HALF-DONE de l'organe i18n levé). 0 `sorry`. | brique k2 (assemblage) | **PROUVÉ** (k2.6a, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (28 s chacun, SUCCESS au 3ᵉ round : 6 classes d'erreur des rounds 1-2 diagnostiquées contre le source Mathlib du pin) ; full-lib **8754 jobs** *Build completed successfully*, **37 warnings — identique à k2.5**, 0 sur les modules nouveaux ; `distinct_code_sorry = 0` (lake discrepancy) ; jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19087) | +| **k2.6** | `Discrepancy.Komlos.sum_smul_inl` : **première brique de l'assemblage** — nouveau module `Komlos/SignedSums.lean` (+ jumeau `_en`), repris nom pour nom de l'oracle. Livré : `sum_smul_inl` **générique** (`{E : Type*} [AddCommGroup E] [Module ℝ E]`, `∑ i, ε i • (v i, 0) = (∑ i, ε i • v i, 0)` par `Prod.ext` + `Prod.smul_mk`/`fst_sum`/`snd_sum` — les trois noms **vérifiés au pin** : `smul_mk` en `GroupWithZero/Action/Prod.lean`, `fst_sum`/`snd_sum` versions additives de `fst_prod`/`snd_prod` en `BigOperators/Pi.lean` l.155, toolkit identique à `Convex/Combination.lean` l.460) — l'assistant que l'oracle invoque au pas de l'induction (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) pour distribuer une somme de couples sur la première composante. **Carte de généricité (mesurée, en tête du module)** : l'induction de l'oracle ré-instancie ses organes à chaque niveau sur un ambiant croissant `E → E × ℝ → …` ; les organes k2.0–k2.5 de ce lake sont **monomorphes** (`Fin d → ℤ`, hauteur `Bool`) — split, mean_split_of_support, shiftDist_split_le, splitBit_eq, pullback, mean_mem_convexHull. Déjà génériques dans le lake : `segment_repr`, `add_smul_mem_convexHull`, `sum_smul_mem_convexHull` (Pullback.lean l.150/189/213). `sum_smul_inl` était **absent** — livré générique ici, consommable à tout niveau. **Voie β (ping-pong deux espaces) close par la mesure** : le pas oracle écrit simultanément dans `E` (les `v i`) et `ℝ` (les hauteurs) au même niveau d'itération, pas en alternance. **Décision de cadre pour l'assemblage restant (voie α : généraliser les organes monomorphes) ouverte et consignée** : cette brique ne la tranche pas. 0 `sorry`. | brique k2 (assemblage, 1/…) | **PROUVÉ** (k2.6 brique 1, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19087) | | **k3.1** | `Discrepancy.Komlos.tent` (`Komlos/Tent.lean` + jumeau `_en`) : **la tente discrète, port complet du module de l'oracle** — les 13 preuves reportées en c.885 (delivery #17918) sont closes, chacune adaptée du `grind` v4.34 vers le pin v4.33.0 / `db584cd6` (détail par preuve dans la note de fin de fichier). Sommes closes : `sum_tent` (Σ tent = M²), `sum_tent_sq` (3·Σ tent² = M(2M²+1)) ; Lipschitz `abs_tent_sub_le` (1-Lipschitz) ; pas `step`/`abs_step_le_one`/`step_eq_zero`/`sum_step_sq_le` (≤ 2M) ; télescopage `tent_sub_tent_eq_sum_step` ; **résultat porteur `sum_tent_sub_sq_le`** (Σ (tent M j − tent M (j−m))² ≤ 2·M·m²) — la borne `L²` **discrète** du Lemme 4.1. Adaptations mesurées : `abs_add`/`neg_le_abs_self` **absents au pin** (sondés — la triangulaire inverse passe par `abs_max_sub_max_le_abs` + `abs_abs_sub_abs_le_abs_sub`) ; `omega` ne splitte pas `\|j\|` sur ℤ (atome opaque) → composites `le_abs_self`+`abs_neg` ; l'énoncé `support_tent_subset` force `Set.Icc` (le `Icc` nu sous `open Finset` s'élabore en coercion Finset) ; bornes en cast entier global `((M+1:ℕ):ℤ)` ; `sum_range_sub'` absent → induction manuelle ; `rw` avec `f := id` échoue → normalisation `simp only [id]`. **Réaudit k3 contre l'oracle** : la voie Dahia est **totalement discrète** — `Grid.lean` consomme `sum_tent_sq` + `sum_tent_sub_sq_le` pour construire le poids normalisé `gridF N` (distance `L²` de translation ≤ \|m\|/(N·√12)) ; le « FTC sur segments » du papier est remplacé par la discrétisation sur grille (`intervalIntegral` absent de l'oracle) — la ligne de planification k3 est réécrite en conséquence. 0 `sorry`. | brique k3 (tente + L² discret) | **PROUVÉ** (k3.1, 10-06, `lake build` local EXIT=0 sur les deux jumeaux — 8708 jobs, `distinct_code_sorry = 0`, jumeaux i18n `1/1 byte-identical` — voir PR) | ce PR (branche `feature/komlos-k3-tent`) | | **k3.2** | `Discrepancy.Komlos.gridF` (`Komlos/Grid.lean` + jumeau `_en`) : **le poids normalisé unidimensionnel et sa borne `L²` de translation — port complet du `Komlos/Grid.lean` de l'oracle** (la voie k3 de l'oracle est désormais complète). Briques closes : `gridM` (demi-largeur `6·N`), `gridZ` (constante de normalisation = `∑ tent²`), `gridF` (`tent (gridM N) j / √(gridZ N)`), `cast_gridM`, `gridZ_eq` (**`gridZ N = 144·N³ + 2·N`**), `gridZ_pos`, `gridF_nonneg`, `support_gridF_subset`, `finsum_gridF_sq` (**masse totale `1`**), `sum_gridF_sub_sq`/`sum_gridF_sq` (formes `Finset` consommables), **résultat porteur `sum_gridF_sub_sq_le`** : distance `L²` au carré entre `gridF N` et son translaté par `m` ≤ `m²/(12·N²)` — l'analogue discret du Lemme 4.1, entrée directe de la discrétisation k4 (Lemme 1.5). Adaptations mesurées : le `positivity` de l'oracle sur `gridZ_pos` échoue au pin (stricte positivité dépend de `hN : 0 < N`) → cast + `linarith` ; le `linarith` final de `gridZ_eq` échoue sur le produit non-linéaire → normalisation `ring` explicite avant `linarith` ; `support_tent_subset` de ce lake étant typé `Set.Icc` (l'oracle : `Finset.Icc`), `support_gridF_subset` est prouvé directement (`Finset.mem_coe` + composite `le_abs_self`) ; l'API `finsum` (**existe au pin**, à la racine — sondée) permet le port quasi verbatim des énoncés de masse. **Correctif i18n embarqué** : `Tent_en.lean` passait en `namespace Discrepancy.Komlos` (seul `_en` du lake non suffixé — défaut #17918) ; il repasse en `Discrepancy.Komlos_en`, condition de l'import propre `Grid_en → Tent_en`. 0 `sorry`. | brique k3 (poids normalisé + L²) | **PROUVÉ** (k3.2, 10-06, `lake build` local EXIT=0 sur les trois cibles — 8710 jobs : `Grid`, `Grid_en`, `Tent_en` recompilé ; `distinct_code_sorry = 0`, jumeaux i18n `2/2 byte-identical` — voir PR) | ce PR (stack sur #19563) | | P3 | Banaszczyk 1998 / formes fortes des papiers 2025 **et 2026** | aspiration | **NON ENGAGÉ** — exige SDP + dualité, indépendance spectrale affine, brownien discret guidé, concentration matricielle : **aucun de cet étage n'existe dans Mathlib** (vérifié 2026-08-24). **Réaudité 2026-09-13** contre le Mathlib pinné (`520045ab`, v4.32.1) : le contournement proposé par arXiv:2609.11189 ne supprime pas l'obstruction, il la **déplace** — sa route exige la *variation totale directionnelle* d'une densité sur convexe ouvert et la *transformée de Banaszczyk* préservée sous translation, deux notions **absentes du même Mathlib** (`Banaszczyk` : 0 occurrence ; `totalVariation` n'existe que pour les mesures signées ; la théorie BV de Mathlib concerne la dérivabilité a.e. des fonctions de `ℝ`). Ce que ce papier rapproche, ce sont les *socles* : gaussiennes (`Probability/Distributions/Gaussian/*`) et `ConvexBody` (`Analysis/Convex/Body.lean`) sont présents ; le **pont** manque. Documenté, jamais promis. **Réaudité 2026-09-25** : la voie **élémentaire** de Karingula–Lovett (arXiv:2609.20979, constante `36`) **supprime** cet étage au lieu de le déplacer — sa mécanique est discrète (distance de décalage `Δ`, opérateur de scission `T_v`, induction sur `n` et `d`) à une seule exception, l'estimation de la densité-tente, qui se fait par FTC sur segments + Cauchy–Schwarz `L²` et **non** par de la théorie BV. Balayage des prérequis sur le checkout Mathlib local (`v4.32.0`) : famille **`norm_image_sub_le` présente** (dont `Analysis/Calculus/IntervalIntegral/DistLEIntegral.lean`), `totalVariation` toujours cantonné aux mesures vectorielles (`VectorMeasure/Decomposition/*`) — mais le papier n'en a plus besoin. Réserve de portée : ce balayage porte sur un checkout **voisin** (`v4.32.0`), pas sur le pin du lake (`520045ab`) — à re-vérifier avant la première boute `.lean`. Une formalisation Lean 4 tierce de cette preuve existe déjà (mise à jour du 2026-09-25 ci-dessous). | — | @@ -166,7 +167,7 @@ branche, jamais `main`. Issue de suivi : #17845. | **k1.7** | Correctif d'hypothèse **avant** k2 : l'invariance du support des briques k1 est insatisfiable aux décalages non nuls (mesuré, `eq_zero_of_image_add_eq_self`) → formes consommables sous **contention** `SupportContained` | fini | k1 | | **k2.0** | **Moments de la scission** (`mean_split`) — décomposition par composante du `mean_split` de Dahia (base `Fin d → ℤ` sans structure de `ℝ`-module : `coordMoment`/`prodMoment`, `heightMoment`), moment de hauteur = `splitBit` (`heightMoment_split`), **conservation du barycentre** par la scission (`prodMoment_split`) — l'item reporté par k1.6 | fini | k1, k1.6 | | **k2.0 — correctif de support** | **Formes consommables des moments** — `prodMoment_split_of_support` + `mean_split_of_support` sous `SupportContained S P {0, v, -v}` : k1.7 appliqué à k2.0 (`heightMoment_split` réutilisé inchangé), + contrôle positif `exists_supportContained_nonzero_shift` (`d = 1`, `v = 1`, `P` Dirac, `S = {-1, 0, 1}` via `supportContained_biUnion`) | fini | k1.7, k2.0 | -| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé** (Fin d → ℤ n’est pas un ℝ-module ; l’oracle énonce pullback sur E →₀ ℝ — le transport plonge la grille dans Fin d → ℝ où convexHull ℝ parle). **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Livré en k2.6a** : **le pont de niveau** (`Lift.lean` + jumeau `_en`, sans contrepartie oracle — l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, design-gate arbitré option (c) consigné dans le header du module ; `pushUp` sur le pattern `Function.extend` de k2.3, les ponts de moment / de distance / de support, et `sum_smul_snoc` — **la forme lake du `sum_smul_inl` dont k2.5 annonçait le consommateur mesuré**, désormais livrée, cf ligne k2.6a). **Reste à ce lake, mesuré** : **k2.6b** (la conservation des moments sous contenance `prodMoment_split_of_support` + le transfert de contenance à travers la scission) puis **k2.6c** — la lecture k1.7 du pas elle-même (`SignedSums.lean` l.37-58 nom pour nom : l'itération `induction n generalizing d` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_snoc` au pas (l.53-54) et `pullback` en clôture). | fini + induction | k1, k1.7, k2.0–k2.6a | +| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé**. **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Livré en k2.6a** : **le pont de niveau** (`Lift.lean` + jumeau `_en`, sans contrepartie oracle — l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, design-gate arbitré option (c) consigné dans le header du module ; `pushUp` sur le pattern `Function.extend` de k2.3, les ponts de moment / de distance / de support, et `sum_smul_snoc` — **la forme lake du `sum_smul_inl` dont k2.5 annonçait le consommateur mesuré**, désormais livrée, cf ligne k2.6a). **Livré en k2.6 (brique 1)** : `sum_smul_inl` **générique** (module `Komlos/SignedSums.lean` + jumeau `_en`, repris nom pour nom — la carte de généricité des organes y est mesurée, la voie β close par la mesure, la décision de cadre consignée ouverte). **Reste à ce lake, mesuré** : **k2.6b** (la conservation des moments sous contenance `prodMoment_split_of_support` + le transfert de contenance à travers la scission) puis **k2.6c** — la lecture k1.7 du pas elle-même (`SignedSums.lean` l.37-58 nom pour nom : l'itération `induction n generalizing d` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_snoc` au pas (l.53-54) et `pullback` en clôture). | fini + induction | k1, k1.7, k2.0–k2.6 | | **k3** | Lemme 4.1 — densité-tente. **Réauditée contre l'oracle au pin (k3.1)** : la voie Dahia est **totalement discrète** — le « FTC sur segments » du papier est remplacé par la discrétisation sur grille, `intervalIntegral` **absent de l'oracle** — la dépendance `norm_image_sub_le` est sans objet. **LIVRÉE EN INTÉGRALITÉ** : k3.1 (`Tent.lean` complet, lignes k3.1/k3.2) puis k3.2 (`Grid.lean` complet — `gridF` normalisé, `gridZ_eq : gridZ N = 144·N³ + 2·N`, masse `1`, **`sum_gridF_sub_sq_le` : distance `L²` de translation ≤ m²/(12·N²)**, l'analogue discret du Lemme 4.1). **Reste** : k4 (Lemme 1.5, discrétisation). | fini (oracle discret, complet) | k3.1, k3.2 | | **k4** | Lemme 1.5 — discrétisation sur la grille, cas rationnel | fini | k3 | | **k5** | Assemblage Thm 1.2 sur `ℚ` (témoin `36`) + corollaires (`KomlosBansalJiangWeak`, Beck–Fiala régulier `72√k`) + notebooks `Search-09c`/`Search-09e` (ligne « course aux bornes » du 22/09/2026) | assemblage | k2, k4 | From d851e33f1727b19236caaa698ea9d2ebbed464b7 Mon Sep 17 00:00:00 2001 From: jsboige Date: Tue, 6 Oct 2026 05:52:12 +0200 Subject: [PATCH 5/8] docs(lean,#17845): k2.6 -- decision de cadre arbitree k2.6a, position inl vs snoc La decision de cadre que la carte de genericite laissait ouverte est arbitree par la brique k2.6a (#19089, option (c) : Fin (d + k) par liftUp). sum_smul_inl se positionne comme l'organe generique R-modulaire complementaire de sum_smul_snoc (forme lake cote grille) : consommable cote transport/hull. Docstrings FR/EN + rangee FORMAL_STATUS. Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit 27b59d46c49607fdf7041317fb063a9145115b1a) --- .../Discrepancy/Komlos/SignedSums.lean | 16 +++++++++------- .../Discrepancy/Komlos/SignedSums_en.lean | 15 ++++++++------- .../Search/discrepancy_lean/FORMAL_STATUS.md | 2 +- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean index fba43ea3a3..24265be21a 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean @@ -10,7 +10,8 @@ Le source Dahia original vit dans le dépôt `gdahia/Komlos` (module L'assemblage final — l'itération `induction n with` du Lemme 1.4 — s'y lit l.37-58. Ce module du lake ouvre la distillation : la première brique `sum_smul_inl` y est livrée générique, la carte de consommation des organes -est mesurée en tête de module, la décision de cadre (voie α) est consignée. +est mesurée en tête de module, la décision de cadre (option (c), +arbitrée en k2.6a) y est consignée. -/ import Discrepancy.Basic @@ -42,12 +43,13 @@ monomorphes (`Fin d → ℤ`, hauteur `Bool`) : | `sum_smul_inl` | **absent — livré ci-dessous, générique** | ✓ k2.6 | | convexHull (`add_smul`/`sum_smul`/`mem_convexHull'`) | `Pullback` l.150/189/213 | ✓ génériques | -L'écart d'architecture est ouvert : la mise au générique des organes -monomorphes (voie α) redémontrerait k2.0–k2.4 en forme générique ; la -voie β (ping-pong deux espaces) est close par la mesure — le pullback -ramène au hull de l'ambiant courant mais le split suivant s'applique à la -distribution scindée, l'ambiant croît à chaque niveau de toute façon. -Décision de cadre à consigner à la livraison. +L'écart d'architecture est **arbitré en k2.6a** (option (c) : l'espace +qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, sans +re-généralisation des organes — la voie α est écartée, la voie β +(ping-pong deux espaces) est close par la mesure). `sum_smul_inl` reste +l'organe générique ℝ-modulaire, **complémentaire de `sum_smul_snoc`** +(k2.6a, forme lake côté grille) : consommable côté transport/hull, où +les moments vivent dans `ℝ`. -/ namespace Discrepancy.Komlos diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean index 801a628b6b..63069e76d2 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean @@ -11,7 +11,7 @@ The original Dahia source lives in the `gdahia/Komlos` repository (module Lemma 1.4 — reads there at l.37-58. This lake module opens the distillation: the first brick `sum_smul_inl` ships here in generic form, the consumption map of the organs is measured at the top of the module, -and the framework decision (route α) is recorded. +and the framework decision (option (c), arbitrated in k2.6a) is recorded. -/ import Discrepancy.Basic_en @@ -43,12 +43,13 @@ growing ambient `E → E × ℝ → (E × ℝ) × ℝ → …` — it is the gen | `sum_smul_inl` | **missing — shipped below, generic** | ✓ k2.6 | | convexHull (`add_smul`/`sum_smul`/`mem_convexHull'`) | `Pullback` l.150/189/213 | ✓ generic | -The architectural gap stays open: moving the monomorphic organs to the -generic setting (route α) would re-prove k2.0–k2.4 in generic form; -route β (two-space ping-pong) is closed by measurement — the pullback -returns to the hull of the current ambient but the next split applies to -the split distribution, the ambient grows at every level anyway. -Framework decision to be recorded at delivery. +The architectural gap is **arbitrated in k2.6a** (option (c): the growing +space is realized as `Fin (d + k) → ℤ` via the `liftUp` embedding, +without re-generalizing the organs — route α is set aside, route β +(two-space ping-pong) is closed by measurement). `sum_smul_inl` remains +the generic ℝ-modular organ, **complementary to `sum_smul_snoc`** +(k2.6a, lake form on the grid side): consumable on the transport/hull +side, where the moments live in `ℝ`. -/ namespace Discrepancy.Komlos_en diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md index 8a8f8a2d25..863f75439d 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md @@ -67,7 +67,7 @@ boutes `k1..k5` ci-dessous ; issue de suivi : #17845. | **k2.4** | `Discrepancy.Komlos.pullback` : **le pas complet du pullback** — le théorème que k2.1 (algèbre), k2.2 (convexité) et k2.3 (transport) ont préparé, porté de `Komlos/Pullback.lean` l.55-92. Briques closes : `toRealProd` + `toRealProd_injective` + `toRealProdEmb` (l'embedding **produit** `(Fin d → ℤ) × Bool → (Fin d → ℝ) × ℝ` — la hauteur `Bool` du lake devient la coordonnée réelle `β` de l'oracle, `false ↦ 0` / `true ↦ 1` ; injectivité par `toReal_injective.eq_iff` + séparation `0 ≠ 1` — le ticket du `Finset.map` du support transporté), `mem_map_toRealProd_snd` (hauteurs de l'image dans `{0, 1}` — le pendant fini de `snd_eq_zero_or_one_of_mem_support_split`), `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` (les **caractérisations de support** de la scission sous `P ≥ 0`, lecture point-par-point des `mk_zero/one_mem_support_split` de l'oracle — le `max` exige la disjonction, le `min` la conjonction) et **le théorème `pullback`** : `(z, β)` dans l'enveloppe du support transporté de `split v P`, `v = 3·w` coordonnée par coordonnée, `β ≥ 1/3` ⇒ un signe `e ∈ {±1}` ramène `z + e • toReal w` dans l'enveloppe du support transporté de `P`. **Trois écarts de cadre arbitrés** : (a) `z` vit côté `ℝ` (le consommateur final Lemme 1.4 produit un barycentre côté grille réelle, d'où l'hypothèse dans l'image transportée) ; (b) `hSQ` exactitude du support de la scission en **hypothèse** (l'oracle la calcule via `Finsupp.support` ; le cadre `Finset` explicite la exige) ; (c) `hPsupp` relaie le support de `P`. Preuve décomposée sur les ingrédients k2.1-k2.3 : `Finset.mem_convexHull'` (`Analysis.Convex/Combination.lean:415` — vérifié au pin, forme `∃ w` exacte) décompose `(z, β)` en poids ; `Finset.abs_sum_le_sum_abs` (`Algebra/Order/BigOperators/Group/Finset.lean:315` — **dans le namespace `Finset`** au pin, l'identifiant nu n'existe pas) borne la part des poids hauteur 0 ; `exists_sign_mul_add_eq` (k2.1) produit `e` et `c` ; chaque point revient dans l'enveloppe par `add_smul_mem_convexHull` (k2.2, tranches hautes) ou l'appartenance directe d'une extrémité via `toReal_mem_map_iff` (k2.3, tranches basses) ; `sum_smul_mem_convexHull` (k2.2) referme. `sum_smul_inl` (`split.lean:50`) **reporté** : le port n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum` ; aucun consommateur mesuré). Module FR + jumeau `_en`, étendus (pas de nouveau fichier). 0 `sorry`. | brique k2 (pas complet) | **PROUVÉ** (k2.4, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (~30 s chacun), puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19081) | | **k2.5** | `Discrepancy.Komlos.mean_mem_convexHull` : **le cas de base `n = 0` de l'assemblage** — porté de `Komlos/Distribution.lean` l.105, module de l'oracle repris **nom pour nom** (nouveau `Distribution.lean` + jumeau `_en` ; le glob `.submodules` du lakefile le découvre — `Komlos.lean` n'est pas un agrégateur, aucun enregistrement). Énoncé : le barycentre — lu coordonnée par coordonnée, `fun i => coordMoment P S i` (k2.0) — d'une distribution positive (`hP`) de masse 1 (`hmass`) sur `S` appartient à l'enveloppe convexe du support **transporté** `S.map ⟨toReal, toReal_injective⟩` — la même forme exacte que la conclusion de `pullback` (k2.4), que la base `n = 0` de l'assemblage consommera (`SignedSums.lean` l.42). **La clé du port** : chez l'oracle le one-liner (`Finset.mem_convexHull'.2 ⟨S, …⟩`) tient parce que les poids demandés sont le `Finsupp` lui-même, **nul hors support par construction** ; le cadre `Finset` explicite du lake exigeait de construire ce poids sur la grille réelle — et c'est **déjà l'organe `push` de k2.3** (`push toReal P` sur `Function.extend`, nul hors image par construction, équivalent du `Finsupp.embDomain` de l'oracle) : aucun poids à inventer, la preuve redevient le one-liner oracle avec ses trois composantes lisant les organes k2.3 — `push_apply` (positivité des poids transportés, chaque point du support transporté relisant `P` à son unique antécédent), `push_mass` (masse conservée, le `mass_push` de l'oracle), `coordMoment_toReal` (le point produit, le `mean_push` de l'oracle — le barycente affirmé dans l'enveloppe est exactement celui que les moments k2.0 calculent). **Trois écarts de cadre arbitrés** (même famille que k2.4) : (a) le `mean` se lit coordonnée par coordonnée (`Fin d → ℤ` n'est pas un `ℝ`-module, bloqueur mesuré en k2.2) ; (b) `IsDist` devient deux hypothèses `hP`/`hmass` (la structure `Finsupp` portait ces faits par construction) ; (c) le support de l'énoncé est `S` transporté exact, pas un `s ⊇ support` arbitraire. **Reportés avec raison mesurée** : l'infrastructure sup/inf du module oracle (`mass_sup_add_mass_inf`, `mean_sup_add_mean_inf`, `support_inf_subset`, `support_sup_subset`) — aucun consommateur dans notre cadre (la préservation de masse à la scission est `split_mass` k1.2, consommée en hypothèse chaînée) ; et **`sum_smul_inl` (`split.lean:50`) acquiert un consommateur mesuré** par la lecture k1.7 du pas (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) — livré avec k2.6 où sa forme exacte se fixe. 0 `sorry`. | brique k2 (cas de base) | **PROUVÉ** (k2.5, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (31 s chacun, SUCCESS au premier round) ; `distinct_code_sorry = 0` ; jumeaux i18n `15/15 byte-identical` — voir PR) | ce PR (stack sur #19084) | | **k2.6a** | `Discrepancy.Komlos.liftUp` : **le pont de niveau — premier préalable mécanique de l'assemblage k2.6**. Ce module n'a **pas de contrepartie oracle**, et cette absence est le fait technique que la brique documente : le Lemme 1.4 de l'oracle est quantifié sur `E` **variable** (`induction n with`, `SignedSums.lean` l.37), son hypothèse d'induction s'applique donc dans l'espace grandi `E × ℝ` (l.52) sans rien construire ; la base du lake `Fin d → ℤ` est **fixe**, et aucun organe k1.x/k2.x ne s'applique à une distribution sur un type réellement différent. **Design-gate arbitré et consigné dans le header du module** : (a) généralisation abstraite `X × Bool` et (b) espace produit itéré `(Fin d → ℤ) × (Fin n → Bool)` **rejetées** — toutes deux une seconde formalisation de la chaîne entière ; **(c) retenue : l'espace qui grandit est `Fin (d + k) → ℤ`**, réalisé par `liftUp : ((Fin d → ℤ) × Bool) → (Fin (d+1) → ℤ)` (partie spatiale par `Fin.snoc`, hauteur `Bool` comme l'entier `{0,1}` à la dernière coordonnée — la contrepartie discrète du `incl b : E ↪ E × ℝ` de l'oracle, `Split.lean` l.31), le miroir d'induction étant `induction n generalizing d` : chaque brique du lake étant générique en `d`, elles s'appliquent **telles quelles à la dimension suivante**. **Livré** : `liftUp` + `liftUp_injective` + `liftUpEmb`/`liftUpEmb_apply` (le pont syntaxique que les rewrites sur les images `Finset.map` exigent — mesuré au round 1 : `rw` ne voit pas `liftUpEmb y` comme `liftUp ?y`) ; `liftUp_add_snoc` (les translations de hauteur nulle commutent avec l'embedding — l'équation qui fait marcher le pont de distance) ; `pushUp` — la poussée le long de `liftUp` sur le **même pattern `Function.extend` que l'organe `push` de k2.3** (et non cet organe : celui-ci est typé sur un morphisme additif, le côté produit n'a pas d'opposé), avec sa lecture `apply`/`eq_zero`/`nonneg`/`mass` ; les **deux ponts de moment** (`coordMoment_pushUp_castSucc` = `prodMoment`, `coordMoment_pushUp_last` = `heightMoment` — les deux composantes de `mean_split` k2.0 lues à travers l'embedding) ; le **pont de distance** `shiftDistance_pushUp` (`Δ(pushUp Q, snoc u 0) = Δprod(Q, u)` — le Claim 3.2 de k1.5 s'applique à la dimension agrandie sans perte) ; l'**exactitude du support** dans les deux sens (`pushUp_ne_zero_of_mem` / `pushUp_mem_map_of_ne_zero`) ; `sum_smul_snoc` — **la forme lake du `sum_smul_inl` de l'oracle dont k2.5 annonçait le consommateur mesuré** (`Split.lean` l.50-53, consommé à `SignedSums.lean` l.54 : une somme pondérée de vecteurs embarqués à hauteur nulle reste à hauteur nulle) ; et `toReal_liftUp` (commutation `toReal ∘ liftUp = snoc ∘ (toReal × hauteur)` — le carré avec `toRealProd` k2.4 se referme : c'est par là que la conclusion d'induction à la dimension `d+1` nourrira `pullback`). **Reportés avec consommateur mesuré** : la conservation des moments sous contenance (`prodMoment_split_of_support`) et le transfert de contenance à travers la scission (k2.6b) ; l'induction elle-même, `SignedSums.lean` nom pour nom (k2.6c). **Trois classes d'erreur mesurées aux rounds 1-2** (consignées pour les portages suivants) : `rfl` échoue sur les lemmes de lecture de `Fin.snoc` au pin (version Tuple hétérogène via `dite`+cast, `Tuple/Basic.lean` l.515 — remplacé par `simp [liftUp]` sur `Fin.snoc_castSucc` l.526 / `Fin.snoc_last` l.539) ; `rw` est syntaxique et exige le pont `liftUpEmb_apply` sur les images `Finset.map` ; `cases` sur un terme non-variable (`y.2`) ne substitue pas dans le but — déstructurer la paire d'abord. Module FR + jumeau `_en` (header et docstring de module en français côté FR, convention du lake — advisory HALF-DONE de l'organe i18n levé). 0 `sorry`. | brique k2 (assemblage) | **PROUVÉ** (k2.6a, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (28 s chacun, SUCCESS au 3ᵉ round : 6 classes d'erreur des rounds 1-2 diagnostiquées contre le source Mathlib du pin) ; full-lib **8754 jobs** *Build completed successfully*, **37 warnings — identique à k2.5**, 0 sur les modules nouveaux ; `distinct_code_sorry = 0` (lake discrepancy) ; jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19087) | -| **k2.6** | `Discrepancy.Komlos.sum_smul_inl` : **première brique de l'assemblage** — nouveau module `Komlos/SignedSums.lean` (+ jumeau `_en`), repris nom pour nom de l'oracle. Livré : `sum_smul_inl` **générique** (`{E : Type*} [AddCommGroup E] [Module ℝ E]`, `∑ i, ε i • (v i, 0) = (∑ i, ε i • v i, 0)` par `Prod.ext` + `Prod.smul_mk`/`fst_sum`/`snd_sum` — les trois noms **vérifiés au pin** : `smul_mk` en `GroupWithZero/Action/Prod.lean`, `fst_sum`/`snd_sum` versions additives de `fst_prod`/`snd_prod` en `BigOperators/Pi.lean` l.155, toolkit identique à `Convex/Combination.lean` l.460) — l'assistant que l'oracle invoque au pas de l'induction (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) pour distribuer une somme de couples sur la première composante. **Carte de généricité (mesurée, en tête du module)** : l'induction de l'oracle ré-instancie ses organes à chaque niveau sur un ambiant croissant `E → E × ℝ → …` ; les organes k2.0–k2.5 de ce lake sont **monomorphes** (`Fin d → ℤ`, hauteur `Bool`) — split, mean_split_of_support, shiftDist_split_le, splitBit_eq, pullback, mean_mem_convexHull. Déjà génériques dans le lake : `segment_repr`, `add_smul_mem_convexHull`, `sum_smul_mem_convexHull` (Pullback.lean l.150/189/213). `sum_smul_inl` était **absent** — livré générique ici, consommable à tout niveau. **Voie β (ping-pong deux espaces) close par la mesure** : le pas oracle écrit simultanément dans `E` (les `v i`) et `ℝ` (les hauteurs) au même niveau d'itération, pas en alternance. **Décision de cadre pour l'assemblage restant (voie α : généraliser les organes monomorphes) ouverte et consignée** : cette brique ne la tranche pas. 0 `sorry`. | brique k2 (assemblage, 1/…) | **PROUVÉ** (k2.6 brique 1, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19087) | +| **k2.6** | `Discrepancy.Komlos.sum_smul_inl` : **première brique de l'assemblage** — nouveau module `Komlos/SignedSums.lean` (+ jumeau `_en`), repris nom pour nom de l'oracle. Livré : `sum_smul_inl` **générique** (`{E : Type*} [AddCommGroup E] [Module ℝ E]`, `∑ i, ε i • (v i, 0) = (∑ i, ε i • v i, 0)` par `Prod.ext` + `Prod.smul_mk`/`fst_sum`/`snd_sum` — les trois noms **vérifiés au pin** : `smul_mk` en `GroupWithZero/Action/Prod.lean`, `fst_sum`/`snd_sum` versions additives de `fst_prod`/`snd_prod` en `BigOperators/Pi.lean` l.155, toolkit identique à `Convex/Combination.lean` l.460) — l'assistant que l'oracle invoque au pas de l'induction (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) pour distribuer une somme de couples sur la première composante. **Carte de généricité (mesurée, en tête du module)** : l'induction de l'oracle ré-instancie ses organes à chaque niveau sur un ambiant croissant `E → E × ℝ → …` ; les organes k2.0–k2.5 de ce lake sont **monomorphes** (`Fin d → ℤ`, hauteur `Bool`) — split, mean_split_of_support, shiftDist_split_le, splitBit_eq, pullback, mean_mem_convexHull. Déjà génériques dans le lake : `segment_repr`, `add_smul_mem_convexHull`, `sum_smul_mem_convexHull` (Pullback.lean l.150/189/213). `sum_smul_inl` était **absent** — livré générique ici, consommable à tout niveau. **Voie β (ping-pong deux espaces) close par la mesure** : le pas oracle écrit simultanément dans `E` (les `v i`) et `ℝ` (les hauteurs) au même niveau d'itération, pas en alternance. **Décision de cadre arbitrée en k2.6a** (option (c) : l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par `liftUp`, la voie α est écartée — cf ligne k2.6a) ; `sum_smul_inl` se positionne comme l'organe générique ℝ-modulaire **complémentaire de `sum_smul_snoc`** (k2.6a, forme lake côté grille), consommable côté transport/hull. 0 `sorry`. | brique k2 (assemblage, 1/…) | **PROUVÉ** (k2.6 brique 1, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19089) | | **k3.1** | `Discrepancy.Komlos.tent` (`Komlos/Tent.lean` + jumeau `_en`) : **la tente discrète, port complet du module de l'oracle** — les 13 preuves reportées en c.885 (delivery #17918) sont closes, chacune adaptée du `grind` v4.34 vers le pin v4.33.0 / `db584cd6` (détail par preuve dans la note de fin de fichier). Sommes closes : `sum_tent` (Σ tent = M²), `sum_tent_sq` (3·Σ tent² = M(2M²+1)) ; Lipschitz `abs_tent_sub_le` (1-Lipschitz) ; pas `step`/`abs_step_le_one`/`step_eq_zero`/`sum_step_sq_le` (≤ 2M) ; télescopage `tent_sub_tent_eq_sum_step` ; **résultat porteur `sum_tent_sub_sq_le`** (Σ (tent M j − tent M (j−m))² ≤ 2·M·m²) — la borne `L²` **discrète** du Lemme 4.1. Adaptations mesurées : `abs_add`/`neg_le_abs_self` **absents au pin** (sondés — la triangulaire inverse passe par `abs_max_sub_max_le_abs` + `abs_abs_sub_abs_le_abs_sub`) ; `omega` ne splitte pas `\|j\|` sur ℤ (atome opaque) → composites `le_abs_self`+`abs_neg` ; l'énoncé `support_tent_subset` force `Set.Icc` (le `Icc` nu sous `open Finset` s'élabore en coercion Finset) ; bornes en cast entier global `((M+1:ℕ):ℤ)` ; `sum_range_sub'` absent → induction manuelle ; `rw` avec `f := id` échoue → normalisation `simp only [id]`. **Réaudit k3 contre l'oracle** : la voie Dahia est **totalement discrète** — `Grid.lean` consomme `sum_tent_sq` + `sum_tent_sub_sq_le` pour construire le poids normalisé `gridF N` (distance `L²` de translation ≤ \|m\|/(N·√12)) ; le « FTC sur segments » du papier est remplacé par la discrétisation sur grille (`intervalIntegral` absent de l'oracle) — la ligne de planification k3 est réécrite en conséquence. 0 `sorry`. | brique k3 (tente + L² discret) | **PROUVÉ** (k3.1, 10-06, `lake build` local EXIT=0 sur les deux jumeaux — 8708 jobs, `distinct_code_sorry = 0`, jumeaux i18n `1/1 byte-identical` — voir PR) | ce PR (branche `feature/komlos-k3-tent`) | | **k3.2** | `Discrepancy.Komlos.gridF` (`Komlos/Grid.lean` + jumeau `_en`) : **le poids normalisé unidimensionnel et sa borne `L²` de translation — port complet du `Komlos/Grid.lean` de l'oracle** (la voie k3 de l'oracle est désormais complète). Briques closes : `gridM` (demi-largeur `6·N`), `gridZ` (constante de normalisation = `∑ tent²`), `gridF` (`tent (gridM N) j / √(gridZ N)`), `cast_gridM`, `gridZ_eq` (**`gridZ N = 144·N³ + 2·N`**), `gridZ_pos`, `gridF_nonneg`, `support_gridF_subset`, `finsum_gridF_sq` (**masse totale `1`**), `sum_gridF_sub_sq`/`sum_gridF_sq` (formes `Finset` consommables), **résultat porteur `sum_gridF_sub_sq_le`** : distance `L²` au carré entre `gridF N` et son translaté par `m` ≤ `m²/(12·N²)` — l'analogue discret du Lemme 4.1, entrée directe de la discrétisation k4 (Lemme 1.5). Adaptations mesurées : le `positivity` de l'oracle sur `gridZ_pos` échoue au pin (stricte positivité dépend de `hN : 0 < N`) → cast + `linarith` ; le `linarith` final de `gridZ_eq` échoue sur le produit non-linéaire → normalisation `ring` explicite avant `linarith` ; `support_tent_subset` de ce lake étant typé `Set.Icc` (l'oracle : `Finset.Icc`), `support_gridF_subset` est prouvé directement (`Finset.mem_coe` + composite `le_abs_self`) ; l'API `finsum` (**existe au pin**, à la racine — sondée) permet le port quasi verbatim des énoncés de masse. **Correctif i18n embarqué** : `Tent_en.lean` passait en `namespace Discrepancy.Komlos` (seul `_en` du lake non suffixé — défaut #17918) ; il repasse en `Discrepancy.Komlos_en`, condition de l'import propre `Grid_en → Tent_en`. 0 `sorry`. | brique k3 (poids normalisé + L²) | **PROUVÉ** (k3.2, 10-06, `lake build` local EXIT=0 sur les trois cibles — 8710 jobs : `Grid`, `Grid_en`, `Tent_en` recompilé ; `distinct_code_sorry = 0`, jumeaux i18n `2/2 byte-identical` — voir PR) | ce PR (stack sur #19563) | | P3 | Banaszczyk 1998 / formes fortes des papiers 2025 **et 2026** | aspiration | **NON ENGAGÉ** — exige SDP + dualité, indépendance spectrale affine, brownien discret guidé, concentration matricielle : **aucun de cet étage n'existe dans Mathlib** (vérifié 2026-08-24). **Réaudité 2026-09-13** contre le Mathlib pinné (`520045ab`, v4.32.1) : le contournement proposé par arXiv:2609.11189 ne supprime pas l'obstruction, il la **déplace** — sa route exige la *variation totale directionnelle* d'une densité sur convexe ouvert et la *transformée de Banaszczyk* préservée sous translation, deux notions **absentes du même Mathlib** (`Banaszczyk` : 0 occurrence ; `totalVariation` n'existe que pour les mesures signées ; la théorie BV de Mathlib concerne la dérivabilité a.e. des fonctions de `ℝ`). Ce que ce papier rapproche, ce sont les *socles* : gaussiennes (`Probability/Distributions/Gaussian/*`) et `ConvexBody` (`Analysis/Convex/Body.lean`) sont présents ; le **pont** manque. Documenté, jamais promis. **Réaudité 2026-09-25** : la voie **élémentaire** de Karingula–Lovett (arXiv:2609.20979, constante `36`) **supprime** cet étage au lieu de le déplacer — sa mécanique est discrète (distance de décalage `Δ`, opérateur de scission `T_v`, induction sur `n` et `d`) à une seule exception, l'estimation de la densité-tente, qui se fait par FTC sur segments + Cauchy–Schwarz `L²` et **non** par de la théorie BV. Balayage des prérequis sur le checkout Mathlib local (`v4.32.0`) : famille **`norm_image_sub_le` présente** (dont `Analysis/Calculus/IntervalIntegral/DistLEIntegral.lean`), `totalVariation` toujours cantonné aux mesures vectorielles (`VectorMeasure/Decomposition/*`) — mais le papier n'en a plus besoin. Réserve de portée : ce balayage porte sur un checkout **voisin** (`v4.32.0`), pas sur le pin du lake (`520045ab`) — à re-vérifier avant la première boute `.lean`. Une formalisation Lean 4 tierce de cette preuve existe déjà (mise à jour du 2026-09-25 ci-dessous). | — | From 913a51528d9f69c72fcfc52076cc4b83a06cd280 Mon Sep 17 00:00:00 2001 From: jsboige Date: Tue, 6 Oct 2026 08:34:11 +0200 Subject: [PATCH 6/8] feat(lean,#17845): brique k2.6b -- la scission sous contention dans la dimension agrandie MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `Komlos/LiftSplit.lean` + jumeau `_en` : sans contrepartie oracle (le `Finsupp` transporte son support gratuitement, le cadre `Finset` du lake paie ce transport) - 5 énoncés : transfert de contenance (`supportContained_pushUp_split`), conservation des moments liftée (`coordMoment_pushUp_split_of_support`/`_last`), lecture du support (`pushUp_split_ne_zero`), forme `{0, snoc u 0, −snoc u 0}` (`supportContained_pushUp_split_three`) - Consommateur mesuré : k2.6c — l'induction elle-même (`SignedSums.lean` l.44-55) - FORMAL_STATUS.md : rangée k2.6b + agrégateur (reste k2.6c seul, déps k2.0–k2.6b) + dédoublonnage de la rangée k2.6 (artefact du restack #19425) Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit 60444936edd638b4db416ecc549d3fa734c3d9c5) --- .../Discrepancy/Komlos/LiftSplit.lean | 221 +++++++++++++++++ .../Discrepancy/Komlos/LiftSplit_en.lean | 222 ++++++++++++++++++ .../Search/discrepancy_lean/FORMAL_STATUS.md | 5 +- 3 files changed, 446 insertions(+), 2 deletions(-) create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit.lean create mode 100644 MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit_en.lean diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit.lean new file mode 100644 index 0000000000..ea88f58a8a --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit.lean @@ -0,0 +1,221 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapté à `discrepancy_lean` (issue #17845, Karingula–Lovett distillation +arXiv:2609.20979) : toolchain v4.33.0, Mathlib `db584cd6`, convention i18n #4980. + +Le source Dahia original vit dans le dépôt `gdahia/Komlos` (toolchain +v4.34.0, cadre `Finsupp` sur `E →₀ ℝ`). Ce module n'a **pas de contrepartie +oracle nom pour nom** : chez l'oracle, l'hypothèse d'induction s'applique à +la distribution scindée dans `E × ℝ` sans aucune précondition de support — +le `Finsupp` transporte son support gratuitement (`Finsupp.embDomain`) ; +c'est le cadre `Finset` explicite du lake qui doit payer ce transport, et +ce paiement est précisément l'objet de cette brique. + +**Portée de ce commit** (brique k2.6b, `lake build SUCCESS` requis, 0 +`sorry`) — la scission sous contention, lue dans la dimension agrandie +`Fin (d+1) → ℤ` : + +- `pushUp_split_ne_zero` — lecture du support de la poussée : toute masse + de `pushUp (split w P)` vit sur l'image de `liftUp` et provient d'une + masse de `P` à distance `± w` de sa base (l'auxiliaire que consomme le + transfert de contenance) ; +- `supportContained_pushUp_split` — **le transfert de contenance à + travers la scission** : si `S` contient le support de `P` et ses + translatés par `A`, et `A` est stable par `± w`, alors l'image liftée + `(S ×ˢ univ).map liftUpEmb` contient le support de `pushUp (split w P)` + et ses translatés par les décalages embarqués `Fin.snoc · 0` de `A` ; +- `coordMoment_pushUp_split_of_support` — **la conservation du moment de + base sous contenance, au niveau lifté** : le moment coordonné de la + scission-poussée, lu en coordonnée héritée `i.castSucc`, est le moment + de `P` en `i` — la composition du pont `coordMoment_pushUp_castSucc` + (k2.6a) avec `prodMoment_split_of_support` (k2.0) ; +- `coordMoment_pushUp_split_last` — la composante de hauteur : le moment + de la scission-poussée en dernière coordonnée est le bit de scission + (`coordMoment_pushUp_last` (k2.6a) × `heightMoment_split` (k2.0)) ; +- `supportContained_pushUp_split_three` — la forme `{0, snoc u 0, + −snoc u 0}` que le cran suivant de l'induction consomme : instance du + transfert par monotonie (`SupportContained.mono`), les trois décalages + étant les images `snoc · 0` de `0`, `u`, `−u`. + +**Consommateur mesuré** : l'induction du Lemme 1.4 (brique k2.6c, oracle +`Komlos/SignedSums.lean` l.44-55) applique son hypothèse d'induction à +`split (3 • v_last) P` dans l'espace agrandi — chez nous, à `pushUp +(split w P)` dans `Fin (d+1) → ℤ`. Les préconditions de support et les +ré-écritures de barycentre que cet appel exige sont exactement les cinq +énoncés ci-dessus : la contenance pour instancier l'hypothèse +(`supportContained_pushUp_split_three`), les moments pour réécrire le +point qu'elle produit (`coordMoment_pushUp_split_of_support` et +`_last`, le miroir lake du `rw [mean_split, …] at hmem` de l.54). + +**Différé** : l'induction elle-même (`SignedSums.lean` nom pour nom, +k2.6c). L'état détaillé vit dans `FORMAL_STATUS.md`. +-/ + +import Discrepancy.Komlos.Containment +import Discrepancy.Komlos.Lift +import Discrepancy.Komlos.MeanSplit +import Discrepancy.Komlos.Split + +/-! +# La scission sous contention, dans la dimension agrandie (k2.6b) + +Chez l'oracle, le pas de l'induction du Lemme 1.4 est gratuit côté +support : `split v P` est un `Finsupp` sur `E × ℝ`, dont le support se +transporte par `Finsupp.embDomain` sans précondition. Dans le cadre +`Finset` explicite du lake, le même pas doit **prouver** que le support +de la scission-poussée `pushUp (split w P)` est contenu — et le restera +au cran suivant de l'induction — dans l'image liftée du support de +départ. + +Ce module paie ce double coût en une brique : le **transfert de +contention** (le support scindé-poussé obéit à la contention transportée +par `snoc · 0`) et la **conservation des moments sous contenance** au +niveau lifté (les deux composantes de `mean_split_of_support` k2.0 lues +à travers les ponts de k2.6a). +-/ + +namespace Discrepancy.Komlos + +/-- **Toute masse de la scission-poussée provient d'une masse de `P` à +distance `± w`** : si `pushUp (split w P) z ≠ 0`, alors `z` est sur +l'image de `liftUp` — `z = liftUp (x, b)` — et l'un de `P (x + w)`, +`P (x − w)` est non nul. La moitié vient de `pushUp_eq_zero` (hors +image, la poussée est nulle), l'autre des formes `max`/`min` de `split` +(une moitié non nulle force l'un des deux arguments non nul). + +C'est l'auxiliaire de support que consomme le transfert de contenance +`supportContained_pushUp_split` : il ramène toute question de support +sur la poussée à une question de support sur `P`. -/ +lemma pushUp_split_ne_zero {d : ℕ} (w : Fin d → ℤ) {P : (Fin d → ℤ) → ℝ} + {z : Fin (d + 1) → ℤ} (hz : pushUp (split w P) z ≠ 0) : + ∃ (x : Fin d → ℤ) (b : Bool), z = liftUp (x, b) ∧ + (P (x + w) ≠ 0 ∨ P (x - w) ≠ 0) := by + by_cases hex : ∃ y : (Fin d → ℤ) × Bool, liftUp y = z + · obtain ⟨⟨x, b⟩, rfl⟩ := hex + rw [pushUp_apply] at hz + refine ⟨x, b, rfl, ?_⟩ + cases b with + | false => + rw [split_apply_zero] at hz + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [max_eq_right h] at hz + exact Or.inr (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + · rw [max_eq_left h] at hz + exact Or.inl (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + | true => + rw [split_apply_one] at hz + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [min_eq_left h] at hz + exact Or.inl (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + · rw [min_eq_right h] at hz + exact Or.inr (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + · rw [pushUp_eq_zero _ (fun y hy => hex ⟨y, hy⟩)] at hz + exact absurd rfl hz + +/-- **Transfert de contenance à travers la scission** : si `S` contient +le support de `P` et ses translatés par `A`, et si `A` est stable par +`± w`, alors l'image liftée `(S ×ˢ univ).map liftUpEmb` contient le +support de la scission-poussée `pushUp (split w P)` et ses translatés +par les décalages embarqués `Fin.snoc · 0` de `A`. + +C'est la précondition de support que le pas de l'induction (k2.6c) doit +établir pour appliquer l'hypothèse d'induction à la dimension `d + 1` : +chez l'oracle (`Komlos/SignedSums.lean` l.44-53), le `Finsupp` paie ce +transport gratuitement (`Finsupp.embDomain`) ; le cadre `Finset` du lake +le paie ici. La stabilité de `A` par `± w` est le prix exact de la +scission : un point de masse `P (x ± w) ≠ 0` déplacé de `a` atterrit en +`x + a`, atteint depuis `x ± w` par le décalage `a ∓ w ∈ A`. -/ +theorem supportContained_pushUp_split {d : ℕ} (w : Fin d → ℤ) + {P : (Fin d → ℤ) → ℝ} {S A : Finset (Fin d → ℤ)} + (hS : SupportContained S P A) + (hA : ∀ a ∈ A, a + w ∈ A ∧ a - w ∈ A) : + SupportContained ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) + (pushUp (split w P)) (A.image (fun a => Fin.snoc a 0)) := by + intro z hz t ht + obtain ⟨a, ha, rfl⟩ := Finset.mem_image.mp ht + obtain ⟨x, b, rfl, hPw⟩ := pushUp_split_ne_zero w hz + rw [liftUp_add_snoc] + show liftUp (x + a, b) ∈ (S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb + refine Finset.mem_map.mpr ⟨(x + a, b), ?_, liftUpEmb_apply _⟩ + refine Finset.mem_product.mpr ⟨?_, Finset.mem_univ _⟩ + rcases hPw with h | h + · have hxw := hS (x + w) h (a - w) (hA a ha).2 + have hxa : (x + w) + (a - w) = x + a := by + funext j; simp only [Pi.add_apply, Pi.sub_apply]; ring + rw [← hxa]; exact hxw + · have hxw := hS (x - w) h (a + w) (hA a ha).1 + have hxa : (x - w) + (a + w) = x + a := by + funext j; simp only [Pi.add_apply, Pi.sub_apply]; ring + rw [← hxa]; exact hxw + +/-- **Conservation du moment de base sous contenance, au niveau lifté** : +le moment coordonné de la scission-poussée, lu en coordonnée héritée +`i.castSucc`, est le moment de `P` en `i` — sous la même contention +`SupportContained S P {0, w, −w}` que `prodMoment_split_of_support` +(k2.0). C'est la composition du pont de moment `coordMoment_pushUp_castSucc` +(k2.6a, inconditionnel) avec l'identité de conservation de k2.0 : le +barycentre de base traverse la scission **puis** le pont de niveau sans +changement. + +Consommateur mesuré : le `rw [mean_split, sum_smul_inl, …] at hmem` du +pas de l'induction (`Komlos/SignedSums.lean` l.54), composante spatiale. -/ +theorem coordMoment_pushUp_split_of_support {d : ℕ} (w : Fin d → ℤ) + {P : (Fin d → ℤ) → ℝ} {S : Finset (Fin d → ℤ)} + (hS : SupportContained S P ({0, w, -w} : Finset (Fin d → ℤ))) + (i : Fin d) : + coordMoment (pushUp (split w P)) + ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) i.castSucc + = coordMoment P S i := by + rw [coordMoment_pushUp_castSucc, prodMoment_split_of_support w hS i] + +/-- **Le moment de hauteur de la scission-poussée, au niveau lifté** : +lu en dernière coordonnée, il est le bit de scission `splitBit w P S` — +la composante de hauteur de `mean_split_of_support` (k2.0) à travers le +pont `coordMoment_pushUp_last` (k2.6a). Aucune contention n'est +requise : le moment de hauteur se lit tranche par tranche +(`heightMoment_split`, k2.0). + +Consommateur mesuré : le `rw [mean_split, …] at hmem` du pas de +l'induction (`Komlos/SignedSums.lean` l.54), composante de hauteur. -/ +theorem coordMoment_pushUp_split_last {d : ℕ} (w : Fin d → ℤ) + (P : (Fin d → ℤ) → ℝ) (S : Finset (Fin d → ℤ)) : + coordMoment (pushUp (split w P)) + ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) (Fin.last d) + = splitBit w P S := by + rw [coordMoment_pushUp_last, heightMoment_split] + +/-- **La contenance du cran suivant, sous la forme exacte que +l'induction consomme** : si `A` contient `0`, `u` et `−u` et est stable +par `± w`, la scission-poussée obéit à la contention `{0, snoc u 0, +−snoc u 0}` sur l'image liftée. C'est l'instance par monotonie +(`SupportContained.mono`) du transfert générique, les trois décalages +étant les images `snoc · 0` de `0` (`snoc 0 0 = 0`), `u` et `−u` +(`−snoc u 0 = snoc (−u) 0`). + +Le cran suivant de l'induction (k2.6c) scinde `pushUp (split w P)` dans +la direction `u` embarquée à hauteur nulle — les formes `_of_support` de +k2.0 (appliquées à la dimension `d + 1`) exigent exactement cette +contention à trois décalages. -/ +theorem supportContained_pushUp_split_three {d : ℕ} (w u : Fin d → ℤ) + {P : (Fin d → ℤ) → ℝ} {S A : Finset (Fin d → ℤ)} + (hS : SupportContained S P A) + (hA : ∀ a ∈ A, a + w ∈ A ∧ a - w ∈ A) + (h0 : (0 : Fin d → ℤ) ∈ A) (hu : u ∈ A) (hu' : -u ∈ A) : + SupportContained ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) + (pushUp (split w P)) + ({0, Fin.snoc u 0, -(Fin.snoc u 0)} : Finset (Fin (d + 1) → ℤ)) := by + refine (supportContained_pushUp_split w hS hA).mono ?_ + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht + rcases ht with rfl | rfl | rfl + · refine Finset.mem_image.mpr ⟨0, h0, ?_⟩ + funext j + induction j using Fin.lastCases <;> simp + · exact Finset.mem_image.mpr ⟨u, hu, rfl⟩ + · refine Finset.mem_image.mpr ⟨-u, hu', ?_⟩ + funext j + induction j using Fin.lastCases <;> simp [Pi.neg_apply] + +end Discrepancy.Komlos diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit_en.lean new file mode 100644 index 0000000000..0143f1ea6b --- /dev/null +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/LiftSplit_en.lean @@ -0,0 +1,222 @@ +/- +Copyright (c) 2026 Gabriel Dahia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gabriel Dahia +Adapted for `discrepancy_lean` (issue #17845, Karingula–Lovett distillation +arXiv:2609.20979): toolchain v4.33.0, Mathlib `db584cd6`, i18n convention #4980. + +The original Dahia source lives in the `gdahia/Komlos` repository (toolchain +v4.34.0, `Finsupp` framework over `E →₀ ℝ`). This module has **no +name-for-name oracle counterpart**: at the oracle, the induction hypothesis +applies to the split distribution in `E × ℝ` with no support precondition +whatsoever — the `Finsupp` transports its support for free +(`Finsupp.embDomain`); it is the lake's explicit `Finset` framework that +must pay for this transport, and that payment is precisely the subject of +this brick. + +**Scope of this commit** (brick k2.6b, `lake build SUCCESS` required, 0 +`sorry`) — the split under containment, read in the grown dimension +`Fin (d+1) → ℤ`: + +- `pushUp_split_ne_zero` — reading the pushed support: any mass of + `pushUp (split w P)` lives on the image of `liftUp` and originates + from a mass of `P` at distance `± w` from its base (the auxiliary + consumed by the containment transfer); +- `supportContained_pushUp_split` — **the containment transfer across + the split**: if `S` contains the support of `P` and its translates by + `A`, and `A` is stable under `± w`, then the lifted image + `(S ×ˢ univ).map liftUpEmb` contains the support of `pushUp (split w P)` + and its translates by the embedded shifts `Fin.snoc · 0` of `A`; +- `coordMoment_pushUp_split_of_support` — **conservation of the base + moment under containment, at the lifted level**: the coordinate moment + of the split-push, read on an inherited coordinate `i.castSucc`, is + the moment of `P` at `i` — the composition of the bridge + `coordMoment_pushUp_castSucc` (k2.6a) with `prodMoment_split_of_support` + (k2.0); +- `coordMoment_pushUp_split_last` — the height component: the moment of + the split-push on the last coordinate is the split bit + (`coordMoment_pushUp_last` (k2.6a) × `heightMoment_split` (k2.0)); +- `supportContained_pushUp_split_three` — the `{0, snoc u 0, −snoc u 0}` + form consumed by the next induction step: an instance of the transfer + by monotonicity (`SupportContained.mono`), the three shifts being the + `snoc · 0` images of `0`, `u`, `−u`. + +**Measured consumer**: the Lemma 1.4 induction (brick k2.6c, oracle +`Komlos/SignedSums.lean` l.44-55) applies its induction hypothesis to +`split (3 • v_last) P` in the grown space — on our side, to `pushUp +(split w P)` in `Fin (d+1) → ℤ`. The support preconditions and the +barycenter rewrites this call requires are exactly the five statements +above: containment to instantiate the hypothesis +(`supportContained_pushUp_split_three`), moments to rewrite the point it +produces (`coordMoment_pushUp_split_of_support` and `_last`, the lake +mirror of l.54's `rw [mean_split, …] at hmem`). + +**Deferred**: the induction itself (`SignedSums.lean` name for name, +k2.6c). The detailed state lives in `FORMAL_STATUS.md`. +-/ + +import Discrepancy.Komlos.Containment_en +import Discrepancy.Komlos.Lift_en +import Discrepancy.Komlos.MeanSplit_en +import Discrepancy.Komlos.Split_en + +/-! +# The split under containment, in the grown dimension (k2.6b) + +At the oracle, the induction step of Lemma 1.4 is free on the support +side: `split v P` is a `Finsupp` over `E × ℝ`, whose support is +transported by `Finsupp.embDomain` with no precondition. In the lake's +explicit `Finset` framework, the same step must **prove** that the +support of the split-push `pushUp (split w P)` is contained — and will +remain so at the next induction step — in the lifted image of the +starting support. + +This module pays that double cost in one brick: the **containment +transfer** (the split-pushed support obeys the containment transported +by `snoc · 0`) and the **conservation of moments under containment** at +the lifted level (the two components of `mean_split_of_support` k2.0 +read through the k2.6a bridges). +-/ + +namespace Discrepancy.Komlos_en + +/-- **Any mass of the split-push originates from a mass of `P` at +distance `± w`**: if `pushUp (split w P) z ≠ 0`, then `z` is on the +image of `liftUp` — `z = liftUp (x, b)` — and one of `P (x + w)`, +`P (x − w)` is nonzero. Half comes from `pushUp_eq_zero` (off the +image, the push is zero), the other half from the `max`/`min` shapes of +`split` (a nonzero half forces one of the two arguments nonzero). + +This is the support auxiliary consumed by the containment transfer +`supportContained_pushUp_split`: it reduces any support question on the +push to a support question on `P`. -/ +lemma pushUp_split_ne_zero {d : ℕ} (w : Fin d → ℤ) {P : (Fin d → ℤ) → ℝ} + {z : Fin (d + 1) → ℤ} (hz : pushUp (split w P) z ≠ 0) : + ∃ (x : Fin d → ℤ) (b : Bool), z = liftUp (x, b) ∧ + (P (x + w) ≠ 0 ∨ P (x - w) ≠ 0) := by + by_cases hex : ∃ y : (Fin d → ℤ) × Bool, liftUp y = z + · obtain ⟨⟨x, b⟩, rfl⟩ := hex + rw [pushUp_apply] at hz + refine ⟨x, b, rfl, ?_⟩ + cases b with + | false => + rw [split_apply_zero] at hz + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [max_eq_right h] at hz + exact Or.inr (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + · rw [max_eq_left h] at hz + exact Or.inl (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + | true => + rw [split_apply_one] at hz + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [min_eq_left h] at hz + exact Or.inl (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + · rw [min_eq_right h] at hz + exact Or.inr (by intro h0; rw [h0, mul_zero] at hz; exact hz rfl) + · rw [pushUp_eq_zero _ (fun y hy => hex ⟨y, hy⟩)] at hz + exact absurd rfl hz + +/-- **Containment transfer across the split**: if `S` contains the +support of `P` and its translates by `A`, and `A` is stable under +`± w`, then the lifted image `(S ×ˢ univ).map liftUpEmb` contains the +support of the split-push `pushUp (split w P)` and its translates by +the embedded shifts `Fin.snoc · 0` of `A`. + +This is the support precondition the induction step (k2.6c) must +establish to apply the induction hypothesis at dimension `d + 1`: at +the oracle (`Komlos/SignedSums.lean` l.44-53), the `Finsupp` pays this +transport for free (`Finsupp.embDomain`); the lake's `Finset` framework +pays it here. The stability of `A` under `± w` is the exact price of +the split: a mass point `P (x ± w) ≠ 0` moved by `a` lands at `x + a`, +reached from `x ± w` through the shift `a ∓ w ∈ A`. -/ +theorem supportContained_pushUp_split {d : ℕ} (w : Fin d → ℤ) + {P : (Fin d → ℤ) → ℝ} {S A : Finset (Fin d → ℤ)} + (hS : SupportContained S P A) + (hA : ∀ a ∈ A, a + w ∈ A ∧ a - w ∈ A) : + SupportContained ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) + (pushUp (split w P)) (A.image (fun a => Fin.snoc a 0)) := by + intro z hz t ht + obtain ⟨a, ha, rfl⟩ := Finset.mem_image.mp ht + obtain ⟨x, b, rfl, hPw⟩ := pushUp_split_ne_zero w hz + rw [liftUp_add_snoc] + show liftUp (x + a, b) ∈ (S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb + refine Finset.mem_map.mpr ⟨(x + a, b), ?_, liftUpEmb_apply _⟩ + refine Finset.mem_product.mpr ⟨?_, Finset.mem_univ _⟩ + rcases hPw with h | h + · have hxw := hS (x + w) h (a - w) (hA a ha).2 + have hxa : (x + w) + (a - w) = x + a := by + funext j; simp only [Pi.add_apply, Pi.sub_apply]; ring + rw [← hxa]; exact hxw + · have hxw := hS (x - w) h (a + w) (hA a ha).1 + have hxa : (x - w) + (a + w) = x + a := by + funext j; simp only [Pi.add_apply, Pi.sub_apply]; ring + rw [← hxa]; exact hxw + +/-- **Conservation of the base moment under containment, at the lifted +level**: the coordinate moment of the split-push, read on an inherited +coordinate `i.castSucc`, is the moment of `P` at `i` — under the same +containment `SupportContained S P {0, w, −w}` as +`prodMoment_split_of_support` (k2.0). This is the composition of the +moment bridge `coordMoment_pushUp_castSucc` (k2.6a, unconditional) with +the k2.0 conservation identity: the base barycenter crosses the split +**and then** the level bridge unchanged. + +Measured consumer: the `rw [mean_split, sum_smul_inl, …] at hmem` of +the induction step (`Komlos/SignedSums.lean` l.54), spatial component. -/ +theorem coordMoment_pushUp_split_of_support {d : ℕ} (w : Fin d → ℤ) + {P : (Fin d → ℤ) → ℝ} {S : Finset (Fin d → ℤ)} + (hS : SupportContained S P ({0, w, -w} : Finset (Fin d → ℤ))) + (i : Fin d) : + coordMoment (pushUp (split w P)) + ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) i.castSucc + = coordMoment P S i := by + rw [coordMoment_pushUp_castSucc, prodMoment_split_of_support w hS i] + +/-- **The height moment of the split-push, at the lifted level**: read +on the last coordinate, it is the split bit `splitBit w P S` — the +height component of `mean_split_of_support` (k2.0) through the bridge +`coordMoment_pushUp_last` (k2.6a). No containment is required: the +height moment is read slice by slice (`heightMoment_split`, k2.0). + +Measured consumer: the `rw [mean_split, …] at hmem` of the induction +step (`Komlos/SignedSums.lean` l.54), height component. -/ +theorem coordMoment_pushUp_split_last {d : ℕ} (w : Fin d → ℤ) + (P : (Fin d → ℤ) → ℝ) (S : Finset (Fin d → ℤ)) : + coordMoment (pushUp (split w P)) + ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) (Fin.last d) + = splitBit w P S := by + rw [coordMoment_pushUp_last, heightMoment_split] + +/-- **The next step's containment, in the exact form the induction +consumes**: if `A` contains `0`, `u` and `−u` and is stable under +`± w`, the split-push obeys the containment `{0, snoc u 0, −snoc u 0}` +on the lifted image. This is the instance by monotonicity +(`SupportContained.mono`) of the generic transfer, the three shifts +being the `snoc · 0` images of `0` (`snoc 0 0 = 0`), `u` and `−u` +(`−snoc u 0 = snoc (−u) 0`). + +The next induction step (k2.6c) splits `pushUp (split w P)` in the +direction `u` embedded at height zero — the `_of_support` forms of +k2.0 (applied at dimension `d + 1`) require exactly this three-shift +containment. -/ +theorem supportContained_pushUp_split_three {d : ℕ} (w u : Fin d → ℤ) + {P : (Fin d → ℤ) → ℝ} {S A : Finset (Fin d → ℤ)} + (hS : SupportContained S P A) + (hA : ∀ a ∈ A, a + w ∈ A ∧ a - w ∈ A) + (h0 : (0 : Fin d → ℤ) ∈ A) (hu : u ∈ A) (hu' : -u ∈ A) : + SupportContained ((S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb) + (pushUp (split w P)) + ({0, Fin.snoc u 0, -(Fin.snoc u 0)} : Finset (Fin (d + 1) → ℤ)) := by + refine (supportContained_pushUp_split w hS hA).mono ?_ + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht + rcases ht with rfl | rfl | rfl + · refine Finset.mem_image.mpr ⟨0, h0, ?_⟩ + funext j + induction j using Fin.lastCases <;> simp + · exact Finset.mem_image.mpr ⟨u, hu, rfl⟩ + · refine Finset.mem_image.mpr ⟨-u, hu', ?_⟩ + funext j + induction j using Fin.lastCases <;> simp [Pi.neg_apply] + +end Discrepancy.Komlos_en diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md index 863f75439d..98ceba896f 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md @@ -67,7 +67,8 @@ boutes `k1..k5` ci-dessous ; issue de suivi : #17845. | **k2.4** | `Discrepancy.Komlos.pullback` : **le pas complet du pullback** — le théorème que k2.1 (algèbre), k2.2 (convexité) et k2.3 (transport) ont préparé, porté de `Komlos/Pullback.lean` l.55-92. Briques closes : `toRealProd` + `toRealProd_injective` + `toRealProdEmb` (l'embedding **produit** `(Fin d → ℤ) × Bool → (Fin d → ℝ) × ℝ` — la hauteur `Bool` du lake devient la coordonnée réelle `β` de l'oracle, `false ↦ 0` / `true ↦ 1` ; injectivité par `toReal_injective.eq_iff` + séparation `0 ≠ 1` — le ticket du `Finset.map` du support transporté), `mem_map_toRealProd_snd` (hauteurs de l'image dans `{0, 1}` — le pendant fini de `snd_eq_zero_or_one_of_mem_support_split`), `split_apply_zero_ne_iff` / `split_apply_one_ne_iff` (les **caractérisations de support** de la scission sous `P ≥ 0`, lecture point-par-point des `mk_zero/one_mem_support_split` de l'oracle — le `max` exige la disjonction, le `min` la conjonction) et **le théorème `pullback`** : `(z, β)` dans l'enveloppe du support transporté de `split v P`, `v = 3·w` coordonnée par coordonnée, `β ≥ 1/3` ⇒ un signe `e ∈ {±1}` ramène `z + e • toReal w` dans l'enveloppe du support transporté de `P`. **Trois écarts de cadre arbitrés** : (a) `z` vit côté `ℝ` (le consommateur final Lemme 1.4 produit un barycentre côté grille réelle, d'où l'hypothèse dans l'image transportée) ; (b) `hSQ` exactitude du support de la scission en **hypothèse** (l'oracle la calcule via `Finsupp.support` ; le cadre `Finset` explicite la exige) ; (c) `hPsupp` relaie le support de `P`. Preuve décomposée sur les ingrédients k2.1-k2.3 : `Finset.mem_convexHull'` (`Analysis.Convex/Combination.lean:415` — vérifié au pin, forme `∃ w` exacte) décompose `(z, β)` en poids ; `Finset.abs_sum_le_sum_abs` (`Algebra/Order/BigOperators/Group/Finset.lean:315` — **dans le namespace `Finset`** au pin, l'identifiant nu n'existe pas) borne la part des poids hauteur 0 ; `exists_sign_mul_add_eq` (k2.1) produit `e` et `c` ; chaque point revient dans l'enveloppe par `add_smul_mem_convexHull` (k2.2, tranches hautes) ou l'appartenance directe d'une extrémité via `toReal_mem_map_iff` (k2.3, tranches basses) ; `sum_smul_mem_convexHull` (k2.2) referme. `sum_smul_inl` (`split.lean:50`) **reporté** : le port n'en a pas eu besoin (la décomposition `(z, β)` passe par `Prod.fst_sum`/`Prod.snd_sum` ; aucun consommateur mesuré). Module FR + jumeau `_en`, étendus (pas de nouveau fichier). 0 `sorry`. | brique k2 (pas complet) | **PROUVÉ** (k2.4, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (~30 s chacun), puis full-lib `8750 jobs` *Build completed successfully* ; `distinct_code_sorry = 0` ; jumeaux i18n `14/14 byte-identical` — voir PR) | ce PR (stack sur #19081) | | **k2.5** | `Discrepancy.Komlos.mean_mem_convexHull` : **le cas de base `n = 0` de l'assemblage** — porté de `Komlos/Distribution.lean` l.105, module de l'oracle repris **nom pour nom** (nouveau `Distribution.lean` + jumeau `_en` ; le glob `.submodules` du lakefile le découvre — `Komlos.lean` n'est pas un agrégateur, aucun enregistrement). Énoncé : le barycentre — lu coordonnée par coordonnée, `fun i => coordMoment P S i` (k2.0) — d'une distribution positive (`hP`) de masse 1 (`hmass`) sur `S` appartient à l'enveloppe convexe du support **transporté** `S.map ⟨toReal, toReal_injective⟩` — la même forme exacte que la conclusion de `pullback` (k2.4), que la base `n = 0` de l'assemblage consommera (`SignedSums.lean` l.42). **La clé du port** : chez l'oracle le one-liner (`Finset.mem_convexHull'.2 ⟨S, …⟩`) tient parce que les poids demandés sont le `Finsupp` lui-même, **nul hors support par construction** ; le cadre `Finset` explicite du lake exigeait de construire ce poids sur la grille réelle — et c'est **déjà l'organe `push` de k2.3** (`push toReal P` sur `Function.extend`, nul hors image par construction, équivalent du `Finsupp.embDomain` de l'oracle) : aucun poids à inventer, la preuve redevient le one-liner oracle avec ses trois composantes lisant les organes k2.3 — `push_apply` (positivité des poids transportés, chaque point du support transporté relisant `P` à son unique antécédent), `push_mass` (masse conservée, le `mass_push` de l'oracle), `coordMoment_toReal` (le point produit, le `mean_push` de l'oracle — le barycente affirmé dans l'enveloppe est exactement celui que les moments k2.0 calculent). **Trois écarts de cadre arbitrés** (même famille que k2.4) : (a) le `mean` se lit coordonnée par coordonnée (`Fin d → ℤ` n'est pas un `ℝ`-module, bloqueur mesuré en k2.2) ; (b) `IsDist` devient deux hypothèses `hP`/`hmass` (la structure `Finsupp` portait ces faits par construction) ; (c) le support de l'énoncé est `S` transporté exact, pas un `s ⊇ support` arbitraire. **Reportés avec raison mesurée** : l'infrastructure sup/inf du module oracle (`mass_sup_add_mass_inf`, `mean_sup_add_mean_inf`, `support_inf_subset`, `support_sup_subset`) — aucun consommateur dans notre cadre (la préservation de masse à la scission est `split_mass` k1.2, consommée en hypothèse chaînée) ; et **`sum_smul_inl` (`split.lean:50`) acquiert un consommateur mesuré** par la lecture k1.7 du pas (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) — livré avec k2.6 où sa forme exacte se fixe. 0 `sorry`. | brique k2 (cas de base) | **PROUVÉ** (k2.5, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (31 s chacun, SUCCESS au premier round) ; `distinct_code_sorry = 0` ; jumeaux i18n `15/15 byte-identical` — voir PR) | ce PR (stack sur #19084) | | **k2.6a** | `Discrepancy.Komlos.liftUp` : **le pont de niveau — premier préalable mécanique de l'assemblage k2.6**. Ce module n'a **pas de contrepartie oracle**, et cette absence est le fait technique que la brique documente : le Lemme 1.4 de l'oracle est quantifié sur `E` **variable** (`induction n with`, `SignedSums.lean` l.37), son hypothèse d'induction s'applique donc dans l'espace grandi `E × ℝ` (l.52) sans rien construire ; la base du lake `Fin d → ℤ` est **fixe**, et aucun organe k1.x/k2.x ne s'applique à une distribution sur un type réellement différent. **Design-gate arbitré et consigné dans le header du module** : (a) généralisation abstraite `X × Bool` et (b) espace produit itéré `(Fin d → ℤ) × (Fin n → Bool)` **rejetées** — toutes deux une seconde formalisation de la chaîne entière ; **(c) retenue : l'espace qui grandit est `Fin (d + k) → ℤ`**, réalisé par `liftUp : ((Fin d → ℤ) × Bool) → (Fin (d+1) → ℤ)` (partie spatiale par `Fin.snoc`, hauteur `Bool` comme l'entier `{0,1}` à la dernière coordonnée — la contrepartie discrète du `incl b : E ↪ E × ℝ` de l'oracle, `Split.lean` l.31), le miroir d'induction étant `induction n generalizing d` : chaque brique du lake étant générique en `d`, elles s'appliquent **telles quelles à la dimension suivante**. **Livré** : `liftUp` + `liftUp_injective` + `liftUpEmb`/`liftUpEmb_apply` (le pont syntaxique que les rewrites sur les images `Finset.map` exigent — mesuré au round 1 : `rw` ne voit pas `liftUpEmb y` comme `liftUp ?y`) ; `liftUp_add_snoc` (les translations de hauteur nulle commutent avec l'embedding — l'équation qui fait marcher le pont de distance) ; `pushUp` — la poussée le long de `liftUp` sur le **même pattern `Function.extend` que l'organe `push` de k2.3** (et non cet organe : celui-ci est typé sur un morphisme additif, le côté produit n'a pas d'opposé), avec sa lecture `apply`/`eq_zero`/`nonneg`/`mass` ; les **deux ponts de moment** (`coordMoment_pushUp_castSucc` = `prodMoment`, `coordMoment_pushUp_last` = `heightMoment` — les deux composantes de `mean_split` k2.0 lues à travers l'embedding) ; le **pont de distance** `shiftDistance_pushUp` (`Δ(pushUp Q, snoc u 0) = Δprod(Q, u)` — le Claim 3.2 de k1.5 s'applique à la dimension agrandie sans perte) ; l'**exactitude du support** dans les deux sens (`pushUp_ne_zero_of_mem` / `pushUp_mem_map_of_ne_zero`) ; `sum_smul_snoc` — **la forme lake du `sum_smul_inl` de l'oracle dont k2.5 annonçait le consommateur mesuré** (`Split.lean` l.50-53, consommé à `SignedSums.lean` l.54 : une somme pondérée de vecteurs embarqués à hauteur nulle reste à hauteur nulle) ; et `toReal_liftUp` (commutation `toReal ∘ liftUp = snoc ∘ (toReal × hauteur)` — le carré avec `toRealProd` k2.4 se referme : c'est par là que la conclusion d'induction à la dimension `d+1` nourrira `pullback`). **Reportés avec consommateur mesuré** : la conservation des moments sous contenance (`prodMoment_split_of_support`) et le transfert de contenance à travers la scission (k2.6b) ; l'induction elle-même, `SignedSums.lean` nom pour nom (k2.6c). **Trois classes d'erreur mesurées aux rounds 1-2** (consignées pour les portages suivants) : `rfl` échoue sur les lemmes de lecture de `Fin.snoc` au pin (version Tuple hétérogène via `dite`+cast, `Tuple/Basic.lean` l.515 — remplacé par `simp [liftUp]` sur `Fin.snoc_castSucc` l.526 / `Fin.snoc_last` l.539) ; `rw` est syntaxique et exige le pont `liftUpEmb_apply` sur les images `Finset.map` ; `cases` sur un terme non-variable (`y.2`) ne substitue pas dans le but — déstructurer la paire d'abord. Module FR + jumeau `_en` (header et docstring de module en français côté FR, convention du lake — advisory HALF-DONE de l'organe i18n levé). 0 `sorry`. | brique k2 (assemblage) | **PROUVÉ** (k2.6a, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (28 s chacun, SUCCESS au 3ᵉ round : 6 classes d'erreur des rounds 1-2 diagnostiquées contre le source Mathlib du pin) ; full-lib **8754 jobs** *Build completed successfully*, **37 warnings — identique à k2.5**, 0 sur les modules nouveaux ; `distinct_code_sorry = 0` (lake discrepancy) ; jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19087) | -| **k2.6** | `Discrepancy.Komlos.sum_smul_inl` : **première brique de l'assemblage** — nouveau module `Komlos/SignedSums.lean` (+ jumeau `_en`), repris nom pour nom de l'oracle. Livré : `sum_smul_inl` **générique** (`{E : Type*} [AddCommGroup E] [Module ℝ E]`, `∑ i, ε i • (v i, 0) = (∑ i, ε i • v i, 0)` par `Prod.ext` + `Prod.smul_mk`/`fst_sum`/`snd_sum` — les trois noms **vérifiés au pin** : `smul_mk` en `GroupWithZero/Action/Prod.lean`, `fst_sum`/`snd_sum` versions additives de `fst_prod`/`snd_prod` en `BigOperators/Pi.lean` l.155, toolkit identique à `Convex/Combination.lean` l.460) — l'assistant que l'oracle invoque au pas de l'induction (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) pour distribuer une somme de couples sur la première composante. **Carte de généricité (mesurée, en tête du module)** : l'induction de l'oracle ré-instancie ses organes à chaque niveau sur un ambiant croissant `E → E × ℝ → …` ; les organes k2.0–k2.5 de ce lake sont **monomorphes** (`Fin d → ℤ`, hauteur `Bool`) — split, mean_split_of_support, shiftDist_split_le, splitBit_eq, pullback, mean_mem_convexHull. Déjà génériques dans le lake : `segment_repr`, `add_smul_mem_convexHull`, `sum_smul_mem_convexHull` (Pullback.lean l.150/189/213). `sum_smul_inl` était **absent** — livré générique ici, consommable à tout niveau. **Voie β (ping-pong deux espaces) close par la mesure** : le pas oracle écrit simultanément dans `E` (les `v i`) et `ℝ` (les hauteurs) au même niveau d'itération, pas en alternance. **Décision de cadre arbitrée en k2.6a** (option (c) : l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par `liftUp`, la voie α est écartée — cf ligne k2.6a) ; `sum_smul_inl` se positionne comme l'organe générique ℝ-modulaire **complémentaire de `sum_smul_snoc`** (k2.6a, forme lake côté grille), consommable côté transport/hull. 0 `sorry`. | brique k2 (assemblage, 1/…) | **PROUVÉ** (k2.6 brique 1, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19089) | +| **k2.6** | `Discrepancy.Komlos.sum_smul_inl` : **première brique de l'assemblage** — nouveau module `Komlos/SignedSums.lean` (+ jumeau `_en`), repris nom pour nom de l'oracle. Livré : `sum_smul_inl` **générique** (`{E : Type*} [AddCommGroup E] [Module ℝ E]`, `∑ i, ε i • (v i, 0) = (∑ i, ε i • v i, 0)` par `Prod.ext` + `Prod.smul_mk`/`fst_sum`/`snd_sum` — les trois noms **vérifiés au pin** : `smul_mk` en `GroupWithZero/Action/Prod.lean`, `fst_sum`/`snd_sum` versions additives de `fst_prod`/`snd_prod` en `BigOperators/Pi.lean` l.155, toolkit identique à `Convex/Combination.lean` l.460) — l'assistant que l'oracle invoque au pas de l'induction (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) pour distribuer une somme de couples sur la première composante. **Carte de généricité (mesurée, en tête du module)** : l'induction de l'oracle ré-instancie ses organes à chaque niveau sur un ambiant croissant `E → E × ℝ → …` ; les organes k2.0–k2.5 de ce lake sont **monomorphes** (`Fin d → ℤ`, hauteur `Bool`) — split, mean_split_of_support, shiftDist_split_le, splitBit_eq, pullback, mean_mem_convexHull. Déjà génériques dans le lake : `segment_repr`, `add_smul_mem_convexHull`, `sum_smul_mem_convexHull` (Pullback.lean l.150/189/213). `sum_smul_inl` était **absent** — livré générique ici, consommable à tout niveau. **Voie β (ping-pong deux espaces) close par la mesure** : le pas oracle écrit simultanément dans `E` (les `v i`) et `ℝ` (les hauteurs) au même niveau d'itération, pas en alternance. **Décision de cadre arbitrée en k2.6a** (option (c) : l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par `liftUp`, la voie α est écartée — cf ligne k2.6a) ; `sum_smul_inl` se positionne comme l'organe générique ℝ-modulaire **complémentaire de `sum_smul_snoc`** (k2.6a, forme lake côté grille), consommable côté transport/hull. 0 `sorry`. | brique k2 (assemblage, 1/…) | **PROUVÉ** (k2.6 brique 1, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | #19425 (stack sur #19089) | +| **k2.6b** | `Discrepancy.Komlos.supportContained_pushUp_split` : **la scission sous contention, lue dans la dimension agrandie** — nouveau module `Komlos/LiftSplit.lean` (+ jumeau `_en`), **sans contrepartie oracle** : chez l'oracle le `Finsupp` transporte son support gratuitement (`Finsupp.embDomain`), c'est le cadre `Finset` explicite du lake qui doit payer ce transport — et ce paiement est l'objet de la brique. **Livré** : `pushUp_split_ne_zero` (toute masse de `pushUp (split w P)` vit sur l'image de `liftUp` et provient d'une masse de `P` à distance `± w` — `pushUp_eq_zero` × formes `max`/`min` de `split` par `le_total`/`max_eq_left`/`min_eq_left`) ; `supportContained_pushUp_split` (**le transfert de contenance à travers la scission** : `SupportContained S P A` + stabilité de `A` par `± w` ⟹ la scission-poussée obéit à la contention sur l'image liftée `(S ×ˢ univ).map liftUpEmb`, pour les décalages embarqués `Fin.snoc · 0` de `A` — la précondition de support que le pas de l'induction doit établir pour appliquer l'hypothèse à la dimension `d+1`) ; `coordMoment_pushUp_split_of_support` + `coordMoment_pushUp_split_last` (**la conservation des moments sous contenance, au niveau lifté** : les deux composantes de `mean_split_of_support` k2.0 composées avec les ponts de moment k2.6a — le miroir lake du `rw [mean_split, …] at hmem` de `SignedSums.lean` l.54, composantes spatiale `i.castSucc` et hauteur `Fin.last`) ; `supportContained_pushUp_split_three` (la forme `{0, snoc u 0, −snoc u 0}` exacte que le cran suivant consomme, instance du transfert par `SupportContained.mono` — `snoc 0 0 = 0`, `−snoc u 0 = snoc (−u) 0`). **La stabilité de `A` par `± w` est le prix exact de la scission** : un point de masse `P (x ± w) ≠ 0` déplacé de `a` atterrit en `x + a`, atteint depuis `x ± w` par le décalage `a ∓ w ∈ A`. **Consommateur mesuré** : k2.6c — l'induction elle-même (`SignedSums.lean` l.44-55). 0 `sorry`. | brique k2 (assemblage, 2/…) | **PROUVÉ** (k2.6b, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19425) | | **k3.1** | `Discrepancy.Komlos.tent` (`Komlos/Tent.lean` + jumeau `_en`) : **la tente discrète, port complet du module de l'oracle** — les 13 preuves reportées en c.885 (delivery #17918) sont closes, chacune adaptée du `grind` v4.34 vers le pin v4.33.0 / `db584cd6` (détail par preuve dans la note de fin de fichier). Sommes closes : `sum_tent` (Σ tent = M²), `sum_tent_sq` (3·Σ tent² = M(2M²+1)) ; Lipschitz `abs_tent_sub_le` (1-Lipschitz) ; pas `step`/`abs_step_le_one`/`step_eq_zero`/`sum_step_sq_le` (≤ 2M) ; télescopage `tent_sub_tent_eq_sum_step` ; **résultat porteur `sum_tent_sub_sq_le`** (Σ (tent M j − tent M (j−m))² ≤ 2·M·m²) — la borne `L²` **discrète** du Lemme 4.1. Adaptations mesurées : `abs_add`/`neg_le_abs_self` **absents au pin** (sondés — la triangulaire inverse passe par `abs_max_sub_max_le_abs` + `abs_abs_sub_abs_le_abs_sub`) ; `omega` ne splitte pas `\|j\|` sur ℤ (atome opaque) → composites `le_abs_self`+`abs_neg` ; l'énoncé `support_tent_subset` force `Set.Icc` (le `Icc` nu sous `open Finset` s'élabore en coercion Finset) ; bornes en cast entier global `((M+1:ℕ):ℤ)` ; `sum_range_sub'` absent → induction manuelle ; `rw` avec `f := id` échoue → normalisation `simp only [id]`. **Réaudit k3 contre l'oracle** : la voie Dahia est **totalement discrète** — `Grid.lean` consomme `sum_tent_sq` + `sum_tent_sub_sq_le` pour construire le poids normalisé `gridF N` (distance `L²` de translation ≤ \|m\|/(N·√12)) ; le « FTC sur segments » du papier est remplacé par la discrétisation sur grille (`intervalIntegral` absent de l'oracle) — la ligne de planification k3 est réécrite en conséquence. 0 `sorry`. | brique k3 (tente + L² discret) | **PROUVÉ** (k3.1, 10-06, `lake build` local EXIT=0 sur les deux jumeaux — 8708 jobs, `distinct_code_sorry = 0`, jumeaux i18n `1/1 byte-identical` — voir PR) | ce PR (branche `feature/komlos-k3-tent`) | | **k3.2** | `Discrepancy.Komlos.gridF` (`Komlos/Grid.lean` + jumeau `_en`) : **le poids normalisé unidimensionnel et sa borne `L²` de translation — port complet du `Komlos/Grid.lean` de l'oracle** (la voie k3 de l'oracle est désormais complète). Briques closes : `gridM` (demi-largeur `6·N`), `gridZ` (constante de normalisation = `∑ tent²`), `gridF` (`tent (gridM N) j / √(gridZ N)`), `cast_gridM`, `gridZ_eq` (**`gridZ N = 144·N³ + 2·N`**), `gridZ_pos`, `gridF_nonneg`, `support_gridF_subset`, `finsum_gridF_sq` (**masse totale `1`**), `sum_gridF_sub_sq`/`sum_gridF_sq` (formes `Finset` consommables), **résultat porteur `sum_gridF_sub_sq_le`** : distance `L²` au carré entre `gridF N` et son translaté par `m` ≤ `m²/(12·N²)` — l'analogue discret du Lemme 4.1, entrée directe de la discrétisation k4 (Lemme 1.5). Adaptations mesurées : le `positivity` de l'oracle sur `gridZ_pos` échoue au pin (stricte positivité dépend de `hN : 0 < N`) → cast + `linarith` ; le `linarith` final de `gridZ_eq` échoue sur le produit non-linéaire → normalisation `ring` explicite avant `linarith` ; `support_tent_subset` de ce lake étant typé `Set.Icc` (l'oracle : `Finset.Icc`), `support_gridF_subset` est prouvé directement (`Finset.mem_coe` + composite `le_abs_self`) ; l'API `finsum` (**existe au pin**, à la racine — sondée) permet le port quasi verbatim des énoncés de masse. **Correctif i18n embarqué** : `Tent_en.lean` passait en `namespace Discrepancy.Komlos` (seul `_en` du lake non suffixé — défaut #17918) ; il repasse en `Discrepancy.Komlos_en`, condition de l'import propre `Grid_en → Tent_en`. 0 `sorry`. | brique k3 (poids normalisé + L²) | **PROUVÉ** (k3.2, 10-06, `lake build` local EXIT=0 sur les trois cibles — 8710 jobs : `Grid`, `Grid_en`, `Tent_en` recompilé ; `distinct_code_sorry = 0`, jumeaux i18n `2/2 byte-identical` — voir PR) | ce PR (stack sur #19563) | | P3 | Banaszczyk 1998 / formes fortes des papiers 2025 **et 2026** | aspiration | **NON ENGAGÉ** — exige SDP + dualité, indépendance spectrale affine, brownien discret guidé, concentration matricielle : **aucun de cet étage n'existe dans Mathlib** (vérifié 2026-08-24). **Réaudité 2026-09-13** contre le Mathlib pinné (`520045ab`, v4.32.1) : le contournement proposé par arXiv:2609.11189 ne supprime pas l'obstruction, il la **déplace** — sa route exige la *variation totale directionnelle* d'une densité sur convexe ouvert et la *transformée de Banaszczyk* préservée sous translation, deux notions **absentes du même Mathlib** (`Banaszczyk` : 0 occurrence ; `totalVariation` n'existe que pour les mesures signées ; la théorie BV de Mathlib concerne la dérivabilité a.e. des fonctions de `ℝ`). Ce que ce papier rapproche, ce sont les *socles* : gaussiennes (`Probability/Distributions/Gaussian/*`) et `ConvexBody` (`Analysis/Convex/Body.lean`) sont présents ; le **pont** manque. Documenté, jamais promis. **Réaudité 2026-09-25** : la voie **élémentaire** de Karingula–Lovett (arXiv:2609.20979, constante `36`) **supprime** cet étage au lieu de le déplacer — sa mécanique est discrète (distance de décalage `Δ`, opérateur de scission `T_v`, induction sur `n` et `d`) à une seule exception, l'estimation de la densité-tente, qui se fait par FTC sur segments + Cauchy–Schwarz `L²` et **non** par de la théorie BV. Balayage des prérequis sur le checkout Mathlib local (`v4.32.0`) : famille **`norm_image_sub_le` présente** (dont `Analysis/Calculus/IntervalIntegral/DistLEIntegral.lean`), `totalVariation` toujours cantonné aux mesures vectorielles (`VectorMeasure/Decomposition/*`) — mais le papier n'en a plus besoin. Réserve de portée : ce balayage porte sur un checkout **voisin** (`v4.32.0`), pas sur le pin du lake (`520045ab`) — à re-vérifier avant la première boute `.lean`. Une formalisation Lean 4 tierce de cette preuve existe déjà (mise à jour du 2026-09-25 ci-dessous). | — | @@ -167,7 +168,7 @@ branche, jamais `main`. Issue de suivi : #17845. | **k1.7** | Correctif d'hypothèse **avant** k2 : l'invariance du support des briques k1 est insatisfiable aux décalages non nuls (mesuré, `eq_zero_of_image_add_eq_self`) → formes consommables sous **contention** `SupportContained` | fini | k1 | | **k2.0** | **Moments de la scission** (`mean_split`) — décomposition par composante du `mean_split` de Dahia (base `Fin d → ℤ` sans structure de `ℝ`-module : `coordMoment`/`prodMoment`, `heightMoment`), moment de hauteur = `splitBit` (`heightMoment_split`), **conservation du barycentre** par la scission (`prodMoment_split`) — l'item reporté par k1.6 | fini | k1, k1.6 | | **k2.0 — correctif de support** | **Formes consommables des moments** — `prodMoment_split_of_support` + `mean_split_of_support` sous `SupportContained S P {0, v, -v}` : k1.7 appliqué à k2.0 (`heightMoment_split` réutilisé inchangé), + contrôle positif `exists_supportContained_nonzero_shift` (`d = 1`, `v = 1`, `P` Dirac, `S = {-1, 0, 1}` via `supportContained_biUnion`) | fini | k1.7, k2.0 | -| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé**. **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Livré en k2.6a** : **le pont de niveau** (`Lift.lean` + jumeau `_en`, sans contrepartie oracle — l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, design-gate arbitré option (c) consigné dans le header du module ; `pushUp` sur le pattern `Function.extend` de k2.3, les ponts de moment / de distance / de support, et `sum_smul_snoc` — **la forme lake du `sum_smul_inl` dont k2.5 annonçait le consommateur mesuré**, désormais livrée, cf ligne k2.6a). **Livré en k2.6 (brique 1)** : `sum_smul_inl` **générique** (module `Komlos/SignedSums.lean` + jumeau `_en`, repris nom pour nom — la carte de généricité des organes y est mesurée, la voie β close par la mesure, la décision de cadre consignée ouverte). **Reste à ce lake, mesuré** : **k2.6b** (la conservation des moments sous contenance `prodMoment_split_of_support` + le transfert de contenance à travers la scission) puis **k2.6c** — la lecture k1.7 du pas elle-même (`SignedSums.lean` l.37-58 nom pour nom : l'itération `induction n generalizing d` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_snoc` au pas (l.53-54) et `pullback` en clôture). | fini + induction | k1, k1.7, k2.0–k2.6 | +| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé**. **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Livré en k2.6a** : **le pont de niveau** (`Lift.lean` + jumeau `_en`, sans contrepartie oracle — l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, design-gate arbitré option (c) consigné dans le header du module ; `pushUp` sur le pattern `Function.extend` de k2.3, les ponts de moment / de distance / de support, et `sum_smul_snoc` — **la forme lake du `sum_smul_inl` dont k2.5 annonçait le consommateur mesuré**, désormais livrée, cf ligne k2.6a). **Livré en k2.6 (brique 1)** : `sum_smul_inl` **générique** (module `Komlos/SignedSums.lean` + jumeau `_en`, repris nom pour nom — la carte de généricité des organes y est mesurée, la voie β close par la mesure, la décision de cadre arbitrée en k2.6a). **Livré en k2.6b** : la scission sous contention dans la dimension agrandie (module `Komlos/LiftSplit.lean` + jumeau `_en` — le **transfert de contenance** `supportContained_pushUp_split` + la **conservation des moments liftée** `coordMoment_pushUp_split_of_support`/`_last` : la précondition de support et les ré-écritures de barycentre que le pas exige pour appliquer l'hypothèse d'induction à `pushUp (split w P)` dans `Fin (d+1) → ℤ`, cf ligne k2.6b). **Reste à ce lake, mesuré** : **k2.6c** — la lecture k1.7 du pas elle-même (`SignedSums.lean` l.37-58 nom pour nom : l'itération `induction n generalizing d` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_snoc` au pas (l.53-54) et `pullback` en clôture). | fini + induction | k1, k1.7, k2.0–k2.6b | | **k3** | Lemme 4.1 — densité-tente. **Réauditée contre l'oracle au pin (k3.1)** : la voie Dahia est **totalement discrète** — le « FTC sur segments » du papier est remplacé par la discrétisation sur grille, `intervalIntegral` **absent de l'oracle** — la dépendance `norm_image_sub_le` est sans objet. **LIVRÉE EN INTÉGRALITÉ** : k3.1 (`Tent.lean` complet, lignes k3.1/k3.2) puis k3.2 (`Grid.lean` complet — `gridF` normalisé, `gridZ_eq : gridZ N = 144·N³ + 2·N`, masse `1`, **`sum_gridF_sub_sq_le` : distance `L²` de translation ≤ m²/(12·N²)**, l'analogue discret du Lemme 4.1). **Reste** : k4 (Lemme 1.5, discrétisation). | fini (oracle discret, complet) | k3.1, k3.2 | | **k4** | Lemme 1.5 — discrétisation sur la grille, cas rationnel | fini | k3 | | **k5** | Assemblage Thm 1.2 sur `ℚ` (témoin `36`) + corollaires (`KomlosBansalJiangWeak`, Beck–Fiala régulier `72√k`) + notebooks `Search-09c`/`Search-09e` (ligne « course aux bornes » du 22/09/2026) | assemblage | k2, k4 | From 595381c14302992cd793e16f87f8159008c788ed Mon Sep 17 00:00:00 2001 From: jsboige Date: Tue, 6 Oct 2026 11:37:49 +0200 Subject: [PATCH 7/8] feat(lean,#17845): brique k2.6c -- assemblage final Lemme 1.4 (SignedSums + jumeau _en) Dernier cran de la pile Komlos : port de l'assemblage final (induction n du Lemme 1.4) de l'oracle gdahia/Komlos (SignedSums.lean l.37-58) dans Discrepancy/Komlos/SignedSums.lean du lake discrepancy_lean. - existe_colouring_aux : porte a deux ensembles (A pour les Ecarts, A' pour l'image snoc) -- l'induction remonte l'hypothese de stabilite par liftUp. - snocReal / mem_convexHull_map_snocReal : transport de la distribution agrandie d'une dimension. - Enonce public existe_colouring (Lemme 1.4) : consommation de la porte. - Jumeau _en regenere (byte-identical, organe i18n : 1/1 pairs). - FORMAL_STATUS.md : rangee k2.6c + agregateur k2 (le k2 est clos). Validation : - lake build Discrepancy.Komlos.SignedSums Discrepancy.Komlos.SignedSums_en -> EXIT=0 - count_code_sorry.py --json : distinct_code_sorry = 0 (44 fichiers) - check_i18n_siblings.py : 1/1 pairs byte-identical, 0 drift/orphan/unbuilt - grep sorry|admit : 0 ligne dans les deux jumeaux See #17845 Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit 10ed0faf6ac347725a1c1b0a464515c3c442d846) --- .../Discrepancy/Komlos/SignedSums.lean | 498 ++++++++++++++++- .../Discrepancy/Komlos/SignedSums_en.lean | 499 +++++++++++++++++- .../Search/discrepancy_lean/FORMAL_STATUS.md | 3 +- 3 files changed, 991 insertions(+), 9 deletions(-) diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean index 24265be21a..b17d95c8b9 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean @@ -8,13 +8,23 @@ arXiv:2609.20979) : toolchain v4.33.0, Mathlib `db584cd6`, convention i18n #4980 Le source Dahia original vit dans le dépôt `gdahia/Komlos` (module `Komlos/SignedSums.lean`, toolchain v4.34.0, cadre `Finsupp` sur `E →₀ ℝ`). L'assemblage final — l'itération `induction n with` du Lemme 1.4 — s'y lit -l.37-58. Ce module du lake ouvre la distillation : la première brique -`sum_smul_inl` y est livrée générique, la carte de consommation des organes -est mesurée en tête de module, la décision de cadre (option (c), -arbitrée en k2.6a) y est consignée. +l.37-58. Ce module du lake porte la distillation entière : la première brique +`sum_smul_inl` y est livrée générique (k2.6, la carte de consommation des +organes mesurée en tête de module, la décision de cadre — option (c) — +arbitrée en k2.6a), puis l'assemblage final lui-même (k2.6c) : le carré réel +`snocReal`, le transport d'enveloppe `mem_convexHull_map_snocReal`, la porte +inductive à deux ensembles `exists_colouring_aux` (fermeture `S` + support +exact `E` — le prix `Finset` du support canonique du `Finsupp` de l'oracle) +et l'énoncé public `exists_isColouring_mean_add_sum_mem_convexHull`. -/ import Discrepancy.Basic +import Discrepancy.Komlos.Containment +import Discrepancy.Komlos.Distribution +import Discrepancy.Komlos.Lift +import Discrepancy.Komlos.LiftSplit +import Discrepancy.Komlos.Pullback +import Discrepancy.Komlos.Split /-! # Sommes signées — assemblage du Lemme 1.4 (brique k2.6) @@ -64,4 +74,484 @@ lemma sum_smul_inl {n : ℕ} {E : Type*} [AddCommGroup E] [Module ℝ E] (∑ i, ε i • (v i, (0 : ℝ))) = (∑ i, ε i • v i, (0 : ℝ)) := by refine Prod.ext ?_ ?_ <;> simp [Prod.smul_mk, Prod.fst_sum, Prod.snd_sum] +/-! ### Brique k2.6c : l'assemblage final — l'induction du Lemme 1.4 -/ + +/-- **L'isomorphisme `snoc` côté réel** : `(Fin d → ℝ) × ℝ → (Fin (d+1) → ℝ)`, +`(z, t) ↦ snoc z t`. C'est la forme réelle du pont de niveau : le carré +`toReal ∘ liftUp = snoc ∘ toRealProd` (cf `toReal_liftUp`, k2.6a) dit que +transporter le support poussé dans la dimension agrandie revient à +`snoc`-er le support produit transporté — et c'est par là que la conclusion +d'induction à la dimension `d+1` nourrit le `pullback` de k2.4, énoncé dans +`(Fin d → ℝ) × ℝ`. -/ +def snocReal {d : ℕ} : ((Fin d → ℝ) × ℝ) → (Fin (d + 1) → ℝ) := + fun p => Fin.snoc p.1 p.2 + +lemma snocReal_apply_castSucc {d : ℕ} (p : (Fin d → ℝ) × ℝ) (j : Fin d) : + snocReal p j.castSucc = p.1 j := by simp [snocReal] + +lemma snocReal_apply_last {d : ℕ} (p : (Fin d → ℝ) × ℝ) : + snocReal p (Fin.last d) = p.2 := by simp [snocReal] + +/-- **Le carré réel** : `snocReal (toRealProd y) = toReal (liftUp y)` — +la lecture combinée de `toReal_liftUp` (k2.6a) et de la définition +`toRealProd` (k2.4). C'est la seule équation qui manque au transport des +enveloppes entre les deux lectures de la dimension agrandie. -/ +lemma snocReal_toRealProd {d : ℕ} (y : (Fin d → ℤ) × Bool) : + snocReal (toRealProd y) = toReal (liftUp y) := by + rw [toReal_liftUp] + funext j + simp [snocReal, toRealProd] + +lemma snocReal_injective {d : ℕ} : Function.Injective (snocReal (d := d)) := by + rintro ⟨z₁, t₁⟩ ⟨z₂, t₂⟩ h + have h1 : z₁ = z₂ := by + funext j + have := congrFun h j.castSucc + simpa [snocReal] using this + have h2 : t₁ = t₂ := by + have := congrFun h (Fin.last d) + simpa [snocReal] using this + exact Prod.ext h1 h2 + +/-- La version `Finset.Embedding` de `snocReal`, pour les `Finset.map` des +supports transportés. -/ +def snocRealEmb {d : ℕ} : ((Fin d → ℝ) × ℝ) ↪ (Fin (d + 1) → ℝ) := + ⟨snocReal, snocReal_injective⟩ + +lemma snocRealEmb_apply {d : ℕ} (p : (Fin d → ℝ) × ℝ) : snocRealEmb p = snocReal p := rfl + +/-- `snocReal` comme application `ℝ`-linéaire. C'est la structure qui +transporte les enveloppes convexes : `LinearMap.image_convexHull` identifie +l'enveloppe de l'image à l'image de l'enveloppe, et l'injectivité restitue +le point — le lemme de transport ci-dessous en découle immédiatement. -/ +def snocLM {d : ℕ} : ((Fin d → ℝ) × ℝ) →ₗ[ℝ] (Fin (d + 1) → ℝ) where + toFun p := snocReal p + map_add' p q := by + funext j + induction j using Fin.lastCases with + | last => simp [snocReal, Fin.snoc_last, Pi.add_apply] + | cast i => simp [snocReal, Fin.snoc_castSucc, Pi.add_apply] + map_smul' c p := by + funext j + induction j using Fin.lastCases with + | last => simp [snocReal, Fin.snoc_last, Pi.smul_apply, smul_eq_mul] + | cast i => simp [snocReal, Fin.snoc_castSucc, Pi.smul_apply, smul_eq_mul] + +/-- **Transport d'enveloppe à travers `snoc`** : appartenir à l'enveloppe +d'un ensemble fini `snoc`-é, c'est appartenir à l'enveloppe de l'ensemble +source. + +C'est l'organe qui referme le carré de diagramme pour l'assemblage k2.6c : +l'hypothèse d'induction conclut dans `Fin (d+1) → ℝ` (enveloppe du support +poussé transporté), le `pullback` de k2.4 consomme `(Fin d → ℝ) × ℝ` +(enveloppe du support produit transporté) — la correspondance est exactement +ce transport. Preuve : `snocReal` est linéaire (`snocLM`) et injective, et +`LinearMap.image_convexHull` commute l'enveloppe et l'image. -/ +lemma mem_convexHull_map_snocReal {d : ℕ} {E : Finset ((Fin d → ℝ) × ℝ)} + {p : (Fin d → ℝ) × ℝ} : + snocReal p ∈ convexHull ℝ + (↑(E.map snocRealEmb) : Set ((Fin (d + 1) → ℝ))) ↔ + p ∈ convexHull ℝ (↑E : Set ((Fin d → ℝ) × ℝ)) := by + have hset : (↑(E.map snocRealEmb) : Set ((Fin (d + 1) → ℝ))) + = (⇑snocLM) '' (↑E : Set ((Fin d → ℝ) × ℝ)) := by + rw [Finset.coe_map] + rfl + rw [hset, ← LinearMap.image_convexHull] + constructor + · rintro ⟨q, hq, hfq⟩ + rwa [snocReal_injective hfq] at hq + · exact fun h => ⟨p, h, rfl⟩ + +/-! ### La porte inductive : deux ensembles, `S` la fermeture et `E` le support -/ + +/-- **Lemme 1.4 (Karingula–Lovett), forme lake — la porte inductive**. + +Chez l'oracle (`gdahia/Komlos`, `SignedSums.lean` l.37-58), l'induction vit +sur les `Finsupp` : le support exact est canonique à chaque niveau, et la +conclusion d'hypothèse d'induction se consomme telle quelle par `pullback`. +Le cadre `Finset` explicite du lake doit payer ce transport : la contenance +`SupportContained` (k1.7) exige un support **fermé par décalages de `A`** +(les points de masse déplacés y atterrissent), tandis que le `pullback` +(k2.4) exige une enveloppe portée par le **support exact** de la scission +(`hSQ : ∀ y ∈ SQ, split v P y ≠ 0`). Ces deux rôles sont incompatibles sur +un seul `Finset` : la porte en porte donc deux — `S` (fermeture : masse, +moments, contenance) et `E` (support exact : enveloppe de la conclusion, +`E ⊆ S`). + +Au niveau suivant, `S'` est l'image liftée du produit plein (la contenance +y est transférée par `supportContained_pushUp_split`, k2.6b) et `E'` le +support exact poussé (`SQ.map liftUpEmb`, `SQ` le filtre des scissions non +nulles). Le pont entre les deux lectures est le carré +`snocReal ∘ toRealProd = toReal ∘ liftUp` plus le transport d'enveloppe +`mem_convexHull_map_snocReal` (ci-dessus). -/ +theorem exists_colouring_aux (n : ℕ) : + ∀ (d : ℕ) (S E : Finset (Fin d → ℤ)) (P : (Fin d → ℤ) → ℝ), + (∀ x, 0 ≤ P x) → (∑ x ∈ S, P x = 1) → + (∀ x, P x ≠ 0 → x ∈ E) → E ⊆ S → + ∀ A : Finset (Fin d → ℤ), 0 ∈ A → SupportContained S P A → + ∀ v : Fin n → (Fin d → ℤ), + (∀ i, v i ∈ A ∧ -v i ∈ A) → + (∀ a ∈ A, ∀ i, a + 3 • v i ∈ A ∧ a - 3 • v i ∈ A) → + (∀ i, shiftDistance S P (6 • v i) ≤ 3⁻¹) → + ∃ ε : Fin n → ℤ, (∀ i, ε i = 1 ∨ ε i = -1) ∧ + (fun j => coordMoment P S j + ∑ i, (ε i : ℝ) * (v i j : ℝ)) ∈ + convexHull ℝ + ↑(E.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ))) := by + induction n with + | zero => + intro d S E P hP0 hmass hE hES A hA0 hC v hAv hAstab hv + have hzero : ∀ x ∈ S, x ∉ E → P x = 0 := by + intro x _ hx + by_contra hp + exact hx (hE x hp) + have hmassE : ∑ x ∈ E, P x = 1 := by + rw [← hmass] + exact Finset.sum_subset hES hzero + have hmean := mean_mem_convexHull hP0 hmassE + refine ⟨fun _ => 1, fun i => i.elim0, ?_⟩ + have hfun : (fun j => coordMoment P S j + + ∑ i : Fin 0, ((fun _ => 1 : Fin 0 → ℤ) i : ℝ) * (v i j : ℝ)) + = (fun j => coordMoment P E j) := by + funext j + have hvan : ∀ x ∈ S, x ∉ E → P x * (x j : ℝ) = 0 := by + intro x _ hxE + by_contra hp + exact hxE (hE x (fun h0 => hp (by rw [h0]; ring))) + simp only [coordMoment] + rw [Finset.sum_subset hES hvan] + simp + rw [hfun] + exact hmean + | succ n ih => + intro d S E P hP0 hmass hE hES A hA0 hC v hAv hAstab hv + classical + -- Le vecteur de scission + set w : Fin d → ℤ := 3 • v (Fin.last n) with hw + -- Appartenances à A (chaînes de stabilité depuis 0) + have hm0 : (0 : Fin d → ℤ) ∈ A := hA0 + have hmw : 3 • v (Fin.last n) ∈ A := by + simpa using (hAstab 0 hA0 (Fin.last n)).1 + have hmnw : -(3 • v (Fin.last n)) ∈ A := by + simpa using (hAstab 0 hA0 (Fin.last n)).2 + have hmn3 : ∀ i : Fin (n + 1), -(3 • v i) ∈ A := by + intro i + simpa using (hAstab 0 hA0 i).2 + have mono3 : SupportContained S P ({0, w, -w} : Finset (Fin d → ℤ)) := + hC.mono (by + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht ⊢ + rcases ht with rfl | rfl | rfl + · exact hm0 + · exact hmw + · exact hmnw) + -- Les données de niveau d + 1 + set SQ : Finset ((Fin d → ℤ) × Bool) := + (S ×ˢ (Finset.univ : Finset Bool)).filter (fun y => split w P y ≠ 0) + with hSQ + set S' : Finset (Fin (d + 1) → ℤ) := + (S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb with hS' + set E' : Finset (Fin (d + 1) → ℤ) := SQ.map liftUpEmb with hE' + set A' : Finset (Fin (d + 1) → ℤ) := + A.image (fun a => Fin.snoc a 0) with hA' + -- Petites équations de snoc + have hadd_snoc : ∀ x y : Fin d → ℤ, + (Fin.snoc x 0 : Fin (d + 1) → ℤ) + Fin.snoc y 0 + = Fin.snoc (x + y) 0 := by + intro x y + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp + have hsub_snoc : ∀ x y : Fin d → ℤ, + (Fin.snoc x 0 : Fin (d + 1) → ℤ) - Fin.snoc y 0 + = Fin.snoc (x - y) 0 := by + intro x y + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp + have hneg_snoc : ∀ x : Fin d → ℤ, + -(Fin.snoc x 0 : Fin (d + 1) → ℤ) = Fin.snoc (-x) 0 := by + intro x + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp + -- Les vecteurs embarqués se lisent comme des snoc à hauteur nulle + have hv'snoc : ∀ i : Fin n, + (liftUp (v i.castSucc, false) : Fin (d + 1) → ℤ) + = Fin.snoc (v i.castSucc) 0 := fun _ => rfl + -- Les arguments du niveau suivant + have hP0' : ∀ z, 0 ≤ pushUp (split w P) z := + fun z => pushUp_nonneg (split_nonneg hP0 w) z + have hmass' : ∑ z ∈ S', pushUp (split w P) z = 1 := by + rw [hS', pushUp_mass, split_mass_of_support w mono3] + exact hmass + have hsupp' : ∀ z, pushUp (split w P) z ≠ 0 → z ∈ E' := by + intro z hz + by_cases hy : ∃ y : (Fin d → ℤ) × Bool, liftUp y = z + · obtain ⟨y, rfl⟩ := hy + have hy' : split w P y ≠ 0 := by + rw [← pushUp_apply (split w P) y] + exact hz + -- l'antécédent vit dans S ×ˢ univ + have hy1 : y.1 ∈ S := by + obtain ⟨x, b⟩ := y + have hne : P (x + w) ≠ 0 ∨ P (x - w) ≠ 0 := by + cases b with + | false => + rw [split_apply_zero] at hy' + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [max_eq_right h] at hy' + exact Or.inr (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + · rw [max_eq_left h] at hy' + exact Or.inl (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + | true => + rw [split_apply_one] at hy' + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [min_eq_left h] at hy' + exact Or.inl (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + · rw [min_eq_right h] at hy' + exact Or.inr (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + rcases hne with h | h + · have hx := hC (x + w) h (-w) hmnw + simpa using hx + · have hx := hC (x - w) h w hmw + simpa using hx + refine Finset.mem_map.2 ⟨y, Finset.mem_filter.2 ⟨?_, hy'⟩, rfl⟩ + exact Finset.mem_product.2 ⟨hy1, Finset.mem_univ _⟩ + · exact absurd (pushUp_eq_zero (split w P) + (fun y hy' => hy ⟨y, hy'⟩)) hz + have hES' : E' ⊆ S' := by + intro z hz + obtain ⟨y, hy, rfl⟩ := Finset.mem_map.1 hz + exact Finset.mem_map.2 ⟨y, Finset.filter_subset _ _ hy, rfl⟩ + have hA0' : 0 ∈ A' := Finset.mem_image.2 ⟨0, hA0, by + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp⟩ + have hC' : SupportContained S' (pushUp (split w P)) A' := + supportContained_pushUp_split w hC + (fun a ha => ⟨(hAstab a ha (Fin.last n)).1, (hAstab a ha (Fin.last n)).2⟩) + have hAv' : ∀ i : Fin n, + liftUp (v i.castSucc, false) ∈ A' ∧ -liftUp (v i.castSucc, false) ∈ A' := by + intro i + constructor + · refine Finset.mem_image.2 ⟨v i.castSucc, (hAv i.castSucc).1, ?_⟩ + rw [hv'snoc i] + · refine Finset.mem_image.2 ⟨-v i.castSucc, (hAv i.castSucc).2, ?_⟩ + rw [hv'snoc i, hneg_snoc] + have hAstab' : ∀ a ∈ A', ∀ i : Fin n, + a + 3 • liftUp (v i.castSucc, false) ∈ A' + ∧ a - 3 • liftUp (v i.castSucc, false) ∈ A' := by + intro a' ha' i + obtain ⟨a, ha, rfl⟩ := Finset.mem_image.1 ha' + rw [hA'] + have h1 : 3 • liftUp (v i.castSucc, false) + = Fin.snoc (3 • v i.castSucc) 0 := by + funext j + induction j using Fin.lastCases with + | last => simp [liftUp] + | cast k => simp [liftUp, Pi.smul_apply, smul_eq_mul] + constructor + · refine Finset.mem_image.2 ⟨a + 3 • v i.castSucc, + (hAstab a ha i.castSucc).1, ?_⟩ + rw [h1, hadd_snoc] + · refine Finset.mem_image.2 ⟨a - 3 • v i.castSucc, + (hAstab a ha i.castSucc).2, ?_⟩ + rw [h1, hsub_snoc] + have hv' : ∀ i : Fin n, + shiftDistance S' (pushUp (split w P)) (6 • liftUp (v i.castSucc, false)) + ≤ 3⁻¹ := by + intro i + have h6 : 6 • liftUp (v i.castSucc, false) + = Fin.snoc (6 • v i.castSucc) 0 := by + funext j + induction j using Fin.lastCases with + | last => simp [liftUp] + | cast k => simp [liftUp, Pi.smul_apply] + -- la contention à six décalages + have hmn6 : -(3 • v i.castSucc) - 3 • v i.castSucc ∈ A := + (hAstab _ (hmn3 i.castSucc) i.castSucc).2 + have hwu : 3 • v (Fin.last n) - 3 • v i.castSucc ∈ A := + (hAstab _ hmw i.castSucc).2 + have hnwu : -(3 • v (Fin.last n)) - 3 • v i.castSucc ∈ A := + (hAstab _ hmnw i.castSucc).2 + have hid1 : (-(3 • v i.castSucc) - 3 • v i.castSucc : Fin d → ℤ) + = -(6 • v i.castSucc) := by + funext j + simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply] + ring + have hid2 : 3 • v (Fin.last n) - 3 • v i.castSucc - 3 • v i.castSucc + = w - 6 • v i.castSucc := by + funext j + simp only [Pi.sub_apply, Pi.smul_apply, hw] + ring + have hid3 : -(3 • v (Fin.last n)) - 3 • v i.castSucc - 3 • v i.castSucc + = -w - 6 • v i.castSucc := by + funext j + simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply, hw] + ring + have h6set : SupportContained S P + ({0, w, -w, -(6 • v i.castSucc), w - 6 • v i.castSucc, + -w - 6 • v i.castSucc} : Finset (Fin d → ℤ)) := + hC.mono (by + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht ⊢ + rcases ht with rfl | rfl | rfl | rfl | rfl | rfl + · exact hm0 + · exact hmw + · exact hmnw + · rw [← hid1] + exact hmn6 + · rw [← hid2] + exact (hAstab _ hwu i.castSucc).2 + · rw [← hid3] + exact (hAstab _ hnwu i.castSucc).2) + rw [h6, hS', shiftDistance_pushUp] + exact (shiftDistanceProd_split_le_of_support w (6 • v i.castSucc) + hP0 hmass h6set).trans (hv i.castSucc) + obtain ⟨ε', hε', hmem'⟩ := ih (d + 1) S' E' (pushUp (split w P)) + hP0' hmass' hsupp' hES' A' hA0' hC' + (fun i => liftUp (v i.castSucc, false)) hAv' hAstab' hv' + -- Le point de niveau d + 1, lu coordonnée par coordonnée + set z : Fin d → ℝ := fun k => + coordMoment P S k + ∑ i : Fin n, (ε' i : ℝ) * (v i.castSucc k : ℝ) + with hz + set β : ℝ := splitBit w P S with hb + have hpt : (fun j => coordMoment (pushUp (split w P)) S' j + + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) j : ℝ)) + = Fin.snoc z β := by + funext j + induction j using Fin.lastCases with + | last => + show coordMoment (pushUp (split w P)) S' (Fin.last d) + + ∑ i : Fin n, (ε' i : ℝ) + * ((liftUp (v i.castSucc, false)) (Fin.last d) : ℝ) + = (Fin.snoc z β : Fin (d + 1) → ℝ) (Fin.last d) + rw [hS', coordMoment_pushUp_split_last w P S, hb] + simp [hv'snoc] + | cast k => + show coordMoment (pushUp (split w P)) S' k.castSucc + + ∑ i : Fin n, (ε' i : ℝ) + * ((liftUp (v i.castSucc, false)) k.castSucc : ℝ) + = (Fin.snoc z β : Fin (d + 1) → ℝ) k.castSucc + rw [hS', coordMoment_pushUp_split_of_support w mono3 k, hz] + simp [hv'snoc] + have hmem2 : (fun j => coordMoment (pushUp (split w P)) S' j + + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) j : ℝ)) + ∈ convexHull ℝ + ↑(E'.map (⟨⇑toReal, toReal_injective⟩ : + (Fin (d + 1) → ℤ) ↪ (Fin (d + 1) → ℝ))) := hmem' + rw [hpt] at hmem2 + -- le carré : le support poussé transporté est l'image snocReal + have hmapE : E'.map + (⟨⇑toReal, toReal_injective⟩ : (Fin (d + 1) → ℤ) ↪ (Fin (d + 1) → ℝ)) + = (SQ.map toRealProdEmb).map snocRealEmb := by + apply Finset.ext + intro t + simp only [Finset.mem_map] + constructor + · rintro ⟨q, hq, rfl⟩ + obtain ⟨y, hy, rfl⟩ := Finset.mem_map.1 hq + exact ⟨toRealProd y, ⟨y, hy, rfl⟩, snocReal_toRealProd y⟩ + · rintro ⟨r, hr, rfl⟩ + obtain ⟨y, hy, rfl⟩ := hr + exact ⟨liftUp y, Finset.mem_map.2 ⟨y, hy, rfl⟩, + (snocReal_toRealProd y).symm⟩ + rw [hmapE] at hmem2 + have h1 : Fin.snoc z β = snocReal (z, β) := rfl + rw [h1] at hmem2 + obtain hmempb := (mem_convexHull_map_snocReal + (E := SQ.map toRealProdEmb) (p := (z, β))).mp hmem2 + -- la clé de hauteur : splitBit ≥ 1/3 + have hw2 : w + w = 6 • v (Fin.last n) := by + funext j + simp only [Pi.add_apply, Pi.smul_apply, hw] + ring + have hidww : -(w + w) = -w - w := by + funext j + simp only [Pi.add_apply, Pi.neg_apply, Pi.sub_apply, hw] + ring + have hP5 : SupportContained S P + ({0, w, -w, -w - w, -(w + w)} : Finset (Fin d → ℤ)) := + hC.mono (by + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht ⊢ + rcases ht with rfl | rfl | rfl | rfl | rfl + · exact hm0 + · exact hmw + · exact hmnw + · exact (hAstab _ hmnw (Fin.last n)).2 + · rw [hidww] + exact (hAstab _ hmnw (Fin.last n)).2) + have hβ : 3⁻¹ ≤ β := by + rw [hb, splitBit_eq_of_support w hP0 hmass hP5, hw2] + linarith [hv (Fin.last n)] + -- le rappel : z + e • toReal (v dernier) ∈ enveloppe du support de P + obtain ⟨e, he, hfin⟩ := pullback (v := w) (w := v (Fin.last n)) hP0 hE + (fun i => by rw [hw]; simp) + (fun y hy => (Finset.mem_filter.1 hy).2) + hβ hmempb + -- l'assemblage final + have hēe : ((if e = 1 then 1 else -1 : ℤ) : ℝ) = e := by + rcases he with h | h + · rw [if_pos h, h] + norm_num + · rw [if_neg (by rw [h]; norm_num), h] + norm_num + refine ⟨Fin.snoc ε' (if e = 1 then 1 else -1), ?_, ?_⟩ + · intro i + induction i using Fin.lastCases with + | last => + simp only [Fin.snoc_last] + rcases he with h | h + · exact Or.inl (by rw [if_pos h]) + · exact Or.inr (by rw [if_neg (by rw [h]; norm_num)]) + | cast j => simpa using hε' j + · have hfe : (fun j => coordMoment P S j + + ∑ i : Fin (n + 1), + ((Fin.snoc ε' (if e = 1 then 1 else -1) : Fin (n + 1) → ℤ) i : ℝ) + * (v i j : ℝ)) + = z + e • toReal (v (Fin.last n)) := by + funext j + rw [Fin.sum_univ_castSucc, Fin.snoc_last, hēe] + simp only [Fin.snoc_castSucc, Pi.add_apply, Pi.smul_apply, toReal_apply, hz] + ring + rw [hfe] + exact hfin + +/-- **Lemme 1.4 (Karingula–Lovett) — énoncé public** : si chaque `v i` +d'un ensemble `A` contenant `0` et stable par `± 3 • v j` a une distance de +décalage `≤ 1/3` pour `6 • v i`, il existe une coloration `ε` telle que le +barycentre de `P` augmenté des sommes signées appartienne à l'enveloppe +convexe du support transporté de `P`. + +La forme porte (`exists_colouring_aux`) conclut sur le support exact `E` ; +l'énoncé public le consomme avec `E := S.filter (P · ≠ 0)` et remonte à +l'enveloppe de `S` par monotonie — c'est la lecture lake de l'oracle +`gdahia/Komlos` (`SignedSums.lean` l.32-36), où le `Finsupp` porte son +support canonique. -/ +theorem exists_isColouring_mean_add_sum_mem_convexHull (n d : ℕ) + (S : Finset (Fin d → ℤ)) (P : (Fin d → ℤ) → ℝ) (hP0 : ∀ x, 0 ≤ P x) + (hmass : ∑ x ∈ S, P x = 1) (hPsupp : ∀ x, P x ≠ 0 → x ∈ S) + (A : Finset (Fin d → ℤ)) (hA0 : 0 ∈ A) (hC : SupportContained S P A) + (v : Fin n → (Fin d → ℤ)) (hAv : ∀ i, v i ∈ A ∧ -v i ∈ A) + (hAstab : ∀ a ∈ A, ∀ i, a + 3 • v i ∈ A ∧ a - 3 • v i ∈ A) + (hv : ∀ i, shiftDistance S P (6 • v i) ≤ 3⁻¹) : + ∃ ε : Fin n → ℤ, (∀ i, ε i = 1 ∨ ε i = -1) ∧ + (fun j => coordMoment P S j + ∑ i, (ε i : ℝ) * (v i j : ℝ)) ∈ + convexHull ℝ + ↑(S.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ))) := by + obtain ⟨ε, hε, hmem⟩ := exists_colouring_aux n d S (S.filter (fun x => P x ≠ 0)) P + hP0 hmass (fun x hx => Finset.mem_filter.2 ⟨hPsupp x hx, hx⟩) + (Finset.filter_subset _ _) A hA0 hC v hAv hAstab hv + refine ⟨ε, hε, ?_⟩ + have hsub : (S.filter (fun x => P x ≠ 0)).map + (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ)) + ⊆ S.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ)) := + Finset.map_subset_map.mpr (Finset.filter_subset _ _) + exact convexHull_mono (Finset.coe_subset.2 hsub) hmem + end Discrepancy.Komlos diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean index 63069e76d2..b679afe088 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean @@ -8,13 +8,24 @@ arXiv:2609.20979): toolchain v4.33.0, Mathlib `db584cd6`, i18n convention #4980. The original Dahia source lives in the `gdahia/Komlos` repository (module `Komlos/SignedSums.lean`, toolchain v4.34.0, `Finsupp` framework over `E →₀ ℝ`). The final assembly — the `induction n with` iteration of -Lemma 1.4 — reads there at l.37-58. This lake module opens the -distillation: the first brick `sum_smul_inl` ships here in generic form, -the consumption map of the organs is measured at the top of the module, -and the framework decision (option (c), arbitrated in k2.6a) is recorded. +Lemma 1.4 — reads there at l.37-58. This lake module carries the whole +distillation: the first brick `sum_smul_inl` ships here in generic form +(k2.6, the consumption map of the organs measured at the top of the module, +the framework decision — option (c) — arbitrated in k2.6a), then the final +assembly itself (k2.6c): the real square `snocReal`, the hull transport +`mem_convexHull_map_snocReal`, the two-set inductive gate +`exists_colouring_aux` (closure `S` + exact support `E` — the `Finset` +price of the oracle's canonical `Finsupp` support) and the public statement +`exists_isColouring_mean_add_sum_mem_convexHull`. -/ import Discrepancy.Basic_en +import Discrepancy.Komlos.Containment_en +import Discrepancy.Komlos.Distribution_en +import Discrepancy.Komlos.Lift_en +import Discrepancy.Komlos.LiftSplit_en +import Discrepancy.Komlos.Pullback_en +import Discrepancy.Komlos.Split_en /-! # Signed sums — assembly of Lemma 1.4 (brick k2.6) @@ -65,4 +76,484 @@ lemma sum_smul_inl {n : ℕ} {E : Type*} [AddCommGroup E] [Module ℝ E] (∑ i, ε i • (v i, (0 : ℝ))) = (∑ i, ε i • v i, (0 : ℝ)) := by refine Prod.ext ?_ ?_ <;> simp [Prod.smul_mk, Prod.fst_sum, Prod.snd_sum] +/-! ### Brick k2.6c: the final assembly — the Lemma 1.4 induction -/ + +/-- **The real-side `snoc` isomorphism**: `(Fin d → ℝ) × ℝ → (Fin (d+1) → ℝ)`, +`(z, t) ↦ snoc z t`. It is the real form of the level bridge: the square +`toReal ∘ liftUp = snoc ∘ toRealProd` (cf `toReal_liftUp`, k2.6a) says that +transporting the pushed support into the grown dimension amounts to +`snoc`-ing the transported product support — and that is how the induction +conclusion at dimension `d+1` feeds the k2.4 `pullback`, stated in +`(Fin d → ℝ) × ℝ`. -/ +def snocReal {d : ℕ} : ((Fin d → ℝ) × ℝ) → (Fin (d + 1) → ℝ) := + fun p => Fin.snoc p.1 p.2 + +lemma snocReal_apply_castSucc {d : ℕ} (p : (Fin d → ℝ) × ℝ) (j : Fin d) : + snocReal p j.castSucc = p.1 j := by simp [snocReal] + +lemma snocReal_apply_last {d : ℕ} (p : (Fin d → ℝ) × ℝ) : + snocReal p (Fin.last d) = p.2 := by simp [snocReal] + +/-- **The real square**: `snocReal (toRealProd y) = toReal (liftUp y)` — +the combined reading of `toReal_liftUp` (k2.6a) and of the definition +`toRealProd` (k2.4). It is the only equation missing from the hull +transport between the two readings of the grown dimension. -/ +lemma snocReal_toRealProd {d : ℕ} (y : (Fin d → ℤ) × Bool) : + snocReal (toRealProd y) = toReal (liftUp y) := by + rw [toReal_liftUp] + funext j + simp [snocReal, toRealProd] + +lemma snocReal_injective {d : ℕ} : Function.Injective (snocReal (d := d)) := by + rintro ⟨z₁, t₁⟩ ⟨z₂, t₂⟩ h + have h1 : z₁ = z₂ := by + funext j + have := congrFun h j.castSucc + simpa [snocReal] using this + have h2 : t₁ = t₂ := by + have := congrFun h (Fin.last d) + simpa [snocReal] using this + exact Prod.ext h1 h2 + +/-- The `Finset.Embedding` version of `snocReal`, for the `Finset.map`s of +the transported supports. -/ +def snocRealEmb {d : ℕ} : ((Fin d → ℝ) × ℝ) ↪ (Fin (d + 1) → ℝ) := + ⟨snocReal, snocReal_injective⟩ + +lemma snocRealEmb_apply {d : ℕ} (p : (Fin d → ℝ) × ℝ) : snocRealEmb p = snocReal p := rfl + +/-- `snocReal` as an `ℝ`-linear map. This is the structure that transports +convex hulls: `LinearMap.image_convexHull` identifies the hull of the image +with the image of the hull, and injectivity restores the point — the +transport lemma below follows immediately. -/ +def snocLM {d : ℕ} : ((Fin d → ℝ) × ℝ) →ₗ[ℝ] (Fin (d + 1) → ℝ) where + toFun p := snocReal p + map_add' p q := by + funext j + induction j using Fin.lastCases with + | last => simp [snocReal, Fin.snoc_last, Pi.add_apply] + | cast i => simp [snocReal, Fin.snoc_castSucc, Pi.add_apply] + map_smul' c p := by + funext j + induction j using Fin.lastCases with + | last => simp [snocReal, Fin.snoc_last, Pi.smul_apply, smul_eq_mul] + | cast i => simp [snocReal, Fin.snoc_castSucc, Pi.smul_apply, smul_eq_mul] + +/-- **Hull transport through `snoc`**: belonging to the hull of a +`snoc`-ed finite set is belonging to the hull of the source set. + +This is the organ that closes the diagram square for the k2.6c assembly: +the induction hypothesis concludes in `Fin (d+1) → ℝ` (hull of the +transported pushed support), the k2.4 `pullback` consumes +`(Fin d → ℝ) × ℝ` (hull of the transported product support) — the +correspondence is exactly this transport. Proof: `snocReal` is linear +(`snocLM`) and injective, and `LinearMap.image_convexHull` commutes the +hull and the image. -/ +lemma mem_convexHull_map_snocReal {d : ℕ} {E : Finset ((Fin d → ℝ) × ℝ)} + {p : (Fin d → ℝ) × ℝ} : + snocReal p ∈ convexHull ℝ + (↑(E.map snocRealEmb) : Set ((Fin (d + 1) → ℝ))) ↔ + p ∈ convexHull ℝ (↑E : Set ((Fin d → ℝ) × ℝ)) := by + have hset : (↑(E.map snocRealEmb) : Set ((Fin (d + 1) → ℝ))) + = (⇑snocLM) '' (↑E : Set ((Fin d → ℝ) × ℝ)) := by + rw [Finset.coe_map] + rfl + rw [hset, ← LinearMap.image_convexHull] + constructor + · rintro ⟨q, hq, hfq⟩ + rwa [snocReal_injective hfq] at hq + · exact fun h => ⟨p, h, rfl⟩ + +/-! ### The inductive gate: two sets, `S` the closure and `E` the support -/ + +/-- **Lemma 1.4 (Karingula–Lovett), lake form — the inductive gate**. + +At the oracle (`gdahia/Komlos`, `SignedSums.lean` l.37-58), the induction +lives on `Finsupp`s: the exact support is canonical at every level, and the +induction-hypothesis conclusion is consumed as-is by `pullback`. The lake's +explicit `Finset` framework must pay for that transport: the containment +`SupportContained` (k1.7) demands a support **closed under shifts of `A`** +(the displaced mass points land there), whereas the `pullback` (k2.4) +demands a hull carried by the **exact support** of the split +(`hSQ : ∀ y ∈ SQ, split v P y ≠ 0`). Those two roles are incompatible on a +single `Finset`: the gate therefore carries two — `S` (closure: mass, +moments, containment) and `E` (exact support: hull of the conclusion, +`E ⊆ S`). + +At the next level, `S'` is the lifted image of the full product (containment +is transferred there by `supportContained_pushUp_split`, k2.6b) and `E'` the +pushed exact support (`SQ.map liftUpEmb`, `SQ` the filter of non-zero +splits). The bridge between the two readings is the square +`snocReal ∘ toRealProd = toReal ∘ liftUp` plus the hull transport +`mem_convexHull_map_snocReal` (above). -/ +theorem exists_colouring_aux (n : ℕ) : + ∀ (d : ℕ) (S E : Finset (Fin d → ℤ)) (P : (Fin d → ℤ) → ℝ), + (∀ x, 0 ≤ P x) → (∑ x ∈ S, P x = 1) → + (∀ x, P x ≠ 0 → x ∈ E) → E ⊆ S → + ∀ A : Finset (Fin d → ℤ), 0 ∈ A → SupportContained S P A → + ∀ v : Fin n → (Fin d → ℤ), + (∀ i, v i ∈ A ∧ -v i ∈ A) → + (∀ a ∈ A, ∀ i, a + 3 • v i ∈ A ∧ a - 3 • v i ∈ A) → + (∀ i, shiftDistance S P (6 • v i) ≤ 3⁻¹) → + ∃ ε : Fin n → ℤ, (∀ i, ε i = 1 ∨ ε i = -1) ∧ + (fun j => coordMoment P S j + ∑ i, (ε i : ℝ) * (v i j : ℝ)) ∈ + convexHull ℝ + ↑(E.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ))) := by + induction n with + | zero => + intro d S E P hP0 hmass hE hES A hA0 hC v hAv hAstab hv + have hzero : ∀ x ∈ S, x ∉ E → P x = 0 := by + intro x _ hx + by_contra hp + exact hx (hE x hp) + have hmassE : ∑ x ∈ E, P x = 1 := by + rw [← hmass] + exact Finset.sum_subset hES hzero + have hmean := mean_mem_convexHull hP0 hmassE + refine ⟨fun _ => 1, fun i => i.elim0, ?_⟩ + have hfun : (fun j => coordMoment P S j + + ∑ i : Fin 0, ((fun _ => 1 : Fin 0 → ℤ) i : ℝ) * (v i j : ℝ)) + = (fun j => coordMoment P E j) := by + funext j + have hvan : ∀ x ∈ S, x ∉ E → P x * (x j : ℝ) = 0 := by + intro x _ hxE + by_contra hp + exact hxE (hE x (fun h0 => hp (by rw [h0]; ring))) + simp only [coordMoment] + rw [Finset.sum_subset hES hvan] + simp + rw [hfun] + exact hmean + | succ n ih => + intro d S E P hP0 hmass hE hES A hA0 hC v hAv hAstab hv + classical + -- The splitting vector + set w : Fin d → ℤ := 3 • v (Fin.last n) with hw + -- Memberships in A (stability chains from 0) + have hm0 : (0 : Fin d → ℤ) ∈ A := hA0 + have hmw : 3 • v (Fin.last n) ∈ A := by + simpa using (hAstab 0 hA0 (Fin.last n)).1 + have hmnw : -(3 • v (Fin.last n)) ∈ A := by + simpa using (hAstab 0 hA0 (Fin.last n)).2 + have hmn3 : ∀ i : Fin (n + 1), -(3 • v i) ∈ A := by + intro i + simpa using (hAstab 0 hA0 i).2 + have mono3 : SupportContained S P ({0, w, -w} : Finset (Fin d → ℤ)) := + hC.mono (by + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht ⊢ + rcases ht with rfl | rfl | rfl + · exact hm0 + · exact hmw + · exact hmnw) + -- The level-(d + 1) data + set SQ : Finset ((Fin d → ℤ) × Bool) := + (S ×ˢ (Finset.univ : Finset Bool)).filter (fun y => split w P y ≠ 0) + with hSQ + set S' : Finset (Fin (d + 1) → ℤ) := + (S ×ˢ (Finset.univ : Finset Bool)).map liftUpEmb with hS' + set E' : Finset (Fin (d + 1) → ℤ) := SQ.map liftUpEmb with hE' + set A' : Finset (Fin (d + 1) → ℤ) := + A.image (fun a => Fin.snoc a 0) with hA' + -- Small snoc equations + have hadd_snoc : ∀ x y : Fin d → ℤ, + (Fin.snoc x 0 : Fin (d + 1) → ℤ) + Fin.snoc y 0 + = Fin.snoc (x + y) 0 := by + intro x y + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp + have hsub_snoc : ∀ x y : Fin d → ℤ, + (Fin.snoc x 0 : Fin (d + 1) → ℤ) - Fin.snoc y 0 + = Fin.snoc (x - y) 0 := by + intro x y + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp + have hneg_snoc : ∀ x : Fin d → ℤ, + -(Fin.snoc x 0 : Fin (d + 1) → ℤ) = Fin.snoc (-x) 0 := by + intro x + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp + -- The embedded vectors read as snoc's at zero height + have hv'snoc : ∀ i : Fin n, + (liftUp (v i.castSucc, false) : Fin (d + 1) → ℤ) + = Fin.snoc (v i.castSucc) 0 := fun _ => rfl + -- The arguments of the next level + have hP0' : ∀ z, 0 ≤ pushUp (split w P) z := + fun z => pushUp_nonneg (split_nonneg hP0 w) z + have hmass' : ∑ z ∈ S', pushUp (split w P) z = 1 := by + rw [hS', pushUp_mass, split_mass_of_support w mono3] + exact hmass + have hsupp' : ∀ z, pushUp (split w P) z ≠ 0 → z ∈ E' := by + intro z hz + by_cases hy : ∃ y : (Fin d → ℤ) × Bool, liftUp y = z + · obtain ⟨y, rfl⟩ := hy + have hy' : split w P y ≠ 0 := by + rw [← pushUp_apply (split w P) y] + exact hz + -- the antecedent lives in S ×ˢ univ + have hy1 : y.1 ∈ S := by + obtain ⟨x, b⟩ := y + have hne : P (x + w) ≠ 0 ∨ P (x - w) ≠ 0 := by + cases b with + | false => + rw [split_apply_zero] at hy' + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [max_eq_right h] at hy' + exact Or.inr (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + · rw [max_eq_left h] at hy' + exact Or.inl (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + | true => + rw [split_apply_one] at hy' + rcases le_total (P (x + w)) (P (x - w)) with h | h + · rw [min_eq_left h] at hy' + exact Or.inl (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + · rw [min_eq_right h] at hy' + exact Or.inr (by intro h0; rw [h0, mul_zero] at hy'; exact hy' rfl) + rcases hne with h | h + · have hx := hC (x + w) h (-w) hmnw + simpa using hx + · have hx := hC (x - w) h w hmw + simpa using hx + refine Finset.mem_map.2 ⟨y, Finset.mem_filter.2 ⟨?_, hy'⟩, rfl⟩ + exact Finset.mem_product.2 ⟨hy1, Finset.mem_univ _⟩ + · exact absurd (pushUp_eq_zero (split w P) + (fun y hy' => hy ⟨y, hy'⟩)) hz + have hES' : E' ⊆ S' := by + intro z hz + obtain ⟨y, hy, rfl⟩ := Finset.mem_map.1 hz + exact Finset.mem_map.2 ⟨y, Finset.filter_subset _ _ hy, rfl⟩ + have hA0' : 0 ∈ A' := Finset.mem_image.2 ⟨0, hA0, by + funext j + induction j using Fin.lastCases with + | last => simp + | cast i => simp⟩ + have hC' : SupportContained S' (pushUp (split w P)) A' := + supportContained_pushUp_split w hC + (fun a ha => ⟨(hAstab a ha (Fin.last n)).1, (hAstab a ha (Fin.last n)).2⟩) + have hAv' : ∀ i : Fin n, + liftUp (v i.castSucc, false) ∈ A' ∧ -liftUp (v i.castSucc, false) ∈ A' := by + intro i + constructor + · refine Finset.mem_image.2 ⟨v i.castSucc, (hAv i.castSucc).1, ?_⟩ + rw [hv'snoc i] + · refine Finset.mem_image.2 ⟨-v i.castSucc, (hAv i.castSucc).2, ?_⟩ + rw [hv'snoc i, hneg_snoc] + have hAstab' : ∀ a ∈ A', ∀ i : Fin n, + a + 3 • liftUp (v i.castSucc, false) ∈ A' + ∧ a - 3 • liftUp (v i.castSucc, false) ∈ A' := by + intro a' ha' i + obtain ⟨a, ha, rfl⟩ := Finset.mem_image.1 ha' + rw [hA'] + have h1 : 3 • liftUp (v i.castSucc, false) + = Fin.snoc (3 • v i.castSucc) 0 := by + funext j + induction j using Fin.lastCases with + | last => simp [liftUp] + | cast k => simp [liftUp, Pi.smul_apply, smul_eq_mul] + constructor + · refine Finset.mem_image.2 ⟨a + 3 • v i.castSucc, + (hAstab a ha i.castSucc).1, ?_⟩ + rw [h1, hadd_snoc] + · refine Finset.mem_image.2 ⟨a - 3 • v i.castSucc, + (hAstab a ha i.castSucc).2, ?_⟩ + rw [h1, hsub_snoc] + have hv' : ∀ i : Fin n, + shiftDistance S' (pushUp (split w P)) (6 • liftUp (v i.castSucc, false)) + ≤ 3⁻¹ := by + intro i + have h6 : 6 • liftUp (v i.castSucc, false) + = Fin.snoc (6 • v i.castSucc) 0 := by + funext j + induction j using Fin.lastCases with + | last => simp [liftUp] + | cast k => simp [liftUp, Pi.smul_apply] + -- the six-shift contention + have hmn6 : -(3 • v i.castSucc) - 3 • v i.castSucc ∈ A := + (hAstab _ (hmn3 i.castSucc) i.castSucc).2 + have hwu : 3 • v (Fin.last n) - 3 • v i.castSucc ∈ A := + (hAstab _ hmw i.castSucc).2 + have hnwu : -(3 • v (Fin.last n)) - 3 • v i.castSucc ∈ A := + (hAstab _ hmnw i.castSucc).2 + have hid1 : (-(3 • v i.castSucc) - 3 • v i.castSucc : Fin d → ℤ) + = -(6 • v i.castSucc) := by + funext j + simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply] + ring + have hid2 : 3 • v (Fin.last n) - 3 • v i.castSucc - 3 • v i.castSucc + = w - 6 • v i.castSucc := by + funext j + simp only [Pi.sub_apply, Pi.smul_apply, hw] + ring + have hid3 : -(3 • v (Fin.last n)) - 3 • v i.castSucc - 3 • v i.castSucc + = -w - 6 • v i.castSucc := by + funext j + simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply, hw] + ring + have h6set : SupportContained S P + ({0, w, -w, -(6 • v i.castSucc), w - 6 • v i.castSucc, + -w - 6 • v i.castSucc} : Finset (Fin d → ℤ)) := + hC.mono (by + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht ⊢ + rcases ht with rfl | rfl | rfl | rfl | rfl | rfl + · exact hm0 + · exact hmw + · exact hmnw + · rw [← hid1] + exact hmn6 + · rw [← hid2] + exact (hAstab _ hwu i.castSucc).2 + · rw [← hid3] + exact (hAstab _ hnwu i.castSucc).2) + rw [h6, hS', shiftDistance_pushUp] + exact (shiftDistanceProd_split_le_of_support w (6 • v i.castSucc) + hP0 hmass h6set).trans (hv i.castSucc) + obtain ⟨ε', hε', hmem'⟩ := ih (d + 1) S' E' (pushUp (split w P)) + hP0' hmass' hsupp' hES' A' hA0' hC' + (fun i => liftUp (v i.castSucc, false)) hAv' hAstab' hv' + -- The level-(d + 1) point, read coordinate by coordinate + set z : Fin d → ℝ := fun k => + coordMoment P S k + ∑ i : Fin n, (ε' i : ℝ) * (v i.castSucc k : ℝ) + with hz + set β : ℝ := splitBit w P S with hb + have hpt : (fun j => coordMoment (pushUp (split w P)) S' j + + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) j : ℝ)) + = Fin.snoc z β := by + funext j + induction j using Fin.lastCases with + | last => + show coordMoment (pushUp (split w P)) S' (Fin.last d) + + ∑ i : Fin n, (ε' i : ℝ) + * ((liftUp (v i.castSucc, false)) (Fin.last d) : ℝ) + = (Fin.snoc z β : Fin (d + 1) → ℝ) (Fin.last d) + rw [hS', coordMoment_pushUp_split_last w P S, hb] + simp [hv'snoc] + | cast k => + show coordMoment (pushUp (split w P)) S' k.castSucc + + ∑ i : Fin n, (ε' i : ℝ) + * ((liftUp (v i.castSucc, false)) k.castSucc : ℝ) + = (Fin.snoc z β : Fin (d + 1) → ℝ) k.castSucc + rw [hS', coordMoment_pushUp_split_of_support w mono3 k, hz] + simp [hv'snoc] + have hmem2 : (fun j => coordMoment (pushUp (split w P)) S' j + + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) j : ℝ)) + ∈ convexHull ℝ + ↑(E'.map (⟨⇑toReal, toReal_injective⟩ : + (Fin (d + 1) → ℤ) ↪ (Fin (d + 1) → ℝ))) := hmem' + rw [hpt] at hmem2 + -- the square: the transported pushed support is the snocReal image + have hmapE : E'.map + (⟨⇑toReal, toReal_injective⟩ : (Fin (d + 1) → ℤ) ↪ (Fin (d + 1) → ℝ)) + = (SQ.map toRealProdEmb).map snocRealEmb := by + apply Finset.ext + intro t + simp only [Finset.mem_map] + constructor + · rintro ⟨q, hq, rfl⟩ + obtain ⟨y, hy, rfl⟩ := Finset.mem_map.1 hq + exact ⟨toRealProd y, ⟨y, hy, rfl⟩, snocReal_toRealProd y⟩ + · rintro ⟨r, hr, rfl⟩ + obtain ⟨y, hy, rfl⟩ := hr + exact ⟨liftUp y, Finset.mem_map.2 ⟨y, hy, rfl⟩, + (snocReal_toRealProd y).symm⟩ + rw [hmapE] at hmem2 + have h1 : Fin.snoc z β = snocReal (z, β) := rfl + rw [h1] at hmem2 + obtain hmempb := (mem_convexHull_map_snocReal + (E := SQ.map toRealProdEmb) (p := (z, β))).mp hmem2 + -- the height key: splitBit ≥ 1/3 + have hw2 : w + w = 6 • v (Fin.last n) := by + funext j + simp only [Pi.add_apply, Pi.smul_apply, hw] + ring + have hidww : -(w + w) = -w - w := by + funext j + simp only [Pi.add_apply, Pi.neg_apply, Pi.sub_apply, hw] + ring + have hP5 : SupportContained S P + ({0, w, -w, -w - w, -(w + w)} : Finset (Fin d → ℤ)) := + hC.mono (by + intro t ht + simp only [Finset.mem_insert, Finset.mem_singleton] at ht ⊢ + rcases ht with rfl | rfl | rfl | rfl | rfl + · exact hm0 + · exact hmw + · exact hmnw + · exact (hAstab _ hmnw (Fin.last n)).2 + · rw [hidww] + exact (hAstab _ hmnw (Fin.last n)).2) + have hβ : 3⁻¹ ≤ β := by + rw [hb, splitBit_eq_of_support w hP0 hmass hP5, hw2] + linarith [hv (Fin.last n)] + -- the recall: z + e • toReal (v last) ∈ hull of the support of P + obtain ⟨e, he, hfin⟩ := pullback (v := w) (w := v (Fin.last n)) hP0 hE + (fun i => by rw [hw]; simp) + (fun y hy => (Finset.mem_filter.1 hy).2) + hβ hmempb + -- the final assembly + have hēe : ((if e = 1 then 1 else -1 : ℤ) : ℝ) = e := by + rcases he with h | h + · rw [if_pos h, h] + norm_num + · rw [if_neg (by rw [h]; norm_num), h] + norm_num + refine ⟨Fin.snoc ε' (if e = 1 then 1 else -1), ?_, ?_⟩ + · intro i + induction i using Fin.lastCases with + | last => + simp only [Fin.snoc_last] + rcases he with h | h + · exact Or.inl (by rw [if_pos h]) + · exact Or.inr (by rw [if_neg (by rw [h]; norm_num)]) + | cast j => simpa using hε' j + · have hfe : (fun j => coordMoment P S j + + ∑ i : Fin (n + 1), + ((Fin.snoc ε' (if e = 1 then 1 else -1) : Fin (n + 1) → ℤ) i : ℝ) + * (v i j : ℝ)) + = z + e • toReal (v (Fin.last n)) := by + funext j + rw [Fin.sum_univ_castSucc, Fin.snoc_last, hēe] + simp only [Fin.snoc_castSucc, Pi.add_apply, Pi.smul_apply, toReal_apply, hz] + ring + rw [hfe] + exact hfin + +/-- **Lemma 1.4 (Karingula–Lovett) — public statement**: if every `v i` +of a set `A` containing `0` and stable under `± 3 • v j` has shift distance +`≤ 1/3` for `6 • v i`, then there exists a coloring `ε` such that the +barycenter of `P` augmented by the signed sums belongs to the convex hull +of the transported support of `P`. + +The gate form (`exists_colouring_aux`) concludes on the exact support `E`; +the public statement consumes it with `E := S.filter (P · ≠ 0)` and climbs +back to the hull of `S` by monotonicity — this is the lake reading of the +oracle `gdahia/Komlos` (`SignedSums.lean` l.32-36), where the `Finsupp` +carries its canonical support. -/ +theorem exists_isColouring_mean_add_sum_mem_convexHull (n d : ℕ) + (S : Finset (Fin d → ℤ)) (P : (Fin d → ℤ) → ℝ) (hP0 : ∀ x, 0 ≤ P x) + (hmass : ∑ x ∈ S, P x = 1) (hPsupp : ∀ x, P x ≠ 0 → x ∈ S) + (A : Finset (Fin d → ℤ)) (hA0 : 0 ∈ A) (hC : SupportContained S P A) + (v : Fin n → (Fin d → ℤ)) (hAv : ∀ i, v i ∈ A ∧ -v i ∈ A) + (hAstab : ∀ a ∈ A, ∀ i, a + 3 • v i ∈ A ∧ a - 3 • v i ∈ A) + (hv : ∀ i, shiftDistance S P (6 • v i) ≤ 3⁻¹) : + ∃ ε : Fin n → ℤ, (∀ i, ε i = 1 ∨ ε i = -1) ∧ + (fun j => coordMoment P S j + ∑ i, (ε i : ℝ) * (v i j : ℝ)) ∈ + convexHull ℝ + ↑(S.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ))) := by + obtain ⟨ε, hε, hmem⟩ := exists_colouring_aux n d S (S.filter (fun x => P x ≠ 0)) P + hP0 hmass (fun x hx => Finset.mem_filter.2 ⟨hPsupp x hx, hx⟩) + (Finset.filter_subset _ _) A hA0 hC v hAv hAstab hv + refine ⟨ε, hε, ?_⟩ + have hsub : (S.filter (fun x => P x ≠ 0)).map + (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ)) + ⊆ S.map (⟨⇑toReal, toReal_injective⟩ : (Fin d → ℤ) ↪ (Fin d → ℝ)) := + Finset.map_subset_map.mpr (Finset.filter_subset _ _) + exact convexHull_mono (Finset.coe_subset.2 hsub) hmem + end Discrepancy.Komlos_en diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md index 98ceba896f..18f94ea426 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/FORMAL_STATUS.md @@ -69,6 +69,7 @@ boutes `k1..k5` ci-dessous ; issue de suivi : #17845. | **k2.6a** | `Discrepancy.Komlos.liftUp` : **le pont de niveau — premier préalable mécanique de l'assemblage k2.6**. Ce module n'a **pas de contrepartie oracle**, et cette absence est le fait technique que la brique documente : le Lemme 1.4 de l'oracle est quantifié sur `E` **variable** (`induction n with`, `SignedSums.lean` l.37), son hypothèse d'induction s'applique donc dans l'espace grandi `E × ℝ` (l.52) sans rien construire ; la base du lake `Fin d → ℤ` est **fixe**, et aucun organe k1.x/k2.x ne s'applique à une distribution sur un type réellement différent. **Design-gate arbitré et consigné dans le header du module** : (a) généralisation abstraite `X × Bool` et (b) espace produit itéré `(Fin d → ℤ) × (Fin n → Bool)` **rejetées** — toutes deux une seconde formalisation de la chaîne entière ; **(c) retenue : l'espace qui grandit est `Fin (d + k) → ℤ`**, réalisé par `liftUp : ((Fin d → ℤ) × Bool) → (Fin (d+1) → ℤ)` (partie spatiale par `Fin.snoc`, hauteur `Bool` comme l'entier `{0,1}` à la dernière coordonnée — la contrepartie discrète du `incl b : E ↪ E × ℝ` de l'oracle, `Split.lean` l.31), le miroir d'induction étant `induction n generalizing d` : chaque brique du lake étant générique en `d`, elles s'appliquent **telles quelles à la dimension suivante**. **Livré** : `liftUp` + `liftUp_injective` + `liftUpEmb`/`liftUpEmb_apply` (le pont syntaxique que les rewrites sur les images `Finset.map` exigent — mesuré au round 1 : `rw` ne voit pas `liftUpEmb y` comme `liftUp ?y`) ; `liftUp_add_snoc` (les translations de hauteur nulle commutent avec l'embedding — l'équation qui fait marcher le pont de distance) ; `pushUp` — la poussée le long de `liftUp` sur le **même pattern `Function.extend` que l'organe `push` de k2.3** (et non cet organe : celui-ci est typé sur un morphisme additif, le côté produit n'a pas d'opposé), avec sa lecture `apply`/`eq_zero`/`nonneg`/`mass` ; les **deux ponts de moment** (`coordMoment_pushUp_castSucc` = `prodMoment`, `coordMoment_pushUp_last` = `heightMoment` — les deux composantes de `mean_split` k2.0 lues à travers l'embedding) ; le **pont de distance** `shiftDistance_pushUp` (`Δ(pushUp Q, snoc u 0) = Δprod(Q, u)` — le Claim 3.2 de k1.5 s'applique à la dimension agrandie sans perte) ; l'**exactitude du support** dans les deux sens (`pushUp_ne_zero_of_mem` / `pushUp_mem_map_of_ne_zero`) ; `sum_smul_snoc` — **la forme lake du `sum_smul_inl` de l'oracle dont k2.5 annonçait le consommateur mesuré** (`Split.lean` l.50-53, consommé à `SignedSums.lean` l.54 : une somme pondérée de vecteurs embarqués à hauteur nulle reste à hauteur nulle) ; et `toReal_liftUp` (commutation `toReal ∘ liftUp = snoc ∘ (toReal × hauteur)` — le carré avec `toRealProd` k2.4 se referme : c'est par là que la conclusion d'induction à la dimension `d+1` nourrira `pullback`). **Reportés avec consommateur mesuré** : la conservation des moments sous contenance (`prodMoment_split_of_support`) et le transfert de contenance à travers la scission (k2.6b) ; l'induction elle-même, `SignedSums.lean` nom pour nom (k2.6c). **Trois classes d'erreur mesurées aux rounds 1-2** (consignées pour les portages suivants) : `rfl` échoue sur les lemmes de lecture de `Fin.snoc` au pin (version Tuple hétérogène via `dite`+cast, `Tuple/Basic.lean` l.515 — remplacé par `simp [liftUp]` sur `Fin.snoc_castSucc` l.526 / `Fin.snoc_last` l.539) ; `rw` est syntaxique et exige le pont `liftUpEmb_apply` sur les images `Finset.map` ; `cases` sur un terme non-variable (`y.2`) ne substitue pas dans le but — déstructurer la paire d'abord. Module FR + jumeau `_en` (header et docstring de module en français côté FR, convention du lake — advisory HALF-DONE de l'organe i18n levé). 0 `sorry`. | brique k2 (assemblage) | **PROUVÉ** (k2.6a, 10-04, `lake build` local — ciblé deux jumeaux 0 erreur **0 warning** (28 s chacun, SUCCESS au 3ᵉ round : 6 classes d'erreur des rounds 1-2 diagnostiquées contre le source Mathlib du pin) ; full-lib **8754 jobs** *Build completed successfully*, **37 warnings — identique à k2.5**, 0 sur les modules nouveaux ; `distinct_code_sorry = 0` (lake discrepancy) ; jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19087) | | **k2.6** | `Discrepancy.Komlos.sum_smul_inl` : **première brique de l'assemblage** — nouveau module `Komlos/SignedSums.lean` (+ jumeau `_en`), repris nom pour nom de l'oracle. Livré : `sum_smul_inl` **générique** (`{E : Type*} [AddCommGroup E] [Module ℝ E]`, `∑ i, ε i • (v i, 0) = (∑ i, ε i • v i, 0)` par `Prod.ext` + `Prod.smul_mk`/`fst_sum`/`snd_sum` — les trois noms **vérifiés au pin** : `smul_mk` en `GroupWithZero/Action/Prod.lean`, `fst_sum`/`snd_sum` versions additives de `fst_prod`/`snd_prod` en `BigOperators/Pi.lean` l.155, toolkit identique à `Convex/Combination.lean` l.460) — l'assistant que l'oracle invoque au pas de l'induction (`SignedSums.lean` l.53 : `rw [mean_split, sum_smul_inl, Prod.mk_add_mk, add_zero] at hmem`) pour distribuer une somme de couples sur la première composante. **Carte de généricité (mesurée, en tête du module)** : l'induction de l'oracle ré-instancie ses organes à chaque niveau sur un ambiant croissant `E → E × ℝ → …` ; les organes k2.0–k2.5 de ce lake sont **monomorphes** (`Fin d → ℤ`, hauteur `Bool`) — split, mean_split_of_support, shiftDist_split_le, splitBit_eq, pullback, mean_mem_convexHull. Déjà génériques dans le lake : `segment_repr`, `add_smul_mem_convexHull`, `sum_smul_mem_convexHull` (Pullback.lean l.150/189/213). `sum_smul_inl` était **absent** — livré générique ici, consommable à tout niveau. **Voie β (ping-pong deux espaces) close par la mesure** : le pas oracle écrit simultanément dans `E` (les `v i`) et `ℝ` (les hauteurs) au même niveau d'itération, pas en alternance. **Décision de cadre arbitrée en k2.6a** (option (c) : l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par `liftUp`, la voie α est écartée — cf ligne k2.6a) ; `sum_smul_inl` se positionne comme l'organe générique ℝ-modulaire **complémentaire de `sum_smul_snoc`** (k2.6a, forme lake côté grille), consommable côté transport/hull. 0 `sorry`. | brique k2 (assemblage, 1/…) | **PROUVÉ** (k2.6 brique 1, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | #19425 (stack sur #19089) | | **k2.6b** | `Discrepancy.Komlos.supportContained_pushUp_split` : **la scission sous contention, lue dans la dimension agrandie** — nouveau module `Komlos/LiftSplit.lean` (+ jumeau `_en`), **sans contrepartie oracle** : chez l'oracle le `Finsupp` transporte son support gratuitement (`Finsupp.embDomain`), c'est le cadre `Finset` explicite du lake qui doit payer ce transport — et ce paiement est l'objet de la brique. **Livré** : `pushUp_split_ne_zero` (toute masse de `pushUp (split w P)` vit sur l'image de `liftUp` et provient d'une masse de `P` à distance `± w` — `pushUp_eq_zero` × formes `max`/`min` de `split` par `le_total`/`max_eq_left`/`min_eq_left`) ; `supportContained_pushUp_split` (**le transfert de contenance à travers la scission** : `SupportContained S P A` + stabilité de `A` par `± w` ⟹ la scission-poussée obéit à la contention sur l'image liftée `(S ×ˢ univ).map liftUpEmb`, pour les décalages embarqués `Fin.snoc · 0` de `A` — la précondition de support que le pas de l'induction doit établir pour appliquer l'hypothèse à la dimension `d+1`) ; `coordMoment_pushUp_split_of_support` + `coordMoment_pushUp_split_last` (**la conservation des moments sous contenance, au niveau lifté** : les deux composantes de `mean_split_of_support` k2.0 composées avec les ponts de moment k2.6a — le miroir lake du `rw [mean_split, …] at hmem` de `SignedSums.lean` l.54, composantes spatiale `i.castSucc` et hauteur `Fin.last`) ; `supportContained_pushUp_split_three` (la forme `{0, snoc u 0, −snoc u 0}` exacte que le cran suivant consomme, instance du transfert par `SupportContained.mono` — `snoc 0 0 = 0`, `−snoc u 0 = snoc (−u) 0`). **La stabilité de `A` par `± w` est le prix exact de la scission** : un point de masse `P (x ± w) ≠ 0` déplacé de `a` atterrit en `x + a`, atteint depuis `x ± w` par le décalage `a ∓ w ∈ A`. **Consommateur mesuré** : k2.6c — l'induction elle-même (`SignedSums.lean` l.44-55). 0 `sorry`. | brique k2 (assemblage, 2/…) | **PROUVÉ** (k2.6b, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19425) | +| **k2.6c** | `Discrepancy.Komlos.exists_isColouring_mean_add_sum_mem_convexHull` : **l'assemblage final — l'induction du Lemme 1.4** (`Komlos/SignedSums.lean` l.37-58, nom pour nom). **Décision d'architecture (mesurée)** : le `Finsupp` de l'oracle porte son support exact gratuitement à chaque niveau ; le cadre `Finset` du lake ne peut pas — la contenance `SupportContained` (k1.7) exige un support **fermé par décalages de `A`**, le `pullback` (k2.4) exige une enveloppe sur le **support exact** (`hSQ`), et ces deux rôles sont incompatibles sur un seul `Finset` (un point de masse déplacé par `a ∈ A` peut atterrir sur masse nulle, hors support exact). **Livré** : `snocReal` + `snocLM` + `snocReal_injective` (l'isomorphisme `snoc` côté réel `(Fin d → ℝ) × ℝ → (Fin (d+1) → ℝ)`, structure linéaire et injectivité) ; `snocReal_toRealProd` (le carré réel `snocReal ∘ toRealProd = toReal ∘ liftUp`) ; `mem_convexHull_map_snocReal` (le transport d'enveloppe à travers `snoc`, par `LinearMap.image_convexHull` — l'organe Mathlib remplace une double décomposition à réindexation de poids) ; **`exists_colouring_aux`** — la porte inductive à **deux ensembles** : `S` (fermeture : masse, moments, contenance) et `E` (support exact : enveloppe de la conclusion, `E ⊆ S`) ; au niveau suivant `S' = (S ×ˢ univ).map liftUpEmb` (contenance par `supportContained_pushUp_split` k2.6b), `E' = SQ.map liftUpEmb` (`SQ` le filtre des scissions non nulles) ; et **`exists_isColouring_mean_add_sum_mem_convexHull`** — l'énoncé public (`E := S.filter (P · ≠ 0)`, remontée par `convexHull_mono` + `Finset.map_subset_map`). **La chaîne du pas** (mirror l.44-58) : scission en `w = 3 • v_last` ; `hmass'` par `pushUp_mass` + `split_mass_of_support` ; `hC'` par k2.6b ; `hv'` par `shiftDistance_pushUp` (k2.6a) + Claim 3.2 (k1.7, contention à six décalages atteinte en 1-3 crans de `hAstab`) ; point IH lu comme `snocReal (z, β)` (moments par `coordMoment_pushUp_split_of_support`/`_last`) ; transport par le carré + `mem_convexHull_map_snocReal` ; `hβ : 3⁻¹ ≤ splitBit` par `splitBit_eq_of_support` + `linarith` ; clôture `pullback` (k2.4, implicites nommés `v := w`, `w := v_last`) ; coloration `Fin.snoc ε' ē`. **Le k2 est clos** (l'assemblage l.37-58 est le lemme entier). 0 `sorry`. | brique k2 (assemblage, 3/3 — **clôture du k2**) | **PROUVÉ** (k2.6c, 10-06, `lake build` local ciblé deux jumeaux EXIT=0, `distinct_code_sorry = 0`, jumeaux i18n byte-identical — voir PR) | ce PR (stack sur #19445) | | **k3.1** | `Discrepancy.Komlos.tent` (`Komlos/Tent.lean` + jumeau `_en`) : **la tente discrète, port complet du module de l'oracle** — les 13 preuves reportées en c.885 (delivery #17918) sont closes, chacune adaptée du `grind` v4.34 vers le pin v4.33.0 / `db584cd6` (détail par preuve dans la note de fin de fichier). Sommes closes : `sum_tent` (Σ tent = M²), `sum_tent_sq` (3·Σ tent² = M(2M²+1)) ; Lipschitz `abs_tent_sub_le` (1-Lipschitz) ; pas `step`/`abs_step_le_one`/`step_eq_zero`/`sum_step_sq_le` (≤ 2M) ; télescopage `tent_sub_tent_eq_sum_step` ; **résultat porteur `sum_tent_sub_sq_le`** (Σ (tent M j − tent M (j−m))² ≤ 2·M·m²) — la borne `L²` **discrète** du Lemme 4.1. Adaptations mesurées : `abs_add`/`neg_le_abs_self` **absents au pin** (sondés — la triangulaire inverse passe par `abs_max_sub_max_le_abs` + `abs_abs_sub_abs_le_abs_sub`) ; `omega` ne splitte pas `\|j\|` sur ℤ (atome opaque) → composites `le_abs_self`+`abs_neg` ; l'énoncé `support_tent_subset` force `Set.Icc` (le `Icc` nu sous `open Finset` s'élabore en coercion Finset) ; bornes en cast entier global `((M+1:ℕ):ℤ)` ; `sum_range_sub'` absent → induction manuelle ; `rw` avec `f := id` échoue → normalisation `simp only [id]`. **Réaudit k3 contre l'oracle** : la voie Dahia est **totalement discrète** — `Grid.lean` consomme `sum_tent_sq` + `sum_tent_sub_sq_le` pour construire le poids normalisé `gridF N` (distance `L²` de translation ≤ \|m\|/(N·√12)) ; le « FTC sur segments » du papier est remplacé par la discrétisation sur grille (`intervalIntegral` absent de l'oracle) — la ligne de planification k3 est réécrite en conséquence. 0 `sorry`. | brique k3 (tente + L² discret) | **PROUVÉ** (k3.1, 10-06, `lake build` local EXIT=0 sur les deux jumeaux — 8708 jobs, `distinct_code_sorry = 0`, jumeaux i18n `1/1 byte-identical` — voir PR) | ce PR (branche `feature/komlos-k3-tent`) | | **k3.2** | `Discrepancy.Komlos.gridF` (`Komlos/Grid.lean` + jumeau `_en`) : **le poids normalisé unidimensionnel et sa borne `L²` de translation — port complet du `Komlos/Grid.lean` de l'oracle** (la voie k3 de l'oracle est désormais complète). Briques closes : `gridM` (demi-largeur `6·N`), `gridZ` (constante de normalisation = `∑ tent²`), `gridF` (`tent (gridM N) j / √(gridZ N)`), `cast_gridM`, `gridZ_eq` (**`gridZ N = 144·N³ + 2·N`**), `gridZ_pos`, `gridF_nonneg`, `support_gridF_subset`, `finsum_gridF_sq` (**masse totale `1`**), `sum_gridF_sub_sq`/`sum_gridF_sq` (formes `Finset` consommables), **résultat porteur `sum_gridF_sub_sq_le`** : distance `L²` au carré entre `gridF N` et son translaté par `m` ≤ `m²/(12·N²)` — l'analogue discret du Lemme 4.1, entrée directe de la discrétisation k4 (Lemme 1.5). Adaptations mesurées : le `positivity` de l'oracle sur `gridZ_pos` échoue au pin (stricte positivité dépend de `hN : 0 < N`) → cast + `linarith` ; le `linarith` final de `gridZ_eq` échoue sur le produit non-linéaire → normalisation `ring` explicite avant `linarith` ; `support_tent_subset` de ce lake étant typé `Set.Icc` (l'oracle : `Finset.Icc`), `support_gridF_subset` est prouvé directement (`Finset.mem_coe` + composite `le_abs_self`) ; l'API `finsum` (**existe au pin**, à la racine — sondée) permet le port quasi verbatim des énoncés de masse. **Correctif i18n embarqué** : `Tent_en.lean` passait en `namespace Discrepancy.Komlos` (seul `_en` du lake non suffixé — défaut #17918) ; il repasse en `Discrepancy.Komlos_en`, condition de l'import propre `Grid_en → Tent_en`. 0 `sorry`. | brique k3 (poids normalisé + L²) | **PROUVÉ** (k3.2, 10-06, `lake build` local EXIT=0 sur les trois cibles — 8710 jobs : `Grid`, `Grid_en`, `Tent_en` recompilé ; `distinct_code_sorry = 0`, jumeaux i18n `2/2 byte-identical` — voir PR) | ce PR (stack sur #19563) | | P3 | Banaszczyk 1998 / formes fortes des papiers 2025 **et 2026** | aspiration | **NON ENGAGÉ** — exige SDP + dualité, indépendance spectrale affine, brownien discret guidé, concentration matricielle : **aucun de cet étage n'existe dans Mathlib** (vérifié 2026-08-24). **Réaudité 2026-09-13** contre le Mathlib pinné (`520045ab`, v4.32.1) : le contournement proposé par arXiv:2609.11189 ne supprime pas l'obstruction, il la **déplace** — sa route exige la *variation totale directionnelle* d'une densité sur convexe ouvert et la *transformée de Banaszczyk* préservée sous translation, deux notions **absentes du même Mathlib** (`Banaszczyk` : 0 occurrence ; `totalVariation` n'existe que pour les mesures signées ; la théorie BV de Mathlib concerne la dérivabilité a.e. des fonctions de `ℝ`). Ce que ce papier rapproche, ce sont les *socles* : gaussiennes (`Probability/Distributions/Gaussian/*`) et `ConvexBody` (`Analysis/Convex/Body.lean`) sont présents ; le **pont** manque. Documenté, jamais promis. **Réaudité 2026-09-25** : la voie **élémentaire** de Karingula–Lovett (arXiv:2609.20979, constante `36`) **supprime** cet étage au lieu de le déplacer — sa mécanique est discrète (distance de décalage `Δ`, opérateur de scission `T_v`, induction sur `n` et `d`) à une seule exception, l'estimation de la densité-tente, qui se fait par FTC sur segments + Cauchy–Schwarz `L²` et **non** par de la théorie BV. Balayage des prérequis sur le checkout Mathlib local (`v4.32.0`) : famille **`norm_image_sub_le` présente** (dont `Analysis/Calculus/IntervalIntegral/DistLEIntegral.lean`), `totalVariation` toujours cantonné aux mesures vectorielles (`VectorMeasure/Decomposition/*`) — mais le papier n'en a plus besoin. Réserve de portée : ce balayage porte sur un checkout **voisin** (`v4.32.0`), pas sur le pin du lake (`520045ab`) — à re-vérifier avant la première boute `.lean`. Une formalisation Lean 4 tierce de cette preuve existe déjà (mise à jour du 2026-09-25 ci-dessous). | — | @@ -168,7 +169,7 @@ branche, jamais `main`. Issue de suivi : #17845. | **k1.7** | Correctif d'hypothèse **avant** k2 : l'invariance du support des briques k1 est insatisfiable aux décalages non nuls (mesuré, `eq_zero_of_image_add_eq_self`) → formes consommables sous **contention** `SupportContained` | fini | k1 | | **k2.0** | **Moments de la scission** (`mean_split`) — décomposition par composante du `mean_split` de Dahia (base `Fin d → ℤ` sans structure de `ℝ`-module : `coordMoment`/`prodMoment`, `heightMoment`), moment de hauteur = `splitBit` (`heightMoment_split`), **conservation du barycentre** par la scission (`prodMoment_split`) — l'item reporté par k1.6 | fini | k1, k1.6 | | **k2.0 — correctif de support** | **Formes consommables des moments** — `prodMoment_split_of_support` + `mean_split_of_support` sous `SupportContained S P {0, v, -v}` : k1.7 appliqué à k2.0 (`heightMoment_split` réutilisé inchangé), + contrôle positif `exists_supportContained_nonzero_shift` (`d = 1`, `v = 1`, `P` Dirac, `S = {-1, 0, 1}` via `supportContained_biUnion`) | fini | k1.7, k2.0 | -| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé**. **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Livré en k2.6a** : **le pont de niveau** (`Lift.lean` + jumeau `_en`, sans contrepartie oracle — l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, design-gate arbitré option (c) consigné dans le header du module ; `pushUp` sur le pattern `Function.extend` de k2.3, les ponts de moment / de distance / de support, et `sum_smul_snoc` — **la forme lake du `sum_smul_inl` dont k2.5 annonçait le consommateur mesuré**, désormais livrée, cf ligne k2.6a). **Livré en k2.6 (brique 1)** : `sum_smul_inl` **générique** (module `Komlos/SignedSums.lean` + jumeau `_en`, repris nom pour nom — la carte de généricité des organes y est mesurée, la voie β close par la mesure, la décision de cadre arbitrée en k2.6a). **Livré en k2.6b** : la scission sous contention dans la dimension agrandie (module `Komlos/LiftSplit.lean` + jumeau `_en` — le **transfert de contenance** `supportContained_pushUp_split` + la **conservation des moments liftée** `coordMoment_pushUp_split_of_support`/`_last` : la précondition de support et les ré-écritures de barycentre que le pas exige pour appliquer l'hypothèse d'induction à `pushUp (split w P)` dans `Fin (d+1) → ℤ`, cf ligne k2.6b). **Reste à ce lake, mesuré** : **k2.6c** — la lecture k1.7 du pas elle-même (`SignedSums.lean` l.37-58 nom pour nom : l'itération `induction n generalizing d` qui consomme `mean_mem_convexHull` en base (l.42), `mean_split` + `sum_smul_snoc` au pas (l.53-54) et `pullback` en clôture). | fini + induction | k1, k1.7, k2.0–k2.6b | +| **k2** | **Lemme 1.4** (la noix de cette voie) — **consomme les formes k1.7**, jamais les formes invariantes de k1.2/k1.4/k1.5/k1.6 (vacueuses aux décalages `6 • v i` / `3 • v (Fin.last n)`). **Décomposition mesurée contre l'oracle** (`gdahia/Komlos`, la formalisation de ce lemme — `grep -rniE "entrop\|Real\.log" dahia*.lean` → **0 occurrence**, le libellé « lemme d'entropie » de k1.6 est **retiré**) : l'oracle **consomme `mean_split`** (`Komlos/SignedSums.lean` **l.54**, avec `splitBit_eq` l.55-57 et `shiftDist_split_le` l.51 — les trois désormais **acquis** : `mean_split_of_support` (k2.0 correctif de support, forme **consommable** — l'invariant `mean_split` reste non instanciable aux décalages non nuls) / k1.6 / Claim 3.2) et **n'itère que sur `n`** (`induction n with`, **l.37**) — l'espace ambiant croît à chaque scission (`E × ℝ`) et la généralité de `E` absorbe cette croissance. **Livré en k2.1** : l'algèbre du pullback **sans** convexité (`exists_sign_mul_add_eq` + `segment_repr` + `sum_mul_add_split`, module `Komlos/Pullback.lean`). **Livré en k2.2** : la **machinerie de convexité** — `convexHull` passe de 0 à sa première occurrence ; `add_smul_mem_convexHull` (verbatim) + `sum_smul_mem_convexHull` (l'étape de clôture `Convex.sum_mem`). **Livré en k2.3** : le **transport de dimension** (`Komlos/Transport.lean` : `toReal` + `push` + `push_mass` + les deux ponts que la conclusion lit sur le support transporté — barycentre `coordMoment_toReal`, appartenance `toReal_mem_map_iff` ; `shiftDist_push` et `tvDist_push` reportés avec raison mesurée, cf ligne k2.3) qui, dans une base concrète `Fin d → ℤ`, remplace la généralité de `E` — **le bloqueur mesuré en k2.2 est levé**. **Livré en k2.4** : **le pas complet** (`pullback`, `Komlos/Pullback.lean` l.55-92 — `toRealProd` + les caractérisations de support + le théorème `pullback` lui-même, porté sur `Finset.mem_convexHull'` du pin ; trois écarts de cadre arbitrés, cf ligne k2.4). **Livré en k2.5** : **le cas de base** (`mean_mem_convexHull`, `Komlos/Distribution.lean` l.105, module repris nom pour nom — nouveau `Distribution.lean` + jumeau `_en` ; le one-liner oracle tient tel quel sur l'organe `push` de k2.3, les trois composantes lisant `push_apply`/`push_mass`/`coordMoment_toReal`, cf ligne k2.5). **Livré en k2.6a** : **le pont de niveau** (`Lift.lean` + jumeau `_en`, sans contrepartie oracle — l'espace qui grandit est réalisé `Fin (d + k) → ℤ` par l'embedding `liftUp`, design-gate arbitré option (c) consigné dans le header du module ; `pushUp` sur le pattern `Function.extend` de k2.3, les ponts de moment / de distance / de support, et `sum_smul_snoc` — **la forme lake du `sum_smul_inl` dont k2.5 annonçait le consommateur mesuré**, désormais livrée, cf ligne k2.6a). **Livré en k2.6 (brique 1)** : `sum_smul_inl` **générique** (module `Komlos/SignedSums.lean` + jumeau `_en`, repris nom pour nom — la carte de généricité des organes y est mesurée, la voie β close par la mesure, la décision de cadre arbitrée en k2.6a). **Livré en k2.6b** : la scission sous contention dans la dimension agrandie (module `Komlos/LiftSplit.lean` + jumeau `_en` — le **transfert de contenance** `supportContained_pushUp_split` + la **conservation des moments liftée** `coordMoment_pushUp_split_of_support`/`_last` : la précondition de support et les ré-écritures de barycentre que le pas exige pour appliquer l'hypothèse d'induction à `pushUp (split w P)` dans `Fin (d+1) → ℤ`, cf ligne k2.6b). **Livré en k2.6c** : **l'assemblage final lui-même** (`SignedSums.lean` l.37-58 nom pour nom — l'itération `induction n` qui consomme `mean_mem_convexHull` en base (l.42), la scission de niveau et les moments k2.6b au pas, `pullback` en clôture (l.55) : la porte inductive à deux ensembles `S`/`E`, le carré réel `snocReal` et le transport d'enveloppe `mem_convexHull_map_snocReal`, cf ligne k2.6c). **Le k2 est clos** — les sept crans k2.0 → k2.6c sont livrés. | fini + induction | k1, k1.7, k2.0–k2.6c | | **k3** | Lemme 4.1 — densité-tente. **Réauditée contre l'oracle au pin (k3.1)** : la voie Dahia est **totalement discrète** — le « FTC sur segments » du papier est remplacé par la discrétisation sur grille, `intervalIntegral` **absent de l'oracle** — la dépendance `norm_image_sub_le` est sans objet. **LIVRÉE EN INTÉGRALITÉ** : k3.1 (`Tent.lean` complet, lignes k3.1/k3.2) puis k3.2 (`Grid.lean` complet — `gridF` normalisé, `gridZ_eq : gridZ N = 144·N³ + 2·N`, masse `1`, **`sum_gridF_sub_sq_le` : distance `L²` de translation ≤ m²/(12·N²)**, l'analogue discret du Lemme 4.1). **Reste** : k4 (Lemme 1.5, discrétisation). | fini (oracle discret, complet) | k3.1, k3.2 | | **k4** | Lemme 1.5 — discrétisation sur la grille, cas rationnel | fini | k3 | | **k5** | Assemblage Thm 1.2 sur `ℚ` (témoin `36`) + corollaires (`KomlosBansalJiangWeak`, Beck–Fiala régulier `72√k`) + notebooks `Search-09c`/`Search-09e` (ligne « course aux bornes » du 22/09/2026) | assemblage | k2, k4 | From ddfaba67206ab773f32e61ac446cfaef0e57896e Mon Sep 17 00:00:00 2001 From: jsboige Date: Tue, 6 Oct 2026 11:46:44 +0200 Subject: [PATCH 8/8] refactor(lean,#17845): k2.6c -- nettoyage des 5 warnings unusedSimpArgs de SignedSums Le build de la brique k2.6c (commit 716651cf6c) etait vert mais portait 5 warnings `unusedSimpArgs` flagges par le linter sur les deux jumeaux. Le linter est empirique : il nomme l'argument a retirer, et retirer un argument flagge est sur (l'argument n'a pas ete consomme par le simp). Sites traites (chaque retrait suit la forme cible donnee par le hint) : - l.356 `exists_colouring_aux`, branche `cast` du `Fin.lastCases` : `simp [liftUp, Pi.smul_apply, smul_eq_mul]` -> `simp [liftUp, Pi.smul_apply]` - l.384 `hid1` : `simp only [..., smul_eq_mul, Pi.neg_apply]` -> sans `smul_eq_mul` - l.394 `hid3` : idem, avec `hw` conserve - l.434 `hpt`, branche `last` : `simp [hv'snoc]` -> `simp` - l.441 `hpt`, branche `cast` : `simp [hv'snoc]` -> `simp` Jumeau `SignedSums_en.lean` regenere par `mk_signedsums_en.py` : les cinq meme lignes, hors docstrings, restent byte-identiques. Validation (post-patch, sur l'arbre de travail) : - lake build Discrepancy.Komlos.SignedSums Discrepancy.Komlos.SignedSums_en -> EXIT=0, **0 warning sur les deux fichiers** (log `k26c_build11.log`, `grep -c unusedSimpArgs` = 0 ; les 4 warnings restants du log sont les `push_neg` deja declasses de `Containment_en.lean`, hors perimetre) - count_code_sorry.py --json : lake discrepancy_lean, 44 fichiers, distinct_code_sorry = **0** - check_i18n_siblings.py --all : `SignedSums_en.lean` **OK** ; verdict global 335/341 byte-identical, **0 drift / 0 orphan / 0 unbuilt** - grep sorry|admit : 0 ligne dans les deux jumeaux Aucune preuve ni enonce modifie : seuls des arguments de `simp` inutilises sont retires, les buts restent resolus par le meme `simp` sans ces arguments. See #17845 Co-Authored-By: Claude Sonnet 5.5 (cherry picked from commit 0d2ede53ec2dc2d3b9c647e103305dfa4a1b8c30) --- .../Discrepancy/Komlos/SignedSums.lean | 10 +++++----- .../Discrepancy/Komlos/SignedSums_en.lean | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean index b17d95c8b9..cd9b4fe7d8 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums.lean @@ -353,7 +353,7 @@ theorem exists_colouring_aux (n : ℕ) : funext j induction j using Fin.lastCases with | last => simp [liftUp] - | cast k => simp [liftUp, Pi.smul_apply, smul_eq_mul] + | cast k => simp [liftUp, Pi.smul_apply] constructor · refine Finset.mem_image.2 ⟨a + 3 • v i.castSucc, (hAstab a ha i.castSucc).1, ?_⟩ @@ -381,7 +381,7 @@ theorem exists_colouring_aux (n : ℕ) : have hid1 : (-(3 • v i.castSucc) - 3 • v i.castSucc : Fin d → ℤ) = -(6 • v i.castSucc) := by funext j - simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply] + simp only [Pi.sub_apply, Pi.smul_apply, Pi.neg_apply] ring have hid2 : 3 • v (Fin.last n) - 3 • v i.castSucc - 3 • v i.castSucc = w - 6 • v i.castSucc := by @@ -391,7 +391,7 @@ theorem exists_colouring_aux (n : ℕ) : have hid3 : -(3 • v (Fin.last n)) - 3 • v i.castSucc - 3 • v i.castSucc = -w - 6 • v i.castSucc := by funext j - simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply, hw] + simp only [Pi.sub_apply, Pi.smul_apply, Pi.neg_apply, hw] ring have h6set : SupportContained S P ({0, w, -w, -(6 • v i.castSucc), w - 6 • v i.castSucc, @@ -431,14 +431,14 @@ theorem exists_colouring_aux (n : ℕ) : * ((liftUp (v i.castSucc, false)) (Fin.last d) : ℝ) = (Fin.snoc z β : Fin (d + 1) → ℝ) (Fin.last d) rw [hS', coordMoment_pushUp_split_last w P S, hb] - simp [hv'snoc] + simp | cast k => show coordMoment (pushUp (split w P)) S' k.castSucc + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) k.castSucc : ℝ) = (Fin.snoc z β : Fin (d + 1) → ℝ) k.castSucc rw [hS', coordMoment_pushUp_split_of_support w mono3 k, hz] - simp [hv'snoc] + simp have hmem2 : (fun j => coordMoment (pushUp (split w P)) S' j + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) j : ℝ)) ∈ convexHull ℝ diff --git a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean index b679afe088..3e5f26610f 100644 --- a/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean +++ b/MyIA.AI.Notebooks/Search/discrepancy_lean/Discrepancy/Komlos/SignedSums_en.lean @@ -355,7 +355,7 @@ theorem exists_colouring_aux (n : ℕ) : funext j induction j using Fin.lastCases with | last => simp [liftUp] - | cast k => simp [liftUp, Pi.smul_apply, smul_eq_mul] + | cast k => simp [liftUp, Pi.smul_apply] constructor · refine Finset.mem_image.2 ⟨a + 3 • v i.castSucc, (hAstab a ha i.castSucc).1, ?_⟩ @@ -383,7 +383,7 @@ theorem exists_colouring_aux (n : ℕ) : have hid1 : (-(3 • v i.castSucc) - 3 • v i.castSucc : Fin d → ℤ) = -(6 • v i.castSucc) := by funext j - simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply] + simp only [Pi.sub_apply, Pi.smul_apply, Pi.neg_apply] ring have hid2 : 3 • v (Fin.last n) - 3 • v i.castSucc - 3 • v i.castSucc = w - 6 • v i.castSucc := by @@ -393,7 +393,7 @@ theorem exists_colouring_aux (n : ℕ) : have hid3 : -(3 • v (Fin.last n)) - 3 • v i.castSucc - 3 • v i.castSucc = -w - 6 • v i.castSucc := by funext j - simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, Pi.neg_apply, hw] + simp only [Pi.sub_apply, Pi.smul_apply, Pi.neg_apply, hw] ring have h6set : SupportContained S P ({0, w, -w, -(6 • v i.castSucc), w - 6 • v i.castSucc, @@ -433,14 +433,14 @@ theorem exists_colouring_aux (n : ℕ) : * ((liftUp (v i.castSucc, false)) (Fin.last d) : ℝ) = (Fin.snoc z β : Fin (d + 1) → ℝ) (Fin.last d) rw [hS', coordMoment_pushUp_split_last w P S, hb] - simp [hv'snoc] + simp | cast k => show coordMoment (pushUp (split w P)) S' k.castSucc + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) k.castSucc : ℝ) = (Fin.snoc z β : Fin (d + 1) → ℝ) k.castSucc rw [hS', coordMoment_pushUp_split_of_support w mono3 k, hz] - simp [hv'snoc] + simp have hmem2 : (fun j => coordMoment (pushUp (split w P)) S' j + ∑ i : Fin n, (ε' i : ℝ) * ((liftUp (v i.castSucc, false)) j : ℝ)) ∈ convexHull ℝ