l3lab/ntp-mathlib huggingface dataset:
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    convert hA; rw [← LinearEquiv.eq_symm_apply]; 

Proof state:
case h.e'_3.h.e'_6
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
hA : IsUnit (det A)
b : Basis m R (m → R) := Pi.basisFun R m
⊢ mulVecLin A = (LinearEquiv.symm (LinearMap.toMatrix b b)) A

Next tactic:
rfl
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    convert hA; rw [← LinearEquiv.eq_symm_apply]; rfl
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
b : Basis m R (m → R) := Pi.basisFun R m
hA : IsUnit (det ((LinearMap.toMatrix b b) (mulVecLin A)))
⊢ rank (A * B) = rank B

Next tactic:
have hAB : mulVecLin (A * B) = (LinearEquiv.ofIsUnitDet hA).comp (mulVecLin B) := by ext; simp
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    convert hA; rw [← LinearEquiv.eq_symm_apply]; rfl
  have hAB : mulVecLin (A * B) = (LinearEquiv.ofIsUnitDet hA).comp (mulVecLin B) := by 

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
b : Basis m R (m → R) := Pi.basisFun R m
hA : IsUnit (det ((LinearMap.toMatrix b b) (mulVecLin A)))
⊢ mulVecLin (A * B) = ↑(LinearEquiv.ofIsUnitDet hA) ∘ₗ mulVecLin B

Next tactic:
ext
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    convert hA; rw [← LinearEquiv.eq_symm_apply]; rfl
  have hAB : mulVecLin (A * B) = (LinearEquiv.ofIsUnitDet hA).comp (mulVecLin B) := by ext; 

Proof state:
case h.h
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
b : Basis m R (m → R) := Pi.basisFun R m
hA : IsUnit (det ((LinearMap.toMatrix b b) (mulVecLin A)))
x✝¹ : n → R
x✝ : m
⊢ (mulVecLin (A * B)) x✝¹ x✝ = (↑(LinearEquiv.ofIsUnitDet hA) ∘ₗ mulVecLin B) x✝¹ x✝

Next tactic:
simp
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    convert hA; rw [← LinearEquiv.eq_symm_apply]; rfl
  have hAB : mulVecLin (A * B) = (LinearEquiv.ofIsUnitDet hA).comp (mulVecLin B) := by ext; simp
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
b : Basis m R (m → R) := Pi.basisFun R m
hA : IsUnit (det ((LinearMap.toMatrix b b) (mulVecLin A)))
hAB : mulVecLin (A * B) = ↑(LinearEquiv.ofIsUnitDet hA) ∘ₗ mulVecLin B
⊢ rank (A * B) = rank B

Next tactic:
rw [rank, rank, hAB, LinearMap.range_comp, LinearEquiv.finrank_map_eq]
/-- Taking a subset of the rows and permuting the columns reduces the rank. -/
theorem rank_submatrix_le [StrongRankCondition R] [Fintype m] (f : n → m) (e : n ≃ m)
    (A : Matrix m m R) : rank (A.submatrix f e) ≤ rank A := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : Fintype m
f : n → m
e : n ≃ m
A : Matrix m m R
⊢ rank (submatrix A f ⇑e) ≤ rank A

Next tactic:
rw [rank, rank, mulVecLin_submatrix, LinearMap.range_comp, LinearMap.range_comp,
    show LinearMap.funLeft R R e.symm = LinearEquiv.funCongrLeft R R e.symm from rfl,
    LinearEquiv.range, Submodule.map_top]
/-- Taking a subset of the rows and permuting the columns reduces the rank. -/
theorem rank_submatrix_le [StrongRankCondition R] [Fintype m] (f : n → m) (e : n ≃ m)
    (A : Matrix m m R) : rank (A.submatrix f e) ≤ rank A := by
  rw [rank, rank, mulVecLin_submatrix, LinearMap.range_comp, LinearMap.range_comp,
    show LinearMap.funLeft R R e.symm = LinearEquiv.funCongrLeft R R e.symm from rfl,
    LinearEquiv.range, Submodule.map_top]
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : Fintype m
f : n → m
e : n ≃ m
A : Matrix m m R
⊢ finrank R ↥(Submodule.map (LinearMap.funLeft R R f) (LinearMap.range (mulVecLin A))) ≤
    finrank R ↥(LinearMap.range (mulVecLin A))

Next tactic:
exact Submodule.finrank_map_le _ _
theorem rank_reindex [Fintype m] (e₁ e₂ : m ≃ n) (A : Matrix m m R) :
    rank (reindex e₁ e₂ A) = rank A := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : Fintype m
e₁ e₂ : m ≃ n
A : Matrix m m R
⊢ rank ((reindex e₁ e₂) A) = rank A

Next tactic:
rw [rank, rank, mulVecLin_reindex, LinearMap.range_comp, LinearMap.range_comp,
    LinearEquiv.range, Submodule.map_top, LinearEquiv.finrank_map_eq]
@[simp]
theorem rank_submatrix [Fintype m] (A : Matrix m m R) (e₁ e₂ : n ≃ m) :
    rank (A.submatrix e₁ e₂) = rank A := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : Fintype m
A : Matrix m m R
e₁ e₂ : n ≃ m
⊢ rank (submatrix A ⇑e₁ ⇑e₂) = rank A

Next tactic:
simpa only [reindex_apply] using rank_reindex e₁.symm e₂.symm A
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
⊢ rank A = finrank R ↥(LinearMap.range ((toLin v₂ v₁) A))

Next tactic:
let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
⊢ rank A = finrank R ↥(LinearMap.range ((toLin v₂ v₁) A))

