Skip to content

Commit 409fa73

Browse files
grunwegRuben-VandeVeldesgouezel
committed
feat: continuity of primitives for parametric integrals (#11185)
From the sphere eversion project and generalised by `sgouezel`. This is used in the sphere eversion project to show that averaging of loops is continuous (which will be PRed to mathlib at a later point). Co-authored by: @fpvandoorn (who write this code originally, I believe) Co-authored-by: Ruben Van de Velde <[email protected]> Co-authored-by: sgouezel <[email protected]>
1 parent 6f1c52c commit 409fa73

File tree

4 files changed

+172
-11
lines changed

4 files changed

+172
-11
lines changed

Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean

+26
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,29 @@ theorem exists_spanning_measurableSet_le {m : MeasurableSpace α} {f : α →
494494
refine fun hif => hif.trans ?_
495495
exact mod_cast hij
496496
rw [this, norm_sets_spanning, iUnion_spanningSets μ, Set.inter_univ]
497+
498+
variable (μ : Measure ℝ) [IsFiniteMeasureOnCompacts μ]
499+
500+
lemma tendsto_measure_Icc_nhdsWithin_right' (b : ℝ) :
501+
Tendsto (fun δ ↦ μ (Icc (b - δ) (b + δ))) (𝓝[>] (0 : ℝ)) (𝓝 (μ {b})) := by
502+
rw [Real.singleton_eq_inter_Icc]
503+
apply tendsto_measure_biInter_gt (fun r hr ↦ measurableSet_Icc)
504+
· intro r s _rpos hrs
505+
exact Icc_subset_Icc (by linarith) (by linarith)
506+
· exact ⟨1, zero_lt_one, isCompact_Icc.measure_ne_top⟩
507+
508+
lemma tendsto_measure_Icc_nhdsWithin_right (b : ℝ) :
509+
Tendsto (fun δ ↦ μ (Icc (b - δ) (b + δ))) (𝓝[≥] (0 : ℝ)) (𝓝 (μ {b})) := by
510+
simp only [← nhdsWithin_right_sup_nhds_singleton, nhdsWithin_singleton, tendsto_sup,
511+
tendsto_measure_Icc_nhdsWithin_right' μ b, true_and, tendsto_pure_left]
512+
intro s hs
513+
simpa using mem_of_mem_nhds hs
514+
515+
lemma tendsto_measure_Icc [NoAtoms μ] (b : ℝ) :
516+
Tendsto (fun δ ↦ μ (Icc (b - δ) (b + δ))) (𝓝 (0 : ℝ)) (𝓝 0) := by
517+
rw [← nhds_left'_sup_nhds_right, tendsto_sup]
518+
constructor
519+
· apply tendsto_const_nhds.congr'
520+
filter_upwards [self_mem_nhdsWithin] with r (hr : r < 0)
521+
rw [Icc_eq_empty (by linarith), measure_empty]
522+
· simpa only [measure_singleton] using tendsto_measure_Icc_nhdsWithin_right μ b

Mathlib/MeasureTheory/Integral/DominatedConvergence.lean

+139-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ for the Bochner integral.
2828
2929
-/
3030

31-
open MeasureTheory
31+
open MeasureTheory Metric
3232

3333
/-!
3434
## The Lebesgue dominated convergence theorem for the Bochner integral
@@ -41,7 +41,7 @@ open scoped Topology
4141
namespace MeasureTheory
4242

4343
variable {α E G : Type*}
44-
[NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E]
44+
[NormedAddCommGroup E] [NormedSpace ℝ E]
4545
[NormedAddCommGroup G] [NormedSpace ℝ G]
4646
{f g : α → E} {m : MeasurableSpace α} {μ : Measure α}
4747

@@ -136,6 +136,8 @@ theorem integral_tsum {ι} [Countable ι] {f : ι → α → G} (hf : ∀ i, AES
136136
lemma hasSum_integral_of_summable_integral_norm {ι} [Countable ι] {F : ι → α → E}
137137
(hF_int : ∀ i : ι, Integrable (F i) μ) (hF_sum : Summable fun i ↦ ∫ a, ‖F i a‖ ∂μ) :
138138
HasSum (∫ a, F · a ∂μ) (∫ a, (∑' i, F i a) ∂μ) := by
139+
by_cases hE : CompleteSpace E; swap
140+
· simp [integral, hE, hasSum_zero]
139141
rw [integral_tsum (fun i ↦ (hF_int i).1)]
140142
· exact (hF_sum.of_norm_bounded _ fun i ↦ norm_integral_le_integral_norm _).hasSum
141143
have (i : ι) : ∫⁻ (a : α), ‖F i a‖₊ ∂μ = ‖(∫ a : α, ‖F i a‖ ∂μ)‖₊ := by
@@ -192,7 +194,7 @@ namespace intervalIntegral
192194

193195
section DCT
194196

195-
variable {ι 𝕜 E F : Type*} [NormedAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E]
197+
variable {ι 𝕜 E F : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
196198
{a b : ℝ} {f : ℝ → E} {μ : Measure ℝ}
197199

198200
/-- Lebesgue dominated convergence theorem for filters with a countable basis -/
@@ -228,6 +230,8 @@ special case of the dominated convergence theorem). -/
228230
theorem hasSum_intervalIntegral_of_summable_norm [Countable ι] {f : ι → C(ℝ, E)}
229231
(hf_sum : Summable fun i : ι => ‖(f i).restrict (⟨uIcc a b, isCompact_uIcc⟩ : Compacts ℝ)‖) :
230232
HasSum (fun i : ι => ∫ x in a..b, f i x) (∫ x in a..b, ∑' i : ι, f i x) := by
233+
by_cases hE : CompleteSpace E; swap
234+
· simp [intervalIntegral, integral, hE, hasSum_zero]
231235
apply hasSum_integral_of_dominated_convergence
232236
(fun i (x : ℝ) => ‖(f i).restrict ↑(⟨uIcc a b, isCompact_uIcc⟩ : Compacts ℝ)‖)
233237
(fun i => (map_continuous <| f i).aestronglyMeasurable)
@@ -237,8 +241,7 @@ theorem hasSum_intervalIntegral_of_summable_norm [Countable ι] {f : ι → C(
237241
· exact ae_of_all _ fun x _ => hf_sum
238242
· exact intervalIntegrable_const
239243
· refine ae_of_all _ fun x hx => Summable.hasSum ?_
240-
let x : (⟨uIcc a b, isCompact_uIcc⟩ : Compacts ℝ) := ⟨x, ?_⟩; swap
241-
· exact ⟨hx.1.le, hx.2
244+
let x : (⟨uIcc a b, isCompact_uIcc⟩ : Compacts ℝ) := ⟨x, ⟨hx.1.le, hx.2⟩⟩
242245
have := hf_sum.of_norm
243246
simpa only [Compacts.coe_mk, ContinuousMap.restrict_apply]
244247
using ContinuousMap.summable_apply this x
@@ -300,7 +303,7 @@ section ContinuousPrimitive
300303

301304
open scoped Interval
302305

303-
variable {E : Type*} [NormedAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E]
306+
variable {E X : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [TopologicalSpace X]
304307
{a b b₀ b₁ b₂ : ℝ} {μ : Measure ℝ} {f : ℝ → E}
305308

306309
theorem continuousWithinAt_primitive (hb₀ : μ {b₀} = 0)
@@ -368,10 +371,8 @@ theorem continuousWithinAt_primitive (hb₀ : μ {b₀} = 0)
368371
· apply continuousWithinAt_of_not_mem_closure
369372
rwa [closure_Icc]
370373

371-
variable {X : Type*} [TopologicalSpace X] [FirstCountableTopology X]
372-
{E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E]
373-
374-
theorem continuousAt_parametric_primitive_of_dominated {F : X → ℝ → E} (bound : ℝ → ℝ) (a b : ℝ)
374+
theorem continuousAt_parametric_primitive_of_dominated [FirstCountableTopology X]
375+
{F : X → ℝ → E} (bound : ℝ → ℝ) (a b : ℝ)
375376
{a₀ b₀ : ℝ} {x₀ : X} (hF_meas : ∀ x, AEStronglyMeasurable (F x) (μ.restrict <| Ι a b))
376377
(h_bound : ∀ᶠ x in 𝓝 x₀, ∀ᵐ t ∂μ.restrict <| Ι a b, ‖F x t‖ ≤ bound t)
377378
(bound_integrable : IntervalIntegrable bound μ a b)
@@ -390,7 +391,7 @@ theorem continuousAt_parametric_primitive_of_dominated {F : X → ℝ → E} (bo
390391
rw [nhds_prod_eq]
391392
refine (h_bound.prod_mk Ioo_nhds).mono ?_
392393
rintro ⟨x, t⟩ ⟨hx : ∀ᵐ t : ℝ ∂μ.restrict (Ι a b), ‖F x t‖ ≤ bound t, ht : t ∈ Ioo a b⟩
393-
dsimp (config := { eta := false })
394+
dsimp
394395
have hiF : ∀ {x a₀ b₀},
395396
(∀ᵐ t : ℝ ∂μ.restrict (Ι a b), ‖F x t‖ ≤ bound t) → a₀ ∈ Ioo a b → b₀ ∈ Ioo a b →
396397
IntervalIntegrable (F x) μ a₀ b₀ := fun {x a₀ b₀} hx ha₀ hb₀ ↦
@@ -498,6 +499,133 @@ nonrec theorem _root_.MeasureTheory.Integrable.continuous_primitive (h_int : Int
498499
(a : ℝ) : Continuous fun b => ∫ x in a..b, f x ∂μ :=
499500
continuous_primitive (fun _ _ => h_int.intervalIntegrable) a
500501

502+
variable [IsLocallyFiniteMeasure μ] {f : X → ℝ → E}
503+
504+
theorem continuous_parametric_primitive_of_continuous
505+
{a₀ : ℝ} (hf : Continuous f.uncurry) :
506+
Continuous fun p : X × ℝ ↦ ∫ t in a₀..p.2, f p.1 t ∂μ := by
507+
-- We will prove continuity at a point `(q, b₀)`.
508+
rw [continuous_iff_continuousAt]
509+
rintro ⟨q, b₀⟩
510+
apply Metric.continuousAt_iff'.2 (fun ε εpos ↦ ?_)
511+
-- choose `a` and `b` such that `(a, b)` contains both `a₀` and `b₀`. We will use uniform
512+
-- estimates on a neighborhood of the compact set `{q} × [a, b]`.
513+
cases' exists_lt (min a₀ b₀) with a a_lt
514+
cases' exists_gt (max a₀ b₀) with b lt_b
515+
rw [lt_min_iff] at a_lt
516+
rw [max_lt_iff] at lt_b
517+
have : IsCompact ({q} ×ˢ (Icc a b)) := isCompact_singleton.prod isCompact_Icc
518+
-- let `M` be a bound for `f` on the compact set `{q} × [a, b]`.
519+
obtain ⟨M, hM⟩ := this.bddAbove_image hf.norm.continuousOn
520+
-- let `δ` be small enough to satisfy several properties that will show up later.
521+
obtain ⟨δ, δpos, hδ, h'δ, h''δ⟩ : ∃ (δ : ℝ), 0 < δ ∧ δ < 1 ∧ Icc (b₀ - δ) (b₀ + δ) ⊆ Icc a b ∧
522+
(M + 1) * (μ (Icc (b₀ - δ) (b₀ + δ))).toReal + δ * (μ (Icc a b)).toReal < ε := by
523+
have A : ∀ᶠ δ in 𝓝[>] (0 : ℝ), δ ∈ Ioo 0 1 := Ioo_mem_nhdsWithin_Ioi (by simp)
524+
have B : ∀ᶠ δ in 𝓝 0, Icc (b₀ - δ) (b₀ + δ) ⊆ Icc a b := by
525+
have I : Tendsto (fun δ ↦ b₀ - δ) (𝓝 0) (𝓝 (b₀ - 0)) := tendsto_const_nhds.sub tendsto_id
526+
have J : Tendsto (fun δ ↦ b₀ + δ) (𝓝 0) (𝓝 (b₀ + 0)) := tendsto_const_nhds.add tendsto_id
527+
simp only [sub_zero, add_zero] at I J
528+
filter_upwards [(tendsto_order.1 I).1 _ a_lt.2, (tendsto_order.1 J).2 _ lt_b.2] with δ hδ h'δ
529+
exact Icc_subset_Icc hδ.le h'δ.le
530+
have C : ∀ᶠ δ in 𝓝 0,
531+
(M + 1) * (μ (Icc (b₀ - δ) (b₀ + δ))).toReal + δ * (μ (Icc a b)).toReal < ε := by
532+
suffices Tendsto
533+
(fun δ ↦ (M + 1) * (μ (Icc (b₀ - δ) (b₀ + δ))).toReal + δ * (μ (Icc a b)).toReal)
534+
(𝓝 0) (𝓝 ((M + 1) * (0 : ℝ≥0∞).toReal + 0 * (μ (Icc a b)).toReal)) by
535+
simp only [zero_toReal, mul_zero, zero_mul, add_zero] at this
536+
exact (tendsto_order.1 this).2 _ εpos
537+
apply Tendsto.add (Tendsto.mul tendsto_const_nhds _)
538+
(Tendsto.mul tendsto_id tendsto_const_nhds)
539+
exact (tendsto_toReal zero_ne_top).comp (tendsto_measure_Icc _ _)
540+
rcases (A.and ((B.and C).filter_mono nhdsWithin_le_nhds)).exists with ⟨δ, hδ, h'δ, h''δ⟩
541+
exact ⟨δ, hδ.1, hδ.2, h'δ, h''δ⟩
542+
-- By compactness of `[a, b]` and continuity of `f` there, if `p` is close enough to `q`
543+
-- then `f p x` is `δ`-close to `f q x`, uniformly in `x ∈ [a, b]`.
544+
-- (Note in particular that this implies a bound `M + δ ≤ M + 1` for `f p x`).
545+
obtain ⟨v, v_mem, hv⟩ : ∃ v ∈ 𝓝[univ] q, ∀ p ∈ v, ∀ x ∈ Icc a b, dist (f p x) (f q x) < δ :=
546+
IsCompact.mem_uniformity_of_prod isCompact_Icc hf.continuousOn (mem_univ _)
547+
(dist_mem_uniformity δpos)
548+
-- for `p` in this neighborhood and `s` which is `δ`-close to `b₀`, we will show that the
549+
-- integrals are `ε`-close.
550+
have : v ×ˢ (Ioo (b₀ - δ) (b₀ + δ)) ∈ 𝓝 (q, b₀) := by
551+
rw [nhdsWithin_univ] at v_mem
552+
simp only [prod_mem_nhds_iff, v_mem, true_and]
553+
apply Ioo_mem_nhds <;> linarith
554+
filter_upwards [this]
555+
rintro ⟨p, s⟩ ⟨hp : p ∈ v, hs : s ∈ Ioo (b₀ - δ) (b₀ + δ)⟩
556+
simp only [dist_eq_norm] at hv ⊢
557+
have J r u v : IntervalIntegrable (f r) μ u v := (hf.uncurry_left _).intervalIntegrable _ _
558+
/- we compute the difference between the integrals by splitting the contribution of the change
559+
from `b₀` to `s` (which gives a contribution controlled by the measure of `(b₀ - δ, b₀ + δ)`,
560+
small enough thanks to our choice of `δ`) and the change from `q` to `p`, which is small as
561+
`f p x` and `f q x` are uniformly close by design. -/
562+
calc
563+
‖∫ t in a₀..s, f p t ∂μ - ∫ t in a₀..b₀, f q t ∂μ‖
564+
= ‖(∫ t in a₀..s, f p t ∂μ - ∫ t in a₀..b₀, f p t ∂μ)
565+
+ (∫ t in a₀..b₀, f p t ∂μ - ∫ t in a₀..b₀, f q t ∂μ)‖ := by congr 1; abel
566+
_ ≤ ‖∫ t in a₀..s, f p t ∂μ - ∫ t in a₀..b₀, f p t ∂μ‖
567+
+ ‖∫ t in a₀..b₀, f p t ∂μ - ∫ t in a₀..b₀, f q t ∂μ‖ := norm_add_le _ _
568+
_ = ‖∫ t in b₀..s, f p t ∂μ‖ + ‖∫ t in a₀..b₀, (f p t - f q t) ∂μ‖ := by
569+
congr 2
570+
· rw [integral_interval_sub_left (J _ _ _) (J _ _ _)]
571+
· rw [integral_sub (J _ _ _) (J _ _ _)]
572+
_ ≤ ∫ t in Ι b₀ s, ‖f p t‖ ∂μ + ∫ t in Ι a₀ b₀, ‖f p t - f q t‖ ∂μ := by
573+
gcongr
574+
· exact norm_integral_le_integral_norm_Ioc
575+
· exact norm_integral_le_integral_norm_Ioc
576+
_ ≤ ∫ t in Icc (b₀ - δ) (b₀ + δ), ‖f p t‖ ∂μ + ∫ t in Icc a b, ‖f p t - f q t‖ ∂μ := by
577+
gcongr
578+
· apply setIntegral_mono_set
579+
· exact (hf.uncurry_left _).norm.integrableOn_Icc
580+
· exact eventually_of_forall (fun x ↦ norm_nonneg _)
581+
· have : Ι b₀ s ⊆ Icc (b₀ - δ) (b₀ + δ) := by
582+
apply uIoc_subset_uIcc.trans (uIcc_subset_Icc ?_ ⟨hs.1.le, hs.2.le⟩ )
583+
simp [δpos.le]
584+
exact eventually_of_forall this
585+
· apply setIntegral_mono_set
586+
· exact ((hf.uncurry_left _).sub (hf.uncurry_left _)).norm.integrableOn_Icc
587+
· exact eventually_of_forall (fun x ↦ norm_nonneg _)
588+
· have : Ι a₀ b₀ ⊆ Icc a b := uIoc_subset_uIcc.trans
589+
(uIcc_subset_Icc ⟨a_lt.1.le, lt_b.1.le⟩ ⟨a_lt.2.le, lt_b.2.le⟩)
590+
exact eventually_of_forall this
591+
_ ≤ ∫ t in Icc (b₀ - δ) (b₀ + δ), M + 1 ∂μ + ∫ _t in Icc a b, δ ∂μ := by
592+
gcongr
593+
· apply setIntegral_mono_on
594+
· exact (hf.uncurry_left _).norm.integrableOn_Icc
595+
· exact continuous_const.integrableOn_Icc
596+
· exact measurableSet_Icc
597+
· intro x hx
598+
calc ‖f p x‖ = ‖f q x + (f p x - f q x)‖ := by congr; abel
599+
_ ≤ ‖f q x‖ + ‖f p x - f q x‖ := norm_add_le _ _
600+
_ ≤ M + δ := by
601+
gcongr
602+
· apply hM
603+
change (fun x ↦ ‖Function.uncurry f x‖) (q, x) ∈ _
604+
apply mem_image_of_mem
605+
simp only [singleton_prod, mem_image, Prod.mk.injEq, true_and, exists_eq_right]
606+
exact h'δ hx
607+
· exact le_of_lt (hv _ hp _ (h'δ hx))
608+
_ ≤ M + 1 := by linarith
609+
· apply setIntegral_mono_on
610+
· exact ((hf.uncurry_left _).sub (hf.uncurry_left _)).norm.integrableOn_Icc
611+
· exact continuous_const.integrableOn_Icc
612+
· exact measurableSet_Icc
613+
· intro x hx
614+
exact le_of_lt (hv _ hp _ hx)
615+
_ = (M + 1) * (μ (Icc (b₀ - δ) (b₀ + δ))).toReal + δ * (μ (Icc a b)).toReal := by simp [mul_comm]
616+
_ < ε := h''δ
617+
618+
@[fun_prop]
619+
theorem continuous_parametric_intervalIntegral_of_continuous {a₀ : ℝ}
620+
(hf : Continuous f.uncurry) {s : X → ℝ} (hs : Continuous s) :
621+
Continuous fun x ↦ ∫ t in a₀..s x, f x t ∂μ :=
622+
show Continuous ((fun p : X × ℝ ↦ ∫ t in a₀..p.2, f p.1 t ∂μ) ∘ fun x ↦ (x, s x)) from
623+
(continuous_parametric_primitive_of_continuous hf).comp₂ continuous_id hs
624+
625+
theorem continuous_parametric_intervalIntegral_of_continuous'
626+
(hf : Continuous f.uncurry) (a₀ b₀ : ℝ) :
627+
Continuous fun x ↦ ∫ t in a₀..b₀, f x t ∂μ := by fun_prop
628+
501629
end ContinuousPrimitive
502630

503631
end intervalIntegral

Mathlib/Topology/MetricSpace/Pseudo/Lemmas.lean

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ instance : OrderTopology ℝ :=
3838
orderTopology_of_nhds_abs fun x => by
3939
simp only [nhds_basis_ball.eq_biInf, ball, Real.dist_eq, abs_sub_comm]
4040

41+
lemma Real.singleton_eq_inter_Icc (b : ℝ) : {b} = ⋂ (r > 0), Icc (b - r) (b + r) := by
42+
simp [Icc_eq_closedBall, biInter_basis_nhds Metric.nhds_basis_closedBall]
43+
4144
/-- Special case of the sandwich lemma; see `tendsto_of_tendsto_of_tendsto_of_le_of_le'` for the
4245
general case. -/
4346
lemma squeeze_zero' {α} {f g : α → ℝ} {t₀ : Filter α} (hf : ∀ᶠ t in t₀, 0 ≤ f t)

Mathlib/Topology/Order/LeftRight.lean

+4
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ theorem nhds_left_sup_nhds_right' (a : α) : 𝓝[≤] a ⊔ 𝓝[>] a = 𝓝 a
107107
theorem nhds_left'_sup_nhds_right' (a : α) : 𝓝[<] a ⊔ 𝓝[>] a = 𝓝[≠] a := by
108108
rw [← nhdsWithin_union, Iio_union_Ioi]
109109

110+
lemma nhdsWithin_right_sup_nhds_singleton (a : α) :
111+
𝓝[>] a ⊔ 𝓝[{a}] a = 𝓝[≥] a := by
112+
simp only [union_singleton, Ioi_insert, ← nhdsWithin_union]
113+
110114
theorem continuousAt_iff_continuous_left_right {a : α} {f : α → β} :
111115
ContinuousAt f a ↔ ContinuousWithinAt f (Iic a) a ∧ ContinuousWithinAt f (Ici a) a := by
112116
simp only [ContinuousWithinAt, ContinuousAt, ← tendsto_sup, nhds_left_sup_nhds_right]

0 commit comments

Comments
 (0)