Skip to content

Commit 3f7a2ea

Browse files
committed
feat(MeasureTheory): aesop rules for strong measurability + measurability? tactic (#5427)
This PR adds aesop tags to a few lemmas pertaining to strong measurability, allowing to prove e.g. `StronglyMeasurable Real.log` using the `measurability` tactic. It also implements `measurability?` via `aesop?`. Co-authored-by: Frédéric Dupuis <31101893+dupuisf@users.noreply.github.com>
1 parent 0285b69 commit 3f7a2ea

File tree

7 files changed

+200
-54
lines changed

7 files changed

+200
-54
lines changed

Mathlib/MeasureTheory/Function/SpecialFunctions/Inner.lean

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,26 @@ variable [IsROrC 𝕜] [NormedAddCommGroup E] [InnerProductSpace 𝕜 E]
2222

2323
local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y
2424

25-
@[measurability]
25+
@[aesop safe 20 apply (rule_sets [Measurable])]
2626
theorem Measurable.inner {_ : MeasurableSpace α} [MeasurableSpace E] [OpensMeasurableSpace E]
2727
[TopologicalSpace.SecondCountableTopology E] {f g : α → E} (hf : Measurable f)
2828
(hg : Measurable g) : Measurable fun t => ⟪f t, g t⟫ :=
2929
Continuous.measurable2 continuous_inner hf hg
3030
#align measurable.inner Measurable.inner
3131

3232
@[measurability]
33+
theorem Measurable.const_inner {_ : MeasurableSpace α} [MeasurableSpace E] [OpensMeasurableSpace E]
34+
[TopologicalSpace.SecondCountableTopology E] {c : E} {f : α → E} (hf : Measurable f) :
35+
Measurable fun t => ⟪c, f t⟫ :=
36+
Measurable.inner measurable_const hf
37+
38+
@[measurability]
39+
theorem Measurable.inner_const {_ : MeasurableSpace α} [MeasurableSpace E] [OpensMeasurableSpace E]
40+
[TopologicalSpace.SecondCountableTopology E] {c : E} {f : α → E} (hf : Measurable f) :
41+
Measurable fun t => ⟪f t, c⟫ :=
42+
Measurable.inner hf measurable_const
43+
44+
@[aesop safe 20 apply (rule_sets [Measurable])]
3345
theorem AEMeasurable.inner {m : MeasurableSpace α} [MeasurableSpace E] [OpensMeasurableSpace E]
3446
[TopologicalSpace.SecondCountableTopology E] {μ : MeasureTheory.Measure α} {f g : α → E}
3547
(hf : AEMeasurable f μ) (hg : AEMeasurable g μ) : AEMeasurable (fun x => ⟪f x, g x⟫) μ := by
@@ -38,3 +50,19 @@ theorem AEMeasurable.inner {m : MeasurableSpace α} [MeasurableSpace E] [OpensMe
3850
dsimp only
3951
congr
4052
#align ae_measurable.inner AEMeasurable.inner
53+
54+
set_option linter.unusedVariables false in
55+
@[measurability]
56+
theorem AEMeasurable.const_inner {m : MeasurableSpace α} [MeasurableSpace E]
57+
[OpensMeasurableSpace E] [TopologicalSpace.SecondCountableTopology E]
58+
{μ : MeasureTheory.Measure α} {f : α → E} {c : E} (hf : AEMeasurable f μ) :
59+
AEMeasurable (fun x => ⟪c, f x⟫) μ :=
60+
AEMeasurable.inner aemeasurable_const hf
61+
62+
set_option linter.unusedVariables false in
63+
@[measurability]
64+
theorem AEMeasurable.inner_const {m : MeasurableSpace α} [MeasurableSpace E]
65+
[OpensMeasurableSpace E] [TopologicalSpace.SecondCountableTopology E]
66+
{μ : MeasureTheory.Measure α} {f : α → E} {c : E} (hf : AEMeasurable f μ) :
67+
AEMeasurable (fun x => ⟪f x, c⟫) μ :=
68+
AEMeasurable.inner hf aemeasurable_const

Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean

Lines changed: 95 additions & 29 deletions
Large diffs are not rendered by default.

Mathlib/MeasureTheory/Group/Arithmetic.lean

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,28 +133,28 @@ theorem AEMeasurable.mul_const [MeasurableMul M] (hf : AEMeasurable f μ) (c : M
133133
#align ae_measurable.mul_const AEMeasurable.mul_const
134134
#align ae_measurable.add_const AEMeasurable.add_const
135135

136-
@[to_additive (attr := measurability)]
136+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
137137
theorem Measurable.mul' [MeasurableMul₂ M] (hf : Measurable f) (hg : Measurable g) :
138138
Measurable (f * g) :=
139139
measurable_mul.comp (hf.prod_mk hg)
140140
#align measurable.mul' Measurable.mul'
141141
#align measurable.add' Measurable.add'
142142

143-
@[to_additive (attr := measurability)]
143+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
144144
theorem Measurable.mul [MeasurableMul₂ M] (hf : Measurable f) (hg : Measurable g) :
145145
Measurable fun a => f a * g a :=
146146
measurable_mul.comp (hf.prod_mk hg)
147147
#align measurable.mul Measurable.mul
148148
#align measurable.add Measurable.add
149149

150-
@[to_additive (attr := measurability)]
150+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
151151
theorem AEMeasurable.mul' [MeasurableMul₂ M] (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) :
152152
AEMeasurable (f * g) μ :=
153153
measurable_mul.comp_aemeasurable (hf.prod_mk hg)
154154
#align ae_measurable.mul' AEMeasurable.mul'
155155
#align ae_measurable.add' AEMeasurable.add'
156156

157-
@[to_additive (attr := measurability)]
157+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
158158
theorem AEMeasurable.mul [MeasurableMul₂ M] (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) :
159159
AEMeasurable (fun a => f a * g a) μ :=
160160
measurable_mul.comp_aemeasurable (hf.prod_mk hg)
@@ -216,12 +216,12 @@ section Pow
216216
variable {β γ α : Type _} [MeasurableSpace β] [MeasurableSpace γ] [Pow β γ] [MeasurablePow β γ]
217217
{m : MeasurableSpace α} {μ : Measure α} {f : α → β} {g : α → γ}
218218

219-
@[measurability]
219+
@[aesop safe 20 apply (rule_sets [Measurable])]
220220
theorem Measurable.pow (hf : Measurable f) (hg : Measurable g) : Measurable fun x => f x ^ g x :=
221221
measurable_pow.comp (hf.prod_mk hg)
222222
#align measurable.pow Measurable.pow
223223

224-
@[measurability]
224+
@[aesop safe 20 apply (rule_sets [Measurable])]
225225
theorem AEMeasurable.pow (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) :
226226
AEMeasurable (fun x => f x ^ g x) μ :=
227227
measurable_pow.comp_aemeasurable (hf.prod_mk hg)
@@ -326,28 +326,28 @@ theorem AEMeasurable.div_const [MeasurableDiv G] (hf : AEMeasurable f μ) (c : G
326326
#align ae_measurable.div_const AEMeasurable.div_const
327327
#align ae_measurable.sub_const AEMeasurable.sub_const
328328

329-
@[to_additive (attr := measurability)]
329+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
330330
theorem Measurable.div' [MeasurableDiv₂ G] (hf : Measurable f) (hg : Measurable g) :
331331
Measurable (f / g) :=
332332
measurable_div.comp (hf.prod_mk hg)
333333
#align measurable.div' Measurable.div'
334334
#align measurable.sub' Measurable.sub'
335335

336-
@[to_additive (attr := measurability)]
336+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
337337
theorem Measurable.div [MeasurableDiv₂ G] (hf : Measurable f) (hg : Measurable g) :
338338
Measurable fun a => f a / g a :=
339339
measurable_div.comp (hf.prod_mk hg)
340340
#align measurable.div Measurable.div
341341
#align measurable.sub Measurable.sub
342342

343-
@[to_additive (attr := measurability)]
343+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
344344
theorem AEMeasurable.div' [MeasurableDiv₂ G] (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) :
345345
AEMeasurable (f / g) μ :=
346346
measurable_div.comp_aemeasurable (hf.prod_mk hg)
347347
#align ae_measurable.div' AEMeasurable.div'
348348
#align ae_measurable.sub' AEMeasurable.sub'
349349

350-
@[to_additive (attr := measurability)]
350+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
351351
theorem AEMeasurable.div [MeasurableDiv₂ G] (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) :
352352
AEMeasurable (fun a => f a / g a) μ :=
353353
measurable_div.comp_aemeasurable (hf.prod_mk hg)
@@ -607,14 +607,14 @@ section SMul
607607
variable {M β α : Type _} [MeasurableSpace M] [MeasurableSpace β] [_root_.SMul M β]
608608
{m : MeasurableSpace α} {f : α → M} {g : α → β}
609609

610-
@[to_additive (attr := measurability)]
610+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
611611
theorem Measurable.smul [MeasurableSMul₂ M β] (hf : Measurable f) (hg : Measurable g) :
612612
Measurable fun x => f x • g x :=
613613
measurable_smul.comp (hf.prod_mk hg)
614614
#align measurable.smul Measurable.smul
615615
#align measurable.vadd Measurable.vadd
616616

617-
@[to_additive (attr := measurability)]
617+
@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable]))]
618618
theorem AEMeasurable.smul [MeasurableSMul₂ M β] {μ : Measure α} (hf : AEMeasurable f μ)
619619
(hg : AEMeasurable g μ) : AEMeasurable (fun x => f x • g x) μ :=
620620
MeasurableSMul₂.measurable_smul.comp_aemeasurable (hf.prod_mk hg)

