l3lab/ntp-mathlib huggingface dataset:
theorem mulVec_surjective_iff_exists_right_inverse [Semiring R] {A : Matrix m n R} :
    Function.Surjective A.mulVec ↔ ∃ B : Matrix n m R, A * B = 1 := by
  refine ⟨fun h ↦ ?_, fun ⟨B, hBA⟩ y ↦ ⟨B.mulVec y, by simp [hBA]⟩⟩
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁶ : Fintype n
inst✝⁵ : DecidableEq n
inst✝⁴ : CommRing α
A✝ B : Matrix n n α
inst✝³ : Fintype m
inst✝² : DecidableEq m
K : Type u_2
R : Type u_3
inst✝¹ : Field K
inst✝ : Semiring R
A : Matrix m n R
h : Function.Surjective (mulVec A)
⊢ ∃ B, A * B = 1

Next tactic:
choose cols hcols using (h <| Pi.single · 1)
theorem mulVec_surjective_iff_exists_right_inverse [Semiring R] {A : Matrix m n R} :
    Function.Surjective A.mulVec ↔ ∃ B : Matrix n m R, A * B = 1 := by
  refine ⟨fun h ↦ ?_, fun ⟨B, hBA⟩ y ↦ ⟨B.mulVec y, by simp [hBA]⟩⟩
  choose cols hcols using (h <| Pi.single · 1)
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁶ : Fintype n
inst✝⁵ : DecidableEq n
inst✝⁴ : CommRing α
A✝ B : Matrix n n α
inst✝³ : Fintype m
inst✝² : DecidableEq m
K : Type u_2
R : Type u_3
inst✝¹ : Field K
inst✝ : Semiring R
A : Matrix m n R
h : Function.Surjective (mulVec A)
cols : m → n → R
hcols : ∀ (x : m), mulVec A (cols x) = Pi.single x 1
⊢ ∃ B, A * B = 1

Next tactic:
refine ⟨(Matrix.of cols)ᵀ, Matrix.ext fun i j ↦ ?_⟩
theorem mulVec_surjective_iff_exists_right_inverse [Semiring R] {A : Matrix m n R} :
    Function.Surjective A.mulVec ↔ ∃ B : Matrix n m R, A * B = 1 := by
  refine ⟨fun h ↦ ?_, fun ⟨B, hBA⟩ y ↦ ⟨B.mulVec y, by simp [hBA]⟩⟩
  choose cols hcols using (h <| Pi.single · 1)
  refine ⟨(Matrix.of cols)ᵀ, Matrix.ext fun i j ↦ ?_⟩
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁶ : Fintype n
inst✝⁵ : DecidableEq n
inst✝⁴ : CommRing α
A✝ B : Matrix n n α
inst✝³ : Fintype m
inst✝² : DecidableEq m
K : Type u_2
R : Type u_3
inst✝¹ : Field K
inst✝ : Semiring R
A : Matrix m n R
h : Function.Surjective (mulVec A)
cols : m → n → R
hcols : ∀ (x : m), mulVec A (cols x) = Pi.single x 1
i j : m
⊢ (A * (of cols)ᵀ) i j = OfNat.ofNat 1 i j

Next tactic:
rw [one_eq_pi_single, Pi.single_comm, ← hcols j]
theorem mulVec_surjective_iff_exists_right_inverse [Semiring R] {A : Matrix m n R} :
    Function.Surjective A.mulVec ↔ ∃ B : Matrix n m R, A * B = 1 := by
  refine ⟨fun h ↦ ?_, fun ⟨B, hBA⟩ y ↦ ⟨B.mulVec y, by simp [hBA]⟩⟩
  choose cols hcols using (h <| Pi.single · 1)
  refine ⟨(Matrix.of cols)ᵀ, Matrix.ext fun i j ↦ ?_⟩
  rw [one_eq_pi_single, Pi.single_comm, ← hcols j]
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁶ : Fintype n
inst✝⁵ : DecidableEq n
inst✝⁴ : CommRing α
A✝ B : Matrix n n α
inst✝³ : Fintype m
inst✝² : DecidableEq m
K : Type u_2
R : Type u_3
inst✝¹ : Field K
inst✝ : Semiring R
A : Matrix m n R
h : Function.Surjective (mulVec A)
cols : m → n → R
hcols : ∀ (x : m), mulVec A (cols x) = Pi.single x 1
i j : m
⊢ (A * (of cols)ᵀ) i j = mulVec A (cols j) i

