l3lab/ntp-mathlib huggingface dataset:
/-- **Diagonalization theorem**, **spectral theorem** for matrices; A hermitian matrix can be
diagonalized by a change of basis.

For the spectral theorem on linear maps, see
`LinearMap.IsSymmetric.eigenvectorBasis_apply_self_apply`. -/
theorem spectral_theorem :
    hA.eigenvectorMatrixInv * A = diagonal ((↑) ∘ hA.eigenvalues) * hA.eigenvectorMatrixInv := by
  rw [eigenvectorMatrixInv, PiLp.basis_toMatrix_basisFun_mul]
  ext i j
  have := isHermitian_iff_isSymmetric.1 hA
  convert this.eigenvectorBasis_apply_self_apply finrank_euclideanSpace (EuclideanSpace.single j 1)
    ((Fintype.equivOfCardEq (Fintype.card_fin _)).symm i) using 1
  · dsimp only [EuclideanSpace.single, toEuclideanLin_piLp_equiv_symm, toLin'_apply,
      Matrix.of_apply, IsHermitian.eigenvectorBasis]
    

Proof state:
case h.e'_2
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i j : n
this : LinearMap.IsSymmetric (toEuclideanLin A)
⊢ ((OrthonormalBasis.toBasis
            (OrthonormalBasis.reindex
              (LinearMap.IsSymmetric.eigenvectorBasis (_ : LinearMap.IsSymmetric (toEuclideanLin A))
                (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n))
              (Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)))).repr
        ((WithLp.equiv 2 (n → 𝕜)).symm (Aᵀ j)))
      i =
    (LinearMap.IsSymmetric.eigenvectorBasis this
          (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n)).repr
      ((WithLp.equiv 2 (n → 𝕜)).symm (mulVec A (Pi.single j 1)))
      ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i)

Next tactic:
simp_rw [mulVec_single, mul_one, OrthonormalBasis.coe_toBasis_repr_apply,
      OrthonormalBasis.repr_reindex]
/-- **Diagonalization theorem**, **spectral theorem** for matrices; A hermitian matrix can be
diagonalized by a change of basis.

For the spectral theorem on linear maps, see
`LinearMap.IsSymmetric.eigenvectorBasis_apply_self_apply`. -/
theorem spectral_theorem :
    hA.eigenvectorMatrixInv * A = diagonal ((↑) ∘ hA.eigenvalues) * hA.eigenvectorMatrixInv := by
  rw [eigenvectorMatrixInv, PiLp.basis_toMatrix_basisFun_mul]
  ext i j
  have := isHermitian_iff_isSymmetric.1 hA
  convert this.eigenvectorBasis_apply_self_apply finrank_euclideanSpace (EuclideanSpace.single j 1)
    ((Fintype.equivOfCardEq (Fintype.card_fin _)).symm i) using 1
  · dsimp only [EuclideanSpace.single, toEuclideanLin_piLp_equiv_symm, toLin'_apply,
      Matrix.of_apply, IsHermitian.eigenvectorBasis]
    simp_rw [mulVec_single, mul_one, OrthonormalBasis.coe_toBasis_repr_apply,
      OrthonormalBasis.repr_reindex]
    

Proof state:
case h.e'_2
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i j : n
this : LinearMap.IsSymmetric (toEuclideanLin A)
⊢ (LinearMap.IsSymmetric.eigenvectorBasis (_ : LinearMap.IsSymmetric (toEuclideanLin A))
          (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n)).repr
      ((WithLp.equiv 2 (n → 𝕜)).symm (Aᵀ j))
      ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i) =
    (LinearMap.IsSymmetric.eigenvectorBasis this
          (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n)).repr
      ((WithLp.equiv 2 (n → 𝕜)).symm fun i => A i j)
      ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i)

Next tactic:
rfl
/-- **Diagonalization theorem**, **spectral theorem** for matrices; A hermitian matrix can be
diagonalized by a change of basis.

For the spectral theorem on linear maps, see
`LinearMap.IsSymmetric.eigenvectorBasis_apply_self_apply`. -/
theorem spectral_theorem :
    hA.eigenvectorMatrixInv * A = diagonal ((↑) ∘ hA.eigenvalues) * hA.eigenvectorMatrixInv := by
  rw [eigenvectorMatrixInv, PiLp.basis_toMatrix_basisFun_mul]
  ext i j
  have := isHermitian_iff_isSymmetric.1 hA
  convert this.eigenvectorBasis_apply_self_apply finrank_euclideanSpace (EuclideanSpace.single j 1)
    ((Fintype.equivOfCardEq (Fintype.card_fin _)).symm i) using 1
  · dsimp only [EuclideanSpace.single, toEuclideanLin_piLp_equiv_symm, toLin'_apply,
      Matrix.of_apply, IsHermitian.eigenvectorBasis]
    simp_rw [mulVec_single, mul_one, OrthonormalBasis.coe_toBasis_repr_apply,
      OrthonormalBasis.repr_reindex]
    rfl
  · 

