linear_algebra.matrix.pos_def
⟷
Mathlib.LinearAlgebra.Matrix.PosDef
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.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(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)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -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)`. -/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -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'
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -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'
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -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"
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -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.
mathlib commit https://github.com/leanprover-community/mathlib/commit/2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/893964fc28cefbcffc7cb784ed00a2895b4e65cf
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -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]
mathlib commit https://github.com/leanprover-community/mathlib/commit/13361559d66b84f80b6d5a1c4a26aa5054766725
@@ -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 :=
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -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'
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -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`. -/
mathlib commit https://github.com/leanprover-community/mathlib/commit/ef95945cd48c932c9e034872bd25c3c220d9c946
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/738054fa93d43512da144ec45ce799d18fd44248
@@ -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] }
mathlib commit https://github.com/leanprover-community/mathlib/commit/55d771df074d0dd020139ee1cd4b95521422df9f
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/1a313d8bba1bad05faba71a4a4e9742ab5bd9efd
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/2af0836443b4cfb5feda0df0051acdb398304931
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
This fixes the delaborators for sums, products, infimums, and supremums of pi types and matrices.
Also adds a missing whenPPOption getPPNotation
to Prefunctor.obj
.
@@ -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
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:
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.StarOrderedRing
instance on C(α, A)
where A
is a complex (or even real) C⋆-algebra, and making this a mixin avoids loops with StarRing
.@@ -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
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 notnpowRec n x * x
in the definition to make sure that definitional unfolding ofnpowRec
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.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
.@@ -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
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
.
@@ -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]
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
Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Christopher Hoskin <christopher.hoskin@overleaf.com>
@@ -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'
@@ -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 ↦ ?_
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>
@@ -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
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>
@@ -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,
@@ -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
@@ -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) _
@@ -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)
This PR adds two main results about positive semidefinite matrices:
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>
@@ -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
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
@@ -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
@@ -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
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.
@@ -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'
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
@@ -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)
We already have noncomputable DecidableEq
instances for Real
and Complex
; putting them here too reduces friction in code generalized to IsROrC K
.
@@ -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
I assume this is mathematically sound, though right now we can't generalize many dependencies due to the reliance of InnerProductSpace
.
@@ -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
⬝
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).
@@ -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 -/
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -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]
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>
@@ -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)
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>
@@ -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)
@@ -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.
The unported dependencies are
algebra.order.module
init.core
linear_algebra.free_module.finite.rank
algebra.order.monoid.cancel.defs
algebra.abs
algebra.group_power.lemmas
init.data.list.basic
linear_algebra.free_module.rank
init.data.list.default
algebra.order.monoid.cancel.basic
topology.subset_properties
init.logic
The following 1 dependencies have changed in mathlib3 since they were ported, which may complicate porting this file