Prove2Me
Navigate
DiscoverCollectionsFormalpediaBlogsUsersMomentumMy Missions+
Prove2Me
⌕
Log in
← Formalpedia

The Lean 4 theorem `memLp_mulProd` in the `?` chapter of the timepiece formalization

Definition
ChapterNsScalarVectorCurry

by leonardopedro · Oct 3, 2026 · Mathlib 0df444a (Lean v4.33.1)

definitionsformalizationtimepiece

Formal definitions for the timepiece Lean 4 formalization (source chapter BookProof/ChapterNsScalarVectorCurry.lean): generated def bundle for ChapterNsScalarVectorCurry. See BookProof/ChapterNsScalarVectorCurry.lean for full context.

Definition code
import Mathlib


/-!
# The scalar–vector identification `L²(V; L²(W)) ≅ L²(V × W)`

This module closes the residual of item 1 of the Navier–Stokes plan items of
`CONSOLIDATED_PLAN.md` — *the spatial Fourier unitary and the diagonal derivative*.  The partial
(spatial-only) transform of `BookProof.ChapterNsPartialFourier` is built on the **fibred** model
of the one-particle space, the vector-valued `L²(V; L²(W))`; the plan's honest boundary was that
the measure-theoretic identification of that model with the **scalar** `L²(V × W)` was not
formalized.  Mathlib has no currying statement for `Lp`, so it is built here.

For σ-finite measures `μ` on `V` and `ν` on `W` the module constructs

* `curryLI : Lp (Lp ℂ 2 ν) 2 μ ≃ₗᵢ[ℂ] Lp ℂ 2 (μ.prod ν)`,

the unitary identification of the fibred `L²` with the scalar `L²` of the product measure, and
pins it down by its values on the generators:

* `curryLI_fibMk` — `curryLI (fibMk a c) = prodMk a c`, where `fibMk a c` is the fibred element
  `x ↦ a x • c` and `prodMk a c` the scalar function `(x, y) ↦ a x * c y`;
* `curryLI_indicator_prod` — on the tensor generators of the two sides,
  `1_s ⊗ 1_t ↦ 1_{s ×ˢ t}`;
* `curryLI_setIntegral_rect` — **currying is slicing**, in the form that needs no measurable
  choice of slices: the integral of the scalar picture over a measurable rectangle `s ×ˢ t` is the
  integral over `s` of the fibre integrals over `t`;
* `isSliceOf_curryLI` — **currying is slicing, pointwise**: almost everywhere in the spatial
  variable, the fibre `f x` of a fibred element *is* the slice `y ↦ (curryLI f) (x, y)` of its
  scalar picture (§7).  Its ingredients are of independent use: `eLpNorm_two_sq` and
  `lintegral_eLpNorm_slice_sq`, the Bochner–Fubini identity for the squared `L²(ν)` seminorms of
  the slices.

The route is the one specified by the plan.  `prodMk` and `fibMk` are bilinear, so they lift to
linear maps `prodTensor` and `fibTensor` out of the algebraic tensor product
`L²(μ) ⊗[ℂ] L²(ν)`; the two lifts have the *same* inner products on generators
(`inner_prodMk`, `inner_fibMk`, both computed by Fubini resp. by the pointwise inner product of
the fibred space), hence the same norms on the whole tensor product
(`norm_prodTensor_eq_norm_fibTensor`).  Both have dense range — on the fibred side because the
`Lp`-simple functions are dense and each of them is a finite sum of generators
(`denseRange_fibTensor`), on the scalar side by the orthogonality argument
`ae_eq_zero_of_forall_setIntegral_rect_eq_zero`: an `L²` function of the product measure whose
integral over every finite-measure measurable rectangle vanishes is zero a.e. (a π–λ induction
over the rectangles, which is the only genuinely new analysis here).  `LinearEquiv.extendOfIsometry`
then assembles the two dense isometric pictures into `curryLI`.

The module is stated for arbitrary σ-finite measures; nothing about `ℝ^d` or Lebesgue measure is
used, so it is Mathlib-level material.
-/

open MeasureTheory Filter Set
open scoped ENNReal ComplexConjugate

namespace BookProof.NsScalarVectorCurry

noncomputable section

variable {V W : Type*} [MeasurableSpace V] [MeasurableSpace W]
  {μ : Measure V} {ν : Measure W}

/-! ## 1.  The generators on the two sides -/

