Skip to content

Commit 160dbc2

Browse files
committed
generalize oscillation
1 parent 35a3c23 commit 160dbc2

2 files changed

Lines changed: 218 additions & 37 deletions

File tree

Mathlib/Analysis/Oscillation.lean

Lines changed: 174 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
/-
22
Copyright (c) 2024 James Sundstrom. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: James Sundstrom
4+
Authors: James Sundstrom, Lua Viana Reis
55
-/
66
module
77

88
public import Mathlib.Data.ENNReal.Real
99
public import Mathlib.Order.WellFoundedSet
1010
public import Mathlib.Topology.EMetricSpace.Diam
11+
public import Mathlib.Topology.EMetricSpace.Lipschitz
12+
public import Mathlib.Topology.UniformSpace.Cauchy
13+
public import Mathlib.Analysis.Normed.Group.Uniform
14+
import Mathlib.Tactic.Scratchpad
1115

1216
/-!
1317
# Oscillation
1418
15-
In this file we define the oscillation of a function `f: E → F` at a point `x` of `E`. (`E` is
16-
required to be a TopologicalSpace and `F` a PseudoEMetricSpace.) The oscillation of `f` at `x` is
17-
defined to be the infimum of `diam f '' N` for all neighborhoods `N` of `x`. We also define
18-
`oscillationWithin f D x`, which is the oscillation at `x` of `f` restricted to `D`.
19+
In this file we define the oscillation of a function `f: E → F` along a filter `l` of `E`. (`F` is
20+
required to be a PseudoEMetricSpace.) The oscillation of `f` at `l` is
21+
defined to be the infimum of `diam f '' N` for all sets `N` in `l`. We also define
22+
`oscillationWithin f D l`, which is the oscillation at `l` of `f` restricted to `D`.
1923
2024
We also prove some simple facts about oscillation, most notably that the oscillation of `f`
2125
at `x` is 0 if and only if `f` is continuous at `x`, with versions for both `oscillation` and
@@ -28,35 +32,39 @@ oscillation, oscillationWithin
2832

2933
@[expose] public section
3034

31-
open Topology Metric Set ENNReal
35+
open Topology Metric Set ENNReal Filter
3236

3337
universe u v
3438

3539
variable {E : Type u} {F : Type v} [PseudoEMetricSpace F]
3640

41+
/-- The oscillation of `f : E → F` along `l`. -/
42+
noncomputable def oscillation (f : E → F) (l : Filter E) : ENNReal :=
43+
⨅ S ∈ l.map f, ediam S
44+
3745
/-- The oscillation of `f : E → F` at `x`. -/
38-
noncomputable def oscillation [TopologicalSpace E] (f : E → F) (x : E) : ENNReal :=
39-
⨅ S ∈ (𝓝 x).map f, ediam S
46+
noncomputable abbrev oscillationAt [TopologicalSpace E] (f : E → F) (x : E) : ENNReal :=
47+
oscillation f (𝓝 x)
4048

4149
/-- The oscillation of `f : E → F` within `D` at `x`. -/
42-
noncomputable def oscillationWithin [TopologicalSpace E] (f : E → F) (D : Set E) (x : E) :
50+
noncomputable def oscillationWithinAt [TopologicalSpace E] (f : E → F) (D : Set E) (x : E) :
4351
ENNReal :=
44-
⨅ S ∈ (𝓝[D] x).map f, ediam S
52+
oscillation f (𝓝[D] x)
4553

4654
/-- The oscillation of `f` at `x` within a neighborhood `D` of `x` is equal to `oscillation f x` -/
47-
theorem oscillationWithin_nhds_eq_oscillation [TopologicalSpace E] (f : E → F) (D : Set E) (x : E)
48-
(hD : D ∈ 𝓝 x) : oscillationWithin f D x = oscillation f x := by
49-
rw [oscillation, oscillationWithin, nhdsWithin_eq_nhds.2 hD]
55+
theorem oscillationWithinAt_nhds_eq_oscillationAt [TopologicalSpace E] (f : E → F) (D : Set E)
56+
(x : E) (hD : D ∈ 𝓝 x) : oscillationWithinAt f D x = oscillationAt f x := by
57+
rw [oscillationAt, oscillationWithinAt, nhdsWithin_eq_nhds.2 hD]
5058

5159
/-- The oscillation of `f` at `x` within `univ` is equal to `oscillation f x` -/
52-
theorem oscillationWithin_univ_eq_oscillation [TopologicalSpace E] (f : E → F) (x : E) :
53-
oscillationWithin f univ x = oscillation f x :=
54-
oscillationWithin_nhds_eq_oscillation f univ x Filter.univ_mem
60+
theorem oscillationWithinAt_univ_eq_oscillationAt [TopologicalSpace E] (f : E → F) (x : E) :
61+
oscillationWithinAt f univ x = oscillationAt f x :=
62+
oscillationWithinAt_nhds_eq_oscillationAt f univ x Filter.univ_mem
5563

5664
namespace ContinuousWithinAt
5765

58-
theorem oscillationWithin_eq_zero [TopologicalSpace E] {f : E → F} {D : Set E}
59-
{x : E} (hf : ContinuousWithinAt f D x) : oscillationWithin f D x = 0 := by
66+
theorem oscillationWithinAt_eq_zero [TopologicalSpace E] {f : E → F} {D : Set E}
67+
{x : E} (hf : ContinuousWithinAt f D x) : oscillationWithinAt f D x = 0 := by
6068
rw [← nonpos_iff_eq_zero]
6169
refine _root_.le_of_forall_pos_le_add fun ε hε ↦ ?_
6270
rw [zero_add]
@@ -69,35 +77,36 @@ end ContinuousWithinAt
6977

7078
namespace ContinuousAt
7179

72-
theorem oscillation_eq_zero [TopologicalSpace E] {f : E → F} {x : E} (hf : ContinuousAt f x) :
73-
oscillation f x = 0 := by
80+
theorem oscillationAt_eq_zero [TopologicalSpace E] {f : E → F} {x : E} (hf : ContinuousAt f x) :
81+
oscillationAt f x = 0 := by
7482
rw [← continuousWithinAt_univ f x] at hf
75-
exact oscillationWithin_univ_eq_oscillation f x ▸ hf.oscillationWithin_eq_zero
83+
exact oscillationWithinAt_univ_eq_oscillationAt f x ▸ hf.oscillationWithinAt_eq_zero
7684

7785
end ContinuousAt
7886

79-
namespace OscillationWithin
87+
namespace OscillationWithinAt
8088

8189
/-- The oscillation within `D` of `f` at `x ∈ D` is 0 if and only if `ContinuousWithinAt f D x`. -/
8290
theorem eq_zero_iff_continuousWithinAt [TopologicalSpace E] (f : E → F) {D : Set E}
83-
{x : E} (xD : x ∈ D) : oscillationWithin f D x = 0 ↔ ContinuousWithinAt f D x := by
84-
refine ⟨fun hf ↦ EMetric.tendsto_nhds.mpr (fun ε ε0 ↦ ?_), fun hf ↦ hf.oscillationWithin_eq_zero⟩
85-
simp_rw [← hf, oscillationWithin, iInf_lt_iff] at ε0
91+
{x : E} (xD : x ∈ D) : oscillationWithinAt f D x = 0 ↔ ContinuousWithinAt f D x := by
92+
refine ⟨fun hf ↦ EMetric.tendsto_nhds.mpr (fun ε ε0 ↦ ?_),
93+
fun hf ↦ hf.oscillationWithinAt_eq_zero⟩
94+
simp_rw [← hf, oscillationWithinAt, oscillation, iInf_lt_iff] at ε0
8695
obtain ⟨S, hS, Sε⟩ := ε0
8796
refine Filter.mem_of_superset hS (fun y hy ↦ lt_of_le_of_lt ?_ Sε)
8897
exact edist_le_ediam_of_mem (mem_preimage.1 hy) <| mem_preimage.1 (mem_of_mem_nhdsWithin xD hS)
8998

90-
end OscillationWithin
99+
end OscillationWithinAt
91100

92-
namespace Oscillation
101+
namespace OscillationAt
93102

94103
/-- The oscillation of `f` at `x` is 0 if and only if `f` is continuous at `x`. -/
95104
theorem eq_zero_iff_continuousAt [TopologicalSpace E] (f : E → F) (x : E) :
96-
oscillation f x = 0 ↔ ContinuousAt f x := by
97-
rw [← oscillationWithin_univ_eq_oscillation, ← continuousWithinAt_univ f x]
98-
exact OscillationWithin.eq_zero_iff_continuousWithinAt f (mem_univ x)
105+
oscillationAt f x = 0 ↔ ContinuousAt f x := by
106+
rw [← oscillationWithinAt_univ_eq_oscillationAt, ← continuousWithinAt_univ f x]
107+
exact OscillationWithinAt.eq_zero_iff_continuousWithinAt f (mem_univ x)
99108

