Created
March 3, 2026 10:37
-
-
Save kbuzzard/c592c9e2f1bfcc98dbefd5b7c0cea91a to your computer and use it in GitHub Desktop.
Documented Lean solution to FirstProof Q9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /- | |
| Solution to Problem 9 (arXiv:2602.05192). | |
| Proves `theorem nine`: existence of a polynomial map F (all 5×5 minors of | |
| mode-unfoldings, degree ≤ 5) characterizing factorizability of blockwise | |
| scalings of determinantal tensors from cameras. | |
| (definition docstrings and occasional comments manually added by Kevin Buzzard, | |
| in the process of working out exactly what was proved in this Lean file) | |
| -/ | |
| import Mathlib | |
| set_option linter.style.setOption false | |
| set_option maxHeartbeats 3200000 | |
| set_option maxRecDepth 4000 | |
| set_option linter.mathlibStandardSet false | |
| set_option linter.unnecessarySimpa false | |
| set_option linter.unusedSimpArgs false | |
| set_option linter.unnecessarySeqFocus false | |
| open scoped BigOperators | |
| open Classical Matrix | |
| noncomputable section | |
| namespace Arxiv.«2602.05192» | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Core types (from problem9_formalisation.lean) | |
| -- ═══════════════════════════════════════════════════════════════ | |
| /-- `Matrix3x4` is the type of 3 × 4 matrices with real coefficients. -/ | |
| abbrev Matrix3x4 := Matrix (Fin 3) (Fin 4) ℝ | |
| abbrev Tensor3333 := Fin 3 → Fin 3 → Fin 3 → Fin 3 → ℝ | |
| /-- A term of type `QFamily n` is a function `{0,1,...,n-1}^4 x {0,1,2}^4 → ℝ`. -/ | |
| abbrev QFamily (n : ℕ) := Fin n → Fin n → Fin n → Fin n → Tensor3333 | |
| /-- A term of type `Lambda n` is a function `{0,1,2,...,n-1}^4 → ℝ`. -/ | |
| abbrev Lambda (n : ℕ) := Fin n → Fin n → Fin n → Fin n → ℝ | |
| /-- A predicate on 4-tuples (α,β,γ,δ) saying "we are not all equal to each other"-/ | |
| def NotIdentical {n : ℕ} (α β γ δ : Fin n) : Prop := ¬ (α = β ∧ β = γ ∧ γ = δ) | |
| /-- If `λ` is a function `{0,1,2,...,n-1}^4 → ℝ` and `Q` is a function `{0,1,...,n-1}^4 x {0,1,2}^4 → ℝ` | |
| then `scaleQ λ Q` is a new function `{0,1,...,n-1}^4 x {0,1,2}^4 → ℝ` whose value at `(v,i)` is `λ(v)*Q(v,i)`.-/ | |
| def scaleQ {n : ℕ} (lam : Lambda n) (Q : QFamily n) : QFamily n := | |
| fun α β γ δ i j k ℓ => (lam α β γ δ) * (Q α β γ δ i j k ℓ) | |
| /-- A term of type `AIndex n` is a triple `(α,i,j)` with 0 ≤ α < n, 0 ≤ i ≤ 2 and 0 ≤ j ≤ 3. | |
| So there are 12n terms of this type. -/ | |
| abbrev AIndex (n : ℕ) := Fin n × Fin 3 × Fin 4 | |
| /-- If A_0,A_1,...,A_{n-1} is a family of 3x4 matrices with real coefficients, | |
| and if `0 ≤ α β γ δ < n` and `0 ≤ i,j,k,l ≤ 2`, then `stackedRowsMatrix A α β γ δ i j k l` | |
| is the 4x4 matrix whose 1st row is the i'th row of A_α, whose 2nd row is the j'th row of A_β, whose | |
| third row is the k'th row of A_γ and whose 4th row is the l'th row of A_δ.-/ | |
| def stackedRowsMatrix {n : ℕ} (A : Fin n → Matrix3x4) | |
| (α β γ δ : Fin n) (i j k ℓ : Fin 3) : Matrix (Fin 4) (Fin 4) ℝ := | |
| Matrix.of ![A α i, A β j, A γ k, A δ ℓ] | |
| /-- If A_0,A_1,...,A_{n-1} is a family of 3x4 real matrices, if `0 ≤ α β γ δ < n` and `0 ≤ i,j,k,l ≤ 2`, | |
| then `constructQ A α β γ δ i j k l` is the determinant of the 4x4 matrix | |
| whose 1st row is the i'th row of A_α, whose 2nd row is the j'th row of A_β, whose | |
| third row is the k'th row of A_γ and whose 4th row is the l'th row of A_δ. | |
| -/ | |
| def constructQ {n : ℕ} (A : Fin n → Matrix3x4) : QFamily n := | |
| fun α β γ δ i j k ℓ => Matrix.det (stackedRowsMatrix A α β γ δ i j k ℓ) | |
| /-- A term of the type `QIndex n` is four numbers `0 ≤ α β γ δ < n` and four numbers `0 ≤ i,j,k,l ≤ 2`. | |
| So a term of this type is an octuple `(α,β,γ,δ,i,j,k,l)` and there are `81n^4` terms of this type. -/ | |
| structure QIndex (n : ℕ) where | |
| alpha : Fin n | |
| beta : Fin n | |
| gamma : Fin n | |
| delta : Fin n | |
| i : Fin 3 | |
| j : Fin 3 | |
| k : Fin 3 | |
| l : Fin 3 | |
| deriving DecidableEq | |
| instance {n : ℕ} : Fintype (QIndex n) := | |
| Fintype.ofEquiv (Fin n × Fin n × Fin n × Fin n × Fin 3 × Fin 3 × Fin 3 × Fin 3) | |
| { toFun := fun ⟨a, b, c, d, i, j, k, l⟩ => ⟨a, b, c, d, i, j, k, l⟩ | |
| invFun := fun ⟨a, b, c, d, i, j, k, l⟩ => ⟨a, b, c, d, i, j, k, l⟩ | |
| left_inv := fun ⟨_, _, _, _, _, _, _, _⟩ => rfl | |
| right_inv := fun ⟨_, _, _, _, _, _, _, _⟩ => rfl } | |
| /-- A term of type `PolyMap n N` is `N` polynomials each in `81n^4` variables and with real coefficients. | |
| The 81n^4 variables are indexed by 8-tuples `(α,β,γ,δ,i,j,k,l)` with `0 ≤ α,β,γ,δ < n` and `0 ≤ i,j,k,l < 2`. -/ | |
| abbrev PolyMap (n N : ℕ) := Fin N → MvPolynomial (QIndex n) ℝ | |
| /-- If `F : PolyMap n N` is `N` polynomials `F_0,F_1,...,F_{N-1}` each in 81n^4 variables indexed by | |
| `(α,β,γ,δ,i,j,k,l)` with `0 ≤ α,β,γ,δ < n` and `0 ≤ i,j,k,l ≤ 2`, and if `Q` is a family | |
| of real numbers indexed by the same `(α,β,γ,δ,i,j,k,l)`, then `F.eval Q` is the function `{0,1,...,N-1} → ℝ` | |
| sending `t` to the evaluation of the polynomial `F_t` at the tuple `Q`. -/ | |
| def PolyMap.eval {n N : ℕ} (F : PolyMap n N) (Q : QFamily n) : Fin N → ℝ := | |
| fun t => | |
| (F t).eval (fun v : QIndex n => Q v.alpha v.beta v.gamma v.delta v.i v.j v.k v.l) | |
| /-- `PolyMap.UniformDegreeBound d F` is the statement that each of the N multivariable polynomials | |
| F_0, F_1, ... F_{N-1} has total degree at most `d`. -/ | |
| def PolyMap.UniformDegreeBound {n N : ℕ} (d : ℕ) (F : PolyMap n N) : Prop := | |
| ∀ t : Fin N, (F t).totalDegree ≤ d | |
| /-- `IsZeroVec v` is a stupid way of saying that the vector v is zero. -/ | |
| def IsZeroVec {N : ℕ} (v : Fin N → ℝ) : Prop := ∀ t, v t = 0 | |
| /-- `evalCameraPolynomial p A` is the real number obtained by evaluating the polynomial `p` in 12n variables | |
| at the 12n real numbers coming from the entries of A_0,A_1,...,A_{n-1}. -/ | |
| def evalCameraPolynomial {n : ℕ} (p : MvPolynomial (AIndex n) ℝ) | |
| (A : Fin n → Matrix3x4) : ℝ := | |
| p.eval (fun idx : AIndex n => A idx.1 idx.2.1 idx.2.2) | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Reindexing | |
| -- ═══════════════════════════════════════════════════════════════ | |
| abbrev RowIdx (n : ℕ) := Fin n × Fin 3 | |
| abbrev ColIdx (n : ℕ) := RowIdx n × RowIdx n × RowIdx n | |
| def modeQIdx {n : ℕ} (m : Fin 4) (row : RowIdx n) (col : ColIdx n) : QIndex n := | |
| match m with | |
| | ⟨0, _⟩ => ⟨row.1, col.1.1, col.2.1.1, col.2.2.1, row.2, col.1.2, col.2.1.2, col.2.2.2⟩ | |
| | ⟨1, _⟩ => ⟨col.1.1, row.1, col.2.1.1, col.2.2.1, col.1.2, row.2, col.2.1.2, col.2.2.2⟩ | |
| | ⟨2, _⟩ => ⟨col.1.1, col.2.1.1, row.1, col.2.2.1, col.1.2, col.2.1.2, row.2, col.2.2.2⟩ | |
| | ⟨3, _⟩ => ⟨col.1.1, col.2.1.1, col.2.2.1, row.1, col.1.2, col.2.1.2, col.2.2.2, row.2⟩ | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Polynomial map F | |
| -- ═══════════════════════════════════════════════════════════════ | |
| structure MinorSel (n : ℕ) where | |
| mode : Fin 4 | |
| rows : Fin 5 → RowIdx n | |
| cols : Fin 5 → ColIdx n | |
| deriving DecidableEq | |
| instance {n : ℕ} : Fintype (MinorSel n) := | |
| Fintype.ofEquiv (Fin 4 × (Fin 5 → RowIdx n) × (Fin 5 → ColIdx n)) | |
| { toFun := fun ⟨m, r, c⟩ => ⟨m, r, c⟩ | |
| invFun := fun ⟨m, r, c⟩ => ⟨m, r, c⟩ | |
| left_inv := fun ⟨_, _, _⟩ => rfl | |
| right_inv := fun ⟨_, _, _⟩ => rfl } | |
| def minorPolyMat {n : ℕ} (sel : MinorSel n) : | |
| Matrix (Fin 5) (Fin 5) (MvPolynomial (QIndex n) ℝ) := | |
| fun a b => MvPolynomial.X (modeQIdx sel.mode (sel.rows a) (sel.cols b)) | |
| def minorDet {n : ℕ} (sel : MinorSel n) : MvPolynomial (QIndex n) ℝ := | |
| Matrix.det (minorPolyMat sel) | |
| def numMinors (n : ℕ) : ℕ := Fintype.card (MinorSel n) | |
| def minorEquiv (n : ℕ) : MinorSel n ≃ Fin (numMinors n) := | |
| Fintype.equivFin (MinorSel n) | |
| def polyMapF (n : ℕ) : PolyMap n (numMinors n) := | |
| fun t => minorDet ((minorEquiv n).symm t) | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Degree bound | |
| -- ═══════════════════════════════════════════════════════════════ | |
| private lemma totalDegree_sign_mul_prod_le {n : ℕ} (σ : Equiv.Perm (Fin 5)) | |
| (M : Matrix (Fin 5) (Fin 5) (MvPolynomial (QIndex n) ℝ)) | |
| (hM : ∀ i j, (M i j).totalDegree ≤ 1) : | |
| (Equiv.Perm.sign σ • ∏ i : Fin 5, M (σ i) i).totalDegree ≤ 5 := by | |
| refine le_trans (MvPolynomial.totalDegree_smul_le _ _) ?_ | |
| refine le_trans (MvPolynomial.totalDegree_finset_prod _ _) ?_ | |
| calc ∑ i : Fin 5, (M (σ i) i).totalDegree | |
| ≤ ∑ _i : Fin 5, 1 := Finset.sum_le_sum (fun i _ => hM (σ i) i) | |
| _ = 5 := by simp | |
| lemma totalDegree_minorDet_le {n : ℕ} (sel : MinorSel n) : | |
| (minorDet sel).totalDegree ≤ 5 := by | |
| unfold minorDet | |
| rw [Matrix.det_apply] | |
| refine le_trans (MvPolynomial.totalDegree_finset_sum _ _) ?_ | |
| apply Finset.sup_le | |
| intro σ _ | |
| exact totalDegree_sign_mul_prod_le σ (minorPolyMat sel) | |
| (fun i j => by simp [minorPolyMat, MvPolynomial.totalDegree_X]) | |
| lemma polyMapF_degree_bound (n : ℕ) : | |
| PolyMap.UniformDegreeBound 5 (polyMapF n) := by | |
| intro t; exact totalDegree_minorDet_le _ | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Stacked matrix and rank infrastructure | |
| -- ═══════════════════════════════════════════════════════════════ | |
| def StackedMat {n : ℕ} (A : Fin n → Matrix3x4) : | |
| Matrix (RowIdx n) (Fin 4) ℝ := | |
| fun p k => A p.1 p.2 k | |
| -- Mode-m unfolding of a QFamily (evaluated at specific cameras) | |
| def Unfold {n : ℕ} (m : Fin 4) (X : QFamily n) : | |
| Matrix (RowIdx n) (ColIdx n) ℝ := | |
| match m with | |
| | ⟨0, _⟩ => fun row col => X row.1 col.1.1 col.2.1.1 col.2.2.1 | |
| row.2 col.1.2 col.2.1.2 col.2.2.2 | |
| | ⟨1, _⟩ => fun row col => X col.1.1 row.1 col.2.1.1 col.2.2.1 | |
| col.1.2 row.2 col.2.1.2 col.2.2.2 | |
| | ⟨2, _⟩ => fun row col => X col.1.1 col.2.1.1 row.1 col.2.2.1 | |
| col.1.2 col.2.1.2 row.2 col.2.2.2 | |
| | ⟨3, _⟩ => fun row col => X col.1.1 col.2.1.1 col.2.2.1 row.1 | |
| col.1.2 col.2.1.2 col.2.2.2 row.2 | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Connection: evaluating polynomial F gives actual minors | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- The evaluation of F at a QFamily Q is exactly the 5×5 minors of Unfold m Q | |
| lemma eval_polyMapF_eq_det {n : ℕ} (sel : MinorSel n) (Qf : QFamily n) : | |
| (minorDet sel).eval | |
| (fun v : QIndex n => Qf v.alpha v.beta v.gamma v.delta v.i v.j v.k v.l) = | |
| Matrix.det ((Unfold sel.mode Qf).submatrix sel.rows sel.cols) := by | |
| classical | |
| -- Package evaluation as a ring hom so we can use `RingHom.map_det`. | |
| let φ : MvPolynomial (QIndex n) ℝ →+* ℝ := | |
| MvPolynomial.eval (fun v : QIndex n => Qf v.alpha v.beta v.gamma v.delta v.i v.j v.k v.l) | |
| have hdet : | |
| φ (Matrix.det (minorPolyMat sel)) = | |
| Matrix.det (φ.mapMatrix (minorPolyMat sel)) := by | |
| simpa using (RingHom.map_det φ (minorPolyMat sel)) | |
| have hmap : | |
| φ.mapMatrix (minorPolyMat sel) = | |
| (Unfold sel.mode Qf).submatrix sel.rows sel.cols := by | |
| ext a b | |
| -- `fin_cases` needs a variable, not a projection. | |
| generalize hm : sel.mode = m | |
| fin_cases m <;> | |
| simp [hm, φ, minorPolyMat, modeQIdx, Unfold, Matrix.submatrix_apply] | |
| simpa [minorDet, φ, hmap] using hdet | |
| -- IsZeroVec of F ↔ all 5×5 minors of all unfoldings vanish | |
| lemma isZeroVec_iff_minors_vanish {n : ℕ} (Qf : QFamily n) : | |
| IsZeroVec (PolyMap.eval (polyMapF n) Qf) ↔ | |
| ∀ (m : Fin 4) (rows : Fin 5 → RowIdx n) (cols : Fin 5 → ColIdx n), | |
| Matrix.det ((Unfold m Qf).submatrix rows cols) = 0 := by | |
| constructor | |
| · intro hz m rows cols | |
| have : (minorDet ⟨m, rows, cols⟩).eval | |
| (fun v : QIndex n => Qf v.alpha v.beta v.gamma v.delta v.i v.j v.k v.l) = 0 := by | |
| have := hz (minorEquiv n ⟨m, rows, cols⟩) | |
| simp [PolyMap.eval, polyMapF, Equiv.symm_apply_apply] at this | |
| exact this | |
| rw [eval_polyMapF_eq_det] at this | |
| exact this | |
| · intro hminors t | |
| simp [PolyMap.eval, polyMapF] | |
| set sel := (minorEquiv n).symm t | |
| rw [eval_polyMapF_eq_det sel] | |
| exact hminors sel.mode sel.rows sel.cols | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Rank ≤ 4 ↔ all 5×5 minors vanish (for real matrices) | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Scaling rows/columns (entrywise) cannot increase rank. | |
| lemma rank_scaled_le {α β : Type*} [Fintype α] [Fintype β] | |
| [DecidableEq α] [DecidableEq β] | |
| (M : Matrix α β ℝ) (r : α → ℝ) (c : β → ℝ) : | |
| (Matrix.of fun i j => r i * c j * M i j).rank ≤ M.rank := by | |
| classical | |
| have h : | |
| (Matrix.of fun i j => r i * c j * M i j) = | |
| Matrix.diagonal r * M * Matrix.diagonal c := by | |
| ext i j | |
| -- Left diagonal scales rows; right diagonal scales columns. | |
| simp [Matrix.mul_apply, Matrix.diagonal, Matrix.of_apply, mul_assoc, mul_left_comm, mul_comm] | |
| -- Now use `rank_mul_le_*`. | |
| -- rank((D_r * M) * D_c) ≤ rank(D_r * M) ≤ rank(M) | |
| calc | |
| (Matrix.of fun i j => r i * c j * M i j).rank | |
| = (Matrix.diagonal r * M * Matrix.diagonal c).rank := by simpa [h] | |
| _ ≤ (Matrix.diagonal r * M).rank := Matrix.rank_mul_le_left _ _ | |
| _ ≤ M.rank := Matrix.rank_mul_le_right _ _ | |
| -- rank ≤ 4 → all 5×5 submatrix dets = 0 | |
| lemma rank_le_four_imp_5x5_det_zero {α β : Type*} [Fintype α] [Fintype β] | |
| [DecidableEq α] [DecidableEq β] | |
| (M : Matrix α β ℝ) (hrank : M.rank ≤ 4) | |
| (rows : Fin 5 → α) (cols : Fin 5 → β) : | |
| (M.submatrix rows cols).det = 0 := by | |
| classical | |
| -- `submatrix rows cols` is obtained from `M` by left/right multiplication by selection matrices. | |
| have hsub : (M.submatrix rows cols).rank ≤ M.rank := by | |
| let P : Matrix (Fin 5) α ℝ := Matrix.of fun i j => if j = rows i then (1 : ℝ) else 0 | |
| let Q : Matrix β (Fin 5) ℝ := Matrix.of fun i j => if i = cols j then (1 : ℝ) else 0 | |
| have hPQ : M.submatrix rows cols = P * M * Q := by | |
| ext i j | |
| simp [P, Q, Matrix.mul_apply, Matrix.of_apply] | |
| -- rank(P * M * Q) ≤ rank M | |
| calc | |
| (M.submatrix rows cols).rank | |
| = (P * M * Q).rank := by simpa [hPQ] | |
| _ ≤ (P * M).rank := Matrix.rank_mul_le_left _ _ | |
| _ ≤ M.rank := Matrix.rank_mul_le_right _ _ | |
| have hsub4 : (M.submatrix rows cols).rank ≤ 4 := hsub.trans hrank | |
| -- If det ≠ 0 over a field, the square matrix is a unit, hence has full rank (5), contradiction. | |
| by_contra hdet0 | |
| have hunitDet : IsUnit ((M.submatrix rows cols).det) := by | |
| simpa [isUnit_iff_ne_zero] using hdet0 | |
| have hunit : IsUnit (M.submatrix rows cols) := | |
| (Matrix.isUnit_iff_isUnit_det (M.submatrix rows cols)).2 hunitDet | |
| have hrankfull : (M.submatrix rows cols).rank = 5 := by | |
| simpa [Fintype.card_fin] using Matrix.rank_of_isUnit (M.submatrix rows cols) hunit | |
| have : ¬ (M.submatrix rows cols).rank ≤ 4 := by | |
| simpa [hrankfull] | |
| exact this hsub4 | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Forward direction: factorable λ ⇒ F(T) = 0 | |
| -- ═══════════════════════════════════════════════════════════════ | |
| -- Diagonal blocks vanish (4 rows from same camera → repeated row → det = 0) | |
| lemma constructQ_diag {n : ℕ} (A : Fin n → Matrix3x4) (α : Fin n) | |
| (i j k l : Fin 3) : | |
| constructQ A α α α α i j k l = 0 := by | |
| classical | |
| unfold constructQ stackedRowsMatrix | |
| -- Among 4 rows from 3 possible rows, two must be equal by pigeonhole | |
| have : i = j ∨ i = k ∨ i = l ∨ j = k ∨ j = l ∨ k = l := by | |
| rcases i with ⟨i, hi⟩; rcases j with ⟨j, hj⟩ | |
| rcases k with ⟨k, hk⟩; rcases l with ⟨l, hl⟩ | |
| omega | |
| -- Convert each equality into a repeated-row determinant. | |
| rcases this with (hij | hik | hil | hjk | hjl | hkl) | |
| · subst hij | |
| refine Matrix.det_zero_of_row_eq (M := Matrix.of ![A α i, A α i, A α k, A α l]) | |
| (i := (0 : Fin 4)) (j := (1 : Fin 4)) (i_ne_j := by decide) ?_ | |
| ext c <;> simp | |
| · subst hik | |
| refine Matrix.det_zero_of_row_eq (M := Matrix.of ![A α i, A α j, A α i, A α l]) | |
| (i := (0 : Fin 4)) (j := (2 : Fin 4)) (i_ne_j := by decide) ?_ | |
| ext c <;> simp | |
| · subst hil | |
| refine Matrix.det_zero_of_row_eq (M := Matrix.of ![A α i, A α j, A α k, A α i]) | |
| (i := (0 : Fin 4)) (j := (3 : Fin 4)) (i_ne_j := by decide) ?_ | |
| ext c <;> simp | |
| · subst hjk | |
| refine Matrix.det_zero_of_row_eq (M := Matrix.of ![A α i, A α j, A α j, A α l]) | |
| (i := (1 : Fin 4)) (j := (2 : Fin 4)) (i_ne_j := by decide) ?_ | |
| ext c <;> simp | |
| · subst hjl | |
| refine Matrix.det_zero_of_row_eq (M := Matrix.of ![A α i, A α j, A α k, A α j]) | |
| (i := (1 : Fin 4)) (j := (3 : Fin 4)) (i_ne_j := by decide) ?_ | |
| ext c <;> simp | |
| · subst hkl | |
| refine Matrix.det_zero_of_row_eq (M := Matrix.of ![A α i, A α j, A α k, A α k]) | |
| (i := (2 : Fin 4)) (j := (3 : Fin 4)) (i_ne_j := by decide) ?_ | |
| ext c <;> simp | |
| -- Rank of each Q-unfolding ≤ 4 | |
| def fixedRowsMat {n : ℕ} (A : Fin n → Matrix3x4) (col : ColIdx n) : | |
| Matrix (Fin 3) (Fin 4) ℝ := | |
| Matrix.of ![A col.1.1 col.1.2, A col.2.1.1 col.2.1.2, A col.2.2.1 col.2.2.2] | |
| def cofactorMat {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) : | |
| Matrix (Fin 4) (ColIdx n) ℝ := | |
| fun k col => | |
| -- Use `Nat` addition to match the sign convention in `Matrix.det_succ_row`. | |
| (-1 : ℝ) ^ ((m : ℕ) + (k : ℕ)) * | |
| Matrix.det ((fixedRowsMat A col).submatrix id (Fin.succAbove k)) | |
| lemma unfold_constructQ_eq_mul {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) : | |
| Unfold m (constructQ A) = StackedMat A * cofactorMat A m := by | |
| classical | |
| ext row col | |
| fin_cases m | |
| · -- mode 0: expand along row 0 | |
| let S : Matrix (Fin 4) (Fin 4) ℝ := | |
| stackedRowsMatrix A row.1 col.1.1 col.2.1.1 col.2.2.1 row.2 col.1.2 col.2.1.2 col.2.2.2 | |
| have hsub : | |
| ∀ k : Fin 4, | |
| S.submatrix Fin.succ k.succAbove = | |
| (fixedRowsMat A col).submatrix id k.succAbove := by | |
| intro k | |
| ext i j | |
| fin_cases i <;> fin_cases j <;> simp [S, fixedRowsMat, stackedRowsMatrix, Fin.succAbove] | |
| -- Unfold both sides; then use Laplace expansion of `det S` along row 0. | |
| simp [Unfold, constructQ, StackedMat, cofactorMat, fixedRowsMat, S, Matrix.mul_apply] | |
| rw [Matrix.det_succ_row_zero (A := S)] | |
| -- Rewrite the minors and the active row entries. | |
| refine Finset.sum_congr rfl ?_ | |
| intro k hk | |
| have hminor : | |
| Matrix.det (S.submatrix Fin.succ k.succAbove) = | |
| Matrix.det ((fixedRowsMat A col).submatrix id k.succAbove) := by | |
| simpa [hsub k] | |
| -- `ring` handles the commutativity/associativity rearrangements cleanly. | |
| rw [hminor] | |
| simp [S, stackedRowsMatrix, StackedMat, fixedRowsMat] | |
| ring_nf | |
| · -- mode 1: expand along row 1 | |
| let S : Matrix (Fin 4) (Fin 4) ℝ := | |
| stackedRowsMatrix A col.1.1 row.1 col.2.1.1 col.2.2.1 col.1.2 row.2 col.2.1.2 col.2.2.2 | |
| have hsub : | |
| ∀ k : Fin 4, | |
| S.submatrix (Fin.succAbove (1 : Fin 4)) k.succAbove = | |
| (fixedRowsMat A col).submatrix id k.succAbove := by | |
| intro k | |
| ext i j | |
| fin_cases i <;> fin_cases j <;> simp [S, fixedRowsMat, stackedRowsMatrix, Fin.succAbove] | |
| simp [Unfold, constructQ, StackedMat, cofactorMat, fixedRowsMat, S, Matrix.mul_apply] | |
| rw [Matrix.det_succ_row (A := S) (i := (1 : Fin 4))] | |
| refine Finset.sum_congr rfl ?_ | |
| intro k hk | |
| have hminor : | |
| Matrix.det (S.submatrix (Fin.succAbove (1 : Fin 4)) k.succAbove) = | |
| Matrix.det ((fixedRowsMat A col).submatrix id k.succAbove) := by | |
| simpa [hsub k] | |
| rw [hminor] | |
| simp [S, stackedRowsMatrix, StackedMat, fixedRowsMat] | |
| ring_nf | |
| · -- mode 2: expand along row 2 | |
| let S : Matrix (Fin 4) (Fin 4) ℝ := | |
| stackedRowsMatrix A col.1.1 col.2.1.1 row.1 col.2.2.1 col.1.2 col.2.1.2 row.2 col.2.2.2 | |
| have hsub : | |
| ∀ k : Fin 4, | |
| S.submatrix (Fin.succAbove (2 : Fin 4)) k.succAbove = | |
| (fixedRowsMat A col).submatrix id k.succAbove := by | |
| intro k | |
| ext i j | |
| fin_cases i <;> fin_cases j <;> simp [S, fixedRowsMat, stackedRowsMatrix, Fin.succAbove] | |
| simp [Unfold, constructQ, StackedMat, cofactorMat, fixedRowsMat, S, Matrix.mul_apply] | |
| rw [Matrix.det_succ_row (A := S) (i := (2 : Fin 4))] | |
| refine Finset.sum_congr rfl ?_ | |
| intro k hk | |
| have hminor : | |
| Matrix.det (S.submatrix (Fin.succAbove (2 : Fin 4)) k.succAbove) = | |
| Matrix.det ((fixedRowsMat A col).submatrix id k.succAbove) := by | |
| simpa [hsub k] | |
| rw [hminor] | |
| simp [S, stackedRowsMatrix, StackedMat, fixedRowsMat] | |
| ring_nf | |
| · -- mode 3: expand along row 3 | |
| let S : Matrix (Fin 4) (Fin 4) ℝ := | |
| stackedRowsMatrix A col.1.1 col.2.1.1 col.2.2.1 row.1 col.1.2 col.2.1.2 col.2.2.2 row.2 | |
| have hsub : | |
| ∀ k : Fin 4, | |
| S.submatrix (Fin.succAbove (3 : Fin 4)) k.succAbove = | |
| (fixedRowsMat A col).submatrix id k.succAbove := by | |
| intro k | |
| ext i j | |
| fin_cases i <;> fin_cases j <;> simp [S, fixedRowsMat, stackedRowsMatrix, Fin.succAbove] | |
| simp [Unfold, constructQ, StackedMat, cofactorMat, fixedRowsMat, S, Matrix.mul_apply] | |
| rw [Matrix.det_succ_row (A := S) (i := (3 : Fin 4))] | |
| refine Finset.sum_congr rfl ?_ | |
| intro k hk | |
| have hminor : | |
| Matrix.det (S.submatrix (Fin.succAbove (3 : Fin 4)) k.succAbove) = | |
| Matrix.det ((fixedRowsMat A col).submatrix id k.succAbove) := by | |
| simpa [hsub k] | |
| rw [hminor] | |
| simp [S, stackedRowsMatrix, StackedMat, fixedRowsMat] | |
| ring_nf | |
| lemma rank_unfold_Q_le_4 {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) : | |
| (Unfold m (constructQ A)).rank ≤ 4 := by | |
| classical | |
| have hB : (StackedMat A).rank ≤ 4 := by | |
| -- rank ≤ number of columns = 4 | |
| simpa [Fintype.card_fin] using (Matrix.rank_le_card_width (StackedMat A)) | |
| -- Each unfolding is a product `StackedMat A * cofactorMat A m`. | |
| rw [unfold_constructQ_eq_mul A m] | |
| exact le_trans (Matrix.rank_mul_le_left _ _) hB | |
| -- If λ factors, the scaled tensor has unfolding rank ≤ 4 | |
| lemma forward_rank_le_4 {n : ℕ} (A : Fin n → Matrix3x4) (lam : Lambda n) | |
| (u v w x : Fin n → ℝˣ) | |
| (hfact : ∀ α β γ δ, NotIdentical α β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ)) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (m : Fin 4) : | |
| (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4 := by | |
| classical | |
| -- Compare `scaleQ lam Q` with `scaleQ lam' Q` where `lam'` factors everywhere. | |
| -- They agree because `Q` vanishes on the diagonal `(α,α,α,α)`. | |
| have hdiag : ∀ α (i j k l : Fin 3), constructQ A α α α α i j k l = 0 := constructQ_diag A | |
| -- Define the factored scalar for all indices. | |
| let lam' : Lambda n := fun α β γ δ => (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ) | |
| have hscale : scaleQ lam (constructQ A) = scaleQ lam' (constructQ A) := by | |
| funext α β γ δ i j k l | |
| by_cases hni : NotIdentical α β γ δ | |
| · simp [scaleQ, hfact α β γ δ hni, lam', hni] | |
| · have : α = β ∧ β = γ ∧ γ = δ := by | |
| by_contra h; exact hni h | |
| rcases this with ⟨rfl, rfl, rfl⟩ | |
| have hlam0 : lam α α α α = 0 := by | |
| have hni' : ¬ NotIdentical α α α α := by | |
| intro h; exact h (by simp) | |
| have : ¬ lam α α α α ≠ 0 := by simpa [hsupp] using hni' | |
| exact not_ne_iff.mp this | |
| simp [scaleQ, hlam0, hdiag] | |
| -- For the factored `lam'`, each unfolding is an entrywise row/column scaling of the original. | |
| -- Use `rank_scaled_le` plus `rank_unfold_Q_le_4`. | |
| fin_cases m | |
| · -- mode 0 | |
| let r : RowIdx n → ℝ := fun p => (u p.1 : ℝ) | |
| let c : ColIdx n → ℝ := fun col => (v col.1.1 : ℝ) * (w col.2.1.1 : ℝ) * (x col.2.2.1 : ℝ) | |
| have hentry : | |
| Unfold 0 (scaleQ lam' (constructQ A)) = | |
| Matrix.of (fun p col => r p * c col * (Unfold 0 (constructQ A) p col)) := by | |
| ext p col | |
| simp [Unfold, scaleQ, lam', r, c, mul_assoc, mul_left_comm, mul_comm] | |
| have hrank : | |
| (Unfold 0 (scaleQ lam' (constructQ A))).rank ≤ (Unfold 0 (constructQ A)).rank := by | |
| simpa [hentry] using (rank_scaled_le (Unfold 0 (constructQ A)) r c) | |
| have hQrank : (Unfold 0 (constructQ A)).rank ≤ 4 := rank_unfold_Q_le_4 A 0 | |
| have : (Unfold 0 (scaleQ lam' (constructQ A))).rank ≤ 4 := hrank.trans hQrank | |
| simpa [hscale] using this | |
| · -- mode 1 | |
| let r : RowIdx n → ℝ := fun p => (v p.1 : ℝ) | |
| let c : ColIdx n → ℝ := fun col => (u col.1.1 : ℝ) * (w col.2.1.1 : ℝ) * (x col.2.2.1 : ℝ) | |
| have hentry : | |
| Unfold 1 (scaleQ lam' (constructQ A)) = | |
| Matrix.of (fun p col => r p * c col * (Unfold 1 (constructQ A) p col)) := by | |
| ext p col | |
| simp [Unfold, scaleQ, lam', r, c, mul_assoc, mul_left_comm, mul_comm] | |
| have hrank : | |
| (Unfold 1 (scaleQ lam' (constructQ A))).rank ≤ (Unfold 1 (constructQ A)).rank := by | |
| simpa [hentry] using (rank_scaled_le (Unfold 1 (constructQ A)) r c) | |
| have hQrank : (Unfold 1 (constructQ A)).rank ≤ 4 := rank_unfold_Q_le_4 A 1 | |
| have : (Unfold 1 (scaleQ lam' (constructQ A))).rank ≤ 4 := hrank.trans hQrank | |
| simpa [hscale] using this | |
| · -- mode 2 | |
| let r : RowIdx n → ℝ := fun p => (w p.1 : ℝ) | |
| let c : ColIdx n → ℝ := fun col => (u col.1.1 : ℝ) * (v col.2.1.1 : ℝ) * (x col.2.2.1 : ℝ) | |
| have hentry : | |
| Unfold 2 (scaleQ lam' (constructQ A)) = | |
| Matrix.of (fun p col => r p * c col * (Unfold 2 (constructQ A) p col)) := by | |
| ext p col | |
| simp [Unfold, scaleQ, lam', r, c, mul_assoc, mul_left_comm, mul_comm] | |
| have hrank : | |
| (Unfold 2 (scaleQ lam' (constructQ A))).rank ≤ (Unfold 2 (constructQ A)).rank := by | |
| simpa [hentry] using (rank_scaled_le (Unfold 2 (constructQ A)) r c) | |
| have hQrank : (Unfold 2 (constructQ A)).rank ≤ 4 := rank_unfold_Q_le_4 A 2 | |
| have : (Unfold 2 (scaleQ lam' (constructQ A))).rank ≤ 4 := hrank.trans hQrank | |
| simpa [hscale] using this | |
| · -- mode 3 | |
| let r : RowIdx n → ℝ := fun p => (x p.1 : ℝ) | |
| let c : ColIdx n → ℝ := fun col => (u col.1.1 : ℝ) * (v col.2.1.1 : ℝ) * (w col.2.2.1 : ℝ) | |
| have hentry : | |
| Unfold 3 (scaleQ lam' (constructQ A)) = | |
| Matrix.of (fun p col => r p * c col * (Unfold 3 (constructQ A) p col)) := by | |
| ext p col | |
| simp [Unfold, scaleQ, lam', r, c, mul_assoc, mul_left_comm, mul_comm] | |
| have hrank : | |
| (Unfold 3 (scaleQ lam' (constructQ A))).rank ≤ (Unfold 3 (constructQ A)).rank := by | |
| simpa [hentry] using (rank_scaled_le (Unfold 3 (constructQ A)) r c) | |
| have hQrank : (Unfold 3 (constructQ A)).rank ≤ 4 := rank_unfold_Q_le_4 A 3 | |
| have : (Unfold 3 (scaleQ lam' (constructQ A))).rank ≤ 4 := hrank.trans hQrank | |
| simpa [hscale] using this | |
| -- Forward direction: factorizable → F(T) = 0 | |
| lemma forward_direction {n : ℕ} (A : Fin n → Matrix3x4) (lam : Lambda n) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (u v w x : Fin n → ℝˣ) | |
| (hfact : ∀ α β γ δ, NotIdentical α β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ)) : | |
| IsZeroVec (PolyMap.eval (polyMapF n) (scaleQ lam (constructQ A))) := by | |
| rw [isZeroVec_iff_minors_vanish] | |
| intro m rows cols | |
| apply rank_le_four_imp_5x5_det_zero | |
| exact forward_rank_le_4 A lam u v w x hfact hsupp m | |
| noncomputable section AristotleLemmas | |
| /- | |
| If the rank of a matrix M is at least n, then there exist n columns of M that are linearly independent. | |
| -/ | |
| lemma exists_linearIndependent_cols_of_rank_ge {α β : Type*} [Fintype α] [Fintype β] | |
| [DecidableEq α] [DecidableEq β] | |
| (M : Matrix α β ℝ) (n : ℕ) (h : n ≤ M.rank) : | |
| ∃ (cols : Fin n → β), LinearIndependent ℝ (fun i => M.col (cols i)) := by | |
| -- Apply the theorem that states if the rank of a matrix is at least n, then there exist n linearly independent columns. | |
| have h_lin_ind : ∃ (cols : Fin n → β), LinearIndependent ℝ (fun i => M.col (cols i)) := by | |
| have h_card : n ≤ Module.finrank ℝ (Submodule.span ℝ (Set.range (Matrix.col M))) := by | |
| convert h using 1; | |
| exact Eq.symm (rank_eq_finrank_span_cols M) | |
| have := exists_linearIndependent ℝ ( Set.range ( Matrix.col M ) ); | |
| rcases this with ⟨ b, hb₁, hb₂, hb₃ ⟩ ; have := hb₃.cardinal_le_rank; simp_all +decide [ Module.finrank ] ; | |
| -- Since $b$ is a subset of the range of $M.col$, we can choose $n$ elements from $b$. | |
| obtain ⟨cols, hcols⟩ : ∃ cols : Fin n → α → ℝ, (∀ i, cols i ∈ b) ∧ LinearIndependent ℝ cols := by | |
| have h_card : n ≤ Cardinal.toNat (Cardinal.mk b) := by | |
| refine' le_trans h_card _; | |
| rw [ ← hb₂, rank_span_set ] ; aesop; | |
| have h_card : ∃ cols : Fin (Cardinal.toNat (Cardinal.mk b)) → α → ℝ, (∀ i, cols i ∈ b) ∧ LinearIndependent ℝ cols := by | |
| have h_card : Nonempty (Fin (Cardinal.toNat (Cardinal.mk b)) ≃ b) := by | |
| have h_card : Fintype b := by | |
| exact Set.Finite.fintype ( Set.Finite.subset ( Set.toFinite ( Set.range M.col ) ) hb₁ ); | |
| exact ⟨ Fintype.equivOfCardEq <| by simp +decide [ Cardinal.toNat_eq_iff ] ⟩; | |
| obtain ⟨ e ⟩ := h_card; | |
| exact ⟨ _, fun i => e i |>.2, hb₃.comp _ e.injective ⟩; | |
| obtain ⟨ cols, hcols₁, hcols₂ ⟩ := h_card; exact ⟨ fun i => cols ⟨ i, by linarith [ Fin.is_lt i ] ⟩, fun i => hcols₁ _, hcols₂.comp _ fun i j hij => by simpa [ Fin.ext_iff ] using hij ⟩ ; | |
| choose f hf using fun i => hb₁ ( hcols.1 i ) ; use f; aesop; | |
| exact h_lin_ind | |
| /- | |
| If the rank of a matrix M is at least n, then there exists an n x n submatrix of M with non-zero determinant. | |
| -/ | |
| lemma exists_submatrix_det_ne_zero_of_rank_ge {α β : Type*} [Fintype α] [Fintype β] | |
| [DecidableEq α] [DecidableEq β] | |
| (M : Matrix α β ℝ) (n : ℕ) (h : n ≤ M.rank) : | |
| ∃ (rows : Fin n → α) (cols : Fin n → β), (M.submatrix rows cols).det ≠ 0 := by | |
| -- Since `n ≤ M.rank`, by `exists_linearIndependent_cols_of_rank_ge`, there exist `cols : Fin n → β` such that the columns of `M` indexed by `cols` are linearly independent. | |
| obtain ⟨cols, hcols⟩ : ∃ cols : Fin n → β, LinearIndependent ℝ (fun i => M.col (cols i)) := exists_linearIndependent_cols_of_rank_ge M n h; | |
| -- Let `S = M.submatrix id cols`. `S` is an `α × n` matrix. | |
| set S : Matrix α (Fin n) ℝ := fun i j => M i (cols j); | |
| -- The columns of `S` are linearly independent, so `S.rank = n`. | |
| have hS_rank : S.rank = n := by | |
| have hS_rank : LinearMap.range (Matrix.mulVecLin S) = Submodule.span ℝ (Set.range (fun i => M.col (cols i))) := by | |
| ext; simp [S]; | |
| simp +decide [ funext_iff, Matrix.mulVec, Submodule.mem_span_range_iff_exists_fun ]; | |
| simp +decide only [dotProduct, mul_comm]; | |
| rw [ Matrix.rank ]; | |
| rw [ hS_rank, finrank_span_eq_card ] <;> aesop; | |
| -- We know `S.rank = Sᵀ.rank`, so `Sᵀ.rank = n`. `Sᵀ` is an `n × α` matrix. | |
| have hS_transpose_rank : (Matrix.transpose S).rank = n := by | |
| rw [ Matrix.rank_transpose, hS_rank ]; | |
| -- Applying `exists_linearIndependent_cols_of_rank_ge` to `Sᵀ` (with `n` and `h' : n ≤ Sᵀ.rank`), we find `rows : Fin n → α` such that the columns of `Sᵀ` indexed by `rows` are linearly independent. | |
| obtain ⟨rows, hrows⟩ : ∃ rows : Fin n → α, LinearIndependent ℝ (fun i => (Matrix.transpose S).col (rows i)) := by | |
| apply exists_linearIndependent_cols_of_rank_ge; | |
| rw [hS_transpose_rank]; | |
| refine' ⟨ rows, cols, _ ⟩; | |
| rw [ Fintype.linearIndependent_iff ] at hrows; | |
| contrapose! hrows; | |
| obtain ⟨ g, hg ⟩ := Matrix.exists_vecMul_eq_zero_iff.mpr hrows; | |
| refine' ⟨ g, _, _ ⟩ <;> simp_all +decide [ funext_iff, Matrix.vecMul, dotProduct ]; | |
| exact hg.2 | |
| end AristotleLemmas | |
| theorem minors5x5_zero_imp_rank_le_four {α β : Type*} [Fintype α] [Fintype β] | |
| [DecidableEq α] [DecidableEq β] | |
| (M : Matrix α β ℝ) | |
| (hminors : ∀ (rows : Fin 5 → α) (cols : Fin 5 → β), | |
| (M.submatrix rows cols).det = 0) : | |
| M.rank ≤ 4 := by | |
| classical | |
| by_contra hminors; | |
| -- By the lemma `exists_submatrix_det_ne_zero_of_rank_ge`, there exist row indices `rows : Fin 5 → α` and column indices `cols : Fin 5 → β` such that `(M.submatrix rows cols).det ≠ 0`. | |
| obtain ⟨rows, cols, h_det⟩ : ∃ (rows : Fin 5 → α) (cols : Fin 5 → β), (M.submatrix rows cols).det ≠ 0 := by | |
| convert exists_submatrix_det_ne_zero_of_rank_ge M 5 ( by linarith ) using 1; | |
| exact h_det ( by solve_by_elim ) | |
| def ColSpan {m n : Type*} [Fintype m] [Fintype n] (M : Matrix m n ℝ) : Submodule ℝ (m → ℝ) := | |
| Submodule.span ℝ (Set.range M.col) | |
| theorem colSpan_eq_of_cols_subtype_and_rank {m k l : Type*} | |
| [Fintype m] [Fintype k] [Fintype l] | |
| [DecidableEq m] [DecidableEq k] [DecidableEq l] | |
| (M : Matrix m l ℝ) (S : Matrix m k ℝ) | |
| (hcols : ∀ j : k, ∃ i : l, S.col j = M.col i) | |
| (hrM : M.rank ≤ 4) (hrS : S.rank = 4) : | |
| ColSpan S = ColSpan M := by | |
| classical | |
| have hle : ColSpan S ≤ ColSpan M := by | |
| refine Submodule.span_le.2 ?_ | |
| rintro _ ⟨j, rfl⟩ | |
| rcases hcols j with ⟨i, hi⟩ | |
| -- `S.col j` is literally one of the columns of `M` | |
| simpa [hi] using (Submodule.subset_span (s := Set.range M.col) ⟨i, rfl⟩) | |
| have hfinS : Module.finrank ℝ (ColSpan S) = 4 := by | |
| -- `rank = finrank(span(cols))` | |
| have : S.rank = Module.finrank ℝ (ColSpan S) := by | |
| simpa [ColSpan] using (Matrix.rank_eq_finrank_span_cols (R := ℝ) (A := S)) | |
| simpa [this] using hrS | |
| have hfinM_le : Module.finrank ℝ (ColSpan M) ≤ 4 := by | |
| have : M.rank = Module.finrank ℝ (ColSpan M) := by | |
| simpa [ColSpan] using (Matrix.rank_eq_finrank_span_cols (R := ℝ) (A := M)) | |
| -- rewrite `hrM` via the finrank characterization | |
| simpa [this] using hrM | |
| have hfinM_ge : 4 ≤ Module.finrank ℝ (ColSpan M) := by | |
| -- monotonicity of finrank under submodule inclusion | |
| have := Submodule.finrank_mono hle | |
| -- rewrite finrank of `ColSpan S` as `4` | |
| simpa [hfinS] using this | |
| have hfinM : Module.finrank ℝ (ColSpan M) = 4 := le_antisymm hfinM_le hfinM_ge | |
| -- same finrank + inclusion gives equality | |
| exact Submodule.eq_of_le_of_finrank_eq hle (by simpa [hfinS, hfinM]) | |
| /- `NotAllEqual3 β γ δ` means the triple `(β,γ,δ)` is not constant. This is the condition under which | |
| `NotIdentical α β γ δ` holds for *every* `α`. -/ | |
| def NotAllEqual3 {n : ℕ} (a b c : Fin n) : Prop := ¬ (a = b ∧ b = c) | |
| /-- The 27-column index type (j,k,ℓ ∈ Fin 3). -/ | |
| abbrev Triple3 := Fin 3 × Fin 3 × Fin 3 | |
| /-- Column index in `ColIdx n` for a fixed triple of cameras `(a,b,c)` and row choices `(j,k,ℓ)`. -/ | |
| def colIdxOfTriple {n : ℕ} (a b c : Fin n) (t : Triple3) : ColIdx n := | |
| ((a, t.1), ((b, t.2.1), (c, t.2.2))) | |
| /-- | |
| The `3n × 27` submatrix of the mode-`m` unfolding obtained by fixing the *camera indices* | |
| for the three column-slots to `(a,b,c)` and varying the within-camera row indices `(j,k,ℓ)`. | |
| -/ | |
| def Submatrix27 {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) (a b c : Fin n) : | |
| Matrix (RowIdx n) Triple3 ℝ := | |
| fun row t => (Unfold m (constructQ A)) row (colIdxOfTriple a b c t) | |
| /-- The 4D subspace `W = col(StackedMat A)` from `solution.md`. -/ | |
| def Wspace {n : ℕ} (A : Fin n → Matrix3x4) : Submodule ℝ (RowIdx n → ℝ) := | |
| ColSpan (StackedMat A) | |
| /-- | |
| (G3_m) from `solution.md`: | |
| for each mode `m` and each triple of camera indices `(a,b,c)` not all equal, | |
| the corresponding 27 columns span `W = col(StackedMat A)`. | |
| -/ | |
| def G3 {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) : Prop := | |
| ∀ a b c : Fin n, NotAllEqual3 a b c → | |
| ColSpan (Submatrix27 A m a b c) = Wspace A | |
| /-- | |
| Block-scalar diagonal linear map on `ℝ^(3n)`: | |
| multiply every row in camera-block `α` by the scalar `s α`. | |
| This is the `diag(s₁ I₃, …, sₙ I₃)` action from Lemma 4.2 in `solution.md`. | |
| -/ | |
| def blockScalarLM {n : ℕ} (s : Fin n → ℝ) : (RowIdx n → ℝ) →ₗ[ℝ] (RowIdx n → ℝ) := | |
| { toFun := fun v p => s p.1 * v p | |
| map_add' := by | |
| intro v w; ext p; simp [mul_add] | |
| map_smul' := by | |
| intro r v; ext p | |
| -- in `RowIdx n → ℝ`, `(r • v) p = r * v p` | |
| simp [mul_assoc, mul_left_comm, mul_comm] } | |
| /-- | |
| Rigidity assumption (Lemma 4.2 in `solution.md`), packaged as a Prop: | |
| any block-scalar diagonal map stabilizing `W` must be constant across blocks. | |
| (You can later *prove* this from rank assumptions if you want, but for the reverse direction | |
| it’s fine to include it as part of “generic”.) | |
| -/ | |
| def RigidBlockScalarStabilizer {n : ℕ} (A : Fin n → Matrix3x4) : Prop := | |
| ∀ s : Fin n → ℝˣ, | |
| (Wspace A).map (blockScalarLM (fun α => (s α : ℝ))) = (Wspace A) → | |
| ∀ α β : Fin n, s α = s β | |
| /-- | |
| “Generic cameras” as needed by the reverse direction in `solution.md`: | |
| - stacked rank = 4 | |
| - each camera rank = 3 | |
| - spanning conditions (G3_m) for all modes | |
| -/ | |
| def GenericCameras {n : ℕ} (A : Fin n → Matrix3x4) : Prop := | |
| (StackedMat A).rank = 4 ∧ | |
| (∀ α : Fin n, (A α).rank = 3) ∧ | |
| (∀ m : Fin 4, G3 A m) | |
| /-! | |
| Lemma 4.2 from `proofdocs/solution.md`: | |
| the block-scalar stabilizer of `W = col(StackedMat A)` is rigid under the rank assumptions. | |
| -/ | |
| lemma rigidBlockScalarStabilizer_of_rank {n : ℕ} (A : Fin n → Matrix3x4) | |
| (hstack : (StackedMat A).rank = 4) (hcam : ∀ α : Fin n, (A α).rank = 3) : | |
| RigidBlockScalarStabilizer A := by | |
| classical | |
| intro s hsW α β | |
| -- Setup notation. | |
| let B : Matrix (RowIdx n) (Fin 4) ℝ := StackedMat A | |
| let M : (RowIdx n → ℝ) →ₗ[ℝ] (RowIdx n → ℝ) := | |
| blockScalarLM (n := n) (fun a => (s a : ℝ)) | |
| have hWrange : (Wspace A) = LinearMap.range B.mulVecLin := by | |
| -- `Wspace A` is the column span of `B`. | |
| simp [Wspace, ColSpan, B, Matrix.range_mulVecLin] | |
| -- `B.mulVecLin` is injective because it has rank 4 and its domain has dimension 4. | |
| have h_finrank_range : Module.finrank ℝ ↥(LinearMap.range B.mulVecLin) = 4 := by | |
| have hspan : | |
| B.rank = Module.finrank ℝ ↥(Submodule.span ℝ (Set.range B.col)) := by | |
| simpa using (Matrix.rank_eq_finrank_span_cols (R := ℝ) (A := B)) | |
| have hrange : B.rank = Module.finrank ℝ ↥(LinearMap.range B.mulVecLin) := by | |
| -- rewrite the span-of-cols as the `mulVecLin` range | |
| calc | |
| B.rank = Module.finrank ℝ ↥(Submodule.span ℝ (Set.range B.col)) := hspan | |
| _ = Module.finrank ℝ ↥(LinearMap.range B.mulVecLin) := by | |
| -- rewrite by `Matrix.range_mulVecLin` (in the reverse direction) | |
| have e : | |
| Submodule.span ℝ (Set.range B.col) = LinearMap.range B.mulVecLin := | |
| (Matrix.range_mulVecLin (M := B)).symm | |
| -- rewriting under the coercion `↥(Submodule ...)` works with `rw`. | |
| rw [e] | |
| have : Module.finrank ℝ ↥(LinearMap.range B.mulVecLin) = B.rank := by | |
| simpa using hrange.symm | |
| simpa [hstack, B] using this | |
| have h_ker : LinearMap.ker B.mulVecLin = ⊥ := by | |
| have hdom : Module.finrank ℝ (Fin 4 → ℝ) = 4 := by | |
| simp [Module.finrank_pi, Fintype.card_fin] | |
| have hsum := | |
| (LinearMap.finrank_range_add_finrank_ker (B.mulVecLin : (Fin 4 → ℝ) →ₗ[ℝ] (RowIdx n → ℝ))) | |
| have hsum' : | |
| Module.finrank ℝ ↥(LinearMap.range B.mulVecLin) + | |
| Module.finrank ℝ ↥(LinearMap.ker B.mulVecLin) = 4 := by | |
| simpa [hdom] using hsum | |
| have hker_finrank : Module.finrank ℝ ↥(LinearMap.ker B.mulVecLin) = 0 := by | |
| have : 4 + Module.finrank ℝ ↥(LinearMap.ker B.mulVecLin) = 4 := by | |
| simpa [h_finrank_range] using hsum' | |
| exact Nat.add_left_cancel this | |
| exact (Submodule.finrank_eq_zero).1 hker_finrank | |
| obtain ⟨g, hg⟩ := | |
| LinearMap.exists_leftInverse_of_injective (f := B.mulVecLin) h_ker | |
| -- `M` stabilizes `W = col(B)`, hence maps `range(B.mulVecLin)` to itself. | |
| have hM_mem_range : ∀ x : Fin 4 → ℝ, M (B.mulVecLin x) ∈ LinearMap.range B.mulVecLin := by | |
| intro x | |
| -- First, show `M` maps `Wspace A` into itself. | |
| have hmap : (Wspace A).map M ≤ Wspace A := le_of_eq hsW | |
| have hxW : B.mulVecLin x ∈ Wspace A := by | |
| have hx : B.mulVecLin x ∈ LinearMap.range B.mulVecLin := ⟨x, rfl⟩ | |
| simpa [hWrange] using hx | |
| have hMxW : M (B.mulVecLin x) ∈ Wspace A := by | |
| -- `M (B.mulVecLin x)` is in `map M (Wspace A)` by construction. | |
| have : M (B.mulVecLin x) ∈ (Wspace A).map M := by | |
| refine (Submodule.mem_map).2 ?_ | |
| exact ⟨B.mulVecLin x, hxW, rfl⟩ | |
| exact hmap this | |
| simpa [hWrange] using hMxW | |
| -- Define the induced endomorphism on `Fin 4 → ℝ` by conjugating through `B.mulVecLin`. | |
| let Rlin : (Fin 4 → ℝ) →ₗ[ℝ] (Fin 4 → ℝ) := | |
| g ∘ₗ M ∘ₗ B.mulVecLin | |
| have hcomm : ∀ x : Fin 4 → ℝ, B.mulVecLin (Rlin x) = M (B.mulVecLin x) := by | |
| intro x | |
| -- `M (B.mulVecLin x)` lies in the range, so write it as `B.mulVecLin z`. | |
| rcases hM_mem_range x with ⟨z, hz⟩ | |
| -- Use the defining property of a left inverse on this representative. | |
| have hg_apply : g (B.mulVecLin z) = z := by | |
| -- apply the equality of linear maps to `z` | |
| simpa using congrArg (fun h => h z) hg | |
| -- Now compute. | |
| -- `Rlin x = g (M (B.mulVecLin x)) = g (B.mulVecLin z) = z`. | |
| calc | |
| B.mulVecLin (Rlin x) | |
| = B.mulVecLin (g (M (B.mulVecLin x))) := by rfl | |
| _ = B.mulVecLin (g (B.mulVecLin z)) := by simpa [hz] | |
| _ = B.mulVecLin z := by | |
| -- avoid unfolding issues: apply `B.mulVecLin` to the equality `g (B.mulVecLin z) = z` | |
| simpa using congrArg (fun w : Fin 4 → ℝ => B.mulVecLin w) hg_apply | |
| _ = M (B.mulVecLin x) := by simpa [hz] | |
| -- Build a concrete matrix for `Rlin` by its action on the standard basis vectors. | |
| let Rmat : Matrix (Fin 4) (Fin 4) ℝ := | |
| fun k j => (Rlin (Pi.single j 1)) k | |
| -- Each row vector in camera block `a` is a left eigenvector for `Rmat` with eigenvalue `s a`. | |
| have hrow_eigen : | |
| ∀ p : RowIdx n, (B.row p) ᵥ* Rmat = (s p.1 : ℝ) • (B.row p) := by | |
| intro p | |
| ext j | |
| -- Apply `hcomm` to the basis vector picking out column `j`. | |
| have hcol := | |
| congrArg (fun v : RowIdx n → ℝ => v p) (hcomm (Pi.single j 1)) | |
| -- Rewrite both sides of the commutation in coordinates. | |
| -- Left side: `B.mulVecLin (Rlin e_j)` evaluated at `p` is a dot product with row `p`. | |
| -- Right side: `M (B.col j)` scales the `p.1` camera block by `s p.1`. | |
| -- Finally, unpack `Rmat` so the dot product matches `vecMul`. | |
| simpa [B, M, Rmat, Matrix.mulVec, Matrix.vecMul, dotProduct, Matrix.row_apply, | |
| Matrix.col_apply, Pi.smul_apply, blockScalarLM, mul_assoc, mul_left_comm, mul_comm, | |
| Matrix.mulVec_single_one] using hcol | |
| -- Convert to an eigenvector statement for `Rmatᵀ.mulVec`. | |
| let T : Module.End ℝ (Fin 4 → ℝ) := (Rmatᵀ).mulVecLin | |
| have hrow_eigen_T : | |
| ∀ p : RowIdx n, T (B.row p) = (s p.1 : ℝ) • (B.row p) := by | |
| intro p | |
| -- `Rmatᵀ *ᵥ v = v ᵥ* Rmat`. | |
| simpa [T, Matrix.mulVec_transpose] using hrow_eigen p | |
| -- For each camera `a`, the 3D row-span of `A a` sits in the eigenspace for eigenvalue `s a`. | |
| have hrowSpan_le_eigenspace : | |
| ∀ a : Fin n, Submodule.span ℝ (Set.range (A a).row) ≤ T.eigenspace (s a : ℝ) := by | |
| intro a | |
| refine Submodule.span_le.2 ?_ | |
| rintro _ ⟨i, rfl⟩ | |
| -- Identify this row with the corresponding row of the stacked matrix. | |
| have hrow_id : (A a).row i = B.row (a, i) := by | |
| ext k; rfl | |
| -- Membership in the eigenspace is exactly the eigenvector equation. | |
| rw [hrow_id] | |
| -- unfold membership condition | |
| exact (Module.End.mem_eigenspace_iff).2 (hrow_eigen_T (p := (a, i))) | |
| have hfinrank_rowSpan : | |
| ∀ a : Fin n, Module.finrank ℝ ↥(Submodule.span ℝ (Set.range (A a).row)) = 3 := by | |
| intro a | |
| -- `rank = finrank(span(rows))`. | |
| have := (Matrix.rank_eq_finrank_span_row (R := ℝ) (A := A a)).symm | |
| -- Use `hcam a : (A a).rank = 3`. | |
| simpa [hcam a] using this | |
| have hfinrank_eigenspace_ge : | |
| ∀ a : Fin n, 3 ≤ Module.finrank ℝ ↥(T.eigenspace (s a : ℝ)) := by | |
| intro a | |
| have hmono := Submodule.finrank_mono (hrowSpan_le_eigenspace a) | |
| -- rewrite the finrank of the row span as 3 | |
| simpa [hfinrank_rowSpan a] using hmono | |
| -- Distinct eigenvalues would force two disjoint eigenspaces of dimension ≥ 3 each, impossible in 4D. | |
| by_contra hneq | |
| have hsneq : (s α : ℝ) ≠ (s β : ℝ) := by | |
| intro h | |
| apply hneq | |
| exact Units.ext (by simpa using h) | |
| -- Prove the eigenspaces are disjoint for distinct eigenvalues. | |
| have hdisj : Disjoint (T.eigenspace (s α : ℝ)) (T.eigenspace (s β : ℝ)) := by | |
| -- use the elementwise characterization | |
| refine (Submodule.disjoint_def).2 ?_ | |
| intro x hxα hxβ | |
| have hxα' : T x = (s α : ℝ) • x := (Module.End.mem_eigenspace_iff).1 hxα | |
| have hxβ' : T x = (s β : ℝ) • x := (Module.End.mem_eigenspace_iff).1 hxβ | |
| have hEq : (s α : ℝ) • x = (s β : ℝ) • x := by | |
| calc | |
| (s α : ℝ) • x = T x := by simpa using hxα'.symm | |
| _ = (s β : ℝ) • x := by simpa using hxβ' | |
| have hdiff : ((s α : ℝ) - (s β : ℝ)) • x = 0 := by | |
| simp [sub_smul, hEq] | |
| have hscal : ((s α : ℝ) - (s β : ℝ)) ≠ 0 := sub_ne_zero.2 hsneq | |
| exact (smul_eq_zero.mp hdiff).resolve_left hscal | |
| have hsum_finrank : | |
| Module.finrank ℝ ↥(T.eigenspace (s α : ℝ)) + | |
| Module.finrank ℝ ↥(T.eigenspace (s β : ℝ)) ≤ 4 := by | |
| -- Use `finrank(sup) ≤ finrank(ambient)` and disjointness to compute `finrank(sup)`. | |
| have hsup_le : Module.finrank ℝ ↥((T.eigenspace (s α : ℝ)) ⊔ (T.eigenspace (s β : ℝ))) ≤ | |
| Module.finrank ℝ (Fin 4 → ℝ) := Submodule.finrank_le _ | |
| have hdim : Module.finrank ℝ (Fin 4 → ℝ) = 4 := by | |
| simp [Module.finrank_pi, Fintype.card_fin] | |
| have hsup_eq : | |
| Module.finrank ℝ ↥((T.eigenspace (s α : ℝ)) ⊔ (T.eigenspace (s β : ℝ))) = | |
| Module.finrank ℝ ↥(T.eigenspace (s α : ℝ)) + | |
| Module.finrank ℝ ↥(T.eigenspace (s β : ℝ)) := by | |
| -- `finrank sup + finrank inf = finrank + finrank`, and `inf = ⊥` by disjointness. | |
| have h := | |
| (Submodule.finrank_sup_add_finrank_inf_eq | |
| (T.eigenspace (s α : ℝ)) (T.eigenspace (s β : ℝ))) | |
| have hinf : (T.eigenspace (s α : ℝ)) ⊓ (T.eigenspace (s β : ℝ)) = ⊥ := by | |
| simpa using (disjoint_iff.1 hdisj) | |
| -- with `inf = ⊥`, the extra term is 0 | |
| -- rewrite `inf` and simplify `+ 0`. | |
| -- We do this with `rw` instead of `simp [hinf]` to ensure the coercion `↥(s ⊓ t)` rewrites. | |
| have h' := h | |
| -- rewrite inside the finrank term | |
| rw [hinf] at h' | |
| simpa using h' | |
| -- Now finish the bound. | |
| have hsup_le' : Module.finrank ℝ ↥((T.eigenspace (s α : ℝ)) ⊔ (T.eigenspace (s β : ℝ))) ≤ 4 := by | |
| simpa [hdim] using hsup_le | |
| simpa [hsup_eq] using hsup_le' | |
| have hge : 6 ≤ | |
| Module.finrank ℝ ↥(T.eigenspace (s α : ℝ)) + | |
| Module.finrank ℝ ↥(T.eigenspace (s β : ℝ)) := by | |
| have hα' := hfinrank_eigenspace_ge (a := α) | |
| have hβ' := hfinrank_eigenspace_ge (a := β) | |
| -- `3+3 = 6` | |
| simpa [Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] using Nat.add_le_add hα' hβ' | |
| have : 6 ≤ 4 := le_trans hge hsum_finrank | |
| exact (by decide : ¬ (6 ≤ 4)) this | |
| def RankGenericCameras {n : ℕ} (A : Fin n → Matrix3x4) : Prop := | |
| (StackedMat A).rank = 4 ∧ (∀ α : Fin n, (A α).rank = 3) | |
| lemma GenericCameras.toRankGeneric {n : ℕ} {A : Fin n → Matrix3x4} (h : GenericCameras A) : | |
| RankGenericCameras A := | |
| ⟨h.1, h.2.1⟩ | |
| lemma GenericCameras.rigid {n : ℕ} {A : Fin n → Matrix3x4} (h : GenericCameras A) : | |
| RigidBlockScalarStabilizer A := | |
| rigidBlockScalarStabilizer_of_rank (A := A) h.1 h.2.1 | |
| /- PROVIDED SOLUTION: | |
| Goal (reverse direction of Problem 9): | |
| Assume cameras `A` are “generic” and `λ` has the prescribed support | |
| `λ_{αβγδ} ≠ 0 ↔ NotIdentical α β γ δ`. | |
| If `F(λ · Q(A)) = 0` (i.e. all `5×5` minors of all four unfoldings vanish), | |
| then `λ` factors as `uα vβ wγ xδ` on all not-identical quadruples. | |
| High-level structure (matches `proofdocs/solution.md`): | |
| 1) Vanishing minors ⇒ unfolding rank ≤ 4. | |
| From `IsZeroVec (polyMapF.eval (scaleQ λ (constructQ A)))` we obtain: | |
| ∀ mode m, ∀ rows cols, det((Unfold m (scaleQ λ Q)).submatrix rows cols) = 0. | |
| By the previous lemma (`minors5x5_zero_imp_rank_le_four`), this implies: | |
| ∀ m, rank(Unfold m (scaleQ λ Q)) ≤ 4. | |
| 2) Define the 4D subspace W from the stacked camera matrix. | |
| Let `B := StackedMat A : (Fin n × Fin 3) × Fin 4 → ℝ`. | |
| Genericity includes `rank(B)=4`, so `W := col(B)` is a 4D subspace of `ℝ^(3n)`. | |
| 3) Generic spanning condition (Zariski-open): | |
| For each mode m and each triple of camera indices (not all equal), consider the `27` columns of | |
| the unfolding `Unfold m (constructQ A)` obtained by fixing the other three tensor slots and | |
| letting the `Fin 3` row-indices vary. Genericity demands these `27` columns span `W`. | |
| (This is exactly the paper’s condition (G3_m). It is expressible as nonvanishing of a suitable | |
| `4×4` minor of the corresponding `3n × 27` submatrix.) | |
| 4) Pin down the column space of the *scaled* unfolding using rank. | |
| Fix a triple (e.g. for mode 1: `(β,γ,δ)` not all equal). Let `S_{βγδ}` be the `3n×27` submatrix | |
| of `Unfold 0 (constructQ A)` with those columns; by (G3_1), `col(S_{βγδ}) = W`. | |
| In the scaled tensor `T := scaleQ λ (constructQ A)`, the corresponding submatrix is obtained by | |
| multiplying each camera-block (the `α`-block of 3 rows) by the scalar `λ_{αβγδ}`. This is | |
| left-multiplication by a block-diagonal matrix `D_{βγδ} = diag(λ_{1βγδ} I_3, …, λ_{nβγδ} I_3)`. | |
| Because `λ_{αβγδ} ≠ 0` for all α when `(β,γ,δ)` are not all equal (by the support rule), | |
| `D_{βγδ}` is invertible and `col(D_{βγδ} S_{βγδ}) = D_{βγδ} W` has dimension 4. | |
| Since `rank(Unfold 0 T) ≤ 4`, its column space has dimension ≤ 4, but it contains | |
| `D_{βγδ} W` (because those 27 columns are among all columns), hence: | |
| col(Unfold 0 T) = D_{βγδ} W, | |
| for every not-all-equal triple `(β,γ,δ)`. | |
| 5) Rigidity of block-diagonal stabilizers (Lemma 4.2 in the paper). | |
| Comparing two triples `(β,γ,δ)` and `(β₀,γ₀,δ₀)` gives: | |
| D_{βγδ} W = col(Unfold 0 T) = D_{β₀γ₀δ₀} W, | |
| so the block-diagonal matrix `M := D_{βγδ}^{-1} D_{β₀γ₀δ₀}` stabilizes W. | |
| Genericity includes the rigidity statement: | |
| If `M = diag(s₁ I_3, …, s_n I_3)` stabilizes W and `rank(B)=4` and each `A α` has rank 3, | |
| then all `sα` are equal. | |
| Applying this shows that the ratio | |
| sα = λ_{αβ₀γ₀δ₀} / λ_{αβγδ} | |
| is independent of α. Equivalently, there exists `u : Fin n → ℝˣ` and a 3-tensor `μ` such that | |
| λ_{αβγδ} = uα * μ_{βγδ} whenever `(β,γ,δ)` are not all equal. | |
| 6) Repeat for other modes to separate β and γ (and similarly δ). | |
| Doing the same argument in modes 2 and 3 yields | |
| λ_{αβγδ} = vβ * ν_{αγδ} whenever `(α,γ,δ)` not all equal, | |
| λ_{αβγδ} = wγ * ξ_{αβδ} whenever `(α,β,δ)` not all equal, | |
| for some `v,w : Fin n → ℝˣ`. | |
| 7) Propagate to full factorization `u⊗v⊗w⊗x` using `n ≥ 5`. | |
| The paper gives a clean propagation: | |
| - Fix `γ ≠ δ`. Combine the first two separations to get | |
| λ_{αβγδ} = uα vβ ρ_{γδ} (γ ≠ δ). | |
| - Fix δ and choose indices α₀,β₀ with α₀ ≠ δ (possible since n ≥ 5). Use the γ-separation to | |
| split `ρ_{γδ} = wγ xδ` for γ ≠ δ. | |
| - Finally extend to the remaining off-diagonal cases γ=δ but not-all-identical using the support | |
| rule and one more index choice. | |
| This yields `λ_{αβγδ} = uα vβ wγ xδ` for all `NotIdentical α β γ δ`. | |
| 8) Ensure the factors are units. | |
| Because the support condition guarantees the needed denominators are nonzero, one can package the | |
| resulting scalars as elements of `ℝˣ` (units) and rewrite the factorization in the required form. | |
| That completes the reverse direction, assuming the generic spanning + rigidity hypotheses encoded in | |
| `GenericCameras`. | |
| -/ | |
| -- -------------------------------------------------------------------- | |
| -- Reverse direction, decomposed into manageable lemmas | |
| -- -------------------------------------------------------------------- | |
| lemma notIdentical_of_notAllEqual3 {n : ℕ} {α β γ δ : Fin n} (h : NotAllEqual3 β γ δ) : | |
| NotIdentical α β γ δ := by | |
| intro hall | |
| exact h ⟨hall.2.1, hall.2.2⟩ | |
| lemma lam_ne_zero_of_notAllEqual3 {n : ℕ} (lam : Lambda n) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| {β γ δ : Fin n} (h : NotAllEqual3 β γ δ) : | |
| ∀ α : Fin n, lam α β γ δ ≠ 0 := by | |
| intro α | |
| exact (hsupp α β γ δ).2 (notIdentical_of_notAllEqual3 (α := α) h) | |
| lemma rank_rowScaled_eq {α β : Type*} [Fintype α] [Fintype β] | |
| [DecidableEq α] [DecidableEq β] | |
| (M : Matrix α β ℝ) (r : α → ℝ) (hr : ∀ i, r i ≠ 0) : | |
| (Matrix.of fun i j => r i * M i j).rank = M.rank := by | |
| classical | |
| let Ms : Matrix α β ℝ := Matrix.of fun i j => r i * M i j | |
| have hle1 : Ms.rank ≤ M.rank := by | |
| simpa [Ms, one_mul] using (rank_scaled_le (M := M) (r := r) (c := fun _ => (1 : ℝ))) | |
| have hM : M = Matrix.of (fun i j => (r i)⁻¹ * Ms i j) := by | |
| ext i j | |
| have hri : (r i)⁻¹ * (r i * M i j) = M i j := by | |
| field_simp [hr i] | |
| simpa [Ms, mul_assoc] using hri.symm | |
| have hle2 : M.rank ≤ Ms.rank := by | |
| have hscaled : (Matrix.of fun i j => (r i)⁻¹ * Ms i j).rank ≤ Ms.rank := by | |
| simpa [one_mul] using | |
| (rank_scaled_le (M := Ms) (r := fun i => (r i)⁻¹) (c := fun _ => (1 : ℝ))) | |
| simpa [hM] using hscaled | |
| exact le_antisymm hle1 hle2 | |
| lemma exists_fin_ne_of_five {n : ℕ} (hn : 5 ≤ n) (a : Fin n) : ∃ b : Fin n, b ≠ a := by | |
| have h0 : (0 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 0 < 5) hn | |
| have h1 : (1 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 1 < 5) hn | |
| by_cases ha : a.1 = 0 | |
| · refine ⟨⟨1, h1⟩, ?_⟩ | |
| intro h | |
| have : (a : ℕ) = 1 := by simpa using congrArg Fin.val h.symm | |
| have : (1 : ℕ) = 0 := by simpa [ha] using this | |
| exact Nat.one_ne_zero this | |
| · refine ⟨⟨0, h0⟩, ?_⟩ | |
| intro h | |
| apply ha | |
| simpa using congrArg Fin.val h.symm | |
| def modeCoeff {n : ℕ} (m : Fin 4) (lam : Lambda n) | |
| (row a b c : Fin n) : ℝ := | |
| match m with | |
| | ⟨0, _⟩ => lam row a b c | |
| | ⟨1, _⟩ => lam a row b c | |
| | ⟨2, _⟩ => lam a b row c | |
| | ⟨3, _⟩ => lam a b c row | |
| lemma notIdentical_mode1_of_notAllEqual3 {n : ℕ} {row a b c : Fin n} | |
| (h : NotAllEqual3 a b c) : NotIdentical a row b c := by | |
| intro hall | |
| exact h ⟨hall.1.trans hall.2.1, hall.2.2⟩ | |
| lemma notIdentical_mode2_of_notAllEqual3 {n : ℕ} {row a b c : Fin n} | |
| (h : NotAllEqual3 a b c) : NotIdentical a b row c := by | |
| intro hall | |
| exact h ⟨hall.1, hall.2.1.trans hall.2.2⟩ | |
| lemma notIdentical_mode3_of_notAllEqual3 {n : ℕ} {row a b c : Fin n} | |
| (h : NotAllEqual3 a b c) : NotIdentical a b c row := by | |
| intro hall | |
| exact h ⟨hall.1, hall.2.1⟩ | |
| lemma modeCoeff_ne_zero_of_notAllEqual3 {n : ℕ} (m : Fin 4) (lam : Lambda n) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| {a b c : Fin n} (h : NotAllEqual3 a b c) : | |
| ∀ row : Fin n, modeCoeff m lam row a b c ≠ 0 := by | |
| intro row | |
| fin_cases m | |
| · simpa [modeCoeff] using (lam_ne_zero_of_notAllEqual3 (lam := lam) hsupp (β := a) (γ := b) | |
| (δ := c) h row) | |
| · simpa [modeCoeff] using (hsupp a row b c).2 (notIdentical_mode1_of_notAllEqual3 (row := row) | |
| (a := a) (b := b) (c := c) h) | |
| · simpa [modeCoeff] using (hsupp a b row c).2 (notIdentical_mode2_of_notAllEqual3 (row := row) | |
| (a := a) (b := b) (c := c) h) | |
| · simpa [modeCoeff] using (hsupp a b c row).2 (notIdentical_mode3_of_notAllEqual3 (row := row) | |
| (a := a) (b := b) (c := c) h) | |
| lemma submatrix27_scaled_eq_rowScale {n : ℕ} (m : Fin 4) (A : Fin n → Matrix3x4) | |
| (lam : Lambda n) (a b c : Fin n) : | |
| ((Unfold m (scaleQ lam (constructQ A))).submatrix id (colIdxOfTriple a b c)) | |
| = Matrix.of (fun p t => modeCoeff m lam p.1 a b c * (Submatrix27 A m a b c) p t) := by | |
| ext p t | |
| fin_cases m <;> | |
| simp [Submatrix27, colIdxOfTriple, modeCoeff, Unfold, scaleQ] | |
| lemma colSpan_rowBlockScale {n : ℕ} {k : Type*} [Fintype k] [DecidableEq k] | |
| (M : Matrix (RowIdx n) k ℝ) (s : Fin n → ℝ) : | |
| ColSpan (Matrix.of (fun p j => s p.1 * M p j)) | |
| = (ColSpan M).map (blockScalarLM s) := by | |
| apply le_antisymm | |
| · refine Submodule.span_le.2 ?_ | |
| rintro _ ⟨j, rfl⟩ | |
| refine (Submodule.mem_map).2 ?_ | |
| refine ⟨M.col j, ?_, ?_⟩ | |
| · exact Submodule.subset_span ⟨j, rfl⟩ | |
| · ext p | |
| simp [blockScalarLM, Matrix.col, Matrix.of_apply] | |
| · refine (Submodule.map_le_iff_le_comap).2 ?_ | |
| refine Submodule.span_le.2 ?_ | |
| rintro _ ⟨j, rfl⟩ | |
| have hcol : | |
| blockScalarLM s (M.col j) = (Matrix.of (fun p j => s p.1 * M p j)).col j := by | |
| ext p | |
| simp [blockScalarLM, Matrix.col, Matrix.of_apply] | |
| simpa [hcol] using | |
| (Submodule.subset_span | |
| (s := Set.range (Matrix.col (Matrix.of (fun p j => s p.1 * M p j)))) | |
| ⟨j, rfl⟩) | |
| theorem separate_mode_of_generic {n : ℕ} (hn : 5 ≤ n) (A : Fin n → Matrix3x4) (lam : Lambda n) | |
| (hgen : GenericCameras A) (m : Fin 4) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hrank : ∀ m : Fin 4, (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4) : | |
| ∃ (u : Fin n → ℝˣ) (μ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ row a b c, NotAllEqual3 a b c → | |
| modeCoeff m lam row a b c = (u row : ℝ) * (μ a b c : ℝ) := by | |
| classical | |
| rcases hgen with ⟨hstack, hcam, hG3⟩ | |
| have _ : ∀ α : Fin n, (A α).rank = 3 := hcam | |
| have hGm : G3 A m := hG3 m | |
| have hrankW : | |
| (StackedMat A).rank = Module.finrank ℝ (Wspace A) := by | |
| simpa [Wspace, ColSpan] using | |
| (Matrix.rank_eq_finrank_span_cols (R := ℝ) (A := StackedMat A)) | |
| have hfinW : Module.finrank ℝ (Wspace A) = 4 := by | |
| simpa [hrankW] using hstack | |
| have h0 : (0 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 0 < 5) hn | |
| have h1 : (1 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 1 < 5) hn | |
| have h2 : (2 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 2 < 5) hn | |
| let i0 : Fin n := ⟨0, h0⟩ | |
| let i1 : Fin n := ⟨1, h1⟩ | |
| let i2 : Fin n := ⟨2, h2⟩ | |
| have h01 : i0 ≠ i1 := by | |
| intro h | |
| have : (0 : ℕ) = 1 := by simpa [i0, i1] using congrArg Fin.val h | |
| exact Nat.zero_ne_one this | |
| have hNotAll012 : NotAllEqual3 i0 i1 i2 := by | |
| intro h | |
| exact h01 h.1 | |
| have hcol_of : | |
| ∀ a b c : Fin n, NotAllEqual3 a b c → | |
| ColSpan (Unfold m (scaleQ lam (constructQ A))) = | |
| (Wspace A).map (blockScalarLM (fun α => modeCoeff m lam α a b c)) := by | |
| intro a b c hneq | |
| let M : Matrix (RowIdx n) (ColIdx n) ℝ := Unfold m (scaleQ lam (constructQ A)) | |
| let S : Matrix (RowIdx n) Triple3 ℝ := Submatrix27 A m a b c | |
| let Ss : Matrix (RowIdx n) Triple3 ℝ := M.submatrix id (colIdxOfTriple a b c) | |
| have hSs_def : Ss = Matrix.of (fun p t => modeCoeff m lam p.1 a b c * S p t) := by | |
| simpa [Ss, M, S] using | |
| (submatrix27_scaled_eq_rowScale (m := m) (A := A) (lam := lam) (a := a) (b := b) (c := c)) | |
| have hcolS : ColSpan S = Wspace A := by | |
| simpa [S] using hGm a b c hneq | |
| have hfinS : Module.finrank ℝ (ColSpan S) = 4 := by | |
| rw [hcolS] | |
| exact hfinW | |
| have hSrank' : S.rank = Module.finrank ℝ (ColSpan S) := by | |
| simpa [ColSpan] using (Matrix.rank_eq_finrank_span_cols (R := ℝ) (A := S)) | |
| have hSrank : S.rank = 4 := by | |
| simpa [hSrank'] using hfinS | |
| have hs_nonzero : ∀ p : RowIdx n, modeCoeff m lam p.1 a b c ≠ 0 := by | |
| intro p | |
| exact modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp (a := a) (b := b) | |
| (c := c) hneq p.1 | |
| have hSs_rank : Ss.rank = 4 := by | |
| calc | |
| Ss.rank = (Matrix.of (fun p t => modeCoeff m lam p.1 a b c * S p t)).rank := by | |
| simpa [hSs_def] | |
| _ = S.rank := by | |
| simpa using | |
| (rank_rowScaled_eq (M := S) (r := fun p : RowIdx n => modeCoeff m lam p.1 a b c) | |
| (hr := hs_nonzero)) | |
| _ = 4 := hSrank | |
| have hcols : ∀ j : Triple3, ∃ i : ColIdx n, Ss.col j = M.col i := by | |
| intro j | |
| refine ⟨colIdxOfTriple a b c j, ?_⟩ | |
| ext p | |
| simp [Ss, M] | |
| have hcolEq : ColSpan Ss = ColSpan M := | |
| colSpan_eq_of_cols_subtype_and_rank (M := M) (S := Ss) hcols (hrank m) hSs_rank | |
| have hscaled : | |
| ColSpan Ss = | |
| (ColSpan S).map (blockScalarLM (fun α => modeCoeff m lam α a b c)) := by | |
| calc | |
| ColSpan Ss = ColSpan (Matrix.of (fun p t => modeCoeff m lam p.1 a b c * S p t)) := by | |
| simpa [hSs_def] | |
| _ = (ColSpan S).map (blockScalarLM (fun α => modeCoeff m lam α a b c)) := | |
| colSpan_rowBlockScale (M := S) (s := fun α => modeCoeff m lam α a b c) | |
| calc | |
| ColSpan (Unfold m (scaleQ lam (constructQ A))) = ColSpan M := by rfl | |
| _ = ColSpan Ss := hcolEq.symm | |
| _ = (ColSpan S).map (blockScalarLM (fun α => modeCoeff m lam α a b c)) := hscaled | |
| _ = (Wspace A).map (blockScalarLM (fun α => modeCoeff m lam α a b c)) := by | |
| simpa [hcolS] | |
| let u : Fin n → ℝˣ := fun row => | |
| Units.mk0 (modeCoeff m lam row i0 i1 i2 / modeCoeff m lam i0 i0 i1 i2) (by | |
| have hnum := modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := i0) (b := i1) (c := i2) hNotAll012 row | |
| have hden := modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := i0) (b := i1) (c := i2) hNotAll012 i0 | |
| exact div_ne_zero hnum hden) | |
| let μ : Fin n → Fin n → Fin n → ℝˣ := fun a b c => | |
| if hneq : NotAllEqual3 a b c then | |
| Units.mk0 (modeCoeff m lam i0 a b c) | |
| (modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := a) (b := b) (c := c) hneq i0) | |
| else 1 | |
| refine ⟨u, μ, ?_⟩ | |
| intro row a b c hneq | |
| let us : Fin n → ℝˣ := fun α => | |
| Units.mk0 (modeCoeff m lam α a b c) | |
| (modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := a) (b := b) (c := c) hneq α) | |
| let usRef : Fin n → ℝˣ := fun α => | |
| Units.mk0 (modeCoeff m lam α i0 i1 i2) | |
| (modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := i0) (b := i1) (c := i2) hNotAll012 α) | |
| let sRatio : Fin n → ℝˣ := fun α => (us α)⁻¹ * usRef α | |
| let Ls := blockScalarLM (fun α => (us α : ℝ)) | |
| let Lref := blockScalarLM (fun α => (usRef α : ℝ)) | |
| let Linv := blockScalarLM (fun α => (((us α)⁻¹ : ℝˣ) : ℝ)) | |
| let Lratio := blockScalarLM (fun α => (sRatio α : ℝ)) | |
| have hmapEq : | |
| (Wspace A).map Ls = (Wspace A).map Lref := by | |
| have hcur := hcol_of a b c hneq | |
| have href := hcol_of i0 i1 i2 hNotAll012 | |
| exact by | |
| simpa [Ls, Lref, us, usRef] using (hcur.symm.trans href) | |
| have hcomp_inv_s : Linv.comp Ls = LinearMap.id := by | |
| apply LinearMap.ext | |
| intro x | |
| ext p | |
| have hmul : (((us p.1)⁻¹ : ℝˣ) : ℝ) * ((us p.1 : ℝ) * x p) = x p := by | |
| calc | |
| (((us p.1)⁻¹ : ℝˣ) : ℝ) * ((us p.1 : ℝ) * x p) | |
| = ((((us p.1)⁻¹ : ℝˣ) : ℝ) * (us p.1 : ℝ)) * x p := by ring | |
| _ = x p := by simp | |
| simpa [Linv, Ls, blockScalarLM, mul_assoc] using hmul | |
| have hcomp_inv_ref : Linv.comp Lref = Lratio := by | |
| ext v p | |
| simp [Linv, Lref, Lratio, sRatio, blockScalarLM, mul_assoc, mul_left_comm, mul_comm] | |
| have hstable : (Wspace A).map Lratio = Wspace A := by | |
| calc | |
| (Wspace A).map Lratio = (Wspace A).map (Linv.comp Lref) := by simpa [hcomp_inv_ref] | |
| _ = ((Wspace A).map Lref).map Linv := by | |
| simpa using (Submodule.map_comp (f := Lref) (g := Linv) (p := Wspace A)) | |
| _ = ((Wspace A).map Ls).map Linv := by simpa [hmapEq] | |
| _ = (Wspace A).map (Linv.comp Ls) := by | |
| simpa using (Submodule.map_comp (f := Ls) (g := Linv) (p := Wspace A)).symm | |
| _ = (Wspace A).map LinearMap.id := by simpa [hcomp_inv_s] | |
| _ = Wspace A := by simp | |
| have hgen' : GenericCameras A := ⟨hstack, hcam, hG3⟩ | |
| have hRigid : RigidBlockScalarStabilizer A := GenericCameras.rigid hgen' | |
| have hsConst : ∀ α β : Fin n, sRatio α = sRatio β := hRigid sRatio hstable | |
| have hsrow : sRatio row = sRatio i0 := hsConst row i0 | |
| have hsrow' : | |
| modeCoeff m lam row i0 i1 i2 / modeCoeff m lam row a b c = | |
| modeCoeff m lam i0 i0 i1 i2 / modeCoeff m lam i0 a b c := by | |
| simpa [sRatio, us, usRef, Units.val_mk0, div_eq_mul_inv, mul_assoc, mul_left_comm, mul_comm] | |
| using congrArg (fun z : ℝˣ => (z : ℝ)) hsrow | |
| have hden0 : modeCoeff m lam i0 a b c ≠ 0 := | |
| modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := a) (b := b) (c := c) hneq i0 | |
| have hdenrow : modeCoeff m lam row a b c ≠ 0 := | |
| modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := a) (b := b) (c := c) hneq row | |
| have href0 : modeCoeff m lam i0 i0 i1 i2 ≠ 0 := | |
| modeCoeff_ne_zero_of_notAllEqual3 (m := m) (lam := lam) hsupp | |
| (a := i0) (b := i1) (c := i2) hNotAll012 i0 | |
| have hcross : | |
| modeCoeff m lam row i0 i1 i2 * modeCoeff m lam i0 a b c = | |
| modeCoeff m lam i0 i0 i1 i2 * modeCoeff m lam row a b c := by | |
| have h := hsrow' | |
| field_simp [hdenrow, hden0] at h | |
| simpa [mul_assoc, mul_left_comm, mul_comm] using h | |
| have hsolve : | |
| modeCoeff m lam row a b c = | |
| modeCoeff m lam i0 a b c * | |
| (modeCoeff m lam row i0 i1 i2 / modeCoeff m lam i0 i0 i1 i2) := by | |
| have hbc : | |
| modeCoeff m lam row a b c * modeCoeff m lam i0 i0 i1 i2 = | |
| modeCoeff m lam row i0 i1 i2 * modeCoeff m lam i0 a b c := by | |
| calc | |
| modeCoeff m lam row a b c * modeCoeff m lam i0 i0 i1 i2 = | |
| modeCoeff m lam i0 i0 i1 i2 * modeCoeff m lam row a b c := by ring | |
| _ = modeCoeff m lam row i0 i1 i2 * modeCoeff m lam i0 a b c := by | |
| simpa [mul_assoc, mul_left_comm, mul_comm] using hcross.symm | |
| have hdiv : | |
| modeCoeff m lam row a b c = | |
| (modeCoeff m lam row i0 i1 i2 * modeCoeff m lam i0 a b c) / | |
| modeCoeff m lam i0 i0 i1 i2 := by | |
| exact (eq_div_iff href0).2 (by | |
| simpa [mul_assoc, mul_left_comm, mul_comm] using hbc) | |
| simpa [div_eq_mul_inv, mul_assoc, mul_left_comm, mul_comm] using hdiv | |
| simpa [u, μ, hneq, Units.val_mk0, mul_assoc, mul_left_comm, mul_comm] using hsolve | |
| theorem separate_alpha_of_generic {n : ℕ} (hn : 5 ≤ n) (A : Fin n → Matrix3x4) (lam : Lambda n) | |
| (hgen : GenericCameras A) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hrank : ∀ m : Fin 4, (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4) : | |
| ∃ (u : Fin n → ℝˣ) (μ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (μ β γ δ : ℝ) := by | |
| classical | |
| simpa [modeCoeff] using | |
| (separate_mode_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (m := (0 : Fin 4)) | |
| (hsupp := hsupp) (hrank := hrank)) | |
| theorem separate_beta_of_generic {n : ℕ} (A : Fin n → Matrix3x4) (lam : Lambda n) | |
| (hn : 5 ≤ n) (hgen : GenericCameras A) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hrank : ∀ m : Fin 4, (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4) : | |
| ∃ (v : Fin n → ℝˣ) (ν : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α γ δ → | |
| lam α β γ δ = (v β : ℝ) * (ν α γ δ : ℝ) := by | |
| classical | |
| rcases separate_mode_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (m := (1 : Fin 4)) | |
| (hsupp := hsupp) (hrank := hrank) with ⟨v, ν, hsep⟩ | |
| refine ⟨v, ν, ?_⟩ | |
| intro α β γ δ hneq | |
| simpa [modeCoeff] using hsep β α γ δ hneq | |
| theorem separate_gamma_of_generic {n : ℕ} (A : Fin n → Matrix3x4) (lam : Lambda n) | |
| (hn : 5 ≤ n) (hgen : GenericCameras A) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hrank : ∀ m : Fin 4, (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4) : | |
| ∃ (w : Fin n → ℝˣ) (ξ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α β δ → | |
| lam α β γ δ = (w γ : ℝ) * (ξ α β δ : ℝ) := by | |
| classical | |
| rcases separate_mode_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (m := (2 : Fin 4)) | |
| (hsupp := hsupp) (hrank := hrank) with ⟨w, ξ, hsep⟩ | |
| refine ⟨w, ξ, ?_⟩ | |
| intro α β γ δ hneq | |
| simpa [modeCoeff] using hsep γ α β δ hneq | |
| theorem separate_delta_of_generic {n : ℕ} (A : Fin n → Matrix3x4) (lam : Lambda n) | |
| (hn : 5 ≤ n) (hgen : GenericCameras A) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hrank : ∀ m : Fin 4, (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4) : | |
| ∃ (x : Fin n → ℝˣ) (ζ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α β γ → | |
| lam α β γ δ = (x δ : ℝ) * (ζ α β γ : ℝ) := by | |
| classical | |
| rcases separate_mode_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (m := (3 : Fin 4)) | |
| (hsupp := hsupp) (hrank := hrank) with ⟨x, ζ, hsep⟩ | |
| refine ⟨x, ζ, ?_⟩ | |
| intro α β γ δ hneq | |
| simpa [modeCoeff] using hsep δ α β γ hneq | |
| theorem full_factorization_of_separations {n : ℕ} (hn : 5 ≤ n) (lam : Lambda n) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hα : | |
| ∃ (u : Fin n → ℝˣ) (μ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (μ β γ δ : ℝ)) | |
| (hβ : | |
| ∃ (v : Fin n → ℝˣ) (ν : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α γ δ → | |
| lam α β γ δ = (v β : ℝ) * (ν α γ δ : ℝ)) | |
| (hγ : | |
| ∃ (w : Fin n → ℝˣ) (ξ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α β δ → | |
| lam α β γ δ = (w γ : ℝ) * (ξ α β δ : ℝ)) | |
| (hδ : | |
| ∃ (x : Fin n → ℝˣ) (ζ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α β γ → | |
| lam α β γ δ = (x δ : ℝ) * (ζ α β γ : ℝ)) : | |
| ∃ (u v w x : Fin n → ℝˣ), | |
| ∀ α β γ δ, NotIdentical α β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ) := by | |
| classical | |
| rcases hα with ⟨u, μ, hαeq⟩ | |
| rcases hβ with ⟨v, ν, hβeq⟩ | |
| rcases hγ with ⟨w, ξ, hγeq⟩ | |
| rcases hδ with ⟨x0, ζ, hδeq⟩ | |
| have _ : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ := hsupp | |
| clear hsupp x0 ζ hδeq | |
| have h0 : (0 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 0 < 5) hn | |
| let i0 : Fin n := ⟨0, h0⟩ | |
| let ρ : Fin n → Fin n → ℝˣ := fun γ δ => (u i0)⁻¹ * ν i0 γ δ | |
| have huvρ : | |
| ∀ α β γ δ, γ ≠ δ → | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (ρ γ δ : ℝ) := by | |
| intro α β γ δ hgd | |
| have hneqβ : NotAllEqual3 β γ δ := by | |
| intro h | |
| exact hgd h.2 | |
| have hneqi0 : NotAllEqual3 i0 γ δ := by | |
| intro h | |
| exact hgd h.2 | |
| have hμ : | |
| (μ β γ δ : ℝ) = (v β : ℝ) * (ρ γ δ : ℝ) := by | |
| have hcross : | |
| (u i0 : ℝ) * (μ β γ δ : ℝ) = (v β : ℝ) * (ν i0 γ δ : ℝ) := by | |
| calc | |
| (u i0 : ℝ) * (μ β γ δ : ℝ) = lam i0 β γ δ := (hαeq i0 β γ δ hneqβ).symm | |
| _ = (v β : ℝ) * (ν i0 γ δ : ℝ) := hβeq i0 β γ δ hneqi0 | |
| have hui0 : (u i0 : ℝ) ≠ 0 := (u i0).ne_zero | |
| have hdiv : | |
| (μ β γ δ : ℝ) = ((v β : ℝ) * (ν i0 γ δ : ℝ)) / (u i0 : ℝ) := by | |
| exact (eq_div_iff hui0).2 (by simpa [mul_assoc, mul_left_comm, mul_comm] using hcross) | |
| simpa [ρ, div_eq_mul_inv, mul_assoc, mul_left_comm, mul_comm] using hdiv | |
| calc | |
| lam α β γ δ = (u α : ℝ) * (μ β γ δ : ℝ) := hαeq α β γ δ hneqβ | |
| _ = (u α : ℝ) * ((v β : ℝ) * (ρ γ δ : ℝ)) := by rw [hμ] | |
| _ = (u α : ℝ) * (v β : ℝ) * (ρ γ δ : ℝ) := by ring | |
| let aPick : Fin n → Fin n := fun δ => Classical.choose (exists_fin_ne_of_five hn δ) | |
| have haPick : ∀ δ : Fin n, aPick δ ≠ δ := by | |
| intro δ | |
| exact Classical.choose_spec (exists_fin_ne_of_five hn δ) | |
| let x : Fin n → ℝˣ := fun δ => ((u (aPick δ)) * (v δ))⁻¹ * ξ (aPick δ) δ δ | |
| have hfull_ne : | |
| ∀ α β γ δ, γ ≠ δ → | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ) := by | |
| intro α β γ δ hgd | |
| have hnePick : NotAllEqual3 (aPick δ) δ δ := by | |
| intro h | |
| exact haPick δ h.1 | |
| have hγpick : | |
| lam (aPick δ) δ γ δ = (w γ : ℝ) * (ξ (aPick δ) δ δ : ℝ) := | |
| hγeq (aPick δ) δ γ δ hnePick | |
| have huvρ_pick : | |
| lam (aPick δ) δ γ δ = (u (aPick δ) : ℝ) * (v δ : ℝ) * (ρ γ δ : ℝ) := | |
| huvρ (aPick δ) δ γ δ hgd | |
| have hρ : | |
| (ρ γ δ : ℝ) = (w γ : ℝ) * (x δ : ℝ) := by | |
| have huvv_ne : ((u (aPick δ) : ℝ) * (v δ : ℝ)) ≠ 0 := by | |
| exact mul_ne_zero (u (aPick δ)).ne_zero (v δ).ne_zero | |
| have hmult : | |
| ((u (aPick δ) : ℝ) * (v δ : ℝ)) * (ρ γ δ : ℝ) = | |
| (w γ : ℝ) * (ξ (aPick δ) δ δ : ℝ) := by | |
| calc | |
| ((u (aPick δ) : ℝ) * (v δ : ℝ)) * (ρ γ δ : ℝ) | |
| = lam (aPick δ) δ γ δ := by simpa [mul_assoc] using huvρ_pick.symm | |
| _ = (w γ : ℝ) * (ξ (aPick δ) δ δ : ℝ) := hγpick | |
| have hscaled := congrArg (fun t => (((u (aPick δ) : ℝ) * (v δ : ℝ))⁻¹) * t) hmult | |
| simpa [x, mul_assoc, mul_left_comm, mul_comm, huvv_ne] using hscaled | |
| calc | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (ρ γ δ : ℝ) := huvρ α β γ δ hgd | |
| _ = (u α : ℝ) * (v β : ℝ) * ((w γ : ℝ) * (x δ : ℝ)) := by rw [hρ] | |
| _ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ) := by ring | |
| refine ⟨u, v, w, x, ?_⟩ | |
| intro α β γ δ hni | |
| by_cases hgd : γ = δ | |
| · subst hgd | |
| have hneqαβγ : NotAllEqual3 α β γ := by | |
| intro h | |
| exact hni ⟨h.1, h.2, rfl⟩ | |
| let η : Fin n := aPick γ | |
| have hηne : η ≠ γ := haPick γ | |
| have hfactη : | |
| lam α β η γ = (u α : ℝ) * (v β : ℝ) * (w η : ℝ) * (x γ : ℝ) := | |
| hfull_ne α β η γ hηne | |
| have hγη : lam α β η γ = (w η : ℝ) * (ξ α β γ : ℝ) := | |
| hγeq α β η γ hneqαβγ | |
| have hξ : | |
| (ξ α β γ : ℝ) = (u α : ℝ) * (v β : ℝ) * (x γ : ℝ) := by | |
| have hwη : (w η : ℝ) ≠ 0 := (w η).ne_zero | |
| apply (mul_left_cancel₀ hwη) | |
| calc | |
| (w η : ℝ) * (ξ α β γ : ℝ) = lam α β η γ := hγη.symm | |
| _ = (u α : ℝ) * (v β : ℝ) * (w η : ℝ) * (x γ : ℝ) := hfactη | |
| _ = (w η : ℝ) * ((u α : ℝ) * (v β : ℝ) * (x γ : ℝ)) := by ring | |
| have hγdiag : lam α β γ γ = (w γ : ℝ) * (ξ α β γ : ℝ) := | |
| hγeq α β γ γ hneqαβγ | |
| calc | |
| lam α β γ γ = (w γ : ℝ) * (ξ α β γ : ℝ) := hγdiag | |
| _ = (w γ : ℝ) * ((u α : ℝ) * (v β : ℝ) * (x γ : ℝ)) := by rw [hξ] | |
| _ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x γ : ℝ) := by ring | |
| · exact hfull_ne α β γ δ hgd | |
| theorem reverse_direction_core {n : ℕ} (hn : 5 ≤ n) (A : Fin n → Matrix3x4) | |
| (hgen : GenericCameras A) (lam : Lambda n) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hrank : ∀ m : Fin 4, (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4) : | |
| ∃ (u v w x : Fin n → ℝˣ), | |
| ∀ α β γ δ, NotIdentical α β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ) := by | |
| classical | |
| -- Extract the four partial separations (one per unfolding mode). | |
| have hα : ∃ (u : Fin n → ℝˣ) (μ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (μ β γ δ : ℝ) := | |
| separate_alpha_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (hsupp := hsupp) | |
| (hrank := hrank) | |
| have hβ : ∃ (v : Fin n → ℝˣ) (ν : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α γ δ → | |
| lam α β γ δ = (v β : ℝ) * (ν α γ δ : ℝ) := | |
| separate_beta_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (hsupp := hsupp) | |
| (hrank := hrank) | |
| have hγ : ∃ (w : Fin n → ℝˣ) (ξ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α β δ → | |
| lam α β γ δ = (w γ : ℝ) * (ξ α β δ : ℝ) := | |
| separate_gamma_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (hsupp := hsupp) | |
| (hrank := hrank) | |
| have hδ : ∃ (x : Fin n → ℝˣ) (ζ : Fin n → Fin n → Fin n → ℝˣ), | |
| ∀ α β γ δ, NotAllEqual3 α β γ → | |
| lam α β γ δ = (x δ : ℝ) * (ζ α β γ : ℝ) := | |
| separate_delta_of_generic (hn := hn) (A := A) (lam := lam) (hgen := hgen) (hsupp := hsupp) | |
| (hrank := hrank) | |
| -- Patch the separations into the full `u⊗v⊗w⊗x` factorization. | |
| exact full_factorization_of_separations (hn := hn) (lam := lam) (hsupp := hsupp) | |
| (hα := hα) (hβ := hβ) (hγ := hγ) (hδ := hδ) | |
| theorem reverse_direction {n : ℕ} (hn : 5 ≤ n) (A : Fin n → Matrix3x4) | |
| (hgen : GenericCameras A) (lam : Lambda n) | |
| (hsupp : ∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) | |
| (hvanish : IsZeroVec (PolyMap.eval (polyMapF n) (scaleQ lam (constructQ A)))) : | |
| ∃ (u v w x : Fin n → ℝˣ), | |
| ∀ α β γ δ, NotIdentical α β γ δ → | |
| lam α β γ δ = (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ) | |
| := by | |
| classical | |
| -- Step 0: derive the "all 5×5 minors vanish" statement and hence rank bounds for each unfolding. | |
| have hminors : | |
| ∀ (m : Fin 4) (rows : Fin 5 → RowIdx n) (cols : Fin 5 → ColIdx n), | |
| Matrix.det ((Unfold m (scaleQ lam (constructQ A))).submatrix rows cols) = 0 := by | |
| -- `IsZeroVec (eval F T)` is definitionally the statement that every 5×5 minor determinant is 0. | |
| exact (isZeroVec_iff_minors_vanish (Qf := scaleQ lam (constructQ A))).1 hvanish | |
| have hrank : | |
| ∀ m : Fin 4, (Unfold m (scaleQ lam (constructQ A))).rank ≤ 4 := by | |
| intro m | |
| refine minors5x5_zero_imp_rank_le_four (M := Unfold m (scaleQ lam (constructQ A))) ?_ | |
| intro rows cols | |
| exact hminors m rows cols | |
| exact reverse_direction_core (hn := hn) (A := A) (hgen := hgen) (lam := lam) | |
| (hsupp := hsupp) (hrank := hrank) | |
| noncomputable section AristotleLemmas | |
| def witnessA (n : ℕ) : Fin n → Matrix3x4 := | |
| fun α => Matrix.of ![![1, 0, 0, 0], ![0, 1, 0, 0], ![0, 0, 1, (α : ℝ)]] | |
| lemma witnessA_properties {n : ℕ} (hn : 5 ≤ n) : | |
| RankGenericCameras (witnessA n) := by | |
| classical | |
| refine ⟨?_, ?_⟩ | |
| · -- `rank (StackedMat (witnessA n)) = 4` by showing the four columns are independent. | |
| -- We do this via row-independence of the transpose. | |
| have h0 : (0 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 0 < 5) hn | |
| have h1 : (1 : ℕ) < n := Nat.lt_of_lt_of_le (by decide : 1 < 5) hn | |
| let a0 : Fin n := ⟨0, h0⟩ | |
| let a1 : Fin n := ⟨1, h1⟩ | |
| have hLI : | |
| LinearIndependent ℝ (fun i : Fin 4 => (StackedMat (witnessA n))ᵀ.row i) := by | |
| -- Use the finite-index characterization. | |
| refine (Fintype.linearIndependent_iff).2 ?_ | |
| intro g hg i | |
| -- Evaluate the vector equation at carefully chosen coordinates. | |
| -- The resulting scalar equations isolate each coefficient of `g`. | |
| have h_at (p : RowIdx n) : | |
| (∑ k : Fin 4, g k • (StackedMat (witnessA n))ᵀ.row k) p = 0 := by | |
| simpa using congrArg (fun v => v p) hg | |
| -- `g 0 = 0` from row `(a0,0)`. | |
| have hg0 : g 0 = 0 := by | |
| have h := h_at (a0, 0) | |
| have h' : (∑ x : Fin 4, g x * (![1, 0, 0, 0] x : ℝ)) = 0 := by | |
| -- Row `(a0,0)` is `[1,0,0,0]`. | |
| simpa [StackedMat, witnessA, a0, Matrix.row_apply, Matrix.transpose_apply, Pi.smul_apply] | |
| using h | |
| have h'' : | |
| g 0 * (1 : ℝ) + g 1 * (0 : ℝ) + g 2 * (0 : ℝ) + g 3 * (0 : ℝ) = 0 := by | |
| simpa [Fin.sum_univ_four] using h' | |
| simpa using h'' | |
| -- `g 1 = 0` from row `(a0,1)`. | |
| have hg1 : g 1 = 0 := by | |
| have h := h_at (a0, 1) | |
| have h' : (∑ x : Fin 4, g x * (![0, 1, 0, 0] x : ℝ)) = 0 := by | |
| -- Row `(a0,1)` is `[0,1,0,0]`. | |
| simpa [StackedMat, witnessA, a0, Matrix.row_apply, Matrix.transpose_apply, Pi.smul_apply] | |
| using h | |
| have h'' : | |
| g 0 * (0 : ℝ) + g 1 * (1 : ℝ) + g 2 * (0 : ℝ) + g 3 * (0 : ℝ) = 0 := by | |
| simpa [Fin.sum_univ_four] using h' | |
| simpa using h'' | |
| -- `g 2 = 0` and then `g 3 = 0` from rows `(a0,2)` and `(a1,2)`. | |
| have hg2 : g 2 = 0 := by | |
| have h := h_at (a0, 2) | |
| have h' : (∑ x : Fin 4, g x * (![0, 0, 1, (a0 : ℝ)] x : ℝ)) = 0 := by | |
| -- Row `(a0,2)` is `[0,0,1,(a0:ℝ)]`. | |
| simpa [StackedMat, witnessA, Matrix.row_apply, Matrix.transpose_apply, Pi.smul_apply] | |
| using h | |
| have h'' : g 2 + g 3 * (a0 : ℝ) = 0 := by | |
| -- Expand the sum; only indices `2` and `3` survive. | |
| simpa [Fin.sum_univ_four, mul_add, add_mul, add_assoc, add_left_comm, add_comm] using h' | |
| -- `a0 = 0`, so `g 3 * a0 = 0`. | |
| simpa [a0] using h'' | |
| have hg3 : g 3 = 0 := by | |
| have h := h_at (a1, 2) | |
| have h' : (∑ x : Fin 4, g x * (![0, 0, 1, (a1 : ℝ)] x : ℝ)) = 0 := by | |
| simpa [StackedMat, witnessA, Matrix.row_apply, Matrix.transpose_apply, Pi.smul_apply] | |
| using h | |
| have h'' : g 2 + g 3 * (a1 : ℝ) = 0 := by | |
| simpa [Fin.sum_univ_four, mul_add, add_mul, add_assoc, add_left_comm, add_comm] using h' | |
| have hmul : g 3 * (a1 : ℝ) = 0 := by | |
| simpa [hg2, add_zero] using h'' | |
| have ha1 : (a1 : ℝ) ≠ 0 := by | |
| simpa [a1] using (one_ne_zero : (1 : ℝ) ≠ 0) | |
| exact (mul_eq_zero.mp hmul).resolve_right ha1 | |
| fin_cases i <;> simp [hg0, hg1, hg2, hg3] | |
| have hrankT : (StackedMat (witnessA n))ᵀ.rank = 4 := by | |
| simpa using (LinearIndependent.rank_matrix (R := ℝ) (M := (StackedMat (witnessA n))ᵀ) hLI) | |
| simpa [Matrix.rank_transpose] using hrankT | |
| · intro α | |
| -- Each camera `witnessA n α` has rank 3: its three rows are linearly independent. | |
| have hLI : | |
| LinearIndependent ℝ (fun i : Fin 3 => (witnessA n α).row i) := by | |
| refine (Fintype.linearIndependent_iff).2 ?_ | |
| intro g hg i | |
| have h_at (j : Fin 4) : | |
| (∑ k : Fin 3, g k • (witnessA n α).row k) j = 0 := by | |
| simpa using congrArg (fun v => v j) hg | |
| have hg0 : g 0 = 0 := by | |
| have h := h_at 0 | |
| have h' : | |
| (∑ x : Fin 3, g x * | |
| (vecCons (1 : ℝ) (fun i => vecCons 0 (fun _ => 0) i) x)) = 0 := by | |
| -- Column `0` of the three rows is `[1,0,0]`. | |
| simpa [witnessA, Matrix.row_apply, Pi.smul_apply] using h | |
| have h'' : g 0 * (1 : ℝ) + g 1 * (0 : ℝ) + g 2 * (0 : ℝ) = 0 := by | |
| simpa [Fin.sum_univ_three] using h' | |
| simpa using h'' | |
| have hg1 : g 1 = 0 := by | |
| have h := h_at 1 | |
| have h' : | |
| (∑ x : Fin 3, g x * | |
| (vecCons (0 : ℝ) (fun i => vecCons 1 (fun _ => 0) i) x)) = 0 := by | |
| -- Column `1` of the three rows is `[0,1,0]`. | |
| simpa [witnessA, Matrix.row_apply, Pi.smul_apply] using h | |
| have h'' : g 0 * (0 : ℝ) + g 1 * (1 : ℝ) + g 2 * (0 : ℝ) = 0 := by | |
| simpa [Fin.sum_univ_three] using h' | |
| simpa using h'' | |
| have hg2 : g 2 = 0 := by | |
| have h := h_at 2 | |
| have h' : | |
| (∑ x : Fin 3, g x * | |
| (vecCons (0 : ℝ) (fun i => vecCons 0 (fun _ => 1) i) x)) = 0 := by | |
| -- Column `2` of the three rows is `[0,0,1]`. | |
| simpa [witnessA, Matrix.row_apply, Pi.smul_apply] using h | |
| have h'' : g 0 * (0 : ℝ) + g 1 * (0 : ℝ) + g 2 * (1 : ℝ) = 0 := by | |
| simpa [Fin.sum_univ_three] using h' | |
| simpa using h'' | |
| fin_cases i <;> simp [hg0, hg1, hg2] | |
| simpa using (LinearIndependent.rank_matrix (R := ℝ) (M := witnessA n α) hLI) | |
| /- | |
| Definitions for the genericity polynomial components: | |
| 1. `mat_poly_stacked`: The stacked matrix with polynomial entries. | |
| 2. `poly_minor_stacked`: Determinant of a 4x4 submatrix of the stacked matrix. | |
| 3. `poly_sum_sq_stacked`: Sum of squares of all 4x4 minors of the stacked matrix. | |
| 4. `mat_poly_cam`: The camera matrix `A α` with polynomial entries. | |
| 5. `poly_minor_cam`: Determinant of a 3x3 submatrix of `A α`. | |
| 6. `poly_sum_sq_cam`: Sum of squares of all 3x3 minors of `A α`. | |
| 7. `total_genericity_poly`: The product of `poly_sum_sq_stacked` and all `poly_sum_sq_cam`. | |
| -/ | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| def mat_poly_stacked (n : ℕ) : Matrix (RowIdx n) (Fin 4) (MvPolynomial (AIndex n) ℝ) := | |
| fun p k => MvPolynomial.X (p.1, p.2, k) | |
| def poly_minor_stacked (n : ℕ) (rows : Fin 4 → RowIdx n) : MvPolynomial (AIndex n) ℝ := | |
| Matrix.det ((mat_poly_stacked n).submatrix rows id) | |
| def poly_sum_sq_stacked (n : ℕ) : MvPolynomial (AIndex n) ℝ := | |
| ∑ rows : Fin 4 → RowIdx n, (poly_minor_stacked n rows)^2 | |
| def mat_poly_cam (n : ℕ) (α : Fin n) : Matrix (Fin 3) (Fin 4) (MvPolynomial (AIndex n) ℝ) := | |
| fun i j => MvPolynomial.X (α, i, j) | |
| def poly_minor_cam (n : ℕ) (α : Fin n) (cols : Fin 3 → Fin 4) : MvPolynomial (AIndex n) ℝ := | |
| Matrix.det ((mat_poly_cam n α).submatrix id cols) | |
| def poly_sum_sq_cam (n : ℕ) (α : Fin n) : MvPolynomial (AIndex n) ℝ := | |
| ∑ cols : Fin 3 → Fin 4, (poly_minor_cam n α cols)^2 | |
| def total_genericity_poly (n : ℕ) : MvPolynomial (AIndex n) ℝ := | |
| (poly_sum_sq_stacked n) * (∏ α : Fin n, poly_sum_sq_cam n α) | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| lemma eval_poly_sum_sq_stacked_ne_zero {n : ℕ} (A : Fin n → Matrix3x4) : | |
| evalCameraPolynomial (poly_sum_sq_stacked n) A ≠ 0 → (StackedMat A).rank = 4 := by | |
| intro h_nonzero | |
| have h_rank_ge_4 : (StackedMat A).rank ≥ 4 := by | |
| -- Since `poly_sum_sq_stacked n` is nonzero, there exists a 4x4 minor of `StackedMat A` that is nonzero. | |
| obtain ⟨rows, hrows⟩ : ∃ rows : Fin 4 → RowIdx n, Matrix.det (Matrix.submatrix (StackedMat A) rows id) ≠ 0 := by | |
| contrapose! h_nonzero; | |
| simp_all +decide [ Arxiv.«2602.05192».evalCameraPolynomial, Arxiv.«2602.05192».poly_sum_sq_stacked ]; | |
| refine Finset.sum_eq_zero fun x hx => ?_; | |
| convert congr_arg ( · ^ 2 ) ( h_nonzero x ) using 1; | |
| · unfold Arxiv.«2602.05192».poly_minor_stacked; simp +decide [ Matrix.det_apply' ] ; | |
| unfold Arxiv.«2602.05192».mat_poly_stacked; aesop; | |
| · norm_num; | |
| have h_rank_ge_4 : Matrix.rank (Matrix.submatrix (StackedMat A) rows id) ≥ 4 := by | |
| have := Matrix.rank_mul_le_left ( Matrix.submatrix ( StackedMat A ) rows id ) ( ( Matrix.submatrix ( StackedMat A ) rows id ) ⁻¹ ) ; simp_all +decide [ Matrix.nonsing_inv_apply_not_isUnit, isUnit_iff_ne_zero ] ; | |
| -- Since the submatrix is a part of the original matrix, its rank is less than or equal to the rank of the original matrix. | |
| have h_submatrix_rank_le : Matrix.rank (Matrix.submatrix (StackedMat A) rows id) ≤ Matrix.rank (StackedMat A) := by | |
| have h_submatrix : ∃ P : Matrix (Fin 4) (RowIdx n) ℝ, ∃ Q : Matrix (Fin 4) (Fin 4) ℝ, Matrix.submatrix (StackedMat A) rows id = P * StackedMat A * Q := by | |
| use Matrix.of (fun i j => if j = rows i then 1 else 0), 1; | |
| ext i j; simp +decide [ Matrix.mul_apply ] ; | |
| simp +decide [ Matrix.one_apply ] | |
| obtain ⟨ P, Q, hPQ ⟩ := h_submatrix; rw [ hPQ ] ; exact Matrix.rank_mul_le_left _ _ |> le_trans <| Matrix.rank_mul_le_right _ _; | |
| exact le_trans h_rank_ge_4 h_submatrix_rank_le | |
| have h_rank_le_4 : (StackedMat A).rank ≤ 4 := by | |
| exact le_trans ( Matrix.rank_le_card_width _ ) ( by simp +decide ) | |
| exact le_antisymm h_rank_le_4 h_rank_ge_4 | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| lemma eval_poly_sum_sq_cam_ne_zero {n : ℕ} (A : Fin n → Matrix3x4) (α : Fin n) : | |
| evalCameraPolynomial (poly_sum_sq_cam n α) A ≠ 0 → (A α).rank = 3 := by | |
| intro h_nonzero | |
| obtain ⟨cols, h_det⟩ : ∃ cols : Fin 3 → Fin 4, Matrix.det ((A α).submatrix id cols) ≠ 0 := by | |
| simp_all +decide [ Arxiv.«2602.05192».evalCameraPolynomial, Arxiv.«2602.05192».poly_sum_sq_cam ]; | |
| contrapose! h_nonzero; simp_all +decide [ Arxiv.«2602.05192».poly_minor_cam ] ; | |
| refine Finset.sum_eq_zero fun x hx => ?_ ; simp_all +decide [ Matrix.det_apply' ]; | |
| unfold Arxiv.«2602.05192».mat_poly_cam; aesop; | |
| have h_rank_ge_3 : Matrix.rank (A α) ≥ 3 := by | |
| have := Matrix.rank_mul_le ( A α ) ( Matrix.of ( fun i j => if i = cols j then 1 else 0 ) ) ; simp_all +decide [ Matrix.rank_transpose, Matrix.mul_apply ] ; | |
| have h_rank_ge_3 : Matrix.rank (Matrix.submatrix (A α) id cols) = 3 := by | |
| have := Matrix.rank_mul_le ( Matrix.submatrix ( A α ) id cols ) ( Matrix.submatrix ( A α ) id cols ) ⁻¹; simp_all +decide [ Matrix.nonsing_inv_apply_not_isUnit, isUnit_iff_ne_zero ] ; | |
| exact le_antisymm ( le_trans ( Matrix.rank_le_card_width _ ) ( by norm_num ) ) this.1; | |
| convert this.1 using 1; | |
| convert h_rank_ge_3.symm using 2; ext i j; simp +decide [ Matrix.mul_apply ] ; | |
| exact le_antisymm ( le_trans ( Matrix.rank_le_card_height _ ) ( by norm_num ) ) h_rank_ge_3 | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| lemma rank_eq_four_imp_eval_stacked_ne_zero {n : ℕ} (A : Fin n → Matrix3x4) : | |
| (StackedMat A).rank = 4 → evalCameraPolynomial (poly_sum_sq_stacked n) A ≠ 0 := by | |
| intro h_rank h_eval_zero; | |
| -- If the rank is 4, then there exists a 4x4 submatrix with a non-zero determinant. | |
| obtain ⟨rows, h_det⟩ : ∃ rows : Fin 4 → RowIdx n, (Matrix.det (Matrix.submatrix (StackedMat A) rows id)) ≠ 0 := by | |
| have h_det : ∃ rows : Fin 4 → RowIdx n, LinearIndependent ℝ (fun i => (StackedMat A).row (rows i)) := by | |
| have h_det : ∃ rows : Fin 4 → RowIdx n, LinearIndependent ℝ (fun i => (StackedMat A).row (rows i)) := by | |
| have h_rank : Module.finrank ℝ (Submodule.span ℝ (Set.range (StackedMat A).row)) = 4 := by | |
| convert h_rank using 1; | |
| exact Eq.symm (rank_eq_finrank_span_row (StackedMat A)) | |
| have := ( exists_linearIndependent ℝ ( Set.range ( StackedMat A |> Matrix.row ) ) ); | |
| obtain ⟨ b, hb₁, hb₂, hb₃ ⟩ := this; | |
| have h_card : Set.ncard b = 4 := by | |
| have h_card : Module.finrank ℝ (Submodule.span ℝ b) = 4 := by | |
| rw [ hb₂, h_rank ]; | |
| have h_card : Module.finrank ℝ (Submodule.span ℝ b) = Set.ncard b := by | |
| have h_finite : Set.Finite b := by | |
| exact Set.Finite.subset ( Set.toFinite ( Set.range ( StackedMat A |> Matrix.row ) ) ) hb₁ | |
| convert ( finrank_span_eq_card <| hb₃ ); | |
| all_goals norm_num [ Set.ncard_eq_toFinset_card' ]; | |
| convert Set.ncard_coe_finset ( h_finite.toFinset ); | |
| all_goals try { exact h_finite.fintype }; | |
| · aesop; | |
| · rw [ Fintype.card_of_subtype ] ; aesop; | |
| linarith; | |
| obtain ⟨rows, hrows⟩ : ∃ rows : Fin 4 → (Fin 4 → ℝ), (∀ i, rows i ∈ b) ∧ LinearIndependent ℝ rows := by | |
| have h_card : Nonempty (Fin 4 ≃ b) := by | |
| have h_card : Fintype b := by | |
| exact Set.Finite.fintype ( Set.finite_of_ncard_pos ( by linarith ) ); | |
| exact ⟨ Fintype.equivOfCardEq <| by simp +decide [ Set.ncard_eq_toFinset_card' ] at *; linarith ⟩; | |
| obtain ⟨ e ⟩ := h_card; | |
| exact ⟨ _, fun i => e i |>.2, hb₃.comp _ e.injective ⟩; | |
| choose f hf using fun i => hb₁ ( hrows.1 i ); | |
| exact ⟨ f, by simpa only [ hf ] using hrows.2 ⟩; | |
| exact h_det; | |
| obtain ⟨ rows, hrows ⟩ := h_det; | |
| refine' ⟨ rows, _ ⟩; | |
| rw [ Fintype.linearIndependent_iff ] at hrows; | |
| contrapose! hrows; | |
| obtain ⟨ g, hg ⟩ := Matrix.exists_vecMul_eq_zero_iff.mpr hrows; | |
| exact ⟨ g, by simpa [ funext_iff, Matrix.vecMul, dotProduct ] using hg.2, Function.ne_iff.mp hg.1 ⟩; | |
| -- Since the determinant of the submatrix is non-zero, the evaluation of the polynomial at A is also non-zero. | |
| have h_eval_nonzero : evalCameraPolynomial (poly_minor_stacked n rows) A ≠ 0 := by | |
| unfold Arxiv.«2602.05192».evalCameraPolynomial; simp_all +decide [ Matrix.det_apply' ] ; | |
| unfold Arxiv.«2602.05192».poly_minor_stacked; simp_all +decide [ Matrix.det_apply' ] ; | |
| convert h_det using 1; | |
| unfold Arxiv.«2602.05192».mat_poly_stacked; simp +decide [ Arxiv.«2602.05192».StackedMat ] ; | |
| -- Since the evaluation of the polynomial at A is zero, the sum of squares of all 4x4 minors must also be zero. | |
| have h_sum_sq_zero : ∑ rows : Fin 4 → RowIdx n, (evalCameraPolynomial (poly_minor_stacked n rows) A)^2 = 0 := by | |
| convert h_eval_zero using 1; | |
| unfold Arxiv.«2602.05192».evalCameraPolynomial Arxiv.«2602.05192».poly_sum_sq_stacked; simp +decide [ sq, MvPolynomial.eval₂_sum ] ; | |
| exact absurd h_sum_sq_zero ( ne_of_gt ( lt_of_lt_of_le ( by positivity ) ( Finset.single_le_sum ( fun x _ => sq_nonneg ( evalCameraPolynomial ( poly_minor_stacked n x ) A ) ) ( Finset.mem_univ rows ) ) ) ) | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| lemma rank_lt_three_of_all_3x3_minors_zero (M : Matrix (Fin 3) (Fin 4) ℝ) | |
| (h : ∀ cols : Fin 3 → Fin 4, (M.submatrix id cols).det = 0) : | |
| M.rank < 3 := by | |
| -- If `M.rank = 3`, then the column space has dimension 3. | |
| by_contra h_contra | |
| have h_col_space : Module.finrank ℝ (Submodule.span ℝ (Set.range M.col)) = 3 := by | |
| rw [ show ( Submodule.span ℝ ( Set.range M.col ) ) = LinearMap.range M.mulVecLin from ?_ ]; | |
| · exact le_antisymm ( le_trans ( Submodule.finrank_le _ ) ( by norm_num ) ) ( not_lt.mp h_contra ); | |
| · exact Eq.symm (range_mulVecLin M); | |
| -- Since the column space has dimension 3, there exists a subset of 3 columns that is linearly independent. | |
| obtain ⟨cols, hcols⟩ : ∃ cols : Fin 3 → Fin 4, LinearIndependent ℝ (fun i : Fin 3 => M.col (cols i)) := by | |
| have := ( exists_linearIndependent ℝ ( Set.range M.col ) ); | |
| obtain ⟨ b, hb₁, hb₂, hb₃ ⟩ := this; | |
| have h_card : Set.ncard b = 3 := by | |
| have h_card : Module.finrank ℝ (Submodule.span ℝ b) = 3 := by | |
| rw [ hb₂, h_col_space ]; | |
| have h_card : Module.finrank ℝ (Submodule.span ℝ b) = Set.ncard b := by | |
| have h_finite : Set.Finite b := by | |
| exact Set.Finite.subset ( Set.toFinite ( Set.range M.col ) ) hb₁ | |
| convert ( finrank_span_eq_card <| hb₃ ); | |
| all_goals norm_num [ Set.ncard_eq_toFinset_card' ]; | |
| convert Set.ncard_coe_finset ( h_finite.toFinset ); | |
| all_goals try { exact h_finite.fintype }; | |
| · aesop; | |
| · rw [ Fintype.card_of_subtype ] ; aesop; | |
| linarith; | |
| have h_card : ∃ cols : Fin 3 → Fin 4, b = Set.range (fun i => M.col (cols i)) := by | |
| have h_card : ∃ cols : Fin 3 → (Fin 3 → ℝ), b = Set.range cols := by | |
| have h_card : ∃ cols : Finset (Fin 3 → ℝ), cols.card = 3 ∧ b = cols := by | |
| have h_card : ∃ cols : Finset (Fin 3 → ℝ), b = cols := by | |
| exact ⟨ Set.Finite.toFinset ( Set.finite_of_ncard_pos ( by linarith ) ), by simpa ⟩; | |
| aesop; | |
| obtain ⟨ cols, hcols₁, hcols₂ ⟩ := h_card; | |
| have h_card : Nonempty (Fin 3 ≃ cols) := by | |
| exact ⟨ Fintype.equivOfCardEq <| by simp +decide [ hcols₁ ] ⟩; | |
| obtain ⟨ e ⟩ := h_card; | |
| use fun i => e i |>.1; | |
| ext x; simp [hcols₂]; | |
| exact ⟨ fun hx => ⟨ e.symm ⟨ x, hx ⟩, by simp +decide ⟩, by rintro ⟨ y, rfl ⟩ ; exact e y |>.2 ⟩; | |
| obtain ⟨ cols, rfl ⟩ := h_card; | |
| choose f hf using fun i => hb₁ ( Set.mem_range_self i ); | |
| exact ⟨ f, by ext; aesop ⟩; | |
| obtain ⟨ cols, rfl ⟩ := h_card; | |
| use cols; | |
| convert hb₃.comp _ _; | |
| rotate_left; | |
| use fun i => ⟨ M.col ( cols i ), Set.mem_range_self i ⟩; | |
| · intro i j hij; have := Finset.card_image_iff.mp ( show Finset.card ( Finset.image ( fun i => M.col ( cols i ) ) Finset.univ ) = Finset.card ( Finset.univ : Finset ( Fin 3 ) ) from ?_ ) ; aesop; | |
| rw [ ← Set.ncard_coe_finset ] ; aesop; | |
| · rfl; | |
| -- Since the columns of `M` are linearly independent, the determinant of the submatrix formed by these columns is nonzero. | |
| have h_det_nonzero : Matrix.det (Matrix.of (fun i j => M i (cols j))) ≠ 0 := by | |
| rw [ Fintype.linearIndependent_iff ] at hcols; | |
| intro h_det_zerocols; | |
| obtain ⟨ v, hv ⟩ := Matrix.exists_mulVec_eq_zero_iff.mpr h_det_zerocols; | |
| exact hv.1 ( funext fun i => hcols v ( by ext j; simpa [ Matrix.mulVec, dotProduct, mul_comm ] using congr_fun hv.2 j ) i ); | |
| exact h_det_nonzero (h cols) | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| lemma rank_eq_three_imp_eval_cam_ne_zero {n : ℕ} (A : Fin n → Matrix3x4) (α : Fin n) : | |
| (A α).rank = 3 → evalCameraPolynomial (poly_sum_sq_cam n α) A ≠ 0 := by | |
| intro h_rank h_zero_sum; | |
| -- By definition of `poly_sum_sq_cam`, we know that `evalCameraPolynomial (poly_sum_sq_cam n α) A` is the sum of squares of determinants of 3x3 submatrices of `A α`. | |
| have h_sum_sq : ∑ cols : Fin 3 → Fin 4, (Matrix.det ((A α).submatrix id cols))^2 = 0 := by | |
| unfold Arxiv.«2602.05192».evalCameraPolynomial at h_zero_sum; | |
| unfold Arxiv.«2602.05192».poly_sum_sq_cam at h_zero_sum; | |
| convert h_zero_sum using 1; | |
| unfold Arxiv.«2602.05192».poly_minor_cam; simp +decide [ Matrix.det_apply' ] ; | |
| unfold Arxiv.«2602.05192».mat_poly_cam; simp +decide [ Matrix.det_apply' ] ; | |
| -- Since the sum of squares of determinants is zero, each determinant must be zero. | |
| have h_det_zero : ∀ cols : Fin 3 → Fin 4, (Matrix.det ((A α).submatrix id cols)) = 0 := by | |
| rw [ Finset.sum_eq_zero_iff_of_nonneg fun _ _ => sq_nonneg _ ] at h_sum_sq ; aesop; | |
| exact absurd ( rank_lt_three_of_all_3x3_minors_zero ( A α ) h_det_zero ) ( by linarith ) | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| lemma total_genericity_poly_ne_zero {n : ℕ} (hn : 5 ≤ n) : | |
| total_genericity_poly n ≠ 0 := by | |
| -- Let's choose any witness A for n ≥ 5. | |
| set A : Fin n → Matrix3x4 := witnessA n; | |
| -- By definition of $A$, we know that its evaluation at the witness cameras is non-zero. | |
| have h_eval_nonzero : (evalCameraPolynomial (poly_sum_sq_stacked n) A) * (∏ α : Fin n, evalCameraPolynomial (poly_sum_sq_cam n α) A) ≠ 0 := by | |
| have h_eval_nonzero : (evalCameraPolynomial (poly_sum_sq_stacked n) A) ≠ 0 ∧ ∀ α : Fin n, (evalCameraPolynomial (poly_sum_sq_cam n α) A) ≠ 0 := by | |
| have h_eval_nonzero : (StackedMat A).rank = 4 ∧ (∀ α : Fin n, (A α).rank = 3) := by | |
| simpa [Arxiv.«2602.05192».RankGenericCameras] using (Arxiv.«2602.05192».witnessA_properties hn) | |
| exact ⟨ by simpa using rank_eq_four_imp_eval_stacked_ne_zero A h_eval_nonzero.1, fun α => by simpa using rank_eq_three_imp_eval_cam_ne_zero A α ( h_eval_nonzero.2 α ) ⟩; | |
| exact mul_ne_zero h_eval_nonzero.1 <| Finset.prod_ne_zero_iff.mpr fun α _ => h_eval_nonzero.2 α; | |
| contrapose! h_eval_nonzero; | |
| convert congr_arg ( fun p => p.eval ( fun v => A v.1 v.2.1 v.2.2 ) ) h_eval_nonzero using 1; | |
| unfold Arxiv.«2602.05192».total_genericity_poly; simp +decide [ Arxiv.«2602.05192».evalCameraPolynomial ] ; | |
| open Arxiv.«2602.05192» | |
| open Classical Matrix BigOperators | |
| lemma eval_total_genericity_poly_witness_ne_zero {n : ℕ} (hn : 5 ≤ n) : | |
| evalCameraPolynomial (total_genericity_poly n) (witnessA n) ≠ 0 := by | |
| -- Apply the definition of `total_genericity_poly`. | |
| simp [Arxiv.«2602.05192».total_genericity_poly]; | |
| unfold Arxiv.«2602.05192».evalCameraPolynomial; | |
| simp +zetaDelta at *; | |
| constructor; | |
| · convert rank_eq_four_imp_eval_stacked_ne_zero _ _; | |
| convert ( witnessA_properties hn ).1; | |
| · apply Finset.prod_ne_zero_iff.mpr; | |
| intro a ha; | |
| convert rank_eq_three_imp_eval_cam_ne_zero _ _ _; | |
| convert Arxiv.«2602.05192».witnessA_properties hn |>.2 a | |
| end AristotleLemmas | |
| theorem genericity_polynomial_exists (n : ℕ) (hn : 5 ≤ n) : | |
| ∃ (G : MvPolynomial (AIndex n) ℝ), G ≠ 0 ∧ | |
| ∀ A : Fin n → Matrix3x4, | |
| evalCameraPolynomial G A ≠ 0 → RankGenericCameras A | |
| := by | |
| classical | |
| refine' ⟨ _, _, _ ⟩; | |
| -- Define the polynomial G as the product of the sum of squares of the minors of the stacked matrix and the sum of squares of the minors of each camera matrix. | |
| set G : MvPolynomial (Arxiv.«2602.05192».AIndex n) ℝ := (poly_sum_sq_stacked n) * (∏ α : Fin n, poly_sum_sq_cam n α); | |
| exact G; | |
| · convert total_genericity_poly_ne_zero hn using 1; | |
| · intro A hA; | |
| refine' ⟨ _, _ ⟩; | |
| · apply Arxiv.«2602.05192».eval_poly_sum_sq_stacked_ne_zero; | |
| exact fun h => hA <| by rw [ Arxiv.«2602.05192».evalCameraPolynomial ] at *; simp_all +decide [ Finset.prod_eq_zero_iff, sub_eq_iff_eq_add ] ; | |
| · intro α; | |
| apply eval_poly_sum_sq_cam_ne_zero A α; | |
| simp_all +decide [ Finset.prod_eq_prod_diff_singleton_mul ( Finset.mem_univ α ) ]; | |
| unfold Arxiv.«2602.05192».evalCameraPolynomial at *; aesop; | |
| /-- | |
| Core theorem proved from `GenericCameras` directly (reverse direction uses `G3`). | |
| -/ | |
| theorem nine_core : | |
| ∃ (d : ℕ), | |
| ∀ n : ℕ, 5 ≤ n → | |
| ∃ (N : ℕ) (F : PolyMap n N), | |
| PolyMap.UniformDegreeBound d F ∧ | |
| ∀ (A : Fin n → Matrix3x4), GenericCameras A → | |
| ∀ (lam : Lambda n), | |
| (∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) → | |
| (IsZeroVec (PolyMap.eval F (scaleQ lam (constructQ A))) ↔ | |
| (∃ (u v w x : Fin n → ℝˣ), | |
| ∀ α β γ δ, NotIdentical α β γ δ → | |
| lam α β γ δ = | |
| (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ))) := by | |
| refine ⟨5, ?_⟩ | |
| intro n hn | |
| refine ⟨numMinors n, polyMapF n, polyMapF_degree_bound n, ?_⟩ | |
| intro A hgen lam hsupp | |
| constructor | |
| · intro hvanish | |
| exact reverse_direction hn A hgen lam hsupp hvanish | |
| · rintro ⟨u, v, w, x, hfact⟩ | |
| exact forward_direction A lam hsupp u v w x hfact | |
| def StrongGenericityPolynomialExists (n : ℕ) : Prop := | |
| ∃ (G : MvPolynomial (AIndex n) ℝ), G ≠ 0 ∧ | |
| ∀ (A : Fin n → Matrix3x4), evalCameraPolynomial G A ≠ 0 → GenericCameras A | |
| noncomputable section AristotleLemmas | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| def poly_stackedRowsMatrix (n : ℕ) (α β γ δ : Fin n) (i j k ℓ : Fin 3) : Matrix (Fin 4) (Fin 4) (MvPolynomial (AIndex n) ℝ) := | |
| Matrix.of ![(mat_poly_cam n α) i, (mat_poly_cam n β) j, (mat_poly_cam n γ) k, (mat_poly_cam n δ) ℓ] | |
| def poly_constructQ_entry (n : ℕ) (α β γ δ : Fin n) (i j k ℓ : Fin 3) : MvPolynomial (AIndex n) ℝ := | |
| Matrix.det (poly_stackedRowsMatrix n α β γ δ i j k ℓ) | |
| def poly_Unfold_entry (n : ℕ) (m : Fin 4) (row : RowIdx n) (col : ColIdx n) : MvPolynomial (AIndex n) ℝ := | |
| match m with | |
| | ⟨0, _⟩ => poly_constructQ_entry n row.1 col.1.1 col.2.1.1 col.2.2.1 row.2 col.1.2 col.2.1.2 col.2.2.2 | |
| | ⟨1, _⟩ => poly_constructQ_entry n col.1.1 row.1 col.2.1.1 col.2.2.1 col.1.2 row.2 col.2.1.2 col.2.2.2 | |
| | ⟨2, _⟩ => poly_constructQ_entry n col.1.1 col.2.1.1 row.1 col.2.2.1 col.1.2 col.2.1.2 row.2 col.2.2.2 | |
| | ⟨3, _⟩ => poly_constructQ_entry n col.1.1 col.2.1.1 col.2.2.1 row.1 col.1.2 col.2.1.2 col.2.2.2 row.2 | |
| def poly_Submatrix27_entry (n : ℕ) (m : Fin 4) (a b c : Fin n) (row : RowIdx n) (t : Triple3) : MvPolynomial (AIndex n) ℝ := | |
| poly_Unfold_entry n m row (colIdxOfTriple a b c t) | |
| def poly_G3_minor (n : ℕ) (m : Fin 4) (a b c : Fin n) (rows : Fin 4 → RowIdx n) (cols : Fin 4 → Triple3) : MvPolynomial (AIndex n) ℝ := | |
| Matrix.det (fun i j => poly_Submatrix27_entry n m a b c (rows i) (cols j)) | |
| def poly_sum_sq_G3_block (n : ℕ) (m : Fin 4) (a b c : Fin n) : MvPolynomial (AIndex n) ℝ := | |
| ∑ rows : Fin 4 → RowIdx n, ∑ cols : Fin 4 → Triple3, (poly_G3_minor n m a b c rows cols)^2 | |
| def poly_G3_total (n : ℕ) : MvPolynomial (AIndex n) ℝ := | |
| ∏ m : Fin 4, ∏ a : Fin n, ∏ b : Fin n, ∏ c : Fin n, | |
| if NotAllEqual3 a b c then poly_sum_sq_G3_block n m a b c else 1 | |
| def strong_genericity_poly (n : ℕ) : MvPolynomial (AIndex n) ℝ := | |
| (total_genericity_poly n) * (poly_G3_total n) | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma eval_poly_constructQ_entry {n : ℕ} (A : Fin n → Matrix3x4) (α β γ δ : Fin n) (i j k ℓ : Fin 3) : | |
| evalCameraPolynomial (poly_constructQ_entry n α β γ δ i j k ℓ) A = constructQ A α β γ δ i j k ℓ := by | |
| unfold Arxiv.«2602.05192».poly_constructQ_entry; | |
| unfold Arxiv.«2602.05192».evalCameraPolynomial Arxiv.«2602.05192».poly_stackedRowsMatrix; simp +decide [ Matrix.det_apply' ] ; | |
| simp +decide [ Arxiv.«2602.05192».mat_poly_cam, Arxiv.«2602.05192».constructQ ]; | |
| simp +decide [ Fin.prod_univ_four, Matrix.det_apply' ]; | |
| congr! 2; | |
| rename_i σ _; | |
| fin_cases σ <;> simp +decide [ Arxiv.«2602.05192».stackedRowsMatrix ]; | |
| all_goals simp +decide [ Equiv.swap_apply_def ] ; | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma eval_poly_Submatrix27_entry {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) (a b c : Fin n) (row : RowIdx n) (t : Triple3) : | |
| evalCameraPolynomial (poly_Submatrix27_entry n m a b c row t) A = Submatrix27 A m a b c row t := by | |
| unfold Arxiv.«2602.05192».poly_Submatrix27_entry Submatrix27; | |
| unfold Arxiv.«2602.05192».poly_Unfold_entry | |
| fin_cases m <;> simp [Unfold] | |
| · exact | |
| eval_poly_constructQ_entry A row.1 (colIdxOfTriple a b c t).1.1 | |
| (colIdxOfTriple a b c t).2.1.1 (colIdxOfTriple a b c t).2.2.1 row.2 | |
| (colIdxOfTriple a b c t).1.2 (colIdxOfTriple a b c t).2.1.2 (colIdxOfTriple a b c t).2.2.2 | |
| · exact | |
| eval_poly_constructQ_entry A (colIdxOfTriple a b c t).1.1 row.1 | |
| (colIdxOfTriple a b c t).2.1.1 (colIdxOfTriple a b c t).2.2.1 (colIdxOfTriple a b c t).1.2 | |
| row.2 (colIdxOfTriple a b c t).2.1.2 (colIdxOfTriple a b c t).2.2.2 | |
| · exact | |
| eval_poly_constructQ_entry A (colIdxOfTriple a b c t).1.1 (colIdxOfTriple a b c t).2.1.1 | |
| row.1 (colIdxOfTriple a b c t).2.2.1 (colIdxOfTriple a b c t).1.2 | |
| (colIdxOfTriple a b c t).2.1.2 row.2 (colIdxOfTriple a b c t).2.2.2 | |
| · exact | |
| eval_poly_constructQ_entry A (colIdxOfTriple a b c t).1.1 (colIdxOfTriple a b c t).2.1.1 | |
| (colIdxOfTriple a b c t).2.2.1 row.1 (colIdxOfTriple a b c t).1.2 | |
| (colIdxOfTriple a b c t).2.1.2 (colIdxOfTriple a b c t).2.2.2 row.2 | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma eval_poly_G3_minor {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) (a b c : Fin n) (rows : Fin 4 → RowIdx n) (cols : Fin 4 → Triple3) : | |
| evalCameraPolynomial (poly_G3_minor n m a b c rows cols) A = Matrix.det ((Submatrix27 A m a b c).submatrix rows cols) := by | |
| -- The determinant of a matrix is a polynomial function, so evaluating each entry of the matrix and then taking the determinant is the same as taking the determinant of the evaluated matrix. | |
| have h_det_poly : ∀ (M : Matrix (Fin 4) (Fin 4) (MvPolynomial (AIndex n) ℝ)), evalCameraPolynomial (Matrix.det M) A = Matrix.det (fun i j => evalCameraPolynomial (M i j) A) := by | |
| simp +decide [ Matrix.det_apply' ]; | |
| simp +decide [ Arxiv.«2602.05192».evalCameraPolynomial, Finset.prod_mul_distrib ]; | |
| convert h_det_poly _ using 2; | |
| ext i j; exact eval_poly_Submatrix27_entry A m a b c ( rows i ) ( cols j ) ▸ rfl; | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma eval_poly_sum_sq_G3_block_ne_zero {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) (a b c : Fin n) : | |
| evalCameraPolynomial (poly_sum_sq_G3_block n m a b c) A ≠ 0 → (Submatrix27 A m a b c).rank ≥ 4 := by | |
| intro h_nonzero | |
| obtain ⟨rows, cols, h_det⟩ : ∃ rows : Fin 4 → RowIdx n, ∃ cols : Fin 4 → Triple3, Matrix.det ((Submatrix27 A m a b c).submatrix rows cols) ≠ 0 := by | |
| contrapose! h_nonzero; | |
| simp +decide [ Arxiv.«2602.05192».poly_sum_sq_G3_block, h_nonzero ]; | |
| simp +decide [ Arxiv.«2602.05192».evalCameraPolynomial, Arxiv.«2602.05192».poly_G3_minor, h_nonzero ]; | |
| convert Finset.sum_eq_zero fun x hx => Finset.sum_eq_zero fun y hy => ?_; | |
| convert congr_arg ( · ^ 2 ) ( h_nonzero x y ) using 1; | |
| · congr! 1; | |
| convert eval_poly_G3_minor A m a b c x y using 1; | |
| · grind; | |
| have h_submatrix : Matrix.rank ((Submatrix27 A m a b c).submatrix rows cols) = 4 := by | |
| have := Matrix.rank_mul_le ( ( Submatrix27 A m a b c ).submatrix rows cols ) ( ( Submatrix27 A m a b c ).submatrix rows cols ) ⁻¹; simp_all +decide [ isUnit_iff_ne_zero ] ; | |
| exact le_antisymm ( le_trans ( Matrix.rank_le_card_width _ ) ( by norm_num ) ) this.1; | |
| refine' h_submatrix ▸ _; | |
| have h_submatrix : ∀ (M : Matrix (RowIdx n) Triple3 ℝ), ∀ (rows : Fin 4 → RowIdx n) (cols : Fin 4 → Triple3), Matrix.rank (M.submatrix rows cols) ≤ Matrix.rank M := by | |
| intros M rows cols | |
| have h_submatrix : ∃ (P : Matrix (Fin 4) (RowIdx n) ℝ) (Q : Matrix (Triple3) (Fin 4) ℝ), M.submatrix rows cols = P * M * Q := by | |
| use Matrix.of (fun i j => if j = rows i then 1 else 0), Matrix.of (fun i j => if i = cols j then 1 else 0); | |
| ext i j; simp +decide [ Matrix.mul_apply ] ; | |
| obtain ⟨ P, Q, hPQ ⟩ := h_submatrix; rw [ hPQ ] ; exact Matrix.rank_mul_le_left _ _ |> le_trans <| Matrix.rank_mul_le_right _ _; | |
| exact h_submatrix _ _ _ | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma G3_of_rank_ge_4 {n : ℕ} (A : Fin n → Matrix3x4) (m : Fin 4) (a b c : Fin n) : | |
| (StackedMat A).rank = 4 → (Submatrix27 A m a b c).rank ≥ 4 → | |
| ColSpan (Submatrix27 A m a b c) = Wspace A := by | |
| intro h1 h2; | |
| refine' Submodule.eq_of_le_of_finrank_eq _ _; | |
| · intro x hx | |
| have h_submatrix : ∀ p : Triple3, (Submatrix27 A m a b c).col p ∈ ColSpan (StackedMat A) := by | |
| intro p | |
| have h_submatrix : (Submatrix27 A m a b c).col p ∈ ColSpan (Unfold m (constructQ A)) := by | |
| exact Submodule.subset_span ⟨ colIdxOfTriple a b c p, rfl ⟩; | |
| have h_submatrix : ∀ x : ColIdx n, (Unfold m (constructQ A)).col x ∈ ColSpan (StackedMat A) := by | |
| intro x | |
| have h_submatrix : (Unfold m (constructQ A)).col x ∈ ColSpan (StackedMat A * cofactorMat A m) := by | |
| rw [unfold_constructQ_eq_mul]; | |
| exact Submodule.subset_span ( Set.mem_range_self x ); | |
| refine' Submodule.span_le.mpr _ h_submatrix; | |
| rintro _ ⟨ y, rfl ⟩; | |
| simp +decide [ Matrix.mul_apply, ColSpan ]; | |
| rw [ Submodule.mem_span_range_iff_exists_fun ]; | |
| use fun i => (cofactorMat A m) i y; | |
| ext i; simp +decide [ Matrix.mul_apply, dotProduct ] ; | |
| ac_rfl; | |
| convert Submodule.span_le.mpr _ ‹_›; | |
| exact Set.range_subset_iff.mpr h_submatrix; | |
| have h_submatrix : ∀ x ∈ ColSpan (Submatrix27 A m a b c), x ∈ ColSpan (StackedMat A) := by | |
| intro x hx | |
| induction' hx using Submodule.span_induction with x hx ih; | |
| · grind; | |
| · exact Submodule.zero_mem _; | |
| · exact Submodule.add_mem _ ‹_› ‹_›; | |
| · exact Submodule.smul_mem _ _ ‹_›; | |
| exact h_submatrix x hx | |
| · refine' le_antisymm _ _; | |
| · refine' Submodule.finrank_mono _; | |
| intro x hx; | |
| -- Since the columns of the submatrix are a subset of the columns of the unfolded matrix, and the unfolded matrix is a submatrix of the stacked matrix, the column span of the submatrix is contained within the column span of the stacked matrix. | |
| have h_subset : ColSpan (Submatrix27 A m a b c) ≤ ColSpan (Unfold m (constructQ A)) := by | |
| refine' Submodule.span_le.mpr _; | |
| rintro _ ⟨ t, rfl ⟩; | |
| refine' Submodule.subset_span ⟨ colIdxOfTriple a b c t, rfl ⟩; | |
| have h_subset : ColSpan (Unfold m (constructQ A)) ≤ ColSpan (StackedMat A) := by | |
| have h_subset : Unfold m (constructQ A) = StackedMat A * cofactorMat A m := by | |
| exact unfold_constructQ_eq_mul A m | |
| rw [h_subset]; | |
| unfold ColSpan; | |
| rw [ Submodule.span_le ]; | |
| rintro _ ⟨ i, rfl ⟩; | |
| simp +decide [ Matrix.mul_apply, Submodule.mem_span_range_iff_exists_fun ]; | |
| use fun j => cofactorMat A m j i; | |
| ext j; simp +decide [ Matrix.mul_apply, dotProduct ] ; | |
| ac_rfl; | |
| exact h_subset <| by solve_by_elim; | |
| · convert h1.le.trans h2 using 1; | |
| · -- The rank of a matrix is equal to the finrank of its column space. | |
| have h_rank_eq_finrank : ∀ (M : Matrix (RowIdx n) (Fin 4) ℝ), Matrix.rank M = Module.finrank ℝ (ColSpan M) := by | |
| intro M; exact (by | |
| convert Matrix.rank_eq_finrank_span_cols M using 1); | |
| exact h_rank_eq_finrank _ ▸ rfl; | |
| · convert rfl; | |
| convert Matrix.rank_eq_finrank_span_cols _ | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma eval_strong_genericity_poly_ne_zero_imp_generic {n : ℕ} (_hn : 5 ≤ n) (A : Fin n → Matrix3x4) : | |
| evalCameraPolynomial (strong_genericity_poly n) A ≠ 0 → GenericCameras A := by | |
| intro h_nonzero; | |
| refine' ⟨ _, _, _ ⟩; | |
| · unfold Arxiv.«2602.05192».strong_genericity_poly at h_nonzero; | |
| unfold Arxiv.«2602.05192».total_genericity_poly at h_nonzero; simp_all +decide [ Arxiv.«2602.05192».evalCameraPolynomial ] ; | |
| exact Arxiv.«2602.05192».eval_poly_sum_sq_stacked_ne_zero A h_nonzero.1.1; | |
| · intro α | |
| have h_eval_poly_sum_sq_cam_ne_zero : evalCameraPolynomial (poly_sum_sq_cam n α) A ≠ 0 := by | |
| unfold Arxiv.«2602.05192».strong_genericity_poly at h_nonzero; simp_all +decide [ Finset.prod_eq_zero_iff ] ; | |
| contrapose! h_nonzero; simp_all +decide [ Arxiv.«2602.05192».total_genericity_poly ] ; | |
| simp_all +decide [ Finset.prod_eq_mul_prod_diff_singleton ( Finset.mem_univ α ), Arxiv.«2602.05192».evalCameraPolynomial ] | |
| exact (eval_poly_sum_sq_cam_ne_zero A α h_eval_poly_sum_sq_cam_ne_zero); | |
| · intro m a b c h_nonall | |
| have h_eval_G3 : evalCameraPolynomial (poly_sum_sq_G3_block n m a b c) A ≠ 0 := by | |
| rw [ Arxiv.«2602.05192».strong_genericity_poly ] at h_nonzero; | |
| contrapose! h_nonzero; simp_all +decide [ Arxiv.«2602.05192».poly_G3_total ] ; | |
| simp +decide [ h_nonzero, Finset.prod_ite ]; | |
| simp +decide [ h_nonzero, Finset.prod_eq_zero_iff, Arxiv.«2602.05192».evalCameraPolynomial ]; | |
| exact Or.inr ⟨ m, a, b, c, h_nonall, h_nonzero ⟩; | |
| have h_eval_stacked : evalCameraPolynomial (poly_sum_sq_stacked n) A ≠ 0 := by | |
| contrapose! h_nonzero; | |
| unfold Arxiv.«2602.05192».strong_genericity_poly; | |
| unfold Arxiv.«2602.05192».total_genericity_poly; simp_all +decide [ Arxiv.«2602.05192».evalCameraPolynomial ] ; | |
| apply G3_of_rank_ge_4 A m a b c (by | |
| exact eval_poly_sum_sq_stacked_ne_zero A h_eval_stacked) (by | |
| exact eval_poly_sum_sq_G3_block_ne_zero A m a b c h_eval_G3) | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| def witnessCols {n : ℕ} (_a b c : Fin n) : Fin 4 → Triple3 := | |
| fun k => | |
| if b ≠ c then | |
| match k with | |
| | 0 => (1, 2, 2) | |
| | 1 => (0, 2, 2) | |
| | 2 => (0, 1, 2) | |
| | _ => (0, 2, 1) | |
| else | |
| match k with | |
| | 0 => (2, 1, 2) | |
| | 1 => (2, 0, 2) | |
| | 2 => (2, 1, 0) | |
| | _ => (0, 1, 2) | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| def witnessCofactorMatrix (n : ℕ) (m : Fin 4) (a b c : Fin n) : Matrix (Fin 4) (Fin 4) ℝ := | |
| fun i j => (cofactorMat (witnessA n) m) i (colIdxOfTriple a b c (witnessCols a b c j)) | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma witnessCofactorMatrix_det_ne_zero {n : ℕ} (m : Fin 4) (a b c : Fin n) (h : NotAllEqual3 a b c) : | |
| (witnessCofactorMatrix n m a b c).det ≠ 0 := by | |
| fin_cases m | |
| · by_cases hbc : b = c | |
| · | |
| simp_all +decide [ NotAllEqual3 ]; | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix; | |
| unfold Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».witnessCols; simp +decide [ Matrix.det_succ_row_zero, Fin.sum_univ_succ, Fin.prod_univ_succ ] ; | |
| unfold Arxiv.«2602.05192».cofactorMat Arxiv.«2602.05192».witnessA; simp +decide [ Matrix.det_succ_row_zero, Fin.sum_univ_succ, Fin.prod_univ_succ ] ; | |
| unfold Arxiv.«2602.05192».fixedRowsMat; simp +decide [ Fin.sum_univ_succ, Fin.prod_univ_succ, Fin.succAbove ] ; ring_nf ; | |
| exact ⟨ by intro H; exact h ( Fin.ext <| by exact Nat.cast_injective ( by linarith : ( a : ℝ ) = c ) ), by intro H; exact h ( Fin.ext <| by exact Nat.cast_injective ( by linarith : ( a : ℝ ) = c ) ), by intro H; exact h ( Fin.ext <| by exact Nat.cast_injective ( by linarith : ( a : ℝ ) = c ) ) ⟩ | |
| · | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix Arxiv.«2602.05192».witnessA Arxiv.«2602.05192».cofactorMat; | |
| unfold Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».witnessCols Arxiv.«2602.05192».fixedRowsMat; simp +decide [ Matrix.det_succ_row_zero ] ; | |
| simp +decide [ Fin.sum_univ_succ, Fin.succAbove, hbc ]; | |
| exact ⟨ by rw [ add_eq_zero_iff_eq_neg ] ; exact fun h => hbc <| Fin.ext <| by aesop, by rw [ add_eq_zero_iff_eq_neg ] ; exact fun h => hbc <| Fin.ext <| by aesop ⟩ | |
| · by_cases hbc : b = c | |
| · | |
| -- Since $b = c$, we can simplify the cofactor matrix entries. | |
| simp [hbc, Arxiv.«2602.05192».witnessCofactorMatrix, Arxiv.«2602.05192».cofactorMat]; | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix; simp +decide [ Arxiv.«2602.05192».cofactorMat ] ; | |
| simp +decide [ Matrix.det_succ_row_zero, Arxiv.«2602.05192».witnessA ] ; | |
| unfold Arxiv.«2602.05192».fixedRowsMat Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».witnessCols; simp +decide [ Arxiv.«2602.05192».witnessA ] ; | |
| simp +decide [ Fin.sum_univ_succ, Fin.succAbove ] at * ; | |
| exact fun h' => h <| by rw [ neg_add_eq_zero ] at h'; aesop; | |
| · | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix Arxiv.«2602.05192».cofactorMat; | |
| simp +decide [ Matrix.det_succ_row_zero, Fin.sum_univ_succ ]; | |
| simp +decide [ Fin.succAbove, Arxiv.«2602.05192».fixedRowsMat, Arxiv.«2602.05192».witnessA ] at *; | |
| unfold Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».witnessCols; simp +decide [ Fin.ext_iff ] ; | |
| split_ifs <;> simp_all +decide [ Fin.forall_fin_succ, Matrix.vecHead, Matrix.vecTail, Matrix.cons_val' ]; | |
| · exact False.elim <| hbc <| Fin.ext ‹_›; | |
| · exact ⟨ by rw [ add_eq_zero_iff_eq_neg ] ; aesop, by rw [ add_eq_zero_iff_eq_neg ] ; aesop ⟩ | |
| · by_cases hbc : b = c | |
| · | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix; | |
| unfold Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».witnessCols; simp +decide [ Matrix.det_succ_row_zero ] ; | |
| simp +decide [ Fin.sum_univ_succ, Fin.prod_univ_succ, Arxiv.«2602.05192».cofactorMat, Arxiv.«2602.05192».witnessA ]; | |
| simp +decide [ Arxiv.«2602.05192».fixedRowsMat, Arxiv.«2602.05192».witnessA ]; | |
| simp +decide [ Matrix.det_fin_three, Matrix.submatrix ] at *; | |
| simp +decide [ Fin.succAbove ] at *; | |
| simp +decide [ hbc ] at *; | |
| exact ⟨ by rw [ neg_add_eq_sub, sub_eq_zero ] ; exact fun h' => h <| by aesop, by rw [ add_eq_zero_iff_eq_neg ] ; exact fun h' => h <| by aesop ⟩ | |
| · | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix; | |
| unfold Arxiv.«2602.05192».cofactorMat Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».witnessCols; simp +decide [ Fin.sum_univ_succ, Matrix.det_succ_row_zero ] ; | |
| simp +decide [ Fin.succAbove, Arxiv.«2602.05192».fixedRowsMat, Arxiv.«2602.05192».witnessA ]; | |
| split_ifs ; norm_num [ Fin.ext_iff, Matrix.vecHead, Matrix.vecTail ] at * ; ring_nf at * ; simp_all +decide [ Fin.ext_iff, Matrix.vecHead, Matrix.vecTail ] ; | |
| exact ⟨ sub_ne_zero_of_ne <| by aesop, by rw [ neg_add_eq_sub ] ; exact sub_ne_zero_of_ne <| by aesop, sub_ne_zero_of_ne <| by aesop ⟩ | |
| · by_cases hbc : b = c | |
| · | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix; | |
| unfold Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».witnessCols Arxiv.«2602.05192».cofactorMat; | |
| simp +decide [ Matrix.det_succ_row_zero, Matrix.submatrix ]; | |
| simp +decide [ Fin.sum_univ_succ, Fin.succAbove ]; | |
| simp +decide [ *, Arxiv.«2602.05192».fixedRowsMat, Arxiv.«2602.05192».witnessA ] at *; | |
| exact fun h' => h <| by rw [ neg_add_eq_zero ] at h'; aesop; | |
| · | |
| unfold Arxiv.«2602.05192».witnessCofactorMatrix; | |
| unfold Arxiv.«2602.05192».witnessCols Arxiv.«2602.05192».colIdxOfTriple Arxiv.«2602.05192».cofactorMat Arxiv.«2602.05192».witnessA ; norm_num [ Fin.sum_univ_succ, Fin.prod_univ_succ ]; | |
| simp +decide [ hbc, Matrix.det_succ_column_zero ]; | |
| simp +decide [ Fin.sum_univ_succ, Fin.prod_univ_succ, Arxiv.«2602.05192».fixedRowsMat ]; | |
| simp +decide [ Fin.succAbove ] at *; | |
| exact ⟨ by rw [ add_eq_zero_iff_eq_neg ] ; exact fun h => hbc <| Fin.ext <| by rw [ ← @Nat.cast_inj ℝ ] ; linarith, by rw [ add_eq_zero_iff_eq_neg ] ; exact fun h => hbc <| Fin.ext <| by rw [ ← @Nat.cast_inj ℝ ] ; linarith ⟩ | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma witnessSubmatrix_eq {n : ℕ} (m : Fin 4) (a b c : Fin n) : | |
| (Submatrix27 (witnessA n) m a b c).submatrix id (witnessCols a b c) = | |
| StackedMat (witnessA n) * witnessCofactorMatrix n m a b c := by | |
| unfold Submatrix27 Arxiv.«2602.05192».StackedMat Arxiv.«2602.05192».witnessCofactorMatrix; | |
| ext ⟨ α, i ⟩ j; simp +decide [ Arxiv.«2602.05192».Unfold, Arxiv.«2602.05192».constructQ ] ; | |
| fin_cases m <;> simp +decide [ Matrix.mul_apply, Arxiv.«2602.05192».stackedRowsMatrix, Arxiv.«2602.05192».constructQ ]; | |
| · rw [ Matrix.det_succ_row_zero ] ; norm_num [ Fin.sum_univ_succ ] ; ring_nf!; | |
| unfold Arxiv.«2602.05192».cofactorMat; simp +decide [ Matrix.det_succ_row_zero ] ; ring!; | |
| · simp +decide [ Matrix.det_succ_row_zero, Arxiv.«2602.05192».cofactorMat ]; | |
| simp +decide [ Fin.sum_univ_succ, Arxiv.«2602.05192».fixedRowsMat, Arxiv.«2602.05192».witnessA ] ; ring!; | |
| · rw [ Matrix.det_succ_row _ 2 ] ; simp +decide [ Fin.sum_univ_succ, Matrix.det_succ_row _ 2 ] ; | |
| unfold Arxiv.«2602.05192».cofactorMat; simp +decide [ Matrix.det_succ_row _ 2 ] ; | |
| unfold Arxiv.«2602.05192».fixedRowsMat; simp +decide [ Fin.sum_univ_succ, Matrix.det_succ_row _ 2 ] ; | |
| simp +decide [ Fin.succAbove, Arxiv.«2602.05192».witnessA ] at *; | |
| · rw [ Matrix.det_succ_row _ 3 ] ; simp +decide [ Fin.sum_univ_succ, Arxiv.«2602.05192».cofactorMat ]; | |
| unfold Arxiv.«2602.05192».fixedRowsMat; simp +decide [ Matrix.det_succ_row _ 3 ] ; | |
| exact rfl | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma witnessA_G3_rank {n : ℕ} (hn : 5 ≤ n) (m : Fin 4) (a b c : Fin n) (h : NotAllEqual3 a b c) : | |
| (Submatrix27 (witnessA n) m a b c).rank ≥ 4 := by | |
| -- By `witnessCofactorMatrix_det_ne_zero`, `det(C) \ne 0`, so `C` is invertible. | |
| have h_C_inv : Matrix.det (witnessCofactorMatrix n m a b c) ≠ 0 := by | |
| exact witnessCofactorMatrix_det_ne_zero m a b c h; | |
| -- Since `S' = StackedMat (witnessA n) * C`, and `C` is invertible, we have `rank(S') = rank(StackedMat (witnessA n))`. | |
| have h_rank_S' : Matrix.rank (Submatrix27 (witnessA n) m a b c |>.submatrix id (witnessCols a b c)) = Matrix.rank (StackedMat (witnessA n)) := by | |
| have h_S'_eq : (Submatrix27 (witnessA n) m a b c).submatrix id (witnessCols a b c) = (StackedMat (witnessA n)) * (witnessCofactorMatrix n m a b c) := by | |
| exact witnessSubmatrix_eq m a b c; | |
| have := Matrix.rank_mul_le ( StackedMat ( witnessA n ) ) ( witnessCofactorMatrix n m a b c ) ; aesop; | |
| have h_rank_S : Matrix.rank (StackedMat (witnessA n)) = 4 := by | |
| convert ( witnessA_properties hn ) |>.1; | |
| refine' h_rank_S ▸ h_rank_S'.symm ▸ _; | |
| -- Since the submatrix is a subset of the original matrix, its rank is less than or equal to the rank of the original matrix. | |
| have h_submatrix_rank : ∀ (M : Matrix (RowIdx n) (Triple3) ℝ) (cols : Fin 4 → Triple3), Matrix.rank (M.submatrix id cols) ≤ Matrix.rank M := by | |
| intro M cols; exact (by | |
| have h_submatrix_rank : ∀ (M : Matrix (RowIdx n) (Triple3) ℝ) (cols : Fin 4 → Triple3), Matrix.rank (M.submatrix id cols) ≤ Matrix.rank M := by | |
| intro M cols | |
| have h_submatrix : ∃ (P : Matrix (RowIdx n) (RowIdx n) ℝ) (Q : Matrix (Triple3) (Fin 4) ℝ), M.submatrix id cols = P * M * Q := by | |
| use 1, Matrix.of (fun i j => if i = cols j then 1 else 0); | |
| ext i j; simp +decide [ Matrix.mul_apply ] ; | |
| obtain ⟨ P, Q, hPQ ⟩ := h_submatrix; rw [ hPQ ] ; exact Matrix.rank_mul_le_left _ _ |> le_trans <| Matrix.rank_mul_le_right _ _; | |
| exact h_submatrix_rank M cols); | |
| exact h_submatrix_rank _ _ | |
| open scoped BigOperators | |
| open Classical Matrix | |
| open Arxiv.«2602.05192» | |
| lemma poly_sum_sq_G3_block_ne_zero_poly {n : ℕ} (hn : 5 ≤ n) (m : Fin 4) (a b c : Fin n) (h : NotAllEqual3 a b c) : | |
| poly_sum_sq_G3_block n m a b c ≠ 0 := by | |
| intro h_zero | |
| have h_eval_zero : evalCameraPolynomial (poly_sum_sq_G3_block n m a b c) (witnessA n) = 0 := by | |
| rw [h_zero] | |
| simp [evalCameraPolynomial] | |
| unfold poly_sum_sq_G3_block at h_eval_zero | |
| simp only [evalCameraPolynomial, map_sum, map_pow] at h_eval_zero | |
| have h_rank : (Submatrix27 (witnessA n) m a b c).rank ≥ 4 := witnessA_G3_rank hn m a b c h | |
| obtain ⟨rows, cols, h_det_ne_zero⟩ := exists_submatrix_det_ne_zero_of_rank_ge (Submatrix27 (witnessA n) m a b c) 4 h_rank | |
| have h_term_zero : (evalCameraPolynomial (poly_G3_minor n m a b c rows cols) (witnessA n))^2 = 0 := by | |
| rw [Finset.sum_eq_zero_iff_of_nonneg] at h_eval_zero | |
| · have h_inner := h_eval_zero rows (Finset.mem_univ rows) | |
| rw [Finset.sum_eq_zero_iff_of_nonneg] at h_inner | |
| · exact h_inner cols (Finset.mem_univ cols) | |
| · intro _ _; apply sq_nonneg | |
| · intro _ _; apply Finset.sum_nonneg; intro _ _; apply sq_nonneg | |
| rw [eval_poly_G3_minor] at h_term_zero | |
| simp at h_term_zero | |
| contradiction | |
| end AristotleLemmas | |
| theorem strong_genericity_polynomial_exists (n : ℕ) (hn : 5 ≤ n) : | |
| StrongGenericityPolynomialExists n := by | |
| have hG3 : ∀ m : Fin 4, ∀ a b c : Fin n, NotAllEqual3 a b c → poly_sum_sq_G3_block n m a b c ≠ 0 := by | |
| exact fun m a b c h => poly_sum_sq_G3_block_ne_zero_poly hn m a b c h | |
| exact ⟨ _, mul_ne_zero ( total_genericity_poly_ne_zero hn ) ( Finset.prod_ne_zero_iff.mpr fun m hm => Finset.prod_ne_zero_iff.mpr fun a ha => Finset.prod_ne_zero_iff.mpr fun b hb => Finset.prod_ne_zero_iff.mpr fun c hc => by aesop ), fun A hA => eval_strong_genericity_poly_ne_zero_imp_generic hn A hA ⟩ | |
| theorem nine_of_hStrong | |
| (hStrong : ∀ n : ℕ, 5 ≤ n → StrongGenericityPolynomialExists n) : | |
| ∃ (d : ℕ), | |
| ∀ n : ℕ, 5 ≤ n → | |
| ∃ (N : ℕ) (F : PolyMap n N), | |
| PolyMap.UniformDegreeBound d F ∧ | |
| ∃ (G : MvPolynomial (AIndex n) ℝ), G ≠ 0 ∧ | |
| ∀ (A : Fin n → Matrix3x4), | |
| evalCameraPolynomial G A ≠ 0 → | |
| ∀ (lam : Lambda n), | |
| (∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) → | |
| (IsZeroVec (PolyMap.eval F (scaleQ lam (constructQ A))) ↔ | |
| (∃ (u v w x : Fin n → ℝˣ), | |
| ∀ α β γ δ, NotIdentical α β γ δ → | |
| lam α β γ δ = | |
| (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ))) := by | |
| refine ⟨5, ?_⟩ | |
| intro n hn | |
| refine ⟨numMinors n, polyMapF n, polyMapF_degree_bound n, ?_⟩ | |
| rcases hStrong n hn with ⟨G, hGne, hGgen⟩ | |
| refine ⟨G, hGne, ?_⟩ | |
| intro A hGA lam hsupp | |
| have hgen : GenericCameras A := hGgen A hGA | |
| constructor | |
| · intro hvanish | |
| exact reverse_direction hn A hgen lam hsupp hvanish | |
| · rintro ⟨u, v, w, x, hfact⟩ | |
| exact forward_direction A lam hsupp u v w x hfact | |
| -- (natural numbers start at zero) | |
| theorem nine : | |
| -- there's a natural number d | |
| ∃ (d : ℕ), | |
| -- such that for all natural numbers n ≥ 5 | |
| ∀ n : ℕ, 5 ≤ n → | |
| -- there's a natural number N and a collection of N polynomials F_0, F_1, ... F_{N-1} with real coefficients | |
| -- and in 81n^4 variables X_{(α,β,γ,δ,i,j,k,l)} indexed by octuples `(α,β,γ,δ,i,j,k,l)` | |
| -- with `0 ≤ α, β, γ, δ < n` and `0 ≤ i,j,k,l ≤ 2`, such that | |
| ∃ (N : ℕ) (F : PolyMap n N), | |
| -- each of the F_i has total degree at most d, and | |
| PolyMap.UniformDegreeBound d F ∧ | |
| -- there exists a nonzero multivariable polynomial `G` in 12n variables, such that | |
| ∃ (G : MvPolynomial (AIndex n) ℝ), G ≠ 0 ∧ | |
| -- for all collections A_0, A_1, ..., A_{n-1} of 3x4 matrices with real coefficients, | |
| ∀ (A : Fin n → Matrix3x4), | |
| -- such that G(A_0,A_1,..,A_{n-1}) isn't 0 (NB this is our definition of-Zariski generic), | |
| evalCameraPolynomial G A ≠ 0 → | |
| -- and for all functions λ : {0,1,2,...,n-1}^4 → ℝ | |
| ∀ (lam : Lambda n), | |
| -- having the property that for all 0 ≤ α, β, γ, δ < n, λ(α,β,γ,δ) = 0 ↔ α=β=γ=δ, (stated in a contrapositive way) | |
| (∀ α β γ δ, (lam α β γ δ ≠ 0) ↔ NotIdentical α β γ δ) → | |
| -- then the following two things are equivalent: | |
| -- (i) For all `0 ≤ t < N`, evaluating `F_t` with the variable `X_{(α,β,γ,δ,i,j,k,l)}` | |
| -- sent to the real number `λ(α,β,γ,δ)*det(4x4 matrix with first row i'th row of A_α,` | |
| -- `2nd row is the j'th row of A_β, third row is the k'th row of A_γ and 4th row is the l'th row of A_δ)`, is zero; and | |
| (IsZeroVec (PolyMap.eval F (scaleQ lam (constructQ A))) ↔ | |
| -- (ii) There exist four families `u_t,v_t,w_t,x_t` of nonzero real numbers, `0 ≤ t < n`, such that | |
| (∃ (u v w x : Fin n → ℝˣ), | |
| -- for all `0 ≤ α, β, γ, δ < n` which are not all equal, | |
| ∀ α β γ δ, NotIdentical α β γ δ → | |
| -- the corresponding nonzero real number `λ(α,β,γ,δ)` equals `u_α*v_β*w_γ*x_δ` | |
| lam α β γ δ = | |
| (u α : ℝ) * (v β : ℝ) * (w γ : ℝ) * (x δ : ℝ))) := by | |
| exact nine_of_hStrong (fun n hn => strong_genericity_polynomial_exists n hn) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment