From 7085d68db489c129c39d3795fb25b3683fded7d7 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Thu, 29 Oct 2026 22:56:13 +0000 Subject: [PATCH 01/18] feat(Foundations): correction factorization and reward transport for transition matrices Pure linear algebra for the correction-and-copy hierarchy (#1444 Phase 2, ideas 2 and 4 of #474), following the OpenAI preprint (2026-09-23), Section 4: the factorization 1 - (C - E + EC) = (1 + E)(1 - C), the corrected inverse, copy splitting intertwined with its projection, and the reward transport identity with the stage error bound. Co-Authored-By: Claude Opus 5.5 --- Complexity.lean | 1 + .../Matrix/CorrectionHierarchy.lean | 461 ++++++++++++++++++ ComplexityTests/CorrectionHierarchy.lean | 122 +++++ references.bib | 9 + 4 files changed, 593 insertions(+) create mode 100644 Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean create mode 100644 ComplexityTests/CorrectionHierarchy.lean diff --git a/Complexity.lean b/Complexity.lean index f59b96f22..c0e4b8629 100644 --- a/Complexity.lean +++ b/Complexity.lean @@ -2620,6 +2620,7 @@ public import Complexity.Foundations.LinearAlgebra.ExchangeReplacement public import Complexity.Foundations.LinearAlgebra.ImageSparsification public import Complexity.Foundations.LinearAlgebra.Interpolation public import Complexity.Foundations.LinearAlgebra.KernelVector +public import Complexity.Foundations.LinearAlgebra.Matrix.CorrectionHierarchy public import Complexity.Foundations.LinearAlgebra.Matrix.CutRank public import Complexity.Foundations.LinearAlgebra.Matrix.Kronecker public import Complexity.Foundations.LinearAlgebra.Matrix.Lindsey diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean new file mode 100644 index 000000000..606c43617 --- /dev/null +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean @@ -0,0 +1,461 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Init +public import Mathlib.LinearAlgebra.Matrix.Block +public import Mathlib.LinearAlgebra.Matrix.NonsingularInverse +import Mathlib.Algebra.Order.BigOperators.Group.Finset +import Mathlib.Tactic.NoncommRing + +/-! +# Corrections, copies and reward transport for transition matrices + +Let `C` be the transition matrix of a finite Markov chain that may stop (its rows sum to at most +one), and let `e` be a reward collected when it stops. The expected reward `p` from each state +solves `(1 - C) p = e`; when `C` is nilpotent, `p = (1 - C)⁻¹ e`. For the time-layered +configuration graph of a randomized machine, `p` is the vector of acceptance probabilities. + +This file develops the exact algebra of a hierarchy that shrinks the entries of `C` while keeping +`p` recoverable, following the OpenAI preprint (2026-09-23), Section 4, idea 2 and the deterministic +part of idea 4 in issue #474 [OpenAI2026LogSpace]. The estimates that choose the corrections and +the copies (factorial truncation, detectors) are not part of this file. + +* **Correction.** For any matrix `E`, the *corrected* matrix `D = C - E + E C` satisfies + `1 - D = (1 + E) (1 - C)` (`one_add_mul_one_sub_eq_one_sub`, a ring identity). So the same `p` + solves `(1 - D) p = (1 + E) e` (`Matrix.one_sub_correction_mulVec`): the correction moves + transition weight into the reward `e + E e`. When `1 + E` is invertible, for example when `E` is + strictly upper triangular, `(1 - D)⁻¹ (e + E e) = (1 - C)⁻¹ e` + (`Matrix.inv_one_sub_correction_mulVec`). If `E ≥ 0` and the rows of `C` sum to at most one, + the rows of `D` sum to at most as much (`Matrix.correction_mulVec_one_le`). +* **Copies.** A vertex `x` is replaced by copies `(x, i)`, weighted by `r i x`, and an entry + `D x y` is split among the copies of `y` in proportions `s x y j` (`Matrix.copySplit`). + If the weighted proportions sum to one on the support of `D`, the projection + `Matrix.copyWeight r` intertwines the two matrices: `copySplit r s D * copyWeight r = + copyWeight r * D` (`Matrix.copySplit_mul_copyWeight`). +* **Reward transport.** Iterating, a sequence of stages with transition matrices `C l`, + corrections `E l` and projections `P l` satisfying `C (l + 1) * P l = P l * D l` carries the + cumulative projection `Matrix.copyProjection` and the transported reward + `Matrix.rewardTransport`, with `C l * Pc l = Pc l - B l * (1 - C 0)` + (`Matrix.mul_copyProjection`). Hence the stage-`l` reward `W l = B l e` equals + `Pc l p - C l Pc l p` (`Matrix.rewardTransport_mulVec`). At a vertex `z l` reached from `z 0` + by primary copies only, the transported reward underestimates `p (z 0)` by at most the row + sum of `C l` (`Matrix.sub_rewardTransport_mulVec_mem_Icc`), so by at most `|A l| * ε l` when + the entries of `C l` are at most `ε l` and its nonzero columns lie in `A l` + (`Matrix.sub_rewardTransport_mulVec_le_card_mul`). With the paper's per-stage rates (entries + shrink by `2 ^ (c + 1)`, active columns at most double) this is the stage bound + `0 ≤ p (z 0) - W l (z l) ≤ n / 2 ^ (c l)` (`Matrix.sub_rewardTransport_mulVec_le_pow`). + +## Main definitions + +* `Matrix.IsStrictUpperTriangular`: entries vanish unless the row index is below the column index. +* `Matrix.copySplit`, `Matrix.copyWeight`: a copy step and its weighted projection. +* `Matrix.copyProjection`, `Matrix.rewardTransport`: cumulative projections and rewards of a + sequence of stages. + +## Main results + +* `one_add_mul_one_sub_eq_one_sub`: `(1 + e) (1 - c) = 1 - (c - e + e c)` in any ring. +* `Matrix.one_sub_correction_mulVec`, `Matrix.inv_one_sub_correction_mulVec`: the expected reward + of `C` is the expected corrected reward of `C - E + E C`. +* `Matrix.IsStrictUpperTriangular.det_one_add`: `det (1 + E) = 1` for strictly upper triangular + `E`. +* `Matrix.correction_mulVec_one_le`: corrections keep matrices substochastic. +* `Matrix.copySplit_mul_copyWeight`: a copy step intertwines with its projection. +* `Matrix.mul_copyProjection`, `Matrix.rewardTransport_mulVec`: the reward transport identity. +* `Matrix.sub_rewardTransport_mulVec_mem_Icc`, `Matrix.sub_rewardTransport_mulVec_le_card_mul`, + `Matrix.sub_rewardTransport_mulVec_le_pow`: the transported reward is a lower bound with error + controlled by the last transition matrix. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Section 4 (preprint, not peer reviewed) +-/ + +public section + +open Finset + +/-- **The correction factorization.** In any ring, correcting `c` by `e` to `c - e + e * c` +factors `1 - (c - e + e * c)` as `(1 + e) * (1 - c)` [OpenAI2026LogSpace, Section 4]. -/ +theorem one_add_mul_one_sub_eq_one_sub {R : Type*} [Ring R] (c e : R) : + (1 + e) * (1 - c) = 1 - (c - e + e * c) := by + noncomm_ring + +namespace Matrix + +section Triangular + +variable {V R : Type*} + +/-- A square matrix is *strictly upper triangular* when its entry at `(i, j)` vanishes unless +`i < j`. For the time-layered transition matrices of a machine, ordered by time, this says that +every transition moves strictly forward. -/ +def IsStrictUpperTriangular [LT V] [Zero R] (M : Matrix V V R) : Prop := + ∀ ⦃i j⦄, ¬ i < j → M i j = 0 + +namespace IsStrictUpperTriangular + +variable [Preorder V] {M N : Matrix V V R} + +/-- A strictly upper triangular matrix is upper triangular. -/ +theorem isUpperTriangular [Zero R] (h : M.IsStrictUpperTriangular) : M.IsUpperTriangular := + fun _ _ hji => h (lt_asymm hji) + +theorem add [AddZeroClass R] (hM : M.IsStrictUpperTriangular) (hN : N.IsStrictUpperTriangular) : + (M + N).IsStrictUpperTriangular := fun i j hij => by + simp only [add_apply, hM hij, hN hij, add_zero] + +theorem neg [SubtractionMonoid R] (hM : M.IsStrictUpperTriangular) : + (-M).IsStrictUpperTriangular := fun i j hij => by + simp only [neg_apply, hM hij, neg_zero] + +theorem sub [SubtractionMonoid R] (hM : M.IsStrictUpperTriangular) + (hN : N.IsStrictUpperTriangular) : (M - N).IsStrictUpperTriangular := fun i j hij => by + simp only [sub_apply, hM hij, hN hij, sub_zero] + +theorem mul [Fintype V] [NonUnitalNonAssocSemiring R] (hM : M.IsStrictUpperTriangular) + (hN : N.IsStrictUpperTriangular) : (M * N).IsStrictUpperTriangular := fun i j hij => by + refine Finset.sum_eq_zero fun k _ => ?_ + change M i k * N k j = 0 + by_cases hik : i < k + · rw [hN fun hkj => hij (hik.trans hkj), mul_zero] + · rw [hM hik, zero_mul] + +/-- `1 + E` has determinant one when `E` is strictly upper triangular. -/ +theorem det_one_add {V : Type*} [Fintype V] [DecidableEq V] [LinearOrder V] [CommRing R] + {E : Matrix V V R} (h : E.IsStrictUpperTriangular) : (1 + E).det = 1 := by + have hT : (1 + E).IsUpperTriangular := fun i j (hji : j < i) => by + rw [add_apply, one_apply_ne (ne_of_lt hji).symm, h.isUpperTriangular hji, add_zero] + rw [det_of_isUpperTriangular hT] + exact Finset.prod_eq_one fun i _ => by rw [add_apply, one_apply_eq, h (lt_irrefl i), add_zero] + +end IsStrictUpperTriangular + +end Triangular + +section Correction + +variable {V R : Type*} [Fintype V] + +/-- **Corrections preserve the expected reward.** Correcting `C` to `C - E + E * C` turns the +equation `(1 - C) p = e` into `(1 - D) p = (1 + E) e` for the same `p`: the weight removed from +the transitions reappears in the reward [OpenAI2026LogSpace, Section 4]. -/ +theorem one_sub_correction_mulVec [DecidableEq V] [Ring R] (C E : Matrix V V R) (p : V → R) : + (1 - (C - E + E * C)) *ᵥ p = (1 + E) *ᵥ ((1 - C) *ᵥ p) := by + rw [mulVec_mulVec, one_add_mul_one_sub_eq_one_sub] + +/-- **The corrected inverse.** When `1 + E` is invertible, the expected reward +`(1 - C)⁻¹ e` of `C` equals the expected reward of the corrected matrix `C - E + E * C` with the +corrected reward `e + E e`. -/ +theorem inv_one_sub_correction_mulVec [DecidableEq V] [CommRing R] {C E : Matrix V V R} + (hE : IsUnit (1 + E).det) (e : V → R) : + (1 - (C - E + E * C))⁻¹ *ᵥ (e + E *ᵥ e) = (1 - C)⁻¹ *ᵥ e := by + have h : (1 - (C - E + E * C))⁻¹ * (1 + E) = (1 - C)⁻¹ := by + rw [← one_add_mul_one_sub_eq_one_sub, mul_inv_rev, + nonsing_inv_mul_cancel_right (1 + E) (1 - C)⁻¹ hE] + rw [← h, ← mulVec_mulVec, add_mulVec, one_mulVec] + +/-- The corrected inverse for a strictly upper triangular correction. -/ +theorem IsStrictUpperTriangular.inv_one_sub_correction_mulVec [DecidableEq V] [LinearOrder V] + [CommRing R] {C E : Matrix V V R} (hE : E.IsStrictUpperTriangular) (e : V → R) : + (1 - (C - E + E * C))⁻¹ *ᵥ (e + E *ᵥ e) = (1 - C)⁻¹ *ᵥ e := + Matrix.inv_one_sub_correction_mulVec (by rw [hE.det_one_add]; exact isUnit_one) e + +/-- The row sums of a corrected matrix: `(C - E + E C) 1 = C 1 - E (1 - C 1)`. -/ +theorem correction_mulVec_one [Ring R] (C E : Matrix V V R) : + (C - E + E * C) *ᵥ 1 = C *ᵥ 1 - E *ᵥ (1 - C *ᵥ 1) := by + rw [add_mulVec, sub_mulVec, ← mulVec_mulVec, mulVec_sub] + abel + +/-- An entrywise nonnegative matrix maps nonnegative vectors to nonnegative vectors. -/ +theorem mulVec_nonneg {m n : Type*} [Fintype n] [Semiring R] [PartialOrder R] [IsOrderedRing R] + {M : Matrix m n R} (hM : ∀ i j, 0 ≤ M i j) {v : n → R} (hv : 0 ≤ v) : 0 ≤ M *ᵥ v := + fun i => Finset.sum_nonneg fun j _ => mul_nonneg (hM i j) (hv j) + +/-- An entrywise nonnegative matrix whose rows sum to at most one maps vectors with entries at +most one to vectors with entries at most one. -/ +theorem mulVec_le_one {m n : Type*} [Fintype n] [Semiring R] [PartialOrder R] [IsOrderedRing R] + {M : Matrix m n R} (hM : ∀ i j, 0 ≤ M i j) (hM1 : M *ᵥ 1 ≤ 1) {v : n → R} + (hv : v ≤ 1) : + M *ᵥ v ≤ 1 := fun i => + le_trans (Finset.sum_le_sum fun j _ => mul_le_mul_of_nonneg_left (hv j) (hM i j)) (hM1 i) + +/-- **Corrections keep rows substochastic.** If `E ≥ 0` and the rows of `C` sum to at most one, +then each row of `C - E + E C` sums to at most the corresponding row of `C`. -/ +theorem correction_mulVec_one_le [Ring R] [PartialOrder R] [IsOrderedRing R] + {C E : Matrix V V R} (hE : ∀ i j, 0 ≤ E i j) (hC : C *ᵥ 1 ≤ 1) : + (C - E + E * C) *ᵥ 1 ≤ C *ᵥ 1 := by + rw [correction_mulVec_one] + exact sub_le_self _ (mulVec_nonneg hE (sub_nonneg.mpr hC)) + +end Correction + +section Copy + +variable {V ι R : Type*} + +/-- **A copy step.** Each vertex `x` gets copies `(x, i)` with row weights `r i x`, and the entry +`D x y` is split among the copies `(y, j)` of its target in proportions `s x y j`. In the +preprint the proportions depend only on the size of `D x y`, and the copies beyond a primary one +are activated only at targets where the correction was suppressed +[OpenAI2026LogSpace, Section 4.4]. -/ +@[expose] def copySplit [Mul R] (r : ι → V → R) (s : V → V → ι → R) (D : Matrix V V R) : + Matrix (V × ι) (V × ι) R := + of fun a b => r a.2 a.1 * D a.1 b.1 * s a.1 b.1 b.2 + +/-- The *copy projection* from copies to their parents, weighted by `r`: the copy `(x, i)` maps +to `x` with weight `r i x`. -/ +@[expose] def copyWeight [DecidableEq V] [Zero R] (r : ι → V → R) : Matrix (V × ι) V R := + of fun a z => if a.1 = z then r a.2 a.1 else 0 + +@[simp] +theorem copyWeight_mulVec [Fintype V] [DecidableEq V] [NonUnitalNonAssocSemiring R] + (r : ι → V → R) (v : V → R) (a : V × ι) : + (copyWeight r *ᵥ v) a = r a.2 a.1 * v a.1 := by + simp [copyWeight, mulVec, dotProduct, ite_mul] + +/-- A copy with weight one projects to its parent exactly. -/ +theorem copyWeight_apply_of_eq_one [DecidableEq V] [Semiring R] {r : ι → V → R} {x : V} + {i : ι} (h : r i x = 1) (w : V) : copyWeight r (x, i) w = if w = x then 1 else 0 := by + simp [copyWeight, h, eq_comm] + +/-- **Copies intertwine with their projection.** If, on every nonzero entry `D x y`, the +proportions `s x y j` weighted by `r j y` sum to one, then splitting `D` into copies and +projecting back agrees with projecting first: `copySplit r s D * copyWeight r = +copyWeight r * D` [OpenAI2026LogSpace, Proposition 4.5]. -/ +theorem copySplit_mul_copyWeight [Fintype V] [DecidableEq V] [Fintype ι] [Semiring R] + {r : ι → V → R} {s : V → V → ι → R} {D : Matrix V V R} + (hs : ∀ x y, D x y ≠ 0 → ∑ j, s x y j * r j y = 1) : + copySplit r s D * copyWeight r = copyWeight r * D := by + ext ⟨x, i⟩ z + have hL : (copySplit r s D * copyWeight r) (x, i) z = r i x * D x z * ∑ j, s x z j * r j z := by + rw [mul_apply, Fintype.sum_prod_type, Fintype.sum_eq_single z fun y hy => ?_, Finset.mul_sum] + · simp [copySplit, copyWeight, mul_assoc] + · simp [copyWeight, hy] + have hR : (copyWeight r * D) (x, i) z = r i x * D x z := by + rw [mul_apply, Fintype.sum_eq_single x fun y hy => ?_] + · simp [copyWeight] + · simp [copyWeight, Ne.symm hy] + rw [hL, hR] + by_cases hD : D x z = 0 + · simp [hD] + · rw [hs x z hD, mul_one] + +theorem copySplit_nonneg [Semiring R] [PartialOrder R] [IsOrderedRing R] {r : ι → V → R} + {s : V → V → ι → R} {D : Matrix V V R} (hr : ∀ i x, 0 ≤ r i x) + (hs : ∀ x y j, 0 ≤ s x y j) (hD : ∀ x y, 0 ≤ D x y) (a b : V × ι) : + 0 ≤ copySplit r s D a b := + mul_nonneg (mul_nonneg (hr _ _) (hD _ _)) (hs _ _ _) + +/-- **Copies keep rows substochastic** when the weights are at most one and the proportions of +each entry sum to at most one. -/ +theorem copySplit_mulVec_one_le [Fintype V] [Fintype ι] [Semiring R] [PartialOrder R] + [IsOrderedRing R] {r : ι → V → R} {s : V → V → ι → R} {D : Matrix V V R} + (hr0 : ∀ i x, 0 ≤ r i x) (hr1 : ∀ i x, r i x ≤ 1) (hs1 : ∀ x y, ∑ j, s x y j ≤ 1) + (hD0 : ∀ x y, 0 ≤ D x y) (hD1 : D *ᵥ 1 ≤ 1) : copySplit r s D *ᵥ 1 ≤ 1 := by + rintro ⟨x, i⟩ + have hrow : ∑ b : V × ι, copySplit r s D (x, i) b ≤ r i x * ∑ y, D x y := by + rw [Fintype.sum_prod_type, Finset.mul_sum] + refine Finset.sum_le_sum fun y _ => ?_ + simp only [copySplit, of_apply, ← Finset.mul_sum] + exact mul_le_of_le_one_right (mul_nonneg (hr0 i x) (hD0 x y)) (hs1 x y) + have hDx : ∑ y, D x y ≤ 1 := by simpa [mulVec, dotProduct] using hD1 x + simpa [mulVec, dotProduct] using + (hrow.trans (mul_le_of_le_one_right (hr0 i x) hDx)).trans (hr1 i x) + +end Copy + +section Hierarchy + +variable {V : ℕ → Type*} [∀ l, Fintype (V l)] [∀ l, DecidableEq (V l)] {R : Type*} + +/-- **The cumulative projection** of a sequence of stages with projections +`P l : Matrix (V (l + 1)) (V l) R`: the product `P (l - 1) * ⋯ * P 0`, from stage `l` to +stage `0`. -/ +@[expose] def copyProjection [Semiring R] (P : ∀ l, Matrix (V (l + 1)) (V l) R) : + ∀ l, Matrix (V l) (V 0) R + | 0 => 1 + | l + 1 => P l * copyProjection P l + +/-- **The transported reward matrix** of a sequence of stages with projections `P l` and +corrections `E l`: `B (l + 1) = P l * (1 + E l) * B l`, starting from `B 0 = 1`. Applied to the +initial reward `e`, it gives the stage-`l` reward `B l e`. -/ +@[expose] def rewardTransport [Semiring R] (P : ∀ l, Matrix (V (l + 1)) (V l) R) + (E : ∀ l, Matrix (V l) (V l) R) : ∀ l, Matrix (V l) (V 0) R + | 0 => 1 + | l + 1 => P l * (1 + E l) * rewardTransport P E l + +variable {C E : ∀ l, Matrix (V l) (V l) R} {P : ∀ l, Matrix (V (l + 1)) (V l) R} + +/-- **The reward transport identity.** If each stage's transition matrix intertwines with the +corrected matrix of the previous stage, `C (l + 1) * P l = P l * (C l - E l + E l * C l)`, then +`C l * Pc l = Pc l - B l * (1 - C 0)` for the cumulative projection `Pc` and the transported +reward matrix `B` [OpenAI2026LogSpace, Proposition 4.7]. -/ +theorem mul_copyProjection [Ring R] + (h : ∀ l, C (l + 1) * P l = P l * (C l - E l + E l * C l)) (l : ℕ) : + C l * copyProjection P l = copyProjection P l - rewardTransport P E l * (1 - C 0) := by + induction l with + | zero => simp [copyProjection, rewardTransport] + | succ l ih => + have hD : C l - E l + E l * C l = 1 - (1 + E l) * (1 - C l) := by + rw [one_add_mul_one_sub_eq_one_sub, sub_sub_cancel] + have hB : (1 - C l) * copyProjection P l = rewardTransport P E l * (1 - C 0) := by + rw [Matrix.sub_mul, Matrix.one_mul, ih, sub_sub_cancel] + calc C (l + 1) * copyProjection P (l + 1) + = P l * (C l - E l + E l * C l) * copyProjection P l := by + rw [copyProjection, ← Matrix.mul_assoc, h] + _ = P l * copyProjection P l - P l * (1 + E l) * ((1 - C l) * copyProjection P l) := by + rw [hD] + simp only [Matrix.mul_sub, Matrix.sub_mul, Matrix.mul_one, Matrix.one_mul, + Matrix.mul_assoc] + _ = copyProjection P (l + 1) - rewardTransport P E (l + 1) * (1 - C 0) := by + rw [hB] + simp only [copyProjection, rewardTransport, Matrix.mul_assoc] + +/-- **The transported reward.** If `p` solves `(1 - C 0) p = e`, the stage-`l` reward is +`B l e = Pc l p - C l (Pc l p)`: the projected solution minus what the remaining transitions +still carry [OpenAI2026LogSpace, Proposition 4.7]. -/ +theorem rewardTransport_mulVec [Ring R] + (h : ∀ l, C (l + 1) * P l = P l * (C l - E l + E l * C l)) {p e : V 0 → R} + (hp : (1 - C 0) *ᵥ p = e) (l : ℕ) : + rewardTransport P E l *ᵥ e = + copyProjection P l *ᵥ p - C l *ᵥ (copyProjection P l *ᵥ p) := by + rw [mulVec_mulVec, mul_copyProjection h, sub_mulVec, ← mulVec_mulVec, hp, sub_sub_cancel] + +/-- The stage rewards are updated by adding the correction's contribution and projecting: +`W (l + 1) = P l (W l + E l W l)`. -/ +theorem rewardTransport_succ_mulVec [Semiring R] (e : V 0 → R) (l : ℕ) : + rewardTransport P E (l + 1) *ᵥ e = + P l *ᵥ (rewardTransport P E l *ᵥ e + E l *ᵥ (rewardTransport P E l *ᵥ e)) := by + rw [rewardTransport, ← mulVec_mulVec, ← mulVec_mulVec, add_mulVec, one_mulVec] + +/-- Along *primary copies* `z l`, whose rows of `P l` are unit vectors, the cumulative projection +reads off the original coordinate. -/ +theorem copyProjection_mulVec_primary [Semiring R] {z : ∀ l, V l} + (hz : ∀ l w, P l (z (l + 1)) w = if w = z l then 1 else 0) (p : V 0 → R) (l : ℕ) : + (copyProjection P l *ᵥ p) (z l) = p (z 0) := by + induction l with + | zero => simp [copyProjection] + | succ l ih => + rw [copyProjection, ← mulVec_mulVec] + simp [mulVec, dotProduct, hz, ite_mul, ← ih] + +section Order + +variable [Ring R] [PartialOrder R] [IsOrderedRing R] + +private theorem one_apply_nonneg {n : Type*} [DecidableEq n] (i j : n) : + (0 : R) ≤ (1 : Matrix n n R) i j := by + rw [one_apply]; split_ifs <;> simp + +private theorem mul_nonneg_entries {m n o : Type*} [Fintype n] {A : Matrix m n R} + {B : Matrix n o R} (hA : ∀ i j, 0 ≤ A i j) (hB : ∀ i j, 0 ≤ B i j) (i : m) (k : o) : + 0 ≤ (A * B) i k := + Finset.sum_nonneg fun j _ => mul_nonneg (hA i j) (hB j k) + +theorem copyProjection_nonneg (hP : ∀ l i j, 0 ≤ P l i j) (l : ℕ) : + ∀ i j, 0 ≤ copyProjection P l i j := by + induction l with + | zero => exact one_apply_nonneg + | succ l ih => exact mul_nonneg_entries (hP l) ih + +/-- The cumulative projection of substochastic projections is substochastic. -/ +theorem copyProjection_mulVec_one_le (hP : ∀ l i j, 0 ≤ P l i j) (hP1 : ∀ l, P l *ᵥ 1 ≤ 1) + (l : ℕ) : copyProjection P l *ᵥ 1 ≤ 1 := by + induction l with + | zero => simp [copyProjection] + | succ l ih => + rw [copyProjection, ← mulVec_mulVec] + exact mulVec_le_one (hP l) (hP1 l) ih + +theorem rewardTransport_nonneg (hP : ∀ l i j, 0 ≤ P l i j) (hE : ∀ l i j, 0 ≤ E l i j) + (l : ℕ) : ∀ i j, 0 ≤ rewardTransport P E l i j := by + induction l with + | zero => exact one_apply_nonneg + | succ l ih => + exact mul_nonneg_entries (mul_nonneg_entries (hP l) + (fun i j => add_nonneg (one_apply_nonneg i j) (hE l i j))) ih + +variable (hP : ∀ l i j, 0 ≤ P l i j) (hP1 : ∀ l, P l *ᵥ 1 ≤ 1) + (hC : ∀ l i j, 0 ≤ C l i j) (hstep : ∀ l, C (l + 1) * P l = P l * (C l - E l + E l * C l)) + {p e : V 0 → R} + (hp : (1 - C 0) *ᵥ p = e) (hp0 : 0 ≤ p) (hp1 : p ≤ 1) +include hP hP1 hC hstep hp hp0 hp1 + +/-- The stage rewards are bounded by the projected solution, hence by one. -/ +theorem rewardTransport_mulVec_le (l : ℕ) : + rewardTransport P E l *ᵥ e ≤ copyProjection P l *ᵥ p ∧ + copyProjection P l *ᵥ p ≤ 1 := by + have hPc0 : 0 ≤ copyProjection P l *ᵥ p := mulVec_nonneg (copyProjection_nonneg hP l) hp0 + refine ⟨?_, mulVec_le_one (copyProjection_nonneg hP l) + (copyProjection_mulVec_one_le hP hP1 l) hp1⟩ + rw [rewardTransport_mulVec hstep hp] + exact sub_le_self _ (mulVec_nonneg (hC l) hPc0) + +/-- **The stage error.** Along primary copies `z l`, the stage-`l` reward underestimates the +solution at `z 0` by at most the row sum of `C l` at `z l` +[OpenAI2026LogSpace, Proposition 4.7]. -/ +theorem sub_rewardTransport_mulVec_mem_Icc {z : ∀ l, V l} + (hz : ∀ l w, P l (z (l + 1)) w = if w = z l then 1 else 0) (l : ℕ) : + p (z 0) - (rewardTransport P E l *ᵥ e) (z l) ∈ Set.Icc 0 (∑ y, C l (z l) y) := by + have hPc0 : 0 ≤ copyProjection P l *ᵥ p := mulVec_nonneg (copyProjection_nonneg hP l) hp0 + have hPc1 : copyProjection P l *ᵥ p ≤ 1 := + (rewardTransport_mulVec_le hP hP1 hC hstep hp hp0 hp1 l).2 + rw [rewardTransport_mulVec hstep hp, Pi.sub_apply, copyProjection_mulVec_primary hz, + sub_sub_cancel] + exact ⟨mulVec_nonneg (hC l) hPc0 _, Finset.sum_le_sum fun y _ => + mul_le_of_le_one_right (hC l _ y) (hPc1 y)⟩ + +/-- **The stage error, by counting.** If the entries of `C l` are at most `ε` and its nonzero +columns lie in `A`, the stage-`l` reward along primary copies underestimates the solution by at +most `|A| ε`. -/ +theorem sub_rewardTransport_mulVec_le_card_mul {z : ∀ l, V l} + (hz : ∀ l w, P l (z (l + 1)) w = if w = z l then 1 else 0) (l : ℕ) {ε : R} + (hε : ∀ x y, C l x y ≤ ε) {A : Finset (V l)} (hA : ∀ x y, C l x y ≠ 0 → y ∈ A) : + p (z 0) - (rewardTransport P E l *ᵥ e) (z l) ≤ A.card • ε := by + refine (sub_rewardTransport_mulVec_mem_Icc hP hP1 hC hstep hp hp0 hp1 hz l).2.trans ?_ + rw [← Finset.sum_subset (Finset.subset_univ A) fun y _ hy => by_contra fun h => hy (hA _ y h)] + exact Finset.sum_le_card_nsmul _ _ _ fun y _ => hε _ y + +end Order + +/-- **The stage bound.** If the entries of `C l` are at most `(2 ^ (c + 1))⁻¹ ^ l` and its +nonzero columns lie in a set of at most `2 ^ l * n` vertices, then along primary copies +`0 ≤ p (z 0) - W l (z l) ≤ n * (2 ^ c)⁻¹ ^ l`. With `n` the number of vertices of stage `0`, +this is the preprint's bound `|V₀| 2 ^ (-(H - 1) l)` for `H = c + 1` +[OpenAI2026LogSpace, Proposition 4.7]. -/ +theorem sub_rewardTransport_mulVec_le_pow [Field R] [LinearOrder R] [IsStrictOrderedRing R] + (hP : ∀ l i j, 0 ≤ P l i j) (hP1 : ∀ l, P l *ᵥ 1 ≤ 1) (hC : ∀ l i j, 0 ≤ C l i j) + (hstep : ∀ l, C (l + 1) * P l = P l * (C l - E l + E l * C l)) {p e : V 0 → R} + (hp : (1 - C 0) *ᵥ p = e) (hp0 : 0 ≤ p) (hp1 : p ≤ 1) {z : ∀ l, V l} + (hz : ∀ l w, P l (z (l + 1)) w = if w = z l then 1 else 0) {c n : ℕ} + (hε : ∀ l x y, C l x y ≤ ((2 : R) ^ (c + 1))⁻¹ ^ l) (A : ∀ l, Finset (V l)) + (hA : ∀ l x y, C l x y ≠ 0 → y ∈ A l) (hAn : ∀ l, (A l).card ≤ 2 ^ l * n) + (l : ℕ) : + 0 ≤ p (z 0) - (rewardTransport P E l *ᵥ e) (z l) ∧ + p (z 0) - (rewardTransport P E l *ᵥ e) (z l) ≤ n * ((2 : R) ^ c)⁻¹ ^ l := by + refine ⟨(sub_rewardTransport_mulVec_mem_Icc hP hP1 hC hstep hp hp0 hp1 hz l).1, ?_⟩ + refine (sub_rewardTransport_mulVec_le_card_mul hP hP1 hC hstep hp hp0 hp1 hz l (hε l) + (hA l)).trans ?_ + rw [nsmul_eq_mul] + calc ((A l).card : R) * ((2 : R) ^ (c + 1))⁻¹ ^ l + ≤ (2 ^ l * n : ℕ) * ((2 : R) ^ (c + 1))⁻¹ ^ l := + mul_le_mul_of_nonneg_right (by exact_mod_cast hAn l) + (pow_nonneg (inv_nonneg.mpr (pow_nonneg zero_le_two _)) _) + _ = n * ((2 : R) ^ c)⁻¹ ^ l := by + have h2 : (2 : R) ^ l ≠ 0 := pow_ne_zero _ two_ne_zero + push_cast + rw [pow_succ, mul_inv, mul_pow, inv_pow (2 : R), mul_comm ((2 : R) ^ l), mul_assoc, + ← mul_assoc ((2 : R) ^ l), mul_comm ((2 : R) ^ l), mul_assoc _ ((2 : R) ^ l), + mul_inv_cancel₀ h2, mul_one] + +end Hierarchy + +end Matrix diff --git a/ComplexityTests/CorrectionHierarchy.lean b/ComplexityTests/CorrectionHierarchy.lean new file mode 100644 index 000000000..03ad463c2 --- /dev/null +++ b/ComplexityTests/CorrectionHierarchy.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ +import Complexity.Foundations.LinearAlgebra.Matrix.CorrectionHierarchy + +/-! +# Tests for corrections, copies and reward transport +-/ + +namespace ComplexityTests.CorrectionHierarchy + +open Matrix + +/-- A walk on three time layers: from `0` to `1` and from `1` to `2`, each with probability +`1 / 2`; it stops otherwise. -/ +private def C : Matrix (Fin 3) (Fin 3) ℚ := !![0, 1 / 2, 0; 0, 0, 1 / 2; 0, 0, 0] + +/-- The reward is collected at `2`. -/ +private def e : Fin 3 → ℚ := ![0, 0, 1] + +/-- The expected rewards: `1 / 4` from `0`, `1 / 2` from `1`. -/ +private def p : Fin 3 → ℚ := ![1 / 4, 1 / 2, 1] + +private theorem one_sub_C_mulVec_p : (1 - C) *ᵥ p = e := by + ext i; fin_cases i <;> norm_num [C, p, e, mulVec, dotProduct, Fin.sum_univ_three, one_apply] + +/-- The correction removes the second transition. -/ +private def E : Matrix (Fin 3) (Fin 3) ℚ := !![0, 0, 0; 0, 0, 1 / 2; 0, 0, 0] + +private theorem E_strict : E.IsStrictUpperTriangular := by + intro i j h + fin_cases i <;> fin_cases j <;> simp_all [E] + +-- The corrected matrix keeps only the first transition. +example : C - E + E * C = !![0, 1 / 2, 0; 0, 0, 0; 0, 0, 0] := by + ext i j; fin_cases i <;> fin_cases j <;> simp [C, E] + +-- The removed weight `1 / 2` reappears as a reward at `1`, and `p` still solves the corrected +-- equation. +example : (1 - (C - E + E * C)) *ᵥ p = ![0, 1 / 2, 1] := by + rw [one_sub_correction_mulVec, one_sub_C_mulVec_p] + ext i; fin_cases i <;> simp [E, e, mulVec, dotProduct, Fin.sum_univ_three, one_apply] + +private theorem inv_one_sub_C : (1 - C)⁻¹ = 1 + C + C * C := + inv_eq_left_inv <| by + ext i j; fin_cases i <;> fin_cases j <;> + simp [C, mul_apply, Fin.sum_univ_three, one_apply] + +-- The acceptance probabilities of the corrected walk with the corrected reward are those of +-- the original walk: `1 / 4` from `0`. +example : ((1 - (C - E + E * C))⁻¹ *ᵥ (e + E *ᵥ e)) 0 = 1 / 4 := by + rw [E_strict.inv_one_sub_correction_mulVec, inv_one_sub_C] + simp [C, e, mulVec, dotProduct, Fin.sum_univ_three, one_apply] + norm_num + +-- Corrections keep the rows substochastic. +example : (C - E + E * C) *ᵥ 1 ≤ C *ᵥ 1 := + correction_mulVec_one_le (fun i j => by fin_cases i <;> fin_cases j <;> simp [E]) fun i => by + fin_cases i <;> simp [C, mulVec, dotProduct, Fin.sum_univ_three] <;> norm_num + +/-! ### Copies -/ + +/-- Both copies of every vertex are active. -/ +private def r : Fin 2 → Fin 3 → ℚ := fun _ _ => 1 + +/-- Every entry is split evenly between the two copies of its target. -/ +private def s : Fin 3 → Fin 3 → Fin 2 → ℚ := fun _ _ _ => 1 / 2 + +-- Splitting halves the entries and intertwines with the copy projection. +example : copySplit r s C ((0 : Fin 3), (0 : Fin 2)) ((1 : Fin 3), (1 : Fin 2)) = 1 / 4 := by + norm_num [copySplit, r, s, C] + +example : copySplit r s C * copyWeight r = copyWeight r * C := + copySplit_mul_copyWeight fun _ _ _ => by simp [r, s] + +example : copySplit r s C *ᵥ 1 ≤ 1 := + copySplit_mulVec_one_le (fun _ _ => by simp [r]) (fun _ _ => le_rfl) + (fun _ _ => by simp [s]) + (fun i j => by fin_cases i <;> fin_cases j <;> simp [C]) + fun i => by fin_cases i <;> norm_num [C, mulVec, dotProduct, Fin.sum_univ_three] + +/-! ### Reward transport + +A one-step hierarchy: the correction `C + C ^ 2` removes every transition of `C`, since +`C ^ 3 = 0`, so the stage-`1` matrix is zero and the stage-`1` reward is exact. -/ + +private def Cs (l : ℕ) : Matrix (Fin 3) (Fin 3) ℚ := if l = 0 then C else 0 + +private def Es (l : ℕ) : Matrix (Fin 3) (Fin 3) ℚ := if l = 0 then C + C * C else 0 + +private def Ps (_ : ℕ) : Matrix (Fin 3) (Fin 3) ℚ := 1 + +private theorem C_cube : C * C * C = 0 := by + ext i j; fin_cases i <;> fin_cases j <;> simp [C, mul_apply, Fin.sum_univ_three] + +private theorem hstep (l : ℕ) : Cs (l + 1) * Ps l = Ps l * (Cs l - Es l + Es l * Cs l) := by + rcases l with _ | l + · simp only [Cs, Es, Ps, ↓reduceIte, Nat.add_one_ne_zero, Matrix.zero_mul, Matrix.one_mul] + rw [← C_cube]; noncomm_ring + · simp [Cs, Es, Ps] + +private theorem nonneg_C : ∀ i j, 0 ≤ C i j := by + intro i j; fin_cases i <;> fin_cases j <;> simp [C] + +-- From `0`, the stage-`1` reward equals the acceptance probability `1 / 4`: the error bound is +-- the row sum of the zero matrix. +example : (rewardTransport (V := fun _ => Fin 3) Ps Es 1 *ᵥ e) 0 = 1 / 4 := by + have h := sub_rewardTransport_mulVec_mem_Icc (V := fun _ => Fin 3) (C := Cs) (E := Es) + (P := Ps) (z := fun _ => 0) (fun _ i j => by simp [Ps, one_apply]; split_ifs <;> simp) + (fun _ => by simp [Ps]) (fun l i j => by unfold Cs; split_ifs <;> simp [nonneg_C]) + hstep (p := p) (e := e) (by simpa [Cs] using one_sub_C_mulVec_p) + (fun i => by fin_cases i <;> norm_num [p]) + (fun i => by fin_cases i <;> norm_num [p]) + (fun _ w => by simp [Ps, one_apply, eq_comm]) 1 + have hp0 : p 0 = 1 / 4 := rfl + simp only [Cs, Nat.add_one_ne_zero, ↓reduceIte, Matrix.zero_apply, Finset.sum_const_zero, + Set.mem_Icc] at h + linarith [h.1, h.2] + +end ComplexityTests.CorrectionHierarchy diff --git a/references.bib b/references.bib index ffd09ecfe..39e270d93 100644 --- a/references.bib +++ b/references.bib @@ -3451,6 +3451,15 @@ @misc{OpenAI2026ETH url = {https://github.com/openai/math/blob/7ef5c0cc5ca4b0e072b7a050fca09ab24bc6fa3a/preprints/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf} } +@misc{OpenAI2026LogSpace, + author = {{OpenAI}}, + title = {Exact Derandomization of Logarithmic Space: {L} = {RL} = {BPL}}, + year = {2026}, + howpublished = {Preprint}, + note = {Dated 23 September 2026, not peer reviewed; source revision 7ef5c0cc5ca4b0e072b7a050fca09ab24bc6fa3a}, + url = {https://github.com/openai/math/blob/7ef5c0cc5ca4b0e072b7a050fca09ab24bc6fa3a/preprints/Exact-Derandomization-of-Logarithmic-Space-L-equals-RL-equals-BPL-September-23-2026/paper.pdf} +} + @misc{OpenAI2026RationalHitting, author = {{OpenAI}}, title = {{Rational} matrix hitting lists for noncommutative rational formulas}, From 832f9390cd08ee432c7d3a14ae70d623b647fd80 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Thu, 29 Oct 2026 23:05:28 +0000 Subject: [PATCH 02/18] fix(Foundations): expose IsStrictUpperTriangular so importers can apply it Co-Authored-By: Claude Opus 5.5 --- .../Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean index 606c43617..4ded7fdbb 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean @@ -97,7 +97,7 @@ variable {V R : Type*} /-- A square matrix is *strictly upper triangular* when its entry at `(i, j)` vanishes unless `i < j`. For the time-layered transition matrices of a machine, ordered by time, this says that every transition moves strictly forward. -/ -def IsStrictUpperTriangular [LT V] [Zero R] (M : Matrix V V R) : Prop := +@[expose] def IsStrictUpperTriangular [LT V] [Zero R] (M : Matrix V V R) : Prop := ∀ ⦃i j⦄, ¬ i < j → M i j = 0 namespace IsStrictUpperTriangular From 1fbc2671b8dbcee6119dbd9f79b4a36b2bf4b52a Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Thu, 29 Oct 2026 23:15:03 +0000 Subject: [PATCH 03/18] fix(Foundations): separate row-sum control from nonnegativity; add reward lower bound Review of #1676: correction_mulVec_one_le only shows that row sums do not grow, so its docstring, the module summary and the test comment no longer call it substochasticity. Add rewardTransport_mulVec_nonneg, the lower half of (4.30), under nonnegative projections, corrections and reward. Co-Authored-By: Claude Opus 5.5 --- .../Matrix/CorrectionHierarchy.lean | 24 ++++++++++++++----- ComplexityTests/CorrectionHierarchy.lean | 12 +++++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean index 4ded7fdbb..2420fb961 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean @@ -65,9 +65,11 @@ the copies (factorial truncation, detectors) are not part of this file. of `C` is the expected corrected reward of `C - E + E C`. * `Matrix.IsStrictUpperTriangular.det_one_add`: `det (1 + E) = 1` for strictly upper triangular `E`. -* `Matrix.correction_mulVec_one_le`: corrections keep matrices substochastic. +* `Matrix.correction_mulVec_one_le`: nonnegative corrections do not increase row sums. * `Matrix.copySplit_mul_copyWeight`: a copy step intertwines with its projection. * `Matrix.mul_copyProjection`, `Matrix.rewardTransport_mulVec`: the reward transport identity. +* `Matrix.rewardTransport_mulVec_nonneg`, `Matrix.rewardTransport_mulVec_le`: the stage rewards + lie between `0` and the projected solution. * `Matrix.sub_rewardTransport_mulVec_mem_Icc`, `Matrix.sub_rewardTransport_mulVec_le_card_mul`, `Matrix.sub_rewardTransport_mulVec_le_pow`: the transported reward is a lower bound with error controlled by the last transition matrix. @@ -187,8 +189,10 @@ theorem mulVec_le_one {m n : Type*} [Fintype n] [Semiring R] [PartialOrder R] [I M *ᵥ v ≤ 1 := fun i => le_trans (Finset.sum_le_sum fun j _ => mul_le_mul_of_nonneg_left (hv j) (hM i j)) (hM1 i) -/-- **Corrections keep rows substochastic.** If `E ≥ 0` and the rows of `C` sum to at most one, -then each row of `C - E + E C` sums to at most the corresponding row of `C`. -/ +/-- **Corrections do not increase row sums.** If `E ≥ 0` and the rows of `C` sum to at most one, +then each row of `C - E + E C` sums to at most the corresponding row of `C`. This says nothing +about the signs of the entries of `C - E + E C`; their nonnegativity depends on how `E` is +chosen [OpenAI2026LogSpace, Lemma 4.4]. -/ theorem correction_mulVec_one_le [Ring R] [PartialOrder R] [IsOrderedRing R] {C E : Matrix V V R} (hE : ∀ i j, 0 ≤ E i j) (hC : C *ᵥ 1 ≤ 1) : (C - E + E * C) *ᵥ 1 ≤ C *ᵥ 1 := by @@ -254,8 +258,9 @@ theorem copySplit_nonneg [Semiring R] [PartialOrder R] [IsOrderedRing R] {r : ι 0 ≤ copySplit r s D a b := mul_nonneg (mul_nonneg (hr _ _) (hD _ _)) (hs _ _ _) -/-- **Copies keep rows substochastic** when the weights are at most one and the proportions of -each entry sum to at most one. -/ +/-- **Copies keep row sums at most one** when the weights lie in `[0, 1]`, `D` is nonnegative +with row sums at most one, and the proportions of each entry sum to at most one. Together with +`Matrix.copySplit_nonneg` this makes the copy step substochastic. -/ theorem copySplit_mulVec_one_le [Fintype V] [Fintype ι] [Semiring R] [PartialOrder R] [IsOrderedRing R] {r : ι → V → R} {s : V → V → ι → R} {D : Matrix V V R} (hr0 : ∀ i x, 0 ≤ r i x) (hr1 : ∀ i x, r i x ≤ 1) (hs1 : ∀ x y, ∑ j, s x y j ≤ 1) @@ -383,13 +388,20 @@ theorem rewardTransport_nonneg (hP : ∀ l i j, 0 ≤ P l i j) (hE : ∀ l i j, exact mul_nonneg_entries (mul_nonneg_entries (hP l) (fun i j => add_nonneg (one_apply_nonneg i j) (hE l i j))) ih +/-- The stage rewards are nonnegative when the projections, the corrections and the initial reward +are [OpenAI2026LogSpace, Proposition 4.7]. -/ +theorem rewardTransport_mulVec_nonneg (hP : ∀ l i j, 0 ≤ P l i j) (hE : ∀ l i j, 0 ≤ E l i j) + {e : V 0 → R} (he : 0 ≤ e) (l : ℕ) : 0 ≤ rewardTransport P E l *ᵥ e := + mulVec_nonneg (rewardTransport_nonneg hP hE l) he + variable (hP : ∀ l i j, 0 ≤ P l i j) (hP1 : ∀ l, P l *ᵥ 1 ≤ 1) (hC : ∀ l i j, 0 ≤ C l i j) (hstep : ∀ l, C (l + 1) * P l = P l * (C l - E l + E l * C l)) {p e : V 0 → R} (hp : (1 - C 0) *ᵥ p = e) (hp0 : 0 ≤ p) (hp1 : p ≤ 1) include hP hP1 hC hstep hp hp0 hp1 -/-- The stage rewards are bounded by the projected solution, hence by one. -/ +/-- The stage rewards are bounded by the projected solution, hence by one. For the lower bound +see `Matrix.rewardTransport_mulVec_nonneg`. -/ theorem rewardTransport_mulVec_le (l : ℕ) : rewardTransport P E l *ᵥ e ≤ copyProjection P l *ᵥ p ∧ copyProjection P l *ᵥ p ≤ 1 := by diff --git a/ComplexityTests/CorrectionHierarchy.lean b/ComplexityTests/CorrectionHierarchy.lean index 03ad463c2..c6bb668e6 100644 --- a/ComplexityTests/CorrectionHierarchy.lean +++ b/ComplexityTests/CorrectionHierarchy.lean @@ -55,7 +55,7 @@ example : ((1 - (C - E + E * C))⁻¹ *ᵥ (e + E *ᵥ e)) 0 = 1 / 4 := by simp [C, e, mulVec, dotProduct, Fin.sum_univ_three, one_apply] norm_num --- Corrections keep the rows substochastic. +-- A nonnegative correction does not increase the row sums. example : (C - E + E * C) *ᵥ 1 ≤ C *ᵥ 1 := correction_mulVec_one_le (fun i j => by fin_cases i <;> fin_cases j <;> simp [E]) fun i => by fin_cases i <;> simp [C, mulVec, dotProduct, Fin.sum_univ_three] <;> norm_num @@ -119,4 +119,14 @@ example : (rewardTransport (V := fun _ => Fin 3) Ps Es 1 *ᵥ e) 0 = 1 / 4 := by Set.mem_Icc] at h linarith [h.1, h.2] +-- The transported rewards are nonnegative. +example : 0 ≤ rewardTransport (V := fun _ => Fin 3) Ps Es 1 *ᵥ e := + rewardTransport_mulVec_nonneg (V := fun _ => Fin 3) + (fun _ i j => by simp only [Ps, one_apply]; split_ifs <;> simp) + (fun l i j => by + unfold Es; split_ifs + · fin_cases i <;> fin_cases j <;> norm_num [C, mul_apply, Fin.sum_univ_three] + · simp) + (fun i => by fin_cases i <;> simp [e]) 1 + end ComplexityTests.CorrectionHierarchy From b5cc0590faa36fabf897783af15a6384793707f6 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Thu, 29 Oct 2026 23:05:40 +0000 Subject: [PATCH 04/18] feat(Foundations): factorial truncation of cutoff corrections Second slice of #1444 Phase 2 (idea 3 of #474), following the OpenAI preprint (2026-09-23), Lemma 4.1 and Lemma 4.4: the cutoff correction recursion E = phi((C + EC)) on a strictly upper triangular C has a unique fixed point, its iterates increase towards it, and after k iterations the error is at most f e^(1/theta) (L/theta)^k / k!, independently of the size of the matrix. The corrected matrix of a finite iterate is nonnegative and small in fully corrected columns. Co-Authored-By: Claude Opus 5.5 --- Complexity.lean | 1 + .../Matrix/FactorialTruncation.lean | 483 ++++++++++++++++++ ComplexityTests/FactorialTruncation.lean | 93 ++++ 3 files changed, 577 insertions(+) create mode 100644 Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean create mode 100644 ComplexityTests/FactorialTruncation.lean diff --git a/Complexity.lean b/Complexity.lean index c0e4b8629..b1c2b3181 100644 --- a/Complexity.lean +++ b/Complexity.lean @@ -2622,6 +2622,7 @@ public import Complexity.Foundations.LinearAlgebra.Interpolation public import Complexity.Foundations.LinearAlgebra.KernelVector public import Complexity.Foundations.LinearAlgebra.Matrix.CorrectionHierarchy public import Complexity.Foundations.LinearAlgebra.Matrix.CutRank +public import Complexity.Foundations.LinearAlgebra.Matrix.FactorialTruncation public import Complexity.Foundations.LinearAlgebra.Matrix.Kronecker public import Complexity.Foundations.LinearAlgebra.Matrix.Lindsey public import Complexity.Foundations.LinearAlgebra.Matrix.ListProd diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean new file mode 100644 index 000000000..ad9fe5b9c --- /dev/null +++ b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean @@ -0,0 +1,483 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Foundations.LinearAlgebra.Matrix.CorrectionHierarchy +public import Mathlib.Analysis.SpecialFunctions.Exp +import Mathlib.Algebra.Ring.GeomSum +import Mathlib.Data.Nat.Choose.Bounds +import Mathlib.Topology.Algebra.Order.Floor + +/-! +# Factorial truncation of cutoff corrections + +Let `C` be a strictly upper triangular transition matrix with nonnegative entries at most `f` +and rows summing to at most one. A *cutoff correction* chooses the correction `E` of +`Matrix.one_sub_correction_mulVec` entrywise from the corrected input, +`E x y = φ y ((C + E C) x y)`, where each cutoff `φ y` is monotone, `L`-Lipschitz and leaves at +least `θ f` behind: `0 ≤ φ y t ≤ max (t - θ f) 0`. In the OpenAI preprint (2026-09-23), idea 3 in +issue #474, `φ y t = f Q (t / f) g y` for a smooth ramp `Q` and a column multiplier `g` +[OpenAI2026LogSpace, Section 4.1]. + +The equation is a recursion along the order of the columns, so it has exactly one solution +`Matrix.cutoffCorrectionFix φ C`, reached by iterating `Matrix.cutoffCorrection φ C` from zero +`card V` times (`Matrix.cutoffCorrection_fix`, `Matrix.eq_cutoffCorrectionFix`). The point of +the estimate is that far fewer iterations suffice, independently of the size of `V`: after `k` +iterations every entry is within `f e^(1 / θ) (L / θ)^k / k!` of the fixed point +(`Matrix.cutoffCorrectionFix_sub_iter_le`). + +The proof counts chains. In a fixed row, every positive entry of the fixed point leaves a residual +at least `θ f`, and the residuals of a row sum to at most one, so the row has at most `1 / (θ f)` +positive entries. Unrolling the recursion `k` times along that row expresses the error as a sum +over increasing chains of `k` of these entries, each weighted by at most `(L f)^k`; there are at +most `binomial (1 / (θ f), k) ≤ (θ f)^(-k) / k!` of them. + +For the finite correction `E = E k`, the corrected matrix `C - E + E C` is nonnegative +(`Matrix.cutoffCorrection_residual_nonneg`), and in a column whose cutoff leaves at most `θ₂ f` +behind its entries are at most `θ₂ f` plus the truncation error +(`Matrix.cutoffCorrection_residual_le`). Since `x ^ k / k!` tends to zero, a number of iterations +depending only on `θ`, `L` and the target accuracy suffices (`Matrix.exists_factorial_bound_le`). + +## Main definitions + +* `Matrix.cutoffCorrection`: one step `F ↦ φ y ((C + F C) x y)` of the recursion. +* `Matrix.cutoffCorrectionIter`: its `k`-th iterate from zero. +* `Matrix.cutoffCorrectionFix`: its unique fixed point. + +## Main results + +* `Matrix.cutoffCorrection_fix`, `Matrix.eq_cutoffCorrectionFix`: existence and uniqueness of the + fixed point, for strictly upper triangular `C`. +* `Matrix.cutoffCorrectionIter_le_fix`: the iterates increase towards the fixed point. +* `Matrix.cutoffCorrectionFix_sub_iter_le`: **factorial truncation**, the bound + `E* - E k ≤ f e^(1 / θ) (L / θ)^k / k!`. +* `Matrix.cutoffCorrection_residual_nonneg`, `Matrix.cutoffCorrection_residual_le`: the corrected + matrix of a finite iterate is nonnegative, with small entries in fully corrected columns. +* `Matrix.exists_factorial_bound_le`: a uniform number of iterations reaches any accuracy. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Lemma 4.1 and Lemma 4.4 (preprint, not peer reviewed). The estimate is of Picard type: compare + the factorial bound for Picard iterates of Lipschitz ODEs. +-/ + +public section + +open Finset + +namespace Matrix + +variable {V R : Type*} [Fintype V] + +section Recursion + +variable [NonUnitalNonAssocSemiring R] + +/-- **One step of the cutoff correction recursion**: the matrix with entry +`φ y ((C + F C) x y)` at `(x, y)`. -/ +@[expose] def cutoffCorrection (φ : V → R → R) (C F : Matrix V V R) : Matrix V V R := + of fun x y => φ y ((C + F * C) x y) + +/-- The `k`-th iterate of `Matrix.cutoffCorrection φ C` from the zero matrix. -/ +@[expose] def cutoffCorrectionIter (φ : V → R → R) (C : Matrix V V R) (k : ℕ) : Matrix V V R := + (cutoffCorrection φ C)^[k] 0 + +/-- The *cutoff correction* of `C`: the iterate after `card V` steps, which is the unique fixed +point of `Matrix.cutoffCorrection φ C` when `C` is strictly upper triangular. -/ +@[expose] def cutoffCorrectionFix (φ : V → R → R) (C : Matrix V V R) : Matrix V V R := + cutoffCorrectionIter φ C (Fintype.card V) + +variable {φ : V → R → R} {C : Matrix V V R} + +theorem cutoffCorrectionIter_succ (k : ℕ) : + cutoffCorrectionIter φ C (k + 1) = cutoffCorrection φ C (cutoffCorrectionIter φ C k) := + Function.iterate_succ_apply' _ _ _ + +variable [LinearOrder V] + +/-- The entry `(x, y)` of a correction step depends only on the entries `(x, z)` with `z < y`. -/ +private theorem cutoffCorrection_congr (hC : C.IsStrictUpperTriangular) {F G : Matrix V V R} + {x y : V} (h : ∀ z < y, F x z = G x z) : + cutoffCorrection φ C F x y = cutoffCorrection φ C G x y := by + simp only [cutoffCorrection, of_apply, add_apply, mul_apply] + congr 2 + refine Finset.sum_congr rfl fun z _ => ?_ + by_cases hz : z < y + · rw [h z hz] + · rw [hC hz, mul_zero, mul_zero] + +private theorem card_filter_lt_lt {y z : V} (hzy : z < y) : + #{w | w < z} < #{w | w < y} := + Finset.card_lt_card <| Finset.ssubset_iff_of_subset + (fun w hw => by simp only [mem_filter, mem_univ, true_and] at hw ⊢; exact hw.trans hzy) + |>.mpr ⟨z, by simpa using hzy, by simp⟩ + +/-- The iterates are stationary at `(x, y)` from the `(#{z | z < y} + 1)`-th on. -/ +private theorem cutoffCorrectionIter_succ_apply (hC : C.IsStrictUpperTriangular) (k : ℕ) : + ∀ x y : V, #{z | z < y} < k → + cutoffCorrectionIter φ C (k + 1) x y = cutoffCorrectionIter φ C k x y := by + induction k with + | zero => intro x y h; exact absurd h (Nat.not_lt_zero _) + | succ k ih => + intro x y h + rw [cutoffCorrectionIter_succ (k := k + 1)] + conv_rhs => rw [cutoffCorrectionIter_succ] + exact cutoffCorrection_congr hC fun z hz => + ih x z ((card_filter_lt_lt hz).trans_le (Nat.lt_succ_iff.mp h)) + +/-- **Existence of the cutoff correction**: `Matrix.cutoffCorrectionFix φ C` is a fixed point of +the recursion when `C` is strictly upper triangular [OpenAI2026LogSpace, Lemma 4.1]. -/ +theorem cutoffCorrection_fix (hC : C.IsStrictUpperTriangular) : + cutoffCorrection φ C (cutoffCorrectionFix φ C) = cutoffCorrectionFix φ C := by + ext x y + rw [cutoffCorrectionFix, ← cutoffCorrectionIter_succ] + refine cutoffCorrectionIter_succ_apply hC _ x y (Finset.card_lt_card ?_) + exact Finset.ssubset_iff_of_subset (Finset.subset_univ _) |>.mpr ⟨y, mem_univ _, by simp⟩ + +/-- **Uniqueness of the cutoff correction**: every fixed point of the recursion is +`Matrix.cutoffCorrectionFix φ C` when `C` is strictly upper triangular +[OpenAI2026LogSpace, Lemma 4.1]. -/ +theorem eq_cutoffCorrectionFix (hC : C.IsStrictUpperTriangular) {F : Matrix V V R} + (hF : cutoffCorrection φ C F = F) : F = cutoffCorrectionFix φ C := by + ext x y + induction y using WellFoundedLT.induction with + | ind y ih => + rw [← hF, ← cutoffCorrection_fix hC] + exact cutoffCorrection_congr hC ih + +end Recursion + +section Bounds + +variable [LinearOrder V] {φ : V → ℝ → ℝ} {C : Matrix V V ℝ} {f θ L : ℝ} + +omit [Fintype V] in +/-- Counting increasing chains by rank: summing a nonnegative `g` of the rank within `S` over the +members of `S` below `y` is at most summing `g` over the ranks below the rank of `y`. -/ +private theorem sum_rank_le (S : Finset V) (y : V) {g : ℕ → ℝ} (hg : ∀ j, 0 ≤ g j) : + ∑ z ∈ S.filter (· < y), g #(S.filter (· < z)) ≤ + ∑ j ∈ range #(S.filter (· < y)), g j := by + have hlt : ∀ {a b : V}, a ∈ S → a < b → #(S.filter (· < a)) < #(S.filter (· < b)) := + fun {a b} ha hab => Finset.card_lt_card <| Finset.ssubset_iff_of_subset + (fun w hw => by simp only [mem_filter] at hw ⊢; exact ⟨hw.1, hw.2.trans hab⟩) + |>.mpr ⟨a, by simp [ha, hab], by simp⟩ + have hinj : Set.InjOn (fun z => #(S.filter (· < z))) (S.filter (· < y) : Set V) := by + intro a ha b hb hab + simp only [coe_filter, Set.mem_ofPred_eq] at ha hb + by_contra hne + rcases lt_or_gt_of_ne hne with h | h + · exact (hlt ha.1 h).ne hab + · exact (hlt hb.1 h).ne hab.symm + rw [← Finset.sum_image (f := g) hinj] + refine Finset.sum_le_sum_of_subset_of_nonneg (fun j hj => ?_) fun j _ _ => hg j + obtain ⟨z, hz, rfl⟩ := Finset.mem_image.mp hj + simp only [mem_filter] at hz + exact Finset.mem_range.mpr (hlt hz.1 hz.2) + +/-- The hockey-stick identity `∑ j < n, (j choose k) = n choose (k + 1)`. -/ +private theorem sum_range_choose_eq (n k : ℕ) : + ∑ j ∈ range n, (j.choose k : ℝ) = (n.choose (k + 1) : ℝ) := by + induction n with + | zero => simp + | succ n ih => rw [sum_range_succ, ih, Nat.choose_succ_succ', Nat.cast_add, add_comm] + +variable (hC : C.IsStrictUpperTriangular) (hC0 : ∀ x y, 0 ≤ C x y) (hCf : ∀ x y, C x y ≤ f) + (hC1 : C *ᵥ 1 ≤ 1) (hφ0 : ∀ y t, 0 ≤ φ y t) (hφθ : ∀ y t, φ y t ≤ max (t - θ * f) 0) + (hφm : ∀ y, Monotone (φ y)) (hφL : ∀ y s t, s ≤ t → φ y t - φ y s ≤ L * (t - s)) + +section Monotone + +omit [LinearOrder V] in +include hC0 hφm in +private theorem cutoffCorrection_mono {F G : Matrix V V ℝ} (hFG : ∀ x y, F x y ≤ G x y) + (x y : V) : cutoffCorrection φ C F x y ≤ cutoffCorrection φ C G x y := by + refine hφm y ?_ + simp only [add_apply, mul_apply] + exact add_le_add_right (Finset.sum_le_sum fun z _ => + mul_le_mul_of_nonneg_right (hFG x z) (hC0 z y)) _ + +omit [LinearOrder V] in +include hφ0 in +theorem cutoffCorrectionIter_nonneg (k : ℕ) (x y : V) : 0 ≤ cutoffCorrectionIter φ C k x y := by + cases k with + | zero => simp [cutoffCorrectionIter] + | succ k => rw [cutoffCorrectionIter_succ]; exact hφ0 _ _ + +omit [LinearOrder V] in +include hC0 hφ0 hφm in +/-- The iterates increase. -/ +theorem cutoffCorrectionIter_le_succ (k : ℕ) (x y : V) : + cutoffCorrectionIter φ C k x y ≤ cutoffCorrectionIter φ C (k + 1) x y := by + induction k generalizing x y with + | zero => exact cutoffCorrectionIter_nonneg hφ0 1 x y + | succ k ih => + rw [cutoffCorrectionIter_succ, cutoffCorrectionIter_succ (k := k + 1)] + exact cutoffCorrection_mono hC0 hφm ih x y + +include hC hC0 hφ0 hφm in +/-- **The iterates increase towards the fixed point** [OpenAI2026LogSpace, Lemma 4.1]. -/ +theorem cutoffCorrectionIter_le_fix (k : ℕ) (x y : V) : + cutoffCorrectionIter φ C k x y ≤ cutoffCorrectionFix φ C x y := by + induction k generalizing x y with + | zero => exact cutoffCorrectionIter_nonneg hφ0 _ x y + | succ k ih => + rw [cutoffCorrectionIter_succ, ← cutoffCorrection_fix hC] + exact cutoffCorrection_mono hC0 hφm ih x y + +end Monotone + +omit [LinearOrder V] in +/-- The input `(C + F C) x y` of a correction step is nonnegative. -/ +private theorem correctionInput_nonneg (hC0 : ∀ x y, 0 ≤ C x y) {F : Matrix V V ℝ} + (hF : ∀ x y, 0 ≤ F x y) (x y : V) : 0 ≤ (C + F * C) x y := + add_nonneg (hC0 x y) (Finset.sum_nonneg fun z _ => mul_nonneg (hF x z) (hC0 z y)) + +omit [Fintype V] [LinearOrder V] in +include hφθ in +/-- A cutoff never exceeds its nonnegative input. -/ +private theorem cutoff_le_self (hθf : 0 ≤ θ * f) (y : V) {t : ℝ} (ht : 0 ≤ t) : φ y t ≤ t := + (hφθ y t).trans (max_le (by linarith) ht) + +omit [Fintype V] [LinearOrder V] in +include hφθ in +/-- A positive cutoff leaves at least `θ f` behind. -/ +private theorem le_sub_cutoff_of_pos (y : V) {t : ℝ} (h : 0 < φ y t) : θ * f ≤ t - φ y t := by + have h1 := hφθ y t + have h2 : 0 < t - θ * f := by + by_contra hneg + rw [max_eq_right (by linarith)] at h1 + linarith + rw [max_eq_left h2.le] at h1 + linarith + +include hC in +private theorem fix_apply (x y : V) : + cutoffCorrectionFix φ C x y = φ y ((C + cutoffCorrectionFix φ C * C) x y) := by + conv_lhs => rw [← cutoffCorrection_fix hC] + rfl + +section Row + +variable (x : V) + +/-- The positive entries of row `x` of the fixed point. -/ +private noncomputable abbrev support : Finset V := {z | cutoffCorrectionFix φ C x z ≠ 0} + +include hC hC0 hC1 hφ0 hφθ in +/-- In each row, the fixed point has at most `1 / (θ f)` positive entries: each leaves a +residual at least `θ f`, and the residuals of a row sum to at most one. -/ +private theorem card_support_mul_le (hθf : 0 ≤ θ * f) : + (#(support (φ := φ) (C := C) x) : ℝ) * (θ * f) ≤ 1 := by + set E := cutoffCorrectionFix φ C + have hE0 : ∀ i j, 0 ≤ E i j := cutoffCorrectionIter_nonneg hφ0 _ + have hEfix : ∀ y, E x y = φ y ((C + E * C) x y) := fix_apply hC x + have hres : ∀ y, (C - E + E * C) x y = (C + E * C) x y - E x y := fun y => by + simp only [add_apply, sub_apply]; ring + have hres0 : ∀ y, 0 ≤ (C - E + E * C) x y := fun y => by + rw [hres, hEfix y, sub_nonneg] + exact cutoff_le_self hφθ hθf y (correctionInput_nonneg hC0 hE0 x y) + have hrow : ∑ y, (C - E + E * C) x y ≤ 1 := by + simpa [mulVec, dotProduct] using (correction_mulVec_one_le hE0 hC1 x).trans (hC1 x) + calc (#(support (φ := φ) (C := C) x) : ℝ) * (θ * f) + = ∑ y ∈ support (φ := φ) (C := C) x, θ * f := by rw [sum_const, nsmul_eq_mul] + _ ≤ ∑ y ∈ support (φ := φ) (C := C) x, (C - E + E * C) x y := by + refine Finset.sum_le_sum fun y hy => ?_ + have hpos : 0 < φ y ((C + E * C) x y) := by + rw [← hEfix y] + exact lt_of_le_of_ne (hE0 x y) (Ne.symm (by simpa using hy)) + rw [hres, hEfix y] + exact le_sub_cutoff_of_pos hφθ y hpos + _ ≤ ∑ y, (C - E + E * C) x y := + Finset.sum_le_sum_of_subset_of_nonneg (subset_univ _) fun y _ _ => hres0 y + _ ≤ 1 := hrow + +/-- A sum `∑ z, F x z * C z y` only sees the members of `support x` below `y`, when `F` vanishes +outside the support. -/ +private theorem sum_mul_eq_sum_support (hC : C.IsStrictUpperTriangular) {F : Matrix V V ℝ} + (hF : ∀ z, cutoffCorrectionFix φ C x z = 0 → F x z = 0) (y : V) : + ∑ z, F x z * C z y = ∑ z ∈ (support (φ := φ) (C := C) x).filter (· < y), F x z * C z y := by + refine (Finset.sum_subset (subset_univ _) fun z _ hz => ?_).symm + simp only [mem_filter, mem_univ, true_and, not_and_or, not_not] at hz + rcases hz with hz | hz + · rw [hF z hz, zero_mul] + · rw [hC hz, mul_zero] + +include hC hC0 hCf hφ0 hφθ in +/-- The entries of the fixed point grow at most geometrically along the support of a row. -/ +private theorem fix_le_pow (hf : 0 ≤ f) (hθf : 0 ≤ θ * f) (y : V) : + cutoffCorrectionFix φ C x y ≤ + f * (1 + f) ^ #((support (φ := φ) (C := C) x).filter (· < y)) := by + set E := cutoffCorrectionFix φ C + have hE0 : ∀ i j, 0 ≤ E i j := cutoffCorrectionIter_nonneg hφ0 _ + induction y using WellFoundedLT.induction with + | ind y ih => + set S := support (φ := φ) (C := C) x + have hEfix : E x y = φ y ((C + E * C) x y) := fix_apply hC x y + have hsum : ∑ z, E x z * C z y = ∑ z ∈ S.filter (· < y), E x z * C z y := + sum_mul_eq_sum_support x hC (fun _ h => h) y + calc E x y ≤ (C + E * C) x y := by + rw [hEfix]; exact cutoff_le_self hφθ hθf y (correctionInput_nonneg hC0 hE0 x y) + _ = C x y + ∑ z ∈ S.filter (· < y), E x z * C z y := by + rw [add_apply, mul_apply, hsum] + _ ≤ f + ∑ z ∈ S.filter (· < y), f * (1 + f) ^ #(S.filter (· < z)) * f := by + refine add_le_add (hCf x y) (Finset.sum_le_sum fun z hz => ?_) + exact mul_le_mul (ih z (mem_filter.mp hz).2) (hCf z y) (hC0 z y) (by positivity) + _ = f + f * f * ∑ z ∈ S.filter (· < y), (1 + f) ^ #(S.filter (· < z)) := by + rw [Finset.mul_sum]; congr 1; exact Finset.sum_congr rfl fun z _ => by ring + _ ≤ f + f * f * ∑ j ∈ range #(S.filter (· < y)), (1 + f) ^ j := by + gcongr + exact sum_rank_le S y fun j => by positivity + _ = f * (1 + f) ^ #(S.filter (· < y)) := by + have := geom_sum_mul_add f #(S.filter (· < y)) + rw [add_comm f 1] at this + linear_combination f * this + +include hC hC0 hCf hφ0 hφθ hφm hφL in +/-- The iteration error along a row is bounded by counting increasing chains in its support. -/ +private theorem fix_sub_iter_le_choose (hf : 0 ≤ f) (hθf : 0 ≤ θ * f) (hL : 0 ≤ L) (k : ℕ) + (y : V) : cutoffCorrectionFix φ C x y - cutoffCorrectionIter φ C k x y ≤ + f * (1 + f) ^ #(support (φ := φ) (C := C) x) * (L * f) ^ k * + (#((support (φ := φ) (C := C) x).filter (· < y))).choose k := by + set E := cutoffCorrectionFix φ C + set S := support (φ := φ) (C := C) x + have hE0 : ∀ i j, 0 ≤ E i j := cutoffCorrectionIter_nonneg hφ0 _ + have hM : ∀ y, E x y ≤ f * (1 + f) ^ #S := fun y => + (fix_le_pow hC hC0 hCf hφ0 hφθ x hf hθf y).trans <| mul_le_mul_of_nonneg_left + (pow_le_pow_right₀ (by linarith) (card_le_card (filter_subset _ _))) hf + induction k generalizing y with + | zero => + simpa using (sub_le_self _ (cutoffCorrectionIter_nonneg hφ0 0 x y)).trans (hM y) + | succ k ih => + set F := cutoffCorrectionIter φ C k + have hFE : ∀ z, F x z ≤ E x z := cutoffCorrectionIter_le_fix hC hC0 hφ0 hφm k x + have hEfix : E x y = φ y ((C + E * C) x y) := fix_apply hC x y + have hsum : ∑ z, (E - F) x z * C z y = ∑ z ∈ S.filter (· < y), (E - F) x z * C z y := + sum_mul_eq_sum_support x hC (fun z hz => by + change E x z = 0 at hz + rw [sub_apply, hz, sub_eq_zero] + exact le_antisymm (cutoffCorrectionIter_nonneg (C := C) hφ0 k x z) (hz ▸ hFE z)) y + have hdiff : (C + E * C) x y - (C + F * C) x y = ∑ z, (E - F) x z * C z y := by + simp only [add_apply, mul_apply, sub_apply, sub_mul, Finset.sum_sub_distrib]; ring + have hle : (C + F * C) x y ≤ (C + E * C) x y := by + rw [← sub_nonneg, hdiff] + exact Finset.sum_nonneg fun z _ => mul_nonneg (by rw [sub_apply, sub_nonneg]; exact hFE z) + (hC0 z y) + calc E x y - cutoffCorrectionIter φ C (k + 1) x y + = φ y ((C + E * C) x y) - φ y ((C + F * C) x y) := by + rw [hEfix, cutoffCorrectionIter_succ]; rfl + _ ≤ L * ∑ z ∈ S.filter (· < y), (E - F) x z * C z y := by + rw [← hsum, ← hdiff] + exact hφL y _ _ hle + _ ≤ L * ∑ z ∈ S.filter (· < y), + f * (1 + f) ^ #S * (L * f) ^ k * (#(S.filter (· < z))).choose k * f := by + refine mul_le_mul_of_nonneg_left (Finset.sum_le_sum fun z _ => ?_) hL + rw [sub_apply] + exact mul_le_mul (ih z) (hCf z y) (hC0 z y) (by positivity) + _ = f * (1 + f) ^ #S * (L * f) ^ (k + 1) * + ∑ z ∈ S.filter (· < y), ((#(S.filter (· < z))).choose k : ℝ) := by + rw [Finset.mul_sum, Finset.mul_sum] + exact Finset.sum_congr rfl fun z _ => by ring + _ ≤ f * (1 + f) ^ #S * (L * f) ^ (k + 1) * + ∑ j ∈ range #(S.filter (· < y)), (j.choose k : ℝ) := by + gcongr + exact sum_rank_le S y (g := fun j => (j.choose k : ℝ)) fun j => by positivity + _ = f * (1 + f) ^ #S * (L * f) ^ (k + 1) * (#(S.filter (· < y))).choose (k + 1) := by + rw [sum_range_choose_eq] + +end Row + +include hC hC0 hCf hC1 hφ0 hφθ hφm hφL in +/-- **Factorial truncation.** After `k` iterations of the cutoff correction recursion, every entry +is within `f e^(1 / θ) (L / θ)^k / k!` of the fixed point, uniformly in the size of `V` +[OpenAI2026LogSpace, Lemma 4.1]. -/ +theorem cutoffCorrectionFix_sub_iter_le (hf : 0 < f) (hθ : 0 < θ) (hL : 0 ≤ L) (k : ℕ) + (x y : V) : cutoffCorrectionFix φ C x y - cutoffCorrectionIter φ C k x y ≤ + f * Real.exp (1 / θ) * (L / θ) ^ k / k.factorial := by + have hθf : 0 ≤ θ * f := by positivity + set S := support (φ := φ) (C := C) x + set m := #S + have hm : (m : ℝ) * f ≤ 1 / θ := by + rw [le_div_iff₀ hθ] + nlinarith [card_support_mul_le hC hC0 hC1 hφ0 hφθ x hθf] + have hr : #(S.filter (· < y)) ≤ m := card_le_card (filter_subset _ _) + refine (fix_sub_iter_le_choose hC hC0 hCf hφ0 hφθ hφm hφL x hf.le hθf hL k y).trans ?_ + have hexp : (1 + f) ^ m ≤ Real.exp (1 / θ) := by + calc (1 + f) ^ m ≤ Real.exp f ^ m := by + gcongr; linarith [Real.add_one_le_exp f] + _ = Real.exp (m * f) := by rw [← Real.exp_nat_mul] + _ ≤ Real.exp (1 / θ) := Real.exp_le_exp.mpr hm + have hchoose : ((#(S.filter (· < y))).choose k : ℝ) ≤ (m : ℝ) ^ k / k.factorial := + (Nat.choose_le_pow_div k _).trans (by gcongr) + have hLf : (L * f) ^ k * ((m : ℝ) ^ k / k.factorial) ≤ (L / θ) ^ k / k.factorial := by + rw [← mul_div_assoc, ← mul_pow] + gcongr + calc L * f * m = L * (m * f) := by ring + _ ≤ L * (1 / θ) := by gcongr + _ = L / θ := by ring + calc f * (1 + f) ^ m * (L * f) ^ k * ((#(S.filter (· < y))).choose k : ℝ) + ≤ f * Real.exp (1 / θ) * ((L * f) ^ k * ((m : ℝ) ^ k / k.factorial)) := by + rw [mul_assoc (f * (1 + f) ^ m)] + gcongr + _ ≤ f * Real.exp (1 / θ) * ((L / θ) ^ k / k.factorial) := by gcongr + _ = f * Real.exp (1 / θ) * (L / θ) ^ k / k.factorial := by ring + +omit [LinearOrder V] in +include hC0 hφ0 hφθ hφm in +/-- **The corrected matrix of a finite iterate is nonnegative.** -/ +theorem cutoffCorrection_residual_nonneg (hθf : 0 ≤ θ * f) (k : ℕ) (x y : V) : + 0 ≤ (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y := by + cases k with + | zero => simpa [cutoffCorrectionIter] using hC0 x y + | succ k => + have hF0 := cutoffCorrectionIter_nonneg (C := C) hφ0 k + have hstep : cutoffCorrectionIter φ C (k + 1) x y = + φ y ((C + cutoffCorrectionIter φ C k * C) x y) := by + rw [cutoffCorrectionIter_succ]; rfl + have hcut := cutoff_le_self hφθ hθf y (correctionInput_nonneg hC0 hF0 x y) + have hgrow : (cutoffCorrectionIter φ C k * C) x y ≤ + (cutoffCorrectionIter φ C (k + 1) * C) x y := + Finset.sum_le_sum fun z _ => mul_le_mul_of_nonneg_right + (cutoffCorrectionIter_le_succ hC0 hφ0 hφm k x z) (hC0 z y) + rw [← hstep, add_apply] at hcut + rw [add_apply, sub_apply] + linarith + +include hC hC0 hCf hC1 hφ0 hφθ hφm hφL in +/-- **Fully corrected columns have small residuals.** If the cutoff of column `y` leaves at most +`θ₂ f` behind, the corrected matrix of the `k`-th iterate has entries at most +`θ₂ f + f e^(1 / θ) (L / θ)^k / k!` in that column [OpenAI2026LogSpace, Lemma 4.4]. -/ +theorem cutoffCorrection_residual_le (hf : 0 < f) (hθ : 0 < θ) (hL : 0 ≤ L) {θ₂ : ℝ} {y : V} + (hgood : ∀ t, t - θ₂ * f ≤ φ y t) (k : ℕ) (x : V) : + (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y ≤ + θ₂ * f + f * Real.exp (1 / θ) * (L / θ) ^ k / k.factorial := by + set E := cutoffCorrectionFix φ C + set F := cutoffCorrectionIter φ C k + have hEfix : E x y = φ y ((C + E * C) x y) := fix_apply hC x y + have hΔ := cutoffCorrectionFix_sub_iter_le hC hC0 hCf hC1 hφ0 hφθ hφm hφL hf hθ hL k x y + have hΔC : (F * C) x y ≤ (E * C) x y := + Finset.sum_le_sum fun z _ => mul_le_mul_of_nonneg_right + (cutoffCorrectionIter_le_fix hC hC0 hφ0 hφm k x z) (hC0 z y) + have hT := hgood ((C + E * C) x y) + rw [← hEfix] at hT + simp only [add_apply, sub_apply] at hT hΔC ⊢ + linarith + +/-- **A constant number of iterations suffices**: for every accuracy `δ > 0` there is `k`, depending +only on `θ`, `L` and `δ`, with `e^(1 / θ) (L / θ)^k / k! ≤ δ` [OpenAI2026LogSpace, Lemma 4.1]. -/ +theorem exists_factorial_bound_le (θ L : ℝ) {δ : ℝ} (hδ : 0 < δ) : + ∃ k : ℕ, Real.exp (1 / θ) * (L / θ) ^ k / k.factorial ≤ δ := by + have h := (FloorSemiring.tendsto_pow_div_factorial_atTop (L / θ)).const_mul + (Real.exp (1 / θ)) + rw [mul_zero] at h + obtain ⟨k, hk⟩ := (h.eventually (gt_mem_nhds hδ)).exists + exact ⟨k, by rw [mul_div_assoc]; exact hk.le⟩ + +end Bounds + +end Matrix diff --git a/ComplexityTests/FactorialTruncation.lean b/ComplexityTests/FactorialTruncation.lean new file mode 100644 index 000000000..1a9743119 --- /dev/null +++ b/ComplexityTests/FactorialTruncation.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ +import Complexity.Foundations.LinearAlgebra.Matrix.FactorialTruncation + +/-! +# Tests for factorial truncation of cutoff corrections +-/ + +namespace ComplexityTests.FactorialTruncation + +open Matrix + +/-- A walk on three time layers: from `0` to `1` and from `1` to `2`, each with probability +`1 / 2`. Its entries are at most `f = 1 / 2`. -/ +private noncomputable def C : Matrix (Fin 3) (Fin 3) ℝ := !![0, 1 / 2, 0; 0, 0, 1 / 2; 0, 0, 0] + +/-- The hard cutoff `t ↦ max (t - θ f) 0` with `θ = 1 / 4`, `f = 1 / 2`: it leaves exactly `1 / 8` +behind. It is monotone and `1`-Lipschitz. -/ +private noncomputable def φ : Fin 3 → ℝ → ℝ := fun _ t => max (t - 1 / 8) 0 + +private theorem hC : C.IsStrictUpperTriangular := by + intro i j h; fin_cases i <;> fin_cases j <;> simp_all [C] + +private theorem hC0 : ∀ x y, 0 ≤ C x y := by + intro x y; fin_cases x <;> fin_cases y <;> norm_num [C] + +private theorem hCf : ∀ x y, C x y ≤ 1 / 2 := by + intro x y; fin_cases x <;> fin_cases y <;> norm_num [C] + +private theorem hC1 : C *ᵥ 1 ≤ 1 := by + intro x; fin_cases x <;> norm_num [C, mulVec, dotProduct, Fin.sum_univ_three] + +private theorem hφ0 : ∀ y t, 0 ≤ φ y t := fun _ _ => le_max_right _ _ + +private theorem hφθ : ∀ y t, φ y t ≤ max (t - 1 / 4 * (1 / 2)) 0 := fun _ t => by + norm_num [φ] + +private theorem hφm : ∀ y, Monotone (φ y) := fun _ _ _ h => max_le_max (by linarith) le_rfl + +private theorem hφL : ∀ y s t, s ≤ t → φ y t - φ y s ≤ 1 * (t - s) := fun _ s t _ => by + simp only [φ, one_mul] + have := le_max_left (s - 1 / 8) 0 + have := le_max_right (s - 1 / 8) 0 + have : max (t - 1 / 8) 0 ≤ max (s - 1 / 8) 0 + (t - s) := max_le (by linarith) (by linarith) + linarith + +/-- The cutoff correction of `C`, computed by hand: `φ (1 / 2) = 3 / 8` on both transitions, +and `φ (3 / 8 * 1 / 2) = 1 / 16` on the corrected two-step entry. -/ +private noncomputable def Estar : Matrix (Fin 3) (Fin 3) ℝ := + !![0, 3 / 8, 1 / 16; 0, 0, 3 / 8; 0, 0, 0] + +-- `Estar` solves the recursion, so it is the cutoff correction. +private theorem Estar_eq : Estar = cutoffCorrectionFix φ C := by + refine eq_cutoffCorrectionFix hC ?_ + ext x y + fin_cases x <;> fin_cases y <;> + norm_num [cutoffCorrection, φ, C, Estar, mul_apply, Fin.sum_univ_three] + +-- One iteration from zero misses the two-step entry entirely. +example : cutoffCorrectionIter φ C 1 0 2 = 0 := by + norm_num [cutoffCorrectionIter, cutoffCorrection, φ, C] + +-- The truncation error after one iteration, `1 / 16`, is within the factorial bound. +example : cutoffCorrectionFix φ C 0 2 - cutoffCorrectionIter φ C 1 0 2 ≤ + 1 / 2 * Real.exp (1 / (1 / 4)) * (1 / (1 / 4)) ^ 1 / (Nat.factorial 1) := + cutoffCorrectionFix_sub_iter_le hC hC0 hCf hC1 hφ0 hφθ hφm hφL (by norm_num) (by norm_num) + (by norm_num) 1 0 2 + +-- After two iterations the iterate has reached the fixed point at `(0, 2)`. +example : cutoffCorrectionIter φ C 2 0 2 = cutoffCorrectionFix φ C 0 2 := by + rw [← Estar_eq] + norm_num [cutoffCorrectionIter, cutoffCorrection, φ, C, Estar, mul_apply, Fin.sum_univ_three] + +-- The corrected matrix of every iterate is nonnegative, and the hard cutoff leaves at most +-- `θ f = 1 / 8` behind in every column. +example (k : ℕ) (x y : Fin 3) : + 0 ≤ (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y := + cutoffCorrection_residual_nonneg hC0 hφ0 hφθ hφm (by norm_num) k x y + +example (k : ℕ) (x y : Fin 3) : + (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y ≤ + 1 / 4 * (1 / 2) + 1 / 2 * Real.exp (1 / (1 / 4)) * (1 / (1 / 4)) ^ k / k.factorial := + cutoffCorrection_residual_le hC hC0 hCf hC1 hφ0 hφθ hφm hφL (by norm_num) (by norm_num) + (by norm_num) (fun t => by norm_num [φ]) k x + +-- A fixed number of iterations gets within `1 / 100` of the factorial bound's limit. +example : ∃ k : ℕ, Real.exp (1 / (1 / 4)) * (1 / (1 / 4)) ^ k / k.factorial ≤ 1 / 100 := + exists_factorial_bound_le _ _ (by norm_num) + +end ComplexityTests.FactorialTruncation From 6e0388d538b591a63b9a59ef5a4337638b31242e Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Thu, 29 Oct 2026 23:17:18 +0000 Subject: [PATCH 05/18] refactor(Foundations): use Nat.sum_Icc_choose for the hockey-stick step Review nit on #1677: drop the private hockey-stick lemma. Co-Authored-By: Claude Opus 5.5 --- .../Matrix/FactorialTruncation.lean | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean index ad9fe5b9c..d9e81c1ed 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean @@ -180,13 +180,6 @@ private theorem sum_rank_le (S : Finset V) (y : V) {g : ℕ → ℝ} (hg : ∀ j simp only [mem_filter] at hz exact Finset.mem_range.mpr (hlt hz.1 hz.2) -/-- The hockey-stick identity `∑ j < n, (j choose k) = n choose (k + 1)`. -/ -private theorem sum_range_choose_eq (n k : ℕ) : - ∑ j ∈ range n, (j.choose k : ℝ) = (n.choose (k + 1) : ℝ) := by - induction n with - | zero => simp - | succ n ih => rw [sum_range_succ, ih, Nat.choose_succ_succ', Nat.cast_add, add_comm] - variable (hC : C.IsStrictUpperTriangular) (hC0 : ∀ x y, 0 ≤ C x y) (hCf : ∀ x y, C x y ≤ f) (hC1 : C *ᵥ 1 ≤ 1) (hφ0 : ∀ y t, 0 ≤ φ y t) (hφθ : ∀ y t, φ y t ≤ max (t - θ * f) 0) (hφm : ∀ y, Monotone (φ y)) (hφL : ∀ y s t, s ≤ t → φ y t - φ y s ≤ L * (t - s)) @@ -388,7 +381,15 @@ private theorem fix_sub_iter_le_choose (hf : 0 ≤ f) (hθf : 0 ≤ θ * f) (hL gcongr exact sum_rank_le S y (g := fun j => (j.choose k : ℝ)) fun j => by positivity _ = f * (1 + f) ^ #S * (L * f) ^ (k + 1) * (#(S.filter (· < y))).choose (k + 1) := by - rw [sum_range_choose_eq] + -- the hockey-stick identity `∑ j ∈ Icc k n, j.choose k = (n + 1).choose (k + 1)` + congr 1 + rcases hn : #(S.filter (· < y)) with _ | n + · simp + · rw [← Nat.sum_Icc_choose, Nat.cast_sum] + refine (Finset.sum_subset (fun j hj => ?_) fun j hj hjn => ?_).symm + · simp only [mem_Icc, mem_range] at hj ⊢; omega + · simp only [mem_Icc, mem_range, not_and_or, not_le] at hj hjn + rw [Nat.choose_eq_zero_of_lt (by omega), Nat.cast_zero] end Row From 8b3f5725d8ca58892463e9848898ea86e29fdc2a Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Thu, 29 Oct 2026 23:26:24 +0000 Subject: [PATCH 06/18] doc(Foundations): count chains with the integer support size Review of #1677: the module docstring now bounds the chain count by m.choose k for the actual support size m, as the proof does. Co-Authored-By: Claude Opus 5.5 --- .../LinearAlgebra/Matrix/FactorialTruncation.lean | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean index d9e81c1ed..f94a429ae 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean @@ -32,10 +32,10 @@ iterations every entry is within `f e^(1 / θ) (L / θ)^k / k!` of the fixed poi (`Matrix.cutoffCorrectionFix_sub_iter_le`). The proof counts chains. In a fixed row, every positive entry of the fixed point leaves a residual -at least `θ f`, and the residuals of a row sum to at most one, so the row has at most `1 / (θ f)` -positive entries. Unrolling the recursion `k` times along that row expresses the error as a sum -over increasing chains of `k` of these entries, each weighted by at most `(L f)^k`; there are at -most `binomial (1 / (θ f), k) ≤ (θ f)^(-k) / k!` of them. +at least `θ f`, and the residuals of a row sum to at most one, so the number `m` of positive +entries in the row satisfies `m θ f ≤ 1`. Unrolling the recursion `k` times along that row +expresses the error as a sum over increasing chains of `k` of these entries, each weighted by at +most `(L f)^k`; there are at most `m.choose k ≤ m^k / k! ≤ (θ f)^(-k) / k!` of them. For the finite correction `E = E k`, the corrected matrix `C - E + E C` is nonnegative (`Matrix.cutoffCorrection_residual_nonneg`), and in a column whose cutoff leaves at most `θ₂ f` From 7fd99bc4ccd4c39d1421d17fe606d092133b5074 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Thu, 29 Oct 2026 23:25:02 +0000 Subject: [PATCH 07/18] feat(Foundations): one stage of the correction-and-copy hierarchy Third slice of #1679 (Phase 2 of #1444, ideas 3 and 4 of #474), following the OpenAI preprint (2026-09-23), Lemma 4.2, Lemma 4.4 and Proposition 4.5: row-sum, entry, domination and support bounds for cutoff corrections; the copy step with explicit split fractions, its density and active-copy bounds; incidence counting; and the one-stage rates that feed the stage bound, given an abstract detector interface. Co-Authored-By: Claude Opus 5.5 --- Complexity.lean | 1 + .../LinearAlgebra/Matrix/CopyStage.lean | 533 ++++++++++++++++++ ComplexityTests/CopyStage.lean | 137 +++++ 3 files changed, 671 insertions(+) create mode 100644 Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean create mode 100644 ComplexityTests/CopyStage.lean diff --git a/Complexity.lean b/Complexity.lean index b1c2b3181..2a5c4feb0 100644 --- a/Complexity.lean +++ b/Complexity.lean @@ -2620,6 +2620,7 @@ public import Complexity.Foundations.LinearAlgebra.ExchangeReplacement public import Complexity.Foundations.LinearAlgebra.ImageSparsification public import Complexity.Foundations.LinearAlgebra.Interpolation public import Complexity.Foundations.LinearAlgebra.KernelVector +public import Complexity.Foundations.LinearAlgebra.Matrix.CopyStage public import Complexity.Foundations.LinearAlgebra.Matrix.CorrectionHierarchy public import Complexity.Foundations.LinearAlgebra.Matrix.CutRank public import Complexity.Foundations.LinearAlgebra.Matrix.FactorialTruncation diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean new file mode 100644 index 000000000..4fd044ed2 --- /dev/null +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean @@ -0,0 +1,533 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Foundations.LinearAlgebra.Matrix.FactorialTruncation +import Mathlib.Algebra.BigOperators.Fin + +/-! +# One stage of the correction-and-copy hierarchy + +One stage of the hierarchy of the OpenAI preprint (2026-09-23), Section 4, ideas 3 and 4 in issue +#474 [OpenAI2026LogSpace], takes a transition matrix `C` with entries at most `f`, corrects it to +`D = C - E + E C` with a finite cutoff correction `E` (`Matrix.cutoffCorrectionIter`), and splits +the remaining large entries of `D` among copies of their targets (`Matrix.copyStage`). This file +proves the deterministic bounds of such a stage. The result `C⁺` has entries at most `f / q`, and +its support lies in a set at most twice as large as the support of `C` +(`Matrix.copyStage_rates`). These are exactly the per-stage hypotheses of the stage bound +`Matrix.sub_rewardTransport_mulVec_le_pow`; `Matrix.sub_rewardTransport_mulVec_le_of_rates` +iterates them. + +The choice of which columns are corrected and which vertices get active copies comes from the +preprint's *detectors*, which are probabilistic. Here it is an interface: copy weights `r` with +`r 0 = 1`, and a finite set `O` of *overloaded* vertices, such that + +* only overloaded vertices have active extra copies: `r j x ≠ 0 → x ∈ O` for `j ≠ 0`; +* every column is either *fully corrected*, `t - θ₂ f ≤ φ y t` for all `t`, or overloaded with all + its copies active; +* `m |O| ≤ |A|`, where `m + 1` is the number of copies and `A` covers the support of `C`. + +The last condition follows from incidence counting (`Matrix.card_mul_le_of_incidences`): if every +overloaded column has many large entries in one of a few substochastic matrices, as the detectors +guarantee for the pilot inputs, then there are few overloaded columns. + +The corrected matrix also satisfies the remaining bounds of Lemma 4.4 of the preprint. Its entries +are at most `(k + 1) f` (`Matrix.cutoffCorrection_residual_le_mul`). It dominates its unsigned +constituents, `θ / (2 (k + 1)) (C + E + E C) ≤ D` (`Matrix.cutoffCorrection_residual_dominates`), +which lets the three terms of `D` be estimated separately. Its support stays within that of `C` +(`Matrix.cutoffCorrection_residual_mem`). + +## Main definitions + +* `Matrix.copyFraction`: the proportions in which an entry is split among `m + 1` copies. +* `Matrix.copyStage`: the copy step `Matrix.copySplit` with these proportions. +* `Matrix.copyCover`: the copies that can be active, given a cover of the parents. + +## Main results + +* `Matrix.cutoffCorrectionIter_sum_le`, `Matrix.cutoffCorrectionIter_le_mul`: row sums and + entries of the iterates. +* `Matrix.cutoffCorrection_residual_le_mul`, `Matrix.cutoffCorrection_residual_dominates`, + `Matrix.cutoffCorrection_residual_mem`: entry bound, domination and support of the residual. +* `Matrix.copyStage_mul_copyWeight`, `Matrix.copyStage_nonneg`, `Matrix.copyStage_mulVec_one_le`, + `Matrix.copyStage_le`, `Matrix.copyStage_mem_copyCover`, `Matrix.card_copyCover_le`: the copy + step intertwines with its projection, is substochastic, has small entries and few active + copies. +* `Matrix.card_mul_le_of_incidences`: incidence counting. +* `Matrix.copyStage_rates`: the one-stage density and active-count bounds. +* `Matrix.sub_rewardTransport_mulVec_le_of_rates`: the stage bound from per-stage rates. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Lemma 4.2, Lemma 4.4, Proposition 4.5 and Proposition 4.7 (preprint, not peer reviewed) +-/ + +public section + +open Finset + +namespace Matrix + +/-! ### Residual bounds for cutoff corrections -/ + +section Residual + +variable {V : Type*} [Fintype V] {φ : V → ℝ → ℝ} {C : Matrix V V ℝ} {f θ : ℝ} + +variable (hC0 : ∀ x y, 0 ≤ C x y) (hφ0 : ∀ y t, 0 ≤ φ y t) + (hφθ : ∀ y t, φ y t ≤ max (t - θ * f) 0) (hθf : 0 ≤ θ * f) + +omit [Fintype V] in +include hφθ hθf in +private theorem cutoff_le_self' (y : V) {t : ℝ} (ht : 0 ≤ t) : φ y t ≤ t := + (hφθ y t).trans (max_le (by linarith) ht) + +omit [Fintype V] in +include hφ0 hφθ hθf in +private theorem cutoff_zero (y : V) : φ y 0 = 0 := + le_antisymm ((hφθ y 0).trans (max_le (by linarith) le_rfl)) (hφ0 y 0) + +include hC0 hφ0 hφθ hθf in +private theorem iter_succ_le_input (k : ℕ) (x y : V) : + cutoffCorrectionIter φ C (k + 1) x y ≤ (C + cutoffCorrectionIter φ C k * C) x y := by + rw [cutoffCorrectionIter_succ] + exact cutoff_le_self' hφθ hθf y <| add_nonneg (hC0 x y) <| Finset.sum_nonneg fun z _ => + mul_nonneg (cutoffCorrectionIter_nonneg hφ0 k x z) (hC0 z y) + +include hC0 hφ0 hφθ hθf in +/-- **Row sums of the iterates**: the `k`-th iterate of a cutoff correction of a substochastic +`C` has row sums at most `k` [OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem cutoffCorrectionIter_sum_le (hC1 : C *ᵥ 1 ≤ 1) (k : ℕ) (x : V) : + ∑ y, cutoffCorrectionIter φ C k x y ≤ k := by + have hrow : ∀ z, ∑ y, C z y ≤ 1 := fun z => by simpa [mulVec, dotProduct] using hC1 z + induction k with + | zero => simp [cutoffCorrectionIter] + | succ k ih => + set F := cutoffCorrectionIter φ C k + calc ∑ y, cutoffCorrectionIter φ C (k + 1) x y ≤ ∑ y, (C + F * C) x y := + Finset.sum_le_sum fun y _ => iter_succ_le_input hC0 hφ0 hφθ hθf k x y + _ = ∑ y, C x y + ∑ z, F x z * ∑ y, C z y := by + simp only [add_apply, mul_apply, Finset.sum_add_distrib, Finset.mul_sum] + rw [Finset.sum_comm] + _ ≤ 1 + ∑ z, F x z * 1 := add_le_add (hrow x) (Finset.sum_le_sum fun z _ => + mul_le_mul_of_nonneg_left (hrow z) (cutoffCorrectionIter_nonneg hφ0 k x z)) + _ ≤ (k + 1 : ℕ) := by simp only [mul_one]; push_cast; linarith + +include hC0 hφ0 hφθ hθf in +/-- The input `(C + E_k C) x y` of the `(k + 1)`-th step is at most `(k + 1) f`. -/ +private theorem input_le (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) (hC1 : C *ᵥ 1 ≤ 1) (k : ℕ) + (x y : V) : (C + cutoffCorrectionIter φ C k * C) x y ≤ (k + 1) * f := by + have hsum := cutoffCorrectionIter_sum_le hC0 hφ0 hφθ hθf hC1 k x + calc (C + cutoffCorrectionIter φ C k * C) x y + = C x y + ∑ z, cutoffCorrectionIter φ C k x z * C z y := rfl + _ ≤ f + ∑ z, cutoffCorrectionIter φ C k x z * f := add_le_add (hCf x y) + (Finset.sum_le_sum fun z _ => + mul_le_mul_of_nonneg_left (hCf z y) (cutoffCorrectionIter_nonneg hφ0 k x z)) + _ ≤ (k + 1) * f := by rw [← Finset.sum_mul]; nlinarith + +include hC0 hφ0 hφθ hθf in +/-- **Entries of the iterates**: the `k`-th iterate has entries at most `k f` +[OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem cutoffCorrectionIter_le_mul (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) (hC1 : C *ᵥ 1 ≤ 1) + (k : ℕ) (x y : V) : cutoffCorrectionIter φ C k x y ≤ k * f := by + cases k with + | zero => simp [cutoffCorrectionIter] + | succ k => + push_cast + exact (iter_succ_le_input hC0 hφ0 hφθ hθf k x y).trans + (input_le hC0 hφ0 hφθ hθf hCf hf hC1 k x y) + +include hC0 hφ0 hφθ hθf in +/-- **The residual entry bound**: `C - E_k + E_k C` has entries at most `(k + 1) f` +[OpenAI2026LogSpace, Lemma 4.4]. -/ +theorem cutoffCorrection_residual_le_mul (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) + (hC1 : C *ᵥ 1 ≤ 1) (k : ℕ) (x y : V) : + (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y ≤ (k + 1) * f := by + have h := input_le hC0 hφ0 hφθ hθf hCf hf hC1 k x y + have h0 := cutoffCorrectionIter_nonneg (C := C) hφ0 k x y + simp only [add_apply, sub_apply] at h ⊢ + linarith + +include hC0 hφ0 hφθ hθf in +/-- **Domination of the unsigned terms**: for `θ ≤ 1`, the residual of the `(k + 1)`-th iterate +dominates a fixed multiple of the sum of its unsigned constituents, +`θ / (2 (k + 1)) (C + E + E C) ≤ C - E + E C` [OpenAI2026LogSpace, Lemma 4.4]. -/ +theorem cutoffCorrection_residual_dominates (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) + (hC1 : C *ᵥ 1 ≤ 1) (hφm : ∀ y, Monotone (φ y)) (hθ0 : 0 ≤ θ) (hθ1 : θ ≤ 1) (k : ℕ) + (x y : V) : + θ / (2 * (k + 1)) * (C + cutoffCorrectionIter φ C (k + 1) + + cutoffCorrectionIter φ C (k + 1) * C) x y ≤ + (C - cutoffCorrectionIter φ C (k + 1) + cutoffCorrectionIter φ C (k + 1) * C) x y := by + have hk : (0 : ℝ) < k + 1 := by positivity + have ha0 : 0 ≤ (C + cutoffCorrectionIter φ C k * C) x y := + add_nonneg (hC0 x y) (Finset.sum_nonneg fun z _ => + mul_nonneg (cutoffCorrectionIter_nonneg hφ0 k x z) (hC0 z y)) + have ha := input_le hC0 hφ0 hφθ hθf hCf hf hC1 k x y + have hEa : cutoffCorrectionIter φ C (k + 1) x y = + φ y ((C + cutoffCorrectionIter φ C k * C) x y) := by + rw [cutoffCorrectionIter_succ]; rfl + have he0 := cutoffCorrectionIter_nonneg (C := C) hφ0 (k + 1) x y + have hea := iter_succ_le_input hC0 hφ0 hφθ hθf k x y + have hFE : (cutoffCorrectionIter φ C k * C) x y ≤ (cutoffCorrectionIter φ C (k + 1) * C) x y := + Finset.sum_le_sum fun z _ => + mul_le_mul_of_nonneg_right (cutoffCorrectionIter_le_succ hC0 hφ0 hφm k x z) (hC0 z y) + have hθa := hφθ y ((C + cutoffCorrectionIter φ C k * C) x y) + rw [← hEa] at hθa + set F := cutoffCorrectionIter φ C k + set E := cutoffCorrectionIter φ C (k + 1) + set a := (C + F * C) x y + set t := θ / (k + 1) + have ht0 : 0 ≤ t := by positivity + have ht1 : t ≤ 1 := by rw [div_le_one hk]; linarith + have hmin : t * a ≤ a - E x y := by + rcases le_or_gt 0 (a - θ * f) with h | h + · have he : E x y ≤ a - θ * f := by rw [max_eq_left h] at hθa; exact hθa + have : t * a ≤ θ * f := by + calc t * a ≤ t * ((k + 1) * f) := mul_le_mul_of_nonneg_left ha ht0 + _ = θ * f := by simp only [t]; field_simp + linarith + · have he : E x y ≤ 0 := by rw [max_eq_right h.le] at hθa; exact hθa + nlinarith + have hcoef : θ / (2 * (k + 1)) = t / 2 := by simp only [t]; field_simp + have h1 : t / 2 * E x y ≤ t / 2 * a := mul_le_mul_of_nonneg_left hea (by positivity) + have h2 : t / 2 * ((E * C) x y - (F * C) x y) ≤ (E * C) x y - (F * C) x y := + mul_le_of_le_one_left (by linarith) (by linarith) + have hadef : a = C x y + (F * C) x y := rfl + rw [hcoef] + simp only [add_apply, sub_apply] + nlinarith + +variable {A : Finset V} + +include hφ0 hφθ hθf in +/-- The iterates are supported within any set `A` covering the support of `C`. -/ +theorem cutoffCorrectionIter_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) (k : ℕ) (x y : V) + (h : cutoffCorrectionIter φ C k x y ≠ 0) : x ∈ A ∧ y ∈ A := by + induction k generalizing x y with + | zero => simp [cutoffCorrectionIter] at h + | succ k ih => + by_contra hxy + apply h + have hCxy : C x y = 0 := by + by_contra h'; exact hxy (hA x y h') + have hin : (C + cutoffCorrectionIter φ C k * C) x y = 0 := by + simp only [add_apply, mul_apply, hCxy, zero_add] + refine Finset.sum_eq_zero fun z _ => ?_ + by_cases hE : cutoffCorrectionIter φ C k x z = 0 + · rw [hE, zero_mul] + by_cases hCz : C z y = 0 + · rw [hCz, mul_zero] + exact absurd ⟨(ih x z hE).1, (hA z y hCz).2⟩ hxy + rw [cutoffCorrectionIter_succ] + change φ y ((C + cutoffCorrectionIter φ C k * C) x y) = 0 + rw [hin, cutoff_zero hφ0 hφθ hθf] + +include hφ0 hφθ hθf in +/-- **The residual stays within the support of `C`** [OpenAI2026LogSpace, Lemma 4.4]. -/ +theorem cutoffCorrection_residual_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) (k : ℕ) + (x y : V) + (h : (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y ≠ 0) : + x ∈ A ∧ y ∈ A := by + by_contra hxy + apply h + have hE : ∀ u v, cutoffCorrectionIter φ C k u v ≠ 0 → u ∈ A ∧ v ∈ A := + cutoffCorrectionIter_mem hφ0 hφθ hθf hA k + have hCxy : C x y = 0 := by by_contra h'; exact hxy (hA x y h') + have hExy : cutoffCorrectionIter φ C k x y = 0 := by by_contra h'; exact hxy (hE x y h') + simp only [add_apply, sub_apply, mul_apply, hCxy, hExy, sub_zero, zero_add] + refine Finset.sum_eq_zero fun z _ => ?_ + by_cases hEz : cutoffCorrectionIter φ C k x z = 0 + · rw [hEz, zero_mul] + by_cases hCz : C z y = 0 + · rw [hCz, mul_zero] + exact absurd ⟨(hE x z hEz).1, (hA z y hCz).2⟩ hxy + +end Residual + +/-! ### Copy fractions -/ + +section Fraction + +/-- **Copy fractions** for `m + 1` copies, driven by a cutoff `χ` with values in `[0, 1]`: the +primary copy `0` receives `1 - m / (m + 1) χ t`, every other copy `χ t / (m + 1)`. Small entries +(`χ t = 0`) stay with the primary copy; large ones (`χ t = 1`) are split evenly +[OpenAI2026LogSpace, (4.21)]. -/ +@[expose] noncomputable def copyFraction (χ : ℝ → ℝ) (m : ℕ) (t : ℝ) (j : Fin (m + 1)) : ℝ := + if j = 0 then 1 - m / (m + 1) * χ t else χ t / (m + 1) + +variable {χ : ℝ → ℝ} {m : ℕ} {t : ℝ} + +theorem sum_copyFraction (χ : ℝ → ℝ) (m : ℕ) (t : ℝ) : ∑ j, copyFraction χ m t j = 1 := by + rw [Fin.sum_univ_succ] + simp only [copyFraction, Fin.succ_ne_zero, ↓reduceIte, Finset.sum_const, card_univ, + Fintype.card_fin, nsmul_eq_mul] + field_simp + ring + +theorem copyFraction_nonneg (h0 : 0 ≤ χ t) (h1 : χ t ≤ 1) (j : Fin (m + 1)) : + 0 ≤ copyFraction χ m t j := by + have hm : (m : ℝ) / (m + 1) ≤ 1 := by rw [div_le_one (by positivity)]; linarith + unfold copyFraction + split_ifs + · nlinarith [mul_le_mul hm h1 h0 zero_le_one] + · positivity + +theorem copyFraction_le_one (h0 : 0 ≤ χ t) (h1 : χ t ≤ 1) (j : Fin (m + 1)) : + copyFraction χ m t j ≤ 1 := by + unfold copyFraction + split_ifs + · have : 0 ≤ (m : ℝ) / (m + 1) * χ t := by positivity + linarith + · rw [div_le_one (by positivity)]; linarith + +theorem copyFraction_of_eq_zero (h : χ t = 0) (j : Fin (m + 1)) : + copyFraction χ m t j = if j = 0 then 1 else 0 := by + simp [copyFraction, h] + +theorem copyFraction_of_eq_one (h : χ t = 1) (j : Fin (m + 1)) : + copyFraction χ m t j = 1 / (m + 1) := by + unfold copyFraction + split_ifs + · rw [h]; field_simp; ring + · rw [h] + +end Fraction + +/-! ### The copy step -/ + +section Stage + +variable {V : Type*} {m : ℕ} {χ : ℝ → ℝ} {τ₀ τ₁ : ℝ} {r : Fin (m + 1) → V → ℝ} + {D : Matrix V V ℝ} + +/-- **The copy step** of the hierarchy: `Matrix.copySplit` with the proportions +`Matrix.copyFraction χ m (D x y)` [OpenAI2026LogSpace, (4.23)]. -/ +@[expose] noncomputable def copyStage (χ : ℝ → ℝ) (m : ℕ) (r : Fin (m + 1) → V → ℝ) + (D : Matrix V V ℝ) : Matrix (V × Fin (m + 1)) (V × Fin (m + 1)) ℝ := + copySplit r (fun x y => copyFraction χ m (D x y)) D + +/-- The copies that can be active: the primary copies of a cover `A` of the parents, and all +copies of the overloaded vertices `O`. -/ +@[expose] def copyCover [DecidableEq V] (A O : Finset V) : Finset (V × Fin (m + 1)) := + A ×ˢ {0} ∪ O ×ˢ univ.erase 0 + +theorem card_copyCover_le [DecidableEq V] (A O : Finset V) : + #(copyCover (m := m) A O) ≤ #A + m * #O := by + refine (card_union_le _ _).trans ?_ + rw [card_product, card_product, card_singleton, card_erase_of_mem (mem_univ _), card_univ, + Fintype.card_fin, mul_one, Nat.add_sub_cancel, mul_comm] + +/-- **The copy step intertwines with its projection** when the primary weight is one and every +large entry `τ₀ < D x y` has all copies of its target active [OpenAI2026LogSpace, (4.26)]. -/ +theorem copyStage_mul_copyWeight [Fintype V] [DecidableEq V] (hr0 : ∀ x, r 0 x = 1) + (hχ₀ : ∀ t, t ≤ τ₀ → χ t = 0) + (hbig : ∀ x y, τ₀ < D x y → ∀ j, r j y = 1) : + copyStage χ m r D * copyWeight r = copyWeight r * D := by + refine copySplit_mul_copyWeight fun x y _ => ?_ + rcases le_or_gt (D x y) τ₀ with h | h + · rw [Fin.sum_univ_succ] + simp [copyFraction_of_eq_zero (hχ₀ _ h), Fin.succ_ne_zero, hr0] + · simp only [hbig x y h, mul_one] + exact sum_copyFraction χ m (D x y) + +theorem copyStage_nonneg (hr : ∀ j x, 0 ≤ r j x) (hD : ∀ x y, 0 ≤ D x y) + (hχ0 : ∀ t, 0 ≤ χ t) (hχ1 : ∀ t, χ t ≤ 1) (a b : V × Fin (m + 1)) : + 0 ≤ copyStage χ m r D a b := + copySplit_nonneg hr (fun _ _ j => copyFraction_nonneg (hχ0 _) (hχ1 _) j) hD a b + +/-- The copy step is substochastic when `D` is and the weights lie in `[0, 1]`. -/ +theorem copyStage_mulVec_one_le [Fintype V] (hr0 : ∀ j x, 0 ≤ r j x) (hr1 : ∀ j x, r j x ≤ 1) + (hD0 : ∀ x y, 0 ≤ D x y) (hD1 : D *ᵥ 1 ≤ 1) : copyStage χ m r D *ᵥ 1 ≤ 1 := + copySplit_mulVec_one_le hr0 hr1 (fun x y => (sum_copyFraction χ m (D x y)).le) hD0 hD1 + +/-- **The density bound**: if the entries of `D` are at most `K`, the cutoff is one from `τ₁` +on, `τ₁ ≤ b` and `K / (m + 1) ≤ b`, the copy step has entries at most `b` +[OpenAI2026LogSpace, Proposition 4.5]. -/ +theorem copyStage_le (hr0 : ∀ j x, 0 ≤ r j x) (hr1 : ∀ j x, r j x ≤ 1) + (hD0 : ∀ x y, 0 ≤ D x y) {K b : ℝ} (hDK : ∀ x y, D x y ≤ K) (hχ0 : ∀ t, 0 ≤ χ t) + (hχ1 : ∀ t, χ t ≤ 1) (hχ₁ : ∀ t, τ₁ ≤ t → χ t = 1) (hτ₁ : τ₁ ≤ b) + (hK : K / (m + 1) ≤ b) (a c : V × Fin (m + 1)) : copyStage χ m r D a c ≤ b := by + simp only [copyStage, copySplit, of_apply] + have hrD : r a.2 a.1 * D a.1 c.1 ≤ D a.1 c.1 := + mul_le_of_le_one_left (hD0 _ _) (hr1 _ _) + have hrD0 : 0 ≤ r a.2 a.1 * D a.1 c.1 := mul_nonneg (hr0 _ _) (hD0 _ _) + rcases lt_or_ge (D a.1 c.1) τ₁ with h | h + · calc r a.2 a.1 * D a.1 c.1 * copyFraction χ m (D a.1 c.1) c.2 + ≤ r a.2 a.1 * D a.1 c.1 := + mul_le_of_le_one_right hrD0 (copyFraction_le_one (hχ0 _) (hχ1 _) _) + _ ≤ b := by linarith + · rw [copyFraction_of_eq_one (hχ₁ _ h)] + calc r a.2 a.1 * D a.1 c.1 * (1 / (m + 1)) ≤ K * (1 / (m + 1)) := + mul_le_mul_of_nonneg_right (hrD.trans (hDK _ _)) (by positivity) + _ ≤ b := by rw [mul_one_div]; exact hK + +/-- **Active copies**: if `A` covers the support of `D`, extra copies of `x` are active only for +overloaded `x`, and large entries have overloaded targets, then the copy step is supported in +`Matrix.copyCover A O` [OpenAI2026LogSpace, Proposition 4.5]. -/ +theorem copyStage_mem_copyCover [DecidableEq V] {A O : Finset V} + (hA : ∀ x y, D x y ≠ 0 → x ∈ A ∧ y ∈ A) + (hrO : ∀ j x, j ≠ 0 → r j x ≠ 0 → x ∈ O) (hχ₀ : ∀ t, t ≤ τ₀ → χ t = 0) + (hcolO : ∀ x y, τ₀ < D x y → y ∈ O) (a b : V × Fin (m + 1)) + (h : copyStage χ m r D a b ≠ 0) : a ∈ copyCover A O ∧ b ∈ copyCover A O := by + obtain ⟨⟨x, i⟩, ⟨y, j⟩⟩ := (⟨a, b⟩ : _ × _) + simp only [copyStage, copySplit, of_apply, ne_eq, mul_eq_zero, not_or] at h + obtain ⟨⟨hr, hD⟩, hs⟩ := h + have hxy := hA _ _ hD + simp only [copyCover, mem_union, mem_product, mem_singleton, mem_erase, mem_univ, and_true] + constructor + · by_cases hi : a.2 = 0 + · exact Or.inl ⟨hxy.1, hi⟩ + · exact Or.inr ⟨hrO _ _ hi hr, hi⟩ + · by_cases hj : b.2 = 0 + · exact Or.inl ⟨hxy.2, hj⟩ + · refine Or.inr ⟨hcolO a.1 b.1 ?_, hj⟩ + by_contra hle + exact hs (by simp [copyFraction_of_eq_zero (hχ₀ _ (not_lt.mp hle)), hj]) + +end Stage + +/-! ### Incidence counting -/ + +/-- **Incidence counting.** Let `G i` be nonnegative matrices whose rows sum to at most `s i` and +vanish outside `A`. If each vertex of `O` is the target of at least `N` entries larger than `δ` +in one of the `G i`, then `|O| N δ ≤ |A| ∑ s i`. With the pilot inputs of the preprint as `G i`, +this bounds the number of overloaded columns [OpenAI2026LogSpace, Proposition 4.5]. -/ +theorem card_mul_le_of_incidences {V : Type*} [Fintype V] {k : ℕ} + (G : Fin k → Matrix V V ℝ) (hG0 : ∀ i x y, 0 ≤ G i x y) (s : Fin k → ℝ) + (hGs : ∀ i x, ∑ y, G i x y ≤ s i) (A : Finset V) (hGA : ∀ i x y, G i x y ≠ 0 → x ∈ A) + {δ : ℝ} (hδ : 0 < δ) (O : Finset V) {N : ℕ} + (hO : ∀ y ∈ O, ∃ i, N ≤ #{x | δ < G i x y}) : + (#O * N : ℝ) * δ ≤ #A * ∑ i, s i := by + classical + -- the indicator of a large entry, scaled by `δ`, is at most the entry + have hind : ∀ i x y, (if δ < G i x y then δ else 0) ≤ G i x y := fun i x y => by + split_ifs with h + · exact h.le + · exact hG0 i x y + have hcount : ∀ i y, (#{x | δ < G i x y} : ℝ) * δ = ∑ x, if δ < G i x y then δ else 0 := + fun i y => by rw [Finset.sum_ite, Finset.sum_const_zero, add_zero, Finset.sum_const, + nsmul_eq_mul] + have hrowA : ∀ i x, (∑ y, if δ < G i x y then δ else 0) ≤ if x ∈ A then s i else 0 := by + intro i x + split_ifs with hx + · exact (Finset.sum_le_sum fun y _ => hind i x y).trans (hGs i x) + · refine le_of_eq (Finset.sum_eq_zero fun y _ => ?_) + have : G i x y = 0 := by by_contra h; exact hx (hGA i x y h) + simp [this, not_lt.mpr hδ.le] + calc (#O * N : ℝ) * δ = ∑ y ∈ O, (N : ℝ) * δ := by + rw [Finset.sum_const, nsmul_eq_mul, mul_assoc] + _ ≤ ∑ y ∈ O, ∑ i, ∑ x, if δ < G i x y then δ else 0 := by + refine Finset.sum_le_sum fun y hy => ?_ + obtain ⟨i, hi⟩ := hO y hy + calc (N : ℝ) * δ ≤ (#{x | δ < G i x y} : ℝ) * δ := + mul_le_mul_of_nonneg_right (by exact_mod_cast hi) hδ.le + _ = ∑ x, if δ < G i x y then δ else 0 := hcount i y + _ ≤ ∑ i, ∑ x, if δ < G i x y then δ else 0 := + Finset.single_le_sum (f := fun i => ∑ x, if δ < G i x y then δ else 0) + (fun i _ => Finset.sum_nonneg fun x _ => by split_ifs <;> linarith) (mem_univ i) + _ ≤ ∑ y, ∑ i, ∑ x, if δ < G i x y then δ else 0 := + Finset.sum_le_sum_of_subset_of_nonneg (subset_univ O) fun y _ _ => + Finset.sum_nonneg fun i _ => Finset.sum_nonneg fun x _ => by split_ifs <;> linarith + _ = ∑ i, ∑ x, ∑ y, if δ < G i x y then δ else 0 := by + rw [Finset.sum_comm] + exact Finset.sum_congr rfl fun i _ => Finset.sum_comm + _ ≤ ∑ i, ∑ x, if x ∈ A then s i else 0 := + Finset.sum_le_sum fun i _ => Finset.sum_le_sum fun x _ => hrowA i x + _ = #A * ∑ i, s i := by + simp only [Finset.sum_ite_mem, univ_inter, Finset.sum_const, nsmul_eq_mul] + rw [Finset.mul_sum] + +/-! ### One stage -/ + +section Rates + +variable {V : Type*} [Fintype V] [DecidableEq V] [LinearOrder V] {φ : V → ℝ → ℝ} + {C : Matrix V V ℝ} {f θ L : ℝ} {m : ℕ} {χ : ℝ → ℝ} {τ₀ τ₁ : ℝ} {r : Fin (m + 1) → V → ℝ} + +/-- **One stage of the hierarchy.** Correct `C` by the `k`-th cutoff iterate and split the residual +`D` by `Matrix.copyStage`. Suppose every column is either fully corrected (its cutoff leaves at most +`θ₂ f`) or overloaded with all copies active, the truncation error keeps fully corrected entries +at most `τ₀`, the cutoff `χ` is `0` up to `τ₀` and `1` from `τ₁ ≤ f / q`, there are enough copies +(`(k + 1) f / (m + 1) ≤ f / q`), and `m |O| ≤ |A|` for a cover `A` of the support of `C`. Then +the copy step has entries at most `f / q`, intertwines with its projection, and is supported in a +set of at most `2 |A|` copies [OpenAI2026LogSpace, Proposition 4.5]. -/ +theorem copyStage_rates (hC : C.IsStrictUpperTriangular) (hC0 : ∀ x y, 0 ≤ C x y) + (hCf : ∀ x y, C x y ≤ f) (hC1 : C *ᵥ 1 ≤ 1) (hφ0 : ∀ y t, 0 ≤ φ y t) + (hφθ : ∀ y t, φ y t ≤ max (t - θ * f) 0) (hφm : ∀ y, Monotone (φ y)) + (hφL : ∀ y s t, s ≤ t → φ y t - φ y s ≤ L * (t - s)) (hf : 0 < f) (hθ : 0 < θ) + (hL : 0 ≤ L) (k : ℕ) {A O : Finset V} (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) + (hr0 : ∀ x, r 0 x = 1) (hr01 : ∀ j x, 0 ≤ r j x ∧ r j x ≤ 1) + (hrO : ∀ j x, j ≠ 0 → r j x ≠ 0 → x ∈ O) {θ₂ : ℝ} + (hcol : ∀ y, (∀ t, t - θ₂ * f ≤ φ y t) ∨ ((∀ j, r j y = 1) ∧ y ∈ O)) + (hτ₀ : θ₂ * f + f * Real.exp (1 / θ) * (L / θ) ^ k / k.factorial ≤ τ₀) + (hχ0 : ∀ t, 0 ≤ χ t) (hχ1 : ∀ t, χ t ≤ 1) (hχ₀ : ∀ t, t ≤ τ₀ → χ t = 0) + (hχ₁ : ∀ t, τ₁ ≤ t → χ t = 1) {q : ℝ} (hτ₁ : τ₁ ≤ f / q) + (hK : (k + 1) * f / (m + 1) ≤ f / q) (hO : m * #O ≤ #A) : + let D := C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C + (∀ a b, copyStage χ m r D a b ≤ f / q) ∧ + copyStage χ m r D * copyWeight r = copyWeight r * D ∧ + (∀ a b, copyStage χ m r D a b ≠ 0 → + a ∈ copyCover A O ∧ b ∈ copyCover A O) ∧ + #(copyCover (m := m) A O) ≤ 2 * #A := by + intro D + have hθf : 0 ≤ θ * f := by positivity + have hD0 : ∀ x y, 0 ≤ D x y := cutoffCorrection_residual_nonneg hC0 hφ0 hφθ hφm hθf k + have hbig : ∀ x y, τ₀ < D x y → (∀ j, r j y = 1) ∧ y ∈ O := fun x y h => by + rcases hcol y with hgood | hcopy + · have := cutoffCorrection_residual_le hC hC0 hCf hC1 hφ0 hφθ hφm hφL hf hθ hL hgood k x + exact absurd (this.trans hτ₀) (not_le.mpr h) + · exact hcopy + refine ⟨copyStage_le (fun j x => (hr01 j x).1) (fun j x => (hr01 j x).2) hD0 + (cutoffCorrection_residual_le_mul hC0 hφ0 hφθ hθf hCf hf.le hC1 k) hχ0 hχ1 hχ₁ hτ₁ hK, + copyStage_mul_copyWeight hr0 hχ₀ fun x y h => (hbig x y h).1, + copyStage_mem_copyCover (cutoffCorrection_residual_mem hφ0 hφθ hθf hA k) hrO hχ₀ + fun x y h => (hbig x y h).2, ?_⟩ + exact (card_copyCover_le A O).trans (by omega) + +end Rates + +/-! ### Iterating the stages -/ + +section Hierarchy + +variable {V : ℕ → Type*} [∀ l, Fintype (V l)] [∀ l, DecidableEq (V l)] + {C E : ∀ l, Matrix (V l) (V l) ℝ} {P : ∀ l, Matrix (V (l + 1)) (V l) ℝ} + +/-- **The stage bound from per-stage rates.** If the entries of `C 0` are at most one, each stage +divides the entry bound by `q = 2 ^ (c + 1)`, and each stage at most doubles a cover of the +support, then along primary copies `0 ≤ p (z 0) - W l (z l) ≤ n * (2 ^ c)⁻¹ ^ l`, where `n` +bounds the initial cover. `Matrix.copyStage_rates` provides the per-stage rates +[OpenAI2026LogSpace, Proposition 4.7]. -/ +theorem sub_rewardTransport_mulVec_le_of_rates (hP : ∀ l i j, 0 ≤ P l i j) + (hP1 : ∀ l, P l *ᵥ 1 ≤ 1) (hC : ∀ l i j, 0 ≤ C l i j) + (hstep : ∀ l, C (l + 1) * P l = P l * (C l - E l + E l * C l)) {p e : V 0 → ℝ} + (hp : (1 - C 0) *ᵥ p = e) (hp0 : 0 ≤ p) (hp1 : p ≤ 1) {z : ∀ l, V l} + (hz : ∀ l w, P l (z (l + 1)) w = if w = z l then 1 else 0) {c n : ℕ} + (hε0 : ∀ x y, C 0 x y ≤ 1) + (hεs : ∀ l, (∀ x y, C l x y ≤ ((2 : ℝ) ^ (c + 1))⁻¹ ^ l) → + ∀ x y, C (l + 1) x y ≤ ((2 : ℝ) ^ (c + 1))⁻¹ ^ (l + 1)) + (A : ∀ l, Finset (V l)) (hA : ∀ l x y, C l x y ≠ 0 → y ∈ A l) (hA0 : #(A 0) ≤ n) + (hAs : ∀ l, #(A (l + 1)) ≤ 2 * #(A l)) (l : ℕ) : + 0 ≤ p (z 0) - (rewardTransport P E l *ᵥ e) (z l) ∧ + p (z 0) - (rewardTransport P E l *ᵥ e) (z l) ≤ n * ((2 : ℝ) ^ c)⁻¹ ^ l := by + have hε : ∀ l x y, C l x y ≤ ((2 : ℝ) ^ (c + 1))⁻¹ ^ l := by + intro l + induction l with + | zero => simpa using hε0 + | succ l ih => exact hεs l ih + have hAn : ∀ l, #(A l) ≤ 2 ^ l * n := by + intro l + induction l with + | zero => simpa using hA0 + | succ l ih => rw [pow_succ]; linarith [hAs l] + exact sub_rewardTransport_mulVec_le_pow hP hP1 hC hstep hp hp0 hp1 hz hε A hA hAn l + +end Hierarchy + +end Matrix diff --git a/ComplexityTests/CopyStage.lean b/ComplexityTests/CopyStage.lean new file mode 100644 index 000000000..0b65b9f50 --- /dev/null +++ b/ComplexityTests/CopyStage.lean @@ -0,0 +1,137 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ +import Complexity.Foundations.LinearAlgebra.Matrix.CopyStage + +/-! +# Tests for one stage of the correction-and-copy hierarchy +-/ + +namespace ComplexityTests.CopyStage + +open Finset Matrix + +/-- A walk on three time layers: from `0` to `1` and from `1` to `2`, each with probability +`1 / 2`. Its entries are at most `f = 1 / 2`. -/ +private noncomputable def C : Matrix (Fin 3) (Fin 3) ℝ := !![0, 1 / 2, 0; 0, 0, 1 / 2; 0, 0, 0] + +/-- The hard cutoff `t ↦ max (t - θ f) 0` with `θ = 1 / 4`, `f = 1 / 2`. -/ +private noncomputable def φ : Fin 3 → ℝ → ℝ := fun _ t => max (t - 1 / 8) 0 + +private theorem hC : C.IsStrictUpperTriangular := by + intro i j h; fin_cases i <;> fin_cases j <;> simp_all [C] + +private theorem hC0 : ∀ x y, 0 ≤ C x y := by + intro x y; fin_cases x <;> fin_cases y <;> norm_num [C] + +private theorem hCf : ∀ x y, C x y ≤ 1 / 2 := by + intro x y; fin_cases x <;> fin_cases y <;> norm_num [C] + +private theorem hC1 : C *ᵥ 1 ≤ 1 := by + intro x; fin_cases x <;> norm_num [C, mulVec, dotProduct, Fin.sum_univ_three] + +private theorem hφ0 : ∀ y t, 0 ≤ φ y t := fun _ _ => le_max_right _ _ + +private theorem hφθ : ∀ y t, φ y t ≤ max (t - 1 / 4 * (1 / 2)) 0 := fun _ t => by + norm_num [φ] + +private theorem hφm : ∀ y, Monotone (φ y) := fun _ _ _ h => max_le_max (by linarith) le_rfl + +private theorem hφL : ∀ y s t, s ≤ t → φ y t - φ y s ≤ 1 * (t - s) := fun _ s t _ => by + simp only [φ, one_mul] + have := le_max_left (s - 1 / 8) 0 + have := le_max_right (s - 1 / 8) 0 + have : max (t - 1 / 8) 0 ≤ max (s - 1 / 8) 0 + (t - s) := max_le (by linarith) (by linarith) + linarith + +/-! ### Residual bounds -/ + +-- One iteration corrects each transition to `1 / 8`, so the row sums are at most one. +example (x : Fin 3) : ∑ y, cutoffCorrectionIter φ C 1 x y ≤ 1 := by + exact_mod_cast cutoffCorrectionIter_sum_le hC0 hφ0 hφθ (by norm_num) hC1 1 x + +example (k : ℕ) (x y : Fin 3) : + (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y ≤ (k + 1) * (1 / 2) := + cutoffCorrection_residual_le_mul hC0 hφ0 hφθ (by norm_num) hCf (by norm_num) hC1 k x y + +-- The residual of the first iterate dominates `θ / 2 = 1 / 8` times its unsigned terms. +example (x y : Fin 3) : + 1 / 4 / (2 * ((0 : ℕ) + 1)) * (C + cutoffCorrectionIter φ C 1 + + cutoffCorrectionIter φ C 1 * C) x y ≤ + (C - cutoffCorrectionIter φ C 1 + cutoffCorrectionIter φ C 1 * C) x y := + cutoffCorrection_residual_dominates hC0 hφ0 hφθ (by norm_num) hCf (by norm_num) hC1 hφm + (by norm_num) (by norm_num) 0 x y + +/-! ### Copy fractions -/ + +/-- A ramp from `0` at `t ≤ 0` to `1` at `t ≥ 1 / 4`. -/ +private noncomputable def χ (t : ℝ) : ℝ := min (max (4 * t) 0) 1 + +private theorem χ0 : ∀ t, 0 ≤ χ t := fun _ => le_min (le_max_right _ _) zero_le_one +private theorem χ1 : ∀ t, χ t ≤ 1 := fun _ => min_le_right _ _ +private theorem χ₀ : ∀ t, t ≤ 0 → χ t = 0 := fun t h => by + simp only [χ]; rw [max_eq_right (by linarith)]; norm_num +private theorem χ₁ : ∀ t, 1 / 4 ≤ t → χ t = 1 := fun t h => by + simp only [χ]; rw [max_eq_left (by linarith)]; exact min_eq_right (by linarith) + +-- A large entry is split evenly between two copies; a small one stays with the primary copy. +example : copyFraction χ 1 (1 / 2) 1 = 1 / 2 := by + rw [copyFraction_of_eq_one (χ₁ _ (by norm_num))]; norm_num + +example (j : Fin 2) : copyFraction χ 1 0 j = if j = 0 then 1 else 0 := + copyFraction_of_eq_zero (χ₀ 0 le_rfl) j + +/-! ### One stage + +Without correction (`k = 0`, so `D = C`) and with every vertex overloaded and both of its copies +active, the stage halves the entries `1 / 2` of `C` and at most doubles the support. -/ + +private def r : Fin 2 → Fin 3 → ℝ := fun _ _ => 1 + +-- The split entry from the primary copy of `0` to the second copy of `1` is `1 / 4`. +example : copyStage χ 1 r (C - cutoffCorrectionIter φ C 0 + cutoffCorrectionIter φ C 0 * C) + ((0 : Fin 3), (0 : Fin 2)) ((1 : Fin 3), (1 : Fin 2)) = 1 / 4 := by + simp only [copyStage, copySplit, of_apply, cutoffCorrectionIter, Function.iterate_zero, id, + sub_zero, Matrix.zero_mul, add_zero] + rw [copyFraction_of_eq_one (χ₁ _ (by norm_num [C]))] + norm_num [r, C] + +private theorem stage : + let D := C - cutoffCorrectionIter φ C 0 + cutoffCorrectionIter φ C 0 * C + (∀ a b, copyStage χ 1 r D a b ≤ 1 / 2 / 2) ∧ + copyStage χ 1 r D * copyWeight r = copyWeight r * D ∧ + (∀ a b, copyStage χ 1 r D a b ≠ 0 → a ∈ copyCover univ univ ∧ b ∈ copyCover univ univ) ∧ + #(copyCover (m := 1) (univ : Finset (Fin 3)) univ) ≤ 2 * #(univ : Finset (Fin 3)) := + copyStage_rates (m := 1) (q := 2) (L := 1) (θ := 1 / 4) hC hC0 hCf hC1 + hφ0 hφθ hφm hφL (by norm_num) (by norm_num) (by norm_num) 0 + (fun _ _ _ => ⟨mem_univ _, mem_univ _⟩) (fun _ => rfl) + (fun _ _ => by norm_num [r]) (fun _ _ _ _ => mem_univ _) + (θ₂ := -(Real.exp (1 / (1 / 4)) * (1 / (1 / 4)) ^ 0 / Nat.factorial 0)) + (fun _ => Or.inr ⟨fun _ => rfl, mem_univ _⟩) (τ₀ := 0) (le_of_eq (by ring)) χ0 χ1 χ₀ + (τ₁ := 1 / 4) χ₁ (by norm_num) (by norm_num) (by simp) + +-- Every entry of the stage is at most `f / q = 1 / 4`, and at most `6` copies are active. +example : ∀ a b, copyStage χ 1 r (C - cutoffCorrectionIter φ C 0 + + cutoffCorrectionIter φ C 0 * C) a b ≤ 1 / 2 / 2 := stage.1 + +example : #(copyCover (m := 1) (univ : Finset (Fin 3)) univ) ≤ 6 := stage.2.2.2 + +/-! ### Incidence counting -/ + +-- In the walk, both targets `1` and `2` have an entry `1 / 2 > 1 / 4`, so +-- `2 · 1 · (1 / 4) ≤ |rows| · 1` with the two nonzero rows `{0, 1}`. +example : + ((#({1, 2} : Finset (Fin 3)) * 1 : ℕ) : ℝ) * (1 / 4) ≤ #({0, 1} : Finset (Fin 3)) * 1 := by + have h := card_mul_le_of_incidences (k := 1) (fun _ => C) (fun _ => hC0) (fun _ => 1) + (fun _ x => by fin_cases x <;> norm_num [C, Fin.sum_univ_three]) {0, 1} + (fun _ x y hxy => by fin_cases x <;> fin_cases y <;> simp_all [C]) (δ := 1 / 4) + (by norm_num) {1, 2} (N := 1) (fun y hy => ⟨0, by + simp only [mem_insert, mem_singleton] at hy + rcases hy with rfl | rfl + · exact card_pos.mpr ⟨0, by norm_num [C]⟩ + · exact card_pos.mpr ⟨1, by norm_num [C]⟩⟩) + simpa using h + +end ComplexityTests.CopyStage From ed3268e11cabe302fe7a7ffe7263d38df994663a Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 00:10:43 +0000 Subject: [PATCH 08/18] feat(Foundations): copy stages preserve strict upper triangularity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add cutoffCorrectionIter_isStrictUpperTriangular, cutoffCorrection_residual_isStrictUpperTriangular and copyStage_isStrictUpperTriangular (for the lexicographic order on Lex (V × Fin (m + 1))), so a stage's output can feed the next stage. Correct two descriptions: the pilot inputs have bounded row sums, not necessarily at most one, and copyStage_mulVec_one_le preserves the row-sum bound, with nonnegativity from copyStage_nonneg. Co-Authored-By: Claude Opus 5.5 --- .../LinearAlgebra/Matrix/CopyStage.lean | 53 +++++++++++++++++-- ComplexityTests/CopyStage.lean | 17 ++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean index 4fd044ed2..f261da8d2 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean @@ -23,6 +23,14 @@ its support lies in a set at most twice as large as the support of `C` `Matrix.sub_rewardTransport_mulVec_le_pow`; `Matrix.sub_rewardTransport_mulVec_le_of_rates` iterates them. +Stages can be chained. If `C` is strictly upper triangular, so is the residual `D` +(`Matrix.cutoffCorrection_residual_isStrictUpperTriangular`), and the copy step is strictly upper +triangular for the lexicographic order on the copies `Lex (V × Fin (m + 1))`, which is linearly +ordered (`Matrix.copyStage_isStrictUpperTriangular`). Its rows sum to at most one +(`Matrix.copyStage_mulVec_one_le` with `Matrix.correction_mulVec_one_le`) and its entries are +nonnegative under the cutoff assumptions `0 ≤ χ ≤ 1` (`Matrix.copyStage_nonneg` with +`Matrix.cutoffCorrection_residual_nonneg`), so it satisfies the input hypotheses of the next stage. + The choice of which columns are corrected and which vertices get active copies comes from the preprint's *detectors*, which are probabilistic. Here it is an interface: copy weights `r` with `r 0 = 1`, and a finite set `O` of *overloaded* vertices, such that @@ -33,8 +41,9 @@ preprint's *detectors*, which are probabilistic. Here it is an interface: copy w * `m |O| ≤ |A|`, where `m + 1` is the number of copies and `A` covers the support of `C`. The last condition follows from incidence counting (`Matrix.card_mul_le_of_incidences`): if every -overloaded column has many large entries in one of a few substochastic matrices, as the detectors -guarantee for the pilot inputs, then there are few overloaded columns. +overloaded column has many large entries in one of a few matrices with the stated row-sum bounds, +as the detectors guarantee for the pilot inputs, then there are few overloaded columns. The pilot +inputs have bounded row sums, not necessarily at most one [OpenAI2026LogSpace, Lemma 4.2]. The corrected matrix also satisfies the remaining bounds of Lemma 4.4 of the preprint. Its entries are at most `(k + 1) f` (`Matrix.cutoffCorrection_residual_le_mul`). It dominates its unsigned @@ -58,6 +67,9 @@ which lets the three terms of `D` be estimated separately. Its support stays wit `Matrix.copyStage_le`, `Matrix.copyStage_mem_copyCover`, `Matrix.card_copyCover_le`: the copy step intertwines with its projection, is substochastic, has small entries and few active copies. +* `Matrix.cutoffCorrection_residual_isStrictUpperTriangular`, + `Matrix.copyStage_isStrictUpperTriangular`: a stage maps strictly upper triangular matrices to + strictly upper triangular ones, for the lexicographic order on the copies. * `Matrix.card_mul_le_of_incidences`: incidence counting. * `Matrix.copyStage_rates`: the one-stage density and active-count bounds. * `Matrix.sub_rewardTransport_mulVec_le_of_rates`: the stage bound from per-stage rates. @@ -248,6 +260,28 @@ theorem cutoffCorrection_residual_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ · rw [hCz, mul_zero] exact absurd ⟨(hE x z hEz).1, (hA z y hCz).2⟩ hxy +include hφ0 hφθ hθf in +/-- The iterates of the cutoff correction of a strictly upper triangular matrix are strictly upper +triangular. -/ +theorem cutoffCorrectionIter_isStrictUpperTriangular [Preorder V] + (hC : C.IsStrictUpperTriangular) (k : ℕ) : + (cutoffCorrectionIter φ C k).IsStrictUpperTriangular := by + induction k with + | zero => intro x y _; simp [cutoffCorrectionIter] + | succ k ih => + intro x y hxy + rw [cutoffCorrectionIter_succ] + change φ y ((C + cutoffCorrectionIter φ C k * C) x y) = 0 + rw [(hC.add (ih.mul hC)) hxy, cutoff_zero hφ0 hφθ hθf] + +include hφ0 hφθ hθf in +/-- **The residual of a strictly upper triangular matrix is strictly upper triangular.** -/ +theorem cutoffCorrection_residual_isStrictUpperTriangular [Preorder V] + (hC : C.IsStrictUpperTriangular) (k : ℕ) : + (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C).IsStrictUpperTriangular := + have hE := cutoffCorrectionIter_isStrictUpperTriangular hφ0 hφθ hθf hC k + (hC.sub hE).add (hE.mul hC) + end Residual /-! ### Copy fractions -/ @@ -317,6 +351,16 @@ copies of the overloaded vertices `O`. -/ @[expose] def copyCover [DecidableEq V] (A O : Finset V) : Finset (V × Fin (m + 1)) := A ×ˢ {0} ∪ O ×ˢ univ.erase 0 +/-- **The copy step stays strictly upper triangular** for the lexicographic order on the copies: +`(x, i)` comes before `(y, j)` when `x < y`, or `x = y` and `i < j`. Indexed by +`Lex (V × Fin (m + 1))`, which is linearly ordered when `V` is, the copy step can be the input of +the next stage. -/ +theorem copyStage_isStrictUpperTriangular [Preorder V] (hD : D.IsStrictUpperTriangular) : + ((copyStage χ m r D).submatrix ofLex ofLex).IsStrictUpperTriangular := by + intro a b hab + simp only [submatrix_apply, copyStage, copySplit, of_apply] + rw [hD fun h => hab (Prod.Lex.lt_iff.2 (Or.inl h)), mul_zero, zero_mul] + theorem card_copyCover_le [DecidableEq V] (A O : Finset V) : #(copyCover (m := m) A O) ≤ #A + m * #O := by refine (card_union_le _ _).trans ?_ @@ -341,7 +385,10 @@ theorem copyStage_nonneg (hr : ∀ j x, 0 ≤ r j x) (hD : ∀ x y, 0 ≤ D x y) 0 ≤ copyStage χ m r D a b := copySplit_nonneg hr (fun _ _ j => copyFraction_nonneg (hχ0 _) (hχ1 _) j) hD a b -/-- The copy step is substochastic when `D` is and the weights lie in `[0, 1]`. -/ +/-- **The copy step preserves the row-sum upper bound**: its rows sum to at most one when `D` is +nonnegative with rows summing to at most one and the weights lie in `[0, 1]`. Substochasticity +also needs nonnegative entries, which `Matrix.copyStage_nonneg` gives under the additional +cutoff assumptions `0 ≤ χ ≤ 1`. -/ theorem copyStage_mulVec_one_le [Fintype V] (hr0 : ∀ j x, 0 ≤ r j x) (hr1 : ∀ j x, r j x ≤ 1) (hD0 : ∀ x y, 0 ≤ D x y) (hD1 : D *ᵥ 1 ≤ 1) : copyStage χ m r D *ᵥ 1 ≤ 1 := copySplit_mulVec_one_le hr0 hr1 (fun x y => (sum_copyFraction χ m (D x y)).le) hD0 hD1 diff --git a/ComplexityTests/CopyStage.lean b/ComplexityTests/CopyStage.lean index 0b65b9f50..fd97008fd 100644 --- a/ComplexityTests/CopyStage.lean +++ b/ComplexityTests/CopyStage.lean @@ -118,6 +118,23 @@ example : ∀ a b, copyStage χ 1 r (C - cutoffCorrectionIter φ C 0 + example : #(copyCover (m := 1) (univ : Finset (Fin 3)) univ) ≤ 6 := stage.2.2.2 +/-! ### Chaining stages -/ + +-- The stage output, indexed by the lexicographically ordered copies, is again strictly upper +-- triangular, so it can be the input `C` of the next stage. +example : ((copyStage χ 1 r (C - cutoffCorrectionIter φ C 0 + + cutoffCorrectionIter φ C 0 * C)).submatrix ofLex ofLex).IsStrictUpperTriangular := + copyStage_isStrictUpperTriangular + (cutoffCorrection_residual_isStrictUpperTriangular hφ0 hφθ (by norm_num) hC 0) + +-- Concretely, the copy `(1, 1)` of the middle vertex comes after both copies of vertex `0`, so +-- the entries from it back to them vanish. +example (i : Fin 2) : (copyStage χ 1 r (C - cutoffCorrectionIter φ C 0 + + cutoffCorrectionIter φ C 0 * C)) (1, 1) (0, i) = 0 := + copyStage_isStrictUpperTriangular (V := Fin 3) + (cutoffCorrection_residual_isStrictUpperTriangular hφ0 hφθ (by norm_num) hC 0) + (i := toLex (1, 1)) (j := toLex (0, i)) (by simp [Prod.Lex.lt_iff]) + /-! ### Incidence counting -/ -- In the walk, both targets `1` and `2` have an entry `1 / 2 > 1 / 4`, so From 35dd78f4d9eed6f507e19309c4af8cebc5c791e7 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 00:20:21 +0000 Subject: [PATCH 09/18] refactor(Foundations): general copySplit_isStrictUpperTriangular beside copySplit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit State the preservation lemma for arbitrary weights and proportions in CorrectionHierarchy.lean, for the lexicographic order on Lex (V × ι), and derive copyStage_isStrictUpperTriangular from it. Co-Authored-By: Claude Opus 5.5 --- .../LinearAlgebra/Matrix/CopyStage.lean | 10 ++++------ .../LinearAlgebra/Matrix/CorrectionHierarchy.lean | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean index f261da8d2..aaad7308f 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean @@ -354,12 +354,10 @@ copies of the overloaded vertices `O`. -/ /-- **The copy step stays strictly upper triangular** for the lexicographic order on the copies: `(x, i)` comes before `(y, j)` when `x < y`, or `x = y` and `i < j`. Indexed by `Lex (V × Fin (m + 1))`, which is linearly ordered when `V` is, the copy step can be the input of -the next stage. -/ -theorem copyStage_isStrictUpperTriangular [Preorder V] (hD : D.IsStrictUpperTriangular) : - ((copyStage χ m r D).submatrix ofLex ofLex).IsStrictUpperTriangular := by - intro a b hab - simp only [submatrix_apply, copyStage, copySplit, of_apply] - rw [hD fun h => hab (Prod.Lex.lt_iff.2 (Or.inl h)), mul_zero, zero_mul] +the next stage (`Matrix.copySplit_isStrictUpperTriangular`). -/ +theorem copyStage_isStrictUpperTriangular [LT V] (hD : D.IsStrictUpperTriangular) : + ((copyStage χ m r D).submatrix ofLex ofLex).IsStrictUpperTriangular := + copySplit_isStrictUpperTriangular hD theorem card_copyCover_le [DecidableEq V] (A O : Finset V) : #(copyCover (m := m) A O) ≤ #A + m * #O := by diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean index 2420fb961..07f8e44b7 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean @@ -67,6 +67,8 @@ the copies (factorial truncation, detectors) are not part of this file. `E`. * `Matrix.correction_mulVec_one_le`: nonnegative corrections do not increase row sums. * `Matrix.copySplit_mul_copyWeight`: a copy step intertwines with its projection. +* `Matrix.copySplit_isStrictUpperTriangular`: a copy step stays strictly upper triangular for the + lexicographic order on the copies. * `Matrix.mul_copyProjection`, `Matrix.rewardTransport_mulVec`: the reward transport identity. * `Matrix.rewardTransport_mulVec_nonneg`, `Matrix.rewardTransport_mulVec_le`: the stage rewards lie between `0` and the projected solution. @@ -258,6 +260,18 @@ theorem copySplit_nonneg [Semiring R] [PartialOrder R] [IsOrderedRing R] {r : ι 0 ≤ copySplit r s D a b := mul_nonneg (mul_nonneg (hr _ _) (hD _ _)) (hs _ _ _) +/-- **Copies stay strictly upper triangular** for the lexicographic order on the copies: `(x, i)` +comes before `(y, j)` when `x < y`, or `x = y` and `i < j`. Indexed by `Lex (V × ι)`, which is +linearly ordered when `V` and `ι` are, a copy step of a strictly upper triangular matrix can be +corrected and copied again. Only the order of the parents matters: an entry from `(x, i)` to +`(y, j)` vanishes unless `x < y`. -/ +theorem copySplit_isStrictUpperTriangular [LT V] [LT ι] [MulZeroClass R] {r : ι → V → R} + {s : V → V → ι → R} {D : Matrix V V R} (hD : D.IsStrictUpperTriangular) : + ((copySplit r s D).submatrix ofLex ofLex).IsStrictUpperTriangular := by + intro a b hab + simp only [submatrix_apply, copySplit, of_apply] + rw [hD fun h => hab (Prod.Lex.lt_iff.2 (Or.inl h)), mul_zero, zero_mul] + /-- **Copies keep row sums at most one** when the weights lie in `[0, 1]`, `D` is nonnegative with row sums at most one, and the proportions of each entry sum to at most one. Together with `Matrix.copySplit_nonneg` this makes the copy step substochastic. -/ From f1303d90f2b557e87bcb16959dc2ba517631af8e Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 01:08:54 +0000 Subject: [PATCH 10/18] feat(Foundations): pilot with step-dependent multipliers and probabilistic column detectors Phase 2 slice 4 of #1444 (tracked in #1679): the pilot of Lemma 4.2 with step-dependent multipliers, the column detector of Lemma 4.3 over an abstract retention-channel interface, and one stage of the hierarchy whose multipliers, copy weights and overloaded set come from the detector, discharging the detector interface of copyStage_rates. Co-Authored-By: Claude Opus 5.5 --- Complexity.lean | 4 + .../Foundations/Data/Finset/KthLargest.lean | 116 +++++ .../LinearAlgebra/Matrix/PilotCorrection.lean | 331 ++++++++++++ .../Probability/ColumnDetector.lean | 469 ++++++++++++++++++ .../Probability/DetectedStage.lean | 295 +++++++++++ ComplexityTests/Detectors.lean | 215 ++++++++ ComplexityTests/KthLargest.lean | 53 ++ 7 files changed, 1483 insertions(+) create mode 100644 Complexity/Foundations/Data/Finset/KthLargest.lean create mode 100644 Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean create mode 100644 Complexity/Foundations/Probability/ColumnDetector.lean create mode 100644 Complexity/Foundations/Probability/DetectedStage.lean create mode 100644 ComplexityTests/Detectors.lean create mode 100644 ComplexityTests/KthLargest.lean diff --git a/Complexity.lean b/Complexity.lean index 2a5c4feb0..28144e01a 100644 --- a/Complexity.lean +++ b/Complexity.lean @@ -2497,6 +2497,7 @@ public import Complexity.Foundations.Data.Fin.Tuple public import Complexity.Foundations.Data.Finset.Average public import Complexity.Foundations.Data.Finset.Expect public import Complexity.Foundations.Data.Finset.Finpartition +public import Complexity.Foundations.Data.Finset.KthLargest public import Complexity.Foundations.Data.Finset.Markov public import Complexity.Foundations.Data.Finset.OrderGlue public import Complexity.Foundations.Data.Finset.OrderedFilter @@ -2628,6 +2629,7 @@ public import Complexity.Foundations.LinearAlgebra.Matrix.Kronecker public import Complexity.Foundations.LinearAlgebra.Matrix.Lindsey public import Complexity.Foundations.LinearAlgebra.Matrix.ListProd public import Complexity.Foundations.LinearAlgebra.Matrix.Moore +public import Complexity.Foundations.LinearAlgebra.Matrix.PilotCorrection public import Complexity.Foundations.LinearAlgebra.Matrix.Rank public import Complexity.Foundations.LinearAlgebra.Matrix.RectPermanent public import Complexity.Foundations.LinearAlgebra.Matrix.SchurComplement @@ -2650,6 +2652,8 @@ public import Complexity.Foundations.NumberTheory.SqrtPrimeWindow public import Complexity.Foundations.Order.BooleanSubalgebra public import Complexity.Foundations.Order.Changes public import Complexity.Foundations.Order.UpperLower +public import Complexity.Foundations.Probability.ColumnDetector +public import Complexity.Foundations.Probability.DetectedStage public import Complexity.Foundations.Probability.Gaussian.Multivariate public import Complexity.Foundations.Probability.Gaussian.Real public import Complexity.Foundations.Probability.Gaussian.Sheppard diff --git a/Complexity/Foundations/Data/Finset/KthLargest.lean b/Complexity/Foundations/Data/Finset/KthLargest.lean new file mode 100644 index 000000000..b1198aef3 --- /dev/null +++ b/Complexity/Foundations/Data/Finset/KthLargest.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Init +public import Mathlib.Data.Finset.Max + +/-! +# The `k`-th largest value, padded with zeros + +`Finset.kthLargest k s h` is the `k`-th largest member of the multiset of values `h x`, `x ∈ s`, +padded with infinitely many zeros. It is the largest value `h x` that is reached or exceeded by at +least `k` of the values, or `0` if that is larger. So it is nonnegative, and it is `0` when fewer +than `k` of the values are positive. This is the order statistic `rank_k` of the detectors in the +OpenAI preprint [OpenAI2026LogSpace, Section 4.2]. + +It is characterized by threshold counts: for `0 < k` and `0 ≤ t`, the `k`-th largest value exceeds +`t` exactly when at least `k` values exceed `t` (`Finset.lt_kthLargest_iff`), and for `0 < t` it +is at least `t` exactly when at least `k` values are at least `t` (`Finset.le_kthLargest_iff`). + +## Main definitions + +* `Finset.kthLargest`: the `k`-th largest value, padded with zeros. + +## Main results + +* `Finset.kthLargest_nonneg`, `Finset.kthLargest_le`: bounds. +* `Finset.lt_kthLargest_iff`, `Finset.le_kthLargest_iff`: the threshold characterizations. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Section 4.2 (preprint, not peer reviewed) +-/ + +public section + +namespace Finset + +variable {α R : Type*} [LinearOrder R] [Zero R] + +/-- The **`k`-th largest value** of `h` on `s`, padded with zeros: the largest value `h x`, +`x ∈ s`, that at least `k` values `h w`, `w ∈ s`, reach or exceed, or `0` if that is larger. -/ +@[expose] def kthLargest (k : ℕ) (s : Finset α) (h : α → R) : R := + (insert 0 ((s.filter fun x => k ≤ #{w ∈ s | h x ≤ h w}).image h)).max' (insert_nonempty _ _) + +variable {k : ℕ} {s : Finset α} {h : α → R} {t : R} + +theorem kthLargest_nonneg : 0 ≤ kthLargest k s h := + le_max' _ _ (mem_insert_self _ _) + +/-- The `k`-th largest value is at most any nonnegative upper bound of the values. -/ +theorem kthLargest_le (ht : 0 ≤ t) (hh : ∀ x ∈ s, h x ≤ t) : kthLargest k s h ≤ t := by + refine max'_le _ _ _ fun a ha => ?_ + rcases mem_insert.mp ha with rfl | ha + · exact ht + · obtain ⟨x, hx, rfl⟩ := mem_image.mp ha + exact hh x (mem_filter.mp hx).1 + +/-- A value of `s` reached or exceeded by at least `k` values is at most the `k`-th largest. -/ +private theorem le_kthLargest_of_le_card {x : α} (hx : x ∈ s) + (hk : k ≤ #{w ∈ s | h x ≤ h w}) : h x ≤ kthLargest k s h := + le_max' _ _ (mem_insert_of_mem (mem_image_of_mem h (mem_filter.mpr ⟨hx, hk⟩))) + +omit [Zero R] in +/-- If at least `k > 0` values satisfy a threshold condition, so does the smallest of them, which +is reached or exceeded by all of them. -/ +private theorem exists_le_card (hk : 0 < k) (p : R → Prop) [DecidablePred p] + (hp : k ≤ #{x ∈ s | p (h x)}) : + ∃ x ∈ s, p (h x) ∧ k ≤ #{w ∈ s | h x ≤ h w} := by + have hne : ({x ∈ s | p (h x)} : Finset α).Nonempty := card_pos.mp (hk.trans_le hp) + obtain ⟨x, hx, hmin⟩ := exists_min_image _ h hne + obtain ⟨hxs, hpx⟩ := mem_filter.mp hx + refine ⟨x, hxs, hpx, hp.trans (card_le_card fun w hw => ?_)⟩ + exact mem_filter.mpr ⟨(mem_filter.mp hw).1, hmin w hw⟩ + +/-- **The `k`-th largest value exceeds `t ≥ 0`** exactly when at least `k > 0` values do. -/ +theorem lt_kthLargest_iff (hk : 0 < k) (ht : 0 ≤ t) : + t < kthLargest k s h ↔ k ≤ #{x ∈ s | t < h x} := by + constructor + · intro hlt + obtain ⟨a, ha, hta⟩ : ∃ a ∈ _, t < a := ⟨_, max'_mem _ _, hlt⟩ + rcases mem_insert.mp ha with rfl | ha + · exact absurd ht (not_le.mpr hta) + obtain ⟨x, hx, rfl⟩ := mem_image.mp ha + obtain ⟨-, hkx⟩ := mem_filter.mp hx + exact hkx.trans (card_le_card fun w hw => by + obtain ⟨hws, hxw⟩ := mem_filter.mp hw + exact mem_filter.mpr ⟨hws, hta.trans_le hxw⟩) + · intro hcard + obtain ⟨x, hxs, htx, hkx⟩ := exists_le_card hk (t < ·) hcard + exact htx.trans_le (le_kthLargest_of_le_card hxs hkx) + +/-- **The `k`-th largest value is at least `t > 0`** exactly when at least `k > 0` values are. -/ +theorem le_kthLargest_iff (hk : 0 < k) (ht : 0 < t) : + t ≤ kthLargest k s h ↔ k ≤ #{x ∈ s | t ≤ h x} := by + constructor + · intro hle + obtain ⟨a, ha, hta⟩ : ∃ a ∈ _, t ≤ a := ⟨_, max'_mem _ _, hle⟩ + rcases mem_insert.mp ha with rfl | ha + · exact absurd ht (not_lt.mpr hta) + obtain ⟨x, hx, rfl⟩ := mem_image.mp ha + obtain ⟨-, hkx⟩ := mem_filter.mp hx + exact hkx.trans (card_le_card fun w hw => by + obtain ⟨hws, hxw⟩ := mem_filter.mp hw + exact mem_filter.mpr ⟨hws, hta.trans hxw⟩) + · intro hcard + obtain ⟨x, hxs, htx, hkx⟩ := exists_le_card hk (t ≤ ·) hcard + exact htx.trans (le_kthLargest_of_le_card hxs hkx) + +end Finset diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean b/Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean new file mode 100644 index 000000000..a6aa6efe3 --- /dev/null +++ b/Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean @@ -0,0 +1,331 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Foundations.LinearAlgebra.Matrix.FactorialTruncation + +/-! +# The pilot correction with step-dependent multipliers + +In the correction-and-copy hierarchy of the OpenAI preprint (2026-09-23), Section 4.2, idea 3 in +issue #474 [OpenAI2026LogSpace], the column multiplier of the cutoff correction is chosen by a +*pilot*: a run of the correction recursion in which the multiplier may decrease from step to +step. At step `i + 1` the pilot forms its input `G = C + Ê_i C`, evaluates a column number +`U G y` on it (in the preprint a detector, see `Complexity.Foundations.Probability.ColumnDetector`), +takes the running maximum `M_(i+1) = M_i ⊔ U G`, and sets +`Ê_(i+1) x y = c (G x y) * γ (M_(i+1) y)` for a base cutoff `c` and a nonincreasing `γ` +(`Matrix.pilotCorrection`, `Matrix.pilotMax`, `Matrix.pilotInput`). The actual correction then +runs the fixed-multiplier recursion `Matrix.cutoffCorrectionIter` with the final multiplier +`γ (M_k y)`. + +All bounds of [OpenAI2026LogSpace, Lemma 4.2] hold for any sequence of corrections that starts at +zero and stays between zero and its input, `0 ≤ F (i + 1) ≤ C + F i C` +(`Matrix.IsCorrectionSeq`). Both the pilot (`Matrix.isCorrectionSeq_pilotCorrection`) and the +fixed-multiplier recursion (`Matrix.isCorrectionSeq_cutoffCorrectionIter`) are of this form. For +a substochastic `C` with entries at most `f`, the `i`-th correction and the input of step `i + 1` +have row sums at most `i` and `i + 1` and entries at most `i f` and `(i + 1) f`; they are +supported within any cover of the support of `C`, and strictly upper triangular when `C` is. +Since the running maximum only grows and `γ` is nonincreasing, the actual correction and its inputs +are bounded by those of the pilot (`Matrix.cutoffCorrectionIter_le_pilotCorrection`). + +## Main definitions + +* `Matrix.IsCorrectionSeq`: corrections starting at zero and dominated by their inputs. +* `Matrix.pilotCorrection`, `Matrix.pilotMax`, `Matrix.pilotInput`: the pilot. + +## Main results + +* `Matrix.IsCorrectionSeq.sum_le`, `Matrix.IsCorrectionSeq.sum_input_le`, + `Matrix.IsCorrectionSeq.le_mul`, `Matrix.IsCorrectionSeq.input_le_mul`: row-sum and entry + bounds. +* `Matrix.IsCorrectionSeq.mem`, `Matrix.IsCorrectionSeq.input_mem`: supports. +* `Matrix.IsCorrectionSeq.isStrictUpperTriangular`, + `Matrix.IsCorrectionSeq.input_isStrictUpperTriangular`: strict forwardness. +* `Matrix.isCorrectionSeq_cutoffCorrectionIter`, `Matrix.isCorrectionSeq_pilotCorrection`: the + actual correction and the pilot are correction sequences. +* `Matrix.cutoffCorrectionIter_le_of_isCorrectionSeq`: comparison with a dominating sequence. +* `Matrix.pilotMax_mono`, `Matrix.exists_lt_pilotInput_of_lt_pilotMax`: the running maximum. +* `Matrix.cutoffCorrectionIter_le_pilotCorrection`: the actual correction is at most the pilot. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Section 4.2 and Lemma 4.2 (preprint, not peer reviewed) +-/ + +public section + +open Finset + +namespace Matrix + +variable {V : Type*} [Fintype V] {F : ℕ → Matrix V V ℝ} {f : ℝ} + +/-- `F` is a **correction sequence** for `C`: it starts at zero, and each correction lies between +zero and its input, `0 ≤ F (i + 1) ≤ C + F i * C` entrywise. The pilot of the preprint, with +step-dependent multipliers, and the actual correction, with a fixed multiplier, are both of this +form [OpenAI2026LogSpace, Lemma 4.2]. -/ +structure IsCorrectionSeq (C : Matrix V V ℝ) (F : ℕ → Matrix V V ℝ) : Prop where + zero : F 0 = 0 + nonneg_succ : ∀ i x y, 0 ≤ F (i + 1) x y + le_input : ∀ i x y, F (i + 1) x y ≤ (C + F i * C) x y + +section Sequence + +variable {C : Matrix V V ℝ} + +namespace IsCorrectionSeq + +variable (hF : IsCorrectionSeq C F) +include hF + +theorem nonneg (i : ℕ) (x y : V) : 0 ≤ F i x y := by + cases i with + | zero => simp [hF.zero] + | succ i => exact hF.nonneg_succ i x y + +theorem input_nonneg (hC0 : ∀ x y, 0 ≤ C x y) (i : ℕ) (x y : V) : 0 ≤ (C + F i * C) x y := + add_nonneg (hC0 x y) (sum_nonneg fun z _ => mul_nonneg (hF.nonneg i x z) (hC0 z y)) + +/-- **Row sums of the corrections**: the `i`-th correction of a substochastic `C` has row sums at +most `i`, and the input of step `i + 1` at most `i + 1` [OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem sum_input_le (hC1 : C *ᵥ 1 ≤ 1) : + ∀ i x, ∑ y, (C + F i * C) x y ≤ i + 1 ∧ ∑ y, F i x y ≤ i := by + have hrow : ∀ z, ∑ y, C z y ≤ 1 := fun z => by simpa [mulVec, dotProduct] using hC1 z + have hinput : ∀ i x, ∑ y, F i x y ≤ i → ∑ y, (C + F i * C) x y ≤ i + 1 := fun i x hi => by + calc ∑ y, (C + F i * C) x y = ∑ y, C x y + ∑ z, F i x z * ∑ y, C z y := by + simp only [add_apply, mul_apply, sum_add_distrib, mul_sum] + rw [sum_comm] + _ ≤ 1 + ∑ z, F i x z * 1 := add_le_add (hrow x) (sum_le_sum fun z _ => + mul_le_mul_of_nonneg_left (hrow z) (hF.nonneg i x z)) + _ ≤ i + 1 := by simp only [mul_one]; linarith + intro i + induction i with + | zero => intro x; simpa [hF.zero] using hinput 0 x (by simp [hF.zero]) + | succ i ih => + intro x + have hsum : ∑ y, F (i + 1) x y ≤ (i + 1 : ℕ) := by + push_cast + exact (sum_le_sum fun y _ => hF.le_input i x y).trans (ih x).1 + exact ⟨hinput _ x hsum, hsum⟩ + +theorem sum_le (hC1 : C *ᵥ 1 ≤ 1) (i : ℕ) (x : V) : ∑ y, F i x y ≤ i := + (hF.sum_input_le hC1 i x).2 + +/-- **Entries of the inputs**: the input of step `i + 1` has entries at most `(i + 1) f` +[OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem input_le_mul (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) (hC1 : C *ᵥ 1 ≤ 1) (i : ℕ) + (x y : V) : (C + F i * C) x y ≤ (i + 1) * f := by + have hsum := hF.sum_le hC1 i x + calc (C + F i * C) x y = C x y + ∑ z, F i x z * C z y := rfl + _ ≤ f + ∑ z, F i x z * f := add_le_add (hCf x y) + (sum_le_sum fun z _ => mul_le_mul_of_nonneg_left (hCf z y) (hF.nonneg i x z)) + _ ≤ (i + 1) * f := by rw [← sum_mul]; nlinarith + +/-- **Entries of the corrections**: the `i`-th correction has entries at most `i f` +[OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem le_mul (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) (hC1 : C *ᵥ 1 ≤ 1) (i : ℕ) (x y : V) : + F i x y ≤ i * f := by + cases i with + | zero => simp [hF.zero] + | succ i => + push_cast + exact (hF.le_input i x y).trans (hF.input_le_mul hCf hf hC1 i x y) + +variable {A : Finset V} + +/-- The corrections and the inputs are supported within any set `A` covering the support of `C` +[OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem input_mem_and_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) : + ∀ i x y, ((C + F i * C) x y ≠ 0 → x ∈ A ∧ y ∈ A) ∧ (F i x y ≠ 0 → x ∈ A ∧ y ∈ A) := by + have hinput : ∀ i, (∀ x y, F i x y ≠ 0 → x ∈ A ∧ y ∈ A) → + ∀ x y, (C + F i * C) x y ≠ 0 → x ∈ A ∧ y ∈ A := fun i hi x y h => by + by_contra hxy + apply h + have hCxy : C x y = 0 := by by_contra h'; exact hxy (hA x y h') + simp only [add_apply, mul_apply, hCxy, zero_add] + refine sum_eq_zero fun z _ => ?_ + by_cases hE : F i x z = 0 + · rw [hE, zero_mul] + by_cases hCz : C z y = 0 + · rw [hCz, mul_zero] + exact absurd ⟨(hi x z hE).1, (hA z y hCz).2⟩ hxy + intro i + induction i with + | zero => + have h0 : ∀ x y, F 0 x y ≠ 0 → x ∈ A ∧ y ∈ A := fun x y h => by simp [hF.zero] at h + exact fun x y => ⟨hinput 0 h0 x y, h0 x y⟩ + | succ i ih => + have hi : ∀ x y, F (i + 1) x y ≠ 0 → x ∈ A ∧ y ∈ A := fun x y h => + (ih x y).1 fun h' => h (le_antisymm (h' ▸ hF.le_input i x y) (hF.nonneg_succ i x y)) + exact fun x y => ⟨hinput _ hi x y, hi x y⟩ + +theorem mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) (i : ℕ) (x y : V) (h : F i x y ≠ 0) : + x ∈ A ∧ y ∈ A := + (hF.input_mem_and_mem hA i x y).2 h + +theorem input_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) (i : ℕ) (x y : V) + (h : (C + F i * C) x y ≠ 0) : x ∈ A ∧ y ∈ A := + (hF.input_mem_and_mem hA i x y).1 h + +/-- The corrections of a strictly upper triangular `C` are strictly upper triangular +[OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem isStrictUpperTriangular [Preorder V] (hC : C.IsStrictUpperTriangular) (i : ℕ) : + (F i).IsStrictUpperTriangular := by + induction i with + | zero => intro x y _; simp [hF.zero] + | succ i ih => + intro x y hxy + have h := hF.le_input i x y + rw [(hC.add (ih.mul hC)) hxy] at h + exact le_antisymm h (hF.nonneg_succ i x y) + +theorem input_isStrictUpperTriangular [Preorder V] (hC : C.IsStrictUpperTriangular) (i : ℕ) : + (C + F i * C).IsStrictUpperTriangular := + hC.add ((hF.isStrictUpperTriangular hC i).mul hC) + +end IsCorrectionSeq + +/-- The fixed-multiplier recursion `Matrix.cutoffCorrectionIter` is a correction sequence when +the cutoffs satisfy `0 ≤ φ y t ≤ max (t - θ f) 0` with `0 ≤ θ f`. -/ +theorem isCorrectionSeq_cutoffCorrectionIter {φ : V → ℝ → ℝ} {θ : ℝ} (hC0 : ∀ x y, 0 ≤ C x y) + (hφ0 : ∀ y t, 0 ≤ φ y t) (hφθ : ∀ y t, φ y t ≤ max (t - θ * f) 0) (hθf : 0 ≤ θ * f) : + IsCorrectionSeq C (cutoffCorrectionIter φ C) where + zero := rfl + nonneg_succ i x y := cutoffCorrectionIter_nonneg hφ0 (i + 1) x y + le_input i x y := by + rw [cutoffCorrectionIter_succ] + refine (hφθ y _).trans (max_le (by linarith) ?_) + exact add_nonneg (hC0 x y) (sum_nonneg fun z _ => + mul_nonneg (cutoffCorrectionIter_nonneg hφ0 i x z) (hC0 z y)) + +/-- **Comparison with a dominating sequence**: if the cutoffs `φ y` are monotone and the first +`k` steps of `F` dominate the cutoffs of their own inputs, then the first `k` iterates of the +fixed-multiplier recursion, and their inputs, are at most those of `F` +[OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem cutoffCorrectionIter_le_of_isCorrectionSeq {φ : V → ℝ → ℝ} (hC0 : ∀ x y, 0 ≤ C x y) + (hφm : ∀ y, Monotone (φ y)) {k : ℕ} + (hφF : ∀ i < k, ∀ x y, φ y ((C + F i * C) x y) ≤ F (i + 1) x y) (hF : IsCorrectionSeq C F) : + ∀ i ≤ k, ∀ x y, cutoffCorrectionIter φ C i x y ≤ F i x y ∧ + (C + cutoffCorrectionIter φ C i * C) x y ≤ (C + F i * C) x y := by + have hinput : ∀ i, (∀ x y, cutoffCorrectionIter φ C i x y ≤ F i x y) → + ∀ x y, (C + cutoffCorrectionIter φ C i * C) x y ≤ (C + F i * C) x y := + fun i hi x y => add_le_add_right (sum_le_sum fun z _ => + mul_le_mul_of_nonneg_right (hi x z) (hC0 z y)) _ + intro i + induction i with + | zero => + have h0 : ∀ x y, cutoffCorrectionIter φ C 0 x y ≤ F 0 x y := fun x y => by + simp [cutoffCorrectionIter, hF.zero] + exact fun _ x y => ⟨h0 x y, hinput 0 h0 x y⟩ + | succ i ih => + intro hik + have hi : ∀ x y, cutoffCorrectionIter φ C (i + 1) x y ≤ F (i + 1) x y := fun x y => by + rw [cutoffCorrectionIter_succ] + exact (hφm y ((ih (by omega) x y).2)).trans (hφF i (by omega) x y) + exact fun x y => ⟨hi x y, hinput _ hi x y⟩ + +end Sequence + +/-! ### The pilot -/ + +section Pilot + +variable (c γ : ℝ → ℝ) (U : Matrix V V ℝ → V → ℝ) (C : Matrix V V ℝ) + +/-- The **pilot** as a pair of the current correction and the running maximum of the column +numbers. Step `i + 1` forms the input `G = C + Ê_i C`, updates the running maximum to +`M_(i+1) = M_i ⊔ U G`, and sets `Ê_(i+1) x y = c (G x y) * γ (M_(i+1) y)` +[OpenAI2026LogSpace, (4.10)–(4.13)]. -/ +noncomputable def pilot : ℕ → Matrix V V ℝ × (V → ℝ) + | 0 => (0, 0) + | i + 1 => + let G := C + (pilot i).1 * C + let M := (pilot i).2 ⊔ U G + (of fun x y => c (G x y) * γ (M y), M) + +/-- The `i`-th pilot correction `Ê_i`. -/ +noncomputable def pilotCorrection (i : ℕ) : Matrix V V ℝ := (pilot c γ U C i).1 + +/-- The input `G = C + Ê_i C` of pilot step `i + 1`; the preprint's `G_(i+1)`. -/ +@[expose] noncomputable def pilotInput (i : ℕ) : Matrix V V ℝ := C + pilotCorrection c γ U C i * C + +/-- The running maximum `M_i = max (0, U G_1, …, U G_i)` of the column numbers after `i` pilot +steps. The pilot multiplier of step `i` is `γ (M_i y)`. -/ +noncomputable def pilotMax (i : ℕ) : V → ℝ := (pilot c γ U C i).2 + +variable {c γ U C} + +@[simp] theorem pilotCorrection_zero : pilotCorrection c γ U C 0 = 0 := by rfl + +@[simp] theorem pilotMax_zero : pilotMax c γ U C 0 = 0 := by rfl + +theorem pilotMax_succ (i : ℕ) : + pilotMax c γ U C (i + 1) = pilotMax c γ U C i ⊔ U (pilotInput c γ U C i) := by rfl + +theorem pilotCorrection_succ_apply (i : ℕ) (x y : V) : + pilotCorrection c γ U C (i + 1) x y = + c (pilotInput c γ U C i x y) * γ (pilotMax c γ U C (i + 1) y) := by rfl + +/-- The running maximum grows. -/ +theorem pilotMax_mono {i j : ℕ} (hij : i ≤ j) (y : V) : + pilotMax c γ U C i y ≤ pilotMax c γ U C j y := by + induction hij with + | refl => exact le_rfl + | step _ ih => exact ih.trans (by rw [pilotMax_succ]; exact le_sup_left) + +/-- If the running maximum after `k` steps exceeds `a ≥ 0`, some column number `U G_(i+1)`, +`i < k`, does. -/ +theorem exists_lt_pilotInput_of_lt_pilotMax {a : ℝ} (ha : 0 ≤ a) {k : ℕ} {y : V} + (h : a < pilotMax c γ U C k y) : ∃ i < k, a < U (pilotInput c γ U C i) y := by + induction k with + | zero => exact absurd h (not_lt.mpr ha) + | succ k ih => + rw [pilotMax_succ, Pi.sup_apply, lt_sup_iff] at h + rcases h with h | h + · obtain ⟨i, hi, hU⟩ := ih h + exact ⟨i, by omega, hU⟩ + · exact ⟨k, by omega, h⟩ + +/-- **The pilot is a correction sequence** when the base cutoff satisfies `0 ≤ c t ≤ t` for +`t ≥ 0` and the multipliers lie in `[0, 1]` [OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem isCorrectionSeq_pilotCorrection (hC0 : ∀ x y, 0 ≤ C x y) (hc0 : ∀ t, 0 ≤ c t) + (hct : ∀ t, 0 ≤ t → c t ≤ t) (hγ0 : ∀ t, 0 ≤ γ t) (hγ1 : ∀ t, γ t ≤ 1) : + IsCorrectionSeq C (pilotCorrection c γ U C) := by + have hnonneg : ∀ i x y, 0 ≤ pilotCorrection c γ U C (i + 1) x y := fun i x y => by + rw [pilotCorrection_succ_apply]; exact mul_nonneg (hc0 _) (hγ0 _) + have hall : ∀ i x y, 0 ≤ pilotCorrection c γ U C i x y := fun i x y => by + cases i with + | zero => simp + | succ i => exact hnonneg i x y + refine ⟨rfl, hnonneg, fun i x y => ?_⟩ + rw [pilotCorrection_succ_apply] + have hG : 0 ≤ pilotInput c γ U C i x y := + add_nonneg (hC0 x y) (sum_nonneg fun z _ => mul_nonneg (hall i x z) (hC0 z y)) + exact (mul_le_of_le_one_right (hc0 _) (hγ1 _)).trans (hct _ hG) + +/-- **The actual correction is at most the pilot.** Run the fixed-multiplier recursion with the +cutoffs `φ y t = c t * γ (M_k y)`, the final pilot multiplier. For a monotone nonnegative `c` and +a nonincreasing `γ`, its first `k` iterates and their inputs are at most the pilot corrections and +pilot inputs [OpenAI2026LogSpace, Lemma 4.2]. -/ +theorem cutoffCorrectionIter_le_pilotCorrection (hC0 : ∀ x y, 0 ≤ C x y) (hc0 : ∀ t, 0 ≤ c t) + (hct : ∀ t, 0 ≤ t → c t ≤ t) (hcm : Monotone c) (hγ0 : ∀ t, 0 ≤ γ t) (hγ1 : ∀ t, γ t ≤ 1) + (hγm : Antitone γ) {k i : ℕ} (hik : i ≤ k) (x y : V) : + cutoffCorrectionIter (fun y t => c t * γ (pilotMax c γ U C k y)) C i x y ≤ + pilotCorrection c γ U C i x y ∧ + (C + cutoffCorrectionIter (fun y t => c t * γ (pilotMax c γ U C k y)) C i * C) x y ≤ + pilotInput c γ U C i x y := by + refine cutoffCorrectionIter_le_of_isCorrectionSeq hC0 + (fun y => hcm.mul_const (hγ0 _)) (fun j hj x y => ?_) + (isCorrectionSeq_pilotCorrection hC0 hc0 hct hγ0 hγ1) i hik x y + rw [pilotCorrection_succ_apply] + exact mul_le_mul_of_nonneg_left (hγm (pilotMax_mono (by omega) y)) (hc0 _) + +end Pilot + +end Matrix diff --git a/Complexity/Foundations/Probability/ColumnDetector.lean b/Complexity/Foundations/Probability/ColumnDetector.lean new file mode 100644 index 000000000..5756f4530 --- /dev/null +++ b/Complexity/Foundations/Probability/ColumnDetector.lean @@ -0,0 +1,469 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Foundations.Data.Finset.KthLargest +public import Mathlib.Algebra.BigOperators.Expect +public import Mathlib.Data.Finset.Density +public import Mathlib.LinearAlgebra.Matrix.Defs +public import Mathlib.Basic.Real.Basic +import Complexity.Foundations.Data.Finset.Markov +import Mathlib.Algebra.Order.BigOperators.Expect +import Mathlib.Algebra.BigOperators.Field +import Mathlib.Algebra.BigOperators.Ring.Finset +import Mathlib.Tactic.FieldSimp +import Mathlib.Tactic.Linarith +import Mathlib.Tactic.Positivity + +/-! +# Column detectors from retention channels + +A *column detector* decides, with true expectations over random retained sets, whether a column +of a nonnegative matrix `G` has many substantial entries. It is the detector of the OpenAI preprint +(2026-09-23), Section 4.2, idea 3 in issue #474 [OpenAI2026LogSpace], which chooses the column +multipliers of the correction-and-copy hierarchy. + +**Channels.** Two *retention channels* `X : ι → V → Prop` and `Y : κ → V → Prop` select random +sets of vertices from independent uniform seeds `s : ι` and `t : κ`; independence is built in, +since the seed space is the product `ι × κ`. `Cslib.Probability.RetentionChannels` records the +properties that the detector uses, at rate `f` [OpenAI2026LogSpace, (4.8), (4.9)]: + +* every vertex is retained with the same probability `π`, with `c_π f ≤ π ≤ C_π f`; +* for `w ≠ y`, `Pr[Y(w) ∧ Y(y)] ≤ C_pair f Pr[Y(y)]`; +* a nonempty set `A` retains fewer than `|A| π / 2` members of `X` with probability at most + `C_var / (|A| π)`. + +**The detector.** For a draw `T` of the terminal channel `Y`, the *row gate* of row `x` is +`ρ (rank_K {G x w / f : w ∈ T})` (`Matrix.rowGate`); it is one unless `K` retained entries of the +row exceed `η f`. For a draw `S` of the start channel `X`, the *trial* at column `y` is +`rank_J {ϕ (G x y / f) * gate x : x ∈ S}` (`Matrix.detectorTrial`), where `rank_j` is the `j`-th +largest value padded with zeros (`Finset.kthLargest`). The *detector number* `U y` is the +expectation of the trial over both channels, conditioned on `Y(y)` (`Matrix.columnDetector`). + +**The detector lemma** [OpenAI2026LogSpace, Lemma 4.3]. Let `ϕ` be zero through `δ₀` and one from +`δ₁`, and `ρ` one through `η > 0`, both with values in `[0, 1]`. + +1. If the rows of `G ≥ 0` sum to at most `k`, the gate rank satisfies `K ≥ 160 (1 + C_pair k / η)`, + and `R` satisfies `c_π R ≥ max (4 J, 40 C_var)`, then a column with more than `R / f` entries + at least `δ₁ f` has `U y ≥ 19 / 20` (`Matrix.le_columnDetector`). +2. If `U y > 1 / 4`, the column has more than `J / (4 C_π f)` entries above `δ₀ f` + (`Matrix.lt_card_of_lt_columnDetector`). + +Each statement uses only the hypotheses it needs; for instance the second needs neither the +row-sum bound nor the row gates' threshold. + +The first statement uses no independence between the row gates of different rows; it combines +Markov's inequality for the gate failures with the lower tail of the start channel. + +## Main definitions + +* `Cslib.Probability.RetentionChannels`: the channel properties used by the detector. +* `Matrix.rowGate`, `Matrix.detectorTrial`, `Matrix.columnDetector`: the detector. + +## Main results + +* `Matrix.columnDetector_nonneg`, `Matrix.columnDetector_le_one`: detector numbers lie in `[0, 1]`. +* `Matrix.le_columnDetector`: columns with many large entries are detected. +* `Matrix.lt_card_of_lt_columnDetector`: detected columns have many substantial entries. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Section 4.2 and Lemma 4.3 (preprint, not peer reviewed) +-/ + +public section + +open Finset +open scoped BigOperators + +namespace Cslib.Probability + +/-- **Retention channels** `X` and `Y` at rate `f`, with independent uniform seeds `s : ι` and +`t : κ`: every vertex is retained by either channel with the same probability `π`, +`c_π f ≤ π ≤ C_π f`; two distinct vertices `w ≠ y` are both retained by `Y` with probability at +most `C_pair f` times that of `y`; and a nonempty set `A` retains fewer than `|A| π / 2` members +of `X` with probability at most `C_var / (|A| π)`. These are the properties +[OpenAI2026LogSpace, (4.8), (4.9)] that the detectors use. -/ +structure RetentionChannels {V ι κ : Type*} [Fintype ι] [Fintype κ] (X : ι → V → Prop) + (Y : κ → V → Prop) [∀ s v, Decidable (X s v)] [∀ t v, Decidable (Y t v)] + (f π cπ Cπ Cpair Cvar : ℝ) : Prop where + dens_X : ∀ v, (dens {s | X s v} : ℝ) = π + dens_Y : ∀ v, (dens {t | Y t v} : ℝ) = π + lower : cπ * f ≤ π + upper : π ≤ Cπ * f + pair : ∀ w y, w ≠ y → (dens {t | Y t w ∧ Y t y} : ℝ) ≤ Cpair * f * dens {t | Y t y} + tail : ∀ A : Finset V, A.Nonempty → + (dens {s | 2 * (#{x ∈ A | X s x} : ℝ) < #A * π} : ℝ) ≤ Cvar / (#A * π) + +end Cslib.Probability + +namespace Matrix + +open Cslib.Probability + +variable {V ι κ : Type*} [Fintype V] [Fintype ι] [Fintype κ] + +section Definitions + +/-- The **row gate** of row `x` for a draw `T` of the terminal channel: +`ρ (rank_K {G x w / f : w ∈ T})` [OpenAI2026LogSpace, (4.11)]. -/ +@[expose] noncomputable def rowGate (ρ : ℝ → ℝ) (K : ℕ) (f : ℝ) (G : Matrix V V ℝ) + (T : Finset V) (x : V) : ℝ := + ρ (kthLargest K T fun w => G x w / f) + +/-- A **detector trial** at column `y`, for draws `S` of the start channel and `T` of the terminal +channel: `rank_J {ϕ (G x y / f) * rowGate x : x ∈ S}` [OpenAI2026LogSpace, (4.12)]. -/ +@[expose] noncomputable def detectorTrial (ϕ ρ : ℝ → ℝ) (J K : ℕ) (f : ℝ) (G : Matrix V V ℝ) + (S T : Finset V) (y : V) : ℝ := + kthLargest J S fun x => ϕ (G x y / f) * rowGate ρ K f G T x + +/-- The **detector number** of column `y`: the expectation of the detector trial over the seeds of +both channels, conditioned on `Y(y)` [OpenAI2026LogSpace, (4.12)]. -/ +@[expose] noncomputable def columnDetector (X : ι → V → Prop) (Y : κ → V → Prop) + [∀ s v, Decidable (X s v)] [∀ t v, Decidable (Y t v)] (ϕ ρ : ℝ → ℝ) (J K : ℕ) (f : ℝ) + (G : Matrix V V ℝ) (y : V) : ℝ := + 𝔼 s, 𝔼 t ∈ {t | Y t y}, detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y + +end Definitions + +variable {X : ι → V → Prop} {Y : κ → V → Prop} [∀ s v, Decidable (X s v)] + [∀ t v, Decidable (Y t v)] {ϕ ρ : ℝ → ℝ} {J K : ℕ} {f : ℝ} {G : Matrix V V ℝ} {y : V} + +private theorem dens_cast {α : Type*} [Fintype α] (s : Finset α) : + ((dens s : ℚ≥0) : ℝ) = #s / Fintype.card α := by + rw [dens_eq_card_div_card]; push_cast; rfl + +private theorem columnDetector_eq_sum : + columnDetector X Y ϕ ρ J K f G y = + (∑ s, ∑ t ∈ {t | Y t y}, detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y) / + (Fintype.card ι * #({t | Y t y} : Finset κ)) := by + rw [columnDetector, Fintype.expect_eq_sum_div_card] + simp only [expect_eq_sum_div_card] + rw [← Finset.sum_div, div_div, mul_comm (#({t | Y t y} : Finset κ) : ℝ)] + +omit [Fintype V] in +theorem detectorTrial_nonneg {S T : Finset V} : 0 ≤ detectorTrial ϕ ρ J K f G S T y := + kthLargest_nonneg + +omit [Fintype V] in +theorem detectorTrial_le_one (hϕ0 : ∀ t, 0 ≤ ϕ t) (hϕ1 : ∀ t, ϕ t ≤ 1) + (hρ1 : ∀ t, ρ t ≤ 1) {S T : Finset V} : detectorTrial ϕ ρ J K f G S T y ≤ 1 := + kthLargest_le zero_le_one fun _ _ => + (mul_le_mul_of_nonneg_left (hρ1 _) (hϕ0 _)).trans (by rw [mul_one]; exact hϕ1 _) + +theorem columnDetector_nonneg : 0 ≤ columnDetector X Y ϕ ρ J K f G y := by + rw [columnDetector] + exact expect_nonneg fun _ _ => expect_nonneg fun _ _ => detectorTrial_nonneg + +theorem columnDetector_le_one (hϕ0 : ∀ t, 0 ≤ ϕ t) (hϕ1 : ∀ t, ϕ t ≤ 1) + (hρ1 : ∀ t, ρ t ≤ 1) : columnDetector X Y ϕ ρ J K f G y ≤ 1 := by + rw [columnDetector_eq_sum] + refine div_le_one_of_le₀ ?_ (by positivity) + calc ∑ s, ∑ t ∈ {t | Y t y}, detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y + ≤ ∑ _s : ι, ∑ _t ∈ ({t | Y t y} : Finset κ), (1 : ℝ) := + sum_le_sum fun _ _ => sum_le_sum fun _ _ => detectorTrial_le_one hϕ0 hϕ1 hρ1 + _ = Fintype.card ι * #({t | Y t y} : Finset κ) := by + simp only [sum_const, card_univ, nsmul_eq_mul, mul_one] + +variable {π cπ Cπ Cpair Cvar : ℝ} + +omit [Fintype V] in +private theorem card_X (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) (v : V) : + (#({s | X s v} : Finset ι) : ℝ) = π * Fintype.card ι := by + have h := hch.dens_X v + rw [dens_cast] at h + rcases (Fintype.card ι).eq_zero_or_pos with h0 | h0 + · have : (#({s | X s v} : Finset ι)) = 0 := Nat.eq_zero_of_le_zero + (h0 ▸ card_le_univ _) + simp [this, h0] + · rw [← h]; field_simp + +/-- **Detected columns have many substantial entries** [OpenAI2026LogSpace, Lemma 4.3 (2)]: if +`ϕ` vanishes through `δ₀` and the detector number of column `y` exceeds `1 / 4`, more than +`J / (4 C_π f)` entries of the column exceed `δ₀ f`. -/ +theorem lt_card_of_lt_columnDetector (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) + (hf : 0 < f) (hϕ0 : ∀ t, 0 ≤ ϕ t) (hϕ1 : ∀ t, ϕ t ≤ 1) {δ₀ : ℝ} + (hϕδ : ∀ t, t ≤ δ₀ → ϕ t = 0) (hρ1 : ∀ t, ρ t ≤ 1) (hJ : 0 < J) + (hU : 1 / 4 < columnDetector X Y ϕ ρ J K f G y) : + J / (4 * Cπ * f) < #({x | δ₀ * f < G x y} : Finset V) := by + set A0 : Finset V := {x | δ₀ * f < G x y} + set T : Finset κ := {t | Y t y} + have hJr : (0 : ℝ) < J := by exact_mod_cast hJ + -- a trial is at most the number of retained substantial entries over `J` + have htrial : ∀ s t, detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y ≤ + (#{x ∈ A0 | X s x} : ℝ) / J := by + intro s t + rcases le_or_gt (detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y) 0 with h | h + · exact h.trans (by positivity) + have hcard := (lt_kthLargest_iff hJ le_rfl).mp h + have hsub : ({x ∈ ({x | X s x} : Finset V) | + 0 < ϕ (G x y / f) * rowGate ρ K f G {w | Y t w} x}) ⊆ {x ∈ A0 | X s x} := by + intro x hx + simp only [mem_filter, mem_univ, true_and, A0] at hx ⊢ + refine ⟨?_, hx.1⟩ + by_contra hle + have : G x y / f ≤ δ₀ := by rw [div_le_iff₀ hf]; linarith + rw [hϕδ _ this, zero_mul] at hx + exact lt_irrefl _ hx.2 + have hJle : (J : ℝ) ≤ #{x ∈ A0 | X s x} := by exact_mod_cast hcard.trans (card_le_card hsub) + rw [le_div_iff₀ hJr] + calc detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y * J ≤ 1 * J := + mul_le_mul_of_nonneg_right (detectorTrial_le_one hϕ0 hϕ1 hρ1) hJr.le + _ ≤ _ := by rw [one_mul]; exact hJle + -- summing over the start seeds counts each substantial entry with its retention probability + have hsumX : ∑ s, (#{x ∈ A0 | X s x} : ℝ) = #A0 * (π * Fintype.card ι) := by + simp only [natCast_card_filter] + rw [sum_comm] + simp only [← natCast_card_filter, card_X hch, sum_const, nsmul_eq_mul] + have hT : 0 < #T := by + rw [card_pos] + by_contra hT + rw [not_nonempty_iff_eq_empty] at hT + have : columnDetector X Y ϕ ρ J K f G y = 0 := by + rw [columnDetector_eq_sum]; simp [T, hT] + linarith + have hι : 0 < Fintype.card ι := by + rw [Fintype.card_pos_iff] + by_contra hι + rw [not_nonempty_iff] at hι + have : columnDetector X Y ϕ ρ J K f G y = 0 := by + rw [columnDetector_eq_sum]; simp + linarith + have hTr : (0 : ℝ) < #T := by exact_mod_cast hT + have hιr : (0 : ℝ) < Fintype.card ι := by exact_mod_cast hι + have hUle : columnDetector X Y ϕ ρ J K f G y ≤ #A0 * π / J := by + rw [columnDetector_eq_sum, div_le_div_iff₀ (by positivity) hJr] + calc (∑ s, ∑ t ∈ T, detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y) * J + ≤ (∑ s, ∑ _t ∈ T, (#{x ∈ A0 | X s x} : ℝ) / J) * J := + mul_le_mul_of_nonneg_right + (sum_le_sum fun s _ => sum_le_sum fun t _ => htrial s t) hJr.le + _ = #T * ∑ s, (#{x ∈ A0 | X s x} : ℝ) := by + simp only [sum_const, nsmul_eq_mul, Finset.mul_sum, Finset.sum_mul] + exact sum_congr rfl fun s _ => by field_simp + _ = #A0 * π * (Fintype.card ι * #T) := by rw [hsumX]; ring + have hπ : 0 < π := by + by_contra hπ + have : #A0 * π / J ≤ 0 := + div_nonpos_of_nonpos_of_nonneg (mul_nonpos_of_nonneg_of_nonpos (by positivity) + (not_lt.mp hπ)) hJr.le + linarith + have hCπ : 0 < Cπ * f := hπ.trans_le hch.upper + have h1 : J / 4 < #A0 * π := by + have := hU.trans_le hUle + rw [lt_div_iff₀ hJr] at this + linarith + rw [div_lt_iff₀ (by nlinarith)] + calc (J : ℝ) = J / 4 * 4 := by ring + _ < #A0 * π * 4 := by linarith + _ ≤ #A0 * (Cπ * f) * 4 := by gcongr; exact hch.upper + _ = #A0 * (4 * Cπ * f) := by ring + +omit [Fintype V] in +private theorem card_pos_of_dens {α : Type*} [Fintype α] {s : Finset α} {π : ℝ} (hπ : 0 < π) + (h : (dens s : ℝ) = π) : 0 < Fintype.card α ∧ 0 < #s := by + rw [dens_cast] at h + rcases (Fintype.card α).eq_zero_or_pos with h0 | h0 + · simp [h0] at h; linarith + refine ⟨h0, Nat.pos_of_ne_zero fun hs => ?_⟩ + simp [hs] at h; linarith + +/-- **Columns with many large entries are detected** [OpenAI2026LogSpace, Lemma 4.3 (1)]. Let the +rows of `G ≥ 0` sum to at most `k`, let `ϕ` be one from `δ₁`, let `ρ ≤ 1` be one through `η > 0`, +let the gate rank satisfy `K ≥ 160 (1 + C_pair k / η)`, and let `c_π R ≥ 4 J` and +`c_π R ≥ 40 C_var`. If more than `R / f` entries of column `y` are at least `δ₁ f`, its detector +number is at least `19 / 20`. -/ +theorem le_columnDetector (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) (hf : 0 < f) + (hcπ : 0 < cπ) (hCpair : 0 ≤ Cpair) {δ₁ : ℝ} (hϕδ : ∀ t, δ₁ ≤ t → ϕ t = 1) + (hρ1 : ∀ t, ρ t ≤ 1) {η : ℝ} (hη : 0 < η) + (hρη : ∀ t, t ≤ η → ρ t = 1) (hG0 : ∀ x w, 0 ≤ G x w) {k : ℝ} + (hGk : ∀ x, ∑ w, G x w ≤ k) (hK : 160 * (1 + Cpair * k / η) ≤ K) (hJ : 0 < J) {R : ℝ} + (hRJ : 4 * J ≤ cπ * R) (hRvar : 40 * Cvar ≤ cπ * R) + (hy : R / f < #({x | δ₁ * f ≤ G x y} : Finset V)) : + 19 / 20 ≤ columnDetector X Y ϕ ρ J K f G y := by + classical + set A : Finset V := {x | δ₁ * f ≤ G x y} + set T : Finset κ := {t | Y t y} + set D : ℝ := 1 + Cpair * k / η + set gate : κ → V → ℝ := fun t x => rowGate ρ K f G {w | Y t w} x + have hπ : 0 < π := (mul_pos hcπ hf).trans_le hch.lower + have hJr : (0 : ℝ) < J := by exact_mod_cast hJ + have hnπ : cπ * R < #A * π := by + have h1 : R < #A * f := by rwa [div_lt_iff₀ hf] at hy + calc cπ * R < cπ * (#A * f) := mul_lt_mul_of_pos_left h1 hcπ + _ = #A * (cπ * f) := by ring + _ ≤ #A * π := mul_le_mul_of_nonneg_left hch.lower (by positivity) + have hnπ0 : 0 < (#A : ℝ) * π := by linarith + have hA : A.Nonempty := by + rw [← card_pos, ← Nat.cast_pos (α := ℝ)] + exact pos_of_mul_pos_left hnπ0 hπ.le + obtain ⟨hι, -⟩ := card_pos_of_dens hπ (hch.dens_X y) + obtain ⟨hκ, hT⟩ := card_pos_of_dens hπ (hch.dens_Y y) + have hκr : (0 : ℝ) < Fintype.card κ := by exact_mod_cast hκ + have hιr : (0 : ℝ) < Fintype.card ι := by exact_mod_cast hι + have hTr : (0 : ℝ) < #T := by exact_mod_cast hT + have hD : 1 ≤ D := by + have : 0 ≤ Cpair * k / η := by + have hk : 0 ≤ k := (sum_nonneg fun w _ => hG0 y w).trans (hGk y) + positivity + linarith + have hKpos : 0 < K := by + have : (0 : ℝ) < K := by linarith + exact_mod_cast this + -- Markov's inequality for the row gates: each row fails its gate on few terminal draws + have hgate : ∀ x, (#{t ∈ T | gate t x < 1} : ℝ) * K ≤ #T * D := by + intro x + set W : Finset V := {w | η * f < G x w} + have hW : (#W : ℝ) * (η * f) ≤ k := + (card_filter_mul_le_sum univ _ (fun w => G x w) (fun w _ => hG0 x w) + fun _ _ hw => hw.le).trans (hGk x) + have hbadK : ∀ t ∈ T, gate t x < 1 → (K : ℝ) ≤ #{w ∈ W | Y t w} := by + intro t _ ht + have hlt : η < kthLargest K {w | Y t w} (fun w => G x w / f) := by + by_contra hle + have h1 := hρη _ (not_lt.mp hle) + simp only [gate, rowGate] at ht + rw [h1] at ht + exact lt_irrefl _ ht + have hcard := (lt_kthLargest_iff hKpos hη.le).mp hlt + have hsub : ({w ∈ ({w | Y t w} : Finset V) | η < G x w / f} : Finset V) ⊆ + {w ∈ W | Y t w} := fun w hw => by + simp only [mem_filter, mem_univ, true_and, W] at hw ⊢ + exact ⟨by rw [lt_div_iff₀ hf] at hw; exact hw.2, hw.1⟩ + exact_mod_cast hcard.trans (card_le_card hsub) + have hMarkov : (#{t ∈ T | gate t x < 1} : ℝ) * K ≤ ∑ t ∈ T, (#{w ∈ W | Y t w} : ℝ) := + card_filter_mul_le_sum T _ _ (fun _ _ => by positivity) hbadK + have hswap : ∑ t ∈ T, (#{w ∈ W | Y t w} : ℝ) = ∑ w ∈ W, (#{t ∈ T | Y t w} : ℝ) := by + simp only [natCast_card_filter] + exact sum_comm + have hterm : ∀ w ∈ W, (#{t ∈ T | Y t w} : ℝ) ≤ (if y = w then (#T : ℝ) else 0) + + Cpair * f * #T := by + intro w _ + have hle : (#{t ∈ T | Y t w} : ℝ) ≤ #T := by exact_mod_cast card_filter_le _ _ + by_cases hwy : y = w + · simp only [hwy, ↓reduceIte] + have : 0 ≤ Cpair * f * #T := by positivity + linarith + · simp only [hwy, ↓reduceIte, zero_add] + have hp := hch.pair w y (Ne.symm hwy) + rw [dens_cast, dens_cast, ← mul_div_assoc, div_le_div_iff_of_pos_right hκr] at hp + have hset : ({t ∈ T | Y t w} : Finset κ) = ({t | Y t w ∧ Y t y} : Finset κ) := by + ext t; simp only [T, mem_filter, mem_univ, true_and]; tauto + rw [hset] + exact hp + have hWf : (#W : ℝ) * f ≤ k / η := by + rw [le_div_iff₀ hη]; linarith + calc (#{t ∈ T | gate t x < 1} : ℝ) * K + ≤ ∑ w ∈ W, ((if y = w then (#T : ℝ) else 0) + Cpair * f * #T) := + hMarkov.trans (hswap ▸ sum_le_sum hterm) + _ = (if y ∈ W then (#T : ℝ) else 0) + #W * (Cpair * f * #T) := by + rw [sum_add_distrib, sum_ite_eq, sum_const, nsmul_eq_mul] + _ ≤ #T + #T * Cpair * (#W * f) := by + have : (if y ∈ W then (#T : ℝ) else 0) ≤ #T := by split_ifs <;> [exact le_rfl; positivity] + nlinarith + _ ≤ #T + #T * Cpair * (k / η) := by gcongr + _ = #T * D := by simp only [D]; ring + -- the expected number of retained large rows that fail their gate + set N : ι → ℝ := fun s => #{x ∈ A | X s x} + set L : ι → κ → ℝ := fun s t => #{x ∈ A | X s x ∧ gate t x < 1} + have hL0 : ∀ s t, 0 ≤ L s t := fun _ _ => by positivity + have hsumL : ∑ s, ∑ t ∈ T, L s t ≤ #A * π * Fintype.card ι * (#T * D / K) := by + have heq : ∑ s, ∑ t ∈ T, L s t = + ∑ x ∈ A, (#{s | X s x} : ℝ) * #{t ∈ T | gate t x < 1} := by + have h1 : ∀ s t, L s t = ∑ x ∈ A, + (if X s x then (1 : ℝ) else 0) * (if gate t x < 1 then 1 else 0) := fun s t => by + simp only [L, natCast_card_filter, ite_zero_mul_ite_zero, mul_one] + simp only [h1, natCast_card_filter, sum_mul_sum] + exact (sum_congr rfl fun s _ => sum_comm).trans sum_comm + rw [heq] + have hKr : (0 : ℝ) < K := by exact_mod_cast hKpos + calc ∑ x ∈ A, (#{s | X s x} : ℝ) * #{t ∈ T | gate t x < 1} + ≤ ∑ _x ∈ A, π * Fintype.card ι * (#T * D / K) := by + refine sum_le_sum fun x _ => ?_ + rw [card_X hch] + exact mul_le_mul_of_nonneg_left (by rw [le_div_iff₀ hKr]; exact hgate x) + (by positivity) + _ = #A * π * Fintype.card ι * (#T * D / K) := by + rw [sum_const, nsmul_eq_mul]; ring + -- outside two bad events, at least `J` retained large rows pass their gates + have hgood : ∀ s t, ¬ 2 * N s < #A * π → ¬ #A * π < 4 * L s t → + 1 ≤ detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y := by + intro s t h1 h2 + push Not at h1 h2 + have hsplit : N s = L s t + #{x ∈ A | X s x ∧ ¬ gate t x < 1} := by + simp only [N, L, natCast_card_filter, ← sum_add_distrib] + refine sum_congr rfl fun x _ => ?_ + by_cases hX : X s x <;> by_cases hg : gate t x < 1 <;> simp [hX, hg] + have hJle : (J : ℝ) ≤ #{x ∈ A | X s x ∧ ¬ gate t x < 1} := by + have : 4 * (J : ℝ) < #A * π := hRJ.trans_lt hnπ + linarith + refine (le_kthLargest_iff hJ one_pos).mpr ?_ + refine Nat.cast_le.mp (hJle.trans ?_) + refine Nat.cast_le.mpr (card_le_card fun x hx => ?_) + simp only [mem_filter, mem_univ, true_and, A] at hx ⊢ + refine ⟨hx.2.1, ?_⟩ + have hϕx : ϕ (G x y / f) = 1 := hϕδ _ (by rw [le_div_iff₀ hf]; exact hx.1) + have hgx : gate t x = 1 := le_antisymm (hρ1 _) (not_lt.mp hx.2.2) + simp only [gate] at hgx + rw [hϕx, hgx, one_mul] + -- sum the pointwise bound `trial ≥ 1 - [bad start draw] - [many gate failures]` + set b1 : ι → ℝ := fun s => if 2 * N s < #A * π then 1 else 0 + set b2 : ι → κ → ℝ := fun s t => if #A * π < 4 * L s t then 1 else 0 + have hpoint : ∀ s t, 1 - b1 s - b2 s t ≤ + detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y := by + intro s t + have h0 : 0 ≤ detectorTrial ϕ ρ J K f G {x | X s x} {w | Y t w} y := detectorTrial_nonneg + by_cases h1 : 2 * N s < #A * π + · have : 0 ≤ b2 s t := by simp only [b2]; split_ifs <;> norm_num + simp only [b1, h1, ↓reduceIte] + linarith + by_cases h2 : #A * π < 4 * L s t + · simp only [b1, b2, h1, h2, ↓reduceIte] + linarith + · simp only [b1, b2, h1, h2, ↓reduceIte, sub_zero] + exact hgood s t h1 h2 + have hb1 : ∑ s, b1 s ≤ Cvar / (#A * π) * Fintype.card ι := by + have ht := hch.tail A hA + rw [dens_cast, div_le_iff₀ hιr] at ht + simp only [b1, N] + rw [sum_boole] + exact ht + have hb2 : ∑ s, ∑ t ∈ T, b2 s t ≤ 4 / (#A * π) * ∑ s, ∑ t ∈ T, L s t := by + rw [mul_sum] + refine sum_le_sum fun s _ => ?_ + rw [mul_sum] + refine sum_le_sum fun t _ => ?_ + simp only [b2] + split_ifs with h + · rw [div_mul_eq_mul_div, le_div_iff₀ hnπ0]; linarith + · have := hL0 s t; positivity + have hvar : Cvar / (#A * π) ≤ 1 / 40 := by + rw [div_le_div_iff₀ hnπ0 (by norm_num)]; linarith + have hgatebound : 4 / (#A * π) * (#A * π * Fintype.card ι * (#T * D / K)) ≤ + Fintype.card ι * #T / 40 := by + have hKr : (0 : ℝ) < K := by exact_mod_cast hKpos + have : 4 / (#A * π) * (#A * π * Fintype.card ι * (#T * D / K)) = + 4 * D / K * (Fintype.card ι * #T) := by + field_simp + rw [this, div_eq_mul_one_div (Fintype.card ι * (#T : ℝ)) 40, mul_comm _ (1 / 40 : ℝ)] + refine mul_le_mul_of_nonneg_right ?_ (by positivity) + rw [div_le_iff₀ hKr]; linarith + rw [columnDetector_eq_sum, le_div_iff₀ (by positivity)] + have h4 : 0 ≤ 4 / (#A * π) := by positivity + calc 19 / 20 * (Fintype.card ι * #T : ℝ) + ≤ Fintype.card ι * #T - #T * (Cvar / (#A * π) * Fintype.card ι) - + 4 / (#A * π) * (#A * π * Fintype.card ι * (#T * D / K)) := by + nlinarith [mul_le_mul_of_nonneg_left hvar (by positivity : (0 : ℝ) ≤ #T * Fintype.card ι)] + _ ≤ Fintype.card ι * #T - #T * ∑ s, b1 s - ∑ s, ∑ t ∈ T, b2 s t := by + nlinarith [mul_le_mul_of_nonneg_left hb1 hTr.le, mul_le_mul_of_nonneg_left hsumL h4] + _ = ∑ s, ∑ t ∈ T, (1 - b1 s - b2 s t) := by + simp only [sum_sub_distrib, sum_const, nsmul_eq_mul, card_univ, mul_one] + rw [← mul_sum] + _ ≤ _ := sum_le_sum fun s _ => sum_le_sum fun t _ => hpoint s t + +end Matrix diff --git a/Complexity/Foundations/Probability/DetectedStage.lean b/Complexity/Foundations/Probability/DetectedStage.lean new file mode 100644 index 000000000..ab425a36c --- /dev/null +++ b/Complexity/Foundations/Probability/DetectedStage.lean @@ -0,0 +1,295 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Foundations.LinearAlgebra.Matrix.CopyStage +public import Complexity.Foundations.LinearAlgebra.Matrix.PilotCorrection +public import Complexity.Foundations.Probability.ColumnDetector +import Mathlib.Algebra.BigOperators.Fin +import Mathlib.Algebra.Order.Floor.Semiring + +/-! +# One stage of the hierarchy with detector-chosen multipliers + +This file closes the detector interface of `Matrix.copyStage_rates` +[OpenAI2026LogSpace, Section 4.2, Proposition 4.5]. One stage of the correction-and-copy hierarchy +runs the pilot (`Matrix.pilotMax`) with the column detector +`Matrix.columnDetector X Y ϕ ρ J K f` as its column number, for retention channels `X`, `Y` +satisfying `Cslib.Probability.RetentionChannels`. Let `M = M_k` be the final running maximum of the +detector numbers. Then + +* the column multiplier of the actual correction is `γ (M y)`, so the cutoffs are + `φ y t = c t * γ (M y)` for the base cutoff `c t = f Q (t / f)`; +* the copy weights are `r 0 x = 1` and `r j x = κ (M x)` for `j ≠ 0` + (`Matrix.detectorWeight`) [OpenAI2026LogSpace, (4.22)]; +* the overloaded vertices are `O = {x | 1 / 4 < M x}` (`Matrix.overloaded`). + +Since `γ` is one through `1 / 2` and `κ` is zero through `1 / 4` and one from `1 / 2`, every +column is either fully corrected or overloaded with all copies active, and only overloaded vertices +have active extra copies. The detector lemma (`Matrix.lt_card_of_lt_columnDetector`) gives each +overloaded column more than `J / (4 C_π f)` entries above `δ₀ f` in some pilot input, and +incidence counting over the pilot inputs, whose rows sum to at most `1, …, k`, gives +`m |O| ≤ |A|` once `2 C_π m k (k + 1) ≤ δ₀ J` [OpenAI2026LogSpace, (4.24)]. So the stage has the +density, intertwining and active-count conclusions of `Matrix.copyStage_rates` +(`Matrix.detectedStage_rates`), with only the channel properties and deterministic constant +conditions as hypotheses. + +The pilot also bounds the column counts of the corrected columns +[OpenAI2026LogSpace, Lemma 4.3 (3)]: if the pilot multiplier of a column is positive, its pilot +inputs have at most `R / f` entries at least `δ₁ f` (`Matrix.card_le_of_pilot_pos`), and so do +the inputs of the actual correction when the final multiplier is positive +(`Matrix.card_le_of_multiplier_pos`). + +## Main definitions + +* `Matrix.detectorWeight`: the copy weights `r` from the running maximum. +* `Matrix.overloaded`: the overloaded vertices. + +## Main results + +* `Matrix.card_overloaded_le`: the incidence bound `m |O| ≤ |A|`. +* `Matrix.detectedStage_rates`: one stage with detector-chosen multipliers and copies. +* `Matrix.card_le_of_pilot_pos`, `Matrix.card_le_of_multiplier_pos`: column counts of corrected + columns. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Section 4.2, Lemma 4.3 and Proposition 4.5 (preprint, not peer reviewed) +-/ + +public section + +open Finset Cslib.Probability + +namespace Matrix + +section Definitions + +variable {V : Type*} + +/-- The **copy weights** from the running maximum `M` of the detector numbers: the primary copy +has weight one, every other copy of `x` weight `κ (M x)` [OpenAI2026LogSpace, (4.22)]. -/ +@[expose] noncomputable def detectorWeight {m : ℕ} (κ : ℝ → ℝ) (M : V → ℝ) (j : Fin (m + 1)) + (x : V) : ℝ := + if j = 0 then 1 else κ (M x) + +/-- The **overloaded** vertices: those whose running maximum of detector numbers exceeds `1 / 4` +[OpenAI2026LogSpace, Proposition 4.5]. -/ +@[expose] noncomputable def overloaded [Fintype V] (M : V → ℝ) : Finset V := + {x | 1 / 4 < M x} + +end Definitions + +variable {V ι ι' : Type*} [Fintype V] [Fintype ι] [Fintype ι'] {X : ι → V → Prop} + {Y : ι' → V → Prop} [∀ s v, Decidable (X s v)] [∀ t v, Decidable (Y t v)] {ϕ ρ : ℝ → ℝ} + {J K : ℕ} {f π cπ Cπ Cpair Cvar : ℝ} {c γ : ℝ → ℝ} {C : Matrix V V ℝ} + +private theorem sum_fin_succ_cast (k : ℕ) : ∑ i : Fin k, ((i : ℝ) + 1) = k * (k + 1) / 2 := by + rw [Fin.sum_univ_eq_sum_range (fun i => (i : ℝ) + 1)] + induction k with + | zero => simp + | succ k ih => rw [sum_range_succ, ih]; push_cast; ring + +/-- **Few overloaded vertices** [OpenAI2026LogSpace, Proposition 4.5]: after `k` pilot steps with +the column detector, if `A` covers the support of `C` and `2 C_π m k (k + 1) ≤ δ₀ J`, then +`m |O| ≤ |A|`. Each overloaded column has more than `J / (4 C_π f)` entries above `δ₀ f` in some +pilot input, and the pilot inputs have row sums at most `1, …, k`. -/ +theorem card_overloaded_le (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) (hf : 0 < f) + (hCπ : 0 < Cπ) (hϕ0 : ∀ t, 0 ≤ ϕ t) (hϕ1 : ∀ t, ϕ t ≤ 1) {δ₀ : ℝ} (hδ₀ : 0 < δ₀) + (hϕδ : ∀ t, t ≤ δ₀ → ϕ t = 0) (hρ1 : ∀ t, ρ t ≤ 1) (hJ : 0 < J) (hC0 : ∀ x y, 0 ≤ C x y) + (hC1 : C *ᵥ 1 ≤ 1) {A : Finset V} (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) + (hc0 : ∀ t, 0 ≤ c t) (hct : ∀ t, 0 ≤ t → c t ≤ t) (hγ0 : ∀ t, 0 ≤ γ t) + (hγ1 : ∀ t, γ t ≤ 1) {k m : ℕ} (hJm : 2 * Cπ * m * k * (k + 1) ≤ δ₀ * J) : + m * #(overloaded (pilotMax c γ (columnDetector X Y ϕ ρ J K f) C k)) ≤ #A := by + set U := columnDetector X Y ϕ ρ J K f + set O := overloaded (pilotMax c γ U C k) + have hseq := isCorrectionSeq_pilotCorrection (U := U) hC0 hc0 hct hγ0 hγ1 + -- every overloaded column has many substantial entries in some pilot input + have hinc : ∀ y ∈ O, ∃ i : Fin k, J / (4 * Cπ * f) < + #({x | δ₀ * f < pilotInput c γ U C i x y} : Finset V) := by + intro y hy + simp only [O, overloaded, mem_filter, mem_univ, true_and] at hy + obtain ⟨i, hi, hU⟩ := exists_lt_pilotInput_of_lt_pilotMax (by norm_num) hy + exact ⟨⟨i, hi⟩, lt_card_of_lt_columnDetector hch hf hϕ0 hϕ1 hϕδ hρ1 hJ hU⟩ + rcases O.eq_empty_or_nonempty with hO | hO + · rw [hO, card_empty, mul_zero]; exact Nat.zero_le _ + have hk : 0 < k := by + obtain ⟨y, hy⟩ := hO + obtain ⟨⟨i, hi⟩, -⟩ := hinc y hy + omega + set N := ⌊J / (4 * Cπ * f)⌋₊ + 1 + have hN : ∀ y ∈ O, ∃ i : Fin k, N ≤ #({x | δ₀ * f < pilotInput c γ U C i x y} : Finset V) := by + intro y hy + obtain ⟨i, hi⟩ := hinc y hy + exact ⟨i, Nat.succ_le_of_lt ((Nat.floor_lt (by positivity)).mpr hi)⟩ + have hcount := card_mul_le_of_incidences (fun i : Fin k => pilotInput c γ U C i) + (fun i x y => hseq.input_nonneg hC0 i x y) (fun i => (i : ℝ) + 1) + (fun i x => (hseq.sum_input_le hC1 i x).1) A + (fun i x y h => (hseq.input_mem hA i x y h).1) (mul_pos hδ₀ hf) O hN + rw [sum_fin_succ_cast] at hcount + have hNJ : J / (4 * Cπ * f) < N := by + simp only [N]; push_cast; exact Nat.lt_floor_add_one _ + have hJN : (J : ℝ) * δ₀ < 4 * Cπ * N * δ₀ * f := by + rw [div_lt_iff₀ (by positivity)] at hNJ + nlinarith + have hkpos : (0 : ℝ) < k * (k + 1) := by + have : (0 : ℝ) < k := by exact_mod_cast hk + positivity + -- `#O N δ₀ f ≤ #A k (k + 1) / 2` and `2 C_π m k (k + 1) ≤ δ₀ J < 4 C_π N δ₀ f` + have key : (m : ℝ) * #O * (2 * Cπ * k * (k + 1)) ≤ #A * (2 * Cπ * k * (k + 1)) := by + have h1 : (m : ℝ) * #O * (2 * Cπ * k * (k + 1)) ≤ #O * (δ₀ * J) := by + have := mul_le_mul_of_nonneg_left hJm (Nat.cast_nonneg (α := ℝ) #O) + nlinarith + have h2 : (#O : ℝ) * (δ₀ * J) ≤ #O * (4 * Cπ * N * δ₀ * f) := + mul_le_mul_of_nonneg_left (by nlinarith) (Nat.cast_nonneg _) + have h3 : (#O : ℝ) * (4 * Cπ * N * δ₀ * f) ≤ #A * (2 * Cπ * k * (k + 1)) := by + have := mul_le_mul_of_nonneg_left hcount (by positivity : (0 : ℝ) ≤ 4 * Cπ) + nlinarith + linarith + have : (m : ℝ) * #O ≤ #A := le_of_mul_le_mul_right key (by positivity) + exact_mod_cast this + +/-- **Corrected pilot columns have few large entries** [OpenAI2026LogSpace, Lemma 4.3 (3)]. Under +the hypotheses of `Matrix.le_columnDetector` with row-sum bound `k`, if `γ` vanishes from `4 / 5` +on and the pilot multiplier `γ (M_(i+1) y)` of step `i + 1 ≤ k` is positive, then the pilot input +of that step has at most `R / f` entries at least `δ₁ f` in column `y`. -/ +theorem card_le_of_pilot_pos (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) (hf : 0 < f) + (hcπ : 0 < cπ) (hCpair : 0 ≤ Cpair) {δ₁ : ℝ} (hϕδ : ∀ t, δ₁ ≤ t → ϕ t = 1) + (hρ1 : ∀ t, ρ t ≤ 1) {η : ℝ} (hη : 0 < η) (hρη : ∀ t, t ≤ η → ρ t = 1) + (hC0 : ∀ x y, 0 ≤ C x y) (hC1 : C *ᵥ 1 ≤ 1) (hc0 : ∀ t, 0 ≤ c t) + (hct : ∀ t, 0 ≤ t → c t ≤ t) (hγ0 : ∀ t, 0 ≤ γ t) (hγ1 : ∀ t, γ t ≤ 1) + (hγ45 : ∀ t, 4 / 5 ≤ t → γ t = 0) {k : ℕ} (hK : 160 * (1 + Cpair * k / η) ≤ K) + (hJ : 0 < J) {R : ℝ} (hRJ : 4 * J ≤ cπ * R) (hRvar : 40 * Cvar ≤ cπ * R) {i : ℕ} + (hi : i < k) {y : V} + (hpos : 0 < γ (pilotMax c γ (columnDetector X Y ϕ ρ J K f) C (i + 1) y)) : + (#({x | δ₁ * f ≤ pilotInput c γ (columnDetector X Y ϕ ρ J K f) C i x y} : Finset V) : ℝ) ≤ + R / f := by + set U := columnDetector X Y ϕ ρ J K f + have hseq := isCorrectionSeq_pilotCorrection (U := U) hC0 hc0 hct hγ0 hγ1 + by_contra hlt + have hrow : ∀ x, ∑ w, pilotInput c γ U C i x w ≤ (k : ℝ) := fun x => by + have := (hseq.sum_input_le hC1 i x).1 + have hik : (i : ℝ) + 1 ≤ k := by exact_mod_cast hi + exact this.trans hik + have hU : 19 / 20 ≤ U (pilotInput c γ U C i) y := + le_columnDetector hch hf hcπ hCpair hϕδ hρ1 hη hρη (hseq.input_nonneg hC0 i) hrow hK hJ hRJ + hRvar (not_le.mp hlt) + have hM : 4 / 5 ≤ pilotMax c γ U C (i + 1) y := by + rw [pilotMax_succ, Pi.sup_apply] + exact le_sup_of_le_right (by linarith) + rw [hγ45 _ hM] at hpos + exact lt_irrefl _ hpos + +/-- **Corrected columns have few large entries** [OpenAI2026LogSpace, Lemma 4.3 (3)]: if the +final multiplier `γ (M_k y)` is positive, then for every `i < k` the input of step `i + 1` of the +actual correction, with cutoffs `c t * γ (M_k y)`, has at most `R / f` entries at least `δ₁ f` in +column `y`. -/ +theorem card_le_of_multiplier_pos (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) + (hf : 0 < f) (hcπ : 0 < cπ) (hCpair : 0 ≤ Cpair) {δ₁ : ℝ} (hϕδ : ∀ t, δ₁ ≤ t → ϕ t = 1) + (hρ1 : ∀ t, ρ t ≤ 1) {η : ℝ} (hη : 0 < η) (hρη : ∀ t, t ≤ η → ρ t = 1) + (hC0 : ∀ x y, 0 ≤ C x y) (hC1 : C *ᵥ 1 ≤ 1) (hc0 : ∀ t, 0 ≤ c t) + (hct : ∀ t, 0 ≤ t → c t ≤ t) (hcm : Monotone c) (hγ0 : ∀ t, 0 ≤ γ t) (hγ1 : ∀ t, γ t ≤ 1) + (hγm : Antitone γ) (hγ45 : ∀ t, 4 / 5 ≤ t → γ t = 0) {k : ℕ} + (hK : 160 * (1 + Cpair * k / η) ≤ K) (hJ : 0 < J) {R : ℝ} (hRJ : 4 * J ≤ cπ * R) + (hRvar : 40 * Cvar ≤ cπ * R) {y : V} + (hpos : 0 < γ (pilotMax c γ (columnDetector X Y ϕ ρ J K f) C k y)) {i : ℕ} (hi : i < k) : + let M := pilotMax c γ (columnDetector X Y ϕ ρ J K f) C k + (#({x | δ₁ * f ≤ (C + cutoffCorrectionIter (fun y t => c t * γ (M y)) C i * C) x y} : + Finset V) : ℝ) ≤ R / f := by + intro M + set U := columnDetector X Y ϕ ρ J K f + have hstep : 0 < γ (pilotMax c γ U C (i + 1) y) := + hpos.trans_le (hγm (pilotMax_mono (by omega) y)) + refine le_trans ?_ (card_le_of_pilot_pos hch hf hcπ hCpair hϕδ hρ1 hη hρη hC0 hC1 hc0 hct + hγ0 hγ1 hγ45 hK hJ hRJ hRvar hi hstep) + refine Nat.cast_le.mpr (card_le_card fun x hx => ?_) + simp only [mem_filter, mem_univ, true_and] at hx ⊢ + exact hx.trans (cutoffCorrectionIter_le_pilotCorrection hC0 hc0 hct hcm hγ0 hγ1 hγm + hi.le x y).2 + +variable [DecidableEq V] [LinearOrder V] {θ L θ₂ : ℝ} {κ χ : ℝ → ℝ} {τ₀ τ₁ q : ℝ} + +/-- **One stage with detector-chosen multipliers and copies** +[OpenAI2026LogSpace, Proposition 4.5]. Run `k` pilot steps with the column detector, let `M` be +the final running maximum, correct `C` by `k` steps of the cutoffs `φ y t = c t * γ (M y)`, and +split the residual `D` with the copy weights `Matrix.detectorWeight κ M` and the overloaded set +`Matrix.overloaded M`. If the base cutoff satisfies the hypotheses of the factorial truncation +together with `t - θ₂ f ≤ c t`, `γ` is nonincreasing and one through `1 / 2`, `κ` is zero through +`1 / 4` and one from `1 / 2`, `2 C_π m k (k + 1) ≤ δ₀ J`, and the copy constants are chosen as in +`Matrix.copyStage_rates`, then the copy step has entries at most `f / q`, intertwines with its +projection, and is supported in at most `2 |A|` copies. -/ +theorem detectedStage_rates (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) + (hC : C.IsStrictUpperTriangular) (hC0 : ∀ x y, 0 ≤ C x y) (hCf : ∀ x y, C x y ≤ f) + (hC1 : C *ᵥ 1 ≤ 1) {A : Finset V} (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) (hf : 0 < f) + (hc0 : ∀ t, 0 ≤ c t) (hcθ : ∀ t, c t ≤ max (t - θ * f) 0) (hcm : Monotone c) + (hcL : ∀ s t, s ≤ t → c t - c s ≤ L * (t - s)) (hcθ₂ : ∀ t, t - θ₂ * f ≤ c t) (hθ : 0 < θ) + (hL : 0 ≤ L) (hγ0 : ∀ t, 0 ≤ γ t) (hγ1 : ∀ t, γ t ≤ 1) (hγhalf : ∀ t, t ≤ 1 / 2 → γ t = 1) + (hκ0 : ∀ t, 0 ≤ κ t) (hκ1 : ∀ t, κ t ≤ 1) (hκq : ∀ t, t ≤ 1 / 4 → κ t = 0) + (hκhalf : ∀ t, 1 / 2 < t → κ t = 1) (hCπ : 0 < Cπ) (hϕ0 : ∀ t, 0 ≤ ϕ t) + (hϕ1 : ∀ t, ϕ t ≤ 1) {δ₀ : ℝ} (hδ₀ : 0 < δ₀) (hϕδ : ∀ t, t ≤ δ₀ → ϕ t = 0) + (hρ1 : ∀ t, ρ t ≤ 1) (hJ : 0 < J) {k m : ℕ} (hJm : 2 * Cπ * m * k * (k + 1) ≤ δ₀ * J) + (hτ₀ : θ₂ * f + f * Real.exp (1 / θ) * (L / θ) ^ k / k.factorial ≤ τ₀) + (hχ0 : ∀ t, 0 ≤ χ t) (hχ1 : ∀ t, χ t ≤ 1) (hχ₀ : ∀ t, t ≤ τ₀ → χ t = 0) + (hχ₁ : ∀ t, τ₁ ≤ t → χ t = 1) (hτ₁ : τ₁ ≤ f / q) (hcopies : (k + 1) * f / (m + 1) ≤ f / q) : + let M := pilotMax c γ (columnDetector X Y ϕ ρ J K f) C k + let E := cutoffCorrectionIter (fun y t => c t * γ (M y)) C k + let D := C - E + E * C + (∀ a b, copyStage χ m (detectorWeight κ M) D a b ≤ f / q) ∧ + copyStage χ m (detectorWeight κ M) D * copyWeight (detectorWeight κ M) = + copyWeight (detectorWeight κ M) * D ∧ + (∀ a b, copyStage χ m (detectorWeight κ M) D a b ≠ 0 → + a ∈ copyCover A (overloaded M) ∧ b ∈ copyCover A (overloaded M)) ∧ + #(copyCover (m := m) A (overloaded M)) ≤ 2 * #A := by + intro M E D + have hct : ∀ t, 0 ≤ t → c t ≤ t := fun t ht => + (hcθ t).trans (max_le (by nlinarith [mul_pos hθ hf]) ht) + have hO := card_overloaded_le (K := K) (k := k) (m := m) hch hf hCπ hϕ0 hϕ1 hδ₀ hϕδ hρ1 hJ hC0 + hC1 hA hc0 hct hγ0 hγ1 hJm + refine copyStage_rates (φ := fun y t => c t * γ (M y)) (θ := θ) (L := L) (m := m) (χ := χ) + (τ₀ := τ₀) (τ₁ := τ₁) (r := detectorWeight κ M) (A := A) (O := overloaded M) (θ₂ := θ₂) + (q := q) hC hC0 hCf hC1 + (fun y t => mul_nonneg (hc0 t) (hγ0 _)) + (fun y t => (mul_le_of_le_one_right (hc0 t) (hγ1 _)).trans (hcθ t)) + (fun y => hcm.mul_const (hγ0 _)) + (fun y s t hst => ?_) hf hθ hL k hA (fun x => by simp [detectorWeight]) + (fun j x => ?_) (fun j x hj hr => ?_) (fun y => ?_) hτ₀ hχ0 hχ1 hχ₀ hχ₁ hτ₁ hcopies hO + · -- the cutoffs are `L`-Lipschitz + have hmono : 0 ≤ c t - c s := sub_nonneg.mpr (hcm hst) + calc c t * γ (M y) - c s * γ (M y) = γ (M y) * (c t - c s) := by ring + _ ≤ 1 * (c t - c s) := mul_le_mul_of_nonneg_right (hγ1 _) hmono + _ ≤ L * (t - s) := by rw [one_mul]; exact hcL s t hst + · -- the weights lie in `[0, 1]` + unfold detectorWeight + split_ifs + · exact ⟨zero_le_one, le_rfl⟩ + · exact ⟨hκ0 _, hκ1 _⟩ + · -- only overloaded vertices have active extra copies + simp only [detectorWeight, hj, ↓reduceIte] at hr + simp only [overloaded, mem_filter, mem_univ, true_and] + by_contra hle + exact hr (hκq _ (not_lt.mp hle)) + · -- every column is fully corrected or overloaded with all copies active + by_cases hg : γ (M y) = 1 + · left + intro t + simp only [hg, mul_one] + exact hcθ₂ t + · right + have hhalf : 1 / 2 < M y := by + by_contra hle + exact hg (hγhalf _ (not_lt.mp hle)) + refine ⟨fun j => ?_, ?_⟩ + · unfold detectorWeight + split_ifs + · rfl + · exact hκhalf _ hhalf + · simp only [overloaded, mem_filter, mem_univ, true_and] + linarith + +end Matrix diff --git a/ComplexityTests/Detectors.lean b/ComplexityTests/Detectors.lean new file mode 100644 index 000000000..fc8731cde --- /dev/null +++ b/ComplexityTests/Detectors.lean @@ -0,0 +1,215 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ +import Complexity.Foundations.Probability.DetectedStage +import Mathlib.Analysis.SpecialFunctions.Exponential +import Mathlib.Analysis.Complex.ExponentialBounds +import Mathlib.Tactic.FinCases + +/-! +# Tests for the pilot, the column detectors and a detected stage +-/ + +namespace ComplexityTests.Detectors + +open Finset Matrix Cslib.Probability + +/-! ### Channels that retain every vertex -/ + +/-- A channel with one seed that retains every vertex. -/ +private abbrev all {V : Type*} : Unit → V → Prop := fun _ _ => True + +/-- Channels that retain everything satisfy the channel interface at every rate `f ∈ (0, 1]`, with +`c_π = 1`, `C_π = C_pair = 1 / f` and `C_var = 0`. -/ +private theorem retentionChannels_all {V : Type*} {f : ℝ} (hf : 0 < f) (hf1 : f ≤ 1) : + RetentionChannels (all (V := V)) all f 1 1 (1 / f) (1 / f) 0 where + dens_X _ := by simp [all] + dens_Y _ := by simp [all] + lower := by simpa using hf1 + upper := by rw [one_div_mul_cancel hf.ne'] + pair _ _ _ := by simp [all, hf.ne'] + tail A _ := by + have : ({s | 2 * (#{x ∈ A | all s x} : ℝ) < #A * 1} : Finset Unit) = ∅ := by + ext s + simp only [all, filter_true, mul_one, mem_filter, mem_univ, true_and, notMem_empty, + iff_false, not_lt] + linarith [(Nat.cast_nonneg (α := ℝ) #A)] + rw [this] + simp + +/-! ### Step cutoffs -/ + +/-- The step `0` through `a`, `1` above. -/ +private noncomputable def up (a t : ℝ) : ℝ := if t ≤ a then 0 else 1 + +/-- The step `1` through `a`, `0` above. -/ +private noncomputable def down (a t : ℝ) : ℝ := if t ≤ a then 1 else 0 + +private theorem up_nonneg (a t : ℝ) : 0 ≤ up a t := by unfold up; split_ifs <;> norm_num +private theorem up_le_one (a t : ℝ) : up a t ≤ 1 := by unfold up; split_ifs <;> norm_num +private theorem up_of_le {a t : ℝ} (h : t ≤ a) : up a t = 0 := by simp only [up, h, ↓reduceIte] +private theorem up_of_lt {a t : ℝ} (h : a < t) : up a t = 1 := by + simp only [up, not_le.mpr h, ↓reduceIte] +private theorem down_nonneg (a t : ℝ) : 0 ≤ down a t := by unfold down; split_ifs <;> norm_num +private theorem down_le_one (a t : ℝ) : down a t ≤ 1 := by unfold down; split_ifs <;> norm_num +private theorem down_of_le {a t : ℝ} (h : t ≤ a) : down a t = 1 := by + simp only [down, h, ↓reduceIte] +private theorem down_antitone (a : ℝ) : Antitone (down a) := fun s t hst => by + unfold down; split_ifs with h1 h2 <;> first | exact absurd (hst.trans h1) h2 | norm_num + +/-! ### The detector lemma on a concrete column -/ + +/-- Rows `0, …, 4` each have one entry `1 / 5`, in column `5`. -/ +private noncomputable def G : Matrix (Fin 6) (Fin 6) ℝ := + of fun x y => if y = 5 ∧ x ≠ 5 then 1 / 5 else 0 + +private theorem G0 : ∀ x w, 0 ≤ G x w := by + intro x w; simp only [G, of_apply]; split_ifs <;> norm_num + +private theorem G_row : ∀ x, ∑ w, G x w ≤ (1 : ℝ) := by + intro x; fin_cases x <;> simp [G] <;> norm_num + +-- Column `5` has five entries `1 / 5 ≥ δ₁ f` with `f = 1` and `δ₁ = 1 / 6`, more than +-- `R / f = 4`, so its detector number is at least `19 / 20`. The score is the step at `1 / 10`, +-- the gate the step at `η = 1 / 2`, and the gate rank `K = 480 ≥ 160 (1 + 1 / (1 / 2))`. +example : 19 / 20 ≤ columnDetector all all (up (1 / 10)) (down (1 / 2)) 1 480 1 G 5 := by + have hcount : (4 : ℝ) / 1 < #(univ.filter fun x => 1 / 6 * 1 ≤ G x 5) := by + have hsub : (univ.erase 5 : Finset (Fin 6)) ⊆ univ.filter fun x => 1 / 6 * 1 ≤ G x 5 := + fun x hx => by + have hx5 : x ≠ 5 := ne_of_mem_erase hx + simp only [mem_filter, mem_univ, true_and, G, of_apply, hx5, ne_eq, not_false_eq_true, + ↓reduceIte] + norm_num + have := card_le_card hsub + rw [card_erase_of_mem (mem_univ _), card_univ, Fintype.card_fin] at this + have : (5 : ℝ) ≤ #(univ.filter fun x => 1 / 6 * 1 ≤ G x 5) := by exact_mod_cast this + linarith + exact le_columnDetector (J := 1) (K := 480) (G := G) (R := 4) + (retentionChannels_all (V := Fin 6) one_pos le_rfl) one_pos one_pos (by norm_num) + (δ₁ := 1 / 6) (fun t ht => up_of_lt (by linarith)) (down_le_one _) + (by norm_num : (0 : ℝ) < 1 / 2) (fun t ht => down_of_le ht) G0 G_row (by norm_num) + one_pos (by norm_num) (by norm_num) hcount + +-- An empty column has no substantial entries, so its detector number is at most `1 / 4`. +example : columnDetector all all (up (1 / 10)) (down (1 / 2)) 1 480 1 G 0 ≤ 1 / 4 := by + refine not_lt.mp fun h => ?_ + have := lt_card_of_lt_columnDetector (J := 1) (K := 480) (G := G) + (retentionChannels_all (V := Fin 6) one_pos le_rfl) one_pos (up_nonneg _) (up_le_one _) + (fun t ht => up_of_le ht) (down_le_one _) one_pos h + have hempty : (univ.filter fun x => 1 / 10 * 1 < G x 0) = ∅ := by + ext x; simp only [G, of_apply, Fin.reduceEq, false_and, ↓reduceIte, mem_filter, mem_univ, + true_and, notMem_empty, iff_false, not_lt]; norm_num + rw [hempty, card_empty, Nat.cast_zero] at this + norm_num at this + +/-! ### A stage of the hierarchy with detector-chosen multipliers -/ + +/-- A walk on three time layers: from `0` to `1` and from `1` to `2`, each with probability +`f = 1 / 2`. -/ +private noncomputable def C : Matrix (Fin 3) (Fin 3) ℝ := !![0, 1 / 2, 0; 0, 0, 1 / 2; 0, 0, 0] + +private theorem hC : C.IsStrictUpperTriangular := by + intro i j h; fin_cases i <;> fin_cases j <;> simp_all [C] + +private theorem hC0 : ∀ x y, 0 ≤ C x y := by + intro x y; fin_cases x <;> fin_cases y <;> norm_num [C] + +private theorem hCf : ∀ x y, C x y ≤ 1 / 2 := by + intro x y; fin_cases x <;> fin_cases y <;> norm_num [C] + +private theorem hC1 : C *ᵥ 1 ≤ 1 := by + intro x; fin_cases x <;> norm_num [C, mulVec, dotProduct, Fin.sum_univ_three] + +/-- The hard base cutoff `t ↦ max (t - θ f) 0` with `θ = 1 / 4`, `f = 1 / 2`. -/ +private noncomputable def c (t : ℝ) : ℝ := max (t - 1 / 8) 0 + +private theorem hcL : ∀ s t, s ≤ t → c t - c s ≤ 1 * (t - s) := fun s t _ => by + simp only [c, one_mul] + have := le_max_left (s - 1 / 8) 0 + have := le_max_right (s - 1 / 8) 0 + have : max (t - 1 / 8) 0 ≤ max (s - 1 / 8) 0 + (t - s) := max_le (by linarith) (by linarith) + linarith + +private theorem c_nonneg (t : ℝ) : 0 ≤ c t := le_max_right _ _ +private theorem c_le (t : ℝ) (ht : 0 ≤ t) : c t ≤ t := max_le (by linarith) ht +private theorem c_mono : Monotone c := fun _ _ h => max_le_max (by linarith) le_rfl + +/-! ### The pilot -/ + +/-- A column number that flags column `2`, whatever the input. -/ +private noncomputable def flag2 : Matrix (Fin 3) (Fin 3) ℝ → Fin 3 → ℝ := + fun _ y => if y = 2 then 1 else 0 + +-- After one pilot step the running maximum flags column `2`, which loses its multiplier. +example : pilotMax c (down (1 / 2)) flag2 C 1 2 = 1 := by + rw [pilotMax_succ]; norm_num [flag2] + +-- Column `1` is corrected, `Ê₁ (0, 1) = c (1 / 2) = 3 / 8`; column `2` is not. +example : pilotCorrection c (down (1 / 2)) flag2 C 1 0 1 = 3 / 8 := by + rw [pilotCorrection_succ_apply, pilotMax_succ] + norm_num [pilotInput, flag2, c, C, down] + +example : pilotCorrection c (down (1 / 2)) flag2 C 1 1 2 = 0 := by + rw [pilotCorrection_succ_apply, pilotMax_succ] + norm_num [flag2, down] + +-- The pilot corrections have row sums at most the step count. +example (x : Fin 3) : ∑ y, pilotCorrection c (down (1 / 2)) flag2 C 2 x y ≤ 2 := by + exact_mod_cast (isCorrectionSeq_pilotCorrection hC0 c_nonneg c_le (down_nonneg _) + (down_le_one _)).sum_le hC1 2 x + +-- The actual correction with the final multiplier stays below the pilot. +example (x y : Fin 3) : + cutoffCorrectionIter (fun y t => c t * down (1 / 2) (pilotMax c (down (1 / 2)) flag2 C 2 y)) + C 1 x y ≤ pilotCorrection c (down (1 / 2)) flag2 C 1 x y := + (cutoffCorrectionIter_le_pilotCorrection hC0 c_nonneg c_le c_mono (down_nonneg _) + (down_le_one _) (down_antitone _) (by norm_num : 1 ≤ 2) x y).1 + +/-! ### One stage -/ + +/-- `e ^ 4 · 4 ^ 15 / 15! ≤ 1 / 8`: fifteen iterations make the truncation error small. -/ +private theorem factorial_bound : + (1 / 2 : ℝ) * Real.exp (1 / (1 / 4)) * (1 / (1 / 4)) ^ 15 / (Nat.factorial 15) ≤ 1 / 16 := by + have he : Real.exp 4 ≤ 55 := by + have h1 : Real.exp 4 = Real.exp 1 ^ 4 := by rw [← Real.exp_nat_mul]; norm_num + rw [h1] + calc Real.exp 1 ^ 4 ≤ 2.7182818286 ^ 4 := + pow_le_pow_left₀ (Real.exp_pos 1).le Real.exp_one_lt_d9.le 4 + _ ≤ 55 := by norm_num + norm_num [Nat.factorial] + nlinarith + +-- One stage with `k = 15` pilot and correction steps, `m + 1 = 32` copies, the full-retention +-- channels at rate `f = 1 / 2`, the detector score `up (1 / 10)` with `δ₀ = 1 / 10` and rank +-- `J = 297600 ≥ 2 C_π m k (k + 1) / δ₀`: the copies have entries at most `f / q = 1 / 4`, +-- intertwine with their projection, and at most `2 · 3` of them are active. +example : + let M := pilotMax c (down (1 / 2)) (columnDetector all all (up (1 / 10)) (down (1 / 2)) 297600 + 1 (1 / 2)) C 15 + let E := cutoffCorrectionIter (fun y t => c t * down (1 / 2) (M y)) C 15 + let D := C - E + E * C + (∀ a b, copyStage (up (3 / 16)) 31 (detectorWeight (up (1 / 4)) M) D a b ≤ 1 / 2 / 2) ∧ + copyStage (up (3 / 16)) 31 (detectorWeight (up (1 / 4)) M) D * + copyWeight (detectorWeight (up (1 / 4)) M) = + copyWeight (detectorWeight (up (1 / 4)) M) * D ∧ + (∀ a b, copyStage (up (3 / 16)) 31 (detectorWeight (up (1 / 4)) M) D a b ≠ 0 → + a ∈ copyCover univ (overloaded M) ∧ b ∈ copyCover univ (overloaded M)) ∧ + #(copyCover (m := 31) (univ : Finset (Fin 3)) (overloaded M)) ≤ + 2 * #(univ : Finset (Fin 3)) := + detectedStage_rates (X := all) (Y := all) (ϕ := up (1 / 10)) (ρ := down (1 / 2)) (J := 297600) + (K := 1) (f := 1 / 2) (c := c) (γ := down (1 / 2)) (C := C) (A := univ) (κ := up (1 / 4)) + (χ := up (3 / 16)) (q := 2) (k := 15) (m := 31) (θ := 1 / 4) (L := 1) (θ₂ := 1 / 4) + (τ₀ := 3 / 16) (τ₁ := 1 / 4) (δ₀ := 1 / 10) + (retentionChannels_all (V := Fin 3) (by norm_num) (by norm_num)) hC hC0 hCf hC1 + (fun _ _ _ => ⟨mem_univ _, mem_univ _⟩) (by norm_num) c_nonneg + (fun t => le_of_eq (by norm_num [c])) c_mono hcL + (fun t => by norm_num [c]) (by norm_num) zero_le_one (down_nonneg _) (down_le_one _) + (fun t ht => down_of_le ht) (up_nonneg _) (up_le_one _) (fun t ht => up_of_le ht) + (fun t ht => up_of_lt (by linarith)) (by norm_num) (up_nonneg _) (up_le_one _) (by norm_num) + (fun t ht => up_of_le ht) (down_le_one _) (by norm_num) (by norm_num) + (by linarith [factorial_bound]) (up_nonneg _) (up_le_one _) (fun t ht => up_of_le ht) + (fun t ht => up_of_lt (by linarith)) (by norm_num) (by norm_num) + +end ComplexityTests.Detectors diff --git a/ComplexityTests/KthLargest.lean b/ComplexityTests/KthLargest.lean new file mode 100644 index 000000000..7dac815a7 --- /dev/null +++ b/ComplexityTests/KthLargest.lean @@ -0,0 +1,53 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ +import Complexity.Foundations.Data.Finset.KthLargest +import Mathlib.Algebra.Order.Ring.Rat +import Mathlib.Data.Fin.VecNotation +import Mathlib.Data.Fintype.Basic +import Mathlib.Tactic.FinCases +import Mathlib.Tactic.NormNum + +/-! +# Tests for the `k`-th largest value +-/ + +namespace ComplexityTests.KthLargest + +open Finset + +/-- The values `3, 1, 2, 0`. -/ +private def h : Fin 4 → ℚ := ![3, 1, 2, 0] + +private theorem filter_two_lt : (univ.filter fun x => (2 : ℚ) < h x) = {0} := by + decide + +private theorem filter_two_le : (univ.filter fun x => (2 : ℚ) ≤ h x) = {0, 2} := by + decide + +private theorem filter_zero_lt : (univ.filter fun x => (0 : ℚ) < h x) = {0, 1, 2} := by + decide + +-- The second largest of `3, 1, 2, 0` is `2`: two values are at least `2`, one exceeds it. +example : kthLargest 2 univ h = 2 := by + refine le_antisymm (not_lt.mp fun hlt => ?_) ?_ + · have := (lt_kthLargest_iff (by norm_num) (by norm_num)).mp hlt + rw [filter_two_lt, card_singleton] at this + omega + · rw [le_kthLargest_iff (by norm_num) (by norm_num), filter_two_le] + rfl + +-- Only three values are positive, so the padded fourth largest is `0`. +example : kthLargest 4 univ h = 0 := by + refine le_antisymm (not_lt.mp fun hlt => ?_) kthLargest_nonneg + have := (lt_kthLargest_iff (by norm_num) le_rfl).mp hlt + rw [filter_zero_lt] at this + exact absurd this (by decide) + +-- Values above a nonnegative bound bound the order statistic. +example (k : ℕ) : kthLargest k univ h ≤ 3 := + kthLargest_le (by norm_num) fun x _ => by fin_cases x <;> norm_num [h] + +end ComplexityTests.KthLargest From 80b604b4b2d9f650f1c5442bd133025c2e998f00 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 01:08:54 +0000 Subject: [PATCH 11/18] refactor(Foundations): derive fixed-multiplier iterate bounds from IsCorrectionSeq The row-sum, entry and input bounds of cutoffCorrectionIter in CopyStage are the fixed-multiplier case of the correction-sequence bounds; reuse them instead of re-proving. Statements are unchanged. Co-Authored-By: Claude Opus 5.5 --- .../LinearAlgebra/Matrix/CopyStage.lean | 58 ++++--------------- 1 file changed, 10 insertions(+), 48 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean index aaad7308f..d61617c73 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean @@ -8,6 +8,7 @@ module -- upstream: candidate public import Complexity.Foundations.LinearAlgebra.Matrix.FactorialTruncation +import Complexity.Foundations.LinearAlgebra.Matrix.PilotCorrection import Mathlib.Algebra.BigOperators.Fin /-! @@ -95,65 +96,24 @@ variable {V : Type*} [Fintype V] {φ : V → ℝ → ℝ} {C : Matrix V V ℝ} { variable (hC0 : ∀ x y, 0 ≤ C x y) (hφ0 : ∀ y t, 0 ≤ φ y t) (hφθ : ∀ y t, φ y t ≤ max (t - θ * f) 0) (hθf : 0 ≤ θ * f) -omit [Fintype V] in -include hφθ hθf in -private theorem cutoff_le_self' (y : V) {t : ℝ} (ht : 0 ≤ t) : φ y t ≤ t := - (hφθ y t).trans (max_le (by linarith) ht) - omit [Fintype V] in include hφ0 hφθ hθf in private theorem cutoff_zero (y : V) : φ y 0 = 0 := le_antisymm ((hφθ y 0).trans (max_le (by linarith) le_rfl)) (hφ0 y 0) -include hC0 hφ0 hφθ hθf in -private theorem iter_succ_le_input (k : ℕ) (x y : V) : - cutoffCorrectionIter φ C (k + 1) x y ≤ (C + cutoffCorrectionIter φ C k * C) x y := by - rw [cutoffCorrectionIter_succ] - exact cutoff_le_self' hφθ hθf y <| add_nonneg (hC0 x y) <| Finset.sum_nonneg fun z _ => - mul_nonneg (cutoffCorrectionIter_nonneg hφ0 k x z) (hC0 z y) - include hC0 hφ0 hφθ hθf in /-- **Row sums of the iterates**: the `k`-th iterate of a cutoff correction of a substochastic `C` has row sums at most `k` [OpenAI2026LogSpace, Lemma 4.2]. -/ theorem cutoffCorrectionIter_sum_le (hC1 : C *ᵥ 1 ≤ 1) (k : ℕ) (x : V) : - ∑ y, cutoffCorrectionIter φ C k x y ≤ k := by - have hrow : ∀ z, ∑ y, C z y ≤ 1 := fun z => by simpa [mulVec, dotProduct] using hC1 z - induction k with - | zero => simp [cutoffCorrectionIter] - | succ k ih => - set F := cutoffCorrectionIter φ C k - calc ∑ y, cutoffCorrectionIter φ C (k + 1) x y ≤ ∑ y, (C + F * C) x y := - Finset.sum_le_sum fun y _ => iter_succ_le_input hC0 hφ0 hφθ hθf k x y - _ = ∑ y, C x y + ∑ z, F x z * ∑ y, C z y := by - simp only [add_apply, mul_apply, Finset.sum_add_distrib, Finset.mul_sum] - rw [Finset.sum_comm] - _ ≤ 1 + ∑ z, F x z * 1 := add_le_add (hrow x) (Finset.sum_le_sum fun z _ => - mul_le_mul_of_nonneg_left (hrow z) (cutoffCorrectionIter_nonneg hφ0 k x z)) - _ ≤ (k + 1 : ℕ) := by simp only [mul_one]; push_cast; linarith - -include hC0 hφ0 hφθ hθf in -/-- The input `(C + E_k C) x y` of the `(k + 1)`-th step is at most `(k + 1) f`. -/ -private theorem input_le (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) (hC1 : C *ᵥ 1 ≤ 1) (k : ℕ) - (x y : V) : (C + cutoffCorrectionIter φ C k * C) x y ≤ (k + 1) * f := by - have hsum := cutoffCorrectionIter_sum_le hC0 hφ0 hφθ hθf hC1 k x - calc (C + cutoffCorrectionIter φ C k * C) x y - = C x y + ∑ z, cutoffCorrectionIter φ C k x z * C z y := rfl - _ ≤ f + ∑ z, cutoffCorrectionIter φ C k x z * f := add_le_add (hCf x y) - (Finset.sum_le_sum fun z _ => - mul_le_mul_of_nonneg_left (hCf z y) (cutoffCorrectionIter_nonneg hφ0 k x z)) - _ ≤ (k + 1) * f := by rw [← Finset.sum_mul]; nlinarith + ∑ y, cutoffCorrectionIter φ C k x y ≤ k := + (isCorrectionSeq_cutoffCorrectionIter hC0 hφ0 hφθ hθf).sum_le hC1 k x include hC0 hφ0 hφθ hθf in /-- **Entries of the iterates**: the `k`-th iterate has entries at most `k f` [OpenAI2026LogSpace, Lemma 4.2]. -/ theorem cutoffCorrectionIter_le_mul (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) (hC1 : C *ᵥ 1 ≤ 1) - (k : ℕ) (x y : V) : cutoffCorrectionIter φ C k x y ≤ k * f := by - cases k with - | zero => simp [cutoffCorrectionIter] - | succ k => - push_cast - exact (iter_succ_le_input hC0 hφ0 hφθ hθf k x y).trans - (input_le hC0 hφ0 hφθ hθf hCf hf hC1 k x y) + (k : ℕ) (x y : V) : cutoffCorrectionIter φ C k x y ≤ k * f := + (isCorrectionSeq_cutoffCorrectionIter hC0 hφ0 hφθ hθf).le_mul hCf hf hC1 k x y include hC0 hφ0 hφθ hθf in /-- **The residual entry bound**: `C - E_k + E_k C` has entries at most `(k + 1) f` @@ -161,7 +121,8 @@ include hC0 hφ0 hφθ hθf in theorem cutoffCorrection_residual_le_mul (hCf : ∀ x y, C x y ≤ f) (hf : 0 ≤ f) (hC1 : C *ᵥ 1 ≤ 1) (k : ℕ) (x y : V) : (C - cutoffCorrectionIter φ C k + cutoffCorrectionIter φ C k * C) x y ≤ (k + 1) * f := by - have h := input_le hC0 hφ0 hφθ hθf hCf hf hC1 k x y + have h := (isCorrectionSeq_cutoffCorrectionIter hC0 hφ0 hφθ hθf).input_le_mul hCf hf hC1 k + x y have h0 := cutoffCorrectionIter_nonneg (C := C) hφ0 k x y simp only [add_apply, sub_apply] at h ⊢ linarith @@ -180,12 +141,13 @@ theorem cutoffCorrection_residual_dominates (hCf : ∀ x y, C x y ≤ f) (hf : 0 have ha0 : 0 ≤ (C + cutoffCorrectionIter φ C k * C) x y := add_nonneg (hC0 x y) (Finset.sum_nonneg fun z _ => mul_nonneg (cutoffCorrectionIter_nonneg hφ0 k x z) (hC0 z y)) - have ha := input_le hC0 hφ0 hφθ hθf hCf hf hC1 k x y + have ha := (isCorrectionSeq_cutoffCorrectionIter hC0 hφ0 hφθ hθf).input_le_mul hCf hf hC1 k + x y have hEa : cutoffCorrectionIter φ C (k + 1) x y = φ y ((C + cutoffCorrectionIter φ C k * C) x y) := by rw [cutoffCorrectionIter_succ]; rfl have he0 := cutoffCorrectionIter_nonneg (C := C) hφ0 (k + 1) x y - have hea := iter_succ_le_input hC0 hφ0 hφθ hθf k x y + have hea := (isCorrectionSeq_cutoffCorrectionIter hC0 hφ0 hφθ hθf).le_input k x y have hFE : (cutoffCorrectionIter φ C k * C) x y ≤ (cutoffCorrectionIter φ C (k + 1) * C) x y := Finset.sum_le_sum fun z _ => mul_le_mul_of_nonneg_right (cutoffCorrectionIter_le_succ hC0 hφ0 hφm k x z) (hC0 z y) From 5d3394d725d50d1e78d52029c2133c0d71416514 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 01:27:19 +0000 Subject: [PATCH 12/18] feat(Foundations): constants of the correction-and-copy hierarchy Bundle the constants and cutoffs of one hierarchy stage with all conditions used by the stage lemmas, prove that they exist for every density divisor q > 0, and restate one detector-driven stage with the bundled constants. Co-Authored-By: Claude Opus 5.5 --- Complexity.lean | 2 + .../Probability/HierarchyParams.lean | 459 ++++++++++++++++++ 2 files changed, 461 insertions(+) create mode 100644 Complexity/Foundations/Probability/HierarchyParams.lean diff --git a/Complexity.lean b/Complexity.lean index 28144e01a..c07c6a329 100644 --- a/Complexity.lean +++ b/Complexity.lean @@ -2653,10 +2653,12 @@ public import Complexity.Foundations.Order.BooleanSubalgebra public import Complexity.Foundations.Order.Changes public import Complexity.Foundations.Order.UpperLower public import Complexity.Foundations.Probability.ColumnDetector +public import Complexity.Foundations.Probability.DetectedHierarchy public import Complexity.Foundations.Probability.DetectedStage public import Complexity.Foundations.Probability.Gaussian.Multivariate public import Complexity.Foundations.Probability.Gaussian.Real public import Complexity.Foundations.Probability.Gaussian.Sheppard +public import Complexity.Foundations.Probability.HierarchyParams public import Complexity.Foundations.Probability.SecondMoment public import Complexity.Foundations.Quantum.Measurement public import Complexity.Foundations.Relation.InductiveCounting diff --git a/Complexity/Foundations/Probability/HierarchyParams.lean b/Complexity/Foundations/Probability/HierarchyParams.lean new file mode 100644 index 000000000..14dc40da2 --- /dev/null +++ b/Complexity/Foundations/Probability/HierarchyParams.lean @@ -0,0 +1,459 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Foundations.Probability.DetectedStage +import Mathlib.Algebra.Order.Floor.Semiring + +/-! +# Constants for the correction-and-copy hierarchy + +One stage of the hierarchy of the OpenAI preprint (2026-09-23), Section 4 [OpenAI2026LogSpace], +is driven by finitely many constants and cutoff functions: the correction ramp `Q` with its +thresholds `θ ≤ θ₂` and Lipschitz constant `L`, the iteration count `k*`, the number of copies +`D₀ = m + 1`, the copy thresholds `τ₀ < τ₁`, the detector thresholds `δ₀ < δ₁` and `η`, the +detector ranks `J` and `K`, the count threshold `R*`, and the cutoffs `ϕ`, `ρ`, `γ`, `κ`, `χ`. +`Matrix.HierarchyParams q cπ Cπ Cpair Cvar` bundles them with every condition that the stage +lemmas need, for the density divisor `q` and the channel constants of +`Cslib.Probability.RetentionChannels`. All of them are fixed before the stage: the thresholds are +relative to the rate `f`, so the same parameters serve every stage. + +**Existence** (`Matrix.HierarchyParams.nonempty`). For every `q > 0` and channel constants with +`c_π > 0`, there are such parameters [OpenAI2026LogSpace, Remark 4.6]. The +choice follows the order of the preprint: first `θ = θ₂ = 1 / (4q)` and the hard ramp +`Q t = max (t - θ) 0`, then `k*` from the factorial bound (`Matrix.exists_factorial_bound_le`), +then `D₀ = ⌈q⌉ (k* + 1)`, then `J` from (4.24), and finally `K` and `R*` from Lemma 4.3. + +**One stage** (`Matrix.HierarchyParams.stage_rates`). At rate `f > 0`, the stage uses the cutoffs +`c t = f Q (t / f)` and `χ (t / f)` (`Matrix.HierarchyParams.cutoff`, +`Matrix.HierarchyParams.copyCutoff`), the detector-driven pilot +(`Matrix.HierarchyParams.pilot`), the corrected residual `D` +(`Matrix.HierarchyParams.residual`) and the copy weights (`Matrix.HierarchyParams.weight`). The +next transition matrix `Matrix.HierarchyParams.next`, indexed by `Lex (V × Fin (m + 1))`, has +entries at most `f / q`, is supported in at most twice as many vertices, intertwines with the +weighted projection, and is again strictly upper triangular and substochastic. The only +hypotheses are those on the input matrix and the channel interface. + +## Main definitions + +* `Matrix.HierarchyParams`: the constants and cutoffs of a stage, with their conditions. +* `Matrix.HierarchyParams.pilot`, `Matrix.HierarchyParams.residual`, + `Matrix.HierarchyParams.weight`, `Matrix.HierarchyParams.next`: one stage. + +## Main results + +* `Matrix.HierarchyParams.nonempty`: the constants exist for every `q > 0`. +* `Matrix.HierarchyParams.stage_rates`: one stage satisfies the per-stage rates. +* `Matrix.HierarchyParams.next_isStrictUpperTriangular`, `Matrix.HierarchyParams.next_nonneg`, + `Matrix.HierarchyParams.next_mulVec_one_le`: the next stage is again a valid input. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Lemma 4.1, Lemma 4.3, Proposition 4.5 and Remark 4.6 (preprint, not peer reviewed) +-/ + +public section + +open Finset Cslib.Probability + +namespace Matrix + +/-- **The constants and cutoffs of a stage** of the hierarchy, for the density divisor `q` and +the channel constants `cπ, Cπ, Cpair, Cvar`, with every condition used by the stage lemmas +[OpenAI2026LogSpace, Sections 4.1–4.4 and Remark 4.6]. Thresholds of the ramp `Q` and of the +copy cutoff `χ` are relative to the rate `f`. -/ +structure HierarchyParams (q cπ Cπ Cpair Cvar : ℝ) where + /-- The correction ramp: the cutoff at rate `f` is `t ↦ f Q (t / f)`. -/ + Q : ℝ → ℝ + /-- The threshold below which `Q` vanishes. -/ + θ : ℝ + /-- The threshold that `Q` leaves behind at most. -/ + θ₂ : ℝ + /-- A Lipschitz constant of `Q`. -/ + L : ℝ + /-- The number of correction iterations `k*`. -/ + k : ℕ + /-- The number of extra copies, `D₀ - 1`. -/ + m : ℕ + /-- The copy thresholds, relative to the rate. -/ + τ₀ : ℝ + τ₁ : ℝ + /-- The copy cutoff. -/ + χ : ℝ → ℝ + /-- The detector score thresholds and cutoff. -/ + δ₀ : ℝ + δ₁ : ℝ + ϕ : ℝ → ℝ + /-- The row-gate threshold and cutoff. -/ + η : ℝ + ρ : ℝ → ℝ + /-- The column multiplier and copy-weight cutoffs. -/ + γ : ℝ → ℝ + κ : ℝ → ℝ + /-- The detector ranks. -/ + J : ℕ + K : ℕ + /-- The column-count threshold `R*` of Lemma 4.3. -/ + R : ℝ + Q_nonneg : ∀ t, 0 ≤ Q t + Q_le : ∀ t, Q t ≤ max (t - θ) 0 + le_Q : ∀ t, t - θ₂ ≤ Q t + Q_mono : Monotone Q + Q_lipschitz : ∀ s t, s ≤ t → Q t - Q s ≤ L * (t - s) + θ_pos : 0 < θ + L_nonneg : 0 ≤ L + truncation : θ₂ + Real.exp (1 / θ) * (L / θ) ^ k / k.factorial ≤ τ₀ + χ_nonneg : ∀ t, 0 ≤ χ t + χ_le_one : ∀ t, χ t ≤ 1 + χ_zero : ∀ t, t ≤ τ₀ → χ t = 0 + χ_one : ∀ t, τ₁ ≤ t → χ t = 1 + τ₁_le : τ₁ ≤ 1 / q + copies : ((k : ℝ) + 1) / (m + 1) ≤ 1 / q + δ₀_pos : 0 < δ₀ + ϕ_nonneg : ∀ t, 0 ≤ ϕ t + ϕ_le_one : ∀ t, ϕ t ≤ 1 + ϕ_zero : ∀ t, t ≤ δ₀ → ϕ t = 0 + ϕ_one : ∀ t, δ₁ ≤ t → ϕ t = 1 + η_pos : 0 < η + ρ_le_one : ∀ t, ρ t ≤ 1 + ρ_one : ∀ t, t ≤ η → ρ t = 1 + γ_nonneg : ∀ t, 0 ≤ γ t + γ_le_one : ∀ t, γ t ≤ 1 + γ_antitone : Antitone γ + γ_one : ∀ t, t ≤ 1 / 2 → γ t = 1 + γ_zero : ∀ t, 4 / 5 ≤ t → γ t = 0 + κ_nonneg : ∀ t, 0 ≤ κ t + κ_le_one : ∀ t, κ t ≤ 1 + κ_zero : ∀ t, t ≤ 1 / 4 → κ t = 0 + κ_one : ∀ t, 1 / 2 < t → κ t = 1 + J_pos : 0 < J + rank : 2 * Cπ * m * k * (k + 1) ≤ δ₀ * J + gate : 160 * (1 + Cpair * k / η) ≤ K + R_rank : 4 * J ≤ cπ * R + R_var : 40 * Cvar ≤ cπ * R + +namespace HierarchyParams + +variable {q cπ Cπ Cpair Cvar : ℝ} + +/-- The step `0` through `a`, `1` above. -/ +private noncomputable def up (a t : ℝ) : ℝ := if t ≤ a then 0 else 1 + +/-- The step `1` through `a`, `0` above. -/ +private noncomputable def down (a t : ℝ) : ℝ := if t ≤ a then 1 else 0 + +private theorem up_nonneg (a t : ℝ) : 0 ≤ up a t := by unfold up; split_ifs <;> norm_num +private theorem up_le_one (a t : ℝ) : up a t ≤ 1 := by unfold up; split_ifs <;> norm_num +private theorem up_of_le {a t : ℝ} (h : t ≤ a) : up a t = 0 := by simp only [up, h, ↓reduceIte] +private theorem up_of_lt {a t : ℝ} (h : a < t) : up a t = 1 := by + simp only [up, not_le.mpr h, ↓reduceIte] +private theorem down_nonneg (a t : ℝ) : 0 ≤ down a t := by unfold down; split_ifs <;> norm_num +private theorem down_le_one (a t : ℝ) : down a t ≤ 1 := by unfold down; split_ifs <;> norm_num +private theorem down_of_le {a t : ℝ} (h : t ≤ a) : down a t = 1 := by + simp only [down, h, ↓reduceIte] +private theorem down_of_lt {a t : ℝ} (h : a < t) : down a t = 0 := by + simp only [down, not_le.mpr h, ↓reduceIte] +private theorem down_antitone (a : ℝ) : Antitone (down a) := fun s t hst => by + unfold down; split_ifs with h1 h2 <;> first | exact absurd (hst.trans h1) h2 | norm_num + +/-- **The constants exist** [OpenAI2026LogSpace, Remark 4.6]: for every density divisor `q > 0` +and channel constants with `c_π > 0`, there are stage parameters. They are chosen +in the order of the preprint: the ramp, then `k*` by factorial truncation, then the copies, then +the detector ranks `J` and `K`, then `R*`. -/ +theorem nonempty (hq : 0 < q) (hcπ : 0 < cπ) : + Nonempty (HierarchyParams q cπ Cπ Cpair Cvar) := by + have hq0 : 0 < q := hq + set θ : ℝ := 1 / (4 * q) + have hθ : 0 < θ := by positivity + obtain ⟨k, hk⟩ := exists_factorial_bound_le θ 1 (δ := 1 / (4 * q)) (by positivity) + set m : ℕ := ⌈q⌉₊ * (k + 1) + set J : ℕ := ⌈4 * Cπ * m * k * (k + 1)⌉₊ + 1 + set K : ℕ := ⌈160 * (1 + Cpair * k / (1 / 2))⌉₊ + set R : ℝ := (4 * J + 40 * |Cvar|) / cπ + have hR : 4 * (J : ℝ) + 40 * |Cvar| ≤ cπ * R := by + simp only [R]; rw [mul_div_cancel₀ _ hcπ.ne'] + refine ⟨{ + Q := fun t => max (t - θ) 0 + θ := θ + θ₂ := θ + L := 1 + k := k + m := m + τ₀ := 1 / (2 * q) + τ₁ := 1 / q + χ := up (1 / (2 * q)) + δ₀ := 1 / 2 + δ₁ := 1 + ϕ := up (1 / 2) + η := 1 / 2 + ρ := down (1 / 2) + γ := down (1 / 2) + κ := up (1 / 4) + J := J + K := K + R := R + Q_nonneg := fun _ => le_max_right _ _ + Q_le := fun _ => le_rfl + le_Q := fun _ => le_max_left _ _ + Q_mono := fun _ _ h => max_le_max (by linarith) le_rfl + Q_lipschitz := fun s t _ => ?_ + θ_pos := hθ + L_nonneg := zero_le_one + truncation := ?_ + χ_nonneg := up_nonneg _ + χ_le_one := up_le_one _ + χ_zero := fun _ h => up_of_le h + χ_one := fun t h => up_of_lt (lt_of_lt_of_le (by + rw [div_lt_div_iff_of_pos_left one_pos (by positivity) hq0]; linarith) h) + τ₁_le := le_rfl + copies := ?_ + δ₀_pos := by norm_num + ϕ_nonneg := up_nonneg _ + ϕ_le_one := up_le_one _ + ϕ_zero := fun _ h => up_of_le h + ϕ_one := fun t h => up_of_lt (by linarith) + η_pos := by norm_num + ρ_le_one := down_le_one _ + ρ_one := fun _ h => down_of_le h + γ_nonneg := down_nonneg _ + γ_le_one := down_le_one _ + γ_antitone := down_antitone _ + γ_one := fun _ h => down_of_le h + γ_zero := fun t h => down_of_lt (by linarith) + κ_nonneg := up_nonneg _ + κ_le_one := up_le_one _ + κ_zero := fun _ h => up_of_le h + κ_one := fun t h => up_of_lt (by linarith) + J_pos := Nat.succ_pos _ + rank := ?_ + gate := Nat.le_ceil _ + R_rank := by linarith [abs_nonneg Cvar] + R_var := by linarith [le_abs_self Cvar] }⟩ + · have := le_max_left (s - θ) 0 + have := le_max_right (s - θ) 0 + have : max (t - θ) 0 ≤ max (s - θ) 0 + (t - s) := max_le (by linarith) (by linarith) + linarith + · have h2 : (1 : ℝ) / (2 * q) = 1 / (4 * q) + 1 / (4 * q) := by field_simp; norm_num + rw [h2] + exact add_le_add le_rfl hk + · rw [div_le_div_iff₀ (by positivity) hq0, one_mul] + have hqc : q ≤ ⌈q⌉₊ := Nat.le_ceil q + have : (m : ℝ) = ⌈q⌉₊ * (k + 1) := by simp only [m]; push_cast; ring + rw [this] + nlinarith [(Nat.cast_nonneg (α := ℝ) k)] + · have h1 : 4 * Cπ * m * k * (k + 1) ≤ (J : ℝ) := by + simp only [J]; push_cast + exact (Nat.le_ceil _).trans (by linarith) + linarith + +variable (P : HierarchyParams q cπ Cπ Cpair Cvar) + +section Stage + +variable {V ι κ : Type*} [Fintype V] [Fintype ι] [Fintype κ] + (X : ι → V → Prop) (Y : κ → V → Prop) [∀ s v, Decidable (X s v)] [∀ t v, Decidable (Y t v)] + (f : ℝ) (C : Matrix V V ℝ) + +/-- The correction cutoff `t ↦ f Q (t / f)` at rate `f`. -/ +noncomputable def cutoff (t : ℝ) : ℝ := f * P.Q (t / f) + +/-- The copy cutoff `t ↦ χ (t / f)` at rate `f`. -/ +noncomputable def copyCutoff (t : ℝ) : ℝ := P.χ (t / f) + +/-- The final running maximum of the detector numbers after the `k*` pilot steps at rate `f`. -/ +noncomputable def pilot : V → ℝ := + pilotMax (P.cutoff f) P.γ (columnDetector X Y P.ϕ P.ρ P.J P.K f) C P.k + +/-- The actual correction `E = E_(k*)` with the column multipliers `γ (M y)`. -/ +noncomputable def correction : Matrix V V ℝ := + cutoffCorrectionIter (fun y t => P.cutoff f t * P.γ (P.pilot X Y f C y)) C P.k + +/-- The corrected residual `D = C - E + E C`. -/ +noncomputable def residual : Matrix V V ℝ := + C - P.correction X Y f C + P.correction X Y f C * C + +theorem residual_eq : P.residual X Y f C = + C - P.correction X Y f C + P.correction X Y f C * C := by rfl + +/-- The copy weights `r` of the stage (4.22). -/ +noncomputable def weight : Fin (P.m + 1) → V → ℝ := + detectorWeight P.κ (P.pilot X Y f C) + +/-- **The next transition matrix** `C⁺`, indexed by the lexicographically ordered copies. -/ +noncomputable def next : Matrix (Lex (V × Fin (P.m + 1))) (Lex (V × Fin (P.m + 1))) ℝ := + (copyStage (P.copyCutoff f) P.m (P.weight X Y f C) (P.residual X Y f C)).submatrix ofLex ofLex + +/-- **The projection** `P_r` from the copies to their parents, weighted by the copy weights. -/ +noncomputable def proj [DecidableEq V] : Matrix (Lex (V × Fin (P.m + 1))) V ℝ := + (copyWeight (P.weight X Y f C)).submatrix ofLex id + +variable {X Y f C} + +theorem cutoff_nonneg (hf : 0 < f) (t : ℝ) : 0 ≤ P.cutoff f t := + mul_nonneg hf.le (P.Q_nonneg _) + +theorem cutoff_le (hf : 0 < f) (t : ℝ) : P.cutoff f t ≤ max (t - P.θ * f) 0 := by + have h := P.Q_le (t / f) + calc P.cutoff f t = f * P.Q (t / f) := rfl + _ ≤ f * max (t / f - P.θ) 0 := mul_le_mul_of_nonneg_left h hf.le + _ = max (t - P.θ * f) 0 := by + rw [mul_max_of_nonneg _ _ hf.le, mul_zero, mul_sub, mul_div_cancel₀ _ hf.ne', mul_comm] + +theorem le_cutoff (hf : 0 < f) (t : ℝ) : t - P.θ₂ * f ≤ P.cutoff f t := by + have h := mul_le_mul_of_nonneg_left (P.le_Q (t / f)) hf.le + rw [mul_sub, mul_div_cancel₀ _ hf.ne'] at h + simp only [cutoff]; linarith + +theorem cutoff_mono (hf : 0 < f) : Monotone (P.cutoff f) := fun _ _ h => + mul_le_mul_of_nonneg_left (P.Q_mono (div_le_div_of_nonneg_right h hf.le)) hf.le + +theorem cutoff_lipschitz (hf : 0 < f) (s t : ℝ) (h : s ≤ t) : + P.cutoff f t - P.cutoff f s ≤ P.L * (t - s) := by + have hl := P.Q_lipschitz (s / f) (t / f) (div_le_div_of_nonneg_right h hf.le) + calc P.cutoff f t - P.cutoff f s = f * (P.Q (t / f) - P.Q (s / f)) := by + simp only [cutoff]; ring + _ ≤ f * (P.L * (t / f - s / f)) := mul_le_mul_of_nonneg_left hl hf.le + _ = P.L * (t - s) := by field_simp + +private theorem phi_nonneg (hf : 0 < f) (y : V) (t : ℝ) : + 0 ≤ P.cutoff f t * P.γ (P.pilot X Y f C y) := + mul_nonneg (P.cutoff_nonneg hf t) (P.γ_nonneg _) + +private theorem phi_le (hf : 0 < f) (y : V) (t : ℝ) : + P.cutoff f t * P.γ (P.pilot X Y f C y) ≤ max (t - P.θ * f) 0 := + (mul_le_of_le_one_right (P.cutoff_nonneg hf t) (P.γ_le_one _)).trans (P.cutoff_le hf t) + +private theorem phi_mono (hf : 0 < f) (y : V) : + Monotone fun t => P.cutoff f t * P.γ (P.pilot X Y f C y) := + (P.cutoff_mono hf).mul_const (P.γ_nonneg _) + +private theorem θf_nonneg (hf : 0 < f) : 0 ≤ P.θ * f := by have := P.θ_pos; positivity + +/-- **One stage with the bundled constants** [OpenAI2026LogSpace, Proposition 4.5]: at rate +`f > 0`, for retention channels with the bundled constants and an input `C` that is strictly +upper triangular, nonnegative, substochastic and has entries at most `f`, the next matrix has +entries at most `f / q`, intertwines with the projection, is supported within the copies of a +cover `A` of `C` and the overloaded vertices, and that cover has at most `2 |A|` copies. -/ +theorem stage_rates [LinearOrder V] {π : ℝ} (hch : RetentionChannels X Y f π cπ Cπ Cpair Cvar) + (hCπ : 0 < Cπ) (hf : 0 < f) (hC : C.IsStrictUpperTriangular) (hC0 : ∀ x y, 0 ≤ C x y) + (hCf : ∀ x y, C x y ≤ f) (hC1 : C *ᵥ 1 ≤ 1) {A : Finset V} + (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) : + (∀ a b, P.next X Y f C a b ≤ f / q) ∧ + P.next X Y f C * P.proj X Y f C = P.proj X Y f C * P.residual X Y f C ∧ + (∀ a b, P.next X Y f C a b ≠ 0 → + ofLex a ∈ copyCover A (overloaded (P.pilot X Y f C)) ∧ + ofLex b ∈ copyCover A (overloaded (P.pilot X Y f C))) ∧ + #(copyCover (m := P.m) A (overloaded (P.pilot X Y f C))) ≤ 2 * #A := by + have hτ₀ : P.θ₂ * f + f * Real.exp (1 / P.θ) * (P.L / P.θ) ^ P.k / P.k.factorial ≤ + P.τ₀ * f := by + have := mul_le_mul_of_nonneg_right P.truncation hf.le + calc P.θ₂ * f + f * Real.exp (1 / P.θ) * (P.L / P.θ) ^ P.k / P.k.factorial + = (P.θ₂ + Real.exp (1 / P.θ) * (P.L / P.θ) ^ P.k / P.k.factorial) * f := by ring + _ ≤ P.τ₀ * f := this + have hτ₁ : P.τ₁ * f ≤ f / q := + calc P.τ₁ * f ≤ 1 / q * f := mul_le_mul_of_nonneg_right P.τ₁_le hf.le + _ = f / q := by ring + have hcopies : (P.k + 1) * f / (P.m + 1) ≤ f / q := + calc (P.k + 1) * f / (P.m + 1) = (P.k + 1) / (P.m + 1) * f := by ring + _ ≤ 1 / q * f := mul_le_mul_of_nonneg_right P.copies hf.le + _ = f / q := by ring + obtain ⟨h1, h2, h3, h4⟩ := detectedStage_rates (c := P.cutoff f) (γ := P.γ) (κ := P.κ) + (χ := P.copyCutoff f) (θ := P.θ) (L := P.L) (θ₂ := P.θ₂) (τ₀ := P.τ₀ * f) (τ₁ := P.τ₁ * f) + (q := q) (k := P.k) (m := P.m) (K := P.K) (δ₀ := P.δ₀) hch hC hC0 hCf hC1 hA hf + (P.cutoff_nonneg hf) (P.cutoff_le hf) (P.cutoff_mono hf) (P.cutoff_lipschitz hf) + (P.le_cutoff hf) P.θ_pos P.L_nonneg P.γ_nonneg P.γ_le_one P.γ_one P.κ_nonneg P.κ_le_one + P.κ_zero P.κ_one hCπ P.ϕ_nonneg P.ϕ_le_one P.δ₀_pos P.ϕ_zero P.ρ_le_one P.J_pos P.rank + hτ₀ (fun t => P.χ_nonneg _) (fun t => P.χ_le_one _) + (fun t ht => P.χ_zero _ (by rwa [div_le_iff₀ hf])) (fun t ht => P.χ_one _ (by + rwa [le_div_iff₀ hf])) hτ₁ hcopies + refine ⟨fun a b => h1 (ofLex a) (ofLex b), ?_, fun a b h => h3 _ _ h, h4⟩ + have hl : P.next X Y f C * P.proj X Y f C = + (copyStage (P.copyCutoff f) P.m (P.weight X Y f C) (P.residual X Y f C) * + copyWeight (P.weight X Y f C)).submatrix ofLex id := + submatrix_mul _ _ _ _ _ ofLex.bijective + have hr : P.proj X Y f C * P.residual X Y f C = + (copyWeight (P.weight X Y f C) * P.residual X Y f C).submatrix ofLex id := by + ext a z + rfl + rw [hl, hr] + exact congrArg (fun M => M.submatrix ofLex id) h2 + +/-- The next matrix is strictly upper triangular for the lexicographic order on the copies. -/ +theorem next_isStrictUpperTriangular [LinearOrder V] (hf : 0 < f) + (hC : C.IsStrictUpperTriangular) : (P.next X Y f C).IsStrictUpperTriangular := by + unfold next residual correction + exact copyStage_isStrictUpperTriangular <| + cutoffCorrection_residual_isStrictUpperTriangular + (φ := fun y t => P.cutoff f t * P.γ (P.pilot X Y f C y)) (P.phi_nonneg hf) (P.phi_le hf) + (P.θf_nonneg hf) hC P.k + +theorem residual_nonneg (hf : 0 < f) (hC0 : ∀ x y, 0 ≤ C x y) (x y : V) : + 0 ≤ P.residual X Y f C x y := by + unfold residual correction + exact cutoffCorrection_residual_nonneg (φ := fun y t => P.cutoff f t * P.γ (P.pilot X Y f C y)) + hC0 (P.phi_nonneg hf) (P.phi_le hf) (P.phi_mono hf) (P.θf_nonneg hf) P.k x y + +theorem weight_nonneg (j : Fin (P.m + 1)) (x : V) : 0 ≤ P.weight X Y f C j x := by + unfold weight detectorWeight; split_ifs + · exact zero_le_one + · exact P.κ_nonneg _ + +theorem weight_le_one (j : Fin (P.m + 1)) (x : V) : P.weight X Y f C j x ≤ 1 := by + unfold weight detectorWeight; split_ifs + · exact le_rfl + · exact P.κ_le_one _ + +theorem next_nonneg (hf : 0 < f) (hC0 : ∀ x y, 0 ≤ C x y) (a b : Lex (V × Fin (P.m + 1))) : + 0 ≤ P.next X Y f C a b := + copyStage_nonneg (P.weight_nonneg (X := X) (Y := Y) (f := f) (C := C)) + (P.residual_nonneg hf hC0) (fun _ => P.χ_nonneg _) (fun _ => P.χ_le_one _) _ _ + +theorem next_mulVec_one_le (hf : 0 < f) (hC0 : ∀ x y, 0 ≤ C x y) (hC1 : C *ᵥ 1 ≤ 1) : + P.next X Y f C *ᵥ 1 ≤ 1 := by + have h := copyStage_mulVec_one_le (χ := P.copyCutoff f) + (P.weight_nonneg (X := X) (Y := Y) (f := f) (C := C)) (P.weight_le_one (X := X) (Y := Y) + (f := f) (C := C)) (P.residual_nonneg hf hC0) (D := P.residual X Y f C) ?_ + · intro a + have h' := h (ofLex a) + simp only [mulVec, dotProduct, Pi.one_apply, mul_one] at h' ⊢ + calc ∑ i, P.next X Y f C a i + = ∑ x, copyStage (P.copyCutoff f) P.m (P.weight X Y f C) (P.residual X Y f C) + (ofLex a) x := Fintype.sum_equiv ofLex _ _ fun _ => rfl + _ ≤ 1 := h' + · unfold residual correction + exact (correction_mulVec_one_le (fun x y => cutoffCorrectionIter_nonneg + (φ := fun y t => P.cutoff f t * P.γ (P.pilot X Y f C y)) (P.phi_nonneg hf) _ x y) + hC1).trans hC1 + +theorem proj_nonneg [DecidableEq V] (a : Lex (V × Fin (P.m + 1))) (x : V) : + 0 ≤ P.proj X Y f C a x := by + simp only [proj, submatrix_apply, copyWeight, of_apply, id] + split_ifs + · exact P.weight_nonneg _ _ + · exact le_rfl + +theorem proj_mulVec_one_le [DecidableEq V] : P.proj X Y f C *ᵥ 1 ≤ 1 := by + intro a + have h := copyWeight_mulVec (P.weight X Y f C) 1 (ofLex a) + simp only [Pi.one_apply, mul_one] at h + have : (P.proj X Y f C *ᵥ 1) a = (copyWeight (P.weight X Y f C) *ᵥ 1) (ofLex a) := rfl + rw [this, h] + exact P.weight_le_one _ _ + +/-- The primary copy projects to its parent with weight one. -/ +theorem proj_primary [DecidableEq V] (x w : V) : + P.proj X Y f C (toLex (x, 0)) w = if w = x then 1 else 0 := by + simp only [proj, submatrix_apply, id, ofLex_toLex] + exact copyWeight_apply_of_eq_one (by simp [weight, detectorWeight]) w + +end Stage + +end HierarchyParams + +end Matrix From 892f45cf241ea94fd326ac937a449277b9c717e9 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 01:27:19 +0000 Subject: [PATCH 13/18] feat(Foundations): the iterated correction-and-copy hierarchy and its stage bound MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Iterate the detector-driven stages on V (l+1) ≃ Lex (V l × Fin D₀) at rates q⁻¹ ^ l and prove 0 ≤ p x - W_l(x̄_l) ≤ |V 0| (2^c)⁻¹^l from the construction. Co-Authored-By: Claude Opus 5.5 --- .../Probability/DetectedHierarchy.lean | 196 ++++++++++++++++++ ComplexityTests/DetectedHierarchy.lean | 114 ++++++++++ 2 files changed, 310 insertions(+) create mode 100644 Complexity/Foundations/Probability/DetectedHierarchy.lean create mode 100644 ComplexityTests/DetectedHierarchy.lean diff --git a/Complexity/Foundations/Probability/DetectedHierarchy.lean b/Complexity/Foundations/Probability/DetectedHierarchy.lean new file mode 100644 index 000000000..22bd8ec44 --- /dev/null +++ b/Complexity/Foundations/Probability/DetectedHierarchy.lean @@ -0,0 +1,196 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ + +module +-- upstream: candidate + +public import Complexity.Foundations.Probability.HierarchyParams + +/-! +# The correction-and-copy hierarchy + +This file iterates the stages of `Complexity.Foundations.Probability.HierarchyParams` and proves +the stage bound of the OpenAI preprint (2026-09-23), Proposition 4.7 [OpenAI2026LogSpace], from +the construction itself. + +Start with a strictly upper triangular, nonnegative, substochastic matrix `S` on a finite linearly +ordered set `V 0`. Stage `l + 1` lives on a finite linearly ordered set `V (l + 1)` identified +with the copies `Lex (V l × Fin (m + 1))` by an equivalence `e l` that reflects the order +[OpenAI2026LogSpace, Section 4.5: `V_(l+1) = V_l × {0, …, D₀ - 1}`, ordered by parent and then +copy symbol]. Taking the family as a parameter lets a client choose identifiers, for instance +numbers in radix `D₀`, on which its channels act. The transition matrices `Matrix.hierarchy` are +`C_0 = S` and `C_(l+1) = C⁺_l` transported by `e l`, where `C⁺_l` is the next matrix of the stage +at rate `f_l = q⁻¹ ^ l` with that stage's retention channels `X l`, `Y l`. The detectors are exact +expectations over the channel seeds, so the hierarchy, its corrections +(`Matrix.hierarchyCorrection`), its projections (`Matrix.hierarchyProj`) and the transported +rewards are deterministic functions of `S`, the parameters and the channel laws: no event over +the seeds has to be excluded, and the channel interface is the only probabilistic input. + +**The stage bound** (`Matrix.sub_hierarchyReward_le`). Let `q = 2 ^ (c + 1)`, let the channels +of every stage `l` satisfy `Cslib.Probability.RetentionChannels` at rate `q⁻¹ ^ l` with the +bundled constants, and let `(1 - S) p = e₀` with `0 ≤ p ≤ 1`. Then at the all-primary copy +`Matrix.primaryCopy P e x l` of a base vertex `x`, + +`0 ≤ p x - W_l (x̄_l) ≤ |V 0| (2 ^ c)⁻¹ ^ l`, + +where `W_l = B_l e₀` is the transported reward (`Matrix.rewardTransport`). Along the way, every +stage is strictly upper triangular, nonnegative and substochastic with entries at most `q⁻¹ ^ l` +(`Matrix.hierarchy_invariant`), and its active vertices at most double from stage to stage. + +## Main definitions + +* `Matrix.hierarchy`, `Matrix.hierarchyCorrection`, `Matrix.hierarchyProj`: the stages. +* `Matrix.primaryCopy`: the all-primary copy of a base vertex. + +## Main results + +* `Matrix.hierarchy_invariant`: every stage is a valid input of the next one. +* `Matrix.sub_hierarchyReward_le`: the stage bound `0 ≤ p x - W_l (x̄_l) ≤ |V 0| (2 ^ c)⁻¹ ^ l`. + +## References + +* [OpenAI, *Exact Derandomization of Logarithmic Space: L = RL = BPL*][OpenAI2026LogSpace], + Section 4.5 and Proposition 4.7 (preprint, not peer reviewed) +-/ + +public section + +open Finset Cslib.Probability + +namespace Matrix + +variable {q cπ Cπ Cpair Cvar : ℝ} (P : HierarchyParams q cπ Cπ Cpair Cvar) {V : ℕ → Type*} + [∀ l, Fintype (V l)] [∀ l, LinearOrder (V l)] (e : ∀ l, V (l + 1) ≃ Lex (V l × Fin (P.m + 1))) + {ι κ : ℕ → Type*} [∀ l, Fintype (ι l)] [∀ l, Fintype (κ l)] (X : ∀ l, ι l → V l → Prop) + (Y : ∀ l, κ l → V l → Prop) [∀ l s v, Decidable (X l s v)] [∀ l t v, Decidable (Y l t v)] + (S : Matrix (V 0) (V 0) ℝ) + +/-- **The transition matrices of the hierarchy**: `C_0 = S`, and `C_(l+1)` is the next matrix of +stage `l` at rate `q⁻¹ ^ l`, with the channels `X l`, `Y l`, transported to `V (l + 1)` by `e l` +[OpenAI2026LogSpace, Section 4.5]. -/ +noncomputable def hierarchy : ∀ l, Matrix (V l) (V l) ℝ + | 0 => S + | l + 1 => (P.next (X l) (Y l) (q⁻¹ ^ l) (hierarchy l)).submatrix (e l) (e l) + +/-- The correction `E_l` of stage `l`. -/ +noncomputable def hierarchyCorrection (l : ℕ) : Matrix (V l) (V l) ℝ := + P.correction (X l) (Y l) (q⁻¹ ^ l) (hierarchy P e X Y S l) + +/-- The weighted projection `P_r` from stage `l + 1` to stage `l`. -/ +noncomputable def hierarchyProj (l : ℕ) : Matrix (V (l + 1)) (V l) ℝ := + (P.proj (X l) (Y l) (q⁻¹ ^ l) (hierarchy P e X Y S l)).submatrix (e l) id + +/-- The **all-primary copy** `x̄_l` of a base vertex `x`: every copy symbol is `0`. -/ +def primaryCopy (x : V 0) : ∀ l, V l + | 0 => x + | l + 1 => (e l).symm (toLex (primaryCopy x l, 0)) + +variable {P e X Y S} + +/-- **Every stage is a valid input of the next**: if `S` is strictly upper triangular, +nonnegative and substochastic and the equivalences reflect the order, then so is every stage +`l`, with entries at most `q⁻¹ ^ l`, provided the channels of the stages before `l` satisfy the +interface [OpenAI2026LogSpace, Proposition 4.5]. -/ +theorem hierarchy_invariant (he : ∀ l a b, e l a < e l b → a < b) {π : ℕ → ℝ} (hq : 0 < q) + (hCπ : 0 < Cπ) (hS : S.IsStrictUpperTriangular) (hS0 : ∀ x y, 0 ≤ S x y) + (hS1 : S *ᵥ 1 ≤ 1) (l : ℕ) + (hch : ∀ l' < l, RetentionChannels (X l') (Y l') (q⁻¹ ^ l') (π l') cπ Cπ Cpair Cvar) : + (hierarchy P e X Y S l).IsStrictUpperTriangular ∧ (∀ x y, 0 ≤ hierarchy P e X Y S l x y) ∧ + hierarchy P e X Y S l *ᵥ 1 ≤ 1 ∧ ∀ x y, hierarchy P e X Y S l x y ≤ q⁻¹ ^ l := by + induction l with + | zero => + refine ⟨hS, hS0, hS1, fun x y => ?_⟩ + have hrow : ∑ z, S x z ≤ 1 := by + have := hS1 x + simpa only [mulVec, dotProduct, Pi.one_apply, mul_one] using this + rw [pow_zero] + exact (single_le_sum (fun z _ => hS0 x z) (mem_univ y)).trans hrow + | succ l ih => + obtain ⟨hC, hC0, hC1, hCf⟩ := ih fun l' hl' => hch l' (by omega) + have hf : 0 < q⁻¹ ^ l := by positivity + have hnext := P.next_isStrictUpperTriangular (X := X l) (Y := Y l) hf hC + have hrow := P.next_mulVec_one_le (X := X l) (Y := Y l) hf hC0 hC1 + refine ⟨fun a b hab => hnext fun h => hab (he l a b h), + fun a b => P.next_nonneg hf hC0 _ _, fun a => ?_, fun a b => ?_⟩ + · have h1 := hrow (e l a) + simp only [mulVec, dotProduct, Pi.one_apply, mul_one] at h1 ⊢ + calc ∑ b, hierarchy P e X Y S (l + 1) a b + = ∑ c, P.next (X l) (Y l) (q⁻¹ ^ l) (hierarchy P e X Y S l) (e l a) c := + Fintype.sum_equiv (e l) _ _ fun _ => rfl + _ ≤ 1 := h1 + · have := (P.stage_rates (hch l (by omega)) hCπ hf hC hC0 hCf hC1 (A := univ) + (fun _ _ _ => ⟨mem_univ _, mem_univ _⟩)).1 (e l a) (e l b) + calc hierarchy P e X Y S (l + 1) a b ≤ q⁻¹ ^ l / q := this + _ = q⁻¹ ^ (l + 1) := by rw [pow_succ, div_eq_mul_inv] + +/-- The active vertices of a matrix: those with a nonzero entry in their row or column. -/ +private noncomputable def active {W : Type*} [Fintype W] (C : Matrix W W ℝ) : Finset W := by + classical exact univ.filter fun x => ∃ y, C x y ≠ 0 ∨ C y x ≠ 0 + +private theorem mem_active {W : Type*} [Fintype W] {C : Matrix W W ℝ} {x y : W} + (h : C x y ≠ 0) : x ∈ active C ∧ y ∈ active C := by + classical + simp only [active, mem_filter, mem_univ, true_and] + exact ⟨⟨y, Or.inl h⟩, ⟨x, Or.inr h⟩⟩ + +/-- **The stage bound from the construction** [OpenAI2026LogSpace, Proposition 4.7]. Let +`q = 2 ^ (c + 1)`, let `S` be strictly upper triangular, nonnegative and substochastic, let the +equivalences `e l` reflect the order, let the channels of every stage `l` satisfy the interface at +rate `q⁻¹ ^ l`, and let `(1 - S) p = e₀` with `0 ≤ p ≤ 1`. Then the reward `W_l = B_l e₀`, +transported along the hierarchy, satisfies `0 ≤ p x - W_l (x̄_l) ≤ |V 0| (2 ^ c)⁻¹ ^ l` at the +all-primary copy of every base vertex `x`. -/ +theorem sub_hierarchyReward_le (he : ∀ l a b, e l a < e l b → a < b) {π : ℕ → ℝ} {c : ℕ} + (hq : q = 2 ^ (c + 1)) + (hch : ∀ l, RetentionChannels (X l) (Y l) (q⁻¹ ^ l) (π l) cπ Cπ Cpair Cvar) (hCπ : 0 < Cπ) + (hS : S.IsStrictUpperTriangular) (hS0 : ∀ x y, 0 ≤ S x y) (hS1 : S *ᵥ 1 ≤ 1) + {p e₀ : V 0 → ℝ} (hp : (1 - S) *ᵥ p = e₀) (hp0 : 0 ≤ p) (hp1 : p ≤ 1) (x : V 0) (l : ℕ) : + 0 ≤ p x - (rewardTransport (hierarchyProj P e X Y S) (hierarchyCorrection P e X Y S) l *ᵥ + e₀) (primaryCopy P e x l) ∧ + p x - (rewardTransport (hierarchyProj P e X Y S) (hierarchyCorrection P e X Y S) l *ᵥ e₀) + (primaryCopy P e x l) ≤ Fintype.card (V 0) * ((2 : ℝ) ^ c)⁻¹ ^ l := by + have hq0 : 0 < q := by rw [hq]; positivity + have hinv := fun l => hierarchy_invariant he hq0 hCπ hS hS0 hS1 l fun l' _ => hch l' + have hf : ∀ l, 0 < q⁻¹ ^ l := fun l => by positivity + have hrates := fun l => P.stage_rates (hch l) hCπ (hf l) (hinv l).1 (hinv l).2.1 + (hinv l).2.2.2 (hinv l).2.2.1 (A := active (hierarchy P e X Y S l)) + fun _ _ h => mem_active h + refine sub_rewardTransport_mulVec_le_of_rates (V := V) (C := hierarchy P e X Y S) + (E := hierarchyCorrection P e X Y S) (P := hierarchyProj P e X Y S) + (fun l a w => P.proj_nonneg _ _) (fun l a => P.proj_mulVec_one_le (e l a)) + (fun l => (hinv l).2.1) (fun l => ?_) hp hp0 hp1 (z := primaryCopy P e x) + (fun l w => ?_) (fun a b => by simpa using (hinv 0).2.2.2 a b) (fun l _ a b => ?_) + (fun l => active (hierarchy P e X Y S l)) (fun l _ _ h => (mem_active h).2) + (card_le_univ _) (fun l => ?_) l + · -- the intertwining, transported by `e l` + have hl : hierarchy P e X Y S (l + 1) * hierarchyProj P e X Y S l = + (P.next (X l) (Y l) (q⁻¹ ^ l) (hierarchy P e X Y S l) * + P.proj (X l) (Y l) (q⁻¹ ^ l) (hierarchy P e X Y S l)).submatrix (e l) id := + (submatrix_mul _ _ _ _ _ (e l).bijective).symm + have hr : hierarchyProj P e X Y S l * (hierarchy P e X Y S l - + hierarchyCorrection P e X Y S l + + hierarchyCorrection P e X Y S l * hierarchy P e X Y S l) = + (P.proj (X l) (Y l) (q⁻¹ ^ l) (hierarchy P e X Y S l) * + P.residual (X l) (Y l) (q⁻¹ ^ l) (hierarchy P e X Y S l)).submatrix (e l) id := by + rw [HierarchyParams.residual_eq] + ext a z + rfl + rw [hl, hr, (hrates l).2.1] + · -- primary copies project to their parents + simp only [hierarchyProj, primaryCopy, submatrix_apply, id, Equiv.apply_symm_apply] + exact P.proj_primary _ w + · calc hierarchy P e X Y S (l + 1) a b ≤ q⁻¹ ^ (l + 1) := (hinv (l + 1)).2.2.2 a b + _ = ((2 : ℝ) ^ (c + 1))⁻¹ ^ (l + 1) := by rw [hq] + · -- the active vertices of the next stage map injectively into the copy cover + classical + refine (card_le_card_of_injOn (fun a => ofLex (e l a)) (fun a ha => mem_coe.mpr ?_) + (fun a _ b _ h => (e l).injective (ofLex.injective h))).trans (hrates l).2.2.2 + rw [mem_coe] at ha + simp only [active, mem_filter, mem_univ, true_and] at ha + obtain ⟨b, hb | hb⟩ := ha + · exact ((hrates l).2.2.1 (e l a) (e l b) hb).1 + · exact ((hrates l).2.2.1 (e l b) (e l a) hb).2 + +end Matrix diff --git a/ComplexityTests/DetectedHierarchy.lean b/ComplexityTests/DetectedHierarchy.lean new file mode 100644 index 000000000..582f9be6d --- /dev/null +++ b/ComplexityTests/DetectedHierarchy.lean @@ -0,0 +1,114 @@ +/- +Copyright (c) 2026 Christian Reitwiessner. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Reitwiessner +-/ +import Complexity.Foundations.Probability.DetectedHierarchy +import Mathlib.Tactic.FinCases + +/-! +# Tests for the hierarchy constants and the iterated hierarchy +-/ + +namespace ComplexityTests.DetectedHierarchy + +open Finset Matrix Cslib.Probability + +/-! ### Constants -/ + +-- Stage parameters exist for the density divisor `q = 2` and any channel constants with +-- `c_π > 0`. +example : Nonempty (HierarchyParams 2 1 2 2 0) := HierarchyParams.nonempty (by norm_num) one_pos + +/-- A channel with one seed that retains every vertex. -/ +private abbrev all {V : Type*} : Unit → V → Prop := fun _ _ => True + +/-- Channels that retain everything satisfy the interface at a rate `f ≤ 1` whenever +`C_π f ≥ 1` and `C_pair f ≥ 1`, with `c_π = 1` and `C_var = 0`. -/ +private theorem retentionChannels_all {V : Type*} {f Cπ Cpair : ℝ} (hf1 : f ≤ 1) + (hCπ : 1 ≤ Cπ * f) (hCp : 1 ≤ Cpair * f) : + RetentionChannels (all (V := V)) all f 1 1 Cπ Cpair 0 where + dens_X _ := by simp [all] + dens_Y _ := by simp [all] + lower := by simpa using hf1 + upper := hCπ + pair _ _ _ := by simpa [all] using hCp + tail A _ := by + have : ({s | 2 * (#{x ∈ A | all s x} : ℝ) < #A * 1} : Finset Unit) = ∅ := by + ext s + simp only [all, filter_true, mul_one, mem_filter, mem_univ, true_and, notMem_empty, + iff_false, not_lt] + linarith [(Nat.cast_nonneg (α := ℝ) #A)] + rw [this] + simp + +/-! ### The walk on `Fin n` -/ + +/-- The walk on `Fin n` that moves from `i` to `i + 1` with probability `1 / 2`. -/ +private noncomputable def walk (n : ℕ) : Matrix (Fin n) (Fin n) ℝ := + of fun i j => if i.val + 1 = j.val then 1 / 2 else 0 + +private theorem walk_upper (n : ℕ) : (walk n).IsStrictUpperTriangular := by + intro i j h + simp only [walk, of_apply, ite_eq_right_iff] + intro hij + exact absurd (Fin.lt_def.mpr (by omega)) h + +private theorem walk_nonneg (n : ℕ) (i j : Fin n) : 0 ≤ walk n i j := by + simp only [walk, of_apply]; split_ifs <;> norm_num + +private theorem walk_row (n : ℕ) : walk n *ᵥ 1 ≤ 1 := by + intro i + simp only [walk, mulVec, dotProduct, of_apply, Pi.one_apply, mul_one] + rw [sum_ite, sum_const_zero, add_zero, sum_const, nsmul_eq_mul] + have hcard : #({j | i.val + 1 = j.val} : Finset (Fin n)) ≤ 1 := + card_le_one.mpr fun a ha b hb => by + simp only [mem_filter, mem_univ, true_and] at ha hb + exact Fin.ext (by omega) + have : (#({j | i.val + 1 = j.val} : Finset (Fin n)) : ℝ) ≤ 1 := by exact_mod_cast hcard + linarith + +/-! ### Stage vertices `Fin (3 (m + 1) ^ l)` with lexicographic copies -/ + +/-- `Fin (3 (m + 1) ^ (l + 1))` as the copies of `Fin (3 (m + 1) ^ l)`: `u = y + (m + 1) x` +corresponds to the copy `y` of the parent `x`. -/ +private def copyEquiv (m l : ℕ) : + Fin (3 * (m + 1) ^ (l + 1)) ≃ Lex (Fin (3 * (m + 1) ^ l) × Fin (m + 1)) := + (finCongr (by ring)).trans (finProdFinEquiv.symm.trans toLex) + +private theorem copyEquiv_val (m l : ℕ) (a : Fin (3 * (m + 1) ^ (l + 1))) : + a.val = (ofLex (copyEquiv m l a)).2.val + (m + 1) * (ofLex (copyEquiv m l a)).1.val := by + have h := finProdFinEquiv_apply_val (ofLex (copyEquiv m l a)) + simp only [copyEquiv, Equiv.trans_apply, ofLex_toLex, Equiv.apply_symm_apply, + finCongr_apply, Fin.val_cast] at h + exact h + +/-- The identification reflects the order. -/ +private theorem copyEquiv_reflect (m l : ℕ) (a b : Fin (3 * (m + 1) ^ (l + 1))) + (h : copyEquiv m l a < copyEquiv m l b) : a < b := by + rw [Fin.lt_def, copyEquiv_val m l a, copyEquiv_val m l b] + rcases Prod.Lex.lt_iff.mp h with h1 | ⟨h1, h2⟩ + · have hx : (ofLex (copyEquiv m l a)).1.val + 1 ≤ (ofLex (copyEquiv m l b)).1.val := h1 + have hy := (ofLex (copyEquiv m l a)).2.isLt + nlinarith + · rw [h1] + have : (ofLex (copyEquiv m l a)).2.val < (ofLex (copyEquiv m l b)).2.val := h2 + omega + +-- After one stage at rate `f₀ = 1` with full-retention channels, the walk on `Fin 3` becomes a +-- strictly upper triangular, nonnegative, substochastic matrix on `Fin (3 (m + 1))` with +-- entries at most `q⁻¹ = 1 / 2`, for every choice of the stage parameters. +example (P : HierarchyParams 2 1 1 1 0) : + let H := hierarchy P (V := fun l => Fin (3 * (P.m + 1) ^ l)) (copyEquiv P.m) + (fun _ => all) (fun _ => all) (walk (3 * (P.m + 1) ^ 0)) 1 + H.IsStrictUpperTriangular ∧ (∀ x y, 0 ≤ H x y) ∧ H *ᵥ 1 ≤ 1 ∧ + ∀ x y, H x y ≤ (2 : ℝ)⁻¹ ^ 1 := + hierarchy_invariant (P := P) (q := 2) (V := fun l => Fin (3 * (P.m + 1) ^ l)) + (e := copyEquiv P.m) (X := fun _ => all) (Y := fun _ => all) (S := walk (3 * (P.m + 1) ^ 0)) + (π := fun _ => 1) (copyEquiv_reflect P.m) (by norm_num) one_pos + (walk_upper _) (walk_nonneg _) (walk_row _) 1 fun l hl => by + obtain rfl : l = 0 := by omega + exact retentionChannels_all (f := (2 : ℝ)⁻¹ ^ 0) (Cπ := 1) (Cpair := 1) (by norm_num) + (by norm_num) (by norm_num) + +end ComplexityTests.DetectedHierarchy From 4a207ab48f5930a0742cc261d4de7a4768c4c1c7 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 01:28:48 +0000 Subject: [PATCH 14/18] doc(Foundations): document every HierarchyParams field Co-Authored-By: Claude Opus 5.5 --- .../Foundations/Probability/HierarchyParams.lean | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Complexity/Foundations/Probability/HierarchyParams.lean b/Complexity/Foundations/Probability/HierarchyParams.lean index 14dc40da2..3619adc13 100644 --- a/Complexity/Foundations/Probability/HierarchyParams.lean +++ b/Complexity/Foundations/Probability/HierarchyParams.lean @@ -81,23 +81,29 @@ structure HierarchyParams (q cπ Cπ Cpair Cvar : ℝ) where k : ℕ /-- The number of extra copies, `D₀ - 1`. -/ m : ℕ - /-- The copy thresholds, relative to the rate. -/ + /-- The copy threshold up to which entries stay with the primary copy, relative to the rate. -/ τ₀ : ℝ + /-- The copy threshold from which entries are split evenly, relative to the rate. -/ τ₁ : ℝ /-- The copy cutoff. -/ χ : ℝ → ℝ - /-- The detector score thresholds and cutoff. -/ + /-- The detector score threshold through which the score vanishes. -/ δ₀ : ℝ + /-- The detector score threshold from which the score is one. -/ δ₁ : ℝ + /-- The detector score cutoff. -/ ϕ : ℝ → ℝ - /-- The row-gate threshold and cutoff. -/ + /-- The row-gate threshold. -/ η : ℝ + /-- The row-gate cutoff. -/ ρ : ℝ → ℝ - /-- The column multiplier and copy-weight cutoffs. -/ + /-- The column-multiplier cutoff, applied to the running maximum of detector numbers. -/ γ : ℝ → ℝ + /-- The copy-weight cutoff, applied to the running maximum of detector numbers. -/ κ : ℝ → ℝ - /-- The detector ranks. -/ + /-- The detector rank `J` of the column trials. -/ J : ℕ + /-- The rank `K` of the row gates. -/ K : ℕ /-- The column-count threshold `R*` of Lemma 4.3. -/ R : ℝ From e136883330c501e953f675972f1d9a6f6464821d Mon Sep 17 00:00:00 2001 From: Samuel Giuseppe Schlesinger Date: Fri, 30 Oct 2026 00:53:19 -0400 Subject: [PATCH 15/18] doc(Foundations): clarify reduced hierarchy parameter scope Address #1702 review5707105708: parameter existence is the reduced algebraic-stage package. Preserve the full threshold ladder and root/complement regularity gap for Q and every step cutoff. Correct m=ceilNat(q)*(k+1) and D0=m+1. No Lean declaration or proof body changes. Codex worker codex-hierarchy-fixes-1702-1704-20261030. Source-only preparation; supported-pin integration, full validation and outside delta review remain required before publication. --- .../Probability/DetectedHierarchy.lean | 6 ++- .../Probability/HierarchyParams.lean | 41 ++++++++++++------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Complexity/Foundations/Probability/DetectedHierarchy.lean b/Complexity/Foundations/Probability/DetectedHierarchy.lean index 22bd8ec44..f898f7bcb 100644 --- a/Complexity/Foundations/Probability/DetectedHierarchy.lean +++ b/Complexity/Foundations/Probability/DetectedHierarchy.lean @@ -13,8 +13,10 @@ public import Complexity.Foundations.Probability.HierarchyParams # The correction-and-copy hierarchy This file iterates the stages of `Complexity.Foundations.Probability.HierarchyParams` and proves -the stage bound of the OpenAI preprint (2026-09-23), Proposition 4.7 [OpenAI2026LogSpace], from -the construction itself. +the finite-matrix stage bound of the OpenAI preprint (2026-09-23), Proposition 4.7 +[OpenAI2026LogSpace], from the construction using the reduced algebraic-stage parameters and +the retention-channel interface. The preprint's full threshold ladder and later-estimation +root/complement regularity for `Q` and all step cutoffs remain separate requirements. Start with a strictly upper triangular, nonnegative, substochastic matrix `S` on a finite linearly ordered set `V 0`. Stage `l + 1` lives on a finite linearly ordered set `V (l + 1)` identified diff --git a/Complexity/Foundations/Probability/HierarchyParams.lean b/Complexity/Foundations/Probability/HierarchyParams.lean index 3619adc13..9cb78ac00 100644 --- a/Complexity/Foundations/Probability/HierarchyParams.lean +++ b/Complexity/Foundations/Probability/HierarchyParams.lean @@ -11,23 +11,32 @@ public import Complexity.Foundations.Probability.DetectedStage import Mathlib.Algebra.Order.Floor.Semiring /-! -# Constants for the correction-and-copy hierarchy +# Algebraic-stage parameters for the correction-and-copy hierarchy One stage of the hierarchy of the OpenAI preprint (2026-09-23), Section 4 [OpenAI2026LogSpace], is driven by finitely many constants and cutoff functions: the correction ramp `Q` with its thresholds `θ ≤ θ₂` and Lipschitz constant `L`, the iteration count `k*`, the number of copies `D₀ = m + 1`, the copy thresholds `τ₀ < τ₁`, the detector thresholds `δ₀ < δ₁` and `η`, the detector ranks `J` and `K`, the count threshold `R*`, and the cutoffs `ϕ`, `ρ`, `γ`, `κ`, `χ`. -`Matrix.HierarchyParams q cπ Cπ Cpair Cvar` bundles them with every condition that the stage -lemmas need, for the density divisor `q` and the channel constants of +`Matrix.HierarchyParams q cπ Cπ Cpair Cvar` bundles the reduced algebraic conditions used by the +stage lemmas, together with additional detector-cutoff data, for the density divisor `q` and the +channel constants of `Cslib.Probability.RetentionChannels`. All of them are fixed before the stage: the thresholds are relative to the rate `f`, so the same parameters serve every stage. -**Existence** (`Matrix.HierarchyParams.nonempty`). For every `q > 0` and channel constants with -`c_π > 0`, there are such parameters [OpenAI2026LogSpace, Remark 4.6]. The +**Reduced algebraic-stage existence** (`Matrix.HierarchyParams.nonempty`). For every `q > 0` +and channel constants with `c_π > 0`, there are parameters satisfying this bundle. Following +[OpenAI2026LogSpace, Remark 4.6], the choice follows the order of the preprint: first `θ = θ₂ = 1 / (4q)` and the hard ramp `Q t = max (t - θ) 0`, then `k*` from the factorial bound (`Matrix.exists_factorial_bound_le`), -then `D₀ = ⌈q⌉ (k* + 1)`, then `J` from (4.24), and finally `K` and `R*` from Lemma 4.3. +then `m = ⌈q⌉₊ (k* + 1)` and `D₀ = m + 1`, then `J` from (4.24), and finally `K` and `R*` +from Lemma 4.3. + +This witness establishes only the reduced algebraic-stage package encoded here. It does not +satisfy the preprint's full threshold ladder or the regularity package needed for later +estimation. Besides the hard ramp `Q`, the cutoffs `χ`, `ϕ`, `ρ`, `γ` and `κ` are discontinuous +steps. The additional threshold conditions and root/complement regularity for `Q` and these +cutoffs remain open; replacing `Q` alone does not supply them. **One stage** (`Matrix.HierarchyParams.stage_rates`). At rate `f > 0`, the stage uses the cutoffs `c t = f Q (t / f)` and `χ (t / f)` (`Matrix.HierarchyParams.cutoff`, @@ -41,13 +50,13 @@ hypotheses are those on the input matrix and the channel interface. ## Main definitions -* `Matrix.HierarchyParams`: the constants and cutoffs of a stage, with their conditions. +* `Matrix.HierarchyParams`: the reduced algebraic-stage parameters and cutoff data. * `Matrix.HierarchyParams.pilot`, `Matrix.HierarchyParams.residual`, `Matrix.HierarchyParams.weight`, `Matrix.HierarchyParams.next`: one stage. ## Main results -* `Matrix.HierarchyParams.nonempty`: the constants exist for every `q > 0`. +* `Matrix.HierarchyParams.nonempty`: reduced algebraic-stage parameters exist for every `q > 0`. * `Matrix.HierarchyParams.stage_rates`: one stage satisfies the per-stage rates. * `Matrix.HierarchyParams.next_isStrictUpperTriangular`, `Matrix.HierarchyParams.next_nonneg`, `Matrix.HierarchyParams.next_mulVec_one_le`: the next stage is again a valid input. @@ -64,10 +73,11 @@ open Finset Cslib.Probability namespace Matrix -/-- **The constants and cutoffs of a stage** of the hierarchy, for the density divisor `q` and -the channel constants `cπ, Cπ, Cpair, Cvar`, with every condition used by the stage lemmas +/-- **The reduced algebraic-stage parameters** of the hierarchy, for the density divisor `q` and +the channel constants `cπ, Cπ, Cpair, Cvar`, together with additional detector-cutoff data [OpenAI2026LogSpace, Sections 4.1–4.4 and Remark 4.6]. Thresholds of the ramp `Q` and of the -copy cutoff `χ` are relative to the rate `f`. -/ +copy cutoff `χ` are relative to the rate `f`. The preprint's full threshold ladder and later +root/complement regularity for `Q` and all the step cutoffs are not part of this bundle. -/ structure HierarchyParams (q cπ Cπ Cpair Cvar : ℝ) where /-- The correction ramp: the cutoff at rate `f` is `t ↦ f Q (t / f)`. -/ Q : ℝ → ℝ @@ -168,10 +178,13 @@ private theorem down_of_lt {a t : ℝ} (h : a < t) : down a t = 0 := by private theorem down_antitone (a : ℝ) : Antitone (down a) := fun s t hst => by unfold down; split_ifs with h1 h2 <;> first | exact absurd (hst.trans h1) h2 | norm_num -/-- **The constants exist** [OpenAI2026LogSpace, Remark 4.6]: for every density divisor `q > 0` -and channel constants with `c_π > 0`, there are stage parameters. They are chosen +/-- **Reduced algebraic-stage parameters exist**: for every density divisor `q > 0` and channel +constants with `c_π > 0`, there are parameters satisfying this bundle. Following +[OpenAI2026LogSpace, Remark 4.6], they are chosen in the order of the preprint: the ramp, then `k*` by factorial truncation, then the copies, then -the detector ranks `J` and `K`, then `R*`. -/ +the detector ranks `J` and `K`, then `R*`. The witness uses a hard ramp and step cutoffs; +the full threshold ladder and later-estimation regularity for all cutoffs and their relevant +complements remain open. -/ theorem nonempty (hq : 0 < q) (hcπ : 0 < cπ) : Nonempty (HierarchyParams q cπ Cπ Cpair Cvar) := by have hq0 : 0 < q := hq From 4014d0c1714f65e566c8c01dbfab34e06b72e803 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 00:04:51 +0000 Subject: [PATCH 16/18] fix(Foundations): qualify Matrix apply lemmas for the rc2 Mathlib API Under rc2 the root-namespace add_apply/neg_apply/sub_apply/mul_apply/one_apply no longer apply to matrices; use the Matrix.* versions in CorrectionHierarchy and its test, as #1653 does elsewhere. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit ea663cedbea1caf5e23e6f38b36fed48ed46dda8) --- .../Matrix/CorrectionHierarchy.lean | 18 ++++++++++-------- ComplexityTests/CorrectionHierarchy.lean | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean index 2420fb961..ec5c5825e 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CorrectionHierarchy.lean @@ -112,15 +112,15 @@ theorem isUpperTriangular [Zero R] (h : M.IsStrictUpperTriangular) : M.IsUpperTr theorem add [AddZeroClass R] (hM : M.IsStrictUpperTriangular) (hN : N.IsStrictUpperTriangular) : (M + N).IsStrictUpperTriangular := fun i j hij => by - simp only [add_apply, hM hij, hN hij, add_zero] + simp only [Matrix.add_apply, hM hij, hN hij, add_zero] theorem neg [SubtractionMonoid R] (hM : M.IsStrictUpperTriangular) : (-M).IsStrictUpperTriangular := fun i j hij => by - simp only [neg_apply, hM hij, neg_zero] + simp only [Matrix.neg_apply, hM hij, neg_zero] theorem sub [SubtractionMonoid R] (hM : M.IsStrictUpperTriangular) (hN : N.IsStrictUpperTriangular) : (M - N).IsStrictUpperTriangular := fun i j hij => by - simp only [sub_apply, hM hij, hN hij, sub_zero] + simp only [Matrix.sub_apply, hM hij, hN hij, sub_zero] theorem mul [Fintype V] [NonUnitalNonAssocSemiring R] (hM : M.IsStrictUpperTriangular) (hN : N.IsStrictUpperTriangular) : (M * N).IsStrictUpperTriangular := fun i j hij => by @@ -134,9 +134,10 @@ theorem mul [Fintype V] [NonUnitalNonAssocSemiring R] (hM : M.IsStrictUpperTrian theorem det_one_add {V : Type*} [Fintype V] [DecidableEq V] [LinearOrder V] [CommRing R] {E : Matrix V V R} (h : E.IsStrictUpperTriangular) : (1 + E).det = 1 := by have hT : (1 + E).IsUpperTriangular := fun i j (hji : j < i) => by - rw [add_apply, one_apply_ne (ne_of_lt hji).symm, h.isUpperTriangular hji, add_zero] + rw [Matrix.add_apply, one_apply_ne (ne_of_lt hji).symm, h.isUpperTriangular hji, add_zero] rw [det_of_isUpperTriangular hT] - exact Finset.prod_eq_one fun i _ => by rw [add_apply, one_apply_eq, h (lt_irrefl i), add_zero] + exact Finset.prod_eq_one fun i _ => by + rw [Matrix.add_apply, one_apply_eq, h (lt_irrefl i), add_zero] end IsStrictUpperTriangular @@ -240,11 +241,12 @@ theorem copySplit_mul_copyWeight [Fintype V] [DecidableEq V] [Fintype ι] [Semir copySplit r s D * copyWeight r = copyWeight r * D := by ext ⟨x, i⟩ z have hL : (copySplit r s D * copyWeight r) (x, i) z = r i x * D x z * ∑ j, s x z j * r j z := by - rw [mul_apply, Fintype.sum_prod_type, Fintype.sum_eq_single z fun y hy => ?_, Finset.mul_sum] + rw [Matrix.mul_apply, Fintype.sum_prod_type, Fintype.sum_eq_single z fun y hy => ?_, + Finset.mul_sum] · simp [copySplit, copyWeight, mul_assoc] · simp [copyWeight, hy] have hR : (copyWeight r * D) (x, i) z = r i x * D x z := by - rw [mul_apply, Fintype.sum_eq_single x fun y hy => ?_] + rw [Matrix.mul_apply, Fintype.sum_eq_single x fun y hy => ?_] · simp [copyWeight] · simp [copyWeight, Ne.symm hy] rw [hL, hR] @@ -358,7 +360,7 @@ variable [Ring R] [PartialOrder R] [IsOrderedRing R] private theorem one_apply_nonneg {n : Type*} [DecidableEq n] (i j : n) : (0 : R) ≤ (1 : Matrix n n R) i j := by - rw [one_apply]; split_ifs <;> simp + rw [Matrix.one_apply]; split_ifs <;> simp private theorem mul_nonneg_entries {m n o : Type*} [Fintype n] {A : Matrix m n R} {B : Matrix n o R} (hA : ∀ i j, 0 ≤ A i j) (hB : ∀ i j, 0 ≤ B i j) (i : m) (k : o) : diff --git a/ComplexityTests/CorrectionHierarchy.lean b/ComplexityTests/CorrectionHierarchy.lean index c6bb668e6..1564bdc7a 100644 --- a/ComplexityTests/CorrectionHierarchy.lean +++ b/ComplexityTests/CorrectionHierarchy.lean @@ -24,7 +24,8 @@ private def e : Fin 3 → ℚ := ![0, 0, 1] private def p : Fin 3 → ℚ := ![1 / 4, 1 / 2, 1] private theorem one_sub_C_mulVec_p : (1 - C) *ᵥ p = e := by - ext i; fin_cases i <;> norm_num [C, p, e, mulVec, dotProduct, Fin.sum_univ_three, one_apply] + ext i; fin_cases i <;> + norm_num [C, p, e, mulVec, dotProduct, Fin.sum_univ_three, Matrix.one_apply] /-- The correction removes the second transition. -/ private def E : Matrix (Fin 3) (Fin 3) ℚ := !![0, 0, 0; 0, 0, 1 / 2; 0, 0, 0] @@ -41,18 +42,18 @@ example : C - E + E * C = !![0, 1 / 2, 0; 0, 0, 0; 0, 0, 0] := by -- equation. example : (1 - (C - E + E * C)) *ᵥ p = ![0, 1 / 2, 1] := by rw [one_sub_correction_mulVec, one_sub_C_mulVec_p] - ext i; fin_cases i <;> simp [E, e, mulVec, dotProduct, Fin.sum_univ_three, one_apply] + ext i; fin_cases i <;> simp [E, e, mulVec, dotProduct, Fin.sum_univ_three, Matrix.one_apply] private theorem inv_one_sub_C : (1 - C)⁻¹ = 1 + C + C * C := inv_eq_left_inv <| by ext i j; fin_cases i <;> fin_cases j <;> - simp [C, mul_apply, Fin.sum_univ_three, one_apply] + simp [C, Matrix.mul_apply, Fin.sum_univ_three, Matrix.one_apply] -- The acceptance probabilities of the corrected walk with the corrected reward are those of -- the original walk: `1 / 4` from `0`. example : ((1 - (C - E + E * C))⁻¹ *ᵥ (e + E *ᵥ e)) 0 = 1 / 4 := by rw [E_strict.inv_one_sub_correction_mulVec, inv_one_sub_C] - simp [C, e, mulVec, dotProduct, Fin.sum_univ_three, one_apply] + simp [C, e, mulVec, dotProduct, Fin.sum_univ_three, Matrix.one_apply] norm_num -- A nonnegative correction does not increase the row sums. @@ -93,7 +94,7 @@ private def Es (l : ℕ) : Matrix (Fin 3) (Fin 3) ℚ := if l = 0 then C + C * C private def Ps (_ : ℕ) : Matrix (Fin 3) (Fin 3) ℚ := 1 private theorem C_cube : C * C * C = 0 := by - ext i j; fin_cases i <;> fin_cases j <;> simp [C, mul_apply, Fin.sum_univ_three] + ext i j; fin_cases i <;> fin_cases j <;> simp [C, Matrix.mul_apply, Fin.sum_univ_three] private theorem hstep (l : ℕ) : Cs (l + 1) * Ps l = Ps l * (Cs l - Es l + Es l * Cs l) := by rcases l with _ | l @@ -108,12 +109,12 @@ private theorem nonneg_C : ∀ i j, 0 ≤ C i j := by -- the row sum of the zero matrix. example : (rewardTransport (V := fun _ => Fin 3) Ps Es 1 *ᵥ e) 0 = 1 / 4 := by have h := sub_rewardTransport_mulVec_mem_Icc (V := fun _ => Fin 3) (C := Cs) (E := Es) - (P := Ps) (z := fun _ => 0) (fun _ i j => by simp [Ps, one_apply]; split_ifs <;> simp) + (P := Ps) (z := fun _ => 0) (fun _ i j => by simp [Ps, Matrix.one_apply]; split_ifs <;> simp) (fun _ => by simp [Ps]) (fun l i j => by unfold Cs; split_ifs <;> simp [nonneg_C]) hstep (p := p) (e := e) (by simpa [Cs] using one_sub_C_mulVec_p) (fun i => by fin_cases i <;> norm_num [p]) (fun i => by fin_cases i <;> norm_num [p]) - (fun _ w => by simp [Ps, one_apply, eq_comm]) 1 + (fun _ w => by simp [Ps, Matrix.one_apply, eq_comm]) 1 have hp0 : p 0 = 1 / 4 := rfl simp only [Cs, Nat.add_one_ne_zero, ↓reduceIte, Matrix.zero_apply, Finset.sum_const_zero, Set.mem_Icc] at h @@ -122,10 +123,10 @@ example : (rewardTransport (V := fun _ => Fin 3) Ps Es 1 *ᵥ e) 0 = 1 / 4 := by -- The transported rewards are nonnegative. example : 0 ≤ rewardTransport (V := fun _ => Fin 3) Ps Es 1 *ᵥ e := rewardTransport_mulVec_nonneg (V := fun _ => Fin 3) - (fun _ i j => by simp only [Ps, one_apply]; split_ifs <;> simp) + (fun _ i j => by simp only [Ps, Matrix.one_apply]; split_ifs <;> simp) (fun l i j => by unfold Es; split_ifs - · fin_cases i <;> fin_cases j <;> norm_num [C, mul_apply, Fin.sum_univ_three] + · fin_cases i <;> fin_cases j <;> norm_num [C, Matrix.mul_apply, Fin.sum_univ_three] · simp) (fun i => by fin_cases i <;> simp [e]) 1 From b0b00058c5845fb44ba7f50f5ec33bf3764cacd9 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 00:10:59 +0000 Subject: [PATCH 17/18] fix(Foundations): qualify Matrix apply lemmas in FactorialTruncation for rc2 Under rc2 the root-namespace add_apply/sub_apply/mul_apply no longer apply to matrices; use the Matrix.* versions in FactorialTruncation and its test, rewrapping lines that crossed 100 columns. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 19cf8a82f0390c89261196084d1838f498523e73) --- .../Matrix/FactorialTruncation.lean | 26 ++++++++++--------- ComplexityTests/FactorialTruncation.lean | 5 ++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean index f94a429ae..856f41393 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/FactorialTruncation.lean @@ -105,7 +105,7 @@ variable [LinearOrder V] private theorem cutoffCorrection_congr (hC : C.IsStrictUpperTriangular) {F G : Matrix V V R} {x y : V} (h : ∀ z < y, F x z = G x z) : cutoffCorrection φ C F x y = cutoffCorrection φ C G x y := by - simp only [cutoffCorrection, of_apply, add_apply, mul_apply] + simp only [cutoffCorrection, of_apply, Matrix.add_apply, Matrix.mul_apply] congr 2 refine Finset.sum_congr rfl fun z _ => ?_ by_cases hz : z < y @@ -191,7 +191,7 @@ include hC0 hφm in private theorem cutoffCorrection_mono {F G : Matrix V V ℝ} (hFG : ∀ x y, F x y ≤ G x y) (x y : V) : cutoffCorrection φ C F x y ≤ cutoffCorrection φ C G x y := by refine hφm y ?_ - simp only [add_apply, mul_apply] + simp only [Matrix.add_apply, Matrix.mul_apply] exact add_le_add_right (Finset.sum_le_sum fun z _ => mul_le_mul_of_nonneg_right (hFG x z) (hC0 z y)) _ @@ -271,7 +271,7 @@ private theorem card_support_mul_le (hθf : 0 ≤ θ * f) : have hE0 : ∀ i j, 0 ≤ E i j := cutoffCorrectionIter_nonneg hφ0 _ have hEfix : ∀ y, E x y = φ y ((C + E * C) x y) := fix_apply hC x have hres : ∀ y, (C - E + E * C) x y = (C + E * C) x y - E x y := fun y => by - simp only [add_apply, sub_apply]; ring + simp only [Matrix.add_apply, Matrix.sub_apply]; ring have hres0 : ∀ y, 0 ≤ (C - E + E * C) x y := fun y => by rw [hres, hEfix y, sub_nonneg] exact cutoff_le_self hφθ hθf y (correctionInput_nonneg hC0 hE0 x y) @@ -317,7 +317,7 @@ private theorem fix_le_pow (hf : 0 ≤ f) (hθf : 0 ≤ θ * f) (y : V) : calc E x y ≤ (C + E * C) x y := by rw [hEfix]; exact cutoff_le_self hφθ hθf y (correctionInput_nonneg hC0 hE0 x y) _ = C x y + ∑ z ∈ S.filter (· < y), E x z * C z y := by - rw [add_apply, mul_apply, hsum] + rw [Matrix.add_apply, Matrix.mul_apply, hsum] _ ≤ f + ∑ z ∈ S.filter (· < y), f * (1 + f) ^ #(S.filter (· < z)) * f := by refine add_le_add (hCf x y) (Finset.sum_le_sum fun z hz => ?_) exact mul_le_mul (ih z (mem_filter.mp hz).2) (hCf z y) (hC0 z y) (by positivity) @@ -353,14 +353,16 @@ private theorem fix_sub_iter_le_choose (hf : 0 ≤ f) (hθf : 0 ≤ θ * f) (hL have hsum : ∑ z, (E - F) x z * C z y = ∑ z ∈ S.filter (· < y), (E - F) x z * C z y := sum_mul_eq_sum_support x hC (fun z hz => by change E x z = 0 at hz - rw [sub_apply, hz, sub_eq_zero] + rw [Matrix.sub_apply, hz, sub_eq_zero] exact le_antisymm (cutoffCorrectionIter_nonneg (C := C) hφ0 k x z) (hz ▸ hFE z)) y have hdiff : (C + E * C) x y - (C + F * C) x y = ∑ z, (E - F) x z * C z y := by - simp only [add_apply, mul_apply, sub_apply, sub_mul, Finset.sum_sub_distrib]; ring + simp only [Matrix.add_apply, Matrix.mul_apply, Matrix.sub_apply, sub_mul, + Finset.sum_sub_distrib] + ring have hle : (C + F * C) x y ≤ (C + E * C) x y := by rw [← sub_nonneg, hdiff] - exact Finset.sum_nonneg fun z _ => mul_nonneg (by rw [sub_apply, sub_nonneg]; exact hFE z) - (hC0 z y) + exact Finset.sum_nonneg fun z _ => + mul_nonneg (by rw [Matrix.sub_apply, sub_nonneg]; exact hFE z) (hC0 z y) calc E x y - cutoffCorrectionIter φ C (k + 1) x y = φ y ((C + E * C) x y) - φ y ((C + F * C) x y) := by rw [hEfix, cutoffCorrectionIter_succ]; rfl @@ -370,7 +372,7 @@ private theorem fix_sub_iter_le_choose (hf : 0 ≤ f) (hθf : 0 ≤ θ * f) (hL _ ≤ L * ∑ z ∈ S.filter (· < y), f * (1 + f) ^ #S * (L * f) ^ k * (#(S.filter (· < z))).choose k * f := by refine mul_le_mul_of_nonneg_left (Finset.sum_le_sum fun z _ => ?_) hL - rw [sub_apply] + rw [Matrix.sub_apply] exact mul_le_mul (ih z) (hCf z y) (hC0 z y) (by positivity) _ = f * (1 + f) ^ #S * (L * f) ^ (k + 1) * ∑ z ∈ S.filter (· < y), ((#(S.filter (· < z))).choose k : ℝ) := by @@ -445,8 +447,8 @@ theorem cutoffCorrection_residual_nonneg (hθf : 0 ≤ θ * f) (k : ℕ) (x y : (cutoffCorrectionIter φ C (k + 1) * C) x y := Finset.sum_le_sum fun z _ => mul_le_mul_of_nonneg_right (cutoffCorrectionIter_le_succ hC0 hφ0 hφm k x z) (hC0 z y) - rw [← hstep, add_apply] at hcut - rw [add_apply, sub_apply] + rw [← hstep, Matrix.add_apply] at hcut + rw [Matrix.add_apply, Matrix.sub_apply] linarith include hC hC0 hCf hC1 hφ0 hφθ hφm hφL in @@ -466,7 +468,7 @@ theorem cutoffCorrection_residual_le (hf : 0 < f) (hθ : 0 < θ) (hL : 0 ≤ L) (cutoffCorrectionIter_le_fix hC hC0 hφ0 hφm k x z) (hC0 z y) have hT := hgood ((C + E * C) x y) rw [← hEfix] at hT - simp only [add_apply, sub_apply] at hT hΔC ⊢ + simp only [Matrix.add_apply, Matrix.sub_apply] at hT hΔC ⊢ linarith /-- **A constant number of iterations suffices**: for every accuracy `δ > 0` there is `k`, depending diff --git a/ComplexityTests/FactorialTruncation.lean b/ComplexityTests/FactorialTruncation.lean index 1a9743119..18bd60c9a 100644 --- a/ComplexityTests/FactorialTruncation.lean +++ b/ComplexityTests/FactorialTruncation.lean @@ -57,7 +57,7 @@ private theorem Estar_eq : Estar = cutoffCorrectionFix φ C := by refine eq_cutoffCorrectionFix hC ?_ ext x y fin_cases x <;> fin_cases y <;> - norm_num [cutoffCorrection, φ, C, Estar, mul_apply, Fin.sum_univ_three] + norm_num [cutoffCorrection, φ, C, Estar, Matrix.mul_apply, Fin.sum_univ_three] -- One iteration from zero misses the two-step entry entirely. example : cutoffCorrectionIter φ C 1 0 2 = 0 := by @@ -72,7 +72,8 @@ example : cutoffCorrectionFix φ C 0 2 - cutoffCorrectionIter φ C 1 0 2 ≤ -- After two iterations the iterate has reached the fixed point at `(0, 2)`. example : cutoffCorrectionIter φ C 2 0 2 = cutoffCorrectionFix φ C 0 2 := by rw [← Estar_eq] - norm_num [cutoffCorrectionIter, cutoffCorrection, φ, C, Estar, mul_apply, Fin.sum_univ_three] + norm_num [cutoffCorrectionIter, cutoffCorrection, φ, C, Estar, Matrix.mul_apply, + Fin.sum_univ_three] -- The corrected matrix of every iterate is nonnegative, and the hard cutoff leaves at most -- `θ f = 1 / 8` behind in every column. From f7f51f73216d7771d1c61da85ebcbd2ea276bf67 Mon Sep 17 00:00:00 2001 From: Christian Reitwiessner Date: Fri, 30 Oct 2026 02:28:47 +0000 Subject: [PATCH 18/18] fix(Foundations): qualify Matrix apply lemmas in CopyStage and PilotCorrection for rc2 Under rc2 the root-namespace add_apply/sub_apply/mul_apply no longer apply to matrices; use the Matrix.* versions, as rc2-refresh/1676 and /1677 do for the lower modules of this stack. Proof-only; no statement changes. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 34406a084312428fd65108771467fbc7086f9c3f) --- .../Foundations/LinearAlgebra/Matrix/CopyStage.lean | 8 ++++---- .../Foundations/LinearAlgebra/Matrix/PilotCorrection.lean | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean index d61617c73..9ee05d128 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/CopyStage.lean @@ -124,7 +124,7 @@ theorem cutoffCorrection_residual_le_mul (hCf : ∀ x y, C x y ≤ f) (hf : 0 have h := (isCorrectionSeq_cutoffCorrectionIter hC0 hφ0 hφθ hθf).input_le_mul hCf hf hC1 k x y have h0 := cutoffCorrectionIter_nonneg (C := C) hφ0 k x y - simp only [add_apply, sub_apply] at h ⊢ + simp only [Matrix.add_apply, Matrix.sub_apply] at h ⊢ linarith include hC0 hφ0 hφθ hθf in @@ -174,7 +174,7 @@ theorem cutoffCorrection_residual_dominates (hCf : ∀ x y, C x y ≤ f) (hf : 0 mul_le_of_le_one_left (by linarith) (by linarith) have hadef : a = C x y + (F * C) x y := rfl rw [hcoef] - simp only [add_apply, sub_apply] + simp only [Matrix.add_apply, Matrix.sub_apply] nlinarith variable {A : Finset V} @@ -191,7 +191,7 @@ theorem cutoffCorrectionIter_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y have hCxy : C x y = 0 := by by_contra h'; exact hxy (hA x y h') have hin : (C + cutoffCorrectionIter φ C k * C) x y = 0 := by - simp only [add_apply, mul_apply, hCxy, zero_add] + simp only [Matrix.add_apply, Matrix.mul_apply, hCxy, zero_add] refine Finset.sum_eq_zero fun z _ => ?_ by_cases hE : cutoffCorrectionIter φ C k x z = 0 · rw [hE, zero_mul] @@ -214,7 +214,7 @@ theorem cutoffCorrection_residual_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ cutoffCorrectionIter_mem hφ0 hφθ hθf hA k have hCxy : C x y = 0 := by by_contra h'; exact hxy (hA x y h') have hExy : cutoffCorrectionIter φ C k x y = 0 := by by_contra h'; exact hxy (hE x y h') - simp only [add_apply, sub_apply, mul_apply, hCxy, hExy, sub_zero, zero_add] + simp only [Matrix.add_apply, Matrix.sub_apply, Matrix.mul_apply, hCxy, hExy, sub_zero, zero_add] refine Finset.sum_eq_zero fun z _ => ?_ by_cases hEz : cutoffCorrectionIter φ C k x z = 0 · rw [hEz, zero_mul] diff --git a/Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean b/Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean index a6aa6efe3..d9373a6d8 100644 --- a/Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean +++ b/Complexity/Foundations/LinearAlgebra/Matrix/PilotCorrection.lean @@ -99,7 +99,7 @@ theorem sum_input_le (hC1 : C *ᵥ 1 ≤ 1) : have hrow : ∀ z, ∑ y, C z y ≤ 1 := fun z => by simpa [mulVec, dotProduct] using hC1 z have hinput : ∀ i x, ∑ y, F i x y ≤ i → ∑ y, (C + F i * C) x y ≤ i + 1 := fun i x hi => by calc ∑ y, (C + F i * C) x y = ∑ y, C x y + ∑ z, F i x z * ∑ y, C z y := by - simp only [add_apply, mul_apply, sum_add_distrib, mul_sum] + simp only [Matrix.add_apply, Matrix.mul_apply, sum_add_distrib, mul_sum] rw [sum_comm] _ ≤ 1 + ∑ z, F i x z * 1 := add_le_add (hrow x) (sum_le_sum fun z _ => mul_le_mul_of_nonneg_left (hrow z) (hF.nonneg i x z)) @@ -148,7 +148,7 @@ theorem input_mem_and_mem (hA : ∀ x y, C x y ≠ 0 → x ∈ A ∧ y ∈ A) : by_contra hxy apply h have hCxy : C x y = 0 := by by_contra h'; exact hxy (hA x y h') - simp only [add_apply, mul_apply, hCxy, zero_add] + simp only [Matrix.add_apply, Matrix.mul_apply, hCxy, zero_add] refine sum_eq_zero fun z _ => ?_ by_cases hE : F i x z = 0 · rw [hE, zero_mul]