l3lab/ntp-mathlib huggingface dataset:
/-- A transvection matrix is obtained from the identity by adding `c` times the `j`-th row to
the `i`-th row. -/
theorem updateRow_eq_transvection [Finite n] (c : R) :
    updateRow (1 : Matrix n n R) i ((1 : Matrix n n R) i + c • (1 : Matrix n n R) j) =
      transvection i j c := by
  cases nonempty_fintype n
  ext a b
  

Proof state:
case intro.a.h
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
i j : n
inst✝ : Finite n
c : R
val✝ : Fintype n
a b : n
⊢ updateRow 1 i (OfNat.ofNat 1 i + c • OfNat.ofNat 1 j) a b = transvection i j c a b

Next tactic:
by_cases ha : i = a
/-- A transvection matrix is obtained from the identity by adding `c` times the `j`-th row to
the `i`-th row. -/
theorem updateRow_eq_transvection [Finite n] (c : R) :
    updateRow (1 : Matrix n n R) i ((1 : Matrix n n R) i + c • (1 : Matrix n n R) j) =
      transvection i j c := by
  cases nonempty_fintype n
  ext a b
  by_cases ha : i = a; 

Proof state:
case pos
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
i j : n
inst✝ : Finite n
c : R
val✝ : Fintype n
a b : n
ha : i = a
⊢ updateRow 1 i (OfNat.ofNat 1 i + c • OfNat.ofNat 1 j) a b = transvection i j c a b
case neg
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
i j : n
inst✝ : Finite n
c : R
val✝ : Fintype n
a b : n
ha : ¬i = a
⊢ updateRow 1 i (OfNat.ofNat 1 i + c • OfNat.ofNat 1 j) a b = transvection i j c a b

Next tactic:
by_cases hb : j = b
/-- A transvection matrix is obtained from the identity by adding `c` times the `j`-th row to
the `i`-th row. -/
theorem updateRow_eq_transvection [Finite n] (c : R) :
    updateRow (1 : Matrix n n R) i ((1 : Matrix n n R) i + c • (1 : Matrix n n R) j) =
      transvection i j c := by
  cases nonempty_fintype n
  ext a b
  by_cases ha : i = a; by_cases hb : j = b
  · 

Proof state:
case pos
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
i j : n
inst✝ : Finite n
c : R
val✝ : Fintype n
a b : n
ha : i = a
hb : j = b
⊢ updateRow 1 i (OfNat.ofNat 1 i + c • OfNat.ofNat 1 j) a b = transvection i j c a b

Next tactic:
simp only [updateRow_self, transvection, ha, hb, Pi.add_apply, StdBasisMatrix.apply_same,
      one_apply_eq, Pi.smul_apply, mul_one, Algebra.id.smul_eq_mul, add_apply]
/-- A transvection matrix is obtained from the identity by adding `c` times the `j`-th row to
the `i`-th row. -/
theorem updateRow_eq_transvection [Finite n] (c : R) :
    updateRow (1 : Matrix n n R) i ((1 : Matrix n n R) i + c • (1 : Matrix n n R) j) =
      transvection i j c := by
  cases nonempty_fintype n
  ext a b
  by_cases ha : i = a; by_cases hb : j = b
  · simp only [updateRow_self, transvection, ha, hb, Pi.add_apply, StdBasisMatrix.apply_same,
      one_apply_eq, Pi.smul_apply, mul_one, Algebra.id.smul_eq_mul, add_apply]
  · 

Proof state:
case neg
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
i j : n
inst✝ : Finite n
c : R
val✝ : Fintype n
a b : n
ha : i = a
hb : ¬j = b
⊢ updateRow 1 i (OfNat.ofNat 1 i + c • OfNat.ofNat 1 j) a b = transvection i j c a b

Next tactic:
simp only [updateRow_self, transvection, ha, hb, StdBasisMatrix.apply_of_ne, Pi.add_apply,
      Ne.def, not_false_iff, Pi.smul_apply, and_false_iff, one_apply_ne, Algebra.id.smul_eq_mul,
      mul_zero, add_apply]
