linear_algebra.matrix.pos_defMathlib.LinearAlgebra.Matrix.PosDef

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -24,7 +24,7 @@ of quadratic forms.
 
 namespace Matrix
 
-variable {𝕜 : Type _} [IsROrC 𝕜] {m n : Type _} [Fintype m] [Fintype n]
+variable {𝕜 : Type _} [RCLike 𝕜] {m n : Type _} [Fintype m] [Fintype n]
 
 open scoped Matrix
 
@@ -32,7 +32,7 @@ open scoped Matrix
 /-- A matrix `M : matrix n n 𝕜` is positive definite if it is hermitian
    and `xᴴMx` is greater than zero for all nonzero `x`. -/
 def PosDef (M : Matrix n n 𝕜) :=
-  M.IsHermitian ∧ ∀ x : n → 𝕜, x ≠ 0 → 0 < IsROrC.re (dotProduct (star x) (M.mulVec x))
+  M.IsHermitian ∧ ∀ x : n → 𝕜, x ≠ 0 → 0 < RCLike.re (dotProduct (star x) (M.mulVec x))
 #align matrix.pos_def Matrix.PosDef
 -/
 
@@ -46,7 +46,7 @@ theorem PosDef.isHermitian {M : Matrix n n 𝕜} (hM : M.PosDef) : M.IsHermitian
 /-- A matrix `M : matrix n n 𝕜` is positive semidefinite if it is hermitian
    and `xᴴMx` is nonnegative for all `x`. -/
 def PosSemidef (M : Matrix n n 𝕜) :=
-  M.IsHermitian ∧ ∀ x : n → 𝕜, 0 ≤ IsROrC.re (dotProduct (star x) (M.mulVec x))
+  M.IsHermitian ∧ ∀ x : n → 𝕜, 0 ≤ RCLike.re (dotProduct (star x) (M.mulVec x))
 #align matrix.pos_semidef Matrix.PosSemidef
 -/
 
@@ -56,7 +56,7 @@ theorem PosDef.posSemidef {M : Matrix n n 𝕜} (hM : M.PosDef) : M.PosSemidef :
   refine' ⟨hM.1, _⟩
   intro x
   by_cases hx : x = 0
-  · simp only [hx, zero_dot_product, star_zero, IsROrC.zero_re']
+  · simp only [hx, zero_dot_product, star_zero, RCLike.zero_re']
   · exact le_of_lt (hM.2 x hx)
 #align matrix.pos_def.pos_semidef Matrix.PosDef.posSemidef
 -/
@@ -169,7 +169,7 @@ end QuadraticForm
 
 namespace Matrix
 
-variable {𝕜 : Type _} [IsROrC 𝕜] {n : Type _} [Fintype n]
+variable {𝕜 : Type _} [RCLike 𝕜] {n : Type _} [Fintype n]
 
 #print Matrix.NormedAddCommGroup.ofMatrix /-
 /-- A positive definite matrix `M` induces a norm `‖x‖ = sqrt (re xᴴMx)`. -/
Diff
@@ -105,7 +105,7 @@ theorem Matrix.PosDef.of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (
   by
   refine' ⟨hM, fun x hx => _⟩
   simp only [to_quadratic_form', QuadraticForm.PosDef, LinearMap.BilinForm.toQuadraticForm_apply,
-    Matrix.toBilin'_apply'] at hMq 
+    Matrix.toBilin'_apply'] at hMq
   apply hMq x hx
 #align matrix.pos_def_of_to_quadratic_form' Matrix.PosDef.of_toQuadraticForm'
 -/
@@ -160,7 +160,7 @@ theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ
     Q.toMatrix'.PosDef :=
   by
   rw [← to_quadratic_form_associated ℝ Q, ←
-    bilin_form.to_matrix'.left_inv ((associated_hom _) Q)] at hQ 
+    bilin_form.to_matrix'.left_inv ((associated_hom _) Q)] at hQ
   apply Matrix.PosDef.of_toQuadraticForm' (is_symm_to_matrix' Q) hQ
 #align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
 -/
Diff
@@ -104,7 +104,7 @@ theorem Matrix.PosDef.of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (
     (hMq : M.toQuadraticForm'.PosDef) : M.PosDef :=
   by
   refine' ⟨hM, fun x hx => _⟩
-  simp only [to_quadratic_form', QuadraticForm.PosDef, BilinForm.toQuadraticForm_apply,
+  simp only [to_quadratic_form', QuadraticForm.PosDef, LinearMap.BilinForm.toQuadraticForm_apply,
     Matrix.toBilin'_apply'] at hMq 
   apply hMq x hx
 #align matrix.pos_def_of_to_quadratic_form' Matrix.PosDef.of_toQuadraticForm'
@@ -114,7 +114,7 @@ theorem Matrix.PosDef.of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (
 theorem Matrix.PosDef.toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
     M.toQuadraticForm'.PosDef := by
   intro x hx
-  simp only [to_quadratic_form', BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
+  simp only [to_quadratic_form', LinearMap.BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
   apply hM.2 x hx
 #align matrix.pos_def_to_quadratic_form' Matrix.PosDef.toQuadraticForm'
 -/
Diff
@@ -99,24 +99,24 @@ theorem PosDef.transpose {M : Matrix n n 𝕜} (hM : M.PosDef) : Mᵀ.PosDef :=
 #align matrix.pos_def.transpose Matrix.PosDef.transpose
 -/
 
-#print Matrix.posDef_of_toQuadraticForm' /-
-theorem posDef_of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
+#print Matrix.PosDef.of_toQuadraticForm' /-
+theorem Matrix.PosDef.of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
     (hMq : M.toQuadraticForm'.PosDef) : M.PosDef :=
   by
   refine' ⟨hM, fun x hx => _⟩
   simp only [to_quadratic_form', QuadraticForm.PosDef, BilinForm.toQuadraticForm_apply,
     Matrix.toBilin'_apply'] at hMq 
   apply hMq x hx
-#align matrix.pos_def_of_to_quadratic_form' Matrix.posDef_of_toQuadraticForm'
+#align matrix.pos_def_of_to_quadratic_form' Matrix.PosDef.of_toQuadraticForm'
 -/
 
-#print Matrix.posDef_toQuadraticForm' /-
-theorem posDef_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
+#print Matrix.PosDef.toQuadraticForm' /-
+theorem Matrix.PosDef.toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
     M.toQuadraticForm'.PosDef := by
   intro x hx
   simp only [to_quadratic_form', BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
   apply hM.2 x hx
-#align matrix.pos_def_to_quadratic_form' Matrix.posDef_toQuadraticForm'
+#align matrix.pos_def_to_quadratic_form' Matrix.PosDef.toQuadraticForm'
 -/
 
 namespace PosDef
@@ -151,7 +151,7 @@ theorem posDef_of_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)}
     (hQ : Q.toMatrix'.PosDef) : Q.PosDef :=
   by
   rw [← to_quadratic_form_associated ℝ Q, ← bilin_form.to_matrix'.left_inv ((associated_hom _) Q)]
-  apply Matrix.posDef_toQuadraticForm' hQ
+  apply Matrix.PosDef.toQuadraticForm' hQ
 #align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDef_of_toMatrix'
 -/
 
@@ -161,7 +161,7 @@ theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ
   by
   rw [← to_quadratic_form_associated ℝ Q, ←
     bilin_form.to_matrix'.left_inv ((associated_hom _) Q)] at hQ 
-  apply Matrix.posDef_of_toQuadraticForm' (is_symm_to_matrix' Q) hQ
+  apply Matrix.PosDef.of_toQuadraticForm' (is_symm_to_matrix' Q) hQ
 #align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
 -/
 
@@ -188,7 +188,7 @@ noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosD
         · exact le_of_lt (hM.2 x h)
       definite := fun x (hx : dotProduct _ _ = 0) =>
         by
-        by_contra' h
+        by_contra! h
         simpa [hx, lt_irrefl] using hM.2 x h
       add_left := by simp only [star_add, add_dot_product, eq_self_iff_true, forall_const]
       smul_left := fun x y r => by
Diff
@@ -3,8 +3,8 @@ Copyright (c) 2022 Alexander Bentkamp. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Alexander Bentkamp
 -/
-import Mathbin.LinearAlgebra.Matrix.Spectrum
-import Mathbin.LinearAlgebra.QuadraticForm.Basic
+import LinearAlgebra.Matrix.Spectrum
+import LinearAlgebra.QuadraticForm.Basic
 
 #align_import linear_algebra.matrix.pos_def from "leanprover-community/mathlib"@"cff8231f04dfa33fd8f2f45792eebd862ef30cad"
 
Diff
@@ -2,15 +2,12 @@
 Copyright (c) 2022 Alexander Bentkamp. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Alexander Bentkamp
-
-! This file was ported from Lean 3 source module linear_algebra.matrix.pos_def
-! leanprover-community/mathlib commit cff8231f04dfa33fd8f2f45792eebd862ef30cad
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.LinearAlgebra.Matrix.Spectrum
 import Mathbin.LinearAlgebra.QuadraticForm.Basic
 
+#align_import linear_algebra.matrix.pos_def from "leanprover-community/mathlib"@"cff8231f04dfa33fd8f2f45792eebd862ef30cad"
+
 /-! # Positive Definite Matrices
 
 > THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
Diff
@@ -31,22 +31,29 @@ variable {𝕜 : Type _} [IsROrC 𝕜] {m n : Type _} [Fintype m] [Fintype n]
 
 open scoped Matrix
 
+#print Matrix.PosDef /-
 /-- A matrix `M : matrix n n 𝕜` is positive definite if it is hermitian
    and `xᴴMx` is greater than zero for all nonzero `x`. -/
 def PosDef (M : Matrix n n 𝕜) :=
   M.IsHermitian ∧ ∀ x : n → 𝕜, x ≠ 0 → 0 < IsROrC.re (dotProduct (star x) (M.mulVec x))
 #align matrix.pos_def Matrix.PosDef
+-/
 
+#print Matrix.PosDef.isHermitian /-
 theorem PosDef.isHermitian {M : Matrix n n 𝕜} (hM : M.PosDef) : M.IsHermitian :=
   hM.1
 #align matrix.pos_def.is_hermitian Matrix.PosDef.isHermitian
+-/
 
+#print Matrix.PosSemidef /-
 /-- A matrix `M : matrix n n 𝕜` is positive semidefinite if it is hermitian
    and `xᴴMx` is nonnegative for all `x`. -/
 def PosSemidef (M : Matrix n n 𝕜) :=
   M.IsHermitian ∧ ∀ x : n → 𝕜, 0 ≤ IsROrC.re (dotProduct (star x) (M.mulVec x))
 #align matrix.pos_semidef Matrix.PosSemidef
+-/
 
+#print Matrix.PosDef.posSemidef /-
 theorem PosDef.posSemidef {M : Matrix n n 𝕜} (hM : M.PosDef) : M.PosSemidef :=
   by
   refine' ⟨hM.1, _⟩
@@ -55,7 +62,9 @@ theorem PosDef.posSemidef {M : Matrix n n 𝕜} (hM : M.PosDef) : M.PosSemidef :
   · simp only [hx, zero_dot_product, star_zero, IsROrC.zero_re']
   · exact le_of_lt (hM.2 x hx)
 #align matrix.pos_def.pos_semidef Matrix.PosDef.posSemidef
+-/
 
+#print Matrix.PosSemidef.submatrix /-
 theorem PosSemidef.submatrix {M : Matrix n n 𝕜} (hM : M.PosSemidef) (e : m ≃ n) :
     (M.submatrix e e).PosSemidef :=
   by
@@ -74,20 +83,26 @@ theorem PosSemidef.submatrix {M : Matrix n n 𝕜} (hM : M.PosSemidef) (e : m 
     simp only [eq_self_iff_true, imp_true_iff, Equiv.symm_apply_apply, Finset.mem_univ,
       submatrix_apply, Equiv.apply_symm_apply, Pi.star_apply]
 #align matrix.pos_semidef.submatrix Matrix.PosSemidef.submatrix
+-/
 
+#print Matrix.posSemidef_submatrix_equiv /-
 @[simp]
 theorem posSemidef_submatrix_equiv {M : Matrix n n 𝕜} (e : m ≃ n) :
     (M.submatrix e e).PosSemidef ↔ M.PosSemidef :=
   ⟨fun h => by simpa using h.submatrix e.symm, fun h => h.submatrix _⟩
 #align matrix.pos_semidef_submatrix_equiv Matrix.posSemidef_submatrix_equiv
+-/
 
+#print Matrix.PosDef.transpose /-
 theorem PosDef.transpose {M : Matrix n n 𝕜} (hM : M.PosDef) : Mᵀ.PosDef :=
   by
   refine' ⟨is_hermitian.transpose hM.1, fun x hx => _⟩
   convert hM.2 (star x) (star_ne_zero.2 hx) using 2
   rw [mul_vec_transpose, Matrix.dotProduct_mulVec, star_star, dot_product_comm]
 #align matrix.pos_def.transpose Matrix.PosDef.transpose
+-/
 
+#print Matrix.posDef_of_toQuadraticForm' /-
 theorem posDef_of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
     (hMq : M.toQuadraticForm'.PosDef) : M.PosDef :=
   by
@@ -96,18 +111,22 @@ theorem posDef_of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.
     Matrix.toBilin'_apply'] at hMq 
   apply hMq x hx
 #align matrix.pos_def_of_to_quadratic_form' Matrix.posDef_of_toQuadraticForm'
+-/
 
+#print Matrix.posDef_toQuadraticForm' /-
 theorem posDef_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
     M.toQuadraticForm'.PosDef := by
   intro x hx
   simp only [to_quadratic_form', BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
   apply hM.2 x hx
 #align matrix.pos_def_to_quadratic_form' Matrix.posDef_toQuadraticForm'
+-/
 
 namespace PosDef
 
 variable {M : Matrix n n ℝ} (hM : M.PosDef)
 
+#print Matrix.PosDef.det_pos /-
 theorem det_pos [DecidableEq n] : 0 < det M :=
   by
   rw [hM.is_hermitian.det_eq_prod_eigenvalues]
@@ -120,6 +139,7 @@ theorem det_pos [DecidableEq n] : 0 < det M :=
   simpa only [h_det, not_isUnit_zero] using
     is_unit_det_of_invertible hM.is_hermitian.eigenvector_matrixᵀ
 #align matrix.pos_def.det_pos Matrix.PosDef.det_pos
+-/
 
 end PosDef
 
@@ -129,13 +149,16 @@ namespace QuadraticForm
 
 variable {n : Type _} [Fintype n]
 
+#print QuadraticForm.posDef_of_toMatrix' /-
 theorem posDef_of_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)}
     (hQ : Q.toMatrix'.PosDef) : Q.PosDef :=
   by
   rw [← to_quadratic_form_associated ℝ Q, ← bilin_form.to_matrix'.left_inv ((associated_hom _) Q)]
   apply Matrix.posDef_toQuadraticForm' hQ
 #align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDef_of_toMatrix'
+-/
 
+#print QuadraticForm.posDef_toMatrix' /-
 theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.PosDef) :
     Q.toMatrix'.PosDef :=
   by
@@ -143,6 +166,7 @@ theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ
     bilin_form.to_matrix'.left_inv ((associated_hom _) Q)] at hQ 
   apply Matrix.posDef_of_toQuadraticForm' (is_symm_to_matrix' Q) hQ
 #align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
+-/
 
 end QuadraticForm
 
@@ -150,6 +174,7 @@ namespace Matrix
 
 variable {𝕜 : Type _} [IsROrC 𝕜] {n : Type _} [Fintype n]
 
+#print Matrix.NormedAddCommGroup.ofMatrix /-
 /-- A positive definite matrix `M` induces a norm `‖x‖ = sqrt (re xᴴMx)`. -/
 @[reducible]
 noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDef) :
@@ -172,12 +197,15 @@ noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosD
       smul_left := fun x y r => by
         rw [← smul_eq_mul, ← smul_dot_product, starRingEnd_apply, ← star_smul] }
 #align matrix.normed_add_comm_group.of_matrix Matrix.NormedAddCommGroup.ofMatrix
+-/
 
+#print Matrix.InnerProductSpace.ofMatrix /-
 /-- A positive definite matrix `M` induces an inner product `⟪x, y⟫ = xᴴMy`. -/
 def InnerProductSpace.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDef) :
     @InnerProductSpace 𝕜 (n → 𝕜) _ (NormedAddCommGroup.ofMatrix hM) :=
   InnerProductSpace.ofCore _
 #align matrix.inner_product_space.of_matrix Matrix.InnerProductSpace.ofMatrix
+-/
 
 end Matrix
 
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Alexander Bentkamp
 
 ! This file was ported from Lean 3 source module linear_algebra.matrix.pos_def
-! leanprover-community/mathlib commit 07992a1d1f7a4176c6d3f160209608be4e198566
+! leanprover-community/mathlib commit cff8231f04dfa33fd8f2f45792eebd862ef30cad
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -12,6 +12,9 @@ import Mathbin.LinearAlgebra.Matrix.Spectrum
 import Mathbin.LinearAlgebra.QuadraticForm.Basic
 
 /-! # Positive Definite Matrices
+
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
 This file defines positive (semi)definite matrices and connects the notion to positive definiteness
 of quadratic forms.
 ## Main definition
Diff
@@ -105,8 +105,6 @@ namespace PosDef
 
 variable {M : Matrix n n ℝ} (hM : M.PosDef)
 
-include hM
-
 theorem det_pos [DecidableEq n] : 0 < det M :=
   by
   rw [hM.is_hermitian.det_eq_prod_eigenvalues]
Diff
@@ -94,12 +94,12 @@ theorem posDef_of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.
   apply hMq x hx
 #align matrix.pos_def_of_to_quadratic_form' Matrix.posDef_of_toQuadraticForm'
 
-theorem posDefToQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
+theorem posDef_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
     M.toQuadraticForm'.PosDef := by
   intro x hx
   simp only [to_quadratic_form', BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
   apply hM.2 x hx
-#align matrix.pos_def_to_quadratic_form' Matrix.posDefToQuadraticForm'
+#align matrix.pos_def_to_quadratic_form' Matrix.posDef_toQuadraticForm'
 
 namespace PosDef
 
@@ -128,12 +128,12 @@ namespace QuadraticForm
 
 variable {n : Type _} [Fintype n]
 
-theorem posDefOfToMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.toMatrix'.PosDef) :
-    Q.PosDef :=
+theorem posDef_of_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)}
+    (hQ : Q.toMatrix'.PosDef) : Q.PosDef :=
   by
   rw [← to_quadratic_form_associated ℝ Q, ← bilin_form.to_matrix'.left_inv ((associated_hom _) Q)]
-  apply Matrix.posDefToQuadraticForm' hQ
-#align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDefOfToMatrix'
+  apply Matrix.posDef_toQuadraticForm' hQ
+#align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDef_of_toMatrix'
 
 theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.PosDef) :
     Q.toMatrix'.PosDef :=
Diff
@@ -90,7 +90,7 @@ theorem posDef_of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.
   by
   refine' ⟨hM, fun x hx => _⟩
   simp only [to_quadratic_form', QuadraticForm.PosDef, BilinForm.toQuadraticForm_apply,
-    Matrix.toBilin'_apply'] at hMq
+    Matrix.toBilin'_apply'] at hMq 
   apply hMq x hx
 #align matrix.pos_def_of_to_quadratic_form' Matrix.posDef_of_toQuadraticForm'
 
@@ -139,7 +139,7 @@ theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ
     Q.toMatrix'.PosDef :=
   by
   rw [← to_quadratic_form_associated ℝ Q, ←
-    bilin_form.to_matrix'.left_inv ((associated_hom _) Q)] at hQ
+    bilin_form.to_matrix'.left_inv ((associated_hom _) Q)] at hQ 
   apply Matrix.posDef_of_toQuadraticForm' (is_symm_to_matrix' Q) hQ
 #align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
 
Diff
@@ -26,7 +26,7 @@ namespace Matrix
 
 variable {𝕜 : Type _} [IsROrC 𝕜] {m n : Type _} [Fintype m] [Fintype n]
 
-open Matrix
+open scoped Matrix
 
 /-- A matrix `M : matrix n n 𝕜` is positive definite if it is hermitian
    and `xᴴMx` is greater than zero for all nonzero `x`. -/
Diff
@@ -156,7 +156,7 @@ noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosD
   @InnerProductSpace.Core.toNormedAddCommGroup _ _ _ _ _
     { inner := fun x y => dotProduct (star x) (M.mulVec y)
       conj_symm := fun x y => by
-        dsimp only [HasInner.inner] <;>
+        dsimp only [Inner.inner] <;>
           rw [star_dot_product, starRingEnd_apply, star_star, star_mul_vec, dot_product_mul_vec,
             hM.is_hermitian.eq]
       nonneg_re := fun x => by
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Alexander Bentkamp
 
 ! This file was ported from Lean 3 source module linear_algebra.matrix.pos_def
-! leanprover-community/mathlib commit 46b633fd842bef9469441c0209906f6dddd2b4f5
+! leanprover-community/mathlib commit 07992a1d1f7a4176c6d3f160209608be4e198566
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -153,18 +153,20 @@ variable {𝕜 : Type _} [IsROrC 𝕜] {n : Type _} [Fintype n]
 @[reducible]
 noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDef) :
     NormedAddCommGroup (n → 𝕜) :=
-  @InnerProductSpace.OfCore.toNormedAddCommGroup _ _ _ _ _
+  @InnerProductSpace.Core.toNormedAddCommGroup _ _ _ _ _
     { inner := fun x y => dotProduct (star x) (M.mulVec y)
       conj_symm := fun x y => by
-        rw [star_dot_product, starRingEnd_apply, star_star, star_mul_vec, dot_product_mul_vec,
-          hM.is_hermitian.eq]
+        dsimp only [HasInner.inner] <;>
+          rw [star_dot_product, starRingEnd_apply, star_star, star_mul_vec, dot_product_mul_vec,
+            hM.is_hermitian.eq]
       nonneg_re := fun x => by
         by_cases h : x = 0
         · simp [h]
         · exact le_of_lt (hM.2 x h)
-      definite := fun x hx => by
+      definite := fun x (hx : dotProduct _ _ = 0) =>
+        by
         by_contra' h
-        simpa [hx, lt_self_iff_false] using hM.2 x h
+        simpa [hx, lt_irrefl] using hM.2 x h
       add_left := by simp only [star_add, add_dot_product, eq_self_iff_true, forall_const]
       smul_left := fun x y r => by
         rw [← smul_eq_mul, ← smul_dot_product, starRingEnd_apply, ← star_smul] }
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Alexander Bentkamp
 
 ! This file was ported from Lean 3 source module linear_algebra.matrix.pos_def
-! leanprover-community/mathlib commit 3fc0b254310908f70a1a75f01147d52e53e9f8a2
+! leanprover-community/mathlib commit 46b633fd842bef9469441c0209906f6dddd2b4f5
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -149,10 +149,11 @@ namespace Matrix
 
 variable {𝕜 : Type _} [IsROrC 𝕜] {n : Type _} [Fintype n]
 
-/-- A positive definite matrix `M` induces an inner product `⟪x, y⟫ = xᴴMy`. -/
-noncomputable def InnerProductSpace.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDef) :
-    InnerProductSpace 𝕜 (n → 𝕜) :=
-  InnerProductSpace.ofCore
+/-- A positive definite matrix `M` induces a norm `‖x‖ = sqrt (re xᴴMx)`. -/
+@[reducible]
+noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDef) :
+    NormedAddCommGroup (n → 𝕜) :=
+  @InnerProductSpace.OfCore.toNormedAddCommGroup _ _ _ _ _
     { inner := fun x y => dotProduct (star x) (M.mulVec y)
       conj_symm := fun x y => by
         rw [star_dot_product, starRingEnd_apply, star_star, star_mul_vec, dot_product_mul_vec,
@@ -167,6 +168,12 @@ noncomputable def InnerProductSpace.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDe
       add_left := by simp only [star_add, add_dot_product, eq_self_iff_true, forall_const]
       smul_left := fun x y r => by
         rw [← smul_eq_mul, ← smul_dot_product, starRingEnd_apply, ← star_smul] }
+#align matrix.normed_add_comm_group.of_matrix Matrix.NormedAddCommGroup.ofMatrix
+
+/-- A positive definite matrix `M` induces an inner product `⟪x, y⟫ = xᴴMy`. -/
+def InnerProductSpace.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDef) :
+    @InnerProductSpace 𝕜 (n → 𝕜) _ (NormedAddCommGroup.ofMatrix hM) :=
+  InnerProductSpace.ofCore _
 #align matrix.inner_product_space.of_matrix Matrix.InnerProductSpace.ofMatrix
 
 end Matrix
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Alexander Bentkamp
 
 ! This file was ported from Lean 3 source module linear_algebra.matrix.pos_def
-! leanprover-community/mathlib commit 68ead6e664f4a86b2405055689683ebdcf44c177
+! leanprover-community/mathlib commit 3fc0b254310908f70a1a75f01147d52e53e9f8a2
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -154,7 +154,7 @@ noncomputable def InnerProductSpace.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDe
     InnerProductSpace 𝕜 (n → 𝕜) :=
   InnerProductSpace.ofCore
     { inner := fun x y => dotProduct (star x) (M.mulVec y)
-      conj_sym := fun x y => by
+      conj_symm := fun x y => by
         rw [star_dot_product, starRingEnd_apply, star_star, star_mul_vec, dot_product_mul_vec,
           hM.is_hermitian.eq]
       nonneg_re := fun x => by
Diff
@@ -85,14 +85,14 @@ theorem PosDef.transpose {M : Matrix n n 𝕜} (hM : M.PosDef) : Mᵀ.PosDef :=
   rw [mul_vec_transpose, Matrix.dotProduct_mulVec, star_star, dot_product_comm]
 #align matrix.pos_def.transpose Matrix.PosDef.transpose
 
-theorem posDefOfToQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
+theorem posDef_of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
     (hMq : M.toQuadraticForm'.PosDef) : M.PosDef :=
   by
   refine' ⟨hM, fun x hx => _⟩
   simp only [to_quadratic_form', QuadraticForm.PosDef, BilinForm.toQuadraticForm_apply,
     Matrix.toBilin'_apply'] at hMq
   apply hMq x hx
-#align matrix.pos_def_of_to_quadratic_form' Matrix.posDefOfToQuadraticForm'
+#align matrix.pos_def_of_to_quadratic_form' Matrix.posDef_of_toQuadraticForm'
 
 theorem posDefToQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
     M.toQuadraticForm'.PosDef := by
@@ -135,13 +135,13 @@ theorem posDefOfToMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (h
   apply Matrix.posDefToQuadraticForm' hQ
 #align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDefOfToMatrix'
 
-theorem posDefToMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.PosDef) :
+theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.PosDef) :
     Q.toMatrix'.PosDef :=
   by
   rw [← to_quadratic_form_associated ℝ Q, ←
     bilin_form.to_matrix'.left_inv ((associated_hom _) Q)] at hQ
-  apply Matrix.posDefOfToQuadraticForm' (is_symm_to_matrix' Q) hQ
-#align quadratic_form.pos_def_to_matrix' QuadraticForm.posDefToMatrix'
+  apply Matrix.posDef_of_toQuadraticForm' (is_symm_to_matrix' Q) hQ
+#align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
 
 end QuadraticForm
 

Changes in mathlib4

mathlib3
mathlib4
fix: add missing withOverApps (#12022)

This fixes the delaborators for sums, products, infimums, and supremums of pi types and matrices.

Also adds a missing whenPPOption getPPNotation to Prefunctor.obj.

Zulip thread.

Diff
@@ -143,6 +143,7 @@ open Lean PrettyPrinter.Delaborator SubExpr in
 def delabSqrt : Delab :=
   whenPPOption getPPNotation <|
   whenNotPPOption getPPAnalysisSkip <|
+  withOverApp 7 <|
   withOptionAtCurrPos `pp.analysis.skip true do
     let e ← getExpr
     guard <| e.isAppOfArity ``Matrix.PosSemidef.sqrt 7
feat: make StarOrderedRing a mixin (#11872)

This makes StarOrderedRing take StarRing as a parameter instead of extending it, and as a result moves the typeclass to Prop. It was already a mixin with respect to the order and algebraic structure. There are two primary motivations:

  1. This makes it possible to directly assume that C(α, R) is a StarOrderedRing with [StarOrderedRing C(α, R)], as currently there is no typeclass on R which would naturally guarantee this property. This is relevant as we want this type class on continuous functions for the continuous functional calculus.
  2. We will eventually want a StarOrderedRing instance on C(α, A) where A is a complex (or even real) C⋆-algebra, and making this a mixin avoids loops with StarRing.
Diff
@@ -34,7 +34,7 @@ namespace Matrix
 
 variable {m n R 𝕜 : Type*}
 variable [Fintype m] [Fintype n]
-variable [CommRing R] [PartialOrder R] [StarOrderedRing R]
+variable [CommRing R] [PartialOrder R] [StarRing R] [StarOrderedRing R]
 variable [RCLike 𝕜]
 open scoped Matrix
 
change the order of operation in zsmulRec and nsmulRec (#11451)

We change the following field in the definition of an additive commutative monoid:

 nsmul_succ : ∀ (n : ℕ) (x : G),
-  AddMonoid.nsmul (n + 1) x = x + AddMonoid.nsmul n x
+  AddMonoid.nsmul (n + 1) x = AddMonoid.nsmul n x + x

where the latter is more natural

We adjust the definitions of ^ in monoids, groups, etc. Originally there was a warning comment about why this natural order was preferred

use x * npowRec n x and not npowRec n x * x in the definition to make sure that definitional unfolding of npowRec is blocked, to avoid deep recursion issues.

but it seems to no longer apply.

Remarks on the PR :

  • pow_succ and pow_succ' have switched their meanings.
  • Most of the time, the proofs were adjusted by priming/unpriming one lemma, or exchanging left and right; a few proofs were more complicated to adjust.
  • In particular, [Mathlib/NumberTheory/RamificationInertia.lean] used Ideal.IsPrime.mul_mem_pow which is defined in [Mathlib/RingTheory/DedekindDomain/Ideal.lean]. Changing the order of operation forced me to add the symmetric lemma Ideal.IsPrime.mem_pow_mul.
  • the docstring for Cauchy condensation test in [Mathlib/Analysis/PSeries.lean] was mathematically incorrect, I added the mention that the function is antitone.
Diff
@@ -107,7 +107,7 @@ protected lemma pow [DecidableEq n] {M : Matrix n n R} (hM : M.PosSemidef) (k :
   | 0 => .one
   | 1 => by simpa using hM
   | (k + 2) => by
-    rw [pow_succ', pow_succ]
+    rw [pow_succ, pow_succ']
     simpa only [hM.isHermitian.eq] using (hM.pow k).mul_mul_conjTranspose_same M
 
 protected lemma inv [DecidableEq n] {M : Matrix n n R} (hM : M.PosSemidef) : M⁻¹.PosSemidef := by
chore: Rename IsROrC to RCLike (#10819)

IsROrC contains data, which goes against the expectation that classes prefixed with Is are prop-valued. People have been complaining about this on and off, so this PR renames IsROrC to RCLike.

Diff
@@ -35,7 +35,7 @@ namespace Matrix
 variable {m n R 𝕜 : Type*}
 variable [Fintype m] [Fintype n]
 variable [CommRing R] [PartialOrder R] [StarOrderedRing R]
-variable [IsROrC 𝕜]
+variable [RCLike 𝕜]
 open scoped Matrix
 
 /-!
@@ -62,8 +62,8 @@ theorem isHermitian {M : Matrix n n R} (hM : M.PosSemidef) : M.IsHermitian :=
   hM.1
 
 theorem re_dotProduct_nonneg {M : Matrix n n 𝕜} (hM : M.PosSemidef) (x : n → 𝕜) :
-    0 ≤ IsROrC.re (dotProduct (star x) (M *ᵥ x)) :=
-  IsROrC.nonneg_iff.mp (hM.2 _) |>.1
+    0 ≤ RCLike.re (dotProduct (star x) (M *ᵥ x)) :=
+  RCLike.nonneg_iff.mp (hM.2 _) |>.1
 
 lemma conjTranspose_mul_mul_same {A : Matrix n n R} (hA : PosSemidef A)
     {m : Type*} [Fintype m] (B : Matrix n m R) :
@@ -153,11 +153,11 @@ def delabSqrt : Delab :=
 lemma posSemidef_sqrt : PosSemidef hA.sqrt := by
   apply PosSemidef.mul_mul_conjTranspose_same
   refine posSemidef_diagonal_iff.mpr fun i ↦ ?_
-  rw [Function.comp_apply, IsROrC.nonneg_iff]
+  rw [Function.comp_apply, RCLike.nonneg_iff]
   constructor
-  · simp only [IsROrC.ofReal_re]
+  · simp only [RCLike.ofReal_re]
     exact Real.sqrt_nonneg _
-  · simp only [IsROrC.ofReal_im]
+  · simp only [RCLike.ofReal_im]
 
 @[simp]
 lemma sq_sqrt : hA.sqrt ^ 2 = A := by
@@ -174,7 +174,7 @@ lemma sq_sqrt : hA.sqrt ^ 2 = A := by
   have : E * E = diagonal ((↑) ∘ hA.1.eigenvalues) := by
     rw [diagonal_mul_diagonal]
     refine congr_arg _ (funext fun v ↦ ?_) -- why doesn't "congr with v" work?
-    simp [← pow_two, ← IsROrC.ofReal_pow, Real.sq_sqrt (hA.eigenvalues_nonneg v)]
+    simp [← pow_two, ← RCLike.ofReal_pow, Real.sq_sqrt (hA.eigenvalues_nonneg v)]
   rw [this]
   convert hA.1.spectral_theorem'.symm
   apply Matrix.IsHermitian.conjTranspose_eigenvectorMatrix
@@ -197,16 +197,16 @@ lemma eq_of_sq_eq_sq {B : Matrix n n 𝕜} (hB : PosSemidef B) (hAB : A ^ 2 = B
       rw [mulVec_mulVec, mulVec_mulVec, ← dotProduct_add, ← add_mulVec, mul_sub, sub_mul,
         add_sub, sub_add_cancel, pow_two, pow_two]
     _ = t * (star v ⬝ᵥ A *ᵥ v) + (star v) ᵥ* (A - B)ᴴ ⬝ᵥ B *ᵥ v := by
-      rw [hv', mulVec_smul, dotProduct_smul, IsROrC.real_smul_eq_coe_mul,
+      rw [hv', mulVec_smul, dotProduct_smul, RCLike.real_smul_eq_coe_mul,
         dotProduct_mulVec _ (A - B), hA.1.sub hB.1]
     _ = t * (star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v) := by
-      simp_rw [← star_mulVec, hv', mul_add, ← IsROrC.real_smul_eq_coe_mul, ← smul_dotProduct]
+      simp_rw [← star_mulVec, hv', mul_add, ← RCLike.real_smul_eq_coe_mul, ← smul_dotProduct]
       congr 2 with i
-      simp only [Pi.star_apply, Pi.smul_apply, IsROrC.real_smul_eq_coe_mul, star_mul',
-        IsROrC.star_def, IsROrC.conj_ofReal]
+      simp only [Pi.star_apply, Pi.smul_apply, RCLike.real_smul_eq_coe_mul, star_mul',
+        RCLike.star_def, RCLike.conj_ofReal]
   replace h_sum : star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v = 0 := by
     rw [eq_comm, ← mul_zero (t : 𝕜)] at h_sum
-    exact mul_left_cancel₀ (IsROrC.ofReal_ne_zero.mpr ht) h_sum
+    exact mul_left_cancel₀ (RCLike.ofReal_ne_zero.mpr ht) h_sum
   have h_van : star v ⬝ᵥ A *ᵥ v = 0 ∧ star v ⬝ᵥ B *ᵥ v = 0 := by
     refine ⟨le_antisymm ?_ (hA.2 v), le_antisymm ?_ (hB.2 v)⟩
     · rw [add_comm, add_eq_zero_iff_eq_neg] at h_sum
@@ -214,9 +214,9 @@ lemma eq_of_sq_eq_sq {B : Matrix n n 𝕜} (hB : PosSemidef B) (hAB : A ^ 2 = B
     · simpa only [add_eq_zero_iff_eq_neg.mp h_sum, neg_nonneg] using hA.2 v
   have aux : star v ⬝ᵥ (A - B) *ᵥ v = 0 := by
     rw [sub_mulVec, dotProduct_sub, h_van.1, h_van.2, sub_zero]
-  rw [hv', dotProduct_smul, IsROrC.real_smul_eq_coe_mul, ← mul_zero ↑t] at aux
+  rw [hv', dotProduct_smul, RCLike.real_smul_eq_coe_mul, ← mul_zero ↑t] at aux
   exact hv <| Matrix.dotProduct_star_self_eq_zero.mp <| mul_left_cancel₀
-    (IsROrC.ofReal_ne_zero.mpr ht) aux
+    (RCLike.ofReal_ne_zero.mpr ht) aux
 
 lemma sqrt_sq : (hA.pow 2 : PosSemidef (A ^ 2)).sqrt = A :=
   (hA.pow 2).posSemidef_sqrt.eq_of_sq_eq_sq hA (hA.pow 2).sq_sqrt
@@ -265,7 +265,7 @@ lemma IsHermitian.posSemidef_of_eigenvalues_nonneg [DecidableEq n] {A : Matrix n
     (hA : IsHermitian A) (h : ∀ i : n, 0 ≤ hA.eigenvalues i) : PosSemidef A := by
   simp_rw [hA.conjTranspose_eigenvectorMatrix.symm ▸ hA.spectral_theorem']
   refine (posSemidef_diagonal_iff.mpr fun i ↦ ?_).mul_mul_conjTranspose_same _
-  rw [IsROrC.le_iff_re_im]
+  rw [RCLike.le_iff_re_im]
   simpa using h i
 
 /-- For `A` positive semidefinite, we have `x⋆ A x = 0` iff `A x = 0`. -/
@@ -304,14 +304,14 @@ theorem isHermitian {M : Matrix n n R} (hM : M.PosDef) : M.IsHermitian :=
 #align matrix.pos_def.is_hermitian Matrix.PosDef.isHermitian
 
 theorem re_dotProduct_pos {M : Matrix n n 𝕜} (hM : M.PosDef) {x : n → 𝕜} (hx : x ≠ 0) :
-    0 < IsROrC.re (dotProduct (star x) (M *ᵥ x)) :=
-  IsROrC.pos_iff.mp (hM.2 _ hx) |>.1
+    0 < RCLike.re (dotProduct (star x) (M *ᵥ x)) :=
+  RCLike.pos_iff.mp (hM.2 _ hx) |>.1
 
 theorem posSemidef {M : Matrix n n R} (hM : M.PosDef) : M.PosSemidef := by
   refine' ⟨hM.1, _⟩
   intro x
   by_cases hx : x = 0
-  · simp only [hx, zero_dotProduct, star_zero, IsROrC.zero_re']
+  · simp only [hx, zero_dotProduct, star_zero, RCLike.zero_re']
     exact le_rfl
   · exact le_of_lt (hM.2 x hx)
 #align matrix.pos_def.pos_semidef Matrix.PosDef.posSemidef
@@ -382,7 +382,7 @@ end QuadraticForm
 
 namespace Matrix
 
-variable {𝕜 : Type*} [IsROrC 𝕜] {n : Type*} [Fintype n]
+variable {𝕜 : Type*} [RCLike 𝕜] {n : Type*} [Fintype n]
 
 /-- A positive definite matrix `M` induces a norm `‖x‖ = sqrt (re xᴴMx)`. -/
 @[reducible]
refactor(LinearAlgebra/QuadraticForm): Replace BilinForm with a scalar valued bi LinearMap (#10238)

Following on from #10097, which converted the companion of a quadratic form with a bilinear map, this PR replaces a number of results about quadratic forms and bilinear forms with results about quadratic forms and scalar valued bilinear maps. The long term aim is to be able to consider quadratic maps.

The main change is to LinearAlgebra/QuadraticForm/Basic, but this necessitates changes throughout LinearAlgebra/QuadraticForm/. Minor changes are also required elsewhere:

  • LinearAlgebra/CliffordAlgebra/
  • LinearAlgebra/Matrix/PosDef
  • LinearAlgebra/SesquilinearForm
  • A number of additional results about tensor products and linear maps are also required.

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Christopher Hoskin <christopher.hoskin@overleaf.com>

Diff
@@ -325,15 +325,16 @@ theorem transpose {M : Matrix n n R} (hM : M.PosDef) : Mᵀ.PosDef := by
 theorem of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
     (hMq : M.toQuadraticForm'.PosDef) : M.PosDef := by
   refine' ⟨hM, fun x hx => _⟩
-  simp only [toQuadraticForm', QuadraticForm.PosDef, BilinForm.toQuadraticForm_apply,
-    Matrix.toBilin'_apply'] at hMq
+  simp only [toQuadraticForm', QuadraticForm.PosDef, LinearMap.BilinForm.toQuadraticForm_apply,
+    toLinearMap₂'_apply'] at hMq
   apply hMq x hx
 #align matrix.pos_def_of_to_quadratic_form' Matrix.PosDef.of_toQuadraticForm'
 
 theorem toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
     M.toQuadraticForm'.PosDef := by
   intro x hx
-  simp only [Matrix.toQuadraticForm', BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
+  simp only [Matrix.toQuadraticForm', LinearMap.BilinForm.toQuadraticForm_apply,
+    toLinearMap₂'_apply']
   apply hM.2 x hx
 #align matrix.pos_def_to_quadratic_form' Matrix.PosDef.toQuadraticForm'
 
@@ -366,14 +367,14 @@ variable {n : Type*} [Fintype n]
 theorem posDef_of_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)}
     (hQ : Q.toMatrix'.PosDef) : Q.PosDef := by
   rw [← toQuadraticForm_associated ℝ Q,
-    ← BilinForm.toMatrix'.left_inv ((associatedHom (R := ℝ) ℝ) Q)]
+    ← LinearMap.toMatrix₂'.left_inv ((associatedHom (R := ℝ) ℝ) Q)]
   exact hQ.toQuadraticForm'
 #align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDef_of_toMatrix'
 
 theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.PosDef) :
     Q.toMatrix'.PosDef := by
   rw [← toQuadraticForm_associated ℝ Q, ←
-    BilinForm.toMatrix'.left_inv ((associatedHom (R := ℝ) ℝ) Q)] at hQ
+    LinearMap.toMatrix₂'.left_inv ((associatedHom (R := ℝ) ℝ) Q)] at hQ
   exact .of_toQuadraticForm' (isSymm_toMatrix' Q) hQ
 #align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
 
chore: move #guard_msgs in PosDef to test file (#10827)

This PR moves a #guard_msgs command from LinearAlgebra/Matrix/PosDef to a test file: it is a preparation for #10809.

Diff
@@ -150,13 +150,6 @@ def delabSqrt : Delab :=
       return (← read).optionsPerPos.setBool (← getPos) `pp.proofs.withType true
     withTheReader Context ({· with optionsPerPos}) delab
 
--- test for custom elaborator
-/--
-info: (_ : PosSemidef A).sqrt : Matrix n n 𝕜
--/
-#guard_msgs in
-#check (id hA).sqrt
-
 lemma posSemidef_sqrt : PosSemidef hA.sqrt := by
   apply PosSemidef.mul_mul_conjTranspose_same
   refine posSemidef_diagonal_iff.mpr fun i ↦ ?_
chore: remove stream-of-consciousness uses of have, replace and suffices (#10640)

No changes to tactic file, it's just boring fixes throughout the library.

This follows on from #6964.

Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -170,16 +170,16 @@ lemma posSemidef_sqrt : PosSemidef hA.sqrt := by
 lemma sq_sqrt : hA.sqrt ^ 2 = A := by
   let C := hA.1.eigenvectorMatrix
   let E := diagonal ((↑) ∘ Real.sqrt ∘ hA.1.eigenvalues : n → 𝕜)
-  suffices : C * (E * (Cᴴ * C) * E) * Cᴴ = A
-  · rw [Matrix.PosSemidef.sqrt, pow_two]
+  suffices C * (E * (Cᴴ * C) * E) * Cᴴ = A by
+    rw [Matrix.PosSemidef.sqrt, pow_two]
     change (C * E * Cᴴ) * (C * E * Cᴴ) = A
     simpa only [← mul_assoc] using this
-  have : Cᴴ * C = 1
-  · rw [Matrix.IsHermitian.conjTranspose_eigenvectorMatrix, mul_eq_one_comm]
+  have : Cᴴ * C = 1 := by
+    rw [Matrix.IsHermitian.conjTranspose_eigenvectorMatrix, mul_eq_one_comm]
     exact hA.1.eigenvectorMatrix_mul_inv
   rw [this, mul_one]
-  have : E * E = diagonal ((↑) ∘ hA.1.eigenvalues)
-  · rw [diagonal_mul_diagonal]
+  have : E * E = diagonal ((↑) ∘ hA.1.eigenvalues) := by
+    rw [diagonal_mul_diagonal]
     refine congr_arg _ (funext fun v ↦ ?_) -- why doesn't "congr with v" work?
     simp [← pow_two, ← IsROrC.ofReal_pow, Real.sq_sqrt (hA.eigenvalues_nonneg v)]
   rw [this]
@@ -198,30 +198,29 @@ lemma eq_of_sq_eq_sq {B : Matrix n n 𝕜} (hB : PosSemidef B) (hAB : A ^ 2 = B
   `⟨v, (A - B) v⟩ = 0`, but this is a nonzero scalar multiple of `⟨v, v⟩`, contradiction. -/
   by_contra h_ne
   let ⟨v, t, ht, hv, hv'⟩ := (hA.1.sub hB.1).exists_eigenvector_of_ne_zero (sub_ne_zero.mpr h_ne)
-  have h_sum : 0 = t * (star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v)
-  · calc
-      0 = star v ⬝ᵥ (A ^ 2 - B ^ 2) *ᵥ v := by rw [hAB, sub_self, zero_mulVec, dotProduct_zero]
-      _ = star v ⬝ᵥ A *ᵥ (A - B) *ᵥ v + star v ⬝ᵥ (A - B) *ᵥ B *ᵥ v := by
-        rw [mulVec_mulVec, mulVec_mulVec, ← dotProduct_add, ← add_mulVec, mul_sub, sub_mul,
-          add_sub, sub_add_cancel, pow_two, pow_two]
-      _ = t * (star v ⬝ᵥ A *ᵥ v) + (star v) ᵥ* (A - B)ᴴ ⬝ᵥ B *ᵥ v := by
-        rw [hv', mulVec_smul, dotProduct_smul, IsROrC.real_smul_eq_coe_mul,
-          dotProduct_mulVec _ (A - B), hA.1.sub hB.1]
-      _ = t * (star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v) := by
-        simp_rw [← star_mulVec, hv', mul_add, ← IsROrC.real_smul_eq_coe_mul, ← smul_dotProduct]
-        congr 2 with i
-        simp only [Pi.star_apply, Pi.smul_apply, IsROrC.real_smul_eq_coe_mul, star_mul',
-          IsROrC.star_def, IsROrC.conj_ofReal]
-  replace h_sum : star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v = 0
-  · rw [eq_comm, ← mul_zero (t : 𝕜)] at h_sum
+  have h_sum : 0 = t * (star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v) := calc
+    0 = star v ⬝ᵥ (A ^ 2 - B ^ 2) *ᵥ v := by rw [hAB, sub_self, zero_mulVec, dotProduct_zero]
+    _ = star v ⬝ᵥ A *ᵥ (A - B) *ᵥ v + star v ⬝ᵥ (A - B) *ᵥ B *ᵥ v := by
+      rw [mulVec_mulVec, mulVec_mulVec, ← dotProduct_add, ← add_mulVec, mul_sub, sub_mul,
+        add_sub, sub_add_cancel, pow_two, pow_two]
+    _ = t * (star v ⬝ᵥ A *ᵥ v) + (star v) ᵥ* (A - B)ᴴ ⬝ᵥ B *ᵥ v := by
+      rw [hv', mulVec_smul, dotProduct_smul, IsROrC.real_smul_eq_coe_mul,
+        dotProduct_mulVec _ (A - B), hA.1.sub hB.1]
+    _ = t * (star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v) := by
+      simp_rw [← star_mulVec, hv', mul_add, ← IsROrC.real_smul_eq_coe_mul, ← smul_dotProduct]
+      congr 2 with i
+      simp only [Pi.star_apply, Pi.smul_apply, IsROrC.real_smul_eq_coe_mul, star_mul',
+        IsROrC.star_def, IsROrC.conj_ofReal]
+  replace h_sum : star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v = 0 := by
+    rw [eq_comm, ← mul_zero (t : 𝕜)] at h_sum
     exact mul_left_cancel₀ (IsROrC.ofReal_ne_zero.mpr ht) h_sum
-  have h_van : star v ⬝ᵥ A *ᵥ v = 0 ∧ star v ⬝ᵥ B *ᵥ v = 0
-  · refine ⟨le_antisymm ?_ (hA.2 v), le_antisymm ?_ (hB.2 v)⟩
+  have h_van : star v ⬝ᵥ A *ᵥ v = 0 ∧ star v ⬝ᵥ B *ᵥ v = 0 := by
+    refine ⟨le_antisymm ?_ (hA.2 v), le_antisymm ?_ (hB.2 v)⟩
     · rw [add_comm, add_eq_zero_iff_eq_neg] at h_sum
       simpa only [h_sum, neg_nonneg] using hB.2 v
     · simpa only [add_eq_zero_iff_eq_neg.mp h_sum, neg_nonneg] using hA.2 v
-  have aux : star v ⬝ᵥ (A - B) *ᵥ v = 0
-  · rw [sub_mulVec, dotProduct_sub, h_van.1, h_van.2, sub_zero]
+  have aux : star v ⬝ᵥ (A - B) *ᵥ v = 0 := by
+    rw [sub_mulVec, dotProduct_sub, h_van.1, h_van.2, sub_zero]
   rw [hv', dotProduct_smul, IsROrC.real_smul_eq_coe_mul, ← mul_zero ↑t] at aux
   exact hv <| Matrix.dotProduct_star_self_eq_zero.mp <| mul_left_cancel₀
     (IsROrC.ofReal_ne_zero.mpr ht) aux
chore: Matrix.mulVec and Matrix.vecMul get infix notation (#10297)

Zulip discussion: https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/Notation.20for.20mul_vec.20and.20vec_mul

Co-authored-by: Martin Dvorak <mdvorak@ista.ac.at>

Diff
@@ -45,7 +45,7 @@ open scoped Matrix
 /-- A matrix `M : Matrix n n R` is positive semidefinite if it is Hermitian and `xᴴ * M * x` is
 nonnegative for all `x`. -/
 def PosSemidef (M : Matrix n n R) :=
-  M.IsHermitian ∧ ∀ x : n → R, 0 ≤ dotProduct (star x) (M.mulVec x)
+  M.IsHermitian ∧ ∀ x : n → R, 0 ≤ dotProduct (star x) (M *ᵥ x)
 #align matrix.pos_semidef Matrix.PosSemidef
 
 /-- A diagonal matrix is positive semidefinite iff its diagonal entries are nonnegative. -/
@@ -62,7 +62,7 @@ theorem isHermitian {M : Matrix n n R} (hM : M.PosSemidef) : M.IsHermitian :=
   hM.1
 
 theorem re_dotProduct_nonneg {M : Matrix n n 𝕜} (hM : M.PosSemidef) (x : n → 𝕜) :
-    0 ≤ IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
+    0 ≤ IsROrC.re (dotProduct (star x) (M *ᵥ x)) :=
   IsROrC.nonneg_iff.mp (hM.2 _) |>.1
 
 lemma conjTranspose_mul_mul_same {A : Matrix n n R} (hA : PosSemidef A)
@@ -71,7 +71,7 @@ lemma conjTranspose_mul_mul_same {A : Matrix n n R} (hA : PosSemidef A)
   constructor
   · exact isHermitian_conjTranspose_mul_mul B hA.1
   · intro x
-    simpa only [star_mulVec, dotProduct_mulVec, vecMul_vecMul] using hA.2 (mulVec B x)
+    simpa only [star_mulVec, dotProduct_mulVec, vecMul_vecMul] using hA.2 (B *ᵥ x)
 
 lemma mul_mul_conjTranspose_same {A : Matrix n n R} (hA : PosSemidef A)
     {m : Type*} [Fintype m] (B : Matrix m n R):
@@ -198,29 +198,29 @@ lemma eq_of_sq_eq_sq {B : Matrix n n 𝕜} (hB : PosSemidef B) (hAB : A ^ 2 = B
   `⟨v, (A - B) v⟩ = 0`, but this is a nonzero scalar multiple of `⟨v, v⟩`, contradiction. -/
   by_contra h_ne
   let ⟨v, t, ht, hv, hv'⟩ := (hA.1.sub hB.1).exists_eigenvector_of_ne_zero (sub_ne_zero.mpr h_ne)
-  have h_sum : 0 = t * (star v ⬝ᵥ mulVec A v + star v ⬝ᵥ mulVec B v)
+  have h_sum : 0 = t * (star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v)
   · calc
-      0 = star v ⬝ᵥ mulVec (A ^ 2 - B ^ 2) v := by rw [hAB, sub_self, zero_mulVec, dotProduct_zero]
-      _ = star v ⬝ᵥ mulVec A (mulVec (A - B) v)  + star v ⬝ᵥ mulVec (A - B) (mulVec B v) := by
+      0 = star v ⬝ᵥ (A ^ 2 - B ^ 2) *ᵥ v := by rw [hAB, sub_self, zero_mulVec, dotProduct_zero]
+      _ = star v ⬝ᵥ A *ᵥ (A - B) *ᵥ v + star v ⬝ᵥ (A - B) *ᵥ B *ᵥ v := by
         rw [mulVec_mulVec, mulVec_mulVec, ← dotProduct_add, ← add_mulVec, mul_sub, sub_mul,
           add_sub, sub_add_cancel, pow_two, pow_two]
-      _ = t * (star v ⬝ᵥ mulVec A v) + vecMul (star v) (A - B)ᴴ ⬝ᵥ mulVec B v := by
+      _ = t * (star v ⬝ᵥ A *ᵥ v) + (star v) ᵥ* (A - B)ᴴ ⬝ᵥ B *ᵥ v := by
         rw [hv', mulVec_smul, dotProduct_smul, IsROrC.real_smul_eq_coe_mul,
           dotProduct_mulVec _ (A - B), hA.1.sub hB.1]
-      _ = t * (star v ⬝ᵥ mulVec A v + star v ⬝ᵥ mulVec B v) := by
+      _ = t * (star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v) := by
         simp_rw [← star_mulVec, hv', mul_add, ← IsROrC.real_smul_eq_coe_mul, ← smul_dotProduct]
         congr 2 with i
         simp only [Pi.star_apply, Pi.smul_apply, IsROrC.real_smul_eq_coe_mul, star_mul',
           IsROrC.star_def, IsROrC.conj_ofReal]
-  replace h_sum : star v ⬝ᵥ mulVec A v + star v ⬝ᵥ mulVec B v = 0
+  replace h_sum : star v ⬝ᵥ A *ᵥ v + star v ⬝ᵥ B *ᵥ v = 0
   · rw [eq_comm, ← mul_zero (t : 𝕜)] at h_sum
     exact mul_left_cancel₀ (IsROrC.ofReal_ne_zero.mpr ht) h_sum
-  have h_van : star v ⬝ᵥ mulVec A v = 0 ∧ star v ⬝ᵥ mulVec B v = 0
+  have h_van : star v ⬝ᵥ A *ᵥ v = 0 ∧ star v ⬝ᵥ B *ᵥ v = 0
   · refine ⟨le_antisymm ?_ (hA.2 v), le_antisymm ?_ (hB.2 v)⟩
     · rw [add_comm, add_eq_zero_iff_eq_neg] at h_sum
       simpa only [h_sum, neg_nonneg] using hB.2 v
     · simpa only [add_eq_zero_iff_eq_neg.mp h_sum, neg_nonneg] using hA.2 v
-  have aux : star v ⬝ᵥ mulVec (A - B) v = 0
+  have aux : star v ⬝ᵥ (A - B) *ᵥ v = 0
   · rw [sub_mulVec, dotProduct_sub, h_van.1, h_van.2, sub_zero]
   rw [hv', dotProduct_smul, IsROrC.real_smul_eq_coe_mul, ← mul_zero ↑t] at aux
   exact hv <| Matrix.dotProduct_star_self_eq_zero.mp <| mul_left_cancel₀
@@ -279,7 +279,7 @@ lemma IsHermitian.posSemidef_of_eigenvalues_nonneg [DecidableEq n] {A : Matrix n
 /-- For `A` positive semidefinite, we have `x⋆ A x = 0` iff `A x = 0`. -/
 theorem PosSemidef.dotProduct_mulVec_zero_iff
     {A : Matrix n n 𝕜} (hA : PosSemidef A) (x : n → 𝕜) :
-    star x ⬝ᵥ mulVec A x = 0 ↔ mulVec A x = 0 := by
+    star x ⬝ᵥ A *ᵥ x = 0 ↔ A *ᵥ x = 0 := by
   constructor
   · obtain ⟨B, rfl⟩ := posSemidef_iff_eq_transpose_mul_self.mp hA
     rw [← Matrix.mulVec_mulVec, dotProduct_mulVec,
@@ -302,7 +302,7 @@ theorem PosSemidef.toLinearMap₂'_zero_iff [DecidableEq n]
 /-- A matrix `M : Matrix n n R` is positive definite if it is hermitian
    and `xᴴMx` is greater than zero for all nonzero `x`. -/
 def PosDef (M : Matrix n n R) :=
-  M.IsHermitian ∧ ∀ x : n → R, x ≠ 0 → 0 < dotProduct (star x) (M.mulVec x)
+  M.IsHermitian ∧ ∀ x : n → R, x ≠ 0 → 0 < dotProduct (star x) (M *ᵥ x)
 #align matrix.pos_def Matrix.PosDef
 
 namespace PosDef
@@ -312,7 +312,7 @@ theorem isHermitian {M : Matrix n n R} (hM : M.PosDef) : M.IsHermitian :=
 #align matrix.pos_def.is_hermitian Matrix.PosDef.isHermitian
 
 theorem re_dotProduct_pos {M : Matrix n n 𝕜} (hM : M.PosDef) {x : n → 𝕜} (hx : x ≠ 0) :
-    0 < IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
+    0 < IsROrC.re (dotProduct (star x) (M *ᵥ x)) :=
   IsROrC.pos_iff.mp (hM.2 _ hx) |>.1
 
 theorem posSemidef {M : Matrix n n R} (hM : M.PosDef) : M.PosSemidef := by
@@ -396,7 +396,7 @@ variable {𝕜 : Type*} [IsROrC 𝕜] {n : Type*} [Fintype n]
 noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosDef) :
     NormedAddCommGroup (n → 𝕜) :=
   @InnerProductSpace.Core.toNormedAddCommGroup _ _ _ _ _
-    { inner := fun x y => dotProduct (star x) (M.mulVec y)
+    { inner := fun x y => dotProduct (star x) (M *ᵥ y)
       conj_symm := fun x y => by
         dsimp only [Inner.inner]
         rw [star_dotProduct, starRingEnd_apply, star_star, star_mulVec, dotProduct_mulVec,
chore(LinearAlgebra,BigOperators): drop some decidability assumptions (#10237)

Found by a linter from #10235.

Diff
@@ -262,8 +262,9 @@ lemma eigenvalues_self_mul_conjTranspose_nonneg (A : Matrix m n 𝕜) [Decidable
   (posSemidef_self_mul_conjTranspose _).eigenvalues_nonneg _
 
 /-- A matrix is positive semidefinite if and only if it has the form `Bᴴ * B` for some `B`. -/
-lemma posSemidef_iff_eq_transpose_mul_self [DecidableEq n] {A : Matrix n n 𝕜} :
+lemma posSemidef_iff_eq_transpose_mul_self {A : Matrix n n 𝕜} :
     PosSemidef A ↔ ∃ (B : Matrix n n 𝕜), A = Bᴴ * B := by
+  classical
   refine ⟨fun hA ↦ ⟨hA.sqrt, ?_⟩, fun ⟨B, hB⟩ ↦ (hB ▸ posSemidef_conjTranspose_mul_self B)⟩
   simp_rw [← PosSemidef.sq_sqrt hA, pow_two]
   rw [hA.posSemidef_sqrt.1]
@@ -276,7 +277,7 @@ lemma IsHermitian.posSemidef_of_eigenvalues_nonneg [DecidableEq n] {A : Matrix n
   simpa using h i
 
 /-- For `A` positive semidefinite, we have `x⋆ A x = 0` iff `A x = 0`. -/
-theorem PosSemidef.dotProduct_mulVec_zero_iff [DecidableEq n]
+theorem PosSemidef.dotProduct_mulVec_zero_iff
     {A : Matrix n n 𝕜} (hA : PosSemidef A) (x : n → 𝕜) :
     star x ⬝ᵥ mulVec A x = 0 ↔ mulVec A x = 0 := by
   constructor
chore(*): drop $/<| before fun (#9361)

Subset of #9319

Diff
@@ -52,7 +52,7 @@ def PosSemidef (M : Matrix n n R) :=
 lemma posSemidef_diagonal_iff [DecidableEq n] {d : n → R} :
     PosSemidef (diagonal d) ↔ (∀ i : n, 0 ≤ d i) := by
   refine ⟨fun ⟨_, hP⟩ i ↦ by simpa using hP (Pi.single i 1), ?_⟩
-  refine fun hd ↦ ⟨isHermitian_diagonal_iff.2 <| fun i ↦ IsSelfAdjoint.of_nonneg (hd i), ?_⟩
+  refine fun hd ↦ ⟨isHermitian_diagonal_iff.2 fun i ↦ IsSelfAdjoint.of_nonneg (hd i), ?_⟩
   refine fun x ↦ Finset.sum_nonneg fun i _ ↦ ?_
   simpa only [mulVec_diagonal, mul_assoc] using conjugate_nonneg (hd i) _
 
feat(LinearAlgebra/Matrix/PosDef): integer powers preserve PosSemidef (#9147)
Diff
@@ -87,6 +87,13 @@ theorem submatrix {M : Matrix n n R} (hM : M.PosSemidef) (e : m → n) :
     conjTranspose_mul_mul_same hM (Matrix.submatrix 1 id e)
 #align matrix.pos_semidef.submatrix Matrix.PosSemidef.submatrix
 
+theorem transpose {M : Matrix n n R} (hM : M.PosSemidef) : Mᵀ.PosSemidef := by
+  refine ⟨IsHermitian.transpose hM.1, fun x => ?_⟩
+  convert hM.2 (star x) using 1
+  rw [mulVec_transpose, Matrix.dotProduct_mulVec, star_star, dotProduct_comm]
+
+theorem conjTranspose {M : Matrix n n R} (hM : M.PosSemidef) : Mᴴ.PosSemidef := hM.1.symm ▸ hM
+
 protected lemma zero : PosSemidef (0 : Matrix n n R) :=
   ⟨isHermitian_zero, by simp⟩
 
@@ -103,16 +110,24 @@ protected lemma pow [DecidableEq n] {M : Matrix n n R} (hM : M.PosSemidef) (k :
     rw [pow_succ', pow_succ]
     simpa only [hM.isHermitian.eq] using (hM.pow k).mul_mul_conjTranspose_same M
 
+protected lemma inv [DecidableEq n] {M : Matrix n n R} (hM : M.PosSemidef) : M⁻¹.PosSemidef := by
+  by_cases h : IsUnit M.det
+  · have := (conjTranspose_mul_mul_same hM M⁻¹).conjTranspose
+    rwa [mul_nonsing_inv_cancel_right _ _ h, conjTranspose_conjTranspose] at this
+  · rw [nonsing_inv_apply_not_isUnit _ h]
+    exact .zero
+
+protected lemma zpow [DecidableEq n] {M : Matrix n n R} (hM : M.PosSemidef) (z : ℤ) :
+    (M ^ z).PosSemidef := by
+  obtain ⟨n, rfl | rfl⟩ := z.eq_nat_or_neg
+  · simpa using hM.pow n
+  · simpa using (hM.pow n).inv
+
 /-- The eigenvalues of a positive semi-definite matrix are non-negative -/
 lemma eigenvalues_nonneg [DecidableEq n] {A : Matrix n n 𝕜}
     (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
   (hA.re_dotProduct_nonneg _).trans_eq (hA.1.eigenvalues_eq _).symm
 
-theorem transpose {M : Matrix n n R} (hM : M.PosSemidef) : Mᵀ.PosSemidef := by
-  refine ⟨IsHermitian.transpose hM.1, fun x => ?_⟩
-  convert hM.2 (star x) using 1
-  rw [mulVec_transpose, Matrix.dotProduct_mulVec, star_star, dotProduct_comm]
-
 section sqrt
 
 variable [DecidableEq n] {A : Matrix n n 𝕜} (hA : PosSemidef A)
feat(LinearAlgebra/Matrix/PosDef): unique positive semidef square root (#8809)

This PR adds two main results about positive semidefinite matrices:

  • a positive semidefinite matrix has a unique positive semidefinite square root;
  • if A is positive semidefinite then x* A x = 0 implies A x = 0 (proof extracted from #8594).

Co-authored-by: Adrian Wüthrich (@awueth)

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -11,20 +11,25 @@ import Mathlib.LinearAlgebra.QuadraticForm.Basic
 /-! # Positive Definite Matrices
 
 This file defines positive (semi)definite matrices and connects the notion to positive definiteness
-of quadratic forms.
+of quadratic forms. Most results require `𝕜 = ℝ` or `ℂ`.
 
-## Main definition
+## Main definitions
 
 * `Matrix.PosDef` : a matrix `M : Matrix n n 𝕜` is positive definite if it is hermitian and `xᴴMx`
   is greater than zero for all nonzero `x`.
 * `Matrix.PosSemidef` : a matrix `M : Matrix n n 𝕜` is positive semidefinite if it is hermitian
   and `xᴴMx` is nonnegative for all `x`.
 
+## Main results
+
+* `Matrix.posSemidef_iff_eq_transpose_mul_self` : a matrix `M : Matrix n n 𝕜` is positive
+  semidefinite iff it has the form `Bᴴ * B` for some `B`.
+* `Matrix.PosSemidef.sqrt` : the unique positive semidefinite square root of a positive semidefinite
+  matrix. (See `Matrix.PosSemidef.eq_sqrt_of_sq_eq` for the proof of uniqueness.)
 -/
 
 open scoped ComplexOrder
 
-
 namespace Matrix
 
 variable {m n R 𝕜 : Type*}
@@ -37,32 +42,186 @@ open scoped Matrix
 ## Positive semidefinite matrices
 -/
 
-/-- A matrix `M : Matrix n n R` is positive semidefinite if it is hermitian
-   and `xᴴMx` is nonnegative for all `x`. -/
+/-- A matrix `M : Matrix n n R` is positive semidefinite if it is Hermitian and `xᴴ * M * x` is
+nonnegative for all `x`. -/
 def PosSemidef (M : Matrix n n R) :=
   M.IsHermitian ∧ ∀ x : n → R, 0 ≤ dotProduct (star x) (M.mulVec x)
 #align matrix.pos_semidef Matrix.PosSemidef
 
-theorem PosSemidef.re_dotProduct_nonneg {M : Matrix n n 𝕜} (hM : M.PosSemidef) (x : n → 𝕜) :
+/-- A diagonal matrix is positive semidefinite iff its diagonal entries are nonnegative. -/
+lemma posSemidef_diagonal_iff [DecidableEq n] {d : n → R} :
+    PosSemidef (diagonal d) ↔ (∀ i : n, 0 ≤ d i) := by
+  refine ⟨fun ⟨_, hP⟩ i ↦ by simpa using hP (Pi.single i 1), ?_⟩
+  refine fun hd ↦ ⟨isHermitian_diagonal_iff.2 <| fun i ↦ IsSelfAdjoint.of_nonneg (hd i), ?_⟩
+  refine fun x ↦ Finset.sum_nonneg fun i _ ↦ ?_
+  simpa only [mulVec_diagonal, mul_assoc] using conjugate_nonneg (hd i) _
+
+namespace PosSemidef
+
+theorem isHermitian {M : Matrix n n R} (hM : M.PosSemidef) : M.IsHermitian :=
+  hM.1
+
+theorem re_dotProduct_nonneg {M : Matrix n n 𝕜} (hM : M.PosSemidef) (x : n → 𝕜) :
     0 ≤ IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
   IsROrC.nonneg_iff.mp (hM.2 _) |>.1
 
-theorem PosSemidef.submatrix {M : Matrix n n R} (hM : M.PosSemidef) (e : m ≃ n) :
+lemma conjTranspose_mul_mul_same {A : Matrix n n R} (hA : PosSemidef A)
+    {m : Type*} [Fintype m] (B : Matrix n m R) :
+    PosSemidef (Bᴴ * A * B) := by
+  constructor
+  · exact isHermitian_conjTranspose_mul_mul B hA.1
+  · intro x
+    simpa only [star_mulVec, dotProduct_mulVec, vecMul_vecMul] using hA.2 (mulVec B x)
+
+lemma mul_mul_conjTranspose_same {A : Matrix n n R} (hA : PosSemidef A)
+    {m : Type*} [Fintype m] (B : Matrix m n R):
+    PosSemidef (B * A * Bᴴ) := by
+  simpa only [conjTranspose_conjTranspose] using hA.conjTranspose_mul_mul_same Bᴴ
+
+theorem submatrix {M : Matrix n n R} (hM : M.PosSemidef) (e : m → n) :
     (M.submatrix e e).PosSemidef := by
-  refine' ⟨hM.1.submatrix e, fun x => _⟩
-  have : (M.submatrix (⇑e) e).mulVec x = (M.mulVec fun i : n => x (e.symm i)) ∘ e := by
-    ext i
-    dsimp only [(· ∘ ·), mulVec, dotProduct]
-    rw [Finset.sum_bij' (fun i _ => e i) _ _ fun i _ => e.symm i] <;>
-      simp only [eq_self_iff_true, imp_true_iff, Equiv.symm_apply_apply, Finset.mem_univ,
-        submatrix_apply, Equiv.apply_symm_apply]
-  rw [this]
-  convert hM.2 fun i => x (e.symm i) using 3
-  unfold dotProduct
-  rw [Finset.sum_bij' (fun i _ => e i) _ _ fun i _ => e.symm i] <;>
-  simp
+  classical
+  rw [(by simp : M = 1 * M * 1), submatrix_mul (he₂ := Function.bijective_id),
+    submatrix_mul (he₂ := Function.bijective_id), submatrix_id_id]
+  simpa only [conjTranspose_submatrix, conjTranspose_one] using
+    conjTranspose_mul_mul_same hM (Matrix.submatrix 1 id e)
 #align matrix.pos_semidef.submatrix Matrix.PosSemidef.submatrix
 
+protected lemma zero : PosSemidef (0 : Matrix n n R) :=
+  ⟨isHermitian_zero, by simp⟩
+
+protected lemma one [DecidableEq n] : PosSemidef (1 : Matrix n n R) :=
+  ⟨isHermitian_one, fun x => by
+    rw [one_mulVec]; exact Fintype.sum_nonneg fun i => star_mul_self_nonneg _⟩
+
+protected lemma pow [DecidableEq n] {M : Matrix n n R} (hM : M.PosSemidef) (k : ℕ) :
+    PosSemidef (M ^ k) :=
+  match k with
+  | 0 => .one
+  | 1 => by simpa using hM
+  | (k + 2) => by
+    rw [pow_succ', pow_succ]
+    simpa only [hM.isHermitian.eq] using (hM.pow k).mul_mul_conjTranspose_same M
+
+/-- The eigenvalues of a positive semi-definite matrix are non-negative -/
+lemma eigenvalues_nonneg [DecidableEq n] {A : Matrix n n 𝕜}
+    (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
+  (hA.re_dotProduct_nonneg _).trans_eq (hA.1.eigenvalues_eq _).symm
+
+theorem transpose {M : Matrix n n R} (hM : M.PosSemidef) : Mᵀ.PosSemidef := by
+  refine ⟨IsHermitian.transpose hM.1, fun x => ?_⟩
+  convert hM.2 (star x) using 1
+  rw [mulVec_transpose, Matrix.dotProduct_mulVec, star_star, dotProduct_comm]
+
+section sqrt
+
+variable [DecidableEq n] {A : Matrix n n 𝕜} (hA : PosSemidef A)
+
+/-- The positive semidefinite square root of a positive semidefinite matrix -/
+@[pp_dot]
+noncomputable def sqrt : Matrix n n 𝕜 :=
+  hA.1.eigenvectorMatrix * diagonal ((↑) ∘ Real.sqrt ∘ hA.1.eigenvalues) * hA.1.eigenvectorMatrixᴴ
+
+open Lean PrettyPrinter.Delaborator SubExpr in
+/-- Custom elaborator to produce output like `(_ : PosSemidef A).sqrt` in the goal view. -/
+@[delab app.Matrix.PosSemidef.sqrt]
+def delabSqrt : Delab :=
+  whenPPOption getPPNotation <|
+  whenNotPPOption getPPAnalysisSkip <|
+  withOptionAtCurrPos `pp.analysis.skip true do
+    let e ← getExpr
+    guard <| e.isAppOfArity ``Matrix.PosSemidef.sqrt 7
+    let optionsPerPos ← withNaryArg 6 do
+      return (← read).optionsPerPos.setBool (← getPos) `pp.proofs.withType true
+    withTheReader Context ({· with optionsPerPos}) delab
+
+-- test for custom elaborator
+/--
+info: (_ : PosSemidef A).sqrt : Matrix n n 𝕜
+-/
+#guard_msgs in
+#check (id hA).sqrt
+
+lemma posSemidef_sqrt : PosSemidef hA.sqrt := by
+  apply PosSemidef.mul_mul_conjTranspose_same
+  refine posSemidef_diagonal_iff.mpr fun i ↦ ?_
+  rw [Function.comp_apply, IsROrC.nonneg_iff]
+  constructor
+  · simp only [IsROrC.ofReal_re]
+    exact Real.sqrt_nonneg _
+  · simp only [IsROrC.ofReal_im]
+
+@[simp]
+lemma sq_sqrt : hA.sqrt ^ 2 = A := by
+  let C := hA.1.eigenvectorMatrix
+  let E := diagonal ((↑) ∘ Real.sqrt ∘ hA.1.eigenvalues : n → 𝕜)
+  suffices : C * (E * (Cᴴ * C) * E) * Cᴴ = A
+  · rw [Matrix.PosSemidef.sqrt, pow_two]
+    change (C * E * Cᴴ) * (C * E * Cᴴ) = A
+    simpa only [← mul_assoc] using this
+  have : Cᴴ * C = 1
+  · rw [Matrix.IsHermitian.conjTranspose_eigenvectorMatrix, mul_eq_one_comm]
+    exact hA.1.eigenvectorMatrix_mul_inv
+  rw [this, mul_one]
+  have : E * E = diagonal ((↑) ∘ hA.1.eigenvalues)
+  · rw [diagonal_mul_diagonal]
+    refine congr_arg _ (funext fun v ↦ ?_) -- why doesn't "congr with v" work?
+    simp [← pow_two, ← IsROrC.ofReal_pow, Real.sq_sqrt (hA.eigenvalues_nonneg v)]
+  rw [this]
+  convert hA.1.spectral_theorem'.symm
+  apply Matrix.IsHermitian.conjTranspose_eigenvectorMatrix
+
+@[simp]
+lemma sqrt_mul_self : hA.sqrt * hA.sqrt = A := by rw [← pow_two, sq_sqrt]
+
+lemma eq_of_sq_eq_sq {B : Matrix n n 𝕜} (hB : PosSemidef B) (hAB : A ^ 2 = B ^ 2) : A = B := by
+  /- This is deceptively hard, much more difficult than the positive *definite* case. We follow a
+  clever proof due to Koeber and Schäfer. The idea is that if `A ≠ B`, then `A - B` has a nonzero
+  real eigenvalue, with eigenvector `v`. Then a manipulation using the identity
+  `A ^ 2 - B ^ 2 = A * (A - B) + (A - B) * B` leads to the conclusion that
+  `⟨v, A v⟩ + ⟨v, B v⟩ = 0`. Since `A, B` are positive semidefinite, both terms must be zero. Thus
+  `⟨v, (A - B) v⟩ = 0`, but this is a nonzero scalar multiple of `⟨v, v⟩`, contradiction. -/
+  by_contra h_ne
+  let ⟨v, t, ht, hv, hv'⟩ := (hA.1.sub hB.1).exists_eigenvector_of_ne_zero (sub_ne_zero.mpr h_ne)
+  have h_sum : 0 = t * (star v ⬝ᵥ mulVec A v + star v ⬝ᵥ mulVec B v)
+  · calc
+      0 = star v ⬝ᵥ mulVec (A ^ 2 - B ^ 2) v := by rw [hAB, sub_self, zero_mulVec, dotProduct_zero]
+      _ = star v ⬝ᵥ mulVec A (mulVec (A - B) v)  + star v ⬝ᵥ mulVec (A - B) (mulVec B v) := by
+        rw [mulVec_mulVec, mulVec_mulVec, ← dotProduct_add, ← add_mulVec, mul_sub, sub_mul,
+          add_sub, sub_add_cancel, pow_two, pow_two]
+      _ = t * (star v ⬝ᵥ mulVec A v) + vecMul (star v) (A - B)ᴴ ⬝ᵥ mulVec B v := by
+        rw [hv', mulVec_smul, dotProduct_smul, IsROrC.real_smul_eq_coe_mul,
+          dotProduct_mulVec _ (A - B), hA.1.sub hB.1]
+      _ = t * (star v ⬝ᵥ mulVec A v + star v ⬝ᵥ mulVec B v) := by
+        simp_rw [← star_mulVec, hv', mul_add, ← IsROrC.real_smul_eq_coe_mul, ← smul_dotProduct]
+        congr 2 with i
+        simp only [Pi.star_apply, Pi.smul_apply, IsROrC.real_smul_eq_coe_mul, star_mul',
+          IsROrC.star_def, IsROrC.conj_ofReal]
+  replace h_sum : star v ⬝ᵥ mulVec A v + star v ⬝ᵥ mulVec B v = 0
+  · rw [eq_comm, ← mul_zero (t : 𝕜)] at h_sum
+    exact mul_left_cancel₀ (IsROrC.ofReal_ne_zero.mpr ht) h_sum
+  have h_van : star v ⬝ᵥ mulVec A v = 0 ∧ star v ⬝ᵥ mulVec B v = 0
+  · refine ⟨le_antisymm ?_ (hA.2 v), le_antisymm ?_ (hB.2 v)⟩
+    · rw [add_comm, add_eq_zero_iff_eq_neg] at h_sum
+      simpa only [h_sum, neg_nonneg] using hB.2 v
+    · simpa only [add_eq_zero_iff_eq_neg.mp h_sum, neg_nonneg] using hA.2 v
+  have aux : star v ⬝ᵥ mulVec (A - B) v = 0
+  · rw [sub_mulVec, dotProduct_sub, h_van.1, h_van.2, sub_zero]
+  rw [hv', dotProduct_smul, IsROrC.real_smul_eq_coe_mul, ← mul_zero ↑t] at aux
+  exact hv <| Matrix.dotProduct_star_self_eq_zero.mp <| mul_left_cancel₀
+    (IsROrC.ofReal_ne_zero.mpr ht) aux
+
+lemma sqrt_sq : (hA.pow 2 : PosSemidef (A ^ 2)).sqrt = A :=
+  (hA.pow 2).posSemidef_sqrt.eq_of_sq_eq_sq hA (hA.pow 2).sq_sqrt
+
+lemma eq_sqrt_of_sq_eq {B : Matrix n n 𝕜} (hB : PosSemidef B) (hAB : A ^ 2 = B) : A = hB.sqrt := by
+  subst B
+  rw [hA.sqrt_sq]
+
+end sqrt
+
+end PosSemidef
+
 @[simp]
 theorem posSemidef_submatrix_equiv {M : Matrix n n R} (e : m ≃ n) :
     (M.submatrix e e).PosSemidef ↔ M.PosSemidef :=
@@ -70,27 +229,55 @@ theorem posSemidef_submatrix_equiv {M : Matrix n n R} (e : m ≃ n) :
 #align matrix.pos_semidef_submatrix_equiv Matrix.posSemidef_submatrix_equiv
 
 /-- The conjugate transpose of a matrix mulitplied by the matrix is positive semidefinite -/
-theorem posSemidef_conjTranspose_mul_self (A : Matrix m n R) : Matrix.PosSemidef (Aᴴ * A) := by
+theorem posSemidef_conjTranspose_mul_self (A : Matrix m n R) : PosSemidef (Aᴴ * A) := by
   refine ⟨isHermitian_transpose_mul_self _, fun x => ?_⟩
   rw [← mulVec_mulVec, dotProduct_mulVec, vecMul_conjTranspose, star_star]
   exact Finset.sum_nonneg fun i _ => star_mul_self_nonneg _
 
 /-- A matrix multiplied by its conjugate transpose is positive semidefinite -/
-theorem posSemidef_self_mul_conjTranspose (A : Matrix m n R) : Matrix.PosSemidef (A * Aᴴ) :=
+theorem posSemidef_self_mul_conjTranspose (A : Matrix m n R) : PosSemidef (A * Aᴴ) :=
   by simpa only [conjTranspose_conjTranspose] using posSemidef_conjTranspose_mul_self Aᴴ
 
-/-- The eigenvalues of a positive semi-definite matrix are non-negative -/
-lemma PosSemidef.eigenvalues_nonneg [DecidableEq n] {A : Matrix n n 𝕜}
-    (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
-  (hA.re_dotProduct_nonneg _).trans_eq (hA.1.eigenvalues_eq _).symm
-
 lemma eigenvalues_conjTranspose_mul_self_nonneg (A : Matrix m n 𝕜) [DecidableEq n] (i : n) :
     0 ≤ (isHermitian_transpose_mul_self A).eigenvalues i :=
-  (Matrix.posSemidef_conjTranspose_mul_self _).eigenvalues_nonneg _
+  (posSemidef_conjTranspose_mul_self _).eigenvalues_nonneg _
 
 lemma eigenvalues_self_mul_conjTranspose_nonneg (A : Matrix m n 𝕜) [DecidableEq m] (i : m) :
     0 ≤ (isHermitian_mul_conjTranspose_self A).eigenvalues i :=
-  (Matrix.posSemidef_self_mul_conjTranspose _).eigenvalues_nonneg _
+  (posSemidef_self_mul_conjTranspose _).eigenvalues_nonneg _
+
+/-- A matrix is positive semidefinite if and only if it has the form `Bᴴ * B` for some `B`. -/
+lemma posSemidef_iff_eq_transpose_mul_self [DecidableEq n] {A : Matrix n n 𝕜} :
+    PosSemidef A ↔ ∃ (B : Matrix n n 𝕜), A = Bᴴ * B := by
+  refine ⟨fun hA ↦ ⟨hA.sqrt, ?_⟩, fun ⟨B, hB⟩ ↦ (hB ▸ posSemidef_conjTranspose_mul_self B)⟩
+  simp_rw [← PosSemidef.sq_sqrt hA, pow_two]
+  rw [hA.posSemidef_sqrt.1]
+
+lemma IsHermitian.posSemidef_of_eigenvalues_nonneg [DecidableEq n] {A : Matrix n n 𝕜}
+    (hA : IsHermitian A) (h : ∀ i : n, 0 ≤ hA.eigenvalues i) : PosSemidef A := by
+  simp_rw [hA.conjTranspose_eigenvectorMatrix.symm ▸ hA.spectral_theorem']
+  refine (posSemidef_diagonal_iff.mpr fun i ↦ ?_).mul_mul_conjTranspose_same _
+  rw [IsROrC.le_iff_re_im]
+  simpa using h i
+
+/-- For `A` positive semidefinite, we have `x⋆ A x = 0` iff `A x = 0`. -/
+theorem PosSemidef.dotProduct_mulVec_zero_iff [DecidableEq n]
+    {A : Matrix n n 𝕜} (hA : PosSemidef A) (x : n → 𝕜) :
+    star x ⬝ᵥ mulVec A x = 0 ↔ mulVec A x = 0 := by
+  constructor
+  · obtain ⟨B, rfl⟩ := posSemidef_iff_eq_transpose_mul_self.mp hA
+    rw [← Matrix.mulVec_mulVec, dotProduct_mulVec,
+      vecMul_conjTranspose, star_star, dotProduct_star_self_eq_zero]
+    intro h0
+    rw [h0, mulVec_zero]
+  · intro h0
+    rw [h0, dotProduct_zero]
+
+/-- For `A` positive semidefinite, we have `x⋆ A x = 0` iff `A x = 0` (linear maps version). -/
+theorem PosSemidef.toLinearMap₂'_zero_iff [DecidableEq n]
+    {A : Matrix n n 𝕜} (hA : PosSemidef A) (x : n → 𝕜) :
+    Matrix.toLinearMap₂' A (star x) x = 0 ↔ Matrix.toLin' A x = 0 := by
+  simpa only [toLinearMap₂'_apply', toLin'_apply] using hA.dotProduct_mulVec_zero_iff x
 
 /-!
 ## Positive definite matrices
refactor(LinearAlgebra/Matrix/PosDef): separate PosDef lemmas from PosSemidef lemmas (#8810)

There are no new or deleted lemmas here, only a reordering; but to enable dot notation I have renamed:

  • posDef_toQuadraticForm' to PosDef.toQuadraticForm'
  • posDef_of_toQuadraticForm' to PosDef.of_toQuadraticForm'

Split from #8809

Diff
@@ -33,19 +33,9 @@ variable [CommRing R] [PartialOrder R] [StarOrderedRing R]
 variable [IsROrC 𝕜]
 open scoped Matrix
 
-/-- A matrix `M : Matrix n n R` is positive definite if it is hermitian
-   and `xᴴMx` is greater than zero for all nonzero `x`. -/
-def PosDef (M : Matrix n n R) :=
-  M.IsHermitian ∧ ∀ x : n → R, x ≠ 0 → 0 < dotProduct (star x) (M.mulVec x)
-#align matrix.pos_def Matrix.PosDef
-
-theorem PosDef.isHermitian {M : Matrix n n R} (hM : M.PosDef) : M.IsHermitian :=
-  hM.1
-#align matrix.pos_def.is_hermitian Matrix.PosDef.isHermitian
-
-theorem PosDef.re_dotProduct_pos {M : Matrix n n 𝕜} (hM : M.PosDef) {x : n → 𝕜} (hx : x ≠ 0) :
-    0 < IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
-  IsROrC.pos_iff.mp (hM.2 _ hx) |>.1
+/-!
+## Positive semidefinite matrices
+-/
 
 /-- A matrix `M : Matrix n n R` is positive semidefinite if it is hermitian
    and `xᴴMx` is nonnegative for all `x`. -/
@@ -57,15 +47,6 @@ theorem PosSemidef.re_dotProduct_nonneg {M : Matrix n n 𝕜} (hM : M.PosSemidef
     0 ≤ IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
   IsROrC.nonneg_iff.mp (hM.2 _) |>.1
 
-theorem PosDef.posSemidef {M : Matrix n n R} (hM : M.PosDef) : M.PosSemidef := by
-  refine' ⟨hM.1, _⟩
-  intro x
-  by_cases hx : x = 0
-  · simp only [hx, zero_dotProduct, star_zero, IsROrC.zero_re']
-    exact le_rfl
-  · exact le_of_lt (hM.2 x hx)
-#align matrix.pos_def.pos_semidef Matrix.PosDef.posSemidef
-
 theorem PosSemidef.submatrix {M : Matrix n n R} (hM : M.PosSemidef) (e : m ≃ n) :
     (M.submatrix e e).PosSemidef := by
   refine' ⟨hM.1.submatrix e, fun x => _⟩
@@ -88,27 +69,6 @@ theorem posSemidef_submatrix_equiv {M : Matrix n n R} (e : m ≃ n) :
   ⟨fun h => by simpa using h.submatrix e.symm, fun h => h.submatrix _⟩
 #align matrix.pos_semidef_submatrix_equiv Matrix.posSemidef_submatrix_equiv
 
-theorem PosDef.transpose {M : Matrix n n R} (hM : M.PosDef) : Mᵀ.PosDef := by
-  refine ⟨IsHermitian.transpose hM.1, fun x hx => ?_⟩
-  convert hM.2 (star x) (star_ne_zero.2 hx) using 1
-  rw [mulVec_transpose, Matrix.dotProduct_mulVec, star_star, dotProduct_comm]
-#align matrix.pos_def.transpose Matrix.PosDef.transpose
-
-theorem posDef_of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
-    (hMq : M.toQuadraticForm'.PosDef) : M.PosDef := by
-  refine' ⟨hM, fun x hx => _⟩
-  simp only [toQuadraticForm', QuadraticForm.PosDef, BilinForm.toQuadraticForm_apply,
-    Matrix.toBilin'_apply'] at hMq
-  apply hMq x hx
-#align matrix.pos_def_of_to_quadratic_form' Matrix.posDef_of_toQuadraticForm'
-
-theorem posDef_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
-    M.toQuadraticForm'.PosDef := by
-  intro x hx
-  simp only [toQuadraticForm', BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
-  apply hM.2 x hx
-#align matrix.pos_def_to_quadratic_form' Matrix.posDef_toQuadraticForm'
-
 /-- The conjugate transpose of a matrix mulitplied by the matrix is positive semidefinite -/
 theorem posSemidef_conjTranspose_mul_self (A : Matrix m n R) : Matrix.PosSemidef (Aᴴ * A) := by
   refine ⟨isHermitian_transpose_mul_self _, fun x => ?_⟩
@@ -119,12 +79,6 @@ theorem posSemidef_conjTranspose_mul_self (A : Matrix m n R) : Matrix.PosSemidef
 theorem posSemidef_self_mul_conjTranspose (A : Matrix m n R) : Matrix.PosSemidef (A * Aᴴ) :=
   by simpa only [conjTranspose_conjTranspose] using posSemidef_conjTranspose_mul_self Aᴴ
 
-/-- The eigenvalues of a positive definite matrix are positive -/
-lemma PosDef.eigenvalues_pos [DecidableEq n] {A : Matrix n n 𝕜}
-    (hA : Matrix.PosDef A) (i : n) : 0 < hA.1.eigenvalues i := by
-  rw [hA.1.eigenvalues_eq, hA.1.transpose_eigenvectorMatrix_apply]
-  exact hA.re_dotProduct_pos <| hA.1.eigenvectorBasis.orthonormal.ne_zero i
-
 /-- The eigenvalues of a positive semi-definite matrix are non-negative -/
 lemma PosSemidef.eigenvalues_nonneg [DecidableEq n] {A : Matrix n n 𝕜}
     (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
@@ -138,11 +92,63 @@ lemma eigenvalues_self_mul_conjTranspose_nonneg (A : Matrix m n 𝕜) [Decidable
     0 ≤ (isHermitian_mul_conjTranspose_self A).eigenvalues i :=
   (Matrix.posSemidef_self_mul_conjTranspose _).eigenvalues_nonneg _
 
+/-!
+## Positive definite matrices
+-/
+
+/-- A matrix `M : Matrix n n R` is positive definite if it is hermitian
+   and `xᴴMx` is greater than zero for all nonzero `x`. -/
+def PosDef (M : Matrix n n R) :=
+  M.IsHermitian ∧ ∀ x : n → R, x ≠ 0 → 0 < dotProduct (star x) (M.mulVec x)
+#align matrix.pos_def Matrix.PosDef
+
 namespace PosDef
 
-variable {M : Matrix n n ℝ} (hM : M.PosDef)
+theorem isHermitian {M : Matrix n n R} (hM : M.PosDef) : M.IsHermitian :=
+  hM.1
+#align matrix.pos_def.is_hermitian Matrix.PosDef.isHermitian
+
+theorem re_dotProduct_pos {M : Matrix n n 𝕜} (hM : M.PosDef) {x : n → 𝕜} (hx : x ≠ 0) :
+    0 < IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
+  IsROrC.pos_iff.mp (hM.2 _ hx) |>.1
+
+theorem posSemidef {M : Matrix n n R} (hM : M.PosDef) : M.PosSemidef := by
+  refine' ⟨hM.1, _⟩
+  intro x
+  by_cases hx : x = 0
+  · simp only [hx, zero_dotProduct, star_zero, IsROrC.zero_re']
+    exact le_rfl
+  · exact le_of_lt (hM.2 x hx)
+#align matrix.pos_def.pos_semidef Matrix.PosDef.posSemidef
+
+theorem transpose {M : Matrix n n R} (hM : M.PosDef) : Mᵀ.PosDef := by
+  refine ⟨IsHermitian.transpose hM.1, fun x hx => ?_⟩
+  convert hM.2 (star x) (star_ne_zero.2 hx) using 1
+  rw [mulVec_transpose, Matrix.dotProduct_mulVec, star_star, dotProduct_comm]
+#align matrix.pos_def.transpose Matrix.PosDef.transpose
+
+theorem of_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.IsSymm)
+    (hMq : M.toQuadraticForm'.PosDef) : M.PosDef := by
+  refine' ⟨hM, fun x hx => _⟩
+  simp only [toQuadraticForm', QuadraticForm.PosDef, BilinForm.toQuadraticForm_apply,
+    Matrix.toBilin'_apply'] at hMq
+  apply hMq x hx
+#align matrix.pos_def_of_to_quadratic_form' Matrix.PosDef.of_toQuadraticForm'
+
+theorem toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) :
+    M.toQuadraticForm'.PosDef := by
+  intro x hx
+  simp only [Matrix.toQuadraticForm', BilinForm.toQuadraticForm_apply, Matrix.toBilin'_apply']
+  apply hM.2 x hx
+#align matrix.pos_def_to_quadratic_form' Matrix.PosDef.toQuadraticForm'
+
+/-- The eigenvalues of a positive definite matrix are positive -/
+lemma eigenvalues_pos [DecidableEq n] {A : Matrix n n 𝕜}
+    (hA : Matrix.PosDef A) (i : n) : 0 < hA.1.eigenvalues i := by
+  rw [hA.1.eigenvalues_eq, hA.1.transpose_eigenvectorMatrix_apply]
+  exact hA.re_dotProduct_pos <| hA.1.eigenvectorBasis.orthonormal.ne_zero i
 
-theorem det_pos [DecidableEq n] : 0 < det M := by
+theorem det_pos [DecidableEq n] {M : Matrix n n ℝ} (hM : M.PosDef) : 0 < det M := by
   rw [hM.isHermitian.det_eq_prod_eigenvalues]
   apply Finset.prod_pos
   intro i _
@@ -166,14 +172,14 @@ theorem posDef_of_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)}
     (hQ : Q.toMatrix'.PosDef) : Q.PosDef := by
   rw [← toQuadraticForm_associated ℝ Q,
     ← BilinForm.toMatrix'.left_inv ((associatedHom (R := ℝ) ℝ) Q)]
-  apply Matrix.posDef_toQuadraticForm' hQ
+  exact hQ.toQuadraticForm'
 #align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDef_of_toMatrix'
 
 theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.PosDef) :
     Q.toMatrix'.PosDef := by
   rw [← toQuadraticForm_associated ℝ Q, ←
     BilinForm.toMatrix'.left_inv ((associatedHom (R := ℝ) ℝ) Q)] at hQ
-  apply Matrix.posDef_of_toQuadraticForm' (isSymm_toMatrix' Q) hQ
+  exact .of_toQuadraticForm' (isSymm_toMatrix' Q) hQ
 #align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
 
 end QuadraticForm
chore: rename by_contra' to by_contra! (#8797)

To fit with the "please try harder" convention of ! tactics.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -197,7 +197,7 @@ noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosD
         · simp [h]
         · exact le_of_lt (hM.re_dotProduct_pos h)
       definite := fun x (hx : dotProduct _ _ = 0) => by
-        by_contra' h
+        by_contra! h
         simpa [hx, lt_irrefl] using hM.re_dotProduct_pos h
       add_left := by simp only [star_add, add_dotProduct, eq_self_iff_true, forall_const]
       smul_left := fun x y r => by
refactor(LinearAlgebra/QuadraticForm/Basic): remove non-commutativity support (#7581)

As discussed on Zulip, this generalization seems nonsensical as currently implemented.

There are sensible ways to make this generalization, but they are much larger refactors, and in the meantime the current generalization is useless anyway.

Diff
@@ -164,14 +164,15 @@ variable {n : Type*} [Fintype n]
 
 theorem posDef_of_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)}
     (hQ : Q.toMatrix'.PosDef) : Q.PosDef := by
-  rw [← toQuadraticForm_associated ℝ Q, ← BilinForm.toMatrix'.left_inv ((associatedHom ℝ) Q)]
+  rw [← toQuadraticForm_associated ℝ Q,
+    ← BilinForm.toMatrix'.left_inv ((associatedHom (R := ℝ) ℝ) Q)]
   apply Matrix.posDef_toQuadraticForm' hQ
 #align quadratic_form.pos_def_of_to_matrix' QuadraticForm.posDef_of_toMatrix'
 
 theorem posDef_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)} (hQ : Q.PosDef) :
     Q.toMatrix'.PosDef := by
   rw [← toQuadraticForm_associated ℝ Q, ←
-    BilinForm.toMatrix'.left_inv ((associatedHom ℝ) Q)] at hQ
+    BilinForm.toMatrix'.left_inv ((associatedHom (R := ℝ) ℝ) Q)] at hQ
   apply Matrix.posDef_of_toQuadraticForm' (isSymm_toMatrix' Q) hQ
 #align quadratic_form.pos_def_to_matrix' QuadraticForm.posDef_toMatrix'
 
feat: eigenvalues of AᴴA and AAᴴ are non-negative (#7312)

The PR provides two lemmas showing that the eigenvalues of $A^HA$ and $AA^H$ are non-negative:

  • eigenvalues_conjTranspose_mul_self_nonneg: $$\text{eig}(A^H A) \geq 0 $$
  • eigenvalues_self_mul_conjTranspose_nonneg: $$\text{eig}(A A^H) \geq 0 $$

This was suggested by @Vierkantor in PR #6042

Diff
@@ -130,6 +130,14 @@ lemma PosSemidef.eigenvalues_nonneg [DecidableEq n] {A : Matrix n n 𝕜}
     (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
   (hA.re_dotProduct_nonneg _).trans_eq (hA.1.eigenvalues_eq _).symm
 
+lemma eigenvalues_conjTranspose_mul_self_nonneg (A : Matrix m n 𝕜) [DecidableEq n] (i : n) :
+    0 ≤ (isHermitian_transpose_mul_self A).eigenvalues i :=
+  (Matrix.posSemidef_conjTranspose_mul_self _).eigenvalues_nonneg _
+
+lemma eigenvalues_self_mul_conjTranspose_nonneg (A : Matrix m n 𝕜) [DecidableEq m] (i : m) :
+    0 ≤ (isHermitian_mul_conjTranspose_self A).eigenvalues i :=
+  (Matrix.posSemidef_self_mul_conjTranspose _).eigenvalues_nonneg _
+
 namespace PosDef
 
 variable {M : Matrix n n ℝ} (hM : M.PosDef)
chore: add IsROrC.toDecidableEq (#7315)

We already have noncomputable DecidableEq instances for Real and Complex; putting them here too reduces friction in code generalized to IsROrC K.

Diff
@@ -120,13 +120,13 @@ theorem posSemidef_self_mul_conjTranspose (A : Matrix m n R) : Matrix.PosSemidef
   by simpa only [conjTranspose_conjTranspose] using posSemidef_conjTranspose_mul_self Aᴴ
 
 /-- The eigenvalues of a positive definite matrix are positive -/
-lemma PosDef.eigenvalues_pos [DecidableEq n] [DecidableEq 𝕜] {A : Matrix n n 𝕜}
+lemma PosDef.eigenvalues_pos [DecidableEq n] {A : Matrix n n 𝕜}
     (hA : Matrix.PosDef A) (i : n) : 0 < hA.1.eigenvalues i := by
   rw [hA.1.eigenvalues_eq, hA.1.transpose_eigenvectorMatrix_apply]
   exact hA.re_dotProduct_pos <| hA.1.eigenvectorBasis.orthonormal.ne_zero i
 
 /-- The eigenvalues of a positive semi-definite matrix are non-negative -/
-lemma PosSemidef.eigenvalues_nonneg [DecidableEq n] [DecidableEq 𝕜] {A : Matrix n n 𝕜}
+lemma PosSemidef.eigenvalues_nonneg [DecidableEq n] {A : Matrix n n 𝕜}
     (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
   (hA.re_dotProduct_nonneg _).trans_eq (hA.1.eigenvalues_eq _).symm
 
refactor(LinearAlgebra/Matrix/PosDef): Generalize to StarOrderedRing (#6489)

I assume this is mathematically sound, though right now we can't generalize many dependencies due to the reliance of InnerProductSpace.

Diff
@@ -9,39 +9,55 @@ import Mathlib.LinearAlgebra.QuadraticForm.Basic
 #align_import linear_algebra.matrix.pos_def from "leanprover-community/mathlib"@"07992a1d1f7a4176c6d3f160209608be4e198566"
 
 /-! # Positive Definite Matrices
+
 This file defines positive (semi)definite matrices and connects the notion to positive definiteness
 of quadratic forms.
+
 ## Main definition
- * `Matrix.PosDef` : a matrix `M : Matrix n n 𝕜` is positive definite if it is hermitian and `xᴴMx`
-   is greater than zero for all nonzero `x`.
- * `Matrix.PosSemidef` : a matrix `M : Matrix n n 𝕜` is positive semidefinite if it is hermitian
-   and `xᴴMx` is nonnegative for all `x`.
+
+* `Matrix.PosDef` : a matrix `M : Matrix n n 𝕜` is positive definite if it is hermitian and `xᴴMx`
+  is greater than zero for all nonzero `x`.
+* `Matrix.PosSemidef` : a matrix `M : Matrix n n 𝕜` is positive semidefinite if it is hermitian
+  and `xᴴMx` is nonnegative for all `x`.
+
 -/
 
+open scoped ComplexOrder
 
-namespace Matrix
 
-variable {𝕜 : Type*} [IsROrC 𝕜] {m n : Type*} [Fintype m] [Fintype n]
+namespace Matrix
 
+variable {m n R 𝕜 : Type*}
+variable [Fintype m] [Fintype n]
+variable [CommRing R] [PartialOrder R] [StarOrderedRing R]
+variable [IsROrC 𝕜]
 open scoped Matrix
 
-/-- A matrix `M : Matrix n n 𝕜` is positive definite if it is hermitian
+/-- A matrix `M : Matrix n n R` is positive definite if it is hermitian
    and `xᴴMx` is greater than zero for all nonzero `x`. -/
-def PosDef (M : Matrix n n 𝕜) :=
-  M.IsHermitian ∧ ∀ x : n → 𝕜, x ≠ 0 → 0 < IsROrC.re (dotProduct (star x) (M.mulVec x))
+def PosDef (M : Matrix n n R) :=
+  M.IsHermitian ∧ ∀ x : n → R, x ≠ 0 → 0 < dotProduct (star x) (M.mulVec x)
 #align matrix.pos_def Matrix.PosDef
 
-theorem PosDef.isHermitian {M : Matrix n n 𝕜} (hM : M.PosDef) : M.IsHermitian :=
+theorem PosDef.isHermitian {M : Matrix n n R} (hM : M.PosDef) : M.IsHermitian :=
   hM.1
 #align matrix.pos_def.is_hermitian Matrix.PosDef.isHermitian
 
-/-- A matrix `M : Matrix n n 𝕜` is positive semidefinite if it is hermitian
+theorem PosDef.re_dotProduct_pos {M : Matrix n n 𝕜} (hM : M.PosDef) {x : n → 𝕜} (hx : x ≠ 0) :
+    0 < IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
+  IsROrC.pos_iff.mp (hM.2 _ hx) |>.1
+
+/-- A matrix `M : Matrix n n R` is positive semidefinite if it is hermitian
    and `xᴴMx` is nonnegative for all `x`. -/
-def PosSemidef (M : Matrix n n 𝕜) :=
-  M.IsHermitian ∧ ∀ x : n → 𝕜, 0 ≤ IsROrC.re (dotProduct (star x) (M.mulVec x))
+def PosSemidef (M : Matrix n n R) :=
+  M.IsHermitian ∧ ∀ x : n → R, 0 ≤ dotProduct (star x) (M.mulVec x)
 #align matrix.pos_semidef Matrix.PosSemidef
 
-theorem PosDef.posSemidef {M : Matrix n n 𝕜} (hM : M.PosDef) : M.PosSemidef := by
+theorem PosSemidef.re_dotProduct_nonneg {M : Matrix n n 𝕜} (hM : M.PosSemidef) (x : n → 𝕜) :
+    0 ≤ IsROrC.re (dotProduct (star x) (M.mulVec x)) :=
+  IsROrC.nonneg_iff.mp (hM.2 _) |>.1
+
+theorem PosDef.posSemidef {M : Matrix n n R} (hM : M.PosDef) : M.PosSemidef := by
   refine' ⟨hM.1, _⟩
   intro x
   by_cases hx : x = 0
@@ -50,7 +66,7 @@ theorem PosDef.posSemidef {M : Matrix n n 𝕜} (hM : M.PosDef) : M.PosSemidef :
   · exact le_of_lt (hM.2 x hx)
 #align matrix.pos_def.pos_semidef Matrix.PosDef.posSemidef
 
-theorem PosSemidef.submatrix {M : Matrix n n 𝕜} (hM : M.PosSemidef) (e : m ≃ n) :
+theorem PosSemidef.submatrix {M : Matrix n n R} (hM : M.PosSemidef) (e : m ≃ n) :
     (M.submatrix e e).PosSemidef := by
   refine' ⟨hM.1.submatrix e, fun x => _⟩
   have : (M.submatrix (⇑e) e).mulVec x = (M.mulVec fun i : n => x (e.symm i)) ∘ e := by
@@ -67,14 +83,14 @@ theorem PosSemidef.submatrix {M : Matrix n n 𝕜} (hM : M.PosSemidef) (e : m 
 #align matrix.pos_semidef.submatrix Matrix.PosSemidef.submatrix
 
 @[simp]
-theorem posSemidef_submatrix_equiv {M : Matrix n n 𝕜} (e : m ≃ n) :
+theorem posSemidef_submatrix_equiv {M : Matrix n n R} (e : m ≃ n) :
     (M.submatrix e e).PosSemidef ↔ M.PosSemidef :=
   ⟨fun h => by simpa using h.submatrix e.symm, fun h => h.submatrix _⟩
 #align matrix.pos_semidef_submatrix_equiv Matrix.posSemidef_submatrix_equiv
 
-theorem PosDef.transpose {M : Matrix n n 𝕜} (hM : M.PosDef) : Mᵀ.PosDef := by
-  refine' ⟨IsHermitian.transpose hM.1, fun x hx => _⟩
-  convert hM.2 (star x) (star_ne_zero.2 hx) using 2
+theorem PosDef.transpose {M : Matrix n n R} (hM : M.PosDef) : Mᵀ.PosDef := by
+  refine ⟨IsHermitian.transpose hM.1, fun x hx => ?_⟩
+  convert hM.2 (star x) (star_ne_zero.2 hx) using 1
   rw [mulVec_transpose, Matrix.dotProduct_mulVec, star_star, dotProduct_comm]
 #align matrix.pos_def.transpose Matrix.PosDef.transpose
 
@@ -94,26 +110,25 @@ theorem posDef_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.Pos
 #align matrix.pos_def_to_quadratic_form' Matrix.posDef_toQuadraticForm'
 
 /-- The conjugate transpose of a matrix mulitplied by the matrix is positive semidefinite -/
-theorem posSemidef_conjTranspose_mul_self (A : Matrix m n 𝕜) : Matrix.PosSemidef (Aᴴ * A) := by
+theorem posSemidef_conjTranspose_mul_self (A : Matrix m n R) : Matrix.PosSemidef (Aᴴ * A) := by
   refine ⟨isHermitian_transpose_mul_self _, fun x => ?_⟩
-  rw [← mulVec_mulVec, dotProduct_mulVec, vecMul_conjTranspose, star_star, dotProduct, map_sum]
-  simp_rw [Pi.star_apply, IsROrC.star_def]
-  simpa using Finset.sum_nonneg fun i _ => add_nonneg (mul_self_nonneg _) (mul_self_nonneg _)
+  rw [← mulVec_mulVec, dotProduct_mulVec, vecMul_conjTranspose, star_star]
+  exact Finset.sum_nonneg fun i _ => star_mul_self_nonneg _
 
 /-- A matrix multiplied by its conjugate transpose is positive semidefinite -/
-theorem posSemidef_self_mul_conjTranspose (A : Matrix m n 𝕜) : Matrix.PosSemidef (A * Aᴴ) :=
+theorem posSemidef_self_mul_conjTranspose (A : Matrix m n R) : Matrix.PosSemidef (A * Aᴴ) :=
   by simpa only [conjTranspose_conjTranspose] using posSemidef_conjTranspose_mul_self Aᴴ
 
 /-- The eigenvalues of a positive definite matrix are positive -/
 lemma PosDef.eigenvalues_pos [DecidableEq n] [DecidableEq 𝕜] {A : Matrix n n 𝕜}
     (hA : Matrix.PosDef A) (i : n) : 0 < hA.1.eigenvalues i := by
   rw [hA.1.eigenvalues_eq, hA.1.transpose_eigenvectorMatrix_apply]
-  exact hA.2 _ <| hA.1.eigenvectorBasis.orthonormal.ne_zero i
+  exact hA.re_dotProduct_pos <| hA.1.eigenvectorBasis.orthonormal.ne_zero i
 
 /-- The eigenvalues of a positive semi-definite matrix are non-negative -/
 lemma PosSemidef.eigenvalues_nonneg [DecidableEq n] [DecidableEq 𝕜] {A : Matrix n n 𝕜}
     (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
-  (hA.2 _).trans_eq (hA.1.eigenvalues_eq _).symm
+  (hA.re_dotProduct_nonneg _).trans_eq (hA.1.eigenvalues_eq _).symm
 
 namespace PosDef
 
@@ -171,10 +186,10 @@ noncomputable def NormedAddCommGroup.ofMatrix {M : Matrix n n 𝕜} (hM : M.PosD
       nonneg_re := fun x => by
         by_cases h : x = 0
         · simp [h]
-        · exact le_of_lt (hM.2 x h)
+        · exact le_of_lt (hM.re_dotProduct_pos h)
       definite := fun x (hx : dotProduct _ _ = 0) => by
         by_contra' h
-        simpa [hx, lt_irrefl] using hM.2 x h
+        simpa [hx, lt_irrefl] using hM.re_dotProduct_pos h
       add_left := by simp only [star_add, add_dotProduct, eq_self_iff_true, forall_const]
       smul_left := fun x y r => by
         simp only
refactor(Data/Matrix): Eliminate notation in favor of HMul (#6487)

The main difficulty here is that * has a slightly difference precedence to . notably around smul and neg.

The other annoyance is that ↑U ⬝ A ⬝ ↑U⁻¹ : Matrix m m 𝔸 now has to be written U.val * A * (U⁻¹).val in order to typecheck.

A downside of this change to consider: if you have a goal of A * (B * C) = (A * B) * C, mul_assoc now gives the illusion of matching, when in fact Matrix.mul_assoc is needed. Previously the distinct symbol made it easy to avoid this mistake.

On the flipside, there is now no need to rewrite by Matrix.mul_eq_mul all the time (indeed, the lemma is now removed).

Diff
@@ -94,14 +94,14 @@ theorem posDef_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.Pos
 #align matrix.pos_def_to_quadratic_form' Matrix.posDef_toQuadraticForm'
 
 /-- The conjugate transpose of a matrix mulitplied by the matrix is positive semidefinite -/
-theorem posSemidef_conjTranspose_mul_self (A : Matrix m n 𝕜) : Matrix.PosSemidef (Aᴴ ⬝ A) := by
+theorem posSemidef_conjTranspose_mul_self (A : Matrix m n 𝕜) : Matrix.PosSemidef (Aᴴ * A) := by
   refine ⟨isHermitian_transpose_mul_self _, fun x => ?_⟩
   rw [← mulVec_mulVec, dotProduct_mulVec, vecMul_conjTranspose, star_star, dotProduct, map_sum]
   simp_rw [Pi.star_apply, IsROrC.star_def]
   simpa using Finset.sum_nonneg fun i _ => add_nonneg (mul_self_nonneg _) (mul_self_nonneg _)
 
 /-- A matrix multiplied by its conjugate transpose is positive semidefinite -/
-theorem posSemidef_self_mul_conjTranspose (A : Matrix m n 𝕜) : Matrix.PosSemidef (A ⬝ Aᴴ) :=
+theorem posSemidef_self_mul_conjTranspose (A : Matrix m n 𝕜) : Matrix.PosSemidef (A * Aᴴ) :=
   by simpa only [conjTranspose_conjTranspose] using posSemidef_conjTranspose_mul_self Aᴴ
 
 /-- The eigenvalues of a positive definite matrix are positive -/
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -21,7 +21,7 @@ of quadratic forms.
 
 namespace Matrix
 
-variable {𝕜 : Type _} [IsROrC 𝕜] {m n : Type _} [Fintype m] [Fintype n]
+variable {𝕜 : Type*} [IsROrC 𝕜] {m n : Type*} [Fintype m] [Fintype n]
 
 open scoped Matrix
 
@@ -137,7 +137,7 @@ end Matrix
 
 namespace QuadraticForm
 
-variable {n : Type _} [Fintype n]
+variable {n : Type*} [Fintype n]
 
 theorem posDef_of_toMatrix' [DecidableEq n] {Q : QuadraticForm ℝ (n → ℝ)}
     (hQ : Q.toMatrix'.PosDef) : Q.PosDef := by
@@ -156,7 +156,7 @@ end QuadraticForm
 
 namespace Matrix
 
-variable {𝕜 : Type _} [IsROrC 𝕜] {n : Type _} [Fintype n]
+variable {𝕜 : Type*} [IsROrC 𝕜] {n : Type*} [Fintype n]
 
 /-- A positive definite matrix `M` induces a norm `‖x‖ = sqrt (re xᴴMx)`. -/
 @[reducible]
feat: Positivity/Nonnegativity of Eigenvalues of PosDef/PosSemidef Matrices (#6368)

Two lemmas:

  • Matrix.PosDef.eigenvalues_pos: $$A \in k^{n\times n}, A > 0 \implies \lambda (A) >0$$
  • Matrix.PosSemidef.eigenvalues_nonneg: $$A \in k^{n\times n}, A \geq 0 \implies \lambda (A) \geq 0$$

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -104,6 +104,17 @@ theorem posSemidef_conjTranspose_mul_self (A : Matrix m n 𝕜) : Matrix.PosSemi
 theorem posSemidef_self_mul_conjTranspose (A : Matrix m n 𝕜) : Matrix.PosSemidef (A ⬝ Aᴴ) :=
   by simpa only [conjTranspose_conjTranspose] using posSemidef_conjTranspose_mul_self Aᴴ
 
+/-- The eigenvalues of a positive definite matrix are positive -/
+lemma PosDef.eigenvalues_pos [DecidableEq n] [DecidableEq 𝕜] {A : Matrix n n 𝕜}
+    (hA : Matrix.PosDef A) (i : n) : 0 < hA.1.eigenvalues i := by
+  rw [hA.1.eigenvalues_eq, hA.1.transpose_eigenvectorMatrix_apply]
+  exact hA.2 _ <| hA.1.eigenvectorBasis.orthonormal.ne_zero i
+
+/-- The eigenvalues of a positive semi-definite matrix are non-negative -/
+lemma PosSemidef.eigenvalues_nonneg [DecidableEq n] [DecidableEq 𝕜] {A : Matrix n n 𝕜}
+    (hA : Matrix.PosSemidef A) (i : n) : 0 ≤ hA.1.eigenvalues i :=
+  (hA.2 _).trans_eq (hA.1.eigenvalues_eq _).symm
+
 namespace PosDef
 
 variable {M : Matrix n n ℝ} (hM : M.PosDef)
ConjTranspose multiplication of a matrix by itself is Positive Semidefinite (#6359)

This PR provides two lemmas isPosSemidef_conjTranspose_mul_self and isPosSemidef_self_mul_conjTranspose stating that for any matrix $A$ the products $A^HA$ and $AA^H$ in the IsROrC fields are positive semidefinite.

Co-authored-by: Mohanad Ahmed <m.a.m.elhassan@gmail.com>

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -1,7 +1,7 @@
 /-
 Copyright (c) 2022 Alexander Bentkamp. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
-Authors: Alexander Bentkamp
+Authors: Alexander Bentkamp, Mohanad Ahmed
 -/
 import Mathlib.LinearAlgebra.Matrix.Spectrum
 import Mathlib.LinearAlgebra.QuadraticForm.Basic
@@ -93,6 +93,17 @@ theorem posDef_toQuadraticForm' [DecidableEq n] {M : Matrix n n ℝ} (hM : M.Pos
   apply hM.2 x hx
 #align matrix.pos_def_to_quadratic_form' Matrix.posDef_toQuadraticForm'
 
+/-- The conjugate transpose of a matrix mulitplied by the matrix is positive semidefinite -/
+theorem posSemidef_conjTranspose_mul_self (A : Matrix m n 𝕜) : Matrix.PosSemidef (Aᴴ ⬝ A) := by
+  refine ⟨isHermitian_transpose_mul_self _, fun x => ?_⟩
+  rw [← mulVec_mulVec, dotProduct_mulVec, vecMul_conjTranspose, star_star, dotProduct, map_sum]
+  simp_rw [Pi.star_apply, IsROrC.star_def]
+  simpa using Finset.sum_nonneg fun i _ => add_nonneg (mul_self_nonneg _) (mul_self_nonneg _)
+
+/-- A matrix multiplied by its conjugate transpose is positive semidefinite -/
+theorem posSemidef_self_mul_conjTranspose (A : Matrix m n 𝕜) : Matrix.PosSemidef (A ⬝ Aᴴ) :=
+  by simpa only [conjTranspose_conjTranspose] using posSemidef_conjTranspose_mul_self Aᴴ
+
 namespace PosDef
 
 variable {M : Matrix n n ℝ} (hM : M.PosDef)
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,15 +2,12 @@
 Copyright (c) 2022 Alexander Bentkamp. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Alexander Bentkamp
-
-! This file was ported from Lean 3 source module linear_algebra.matrix.pos_def
-! leanprover-community/mathlib commit 07992a1d1f7a4176c6d3f160209608be4e198566
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.LinearAlgebra.Matrix.Spectrum
 import Mathlib.LinearAlgebra.QuadraticForm.Basic
 
+#align_import linear_algebra.matrix.pos_def from "leanprover-community/mathlib"@"07992a1d1f7a4176c6d3f160209608be4e198566"
+
 /-! # Positive Definite Matrices
 This file defines positive (semi)definite matrices and connects the notion to positive definiteness
 of quadratic forms.
feat: port LinearAlgebra.Matrix.PosDef (#5060)

Dependencies 12 + 993

994 files ported (98.8%)
434801 lines ported (98.7%)
Show graph

The unported dependencies are

The following 1 dependencies have changed in mathlib3 since they were ported, which may complicate porting this file