Proof state:
case h.e'_3
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i j : n
this : LinearMap.IsSymmetric (toEuclideanLin A)
⊢ (diagonal (IsROrC.ofReal ∘ eigenvalues hA) *
        Basis.toMatrix (OrthonormalBasis.toBasis (eigenvectorBasis hA)) ⇑(PiLp.basisFun 2 𝕜 n))
      i j =
    ↑(LinearMap.IsSymmetric.eigenvalues this (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n)
          ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i)) *
      (LinearMap.IsSymmetric.eigenvectorBasis this
            (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n)).repr
        (EuclideanSpace.single j 1)
        ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i)

Next tactic:
simp only [diagonal_mul, (· ∘ ·), eigenvalues]
/-- **Diagonalization theorem**, **spectral theorem** for matrices; A hermitian matrix can be
diagonalized by a change of basis.

For the spectral theorem on linear maps, see
`LinearMap.IsSymmetric.eigenvectorBasis_apply_self_apply`. -/
theorem spectral_theorem :
    hA.eigenvectorMatrixInv * A = diagonal ((↑) ∘ hA.eigenvalues) * hA.eigenvectorMatrixInv := by
  rw [eigenvectorMatrixInv, PiLp.basis_toMatrix_basisFun_mul]
  ext i j
  have := isHermitian_iff_isSymmetric.1 hA
  convert this.eigenvectorBasis_apply_self_apply finrank_euclideanSpace (EuclideanSpace.single j 1)
    ((Fintype.equivOfCardEq (Fintype.card_fin _)).symm i) using 1
  · dsimp only [EuclideanSpace.single, toEuclideanLin_piLp_equiv_symm, toLin'_apply,
      Matrix.of_apply, IsHermitian.eigenvectorBasis]
    simp_rw [mulVec_single, mul_one, OrthonormalBasis.coe_toBasis_repr_apply,
      OrthonormalBasis.repr_reindex]
    rfl
  · simp only [diagonal_mul, (· ∘ ·), eigenvalues]
    

Proof state:
case h.e'_3
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i j : n
this : LinearMap.IsSymmetric (toEuclideanLin A)
⊢ ↑(eigenvalues₀ hA ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i)) *
      Basis.toMatrix (OrthonormalBasis.toBasis (eigenvectorBasis hA)) (⇑(PiLp.basisFun 2 𝕜 n)) i j =
    ↑(LinearMap.IsSymmetric.eigenvalues this (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n)
          ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i)) *
      (LinearMap.IsSymmetric.eigenvectorBasis this
            (_ : FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 n) = Fintype.card n)).repr
        (EuclideanSpace.single j 1)
        ((Fintype.equivOfCardEq (_ : Fintype.card (Fin (Fintype.card n)) = Fintype.card n)).symm i)

Next tactic:
rw [eigenvectorBasis, Basis.toMatrix_apply, OrthonormalBasis.coe_toBasis_repr_apply,
      OrthonormalBasis.repr_reindex, eigenvalues₀, PiLp.basisFun_apply, WithLp.equiv_symm_single]
theorem eigenvalues_eq (i : n) :
    hA.eigenvalues i =
      IsROrC.re (star (hA.eigenvectorMatrixᵀ i) ⬝ᵥ A.mulVec (hA.eigenvectorMatrixᵀ i)) := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
⊢ eigenvalues hA i = IsROrC.re (star ((eigenvectorMatrix hA)ᵀ i) ⬝ᵥ mulVec A ((eigenvectorMatrix hA)ᵀ i))

Next tactic:
have := hA.spectral_theorem
theorem eigenvalues_eq (i : n) :
    hA.eigenvalues i =
      IsROrC.re (star (hA.eigenvectorMatrixᵀ i) ⬝ᵥ A.mulVec (hA.eigenvectorMatrixᵀ i)) := by
  have := hA.spectral_theorem
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this : eigenvectorMatrixInv hA * A = diagonal (IsROrC.ofReal ∘ eigenvalues hA) * eigenvectorMatrixInv hA
⊢ eigenvalues hA i = IsROrC.re (star ((eigenvectorMatrix hA)ᵀ i) ⬝ᵥ mulVec A ((eigenvectorMatrix hA)ᵀ i))

