Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat: Levy-Prokhorov topology is finer than convergence in distribution #10406

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
760d4ab
feat: Add the Lévy-Prokhorov (pseudo)metric on finite measures.
kkytola Nov 28, 2023
c5c8e7a
Fix lints, move a lemma, include in Mathlib.lean.
Nov 29, 2023
410495b
Fix the name of the module to import.
kkytola Nov 29, 2023
f10bb64
Fix linting complaints.
kkytola Nov 29, 2023
0b451aa
Clean-up and improvements.
kkytola Dec 4, 2023
be4b0bd
Merge branch 'master' into kkytola/LevyProkhorovPseudoEMetric
kkytola Dec 4, 2023
3cd6367
Small streamlining.
kkytola Dec 6, 2023
daff239
Merge master.
kkytola Dec 7, 2023
4433b7e
Merge branch 'master' into kkytola/LevyProkhorovPseudoEMetric
urkud Dec 26, 2023
1e85269
Golf 2 proofs
urkud Dec 26, 2023
21a2e1a
Golf more
urkud Dec 26, 2023
aae8b19
Update Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean
kkytola Dec 30, 2023
98e1e53
Record the pseudo(e)metric space instances on type synonyms.
kkytola Dec 30, 2023
6b5508d
Let's not import the whole tactic folder (I was looking for the finit…
kkytola Dec 30, 2023
1f23ff1
Fix merge conflict.
kkytola Jan 6, 2024
2d23ce6
Update Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean
kkytola Jan 26, 2024
8a2986e
Merge branch 'master' into kkytola/LevyProkhorovPseudoEMetric
kkytola Jan 26, 2024
e591559
Fix broken proofs and add a comment.
kkytola Jan 26, 2024
e4ff062
feat: Add the easy topology comparison - Levy Prokhorov topology is f…
kkytola Feb 10, 2024
e124ac6
Apply suggestions from code review
kkytola Feb 10, 2024
e266408
Fix long lines.
kkytola Feb 10, 2024
e3a221a
Fix line breaks.
kkytola Feb 10, 2024
c03b392
Merge master.
kkytola Feb 17, 2024
51255c4
Move a lemma and clean up slightly.
kkytola Feb 17, 2024
602a34a
Correct a naming misprint.
kkytola Feb 17, 2024
c1dceef
Remove TODO comments.
kkytola Feb 17, 2024
56111a6
Remove one transitively redundant import and golf one line.
kkytola Feb 17, 2024
de3322d
Apply suggestions from code review
kkytola Mar 5, 2024
9385c39
Remove unnecessary parentheses in integrations.
kkytola Mar 15, 2024
6738e2e
Cleaner apply with bdd_above bdd_below.
kkytola Mar 15, 2024
1d99919
Remove unnecessary parentheses around integrations in Layercake.
kkytola Mar 15, 2024
bc8adbf
Fix broken proofs.
kkytola Mar 15, 2024
227d4f0
Remove some more unnecessary parentheses.
kkytola Mar 15, 2024
22b1227
Do the proof using the more general version of the lemma (but should …
kkytola Mar 15, 2024
c4f7a06
Clean up one line (unnecessarily providing implicit arguments).
kkytola Mar 16, 2024
f4fb504
Update Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean
kkytola Mar 17, 2024
bba009a
Renaming declarations as recommended in the review.
kkytola Mar 17, 2024
c604c48
Remove the unnecessary special case version tendsto_integral_meas_thi…
kkytola Mar 17, 2024
169d11f
Rename one more layer cake lemma, put it to the Integrable namespace …
Mar 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
65 changes: 61 additions & 4 deletions Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kalle Kytölä
-/
import Mathlib.MeasureTheory.Integral.Bochner
import Mathlib.Topology.Order.Bounded
Copy link
Collaborator Author

@kkytola kkytola Feb 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added import is due to moving the lemma tendsto_integral_of_forall_integral_le_liminf_integral from Portmanteau.lean to here, and adding the analoguous tendsto_integral_of_forall_integral_le_liminf_integral, which is used in LevyProkhorovMetric.lean. When also the other topology comparison will be added, LevyProkhorovMetric.lean will also have to import Portmanteau.lean, so this amounts to a minor import creep. However, I think this is the natural place for these two lemmas. Also, this file is currently basically only used for the weak convergence of measures.


/-!
# Integration of bounded continuous functions
Expand Down Expand Up @@ -99,22 +100,22 @@ lemma integrable [IsFiniteMeasure μ] (f : X →ᵇ E) :
variable [NormedSpace ℝ E]

lemma norm_integral_le_mul_norm [IsFiniteMeasure μ] (f : X →ᵇ E) :
‖∫ x, (f x) ∂μ‖ ≤ ENNReal.toReal (μ Set.univ) * ‖f‖ := by
calc ‖∫ x, (f x) ∂μ‖
‖∫ x, f x ∂μ‖ ≤ ENNReal.toReal (μ Set.univ) * ‖f‖ := by
calc ‖∫ x, f x ∂μ‖
_ ≤ ∫ x, ‖f x‖ ∂μ := by exact norm_integral_le_integral_norm _
_ ≤ ∫ _, ‖f‖ ∂μ := ?_
_ = ENNReal.toReal (μ Set.univ) • ‖f‖ := by rw [integral_const]
· apply integral_mono _ (integrable_const ‖f‖) (fun x ↦ f.norm_coe_le_norm x) -- NOTE: `gcongr`?
exact (integrable_norm_iff f.continuous.measurable.aestronglyMeasurable).mpr (f.integrable μ)

lemma norm_integral_le_norm [IsProbabilityMeasure μ] (f : X →ᵇ E) :
‖∫ x, (f x) ∂μ‖ ≤ ‖f‖ := by
‖∫ x, f x ∂μ‖ ≤ ‖f‖ := by
convert f.norm_integral_le_mul_norm μ
simp only [measure_univ, ENNReal.one_toReal, one_mul]

lemma isBounded_range_integral
{ι : Type*} (μs : ι → Measure X) [∀ i, IsProbabilityMeasure (μs i)] (f : X →ᵇ E) :
Bornology.IsBounded (Set.range (fun i ↦ ∫ x, (f x) ∂ (μs i))) := by
Bornology.IsBounded (Set.range (fun i ↦ ∫ x, f x ∂ (μs i))) := by
apply isBounded_iff_forall_norm_le.mpr ⟨‖f‖, fun v hv ↦ ?_⟩
obtain ⟨i, hi⟩ := hv
rw [← hi]
Expand All @@ -137,4 +138,60 @@ lemma integral_const_sub (f : X →ᵇ ℝ) (c : ℝ) :

end RealValued

section tendsto_integral

variable {X : Type*} [TopologicalSpace X] [MeasurableSpace X] [OpensMeasurableSpace X]

lemma tendsto_integral_of_forall_limsup_integral_le_integral {ι : Type*} {L : Filter ι}
{μ : Measure X} [IsProbabilityMeasure μ] {μs : ι → Measure X} [∀ i, IsProbabilityMeasure (μs i)]
(h : ∀ f : X →ᵇ ℝ, 0 ≤ f → L.limsup (fun i ↦ ∫ x, f x ∂ (μs i)) ≤ ∫ x, f x ∂μ)
(f : X →ᵇ ℝ) :
Tendsto (fun i ↦ ∫ x, f x ∂ (μs i)) L (𝓝 (∫ x, f x ∂μ)) := by
rcases eq_or_neBot L with rfl|hL
· simp only [tendsto_bot]
have obs := BoundedContinuousFunction.isBounded_range_integral μs f
have bdd_above : IsBoundedUnder (· ≤ ·) L (fun i ↦ ∫ x, f x ∂μs i) :=
isBounded_le_map_of_bounded_range _ obs
have bdd_below : IsBoundedUnder (· ≥ ·) L (fun i ↦ ∫ x, f x ∂μs i) :=
isBounded_ge_map_of_bounded_range _ obs
apply tendsto_of_le_liminf_of_limsup_le _ _ bdd_above bdd_below
· have key := h _ (f.norm_sub_nonneg)
simp_rw [f.integral_const_sub ‖f‖] at key
simp only [measure_univ, ENNReal.one_toReal, smul_eq_mul, one_mul] at key
have := limsup_const_sub L (fun i ↦ ∫ x, f x ∂ (μs i)) ‖f‖ bdd_above bdd_below
rwa [this, _root_.sub_le_sub_iff_left ‖f‖] at key
· have key := h _ (f.add_norm_nonneg)
simp_rw [f.integral_add_const ‖f‖] at key
simp only [measure_univ, ENNReal.one_toReal, smul_eq_mul, one_mul] at key
have := limsup_add_const L (fun i ↦ ∫ x, f x ∂ (μs i)) ‖f‖ bdd_above bdd_below
rwa [this, add_le_add_iff_right] at key

lemma tendsto_integral_of_forall_integral_le_liminf_integral {ι : Type*} {L : Filter ι}
{μ : Measure X} [IsProbabilityMeasure μ] {μs : ι → Measure X} [∀ i, IsProbabilityMeasure (μs i)]
(h : ∀ f : X →ᵇ ℝ, 0 ≤ f → ∫ x, f x ∂μ ≤ L.liminf (fun i ↦ ∫ x, f x ∂ (μs i)))
(f : X →ᵇ ℝ) :
Tendsto (fun i ↦ ∫ x, f x ∂ (μs i)) L (𝓝 (∫ x, f x ∂μ)) := by
rcases eq_or_neBot L with rfl|hL
· simp only [tendsto_bot]
have obs := BoundedContinuousFunction.isBounded_range_integral μs f
have bdd_above : IsBoundedUnder (· ≤ ·) L (fun i ↦ ∫ x, f x ∂μs i) :=
isBounded_le_map_of_bounded_range _ obs
have bdd_below : IsBoundedUnder (· ≥ ·) L (fun i ↦ ∫ x, f x ∂μs i) :=
isBounded_ge_map_of_bounded_range _ obs
apply @tendsto_of_le_liminf_of_limsup_le ℝ ι _ _ _ L (fun i ↦ ∫ x, f x ∂ (μs i)) (∫ x, f x ∂μ)
· have key := h _ (f.add_norm_nonneg)
simp_rw [f.integral_add_const ‖f‖] at key
simp only [measure_univ, ENNReal.one_toReal, smul_eq_mul, one_mul] at key
have := liminf_add_const L (fun i ↦ ∫ x, f x ∂ (μs i)) ‖f‖ bdd_above bdd_below
rwa [this, add_le_add_iff_right] at key
· have key := h _ (f.norm_sub_nonneg)
simp_rw [f.integral_const_sub ‖f‖] at key
simp only [measure_univ, ENNReal.one_toReal, smul_eq_mul, one_mul] at key
have := liminf_const_sub L (fun i ↦ ∫ x, f x ∂ (μs i)) ‖f‖ bdd_above bdd_below
rwa [this, sub_le_sub_iff_left] at key
· exact bdd_above
· exact bdd_below

end tendsto_integral --section

end BoundedContinuousFunction
5 changes: 5 additions & 0 deletions Mathlib/MeasureTheory/Integral/IntegrableOn.lean
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,11 @@ alias _root_.Filter.Tendsto.integrableAtFilter :=
Measure.FiniteAtFilter.integrableAtFilter_of_tendsto
#align filter.tendsto.integrable_at_filter Filter.Tendsto.integrableAtFilter

lemma Measure.integrableOn_of_bounded (s_finite : μ s ≠ ∞) (f_mble : AEStronglyMeasurable f μ)
{M : ℝ} (f_bdd : ∀ᵐ a ∂(μ.restrict s), ‖f a‖ ≤ M) :
IntegrableOn f s μ :=
⟨f_mble.restrict, hasFiniteIntegral_restrict_of_bounded (C := M) s_finite.lt_top f_bdd⟩

theorem integrable_add_of_disjoint {f g : α → E} (h : Disjoint (support f) (support g))
(hf : StronglyMeasurable f) (hg : StronglyMeasurable g) :
Integrable (f + g) μ ↔ Integrable f μ ∧ Integrable g μ := by
Expand Down
46 changes: 34 additions & 12 deletions Mathlib/MeasureTheory/Integral/Layercake.lean
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,15 @@ theorem lintegral_comp_eq_lintegral_meas_le_mul_of_measurable_of_sigmaFinite
(f_nn : 0 ≤ f) (f_mble : Measurable f)
(g_intble : ∀ t > 0, IntervalIntegrable g volume 0 t) (g_mble : Measurable g)
(g_nn : ∀ t > 0, 0 ≤ g t) :
(∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ) =
∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ =
∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} * ENNReal.ofReal (g t) := by
have g_intble' : ∀ t : ℝ, 0 ≤ t → IntervalIntegrable g volume 0 t := by
intro t ht
cases' eq_or_lt_of_le ht with h h
· simp [← h]
· exact g_intble t h
have integrand_eq : ∀ ω,
ENNReal.ofReal (∫ t in (0)..f ω, g t) = (∫⁻ t in Ioc 0 (f ω), ENNReal.ofReal (g t)) := by
ENNReal.ofReal (∫ t in (0)..f ω, g t) = ∫⁻ t in Ioc 0 (f ω), ENNReal.ofReal (g t) := by
intro ω
have g_ae_nn : 0 ≤ᵐ[volume.restrict (Ioc 0 (f ω))] g := by
filter_upwards [self_mem_ae_restrict (measurableSet_Ioc : MeasurableSet (Ioc 0 (f ω)))]
Expand Down Expand Up @@ -196,7 +196,7 @@ theorem lintegral_comp_eq_lintegral_meas_le_mul_of_measurable (μ : Measure α)
(f_nn : 0 ≤ f) (f_mble : Measurable f)
(g_intble : ∀ t > 0, IntervalIntegrable g volume 0 t) (g_mble : Measurable g)
(g_nn : ∀ t > 0, 0 ≤ g t) :
(∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ) =
∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ =
∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} * ENNReal.ofReal (g t) := by
/- We will reduce to the sigma-finite case, after excluding two easy cases where the result
is more or less obvious. -/
Expand Down Expand Up @@ -395,7 +395,7 @@ instead. -/
theorem lintegral_comp_eq_lintegral_meas_le_mul (μ : Measure α) (f_nn : 0 ≤ᵐ[μ] f)
(f_mble : AEMeasurable f μ) (g_intble : ∀ t > 0, IntervalIntegrable g volume 0 t)
(g_nn : ∀ᵐ t ∂volume.restrict (Ioi 0), 0 ≤ g t) :
(∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ) =
∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ =
∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} * ENNReal.ofReal (g t) := by
obtain ⟨G, G_mble, G_nn, g_eq_G⟩ : ∃ G : ℝ → ℝ, Measurable G ∧ 0 ≤ G
∧ g =ᵐ[volume.restrict (Ioi 0)] G := by
Expand All @@ -414,7 +414,7 @@ theorem lintegral_comp_eq_lintegral_meas_le_mul (μ : Measure α) (f_nn : 0 ≤
rw [← hω]
exact (max_eq_left h'ω).symm
have eq₁ :
(∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} * ENNReal.ofReal (g t)) =
∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} * ENNReal.ofReal (g t) =
∫⁻ t in Ioi 0, μ {a : α | t ≤ F a} * ENNReal.ofReal (G t) := by
apply lintegral_congr_ae
filter_upwards [g_eq_G] with t ht
Expand Down Expand Up @@ -446,7 +446,7 @@ See `lintegral_eq_lintegral_meas_lt` for a version with sets of the form `{ω |
instead. -/
theorem lintegral_eq_lintegral_meas_le (μ : Measure α) (f_nn : 0 ≤ᵐ[μ] f)
(f_mble : AEMeasurable f μ) :
(∫⁻ ω, ENNReal.ofReal (f ω) ∂μ) = ∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} := by
∫⁻ ω, ENNReal.ofReal (f ω) ∂μ = ∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} := by
set cst := fun _ : ℝ => (1 : ℝ)
have cst_intble : ∀ t > 0, IntervalIntegrable cst volume 0 t := fun _ _ =>
intervalIntegrable_const
Expand All @@ -468,10 +468,10 @@ See `lintegral_rpow_eq_lintegral_meas_lt_mul` for a version with sets of the for
instead. -/
theorem lintegral_rpow_eq_lintegral_meas_le_mul (μ : Measure α) (f_nn : 0 ≤ᵐ[μ] f)
(f_mble : AEMeasurable f μ) {p : ℝ} (p_pos : 0 < p) :
(∫⁻ ω, ENNReal.ofReal (f ω ^ p) ∂μ) =
∫⁻ ω, ENNReal.ofReal (f ω ^ p) ∂μ =
ENNReal.ofReal p * ∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} * ENNReal.ofReal (t ^ (p - 1)) := by
have one_lt_p : -1 < p - 1 := by linarith
have obs : ∀ x : ℝ, (∫ t : ℝ in (0)..x, t ^ (p - 1)) = x ^ p / p := by
have obs : ∀ x : ℝ, ∫ t : ℝ in (0)..x, t ^ (p - 1) = x ^ p / p := by
intro x
rw [integral_rpow (Or.inl one_lt_p)]
simp [Real.zero_rpow p_pos.ne.symm]
Expand Down Expand Up @@ -517,7 +517,7 @@ instead. -/
theorem lintegral_comp_eq_lintegral_meas_lt_mul (μ : Measure α) (f_nn : 0 ≤ᵐ[μ] f)
(f_mble : AEMeasurable f μ) (g_intble : ∀ t > 0, IntervalIntegrable g volume 0 t)
(g_nn : ∀ᵐ t ∂volume.restrict (Ioi 0), 0 ≤ g t) :
(∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ) =
∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ =
∫⁻ t in Ioi 0, μ {a : α | t < f a} * ENNReal.ofReal (g t) := by
rw [lintegral_comp_eq_lintegral_meas_le_mul μ f_nn f_mble g_intble g_nn]
apply lintegral_congr_ae
Expand All @@ -535,7 +535,7 @@ See `lintegral_eq_lintegral_meas_le` for a version with sets of the form `{ω |
instead. -/
theorem lintegral_eq_lintegral_meas_lt (μ : Measure α)
(f_nn : 0 ≤ᵐ[μ] f) (f_mble : AEMeasurable f μ) :
(∫⁻ ω, ENNReal.ofReal (f ω) ∂μ) = ∫⁻ t in Ioi 0, μ {a : α | t < f a} := by
∫⁻ ω, ENNReal.ofReal (f ω) ∂μ = ∫⁻ t in Ioi 0, μ {a : α | t < f a} := by
rw [lintegral_eq_lintegral_meas_le μ f_nn f_mble]
apply lintegral_congr_ae
filter_upwards [meas_le_ae_eq_meas_lt μ (volume.restrict (Ioi 0)) f]
Expand All @@ -552,7 +552,7 @@ See `lintegral_rpow_eq_lintegral_meas_le_mul` for a version with sets of the for
instead. -/
theorem lintegral_rpow_eq_lintegral_meas_lt_mul (μ : Measure α)
(f_nn : 0 ≤ᵐ[μ] f) (f_mble : AEMeasurable f μ) {p : ℝ} (p_pos : 0 < p) :
(∫⁻ ω, ENNReal.ofReal (f ω ^ p) ∂μ) =
∫⁻ ω, ENNReal.ofReal (f ω ^ p) ∂μ =
ENNReal.ofReal p * ∫⁻ t in Ioi 0, μ {a : α | t < f a} * ENNReal.ofReal (t ^ (p - 1)) := by
rw [lintegral_rpow_eq_lintegral_meas_le_mul μ f_nn f_mble p_pos]
apply congr_arg fun z => ENNReal.ofReal p * z
Expand All @@ -576,7 +576,7 @@ written (roughly speaking) as: `∫ f ∂μ = ∫ t in 0..∞, μ {ω | f(ω) >
See `lintegral_eq_lintegral_meas_lt` for a version with Lebesgue integral `∫⁻` instead. -/
theorem Integrable.integral_eq_integral_meas_lt
(f_intble : Integrable f μ) (f_nn : 0 ≤ᵐ[μ] f) :
(∫ ω, f ω ∂μ) = ∫ t in Set.Ioi 0, ENNReal.toReal (μ {a : α | t < f a}) := by
∫ ω, f ω ∂μ = ∫ t in Set.Ioi 0, ENNReal.toReal (μ {a : α | t < f a}) := by
have key := lintegral_eq_lintegral_meas_lt μ f_nn f_intble.aemeasurable
have lhs_finite : ∫⁻ (ω : α), ENNReal.ofReal (f ω) ∂μ < ∞ := Integrable.lintegral_lt_top f_intble
have rhs_finite : ∫⁻ (t : ℝ) in Set.Ioi 0, μ {a | t < f a} < ∞ := by simp only [← key, lhs_finite]
Expand All @@ -595,6 +595,28 @@ theorem Integrable.integral_eq_integral_meas_lt
refine Measurable.ennreal_toReal ?_
exact Antitone.measurable (fun _ _ hst ↦ measure_mono (fun _ h ↦ lt_of_le_of_lt hst h))

theorem Integrable.integral_eq_integral_meas_le
(f_intble : Integrable f μ) (f_nn : 0 ≤ᵐ[μ] f) :
∫ ω, f ω ∂μ = ∫ t in Set.Ioi 0, ENNReal.toReal (μ {a : α | t ≤ f a}) := by
rw [Integrable.integral_eq_integral_meas_lt f_intble f_nn]
apply integral_congr_ae
filter_upwards [meas_le_ae_eq_meas_lt μ (volume.restrict (Ioi 0)) f] with t ht
exact congrArg ENNReal.toReal ht.symm

lemma integral_eq_integral_Ioc_meas_le {f : α → ℝ} (f_nn : 0 ≤ᵐ[μ] f)
{M : ℝ} (f_bdd : f ≤ᵐ[μ] (fun _ ↦ M)) (f_intble : Integrable f μ) :
∫ ω, f ω ∂μ = ∫ t in Ioc 0 M, ENNReal.toReal (μ {a : α | t ≤ f a}) := by
rw [f_intble.integral_eq_integral_meas_le f_nn]
rw [set_integral_eq_of_subset_of_ae_diff_eq_zero
measurableSet_Ioi.nullMeasurableSet Ioc_subset_Ioi_self ?_]
apply eventually_of_forall (fun t ht ↦ ?_)
have htM : M < t := by simp_all only [mem_diff, mem_Ioi, mem_Ioc, not_and, not_le]
have obs : μ {a | M < f a} = 0 := by
rw [measure_zero_iff_ae_nmem]
filter_upwards [f_bdd] with a ha using not_lt.mpr ha
rw [ENNReal.toReal_eq_zero_iff]
exact Or.inl <| measure_mono_null (fun a ha ↦ lt_of_lt_of_le htM ha) obs

end LayercakeIntegral

end MeasureTheory