Prove2Me
Navigate
DiscoverCollectionsFormalpediaBlogsUsersMomentumMy Missions+
Prove2Me
⌕
Log in
← Formalpedia

κ-improvement development, part 2: array model and networks

Definition
IntMul_Kappa_K_Defs2

by xuanji · Oct 13, 2026 · Mathlib 0df444a (Lean v4.33.1)

complexity-theoryinteger-multiplicationkappa-improvement

Definitions (part 2): array-model and network definitions for the OpenAI-preprint formalization (mixed-radix arrays, pull maps, interchange networks, labelled networks, butterfly layers, synthesis, resampling, parameters).

Source modules (in order): Solutions.AModelFac, Solutions.AModelL12Basic, Solutions.AModelL12, Solutions.AModelL12Cost, Solutions.AModelRat, Solutions.AModelL12Main, Solutions.ButterflyTensor, Solutions.ButterflyLayer, Solutions.ButterflyGuard.

The file was generated from the development by deleting all theorems not needed by the definitions; it keeps all definitions plus the lemmas the definitions themselves need (proof fields of structures, decreasing_by facts) and simple @[simp]/rfl lemmas.

Definition code
-- OpenAI-preprint / κ-improvement development (integer-multiplication-kappa), generated by skeleton subtraction.

import Definitions.Def_IntMul_Kappa_K_Defs1

set_option autoImplicit false
set_option relaxedAutoImplicit false
set_option maxHeartbeats 1000000

section
-- Source module: Solutions.AModelFac
/-!
# Discharging the factorization hypothesis of Proposition 11 (Lemma 10 data)

`AModelProp11.prop11` assumes, as data, integer factorizations `fac A = (E₁, Π, E₂)` with
`A = E₁ Π E₂` **over `ℤ`** (`FacAt`). This cannot be produced in general from Lemma 9 (the
factors are rational, and their reductions mod `q ^ b` are `q`-adic, not integral). This file:

0. `bruhat_lower`: a copy of `Solutions/Bruhat.lean` (Lemma 9 over a field), renamed.
1. `ratFac`, `RatFacSpec`, `GoodAt`, `exists_good_primes`, `exists_good_prime`: for any finite set
   of integer matrices, every prime `q > q₀` avoids all denominators of the `E`'s and all
   numerators of their diagonals; `#ones Π = rank_ℚ A`.
2. `goodSub N` (rationals with denominator coprime to `N`), the ring hom `redHom N` to `ZMod N`,
   the total map `redQ N`, `redQ_matrix_identity`, `redQ_lower`, `isUnit_redQ`.
3. `FacAtZ` (the identity only mod `N`), `facAtZ_of_facAt`, the integer lifts `facZ Q`
   (entries `(redQ Q r).val`), the bridge `facAtZ_facZ`, and the re-proved chain
   `implΦ_eqZ`, `levelR_correct_amapZ`, `levelR_correctZ`, `prog_correctZ` (bounded level),
   `levelCost_eqZ`, `prog_costZ`, `prop11Z`, and the assembled `prop11_rat`.
-/

section BruhatCopy

open Matrix Finset

namespace FacBruhat

variable {K : Type*} [Field K] {m : ℕ}

/-- Lower triangular with nonzero diagonal. -/
def LowerND (M : Matrix (Fin m) (Fin m) K) : Prop :=
  (∀ i j, i < j → M i j = 0) ∧ ∀ i, M i i ≠ 0

lemma lowerND_one : LowerND (1 : Matrix (Fin m) (Fin m) K) :=
  ⟨fun i j h => by simp [one_apply, h.ne], fun i => by simp⟩

lemma lowerND_mul {M N : Matrix (Fin m) (Fin m) K} (hM : LowerND M) (hN : LowerND N) :
    LowerND (M * N) := by
  have diag : ∀ i, (M * N) i i = M i i * N i i := by
    intro i
    rw [mul_apply, Finset.sum_eq_single i]
    · intro k _ hk
      rcases lt_or_gt_of_ne hk with h | h
      · rw [hN.1 k i h, mul_zero]
      · rw [hM.1 i k h, zero_mul]
    · simp
  refine ⟨fun i j hij => ?_, fun i => by rw [diag]; exact mul_ne_zero (hM.2 i) (hN.2 i)⟩
  rw [mul_apply]
  refine Finset.sum_eq_zero fun k _ => ?_
  rcases lt_or_ge i k with h | h
  · rw [hM.1 i k h, zero_mul]
  · rw [hN.1 k j (lt_of_le_of_lt h hij), mul_zero]

lemma isLower_of (M : Matrix (Fin m) (Fin m) K) (h : LowerND M) : M.IsLowerTriangular :=
  fun i j hij => h.1 i j hij

lemma det_ne_zero_of (M : Matrix (Fin m) (Fin m) K) (h : LowerND M) : M.det ≠ 0 := by
  rw [det_of_isLowerTriangular M (isLower_of M h)]
  exact Finset.prod_ne_zero_iff.2 fun i _ => h.2 i

lemma lowerND_inv (M : Matrix (Fin m) (Fin m) K) (h : LowerND M) : LowerND M⁻¹ := by
  have hd : IsUnit M.det := isUnit_iff_ne_zero.2 (det_ne_zero_of M h)
  have : Invertible M := invertibleOfIsUnitDet M hd
  have hl : M⁻¹.IsLowerTriangular := blockTriangular_inv_of_blockTriangular (isLower_of M h)
  refine ⟨fun i j hij => hl hij, fun i => ?_⟩
  -- diagonal of M * M⁻¹ = 1
  have h1 : (M * M⁻¹) i i = 1 := by rw [mul_inv_of_invertible]; simp
  have h2 : (M * M⁻¹) i i = M i i * M⁻¹ i i := by
    rw [mul_apply, Finset.sum_eq_single i]
    · intro k _ hk
      rcases lt_or_gt_of_ne hk with hk | hk
      · rw [hl hk, mul_zero]
      · rw [h.1 i k hk, zero_mul]
    · simp
  intro h0
  rw [h2, h0, mul_zero] at h1
  exact zero_ne_one h1

