Skip to content

Commit 404116c

Browse files
committed
pointwise birkhoff theorem
1 parent 160dbc2 commit 404116c

7 files changed

Lines changed: 231 additions & 19 deletions

File tree

Mathlib/Analysis/Oscillation.lean

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public import Mathlib.Topology.EMetricSpace.Diam
1111
public import Mathlib.Topology.EMetricSpace.Lipschitz
1212
public import Mathlib.Topology.UniformSpace.Cauchy
1313
public import Mathlib.Analysis.Normed.Group.Uniform
14+
public import Mathlib.Order.LiminfLimsup
1415
import Mathlib.Tactic.Scratchpad
1516

1617
/-!
@@ -42,6 +43,9 @@ variable {E : Type u} {F : Type v} [PseudoEMetricSpace F]
4243
noncomputable def oscillation (f : E → F) (l : Filter E) : ENNReal :=
4344
⨅ S ∈ l.map f, ediam S
4445

46+
theorem oscillation_le_ediam_range {f : E → F} {l} : oscillation f l ≤ ediam (range f) :=
47+
iInf_le_of_le (range f) (by simp)
48+
4549
/-- The oscillation of `f : E → F` at `x`. -/
4650
noncomputable abbrev oscillationAt [TopologicalSpace E] (f : E → F) (x : E) : ENNReal :=
4751
oscillation f (𝓝 x)
@@ -209,6 +213,14 @@ lemma mul_biInf {p : ι → Prop} (hp : ∃ i, p i) {a : ℝ≥0∞} {f : ι →
209213
simp_rw [iInf_subtype, Subtype.exists] at this
210214
exact this hinfty
211215

216+
@[to_dual iInf₂_eq_of_forall_ge_of_forall_gt_exists_lt]
217+
theorem iSup₂_eq_of_forall_le_of_forall_lt_exists_gt [CompleteLattice α] {b : α}
218+
(h₁ : ∀ i j, f i j ≤ b) (h₂ : ∀ w, w < b → ∃ i j, w < f i j) : ⨆ (i) (j), f i j = b := by
219+
have := iSup_eq_of_forall_le_of_forall_lt_exists_gt
220+
(f := fun (ij : PSigma κ) ↦ f ij.1 ij.2) (b := b)
221+
simp_rw [PSigma.forall, PSigma.exists, iSup_psigma] at this
222+
exact this h₁ h₂
223+
212224
end MoveMe
213225

214226
section Cauchy
@@ -266,8 +278,8 @@ theorem LipschitzWith.oscillation_comp₂_le (g : α → β → γ) (f₁ : E
266278
change_set _ ≤ (?a + ?b : ℝ≥0∞)
267279
by_cases! ha : a = ∞; · simp [ha]
268280
by_cases! hb : b = ∞; · simp [hb]
269-
apply ENNReal.le_of_forall_pos_le_add
270-
intro ε hε hfin
281+
apply _root_.le_of_forall_pos_le_add
282+
intro ε hε
271283
rcases iInf₂_le_iff_forall_lt (l := a) |>.mp le_rfl (a + ε / 2)
272284
(lt_add_right ha (by norm_num [hε.ne'])) with ⟨sa, hsa, hsa'⟩
273285
rcases iInf₂_le_iff_forall_lt (l := b) |>.mp le_rfl (b + ε / 2)
@@ -297,4 +309,20 @@ theorem oscillation_mul_le (f₁ : E → F) (f₂ : E → F) (l : Filter E) :
297309
(fun _ => (isometry_mul_left _).lipschitz)
298310
|>.trans_eq (by simp only [coe_one, one_mul])
299311

312+
@[to_additive]
313+
theorem oscillation_le_add_div (f₁ : E → F) (f₂ : E → F) (l : Filter E) :
314+
oscillation f₁ l ≤ oscillation f₂ l + oscillation (f₁ / f₂) l := by
315+
nth_rw 1 [show f₁ = f₂ * (f₁ / f₂) by simp]
316+
exact oscillation_mul_le ..
317+
318+
@[to_additive oscillation_le_two_mul_iSup_enorm]
319+
theorem oscillation_le_two_mul_iSup_enorm' (f : E → F) (l : Filter E) :
320+
oscillation f l ≤ 2 * iSup (‖f ·‖ₑ) := by
321+
apply oscillation_le_ediam_range.trans
322+
refine ediam_le fun x hx y hy => ?_
323+
rw [edist_eq_enorm_div x y, two_mul]
324+
apply enorm_div_le.trans <| add_le_add _ _
325+
· exact hx.out.elim fun z hz ↦ hz ▸ le_iSup (‖f ·‖ₑ) ..
326+
· exact hy.out.elim fun z hz ↦ hz ▸ le_iSup (‖f ·‖ₑ) ..
327+
300328
end SeminormedAddCommGroup

Mathlib/Dynamics/BirkhoffSum/Average.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module
77

88
public import Mathlib.Dynamics.BirkhoffSum.Basic
99
public import Mathlib.Algebra.Module.Basic
10+
public import Mathlib.Analysis.Normed.Group.Defs
1011

1112
/-!
1213
# Birkhoff average

Mathlib/Dynamics/BirkhoffSum/Maximal.lean

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import Mathlib.Analysis.InnerProductSpace.Basic
1313
import Mathlib.Analysis.RCLike.Lemmas
1414
import Mathlib.Data.Real.StarOrdered
1515
public import Mathlib.Dynamics.BirkhoffSum.Average
16-
import Mathlib.Dynamics.BirkhoffSum.Measurable
17-
import Mathlib.Dynamics.BirkhoffSum.Integrable
16+
public import Mathlib.Dynamics.BirkhoffSum.Measurable
17+
public import Mathlib.Dynamics.BirkhoffSum.Integrable
1818

1919
/-!
2020
# Maximal ergodic theorem.
@@ -93,14 +93,14 @@ variable [MeasurableSpace α] (μ : Measure α := by volume_tac) (hf : MeasurePr
9393
include hf
9494

9595
@[fun_prop]
96-
lemma birkhoffMax_aestronglyMeasurable (hg : AEStronglyMeasurable g μ) :
96+
public lemma birkhoffMax_aestronglyMeasurable (hg : AEStronglyMeasurable g μ) :
9797
AEStronglyMeasurable (birkhoffMax f g n) μ := by
9898
unfold birkhoffMax
9999
induction n <;> measurability
100100

101101
include hg
102102

103-
lemma birkhoffMax_integrable : Integrable (birkhoffMax f g n) μ := by
103+
public lemma birkhoffMax_integrable : Integrable (birkhoffMax f g n) μ := by
104104
unfold birkhoffMax
105105
induction n with
106106
| zero => exact integrable_zero ..
@@ -192,8 +192,7 @@ theorem lt_birkhoffAverageSup_iff_lt_birkhoffSumSup {a : ℝ} (ha : 0 < a) :
192192

193193
section MeasurePreserving
194194

195-
variable {f : α → α} [MeasurableSpace α] (μ : Measure α := by volume_tac)
196-
(hf : MeasurePreserving f μ μ)
195+
variable [MeasurableSpace α] (μ : Measure α := by volume_tac) (hf : MeasurePreserving f μ μ)
197196

198197
include hf
199198

@@ -243,14 +242,14 @@ end Real
243242

244243
section NormedAddCommGroup
245244

246-
variable {E : Type*} [NormedAddCommGroup E] {g : α → E} (hg : Integrable g μ) [IsFiniteMeasure μ]
245+
variable [NormedAddCommGroup M] {g : α → M} (hg : Integrable g μ) [IsFiniteMeasure μ]
247246

248247
include hg
249248

250249
/-- Maximal ergodic theorem: the operator `birkhoffAverageSup` satisfies a weak-type inequality. -/
251250
public theorem iSup_distribution_birkhoffAverageSup_le_norm :
252-
a : ℝ, a * μ.real {x | a < birkhoffAverageSup f (‖g ·‖) x} ≤ ∫ x, ‖g x‖ ∂μ := by
253-
refine ciSup_le fun a ↦ ?_
251+
a : ℝ, a * μ.real {x | a < birkhoffAverageSup f (‖g ·‖) x} ≤ ∫ x, ‖g x‖ ∂μ := by
252+
intro a
254253
by_cases! ha : 0 < a; swap
255254
· apply mul_nonpos_of_nonpos_of_nonneg ha measureReal_nonneg |>.trans
256255
exact integral_nonneg (fun _ ↦ norm_nonneg _)

Mathlib/Dynamics/BirkhoffSum/NormedSpace.lean

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,27 @@ theorem tendsto_birkhoffAverage_apply_sub_birkhoffAverage' {g : α → E}
9898
Tendsto (fun n ↦ birkhoffAverage 𝕜 f g n (f x) - birkhoffAverage 𝕜 f g n x) atTop (𝓝 0) :=
9999
tendsto_birkhoffAverage_apply_sub_birkhoffAverage _ <| h.subset <| range_comp_subset_range _ _
100100

101+
section TriangleInequality
102+
103+
variable {f : α → α} {g : α → E} {n : ℕ} {x : α}
104+
105+
@[bound]
106+
lemma norm_birkhoffSum_le :
107+
‖birkhoffSum f g n x‖ ≤ birkhoffSum f (‖g ·‖) n x :=
108+
norm_sum_le _ _
109+
110+
@[bound]
111+
lemma norm_birkhoffAverage_le [NormedSpace ℝ E] :
112+
‖birkhoffAverage ℝ f g n x‖ ≤ birkhoffAverage ℝ f (‖g ·‖) n x := by
113+
by_cases! h : n = 0
114+
· simp [birkhoffAverage, h]
115+
apply Nat.zero_lt_of_ne_zero at h
116+
simp only [birkhoffAverage, norm_smul, norm_inv, RCLike.norm_natCast, smul_eq_mul]
117+
gcongr
118+
exact norm_birkhoffSum_le
119+
120+
end TriangleInequality
121+
101122
end
102123

103124
variable (𝕜 : Type*) {X E : Type*}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/-
2+
Copyright (c) 2025 Lua Viana Reis. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Lua Viana Reis
5+
-/
6+
module
7+
8+
import Mathlib.Analysis.Oscillation
9+
import Mathlib.Dynamics.BirkhoffSum.Maximal
10+
import Mathlib.Tactic.Scratchpad
11+
import Mathlib.Dynamics.BirkhoffSum.NormedSpace
12+
13+
open MeasureTheory Measure MeasurableSpace Filter Topology
14+
15+
variable {α M : Type*} {f : α → α} {g : α → M} {n : ℕ}
16+
17+
variable [MeasurableSpace α] (μ : Measure α) (hf : MeasurePreserving f μ μ)
18+
19+
variable [NormedAddCommGroup M] (hg : Integrable g μ) [IsFiniteMeasure μ] [NormedSpace ℝ M]
20+
21+
variable (M f) in
22+
def convergenceSet :=
23+
{g : Lp M 1 μ | ∀ᵐ x ∂μ, oscillation (birkhoffAverage ℝ f g · x) atTop = 0}
24+
25+
open scoped NNReal ENNReal
26+
27+
theorem ENNReal.forall_pos_of_forall_nat_mul {motive : ℝ≥0∞ → Prop} (k : ℝ≥0∞)
28+
(h : ∀ ε > 0, motive (k * ε)) (hk₀ : k ≠ 0 := by positivity) (hk : k ≠ ∞ := by finiteness) :
29+
∀ ε > 0, motive ε := fun ε hε ↦
30+
ENNReal.mul_div_cancel (a := k) (b := ε) hk₀ hk ▸ h (ε / k) (ENNReal.div_pos hε.ne_zero hk)
31+
32+
omit [IsFiniteMeasure μ] in
33+
lemma foo {f : α → ℝ≥0∞} (h : ∀ ε > 0, ∀ᵐ x ∂μ, f x ≤ ε) : ∀ᵐ x ∂μ, f x ≤ 0 := by
34+
have H : ∀ᵐ x ∂μ, ∀ n : ℕ, f x ≤ (n : ℝ≥0∞)⁻¹ :=
35+
ae_all_iff.mpr fun n => h _ (ENNReal.inv_pos.mpr (by finiteness))
36+
filter_upwards [H] with x hx
37+
refine le_of_forall_pos_le_add fun ε hε => ?_
38+
obtain ⟨n, hn⟩ := ENNReal.exists_inv_nat_lt hε.ne_zero
39+
exact (hx n).trans (by simp [hn.le])
40+
41+
theorem EReal.coe_ennreal_iSup {ι : Sort*} [hι : Nonempty ι] (f : ι → ℝ≥0∞) :
42+
((⨆ i, f i : ℝ≥0∞) : EReal) = ⨆ i, (f i : EReal) := by
43+
refine le_antisymm ?_ (iSup_le fun i ↦ mod_cast le_iSup f i)
44+
refine le_iSup_iff.mpr fun b hb ↦ ?_
45+
have h0 : 0 ≤ b := hι.elim fun i ↦ (EReal.coe_ennreal_nonneg _).trans (hb i)
46+
obtain ⟨c, rfl⟩ : ∃ c : ℝ≥0∞, (c : EReal) = b := ⟨b.toENNReal, EReal.coe_toENNReal h0⟩
47+
exact mod_cast iSup_le fun i ↦ mod_cast hb i
48+
49+
include hf in
50+
theorem closed_convergenceSet : IsClosed (convergenceSet M f μ) := by
51+
refine isClosed_of_closure_subset (fun g hg ↦ ?_)
52+
rw [EMetric.mem_closure_iff] at hg
53+
simp only [convergenceSet, ← nonpos_iff_eq_zero, Set.mem_setOf_eq]
54+
apply foo
55+
refine ENNReal.forall_pos_of_forall_nat_mul 2 fun δ hδ ↦ ?_
56+
apply ae_iff.mpr <| nonpos_iff_eq_zero.mp _
57+
push Not
58+
have (h : Lp M 1 μ) (hh : h ∈ convergenceSet M f μ) :
59+
∀ᵐ x ∂μ, 2 * δ < oscillation (birkhoffAverage ℝ f ⇑g · x) atTop →
60+
δ < birkhoffAverageSup f (‖(⇑g - ⇑h) ·‖) x := by
61+
filter_upwards [hh] with x hosc hx
62+
have := hx.trans_le <| oscillation_le_add_sub (f₂ := (birkhoffAverage ℝ f h · x)) ..
63+
rw [hosc] at this
64+
grw [oscillation_le_two_mul_iSup_enorm] at this
65+
simp [ENNReal.mul_lt_mul_iff_right] at this
66+
change _ < ⨆ n, ‖(birkhoffAverage ℝ f g - _) n x‖ₑ at this
67+
rw [← birkhoffAverage_sub] at this
68+
simp_rw [←ofReal_norm, ←EReal.coe_ennreal_lt_coe_ennreal_iff] at this
69+
simp_rw [EReal.coe_ennreal_iSup, EReal.coe_ennreal_ofReal, max_eq_left (norm_nonneg _)] at this
70+
exact this.trans_le (iSup_mono fun _ ↦ EReal.coe_le_coe norm_birkhoffAverage_le)
71+
refine le_of_forall_gt fun c hc ↦ ?_
72+
73+
apply measure_mono_ae (this _)
74+
75+
76+
done
77+
78+
/- simp only [convergenceSet, ← nonpos_iff_eq_zero, Set.mem_setOf_eq]
79+
apply foo
80+
refine ENNReal.forall_pos_of_forall_nat_mul 2 fun δ hδ ↦ ?_
81+
rcases hg δ hδ with ⟨h, hh, hh'⟩
82+
filter_upwards [hh] with x hx
83+
apply le_of_forall_pos_le_add
84+
refine ENNReal.forall_pos_of_forall_nat_mul 2 fun ε hε ↦ ?_
85+
apply oscillation_le_add_sub (f₂ := (birkhoffAverage ℝ f h · x)) .. |>.trans
86+
change _ + oscillation ((birkhoffAverage ℝ f g - birkhoffAverage ℝ f h) · x) _ ≤ _
87+
rw [←birkhoffAverage_sub, hx, zero_add, ←mul_add]
88+
apply oscillation_le_two_mul_norm_max _ _ |>.trans
89+
gcongr
90+
simp_rw [←ofReal_norm]
91+
apply (iSup_mono fun _ ↦ ENNReal.ofReal_le_ofReal norm_birkhoffAverage_le).trans
92+
apply EReal.coe_ennreal_le_coe_ennreal_iff.mp
93+
simp only [Pi.sub_apply, EReal.coe_ennreal_iSup, EReal.coe_ennreal_ofReal, EReal.coe_max,
94+
EReal.coe_zero, EReal.coe_ennreal_add, iSup_le_iff, sup_le_iff]
95+
push ∀ _, _
96+
rw [← iSup_le_iff, ← birkhoffAverageSup]
97+
98+
99+
push_cast
100+
simp
101+
-- apply iSup_le_iff.mpr
102+
-- intro i
103+
done
104+
-/

Mathlib/Order/LiminfLimsup.lean

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -815,17 +815,17 @@ section ConditionallyCompleteLinearOrder
815815
variable [ConditionallyCompleteLinearOrder α]
816816

817817
/-- If `Filter.limsup u atTop ≤ x`, then for all `ε > 0`, eventually we have `u b < x + ε`. -/
818-
theorem eventually_lt_add_pos_of_limsup_le [Preorder β] [AddZeroClass α] [AddLeftStrictMono α]
819-
{x ε : α} {u : β → α} (hu_bdd : IsBoundedUnder LE.le atTop u) (hu : Filter.limsup u atTop ≤ x)
820-
(hε : 0 < ε) :
821-
∀ᶠ b : β in atTop, u b < x + ε :=
818+
theorem eventually_lt_add_pos_of_limsup_le [AddZeroClass α] [AddLeftStrictMono α]
819+
{x ε : α} {u : β → α} {f : Filter β} (hu_bdd : IsBoundedUnder LE.le f u)
820+
(hu : Filter.limsup u f ≤ x) (hε : 0 < ε) :
821+
∀ᶠ b : β in f, u b < x + ε :=
822822
eventually_lt_of_limsup_lt (lt_of_le_of_lt hu (lt_add_of_pos_right x hε)) hu_bdd
823823

824824
/-- If `x ≤ Filter.liminf u atTop`, then for all `ε < 0`, eventually we have `x + ε < u b`. -/
825-
theorem eventually_add_neg_lt_of_le_liminf [Preorder β] [AddZeroClass α] [AddLeftStrictMono α]
826-
{x ε : α} {u : β → α} (hu_bdd : IsBoundedUnder GE.ge atTop u) (hu : x ≤ Filter.liminf u atTop)
827-
(hε : ε < 0) :
828-
∀ᶠ b : β in atTop, x + ε < u b :=
825+
theorem eventually_add_neg_lt_of_le_liminf [AddZeroClass α] [AddLeftStrictMono α]
826+
{x ε : α} {u : β → α} {f : Filter β} (hu_bdd : IsBoundedUnder GE.ge f u)
827+
(hu : x ≤ Filter.liminf u f) (hε : ε < 0) :
828+
∀ᶠ b : β in f, x + ε < u b :=
829829
eventually_lt_of_lt_liminf (lt_of_lt_of_le (add_lt_of_neg_right x hε) hu) hu_bdd
830830

831831
/-- If `Filter.limsup u atTop ≤ x`, then for all `ε > 0`, there exists a positive natural

Mathlib/Tactic/Scratchpad.lean

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module
22

33
public import Mathlib.Tactic.Set
4+
public import Lean.Meta.Tactic.TryThis
5+
public import Lean.Meta.Tactic.ExposeNames
46

57
set_option trace.debug true
68
set_option pp.rawOnError true
@@ -42,3 +44,60 @@ example : (fun x => x + 1) 0 = 1 + 0 := by
4244
change_set ?a + 1 = ?b
4345

4446
rfl
47+
48+
49+
open Lean Elab Meta Tactic
50+
open Lean.Meta.Tactic.TryThis
51+
52+
namespace MakeHave
53+
54+
private meta partial def leadingIndent (source : String) (pos : String.Pos.Raw) : String :=
55+
let rec go (i : String.Pos.Raw) : String.Pos.Raw :=
56+
if i.atEnd source then
57+
i
58+
else
59+
let c := i.get source
60+
if c == ' ' || c == '\t' then
61+
go (i.next source)
62+
else
63+
i
64+
String.Pos.Raw.extract source pos (go pos)
65+
66+
private meta def insertHaveSuggestion (ref : Syntax) : TacticM Unit := do
67+
let some refRange := ref.getRange?
68+
| return
69+
let target ← instantiateMVars (← getMainTarget)
70+
let targetFmt ← withOptions (pp.mvars.set · false) <| withExposedNames <|
71+
PrettyPrinter.ppExpr target
72+
let targetText := targetFmt.pretty 100000
73+
let fileMap ← getFileMap
74+
let lineStart := fileMap.lineStart (fileMap.toPosition refRange.start).line
75+
let indent := leadingIndent fileMap.source lineStart
76+
let newText := s!"{indent}have : {targetText} := sorry\n"
77+
let insertionRange : Syntax.Range := ⟨lineStart, lineStart⟩
78+
let title := "Insert `have` for current goal"
79+
let suggestion : Suggestion := {
80+
suggestion := .string newText
81+
toCodeActionTitle? := some fun _ => title
82+
}
83+
addSuggestion ref suggestion (origSpan? := some (Syntax.ofRange insertionRange))
84+
(header := "Code action:")
85+
86+
/--
87+
Emit a code action inserting `have : <current goal> := sorry` before the current tactic line.
88+
89+
This is intended for use as a `simp` discharger, for example:
90+
`simp (disch:=make_have)`. For `simp` discharger goals, the tactic records the
91+
code action and admits the generated side condition so that `simp` can finish.
92+
The inserted `have` can then discharge later runs via `simp (disch:=assumption)`.
93+
-/
94+
elab "make_have" : tactic => do
95+
let goal ← getMainGoal
96+
insertHaveSuggestion (← getRef)
97+
if (← goal.getTag) == `simp.discharger then
98+
admitGoal goal (synthetic := false)
99+
100+
example (x y : Int) : x / x + y / y = 2 := by
101+
simp (disch := first | assumption | make_have)
102+
103+
end MakeHave

0 commit comments

Comments
 (0)