/- Copyright (c) 2026 Michael R. Douglas. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael R. Douglas -/ import Mathlib.Data.Complex.Basic import Mathlib.Analysis.Complex.Order import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Fintype.Basic import Mathlib.Algebra.Module.LinearMap.Defs import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Analysis.InnerProductSpace.Basic import Mathlib.LinearAlgebra.Matrix.PosDef import Mathlib.LinearAlgebra.Matrix.Kronecker import Mathlib.Analysis.Matrix.Hermitian import Mathlib.Analysis.Matrix.Order import Mathlib.Analysis.SpecialFunctions.Complex.Circle /-! # Positive Definite Functions A function φ : α → ℂ on an additive group is **positive definite** if: 1. φ(-x) = conj(φ(x)) for all x (Hermitian symmetry), and 2. For any finite collection of points x₁, ..., xₘ and complex coefficients c₁, ..., cₘ, the quadratic form ∑ᵢⱼ c̄ᵢ cⱼ φ(xᵢ - xⱼ) ≥ 0. Condition (1) ensures that the matrix [φ(xᵢ-xⱼ)] is Hermitian, so the quadratic form in (2) is automatically real-valued. Together they say the matrix is Hermitian positive semidefinite. This is the standard definition in harmonic analysis (Rudin, *Fourier Analysis on Groups*, §1.4). Note: some references define PD using only `.re ≥ 0`, but that weaker condition does not imply Hermitian symmetry. ## Main definitions - `IsPositiveDefinite`: positive definiteness for functions on additive groups ## Main results - `IsPositiveDefinite.conj_symm`: φ(-x) = conj(φ(x)) - `IsPositiveDefinite.nonneg`: the quadratic form is nonneg - `IsPositiveDefinite.eval_zero_nonneg`: φ(0) ≥ 0 - `IsPositiveDefinite.bounded_by_zero`: ‖φ(x)‖ ≤ φ(0).re for all x - `IsPositiveDefinite.mul`: pointwise product of PD functions is PD (Schur) - `isPositiveDefinite_precomp_linear`: composition with linear maps preserves PD -/ open Complex BigOperators open scoped Kronecker open scoped ComplexOrder /-- A function φ : α → ℂ is positive definite if the matrix [φ(xᵢ-xⱼ)] is Hermitian positive semidefinite for every finite set of points. This bundles two conditions: - `hermitian`: φ(-x) = conj(φ(x)) (ensures the matrix is Hermitian) - `nonneg`: Re(∑ᵢⱼ c̄ᵢ cⱼ φ(xᵢ - xⱼ)) ≥ 0 (positive semidefiniteness) The Hermitian condition ensures the quadratic form is real, so Re ≥ 0 is equivalent to the full condition ≥ 0. -/ structure IsPositiveDefinite {α : Type*} [AddGroup α] (φ : α → ℂ) : Prop where hermitian : ∀ x : α, φ (-x) = starRingEnd ℂ (φ x) nonneg : ∀ (m : ℕ) (x : Fin m → α) (c : Fin m → ℂ), 0 ≤ (∑ i, ∑ j, (starRingEnd ℂ) (c i) * c j * φ (x i - x j)).re /-- Composition preserves positive definiteness: if ψ is positive definite on H and T : E →ₗ[ℝ] H is linear, then ψ ∘ T is positive definite on E. -/ lemma isPositiveDefinite_precomp_linear {E H : Type*} [AddCommGroup E] [AddCommGroup H] [Module ℝ E] [Module ℝ H] (ψ : H → ℂ) (hPD : IsPositiveDefinite ψ) (T : E →ₗ[ℝ] H) : IsPositiveDefinite (fun f : E => ψ (T f)) where hermitian x := by simp [map_neg, hPD.hermitian] nonneg m x c := by simpa using hPD.nonneg m (fun i => T (x i)) c namespace IsPositiveDefinite variable {α : Type*} [AddGroup α] {φ : α → ℂ} private lemma kernelMatrix_posSemidef {m : ℕ} (hpd : IsPositiveDefinite φ) (x : Fin m → α) : (((Matrix.of fun i j => φ (x i - x j)) : Matrix (Fin m) (Fin m) ℂ).PosSemidef) := by let M : Matrix (Fin m) (Fin m) ℂ := Matrix.of fun i j => φ (x i - x j) have hM_herm : M.IsHermitian := by refine Matrix.IsHermitian.ext ?_ intro i j change starRingEnd ℂ (φ (x j - x i)) = φ (x i - x j) simpa [sub_eq_add_neg, add_comm, add_left_comm, add_assoc] using (hpd.hermitian (x j - x i)).symm refine Matrix.posSemidef_iff_dotProduct_mulVec.mpr ⟨hM_herm, ?_⟩ intro c have hre : 0 ≤ (dotProduct (star c) (M.mulVec c)).re := by simpa [M, dotProduct, Matrix.mulVec, Finset.mul_sum, mul_assoc, mul_left_comm, mul_comm] using hpd.nonneg m x c have him : (dotProduct (star c) (M.mulVec c)).im = 0 := by simpa [M] using hM_herm.im_star_dotProduct_mulVec_self c exact Complex.nonneg_iff.mpr ⟨hre, him.symm⟩ /-- φ(-x) = conj(φ(x)). -/ lemma conj_symm (hpd : IsPositiveDefinite φ) (x : α) : φ (-x) = starRingEnd ℂ (φ x) := hpd.hermitian x /-- φ(0) is real and nonneg. (Test with m = 1, c₁ = 1.) -/ lemma eval_zero_nonneg (hpd : IsPositiveDefinite φ) : 0 ≤ (φ 0).re := by have h := hpd.nonneg 1 (fun _ => 0) (fun _ => 1) simp [starRingEnd_apply, star_one] at h exact h /-- φ(0) is real (imaginary part is zero). -/ lemma eval_zero_real (hpd : IsPositiveDefinite φ) : (φ 0).im = 0 := by have h := hpd.hermitian 0 simp only [neg_zero] at h -- h : φ 0 = starRingEnd ℂ (φ 0), i.e., φ 0 = conj(φ 0) -- This means Im(φ 0) = 0 have := congr_arg Complex.im h simp [Complex.conj_im] at this linarith /-- Helper: expand the PD condition for m=2. -/ private lemma pd_two (hpd : IsPositiveDefinite φ) (a b : α) (c₀ c₁ : ℂ) : 0 ≤ (starRingEnd ℂ c₀ * c₀ * φ (a - a) + starRingEnd ℂ c₀ * c₁ * φ (a - b) + (starRingEnd ℂ c₁ * c₀ * φ (b - a) + starRingEnd ℂ c₁ * c₁ * φ (b - b))).re := by have h := hpd.nonneg 2 ![a, b] ![c₀, c₁] simp only [Fin.sum_univ_two, Matrix.cons_val_zero, Matrix.cons_val_one] at h exact h /-- ‖φ(x)‖ ≤ φ(0).re for all x. (Cauchy-Schwarz on the 2×2 PD matrix.) -/ lemma bounded_by_zero (hpd : IsPositiveDefinite φ) (x : α) : ‖φ x‖ ≤ (φ 0).re := by -- Handle the case φ x = 0 by_cases hφx : φ x = 0 · have : ‖φ x‖ = 0 := by rw [hφx]; simp linarith [hpd.eval_zero_nonneg] -- Use the 2×2 PD condition with c = ![1, -φ(x)/‖φ(x)‖] -- which gives φ(0).re - ‖φ(x)‖ ≥ 0 set t : ℂ := -(φ x / (‖φ x‖ : ℂ)) have h := pd_two hpd 0 x 1 t simp only [sub_self, sub_zero, zero_sub] at h -- Now h : 0 ≤ (conj(1)·1·φ(0) + conj(1)·t·φ(-x) + conj(t)·1·φ(x) + conj(t)·t·φ(0)).re simp only [map_one, one_mul, mul_one] at h rw [hpd.hermitian x] at h -- h now has conj(φ x) in place of φ(-x) -- t = -φ(x)/‖φ(x)‖, so conj(t) = -conj(φ x)/‖φ(x)‖ simp only [t, map_neg, map_div₀, conj_ofReal] at h -- Simplify conj(z)*z and z*conj(z) terms using normSq have hnorm_pos : (‖φ x‖ : ℝ) ≠ 0 := by positivity have hnorm_pos' : (‖φ x‖ : ℂ) ≠ 0 := Complex.ofReal_ne_zero.mpr hnorm_pos -- Key: φ(x) * conj(φ(x)) = ‖φ(x)‖² and conj(φ(x)) * φ(x) = ‖φ(x)‖² have hns : (starRingEnd ℂ) (φ x) * φ x = ↑(‖φ x‖ ^ 2) := by rw [mul_comm, Complex.mul_conj, normSq_eq_norm_sq] have hns' : φ x * (starRingEnd ℂ) (φ x) = ↑(‖φ x‖ ^ 2) := by rw [Complex.mul_conj, normSq_eq_norm_sq] -- Rewrite the three non-trivial terms in h -- Term 1: -(φ x / ↑‖φ x‖) * conj(φ x) = -‖φ x‖² / ‖φ x‖ = -‖φ x‖ have ht1 : -(φ x / ↑‖φ x‖) * (starRingEnd ℂ) (φ x) = -(↑‖φ x‖) := by rw [neg_mul, neg_inj, div_mul_eq_mul_div, hns', Complex.ofReal_pow, sq, mul_div_cancel_right₀ _ hnorm_pos'] -- Term 2: -(conj(φ x) / ↑‖φ x‖) * φ x = -‖φ x‖ have ht2 : -((starRingEnd ℂ) (φ x) / ↑‖φ x‖) * φ x = -(↑‖φ x‖) := by rw [neg_mul, neg_inj, div_mul_eq_mul_div, hns, Complex.ofReal_pow, sq, mul_div_cancel_right₀ _ hnorm_pos'] -- Term 3: -(conj(φ x)/‖φ x‖) * -(φ x/‖φ x‖) = ‖φ x‖²/‖φ x‖² = 1 have ht3 : -((starRingEnd ℂ) (φ x) / ↑‖φ x‖) * -(φ x / ↑‖φ x‖) = 1 := by rw [neg_mul_neg, div_mul_div_comm, hns, Complex.ofReal_pow, sq, div_self (mul_ne_zero hnorm_pos' hnorm_pos')] rw [ht1, ht2, ht3, one_mul] at h -- h : 0 ≤ (φ 0 + -↑‖φ x‖ + (-↑‖φ x‖ + φ 0)).re -- = 2 * (φ 0).re - 2 * ‖φ x‖ simp only [Complex.add_re, Complex.neg_re, Complex.ofReal_re] at h have him : (φ 0).im = 0 := hpd.eval_zero_real linarith /-- Pointwise product of PD functions is PD (Schur product theorem for functions). This is the key fact used in Phase 2 (Gaussian regularization). Proof idea: The Hadamard (entrywise) product of two PSD Hermitian matrices is PSD. For the Hermitian condition, use conj(φψ) = conj(φ)conj(ψ). -/ lemma mul (hpd : IsPositiveDefinite φ) {ψ : α → ℂ} (hψ : IsPositiveDefinite ψ) : IsPositiveDefinite (fun x => φ x * ψ x) := by refine ⟨?_, ?_⟩ · intro x rw [map_mul, hpd.hermitian x, hψ.hermitian x] · intro m x c let A : Matrix (Fin m) (Fin m) ℂ := fun i j => φ (x i - x j) let B : Matrix (Fin m) (Fin m) ℂ := fun i j => ψ (x i - x j) let e : Fin m → Fin m × Fin m := fun i => (i, i) have hA : A.PosSemidef := by simpa [A] using kernelMatrix_posSemidef hpd x have hB : B.PosSemidef := by simpa [B] using kernelMatrix_posSemidef hψ x have hK : (A ⊗ₖ B).PosSemidef := hA.kronecker hB have hSub : ((A ⊗ₖ B).submatrix e e).PosSemidef := hK.submatrix e have hnonneg := hSub.dotProduct_mulVec_nonneg c exact (RCLike.nonneg_iff.mp hnonneg).1.trans_eq <| by simp [A, B, e, dotProduct, Matrix.mulVec, Finset.mul_sum, mul_assoc, mul_left_comm, mul_comm] end IsPositiveDefinite