/-- A transvection matrix is obtained from the identity by adding `c` times the `j`-th row to
the `i`-th row. -/
theorem updateRow_eq_transvection [Finite n] (c : R) :
    updateRow (1 : Matrix n n R) i ((1 : Matrix n n R) i + c • (1 : Matrix n n R) j) =
      transvection i j c := by
  cases nonempty_fintype n
  ext a b
  by_cases ha : i = a; by_cases hb : j = b
  · simp only [updateRow_self, transvection, ha, hb, Pi.add_apply, StdBasisMatrix.apply_same,
      one_apply_eq, Pi.smul_apply, mul_one, Algebra.id.smul_eq_mul, add_apply]
  · simp only [updateRow_self, transvection, ha, hb, StdBasisMatrix.apply_of_ne, Pi.add_apply,
      Ne.def, not_false_iff, Pi.smul_apply, and_false_iff, one_apply_ne, Algebra.id.smul_eq_mul,
      mul_zero, add_apply]
  · 

Proof state:
case neg
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
i j : n
inst✝ : Finite n
c : R
val✝ : Fintype n
a b : n
ha : ¬i = a
⊢ updateRow 1 i (OfNat.ofNat 1 i + c • OfNat.ofNat 1 j) a b = transvection i j c a b

Next tactic:
simp only [updateRow_ne, transvection, ha, Ne.symm ha, StdBasisMatrix.apply_of_ne, add_zero,
      Algebra.id.smul_eq_mul, Ne.def, not_false_iff, DMatrix.add_apply, Pi.smul_apply,
      mul_zero, false_and_iff, add_apply]
