l3lab/ntp-mathlib huggingface dataset:
/-- Any matrix can be reduced to diagonal form by elementary operations. Formulated here on `Type 0`
because we will make an induction using `Fin r`.
See `exists_list_transvec_mul_mul_list_transvec_eq_diagonal` for the general version (which follows
from this one and reindexing). -/
theorem exists_list_transvec_mul_mul_list_transvec_eq_diagonal_aux (n : Type) [Fintype n]
    [DecidableEq n] (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      (L.map toMatrix).prod * M * (L'.map toMatrix).prod = diagonal D := by
  induction' hn : Fintype.card n with r IH generalizing n M
  · refine' ⟨List.nil, List.nil, fun _ => 1, _⟩
    ext i j
    rw [Fintype.card_eq_zero_iff] at hn
    exact hn.elim' i
  · have e : n ≃ Sum (Fin r) Unit := by
      refine' Fintype.equivOfCardEq _
      rw [hn]
      rw [@Fintype.card_sum (Fin r) Unit _ _]
      simp
    apply reindex_exists_list_transvec_mul_mul_list_transvec_eq_diagonal M e
    apply
      exists_list_transvec_mul_mul_list_transvec_eq_diagonal_induction fun N =>
        IH (Fin r) N (by 

Proof state:
n✝ : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁷ : Field 𝕜
inst✝⁶ : DecidableEq n✝
inst✝⁵ : DecidableEq p
inst✝⁴ : CommRing R
r✝ : ℕ
M✝ : Matrix (Fin r✝ ⊕ Unit) (Fin r✝ ⊕ Unit) 𝕜
inst✝³ : Fintype n✝
inst✝² : Fintype p
r : ℕ
IH :
  ∀ (n : Type) [inst : Fintype n] [inst_1 : DecidableEq n] (M : Matrix n n 𝕜),
    Fintype.card n = r → ∃ L L' D, List.prod (List.map toMatrix L) * M * List.prod (List.map toMatrix L') = diagonal D
n : Type
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n 𝕜
hn : Fintype.card n = Nat.succ r
e : n ≃ Fin r ⊕ Unit
N : Matrix (Fin r) (Fin r) 𝕜
⊢ Fintype.card (Fin r) = r

Next tactic:
simp
/-- Any matrix can be reduced to diagonal form by elementary operations. -/
theorem exists_list_transvec_mul_mul_list_transvec_eq_diagonal (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      (L.map toMatrix).prod * M * (L'.map toMatrix).prod = diagonal D := by
  

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
⊢ ∃ L L' D, List.prod (List.map toMatrix L) * M * List.prod (List.map toMatrix L') = diagonal D

Next tactic:
have e : n ≃ Fin (Fintype.card n) := Fintype.equivOfCardEq (by simp)
/-- Any matrix can be reduced to diagonal form by elementary operations. -/
theorem exists_list_transvec_mul_mul_list_transvec_eq_diagonal (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      (L.map toMatrix).prod * M * (L'.map toMatrix).prod = diagonal D := by
  have e : n ≃ Fin (Fintype.card n) := Fintype.equivOfCardEq (by 

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
⊢ Fintype.card n = Fintype.card (Fin (Fintype.card n))

Next tactic:
simp
/-- Any matrix can be reduced to diagonal form by elementary operations. -/
theorem exists_list_transvec_mul_mul_list_transvec_eq_diagonal (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      (L.map toMatrix).prod * M * (L'.map toMatrix).prod = diagonal D := by
  have e : n ≃ Fin (Fintype.card n) := Fintype.equivOfCardEq (by simp)
  

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
e : n ≃ Fin (Fintype.card n)
⊢ ∃ L L' D, List.prod (List.map toMatrix L) * M * List.prod (List.map toMatrix L') = diagonal D

Next tactic:
apply reindex_exists_list_transvec_mul_mul_list_transvec_eq_diagonal M e
/-- Any matrix can be reduced to diagonal form by elementary operations. -/
theorem exists_list_transvec_mul_mul_list_transvec_eq_diagonal (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      (L.map toMatrix).prod * M * (L'.map toMatrix).prod = diagonal D := by
  have e : n ≃ Fin (Fintype.card n) := Fintype.equivOfCardEq (by simp)
  apply reindex_exists_list_transvec_mul_mul_list_transvec_eq_diagonal M e
  

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
e : n ≃ Fin (Fintype.card n)
⊢ ∃ L L' D, List.prod (List.map toMatrix L) * (reindexAlgEquiv 𝕜 e) M * List.prod (List.map toMatrix L') = diagonal D

Next tactic:
apply exists_list_transvec_mul_mul_list_transvec_eq_diagonal_aux
/-- Any matrix can be written as the product of transvections, a diagonal matrix, and
transvections.-/
theorem exists_list_transvec_mul_diagonal_mul_list_transvec (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      M = (L.map toMatrix).prod * diagonal D * (L'.map toMatrix).prod := by
  

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
⊢ ∃ L L' D, M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')

Next tactic:
rcases exists_list_transvec_mul_mul_list_transvec_eq_diagonal M with ⟨L, L', D, h⟩
/-- Any matrix can be written as the product of transvections, a diagonal matrix, and
transvections.-/
theorem exists_list_transvec_mul_diagonal_mul_list_transvec (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      M = (L.map toMatrix).prod * diagonal D * (L'.map toMatrix).prod := by
  rcases exists_list_transvec_mul_mul_list_transvec_eq_diagonal M with ⟨L, L', D, h⟩
  

Proof state:
case intro.intro.intro
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : List.prod (List.map toMatrix L) * M * List.prod (List.map toMatrix L') = diagonal D
⊢ ∃ L L' D, M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')

Next tactic:
refine' ⟨L.reverse.map TransvectionStruct.inv, L'.reverse.map TransvectionStruct.inv, D, _⟩
/-- Any matrix can be written as the product of transvections, a diagonal matrix, and
transvections.-/
theorem exists_list_transvec_mul_diagonal_mul_list_transvec (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      M = (L.map toMatrix).prod * diagonal D * (L'.map toMatrix).prod := by
  rcases exists_list_transvec_mul_mul_list_transvec_eq_diagonal M with ⟨L, L', D, h⟩
  refine' ⟨L.reverse.map TransvectionStruct.inv, L'.reverse.map TransvectionStruct.inv, D, _⟩
  

Proof state:
case intro.intro.intro
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : List.prod (List.map toMatrix L) * M * List.prod (List.map toMatrix L') = diagonal D
⊢ M =
    List.prod (List.map toMatrix (List.map TransvectionStruct.inv (List.reverse L))) * diagonal D *
      List.prod (List.map toMatrix (List.map TransvectionStruct.inv (List.reverse L')))

Next tactic:
suffices
    M =
      (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod * M *
        ((L'.map toMatrix).prod * (L'.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod)
    by simpa [← h, Matrix.mul_assoc]
/-- Any matrix can be written as the product of transvections, a diagonal matrix, and
transvections.-/
theorem exists_list_transvec_mul_diagonal_mul_list_transvec (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      M = (L.map toMatrix).prod * diagonal D * (L'.map toMatrix).prod := by
  rcases exists_list_transvec_mul_mul_list_transvec_eq_diagonal M with ⟨L, L', D, h⟩
  refine' ⟨L.reverse.map TransvectionStruct.inv, L'.reverse.map TransvectionStruct.inv, D, _⟩
  suffices
    M =
      (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod * M *
        ((L'.map toMatrix).prod * (L'.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod)
    by 

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : List.prod (List.map toMatrix L) * M * List.prod (List.map toMatrix L') = diagonal D
this :
  M =
    List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) * List.prod (List.map toMatrix L) * M *
      (List.prod (List.map toMatrix L') * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L')))
⊢ M =
    List.prod (List.map toMatrix (List.map TransvectionStruct.inv (List.reverse L))) * diagonal D *
      List.prod (List.map toMatrix (List.map TransvectionStruct.inv (List.reverse L')))

Next tactic:
simpa [← h, Matrix.mul_assoc]
/-- Any matrix can be written as the product of transvections, a diagonal matrix, and
transvections.-/
theorem exists_list_transvec_mul_diagonal_mul_list_transvec (M : Matrix n n 𝕜) :
    ∃ (L L' : List (TransvectionStruct n 𝕜)) (D : n → 𝕜),
      M = (L.map toMatrix).prod * diagonal D * (L'.map toMatrix).prod := by
  rcases exists_list_transvec_mul_mul_list_transvec_eq_diagonal M with ⟨L, L', D, h⟩
  refine' ⟨L.reverse.map TransvectionStruct.inv, L'.reverse.map TransvectionStruct.inv, D, _⟩
  suffices
    M =
      (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod * M *
        ((L'.map toMatrix).prod * (L'.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod)
    by simpa [← h, Matrix.mul_assoc]
  

Proof state:
case intro.intro.intro
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁵ : Field 𝕜
inst✝⁴ : DecidableEq n
inst✝³ : DecidableEq p
inst✝² : CommRing R
r : ℕ
M✝ : Matrix (Fin r ⊕ Unit) (Fin r ⊕ Unit) 𝕜
inst✝¹ : Fintype n
inst✝ : Fintype p
M : Matrix n n 𝕜
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : List.prod (List.map toMatrix L) * M * List.prod (List.map toMatrix L') = diagonal D
⊢ M =
    List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) * List.prod (List.map toMatrix L) * M *
      (List.prod (List.map toMatrix L') * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L')))

Next tactic:
rw [reverse_inv_prod_mul_prod, prod_mul_reverse_inv_prod, Matrix.one_mul, Matrix.mul_one]
/-- Induction principle for matrices based on transvections: if a property is true for all diagonal
matrices, all transvections, and is stable under product, then it is true for all matrices. This is
the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix `M`, it suffices to
assume that the diagonal matrices we consider have the same determinant as `M`. This is useful to
obtain similar principles for `SLₙ` or `GLₙ`. -/
theorem diagonal_transvection_induction (P : Matrix n n 𝕜 → Prop) (M : Matrix n n 𝕜)
    (hdiag : ∀ D : n → 𝕜, det (diagonal D) = det M → P (diagonal D))
    (htransvec : ∀ t : TransvectionStruct n 𝕜, P t.toMatrix) (hmul : ∀ A B, P A → P B → P (A * B)) :
    P M := by
  

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁴ : Field 𝕜
inst✝³ : DecidableEq n
inst✝² : DecidableEq p
inst✝¹ : CommRing R
inst✝ : Fintype n
P : Matrix n n 𝕜 → Prop
M : Matrix n n 𝕜
hdiag : ∀ (D : n → 𝕜), det (diagonal D) = det M → P (diagonal D)
htransvec : ∀ (t : TransvectionStruct n 𝕜), P (toMatrix t)
hmul : ∀ (A B : Matrix n n 𝕜), P A → P B → P (A * B)
⊢ P M

Next tactic:
rcases exists_list_transvec_mul_diagonal_mul_list_transvec M with ⟨L, L', D, h⟩
/-- Induction principle for matrices based on transvections: if a property is true for all diagonal
matrices, all transvections, and is stable under product, then it is true for all matrices. This is
the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix `M`, it suffices to
assume that the diagonal matrices we consider have the same determinant as `M`. This is useful to
obtain similar principles for `SLₙ` or `GLₙ`. -/
theorem diagonal_transvection_induction (P : Matrix n n 𝕜 → Prop) (M : Matrix n n 𝕜)
    (hdiag : ∀ D : n → 𝕜, det (diagonal D) = det M → P (diagonal D))
    (htransvec : ∀ t : TransvectionStruct n 𝕜, P t.toMatrix) (hmul : ∀ A B, P A → P B → P (A * B)) :
    P M := by
  rcases exists_list_transvec_mul_diagonal_mul_list_transvec M with ⟨L, L', D, h⟩
  

Proof state:
case intro.intro.intro
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁴ : Field 𝕜
inst✝³ : DecidableEq n
inst✝² : DecidableEq p
inst✝¹ : CommRing R
inst✝ : Fintype n
P : Matrix n n 𝕜 → Prop
M : Matrix n n 𝕜
hdiag : ∀ (D : n → 𝕜), det (diagonal D) = det M → P (diagonal D)
htransvec : ∀ (t : TransvectionStruct n 𝕜), P (toMatrix t)
hmul : ∀ (A B : Matrix n n 𝕜), P A → P B → P (A * B)
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')
⊢ P M

Next tactic:
have PD : P (diagonal D) := hdiag D (by simp [h])
/-- Induction principle for matrices based on transvections: if a property is true for all diagonal
matrices, all transvections, and is stable under product, then it is true for all matrices. This is
the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix `M`, it suffices to
assume that the diagonal matrices we consider have the same determinant as `M`. This is useful to
obtain similar principles for `SLₙ` or `GLₙ`. -/
theorem diagonal_transvection_induction (P : Matrix n n 𝕜 → Prop) (M : Matrix n n 𝕜)
    (hdiag : ∀ D : n → 𝕜, det (diagonal D) = det M → P (diagonal D))
    (htransvec : ∀ t : TransvectionStruct n 𝕜, P t.toMatrix) (hmul : ∀ A B, P A → P B → P (A * B)) :
    P M := by
  rcases exists_list_transvec_mul_diagonal_mul_list_transvec M with ⟨L, L', D, h⟩
  have PD : P (diagonal D) := hdiag D (by 

Proof state:
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁴ : Field 𝕜
inst✝³ : DecidableEq n
inst✝² : DecidableEq p
inst✝¹ : CommRing R
inst✝ : Fintype n
P : Matrix n n 𝕜 → Prop
M : Matrix n n 𝕜
hdiag : ∀ (D : n → 𝕜), det (diagonal D) = det M → P (diagonal D)
htransvec : ∀ (t : TransvectionStruct n 𝕜), P (toMatrix t)
hmul : ∀ (A B : Matrix n n 𝕜), P A → P B → P (A * B)
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')
⊢ det (diagonal D) = det M

Next tactic:
simp [h]
/-- Induction principle for matrices based on transvections: if a property is true for all diagonal
matrices, all transvections, and is stable under product, then it is true for all matrices. This is
the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix `M`, it suffices to
assume that the diagonal matrices we consider have the same determinant as `M`. This is useful to
obtain similar principles for `SLₙ` or `GLₙ`. -/
theorem diagonal_transvection_induction (P : Matrix n n 𝕜 → Prop) (M : Matrix n n 𝕜)
    (hdiag : ∀ D : n → 𝕜, det (diagonal D) = det M → P (diagonal D))
    (htransvec : ∀ t : TransvectionStruct n 𝕜, P t.toMatrix) (hmul : ∀ A B, P A → P B → P (A * B)) :
    P M := by
  rcases exists_list_transvec_mul_diagonal_mul_list_transvec M with ⟨L, L', D, h⟩
  have PD : P (diagonal D) := hdiag D (by simp [h])
  

Proof state:
case intro.intro.intro
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁴ : Field 𝕜
inst✝³ : DecidableEq n
inst✝² : DecidableEq p
inst✝¹ : CommRing R
inst✝ : Fintype n
P : Matrix n n 𝕜 → Prop
M : Matrix n n 𝕜
hdiag : ∀ (D : n → 𝕜), det (diagonal D) = det M → P (diagonal D)
htransvec : ∀ (t : TransvectionStruct n 𝕜), P (toMatrix t)
hmul : ∀ (A B : Matrix n n 𝕜), P A → P B → P (A * B)
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')
PD : P (diagonal D)
⊢ P M

Next tactic:
suffices H :
    ∀ (L₁ L₂ : List (TransvectionStruct n 𝕜)) (E : Matrix n n 𝕜),
      P E → P ((L₁.map toMatrix).prod * E * (L₂.map toMatrix).prod)
/-- Induction principle for matrices based on transvections: if a property is true for all diagonal
matrices, all transvections, and is stable under product, then it is true for all matrices. This is
the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix `M`, it suffices to
assume that the diagonal matrices we consider have the same determinant as `M`. This is useful to
obtain similar principles for `SLₙ` or `GLₙ`. -/
theorem diagonal_transvection_induction (P : Matrix n n 𝕜 → Prop) (M : Matrix n n 𝕜)
    (hdiag : ∀ D : n → 𝕜, det (diagonal D) = det M → P (diagonal D))
    (htransvec : ∀ t : TransvectionStruct n 𝕜, P t.toMatrix) (hmul : ∀ A B, P A → P B → P (A * B)) :
    P M := by
  rcases exists_list_transvec_mul_diagonal_mul_list_transvec M with ⟨L, L', D, h⟩
  have PD : P (diagonal D) := hdiag D (by simp [h])
  suffices H :
    ∀ (L₁ L₂ : List (TransvectionStruct n 𝕜)) (E : Matrix n n 𝕜),
      P E → P ((L₁.map toMatrix).prod * E * (L₂.map toMatrix).prod)
  · 

Proof state:
case intro.intro.intro
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁴ : Field 𝕜
inst✝³ : DecidableEq n
inst✝² : DecidableEq p
inst✝¹ : CommRing R
inst✝ : Fintype n
P : Matrix n n 𝕜 → Prop
M : Matrix n n 𝕜
hdiag : ∀ (D : n → 𝕜), det (diagonal D) = det M → P (diagonal D)
htransvec : ∀ (t : TransvectionStruct n 𝕜), P (toMatrix t)
hmul : ∀ (A B : Matrix n n 𝕜), P A → P B → P (A * B)
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')
PD : P (diagonal D)
H :
  ∀ (L₁ L₂ : List (TransvectionStruct n 𝕜)) (E : Matrix n n 𝕜),
    P E → P (List.prod (List.map toMatrix L₁) * E * List.prod (List.map toMatrix L₂))
⊢ P M

Next tactic:
rw [h]
/-- Induction principle for matrices based on transvections: if a property is true for all diagonal
matrices, all transvections, and is stable under product, then it is true for all matrices. This is
the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix `M`, it suffices to
assume that the diagonal matrices we consider have the same determinant as `M`. This is useful to
obtain similar principles for `SLₙ` or `GLₙ`. -/
theorem diagonal_transvection_induction (P : Matrix n n 𝕜 → Prop) (M : Matrix n n 𝕜)
    (hdiag : ∀ D : n → 𝕜, det (diagonal D) = det M → P (diagonal D))
    (htransvec : ∀ t : TransvectionStruct n 𝕜, P t.toMatrix) (hmul : ∀ A B, P A → P B → P (A * B)) :
    P M := by
  rcases exists_list_transvec_mul_diagonal_mul_list_transvec M with ⟨L, L', D, h⟩
  have PD : P (diagonal D) := hdiag D (by simp [h])
  suffices H :
    ∀ (L₁ L₂ : List (TransvectionStruct n 𝕜)) (E : Matrix n n 𝕜),
      P E → P ((L₁.map toMatrix).prod * E * (L₂.map toMatrix).prod)
  · rw [h]
    

Proof state:
case intro.intro.intro
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁴ : Field 𝕜
inst✝³ : DecidableEq n
inst✝² : DecidableEq p
inst✝¹ : CommRing R
inst✝ : Fintype n
P : Matrix n n 𝕜 → Prop
M : Matrix n n 𝕜
hdiag : ∀ (D : n → 𝕜), det (diagonal D) = det M → P (diagonal D)
htransvec : ∀ (t : TransvectionStruct n 𝕜), P (toMatrix t)
hmul : ∀ (A B : Matrix n n 𝕜), P A → P B → P (A * B)
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')
PD : P (diagonal D)
H :
  ∀ (L₁ L₂ : List (TransvectionStruct n 𝕜)) (E : Matrix n n 𝕜),
    P E → P (List.prod (List.map toMatrix L₁) * E * List.prod (List.map toMatrix L₂))
⊢ P (List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L'))

Next tactic:
apply H L L'
/-- Induction principle for matrices based on transvections: if a property is true for all diagonal
matrices, all transvections, and is stable under product, then it is true for all matrices. This is
the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix `M`, it suffices to
assume that the diagonal matrices we consider have the same determinant as `M`. This is useful to
obtain similar principles for `SLₙ` or `GLₙ`. -/
theorem diagonal_transvection_induction (P : Matrix n n 𝕜 → Prop) (M : Matrix n n 𝕜)
    (hdiag : ∀ D : n → 𝕜, det (diagonal D) = det M → P (diagonal D))
    (htransvec : ∀ t : TransvectionStruct n 𝕜, P t.toMatrix) (hmul : ∀ A B, P A → P B → P (A * B)) :
    P M := by
  rcases exists_list_transvec_mul_diagonal_mul_list_transvec M with ⟨L, L', D, h⟩
  have PD : P (diagonal D) := hdiag D (by simp [h])
  suffices H :
    ∀ (L₁ L₂ : List (TransvectionStruct n 𝕜)) (E : Matrix n n 𝕜),
      P E → P ((L₁.map toMatrix).prod * E * (L₂.map toMatrix).prod)
  · rw [h]
    apply H L L'
    

Proof state:
case intro.intro.intro.a
n : Type u_1
p : Type u_2
R : Type u₂
𝕜 : Type u_3
inst✝⁴ : Field 𝕜
inst✝³ : DecidableEq n
inst✝² : DecidableEq p
inst✝¹ : CommRing R
inst✝ : Fintype n
P : Matrix n n 𝕜 → Prop
M : Matrix n n 𝕜
hdiag : ∀ (D : n → 𝕜), det (diagonal D) = det M → P (diagonal D)
htransvec : ∀ (t : TransvectionStruct n 𝕜), P (toMatrix t)
hmul : ∀ (A B : Matrix n n 𝕜), P A → P B → P (A * B)
L L' : List (TransvectionStruct n 𝕜)
D : n → 𝕜
h : M = List.prod (List.map toMatrix L) * diagonal D * List.prod (List.map toMatrix L')
PD : P (diagonal D)
H :
  ∀ (L₁ L₂ : List (TransvectionStruct n 𝕜)) (E : Matrix n n 𝕜),
    P E → P (List.prod (List.map toMatrix L₁) * E * List.prod (List.map toMatrix L₂))
⊢ P (diagonal D)

Next tactic:
exact PD