Mathlib/MeasureTheory/MeasurableSpace.lean

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -842,18 +842,18 @@ theorem measurable_pi_iff {g : α → ∀ a, π a} : Measurable g ↔ ∀ a, Mea
842842
MeasurableSpace.comap_comp, Function.comp, iSup_le_iff]
843843
#align measurable_pi_iff measurable_pi_iff
844844

845-
@[measurability]
845+
@[aesop safe 100 apply (rule_sets [Measurable])]
846846
theorem measurable_pi_apply (a : δ) : Measurable fun f : ∀ a, π a => f a :=
847847
measurable_pi_iff.1 measurable_id a
848848
#align measurable_pi_apply measurable_pi_apply
849849

850-
@[measurability]
850+
@[aesop safe 100 apply (rule_sets [Measurable])]
851851
theorem Measurable.eval {a : δ} {g : α → ∀ a, π a} (hg : Measurable g) :
852852
Measurable fun x => g x a :=
853853
(measurable_pi_apply a).comp hg
854854
#align measurable.eval Measurable.eval
855855

856-
@[measurability]
856+
@[aesop safe 100 apply (rule_sets [Measurable])]
857857
theorem measurable_pi_lambda (f : α → ∀ a, π a) (hf : ∀ a, Measurable fun c => f c a) :
858858
Measurable f :=
859859
measurable_pi_iff.mpr hf