theorem transvection_mul_transvection_same (h : i ≠ j) (c d : R) :
    transvection i j c * transvection i j d = transvection i j (c + 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
i j : n
inst✝ : Fintype n
h : i ≠ j
c d : R
⊢ transvection i j c * transvection i j d = transvection i j (c + d)

Next tactic:
simp [transvection, Matrix.add_mul, Matrix.mul_add, h, h.symm, add_smul, add_assoc,
    stdBasisMatrix_add]
@[simp]
theorem transvection_mul_apply_same (b : n) (c : R) (M : Matrix n n R) :
    (transvection i j c * M) i b = M i b + c * M j b := 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
i j : n
inst✝ : Fintype n
b : n
c : R
M : Matrix n n R
⊢ (transvection i j c * M) i b = M i b + c * M j b

Next tactic:
simp [transvection, Matrix.add_mul]
@[simp]
theorem mul_transvection_apply_same (a : n) (c : R) (M : Matrix n n R) :
    (M * transvection i j c) a j = M a j + c * M a i := 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
i j : n
inst✝ : Fintype n
a : n
c : R
M : Matrix n n R
⊢ (M * transvection i j c) a j = M a j + c * M a i

Next tactic:
simp [transvection, Matrix.mul_add, mul_comm]
@[simp]
theorem transvection_mul_apply_of_ne (a b : n) (ha : a ≠ i) (c : R) (M : Matrix n n R) :
    (transvection i j c * M) a b = M a b := 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
i j : n
inst✝ : Fintype n
a b : n
ha : a ≠ i
c : R
M : Matrix n n R
⊢ (transvection i j c * M) a b = M a b

Next tactic:
simp [transvection, Matrix.add_mul, ha]
@[simp]
theorem mul_transvection_apply_of_ne (a b : n) (hb : b ≠ j) (c : R) (M : Matrix n n R) :
    (M * transvection i j c) a b = M a b := 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
i j : n
inst✝ : Fintype n
a b : n
hb : b ≠ j
c : R
M : Matrix n n R
⊢ (M * transvection i j c) a b = M a b

Next tactic:
simp [transvection, Matrix.mul_add, hb]
@[simp]
theorem det_transvection_of_ne (h : i ≠ j) (c : R) : det (transvection i j c) = 1 := 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
i j : n
inst✝ : Fintype n
h : i ≠ j
c : R
⊢ det (transvection i j c) = 1

Next tactic:
rw [← updateRow_eq_transvection i j, det_updateRow_add_smul_self _ h, det_one]
instance [Nontrivial n] : Nonempty (TransvectionStruct n R) := 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
i j : n
inst✝ : Nontrivial n
⊢ Nonempty (TransvectionStruct n R)

Next tactic:
choose x y hxy using exists_pair_ne n
instance [Nontrivial n] : Nonempty (TransvectionStruct n R) := by
  choose x y hxy using exists_pair_ne n
  

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
i j : n
inst✝ : Nontrivial n
x y : n
hxy : x ≠ y
⊢ Nonempty (TransvectionStruct n R)

Next tactic:
exact ⟨⟨x, y, hxy, 0⟩⟩
@[simp]
theorem det_toMatrix_prod [Fintype n] (L : List (TransvectionStruct n 𝕜)) :
    det (L.map toMatrix).prod = 1 := 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
i j : n
inst✝ : Fintype n
L : List (TransvectionStruct n 𝕜)
⊢ det (List.prod (List.map toMatrix L)) = 1

Next tactic:
induction' L with t L IH
@[simp]
theorem det_toMatrix_prod [Fintype n] (L : List (TransvectionStruct n 𝕜)) :
    det (L.map toMatrix).prod = 1 := by
  induction' L with t L IH
  · 

Proof state:
case nil
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
i j : n
inst✝ : Fintype n
⊢ det (List.prod (List.map toMatrix [])) = 1

Next tactic:
simp
@[simp]
theorem det_toMatrix_prod [Fintype n] (L : List (TransvectionStruct n 𝕜)) :
    det (L.map toMatrix).prod = 1 := by
  induction' L with t L IH
  · simp
  · 

Proof state:
case cons
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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n 𝕜
L : List (TransvectionStruct n 𝕜)
IH : det (List.prod (List.map toMatrix L)) = 1
⊢ det (List.prod (List.map toMatrix (t :: L))) = 1

Next tactic:
simp [IH]
theorem inv_mul (t : TransvectionStruct n R) : t.inv.toMatrix * t.toMatrix = 1 := 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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
⊢ toMatrix (TransvectionStruct.inv t) * toMatrix t = 1

Next tactic:
rcases t with ⟨_, _, t_hij⟩
theorem inv_mul (t : TransvectionStruct n R) : t.inv.toMatrix * t.toMatrix = 1 := by
  rcases t with ⟨_, _, t_hij⟩
  

Proof state:
case mk
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
i j : n
inst✝ : Fintype n
i✝ j✝ : n
t_hij : i✝ ≠ j✝
c✝ : R
⊢ toMatrix (TransvectionStruct.inv { i := i✝, j := j✝, hij := t_hij, c := c✝ }) *
      toMatrix { i := i✝, j := j✝, hij := t_hij, c := c✝ } =
    1

Next tactic:
simp [toMatrix, transvection_mul_transvection_same, t_hij]
theorem mul_inv (t : TransvectionStruct n R) : t.toMatrix * t.inv.toMatrix = 1 := 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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
⊢ toMatrix t * toMatrix (TransvectionStruct.inv t) = 1

Next tactic:
rcases t with ⟨_, _, t_hij⟩
theorem mul_inv (t : TransvectionStruct n R) : t.toMatrix * t.inv.toMatrix = 1 := by
  rcases t with ⟨_, _, t_hij⟩
  

Proof state:
case mk
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
i j : n
inst✝ : Fintype n
i✝ j✝ : n
t_hij : i✝ ≠ j✝
c✝ : R
⊢ toMatrix { i := i✝, j := j✝, hij := t_hij, c := c✝ } *
      toMatrix (TransvectionStruct.inv { i := i✝, j := j✝, hij := t_hij, c := c✝ }) =
    1

Next tactic:
simp [toMatrix, transvection_mul_transvection_same, t_hij]
theorem reverse_inv_prod_mul_prod (L : List (TransvectionStruct n R)) :
    (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod = 1 := 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
i j : n
inst✝ : Fintype n
L : List (TransvectionStruct n R)
⊢ List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) * List.prod (List.map toMatrix L) = 1

Next tactic:
induction' L with t L IH
theorem reverse_inv_prod_mul_prod (L : List (TransvectionStruct n R)) :
    (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod = 1 := by
  induction' L with t L IH
  · 

Proof state:
case nil
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
i j : n
inst✝ : Fintype n
⊢ List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse [])) * List.prod (List.map toMatrix []) = 1

Next tactic:
simp
theorem reverse_inv_prod_mul_prod (L : List (TransvectionStruct n R)) :
    (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod = 1 := by
  induction' L with t L IH
  · simp
  · 

Proof state:
case cons
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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
L : List (TransvectionStruct n R)
IH : List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) * List.prod (List.map toMatrix L) = 1
⊢ List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse (t :: L))) *
      List.prod (List.map toMatrix (t :: L)) =
    1

Next tactic:
suffices
      (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (t.inv.toMatrix * t.toMatrix) *
          (L.map toMatrix).prod = 1
      by simpa [Matrix.mul_assoc]
theorem reverse_inv_prod_mul_prod (L : List (TransvectionStruct n R)) :
    (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod = 1 := by
  induction' L with t L IH
  · simp
  · suffices
      (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (t.inv.toMatrix * t.toMatrix) *
          (L.map toMatrix).prod = 1
      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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
L : List (TransvectionStruct n R)
IH : List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) * List.prod (List.map toMatrix L) = 1
this :
  List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) *
        (toMatrix (TransvectionStruct.inv t) * toMatrix t) *
      List.prod (List.map toMatrix L) =
    1
⊢ List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse (t :: L))) *
      List.prod (List.map toMatrix (t :: L)) =
    1