/-- The product `(x, y) ↦ a x * c y` of two square-integrable functions is square integrable for
the product measure. -/
theorem memLp_mulProd (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    MemLp (fun z : V × W => (a : V → ℂ) z.1 * (c : W → ℂ) z.2) 2 (μ.prod ν) := by
  have ha : AEStronglyMeasurable (fun z : V × W => (a : V → ℂ) z.1) (μ.prod ν) :=
    (Lp.aestronglyMeasurable a).comp_quasiMeasurePreserving Measure.quasiMeasurePreserving_fst
  have hc : AEStronglyMeasurable (fun z : V × W => (c : W → ℂ) z.2) (μ.prod ν) :=
    (Lp.aestronglyMeasurable c).comp_quasiMeasurePreserving Measure.quasiMeasurePreserving_snd
  refine (memLp_two_iff_integrable_sq_norm (ha.mul hc)).2 ?_
  have h1 : Integrable (fun x => ‖(a : V → ℂ) x‖ ^ 2) μ :=
    (memLp_two_iff_integrable_sq_norm (Lp.aestronglyMeasurable a)).1 (Lp.memLp a)
  have h2 : Integrable (fun y => ‖(c : W → ℂ) y‖ ^ 2) ν :=
    (memLp_two_iff_integrable_sq_norm (Lp.aestronglyMeasurable c)).1 (Lp.memLp c)
  simpa [norm_mul, mul_pow, smul_eq_mul] using h1.smul_prod h2

/-- The fibre-valued function `x ↦ a x • c` is square integrable. -/
theorem memLp_smulConst (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    MemLp (fun x : V => (a : V → ℂ) x • c) 2 μ := by
  refine (memLp_two_iff_integrable_sq_norm ((Lp.aestronglyMeasurable a).smul_const c)).2 ?_
  have h1 : Integrable (fun x => ‖(a : V → ℂ) x‖ ^ 2) μ :=
    (memLp_two_iff_integrable_sq_norm (Lp.aestronglyMeasurable a)).1 (Lp.memLp a)
  have key : (fun x => ‖(a : V → ℂ) x • c‖ ^ 2)
      = ‖c‖ ^ 2 • fun x => ‖(a : V → ℂ) x‖ ^ 2 := by
    funext x
    rw [norm_smul, mul_pow]
    simp [mul_comm, smul_eq_mul]
  rw [key]
  exact h1.smul (‖c‖ ^ 2)

/-- The scalar generator: the class of `(x, y) ↦ a x * c y` in `L²(μ.prod ν)`. -/
def prodMk (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) : Lp ℂ 2 (μ.prod ν) := (memLp_mulProd a c).toLp _

/-- The fibred generator: the class of `x ↦ a x • c` in `L²(μ; L²(ν))`. -/
def fibMk (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) : Lp (Lp ℂ 2 ν) 2 μ := (memLp_smulConst a c).toLp _

theorem coeFn_prodMk (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    (prodMk a c : V × W → ℂ) =ᵐ[μ.prod ν] fun z => (a : V → ℂ) z.1 * (c : W → ℂ) z.2 :=
  (memLp_mulProd a c).coeFn_toLp

theorem coeFn_fibMk (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    (fibMk a c : V → Lp ℂ 2 ν) =ᵐ[μ] fun x => (a : V → ℂ) x • c :=
  (memLp_smulConst a c).coeFn_toLp

/-! ### Bilinearity -/

theorem prodMk_add_left (a a' : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    prodMk (a + a') c = prodMk a c + prodMk a' c := by
  have hfst : ((fun x => ((a + a' : Lp ℂ 2 μ) : V → ℂ) x) ∘ Prod.fst)
      =ᵐ[μ.prod ν] ((fun x => (a : V → ℂ) x + (a' : V → ℂ) x) ∘ Prod.fst) :=
    Measure.quasiMeasurePreserving_fst.ae_eq_comp (Lp.coeFn_add a a')
  refine Lp.ext ?_
  filter_upwards [coeFn_prodMk (a + a') c, Lp.coeFn_add (prodMk a c) (prodMk a' c),
    coeFn_prodMk a c, coeFn_prodMk a' c, hfst] with z h1 h2 h3 h4 h5
  simp only [Function.comp_apply] at h5
  rw [h1, h2, Pi.add_apply, h3, h4, h5]
  ring

theorem prodMk_smul_left (r : ℂ) (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    prodMk (r • a) c = r • prodMk a c := by
  have hfst : ((fun x => ((r • a : Lp ℂ 2 μ) : V → ℂ) x) ∘ Prod.fst)
      =ᵐ[μ.prod ν] ((fun x => r • (a : V → ℂ) x) ∘ Prod.fst) :=
    Measure.quasiMeasurePreserving_fst.ae_eq_comp (Lp.coeFn_smul r a)
  refine Lp.ext ?_
  filter_upwards [coeFn_prodMk (r • a) c, Lp.coeFn_smul r (prodMk a c),
    coeFn_prodMk a c, hfst] with z h1 h2 h3 h5
  simp only [Function.comp_apply] at h5
  rw [h1, h2, Pi.smul_apply, h3, h5]
  simp only [smul_eq_mul]
  ring

theorem prodMk_add_right (a : Lp ℂ 2 μ) (c c' : Lp ℂ 2 ν) :
    prodMk a (c + c') = prodMk a c + prodMk a c' := by
  have hsnd : ((fun y => ((c + c' : Lp ℂ 2 ν) : W → ℂ) y) ∘ Prod.snd)
      =ᵐ[μ.prod ν] ((fun y => (c : W → ℂ) y + (c' : W → ℂ) y) ∘ Prod.snd) :=
    Measure.quasiMeasurePreserving_snd.ae_eq_comp (Lp.coeFn_add c c')
  refine Lp.ext ?_
  filter_upwards [coeFn_prodMk a (c + c'), Lp.coeFn_add (prodMk a c) (prodMk a c'),
    coeFn_prodMk a c, coeFn_prodMk a c', hsnd] with z h1 h2 h3 h4 h5
  simp only [Function.comp_apply] at h5
  rw [h1, h2, Pi.add_apply, h3, h4, h5]
  ring

theorem prodMk_smul_right (r : ℂ) (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    prodMk a (r • c) = r • prodMk a c := by
  have hsnd : ((fun y => ((r • c : Lp ℂ 2 ν) : W → ℂ) y) ∘ Prod.snd)
      =ᵐ[μ.prod ν] ((fun y => r • (c : W → ℂ) y) ∘ Prod.snd) :=
    Measure.quasiMeasurePreserving_snd.ae_eq_comp (Lp.coeFn_smul r c)
  refine Lp.ext ?_
  filter_upwards [coeFn_prodMk a (r • c), Lp.coeFn_smul r (prodMk a c),
    coeFn_prodMk a c, hsnd] with z h1 h2 h3 h5
  simp only [Function.comp_apply] at h5
  rw [h1, h2, Pi.smul_apply, h3, h5]
  simp only [smul_eq_mul]
  ring

theorem fibMk_add_left (a a' : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    fibMk (a + a') c = fibMk a c + fibMk a' c := by
  refine Lp.ext ?_
  filter_upwards [coeFn_fibMk (a + a') c, Lp.coeFn_add (fibMk a c) (fibMk a' c),
    coeFn_fibMk a c, coeFn_fibMk a' c, Lp.coeFn_add a a'] with x h1 h2 h3 h4 h5
  rw [h1, h2, Pi.add_apply, h3, h4, h5]
  simp [add_smul]

theorem fibMk_smul_left (r : ℂ) (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    fibMk (r • a) c = r • fibMk a c := by
  refine Lp.ext ?_
  filter_upwards [coeFn_fibMk (r • a) c, Lp.coeFn_smul r (fibMk a c),
    coeFn_fibMk a c, Lp.coeFn_smul r a] with x h1 h2 h3 h4
  rw [h1, h2, Pi.smul_apply, h3, h4]
  simp [smul_smul]

theorem fibMk_add_right (a : Lp ℂ 2 μ) (c c' : Lp ℂ 2 ν) :
    fibMk a (c + c') = fibMk a c + fibMk a c' := by
  refine Lp.ext ?_
  filter_upwards [coeFn_fibMk a (c + c'), Lp.coeFn_add (fibMk a c) (fibMk a c'),
    coeFn_fibMk a c, coeFn_fibMk a c'] with x h1 h2 h3 h4
  rw [h1, h2, Pi.add_apply, h3, h4, smul_add]

theorem fibMk_smul_right (r : ℂ) (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    fibMk a (r • c) = r • fibMk a c := by
  refine Lp.ext ?_
  filter_upwards [coeFn_fibMk a (r • c), Lp.coeFn_smul r (fibMk a c),
    coeFn_fibMk a c] with x h1 h2 h3
  rw [h1, h2, Pi.smul_apply, h3, smul_comm]

/-! ### The inner products of the generators agree -/

theorem inner_eq_integral (a b : Lp ℂ 2 μ) :
    inner ℂ a b = ∫ x, (b : V → ℂ) x * conj ((a : V → ℂ) x) ∂μ := by
  rw [L2.inner_def]
  simp [RCLike.inner_apply]

variable [SigmaFinite μ] [SigmaFinite ν]

/-- Fubini: the inner product of two scalar generators factorizes. -/
theorem inner_prodMk (a b : Lp ℂ 2 μ) (c d : Lp ℂ 2 ν) :
    inner ℂ (prodMk a c) (prodMk b d) = inner ℂ a b * inner ℂ c d := by
  rw [L2.inner_def]
  have hcongr : ∫ z : V × W, inner ℂ ((prodMk a c : V × W → ℂ) z) ((prodMk b d : V × W → ℂ) z)
        ∂(μ.prod ν)
      = ∫ z : V × W, ((b : V → ℂ) z.1 * conj ((a : V → ℂ) z.1)) *
          ((d : W → ℂ) z.2 * conj ((c : W → ℂ) z.2)) ∂(μ.prod ν) := by
    refine integral_congr_ae ?_
    filter_upwards [coeFn_prodMk a c, coeFn_prodMk b d] with z h1 h2
    rw [h1, h2, RCLike.inner_apply]
    simp only [map_mul]
    ring
  rw [hcongr, integral_prod_mul (fun x : V => (b : V → ℂ) x * conj ((a : V → ℂ) x))
    (fun y : W => (d : W → ℂ) y * conj ((c : W → ℂ) y)), inner_eq_integral, inner_eq_integral]

omit [SigmaFinite μ] [SigmaFinite ν] in
/-- The inner product of two fibred generators factorizes in the same way. -/
theorem inner_fibMk (a b : Lp ℂ 2 μ) (c d : Lp ℂ 2 ν) :
    inner ℂ (fibMk a c) (fibMk b d) = inner ℂ a b * inner ℂ c d := by
  rw [L2.inner_def]
  have hcongr : ∫ x : V, inner ℂ ((fibMk a c : V → Lp ℂ 2 ν) x) ((fibMk b d : V → Lp ℂ 2 ν) x) ∂μ
      = ∫ x : V, ((b : V → ℂ) x * conj ((a : V → ℂ) x)) * inner ℂ c d ∂μ := by
    refine integral_congr_ae ?_
    filter_upwards [coeFn_fibMk a c, coeFn_fibMk b d] with x h1 h2
    rw [h1, h2, inner_smul_left, inner_smul_right]
    ring
  rw [hcongr, integral_mul_const, inner_eq_integral a b]

/-! ## 2.  The two lifts to the algebraic tensor product -/

/-- The scalar generator as a bilinear map. -/
def prodBil : Lp ℂ 2 μ →ₗ[ℂ] Lp ℂ 2 ν →ₗ[ℂ] Lp ℂ 2 (μ.prod ν) :=
  LinearMap.mk₂ ℂ prodMk prodMk_add_left prodMk_smul_left prodMk_add_right prodMk_smul_right

/-- The fibred generator as a bilinear map. -/
def fibBil : Lp ℂ 2 μ →ₗ[ℂ] Lp ℂ 2 ν →ₗ[ℂ] Lp (Lp ℂ 2 ν) 2 μ :=
  LinearMap.mk₂ ℂ fibMk fibMk_add_left fibMk_smul_left fibMk_add_right fibMk_smul_right

/-- The scalar side, as a linear map out of the algebraic tensor product. -/
def prodTensor : TensorProduct ℂ (Lp ℂ 2 μ) (Lp ℂ 2 ν) →ₗ[ℂ] Lp ℂ 2 (μ.prod ν) :=
  TensorProduct.lift prodBil

/-- The fibred side, as a linear map out of the algebraic tensor product. -/
def fibTensor : TensorProduct ℂ (Lp ℂ 2 μ) (Lp ℂ 2 ν) →ₗ[ℂ] Lp (Lp ℂ 2 ν) 2 μ :=
  TensorProduct.lift fibBil

omit [SigmaFinite μ] [SigmaFinite ν] in
@[simp] theorem prodTensor_tmul (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    prodTensor (a ⊗ₜ[ℂ] c) = prodMk a c := rfl

omit [SigmaFinite μ] [SigmaFinite ν] in
@[simp] theorem fibTensor_tmul (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    fibTensor (a ⊗ₜ[ℂ] c) = fibMk a c := rfl

/-- The two lifts have the same inner products. -/
theorem inner_prodTensor_eq_inner_fibTensor
    (s t : TensorProduct ℂ (Lp ℂ 2 μ) (Lp ℂ 2 ν)) :
    inner ℂ (prodTensor s) (prodTensor t) = inner ℂ (fibTensor s) (fibTensor t) := by
  induction s using TensorProduct.induction_on with
  | zero => simp
  | tmul a c =>
      induction t using TensorProduct.induction_on with
      | zero => simp
      | tmul b d => simp [inner_prodMk, inner_fibMk]
      | add t₁ t₂ h₁ h₂ => simp only [map_add, inner_add_right, h₁, h₂]
  | add s₁ s₂ h₁ h₂ => simp only [map_add, inner_add_left, h₁, h₂]

/-- Hence the same norms: this is the isometry that gets extended. -/
theorem norm_prodTensor_eq_norm_fibTensor (s : TensorProduct ℂ (Lp ℂ 2 μ) (Lp ℂ 2 ν)) :
    ‖prodTensor s‖ = ‖fibTensor s‖ := by
  have h := inner_prodTensor_eq_inner_fibTensor s s
  rw [inner_self_eq_norm_sq_to_K, inner_self_eq_norm_sq_to_K] at h
  have h' : (‖prodTensor s‖ : ℝ) ^ 2 = (‖fibTensor s‖ : ℝ) ^ 2 := by
    exact_mod_cast h
  nlinarith [norm_nonneg (prodTensor s), norm_nonneg (fibTensor s)]

/-! ## 3.  Density of the fibred side -/

omit [SigmaFinite μ] [SigmaFinite ν] in
/-- A fibred indicator is a generator. -/
theorem fibMk_indicatorConstLp {s : Set V} (hs : MeasurableSet s) (hμs : μ s ≠ ∞)
    (c : Lp ℂ 2 ν) :
    fibMk (indicatorConstLp 2 hs hμs (1 : ℂ)) c = indicatorConstLp 2 hs hμs c := by
  refine Lp.ext ?_
  filter_upwards [coeFn_fibMk (indicatorConstLp 2 hs hμs (1 : ℂ)) c,
    indicatorConstLp_coeFn (p := (2 : ℝ≥0∞)) (hs := hs) (hμs := hμs) (c := (1 : ℂ)),
    indicatorConstLp_coeFn (p := (2 : ℝ≥0∞)) (hs := hs) (hμs := hμs) (c := c)] with x h1 h2 h3
  rw [h1, h2, h3]
  by_cases hx : x ∈ s <;> simp [hx]

omit [SigmaFinite μ] [SigmaFinite ν] in
/-- Every `Lp`-simple function with values in the fibre is a finite sum of fibred generators. -/
theorem simpleFunc_mem_range_fibTensor (f : Lp.simpleFunc (Lp ℂ 2 ν) 2 μ) :
    (f : Lp (Lp ℂ 2 ν) 2 μ) ∈ LinearMap.range (fibTensor (μ := μ) (ν := ν)) := by
  induction f using Lp.simpleFunc.induction (p := (2 : ℝ≥0∞)) (by simp) (by simp) with
  | @indicatorConst c s hs hμs =>
      refine ⟨(indicatorConstLp 2 hs hμs.ne (1 : ℂ)) ⊗ₜ[ℂ] c, ?_⟩
      rw [fibTensor_tmul, fibMk_indicatorConstLp]
      exact (Lp.simpleFunc.coe_indicatorConst hs hμs.ne c).symm
  | @add f g hf hg _ hfr hgr =>
      obtain ⟨u, hu⟩ := hfr
      obtain ⟨v, hv⟩ := hgr
      exact ⟨u + v, by rw [map_add, hu, hv]; rfl⟩

omit [SigmaFinite μ] [SigmaFinite ν] in
theorem denseRange_fibTensor :
    DenseRange (fibTensor (μ := μ) (ν := ν)) := by
  have hsub : (Lp.simpleFunc (Lp ℂ 2 ν) 2 μ : Set (Lp (Lp ℂ 2 ν) 2 μ)) ⊆
      Set.range (fibTensor (μ := μ) (ν := ν)) := by
    rintro f hf
    exact simpleFunc_mem_range_fibTensor (⟨f, hf⟩ : Lp.simpleFunc (Lp ℂ 2 ν) 2 μ)
  exact Dense.mono hsub (Lp.simpleFunc.dense (E := Lp ℂ 2 ν) (μ := μ) (p := 2) (by simp))

omit [SigmaFinite μ] [SigmaFinite ν] in
theorem prodMk_indicatorConstLp {s : Set V} {t : Set W} (hs : MeasurableSet s)
    (ht : MeasurableSet t) (hμs : μ s ≠ ∞) (hνt : ν t ≠ ∞)
    (hst : (μ.prod ν) (s ×ˢ t) ≠ ∞) :
    prodMk (indicatorConstLp 2 hs hμs (1 : ℂ)) (indicatorConstLp 2 ht hνt (1 : ℂ))
      = indicatorConstLp 2 (hs.prod ht) hst (1 : ℂ) := by
  refine Lp.ext ?_
  have h2 : ((fun x => (indicatorConstLp 2 hs hμs (1 : ℂ) : V → ℂ) x) ∘ Prod.fst)
      =ᵐ[μ.prod ν] ((s.indicator fun _ => (1 : ℂ)) ∘ Prod.fst) :=
    Measure.quasiMeasurePreserving_fst.ae_eq_comp indicatorConstLp_coeFn
  have h3 : ((fun y => (indicatorConstLp 2 ht hνt (1 : ℂ) : W → ℂ) y) ∘ Prod.snd)
      =ᵐ[μ.prod ν] ((t.indicator fun _ => (1 : ℂ)) ∘ Prod.snd) :=
    Measure.quasiMeasurePreserving_snd.ae_eq_comp indicatorConstLp_coeFn
  filter_upwards [coeFn_prodMk (indicatorConstLp 2 hs hμs (1 : ℂ))
      (indicatorConstLp 2 ht hνt (1 : ℂ)),
    indicatorConstLp_coeFn (p := (2 : ℝ≥0∞)) (hs := hs.prod ht) (hμs := hst) (c := (1 : ℂ)),
    h2, h3] with z e1 e4 e2 e3
  simp only [Function.comp_apply] at e2 e3
  rw [e1, e4, e2, e3]
  by_cases hz1 : z.1 ∈ s <;> by_cases hz2 : z.2 ∈ t <;>
    simp [Set.indicator_of_mem, Set.indicator_of_notMem, hz1, hz2, Set.mem_prod]

/-! ## 4.  Density of the scalar side: the rectangles are total -/

theorem integrableOn_of_measure_lt_top {X : Type*} [MeasurableSpace X] {ρ : Measure X}
    (g : Lp ℂ 2 ρ) {A : Set X} (hA : ρ A < ∞) : IntegrableOn (g : X → ℂ) A ρ := by
  haveI : IsFiniteMeasure (ρ.restrict A) := ⟨by rwa [Measure.restrict_apply_univ]⟩
  exact ((Lp.memLp g).restrict A).integrable (by norm_num)

/-- **Totality of the rectangles.**  An `L²` function of a product of σ-finite measures whose
integral over every finite-measure measurable rectangle vanishes is zero almost everywhere. -/
theorem ae_eq_zero_of_forall_setIntegral_rect_eq_zero (g : Lp ℂ 2 (μ.prod ν))
    (h : ∀ s : Set V, ∀ t : Set W, MeasurableSet s → MeasurableSet t → μ s < ∞ → ν t < ∞ →
      ∫ z in s ×ˢ t, (g : V × W → ℂ) z ∂(μ.prod ν) = 0) :
    (g : V × W → ℂ) =ᵐ[μ.prod ν] 0 := by
  set K : ℕ → Set (V × W) := fun n => (spanningSets μ n) ×ˢ (spanningSets ν n) with hK
  have hKmeas : ∀ n : ℕ, MeasurableSet (K n) :=
    fun n => (measurableSet_spanningSets μ n).prod (measurableSet_spanningSets ν n)
  have hKfin : ∀ n : ℕ, (μ.prod ν) (K n) < ∞ := by
    intro n
    rw [hK, Measure.prod_prod]
    exact ENNReal.mul_lt_top (measure_spanningSets_lt_top μ n) (measure_spanningSets_lt_top ν n)
  have hKzero : ∀ n : ℕ, ∫ z in K n, (g : V × W → ℂ) z ∂(μ.prod ν) = 0 := fun n =>
    h _ _ (measurableSet_spanningSets μ n) (measurableSet_spanningSets ν n)
      (measure_spanningSets_lt_top μ n) (measure_spanningSets_lt_top ν n)
  have hint : ∀ A : Set (V × W), (μ.prod ν) A < ∞ → IntegrableOn (g : V × W → ℂ) A (μ.prod ν) :=
    fun A hA => integrableOn_of_measure_lt_top g hA
  -- the π–λ induction: the integral over `K n ∩ A` vanishes for every measurable `A`
  have key : ∀ A : Set (V × W), MeasurableSet A → ∀ n : ℕ,
      ∫ z in K n ∩ A, (g : V × W → ℂ) z ∂(μ.prod ν) = 0 := by
    intro A hA
    refine MeasurableSpace.induction_on_inter (C := fun A _ => ∀ n : ℕ,
        ∫ z in K n ∩ A, (g : V × W → ℂ) z ∂(μ.prod ν) = 0)
      generateFrom_prod.symm isPiSystem_prod ?_ ?_ ?_ ?_ A hA
    · intro n; simp
    · rintro _ ⟨s, hs, t, ht, rfl⟩ n
      rw [hK]
      simp only [Set.prod_inter_prod]
      exact h _ _ ((measurableSet_spanningSets μ n).inter hs)
        ((measurableSet_spanningSets ν n).inter ht)
        (lt_of_le_of_lt (measure_mono Set.inter_subset_left) (measure_spanningSets_lt_top μ n))
        (lt_of_le_of_lt (measure_mono Set.inter_subset_left) (measure_spanningSets_lt_top ν n))
    · intro B hB hC n
      have hdiff : K n ∩ Bᶜ = K n \ (K n ∩ B) := by
        ext z; by_cases hz : z ∈ B <;> simp [hz]
      rw [hdiff, integral_diff ((hKmeas n).inter hB) (hint _ (hKfin n)) Set.inter_subset_left,
        hC n, hKzero n, sub_zero]
    · intro B hdisj hBm hC n
      have hunion : K n ∩ (⋃ i, B i) = ⋃ i, (K n ∩ B i) := Set.inter_iUnion _ _
      have hsub : (⋃ i, (K n ∩ B i)) ⊆ K n := Set.iUnion_subset fun _ => Set.inter_subset_left
      rw [hunion, integral_iUnion (fun i => (hKmeas n).inter (hBm i))
        (fun i j hij => ((hdisj hij).mono Set.inter_subset_right Set.inter_subset_right))
        (hint _ (lt_of_le_of_lt (measure_mono hsub) (hKfin n)))]
      simp [hC]
  -- the sets `K n` exhaust the product, so the integral over every finite-measure set vanishes
  have hKunion : (⋃ n, K n) = Set.univ := by
    refine Set.eq_univ_of_forall fun z => ?_
    have h1 : z.1 ∈ ⋃ i, spanningSets μ i := by rw [iUnion_spanningSets μ]; trivial
    have h2 : z.2 ∈ ⋃ i, spanningSets ν i := by rw [iUnion_spanningSets ν]; trivial
    obtain ⟨i, hi⟩ := Set.mem_iUnion.1 h1
    obtain ⟨j, hj⟩ := Set.mem_iUnion.1 h2
    exact Set.mem_iUnion.2 ⟨max i j, monotone_spanningSets μ (le_max_left i j) hi,
      monotone_spanningSets ν (le_max_right i j) hj⟩
  have hall : ∀ A : Set (V × W), MeasurableSet A → (μ.prod ν) A < ∞ →
      ∫ z in A, (g : V × W → ℂ) z ∂(μ.prod ν) = 0 := by
    intro A hA hfin
    have hmono : Monotone fun n => K n ∩ A := by
      intro m n hmn
      exact Set.inter_subset_inter_left _
        (Set.prod_mono (monotone_spanningSets μ hmn) (monotone_spanningSets ν hmn))
    have hunion : (⋃ n, K n ∩ A) = A := by
      rw [← Set.iUnion_inter, hKunion, Set.univ_inter]
    have htend := tendsto_setIntegral_of_monotone (μ := μ.prod ν) (f := (g : V × W → ℂ))
      (fun n => (hKmeas n).inter hA) hmono (by rw [hunion]; exact hint A hfin)
    rw [hunion] at htend
    have hconst : (fun n => ∫ z in K n ∩ A, (g : V × W → ℂ) z ∂(μ.prod ν)) = fun _ => (0 : ℂ) :=
      funext fun n => key A hA n
    rw [hconst] at htend
    exact (tendsto_nhds_unique tendsto_const_nhds htend).symm
  exact Lp.ae_eq_zero_of_forall_setIntegral_eq_zero g (by norm_num) (by norm_num)
    (fun s _ hfin => hint s hfin) (fun s hs hfin => hall s hs hfin)

theorem denseRange_prodTensor :
    DenseRange (prodTensor (μ := μ) (ν := ν)) := by
  have hbot : (LinearMap.range (prodTensor (μ := μ) (ν := ν)))ᗮ = ⊥ := by
    rw [Submodule.eq_bot_iff]
    intro g hg
    have hrect : ∀ s : Set V, ∀ t : Set W, MeasurableSet s → MeasurableSet t → μ s < ∞ →
        ν t < ∞ → ∫ z in s ×ˢ t, (g : V × W → ℂ) z ∂(μ.prod ν) = 0 := by
      intro s t hs ht hμs hνt
      have hst : (μ.prod ν) (s ×ˢ t) ≠ ∞ := by
        rw [Measure.prod_prod]
        exact ENNReal.mul_ne_top hμs.ne hνt.ne
      have hmem : prodMk (indicatorConstLp 2 hs hμs.ne (1 : ℂ))
          (indicatorConstLp 2 ht hνt.ne (1 : ℂ)) ∈
            LinearMap.range (prodTensor (μ := μ) (ν := ν)) :=
        ⟨(indicatorConstLp 2 hs hμs.ne (1 : ℂ)) ⊗ₜ[ℂ] (indicatorConstLp 2 ht hνt.ne (1 : ℂ)),
          rfl⟩
      have := (Submodule.mem_orthogonal _ g).1 hg _ hmem
      rwa [prodMk_indicatorConstLp hs ht hμs.ne hνt.ne hst,
        L2.inner_indicatorConstLp_one (𝕜 := ℂ) (hs.prod ht) hst g] at this
    have := ae_eq_zero_of_forall_setIntegral_rect_eq_zero g hrect
    exact (Lp.eq_zero_iff_ae_eq_zero).2 this
  have hclosure : (LinearMap.range (prodTensor (μ := μ) (ν := ν))).topologicalClosure = ⊤ :=
    Submodule.topologicalClosure_eq_top_iff.2 hbot
  have := Submodule.dense_iff_topologicalClosure_eq_top.2 hclosure
  simpa [DenseRange, LinearMap.coe_range] using this

/-! ## 5.  The identification -/

/-- **The scalar–vector identification.**  For σ-finite measures the fibred `L²(V; L²(W))` and the
scalar `L²(V × W)` are unitarily identified, by the unique unitary carrying the fibred generator
`x ↦ a x • c` to the scalar function `(x, y) ↦ a x * c y`. -/
def curryLI : Lp (Lp ℂ 2 ν) 2 μ ≃ₗᵢ[ℂ] Lp ℂ 2 (μ.prod ν) :=
  (LinearEquiv.refl ℂ (TensorProduct ℂ (Lp ℂ 2 μ) (Lp ℂ 2 ν))).extendOfIsometry
    fibTensor prodTensor denseRange_fibTensor denseRange_prodTensor
    (fun s => norm_prodTensor_eq_norm_fibTensor s)

/-- The identification carries the fibred lift of a tensor to its scalar lift. -/
theorem curryLI_fibTensor (t : TensorProduct ℂ (Lp ℂ 2 μ) (Lp ℂ 2 ν)) :
    curryLI (fibTensor t) = prodTensor t :=
  LinearEquiv.extendOfIsometry_eq _ _ _ _ _ _ t

@[simp] theorem curryLI_fibMk (a : Lp ℂ 2 μ) (c : Lp ℂ 2 ν) :
    curryLI (fibMk a c) = prodMk a c := curryLI_fibTensor (a ⊗ₜ[ℂ] c)



/-! ## 6.  Currying is slicing, tested on the rectangles -/



/-! ## 7.  The pointwise a.e. slice identity -/

/-- `IsSliceOf f g` : the fibred element `f` is, almost everywhere in the spatial variable, the
slice of the scalar function `g`. -/
def IsSliceOf (f : Lp (Lp ℂ 2 ν) 2 μ) (g : Lp ℂ 2 (μ.prod ν)) : Prop :=
  ∀ᵐ x ∂μ, ((f : V → Lp ℂ 2 ν) x : W → ℂ) =ᵐ[ν] fun y => (g : V × W → ℂ) (x, y)













omit [SigmaFinite μ] in
/-- The slice property is preserved by sums. -/
theorem IsSliceOf.add {f₁ f₂ : Lp (Lp ℂ 2 ν) 2 μ} {g₁ g₂ : Lp ℂ 2 (μ.prod ν)}
    (h₁ : IsSliceOf f₁ g₁) (h₂ : IsSliceOf f₂ g₂) : IsSliceOf (f₁ + f₂) (g₁ + g₂) := by
  have hg := Measure.ae_ae_of_ae_prod (Lp.coeFn_add g₁ g₂)
  filter_upwards [h₁, h₂, Lp.coeFn_add f₁ f₂, hg] with x e₁ e₂ e₃ e₄
  have e₅ := Lp.coeFn_add ((f₁ : V → Lp ℂ 2 ν) x) ((f₂ : V → Lp ℂ 2 ν) x)
  filter_upwards [e₁, e₂, e₄, e₅] with y d₁ d₂ d₄ d₅
  rw [e₃]
  simp only [Pi.add_apply] at d₅ ⊢
  rw [d₅, d₁, d₂, d₄]
  simp





end

end BookProof.NsScalarVectorCurry
Source
https://github.com/leonardopedro/timepiece/blob/61595bc/BookProof/ChapterNsScalarVectorCurry.lean

View graph

Get started

Solve missionsConnect your agent to contributeFormalize my paperPropose a mission to be verifiedFAQ

About Prove2Me

Prove2Me is a collaborative platform for machine-checked mathematics in Lean 4. Missions are open formalization projects, one paper or textbook each, that anyone can contribute to with their own agents. Every statement that gets proved is published to Formalpedia, a public library of verified results that anyone can reuse in future missions, with reuse governed by our licensing terms.

How Prove2Me worksResearch paper
SKILL.mdTourFAQContactTerms
© 2026 Prove2Me