100-
end Oscillation
109+
end OscillationAt
101110

102111
namespace IsCompact
103112

@@ -106,7 +115,7 @@ variable {f : E → F} {D : Set E} {ε : ENNReal}
106115

107116
/-- If `oscillationWithin f D x < ε` at every `x` in a compact set `K`, then there exists `δ > 0`
108117
such that the oscillation of `f` on `ball x δ ∩ D` is less than `ε` for every `x` in `K`. -/
109-
theorem uniform_oscillationWithin (comp : IsCompact K) (hK : ∀ x ∈ K, oscillationWithin f D x < ε) :
118+
theorem uniform_oscillationWithinAt (comp : IsCompact K) (hK : ∀ x ∈ K, oscillationWithinAt f D x < ε) :
110119
∃ δ > 0, ∀ x ∈ K, ediam (f '' (eball x (ENNReal.ofReal δ) ∩ D)) ≤ ε := by
111120
let S := fun r ↦
112121
{x : E | ∃ (a : ℝ), (a > r ∧ ediam (f '' (eball x (ENNReal.ofReal a) ∩ D)) ≤ ε)}
@@ -120,8 +129,8 @@ theorem uniform_oscillationWithin (comp : IsCompact K) (hK : ∀ x ∈ K, oscill
120129
rw [← ofReal_add (by linarith) (by linarith), sub_add_cancel]
121130
have S_cover : K ⊆ ⋃ r > 0, S r := by
122131
intro x hx
123-
have : oscillationWithin f D x < ε := hK x hx
124-
simp only [oscillationWithin, Filter.mem_map, iInf_lt_iff] at this
132+
have : oscillationWithinAt f D x < ε := hK x hx
133+
simp only [oscillationWithinAt, oscillation, Filter.mem_map, iInf_lt_iff] at this
125134
obtain ⟨n, hn₁, hn₂⟩ := this
126135
obtain ⟨r, r0, hr⟩ := EMetric.mem_nhdsWithin_iff.1 hn₁
127136
simp only [gt_iff_lt, mem_iUnion, exists_prop]
@@ -154,10 +163,138 @@ theorem uniform_oscillationWithin (comp : IsCompact K) (hK : ∀ x ∈ K, oscill
154163
/-- If `oscillation f x < ε` at every `x` in a compact set `K`, then there exists `δ > 0` such
155164
that the oscillation of `f` on `ball x δ` is less than `ε` for every `x` in `K`. -/
156165
theorem uniform_oscillation {K : Set E} (comp : IsCompact K)
157-
{f : E → F} {ε : ENNReal} (hK : ∀ x ∈ K, oscillation f x < ε) :
166+
{f : E → F} {ε : ENNReal} (hK : ∀ x ∈ K, oscillationAt f x < ε) :
158167
∃ δ > 0, ∀ x ∈ K, ediam (f '' (eball x (ENNReal.ofReal δ))) ≤ ε := by
159-
simp only [← oscillationWithin_univ_eq_oscillation] at hK
160-
convert ← comp.uniform_oscillationWithin hK
168+
simp only [← oscillationWithinAt_univ_eq_oscillationAt] at hK
169+
convert ← comp.uniform_oscillationWithinAt hK
161170
exact inter_univ _
162171

163172
end IsCompact
173+
174+
section MoveMe
175+
176+
variable {ι : Sort*} {κ : ι → Sort*} {α : Type*} {f : (i : ι) → κ i → α}
177+
178+
@[to_dual iInf₂_le_iff]
179+
theorem le_iSup₂_iff [CompleteSemilatticeSup α] {a : α} :
180+
a ≤ ⨆ (i) (j), f i j ↔ ∀ b, (∀ i j, f i j ≤ b) → a ≤ b := by
181+
simp [iSup, le_sSup_iff, upperBounds]
182+
183+
@[to_dual iInf₂_lt_iff]
184+
theorem lt_iSup₂_iff [CompleteLinearOrder α] {a : α} :
185+
a < ⨆ (i) (j), f i j ↔ ∃ i j, a < f i j := by
186+
have := lt_iSup_iff (f := fun (ij : PSigma κ) ↦ f ij.1 ij.2) (a := a)
187+
simp_rw [PSigma.exists, iSup_psigma] at this
188+
exact this
189+
190+
@[to_dual iInf₂_le_iff_forall_lt]
191+
theorem le_iSup₂_iff_forall_lt [CompleteLinearOrder α] {l : α} :
192+
l ≤ ⨆ (i) (j), f i j ↔ ∀ b < l, ∃ i j, b < f i j := by
193+
have := le_iSup_iff_forall_lt (f := fun (ij : PSigma κ) ↦ f ij.1 ij.2) (l := l)
194+
simp_rw [PSigma.exists, iSup_psigma] at this
195+
exact this
196+
197+
@[to_dual lt_iInf₂_iff]
198+
theorem iSup₂_lt_iff [CompleteLattice α] {l : α} :
199+
⨆ (i) (j), f i j < l ↔ ∃ b < l, ∀ i j, f i j ≤ b := by
200+
have := iSup_lt_iff (f := fun (ij : PSigma κ) ↦ f ij.1 ij.2) (l := l)
201+
simp_rw [PSigma.forall, iSup_psigma] at this
202+
exact this
203+
204+
lemma mul_biInf {p : ι → Prop} (hp : ∃ i, p i) {a : ℝ≥0∞} {f : ι → ℝ≥0∞}
205+
(hinfty : a = ∞ → ⨅ (i) (_ : p i), f i = 0 → ∃ i, ∃ (_ : p i), f i = 0) :
206+
a * ⨅ (i) (_ : p i), f i = ⨅ (i) (_ : p i), a * f i := by
207+
haveI : Nonempty {i // p i} := nonempty_subtype.mpr hp
208+
have := mul_iInf (ι := {i // p i}) (a := a) (f := (f ·))
209+
simp_rw [iInf_subtype, Subtype.exists] at this
210+
exact this hinfty
211+
212+
end MoveMe
213+
214+
section Cauchy
215+
216+
variable {f : E → F}
217+
218+
theorem EMetric.cauchy_iff_iInf_ediam_eq_zero (l : Filter F) [NeBot l] :
219+
Cauchy l ↔ ⨅ s ∈ l, ediam s = 0 := by
220+
rw [EMetric.cauchy_iff, ←nonpos_iff_eq_zero, iInf₂_le_iff_forall_lt]
221+
constructor
222+
· intro h ε hε
223+
rcases exists_between hε with ⟨η, hη⟩
224+
rcases h.right η hη.1 with ⟨s, hs₁, hs₂⟩
225+
use s, hs₁
226+
apply iSup₂_lt_iff.mpr
227+
use η, hη.2
228+
intro i hi
229+
apply iSup₂_le_iff.mpr
230+
intro j hj
231+
exact hs₂ i hi j hj |>.le
232+
· intro h
233+
use NeBot.ne'
234+
intro ε hε
235+
rcases h ε hε with ⟨s, hs₁, hs₂⟩
236+
use s, hs₁
237+
intro i hi j hj
238+
rcases iSup₂_lt_iff.mp hs₂ with ⟨l, hl, hs₃⟩
239+
specialize hs₃ i hi
240+
exact iSup₂_le_iff.mp hs₃ j hj |>.trans_lt hl
241+
242+
theorem cauchy_iff_oscillation_eq_zero (l : Filter E) [NeBot l] :
243+
Cauchy (l.map f) ↔ oscillation f l = 0 :=
244+
EMetric.cauchy_iff_iInf_ediam_eq_zero _
245+
246+
/-- A function `f` whose domain is a complete `EMetric` space converges to a point along a filter if
247+
and only if its oscillation along `l` is equal to zero. -/
248+
theorem EMetric.tendsTo_nhds_iff_oscillation_eq_zero [CompleteSpace F] (l : Filter E) [NeBot l] :
249+
(∃ x, Tendsto f l (𝓝 x)) ↔ oscillation f l = 0 := by
250+
rw [←cauchy_map_iff_exists_tendsto]
251+
exact cauchy_iff_oscillation_eq_zero _
252+
253+
end Cauchy
254+
255+
section Lipschitz
256+
257+
variable {α β γ : Type*} [PseudoEMetricSpace α] [PseudoEMetricSpace β] [PseudoEMetricSpace γ]
258+
259+
theorem LipschitzWith.oscillation_comp₂_le (g : α → β → γ) (f₁ : E → α) (f₂ : E → β)
260+
{K₁ K₂ : NNReal} (l : Filter E)
261+
(hf₁ : ∀ b, LipschitzWith K₁ (g · b)) (hf₂ : ∀ a, LipschitzWith K₂ (g a ·)) :
262+
oscillation (fun a ↦ g (f₁ a) (f₂ a)) l
263+
≤ ↑K₁ * oscillation f₁ l + ↑K₂ * oscillation f₂ l := by
264+
unfold oscillation
265+
simp_rw [mul_biInf ⟨_, Filter.univ_mem⟩ (coe_ne_top · |>.elim)]
266+
change_set _ ≤ (?a + ?b : ℝ≥0∞)
267+
by_cases! ha : a = ∞; · simp [ha]
268+
by_cases! hb : b = ∞; · simp [hb]
269+
apply ENNReal.le_of_forall_pos_le_add
270+
intro ε hε hfin
271+
rcases iInf₂_le_iff_forall_lt (l := a) |>.mp le_rfl (a + ε / 2)
272+
(lt_add_right ha (by norm_num [hε.ne'])) with ⟨sa, hsa, hsa'⟩
273+
rcases iInf₂_le_iff_forall_lt (l := b) |>.mp le_rfl (b + ε / 2)
274+
(lt_add_right hb (by norm_num [hε.ne'])) with ⟨sb, hsb, hsb'⟩
275+
rw [show a + b + ε = a + ε / 2 + (b + ε / 2) by
276+
ring_nf
277+
rw [ENNReal.div_mul_cancel (by positivity) (by finiteness)]]
278+
apply ENNReal.add_lt_add hsa' hsb' |>.trans_le' _ |>.le
279+
apply iInf₂_le_of_le (image2 g sa sb) _ _
280+
· rw [mem_map] at ⊢ hsa hsb
281+
exact l.mem_of_superset (l.inter_mem hsa hsb) fun a ⟨h₁, h₂⟩ ↦ ⟨f₁ a, h₁, f₂ a, h₂, rfl⟩
282+
· exact LipschitzOnWith.ediam_image2_le _ _ _
283+
(fun s _ ↦ hf₁ s |>.lipschitzOnWith)
284+
(fun s _ ↦ hf₂ s |>.lipschitzOnWith)
285+
286+
end Lipschitz
287+
288+
section SeminormedAddCommGroup
289+
290+
variable {F : Type*} [SeminormedCommGroup F]
291+
292+
@[to_additive]
293+
theorem oscillation_mul_le (f₁ : E → F) (f₂ : E → F) (l : Filter E) :
294+
oscillation (f₁ * f₂) l ≤ oscillation f₁ l + oscillation f₂ l :=
295+
LipschitzWith.oscillation_comp₂_le (· * ·) f₁ f₂ l
296+
(fun _ => (isometry_mul_right _).lipschitz)
297+
(fun _ => (isometry_mul_left _).lipschitz)
298+
|>.trans_eq (by simp only [coe_one, one_mul])
299+
300+
end SeminormedAddCommGroup

Mathlib/Tactic/Scratchpad.lean

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module
2+
3+
public import Mathlib.Tactic.Set
4+
5+
set_option trace.debug true
6+
set_option pp.rawOnError true
7+
8+
open Lean Elab Tactic Meta in
9+
elab "change_set " p:term : tactic => withMainContext do
10+
let e ← getMainTarget
11+
let p ← runTermElab do
12+
let p ← Term.elabTermEnsuringType p (← inferType e)
13+
unless ← isDefEq p e do
14+
/-
15+
Sometimes isDefEq can fail due to postponed elaboration problems.
16+
We synthesize pending synthetic mvars while allowing typeclass instances to be postponed,
17+
which might enable solving for them with an additional `isDefEq`.
18+
-/
19+
Term.synthesizeSyntheticMVars (postpone := .partial)
20+
discard <| isDefEq p e
21+
pure p
22+
let mvars := (← instantiateMVars p).collectMVars {} |>.result
23+
_ ← withAssignableSyntheticOpaque do
24+
unless ← isDefEq p e do
25+
throwError MessageData.ofLazyM (es := #[p, e]) do
26+
let (p, tgt) ← addPPExplicitToExposeDiff p e
27+
throwError "change_set: pattern {p} does not match goal{indentExpr tgt}"
28+
instantiateMVars p
29+
for m in mvars do
30+
let d ← m.getDecl
31+
if d.userName.isAnonymous then continue
32+
let val ← instantiateMVars (.mvar m)
33+
let valStx ← PrettyPrinter.delab val
34+
let name := mkIdent d.userName
35+
evalTactic (← `(tactic| set $name:ident := $valStx))
36+
37+
example : (fun x => x + 1) 0 = 1 + 0 := by
38+
change_set _
39+
rfl
40+
41+
example : (fun x => x + 1) 0 = 1 + 0 := by
42+
change_set ?a + 1 = ?b
43+
44+
rfl

0 commit comments

Comments
 (0)