/- Copyright (c) 2026 Michael R. Douglas. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. # Nuclear Tensor Product via Köthe Sequence Spaces Defines `RapidDecaySeq`, the Köthe sequence space s(ℕ) of rapidly decreasing sequences, and proves it is a nuclear Fréchet space. Then defines `NuclearTensorProduct E₁ E₂` as `RapidDecaySeq` (via Cantor pairing), providing a `DyninMityaginSpace` instance for tensor products of nuclear spaces. ## Main definitions - `RapidDecaySeq` — rapidly decreasing sequences on ℕ - `rapidDecaySeminorm k` — the k-th seminorm: `∑ₘ |aₘ| (1+m)^k` - `NuclearTensorProduct E₁ E₂` — tensor product of nuclear spaces ## Mathematical background Every nuclear Fréchet space with a Schauder basis is isomorphic to a Köthe sequence space s(ℕ) with rapidly decreasing weights (Dynin-Mityagin). The tensor product s(ℕ) ⊗̂ s(ℕ) ≅ s(ℕ²) ≅ s(ℕ) via Cantor pairing. ## References - Dynin, Mityagin, "Criterion for nuclearity in terms of approximative dimension" - Gel'fand-Vilenkin, "Generalized Functions" Vol. 4 -/ import Nuclear.DyninMityagin import Nuclear.NuclearSpace import Mathlib.Analysis.LocallyConvex.WithSeminorms import Mathlib.Analysis.PSeries import Mathlib.Topology.Algebra.InfiniteSum.Basic import Mathlib.Topology.Algebra.InfiniteSum.Order import Mathlib.Topology.Algebra.InfiniteSum.Ring noncomputable section namespace GaussianField /-! ## Rapidly Decreasing Sequences -/ /-- A rapidly decreasing sequence: `val : ℕ → ℝ` such that `∑ₘ |val m| · (1 + m)^k` converges for all `k : ℕ`. -/ structure RapidDecaySeq where val : ℕ → ℝ rapid_decay : ∀ k : ℕ, Summable (fun m => |val m| * (1 + (m : ℝ)) ^ k) namespace RapidDecaySeq @[ext] theorem ext {a b : RapidDecaySeq} (h : ∀ m, a.val m = b.val m) : a = b := by cases a; cases b; congr 1; exact funext h /-! ### Weight function lemmas -/ theorem weight_pos (m : ℕ) (k : ℕ) : (0 : ℝ) < (1 + (m : ℝ)) ^ k := by positivity theorem weight_nonneg (m : ℕ) (k : ℕ) : (0 : ℝ) ≤ (1 + (m : ℝ)) ^ k := le_of_lt (weight_pos m k) /-! ### Algebraic structure -/ instance instZero : Zero RapidDecaySeq where zero := ⟨0, fun k => by simp [summable_zero]⟩ @[simp] theorem zero_val (m : ℕ) : (0 : RapidDecaySeq).val m = 0 := rfl instance instAdd : Add RapidDecaySeq where add a b := ⟨a.val + b.val, fun k => by apply Summable.of_nonneg_of_le · intro m; exact mul_nonneg (abs_nonneg _) (weight_nonneg m k) · intro m; simp only [Pi.add_apply] calc |a.val m + b.val m| * (1 + ↑m) ^ k ≤ (|a.val m| + |b.val m|) * (1 + ↑m) ^ k := mul_le_mul_of_nonneg_right (abs_add_le _ _) (weight_nonneg m k) _ = |a.val m| * (1 + ↑m) ^ k + |b.val m| * (1 + ↑m) ^ k := add_mul _ _ _ · exact (a.rapid_decay k).add (b.rapid_decay k)⟩ @[simp] theorem add_val (a b : RapidDecaySeq) (m : ℕ) : (a + b).val m = a.val m + b.val m := rfl instance instNeg : Neg RapidDecaySeq where neg a := ⟨fun m => -a.val m, fun k => by simp only [abs_neg]; exact a.rapid_decay k⟩ @[simp] theorem neg_val (a : RapidDecaySeq) (m : ℕ) : (-a).val m = -a.val m := rfl instance instSMul : SMul ℝ RapidDecaySeq where smul r a := ⟨fun m => r * a.val m, fun k => by have h : (fun m => |r * a.val m| * (1 + (m : ℝ)) ^ k) = fun m => |r| * (|a.val m| * (1 + (m : ℝ)) ^ k) := by ext m; rw [abs_mul, mul_assoc] rw [h] exact (a.rapid_decay k).const_smul |r|⟩ @[simp] theorem smul_val (r : ℝ) (a : RapidDecaySeq) (m : ℕ) : (r • a).val m = r * a.val m := rfl instance instAddCommGroup : AddCommGroup RapidDecaySeq where add_assoc a b c := ext fun m => add_assoc _ _ _ zero_add a := ext fun m => zero_add _ add_zero a := ext fun m => add_zero _ nsmul := nsmulRec zsmul := zsmulRec neg_add_cancel a := ext fun m => neg_add_cancel _ add_comm a b := ext fun m => add_comm _ _ instance instModule : Module ℝ RapidDecaySeq where one_smul _ := ext fun _ => one_mul _ mul_smul _ _ _ := ext fun _ => mul_assoc _ _ _ smul_zero _ := ext fun _ => mul_zero _ smul_add _ _ _ := ext fun _ => mul_add _ _ _ add_smul _ _ _ := ext fun _ => add_mul _ _ _ zero_smul _ := ext fun _ => zero_mul _ /-! ### Seminorm family -/ /-- The k-th seminorm on rapid decay sequences: `∑ₘ |aₘ| · (1+m)^k`. -/ def rapidDecaySeminorm (k : ℕ) : Seminorm ℝ RapidDecaySeq where toFun a := ∑' m, |a.val m| * (1 + (m : ℝ)) ^ k map_zero' := by simp [zero_val, tsum_zero] add_le' a b := by calc ∑' m, |(a + b).val m| * (1 + ↑m) ^ k ≤ ∑' m, (|a.val m| * (1 + ↑m) ^ k + |b.val m| * (1 + ↑m) ^ k) := by exact ((a + b).rapid_decay k).tsum_le_tsum (fun m => by simp only [add_val] calc |a.val m + b.val m| * (1 + ↑m) ^ k ≤ (|a.val m| + |b.val m|) * (1 + ↑m) ^ k := mul_le_mul_of_nonneg_right (abs_add_le _ _) (weight_nonneg m k) _ = _ := add_mul _ _ _) ((a.rapid_decay k).add (b.rapid_decay k)) _ = ∑' m, |a.val m| * (1 + ↑m) ^ k + ∑' m, |b.val m| * (1 + ↑m) ^ k := (a.rapid_decay k).tsum_add (b.rapid_decay k) neg' a := by congr 1; ext m; rw [neg_val, abs_neg] smul' r a := by show ∑' m, |r * a.val m| * (1 + ↑m) ^ k = ‖r‖ * ∑' m, |a.val m| * (1 + ↑m) ^ k simp_rw [abs_mul, Real.norm_eq_abs, mul_assoc] exact tsum_mul_left /-! ### Topology from seminorms -/ instance instTopologicalSpace : TopologicalSpace RapidDecaySeq := (SeminormFamily.moduleFilterBasis (𝕜 := ℝ) rapidDecaySeminorm).topology theorem rapidDecay_withSeminorms : WithSeminorms (rapidDecaySeminorm : ℕ → Seminorm ℝ RapidDecaySeq) := ⟨rfl⟩ instance instIsTopologicalAddGroup : IsTopologicalAddGroup RapidDecaySeq := rapidDecay_withSeminorms.topologicalAddGroup instance instContinuousSMul : ContinuousSMul ℝ RapidDecaySeq := rapidDecay_withSeminorms.continuousSMul /-- `RapidDecaySeq` is complete with respect to the right uniform structure induced by its topological add group structure. **Proof outline.** Given a Cauchy sequence `u : ℕ → RapidDecaySeq`: 1. Each coordinate `m ↦ (u n).val m` is Cauchy in ℝ (bounded by seminorm 0), hence converges to some `a m`. 2. The sequence `u` is eventually bounded in each seminorm (Cauchy property), so `a` inherits rapid decay: `∑ |a m| (1+m)^k ≤ B`. 3. Convergence `u n → a` in the seminorm topology follows from passing the Cauchy bounds through limits of partial sums. -/ -- Helper: coordinate projection is bounded by seminorm 0 private theorem coord_le_seminorm0 (a : RapidDecaySeq) (m : ℕ) : |a.val m| ≤ rapidDecaySeminorm 0 a := by show |a.val m| ≤ ∑' n, |a.val n| * (1 + (n : ℝ)) ^ 0 calc |a.val m| = |a.val m| * (1 + (m : ℝ)) ^ 0 := by simp [pow_zero] _ ≤ ∑' n, |a.val n| * (1 + (n : ℝ)) ^ 0 := (a.rapid_decay 0).le_tsum m (fun j _ => mul_nonneg (abs_nonneg _) (weight_nonneg j 0)) -- Helper: finite sum of weighted coords ≤ seminorm private theorem finset_sum_le_seminorm (a : RapidDecaySeq) (k : ℕ) (s : Finset ℕ) : ∑ m ∈ s, |a.val m| * (1 + (m : ℝ)) ^ k ≤ rapidDecaySeminorm k a := (a.rapid_decay k).sum_le_tsum s (fun m _ => mul_nonneg (abs_nonneg _) (weight_nonneg m k)) -- Helper: Cauchy condition for seminorms. From CauchySeq in the seminorm topology, -- extract: for each k and ε > 0, ∃ N, ∀ n m ≥ N, seminorm k (u n - u m) < ε. private theorem cauchySeq_seminorm_bound (u : ℕ → RapidDecaySeq) (hu : @CauchySeq RapidDecaySeq ℕ (IsTopologicalAddGroup.rightUniformSpace RapidDecaySeq) _ u) (k : ℕ) (ε : ℝ) (hε : 0 < ε) : ∃ N, ∀ n m, N ≤ n → N ≤ m → rapidDecaySeminorm k (u n - u m) < ε := by letI : UniformSpace RapidDecaySeq := IsTopologicalAddGroup.rightUniformSpace RapidDecaySeq -- The Cauchy condition says differences u n - u m are eventually in any nhds 0 set. -- We use the additive Cauchy characterization via entourages. -- The set {(x,y) | seminorm k (x - y) < ε} is an entourage because -- the uniformity = comap (fun p => p.2 - p.1) (nhds 0) for the right uniform structure, -- and {x | seminorm k x < ε} is a neighborhood of 0. have h_ent : {p : RapidDecaySeq × RapidDecaySeq | rapidDecaySeminorm k (p.1 - p.2) < ε} ∈ uniformity RapidDecaySeq := by -- Rewrite using the right uniform structure definition show {p : RapidDecaySeq × RapidDecaySeq | rapidDecaySeminorm k (p.1 - p.2) < ε} ∈ uniformity RapidDecaySeq rw [show uniformity RapidDecaySeq = Filter.comap (fun p : RapidDecaySeq × RapidDecaySeq => p.2 - p.1) (nhds 0) from rfl] apply Filter.mem_comap.mpr refine ⟨{x | rapidDecaySeminorm k x < ε}, ?_, ?_⟩ · -- {x | seminorm k x < ε} ∈ nhds 0 have h0 : rapidDecaySeminorm k 0 = 0 := map_zero _ have : {x | rapidDecaySeminorm k x < ε} ∈ nhds (0 : RapidDecaySeq) := (rapidDecay_withSeminorms.continuous_seminorm k).continuousAt.preimage_mem_nhds (by rw [h0]; exact Iio_mem_nhds hε) exact this · intro ⟨a, b⟩ (hx : rapidDecaySeminorm k (b - a) < ε) show rapidDecaySeminorm k (a - b) < ε rwa [show a - b = -(b - a) from (neg_sub b a).symm, map_neg_eq_map] exact hu.mem_entourage h_ent instance instCompleteSpace : @CompleteSpace RapidDecaySeq (IsTopologicalAddGroup.rightUniformSpace RapidDecaySeq) := by letI : UniformSpace RapidDecaySeq := IsTopologicalAddGroup.rightUniformSpace RapidDecaySeq haveI : IsUniformAddGroup RapidDecaySeq := isUniformAddGroup_of_addCommGroup haveI : (nhds (0 : RapidDecaySeq)).IsCountablyGenerated := by rw [(SeminormFamily.withSeminorms_iff_nhds_eq_iInf rapidDecaySeminorm).1 rapidDecay_withSeminorms] exact Filter.iInf.isCountablyGenerated _ haveI : (uniformity RapidDecaySeq).IsCountablyGenerated := IsUniformAddGroup.uniformity_countably_generated apply UniformSpace.complete_of_cauchySeq_tendsto intro u hu -- Step 1: Extract Cauchy condition for seminorms have hcauchy : ∀ k ε, 0 < ε → ∃ N, ∀ n m, N ≤ n → N ≤ m → rapidDecaySeminorm k (u n - u m) < ε := fun k ε hε => cauchySeq_seminorm_bound u hu k ε hε -- Step 2: Each coordinate sequence is Cauchy in ℝ, hence convergent have coord_cauchy : ∀ m, CauchySeq (fun n => (u n).val m) := by intro m rw [Metric.cauchySeq_iff'] intro ε hε obtain ⟨N, hN⟩ := hcauchy 0 ε hε exact ⟨N, fun n hn => by rw [Real.dist_eq] calc |((u n).val m - (u N).val m)| = |(u n - u N).val m| := by show _ = |((u n) + (-(u N))).val m|; simp [add_val, neg_val, sub_eq_add_neg] _ ≤ rapidDecaySeminorm 0 (u n - u N) := coord_le_seminorm0 _ m _ < ε := hN n N hn le_rfl⟩ -- Get the pointwise limit choose a ha using fun m => cauchySeq_tendsto_of_complete (coord_cauchy m) -- Step 3: Show `a` has rapid decay -- From Cauchy: for each k, ∃ bound B such that all seminorm k (u n) ≤ B have seminorm_bound : ∀ k, ∃ B, ∀ n, rapidDecaySeminorm k (u n) ≤ B := by intro k obtain ⟨N, hN⟩ := hcauchy k 1 one_pos -- For n ≥ N, seminorm k (u n) ≤ seminorm k (u N) + 1 by triangle inequality -- For n < N, we can take the max have h_large : ∀ n, N ≤ n → rapidDecaySeminorm k (u n) ≤ rapidDecaySeminorm k (u N) + 1 := by intro n hn calc rapidDecaySeminorm k (u n) = rapidDecaySeminorm k ((u n - u N) + u N) := by rw [sub_add_cancel] _ ≤ rapidDecaySeminorm k (u n - u N) + rapidDecaySeminorm k (u N) := map_add_le_add _ _ _ _ ≤ 1 + rapidDecaySeminorm k (u N) := by linarith [hN n N hn le_rfl] _ = rapidDecaySeminorm k (u N) + 1 := by ring -- Take the max of all values let B := (Finset.range (N + 1)).sup' ⟨0, Finset.mem_range.mpr (Nat.zero_lt_succ N)⟩ (fun n => rapidDecaySeminorm k (u n)) ⊔ (rapidDecaySeminorm k (u N) + 1) refine ⟨B, fun n => ?_⟩ by_cases hn : N ≤ n · exact le_sup_of_le_right (h_large n hn) · push Not at hn apply le_sup_of_le_left exact Finset.le_sup' (fun i => rapidDecaySeminorm k (u i)) (Finset.mem_range.mpr (by omega)) -- Now show a has rapid decay: for each k, ∑ |a m| * (1+m)^k converges -- Key: for any finite s, ∑_{m∈s} |a m| * (1+m)^k ≤ B -- because ∑_{m∈s} |a m| * (1+m)^k = lim_n ∑_{m∈s} |(u n).val m| * (1+m)^k ≤ B have a_rapid : ∀ k, Summable (fun m => |a m| * (1 + (m : ℝ)) ^ k) := by intro k obtain ⟨B, hB⟩ := seminorm_bound k apply summable_of_sum_le (fun m => mul_nonneg (abs_nonneg _) (weight_nonneg m k)) intro s -- ∑_{m∈s} |a m| * w m = lim_n ∑_{m∈s} |(u n).val m| * w m -- For each finite m, (u n).val m → a m, so |(u n).val m| → |a m| -- Hence the finite sum converges have h_sum_lim : Filter.Tendsto (fun n => ∑ m ∈ s, |(u n).val m| * (1 + (m : ℝ)) ^ k) Filter.atTop (nhds (∑ m ∈ s, |a m| * (1 + (m : ℝ)) ^ k)) := by apply tendsto_finsetSum intro m _ exact (Filter.Tendsto.abs (ha m)).mul tendsto_const_nhds -- Each partial sum ≤ seminorm k (u n) ≤ B have h_sum_le : ∀ n, ∑ m ∈ s, |(u n).val m| * (1 + (m : ℝ)) ^ k ≤ B := by intro n exact le_trans (finset_sum_le_seminorm (u n) k s) (hB n) exact le_of_tendsto h_sum_lim (Filter.Eventually.of_forall h_sum_le) -- Construct the limit element let L : RapidDecaySeq := ⟨a, a_rapid⟩ -- Step 4: Show u n → L in the seminorm topology refine ⟨L, ?_⟩ rw [rapidDecay_withSeminorms.tendsto_nhds_atTop u L] intro k ε hε obtain ⟨N, hN⟩ := hcauchy k (ε / 2) (half_pos hε) refine ⟨N, fun n hn => ?_⟩ -- Need: rapidDecaySeminorm k (u n - L) < ε -- i.e., ∑' m, |(u n).val m - a m| * (1+m)^k < ε -- For any finite s: -- ∑_{m∈s} |(u n).val m - a m| * w m -- = lim_j ∑_{m∈s} |(u n).val m - (u j).val m| * w m (since (u j).val m → a m) -- ≤ lim_j rapidDecaySeminorm k (u n - u j) (finite sum ≤ seminorm) -- But for j ≥ N, rapidDecaySeminorm k (u n - u j) < ε/2 -- So ∑_{m∈s} |(u n).val m - a m| * w m ≤ ε/2 -- By tsum_le_of_sum_le (taking sup over all s), ∑' m ≤ ε/2 < ε show rapidDecaySeminorm k (u n - L) < ε -- Rewrite the seminorm as a tsum of |(u n).val m - a m| * weight have h_eq : rapidDecaySeminorm k (u n - L) = ∑' m, |(u n).val m - a m| * (1 + (m : ℝ)) ^ k := by show ∑' m, |(u n - L).val m| * (1 + (m : ℝ)) ^ k = _ simp only [sub_eq_add_neg, add_val, neg_val, L] rw [h_eq] -- Show the tsum ≤ ε/2 suffices h : ∑' m, |(u n).val m - a m| * (1 + (m : ℝ)) ^ k ≤ ε / 2 by linarith apply Real.tsum_le_of_sum_le (fun m => mul_nonneg (abs_nonneg _) (weight_nonneg m k)) intro s -- For each finite s, the partial sum ≤ ε/2 -- ∑_{m∈s} |(u n).val m - a m| * w m = lim_j ∑_{m∈s} |(u n).val m - (u j).val m| * w m have h_lim : Filter.Tendsto (fun j => ∑ m ∈ s, |(u n).val m - (u j).val m| * (1 + (m : ℝ)) ^ k) Filter.atTop (nhds (∑ m ∈ s, |(u n).val m - a m| * (1 + (m : ℝ)) ^ k)) := by apply tendsto_finsetSum intro m _ exact ((tendsto_const_nhds.sub (ha m)).abs).mul tendsto_const_nhds apply le_of_tendsto h_lim rw [Filter.eventually_atTop] refine ⟨N, fun j hj => ?_⟩ calc ∑ m ∈ s, |(u n).val m - (u j).val m| * (1 + (m : ℝ)) ^ k = ∑ m ∈ s, |(u n - u j).val m| * (1 + (m : ℝ)) ^ k := by simp only [sub_eq_add_neg, add_val, neg_val] _ ≤ rapidDecaySeminorm k (u n - u j) := finset_sum_le_seminorm (u n - u j) k s _ ≤ ε / 2 := le_of_lt (hN n j hn hj) /-! ### Standard basis and coefficients -/ /-- The m-th standard basis vector: 1 at position m, 0 elsewhere. -/ def basisVec (m : ℕ) : RapidDecaySeq where val n := if n = m then 1 else 0 rapid_decay k := by apply summable_of_ne_finset_zero (s := {m}) intro n hn simp only [Finset.mem_singleton] at hn simp [hn] @[simp] theorem basisVec_val_self (m : ℕ) : (basisVec m).val m = 1 := by simp [basisVec] @[simp] theorem basisVec_val_ne {m n : ℕ} (h : n ≠ m) : (basisVec m).val n = 0 := by simp [basisVec, h] /-- Seminorm of a basis vector is exactly `(1 + m)^k`. -/ theorem rapidDecaySeminorm_basisVec (k m : ℕ) : rapidDecaySeminorm k (basisVec m) = (1 + (m : ℝ)) ^ k := by show ∑' n, |(basisVec m).val n| * (1 + (n : ℝ)) ^ k = (1 + (m : ℝ)) ^ k rw [tsum_eq_single m] · simp [basisVec] · intro n hn; simp [basisVec, hn] /-- The m-th coefficient linear map: extracts coordinate m. -/ def coeffLM (m : ℕ) : RapidDecaySeq →ₗ[ℝ] ℝ where toFun a := a.val m map_add' a b := rfl map_smul' r a := by simp [smul_eq_mul] /-- The m-th coefficient as a continuous linear map. Continuity follows from `|a.val m| ≤ rapidDecaySeminorm 0 a`: the coordinate projection is bounded by the 0-th seminorm. -/ def coeffCLM (m : ℕ) : RapidDecaySeq →L[ℝ] ℝ where toLinearMap := coeffLM m cont := by apply WithSeminorms.continuous_of_isBounded rapidDecay_withSeminorms (norm_withSeminorms ℝ ℝ) intro _ refine ⟨{0}, 1, ?_⟩ intro a simp only [Seminorm.comp_apply, Finset.sup_singleton, one_smul, coe_normSeminorm, coeffLM, LinearMap.coe_mk, AddHom.coe_mk, Real.norm_eq_abs] change |a.val m| ≤ ∑' n, |a.val n| * (1 + (n : ℝ)) ^ 0 calc |a.val m| = |a.val m| * (1 + (m : ℝ)) ^ 0 := by simp [pow_zero] _ ≤ ∑' n, |a.val n| * (1 + (n : ℝ)) ^ 0 := (a.rapid_decay 0).le_tsum m (fun j _ => mul_nonneg (abs_nonneg _) (weight_nonneg j 0)) /-! ### DyninMityaginSpace instance -/ /-- The partial sums `∑_{m∈s} a.val(m) • basisVec(m)` converge to `a`. For each seminorm `k` and `ε > 0`, the error `∑_{n ∉ s} |aₙ| · (1+n)^k` is the tail of the convergent series `a.rapid_decay k`, hence eventually less than `ε`. -/ private theorem sum_smul_basisVec_val (a : RapidDecaySeq) (s : Finset ℕ) (n : ℕ) : (∑ m ∈ s, a.val m • basisVec m).val n = if n ∈ s then a.val n else 0 := by induction s using Finset.induction with | empty => simp | insert m _ hm ih => rw [Finset.sum_insert hm, add_val, ih] simp only [smul_val, basisVec, mul_ite, mul_one, mul_zero, Finset.mem_insert] by_cases h : n = m · subst h; simp [show n ∉ _ from hm] · simp [h] theorem hasSum_basisVec (a : RapidDecaySeq) : HasSum (fun m => a.val m • basisVec m) a := by rw [HasSum, (rapidDecay_withSeminorms.tendsto_nhds _ a)] intro k ε hε simp only [SummationFilter.unconditional_filter] -- g n = |a.val n| * (1+n)^k is summable with nonneg terms set g : ℕ → ℝ := fun n => |a.val n| * (1 + (n : ℝ)) ^ k with hg_def have hg_nn : ∀ n, 0 ≤ g n := fun n => mul_nonneg (abs_nonneg _) (weight_nonneg n k) have hg_sum : Summable g := a.rapid_decay k -- Partial sums of g converge to tsum g; extract eventual bound have hgHS := hg_sum.hasSum rw [HasSum, SummationFilter.unconditional_filter] at hgHS have h_ev := (tendsto_order.mp hgHS).1 _ (sub_lt_self (∑' n, g n) hε) rw [Filter.eventually_atTop] at h_ev ⊢ obtain ⟨s₀, hs₀⟩ := h_ev exact ⟨s₀, fun s hss => by have h_partial := hs₀ s hss -- Error terms: |error.val n| * (1+n)^k = if n ∈ s then 0 else g n have h_err_terms : ∀ n, |((∑ m ∈ s, a.val m • basisVec m) - a).val n| * (1 + ↑n) ^ k = if n ∈ s then 0 else g n := by intro n simp only [sub_eq_add_neg, add_val, neg_val, sum_smul_basisVec_val] split <;> simp [g, abs_neg] -- Show seminorm < ε show (rapidDecaySeminorm k) ((∑ m ∈ s, a.val m • basisVec m) - a) < ε change ∑' n, |((∑ m ∈ s, a.val m • basisVec m) - a).val n| * (1 + ↑n) ^ k < ε simp_rw [h_err_terms] -- ∑' n, (if n ∈ s then 0 else g n) = ∑' n, g n - ∑ n ∈ s, g n < ε have h_compl_summable : Summable (fun n => if (n ∈ s) then (0 : ℝ) else g n) := Summable.of_nonneg_of_le (fun n => by split <;> simp [hg_nn]) (fun n => by split <;> simp [hg_nn]) hg_sum have h_fin_summable : Summable (fun n => if (n ∈ s) then g n else (0 : ℝ)) := summable_of_ne_finset_zero (s := s) (fun n hn => if_neg hn) have h_split : ∑' n, g n = ∑' n, (if (n ∈ s) then g n else (0 : ℝ)) + ∑' n, (if (n ∈ s) then (0 : ℝ) else g n) := by rw [← h_fin_summable.tsum_add h_compl_summable] congr 1; ext n; split <;> simp have h_fin_eq : ∑' n, (if (n ∈ s) then g n else (0 : ℝ)) = ∑ n ∈ s, g n := by rw [tsum_eq_sum (fun n hn => if_neg hn)] exact Finset.sum_congr rfl (fun n hn => if_pos hn) linarith⟩ theorem rapidDecay_expansion (φ : RapidDecaySeq →L[ℝ] ℝ) (a : RapidDecaySeq) : φ a = ∑' m, (a.val m) * φ (basisVec m) := by have h : HasSum (fun m => φ (a.val m • basisVec m)) (φ a) := (hasSum_basisVec a).mapL φ have h' : HasSum (fun m => a.val m * φ (basisVec m)) (φ a) := by convert h using 1; ext m; simp [map_smul, smul_eq_mul] exact h'.tsum_eq.symm /-- `RapidDecaySeq` is T1: if `a ≠ 0`, the 0-th seminorm `∑ |a_m| > 0`. -/ instance rapidDecay_t1Space : T1Space RapidDecaySeq := rapidDecay_withSeminorms.T1_of_separating fun a ha => by refine ⟨0, ?_⟩ -- rapidDecaySeminorm 0 a = ∑' m, |a.val m| * 1 = ∑' m, |a.val m| intro h apply ha -- h : rapidDecaySeminorm 0 a = 0, i.e., ∑' m, |a.val m| * 1 = 0 have h' : ∑' m, |a.val m| = 0 := by have := h; simp only [rapidDecaySeminorm, pow_zero, mul_one] at this; exact this -- Each |a.val m| = 0 since nonneg terms sum to 0 have hcomp : ∀ m, a.val m = 0 := by intro m have hle : |a.val m| ≤ 0 := by calc |a.val m| = |a.val m| * (1 + (m : ℝ)) ^ 0 := by simp [pow_zero] _ ≤ ∑' n, |a.val n| * (1 + (n : ℝ)) ^ 0 := (a.rapid_decay 0).le_tsum m (fun j _ => mul_nonneg (abs_nonneg _) (weight_nonneg j 0)) _ = 0 := by simp [pow_zero, mul_one, h'] exact abs_eq_zero.mp (le_antisymm hle (abs_nonneg _)) ext m; exact hcomp m instance rapidDecay_dyninMityaginSpace : DyninMityaginSpace RapidDecaySeq where ι := ℕ p := rapidDecaySeminorm h_with := rapidDecay_withSeminorms h_countable := instCountableNat h_completeSpace := instCompleteSpace basis := basisVec coeff := coeffCLM expansion := rapidDecay_expansion basis_growth k := ⟨1, one_pos, k, fun m => by rw [rapidDecaySeminorm_basisVec]; linarith⟩ coeff_decay k := ⟨1, one_pos, {k}, fun a m => by simp only [Finset.sup_singleton, coeffCLM, ContinuousLinearMap.coe_mk', coeffLM, LinearMap.coe_mk, AddHom.coe_mk, one_mul] show |a.val m| * (1 + ↑m) ^ k ≤ ∑' n, |a.val n| * (1 + ↑n) ^ k exact (a.rapid_decay k).le_tsum m (fun j _ => mul_nonneg (abs_nonneg _) (weight_nonneg j k))⟩ instance rapidDecay_hasBiorthogonalBasis : DyninMityaginSpace.HasBiorthogonalBasis RapidDecaySeq where coeff_basis n m := by show (basisVec m).val n = if n = m then 1 else 0 simp [basisVec] /-! ### Helper lemmas for seminorm transfer -/ /-- Monotonicity of rapid-decay seminorms: for j ≤ j', seminorm j ≤ seminorm j'. -/ theorem rapidDecaySeminorm_mono {j j' : ℕ} (hjj : j ≤ j') : rapidDecaySeminorm j ≤ rapidDecaySeminorm j' := by intro a show ∑' m, |a.val m| * (1 + (m : ℝ)) ^ j ≤ ∑' m, |a.val m| * (1 + (m : ℝ)) ^ j' apply (a.rapid_decay j).tsum_le_tsum _ (a.rapid_decay j') intro m apply mul_le_mul_of_nonneg_left _ (abs_nonneg _) exact pow_le_pow_right₀ (le_add_of_nonneg_right (Nat.cast_nonneg m)) hjj /-- The sup of rapid-decay seminorms over a finset is bounded by the seminorm at the max index. -/ theorem finset_sup_rapidDecaySeminorm_le (s : Finset ℕ) : s.sup rapidDecaySeminorm ≤ rapidDecaySeminorm (s.sup id) := by apply Finset.sup_le intro j hj exact rapidDecaySeminorm_mono (Finset.le_sup (f := id) hj) /-- The sup of rapid-decay seminorms evaluated at a basis vector gives polynomial growth. -/ theorem finset_sup_rapidDecaySeminorm_basisVec_le (s : Finset ℕ) (m : ℕ) : (s.sup rapidDecaySeminorm) (basisVec m) ≤ (1 + (m : ℝ)) ^ (s.sup id) := by calc (s.sup rapidDecaySeminorm) (basisVec m) ≤ rapidDecaySeminorm (s.sup id) (basisVec m) := finset_sup_rapidDecaySeminorm_le s (basisVec m) _ = (1 + (m : ℝ)) ^ (s.sup id) := rapidDecaySeminorm_basisVec _ m end RapidDecaySeq /-! ### Transfer constructor for DyninMityaginSpace -/ /-- Transfer a `DyninMityaginSpace` structure from `RapidDecaySeq` to any space that is continuously linearly equivalent to it. Given seminorms `p` with `WithSeminorms p` and a CLE `equiv : E ≃L[ℝ] RapidDecaySeq`, constructs the DyninMityaginSpace instance using `basis m := equiv.symm (basisVec m)` and `coeff m := coeffCLM m ∘ equiv`. Countability of `ι` and completeness of `E` (transferred from `RapidDecaySeq` via the CLE) are propagated automatically. -/ @[reducible] noncomputable def DyninMityaginSpace.ofRapidDecayEquiv {E : Type*} [AddCommGroup E] [Module ℝ E] [TopologicalSpace E] [IsTopologicalAddGroup E] [ContinuousSMul ℝ E] {ι : Type} [Countable ι] (p : ι → Seminorm ℝ E) (hp : WithSeminorms p) (equiv : E ≃L[ℝ] RapidDecaySeq) : DyninMityaginSpace E where toT1Space := t1Space_of_injective_of_continuous equiv.injective equiv.continuous ι := ι p := p h_with := hp h_countable := ‹Countable ι› h_completeSpace := by -- Transfer CompleteSpace from RapidDecaySeq to E via the CLE. -- Set up uniform spaces on both sides from rightUniformSpace. letI uE : UniformSpace E := IsTopologicalAddGroup.rightUniformSpace E haveI : IsUniformAddGroup E := isUniformAddGroup_of_addCommGroup letI uR : UniformSpace RapidDecaySeq := IsTopologicalAddGroup.rightUniformSpace RapidDecaySeq haveI : IsUniformAddGroup RapidDecaySeq := isUniformAddGroup_of_addCommGroup exact (completeSpace_congr (e := equiv.toLinearEquiv.toEquiv) equiv.isUniformEmbedding).2 RapidDecaySeq.instCompleteSpace basis m := equiv.symm (RapidDecaySeq.basisVec m) coeff m := (RapidDecaySeq.coeffCLM m).comp equiv.toContinuousLinearMap expansion φ f := by show φ f = ∑' m, (equiv f).val m * φ (equiv.symm (RapidDecaySeq.basisVec m)) have h := RapidDecaySeq.rapidDecay_expansion (φ.comp equiv.symm.toContinuousLinearMap) (equiv f) simp only [ContinuousLinearMap.comp_apply] at h rwa [show (↑equiv.symm : RapidDecaySeq →L[ℝ] E) (equiv f) = f from equiv.symm_apply_apply f] at h basis_growth i := by set q : Seminorm ℝ RapidDecaySeq := (p i).comp equiv.symm.toLinearMap have hq_cont : Continuous q := (hp.continuous_seminorm i).comp equiv.symm.continuous obtain ⟨s_fin, C_nn, hC_nn, hle⟩ := Seminorm.bound_of_continuous RapidDecaySeq.rapidDecay_withSeminorms q hq_cont set N := s_fin.sup id have hC_pos : (0 : ℝ) < C_nn := NNReal.coe_pos.mpr (bot_lt_iff_ne_bot.mpr hC_nn) refine ⟨(C_nn : ℝ), hC_pos, N, fun m => ?_⟩ calc p i (equiv.symm (RapidDecaySeq.basisVec m)) = q (RapidDecaySeq.basisVec m) := rfl _ ≤ C_nn • (s_fin.sup RapidDecaySeq.rapidDecaySeminorm) (RapidDecaySeq.basisVec m) := hle (RapidDecaySeq.basisVec m) _ ≤ (C_nn : ℝ) * (1 + (m : ℝ)) ^ N := by simp only [NNReal.smul_def, smul_eq_mul] exact mul_le_mul_of_nonneg_left (RapidDecaySeq.finset_sup_rapidDecaySeminorm_basisVec_le s_fin m) (NNReal.coe_nonneg C_nn) coeff_decay k := by set q : Seminorm ℝ E := (RapidDecaySeq.rapidDecaySeminorm k).comp equiv.toLinearMap have hq_cont : Continuous q := (RapidDecaySeq.rapidDecay_withSeminorms.continuous_seminorm k).comp equiv.continuous obtain ⟨s_fin, C_nn, hC_nn, hle⟩ := Seminorm.bound_of_continuous hp q hq_cont have hC_pos : (0 : ℝ) < C_nn := NNReal.coe_pos.mpr (bot_lt_iff_ne_bot.mpr hC_nn) refine ⟨(C_nn : ℝ), hC_pos, s_fin, fun f m => ?_⟩ have h_le_tsum : |(RapidDecaySeq.coeffCLM m (equiv f))| * (1 + (m : ℝ)) ^ k ≤ RapidDecaySeq.rapidDecaySeminorm k (equiv f) := by show |(equiv f).val m| * (1 + (m : ℝ)) ^ k ≤ ∑' n, |(equiv f).val n| * (1 + (n : ℝ)) ^ k exact ((equiv f).rapid_decay k).le_tsum m (fun j _ => mul_nonneg (abs_nonneg _) (RapidDecaySeq.weight_nonneg j k)) have h_bound : RapidDecaySeq.rapidDecaySeminorm k (equiv f) ≤ (C_nn : ℝ) * (s_fin.sup p) f := by have := hle f simp only [smul_apply, NNReal.smul_def, smul_eq_mul] at this exact this show |(RapidDecaySeq.coeffCLM m (equiv f))| * (1 + (m : ℝ)) ^ k ≤ (C_nn : ℝ) * (s_fin.sup p) f exact le_trans h_le_tsum h_bound /-- `ofRapidDecayEquiv` always produces a biorthogonal DM space. -/ theorem DyninMityaginSpace.ofRapidDecayEquiv_hasBiorthogonalBasis {E : Type*} [AddCommGroup E] [Module ℝ E] [TopologicalSpace E] [IsTopologicalAddGroup E] [ContinuousSMul ℝ E] {ι : Type} [Countable ι] (p : ι → Seminorm ℝ E) (hp : WithSeminorms p) (equiv : E ≃L[ℝ] RapidDecaySeq) : letI := DyninMityaginSpace.ofRapidDecayEquiv p hp equiv DyninMityaginSpace.HasBiorthogonalBasis E := letI := DyninMityaginSpace.ofRapidDecayEquiv p hp equiv { coeff_basis := fun n m => by show RapidDecaySeq.coeffCLM n (equiv (equiv.symm (RapidDecaySeq.basisVec m))) = if n = m then 1 else 0 rw [ContinuousLinearEquiv.apply_symm_apply] show (RapidDecaySeq.basisVec m).val n = if n = m then 1 else 0 simp [RapidDecaySeq.basisVec, eq_comm] } /-! ## Cantor Pairing Bound -/ /-- The Cantor pairing function is bounded by a quadratic. -/ theorem nat_pair_bound (n m : ℕ) : Nat.pair n m ≤ (n + m + 1) ^ 2 := by have hpair : Nat.pair n m ≤ (max n m + 1) ^ 2 := Nat.le_of_lt (Nat.pair_lt_max_add_one_sq n m) have hmax : max n m + 1 ≤ n + m + 1 := by exact Nat.succ_le_succ (max_le (Nat.le_add_right n m) (Nat.le_add_left m n)) exact hpair.trans (Nat.pow_le_pow_left hmax 2) /-- Converse bound: each component of `Nat.unpair` is bounded by the pair index. -/ theorem nat_unpair_le (p : ℕ) : (Nat.unpair p).1 ≤ p ∧ (Nat.unpair p).2 ≤ p := ⟨Nat.unpair_left_le p, Nat.unpair_right_le p⟩ /-! ## Nuclear Tensor Product -/ /-- The nuclear tensor product of two nuclear spaces, realized as the Köthe sequence space of rapidly decreasing sequences. The product basis indices `ℕ × ℕ` are encoded into `ℕ` via `Nat.pair`. Mathematically, if `E₁ ≅ s(ℕ)` and `E₂ ≅ s(ℕ)` as nuclear Fréchet spaces, then `E₁ ⊗̂ E₂ ≅ s(ℕ × ℕ) ≅ s(ℕ)` via the Cantor pairing. -/ def NuclearTensorProduct (_E₁ _E₂ : Type*) := RapidDecaySeq namespace NuclearTensorProduct variable {E₁ E₂ : Type*} @[ext] theorem ext {a b : NuclearTensorProduct E₁ E₂} (h : ∀ m, a.val m = b.val m) : a = b := RapidDecaySeq.ext h instance : AddCommGroup (NuclearTensorProduct E₁ E₂) := inferInstanceAs (AddCommGroup RapidDecaySeq) instance : Module ℝ (NuclearTensorProduct E₁ E₂) := inferInstanceAs (Module ℝ RapidDecaySeq) @[simp] theorem add_val (a b : NuclearTensorProduct E₁ E₂) (m : ℕ) : (a + b).val m = a.val m + b.val m := rfl @[simp] theorem smul_val (r : ℝ) (a : NuclearTensorProduct E₁ E₂) (m : ℕ) : (r • a).val m = r * a.val m := rfl instance : TopologicalSpace (NuclearTensorProduct E₁ E₂) := inferInstanceAs (TopologicalSpace RapidDecaySeq) instance : IsTopologicalAddGroup (NuclearTensorProduct E₁ E₂) := inferInstanceAs (IsTopologicalAddGroup RapidDecaySeq) instance : ContinuousSMul ℝ (NuclearTensorProduct E₁ E₂) := inferInstanceAs (ContinuousSMul ℝ RapidDecaySeq) /-- The nuclear tensor product is a nuclear space. -/ instance dyninMityaginSpace : DyninMityaginSpace (NuclearTensorProduct E₁ E₂) := RapidDecaySeq.rapidDecay_dyninMityaginSpace /-- Map from product basis indices to the Cantor-paired linear index. -/ def fromPairIndex (n m : ℕ) : ℕ := Nat.pair n m /-- Recover product basis indices from a linear index. -/ def toPairIndex (p : ℕ) : ℕ × ℕ := Nat.unpair p theorem toPairIndex_fromPairIndex (n m : ℕ) : toPairIndex (fromPairIndex n m) = (n, m) := Nat.unpair_pair n m theorem fromPairIndex_toPairIndex (p : ℕ) : fromPairIndex (toPairIndex p).1 (toPairIndex p).2 = p := Nat.pair_unpair p /-! ### Pure tensor embedding -/ /-- The Cantor pairing as an equivalence `ℕ ≃ ℕ × ℕ`. -/ private def natUnpairEquiv : ℕ ≃ ℕ × ℕ where toFun := Nat.unpair invFun p := Nat.pair p.1 p.2 left_inv := Nat.pair_unpair right_inv p := Nat.unpair_pair p.1 p.2 /-- `∑_n 1/(1+n)^2` converges, as a shifted version of `∑ 1/n^2`. -/ theorem summable_inv_one_add_sq : Summable (fun n : ℕ => ((1 + (n : ℝ)) ^ 2)⁻¹) := by -- Reindex: (fun n => ((1 + n)^2)⁻¹) = (fun n => (n^2)⁻¹) ∘ (· + 1) have h_eq : (fun n : ℕ => ((1 + (n : ℝ)) ^ 2)⁻¹) = (fun n : ℕ => (((n : ℝ)) ^ 2)⁻¹) ∘ (· + 1) := by ext n; simp [Function.comp, add_comm] rw [h_eq] apply Summable.comp_injective · exact Real.summable_nat_pow_inv.mpr (by norm_num : 1 < 2) · exact fun a b hab => by omega /-- The inverse-square series over Cantor-paired indices converges: `∑_m 1/((1+fst(m))² · (1+snd(m))²)` is finite. -/ private theorem summable_unpair_inv_sq : Summable (fun m : ℕ => ((1 + ((Nat.unpair m).1 : ℝ)) ^ 2 * (1 + ((Nat.unpair m).2 : ℝ)) ^ 2)⁻¹) := by -- Rewrite as product of inverse squares, transfer to ℕ×ℕ via pairing equiv, -- then factor as product of two convergent series have h_eq : (fun m => ((1 + ((Nat.unpair m).1 : ℝ)) ^ 2 * (1 + ((Nat.unpair m).2 : ℝ)) ^ 2)⁻¹) = (fun p : ℕ × ℕ => ((1 + (p.1 : ℝ)) ^ 2)⁻¹ * ((1 + (p.2 : ℝ)) ^ 2)⁻¹) ∘ natUnpairEquiv := by ext m; simp [natUnpairEquiv, mul_inv_rev, mul_comm] rw [h_eq, natUnpairEquiv.summable_iff] set g : ℕ × ℕ → ℝ := fun p => ((1 + (p.1 : ℝ)) ^ 2)⁻¹ * ((1 + (p.2 : ℝ)) ^ 2)⁻¹ show Summable g have hg_nn : 0 ≤ g := fun p => by dsimp [g]; positivity have h1 : ∀ x, Summable fun y => g (x, y) := fun x => by dsimp [g] exact summable_inv_one_add_sq.mul_left _ have h2 : Summable fun x => ∑' y, g (x, y) := by have : (fun x : ℕ => ∑' y, g (x, y)) = fun x : ℕ => ((1 + (x : ℝ)) ^ 2)⁻¹ * ∑' (y : ℕ), ((1 + (y : ℝ)) ^ 2)⁻¹ := by ext x; dsimp [g]; rw [tsum_mul_left] rw [this] exact summable_inv_one_add_sq.mul_right _ exact (summable_prod_of_nonneg hg_nn).mpr ⟨h1, h2⟩ /-- Arithmetic bound: `(1 + Nat.pair i j) ≤ (2 * (1 + i) * (1 + j)) ^ 2`. Used to transfer rapid decay of individual coefficient sequences to rapid decay of the tensor product sequence indexed via Cantor pairing. -/ private theorem one_add_pair_le_sq (i j : ℕ) : (1 + (Nat.pair i j : ℝ)) ≤ (2 * (1 + (i : ℝ)) * (1 + (j : ℝ))) ^ 2 := by have hi : (0 : ℝ) ≤ i := Nat.cast_nonneg i have hj : (0 : ℝ) ≤ j := Nat.cast_nonneg j have h_pair : (Nat.pair i j : ℝ) ≤ ((i : ℝ) + j + 1) ^ 2 := by exact_mod_cast nat_pair_bound i j calc (1 : ℝ) + Nat.pair i j ≤ 1 + (i + j + 1) ^ 2 := by linarith _ ≤ (i + j + 2) ^ 2 := by nlinarith _ ≤ (2 * (1 + i) * (1 + j)) ^ 2 := by exact pow_le_pow_left₀ (by positivity) (by nlinarith) _ /-- The pure tensor map: given `e₁ : E₁` and `e₂ : E₂` with DM structure, produces the sequence `m ↦ coeff(unpair(m).1, e₁) * coeff(unpair(m).2, e₂)`. This is the bilinear embedding `E₁ × E₂ → E₁ ⊗̂ E₂` realized at the level of Köthe sequence spaces. -/ noncomputable def pure [AddCommGroup E₁] [Module ℝ E₁] [TopologicalSpace E₁] [IsTopologicalAddGroup E₁] [ContinuousSMul ℝ E₁] [AddCommGroup E₂] [Module ℝ E₂] [TopologicalSpace E₂] [IsTopologicalAddGroup E₂] [ContinuousSMul ℝ E₂] [DyninMityaginSpace E₁] [DyninMityaginSpace E₂] (e₁ : E₁) (e₂ : E₂) : NuclearTensorProduct E₁ E₂ := (⟨fun m => let p := Nat.unpair m DyninMityaginSpace.coeff p.1 e₁ * DyninMityaginSpace.coeff p.2 e₂, fun k => by -- Strategy: bound each term by B/(1+i)²(1+j)² where (i,j) = unpair m, -- then show the bounding series converges. -- Get uniform bounds from coeff_decay at exponent 2k+2 obtain ⟨C₁, hC₁_pos, s₁, hs₁⟩ := DyninMityaginSpace.coeff_decay (E := E₁) (2 * k + 2) obtain ⟨C₂, hC₂_pos, s₂, hs₂⟩ := DyninMityaginSpace.coeff_decay (E := E₂) (2 * k + 2) set B₁ := C₁ * (s₁.sup DyninMityaginSpace.p) e₁ set B₂ := C₂ * (s₂.sup DyninMityaginSpace.p) e₂ have hc₁ : ∀ n, |DyninMityaginSpace.coeff n e₁| * (1 + (n : ℝ)) ^ (2 * k + 2) ≤ B₁ := fun n => hs₁ e₁ n have hc₂ : ∀ n, |DyninMityaginSpace.coeff n e₂| * (1 + (n : ℝ)) ^ (2 * k + 2) ≤ B₂ := fun n => hs₂ e₂ n apply Summable.of_nonneg_of_le · intro m; exact mul_nonneg (abs_nonneg _) (RapidDecaySeq.weight_nonneg m k) · intro m set i := (Nat.unpair m).1 set j := (Nat.unpair m).2 show |DyninMityaginSpace.coeff i e₁ * DyninMityaginSpace.coeff j e₂| * (1 + (m : ℝ)) ^ k ≤ B₁ * B₂ * (4 : ℝ) ^ k / ((1 + (i : ℝ)) ^ 2 * (1 + (j : ℝ)) ^ 2) rw [abs_mul] have hm_eq : m = Nat.pair i j := (Nat.pair_unpair m).symm have hi_pos : (0 : ℝ) < 1 + (i : ℝ) := by positivity have hj_pos : (0 : ℝ) < 1 + (j : ℝ) := by positivity -- Key: (1+m)^k ≤ 4^k * (1+i)^{2k} * (1+j)^{2k} have h_weight : (1 + (m : ℝ)) ^ k ≤ (4 : ℝ) ^ k * (1 + (i : ℝ)) ^ (2 * k) * (1 + (j : ℝ)) ^ (2 * k) := by have h1 : (1 + (m : ℝ)) ^ k ≤ ((2 * (1 + (i : ℝ)) * (1 + (j : ℝ))) ^ 2) ^ k := by rw [hm_eq] exact pow_le_pow_left₀ (by positivity) (by exact_mod_cast one_add_pair_le_sq i j) _ have h2 : ((2 * (1 + (i : ℝ)) * (1 + (j : ℝ))) ^ 2) ^ k = (4 : ℝ) ^ k * (1 + (i : ℝ)) ^ (2 * k) * (1 + (j : ℝ)) ^ (2 * k) := by have h4 : (4 : ℝ) ^ k = (2 : ℝ) ^ (2 * k) := by rw [show (4 : ℝ) = 2 ^ 2 from by norm_num, ← pow_mul] rw [h4, ← pow_mul, mul_pow, mul_pow] linarith -- From coeff decay: |a_i| * (1+i)^{2k} ≤ B₁ / (1+i)^2 have h_a : |DyninMityaginSpace.coeff i e₁| * (1 + (i : ℝ)) ^ (2 * k) ≤ B₁ / (1 + (i : ℝ)) ^ 2 := by rw [le_div_iff₀ (pow_pos hi_pos 2)] calc |DyninMityaginSpace.coeff i e₁| * (1 + ↑i) ^ (2 * k) * (1 + ↑i) ^ 2 = |DyninMityaginSpace.coeff i e₁| * ((1 + ↑i) ^ (2 * k) * (1 + ↑i) ^ 2) := by ring _ = |DyninMityaginSpace.coeff i e₁| * (1 + ↑i) ^ (2 * k + 2) := by rw [← pow_add] _ ≤ B₁ := hc₁ i have h_b : |DyninMityaginSpace.coeff j e₂| * (1 + (j : ℝ)) ^ (2 * k) ≤ B₂ / (1 + (j : ℝ)) ^ 2 := by rw [le_div_iff₀ (pow_pos hj_pos 2)] calc |DyninMityaginSpace.coeff j e₂| * (1 + ↑j) ^ (2 * k) * (1 + ↑j) ^ 2 = |DyninMityaginSpace.coeff j e₂| * ((1 + ↑j) ^ (2 * k) * (1 + ↑j) ^ 2) := by ring _ = |DyninMityaginSpace.coeff j e₂| * (1 + ↑j) ^ (2 * k + 2) := by rw [← pow_add] _ ≤ B₂ := hc₂ j -- Combine the bounds calc |DyninMityaginSpace.coeff i e₁| * |DyninMityaginSpace.coeff j e₂| * (1 + (m : ℝ)) ^ k ≤ |DyninMityaginSpace.coeff i e₁| * |DyninMityaginSpace.coeff j e₂| * ((4 : ℝ) ^ k * (1 + ↑i) ^ (2 * k) * (1 + ↑j) ^ (2 * k)) := mul_le_mul_of_nonneg_left h_weight (by positivity) _ = (|DyninMityaginSpace.coeff i e₁| * (1 + ↑i) ^ (2 * k)) * (|DyninMityaginSpace.coeff j e₂| * (1 + ↑j) ^ (2 * k)) * (4 : ℝ) ^ k := by ring _ ≤ (B₁ / (1 + ↑i) ^ 2) * (B₂ / (1 + ↑j) ^ 2) * (4 : ℝ) ^ k := by apply mul_le_mul_of_nonneg_right _ (by positivity) exact mul_le_mul h_a h_b (mul_nonneg (abs_nonneg _) (by positivity)) (by positivity) _ = B₁ * B₂ * (4 : ℝ) ^ k / ((1 + ↑i) ^ 2 * (1 + ↑j) ^ 2) := by field_simp · -- Summability: ∑_m B₁*B₂*4^k / ((1+i)²*(1+j)²) converges have hconst : (0 : ℝ) ≤ B₁ * B₂ * (4 : ℝ) ^ k := by positivity simp_rw [div_eq_mul_inv] exact (summable_unpair_inv_sq.mul_left (B₁ * B₂ * (4 : ℝ) ^ k))⟩ : RapidDecaySeq) variable [AddCommGroup E₁] [Module ℝ E₁] [TopologicalSpace E₁] [IsTopologicalAddGroup E₁] [ContinuousSMul ℝ E₁] [AddCommGroup E₂] [Module ℝ E₂] [TopologicalSpace E₂] [IsTopologicalAddGroup E₂] [ContinuousSMul ℝ E₂] [DyninMityaginSpace E₁] [DyninMityaginSpace E₂] @[simp] theorem pure_val (e₁ : E₁) (e₂ : E₂) (m : ℕ) : (pure e₁ e₂).val m = DyninMityaginSpace.coeff (Nat.unpair m).1 e₁ * DyninMityaginSpace.coeff (Nat.unpair m).2 e₂ := rfl /-- Seminorm bound for the pure tensor: for each target seminorm index `k`, there exist constants `C`, source seminorm index sets `s₁, s₂` such that `rapidDecaySeminorm k (pure e₁ e₂) ≤ C * (s₁.sup p) e₁ * (s₂.sup p) e₂`. -/ theorem pure_seminorm_bound (k : ℕ) : ∃ (C : NNReal) (s₁ : Finset (@DyninMityaginSpace.ι E₁ _ _ _ _ _ _)) (s₂ : Finset (@DyninMityaginSpace.ι E₂ _ _ _ _ _ _)), ∀ (e₁ : E₁) (e₂ : E₂), RapidDecaySeq.rapidDecaySeminorm k (pure e₁ e₂) ≤ C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂ := by obtain ⟨C₁, hC₁_pos, s₁, hs₁⟩ := DyninMityaginSpace.coeff_decay (E := E₁) (2 * k + 2) obtain ⟨C₂, hC₂_pos, s₂, hs₂⟩ := DyninMityaginSpace.coeff_decay (E := E₂) (2 * k + 2) -- The constant is C₁ * C₂ * 4^k * (tsum of inverse squares) set T := ∑' (m : ℕ), ((1 + ((Nat.unpair m).1 : ℝ)) ^ 2 * (1 + ((Nat.unpair m).2 : ℝ)) ^ 2)⁻¹ have hT_pos : 0 < T := summable_unpair_inv_sq.tsum_pos (fun m => by positivity) 0 (by positivity) have hC_nn : (0 : ℝ) ≤ C₁ * C₂ * (4 : ℝ) ^ k * T := by positivity refine ⟨⟨C₁ * C₂ * (4 : ℝ) ^ k * T, hC_nn⟩, s₁, s₂, fun e₁ e₂ => ?_⟩ -- The seminorm is a tsum; bound each term show ∑' m, |(pure e₁ e₂).val m| * (1 + (m : ℝ)) ^ k ≤ C₁ * C₂ * (4 : ℝ) ^ k * T * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂ set B₁ := C₁ * (s₁.sup DyninMityaginSpace.p) e₁ set B₂ := C₂ * (s₂.sup DyninMityaginSpace.p) e₂ -- Each term is bounded by B₁*B₂*4^k / ((1+i)²*(1+j)²) have h_term_bound : ∀ m, |(pure e₁ e₂).val m| * (1 + (m : ℝ)) ^ k ≤ B₁ * B₂ * (4 : ℝ) ^ k * ((1 + ((Nat.unpair m).1 : ℝ)) ^ 2 * (1 + ((Nat.unpair m).2 : ℝ)) ^ 2)⁻¹ := by intro m set i := (Nat.unpair m).1 set j := (Nat.unpair m).2 simp only [pure_val, abs_mul] have hm_eq : m = Nat.pair i j := (Nat.pair_unpair m).symm have hi_pos : (0 : ℝ) < 1 + (i : ℝ) := by positivity have hj_pos : (0 : ℝ) < 1 + (j : ℝ) := by positivity have h_weight : (1 + (m : ℝ)) ^ k ≤ (4 : ℝ) ^ k * (1 + (i : ℝ)) ^ (2 * k) * (1 + (j : ℝ)) ^ (2 * k) := by have h1 : (1 + (m : ℝ)) ^ k ≤ ((2 * (1 + (i : ℝ)) * (1 + (j : ℝ))) ^ 2) ^ k := by rw [hm_eq] exact pow_le_pow_left₀ (by positivity) (by exact_mod_cast one_add_pair_le_sq i j) _ have h2 : ((2 * (1 + (i : ℝ)) * (1 + (j : ℝ))) ^ 2) ^ k = (4 : ℝ) ^ k * (1 + (i : ℝ)) ^ (2 * k) * (1 + (j : ℝ)) ^ (2 * k) := by have h4 : (4 : ℝ) ^ k = (2 : ℝ) ^ (2 * k) := by rw [show (4 : ℝ) = 2 ^ 2 from by norm_num, ← pow_mul] rw [h4, ← pow_mul, mul_pow, mul_pow] linarith have h_a : |DyninMityaginSpace.coeff i e₁| * (1 + (i : ℝ)) ^ (2 * k) ≤ B₁ / (1 + (i : ℝ)) ^ 2 := by rw [le_div_iff₀ (pow_pos hi_pos 2)] calc |DyninMityaginSpace.coeff i e₁| * (1 + ↑i) ^ (2 * k) * (1 + ↑i) ^ 2 = |DyninMityaginSpace.coeff i e₁| * ((1 + ↑i) ^ (2 * k) * (1 + ↑i) ^ 2) := by ring _ = |DyninMityaginSpace.coeff i e₁| * (1 + ↑i) ^ (2 * k + 2) := by rw [← pow_add] _ ≤ B₁ := hs₁ e₁ i have h_b : |DyninMityaginSpace.coeff j e₂| * (1 + (j : ℝ)) ^ (2 * k) ≤ B₂ / (1 + (j : ℝ)) ^ 2 := by rw [le_div_iff₀ (pow_pos hj_pos 2)] calc |DyninMityaginSpace.coeff j e₂| * (1 + ↑j) ^ (2 * k) * (1 + ↑j) ^ 2 = |DyninMityaginSpace.coeff j e₂| * ((1 + ↑j) ^ (2 * k) * (1 + ↑j) ^ 2) := by ring _ = |DyninMityaginSpace.coeff j e₂| * (1 + ↑j) ^ (2 * k + 2) := by rw [← pow_add] _ ≤ B₂ := hs₂ e₂ j calc |DyninMityaginSpace.coeff i e₁| * |DyninMityaginSpace.coeff j e₂| * (1 + (m : ℝ)) ^ k ≤ |DyninMityaginSpace.coeff i e₁| * |DyninMityaginSpace.coeff j e₂| * ((4 : ℝ) ^ k * (1 + ↑i) ^ (2 * k) * (1 + ↑j) ^ (2 * k)) := mul_le_mul_of_nonneg_left h_weight (by positivity) _ = (|DyninMityaginSpace.coeff i e₁| * (1 + ↑i) ^ (2 * k)) * (|DyninMityaginSpace.coeff j e₂| * (1 + ↑j) ^ (2 * k)) * (4 : ℝ) ^ k := by ring _ ≤ (B₁ / (1 + ↑i) ^ 2) * (B₂ / (1 + ↑j) ^ 2) * (4 : ℝ) ^ k := by apply mul_le_mul_of_nonneg_right _ (by positivity) exact mul_le_mul h_a h_b (mul_nonneg (abs_nonneg _) (by positivity)) (by positivity) _ = B₁ * B₂ * (4 : ℝ) ^ k / ((1 + ↑i) ^ 2 * (1 + ↑j) ^ 2) := by field_simp _ = B₁ * B₂ * (4 : ℝ) ^ k * ((1 + (i : ℝ)) ^ 2 * (1 + (j : ℝ)) ^ 2)⁻¹ := by rw [div_eq_mul_inv] -- Sum the bound calc ∑' m, |(pure e₁ e₂).val m| * (1 + (m : ℝ)) ^ k ≤ ∑' m, B₁ * B₂ * (4 : ℝ) ^ k * ((1 + ((Nat.unpair m).1 : ℝ)) ^ 2 * (1 + ((Nat.unpair m).2 : ℝ)) ^ 2)⁻¹ := by exact ((pure e₁ e₂).rapid_decay k).tsum_le_tsum h_term_bound ((summable_unpair_inv_sq).mul_left _) _ = B₁ * B₂ * (4 : ℝ) ^ k * T := tsum_mul_left _ = C₁ * C₂ * (4 : ℝ) ^ k * T * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂ := by simp only [B₁, B₂]; ring /-- The pure tensor map as a bilinear map. -/ def pureLin : E₁ →ₗ[ℝ] E₂ →ₗ[ℝ] NuclearTensorProduct E₁ E₂ where toFun e₁ := { toFun := fun e₂ => pure e₁ e₂ map_add' := fun e₂ e₂' => by ext m; simp only [pure_val, add_val, map_add, mul_add] map_smul' := fun r e₂ => by simp only [RingHom.id_apply] ext m; simp only [pure_val, smul_val, map_smul, smul_eq_mul]; ring } map_add' e₁ e₁' := by apply LinearMap.ext; intro e₂; ext m simp only [pure_val, add_val, LinearMap.coe_mk, AddHom.coe_mk, LinearMap.add_apply, map_add, add_mul] map_smul' r e₁ := by apply LinearMap.ext; intro e₂; ext m simp only [pure_val, smul_val, LinearMap.coe_mk, AddHom.coe_mk, LinearMap.smul_apply, map_smul, smul_eq_mul, RingHom.id_apply, mul_assoc] /-- For fixed `e₁`, the map `e₂ ↦ pure e₁ e₂` is a continuous linear map. Continuity follows from the seminorm bound via `continuous_of_isBounded`. -/ def pureCLM_right (e₁ : E₁) : E₂ →L[ℝ] NuclearTensorProduct E₁ E₂ where toLinearMap := pureLin e₁ cont := by apply WithSeminorms.continuous_of_isBounded (DyninMityaginSpace.h_with (E := E₂)) RapidDecaySeq.rapidDecay_withSeminorms intro k obtain ⟨C, s₁, s₂, hbound⟩ := pure_seminorm_bound (E₁ := E₁) (E₂ := E₂) k refine ⟨s₂, ⟨C * (s₁.sup DyninMityaginSpace.p) e₁, mul_nonneg (NNReal.coe_nonneg C) (apply_nonneg _ _)⟩, fun e₂ => ?_⟩ simp only [] exact hbound e₁ e₂ /-- For fixed `e₂`, the map `e₁ ↦ pure e₁ e₂` is continuous. -/ theorem pure_continuous_left (e₂ : E₂) : Continuous (fun e₁ : E₁ => pure e₁ e₂) := by have : (fun e₁ : E₁ => pure e₁ e₂) = (pureLin (E₁ := E₁) (E₂ := E₂)).flip e₂ := by ext e₁ m; simp [pureLin, pure_val] rw [this] apply WithSeminorms.continuous_of_isBounded (DyninMityaginSpace.h_with (E := E₁)) RapidDecaySeq.rapidDecay_withSeminorms intro k obtain ⟨C, s₁, s₂, hbound⟩ := pure_seminorm_bound (E₁ := E₁) (E₂ := E₂) k refine ⟨s₁, ⟨C * (s₂.sup DyninMityaginSpace.p) e₂, mul_nonneg (NNReal.coe_nonneg C) (apply_nonneg _ _)⟩, fun e₁ => ?_⟩ simp only [] calc RapidDecaySeq.rapidDecaySeminorm k (pure e₁ e₂) ≤ ↑C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂ := hbound e₁ e₂ _ = ↑C * (s₂.sup DyninMityaginSpace.p) e₂ * (s₁.sup DyninMityaginSpace.p) e₁ := by ring /-- A finset sup of seminorms with `WithSeminorms` has its ball in nhds 0. -/ private theorem finsetSup_seminorm_ball_mem_nhds {F : Type*} [AddCommGroup F] [Module ℝ F] [TopologicalSpace F] [IsTopologicalAddGroup F] [ContinuousSMul ℝ F] {ι' : Type} {q : ι' → Seminorm ℝ F} (hq : WithSeminorms q) (t : Finset ι') {ε : ℝ} (hε : 0 < ε) : {x : F | (t.sup q) x < ε} ∈ nhds (0 : F) := by have hmem : ⋂ i ∈ t, {x : F | q i x < ε} ∈ nhds (0 : F) := by rw [t.iInter_mem_sets] intro i _ exact (hq.continuous_seminorm i).isOpen_preimage _ isOpen_Iio |>.mem_nhds (show (0 : F) ∈ {x | q i x < ε} by simp [map_zero, hε]) apply Filter.mem_of_superset hmem intro x hx simp only [Set.mem_iInter, Set.mem_setOf_eq] at hx ⊢ rcases Seminorm.zero_or_exists_apply_eq_finset_sup q t x with h | ⟨i, hi, heq⟩ · linarith · linarith [hx i hi] /-- The pure tensor map is jointly continuous on `E₁ × E₂`. -/ theorem pure_continuous : Continuous (fun p : E₁ × E₂ => pure p.1 p.2) := by -- Package as AddMonoidHom for continuous_of_continuousAt_zero₂ set f : E₁ →+ E₂ →+ NuclearTensorProduct E₁ E₂ := { toFun := fun e₁ => (pureLin e₁).toAddMonoidHom map_zero' := by ext e₂ m; simp [pureLin, pure_val]; rfl map_add' := fun e₁ e₁' => by ext e₂ m; simp [pureLin, pure_val, add_mul] } show Continuous (fun p : E₁ × E₂ => f p.1 p.2) apply continuous_of_continuousAt_zero₂ f · -- Continuity at (0, 0): use the seminorm bound have hf00 : f 0 0 = 0 := by ext m; simp rw [ContinuousAt, hf00] apply (RapidDecaySeq.rapidDecay_withSeminorms.tendsto_nhds _ 0).mpr intro k ε hε obtain ⟨C, s₁, s₂, hbound⟩ := pure_seminorm_bound (E₁ := E₁) (E₂ := E₂) k -- Pick nhds: {e₁ | s₁.sup p₁ e₁ < 1} and {e₂ | s₂.sup p₂ e₂ < ε/(C+1)} have h_mem₁ : {e₁ : E₁ | (s₁.sup DyninMityaginSpace.p) e₁ < 1} ∈ nhds (0 : E₁) := finsetSup_seminorm_ball_mem_nhds DyninMityaginSpace.h_with s₁ one_pos have h_mem₂ : {e₂ : E₂ | (s₂.sup DyninMityaginSpace.p) e₂ < ε / (↑C + 1)} ∈ nhds (0 : E₂) := finsetSup_seminorm_ball_mem_nhds DyninMityaginSpace.h_with s₂ (div_pos hε (by positivity)) rw [nhds_prod_eq] apply Filter.mem_of_superset (Filter.prod_mem_prod h_mem₁ h_mem₂) intro ⟨e₁, e₂⟩ ⟨he₁, he₂⟩ simp only [Set.mem_setOf_eq] at he₁ he₂ ⊢ have hpure : RapidDecaySeq.rapidDecaySeminorm k (pure e₁ e₂) < ε := by calc RapidDecaySeq.rapidDecaySeminorm k (pure e₁ e₂) ≤ ↑C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂ := hbound e₁ e₂ _ ≤ ↑C * 1 * (ε / (↑C + 1)) := by apply mul_le_mul (mul_le_mul_of_nonneg_left he₁.le (NNReal.coe_nonneg C)) he₂.le (apply_nonneg _ _) (mul_nonneg (NNReal.coe_nonneg C) (by linarith)) _ = ↑C * ε / (↑C + 1) := by ring _ < ε := by rw [div_lt_iff₀ (by positivity : (0 : ℝ) < ↑C + 1)] linarith [NNReal.coe_nonneg C] change RapidDecaySeq.rapidDecaySeminorm k ((show RapidDecaySeq from f e₁ e₂) - 0) < ε rw [sub_zero] change RapidDecaySeq.rapidDecaySeminorm k (show RapidDecaySeq from pure e₁ e₂) < ε exact hpure · -- Continuity of f x at 0 for each x intro e₁ exact (pureCLM_right e₁).continuous.continuousAt · -- Continuity of f · y at 0 for each y intro e₂ exact (pure_continuous_left e₂).continuousAt /-! ### Universal Property: Lift -/ section Lift variable {G : Type*} [NormedAddCommGroup G] [NormedSpace ℝ G] [CompleteSpace G] /-- Summability of the lifted series. Given a bilinear map `B : E₁ →ₗ E₂ →ₗ G` that is bounded by seminorms, the series `∑ₘ aₘ • B(ψ₁ᵢ, ψ₂ⱼ)` converges for any `a : NuclearTensorProduct E₁ E₂`, where `(i,j) = unpair(m)`. -/ private lemma lift_summable (B : E₁ →ₗ[ℝ] E₂ →ₗ[ℝ] G) {C : ℝ} {s₁ : Finset (@DyninMityaginSpace.ι E₁ _ _ _ _ _ _)} {s₂ : Finset (@DyninMityaginSpace.ι E₂ _ _ _ _ _ _)} (hC : 0 < C) (hB : ∀ e₁ e₂, ‖B e₁ e₂‖ ≤ C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂) (a : NuclearTensorProduct E₁ E₂) : Summable (fun m => a.val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2)) := by classical have hgrowth₁ : ∀ i ∈ s₁, ∃ C' > 0, ∃ t : ℕ, ∀ m, DyninMityaginSpace.p i (DyninMityaginSpace.basis m : E₁) ≤ C' * (1 + (m : ℝ)) ^ t := fun i _ => DyninMityaginSpace.basis_growth i have hgrowth₂ : ∀ i ∈ s₂, ∃ C' > 0, ∃ t : ℕ, ∀ m, DyninMityaginSpace.p i (DyninMityaginSpace.basis m : E₂) ≤ C' * (1 + (m : ℝ)) ^ t := fun i _ => DyninMityaginSpace.basis_growth i obtain ⟨D₁, hD₁, S₁, hbound₁⟩ := finset_sup_poly_bound DyninMityaginSpace.p s₁ DyninMityaginSpace.basis hgrowth₁ obtain ⟨D₂, hD₂, S₂, hbound₂⟩ := finset_sup_poly_bound DyninMityaginSpace.p s₂ DyninMityaginSpace.basis hgrowth₂ set K := C * D₁ * D₂ with hK_def apply Summable.of_norm_bounded (g := fun m => K * (|a.val m| * (1 + (m : ℝ)) ^ (S₁ + S₂))) · exact ((a.rapid_decay (S₁ + S₂)).mul_left K) · intro m set i := (Nat.unpair m).1 set j := (Nat.unpair m).2 rw [norm_smul, Real.norm_eq_abs] have hi_le : (1 + (i : ℝ)) ≤ (1 + (m : ℝ)) := by linarith [(Nat.cast_le (α := ℝ)).mpr (Nat.unpair_left_le m)] have hj_le : (1 + (j : ℝ)) ≤ (1 + (m : ℝ)) := by linarith [(Nat.cast_le (α := ℝ)).mpr (Nat.unpair_right_le m)] have h1i : (0 : ℝ) ≤ 1 + (i : ℝ) := by positivity have h1j : (0 : ℝ) ≤ 1 + (j : ℝ) := by positivity calc |a.val m| * ‖B (DyninMityaginSpace.basis i) (DyninMityaginSpace.basis j)‖ ≤ |a.val m| * (C * (s₁.sup DyninMityaginSpace.p) (DyninMityaginSpace.basis i) * (s₂.sup DyninMityaginSpace.p) (DyninMityaginSpace.basis j)) := mul_le_mul_of_nonneg_left (hB _ _) (abs_nonneg _) _ ≤ |a.val m| * (C * (D₁ * (1 + (i : ℝ)) ^ S₁) * (D₂ * (1 + (j : ℝ)) ^ S₂)) := by apply mul_le_mul_of_nonneg_left _ (abs_nonneg _) apply mul_le_mul (mul_le_mul_of_nonneg_left (hbound₁ i) (le_of_lt hC)) (hbound₂ j) (apply_nonneg _ _) (by positivity) _ ≤ |a.val m| * (C * (D₁ * (1 + (m : ℝ)) ^ S₁) * (D₂ * (1 + (m : ℝ)) ^ S₂)) := by apply mul_le_mul_of_nonneg_left _ (abs_nonneg _) apply mul_le_mul (mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left (pow_le_pow_left₀ h1i hi_le S₁) (le_of_lt hD₁)) (le_of_lt hC)) (mul_le_mul_of_nonneg_left (pow_le_pow_left₀ h1j hj_le S₂) (le_of_lt hD₂)) (by positivity) (by positivity) _ = K * (|a.val m| * (1 + (m : ℝ)) ^ (S₁ + S₂)) := by rw [hK_def, pow_add]; ring /-- Auxiliary: the norm bound for `lift` as a term-by-term inequality. Extracts the common calculation used in both `lift` continuity and `lift_summable`. -/ private lemma lift_norm_bound (B : E₁ →ₗ[ℝ] E₂ →ₗ[ℝ] G) {C : ℝ} {s₁ : Finset (@DyninMityaginSpace.ι E₁ _ _ _ _ _ _)} {s₂ : Finset (@DyninMityaginSpace.ι E₂ _ _ _ _ _ _)} (hC : 0 < C) (hB : ∀ e₁ e₂, ‖B e₁ e₂‖ ≤ C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂) : ∃ K > 0, ∃ N : ℕ, ∀ (a : NuclearTensorProduct E₁ E₂), ‖∑' m, a.val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2)‖ ≤ K * RapidDecaySeq.rapidDecaySeminorm N a := by classical have hgrowth₁ : ∀ i ∈ s₁, ∃ C' > 0, ∃ t : ℕ, ∀ m, DyninMityaginSpace.p i (DyninMityaginSpace.basis m : E₁) ≤ C' * (1 + (m : ℝ)) ^ t := fun i _ => DyninMityaginSpace.basis_growth i have hgrowth₂ : ∀ i ∈ s₂, ∃ C' > 0, ∃ t : ℕ, ∀ m, DyninMityaginSpace.p i (DyninMityaginSpace.basis m : E₂) ≤ C' * (1 + (m : ℝ)) ^ t := fun i _ => DyninMityaginSpace.basis_growth i obtain ⟨D₁, hD₁, S₁, hbnd₁⟩ := finset_sup_poly_bound DyninMityaginSpace.p s₁ DyninMityaginSpace.basis hgrowth₁ obtain ⟨D₂, hD₂, S₂, hbnd₂⟩ := finset_sup_poly_bound DyninMityaginSpace.p s₂ DyninMityaginSpace.basis hgrowth₂ set K := C * D₁ * D₂ set N := S₁ + S₂ refine ⟨K, by positivity, N, fun a => ?_⟩ have hsumm := lift_summable B hC hB a -- Pointwise norm bound have hpw : ∀ m, ‖a.val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2)‖ ≤ K * (|a.val m| * (1 + (m : ℝ)) ^ N) := by intro m set i := (Nat.unpair m).1 set j := (Nat.unpair m).2 rw [norm_smul, Real.norm_eq_abs] have hi_le : (1 + (i : ℝ)) ≤ (1 + (m : ℝ)) := add_le_add_right (Nat.cast_le.mpr (Nat.unpair_left_le m)) 1 have hj_le : (1 + (j : ℝ)) ≤ (1 + (m : ℝ)) := add_le_add_right (Nat.cast_le.mpr (Nat.unpair_right_le m)) 1 have h1i : (0 : ℝ) ≤ 1 + (i : ℝ) := by positivity have h1j : (0 : ℝ) ≤ 1 + (j : ℝ) := by positivity calc |a.val m| * ‖B (DyninMityaginSpace.basis i) (DyninMityaginSpace.basis j)‖ ≤ |a.val m| * (C * (D₁ * (1 + (m : ℝ)) ^ S₁) * (D₂ * (1 + (m : ℝ)) ^ S₂)) := by apply mul_le_mul_of_nonneg_left _ (abs_nonneg _) calc ‖B (DyninMityaginSpace.basis i) (DyninMityaginSpace.basis j)‖ ≤ C * (s₁.sup DyninMityaginSpace.p) (DyninMityaginSpace.basis i) * (s₂.sup DyninMityaginSpace.p) (DyninMityaginSpace.basis j) := hB _ _ _ ≤ C * (D₁ * (1 + (i : ℝ)) ^ S₁) * (D₂ * (1 + (j : ℝ)) ^ S₂) := by apply mul_le_mul (mul_le_mul_of_nonneg_left (hbnd₁ i) (le_of_lt hC)) (hbnd₂ j) (apply_nonneg _ _) (by positivity) _ ≤ C * (D₁ * (1 + (m : ℝ)) ^ S₁) * (D₂ * (1 + (m : ℝ)) ^ S₂) := by apply mul_le_mul (mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left (pow_le_pow_left₀ h1i hi_le S₁) (le_of_lt hD₁)) (le_of_lt hC)) (mul_le_mul_of_nonneg_left (pow_le_pow_left₀ h1j hj_le S₂) (le_of_lt hD₂)) (by positivity) (by positivity) _ = K * (|a.val m| * (1 + (m : ℝ)) ^ N) := by show |a.val m| * (C * (D₁ * (1 + ↑m) ^ S₁) * (D₂ * (1 + ↑m) ^ S₂)) = C * D₁ * D₂ * (|a.val m| * (1 + ↑m) ^ (S₁ + S₂)) rw [pow_add]; ring have hg_summ : Summable (fun m => K * (|a.val m| * (1 + (m : ℝ)) ^ N)) := (a.rapid_decay N).mul_left K have hnorm_summ : Summable (fun m => ‖a.val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2)‖) := Summable.of_nonneg_of_le (fun _ => norm_nonneg _) hpw hg_summ calc ‖∑' m, a.val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2)‖ ≤ ∑' m, ‖a.val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2)‖ := norm_tsum_le_tsum_norm hnorm_summ _ ≤ ∑' m, K * (|a.val m| * (1 + (m : ℝ)) ^ N) := hnorm_summ.tsum_le_tsum hpw hg_summ _ = K * ∑' m, |a.val m| * (1 + (m : ℝ)) ^ N := tsum_mul_left _ = K * RapidDecaySeq.rapidDecaySeminorm N a := by rfl /-- The underlying linear map for `lift`. -/ private def liftLM (B : E₁ →ₗ[ℝ] E₂ →ₗ[ℝ] G) {C : ℝ} {s₁ : Finset (@DyninMityaginSpace.ι E₁ _ _ _ _ _ _)} {s₂ : Finset (@DyninMityaginSpace.ι E₂ _ _ _ _ _ _)} (hC : 0 < C) (hB : ∀ e₁ e₂, ‖B e₁ e₂‖ ≤ C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂) : NuclearTensorProduct E₁ E₂ →ₗ[ℝ] G where toFun := fun a => ∑' m, a.val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2) map_add' := fun a b => by have ha := lift_summable B hC hB a have hb := lift_summable B hC hB b simp only [add_val] simp_rw [add_smul] exact ha.tsum_add hb map_smul' := fun r a => by have ha := lift_summable B hC hB a simp only [smul_val, RingHom.id_apply] simp_rw [mul_smul] exact ha.tsum_const_smul r /-- **Universal property of the nuclear tensor product.** Every continuous bilinear map `B : E₁ × E₂ → G` (into a complete normed space) factors through `pure` via a CLM `lift B : NuclearTensorProduct E₁ E₂ →L[ℝ] G`. The definition is `lift B a = ∑' m, aₘ • B(ψ₁ᵢ, ψ₂ⱼ)` where `(i,j) = unpair(m)`. Linearity follows from tsum linearity; continuity from a seminorm bound. -/ def lift (B : E₁ →ₗ[ℝ] E₂ →ₗ[ℝ] G) {C : ℝ} {s₁ : Finset (@DyninMityaginSpace.ι E₁ _ _ _ _ _ _)} {s₂ : Finset (@DyninMityaginSpace.ι E₂ _ _ _ _ _ _)} (hC : 0 < C) (hB : ∀ e₁ e₂, ‖B e₁ e₂‖ ≤ C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂) : NuclearTensorProduct E₁ E₂ →L[ℝ] G where toLinearMap := liftLM B hC hB cont := by obtain ⟨K, hK, N, hbound⟩ := lift_norm_bound B hC hB apply WithSeminorms.continuous_of_isBounded (RapidDecaySeq.rapidDecay_withSeminorms : WithSeminorms (RapidDecaySeq.rapidDecaySeminorm : ℕ → Seminorm ℝ (NuclearTensorProduct E₁ E₂))) (norm_withSeminorms ℝ G) intro _ refine ⟨{N}, ⟨K, le_of_lt hK⟩, fun a => ?_⟩ simp only [Finset.sup_singleton, liftLM] exact hbound a /-- The lift factors through pure: `lift B (pure e₁ e₂) = B e₁ e₂`. The proof uses the double Schauder expansion: `hasSum_basis` gives convergent expansions `e₁ = ∑ c₁_n • ψ₁_n` and `e₂ = ∑ c₂_j • ψ₂_j`, then applies `B` (continuous from the bound) and rearranges via Cantor pairing. -/ theorem lift_pure (B : E₁ →ₗ[ℝ] E₂ →ₗ[ℝ] G) {C : ℝ} {s₁ : Finset (@DyninMityaginSpace.ι E₁ _ _ _ _ _ _)} {s₂ : Finset (@DyninMityaginSpace.ι E₂ _ _ _ _ _ _)} (hC : 0 < C) (hB : ∀ e₁ e₂, ‖B e₁ e₂‖ ≤ C * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂) (e₁ : E₁) (e₂ : E₂) : lift B hC hB (pure e₁ e₂) = B e₁ e₂ := by -- Unfold lift to the tsum definition show ∑' m, (pure e₁ e₂).val m • B (DyninMityaginSpace.basis (Nat.unpair m).1) (DyninMityaginSpace.basis (Nat.unpair m).2) = B e₁ e₂ simp only [pure_val] -- Abbreviations for readability (used only in types, not in HasSum.map) let ψ₁ := DyninMityaginSpace.basis (E := E₁) let ψ₂ := DyninMityaginSpace.basis (E := E₂) let c₁ := DyninMityaginSpace.coeff (E := E₁) let c₂ := DyninMityaginSpace.coeff (E := E₂) -- Step 1: Continuity of B(ψ₁ n) : E₂ →ₗ G for each n have hBn_cont : ∀ n, Continuous (B (ψ₁ n)) := by intro n apply WithSeminorms.continuous_of_isBounded (DyninMityaginSpace.h_with (E := E₂)) (norm_withSeminorms ℝ G) intro _ refine ⟨s₂, ⟨C * (s₁.sup DyninMityaginSpace.p) (ψ₁ n), mul_nonneg (le_of_lt hC) (apply_nonneg _ _)⟩, fun x => ?_⟩ show ‖(B (ψ₁ n)) x‖ ≤ C * (s₁.sup DyninMityaginSpace.p) (ψ₁ n) * (s₂.sup DyninMityaginSpace.p) x exact hB (ψ₁ n) x -- Step 2: Continuity of B.flip e₂ : E₁ →ₗ G have hBflip_cont : Continuous (B.flip e₂) := by apply WithSeminorms.continuous_of_isBounded (DyninMityaginSpace.h_with (E := E₁)) (norm_withSeminorms ℝ G) intro _ refine ⟨s₁, ⟨C * (s₂.sup DyninMityaginSpace.p) e₂, mul_nonneg (le_of_lt hC) (apply_nonneg _ _)⟩, fun x => ?_⟩ show ‖(B.flip e₂) x‖ ≤ C * (s₂.sup DyninMityaginSpace.p) e₂ * (s₁.sup DyninMityaginSpace.p) x rw [LinearMap.flip_apply] calc ‖(B x) e₂‖ ≤ C * (s₁.sup DyninMityaginSpace.p) x * (s₂.sup DyninMityaginSpace.p) e₂ := hB x e₂ _ = C * (s₂.sup DyninMityaginSpace.p) e₂ * (s₁.sup DyninMityaginSpace.p) x := by ring -- Step 3: Inner HasSum: ∑ₖ c₂(k)(e₂) • B(ψ₁(n))(ψ₂(k)) → B(ψ₁(n))(e₂) have h_inner : ∀ n, HasSum (fun k => c₂ k e₂ • B (ψ₁ n) (ψ₂ k)) (B (ψ₁ n) e₂) := by intro n have h := (DyninMityaginSpace.hasSum_basis e₂).map (B (ψ₁ n)) (hBn_cont n) exact h.congr_fun (fun k => (map_smul (B (ψ₁ n)) (c₂ k e₂) (ψ₂ k)).symm) -- Step 4: Outer HasSum: ∑ₙ c₁(n)(e₁) • B(ψ₁(n))(e₂) → B(e₁)(e₂) have h_outer : HasSum (fun n => c₁ n e₁ • B (ψ₁ n) e₂) (B e₁ e₂) := by have h := (DyninMityaginSpace.hasSum_basis e₁).map (B.flip e₂) hBflip_cont exact h.congr_fun (fun n => by simp only [Function.comp, LinearMap.flip_apply] exact (map_smul (B.flip e₂) (c₁ n e₁) (ψ₁ n)).symm) -- Step 5: Summability of the ℕ-indexed sum (from lift_summable via pure_val) have h_summ_nat : Summable (fun m => (c₁ (Nat.unpair m).1 e₁ * c₂ (Nat.unpair m).2 e₂) • B (ψ₁ (Nat.unpair m).1) (ψ₂ (Nat.unpair m).2)) := by have := lift_summable B hC hB (pure e₁ e₂) simp only [pure_val] at this; exact this -- Step 6: Summability of ℕ × ℕ-indexed version (via Cantor pairing equivalence) have h_summ_prod : Summable (fun (p : ℕ × ℕ) => (c₁ p.1 e₁ * c₂ p.2 e₂) • B (ψ₁ p.1) (ψ₂ p.2)) := (Nat.pairEquiv.symm.summable_iff).mp h_summ_nat -- Step 7: Fiber summability (each inner sum converges) have h_fiber : ∀ n, Summable (fun k => (c₁ n e₁ * c₂ k e₂) • B (ψ₁ n) (ψ₂ k)) := by intro n have := (h_inner n).const_smul (c₁ n e₁) simp only [smul_smul] at this exact this.summable -- Step 8: Double Schauder expansion via calc chain symm calc B e₁ e₂ = ∑' n, c₁ n e₁ • B (ψ₁ n) e₂ := h_outer.tsum_eq.symm _ = ∑' n, c₁ n e₁ • ∑' k, c₂ k e₂ • B (ψ₁ n) (ψ₂ k) := by congr 1; ext n; congr 1; exact (h_inner n).tsum_eq.symm _ = ∑' n, ∑' k, c₁ n e₁ • (c₂ k e₂ • B (ψ₁ n) (ψ₂ k)) := by congr 1; ext n; exact ((h_inner n).summable.tsum_const_smul _).symm _ = ∑' n, ∑' k, (c₁ n e₁ * c₂ k e₂) • B (ψ₁ n) (ψ₂ k) := by simp_rw [mul_smul] _ = ∑' (p : ℕ × ℕ), (c₁ p.1 e₁ * c₂ p.2 e₂) • B (ψ₁ p.1) (ψ₂ p.2) := (h_summ_prod.tsum_prod' h_fiber).symm _ = ∑' m, (c₁ (Nat.unpair m).1 e₁ * c₂ (Nat.unpair m).2 e₂) • B (ψ₁ (Nat.unpair m).1) (ψ₂ (Nat.unpair m).2) := (Equiv.tsum_eq Nat.pairEquiv.symm _).symm end Lift /-! ### Bilinear evaluation: tensor product of functionals -/ section Eval /-- The bilinear multiplication form `(x, y) ↦ x * y` as a bilinear map ℝ →ₗ ℝ →ₗ ℝ. -/ private def mulBilin : ℝ →ₗ[ℝ] ℝ →ₗ[ℝ] ℝ where toFun x := { toFun := fun y => x * y map_add' := fun y₁ y₂ => mul_add x y₁ y₂ map_smul' := fun r y => by simp [mul_comm r, mul_assoc] } map_add' x₁ x₂ := by ext; simp [add_mul] map_smul' r x := by ext; simp [mul_assoc] /-- Compose the multiplication bilinear form with CLMs on each factor. -/ private def compBilin (φ₁ : E₁ →L[ℝ] ℝ) (φ₂ : E₂ →L[ℝ] ℝ) : E₁ →ₗ[ℝ] E₂ →ₗ[ℝ] ℝ := (mulBilin.comp φ₁.toLinearMap).compl₂ φ₂.toLinearMap @[simp] private theorem compBilin_apply {E₁ : Type*} [AddCommGroup E₁] [Module ℝ E₁] [TopologicalSpace E₁] {E₂ : Type*} [AddCommGroup E₂] [Module ℝ E₂] [TopologicalSpace E₂] (φ₁ : E₁ →L[ℝ] ℝ) (φ₂ : E₂ →L[ℝ] ℝ) (e₁ : E₁) (e₂ : E₂) : compBilin φ₁ φ₂ e₁ e₂ = φ₁ e₁ * φ₂ e₂ := rfl /-- **Tensor product of continuous linear functionals.** Given `φ₁ ∈ E₁'` and `φ₂ ∈ E₂'`, the tensor product functional `φ₁ ⊗ φ₂ : E₁ ⊗̂ E₂ → ℝ` is defined via the universal property `lift` applied to the bilinear form `(e₁, e₂) ↦ φ₁(e₁) · φ₂(e₂)`. On pure tensors: `evalCLM φ₁ φ₂ (pure e₁ e₂) = φ₁ e₁ * φ₂ e₂`. The bilinear bound `‖φ₁(e₁) · φ₂(e₂)‖ ≤ C · p₁(e₁) · p₂(e₂)` follows from `Seminorm.bound_of_continuous` applied to each functional. -/ def evalCLM (φ₁ : E₁ →L[ℝ] ℝ) (φ₂ : E₂ →L[ℝ] ℝ) : NuclearTensorProduct E₁ E₂ →L[ℝ] ℝ := by classical -- Extract seminorm bounds for each functional via Classical.choice have hq₁ : Continuous ((normSeminorm ℝ ℝ).comp φ₁.toLinearMap) := continuous_norm.comp φ₁.continuous have hq₂ : Continuous ((normSeminorm ℝ ℝ).comp φ₂.toLinearMap) := continuous_norm.comp φ₂.continuous choose s₁ C₁ hC₁ne hle₁ using Seminorm.bound_of_continuous (DyninMityaginSpace.h_with (E := E₁)) ((normSeminorm ℝ ℝ).comp φ₁.toLinearMap) hq₁ choose s₂ C₂ hC₂ne hle₂ using Seminorm.bound_of_continuous (DyninMityaginSpace.h_with (E := E₂)) ((normSeminorm ℝ ℝ).comp φ₂.toLinearMap) hq₂ -- The bilinear bound: ‖φ₁ e₁ * φ₂ e₂‖ ≤ (C₁ * C₂) * (s₁.sup p) e₁ * (s₂.sup p) e₂ have hC_pos : (0 : ℝ) < C₁ * C₂ := by positivity exact lift (compBilin φ₁ φ₂) hC_pos (fun e₁ e₂ => by simp only [compBilin_apply] rw [Real.norm_eq_abs, abs_mul] have h₁ : |φ₁ e₁| ≤ C₁ * (s₁.sup DyninMityaginSpace.p) e₁ := by have := hle₁ e₁; simp [Seminorm.comp_apply, NNReal.smul_def] at this; exact this have h₂ : |φ₂ e₂| ≤ C₂ * (s₂.sup DyninMityaginSpace.p) e₂ := by have := hle₂ e₂; simp [Seminorm.comp_apply, NNReal.smul_def] at this; exact this calc |φ₁ e₁| * |φ₂ e₂| ≤ (↑C₁ * (s₁.sup DyninMityaginSpace.p) e₁) * (↑C₂ * (s₂.sup DyninMityaginSpace.p) e₂) := mul_le_mul h₁ h₂ (abs_nonneg _) (by positivity) _ = ↑C₁ * ↑C₂ * (s₁.sup DyninMityaginSpace.p) e₁ * (s₂.sup DyninMityaginSpace.p) e₂ := by ring) /-- `evalCLM` on pure tensors gives the product of evaluations. -/ theorem evalCLM_pure {E₁ : Type*} [AddCommGroup E₁] [Module ℝ E₁] [TopologicalSpace E₁] [IsTopologicalAddGroup E₁] [ContinuousSMul ℝ E₁] [DyninMityaginSpace E₁] {E₂ : Type*} [AddCommGroup E₂] [Module ℝ E₂] [TopologicalSpace E₂] [IsTopologicalAddGroup E₂] [ContinuousSMul ℝ E₂] [DyninMityaginSpace E₂] (φ₁ : E₁ →L[ℝ] ℝ) (φ₂ : E₂ →L[ℝ] ℝ) (e₁ : E₁) (e₂ : E₂) : evalCLM φ₁ φ₂ (pure e₁ e₂) = φ₁ e₁ * φ₂ e₂ := by unfold evalCLM rw [lift_pure] simp [compBilin_apply] end Eval /-- Under biorthogonality, basis vectors equal pure tensors of basis elements. `basisVec m = pure (basis a) (basis b)` where `(a,b) = unpair(m)`. -/ theorem basisVec_eq_pure {E₁ : Type*} [AddCommGroup E₁] [Module ℝ E₁] [TopologicalSpace E₁] [IsTopologicalAddGroup E₁] [ContinuousSMul ℝ E₁] [DyninMityaginSpace E₁] {E₂ : Type*} [AddCommGroup E₂] [Module ℝ E₂] [TopologicalSpace E₂] [IsTopologicalAddGroup E₂] [ContinuousSMul ℝ E₂] [DyninMityaginSpace E₂] (hbasis₁ : ∀ n m, DyninMityaginSpace.coeff (E := E₁) n (DyninMityaginSpace.basis m) = if n = m then 1 else 0) (hbasis₂ : ∀ n m, DyninMityaginSpace.coeff (E := E₂) n (DyninMityaginSpace.basis m) = if n = m then 1 else 0) (m : ℕ) : (RapidDecaySeq.basisVec m : NuclearTensorProduct E₁ E₂) = NuclearTensorProduct.pure (DyninMityaginSpace.basis (E := E₁) (Nat.unpair m).1) (DyninMityaginSpace.basis (E := E₂) (Nat.unpair m).2) := by ext n simp only [RapidDecaySeq.basisVec, pure_val, hbasis₁, hbasis₂] by_cases h : n = m · subst h; simp · simp [h] by_cases h₁ : (Nat.unpair n).1 = (Nat.unpair m).1 · simp [h₁] intro h₂; apply h rw [← Nat.pair_unpair n, ← Nat.pair_unpair m, h₁, h₂] · simp [h₁] end NuclearTensorProduct end GaussianField