/-- Rows with index `< k` are clean: zero, or a single `1` whose column is otherwise zero. -/
def Clean (B : Matrix (Fin m) (Fin m) K) (k : ℕ) : Prop :=
  ∀ i : Fin m, i.val < k → (∀ j, B i j = 0) ∨
    ∃ j, B i j = 1 ∧ (∀ j', j' ≠ j → B i j' = 0) ∧ ∀ i', i' ≠ i → B i' j = 0

lemma clean_zero (B : Matrix (Fin m) (Fin m) K) : Clean B 0 := fun _ h => absurd h (Nat.not_lt_zero _)

/-- In a clean row `r < k`, the entry in any column `j` where row `k'` (with `k' ≥ k`) is nonzero vanishes. -/
lemma clean_col_zero {B : Matrix (Fin m) (Fin m) K} {k : ℕ} (hB : Clean B k) (r k' : Fin m)
    (hr : r.val < k) (hk' : k ≤ k'.val) (j : Fin m) (hj : B k' j ≠ 0) : B r j = 0 := by
  rcases hB r hr with h | ⟨σ, -, hrow, hcol⟩
  · exact h j
  · by_cases hσ : j = σ
    · subst hσ
      exact absurd (hcol k' (fun h => by subst h; omega)) hj
    · exact hrow j hσ

lemma step (B : Matrix (Fin m) (Fin m) K) (k : Fin m) (hB : Clean B k.val) :
    ∃ L R : Matrix (Fin m) (Fin m) K, LowerND L ∧ LowerND R ∧ Clean (L * B * R) (k.val + 1) := by
  classical
  by_cases hz : ∀ j, B k j = 0
  · refine ⟨1, 1, lowerND_one, lowerND_one, ?_⟩
    simp only [Matrix.one_mul, Matrix.mul_one]
    intro i hi
    rcases Nat.lt_succ_iff_lt_or_eq.1 hi with h | h
    · exact hB i h
    · left; have : i = k := Fin.ext h; subst this; exact hz
  push Not at hz
  have hne : (univ.filter fun j => B k j ≠ 0).Nonempty := by
    obtain ⟨j, hj⟩ := hz; exact ⟨j, by simp [hj]⟩
  set j0 := (univ.filter fun j => B k j ≠ 0).max' hne with hj0def
  have hj0 : B k j0 ≠ 0 := by
    have := Finset.max'_mem _ hne
    simpa using this
  have hright : ∀ j, j0 < j → B k j = 0 := by
    intro j hj
    by_contra h
    have : j ≤ j0 := Finset.le_max' _ j (by simp [h])
    exact absurd hj (not_lt.2 this)
  set b := B k j0 with hb
  -- column operations
  set N : Matrix (Fin m) (Fin m) K := Matrix.of fun a c => if a = j0 ∧ c < j0 then -(B k c / b) else 0
  set R1 : Matrix (Fin m) (Fin m) K := 1 + N
  have hR1 : LowerND R1 := by
    refine ⟨fun i j hij => ?_, fun i => ?_⟩
    · simp only [R1, N, Matrix.add_apply, one_apply, of_apply, hij.ne, if_false, zero_add]
      rw [if_neg]; rintro ⟨rfl, h⟩; exact absurd (hij.trans h) (lt_irrefl _)
    · simp only [R1, N, Matrix.add_apply, of_apply, one_apply_eq]
      rw [if_neg (by rintro ⟨rfl, h⟩; exact lt_irrefl _ h)]; simp
  set B1 := B * R1 with hB1def
  have hB1 : ∀ r c, B1 r c = B r c + (if c < j0 then -(B k c / b) * B r j0 else 0) := by
    intro r c
    simp only [B1, R1, Matrix.mul_add, Matrix.mul_one, Matrix.add_apply]
    congr 1
    rw [mul_apply, Finset.sum_eq_single j0]
    · simp only [N, of_apply, true_and]
      split_ifs <;> ring
    · intro a _ ha; simp [N, ha]
    · simp
  have hB1k : ∀ c, B1 k c = if c = j0 then b else 0 := by
    intro c
    rw [hB1]
    rcases lt_trichotomy c j0 with h | h | h
    · rw [if_pos h, if_neg h.ne]; field_simp; ring
    · subst h; simp [hb]
    · rw [if_neg (not_lt.2 h.le), if_neg h.ne', hright c h, add_zero]
  -- row operations
  set M : Matrix (Fin m) (Fin m) K := Matrix.of fun r a => if a = k ∧ k < r then -(B1 r j0 / b) else 0
  set L1 : Matrix (Fin m) (Fin m) K := 1 + M
  have hL1 : LowerND L1 := by
    refine ⟨fun i j hij => ?_, fun i => ?_⟩
    · simp only [L1, M, Matrix.add_apply, one_apply, of_apply, hij.ne, if_false, zero_add]
      rw [if_neg]; rintro ⟨rfl, h⟩; exact absurd (hij.trans h) (lt_irrefl _)
    · simp only [L1, M, Matrix.add_apply, of_apply, one_apply_eq]
      rw [if_neg (by rintro ⟨rfl, h⟩; exact lt_irrefl _ h)]; simp
  set B2 := L1 * B1 with hB2def
  have hB2 : ∀ r c, B2 r c = B1 r c + (if k < r then -(B1 r j0 / b) * B1 k c else 0) := by
    intro r c
    simp only [B2, L1, Matrix.add_mul, Matrix.one_mul, Matrix.add_apply]
    congr 1
    rw [mul_apply, Finset.sum_eq_single k]
    · simp only [M, of_apply, true_and]
      split_ifs <;> ring
    · intro a _ ha; simp [M, ha]
    · simp
  -- scaling
  set D : Matrix (Fin m) (Fin m) K := diagonal fun i => if i = k then b⁻¹ else 1
  have hD : LowerND D := by
    refine ⟨fun i j hij => by simp [D, hij.ne], fun i => ?_⟩
    simp only [D, diagonal_apply_eq]
    split_ifs
    · exact inv_ne_zero hj0
    · exact one_ne_zero
  refine ⟨D * L1, R1, lowerND_mul hD hL1, hR1, ?_⟩
  have hfin : D * L1 * B * R1 = D * B2 := by
    simp only [B2, B1, Matrix.mul_assoc]
  rw [hfin]
  have hDB : ∀ r c, (D * B2) r c = (if r = k then b⁻¹ else 1) * B2 r c := by
    intro r c; simp [D, diagonal_mul]
  -- clean rows below k are untouched
  have hold : ∀ r : Fin m, r.val < k.val → ∀ c, (D * B2) r c = B r c := by
    intro r hr c
    have hrk : r ≠ k := fun h => by subst h; omega
    have hkr : ¬ k < r := fun h => by rw [Fin.lt_def] at h; omega
    have hrj0 : B r j0 = 0 := clean_col_zero hB r k hr le_rfl j0 hj0
    rw [hDB, if_neg hrk, one_mul, hB2, if_neg hkr, add_zero, hB1, hrj0]
    simp
  intro i hi
  rcases Nat.lt_succ_iff_lt_or_eq.1 hi with hi | hi
  · rcases hB i hi with h | ⟨σ, h1, hrow, hcol⟩
    · left; intro j; rw [hold i hi, h]
    · right
      refine ⟨σ, by rw [hold i hi, h1], fun j hj => by rw [hold i hi, hrow j hj], fun i' hi' => ?_⟩
      have hσj0 : σ ≠ j0 := by
        rintro rfl; exact hj0 (hcol k (fun h => by subst h; omega))
      have hkσ : B k σ = 0 := hcol k (fun h => by subst h; omega)
      rw [hDB, hB2, hB1k, if_neg hσj0, mul_zero]
      simp only [ite_self, add_zero]
      rw [hB1, hcol i' hi', hkσ]
      simp
  · have hik : i = k := Fin.ext hi
    subst hik
    right
    refine ⟨j0, ?_, fun j hj => ?_, fun i' hi' => ?_⟩
    · rw [hDB, if_pos rfl, hB2, if_neg (lt_irrefl _), add_zero, hB1k, if_pos rfl]
      exact inv_mul_cancel₀ hj0
    · rw [hDB, hB2, if_neg (lt_irrefl _), add_zero, hB1k, if_neg hj, mul_zero]
    · rw [hDB, if_neg hi', hB2, hB1k, if_pos rfl, one_mul]
      rcases lt_trichotomy i' i with h | h | h
      · rw [if_neg (not_lt.2 h.le), add_zero]
        have := hold i' h j0
        rw [hDB, if_neg hi', one_mul, hB2, if_neg (not_lt.2 h.le), add_zero] at this
        rw [this]
        exact clean_col_zero hB i' i h le_rfl j0 hj0
      · exact absurd h hi'
      · rw [if_pos h]; field_simp; ring

lemma reduce (A : Matrix (Fin m) (Fin m) K) :
    ∀ k ≤ m, ∃ L R : Matrix (Fin m) (Fin m) K, LowerND L ∧ LowerND R ∧ Clean (L * A * R) k := by
  intro k
  induction k with
  | zero => intro _; exact ⟨1, 1, lowerND_one, lowerND_one, clean_zero _⟩
  | succ k ih =>
    intro hk
    obtain ⟨L, R, hL, hR, hc⟩ := ih (by omega)
    obtain ⟨L', R', hL', hR', hc'⟩ := step (L * A * R) ⟨k, by omega⟩ hc
    refine ⟨L' * L, R * R', lowerND_mul hL' hL, lowerND_mul hR hR', ?_⟩
    simpa [Matrix.mul_assoc] using hc'

end FacBruhat

open FacBruhat in
theorem bruhat_lower {m : ℕ} {K : Type*} [Field K] [DecidableEq K] (A : Matrix (Fin m) (Fin m) K) :
    ∃ E₁ P E₂ : Matrix (Fin m) (Fin m) K,
      (∀ i j, i < j → E₁ i j = 0) ∧ (∀ i, E₁ i i ≠ 0) ∧
      (∀ i j, i < j → E₂ i j = 0) ∧ (∀ i, E₂ i i ≠ 0) ∧
      (∀ i j, P i j = 0 ∨ P i j = 1) ∧
      (∀ i j j', P i j = 1 → P i j' = 1 → j = j') ∧
      (∀ i i' j, P i j = 1 → P i' j = 1 → i = i') ∧
      (Finset.univ.filter fun x : Fin m × Fin m => P x.1 x.2 = 1).card = A.rank ∧
      A = E₁ * P * E₂ := by
  classical
  obtain ⟨L, R, hL, hR, hc⟩ := reduce A m le_rfl
  set P := L * A * R with hP
  have hLd := det_ne_zero_of L hL
  have hRd := det_ne_zero_of R hR
  have : Invertible L := invertibleOfIsUnitDet L (isUnit_iff_ne_zero.2 hLd)
  have : Invertible R := invertibleOfIsUnitDet R (isUnit_iff_ne_zero.2 hRd)
  have hA : A = L⁻¹ * P * R⁻¹ := by
    simp only [hP, Matrix.mul_assoc, inv_mul_cancel_left_of_invertible]
    rw [Matrix.mul_inv_of_invertible, Matrix.mul_one]
  have hrow : ∀ i, (∀ j, P i j = 0) ∨
      ∃ j, P i j = 1 ∧ (∀ j', j' ≠ j → P i j' = 0) ∧ ∀ i', i' ≠ i → P i' j = 0 :=
    fun i => hc i i.isLt
  have h01 : ∀ i j, P i j = 0 ∨ P i j = 1 := by
    intro i j
    rcases hrow i with h | ⟨σ, h1, hr, -⟩
    · exact Or.inl (h j)
    · by_cases hj : j = σ
      · subst hj; exact Or.inr h1
      · exact Or.inl (hr j hj)
  have hrowu : ∀ i j j', P i j = 1 → P i j' = 1 → j = j' := by
    intro i j j' h h'
    rcases hrow i with hz | ⟨σ, -, hr, -⟩
    · rw [hz j] at h; exact absurd h zero_ne_one
    · by_contra hne
      by_cases hj : j = σ
      · subst hj; rw [hr j' (Ne.symm hne)] at h'; exact zero_ne_one h'
      · rw [hr j hj] at h; exact zero_ne_one h
  have hcolu : ∀ i i' j, P i j = 1 → P i' j = 1 → i = i' := by
    intro i i' j h h'
    rcases hrow i with hz | ⟨σ, -, hr, hcl⟩
    · rw [hz j] at h; exact absurd h zero_ne_one
    · have hjσ : j = σ := by
        by_contra hj; rw [hr j hj] at h; exact zero_ne_one h
      subst hjσ
      by_contra hne
      rw [hcl i' (Ne.symm hne)] at h'; exact zero_ne_one h'
  -- rank count
  have hrankP : P.rank = A.rank := by
    rw [hP, rank_mul_eq_left_of_isUnit_det R _ (isUnit_iff_ne_zero.2 hRd),
      rank_mul_eq_right_of_isUnit_det L A (isUnit_iff_ne_zero.2 hLd)]
  have hPPt : P * Pᵀ = diagonal fun i => if ∃ j, P i j = 1 then (1 : K) else 0 := by
    ext i i'
    rw [mul_apply, diagonal_apply]
    simp only [transpose_apply]
    by_cases hii : i = i'
    · subst hii
      rw [if_pos rfl]
      split_ifs with hex
      · obtain ⟨j, hj⟩ := hex
        rw [Finset.sum_eq_single j]
        · rw [hj, one_mul]
        · intro j' _ hj'
          rcases h01 i j' with h | h
          · rw [h, zero_mul]
          · exact absurd (hrowu i j j' hj h).symm hj'
        · simp
      · push Not at hex
        refine Finset.sum_eq_zero fun j _ => ?_
        rcases h01 i j with h | h
        · rw [h, zero_mul]
        · exact absurd h (hex j)
    · rw [if_neg hii]
      refine Finset.sum_eq_zero fun j _ => ?_
      rcases h01 i j with h | h
      · rw [h, zero_mul]
      rcases h01 i' j with h' | h'
      · rw [h', mul_zero]
      · exact absurd (hcolu i i' j h h') hii
  have hPPtP : P * Pᵀ * P = P := by
    rw [hPPt]
    ext i j
    rw [diagonal_mul]
    split_ifs with hex
    · rw [one_mul]
    · push Not at hex
      rw [zero_mul]
      rcases h01 i j with h | h
      · exact h.symm
      · exact absurd h (hex j)
  have hrank1 : P.rank = (P * Pᵀ).rank := by
    apply le_antisymm
    · calc P.rank = (P * Pᵀ * P).rank := by rw [hPPtP]
        _ ≤ (P * Pᵀ).rank := rank_mul_le_left _ _
    · exact rank_mul_le_left _ _
  have hrank2 : (P * Pᵀ).rank = (univ.filter fun i => ∃ j, P i j = 1).card := by
    rw [hPPt, rank_diagonal, Fintype.card_subtype]
    congr 1
    ext i; simp
  have hcount : (univ.filter fun x : Fin m × Fin m => P x.1 x.2 = 1).card =
      (univ.filter fun i => ∃ j, P i j = 1).card := by
    refine Finset.card_bij (fun x _ => x.1) ?_ ?_ ?_
    · intro x hx; simp only [mem_filter, mem_univ, true_and] at hx ⊢; exact ⟨x.2, hx⟩
    · intro x hx y hy hxy
      simp only [mem_filter, mem_univ, true_and] at hx hy
      have h2 : x.2 = y.2 := hrowu x.1 x.2 y.2 hx (hxy ▸ hy)
      exact Prod.ext hxy h2
    · intro i hi
      simp only [mem_filter, mem_univ, true_and] at hi
      obtain ⟨j, hj⟩ := hi
      exact ⟨(i, j), by simp [hj], rfl⟩
  have hLi := lowerND_inv L hL
  have hRi := lowerND_inv R hR
  exact ⟨L⁻¹, P, R⁻¹, hLi.1, hLi.2, hRi.1, hRi.2, h01, hrowu, hcolu,
    by rw [hcount, ← hrank2, ← hrank1, hrankP], hA⟩
end BruhatCopy

namespace AModelFac

open Matrix AModel

/-! ## 1. Rational Lemma 9 factorizations and good primes -/

section Rational

variable {m : ℕ}

/-- Rational `m × m` matrices. -/
abbrev QMat (m : ℕ) := Matrix (Fin m) (Fin m) ℚ

/-- An integer matrix viewed over `ℚ`. -/
def ratM (A : IMat m) : QMat m := A.map (Int.cast)

/-- The Lemma 9 properties of a triple `(E₁, Π, E₂)` for `A` over `ℚ`. -/
def RatFacSpec (A : QMat m) (F : QMat m × QMat m × QMat m) : Prop :=
  (∀ i j, i < j → F.1 i j = 0) ∧ (∀ i, F.1 i i ≠ 0) ∧
  (∀ i j, i < j → F.2.2 i j = 0) ∧ (∀ i, F.2.2 i i ≠ 0) ∧
  (∀ i j, F.2.1 i j = 0 ∨ F.2.1 i j = 1) ∧
  (∀ i j j', F.2.1 i j = 1 → F.2.1 i j' = 1 → j = j') ∧
  (∀ i i' j, F.2.1 i j = 1 → F.2.1 i' j = 1 → i = i') ∧
  (Finset.univ.filter fun x : Fin m × Fin m => F.2.1 x.1 x.2 = 1).card = A.rank ∧
  A = F.1 * F.2.1 * F.2.2

lemma exists_ratFac (A : IMat m) : ∃ F, RatFacSpec (ratM A) F := by
  obtain ⟨E₁, P, E₂, h⟩ := bruhat_lower (ratM A)
  exact ⟨(E₁, P, E₂), h⟩

/-- The rational factorization of `A`, chosen once (Lemma 9 over `ℚ`). -/
noncomputable def ratFac (A : IMat m) : QMat m × QMat m × QMat m := (exists_ratFac A).choose

/-- `q` avoids every denominator of `E₁, E₂` and every numerator of their diagonals. -/
def GoodAt (q : ℕ) (F : QMat m × QMat m × QMat m) : Prop :=
  (∀ i j, Nat.Coprime (F.1 i j).den q) ∧ (∀ i j, Nat.Coprime (F.2.2 i j).den q) ∧
  (∀ i, Nat.Coprime (F.1 i i).num.natAbs q) ∧ (∀ i, Nat.Coprime (F.2.2 i i).num.natAbs q)

/-- A bound beyond which every prime is good for `ratFac A`. -/
noncomputable def facBound (A : IMat m) : ℕ :=
  (∑ i, ∑ j, (((ratFac A).1 i j).den + ((ratFac A).2.2 i j).den)) +
  ∑ i, (((ratFac A).1 i i).num.natAbs + ((ratFac A).2.2 i i).num.natAbs)

end Rational

/-! ## 2. Reduction `ℚ_(N) → ZMod N` -/

section Reduction

/-- Rationals whose denominator is coprime to `N` (a subring). -/
def goodSub (N : ℕ) : Subring ℚ where
  carrier := {r | Nat.Coprime r.den N}
  zero_mem' := by simp
  one_mem' := by simp
  add_mem' := fun {a b} ha hb =>
    Nat.Coprime.coprime_dvd_left (Rat.add_den_dvd a b) (Nat.Coprime.mul_left ha hb)
  mul_mem' := fun {a b} ha hb =>
    Nat.Coprime.coprime_dvd_left (Rat.mul_den_dvd a b) (Nat.Coprime.mul_left ha hb)
  neg_mem' := fun {a} ha => by simpa [Rat.neg_den] using ha

/-- `r ↦ num · den⁻¹` in `ZMod N`. -/
def redFun (N : ℕ) (r : ℚ) : ZMod N := (r.num : ZMod N) * ((r.den : ℕ) : ZMod N)⁻¹

lemma cancel_coprime {N d : ℕ} (h : Nat.Coprime d N) {x y : ZMod N}
    (hxy : x * d = y * d) : x = y := by
  have := congrArg (· * (d : ZMod N)⁻¹) hxy
  simpa only [mul_assoc, ZMod.coe_mul_inv_eq_one d h, mul_one] using this

lemma redFun_mul_den {N : ℕ} {r : ℚ} (h : Nat.Coprime r.den N) :
    redFun N r * r.den = r.num := by
  rw [redFun, mul_assoc, mul_comm _ (r.den : ZMod N), ZMod.coe_mul_inv_eq_one _ h, mul_one]

/-- Characterization: if `r * d = x` with `d` coprime to `N`, then `red r * d = x`. -/
lemma redFun_spec {N : ℕ} {r : ℚ} (h : Nat.Coprime r.den N) (x : ℤ) (d : ℕ)
    (hr : r * d = x) : redFun N r * d = x := by
  have h1 : (r.num : ℚ) * d = x * r.den := by
    rw [← Rat.mul_den_eq_num r, ← hr]; ring
  have h2 : r.num * (d : ℤ) = x * (r.den : ℤ) := by exact_mod_cast h1
  apply cancel_coprime h
  rw [mul_right_comm, redFun_mul_den h]
  have := congrArg (Int.cast : ℤ → ZMod N) h2
  push_cast at this
  exact this

/-- **Task 2.** The reduction `ℚ_(N) → ZMod N` is a ring hom. -/
def redHom (N : ℕ) : goodSub N →+* ZMod N where
  toFun r := redFun N r
  map_one' := by
    have := redFun_spec (N := N) (r := 1) (by simp) 1 1 (by simp)
    simpa using this
  map_zero' := by
    have := redFun_spec (N := N) (r := 0) (by simp) 0 1 (by simp)
    simpa using this
  map_mul' a b := by
    have ha : Nat.Coprime a.1.den N := a.2
    have hb : Nat.Coprime b.1.den N := b.2
    change redFun N (a.1 * b.1) = redFun N a.1 * redFun N b.1
    have hc : Nat.Coprime (a.1.den * b.1.den) N := Nat.Coprime.mul_left ha hb
    apply cancel_coprime hc
    rw [redFun_spec ((goodSub N).mul_mem a.2 b.2) (a.1.num * b.1.num) _ (by
      push_cast; rw [← Rat.mul_den_eq_num a.1, ← Rat.mul_den_eq_num b.1]; ring)]
    push_cast
    rw [← redFun_mul_den ha, ← redFun_mul_den hb]; ring
  map_add' a b := by
    have ha : Nat.Coprime a.1.den N := a.2
    have hb : Nat.Coprime b.1.den N := b.2
    change redFun N (a.1 + b.1) = redFun N a.1 + redFun N b.1
    have hc : Nat.Coprime (a.1.den * b.1.den) N := Nat.Coprime.mul_left ha hb
    apply cancel_coprime hc
    rw [redFun_spec ((goodSub N).add_mem a.2 b.2) (a.1.num * b.1.den + b.1.num * a.1.den) _ (by
      push_cast; rw [← Rat.mul_den_eq_num a.1, ← Rat.mul_den_eq_num b.1]; ring)]
    push_cast
    rw [← redFun_mul_den ha, ← redFun_mul_den hb]; ring

/-- Into the subring (junk value `0` off it). -/
def toGood (N : ℕ) (r : ℚ) : goodSub N := if h : Nat.Coprime r.den N then ⟨r, h⟩ else 0

/-- The total reduction map `ℚ → ZMod N` (the ring hom `redHom` on `goodSub N`). -/
def redQ (N : ℕ) (r : ℚ) : ZMod N := redHom N (toGood N r)

variable {m : ℕ}

end Reduction

/-! ## 3. `FacAtZ`: the factorization only mod `N`; integer lifts; the bridge -/

section Bridge

variable {m : ℕ}

/-- **Generalized Lemma 10 data mod `N`.** As `FacAt`, but `A = E₁ Π E₂` is only required in
`ZMod N` (this is all `shear_via_pivots_array` uses). -/
def FacAtZ (N : ℕ) (fac : IMat m → IMat m × IMat m × IMat m) (A : IMat m) : Prop :=
  (∀ i j, i < j → (fac A).1 i j = 0) ∧ (∀ i j, i < j → (fac A).2.2 i j = 0) ∧
  (∀ i, IsUnit (((fac A).1 i i : ℤ) : ZMod N)) ∧ (∀ i, IsUnit (((fac A).2.2 i i : ℤ) : ZMod N)) ∧
  (∀ i j, (fac A).2.1 i j = 0 ∨ (fac A).2.1 i j = 1) ∧
  castM N A = castM N (fac A).1 * castM N (fac A).2.1 * castM N (fac A).2.2

/-- Integer lift of the reduction mod `Q` (the representative in `[0, Q)`). -/
def liftZ (Q : ℕ) (r : ℚ) : ℤ := ((redQ Q r).val : ℤ)

/-- The `Π` of `ratFac A` as an integer `0/1` matrix. -/
noncomputable def ratPi (A : IMat m) : IMat m :=
  fun i j => if (ratFac A).2.1 i j = 1 then 1 else 0

/-- The factorization data handed to Prop. 11 at modulus `Q = q ^ b`: integer lifts of the
reductions of the rational `E`'s, and the integer `0/1` matrix `Π`. -/
noncomputable def facZ (Q : ℕ) (A : IMat m) : IMat m × IMat m × IMat m :=
  ((ratFac A).1.map (liftZ Q), ratPi A, (ratFac A).2.2.map (liftZ Q))

end Bridge

/-! ## 4. Prop. 11 from `FacAtZ` (re-proved chain, reusing `AModelProp11`'s lemmas) -/

section Frames

variable {Wr R M : Type*} [Fintype Wr] [DecidableEq Wr] [AddGroup M]

/-- The multiset of all frame changes of a run (the finite set of matrices to factor). -/
def frameMS (gates : List (NGate Wr R M)) (lab Mout : Wr → M) : Multiset M :=
  frameSum (fun a => ({a} : Multiset M)) gates lab Mout

end Frames

section Level

variable {R : Type*} [CommRing R] {m W : ℕ}

/-- The circuit hypotheses of Prop. 11 at field size `N`, with `FacAtZ` in place of `FacAt`. -/
structure OKZ (C : Circuit R m W) (N : ℕ) : Prop where
  gatesOK : ∀ g ∈ C.gates, g.OK
  route : ∀ (v : Fin W → R) w, scalarRun C.gates v (C.ρ w) = v w
  unit : ∀ w, C.Mout (C.ρ w) - C.Min w = 1
  frames : FramesOK (FacAtZ N C.fac) C.gates C.Min C.Mout

variable (C : Circuit R m W) {N : ℕ} [NeZero N] (P L' : ℕ) (A B Cs : Shape)

variable [NeZero W]

end Level

section Recursion

variable {R : Type*} [CommRing R] {m W : ℕ} [NeZero W]

end Recursion

section Cost

variable {R : Type*} [CommRing R] {m W : ℕ}

/-- The only property of the factorization used by the cost analysis: `Π` is `0/1`. -/
def PiOK (fac : IMat m → IMat m × IMat m × IMat m) (A : IMat m) : Prop :=
  ∀ i j, (fac A).2.1 i j = 0 ∨ (fac A).2.1 i j = 1

end Cost

section Assembled

variable {R : Type*} [CommRing R] {m W : ℕ} [NeZero W]

/-- The circuit with its factorization data replaced. -/
def withFac (C : Circuit R m W) (f : IMat m → IMat m × IMat m × IMat m) : Circuit R m W :=
  { C with fac := f }

end Assembled

end AModelFac

end

section
-- Source module: Solutions.AModelL12Basic
/-!
# Lemma 12 (arbitrary-width interchange), generic array-model lemmas

1. `decode_append`, `encode_append_len`; `pull_prefix` (a pull acting only after a prefix does
   not see how the prefix is split into fields), `pull_blockSwap_prefix`.
2. Embedding a small shape into a pointwise larger one (`embed`, zero/default filled) and
   extracting back (`pull T S id`): `extract_pull_embed` — for every address map preserving
   the small-shape validity, embed → pull → extract = pull on the original.
   This is both the row padding `R → R'` and the binary padding `[2^u] → [q^e]`.
3. Adjacent block swaps compose (`blockSwap_blockSwap_adj`); a list of aligned pieces
   (`runPieces`) composes to the swap of the whole chunks (`runPieces_eq`).
4. Block rotation `rotIdx` (the joining moves) on lists, validity, inverse.
-/

namespace AModelL12

open AModel

/-! ## 1. Prefix transport -/

section Prefix

end Prefix

/-! ## 2. Embedding into a larger shape (padding) and extraction -/

section Embed

variable {α : Type*}

/-- `S` is pointwise at most `T` (same number of fields). -/
def ShapeLE (S T : Shape) : Prop :=
  S.length = T.length ∧ ∀ k (h₁ : k < S.length) (h₂ : k < T.length), S[k] ≤ T[k]

open Classical in
/-- Embed an array on `S` into the larger shape `T`: an entry at a `T`-address that is a valid
`S`-address is copied, every other entry is the default `d` (zero padding). -/
noncomputable def embed (S T : Shape) (d : α) (xs : List α) : List α :=
  (List.range (vol T)).map fun j =>
    if Valid S (decode T j) then xs.getD (encode S (decode T j)) d else d

/-- Extraction (scanning away the padding): the pull `T → S` by the identity address map. -/
def extract (S T : Shape) (d : α) (ys : List α) : List α := pull T S id d ys

end Embed

/-! ## 3. Pieces: adjacent block swaps compose -/

section Pieces

/-- Run piece operations: piece `t` has offset `o` (sum of the earlier widths) and width `w t`. -/
def runPieces {α β : Type*} (step : ℕ → β → List α → List α) (w : β → ℕ) :
    ℕ → List β → List α → List α
  | _, [], xs => xs
  | o, t :: ts, xs => runPieces step w (o + w t) ts (step o t xs)

end Pieces

/-! ## 4. Block rotation (the joining moves) -/

section Rotation

/-- Index map of the rotation `A ++ B ++ C ++ D ↦ A ++ C ++ B ++ D` with `|A| = s`, `|B| = b`,
`|C| = c` (digit `k` of the result is digit `rotIdx s b c k` of the input). -/
def rotIdx (s b c k : ℕ) : ℕ :=
  if s ≤ k ∧ k < s + c then k + b else if s + c ≤ k ∧ k < s + c + b then k - c else k

end Rotation

end AModelL12

end

section
-- Source module: Solutions.AModelL12
/-!
# Lemma 12 (arbitrary-width interchange), array model: the procedure and its denotation

Radix-`q` layer. The array lives on `qShape Pre G Suf q e = Pre ++ [q]*e ++ G ++ [q]*e ++ Suf`
(prefix, chunk `h`, gap, chunk `d`, suffix; the chunks are `e` radix-`q` digits each).
The procedure `l12q` (paper, proof of Lemma 12):
1. interchange the top `ρ` digits of the two chunks one pair at a time (`highSwaps`, `ρ` primitive
   single-digit swaps);
2. join: move `h⁺` next to `d⁺` (a field rotation; the result lives on `joinShape`);
3. reshape (free): prefix ↦ one field `P = vol Pre`, `d⁺h⁺` ↦ one row field `R = q^(2ρ)`;
4. pad the row field to `R' = padRows W Kp R` (a multiple of `W ^ Kp`, zero rows appended);
5. write `n = e - ρ` in base `m` and call the Prop. 11 oracle `child j` on each corresponding pair of
   pieces of width `m ^ j` (`pieceLevels`, `runPieces`), all with the shared row field `R'`;
6. unpad (scan away the padded rows), reshape back, reverse the joining rotation.
If `ρ > e` (bounded widths) the procedure does `e` single-digit interchanges instead.

Main theorem `l12q_correct`: for every Prop.-11 oracle `child` satisfying the block-swap spec
(as `prop11`'s first conjunct gives it, when `W ^ j ∣ rows`), `l12q` is the pull by the full
chunk interchange `blockSwap a (a + e + |G|) e`.

Binary layer (`l12bin`): pad each `[2^u]` chunk numerically to `[q^e]` (`embed`, zero outside),
run `l12q` on the radix-`q` digits (reshape is free), extract. `l12bin_correct`: the result is
the pull by the single-field interchange `swapPos a (a + 1 + |G|)` on
`Pre ++ [2^u] ++ G ++ [2^u] ++ Suf` — the paper's `(p,h,g,d,z) ↦ (p,d,g,h,z)`.
-/

namespace AModelL12

open AModel

/-! ## 1. Shapes -/

section Shapes

/-- `[q]*n ++ G ++ [q]*n ++ Suf`: the two remaining chunks with the gap and suffix. -/
def restShape (G Suf : Shape) (q n : ℕ) : Shape :=
  List.replicate n q ++ (G ++ (List.replicate n q ++ Suf))

/-- The radix-`q` shape `Pre ++ [q]*e ++ G ++ [q]*e ++ Suf`. -/
def qShape (Pre G Suf : Shape) (q e : ℕ) : Shape := Pre ++ restShape G Suf q e

/-- The shape after joining: `Pre ++ (d⁺ h⁺) ++ h⁻ ++ G ++ d⁻ ++ Suf` (all digits of size `q`). -/
def joinShape (Pre G Suf : Shape) (q ρ n : ℕ) : Shape :=
  (Pre ++ List.replicate (ρ + ρ) q) ++ restShape G Suf q n

/-- The shape with a single prefix field `P`, a row field `R`, and the remaining chunks. -/
def rowShape (P R : ℕ) (G Suf : Shape) (q n : ℕ) : Shape := P :: R :: restShape G Suf q n

/-- Row count padded to the next multiple of `W ^ K`. -/
def padRows (W K R : ℕ) : ℕ := W ^ K * ((R + W ^ K - 1) / W ^ K)

end Shapes

/-! ## 2. The pieces -/

section PiecesDef

/-- The piece levels: `digit m n j` pieces of width `m ^ j` for every base-`m` digit position `j`. -/
def pieceLevels (m n : ℕ) : List ℕ :=
  (List.range (Nat.digits m n).length).flatMap fun j => List.replicate (digit m n j) j

end PiecesDef

/-! ## 3. The procedure -/

section Procedure

variable {α : Type*}

/-- The oracle type: `child j P L A B Cs` acts on `P :: L :: hdShape A B Cs (m ^ j) q`
(the signature of `prog C q`). -/
abbrev Oracle (α : Type*) := ℕ → ℕ → ℕ → Shape → Shape → Shape → List α → List α

/-- The oracle specification (`prop11`'s first conjunct): at every level `j ≤ K`, with `W ^ j`
dividing the row count, the call is the block swap of the two `m ^ j`-digit chunks. -/
def OracleSpec (child : Oracle α) (d : α) (W m q K : ℕ) : Prop :=
  ∀ j ≤ K, ∀ (P L : ℕ) (A B Cs : Shape) (ys : List α), W ^ j ∣ L →
    ys.length = vol (P :: L :: hdShape A B Cs (m ^ j) q) →
    child j P L A B Cs ys =
      pull (P :: L :: hdShape A B Cs (m ^ j) q) (P :: L :: hdShape A B Cs (m ^ j) q)
        (blockSwap (A.length + 2) (A.length + B.length + m ^ j + 2) (m ^ j)) d ys

/-- `r` primitive single-digit interchanges of positions `i + t ↔ j + t`, `t < r`. -/
def highSwaps (sh : Shape) (i j r : ℕ) (d : α) (xs : List α) : List α :=
  (List.range r).foldl (fun ys t => pull sh sh (swapPos (i + t) (j + t)) d ys) xs

/-- The call on the piece at offset `o` of level `j` (width `m ^ j`): prefix `P`, rows `R'`,
`A = [q]*o`, `B = [q]*(n-o-m^j) ++ G ++ [q]*o`, `Cs = [q]*(n-o-m^j) ++ Suf`. -/
def pieceStep (child : Oracle α) (P R' : ℕ) (G Suf : Shape) (q m n o j : ℕ) (ys : List α) :
    List α :=
  child j P R' (List.replicate o q)
    (List.replicate (n - o - m ^ j) q ++ (G ++ List.replicate o q))
    (List.replicate (n - o - m ^ j) q ++ Suf) ys

/-- **The radix-`q` procedure of Lemma 12.** -/
noncomputable def l12q (child : Oracle α) (W m q Kp ρ : ℕ) (Pre G Suf : Shape) (e : ℕ) (d : α)
    (xs : List α) : List α :=
  if ρ ≤ e then
    let a := Pre.length
    let g := G.length
    let n := e - ρ
    let sh0 := qShape Pre G Suf q e
    let sh1 := joinShape Pre G Suf q ρ n
    let S := rowShape (vol Pre) (q ^ (ρ + ρ)) G Suf q n
    let R' := padRows W Kp (q ^ (ρ + ρ))
    let T := rowShape (vol Pre) R' G Suf q n
    let xs1 := highSwaps sh0 a (a + e + g) ρ d xs
    let xs2 := pull sh0 sh1 (permIdx (rotIdx (a + ρ) ρ (n + g))) d xs1
    let xs3 := AModelL12.embed S T d xs2
    let xs4 := runPieces (pieceStep child (vol Pre) R' G Suf q m n) (fun j => m ^ j) 0
      (pieceLevels m n) xs3
    let xs5 := extract S T d xs4
    pull sh1 sh0 (permIdx (rotIdx (a + ρ) (n + g) ρ)) d xs5
  else
    highSwaps (qShape Pre G Suf q e) Pre.length (Pre.length + e + G.length) e d xs

end Procedure

/-! ## 4. Correctness -/

section Correct

variable {α : Type*}

end Correct

/-! ## 5. Binary chunks: numeric padding `[2^u] → [q^e]` -/

section Binary

variable {α : Type*}

/-- `Pre ++ [F] ++ G ++ [F] ++ Suf`: the two chunks as single fields of size `F`. -/
def binShape (Pre G Suf : Shape) (F : ℕ) : Shape := Pre ++ (F :: (G ++ (F :: Suf)))

/-- **The binary procedure of Lemma 12**: pad both `[2^u]` chunks numerically to `[q^e]` (zero
outside), run the radix-`q` procedure on the digits (reshape is free), scan away the padding. -/
noncomputable def l12bin (child : Oracle α) (W m q Kp ρ e u : ℕ) (Pre G Suf : Shape) (d : α)
    (xs : List α) : List α :=
  extract (binShape Pre G Suf (2 ^ u)) (binShape Pre G Suf (q ^ e)) d
    (l12q child W m q Kp ρ Pre G Suf e d
      (AModelL12.embed (binShape Pre G Suf (2 ^ u)) (binShape Pre G Suf (q ^ e)) d xs))

end Binary

end AModelL12

end

section
-- Source module: Solutions.AModelL12Cost
/-!
# Lemma 12 (arbitrary-width interchange), array model: cost

Cost model (analogous to `progCost`): every primitive pass over the array is charged `c · V`
(`V` its current volume): each of the `ρ` single-digit swaps, each of the `ρ` single-field moves
of the joining and of the separating rotation, the row padding and unpadding (on the padded
volume `V'`). Each Prop. 11 call on a piece of level `j` costs `Tc j V'` (oracle cost at the
padded volume). The fallback (`ρ > e`) costs `e` passes.

* `l12qCost_le`: if `Tc j V ≤ K₀ V (m^j)^τ`, `W ^ Kp ≤ q^(2ρ)` (so `V' < 2V`) and `ρ ≤ D e^τ`,
  then `l12qCost ≤ K'' V e^τ` with `K''` depending only on `m, τ, K₀, c, D`.
* `clog_le_rpow`: `⌈log_m e⌉ ≤ C e^τ`, so `ρ = ρ₀ ⌈log_m e⌉` satisfies the hypothesis.
* `l12binCost`: adds the binary padding / extraction passes.
-/

namespace AModelL12

open AModel Finset

section Cost

/-- **Cost model of `l12q`.** `V = vol (qShape …)`, `V' = vol` of the padded row shape. -/
noncomputable def l12qCost (Tc : ℕ → ℝ → ℝ) (c : ℝ) (W m q Kp ρ : ℕ) (Pre G Suf : Shape)
    (e : ℕ) : ℝ :=
  if ρ ≤ e then
    -- `ρ` single-digit swaps, `ρ` joining moves
    c * (vol (qShape Pre G Suf q e) : ℝ) * ρ + c * (vol (qShape Pre G Suf q e) : ℝ) * ρ +
    -- padding
    c * (vol (rowShape (vol Pre) (padRows W Kp (q ^ (ρ + ρ))) G Suf q (e - ρ)) : ℝ) +
    -- the Prop. 11 calls on the pieces
    ((pieceLevels m (e - ρ)).map fun j =>
      Tc j (vol (rowShape (vol Pre) (padRows W Kp (q ^ (ρ + ρ))) G Suf q (e - ρ)) : ℝ)).sum +
    -- unpadding, `ρ` separating moves
    c * (vol (rowShape (vol Pre) (padRows W Kp (q ^ (ρ + ρ))) G Suf q (e - ρ)) : ℝ) +
    c * (vol (qShape Pre G Suf q e) : ℝ) * ρ
  else c * (vol (qShape Pre G Suf q e) : ℝ) * e

/-- **Cost model of the binary layer**: the padding and extraction passes (on the padded
volume `vol (binShape … (q^e)) = vol (qShape … e)`) plus the radix-`q` procedure. -/
noncomputable def l12binCost (Tc : ℕ → ℝ → ℝ) (c : ℝ) (W m q Kp ρ e : ℕ)
    (Pre G Suf : Shape) : ℝ :=
  c * (vol (binShape Pre G Suf (q ^ e)) : ℝ) + l12qCost Tc c W m q Kp ρ Pre G Suf e +
    c * (vol (binShape Pre G Suf (q ^ e)) : ℝ)

end Cost

end AModelL12

end

section
-- Source module: Solutions.AModelRat
/-!
# Proposition 11 for circuits with rational labels

The paper's circuit (Prop. 7) has rational labels (projections `P_U` with denominators). This
file proves Prop. 11 for a circuit `QCircuit R m W` whose labels are `Matrix (Fin m) (Fin m) ℚ`.

Route (scaling, with a scaled frame action): let `D` be a common denominator of all labels.
The integer circuit `C.toCircuit Q` has labels `D • M` (exact integers, `intM`), so every integer
frame change is exactly `D • A_e` (`A_e` the rational frame change) and the endpoint differences
are exactly `I0 = D • 1` over `ℤ`. The frame action at field size `N` is `φ_N X = D⁻¹ • (X mod N)`
(`phiD`), with `φ_N I0 = 1` and `φ_N (D • A) = A mod N`. The Lemma 10 data of an integer frame
change `X` is the lift mod `Q = q ^ m ^ K` of the rational Bruhat factorization of
`D⁻¹ • X = A_e` (`facD`). The correctness chain of `AModelFac` is re-proved with a general
additive frame action `φ` (`FacAtφ`, `OKφ`, `implΦ_eqφ`, ..., `prog_correctφ`); the cost chain
is reused unchanged (`prog_costZ`, `levelCost_eqZ`).

1. Rational Lemma 9 for rational matrices (`ratFacQ`, `facQ`), the bridge `facAtφ_facD`.
2. Pair-level frame bookkeeping (`FramesOK2`, `frameSum2`) and label maps.
3. The chain with a general frame action.
4. `QCircuit`, `QCircuit.toCircuit`, and `prop11_ratLabels`.
-/

namespace AModelRat

open Matrix AModel AModelFac

/-! ## 1. Rational factorizations of rational matrices; the bridge -/

section RatFac

variable {m : ℕ}

lemma exists_ratFacQ (A : QMat m) : ∃ F, RatFacSpec A F := by
  obtain ⟨E₁, P, E₂, h⟩ := bruhat_lower A
  exact ⟨(E₁, P, E₂), h⟩

/-- The rational Lemma 9 factorization of a rational matrix, chosen once. -/
noncomputable def ratFacQ (A : QMat m) : QMat m × QMat m × QMat m := (exists_ratFacQ A).choose

/-- `q` avoids the denominators of `A` and is good for `ratFacQ A`. -/
def GoodAtQ (q : ℕ) (A : QMat m) : Prop :=
  (∀ i j, Nat.Coprime (A i j).den q) ∧ GoodAt q (ratFacQ A)

/-- A bound beyond which every prime is good for `A`. -/
noncomputable def facBoundQ (A : QMat m) : ℕ :=
  (∑ i, ∑ j, (((ratFacQ A).1 i j).den + ((ratFacQ A).2.2 i j).den + (A i j).den)) +
  ∑ i, (((ratFacQ A).1 i i).num.natAbs + ((ratFacQ A).2.2 i i).num.natAbs)

/-- The `Π` of `ratFacQ A` as an integer `0/1` matrix. -/
noncomputable def piQ (A : QMat m) : IMat m :=
  fun i j => if (ratFacQ A).2.1 i j = 1 then 1 else 0

/-- Lemma 10 data at modulus `Q` for the rational matrix `A`. -/
noncomputable def facQ (Q : ℕ) (A : QMat m) : IMat m × IMat m × IMat m :=
  ((ratFacQ A).1.map (liftZ Q), piQ A, (ratFacQ A).2.2.map (liftZ Q))

/-- Lemma 10 data of an integer frame change `X = D • A`: that of `A = D⁻¹ • X`. -/
noncomputable def facD (Q D : ℕ) (X : IMat m) : IMat m × IMat m × IMat m :=
  facQ Q ((D : ℚ)⁻¹ • ratM X)

/-- The scaled frame action `X ↦ D⁻¹ • (X mod N)`. -/
noncomputable def phiD (N D : ℕ) : IMat m →+ Matrix (Fin m) (Fin m) (ZMod N) where
  toFun X := ((D : ZMod N)⁻¹) • castM N X
  map_zero' := by ext i j; simp [castM]
  map_add' X Y := by ext i j; simp [castM, mul_add]

/-- Lemma 10 data mod `N` for a general additive frame action `φ`: as `FacAtZ`, with the
identity `φ A = E₁ Π E₂` in `ZMod N`. -/
def FacAtφ (N : ℕ) (φ : IMat m →+ Matrix (Fin m) (Fin m) (ZMod N))
    (fac : IMat m → IMat m × IMat m × IMat m) (A : IMat m) : Prop :=
  (∀ i j, i < j → (fac A).1 i j = 0) ∧ (∀ i j, i < j → (fac A).2.2 i j = 0) ∧
  (∀ i, IsUnit (((fac A).1 i i : ℤ) : ZMod N)) ∧ (∀ i, IsUnit (((fac A).2.2 i i : ℤ) : ZMod N)) ∧
  (∀ i j, (fac A).2.1 i j = 0 ∨ (fac A).2.1 i j = 1) ∧
  φ A = castM N (fac A).1 * castM N (fac A).2.1 * castM N (fac A).2.2

end RatFac

/-! ## 2. Pair-level frame bookkeeping -/

section Pairs

variable {Wr R M M' : Type*} [Fintype Wr] [DecidableEq Wr]

/-- `FramesOK` on (new label, old label) pairs. -/
def FramesOK2 (Pr : M → M → Prop) : List (NGate Wr R M) → (Wr → M) → (Wr → M) → Prop
  | [], lab, Mout => ∀ w, Pr (Mout w) (lab w)
  | g :: gs, lab, Mout => (∀ w ∈ g.2.1, Pr g.2.2 (lab w)) ∧ FramesOK2 Pr gs (labStep lab g) Mout

/-- `frameSum` on pairs. -/
def frameSum2 {β : Type*} [AddCommMonoid β] (F : M → M → β) :
    List (NGate Wr R M) → (Wr → M) → (Wr → M) → β
  | [], lab, Mout => ∑ w, F (Mout w) (lab w)
  | g :: gs, lab, Mout => (∑ w ∈ g.2.1, F g.2.2 (lab w)) + frameSum2 F gs (labStep lab g) Mout

/-- Relabel the gates by `f`. -/
def mapG (f : M → M') (gates : List (NGate Wr R M)) : List (NGate Wr R M') :=
  gates.map fun g => (g.1, g.2.1, f g.2.2)

omit [Fintype Wr] in
lemma framesOK2_mono {P P' : M → M → Prop} (h : ∀ a b, P a b → P' a b) :
    ∀ (gates : List (NGate Wr R M)) (lab Mout : Wr → M),
      FramesOK2 P gates lab Mout → FramesOK2 P' gates lab Mout := by
  intro gates
  induction gates with
  | nil => intro lab Mout hF w; exact h _ _ (hF w)
  | cons g gs ih => intro lab Mout hF; exact ⟨fun w hw => h _ _ (hF.1 w hw), ih _ _ hF.2⟩

end Pairs

/-! ## 3. The correctness chain with a general frame action -/

section Level

variable {R : Type*} [CommRing R] {m W : ℕ}

/-- The circuit hypotheses at field size `N` with frame action `φ` and endpoint difference `I0`
(`φ I0 = 1`). -/
structure OKφ (C : Circuit R m W) (N : ℕ) (φ : IMat m →+ Matrix (Fin m) (Fin m) (ZMod N))
    (I0 : IMat m) : Prop where
  gatesOK : ∀ g ∈ C.gates, g.OK
  route : ∀ (v : Fin W → R) w, scalarRun C.gates v (C.ρ w) = v w
  unit : ∀ w, C.Mout (C.ρ w) - C.Min w = I0
  one : φ I0 = 1
  frames : FramesOK (FacAtφ N φ C.fac) C.gates C.Min C.Mout

variable (C : Circuit R m W) {N : ℕ} [NeZero N] (P L' : ℕ) (A B Cs : Shape)

variable [NeZero W]

end Level

section Recursion

variable {R : Type*} [CommRing R] {m W : ℕ} [NeZero W]

end Recursion

/-! ## 4. Rational-label circuits and Proposition 11 -/

section QCirc

variable {m : ℕ}

/-- Product of the denominators of the entries of `M`. -/
def matDen (M : QMat m) : ℕ := ∏ i, ∏ j, (M i j).den

/-- All denominators of `M` divide `D`. -/
def LabOK (D : ℕ) (M : QMat m) : Prop := ∀ i j, (M i j).den ∣ D

/-- The integer matrix `D • M` (exact when `LabOK D M`). -/
def intM (D : ℕ) (M : QMat m) : IMat m := fun i j => ((D : ℚ) * M i j).num

end QCirc

/-- A circuit with **rational** matrix labels (the paper's Prop. 7 circuit): gates on `W` wires
with labels in `Matrix (Fin m) (Fin m) ℚ`, input/output labels, and the routing `ρ`. -/
structure QCircuit (R : Type*) [CommRing R] (m W : ℕ) where
  gates : List (NGate (Fin W) R (QMat m))
  Min : Fin W → QMat m
  Mout : Fin W → QMat m
  ρ : Fin W → Fin W

namespace QCircuit

variable {R : Type*} [CommRing R] {m W : ℕ}

/-- A common denominator of all labels. -/
def den (C : QCircuit R m W) : ℕ :=
  (C.gates.map fun g => matDen g.2.2).prod * (∏ w, matDen (C.Min w)) * ∏ w, matDen (C.Mout w)

/-- **The integer circuit run by the program at modulus `Q`**: labels `D • M` (`D = C.den`),
Lemma 10 data `facD Q D` (lifts mod `Q` of the rational Bruhat factors of `D⁻¹ • X`). -/
noncomputable def toCircuit (C : QCircuit R m W) (Q : ℕ) : Circuit R m W where
  gates := mapG (intM C.den) C.gates
  Min w := intM C.den (C.Min w)
  Mout w := intM C.den (C.Mout w)
  ρ := C.ρ
  fac := facD Q C.den

end QCircuit

section Main

variable {R : Type*} [CommRing R] {m W : ℕ} [NeZero W]

end Main

end AModelRat

end

section
-- Source module: Solutions.AModelL12Main
/-!
# Lemma 12 (arbitrary-width interchange), array model: final statements

* `lemma12`: parametric in a Prop.-11 oracle family `child K` (level bound `K`) satisfying the
  block-swap spec (`OracleSpec`) with cost `Tc K j V ≤ K₀ V (m^j)^τ`. With the parameters of the
  paper — `e = ⌈log_q 2^u⌉` (`eOf`), `Kp = ⌈log_m e⌉` (`kOf`), `ρ = ρ₀ Kp` where
  `W ≤ q^(2ρ₀)` (so `q^(2ρ) ≥ W^Kp`) — the procedure `lemma12Prog` is the interchange
  `(…, h, g, d, …) ↦ (…, d, g, h, …)` of the two `[2^u]` fields of `Pre ++ [2^u] ++ G ++ [2^u] ++ Suf`,
  for every `u ≥ 1` and all shapes, and its cost is `≤ K V u^τ`.
* `lemma12_paper`: the layout `[P] × [2^u] × [G] × [2^u] × [B]`, permutation `swapPos 1 3`.
* `lemma12_rat`: the oracle instantiated with the Prop. 11 program of `prop11_ratLabels`
  (`prog (C.toCircuit (q ^ m ^ K)) q`, cost `progCost`), for every large prime `q`, `ρ₀ = W`.
-/

namespace AModelL12

open AModel

section Final

variable {α : Type*}

/-- `e = ⌈log_q 2^u⌉`: the least `e` with `2^u ≤ q^e`. -/
def eOf (q u : ℕ) : ℕ := Nat.clog q (2 ^ u)

/-- `Kp = ⌈log_m e⌉`: the least `k` with `e ≤ m^k`. -/
def kOf (m q u : ℕ) : ℕ := Nat.clog m (eOf q u)

/-- **The Lemma 12 procedure** with the paper's parameters (`ρ = ρ₀ Kp`). -/
noncomputable def lemma12Prog (child : ℕ → Oracle α) (W m q ρ₀ : ℕ) (Pre G Suf : Shape) (u : ℕ)
    (d : α) (xs : List α) : List α :=
  l12bin (child (kOf m q u)) W m q (kOf m q u) (ρ₀ * kOf m q u) (eOf q u) u Pre G Suf d xs

/-- Its cost under the model of `l12binCost` with oracle costs `Tc (kOf m q u)`. -/
noncomputable def lemma12Cost (Tc : ℕ → ℕ → ℝ → ℝ) (c : ℝ) (W m q ρ₀ : ℕ) (Pre G Suf : Shape)
    (u : ℕ) : ℝ :=
  l12binCost (Tc (kOf m q u)) c W m q (kOf m q u) (ρ₀ * kOf m q u) (eOf q u) Pre G Suf

end Final

/-! ## Instantiation with the Prop. 11 program (`prop11_ratLabels`) -/

section Rat

open AModelRat AModelFac

end Rat

end AModelL12

end

section
-- Source module: Solutions.ButterflyTensor
/-!
# §5.1 Phase-frame identities and tensor products on selected bits

The `2 × 2` matrices of §5.1 of the OpenAI preprint "Integer multiplication below n log n":
`H0 = ½[[1,1],[1,-1]]`, `S = diag(1,i)`, `Z = diag(1,-1)`, `X = [[0,1],[1,0]]`,
`C = HSH = aI + bX` with `a = (1+i)/2`, `b = (1-i)/2`, and the identities (13), (14), (17), (18).

Tensor products over an arbitrary finite set `ι` of selected bits:
`tensF A x y = ∏ i, A i (x i) (y i)` for a family `A : ι → M₂`.
-/

namespace Butterfly

open Matrix Complex Finset

/-- `2 × 2` complex matrices. -/
abbrev M2 := Matrix (Fin 2) (Fin 2) ℂ

/-- `H0 = ½ [[1,1],[1,-1]]`, the normalized butterfly `(u,v) ↦ ((u+v)/2, (u-v)/2)`. -/
noncomputable def H0 : M2 := !![1 / 2, 1 / 2; 1 / 2, -1 / 2]
/-- `S = diag(1, i)`. -/
def Sm : M2 := !![1, 0; 0, I]
/-- `Z = diag(1, -1)`. -/
def Zm : M2 := !![1, 0; 0, -1]
/-- The bit flip `X`. -/
def Xm : M2 := !![0, 1; 1, 0]
/-- `a = (1+i)/2`. -/
noncomputable def ca : ℂ := (1 + I) / 2
/-- `b = (1-i)/2`. -/
noncomputable def cb : ℂ := (1 - I) / 2
/-- The auxiliary two-point kernel `C = aI + bX` (13). -/
noncomputable def Cm : M2 := Butterfly.ca • (1 : M2) + Butterfly.cb • Xm
/-- Its inverse `C⁻¹ = bI + aX` (14). -/
noncomputable def Cinv : M2 := Butterfly.cb • (1 : M2) + Butterfly.ca • Xm

lemma Cm_eq : Butterfly.Cm = !![Butterfly.ca, Butterfly.cb; Butterfly.cb, Butterfly.ca] := by
  ext i j; fin_cases i <;> fin_cases j <;> simp [Butterfly.Cm, Xm]

lemma Cinv_eq : Cinv = !![Butterfly.cb, Butterfly.ca; Butterfly.ca, Butterfly.cb] := by
  ext i j; fin_cases i <;> fin_cases j <;> simp [Cinv, Xm]

/-- (14): `C⁻¹ = -i Z C Z`. -/
theorem Cinv_eq_ZCZ : Cinv = (-I) • (Zm * Butterfly.Cm * Zm) := by
  rw [Cm_eq, Cinv_eq]
  ext i j; fin_cases i <;> fin_cases j <;>
    simp [Zm, Matrix.mul_apply, Fin.sum_univ_two, Butterfly.ca, Butterfly.cb] <;> ring_nf <;> simp [I_sq] <;> ring

/-! ## Tensor products on selected bits -/

section Tensor

variable {ι : Type*} [Fintype ι] [DecidableEq ι]

/-- Tensor product of a family of `2 × 2` matrices over the selected bits `ι`. -/
def tensF (A : ι → M2) : Matrix (ι → Fin 2) (ι → Fin 2) ℂ := fun x y => ∏ i, A i (x i) (y i)

/-- Tensor power of one `2 × 2` matrix. -/
def tens (A : M2) : Matrix (ι → Fin 2) (ι → Fin 2) ℂ := tensF (fun _ => A)

/-- The tensor product is multiplicative. -/
theorem tensF_mul (A B : ι → M2) : tensF (fun i => A i * B i) = tensF A * tensF B := by
  ext x z
  simp only [tensF, Matrix.mul_apply]
  rw [Fintype.prod_sum]
  simp only [← Finset.prod_mul_distrib]

theorem tensF_smul (c : ι → ℂ) (A : ι → M2) :
    tensF (fun i => c i • A i) = (∏ i, c i) • tensF A := by
  ext x y
  simp [tensF, Finset.prod_mul_distrib]

theorem tens_mul (A B : M2) : (Butterfly.tens (A * B) : Matrix (ι → Fin 2) (ι → Fin 2) ℂ) =
    Butterfly.tens A * Butterfly.tens B := tensF_mul _ _

theorem tens_smul (c : ℂ) (A : M2) :
    (Butterfly.tens (c • A) : Matrix (ι → Fin 2) (ι → Fin 2) ℂ) = c ^ Fintype.card ι • Butterfly.tens A := by
  rw [Butterfly.tens, tensF_smul (fun _ => c), Finset.prod_const, Finset.card_univ]; rfl

/-- (17): `(C⁻¹)^{⊗f} = (-i)^f Z^{⊗f} C^{⊗f} Z^{⊗f}`. -/
theorem tens_Cinv : (Butterfly.tens Cinv : Matrix (ι → Fin 2) (ι → Fin 2) ℂ) =
    (-I) ^ Fintype.card ι • (Butterfly.tens Zm * Butterfly.tens Butterfly.Cm * Butterfly.tens Zm) := by
  rw [Cinv_eq_ZCZ, tens_smul, tens_mul, tens_mul]

/-- Number of selected bits equal to one. -/
def wt (x : ι → Fin 2) : ℕ := ∑ i, (x i : ℕ)

/-- The phase diagonal `S_D`: `(S_D z)(x) = i^{x_1+⋯+x_D} z(x)`. -/
noncomputable def SD : Matrix (ι → Fin 2) (ι → Fin 2) ℂ := diagonal fun x => I ^ Butterfly.wt x

/-- The sign diagonal `Z^{⊗}`: `(-1)^{x_1+⋯+x_D}`. -/
noncomputable def ZD : Matrix (ι → Fin 2) (ι → Fin 2) ℂ := diagonal fun x => (-1) ^ Butterfly.wt x

lemma diag2_tens (u v : ℂ) : (Butterfly.tens !![u, 0; 0, v] : Matrix (ι → Fin 2) (ι → Fin 2) ℂ) =
    diagonal fun x => ∏ i, (if x i = 0 then u else v) := by
  ext x y
  simp only [Butterfly.tens, tensF, diagonal_apply]
  by_cases h : x = y
  · subst h; simp only [if_true]
    refine Finset.prod_congr rfl fun i _ => ?_
    rcases Fin.exists_fin_two.1 ⟨x i, rfl⟩ with h0 | h1 <;> simp [*]
  · simp only [h, if_false]
    obtain ⟨i, hi⟩ : ∃ i, x i ≠ y i := by
      by_contra hc; push Not at hc; exact h (funext hc)
    apply Finset.prod_eq_zero (mem_univ i)
    rcases Fin.exists_fin_two.1 ⟨x i, rfl⟩ with h0 | h0 <;>
    rcases Fin.exists_fin_two.1 ⟨y i, rfl⟩ with h1 | h1 <;> simp_all

lemma prod_phase (c : ℂ) (x : ι → Fin 2) :
    ∏ i, (if x i = 0 then (1 : ℂ) else c) = c ^ Butterfly.wt x := by
  rw [Butterfly.wt, ← Finset.prod_pow_eq_pow_sum]
  congr 1; ext i
  rcases Fin.exists_fin_two.1 ⟨x i, rfl⟩ with h | h <;> simp [h]

theorem tens_Zm : (Butterfly.tens Zm : Matrix (ι → Fin 2) (ι → Fin 2) ℂ) = ZD := by
  rw [Zm, diag2_tens, ZD]; congr 1; funext x; exact prod_phase (-1) x

/-- (17) with the `S_D`/`Z_D` diagonals named. -/
theorem tens_Cinv' : (Butterfly.tens Cinv : Matrix (ι → Fin 2) (ι → Fin 2) ℂ) =
    (-I) ^ Fintype.card ι • (ZD * Butterfly.tens Butterfly.Cm * ZD) := by
  rw [tens_Cinv, tens_Zm]

end Tensor

/-! ## (15): address permutations conjugate translations -/

section Translate

variable {K V : Type*} [Ring K] [AddCommGroup V] [Module K V] {β : Type*}

end Translate

/-! ## Elementary row additions generate `GL(m, F₂)` -/

end Butterfly

end

section
-- Source module: Solutions.ButterflyLayer
/-!
# §5 The simultaneous butterfly layer as an array denotation

The array has complete address set `[P] × [2^K]^D × [S]` (shape `layerShape P K D S`), in
lexicographic order, one record per address. Records live in a complex vector space `M`
(a record of `r` coefficients is `Fin r → ℂ`; its sup norm is the maximum coefficient norm, and
every operator below acts coefficientwise because it is `ℂ`-linear on records).

On each of the `D` chunks, bit `ρ` (from the least significant end) is selected.
A matrix `T` on the selected bits acts by
`(selOp T xs)(a) = ∑_y T(bits a, y) • xs(a with selected bits y)`,
fixing every unselected bit and both spectator fields.

* `selOp_mul`, `selOp_one`, `selOp_list_prod`: composition = matrix product.
* `selOp_diagonal`: diagonals are pointwise maps (the phase `S_D`, the signs `Z^{⊗}`).
* `kernel_pair`: an individual selected-bit kernel is the paired map of (25) on the two
  aligned streams split at that bit.
* `layer_eq_kernels`: the layer `A^{⊗D}` is the composition of the `D` individual kernels.
* `butterflyLayer_eq` (18 on arrays): `H0`-layer `= b^D • S_D ∘ C-layer ∘ S_D`.
* `butterflyLayer_norm_le`: disk arrays go to disk arrays.
-/

set_option linter.unusedSectionVars false
set_option linter.unusedSimpArgs false

namespace Butterfly

open AModel Matrix Finset

/-! ## 1. Abstract selected-bit structure on a shape -/

/-- Selected bits of a shape: read them (`bits`) and overwrite them (`set`). -/
structure SelBits (sh : Shape) (ι : Type*) where
  bits : List ℕ → ι → Fin 2
  set : List ℕ → (ι → Fin 2) → List ℕ
  valid_set : ∀ a y, Valid sh a → Valid sh (set a y)
  bits_set : ∀ a y, Valid sh a → bits (set a y) = y
  set_set : ∀ a y z, Valid sh a → set (set a y) z = set a z
  set_bits : ∀ a, Valid sh a → set a (bits a) = a

variable {sh : Shape} {ι : Type*} [Fintype ι] [DecidableEq ι]
variable {M : Type*} [AddCommMonoid M] [Module ℂ M]

/-- A matrix on the selected bits acting on the array (coefficientwise on records). -/
noncomputable def selOp (Sb : SelBits sh ι) (T : Matrix (ι → Fin 2) (ι → Fin 2) ℂ)
    (xs : List M) : List M :=
  (List.range (vol sh)).map fun j =>
    ∑ y, T (Sb.bits (decode sh j)) y • xs.getD (encode sh (Sb.set (decode sh j) y)) 0

variable (Sb : SelBits sh ι)

/-! ## 2. Individual kernels and the full layer -/

/-- The individual kernel of `A` on selected bit `i`: `A` on bit `i`, identity elsewhere. -/
def kerAt (i : ι) (A : M2) : ι → M2 := Function.update (fun _ => 1) i A

/-- The normalized simultaneous butterfly layer `H0^{⊗D}`. -/
noncomputable def butterflyLayer (xs : List M) : List M := selOp Sb (Butterfly.tens H0) xs

/-- The `C`-layer `C^{⊗D}`. -/
noncomputable def cLayer (xs : List M) : List M := selOp Sb (Butterfly.tens Butterfly.Cm) xs

/-- The phase layer `S_D` (pointwise). -/
noncomputable def phaseLayer (xs : List M) : List M := selOp Sb SD xs

/-! ## 3. The concrete layout `[P] × [2^K]^D × [S]` with bit `ρ` selected in every chunk -/

/-- The shape `[P] × [2^K]^D × [S]`. -/
def layerShape (P K D S : ℕ) : Shape := P :: List.replicate D (2 ^ K) ++ [S]

/-- Bit `ρ` of `v` (from the least significant end). -/
def getBit (ρ v : ℕ) : Fin 2 := ⟨(v / 2 ^ ρ) % 2, Nat.mod_lt _ (by norm_num)⟩

/-- Overwrite bit `ρ` of `v` by `b`. -/
def setBit (ρ v : ℕ) (b : Fin 2) : ℕ := v / 2 ^ (ρ + 1) * 2 ^ (ρ + 1) + (b : ℕ) * 2 ^ ρ + v % 2 ^ ρ

section BitArith

lemma setBit_eq (ρ v : ℕ) (b : Fin 2) :
    setBit ρ v b = (2 * (v / 2 ^ (ρ + 1)) + b) * 2 ^ ρ + v % 2 ^ ρ := by
  simp only [setBit, pow_succ]; ring

lemma setBit_div (ρ v : ℕ) (b : Fin 2) : setBit ρ v b / 2 ^ ρ = 2 * (v / 2 ^ (ρ + 1)) + b := by
  rw [setBit_eq, Nat.add_comm, Nat.add_mul_div_right _ _ (by positivity),
    Nat.div_eq_of_lt (Nat.mod_lt _ (by positivity)), zero_add]

lemma setBit_mod (ρ v : ℕ) (b : Fin 2) : setBit ρ v b % 2 ^ ρ = v % 2 ^ ρ := by
  rw [setBit_eq, Nat.add_comm, Nat.add_mul_mod_self_right, Nat.mod_mod]

lemma getBit_setBit (ρ v : ℕ) (b : Fin 2) : getBit ρ (setBit ρ v b) = b := by
  ext; simp only [getBit, setBit_div]
  have := b.isLt; omega

lemma div_two_pow_succ (ρ v : ℕ) : v / 2 ^ (ρ + 1) = v / 2 ^ ρ / 2 := by
  rw [pow_succ, Nat.div_div_eq_div_mul]

lemma setBit_setBit (ρ v : ℕ) (b c : Fin 2) : setBit ρ (setBit ρ v b) c = setBit ρ v c := by
  have h1 : setBit ρ v b / 2 ^ (ρ + 1) = v / 2 ^ (ρ + 1) := by
    rw [div_two_pow_succ, setBit_div]; have := b.isLt; omega
  rw [setBit_eq ρ (setBit ρ v b) c, h1, setBit_mod, ← setBit_eq]

lemma setBit_getBit (ρ v : ℕ) : setBit ρ v (getBit ρ v) = v := by
  have h := Nat.div_add_mod v (2 ^ ρ)
  have h2 := Nat.div_add_mod (v / 2 ^ ρ) 2
  rw [setBit_eq, div_two_pow_succ]
  simp only [getBit]
  calc (2 * (v / 2 ^ ρ / 2) + (v / 2 ^ ρ) % 2) * 2 ^ ρ + v % 2 ^ ρ
      = (v / 2 ^ ρ) * 2 ^ ρ + v % 2 ^ ρ := by rw [h2]
    _ = v := by rw [Nat.mul_comm]; exact h

lemma setBit_lt {ρ K v : ℕ} (hρ : ρ < K) (hv : v < 2 ^ K) (b : Fin 2) : setBit ρ v b < 2 ^ K := by
  have hP : 0 < 2 ^ ρ := by positivity
  have hK : 2 ^ K = 2 ^ (ρ + 1) * 2 ^ (K - (ρ + 1)) := by rw [← pow_add]; congr 1; omega
  have hq : v / 2 ^ (ρ + 1) < 2 ^ (K - (ρ + 1)) := by
    rw [Nat.div_lt_iff_lt_mul (by positivity), Nat.mul_comm, ← hK]; exact hv
  have hr := Nat.mod_lt v hP
  rw [setBit_eq, hK, pow_succ]
  have hb := b.isLt
  have : (2 * (v / 2 ^ (ρ + 1)) + b) * 2 ^ ρ + v % 2 ^ ρ < (2 * (v / 2 ^ (ρ + 1)) + 2) * 2 ^ ρ := by
    nlinarith
  calc _ < (2 * (v / 2 ^ (ρ + 1)) + 2) * 2 ^ ρ := this
    _ = 2 ^ ρ * 2 * (v / 2 ^ (ρ + 1) + 1) := by ring
    _ ≤ 2 ^ ρ * 2 * 2 ^ (K - (ρ + 1)) := Nat.mul_le_mul_left _ hq

end BitArith

section Layout

variable (P K D S ρ : ℕ)

/-- Address normal form `p :: c₀ … c_{D-1} :: [s]`. -/
def mkAddr (p : ℕ) (c : Fin D → ℕ) (s : ℕ) : List ℕ := p :: (List.ofFn c ++ [s])

lemma getD_mkAddr_chunk (p : ℕ) (c : Fin D → ℕ) (s : ℕ) (i : Fin D) :
    (mkAddr D p c s).getD (i + 1) 0 = c i := by
  simp [mkAddr, List.getD_eq_getElem?_getD, List.getElem?_append_left (by simp : (i : ℕ) < (List.ofFn c).length)]

lemma getD_mkAddr_last (p : ℕ) (c : Fin D → ℕ) (s : ℕ) :
    (mkAddr D p c s).getD (D + 1) 0 = s := by
  simp [mkAddr, List.getD_eq_getElem?_getD, List.getElem?_append_right]

lemma headD_mkAddr (p : ℕ) (c : Fin D → ℕ) (s : ℕ) : (mkAddr D p c s).headD 0 = p := rfl

lemma eq_mkAddr {a : List ℕ} (h : a.length = D + 2) :
    a = mkAddr D (a.headD 0) (fun i => a.getD (i + 1) 0) (a.getD (D + 1) 0) := by
  apply List.ext_getElem (by simp [mkAddr, h])
  intro k h₁ h₂
  rcases k with _ | k
  · cases a with
    | nil => simp at h
    | cons x l => simp [mkAddr]
  · simp only [mkAddr, List.getElem_cons_succ]
    by_cases hk : k < D
    · rw [List.getElem_append_left (by simpa using hk)]
      simp [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem h₁]
    · have hk' : k = D := by rw [h] at h₁; omega
      subst hk'
      rw [List.getElem_append_right (by simp)]
      simp [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem h₁]

lemma valid_layer_iff {a : List ℕ} :
    Valid (layerShape P K D S) a ↔ a.length = D + 2 ∧ a.headD 0 < P ∧
      (∀ i : Fin D, a.getD (i + 1) 0 < 2 ^ K) ∧ a.getD (D + 1) 0 < S := by
  constructor
  · intro hv
    have hl : a.length = D + 2 := by rw [hv.length_eq]; simp [layerShape]
    rw [eq_mkAddr D hl] at hv
    refine ⟨hl, ?_, ?_, ?_⟩
    · have := (valid_iff _ _).1 hv
      have h0 := this.2 0 (by simp [mkAddr]) (by simp [layerShape])
      simpa [mkAddr, layerShape] using h0
    · intro i
      have := ((valid_iff _ _).1 hv).2 (i + 1) (by simp [mkAddr]) (by simp [layerShape])
      rw [← getD_mkAddr_chunk D (a.headD 0) (fun i => a.getD (i + 1) 0) (a.getD (D + 1) 0) i]
      rw [List.getD_eq_getElem _ _ (by simp [mkAddr])]
      simpa [layerShape, List.getElem_append_left, mkAddr] using this
    · have := ((valid_iff _ _).1 hv).2 (D + 1) (by simp [mkAddr]) (by simp [layerShape])
      rw [← getD_mkAddr_last D (a.headD 0) (fun i => a.getD (i + 1) 0) (a.getD (D + 1) 0)]
      rw [List.getD_eq_getElem _ _ (by simp [mkAddr])]
      simpa [layerShape, List.getElem_append_right, mkAddr] using this
  · rintro ⟨hl, hp, hc, hs⟩
    rw [valid_iff]
    refine ⟨by simp [hl, layerShape], ?_⟩
    intro k h₁ h₂
    rcases k with _ | k
    · cases a with
      | nil => simp at hl
      | cons x l => simpa [layerShape] using hp
    · simp only [layerShape, List.getElem_cons_succ]
      by_cases hk : k < D
      · rw [List.getElem_append_left (by simpa using hk)]
        have := hc ⟨k, hk⟩
        simpa [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem h₁] using this
      · have hk' : k = D := by rw [hl] at h₁; omega
        subst hk'
        rw [List.getElem_append_right (by simp)]
        simpa [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem h₁] using hs

/-- Selected bits of an address: bit `ρ` of each chunk. -/
def layerBits (a : List ℕ) (i : Fin D) : Fin 2 := getBit ρ (a.getD (i + 1) 0)

/-- Overwrite the selected bits. -/
def layerSet (a : List ℕ) (y : Fin D → Fin 2) : List ℕ :=
  mkAddr D (a.headD 0) (fun i => setBit ρ (a.getD (i + 1) 0) (y i)) (a.getD (D + 1) 0)

/-- The selected-bit structure of `[P] × [2^K]^D × [S]` with offset `ρ < K`. -/
def layerSel (hρ : ρ < K) : SelBits (layerShape P K D S) (Fin D) where
  bits := layerBits D ρ
  set := layerSet D ρ
  valid_set a y ha := by
    obtain ⟨hl, hp, hc, hs⟩ := (valid_layer_iff P K D S).1 ha
    refine (valid_layer_iff P K D S).2 ⟨by simp [layerSet, mkAddr], hp, fun i => ?_, ?_⟩
    · rw [layerSet, getD_mkAddr_chunk]; exact setBit_lt hρ (hc i) _
    · rw [layerSet, getD_mkAddr_last]; exact hs
  bits_set a y _ := by
    funext i; simp only [layerBits, layerSet, getD_mkAddr_chunk, getBit_setBit]
  set_set a y z _ := by
    simp only [layerSet, getD_mkAddr_chunk, getD_mkAddr_last, headD_mkAddr, setBit_setBit]
  set_bits a ha := by
    obtain ⟨hl, -⟩ := (valid_layer_iff P K D S).1 ha
    conv_rhs => rw [eq_mkAddr D hl]
    simp only [layerSet, layerBits, setBit_getBit]

/-- **The simultaneous normalized butterfly layer** of §5 on `[P] × [2^K]^D × [S]`:
`H0^{⊗D}` on bit `ρ` of each of the `D` chunks, coefficientwise, fixing all other bits. -/
noncomputable def layerH (hρ : ρ < K) (xs : List M) : List M :=
  butterflyLayer (layerSel P K D S ρ hρ) xs

end Layout

end Butterfly

end

section
-- Source module: Solutions.ButterflyGuard
/-!
# §5.4 An explicit guard-width bound (and the numeric parts of Proposition 14)

1. The constants `E = 64(W+m+1)³`, `B = s+E`, `ν = min{j ≥ 1 : m^j ≥ B}`, `C1 = max{20, ν+3}`,
   `C0 = 128 m B²` for the complex network `m = 10⁶`, `W_c`, `s_c`: `m^10 < B < m^11`, `ν = 11`,
   `C1 = 20`.
2. The depth recurrence `A(e) ≤ s A(e/m) + E`, `A ≤ 8e` at leaves, gives `A ≤ 8 d B^{k+1}
   ≤ 8 B² d^{ν+1}`, and the final chain `8mB²d^{ν+2}+8d+t+9 ≤ … < 128mB²d^{ν+3} ≤ C0 d^{C1}`.
3. Dyadic growth: a value at arithmetic depth `ℓ` (add, sub, halve, negate, multiply by `i`)
   lies in `2^{-(p+ℓ)} ℤ[i]` with modulus `≤ 2^ℓ`; hence `p+Δ` fractional and `Δ+3` integer and
   sign bits represent it exactly.
4. The final truncation `Q_p` toward zero: `|Q_p z| ≤ |z|`, `|Q_p z - z| < √2 · 2^{-p}`.
5. The width bookkeeping of the proof of Proposition 14.
-/

namespace Butterfly

open Complex

/-! ## 1. The constants -/

/-! ## 2. Depth recurrence and the chain -/

/-! ## 3. Dyadic depth invariant -/

/-! ## 4. Final truncation toward zero -/

/-- Truncation of a real toward zero to the grid `2^{-p} ℤ`, as an integer numerator. -/
noncomputable def truncNum (p : ℕ) (x : ℝ) : ℤ := if 0 ≤ x then ⌊x * 2 ^ p⌋ else ⌈x * 2 ^ p⌉

/-- `Q_p` on a real component. -/
noncomputable def truncR (p : ℕ) (x : ℝ) : ℝ := truncNum p x / 2 ^ p

/-- `Q_p` on a complex coefficient: truncate both components toward zero. -/
noncomputable def Qp (p : ℕ) (z : ℂ) : ℂ := ⟨truncR p z.re, truncR p z.im⟩

/-! ## 5. Width bookkeeping in the proof of Proposition 14 -/

end Butterfly

end
Source
OpenAI, Integer multiplication below n log n (preprint, 23 Sep 2026), https://github.com/openai/math/tree/adc7f1241b42e322a6451854ab7e4b4c146bf78a/preprints/Integer-multiplication-below-n-log-n-September-23-2026. Lean development of the integer-multiplication-kappa campaign.

View graph

Get started

Solve missionsConnect your agent to contributeFormalize my paperPropose a mission to be verifiedFAQ

About Prove2Me

Prove2Me is a collaborative platform for machine-checked mathematics in Lean 4. Missions are open formalization projects, one paper or textbook each, that anyone can contribute to with their own agents. Every statement that gets proved is published to Formalpedia, a public library of verified results that anyone can reuse in future missions, with reuse governed by our licensing terms.

How Prove2Me worksResearch paper
SKILL.mdTourFAQContactTerms
© 2026 Prove2Me