Next tactic:
rw [← @Matrix.mul_inv_eq_iff_eq_mul_of_invertible (A := hA.eigenvectorMatrixInv)] at this
theorem eigenvalues_eq (i : n) :
    hA.eigenvalues i =
      IsROrC.re (star (hA.eigenvectorMatrixᵀ i) ⬝ᵥ A.mulVec (hA.eigenvectorMatrixᵀ i)) := by
  have := hA.spectral_theorem
  rw [← @Matrix.mul_inv_eq_iff_eq_mul_of_invertible (A := hA.eigenvectorMatrixInv)] at this
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this : eigenvectorMatrixInv hA * A * (eigenvectorMatrixInv hA)⁻¹ = diagonal (IsROrC.ofReal ∘ eigenvalues hA)
⊢ eigenvalues hA i = IsROrC.re (star ((eigenvectorMatrix hA)ᵀ i) ⬝ᵥ mulVec A ((eigenvectorMatrix hA)ᵀ i))

Next tactic:
have := congr_arg IsROrC.re (congr_fun (congr_fun this i) i)
theorem eigenvalues_eq (i : n) :
    hA.eigenvalues i =
      IsROrC.re (star (hA.eigenvectorMatrixᵀ i) ⬝ᵥ A.mulVec (hA.eigenvectorMatrixᵀ i)) := by
  have := hA.spectral_theorem
  rw [← @Matrix.mul_inv_eq_iff_eq_mul_of_invertible (A := hA.eigenvectorMatrixInv)] at this
  have := congr_arg IsROrC.re (congr_fun (congr_fun this i) i)
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this✝ : eigenvectorMatrixInv hA * A * (eigenvectorMatrixInv hA)⁻¹ = diagonal (IsROrC.ofReal ∘ eigenvalues hA)
this :
  IsROrC.re ((eigenvectorMatrixInv hA * A * (eigenvectorMatrixInv hA)⁻¹) i i) =
    IsROrC.re (diagonal (IsROrC.ofReal ∘ eigenvalues hA) i i)
⊢ eigenvalues hA i = IsROrC.re (star ((eigenvectorMatrix hA)ᵀ i) ⬝ᵥ mulVec A ((eigenvectorMatrix hA)ᵀ i))

Next tactic:
rw [diagonal_apply_eq, Function.comp_apply, IsROrC.ofReal_re,
    inv_eq_left_inv hA.eigenvectorMatrix_mul_inv, ← conjTranspose_eigenvectorMatrix, mul_mul_apply]
    at this
theorem eigenvalues_eq (i : n) :
    hA.eigenvalues i =
      IsROrC.re (star (hA.eigenvectorMatrixᵀ i) ⬝ᵥ A.mulVec (hA.eigenvectorMatrixᵀ i)) := by
  have := hA.spectral_theorem
  rw [← @Matrix.mul_inv_eq_iff_eq_mul_of_invertible (A := hA.eigenvectorMatrixInv)] at this
  have := congr_arg IsROrC.re (congr_fun (congr_fun this i) i)
  rw [diagonal_apply_eq, Function.comp_apply, IsROrC.ofReal_re,
    inv_eq_left_inv hA.eigenvectorMatrix_mul_inv, ← conjTranspose_eigenvectorMatrix, mul_mul_apply]
    at this
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this✝ : eigenvectorMatrixInv hA * A * (eigenvectorMatrixInv hA)⁻¹ = diagonal (IsROrC.ofReal ∘ eigenvalues hA)
this : IsROrC.re ((eigenvectorMatrix hA)ᴴ i ⬝ᵥ mulVec A ((eigenvectorMatrix hA)ᵀ i)) = eigenvalues hA i
⊢ eigenvalues hA i = IsROrC.re (star ((eigenvectorMatrix hA)ᵀ i) ⬝ᵥ mulVec A ((eigenvectorMatrix hA)ᵀ i))

Next tactic:
exact this.symm
/-- The determinant of a hermitian matrix is the product of its eigenvalues. -/
theorem det_eq_prod_eigenvalues : det A = ∏ i, (hA.eigenvalues i : 𝕜) := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
⊢ det A = ∏ i : n, ↑(eigenvalues hA i)