Next tactic:
rfl
theorem vecMul_surjective_iff_isUnit {A : Matrix m m α} :
    Function.Surjective A.vecMul ↔ IsUnit A := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m α
⊢ (Function.Surjective fun v => vecMul v A) ↔ IsUnit A

Next tactic:
rw [vecMul_surjective_iff_exists_left_inverse, exists_left_inverse_iff_isUnit]
theorem mulVec_surjective_iff_isUnit {A : Matrix m m α} :
    Function.Surjective A.mulVec ↔ IsUnit A := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m α
⊢ Function.Surjective (mulVec A) ↔ IsUnit A

Next tactic:
rw [mulVec_surjective_iff_exists_right_inverse, exists_right_inverse_iff_isUnit]
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
⊢ (Function.Injective fun v => vecMul v A) ↔ IsUnit A

Next tactic:
refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · 

Proof state:
case refine_1
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
h : Function.Injective fun v => vecMul v A
⊢ IsUnit A

Next tactic:
rw [← vecMul_surjective_iff_isUnit]
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · rw [← vecMul_surjective_iff_isUnit]
    

Proof state:
case refine_1
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
h : Function.Injective fun v => vecMul v A
⊢ Function.Surjective fun v => vecMul v A

Next tactic:
exact LinearMap.surjective_of_injective (f := A.vecMulLinear) h
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · rw [← vecMul_surjective_iff_isUnit]
    exact LinearMap.surjective_of_injective (f := A.vecMulLinear) h
  

Proof state:
case refine_2
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
h : IsUnit A
⊢ Function.Injective fun v => vecMul v A

Next tactic:
change Function.Injective A.vecMulLinear
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · rw [← vecMul_surjective_iff_isUnit]
    exact LinearMap.surjective_of_injective (f := A.vecMulLinear) h
  change Function.Injective A.vecMulLinear
  

Proof state:
case refine_2
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
h : IsUnit A
⊢ Function.Injective ⇑(vecMulLinear A)