Next tactic:
simpa [Matrix.mul_assoc]
theorem reverse_inv_prod_mul_prod (L : List (TransvectionStruct n R)) :
    (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (L.map toMatrix).prod = 1 := by
  induction' L with t L IH
  · simp
  · suffices
      (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod * (t.inv.toMatrix * t.toMatrix) *
          (L.map toMatrix).prod = 1
      by simpa [Matrix.mul_assoc]
    

Proof state:
case cons
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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
L : List (TransvectionStruct n R)
IH : List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) * List.prod (List.map toMatrix L) = 1
⊢ List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) *
        (toMatrix (TransvectionStruct.inv t) * toMatrix t) *
      List.prod (List.map toMatrix L) =
    1

Next tactic:
simpa [inv_mul] using IH
theorem prod_mul_reverse_inv_prod (L : List (TransvectionStruct n R)) :
    (L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod = 1 := 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
i j : n
inst✝ : Fintype n
L : List (TransvectionStruct n R)
⊢ List.prod (List.map toMatrix L) * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) = 1

Next tactic:
induction' L with t L IH
theorem prod_mul_reverse_inv_prod (L : List (TransvectionStruct n R)) :
    (L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod = 1 := by
  induction' L with t L IH
  · 

Proof state:
case nil
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
i j : n
inst✝ : Fintype n
⊢ List.prod (List.map toMatrix []) * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse [])) = 1

Next tactic:
simp
theorem prod_mul_reverse_inv_prod (L : List (TransvectionStruct n R)) :
    (L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod = 1 := by
  induction' L with t L IH
  · simp
  · 

Proof state:
case cons
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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
L : List (TransvectionStruct n R)
IH : List.prod (List.map toMatrix L) * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) = 1
⊢ List.prod (List.map toMatrix (t :: L)) *
      List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse (t :: L))) =
    1

Next tactic:
suffices
      t.toMatrix *
            ((L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod) *
          t.inv.toMatrix = 1
      by simpa [Matrix.mul_assoc]
theorem prod_mul_reverse_inv_prod (L : List (TransvectionStruct n R)) :
    (L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod = 1 := by
  induction' L with t L IH
  · simp
  · suffices
      t.toMatrix *
            ((L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod) *
          t.inv.toMatrix = 1
      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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
L : List (TransvectionStruct n R)
IH : List.prod (List.map toMatrix L) * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) = 1
this :
  toMatrix t *
        (List.prod (List.map toMatrix L) * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L))) *
      toMatrix (TransvectionStruct.inv t) =
    1
⊢ List.prod (List.map toMatrix (t :: L)) *
      List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse (t :: L))) =
    1

Next tactic:
simpa [Matrix.mul_assoc]
theorem prod_mul_reverse_inv_prod (L : List (TransvectionStruct n R)) :
    (L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod = 1 := by
  induction' L with t L IH
  · simp
  · suffices
      t.toMatrix *
            ((L.map toMatrix).prod * (L.reverse.map (toMatrix ∘ TransvectionStruct.inv)).prod) *
          t.inv.toMatrix = 1
      by simpa [Matrix.mul_assoc]
    

Proof state:
case cons
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
i j : n
inst✝ : Fintype n
t : TransvectionStruct n R
L : List (TransvectionStruct n R)
IH : List.prod (List.map toMatrix L) * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L)) = 1
⊢ toMatrix t *
        (List.prod (List.map toMatrix L) * List.prod (List.map (toMatrix ∘ TransvectionStruct.inv) (List.reverse L))) *
      toMatrix (TransvectionStruct.inv t) =
    1

Next tactic:
simp_rw [IH, Matrix.mul_one, t.mul_inv]
/-- Given a `TransvectionStruct` on `n`, define the corresponding `TransvectionStruct` on `n ⊕ p`
using the identity on `p`. -/
def sumInl (t : TransvectionStruct n R) : TransvectionStruct (Sum n p) R where
  i := inl t.i
  j := inl t.j
  hij := 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
i j : n
t : TransvectionStruct n R
⊢ inl t.i ≠ inl t.j

Next tactic:
simp [t.hij]
theorem toMatrix_sumInl (t : TransvectionStruct n R) :
    (t.sumInl p).toMatrix = fromBlocks t.toMatrix 0 0 1 := 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