Next tactic:
apply mul_left_cancel₀ (det_ne_zero_of_left_inverse (eigenvectorMatrix_mul_inv hA))
/-- The determinant of a hermitian matrix is the product of its eigenvalues. -/
theorem det_eq_prod_eigenvalues : det A = ∏ i, (hA.eigenvalues i : 𝕜) := by
  apply mul_left_cancel₀ (det_ne_zero_of_left_inverse (eigenvectorMatrix_mul_inv hA))
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
⊢ det (eigenvectorMatrixInv hA) * det A = det (eigenvectorMatrixInv hA) * ∏ i : n, ↑(eigenvalues hA i)

Next tactic:
rw [← det_mul, spectral_theorem, det_mul, mul_comm, det_diagonal]
/-- The determinant of a hermitian matrix is the product of its eigenvalues. -/
theorem det_eq_prod_eigenvalues : det A = ∏ i, (hA.eigenvalues i : 𝕜) := by
  apply mul_left_cancel₀ (det_ne_zero_of_left_inverse (eigenvectorMatrix_mul_inv hA))
  rw [← det_mul, spectral_theorem, det_mul, mul_comm, det_diagonal]
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
⊢ det (eigenvectorMatrixInv hA) * ∏ i : n, (IsROrC.ofReal ∘ eigenvalues hA) i =
    det (eigenvectorMatrixInv hA) * ∏ i : n, ↑(eigenvalues hA i)

Next tactic:
simp_rw [Function.comp_apply]
/-- *spectral theorem* (Alternate form for convenience) A hermitian matrix can be can be
replaced by a diagonal matrix sandwiched between the eigenvector matrices. This alternate form
allows direct rewriting of A since: $ A = V D V⁻¹$ -/
lemma spectral_theorem' :
    A = hA.eigenvectorMatrix * diagonal ((↑) ∘ hA.eigenvalues) * hA.eigenvectorMatrixInv := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
⊢ A = eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA) * eigenvectorMatrixInv hA

Next tactic:
simpa [ ← Matrix.mul_assoc, hA.eigenvectorMatrix_mul_inv, Matrix.one_mul] using
    congr_arg (hA.eigenvectorMatrix * ·) hA.spectral_theorem
/-- rank of a hermitian matrix is the rank of after diagonalization by the eigenvector matrix -/
lemma rank_eq_rank_diagonal : A.rank = (Matrix.diagonal hA.eigenvalues).rank := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
⊢ rank A = rank (diagonal (eigenvalues hA))