Mathlib/MeasureTheory/MeasurableSpaceDef.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ protected theorem Measurable.comp {_ : MeasurableSpace α} {_ : MeasurableSpace
557557
#align measurable.comp Measurable.comp
558558

559559
-- This is needed due to reducibility issues with the `measurability` tactic.
560-
@[measurability]
560+
@[aesop safe 50 (rule_sets [Measurable])]
561561
protected theorem Measurable.comp' {_ : MeasurableSpace α} {_ : MeasurableSpace β}
562562
{_ : MeasurableSpace γ} {g : β → γ} {f : α → β} (hg : Measurable g) (hf : Measurable f) :
563563
Measurable (fun x => g (f x)) := Measurable.comp hg hf

Mathlib/Tactic/Measurability.lean

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,21 @@ macro "measurability" : attr =>
2424

2525
/--
2626
The tactic `measurability` solves goals of the form `Measurable f`, `AEMeasurable f`,
27-
`AEStronglyMeasurable f μ`, or `MeasurableSet s` by applying lemmas tagged with the
28-
`measurability` user attribute. -/
27+
`StronglyMeasurable f`, `AEStronglyMeasurable f μ`, or `MeasurableSet s` by applying lemmas tagged
28+
with the `measurability` user attribute. -/
2929
macro "measurability" (config)? : tactic =>
3030
`(tactic| aesop (options := { terminal := true }) (rule_sets [$(Lean.mkIdent `Measurable):ident]))
3131