Next tactic:
let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
⊢ rank A = finrank R ↥(LinearMap.range ((toLin v₂ v₁) A))

Next tactic:
have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
⊢ LinearMap.range e₂ = ⊤

Next tactic:
rw [LinearMap.range_eq_top]
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
⊢ Function.Surjective ⇑e₂

Next tactic:
exact e₂.surjective
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
⊢ rank A = finrank R ↥(LinearMap.range ((toLin v₂ v₁) A))

Next tactic:
refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
⊢ Submodule.map (↑e₁) (LinearMap.range (mulVecLin A)) = LinearMap.range ((toLin v₂ v₁) A)

Next tactic:
rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
⊢ LinearMap.range (↑e₁ ∘ₗ mulVecLin A) = LinearMap.range ((toLin v₂ v₁) A ∘ₗ ↑e₂)

Next tactic:
congr 1
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
  congr 1
  

Proof state:
case e_f
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
⊢ ↑e₁ ∘ₗ mulVecLin A = (toLin v₂ v₁) A ∘ₗ ↑e₂

Next tactic:
apply LinearMap.pi_ext'
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
  congr 1
  apply LinearMap.pi_ext'
  

Proof state:
case e_f.h
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
⊢ ∀ (i : n), (↑e₁ ∘ₗ mulVecLin A) ∘ₗ LinearMap.single i = ((toLin v₂ v₁) A ∘ₗ ↑e₂) ∘ₗ LinearMap.single i

Next tactic:
rintro i
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
  congr 1
  apply LinearMap.pi_ext'
  rintro i
  

Proof state:
case e_f.h
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
i : n
⊢ (↑e₁ ∘ₗ mulVecLin A) ∘ₗ LinearMap.single i = ((toLin v₂ v₁) A ∘ₗ ↑e₂) ∘ₗ LinearMap.single i

Next tactic:
apply LinearMap.ext_ring
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
  congr 1
  apply LinearMap.pi_ext'
  rintro i
  apply LinearMap.ext_ring
  

Proof state:
case e_f.h.h
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
i : n
⊢ ((↑e₁ ∘ₗ mulVecLin A) ∘ₗ LinearMap.single i) 1 = (((toLin v₂ v₁) A ∘ₗ ↑e₂) ∘ₗ LinearMap.single i) 1

Next tactic:
have aux₁ := toLin_self (Pi.basisFun R n) (Pi.basisFun R m) A i
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
  congr 1
  apply LinearMap.pi_ext'
  rintro i
  apply LinearMap.ext_ring
  have aux₁ := toLin_self (Pi.basisFun R n) (Pi.basisFun R m) A i
  

Proof state:
case e_f.h.h
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
i : n
aux₁ :
  ((toLin (Pi.basisFun R n) (Pi.basisFun R m)) A) ((Pi.basisFun R n) i) =
    Finset.sum Finset.univ fun j => A j i • (Pi.basisFun R m) j
⊢ ((↑e₁ ∘ₗ mulVecLin A) ∘ₗ LinearMap.single i) 1 = (((toLin v₂ v₁) A ∘ₗ ↑e₂) ∘ₗ LinearMap.single i) 1

Next tactic:
have aux₂ := Basis.equiv_apply (Pi.basisFun R n) i v₂
theorem rank_eq_finrank_range_toLin [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
    [AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
    (v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
  let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
  let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
  have range_e₂ : LinearMap.range e₂ = ⊤ := by
    rw [LinearMap.range_eq_top]
    exact e₂.surjective
  refine' LinearEquiv.finrank_eq (e₁.ofSubmodules _ _ _)
  rw [← LinearMap.range_comp, ← LinearMap.range_comp_of_range_eq_top (toLin v₂ v₁ A) range_e₂]
  congr 1
  apply LinearMap.pi_ext'
  rintro i
  apply LinearMap.ext_ring
  have aux₁ := toLin_self (Pi.basisFun R n) (Pi.basisFun R m) A i
  have aux₂ := Basis.equiv_apply (Pi.basisFun R n) i v₂
  

Proof state:
case e_f.h.h
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁷ : Fintype n
inst✝⁶ : Fintype o
inst✝⁵ : CommRing R
inst✝⁴ : DecidableEq n
M₁ : Type u_6
M₂ : Type u_7
inst✝³ : AddCommGroup M₁
inst✝² : AddCommGroup M₂
inst✝¹ : Module R M₁
inst✝ : Module R M₂
A : Matrix m n R
v₁ : Basis m R M₁
v₂ : Basis n R M₂
e₁ : (m → R) ≃ₗ[R] M₁ := Basis.equiv (Pi.basisFun R m) v₁ (Equiv.refl m)
e₂ : (n → R) ≃ₗ[R] M₂ := Basis.equiv (Pi.basisFun R n) v₂ (Equiv.refl n)
range_e₂ : LinearMap.range e₂ = ⊤
i : n
aux₁ :
  ((toLin (Pi.basisFun R n) (Pi.basisFun R m)) A) ((Pi.basisFun R n) i) =
    Finset.sum Finset.univ fun j => A j i • (Pi.basisFun R m) j
aux₂ : ∀ (e : n ≃ n), (Basis.equiv (Pi.basisFun R n) v₂ e) ((Pi.basisFun R n) i) = v₂ (e i)
⊢ ((↑e₁ ∘ₗ mulVecLin A) ∘ₗ LinearMap.single i) 1 = (((toLin v₂ v₁) A ∘ₗ ↑e₂) ∘ₗ LinearMap.single i) 1

Next tactic:
rw [toLin_eq_toLin', toLin'_apply'] at aux₁