/- Copyright (c) 2025 Michael R. Douglas, Sarah Hoback, Anna Mei, Ron Nissim. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael R. Douglas, Sarah Hoback, Anna Mei, Ron Nissim -/ import OSforGFF.General.SchurProduct import Mathlib.Analysis.SpecialFunctions.Exp import Mathlib.Analysis.Normed.Algebra.Exponential import Mathlib.Analysis.Complex.TaylorSeries import Mathlib.Analysis.SpecialFunctions.ExpDeriv import Mathlib.Topology.Basic import Mathlib.Order.Filter.Defs import Mathlib.Order.Filter.Basic import Mathlib.Topology.Constructions /-! # Entrywise Exponential of PSD Matrices Develops Hadamard (entrywise) operations on real matrices and proves that the entrywise exponential preserves positive semidefiniteness. The key tool is the Schur product theorem (from `SchurProduct.lean`): Hadamard powers of a PD matrix remain PD, so summing them with coefficients `1/n!` yields a PD matrix. The PSD case follows by a continuity argument: `R + ε I` is PD for every `ε > 0`, and the limit `ε → 0` uses continuity of the entrywise exponential. -/ set_option linter.unusedSectionVars false open Complex open scoped BigOperators open Filter open scoped Topology namespace OSforGFF universe u variable {ι : Type u} [Fintype ι] [DecidableEq ι] /-- Entrywise real exponential of a matrix: `(entrywiseExp R) i j = exp (R i j)`. Used for the OS3 proof (Glimm–Jaffe): if `R` is PSD, then `exp(R)` (entrywise) should be PSD. -/ noncomputable def entrywiseExp (R : Matrix ι ι ℝ) : Matrix ι ι ℝ := fun i j => Real.exp (R i j) @[simp] lemma entrywiseExp_apply (R : Matrix ι ι ℝ) (i j : ι) : entrywiseExp R i j = Real.exp (R i j) := rfl /-- Continuity of the entrywise exponential map `R ↦ exp ∘ R` on matrices. -/ lemma continuous_entrywiseExp (ι : Type u) [Fintype ι] [DecidableEq ι] : Continuous (fun R : Matrix ι ι ℝ => entrywiseExp R) := by classical -- Matrices are pi-types `ι → ι → ℝ`; use coordinatewise continuity refine continuous_pi_iff.2 (fun i => ?_) refine continuous_pi_iff.2 (fun j => ?_) -- Coordinate map R ↦ R i j is continuous; compose with exp have hcoord : Continuous (fun R : Matrix ι ι ℝ => R i j) := (continuous_apply j).comp (continuous_apply i) simpa [entrywiseExp] using (Real.continuous_exp.comp hcoord) /-- Over `ℝ`, entrywise exponential preserves Hermitian symmetry. -/ private lemma isHermitian_entrywiseExp_real (R : Matrix ι ι ℝ) (hR : R.IsHermitian) : (entrywiseExp R).IsHermitian := by rw [Matrix.IsHermitian] ext i j have h_R_herm : R j i = R i j := by simpa using (Matrix.IsHermitian.apply hR j i).symm simpa [Matrix.conjTranspose, entrywiseExp] using congrArg Real.exp h_R_herm /-- Hadamard identity element: the all-ones matrix for entrywise multiplication. -/ @[simp] def hadamardOne (ι : Type u) [Fintype ι] : Matrix ι ι ℝ := fun _ _ => 1 /-- n-fold Hadamard power of a matrix: `hadamardPow R n = R ∘ₕ ⋯ ∘ₕ R` (n times), with `hadamardPow R 0 = hadamardOne`. -/ @[simp] def hadamardPow (R : Matrix ι ι ℝ) : ℕ → Matrix ι ι ℝ | 0 => hadamardOne (ι := ι) | n+1 => hadamardPow R n ∘ₕ R @[simp] lemma hadamardPow_zero (R : Matrix ι ι ℝ) : hadamardPow R 0 = hadamardOne (ι := ι) := rfl @[simp] lemma hadamardPow_succ (R : Matrix ι ι ℝ) (n : ℕ) : hadamardPow R (n+1) = hadamardPow R n ∘ₕ R := rfl /-- Over `ℝ`, the Hadamard product of Hermitian matrices is Hermitian. -/ private lemma isHermitian_hadamard_real {A B : Matrix ι ι ℝ} (hA : A.IsHermitian) (hB : B.IsHermitian) : (A ∘ₕ B).IsHermitian := by rw [Matrix.IsHermitian] ext i j have hAij : A i j = A j i := by simpa using (Matrix.IsHermitian.apply hA i j).symm have hBij : B i j = B j i := by simpa using (Matrix.IsHermitian.apply hB i j).symm simp [Matrix.conjTranspose, Matrix.hadamard, hAij, hBij] /-- Hadamard powers act entrywise as usual scalar powers. -/ lemma hadamardPow_apply (R : Matrix ι ι ℝ) (n : ℕ) (i j : ι) : hadamardPow R n i j = (R i j) ^ n := by induction n with | zero => simp [hadamardPow, hadamardOne] | succ n ih => simp [Matrix.hadamard, ih, pow_succ] /-- One term of the Hadamard-series for the entrywise exponential. -/ noncomputable def entrywiseExpSeriesTerm (R : Matrix ι ι ℝ) (n : ℕ) : Matrix ι ι ℝ := (1 / (Nat.factorial n : ℝ)) • hadamardPow R n /-- Series definition of the entrywise exponential using Hadamard powers (entrywise `tsum`). -/ noncomputable def entrywiseExp_hadamardSeries (R : Matrix ι ι ℝ) : Matrix ι ι ℝ := fun i j => tsum (fun n : ℕ => (1 / (Nat.factorial n : ℝ)) * (hadamardPow R n i j)) /-- The entrywise exponential agrees with its Hadamard series expansion. Uses the Taylor series for Complex.exp and converts to the real case. -/ lemma entrywiseExp_eq_hadamardSeries (R : Matrix ι ι ℝ) : entrywiseExp R = entrywiseExp_hadamardSeries R := by classical funext i j dsimp [entrywiseExp, entrywiseExp_hadamardSeries] -- Scalar reduction set x : ℝ := R i j -- Complex Taylor series for exp at 0 have h_taylor : ∑' n : ℕ, (↑n.factorial)⁻¹ * (iteratedDeriv n Complex.exp 0) * ((x : ℂ) - 0) ^ n = Complex.exp (x : ℂ) := by exact Complex.taylorSeries_eq_on_eball' (c := 0) (r := ⊤) (z := (x : ℂ)) (by simp) (by simpa using Complex.differentiable_exp.differentiableOn) -- iteratedDeriv n exp 0 = 1 have h_deriv : ∀ n, iteratedDeriv n Complex.exp 0 = 1 := by intro n; rw [iteratedDeriv_eq_iterate, Complex.iter_deriv_exp, Complex.exp_zero] -- Define series terms let fC : ℕ → ℂ := fun n => (x : ℂ) ^ n / (Nat.factorial n : ℂ) let fR : ℕ → ℝ := fun n => x ^ n / (Nat.factorial n : ℝ) -- Standard complex power series for exp have h_seriesC : ∑' n : ℕ, fC n = Complex.exp (x : ℂ) := by -- simplify Taylor series to the usual form simpa [fC, div_eq_mul_inv, sub_zero, h_deriv, mul_comm, mul_left_comm, mul_assoc] using h_taylor -- Summability of the complex series via the real one have hsR : Summable fR := Real.summable_pow_div_factorial x have hsC_ofReal : Summable (fun n : ℕ => (fR n : ℂ)) := (Complex.summable_ofReal).2 hsR have h_eqfun : (fun n : ℕ => (fR n : ℂ)) = fC := by funext n; simp [fR, fC, div_eq_mul_inv] have hsC : Summable fC := by simpa [h_eqfun] using hsC_ofReal -- Take real parts in the complex series identity have h_re_tsum : (∑' n : ℕ, fC n).re = ∑' n : ℕ, (fC n).re := Complex.re_tsum hsC have h_re_exp : (Complex.exp (x : ℂ)).re = Real.exp x := Complex.exp_ofReal_re x have h_re_terms : (fun n : ℕ => (fC n).re) = fR := by funext n -- First show fC n equals the complexification of fR n have hpt : fC n = (fR n : ℂ) := by simp [fC, fR, div_eq_mul_inv] -- Then take real parts simpa [Complex.ofReal_re] using congrArg Complex.re hpt -- Combine: real parts of both sides of h_seriesC give the real series identity have hx_sum : ∑' n : ℕ, fR n = Real.exp x := by have := congrArg Complex.re h_seriesC simpa [h_re_tsum, h_re_exp, h_re_terms] using this -- Massaging coefficients and finishing have hx_sum' : Real.exp x = ∑' n : ℕ, (1 / (Nat.factorial n : ℝ)) * x ^ n := by simpa [fR, one_div, div_eq_mul_inv, mul_comm] using hx_sum.symm simpa [x, hadamardPow_apply, one_div, div_eq_mul_inv, mul_comm] using hx_sum' /-- Ones is the identity for the Hadamard product. -/ lemma hadamardOne_hMul_left (R : Matrix ι ι ℝ) : Matrix.hadamard (hadamardOne ι) R = R := by ext i j; simp [hadamardOne, Matrix.hadamard] /-- Hadamard powers of a positive definite matrix are positive definite for all n ≥ 1. -/ lemma hadamardPow_posDef_of_posDef (R : Matrix ι ι ℝ) (hR : R.PosDef) : ∀ n, 1 ≤ n → (hadamardPow R n).PosDef := by classical intro n hn -- write n = k+1 obtain ⟨k, hk⟩ := Nat.exists_eq_succ_of_ne_zero (Nat.pos_iff_ne_zero.mp hn) subst hk induction k with | zero => -- n = 1 have hEq : hadamardPow R 1 = R := by ext i j; simp rw [hEq]; exact hR | succ k ih => -- n = (k+1)+1 = k+2 have hPD_k1 : (hadamardPow R (k+1)).PosDef := ih (Nat.succ_pos _) -- Schur product with R preserves PD simpa [hadamardPow_succ] using schur_product_posDef (A := hadamardPow R (k+1)) (B := R) hPD_k1 hR /-- The quadratic form of the Hadamard series equals the sum of quadratic forms of individual terms. This lemma handles the complex interchange of summation and quadratic form evaluation. -/ lemma quadratic_form_entrywiseExp_hadamardSeries (R : Matrix ι ι ℝ) (x : ι → ℝ) : x ⬝ᵥ (entrywiseExp_hadamardSeries R).mulVec x = ∑' n : ℕ, (1 / (Nat.factorial n : ℝ)) * (x ⬝ᵥ (hadamardPow R n).mulVec x) := by classical -- Per entry: s_ij n := (1 / (n!)) * hadamardPow R n i j let s_ij (i j : ι) (n : ℕ) := (1 / (Nat.factorial n : ℝ)) * hadamardPow R n i j -- Summability for each entry have hs_ij (i j : ι) : Summable (s_ij i j) := by simpa [s_ij, hadamardPow_apply, one_div, div_eq_mul_inv, mul_comm, mul_left_comm, mul_assoc] using Real.summable_pow_div_factorial (R i j) -- HasSum for each entry have hHas_ij (i j : ι) : HasSum (s_ij i j) ((entrywiseExp_hadamardSeries R) i j) := by have h1 : (entrywiseExp_hadamardSeries R) i j = tsum (s_ij i j) := by simp [entrywiseExp_hadamardSeries, s_ij] rw [h1] exact (hs_ij i j).hasSum -- Push scalars inside: first x j have hHas_ij_xj (i j : ι) : HasSum (fun n => s_ij i j n * x j) ((entrywiseExp_hadamardSeries R) i j * x j) := (hHas_ij i j).mul_right (x j) -- Then x i have hHas_ij_xi_xj (i j : ι) : HasSum (fun n => x i * (s_ij i j n * x j)) (x i * ((entrywiseExp_hadamardSeries R) i j * x j)) := (hHas_ij_xj i j).mul_left (x i) -- Rewrite term have hHas_ij_rewrite (i j : ι) : HasSum (fun n => (1 / (Nat.factorial n : ℝ)) * (x i * hadamardPow R n i j * x j)) (x i * ((entrywiseExp_hadamardSeries R) i j) * x j) := by convert hHas_ij_xi_xj i j using 1 · funext n; simp only [s_ij]; ring · simp [mul_assoc] -- Combine over j (finite) with hasSum_sum have hHas_sum_j (i : ι) : HasSum (fun n => ∑ j, (1 / (Nat.factorial n : ℝ)) * (x i * hadamardPow R n i j * x j)) (∑ j, x i * ((entrywiseExp_hadamardSeries R) i j) * x j) := by apply hasSum_sum intro j _ exact hHas_ij_rewrite i j -- Combine over i (finite) similarly have hHas_sum_i : HasSum (fun n => ∑ i, ∑ j, (1 / (Nat.factorial n : ℝ)) * (x i * hadamardPow (ι:=ι) R n i j * x j)) (∑ i, ∑ j, x i * ((entrywiseExp_hadamardSeries (ι:=ι) R) i j) * x j) := by apply hasSum_sum intro i _ exact hHas_sum_j i -- Take tsum of hHas_sum_i have htsum_eq := hHas_sum_i.tsum_eq -- Expand the RHS to x ⬝ᵥ (...) ⬝ᵥ x have hrhs_expand : ∑ i, ∑ j, x i * ((entrywiseExp_hadamardSeries (ι:=ι) R) i j) * x j = x ⬝ᵥ (entrywiseExp_hadamardSeries (ι:=ι) R).mulVec x := by simp only [Matrix.mulVec, dotProduct, Finset.mul_sum] congr 1; ext i; ring_nf -- Identify the LHS coefficient structure have hlhs_identify (n : ℕ) : ∑ i, ∑ j, (1 / (Nat.factorial n : ℝ)) * (x i * hadamardPow (ι:=ι) R n i j * x j) = (1 / (Nat.factorial n : ℝ)) * (x ⬝ᵥ (hadamardPow (ι:=ι) R n).mulVec x) := by simp only [Matrix.mulVec, dotProduct, Finset.mul_sum] congr 1; ext i; congr 1; ext j; ring -- Put it all together rw [← hrhs_expand, ← htsum_eq] simp only [hlhs_identify] /-- Summability of the scalar quadratic-form coefficients appearing in the Hadamard exponential series. -/ lemma summable_hadamardQuadSeries (R : Matrix ι ι ℝ) (x : ι → ℝ) : Summable (fun n : ℕ => (1 / (Nat.factorial n : ℝ)) * (x ⬝ᵥ (hadamardPow (ι:=ι) R n).mulVec x)) := by classical -- Each individual coordinate contributes a summable exponential series. have h_single : ∀ i j : ι, Summable (fun n : ℕ => (1 / (Nat.factorial n : ℝ)) * (x i * (R i j) ^ n * x j)) := by intro i j have h := Real.summable_pow_div_factorial (R i j) simpa [div_eq_mul_inv, mul_comm, mul_left_comm, mul_assoc] using h.mul_left (x i * x j) -- Inner sums over j are summable for every fixed i. have h_inner_hasSum : ∀ i : ι, HasSum (fun n : ℕ => ∑ j : ι, (1 / (Nat.factorial n : ℝ)) * (x i * (R i j) ^ n * x j)) (∑ j : ι, tsum (fun n : ℕ => (1 / (Nat.factorial n : ℝ)) * (x i * (R i j) ^ n * x j))) := by intro i classical apply hasSum_sum exact fun j _ => (h_single i j).hasSum have h_inner : ∀ i : ι, Summable (fun n : ℕ => ∑ j : ι, (1 / (Nat.factorial n : ℝ)) * (x i * (R i j) ^ n * x j)) := fun i => (h_inner_hasSum i).summable -- The outer sum over i remains summable. have h_outer : Summable (fun n : ℕ => ∑ i : ι, ∑ j : ι, (1 / (Nat.factorial n : ℝ)) * (x i * (R i j) ^ n * x j)) := by classical exact summable_sum fun i a => h_inner i -- Identify the quadratic form with the double sum built above. have h_eq : (fun n : ℕ => (1 / (Nat.factorial n : ℝ)) * (x ⬝ᵥ (hadamardPow (ι:=ι) R n).mulVec x)) = fun n : ℕ => ∑ i : ι, ∑ j : ι, (1 / (Nat.factorial n : ℝ)) * (x i * (R i j) ^ n * x j) := by funext n simp [Matrix.mulVec, dotProduct, hadamardPow_apply, div_eq_mul_inv, Finset.mul_sum, mul_comm, mul_left_comm, mul_assoc] -- Conclude summability via the established equality. rw [h_eq] exact h_outer /-- The Hadamard-series entrywise exponential preserves positive definiteness. Sketch: each Hadamard power (for n ≥ 1) is PD by the Schur product theorem and induction; summing with positive coefficients 1/n! yields strictly positive quadratic form for every x ≠ 0 since the n = 1 term already contributes xᵀ R x > 0. Interchange of sum and quadratic form follows from absolute convergence of the scalar exp series; IsHermitian follows termwise. -/ lemma posDef_entrywiseExp_hadamardSeries_of_posDef (R : Matrix ι ι ℝ) (hR : R.PosDef) : (entrywiseExp_hadamardSeries (ι:=ι) R).PosDef := by classical -- Extract Hermitian part from PosDef have hHermR : R.IsHermitian := hR.isHermitian -- Each Hadamard power is Hermitian have hHermPow : ∀ n, (hadamardPow (ι:=ι) R n).IsHermitian := by intro n induction n with | zero => rw [hadamardPow_zero] rw [Matrix.IsHermitian] ext i j simp [hadamardOne, Matrix.conjTranspose] | succ n ih => rw [hadamardPow_succ] exact isHermitian_hadamard_real (ι:=ι) ih hHermR -- Show IsHermitian for the series (termwise symmetry) have hHermS : (entrywiseExp_hadamardSeries (ι:=ι) R).IsHermitian := by rw [Matrix.IsHermitian] ext i j simp [entrywiseExp_hadamardSeries, Matrix.conjTranspose] -- Use termwise symmetry under tsum have hsym_term : ∀ n, (hadamardPow (ι:=ι) R n i j) = (hadamardPow (ι:=ι) R n j i) := by intro n -- from hHermPow n simpa using (Matrix.IsHermitian.apply (hHermPow n) i j).symm -- Apply symmetry termwise in the tsum simp_rw [hsym_term] -- Now show strict positivity of the quadratic form using dotProduct characterization apply Matrix.PosDef.of_dotProduct_mulVec_pos hHermS intro x hx -- Define the scalar series of quadratic forms let f : ℕ → ℝ := fun n => (1 / (Nat.factorial n : ℝ)) * (x ⬝ᵥ (hadamardPow (ι:=ι) R n).mulVec x) -- Identify the quadratic form of the series with the tsum of `f` have hq_tsum : x ⬝ᵥ (entrywiseExp_hadamardSeries (ι:=ι) R).mulVec x = tsum f := by -- Use the helper lemma to establish the quadratic form interchange exact quadratic_form_entrywiseExp_hadamardSeries R x -- Each term f n is nonnegative, and f 1 is strictly positive have hterm_nonneg : ∀ n, 0 ≤ f n := by intro n by_cases hn : n = 0 · -- n = 0: ones matrix subst hn -- Compute the quadratic form against the ones matrix explicitly classical have hmv : (hadamardOne (ι:=ι)).mulVec x = (fun _ => ∑ j, x j) := by funext i; simp [hadamardOne, Matrix.mulVec, dotProduct] have hquad : x ⬝ᵥ (hadamardOne (ι:=ι)).mulVec x = (∑ i, x i) * (∑ i, x i) := by simp [hmv, dotProduct, Finset.sum_mul] -- Reduce to a square ≥ 0 have : 0 ≤ (∑ i, x i) ^ 2 := by exact sq_nonneg _ simpa [f, hadamardPow, Nat.factorial_zero, one_div, hquad, pow_two, inv_one] using this · -- n ≥ 1: use PosSemidef from PosDef have hn1 : 1 ≤ n := Nat.succ_le_of_lt (Nat.pos_of_ne_zero hn) have hPD : (hadamardPow (ι:=ι) R n).PosDef := hadamardPow_posDef_of_posDef (ι:=ι) R hR n hn1 -- hence PosSemidef have hPSD : (hadamardPow (ι:=ι) R n).PosSemidef := Matrix.PosDef.posSemidef hPD -- evaluate quadratic form have hxq : 0 ≤ x ⬝ᵥ (hadamardPow (ι:=ι) R n).mulVec x := hPSD.dotProduct_mulVec_nonneg x positivity have hterm_pos : 0 < f 1 := by -- n = 1 term equals xᵀ R x, which is strictly positive by hR have hEq1' : hadamardPow (ι:=ι) R 1 = Matrix.hadamard (hadamardOne (ι:=ι)) R := rfl have hRpos := hR.dotProduct_mulVec_pos hx simpa [f, hEq1', hadamardOne_hMul_left, Nat.factorial, one_div, inv_one] using hRpos -- Strict positivity of the sum from the positive n=1 term and nonnegativity of the rest have : 0 < tsum f := by -- f is summable because it comes from the quadratic form of a convergent series have hSumm_f : Summable f := by -- The summability of f follows from summable_hadamardQuadSeries -- f n = (1/n!) * (quadratic form in hadamardPow R n) exact summable_hadamardQuadSeries R x -- Now compare tsum with the singleton partial sum at {1} have h_f1_le : f 1 ≤ tsum f := by -- bound partial sum by tsum for nonnegative terms have h := (Summable.sum_le_tsum (s := ({1} : Finset ℕ)) (f := f) (by intro n hn; exact hterm_nonneg n) hSumm_f) simpa using h -- Use strict positivity of f 1 exact lt_of_lt_of_le hterm_pos h_f1_le -- Conclude simpa [hq_tsum] using this set_option maxHeartbeats 1000000 --set_option diagnostics true /-- The Hadamard-series entrywise exponential preserves positive semidefiniteness. This follows from the positive definite case by continuity: if R is PSD, then R + εI is PD for ε > 0, so entrywiseExp_hadamardSeries(R + εI) is PD, and taking ε → 0⁺ with continuity of entrywiseExp_hadamardSeries gives that entrywiseExp_hadamardSeries(R) is PSD. NOTE: This proof is simplified to avoid matrix reduction timeouts. -/ lemma posSemidef_entrywiseExp_hadamardSeries_of_posSemidef (R : Matrix ι ι ℝ) (hR : R.PosSemidef) : (entrywiseExp_hadamardSeries (ι:=ι) R).PosSemidef := by classical -- Step 1: For any ε > 0, R + εI is positive definite have h_perturb_posDef : ∀ (ε : ℝ), ε > 0 → (R + ε • (1 : Matrix ι ι ℝ)).PosDef := by intro ε hε -- R is PSD + εI is PD for ε > 0 gives PD -- This uses: (1) R + εI is Hermitian, (2) quadratic form is x^T R x + ε ||x||^2 > 0 for x ≠ 0 have hR_herm := hR.isHermitian have h_add_herm : (R + ε • (1 : Matrix ι ι ℝ)).IsHermitian := by apply Matrix.IsHermitian.add hR_herm -- ε • 1 is Hermitian since 1 is Hermitian and ε is real rw [Matrix.IsHermitian, Matrix.conjTranspose_smul, Matrix.conjTranspose_one] simp apply Matrix.PosDef.of_dotProduct_mulVec_pos h_add_herm intro x hx_ne_zero have hR_nonneg := hR.dotProduct_mulVec_nonneg x have hε_pos : 0 < ε * (x ⬝ᵥ x) := by have h_norm_pos : 0 < x ⬝ᵥ x := by -- For real vectors, x ⬝ᵥ x = star x ⬝ᵥ x since star = id on ℝ have : x ⬝ᵥ x = star x ⬝ᵥ x := by simp [star] rw [this, Matrix.dotProduct_star_self_pos_iff] exact hx_ne_zero exact mul_pos hε h_norm_pos have h_expand : x ⬝ᵥ (R + ε • (1 : Matrix ι ι ℝ)).mulVec x = x ⬝ᵥ R.mulVec x + ε * (x ⬝ᵥ x) := by rw [Matrix.add_mulVec, dotProduct_add] -- Need to show: x ⬝ᵥ ε • x = ε * x ⬝ᵥ x rw [Matrix.smul_mulVec, Matrix.one_mulVec] rw [dotProduct_smul] -- Now need: ε • (x ⬝ᵥ x) = ε * x ⬝ᵥ x rw [smul_eq_mul] -- Goal has star x, but for real vectors star x = x have : star x ⬝ᵥ (R + ε • 1).mulVec x = x ⬝ᵥ (R + ε • 1).mulVec x := by simp [star] rw [this, h_expand] exact add_pos_of_nonneg_of_pos hR_nonneg hε_pos -- Step 2: For each ε > 0, entrywiseExp_hadamardSeries(R + εI) is positive definite have h_exp_perturb_posDef : ∀ (ε : ℝ), ε > 0 → (entrywiseExp (R + ε • (1 : Matrix ι ι ℝ))).PosDef := by intro ε hε have h := posDef_entrywiseExp_hadamardSeries_of_posDef (R + ε • (1 : Matrix ι ι ℝ)) (h_perturb_posDef ε hε) simpa [entrywiseExp_eq_hadamardSeries] using h -- Step 3: Continuity of the map S ↦ entrywiseExp_hadamardSeries(S) have h_continuous : Continuous (fun S : Matrix ι ι ℝ => entrywiseExp S) := continuous_entrywiseExp ι -- Step 4: Continuity of diagonal perturbation ε ↦ R + εI have h_perturb_continuous : Continuous (fun ε : ℝ => R + ε • (1 : Matrix ι ι ℝ)) := by -- Linear in ε, hence continuous have : Continuous (fun ε : ℝ => ε • (1 : Matrix ι ι ℝ)) := by exact continuous_id.smul continuous_const exact Continuous.add continuous_const this -- Step 5: Composition gives continuity of ε ↦ entrywiseExp_hadamardSeries(R + εI) have h_comp_continuous : Continuous (fun ε : ℝ => entrywiseExp (R + ε • (1 : Matrix ι ι ℝ))) := by exact h_continuous.comp h_perturb_continuous -- Step 6: Limit as ε → 0⁺ gives the result at ε = 0 have h_limit : entrywiseExp R = entrywiseExp (R + 0 • (1 : Matrix ι ι ℝ)) := by -- This uses continuity at ε = 0: lim_{ε→0} entrywiseExp_hadamardSeries(R + εI) = entrywiseExp_hadamardSeries(R) simp only [zero_smul, add_zero] -- Step 7: PosSemidef is preserved under limits of PosDef sequences have h_limit_posSemidef_entry : (entrywiseExp R).PosSemidef := by -- Use the fact that: -- (1) For each ε > 0, entrywiseExp (R + εI) is PosDef (hence PosSemidef) -- (2) The limit entrywiseExp R exists by continuity -- (3) PosSemidef is a closed condition (IsHermitian + nonnegative quadratic form) have h_herm : (entrywiseExp R).IsHermitian := isHermitian_entrywiseExp_real (ι:=ι) R hR.isHermitian apply Matrix.PosSemidef.of_dotProduct_mulVec_nonneg h_herm intro x -- For real vectors, star x = x have h_star_eq : star x = x := by simp [star] -- For each ε > 0: 0 ≤ xᵀ entrywiseExp(R + εI) x have h_nonneg_eps : ∀ (ε : ℝ), ε > 0 → 0 ≤ x ⬝ᵥ (entrywiseExp (R + ε • (1 : Matrix ι ι ℝ))).mulVec x := by intro ε hε -- Use the positive semidefiniteness of entrywiseExp (R + εI) have hPSD := Matrix.PosDef.posSemidef (h_exp_perturb_posDef ε hε) exact hPSD.dotProduct_mulVec_nonneg x -- Quadratic form is continuous: x ⬝ᵥ A.mulVec x is continuous in A have h_quad_continuous : Continuous (fun A : Matrix ι ι ℝ => x ⬝ᵥ A.mulVec x) := by -- Quadratic forms are finite sums of coordinate functions, hence continuous simp only [Matrix.mulVec, dotProduct] apply continuous_finset_sum intro i _ -- Inner sum over j is continuous, then multiply by constant x i have h_inner : Continuous (fun A : Matrix ι ι ℝ => ∑ j, A i j * x j) := by apply continuous_finset_sum intro j _ have h_ij : Continuous fun A : Matrix ι ι ℝ => A i j := (continuous_apply j).comp (continuous_apply i) exact h_ij.mul continuous_const exact continuous_const.mul h_inner -- Consider the composition ε ↦ entrywiseExp (R + εI) have h_path_continuous : Continuous (fun ε : ℝ => entrywiseExp (R + ε • (1 : Matrix ι ι ℝ))) := h_comp_continuous -- Compose with the quadratic form to get the scalar function have h_quad_path_continuous : Continuous (fun ε : ℝ => x ⬝ᵥ (entrywiseExp (R + ε • (1 : Matrix ι ι ℝ))).mulVec x) := h_quad_continuous.comp h_path_continuous -- Apply ge_of_tendsto: if f(ε) ≥ 0 eventually and f → f(0), then f(0) ≥ 0 have h_tendsto : Tendsto (fun ε : ℝ => x ⬝ᵥ (entrywiseExp (R + ε • (1 : Matrix ι ι ℝ))).mulVec x) (𝓝[Set.Ioi 0] 0) (𝓝 (x ⬝ᵥ (entrywiseExp R).mulVec x)) := by -- Use the continuity at 0 to get the right-sided limit have h_cont_at_zero : ContinuousAt (fun ε : ℝ => x ⬝ᵥ (entrywiseExp (R + ε • (1 : Matrix ι ι ℝ))).mulVec x) (0 : ℝ) := h_quad_path_continuous.continuousAt -- Show that the limit value simplifies to the desired form have h_limit_simplify : x ⬝ᵥ (entrywiseExp (R + (0 : ℝ) • (1 : Matrix ι ι ℝ))).mulVec x = x ⬝ᵥ (entrywiseExp R).mulVec x := by simp only [zero_smul, add_zero] -- Convert continuousAt to the right-sided limit rw [← h_limit_simplify] exact tendsto_nhdsWithin_of_tendsto_nhds h_cont_at_zero.tendsto -- Apply ge_of_tendsto: if f(ε) ≥ 0 eventually and f → f(0), then f(0) ≥ 0 have h_final : 0 ≤ x ⬝ᵥ (entrywiseExp R).mulVec x := ge_of_tendsto h_tendsto (by -- Show eventually in 𝓝[Set.Ioi 0] 0, the quadratic form is nonnegative apply eventually_nhdsWithin_of_forall exact h_nonneg_eps) -- Convert from regular inner product to star inner product simpa [h_star_eq] using h_final -- Convert the result back to entrywiseExp_hadamardSeries rw [← entrywiseExp_eq_hadamardSeries] exact h_limit_posSemidef_entry end OSforGFF