32-
-- Todo: implement `measurability?`, `measurability!` and `measurability!?` and add configuration,
32+
/--
33+
The tactic `measurability?` solves goals of the form `Measurable f`, `AEMeasurable f`,
34+
`StronglyMeasurable f`, `AEStronglyMeasurable f μ`, or `MeasurableSet s` by applying lemmas tagged
35+
with the `measurability` user attribute, and suggests a faster proof script that can be substituted
36+
for the tactic call in case of success. -/
37+
macro "measurability?" (config)? : tactic =>
38+
`(tactic| aesop? (options := { terminal := true })
39+
(rule_sets [$(Lean.mkIdent `Measurable):ident]))
40+
41+
-- Todo: implement `measurability!` and `measurability!?` and add configuration,
3342
-- original syntax was (same for the missing `measurability` variants):
3443
syntax (name := measurability!) "measurability!" (config)? : tactic
35-
syntax (name := measurability?) "measurability?" (config)? : tactic
3644
syntax (name := measurability!?) "measurability!?" (config)? : tactic

test/measurability.lean

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ Authors: Rémy Degenne
55
-/
66
import Mathlib.MeasureTheory.Tactic
77
import Mathlib.MeasureTheory.MeasurableSpace
8+
import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic
9+
import Mathlib.MeasureTheory.Function.SpecialFunctions.Basic
10+
import Mathlib.MeasureTheory.Function.SpecialFunctions.Inner
11+
import Mathlib.MeasureTheory.Function.StronglyMeasurable.Basic
12+
13+
open scoped BigOperators
14+
open MeasureTheory TopologicalSpace
815