Next tactic:
conv_lhs => rw [hA.spectral_theorem']
/-- rank of a hermitian matrix is the rank of after diagonalization by the eigenvector matrix -/
lemma rank_eq_rank_diagonal : A.rank = (Matrix.diagonal hA.eigenvalues).rank := by
  conv_lhs => 

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
| rank A

Next tactic:
rw [hA.spectral_theorem']
/-- rank of a hermitian matrix is the rank of after diagonalization by the eigenvector matrix -/
lemma rank_eq_rank_diagonal : A.rank = (Matrix.diagonal hA.eigenvalues).rank := by
  conv_lhs => rw [hA.spectral_theorem']
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
⊢ rank (eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA) * eigenvectorMatrixInv hA) =
    rank (diagonal (eigenvalues hA))

Next tactic:
have hE := isUnit_det_of_invertible (hA.eigenvectorMatrix)
/-- rank of a hermitian matrix is the rank of after diagonalization by the eigenvector matrix -/
lemma rank_eq_rank_diagonal : A.rank = (Matrix.diagonal hA.eigenvalues).rank := by
  conv_lhs => rw [hA.spectral_theorem']
  have hE := isUnit_det_of_invertible (hA.eigenvectorMatrix)
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
hE : IsUnit (det (eigenvectorMatrix hA))
⊢ rank (eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA) * eigenvectorMatrixInv hA) =
    rank (diagonal (eigenvalues hA))

Next tactic:
have hiE := isUnit_det_of_invertible (hA.eigenvectorMatrixInv)
/-- rank of a hermitian matrix is the rank of after diagonalization by the eigenvector matrix -/
lemma rank_eq_rank_diagonal : A.rank = (Matrix.diagonal hA.eigenvalues).rank := by
  conv_lhs => rw [hA.spectral_theorem']
  have hE := isUnit_det_of_invertible (hA.eigenvectorMatrix)
  have hiE := isUnit_det_of_invertible (hA.eigenvectorMatrixInv)
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
hE : IsUnit (det (eigenvectorMatrix hA))
hiE : IsUnit (det (eigenvectorMatrixInv hA))
⊢ rank (eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA) * eigenvectorMatrixInv hA) =
    rank (diagonal (eigenvalues hA))

Next tactic:
simp only [rank_mul_eq_right_of_isUnit_det hA.eigenvectorMatrix _ hE,
    rank_mul_eq_left_of_isUnit_det hA.eigenvectorMatrixInv _ hiE,
    rank_diagonal, Function.comp_apply, ne_eq, algebraMap.lift_map_eq_zero_iff]
/-- rank of a hermitian matrix is the number of nonzero eigenvalues of the hermitian matrix -/
lemma rank_eq_card_non_zero_eigs : A.rank = Fintype.card {i // hA.eigenvalues i ≠ 0} := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
⊢ rank A = Fintype.card { i // eigenvalues hA i ≠ 0 }

Next tactic:
rw [rank_eq_rank_diagonal hA, Matrix.rank_diagonal]
/-- The entries of `eigenvectorBasis` are eigenvectors. -/
lemma mulVec_eigenvectorBasis (i : n) :
    mulVec A (hA.eigenvectorBasis i) = hA.eigenvalues i • hA.eigenvectorBasis i := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
⊢ mulVec A ((eigenvectorBasis hA) i) = eigenvalues hA i • (eigenvectorBasis hA) i

Next tactic:
have := congr_arg (· * hA.eigenvectorMatrix) hA.spectral_theorem'
/-- The entries of `eigenvectorBasis` are eigenvectors. -/
lemma mulVec_eigenvectorBasis (i : n) :
    mulVec A (hA.eigenvectorBasis i) = hA.eigenvalues i • hA.eigenvectorBasis i := by
  have := congr_arg (· * hA.eigenvectorMatrix) hA.spectral_theorem'
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this :
  (fun x => x * eigenvectorMatrix hA) A =
    (fun x => x * eigenvectorMatrix hA)
      (eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA) * eigenvectorMatrixInv hA)
⊢ mulVec A ((eigenvectorBasis hA) i) = eigenvalues hA i • (eigenvectorBasis hA) i

Next tactic:
simp only [mul_assoc, mul_eq_one_comm.mp hA.eigenvectorMatrix_mul_inv, mul_one] at this
/-- The entries of `eigenvectorBasis` are eigenvectors. -/
lemma mulVec_eigenvectorBasis (i : n) :
    mulVec A (hA.eigenvectorBasis i) = hA.eigenvalues i • hA.eigenvectorBasis i := by
  have := congr_arg (· * hA.eigenvectorMatrix) hA.spectral_theorem'
  simp only [mul_assoc, mul_eq_one_comm.mp hA.eigenvectorMatrix_mul_inv, mul_one] at this
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this : A * eigenvectorMatrix hA = eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA)
⊢ mulVec A ((eigenvectorBasis hA) i) = eigenvalues hA i • (eigenvectorBasis hA) i

Next tactic:
ext1 j
/-- The entries of `eigenvectorBasis` are eigenvectors. -/
lemma mulVec_eigenvectorBasis (i : n) :
    mulVec A (hA.eigenvectorBasis i) = hA.eigenvalues i • hA.eigenvectorBasis i := by
  have := congr_arg (· * hA.eigenvectorMatrix) hA.spectral_theorem'
  simp only [mul_assoc, mul_eq_one_comm.mp hA.eigenvectorMatrix_mul_inv, mul_one] at this
  ext1 j
  

Proof state:
case h
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this : A * eigenvectorMatrix hA = eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA)
j : n
⊢ mulVec A ((eigenvectorBasis hA) i) j = (eigenvalues hA i • (eigenvectorBasis hA) i) j

Next tactic:
have := congr_fun (congr_fun this j) i
/-- The entries of `eigenvectorBasis` are eigenvectors. -/
lemma mulVec_eigenvectorBasis (i : n) :
    mulVec A (hA.eigenvectorBasis i) = hA.eigenvalues i • hA.eigenvectorBasis i := by
  have := congr_arg (· * hA.eigenvectorMatrix) hA.spectral_theorem'
  simp only [mul_assoc, mul_eq_one_comm.mp hA.eigenvectorMatrix_mul_inv, mul_one] at this
  ext1 j
  have := congr_fun (congr_fun this j) i
  

Proof state:
case h
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this✝ : A * eigenvectorMatrix hA = eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA)
j : n
this : (A * eigenvectorMatrix hA) j i = (eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA)) j i
⊢ mulVec A ((eigenvectorBasis hA) i) j = (eigenvalues hA i • (eigenvectorBasis hA) i) j

