Skip to content

Commit 51d732a

Browse files
committed
feat: use IndexedPartition.piecewise to create simple/measurable/strongly measurable functions (leanprover-community#32127)
The lemmas proved in this PR are needed in RemyDegenne/brownian-motion#304.
1 parent 76468a8 commit 51d732a

4 files changed

Lines changed: 151 additions & 14 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5009,6 +5009,7 @@ public import Mathlib.MeasureTheory.Function.LpSpace.ContinuousFunctions
50095009
public import Mathlib.MeasureTheory.Function.LpSpace.DomAct.Basic
50105010
public import Mathlib.MeasureTheory.Function.LpSpace.DomAct.Continuous
50115011
public import Mathlib.MeasureTheory.Function.LpSpace.Indicator
5012+
public import Mathlib.MeasureTheory.Function.Piecewise
50125013
public import Mathlib.MeasureTheory.Function.SimpleFunc
50135014
public import Mathlib.MeasureTheory.Function.SimpleFuncDense
50145015
public import Mathlib.MeasureTheory.Function.SimpleFuncDenseLp

Mathlib/Data/Setoid/Partition.lean

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -443,11 +443,12 @@ lemma piecewise_apply {β : Type*} {f : ι → α → β} (x : α) : hs.piecewis
443443

444444
open Function
445445

446+
variable {β : Type*} {f : ι → α → β}
447+
446448
/-- A family of injective functions with pairwise disjoint
447449
domains and pairwise disjoint ranges can be glued together
448450
to form an injective function. -/
449-
theorem piecewise_inj {β : Type*} {f : ι → α → β}
450-
(h_injOn : ∀ i, InjOn (f i) (s i))
451+
theorem piecewise_inj (h_injOn : ∀ i, InjOn (f i) (s i))
451452
(h_disjoint : PairwiseDisjoint (univ : Set ι) fun i => (f i) '' (s i)) :
452453
Injective (piecewise hs f) := by
453454
intro x y h
@@ -461,23 +462,64 @@ theorem piecewise_inj {β : Type*} {f : ι → α → β}
461462
/-- A family of bijective functions with pairwise disjoint
462463
domains and pairwise disjoint ranges can be glued together
463464
to form a bijective function. -/
464-
theorem piecewise_bij {β : Type*} {f : ι → α → β}
465-
{t : ι → Set β} (ht : IndexedPartition t)
465+
theorem piecewise_bij {t : ι → Set β} (ht : IndexedPartition t)
466466
(hf : ∀ i, BijOn (f i) (s i) (t i)) :
467467
Bijective (piecewise hs f) := by
468468
set g := piecewise hs f with hg
469-
have hg_bij : ∀ i, BijOn g (s i) (t i) := by
470-
intro i
471-
refine BijOn.congr (hf i) ?_
472-
intro x hx
469+
have hg_bij (i) : BijOn g (s i) (t i) := by
470+
refine (hf i).congr fun x hx => ?_
473471
rw [hg, piecewise_apply, hs.mem_iff_index_eq.mp hx]
474472
have hg_inj : InjOn g (⋃ i, s i) := by
475-
refine injOn_of_injective ?_
476-
refine piecewise_inj hs (fun i ↦ BijOn.injOn (hf i)) ?h_disjoint
473+
refine injOn_of_injective (piecewise_inj hs (fun i ↦ BijOn.injOn (hf i)) ?_)
477474
simp only [fun i ↦ BijOn.image_eq (hf i)]
478475
rintro i - j - hij
479476
exact ht.disjoint hij
480477
rw [← bijOn_univ, ← hs.iUnion, ← ht.iUnion]
481478
exact bijOn_iUnion hg_bij hg_inj
482479

480+
theorem piecewise_preimage (f : ι → α → β) (t : Set β) :
481+
hs.piecewise f ⁻¹' t = ⋃ i, s i ∩ (f i ⁻¹' t) := by
482+
refine ext fun x => ⟨fun hx => ?_, fun ⟨a, ⟨i, hi⟩, ha⟩ => ?_⟩
483+
· rw [mem_preimage, piecewise_apply, ← mem_preimage] at hx
484+
exact mem_iUnion_of_mem (hs.index x) (mem_inter (hs.mem_index x) hx)
485+
· rw [← hi, ← (mem_iff_index_eq hs).mp ha.1] at ha
486+
simp_all [piecewise_apply]
487+
488+
theorem range_piecewise (f : ι → α → β) : range (hs.piecewise f) = ⋃ i, f i '' s i := by
489+
refine ext fun x => ⟨?_, fun ⟨t, ⟨i, hi⟩, ht⟩ ↦ ?_⟩
490+
· rintro ⟨x, rfl⟩
491+
exact mem_iUnion_of_mem (hs.index x) ⟨x, hs.mem_index x, rfl⟩
492+
· simp only [← hi, mem_image] at ht
493+
obtain ⟨a, ha1, ha2⟩ := ht
494+
refine ⟨a, ?_⟩
495+
simp only [hs.mem_iff_index_eq] at ha1
496+
simpa [hs.mem_iff_index_eq, ← ha1] using ha2
497+
498+
theorem range_piecewise_subset (f : ι → α → β) : range (hs.piecewise f) ⊆ ⋃ i, range (f i) :=
499+
fun x ⟨y, hy⟩ => by simpa [IndexedPartition.piecewise_apply] using ⟨hs.index y, y, hy⟩
500+
501+
/-- Given a collections of sets `s : ι → Set α` that forms an indexed partition, we can group
502+
some of the sets to obtain a coarser partition. -/
503+
noncomputable def coarserPartition (hs : IndexedPartition s) {κ : Type*} (g : ι → κ)
504+
(hg : g.Surjective) :
505+
IndexedPartition (fun k : κ => ⋃ i ∈ g ⁻¹' {k}, s i) where
506+
eq_of_mem {_x _i _j} hxi hxj := by
507+
obtain ⟨a, ⟨c, hc⟩, ha⟩ := hxi
508+
obtain ⟨b, ⟨d, hd⟩, hb⟩ := hxj
509+
simp only [← hc, mem_iUnion] at ha
510+
simp only [← hd, mem_iUnion] at hb
511+
have : c = d := hs.eq_of_mem ha.2 hb.2
512+
by_contra!
513+
have : c ≠ d := disjoint_iff_forall_ne.mp ((disjoint_singleton.mpr this).preimage g) ha.1 hb.1
514+
grind
515+
some k := hs.some ((singleton_nonempty k).preimage hg).some
516+
some_mem k := by
517+
refine mem_iUnion_of_mem ((singleton_nonempty k).preimage hg).some ?_
518+
simp only [mem_preimage, mem_singleton_iff, mem_iUnion, exists_prop]
519+
constructor
520+
· simpa using ((singleton_nonempty k).preimage hg).some_mem
521+
· exact hs.some_mem ((singleton_nonempty k).preimage hg).some
522+
index x := g (hs.index x)
523+
mem_index x := mem_iUnion_of_mem (hs.index x) (by simp [hs.mem_index])
524+
483525
end IndexedPartition
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/-
2+
Copyright (c) 2026 Yongxi Lin. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yongxi Lin
5+
-/
6+
module
7+
8+
public import Mathlib.Data.Setoid.Partition
9+
public import Mathlib.MeasureTheory.Function.StronglyMeasurable.AEStronglyMeasurable
10+
11+
/-!
12+
# Measurability of piecewise functions
13+
14+
In this file, we prove some results about measurability of functions defined by using
15+
`IndexedPartition.piecewise`.
16+
17+
-/
18+
19+
@[expose] public section
20+
21+
open MeasureTheory Set Filter
22+
23+
namespace IndexedPartition
24+
25+
variable {ι α β : Type*} [MeasurableSpace α] {s : ι → Set α} {f : ι → α → β}
26+
27+
@[fun_prop]
28+
theorem measurable_piecewise [MeasurableSpace β] [Countable ι]
29+
(hs : IndexedPartition s) (hm : ∀ i, MeasurableSet (s i)) (hf : ∀ i, Measurable (f i)) :
30+
Measurable (hs.piecewise f) :=
31+
fun t ht => by simpa [piecewise_preimage] using .iUnion (fun i => (hm i).inter ((hf i) ht))
32+
33+
@[fun_prop]
34+
theorem aemeasurable_piecewise {μ : Measure α} [MeasurableSpace β] [Countable ι]
35+
(hs : IndexedPartition s) (hm : ∀ i, MeasurableSet (s i)) (hf : ∀ i, AEMeasurable (f i) μ) :
36+
AEMeasurable (hs.piecewise f) μ := by
37+
choose p hp hq using hf
38+
refine ⟨hs.piecewise p, hs.measurable_piecewise hm hp, ?_⟩
39+
filter_upwards [ae_all_iff.2 hq] with x hx using hx (hs.index x)
40+
41+
/-- This is the analogue of `SimpleFunc.piecewise` for `IndexedPartition`. -/
42+
def simpleFunc_piecewise [Finite ι] (hs : IndexedPartition s)
43+
(hm : ∀ i, MeasurableSet (s i)) (f : ι → SimpleFunc α β) : SimpleFunc α β where
44+
toFun := hs.piecewise (fun i => f i)
45+
measurableSet_fiber' := fun _ =>
46+
letI : MeasurableSpace β := ⊤
47+
hs.measurable_piecewise hm (fun i => (f i).measurable) trivial
48+
finite_range' := (finite_iUnion (fun i => (f i).finite_range)).subset
49+
(hs.range_piecewise_subset _)
50+
51+
@[fun_prop]
52+
theorem stronglyMeasurable_piecewise [Countable ι] (hs : IndexedPartition s)
53+
(hm : ∀ i, MeasurableSet (s i)) [TopologicalSpace β] (hf : ∀ i, StronglyMeasurable (f i)) :
54+
StronglyMeasurable (hs.piecewise f) := by
55+
by_cases Fi : Finite ι
56+
· refine ⟨fun n => simpleFunc_piecewise hs hm (fun i => (hf i).approx n), fun x => ?_⟩
57+
simp [simpleFunc_piecewise, piecewise_apply, StronglyMeasurable.tendsto_approx]
58+
simp only [not_finite_iff_infinite] at Fi
59+
obtain ⟨e, -⟩ := exists_true_iff_nonempty.mpr (nonempty_equiv_of_countable (α := ℕ) (β := ι))
60+
classical
61+
let g (n : ℕ) (i : ι) : Fin (n + 1) :=
62+
if hi : ∃ m < n, i = e m then ⟨hi.choose, by grind⟩ else Fin.last n
63+
have sg (n : ℕ) : (g n).Surjective := by
64+
intro b
65+
unfold g
66+
refine ⟨e b, ?_⟩
67+
by_cases hb : b < n
68+
· have : ∃ m < n, e b = e m := ⟨b, ⟨hb, rfl⟩⟩
69+
simpa only [this, Fin.ext_iff] using e.injective this.choose_spec.2.symm
70+
· simp [hb]
71+
grind
72+
have G (n : ℕ) := hs.coarserPartition (g n) (sg n)
73+
refine ⟨fun n => (G n).simpleFunc_piecewise (fun i => ?_) (fun i => (hf (e i)).approx n),
74+
fun x => ?_⟩
75+
· exact .biUnion (to_countable _) fun _ _ ↦ hm _
76+
simp only [simpleFunc_piecewise, SimpleFunc.coe_mk, piecewise_apply]
77+
have : ∀ᶠ n in atTop, e ((G n).index x) = hs.index x := by
78+
obtain ⟨y, hy⟩ := e.bijective.2 (hs.index x)
79+
refine eventually_atTop.mpr ⟨y + 1, fun b hb => ?_⟩
80+
have : y = (⟨y, by lia⟩ : Fin (b + 1)).1 := rfl
81+
rw [← hy, EmbeddingLike.apply_eq_iff_eq, this, ← Fin.ext_iff, ← (G b).mem_iff_index_eq]
82+
have : ∃ m < b, hs.index x = e m := ⟨y, ⟨by lia, hy.symm⟩⟩
83+
simpa [g, hs.mem_iff_index_eq, this] using e.injective (hy.trans this.choose_spec.2).symm
84+
have : ∀ᶠ n in atTop, (hf (hs.index x)).approx n x = (hf (e ((G n).index x))).approx n x := by
85+
filter_upwards [this] with n hn using by rw [hn]
86+
exact (Filter.tendsto_congr' this).mp (by simp [StronglyMeasurable.tendsto_approx])
87+
88+
@[fun_prop]
89+
theorem aestronglyMeasurable_piecewise {μ : Measure α} [Countable ι] (hs : IndexedPartition s)
90+
(hm : ∀ i, MeasurableSet (s i)) [TopologicalSpace β] (hf : ∀ i, AEStronglyMeasurable (f i) μ) :
91+
AEStronglyMeasurable (hs.piecewise f) μ := by
92+
choose p hp hq using hf
93+
refine ⟨hs.piecewise p, hs.stronglyMeasurable_piecewise hm hp, ?_⟩
94+
filter_upwards [ae_all_iff.2 hq] with x hx using hx (hs.index x)
95+
96+
end IndexedPartition

Mathlib/MeasureTheory/MeasurableSpace/Basic.lean

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,8 @@ protected theorem MeasurableSet.preimage {t : Set β} (ht : MeasurableSet t) (hf
293293

294294
@[fun_prop]
295295
protected theorem Measurable.piecewise {_ : DecidablePred (· ∈ s)} (hs : MeasurableSet s)
296-
(hf : Measurable f) (hg : Measurable g) : Measurable (piecewise s f g) := by
297-
intro t ht
298-
rw [piecewise_preimage]
299-
exact hs.ite (hf ht) (hg ht)
296+
(hf : Measurable f) (hg : Measurable g) : Measurable (piecewise s f g) :=
297+
fun t ht => by simpa [piecewise_preimage] using hs.ite (hf ht) (hg ht)
300298

301299
/-- This is slightly different from `Measurable.piecewise`. It can be used to show
302300
`Measurable (ite (x=0) 0 1)` by

0 commit comments

Comments
 (0)