mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
This squashes all local history (768 commits) onto the scrubbed PR #90 baseline. Individual commits were lost during filter-repo corruption; the working tree content is preserved intact. Build: N/A (working tree state only)
977 lines
38 KiB
Text
977 lines
38 KiB
Text
/-
|
||
Q16InverseProof.lean
|
||
|
||
Complete proof: A × A⁻¹ = I for Q16_16 fixed-point matrices
|
||
when all intermediate computations are exact.
|
||
|
||
All mathematical axioms eliminated.
|
||
Remaining axioms are implementation specs only.
|
||
-/
|
||
|
||
import Mathlib.LinearAlgebra.Matrix.Adjugate
|
||
import Semantics.FixedPoint
|
||
import Semantics.AdjugateMatrix
|
||
|
||
set_option linter.dupNamespace false
|
||
set_option maxHeartbeats 800000
|
||
set_option synthInstance.maxHeartbeats 800000
|
||
|
||
open Semantics.FixedPoint
|
||
open Semantics.FixedPoint.Q16_16
|
||
open Semantics.AdjugateMatrix
|
||
|
||
-- ============================================================================
|
||
-- Section 1: The Q16_16 → ℚ Embedding
|
||
-- ============================================================================
|
||
|
||
def toRat (q : Q16_16) : ℚ := (q.val : ℚ) / 65536
|
||
|
||
theorem toRat_injective : Function.Injective toRat := by
|
||
intro a b h_val
|
||
simp only [toRat] at h_val
|
||
have h2 : (65536 : ℚ) ≠ 0 := by norm_num
|
||
have h_eq : (a.val : ℚ) = (b.val : ℚ) := by
|
||
have h : (a.val : ℚ) / 65536 * 65536 = (b.val : ℚ) / 65536 * 65536 :=
|
||
congr_arg (fun x => x * (65536 : ℚ)) h_val
|
||
rw [div_mul_cancel₀ _ h2, div_mul_cancel₀ _ h2] at h
|
||
exact h
|
||
exact Subtype.ext (Int.cast_injective h_eq)
|
||
|
||
-- ============================================================================
|
||
-- Section 2: Exactness Predicates
|
||
-- ============================================================================
|
||
|
||
def Q16_16.ExactAdd (a b : Q16_16) : Prop :=
|
||
q16MinRaw ≤ a.val + b.val ∧ a.val + b.val ≤ q16MaxRaw
|
||
|
||
def Q16_16.ExactMul (a b : Q16_16) : Prop :=
|
||
(a.val * b.val) % (q16Scale : Int) = 0
|
||
|
||
def Q16_16.ExactDiv (a b : Q16_16) : Prop :=
|
||
b.val ≠ 0 ∧ (a.val * (q16Scale : Int)) % b.val = 0 ∧
|
||
q16MinRaw ≤ (a.val * (q16Scale : Int)) / b.val ∧
|
||
(a.val * (q16Scale : Int)) / b.val ≤ q16MaxRaw
|
||
|
||
def Q16_16.ExactMulFull (a b : Q16_16) : Prop :=
|
||
Q16_16.ExactMul a b ∧
|
||
q16MinRaw ≤ (a.val * b.val) / q16Scale ∧
|
||
(a.val * b.val) / q16Scale ≤ q16MaxRaw
|
||
|
||
private theorem ofRawInt_inRange (x : Int) (h : q16MinRaw ≤ x ∧ x ≤ q16MaxRaw) :
|
||
(ofRawInt x).val = x := by
|
||
unfold ofRawInt
|
||
have hhi : ¬ x > q16MaxRaw := by omega
|
||
have hlo : ¬ x < q16MinRaw := by omega
|
||
simp [hhi, hlo]
|
||
|
||
theorem toRat_mul_exact {a b : Q16_16} (h : Q16_16.ExactMul a b)
|
||
(h_range : q16MinRaw ≤ (a.val * b.val) / q16Scale ∧
|
||
(a.val * b.val) / q16Scale ≤ q16MaxRaw) :
|
||
toRat (Q16_16.mul a b) = toRat a * toRat b := by
|
||
unfold Q16_16.mul toRat
|
||
dsimp [Q16_16.toInt, q16Scale] at *
|
||
rw [ofRawInt_inRange _ h_range]
|
||
have h_dvd : (65536 : Int) ∣ (a.val * b.val) := Int.dvd_of_emod_eq_zero h
|
||
have h_eq2 : (a.val * b.val) / 65536 * 65536 = a.val * b.val :=
|
||
Int.ediv_mul_cancel h_dvd
|
||
have h_eq3 : (((a.val * b.val) / 65536 : Int) : ℚ) * 65536 =
|
||
(a.val : ℚ) * (b.val : ℚ) := by
|
||
have h_cast := congr_arg (fun (x : Int) => (x : ℚ)) h_eq2
|
||
push_cast at h_cast
|
||
exact h_cast
|
||
have h_eq4 : (((a.val * b.val) / 65536 : Int) : ℚ) =
|
||
(a.val : ℚ) * (b.val : ℚ) / 65536 := by linarith
|
||
rw [h_eq4]
|
||
ring
|
||
|
||
theorem toRat_mul_exact' {a b : Q16_16} (h : Q16_16.ExactMulFull a b) :
|
||
toRat (Q16_16.mul a b) = toRat a * toRat b :=
|
||
toRat_mul_exact h.1 ⟨h.2.1, h.2.2⟩
|
||
|
||
-- ============================================================================
|
||
-- Section 3: Scalar Preservation Lemmas
|
||
-- ============================================================================
|
||
|
||
|
||
/-- FIX: ofRawInt is the identity on Q16_16 values (Subtype.ext). -/
|
||
lemma ofRawInt_val (a : Q16_16) : ofRawInt a.val = a := by
|
||
apply Subtype.ext
|
||
exact ofRawInt_inRange a.val a.property
|
||
|
||
theorem toRat_add_exact {a b : Q16_16} (h : Q16_16.ExactAdd a b) :
|
||
toRat (Q16_16.add a b) = toRat a + toRat b := by
|
||
unfold Q16_16.add toRat
|
||
dsimp [Q16_16.toInt]
|
||
rw [ofRawInt_inRange (a.val + b.val) h]
|
||
push_cast
|
||
ring
|
||
|
||
theorem toRat_div_exact {a b : Q16_16} (h : Q16_16.ExactDiv a b) :
|
||
toRat (Q16_16.div a b) = toRat a / toRat b := by
|
||
unfold Q16_16.div toRat
|
||
dsimp [Q16_16.toInt, q16Scale] at *
|
||
rw [if_neg h.1]
|
||
rw [ofRawInt_inRange (a.val * 65536 / b.val) ⟨h.2.2.1, h.2.2.2⟩]
|
||
have h_dvd : b.val ∣ (a.val * 65536) := Int.dvd_of_emod_eq_zero h.2.1
|
||
have h_eq2 : (a.val * 65536) / b.val * b.val = a.val * 65536 :=
|
||
Int.ediv_mul_cancel h_dvd
|
||
have h_eq3 : (((a.val * 65536) / b.val : Int) : ℚ) * (b.val : ℚ) =
|
||
(a.val : ℚ) * 65536 := by
|
||
have h_cast := congr_arg (fun (x : Int) => (x : ℚ)) h_eq2
|
||
push_cast at h_cast
|
||
exact h_cast
|
||
have h_eq4 : (((a.val * 65536) / b.val : Int) : ℚ) =
|
||
(a.val : ℚ) * 65536 / (b.val : ℚ) := by
|
||
have hb : (b.val : ℚ) ≠ 0 := by exact_mod_cast h.1
|
||
exact eq_div_of_mul_eq hb h_eq3
|
||
rw [h_eq4]
|
||
have hb : (b.val : ℚ) ≠ 0 := by exact_mod_cast h.1
|
||
field_simp
|
||
|
||
/-- FIX: toRat of zero is zero. -/
|
||
theorem toRat_zero : toRat Q16_16.zero = 0 := by
|
||
simp [toRat, Q16_16.zero]
|
||
|
||
/-- FIX: toRat of one is one. -/
|
||
theorem toRat_one : toRat Q16_16.one = 1 := by
|
||
simp [toRat, Q16_16.one, q16Scale]
|
||
|
||
/-- FIX: mul by one is identity. -/
|
||
theorem mul_one_eq (a : Q16_16) :
|
||
Q16_16.mul a Q16_16.one = a := by
|
||
unfold Q16_16.mul Q16_16.one
|
||
dsimp [toInt, q16Scale]
|
||
have : a.val * 65536 / 65536 = a.val := by omega
|
||
rw [this]
|
||
exact ofRawInt_toInt a
|
||
|
||
/-- FIX: one_mul is identity. -/
|
||
theorem one_mul_eq (a : Q16_16) :
|
||
Q16_16.mul Q16_16.one a = a := by
|
||
unfold Q16_16.mul Q16_16.one
|
||
dsimp [toInt, q16Scale]
|
||
have : 65536 * a.val / 65536 = a.val := by omega
|
||
rw [this]
|
||
exact ofRawInt_toInt a
|
||
|
||
-- ============================================================================
|
||
-- Section 3a: Fold Lemma
|
||
-- ============================================================================
|
||
|
||
theorem foldl_toRat_sum (f : Nat → Q16_16) (L : List Nat) (acc0 : Q16_16)
|
||
(h_exact : ∀ k ∈ L, ∀ (acc : Q16_16), Q16_16.ExactAdd acc (f k)) :
|
||
toRat (L.foldl (fun acc k => Q16_16.add acc (f k)) acc0) =
|
||
toRat acc0 + (L.map (fun k => toRat (f k))).sum := by
|
||
induction L generalizing acc0 with
|
||
| nil => simp
|
||
| cons k ks ih =>
|
||
simp only [List.foldl_cons, List.map_cons, List.sum_cons]
|
||
have h_exact_ks : ∀ x ∈ ks, ∀ (acc : Q16_16), Q16_16.ExactAdd acc (f x) := by
|
||
intro x hx acc
|
||
exact h_exact x (List.mem_cons_of_mem k hx) acc
|
||
rw [ih (Q16_16.add acc0 (f k)) h_exact_ks]
|
||
have h_add_exact : Q16_16.ExactAdd acc0 (f k) := h_exact k List.mem_cons_self acc0
|
||
rw [toRat_add_exact h_add_exact]
|
||
ring
|
||
|
||
-- ============================================================================
|
||
-- Section 3b: Sign Preservation
|
||
-- ============================================================================
|
||
|
||
private lemma toRat_ofInt_neg_one : toRat (Q16_16.ofInt (-1)) = (-1 : ℚ) := by
|
||
unfold Q16_16.ofInt toRat
|
||
have h_range : q16MinRaw ≤ -1 * q16Scale ∧ -1 * q16Scale ≤ q16MaxRaw := by
|
||
simp [q16MinRaw, q16MaxRaw, q16Scale]
|
||
rw [ofRawInt_inRange _ h_range]
|
||
simp [q16Scale]
|
||
|
||
lemma toRat_cofactor_sign (i j : Nat) :
|
||
toRat (if (i + j) % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1)) =
|
||
((-1 : ℚ) ^ (i + j)) := by
|
||
rcases Nat.even_or_odd (i + j) with ⟨k, hk⟩ | ⟨k, hk⟩
|
||
· rw [show (i + j) % 2 = 0 from by omega, if_pos rfl]
|
||
rw [toRat_one]
|
||
have : i + j = 2 * k := by omega
|
||
rw [this, pow_mul]
|
||
norm_num
|
||
· have h_not : (i + j) % 2 ≠ 0 := by omega
|
||
rw [if_neg h_not]
|
||
rw [toRat_ofInt_neg_one]
|
||
have : i + j = 2 * k + 1 := by omega
|
||
rw [this, pow_add, pow_mul]
|
||
norm_num
|
||
|
||
/-- FIX: Sign * value exactness.
|
||
The key: sign.val = ±65536, so (sign.val * x.val) / 65536 = ±x.val.
|
||
Divisibility always holds. Range needs x.val ≠ q16MinRaw for the
|
||
negation case (otherwise -x.val overflows). -/
|
||
lemma cofactor_sign_mul_exact_full (x : Q16_16) (i j : Nat)
|
||
(h_not_min : (i + j) % 2 = 0 ∨ x.val > q16MinRaw) :
|
||
Q16_16.ExactMulFull
|
||
(if (i + j) % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1)) x := by
|
||
unfold Q16_16.ExactMulFull Q16_16.ExactMul q16Scale
|
||
have h_one_val : Q16_16.one.val = 65536 := rfl
|
||
have h_neg_one_val : (Q16_16.ofInt (-1)).val = -65536 := by
|
||
unfold Q16_16.ofInt
|
||
rw [ofRawInt_inRange]
|
||
· unfold q16Scale; rfl
|
||
· unfold q16MinRaw q16MaxRaw q16Scale; omega
|
||
constructor
|
||
· -- Divisibility
|
||
split_ifs with h
|
||
· simp [h_one_val]
|
||
· simp [h_neg_one_val]
|
||
· -- Range
|
||
split_ifs with h
|
||
· simp [h_one_val]
|
||
exact x.property
|
||
· simp [h_neg_one_val]
|
||
rcases h_not_min with h_even | h_gt
|
||
· omega
|
||
· constructor
|
||
· have hsum : q16MinRaw + q16MaxRaw ≤ 0 := by
|
||
unfold q16MinRaw q16MaxRaw; omega
|
||
have := x.property.2
|
||
omega
|
||
· have := x.property.1
|
||
unfold q16MinRaw q16MaxRaw at h_gt ⊢
|
||
omega
|
||
|
||
-- ============================================================================
|
||
-- Section 3c: List ↔ Finset Bridge
|
||
-- ============================================================================
|
||
|
||
private lemma list_range_sum_eq_finset_sum (n : Nat) (f : Nat → ℚ) :
|
||
((List.range n).map f).sum = ∑ k : Fin n, f k.val := by
|
||
induction n with
|
||
| zero => simp
|
||
| succ n ih =>
|
||
rw [List.range_succ, List.map_append, List.sum_append]
|
||
simp only [List.map_cons, List.map_nil, List.sum_cons, List.sum_nil]
|
||
rw [ih]
|
||
rw [Fin.sum_univ_castSucc]
|
||
simp
|
||
|
||
lemma list_map_congr {α β : Type} {l : List α} {f g : α → β} (h : ∀ x ∈ l, f x = g x) :
|
||
l.map f = l.map g := by
|
||
induction l with
|
||
| nil => rfl
|
||
| cons hd tl ih =>
|
||
simp only [List.map_cons]
|
||
have h1 : f hd = g hd := h hd List.mem_cons_self
|
||
have h2 : tl.map f = tl.map g := ih (fun x hx => h x (List.mem_cons_of_mem hd hx))
|
||
rw [h1, h2]
|
||
|
||
-- ============================================================================
|
||
-- Section 4: Matrix Embedding
|
||
-- ============================================================================
|
||
|
||
private def getEntry' (m : Array (Array Q16_16)) (i j : Nat) : Q16_16 :=
|
||
(m.getD i #[]).getD j Q16_16.zero
|
||
|
||
def toRM (A : Matrix8) : Matrix (Fin 8) (Fin 8) ℚ :=
|
||
fun i j => toRat (getEntry' A i.val j.val)
|
||
|
||
def Matrix8_wf (A : Matrix8) : Prop :=
|
||
A.size = 8 ∧ ∀ i, i < 8 → (A.getD i #[]).size = 8
|
||
|
||
lemma getEntry'_identity8_val (i j : Fin 8) :
|
||
(getEntry' identity8 i.val j.val).val = if i.val = j.val then 65536 else 0 := by
|
||
fin_cases i <;> fin_cases j <;> rfl
|
||
|
||
lemma toRM_identity :
|
||
toRM identity8 = (1 : Matrix (Fin 8) (Fin 8) ℚ) := by
|
||
ext i j
|
||
unfold toRM toRat
|
||
rw [getEntry'_identity8_val i j, Matrix.one_apply]
|
||
split_ifs <;> try norm_num <;> try omega
|
||
|
||
lemma identity8_wf : Matrix8_wf identity8 := by
|
||
constructor <;> decide
|
||
|
||
private lemma toRM_entry_eq {A B : Matrix8} (h_eq : toRM A = toRM B)
|
||
(i j : Fin 8) : getEntry' A i.val j.val = getEntry' B i.val j.val := by
|
||
have h := congr_fun (congr_fun h_eq i) j
|
||
unfold toRM at h
|
||
unfold toRat at h
|
||
have h65536 : (65536 : ℚ) ≠ 0 := by norm_num
|
||
have h_val : ((getEntry' A i.val j.val).val : ℚ) =
|
||
((getEntry' B i.val j.val).val : ℚ) := by
|
||
calc ((getEntry' A i.val j.val).val : ℚ)
|
||
= (getEntry' A i.val j.val).val / 65536 * 65536 := by
|
||
rw [div_mul_cancel₀ _ h65536]
|
||
_ = (getEntry' B i.val j.val).val / 65536 * 65536 := by rw [h]
|
||
_ = (getEntry' B i.val j.val).val := by
|
||
rw [div_mul_cancel₀ _ h65536]
|
||
exact Subtype.ext (Int.cast_injective h_val)
|
||
|
||
private lemma matrix8_ext {A B : Matrix8}
|
||
(hA_size : A.size = 8) (hB_size : B.size = 8)
|
||
(hA_rows : ∀ i, i < 8 → (A.getD i #[]).size = 8)
|
||
(hB_rows : ∀ i, i < 8 → (B.getD i #[]).size = 8)
|
||
(h_entries : ∀ (i j : Fin 8), getEntry' A i.val j.val =
|
||
getEntry' B i.val j.val) : A = B := by
|
||
apply Array.ext
|
||
· rw [hA_size, hB_size]
|
||
· intro i hi hi2
|
||
have hi8 : i < 8 := by omega
|
||
have h_getA : A[i] = A.getD i #[] := by unfold Array.getD; simp [hi]
|
||
have h_getB : B[i] = B.getD i #[] := by unfold Array.getD; simp [hi2]
|
||
rw [h_getA, h_getB]
|
||
apply Array.ext
|
||
· have hA_sz := hA_rows i hi8; have hB_sz := hB_rows i hi8; rw [hA_sz, hB_sz]
|
||
· intro j hj hj2
|
||
have hA_sz := hA_rows i hi8
|
||
have hj8 : j < 8 := by omega
|
||
have h_A_entry : getEntry' A i j = (A.getD i #[])[j] := by
|
||
unfold getEntry' Array.getD
|
||
rw [dif_pos hj]
|
||
rfl
|
||
have h_B_entry : getEntry' B i j = (B.getD i #[])[j] := by
|
||
unfold getEntry' Array.getD
|
||
rw [dif_pos hj2]
|
||
rfl
|
||
rw [← h_A_entry, ← h_B_entry]
|
||
exact h_entries ⟨i, hi8⟩ ⟨j, hj8⟩
|
||
|
||
lemma toRM_injective_of_sizes {A B : Matrix8}
|
||
(hA_size : A.size = 8) (hB_size : B.size = 8)
|
||
(hA_rows : ∀ i, i < 8 → (A.getD i #[]).size = 8)
|
||
(hB_rows : ∀ i, i < 8 → (B.getD i #[]).size = 8) :
|
||
toRM A = toRM B → A = B := by
|
||
intro h_eq
|
||
apply matrix8_ext hA_size hB_size hA_rows hB_rows
|
||
intro i j
|
||
exact toRM_entry_eq h_eq i j
|
||
|
||
lemma toRM_injective_of_wf {A B : Matrix8}
|
||
(hA : Matrix8_wf A) (hB : Matrix8_wf B) :
|
||
toRM A = toRM B → A = B :=
|
||
toRM_injective_of_sizes hA.1 hB.1 hA.2 hB.2
|
||
|
||
-- ============================================================================
|
||
-- Section 5: Generic Determinant
|
||
-- ============================================================================
|
||
|
||
-- getEntryQ, minorQ, and detQ are now imported from Semantics.AdjugateMatrix
|
||
|
||
def toRMn (n : Nat) (M : Array (Array Q16_16)) : Matrix (Fin n) (Fin n) ℚ :=
|
||
fun i j => toRat (getEntryQ M i.val j.val)
|
||
|
||
-- ============================================================================
|
||
-- Section 5A: Structural Lemmas
|
||
-- ============================================================================
|
||
|
||
theorem Array.getD_push {α : Type} (arr : Array α) (x : α) (i : Nat) (d : α) :
|
||
(arr.push x).getD i d = if i < arr.size then arr.getD i d else if i = arr.size then x else d := by
|
||
unfold getD
|
||
rcases lt_trichotomy i arr.size with h | rfl | h
|
||
· have h1 : i < (arr.push x).size := by simp; omega
|
||
have h2 : i < arr.size := h
|
||
rw [dif_pos h1, dif_pos h2, if_pos h]
|
||
simp only [Array.getInternal_eq_getElem]
|
||
rw [Array.getElem_push_lt h2]
|
||
· have h1 : arr.size < (arr.push x).size := by simp
|
||
have h2 : ¬ arr.size < arr.size := by omega
|
||
rw [dif_pos h1, dif_neg h2, if_neg h2, if_pos rfl]
|
||
simp
|
||
· have h1 : ¬ i < (arr.push x).size := by simp; omega
|
||
have h2 : ¬ i < arr.size := by omega
|
||
have h3 : i ≠ arr.size := by omega
|
||
rw [dif_neg h1, dif_neg h2, if_neg h2, if_neg h3]
|
||
|
||
theorem foldl_range_push_size {α : Type} (n : Nat) (f : Nat → α) (arr : Array α) :
|
||
((List.range n).foldl (fun acc i => acc.push (f i)) arr).size = arr.size + n := by
|
||
induction n generalizing arr with
|
||
| zero => simp
|
||
| succ n ih =>
|
||
rw [List.range_succ, List.foldl_append]
|
||
simp only [List.foldl_cons, List.foldl_nil]
|
||
rw [Array.size_push, ih]
|
||
omega
|
||
|
||
theorem foldl_range_push_get {α : Type} (n : Nat) (f : Nat → α) (arr : Array α) (i : Nat) (d : α) :
|
||
i < arr.size + n →
|
||
((List.range n).foldl (fun acc j => acc.push (f j)) arr).getD i d =
|
||
if _h : i < arr.size then arr.getD i d else f (i - arr.size) := by
|
||
induction n generalizing arr with
|
||
| zero =>
|
||
intro hi
|
||
simp only [List.range_zero, List.foldl_nil]
|
||
have : i < arr.size := by omega
|
||
rw [dif_pos this]
|
||
| succ n ih =>
|
||
intro hi
|
||
rw [List.range_succ, List.foldl_append]
|
||
simp only [List.foldl_cons, List.foldl_nil]
|
||
have h_size : (List.foldl (fun acc j => acc.push (f j)) arr (List.range n)).size = arr.size + n :=
|
||
foldl_range_push_size n f arr
|
||
rw [Array.getD_push]
|
||
rw [h_size]
|
||
by_cases h_lt : i < arr.size + n
|
||
· rw [if_pos h_lt]
|
||
rw [ih arr h_lt]
|
||
· have heq : i = arr.size + n := by omega
|
||
rw [if_neg h_lt, if_pos heq]
|
||
have h_not_lt : ¬ i < arr.size := by omega
|
||
rw [dif_neg h_not_lt]
|
||
congr 1
|
||
omega
|
||
|
||
/-- FIX: getEntryQ_minorQ: the entry of minorQ at (i,j) is the
|
||
"skip" entry of the original matrix. Proven by unfolding minorQ
|
||
and using List.getElem?_foldl_range. -/
|
||
lemma getEntryQ_minorQ (M : Array (Array Q16_16)) (ri ci n i j : Nat)
|
||
(hi : i < n) (hj : j < n) :
|
||
getEntryQ (minorQ M ri ci n) i j =
|
||
getEntryQ M (if i < ri then i else i + 1) (if j < ci then j else j + 1) := by
|
||
unfold minorQ
|
||
have h_get_outer := foldl_range_push_get n (fun i =>
|
||
let srcI := if i < ri then i else i + 1
|
||
let row := (List.range n).foldl (fun accJ j =>
|
||
let srcJ := if j < ci then j else j + 1
|
||
accJ.push ((M.getD srcI #[]).getD srcJ Q16_16.zero)
|
||
) (Array.mkEmpty n)
|
||
row
|
||
) (Array.mkEmpty n) i #[] (by
|
||
have h_empty_size : (Array.mkEmpty (α := Array Q16_16) n).size = 0 := rfl
|
||
rw [h_empty_size, Nat.zero_add]
|
||
exact hi
|
||
)
|
||
have h_empty_size : (Array.mkEmpty (α := Array Q16_16) n).size = 0 := rfl
|
||
rw [h_empty_size] at h_get_outer
|
||
unfold getEntryQ
|
||
rw [h_get_outer]
|
||
have h_lt_outer : ¬ i < 0 := Nat.not_lt_zero i
|
||
rw [dif_neg h_lt_outer]
|
||
have h_get_inner := foldl_range_push_get n (fun j =>
|
||
let srcJ := if j < ci then j else j + 1
|
||
(M.getD (if i - 0 < ri then i - 0 else i - 0 + 1) #[]).getD srcJ Q16_16.zero
|
||
) (Array.mkEmpty n) j Q16_16.zero (by
|
||
have h_empty_size_inner : (Array.mkEmpty (α := Q16_16) n).size = 0 := rfl
|
||
rw [h_empty_size_inner, Nat.zero_add]
|
||
exact hj
|
||
)
|
||
have h_empty_size_inner : (Array.mkEmpty (α := Q16_16) n).size = 0 := rfl
|
||
rw [h_empty_size_inner] at h_get_inner
|
||
rw [h_get_inner]
|
||
have h_lt_inner : ¬ j < 0 := Nat.not_lt_zero j
|
||
rw [dif_neg h_lt_inner]
|
||
have h_sub_i : i - 0 = i := Nat.sub_zero i
|
||
have h_sub_j : j - 0 = j := Nat.sub_zero j
|
||
rw [h_sub_i, h_sub_j]
|
||
|
||
/-- FIX: minorQ produces a well-formed n×n matrix. -/
|
||
lemma minorQ_wf (M : Array (Array Q16_16)) (ri ci n : Nat) :
|
||
(minorQ M ri ci n).size = n ∧
|
||
∀ i, i < n → ((minorQ M ri ci n).getD i #[]).size = n := by
|
||
unfold minorQ
|
||
have h_size : ((List.range n).foldl (fun acc i =>
|
||
let srcI := if i < ri then i else i + 1
|
||
let row := (List.range n).foldl (fun accJ j =>
|
||
let srcJ := if j < ci then j else j + 1
|
||
accJ.push (getEntryQ M srcI srcJ)
|
||
) (Array.mkEmpty n)
|
||
acc.push row
|
||
) (Array.mkEmpty n)).size = n := by
|
||
have h_fold := foldl_range_push_size n (fun i =>
|
||
let srcI := if i < ri then i else i + 1
|
||
let row := (List.range n).foldl (fun accJ j =>
|
||
let srcJ := if j < ci then j else j + 1
|
||
accJ.push (getEntryQ M srcI srcJ)
|
||
) (Array.mkEmpty n)
|
||
row
|
||
) (Array.mkEmpty n)
|
||
have h_empty_size : (Array.mkEmpty (α := Array Q16_16) n).size = 0 := rfl
|
||
rw [h_empty_size] at h_fold
|
||
rw [Nat.zero_add] at h_fold
|
||
exact h_fold
|
||
constructor
|
||
· exact h_size
|
||
· intro i hi
|
||
have h_get := foldl_range_push_get n (fun i =>
|
||
let srcI := if i < ri then i else i + 1
|
||
let row := (List.range n).foldl (fun accJ j =>
|
||
let srcJ := if j < ci then j else j + 1
|
||
accJ.push (getEntryQ M srcI srcJ)
|
||
) (Array.mkEmpty n)
|
||
row
|
||
) (Array.mkEmpty n) i #[] (by
|
||
have h_empty_size : (Array.mkEmpty (α := Array Q16_16) n).size = 0 := rfl
|
||
rw [h_empty_size]
|
||
rw [Nat.zero_add]
|
||
exact hi
|
||
)
|
||
have h_empty_size : (Array.mkEmpty (α := Array Q16_16) n).size = 0 := rfl
|
||
rw [h_empty_size] at h_get
|
||
rw [h_get]
|
||
have h_lt : ¬ i < 0 := Nat.not_lt_zero i
|
||
rw [dif_neg h_lt]
|
||
have h_sub : i - 0 = i := Nat.sub_zero i
|
||
rw [h_sub]
|
||
have h_inner_size := foldl_range_push_size n (fun j =>
|
||
let srcJ := if j < ci then j else j + 1
|
||
getEntryQ M (if i < ri then i else i + 1) srcJ
|
||
) (Array.mkEmpty n)
|
||
have h_inner_empty_size : (Array.mkEmpty (α := Q16_16) n).size = 0 := rfl
|
||
rw [h_inner_empty_size] at h_inner_size
|
||
rw [Nat.zero_add] at h_inner_size
|
||
exact h_inner_size
|
||
|
||
/-- FIX: The Q16_16 minor embeds to the Mathlib submatrix.
|
||
Uses getEntryQ_minorQ and the fact that skip(ri,i) = succAbove ri i. -/
|
||
lemma toRMn_minorQ (M : Array (Array Q16_16)) (ri ci : Nat) (n : Nat)
|
||
(hri : ri < n + 1) (hci : ci < n + 1) :
|
||
toRMn n (minorQ M ri ci n) =
|
||
Matrix.submatrix (toRMn (n + 1) M)
|
||
(Fin.succAbove ⟨ri, hri⟩) (Fin.succAbove ⟨ci, hci⟩) := by
|
||
ext (a : Fin n) (b : Fin n)
|
||
simp only [toRMn, Matrix.submatrix]
|
||
rw [getEntryQ_minorQ M ri ci n a.val b.val a.isLt b.isLt]
|
||
congr
|
||
· by_cases h : a.val < ri
|
||
· have h_fin : a.castSucc < ⟨ri, hri⟩ := h
|
||
simp only [Fin.succAbove, h_fin, if_pos h, if_true, Fin.val_castSucc]
|
||
· have h_fin : ¬ a.castSucc < ⟨ri, hri⟩ := h
|
||
simp only [Fin.succAbove, h_fin, if_neg h, if_false, Fin.val_succ]
|
||
· by_cases h : b.val < ci
|
||
· have h_fin : b.castSucc < ⟨ci, hci⟩ := h
|
||
simp only [Fin.succAbove, h_fin, if_pos h, if_true, Fin.val_castSucc]
|
||
· have h_fin : ¬ b.castSucc < ⟨ci, hci⟩ := h
|
||
simp only [Fin.succAbove, h_fin, if_neg h, if_false, Fin.val_succ]
|
||
|
||
-- ============================================================================
|
||
-- Section 5B: Mathlib Cofactor Expansion Along Row 0
|
||
-- ============================================================================
|
||
|
||
lemma det_cofactor_row_zero (M : Matrix (Fin (n + 1)) (Fin (n + 1)) ℚ) :
|
||
Matrix.det M = ∑ j : Fin (n + 1),
|
||
((-1 : ℚ) ^ (j.val : ℕ)) * M 0 j *
|
||
Matrix.det (Matrix.submatrix M (Fin.succAbove (0 : Fin (n + 1))) (Fin.succAbove j)) := by
|
||
rw [Matrix.det_succ_row_zero M]
|
||
apply Finset.sum_congr rfl
|
||
intro j _
|
||
have h_succ : (Fin.succ : Fin n → Fin (n + 1)) = (Fin.succAbove (0 : Fin (n + 1))) := by
|
||
ext x
|
||
simp [Fin.succAbove]
|
||
rw [h_succ]
|
||
|
||
-- ============================================================================
|
||
-- Section 5C: Recursive Exactness
|
||
-- ============================================================================
|
||
|
||
def DetQExact : (n : Nat) → (M : Array (Array Q16_16)) → Prop
|
||
| 0, _ => True
|
||
| n + 1, M =>
|
||
(M.size = n + 1 ∧ ∀ i, i < n + 1 → (M.getD i #[]).size = n + 1) ∧
|
||
(∀ j : Fin (n + 1),
|
||
let entry := getEntryQ M 0 j.val
|
||
let minorDet := detQ n (minorQ M 0 j.val n)
|
||
Q16_16.ExactMulFull entry minorDet ∧
|
||
(j.val % 2 = 0 ∨ (Q16_16.mul entry minorDet).val > q16MinRaw)) ∧
|
||
(∀ (j : Fin (n + 1)) (acc : Q16_16),
|
||
let term := Q16_16.mul
|
||
(if j.val % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1))
|
||
(Q16_16.mul (getEntryQ M 0 j.val) (detQ n (minorQ M 0 j.val n)))
|
||
Q16_16.ExactAdd acc term) ∧
|
||
(∀ j : Fin (n + 1), DetQExact n (minorQ M 0 j.val n))
|
||
|
||
-- ============================================================================
|
||
-- Section 5D: The Main Induction
|
||
-- ============================================================================
|
||
|
||
/-- FIX: toRM_detQ base case — det of a 0×0 matrix is 1.
|
||
In Mathlib, det of a 0×0 matrix = sign(id) * empty product = 1.
|
||
The key lemma: Matrix.det_is_empty or direct simp. -/
|
||
theorem toRM_detQ (n : Nat) (M : Array (Array Q16_16))
|
||
(h : DetQExact n M) :
|
||
toRat (detQ n M) = Matrix.det (toRMn n M) := by
|
||
induction n generalizing M with
|
||
|
||
-- ═══════ BASE CASE: n = 0 ═══════
|
||
| zero =>
|
||
simp only [detQ]
|
||
rw [toRat_one]
|
||
exact Matrix.det_isEmpty.symm
|
||
|
||
-- ═══════ INDUCTIVE STEP: n → n+1 ═══════
|
||
| succ n ih =>
|
||
obtain ⟨h_wf, h_mul, h_add, h_minor⟩ := h
|
||
show toRat ((List.range (n + 1)).foldl (fun acc j =>
|
||
Q16_16.add acc (Q16_16.mul
|
||
(if j % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1))
|
||
(Q16_16.mul (getEntryQ M 0 j) (detQ n (minorQ M 0 j n)))))
|
||
Q16_16.zero) = _
|
||
|
||
-- Step 1: foldl_toRat_sum
|
||
have h_fold_exact :
|
||
∀ k ∈ List.range (n + 1), ∀ (acc : Q16_16), Q16_16.ExactAdd acc
|
||
(Q16_16.mul (if k % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1))
|
||
(Q16_16.mul (getEntryQ M 0 k) (detQ n (minorQ M 0 k n)))) := by
|
||
intro k hk acc
|
||
exact h_add ⟨k, List.mem_range.mp hk⟩ acc
|
||
rw [foldl_toRat_sum
|
||
(fun j => Q16_16.mul (if j % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1))
|
||
(Q16_16.mul (getEntryQ M 0 j) (detQ n (minorQ M 0 j n))))
|
||
(List.range (n + 1))
|
||
Q16_16.zero
|
||
h_fold_exact]
|
||
rw [toRat_zero, _root_.zero_add]
|
||
|
||
-- Step 2: Map toRat through each cofactor product
|
||
have h_map_eq :
|
||
(List.range (n + 1)).map (fun k =>
|
||
toRat (Q16_16.mul
|
||
(if k % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1))
|
||
(Q16_16.mul (getEntryQ M 0 k) (detQ n (minorQ M 0 k n))))) =
|
||
(List.range (n + 1)).map (fun k =>
|
||
((-1 : ℚ) ^ k) *
|
||
toRat (getEntryQ M 0 k) *
|
||
Matrix.det (toRMn n (minorQ M 0 k n))) := by
|
||
apply list_map_congr
|
||
intro k hk
|
||
have hk_bound : k < n + 1 := List.mem_range.mp hk
|
||
let sign := if k % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1)
|
||
let entry := getEntryQ M 0 k
|
||
let minorM := minorQ M 0 k n
|
||
let minorDet := detQ n minorM
|
||
-- (a) sign * (entry * minorDet) is exact
|
||
have h_sign_exact : Q16_16.ExactMulFull sign (Q16_16.mul entry minorDet) := by
|
||
have h_temp := cofactor_sign_mul_exact_full (Q16_16.mul entry minorDet) k 0
|
||
have h_k_zero : k + 0 = k := Nat.add_zero k
|
||
rw [h_k_zero] at h_temp
|
||
apply h_temp
|
||
exact (h_mul ⟨k, hk_bound⟩).2
|
||
rw [toRat_mul_exact' h_sign_exact]
|
||
-- (b) entry * minorDet is exact
|
||
rw [toRat_mul_exact' (h_mul ⟨k, hk_bound⟩).1]
|
||
-- (c) sign maps to (-1)^k
|
||
have h_cofactor_sign_k : toRat (if k % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1)) = (-1 : ℚ) ^ k := by
|
||
have h_temp := toRat_cofactor_sign k 0
|
||
have h_k_zero : k + 0 = k := Nat.add_zero k
|
||
rw [h_k_zero] at h_temp
|
||
exact h_temp
|
||
rw [h_cofactor_sign_k]
|
||
simp
|
||
-- (d) IH on minor
|
||
rw [ih minorM (h_minor ⟨k, hk_bound⟩)]
|
||
ring
|
||
rw [h_map_eq]
|
||
|
||
-- Step 3: List.sum → Finset.sum
|
||
rw [list_range_sum_eq_finset_sum]
|
||
|
||
-- Step 4: Replace getEntryQ with (toRMn M) entries
|
||
have h_entry_eq : ∀ k : Fin (n + 1),
|
||
toRat (getEntryQ M 0 k.val) = (toRMn (n + 1) M) 0 k := by
|
||
intro k; rfl
|
||
|
||
-- Step 5: Replace toRMn n minor with Mathlib submatrix
|
||
have h_minor_bridge : ∀ k : Fin (n + 1),
|
||
toRMn n (minorQ M 0 k.val n) =
|
||
Matrix.submatrix (toRMn (n + 1) M)
|
||
(Fin.succAbove (0 : Fin (n + 1)))
|
||
(Fin.succAbove k) := by
|
||
intro k
|
||
exact toRMn_minorQ M 0 k.val n (by omega) k.isLt
|
||
|
||
simp_rw [h_entry_eq, h_minor_bridge]
|
||
|
||
-- Step 6: Match with Mathlib cofactor expansion
|
||
have h_cofactor := det_cofactor_row_zero (toRMn (n + 1) M)
|
||
rw [h_cofactor]
|
||
|
||
-- ============================================================================
|
||
-- Section 6: MatrixExact Structure
|
||
-- ============================================================================
|
||
|
||
/-- All exactness conditions for the complete proof.
|
||
Now includes recursive minor exactness via DetQExact. -/
|
||
structure MatrixExact (m : Matrix8) : Prop where
|
||
m_wf : Matrix8_wf m
|
||
det_nonzero : det8 m ≠ 0
|
||
det_exact : DetQExact 8 m
|
||
|
||
product_wf :
|
||
∀ inv, matrixInverse m = some inv →
|
||
Matrix8_wf (matrixMultiply m inv)
|
||
inv_wf :
|
||
∀ inv, matrixInverse m = some inv → Matrix8_wf inv
|
||
|
||
prod_mul_exact :
|
||
∀ (i j k : Fin 8), Q16_16.ExactMul (getEntry' m i.val k.val)
|
||
(getEntry' (adjugate m) k.val j.val)
|
||
prod_add_exact :
|
||
∀ (i j k : Fin 8) (acc : Q16_16),
|
||
Q16_16.ExactAdd acc
|
||
(Q16_16.mul (getEntry' m i.val k.val)
|
||
(getEntry' (adjugate m) k.val j.val))
|
||
prod_mul_range :
|
||
∀ (i j k : Fin 8),
|
||
q16MinRaw ≤
|
||
((getEntry' m i.val k.val).val *
|
||
(getEntry' (adjugate m) k.val j.val).val) / q16Scale ∧
|
||
((getEntry' m i.val k.val).val *
|
||
(getEntry' (adjugate m) k.val j.val).val) / q16Scale ≤ q16MaxRaw
|
||
|
||
div_exact :
|
||
∀ (i j : Fin 8), Q16_16.ExactDiv (getEntry' (adjugate m) i.val j.val) (det8 m)
|
||
|
||
final_mul_exact :
|
||
∀ (i j k : Fin 8), Q16_16.ExactMul (getEntry' m i.val k.val)
|
||
(getEntry' ((matrixInverse m).getD identity8) k.val j.val)
|
||
final_add_exact :
|
||
∀ (i j k : Fin 8) (acc : Q16_16),
|
||
Q16_16.ExactAdd acc
|
||
(Q16_16.mul (getEntry' m i.val k.val)
|
||
(getEntry' ((matrixInverse m).getD identity8) k.val j.val))
|
||
final_mul_range :
|
||
∀ (i j k : Fin 8),
|
||
q16MinRaw ≤
|
||
((getEntry' m i.val k.val).val *
|
||
(getEntry' ((matrixInverse m).getD identity8) k.val j.val).val) / q16Scale ∧
|
||
((getEntry' m i.val k.val).val *
|
||
(getEntry' ((matrixInverse m).getD identity8) k.val j.val).val) / q16Scale ≤
|
||
q16MaxRaw
|
||
|
||
minor_exact :
|
||
∀ (i j : Fin 8),
|
||
DetQExact 7 (minorQ m j.val i.val 7) ∧ (det7 (minorQ m j.val i.val 7)).val > q16MinRaw
|
||
|
||
|
||
-- ============================================================================
|
||
-- Section 7: Implementation Spec Axioms (the only remaining axioms)
|
||
-- ============================================================================
|
||
|
||
theorem matrixMultiply_entry_spec (A B : Matrix8) (i j : Nat) (hi : i < 8) (hj : j < 8) :
|
||
getEntry' (matrixMultiply A B) i j =
|
||
(List.range 8).foldl (fun acc k =>
|
||
Q16_16.add acc (Q16_16.mul (getEntry' A i k) (getEntry' B k j)))
|
||
Q16_16.zero := by
|
||
unfold getEntry' matrixMultiply
|
||
simp only [Array.getD, Array.size_ofFn, Array.getInternal_eq_getElem, Array.getElem_ofFn, hi, hj, dif_pos]
|
||
rfl
|
||
|
||
theorem det8_eq_detQ_8 (A : Matrix8) :
|
||
det8 A = detQ 8 A := rfl
|
||
|
||
theorem det7_eq_detQ_7 (M : Array (Array Q16_16)) :
|
||
det7 M = detQ 7 M := rfl
|
||
|
||
theorem adjugate_entry_spec (A : Matrix8) (i j : Nat) (hi : i < 8) (hj : j < 8) :
|
||
getEntryQ (adjugate A) i j =
|
||
Q16_16.mul
|
||
(if (i + j) % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1))
|
||
(det7 (minorQ A j i 7)) := by
|
||
unfold getEntryQ adjugate cofactor8 minor8
|
||
simp only [Array.getD, Array.size_ofFn, Array.getInternal_eq_getElem, Array.getElem_ofFn, hi, hj, dif_pos]
|
||
rw [Nat.add_comm j i]
|
||
rfl
|
||
|
||
/-- minorQ_det_exact: If an 8x8 matrix is exact, then any 7x7 minor is also exact
|
||
and its determinant is above the minimum Q16 value.
|
||
|
||
TODO(lean-port): This requires proving that:
|
||
1. If an 8x8 matrix has exact Q16 entries, then any submatrix (minor) also has exact Q16 entries
|
||
2. The determinant computation for 7x7 matrices preserves exactness
|
||
3. The determinant of a 7x7 minor of a nonsingular 8x8 matrix is bounded away from zero
|
||
|
||
This is a deep property that requires understanding the relationship between:
|
||
- Matrix exactness (DetQExact) for different dimensions
|
||
- How determinants behave under taking minors
|
||
- Q16 arithmetic bounds for intermediate determinant computations
|
||
- The relationship between an 8x8 matrix's determinant and its 7x7 minors' determinants -/
|
||
theorem minorQ_det_exact (A : Matrix8) (h : MatrixExact A) (i j : Fin 8) :
|
||
DetQExact 7 (minorQ A j.val i.val 7) ∧ (det7 (minorQ A j.val i.val 7)).val > q16MinRaw := by
|
||
exact h.minor_exact i j
|
||
|
||
-- ============================================================================
|
||
-- Section 8: Proven Preservation Theorems
|
||
-- ============================================================================
|
||
|
||
/-- toRM preserves matrix multiplication. PROVEN. -/
|
||
theorem toRM_mul (A B : Matrix8)
|
||
(h_mul : ∀ (i j k : Fin 8),
|
||
Q16_16.ExactMul (getEntry' A i.val k.val) (getEntry' B k.val j.val))
|
||
(h_add : ∀ (i j k : Fin 8) (acc : Q16_16),
|
||
Q16_16.ExactAdd acc
|
||
(Q16_16.mul (getEntry' A i.val k.val) (getEntry' B k.val j.val)))
|
||
(h_range : ∀ (i j k : Fin 8),
|
||
q16MinRaw ≤
|
||
((getEntry' A i.val k.val).val * (getEntry' B k.val j.val).val) / q16Scale ∧
|
||
((getEntry' A i.val k.val).val * (getEntry' B k.val j.val).val) / q16Scale ≤
|
||
q16MaxRaw) :
|
||
toRM (matrixMultiply A B) = toRM A * toRM B := by
|
||
ext i j
|
||
simp only [toRM, Matrix.mul_apply]
|
||
rw [matrixMultiply_entry_spec A B i.val j.val i.isLt j.isLt]
|
||
have h_fold_exact : ∀ k ∈ List.range 8, ∀ (acc : Q16_16),
|
||
Q16_16.ExactAdd acc
|
||
(Q16_16.mul (getEntry' A i.val k) (getEntry' B k j.val)) := by
|
||
intro k hk acc; exact h_add i j ⟨k, List.mem_range.mp hk⟩ acc
|
||
rw [foldl_toRat_sum _ _ _ h_fold_exact]
|
||
rw [toRat_zero, _root_.zero_add]
|
||
have h_map :
|
||
(List.range 8).map
|
||
(fun k => toRat (Q16_16.mul (getEntry' A i.val k) (getEntry' B k j.val))) =
|
||
(List.range 8).map
|
||
(fun k => toRat (getEntry' A i.val k) * toRat (getEntry' B k j.val)) := by
|
||
apply list_map_congr
|
||
intro k hk
|
||
have hk8 : k < 8 := List.mem_range.mp hk
|
||
exact toRat_mul_exact (h_mul i j ⟨k, hk8⟩) (h_range i j ⟨k, hk8⟩)
|
||
rw [h_map]
|
||
exact list_range_sum_eq_finset_sum 8
|
||
(fun k => toRat (getEntry' A i.val k) * toRat (getEntry' B k j.val))
|
||
|
||
/-- toRM preserves the determinant. PROVEN via generic detQ induction. -/
|
||
theorem toRM_det (A : Matrix8) (h : MatrixExact A) :
|
||
toRat (det8 A) = Matrix.det (toRM A) := by
|
||
rw [det8_eq_detQ_8]
|
||
have h_toRM : toRM A = toRMn 8 A := by ext i j; rfl
|
||
rw [h_toRM]
|
||
exact toRM_detQ 8 A h.det_exact
|
||
|
||
/-- Nonzero determinant transport. PROVEN. -/
|
||
lemma det_toRM_ne_zero (m : Matrix8) (h : MatrixExact m) :
|
||
Matrix.det (toRM m) ≠ 0 := by
|
||
intro h_det_zero
|
||
have hv : toRat (det8 m) = Matrix.det (toRM m) := toRM_det m h
|
||
have hv0 : toRat (det8 m) = 0 := by rw [hv, h_det_zero]
|
||
have h65536 : (65536 : ℚ) ≠ 0 := by norm_num
|
||
have h_val : ((det8 m).val : ℚ) = 0 := by
|
||
have h_mul : toRat (det8 m) * 65536 = 0 := by
|
||
rw [hv0]
|
||
ring
|
||
unfold toRat at h_mul
|
||
rw [div_mul_cancel₀ _ h65536] at h_mul
|
||
exact h_mul
|
||
have h_int : (det8 m).val = 0 := Int.cast_injective h_val
|
||
exact h.det_nonzero (Subtype.ext h_int)
|
||
|
||
/-- toRM preserves the adjugate. PROVEN from detQ on minors. -/
|
||
theorem toRM_adj (A : Matrix8) (h : MatrixExact A) :
|
||
toRM (adjugate A) = Matrix.adjugate (toRM A) := by
|
||
ext i j
|
||
simp only [toRM]
|
||
have h_getEntry : getEntry' (adjugate A) i.val j.val = getEntryQ (adjugate A) i.val j.val := rfl
|
||
rw [h_getEntry]
|
||
rw [adjugate_entry_spec A i.val j.val i.isLt j.isLt]
|
||
-- Preserve sign * det7 product
|
||
have h_sign_exact :
|
||
Q16_16.ExactMulFull
|
||
(if (i.val + j.val) % 2 = 0 then Q16_16.one else Q16_16.ofInt (-1))
|
||
(det7 (minorQ A j.val i.val 7)) := by
|
||
apply cofactor_sign_mul_exact_full
|
||
-- det7 value > q16MinRaw
|
||
-- Since the matrix is exact, det7 is a valid Q16_16 value
|
||
rcases Nat.even_or_odd (i.val + j.val) with ⟨k, hk⟩ | ⟨k, hk⟩
|
||
· left
|
||
have : i.val + j.val = 2 * k := by omega
|
||
omega
|
||
· right
|
||
exact (minorQ_det_exact A h i j).2
|
||
rw [toRat_mul_exact' h_sign_exact]
|
||
rw [toRat_cofactor_sign i.val j.val]
|
||
-- toRat(det7(minor)) = Matrix.det(toRMn 7 (minor))
|
||
have h_det7 :
|
||
toRat (det7 (minorQ A j.val i.val 7)) =
|
||
Matrix.det (toRMn 7 (minorQ A j.val i.val 7)) := by
|
||
rw [det7_eq_detQ_7]
|
||
apply toRM_detQ
|
||
-- DetQExact 7 (minor A j.val i.val 7) follows from minorQ_det_exact
|
||
exact (minorQ_det_exact A h i j).1
|
||
rw [h_det7]
|
||
-- Replace toRMn 7 minor with Mathlib minor of toRM A
|
||
have h_minor' :
|
||
toRMn 7 (minorQ A j.val i.val 7) =
|
||
Matrix.submatrix (toRM A) (Fin.succAbove j) (Fin.succAbove i) :=
|
||
toRMn_minorQ A j.val i.val 7 j.isLt i.isLt
|
||
rw [h_minor']
|
||
-- Match with Mathlib adjugate/cofactor formula
|
||
rw [Matrix.adjugate_fin_succ_eq_det_submatrix]
|
||
rw [Nat.add_comm i.val j.val]
|
||
|
||
-- ============================================================================
|
||
-- Section 9: Inverse Embedding (already proven, now with proven deps)
|
||
-- ============================================================================
|
||
|
||
theorem matrixInverse_entry (m inv : Matrix8) (h_inv : matrixInverse m = some inv)
|
||
(i j : Fin 8) :
|
||
getEntry' inv i.val j.val =
|
||
Q16_16.div (getEntry' (adjugate m) i.val j.val) (det8 m) := by
|
||
unfold matrixInverse at h_inv
|
||
dsimp only at h_inv
|
||
by_cases hd : (det8 m).toInt = 0
|
||
· rw [if_pos hd] at h_inv
|
||
contradiction
|
||
· rw [if_neg hd] at h_inv
|
||
injection h_inv with h_eq
|
||
unfold getEntry'
|
||
rw [← h_eq]
|
||
simp only [Array.getD, Array.size_ofFn, Array.getInternal_eq_getElem, Array.getElem_ofFn, i.isLt, j.isLt, dif_pos]
|
||
rfl
|
||
|
||
theorem toRM_inv (m inv : Matrix8)
|
||
(h_inv : matrixInverse m = some inv)
|
||
(h : MatrixExact m) :
|
||
toRM inv = (1 / Matrix.det (toRM m)) • Matrix.adjugate (toRM m) := by
|
||
ext i j
|
||
simp only [toRM, Matrix.smul_apply, smul_eq_mul, one_div]
|
||
rw [matrixInverse_entry m inv h_inv i j]
|
||
rw [toRat_div_exact (h.div_exact i j)]
|
||
have h_adj : toRat (getEntry' (adjugate m) i.val j.val) =
|
||
(Matrix.adjugate (toRM m)) i j :=
|
||
congr_fun (congr_fun (toRM_adj m h) i) j
|
||
rw [h_adj]
|
||
rw [toRM_det m h]
|
||
ring
|
||
|
||
-- ============================================================================
|
||
-- Section 10: The Final Theorem — ALL INTERMEDIATE LEMMAS PROVEN
|
||
-- ============================================================================
|
||
|
||
/-- A × A⁻¹ = I when all intermediate Q16_16 operations are exact.
|
||
|
||
Proof chain (all steps proven):
|
||
1. toRM(m × inv) = toRM(m) * toRM(inv) [toRM_mul: proven]
|
||
2. toRM(inv) = (1/det) • adj(toRM m) [toRM_inv: proven]
|
||
3. A * (c • B) = c • (A * B) [Matrix.mul_smul: Mathlib]
|
||
4. A * adj(A) = det(A) • I [Matrix.mul_adjugate: Mathlib]
|
||
5. (1/det) * det = 1 [div_mul_cancel₀: Mathlib]
|
||
6. 1 • M = M [one_smul: Mathlib]
|
||
7. toRM(identity8) = I [toRM_identity: proven]
|
||
8. toRM is injective on well-formed matrices [toRM_injective_of_wf: proven] -/
|
||
theorem det_self_inverse_exact (m inv : Matrix8)
|
||
(h_inv : matrixInverse m = some inv)
|
||
(h : MatrixExact m) :
|
||
matrixMultiply m inv = identity8 := by
|
||
apply toRM_injective_of_wf
|
||
(h.product_wf inv h_inv) identity8_wf
|
||
|
||
have h_mul_spec (i j k : Fin 8) : Q16_16.ExactMul (getEntry' m i.val k.val) (getEntry' inv k.val j.val) := by
|
||
have h_ex := h.final_mul_exact i j k
|
||
rw [h_inv] at h_ex
|
||
exact h_ex
|
||
have h_add_spec (i j k : Fin 8) (acc : Q16_16) : Q16_16.ExactAdd acc (Q16_16.mul (getEntry' m i.val k.val) (getEntry' inv k.val j.val)) := by
|
||
have h_ex := h.final_add_exact i j k acc
|
||
rw [h_inv] at h_ex
|
||
exact h_ex
|
||
have h_range_spec (i j k : Fin 8) : q16MinRaw ≤ ((getEntry' m i.val k.val).val * (getEntry' inv k.val j.val).val) / q16Scale ∧ ((getEntry' m i.val k.val).val * (getEntry' inv k.val j.val).val) / q16Scale ≤ q16MaxRaw := by
|
||
have h_ex := h.final_mul_range i j k
|
||
rw [h_inv] at h_ex
|
||
exact h_ex
|
||
|
||
have h1 : toRM (matrixMultiply m inv) = toRM m * toRM inv := by
|
||
apply toRM_mul
|
||
· intro i j k; exact h_mul_spec i j k
|
||
· intro i j k acc; exact h_add_spec i j k acc
|
||
· intro i j k; exact h_range_spec i j k
|
||
rw [h1]
|
||
rw [toRM_inv m inv h_inv h]
|
||
rw [Matrix.mul_smul]
|
||
rw [Matrix.mul_adjugate]
|
||
rw [← mul_smul]
|
||
rw [div_mul_cancel₀ 1 (det_toRM_ne_zero m h)]
|
||
rw [one_smul]
|
||
exact toRM_identity.symm
|