916
variable {α β : Type _} [MeasurableSpace α] [MeasurableSpace β]
1017
{f g : α → β} {s₁ s₂ : Set α} {t₁ t₂ : Set β} {μ ν : MeasureTheory.Measure α}
@@ -37,7 +44,23 @@ example {ι} [Encodable ι] {S : ι → Set α} (hs : ∀ i, MeasurableSet (S i)
3744
example (hf : Measurable f) (hs₁ : MeasurableSet s₁) (ht₂ : MeasurableSet t₂) :
3845
MeasurableSet ((f ⁻¹' t₂) ∩ s₁) := by measurability
3946

40-
/- Porting note: TODO Uncomment these
47+
-- Strong measurability
48+
section strong_measurability
49+
50+
variable [TopologicalSpace β] [PseudoMetrizableSpace β] [BorelSpace β]
51+
52+
-- Test the use of apply_assumption to get (h i) from a hypothesis (h : ∀ i, ...).
53+
54+
example {F : ℕ → α → β} (hF : ∀ i, StronglyMeasurable (F i)) : Measurable (F 0) := by
55+
measurability
56+
57+
example [Zero β] {F : ℕ → α → β} (hF : ∀ i, AEFinStronglyMeasurable (F i) μ) :
58+
AEMeasurable (F 0) μ := by measurability
59+
60+
example {ι} [Encodable ι] {S₁ S₂ : ι → Set α} (hS₁ : ∀ i, MeasurableSet (S₁ i))
61+
(hS₂ : ∀ i, MeasurableSet (S₂ i)) : MeasurableSet (⋃ i, (S₁ i) ∪ (S₂ i)) := by measurability
62+
63+
end strong_measurability
4164

4265
/-- `ℝ` is a good test case because it verifies many assumptions, hence many lemmas apply and we
4366
are more likely to detect a bad lemma. In a previous version of the tactic, `measurability` got
@@ -56,10 +79,14 @@ example [Add β] [MeasurableAdd₂ β] (hf : Measurable f) (hg : AEMeasurable g
5679
AEMeasurable (fun x => f x + g x) μ := by measurability
5780

5881
example [Div β] [MeasurableDiv₂ β] (hf : Measurable f) (hg : Measurable g)
59-
(ht : MeasurableSet t₂): MeasurableSet ((fun x => f x / g x) ⁻¹' t₂) := by measurability
82+
(ht : MeasurableSet t₂) : MeasurableSet ((fun x => f x / g x) ⁻¹' t₂) := by measurability
6083

6184
example [AddCommMonoid β] [MeasurableAdd₂ β] {s : Finset ℕ} {F : ℕ → α → β}
62-
(hF : ∀ i, AEMeasurable (F i) μ) : AEMeasurable (∑ i in s, (λ x, F (i+1) x + F i x)) μ := by
85+
(hF : ∀ i, Measurable (F i)) : Measurable (∑ i in s, (fun x => F (i+1) x + F i x)) := by
86+
measurability
87+
88+
example [AddCommMonoid β] [MeasurableAdd₂ β] {s : Finset ℕ} {F : ℕ → α → β}
89+
(hF : ∀ i, AEMeasurable (F i) μ) : AEMeasurable (∑ i in s, (fun x => F (i+1) x + F i x)) μ := by
6390
measurability
6491

6592
-- even with many assumptions, the tactic is not trapped by a bad lemma
@@ -69,8 +96,25 @@ example [TopologicalSpace α] [BorelSpace α] [NormedAddCommGroup β] [BorelSpac
6996
measurability
7097

7198
example : Measurable (fun x : ℝ => Real.exp (2 * inner x 3)) := by measurability
72-
-/
99+
100+
example : StronglyMeasurable (fun x : ℝ => Real.exp (2 * inner x 3)) := by measurability
101+
102+
example {γ : MeasureTheory.Measure ℝ} :
103+
AEMeasurable (fun x : ℝ => Real.exp (2 * inner x 3)) γ := by measurability
104+
105+
example {γ : MeasureTheory.Measure ℝ} :
106+
AEStronglyMeasurable (fun x : ℝ => Real.exp (2 * inner x 3)) γ := by measurability
107+
108+
example {γ : MeasureTheory.Measure ℝ} [SigmaFinite γ] :
109+
FinStronglyMeasurable (fun x : ℝ => Real.exp (2 * inner x 3)) γ := by measurability
110+
111+
example {γ : MeasureTheory.Measure ℝ} [SigmaFinite γ] :
112+
AEFinStronglyMeasurable (fun x : ℝ => Real.exp (2 * inner x 3)) γ := by measurability
73113

74114
/-- An older version of the tactic failed in the presence of a negated hypothesis due to an
75115
internal call to `apply_assumption`. -/
76116
example {ι : Type _} (i k : ι) (hik : i ≠ k) : Measurable (id : α → α) := by measurability
117+
118+
--This search problem loops (StronglyMeasurable -> Measurable -> StronglyMeasurable) but fails
119+
--quickly nevertheless.
120+
--example (f : ℝ → ℝ) : StronglyMeasurable f := by measurability

0 commit comments

Comments
 (0)