Next tactic:
rw [← LinearMap.ker_eq_bot, LinearMap.ker_eq_bot']
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · rw [← vecMul_surjective_iff_isUnit]
    exact LinearMap.surjective_of_injective (f := A.vecMulLinear) h
  change Function.Injective A.vecMulLinear
  rw [← LinearMap.ker_eq_bot, LinearMap.ker_eq_bot']
  

Proof state:
case refine_2
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
h : IsUnit A
⊢ ∀ (m_1 : m → K), (vecMulLinear A) m_1 = 0 → m_1 = 0

Next tactic:
intro c hc
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · rw [← vecMul_surjective_iff_isUnit]
    exact LinearMap.surjective_of_injective (f := A.vecMulLinear) h
  change Function.Injective A.vecMulLinear
  rw [← LinearMap.ker_eq_bot, LinearMap.ker_eq_bot']
  intro c hc
  

Proof state:
case refine_2
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
h : IsUnit A
c : m → K
hc : (vecMulLinear A) c = 0
⊢ c = 0

Next tactic:
replace h := h.invertible
theorem vecMul_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.vecMul ↔ IsUnit A := by
  refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
  · rw [← vecMul_surjective_iff_isUnit]
    exact LinearMap.surjective_of_injective (f := A.vecMulLinear) h
  change Function.Injective A.vecMulLinear
  rw [← LinearMap.ker_eq_bot, LinearMap.ker_eq_bot']
  intro c hc
  replace h := h.invertible
  

Proof state:
case refine_2
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
c : m → K
hc : (vecMulLinear A) c = 0
h : Invertible A
⊢ c = 0

Next tactic:
simpa using congr_arg A⁻¹.vecMulLinear hc
theorem mulVec_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.mulVec ↔ IsUnit A := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
⊢ Function.Injective (mulVec A) ↔ IsUnit A

Next tactic:
rw [← isUnit_transpose, ← vecMul_injective_iff_isUnit]
theorem mulVec_injective_iff_isUnit {A : Matrix m m K} :
    Function.Injective A.mulVec ↔ IsUnit A := by
  rw [← isUnit_transpose, ← vecMul_injective_iff_isUnit]
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
⊢ Function.Injective (mulVec A) ↔ Function.Injective fun v => vecMul v Aᵀ

Next tactic:
simp_rw [vecMul_transpose]
theorem linearIndependent_rows_iff_isUnit {A : Matrix m m K} :
    LinearIndependent K (fun i ↦ A i) ↔ IsUnit A := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
⊢ (LinearIndependent K fun i => A i) ↔ IsUnit A

Next tactic:
rw [← transpose_transpose A, ← mulVec_injective_iff, ← coe_mulVecLin, mulVecLin_transpose,
    transpose_transpose, ← vecMul_injective_iff_isUnit, coe_vecMulLinear]
theorem linearIndependent_cols_iff_isUnit {A : Matrix m m K} :
    LinearIndependent K (fun i ↦ Aᵀ i) ↔ IsUnit A := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq n
inst✝³ : CommRing α
A✝ B : Matrix n n α
inst✝² : Fintype m
inst✝¹ : DecidableEq m
K : Type u_2
R : Type u_3
inst✝ : Field K
A : Matrix m m K
⊢ (LinearIndependent K fun i => Aᵀ i) ↔ IsUnit A

Next tactic:
rw [← transpose_transpose A, isUnit_transpose, linearIndependent_rows_iff_isUnit,
    transpose_transpose]
theorem nonsing_inv_cancel_or_zero : A⁻¹ * A = 1 ∧ A * A⁻¹ = 1 ∨ A⁻¹ = 0 := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
⊢ A⁻¹ * A = 1 ∧ A * A⁻¹ = 1 ∨ A⁻¹ = 0

Next tactic:
by_cases h : IsUnit A.det
theorem nonsing_inv_cancel_or_zero : A⁻¹ * A = 1 ∧ A * A⁻¹ = 1 ∨ A⁻¹ = 0 := by
  by_cases h : IsUnit A.det
  · 

Proof state:
case pos
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
⊢ A⁻¹ * A = 1 ∧ A * A⁻¹ = 1 ∨ A⁻¹ = 0

Next tactic:
exact Or.inl ⟨nonsing_inv_mul _ h, mul_nonsing_inv _ h⟩
theorem nonsing_inv_cancel_or_zero : A⁻¹ * A = 1 ∧ A * A⁻¹ = 1 ∨ A⁻¹ = 0 := by
  by_cases h : IsUnit A.det
  · exact Or.inl ⟨nonsing_inv_mul _ h, mul_nonsing_inv _ h⟩
  · 

Proof state:
case neg
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : ¬IsUnit (det A)
⊢ A⁻¹ * A = 1 ∧ A * A⁻¹ = 1 ∨ A⁻¹ = 0

Next tactic:
exact Or.inr (nonsing_inv_apply_not_isUnit _ h)
theorem det_nonsing_inv_mul_det (h : IsUnit A.det) : A⁻¹.det * A.det = 1 := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
⊢ det A⁻¹ * det A = 1

Next tactic:
rw [← det_mul, A.nonsing_inv_mul h, det_one]
@[simp]
theorem det_nonsing_inv : A⁻¹.det = Ring.inverse A.det := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
⊢ det A⁻¹ = Ring.inverse (det A)

Next tactic:
by_cases h : IsUnit A.det
@[simp]
theorem det_nonsing_inv : A⁻¹.det = Ring.inverse A.det := by
  by_cases h : IsUnit A.det
  · 

Proof state:
case pos
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
⊢ det A⁻¹ = Ring.inverse (det A)

Next tactic:
cases h.nonempty_invertible
@[simp]
theorem det_nonsing_inv : A⁻¹.det = Ring.inverse A.det := by
  by_cases h : IsUnit A.det
  · cases h.nonempty_invertible
    

Proof state:
case pos.intro
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
val✝ : Invertible (det A)
⊢ det A⁻¹ = Ring.inverse (det A)

Next tactic:
letI := invertibleOfDetInvertible A
@[simp]
theorem det_nonsing_inv : A⁻¹.det = Ring.inverse A.det := by
  by_cases h : IsUnit A.det
  · cases h.nonempty_invertible
    letI := invertibleOfDetInvertible A
    

Proof state:
case pos.intro
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
val✝ : Invertible (det A)
this : Invertible A := invertibleOfDetInvertible A
⊢ det A⁻¹ = Ring.inverse (det A)

Next tactic:
rw [Ring.inverse_invertible, ← invOf_eq_nonsing_inv, det_invOf]
@[simp]
theorem det_nonsing_inv : A⁻¹.det = Ring.inverse A.det := by
  by_cases h : IsUnit A.det
  · cases h.nonempty_invertible
    letI := invertibleOfDetInvertible A
    rw [Ring.inverse_invertible, ← invOf_eq_nonsing_inv, det_invOf]
  

Proof state:
case neg
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : ¬IsUnit (det A)
⊢ det A⁻¹ = Ring.inverse (det A)

Next tactic:
cases isEmpty_or_nonempty n
@[simp]
theorem det_nonsing_inv : A⁻¹.det = Ring.inverse A.det := by
  by_cases h : IsUnit A.det
  · cases h.nonempty_invertible
    letI := invertibleOfDetInvertible A
    rw [Ring.inverse_invertible, ← invOf_eq_nonsing_inv, det_invOf]
  cases isEmpty_or_nonempty n
  · 

Proof state:
case neg.inl
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : ¬IsUnit (det A)
h✝ : IsEmpty n
⊢ det A⁻¹ = Ring.inverse (det A)

Next tactic:
rw [det_isEmpty, det_isEmpty, Ring.inverse_one]
@[simp]
theorem det_nonsing_inv : A⁻¹.det = Ring.inverse A.det := by
  by_cases h : IsUnit A.det
  · cases h.nonempty_invertible
    letI := invertibleOfDetInvertible A
    rw [Ring.inverse_invertible, ← invOf_eq_nonsing_inv, det_invOf]
  cases isEmpty_or_nonempty n
  · rw [det_isEmpty, det_isEmpty, Ring.inverse_one]
  · 

Proof state:
case neg.inr
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : ¬IsUnit (det A)
h✝ : Nonempty n
⊢ det A⁻¹ = Ring.inverse (det A)

Next tactic:
rw [Ring.inverse_non_unit _ h, nonsing_inv_apply_not_isUnit _ h, det_zero ‹_›]
@[simp]
theorem nonsing_inv_nonsing_inv (h : IsUnit A.det) : A⁻¹⁻¹ = A :=
  calc
    A⁻¹⁻¹ = 1 * A⁻¹⁻¹ := by 

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
⊢ A⁻¹⁻¹ = 1 * A⁻¹⁻¹

Next tactic:
rw [Matrix.one_mul]
@[simp]
theorem nonsing_inv_nonsing_inv (h : IsUnit A.det) : A⁻¹⁻¹ = A :=
  calc
    A⁻¹⁻¹ = 1 * A⁻¹⁻¹ := by rw [Matrix.one_mul]
    _ = A * A⁻¹ * A⁻¹⁻¹ := by 

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
⊢ 1 * A⁻¹⁻¹ = A * A⁻¹ * A⁻¹⁻¹

Next tactic:
rw [A.mul_nonsing_inv h]
@[simp]
theorem nonsing_inv_nonsing_inv (h : IsUnit A.det) : A⁻¹⁻¹ = A :=
  calc
    A⁻¹⁻¹ = 1 * A⁻¹⁻¹ := by rw [Matrix.one_mul]
    _ = A * A⁻¹ * A⁻¹⁻¹ := by rw [A.mul_nonsing_inv h]
    _ = A := by
      

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : IsUnit (det A)
⊢ A * A⁻¹ * A⁻¹⁻¹ = A

Next tactic:
rw [Matrix.mul_assoc, A⁻¹.mul_nonsing_inv (A.isUnit_nonsing_inv_det h), Matrix.mul_one]
theorem isUnit_nonsing_inv_det_iff {A : Matrix n n α} : IsUnit A⁻¹.det ↔ IsUnit A.det := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A✝ B A : Matrix n n α
⊢ IsUnit (det A⁻¹) ↔ IsUnit (det A)

Next tactic:
rw [Matrix.det_nonsing_inv, isUnit_ring_inverse]
theorem unitOfDetInvertible_eq_nonsingInvUnit [Invertible A.det] :
    unitOfDetInvertible A = nonsingInvUnit A (isUnit_of_invertible _) := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝³ : Fintype n
inst✝² : DecidableEq n
inst✝¹ : CommRing α
A B : Matrix n n α
inst✝ : Invertible (det A)
⊢ unitOfDetInvertible A = nonsingInvUnit A (_ : IsUnit (det A))

Next tactic:
ext
theorem unitOfDetInvertible_eq_nonsingInvUnit [Invertible A.det] :
    unitOfDetInvertible A = nonsingInvUnit A (isUnit_of_invertible _) := by
  ext
  

Proof state:
case a.a.h
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝³ : Fintype n
inst✝² : DecidableEq n
inst✝¹ : CommRing α
A B : Matrix n n α
inst✝ : Invertible (det A)
i✝ x✝ : n
⊢ ↑(unitOfDetInvertible A) i✝ x✝ = ↑(nonsingInvUnit A (_ : IsUnit (det A))) i✝ x✝

Next tactic:
rfl
/-- The left inverse of matrix A is unique when existing. -/
theorem left_inv_eq_left_inv (h : B * A = 1) (g : C * A = 1) : B = C := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B C : Matrix n n α
h : B * A = 1
g : C * A = 1
⊢ B = C

Next tactic:
rw [← inv_eq_left_inv h, ← inv_eq_left_inv g]
/-- The right inverse of matrix A is unique when existing. -/
theorem right_inv_eq_right_inv (h : A * B = 1) (g : A * C = 1) : B = C := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B C : Matrix n n α
h : A * B = 1
g : A * C = 1
⊢ B = C

Next tactic:
rw [← inv_eq_right_inv h, ← inv_eq_right_inv g]
/-- The right inverse of matrix A equals the left inverse of A when they exist. -/
theorem right_inv_eq_left_inv (h : A * B = 1) (g : C * A = 1) : B = C := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B C : Matrix n n α
h : A * B = 1
g : C * A = 1
⊢ B = C

Next tactic:
rw [← inv_eq_right_inv h, ← inv_eq_left_inv g]
theorem inv_inj (h : A⁻¹ = B⁻¹) (h' : IsUnit A.det) : A = B := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B C : Matrix n n α
h : A⁻¹ = B⁻¹
h' : IsUnit (det A)
⊢ A = B

Next tactic:
refine' left_inv_eq_left_inv (mul_nonsing_inv _ h') _
theorem inv_inj (h : A⁻¹ = B⁻¹) (h' : IsUnit A.det) : A = B := by
  refine' left_inv_eq_left_inv (mul_nonsing_inv _ h') _
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B C : Matrix n n α
h : A⁻¹ = B⁻¹
h' : IsUnit (det A)
⊢ B * A⁻¹ = 1

Next tactic:
rw [h]
theorem inv_inj (h : A⁻¹ = B⁻¹) (h' : IsUnit A.det) : A = B := by
  refine' left_inv_eq_left_inv (mul_nonsing_inv _ h') _
  rw [h]
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B C : Matrix n n α
h : A⁻¹ = B⁻¹
h' : IsUnit (det A)
⊢ B * B⁻¹ = 1

Next tactic:
refine' mul_nonsing_inv _ _
theorem inv_inj (h : A⁻¹ = B⁻¹) (h' : IsUnit A.det) : A = B := by
  refine' left_inv_eq_left_inv (mul_nonsing_inv _ h') _
  rw [h]
  refine' mul_nonsing_inv _ _
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B C : Matrix n n α
h : A⁻¹ = B⁻¹
h' : IsUnit (det A)
⊢ IsUnit (det B)

Next tactic:
rwa [← isUnit_nonsing_inv_det_iff, ← h, isUnit_nonsing_inv_det_iff]
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
⊢ 0⁻¹ = 0

Next tactic:
cases' subsingleton_or_nontrivial α with ht ht
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  cases' subsingleton_or_nontrivial α with ht ht
  · 

Proof state:
case inl
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
ht : Subsingleton α
⊢ 0⁻¹ = 0

Next tactic:
simp [eq_iff_true_of_subsingleton]
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  cases' subsingleton_or_nontrivial α with ht ht
  · simp [eq_iff_true_of_subsingleton]
  

Proof state:
case inr
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
ht : Nontrivial α
⊢ 0⁻¹ = 0

Next tactic:
rcases (Fintype.card n).zero_le.eq_or_lt with hc | hc
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  cases' subsingleton_or_nontrivial α with ht ht
  · simp [eq_iff_true_of_subsingleton]
  rcases (Fintype.card n).zero_le.eq_or_lt with hc | hc
  · 

Proof state:
case inr.inl
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
ht : Nontrivial α
hc : 0 = Fintype.card n
⊢ 0⁻¹ = 0

Next tactic:
rw [eq_comm, Fintype.card_eq_zero_iff] at hc
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  cases' subsingleton_or_nontrivial α with ht ht
  · simp [eq_iff_true_of_subsingleton]
  rcases (Fintype.card n).zero_le.eq_or_lt with hc | hc
  · rw [eq_comm, Fintype.card_eq_zero_iff] at hc
    

Proof state:
case inr.inl
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
ht : Nontrivial α
hc : IsEmpty n
⊢ 0⁻¹ = 0

Next tactic:
haveI := hc
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  cases' subsingleton_or_nontrivial α with ht ht
  · simp [eq_iff_true_of_subsingleton]
  rcases (Fintype.card n).zero_le.eq_or_lt with hc | hc
  · rw [eq_comm, Fintype.card_eq_zero_iff] at hc
    haveI := hc
    

Proof state:
case inr.inl
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
ht : Nontrivial α
hc this : IsEmpty n
⊢ 0⁻¹ = 0

Next tactic:
ext i
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  cases' subsingleton_or_nontrivial α with ht ht
  · simp [eq_iff_true_of_subsingleton]
  rcases (Fintype.card n).zero_le.eq_or_lt with hc | hc
  · rw [eq_comm, Fintype.card_eq_zero_iff] at hc
    haveI := hc
    ext i
    

Proof state:
case inr.inl.a.h
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
ht : Nontrivial α
hc this : IsEmpty n
i x✝ : n
⊢ 0⁻¹ i x✝ = OfNat.ofNat 0 i x✝

Next tactic:
exact (IsEmpty.false i).elim
@[simp]
theorem inv_zero : (0 : Matrix n n α)⁻¹ = 0 := by
  cases' subsingleton_or_nontrivial α with ht ht
  · simp [eq_iff_true_of_subsingleton]
  rcases (Fintype.card n).zero_le.eq_or_lt with hc | hc
  · rw [eq_comm, Fintype.card_eq_zero_iff] at hc
    haveI := hc
    ext i
    exact (IsEmpty.false i).elim
  · 

Proof state:
case inr.inr
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
ht : Nontrivial α
hc : 0 < Fintype.card n
⊢ 0⁻¹ = 0

Next tactic:
have hn : Nonempty n := Fintype.card_pos_iff.mp hc