Next tactic:
simp only [mul_diagonal, Function.comp_apply] at this
/-- The entries of `eigenvectorBasis` are eigenvectors. -/
lemma mulVec_eigenvectorBasis (i : n) :
    mulVec A (hA.eigenvectorBasis i) = hA.eigenvalues i • hA.eigenvectorBasis i := by
  have := congr_arg (· * hA.eigenvectorMatrix) hA.spectral_theorem'
  simp only [mul_assoc, mul_eq_one_comm.mp hA.eigenvectorMatrix_mul_inv, mul_one] at this
  ext1 j
  have := congr_fun (congr_fun this j) i
  simp only [mul_diagonal, Function.comp_apply] at this
  

Proof state:
case h
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this✝ : A * eigenvectorMatrix hA = eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA)
j : n
this : (A * eigenvectorMatrix hA) j i = eigenvectorMatrix hA j i * ↑(eigenvalues hA i)
⊢ mulVec A ((eigenvectorBasis hA) i) j = (eigenvalues hA i • (eigenvectorBasis hA) i) j

Next tactic:
convert this using 1
/-- The entries of `eigenvectorBasis` are eigenvectors. -/
lemma mulVec_eigenvectorBasis (i : n) :
    mulVec A (hA.eigenvectorBasis i) = hA.eigenvalues i • hA.eigenvectorBasis i := by
  have := congr_arg (· * hA.eigenvectorMatrix) hA.spectral_theorem'
  simp only [mul_assoc, mul_eq_one_comm.mp hA.eigenvectorMatrix_mul_inv, mul_one] at this
  ext1 j
  have := congr_fun (congr_fun this j) i
  simp only [mul_diagonal, Function.comp_apply] at this
  convert this using 1
  

Proof state:
case h.e'_3
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
i : n
this✝ : A * eigenvectorMatrix hA = eigenvectorMatrix hA * diagonal (IsROrC.ofReal ∘ eigenvalues hA)
j : n
this : (A * eigenvectorMatrix hA) j i = eigenvectorMatrix hA j i * ↑(eigenvalues hA i)
⊢ (eigenvalues hA i • (eigenvectorBasis hA) i) j = eigenvectorMatrix hA j i * ↑(eigenvalues hA i)

Next tactic:
rw [mul_comm, Pi.smul_apply, IsROrC.real_smul_eq_coe_mul, hA.eigenvectorMatrix_apply]
/-- A nonzero Hermitian matrix has an eigenvector with nonzero eigenvalue. -/
lemma exists_eigenvector_of_ne_zero (h_ne : A ≠ 0) :
    ∃ (v : n → 𝕜) (t : ℝ), t ≠ 0 ∧ v ≠ 0 ∧ mulVec A v = t • v := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
h_ne : A ≠ 0
⊢ ∃ v t, t ≠ 0 ∧ v ≠ 0 ∧ mulVec A v = t • v

Next tactic:
have : hA.eigenvalues ≠ 0
/-- A nonzero Hermitian matrix has an eigenvector with nonzero eigenvalue. -/
lemma exists_eigenvector_of_ne_zero (h_ne : A ≠ 0) :
    ∃ (v : n → 𝕜) (t : ℝ), t ≠ 0 ∧ v ≠ 0 ∧ mulVec A v = t • v := by
  have : hA.eigenvalues ≠ 0
  · 

Proof state:
case this
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
h_ne : A ≠ 0
⊢ eigenvalues hA ≠ 0

Next tactic:
contrapose! h_ne
/-- A nonzero Hermitian matrix has an eigenvector with nonzero eigenvalue. -/
lemma exists_eigenvector_of_ne_zero (h_ne : A ≠ 0) :
    ∃ (v : n → 𝕜) (t : ℝ), t ≠ 0 ∧ v ≠ 0 ∧ mulVec A v = t • v := by
  have : hA.eigenvalues ≠ 0
  · contrapose! h_ne
    

Proof state:
case this
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : Type u_2
inst✝¹ : Fintype n
inst✝ : DecidableEq n
A : Matrix n n 𝕜
hA : IsHermitian A
h_ne : eigenvalues hA = 0
⊢ A = 0

Next tactic:
have := hA.spectral_theorem'