i j : n
t : TransvectionStruct n R
⊢ toMatrix (sumInl p t) = fromBlocks (toMatrix t) 0 0 1

Next tactic:
cases t
theorem toMatrix_sumInl (t : TransvectionStruct n R) :
    (t.sumInl p).toMatrix = fromBlocks t.toMatrix 0 0 1 := by
  cases t
  

Proof state:
case mk
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
i j i✝ j✝ : n
hij✝ : i✝ ≠ j✝
c✝ : R
⊢ toMatrix (sumInl p { i := i✝, j := j✝, hij := hij✝, c := c✝ }) =
    fromBlocks (toMatrix { i := i✝, j := j✝, hij := hij✝, c := c✝ }) 0 0 1

Next tactic:
ext a b
theorem toMatrix_sumInl (t : TransvectionStruct n R) :
    (t.sumInl p).toMatrix = fromBlocks t.toMatrix 0 0 1 := by
  cases t
  ext a b
  

Proof state:
case mk.a.h
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
i j i✝ j✝ : n
hij✝ : i✝ ≠ j✝
c✝ : R
a b : n ⊕ p
⊢ toMatrix (sumInl p { i := i✝, j := j✝, hij := hij✝, c := c✝ }) a b =
    fromBlocks (toMatrix { i := i✝, j := j✝, hij := hij✝, c := c✝ }) 0 0 1 a b

Next tactic:
cases' a with a a
theorem toMatrix_sumInl (t : TransvectionStruct n R) :
    (t.sumInl p).toMatrix = fromBlocks t.toMatrix 0 0 1 := by
  cases t
  ext a b
  cases' a with a a <;> 

Proof state:
case mk.a.h.inl
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
i j i✝ j✝ : n
hij✝ : i✝ ≠ j✝
c✝ : R
b : n ⊕ p
a : n
⊢ toMatrix (sumInl p { i := i✝, j := j✝, hij := hij✝, c := c✝ }) (inl a) b =
    fromBlocks (toMatrix { i := i✝, j := j✝, hij := hij✝, c := c✝ }) 0 0 1 (inl a) b

Next tactic:
cases' b with b b
theorem toMatrix_sumInl (t : TransvectionStruct n R) :
    (t.sumInl p).toMatrix = fromBlocks t.toMatrix 0 0 1 := by
  cases t
  ext a b
  cases' a with a a <;> 

Proof state:
case mk.a.h.inr
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
i j i✝ j✝ : n
hij✝ : i✝ ≠ j✝
c✝ : R
b : n ⊕ p
a : p
⊢ toMatrix (sumInl p { i := i✝, j := j✝, hij := hij✝, c := c✝ }) (inr a) b =
    fromBlocks (toMatrix { i := i✝, j := j✝, hij := hij✝, c := c✝ }) 0 0 1 (inr a) b

Next tactic:
cases' b with b b
theorem toMatrix_sumInl (t : TransvectionStruct n R) :
    (t.sumInl p).toMatrix = fromBlocks t.toMatrix 0 0 1 := by
  cases t
  ext a b
  cases' a with a a <;> cases' b with b b
  · 

Proof state:
case mk.a.h.inl.inl
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
i j i✝ j✝ : n
hij✝ : i✝ ≠ j✝
c✝ : R
a b : n
⊢ toMatrix (sumInl p { i := i✝, j := j✝, hij := hij✝, c := c✝ }) (inl a) (inl b) =
    fromBlocks (toMatrix { i := i✝, j := j✝, hij := hij✝, c := c✝ }) 0 0 1 (inl a) (inl b)

Next tactic:
by_cases h : a = b
theorem toMatrix_sumInl (t : TransvectionStruct n R) :
    (t.sumInl p).toMatrix = fromBlocks t.toMatrix 0 0 1 := by
  cases t
  ext a b
  cases' a with a a <;> cases' b with b b
  · by_cases h : a = b <;> 

Proof state:
case pos
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
i j i✝ j✝ : n
hij✝ : i✝ ≠ j✝
c✝ : R
a b : n
h : a = b
⊢ toMatrix (sumInl p { i := i✝, j := j✝, hij := hij✝, c := c✝ }) (inl a) (inl b) =
    fromBlocks (toMatrix { i := i✝, j := j✝, hij := hij✝, c := c✝ }) 0 0 1 (inl a) (inl b)

Next tactic:
simp [TransvectionStruct.sumInl, transvection, h, stdBasisMatrix]