Skip to content

Commit ec80061

Browse files
committed
refactor(analysis/asymptotics): make is_o irreducible (leanprover-community#2416)
`is_o` is currently not irreducible. Since it is a complicated type, Lean can have trouble checking if two types with `is_o` are defeq or not, leading to timeouts as described in https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/undergraduate.20calculus/near/193776607 This PR makes `is_o` irreducible.
1 parent 5fd4afc commit ec80061

File tree

5 files changed

+47
-7
lines changed

5 files changed

+47
-7
lines changed

src/analysis/asymptotics.lean

+37
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,53 @@ avoided by this definition. Probably you want to use `is_O` instead of this rela
6666
def is_O_with (c : ℝ) (f : α → E) (g : α → F) (l : filter α) : Prop :=
6767
∀ᶠ x in l, ∥ f x ∥ ≤ c * ∥ g x ∥
6868

69+
/-- Definition of `is_O_with`. We record it in a lemma as we will set `is_O_with` to be irreducible
70+
at the end of this file. -/
71+
lemma is_O_with_iff {c : ℝ} {f : α → E} {g : α → F} {l : filter α} :
72+
is_O_with c f g l ↔ ∀ᶠ x in l, ∥ f x ∥ ≤ c * ∥ g x ∥ := iff.rfl
73+
74+
lemma is_O_with.of_bound {c : ℝ} {f : α → E} {g : α → F} {l : filter α}
75+
(h : ∀ᶠ x in l, ∥ f x ∥ ≤ c * ∥ g x ∥) : is_O_with c f g l := h
76+
6977
/-- The Landau notation `is_O f g l` where `f` and `g` are two functions on a type `α` and `l` is
7078
a filter on `α`, means that eventually for `l`, `∥f∥` is bounded by a constant multiple of `∥g∥`.
7179
In other words, `∥f∥ / ∥g∥` is eventually bounded, modulo division by zero issues that are avoided
7280
by this definition. -/
7381
def is_O (f : α → E) (g : α → F) (l : filter α) : Prop := ∃ c : ℝ, is_O_with c f g l
7482

83+
/-- Definition of `is_O` in terms of `is_O_with`. We record it in a lemma as we will set
84+
`is_O` to be irreducible at the end of this file. -/
85+
lemma is_O_iff_is_O_with {f : α → E} {g : α → F} {l : filter α} :
86+
is_O f g l ↔ ∃ c : ℝ, is_O_with c f g l := iff.rfl
87+
88+
/-- Definition of `is_O` in terms of filters. We record it in a lemma as we will set
89+
`is_O` to be irreducible at the end of this file. -/
90+
lemma is_O_iff {f : α → E} {g : α → F} {l : filter α} :
91+
is_O f g l ↔ ∃ c : ℝ, ∀ᶠ x in l, ∥ f x ∥ ≤ c * ∥ g x ∥ := iff.rfl
92+
93+
lemma is_O.of_bound (c : ℝ) {f : α → E} {g : α → F} {l : filter α}
94+
(h : ∀ᶠ x in l, ∥ f x ∥ ≤ c * ∥ g x ∥) : is_O f g l := ⟨c, h⟩
95+
7596
/-- The Landau notation `is_o f g l` where `f` and `g` are two functions on a type `α` and `l` is
7697
a filter on `α`, means that eventually for `l`, `∥f∥` is bounded by an arbitrarily small constant
7798
multiple of `∥g∥`. In other words, `∥f∥ / ∥g∥` tends to `0` along `l`, modulo division by zero
7899
issues that are avoided by this definition. -/
79100
def is_o (f : α → E) (g : α → F) (l : filter α) : Prop := ∀ ⦃c : ℝ⦄, 0 < c → is_O_with c f g l
80101

102+
/-- Definition of `is_o` in terms of `is_O_with`. We record it in a lemma as we will set
103+
`is_o` to be irreducible at the end of this file. -/
104+
lemma is_o_iff_forall_is_O_with {f : α → E} {g : α → F} {l : filter α} :
105+
is_o f g l ↔ ∀ ⦃c : ℝ⦄, 0 < c → is_O_with c f g l := iff.rfl
106+
107+
/-- Definition of `is_o` in terms of filters. We record it in a lemma as we will set
108+
`is_o` to be irreducible at the end of this file. -/
109+
lemma is_o_iff {f : α → E} {g : α → F} {l : filter α} :
110+
is_o f g l ↔ ∀ ⦃c : ℝ⦄, 0 < c → ∀ᶠ x in l, ∥ f x ∥ ≤ c * ∥ g x ∥ := iff.rfl
111+
112+
lemma is_o.def {f : α → E} {g : α → F} {l : filter α} (h : is_o f g l) {c : ℝ} (hc : 0 < c) :
113+
∀ᶠ x in l, ∥ f x ∥ ≤ c * ∥ g x ∥ :=
114+
h hc
115+
81116
end defs
82117

83118
/-! ### Conversions -/
@@ -1058,3 +1093,5 @@ lemma is_o_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F} :
10581093
forall_congr $ λ c, forall_congr $ λ hc, e.is_O_with_congr
10591094

10601095
end homeomorph
1096+
1097+
attribute [irreducible] asymptotics.is_o asymptotics.is_O asymptotics.is_O_with

src/analysis/calculus/extend_deriv.lean

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ begin
4646
by_cases hx : x ∉ closure s,
4747
{ rw ← closure_closure at hx, exact has_fderiv_within_at_of_not_mem_closure hx },
4848
push_neg at hx,
49+
rw [has_fderiv_within_at, has_fderiv_at_filter, asymptotics.is_o_iff],
4950
/- One needs to show that `∥f y - f x∥ ≤ ε ∥y - x∥` for `y` close to `x` in `closure s`, where
5051
`ε` is an arbitrary positive constant. By continuity of the functions, it suffices to prove this
5152
for nearby points inside `s`. In a neighborhood of `x`, the derivative of `f` is arbitrarily small

src/analysis/calculus/fderiv.lean

+5-2
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,10 @@ h.is_O.congr_of_sub.2 (f'.is_O_sub _ _)
319319

320320
lemma has_strict_fderiv_at.has_fderiv_at (hf : has_strict_fderiv_at f f' x) :
321321
has_fderiv_at f f' x :=
322-
λ c hc, tendsto_id.prod_mk_nhds tendsto_const_nhds (hf hc)
322+
begin
323+
rw [has_fderiv_at, has_fderiv_at_filter, is_o_iff],
324+
exact (λ c hc, tendsto_id.prod_mk_nhds tendsto_const_nhds (is_o_iff.1 hf hc))
325+
end
323326

324327
lemma has_strict_fderiv_at.differentiable_at (hf : has_strict_fderiv_at f f' x) :
325328
differentiable_at 𝕜 f x :=
@@ -1615,7 +1618,7 @@ begin
16151618
apply is_bounded_bilinear_map_apply.is_O_comp.trans_is_o,
16161619
refine is_o.trans_is_O _ (is_O_const_mul_self 1 _ _).of_norm_right,
16171620
refine is_o.mul_is_O _ (is_O_refl _ _),
1618-
exact (((h.is_bounded_linear_map_deriv.is_O_id ⊤).comp_tendsto le_top).trans_is_o this).norm_left
1621+
exact (((h.is_bounded_linear_map_deriv.is_O_id ⊤).comp_tendsto le_top : _).trans_is_o this).norm_left
16191622
end
16201623

16211624
lemma is_bounded_bilinear_map.has_fderiv_at (h : is_bounded_bilinear_map 𝕜 b) (p : E × F) :

src/analysis/complex/exponential.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ lemma has_deriv_at_exp (x : ℂ) : has_deriv_at exp (exp x) x :=
4949
begin
5050
rw has_deriv_at_iff_is_o_nhds_zero,
5151
have : (1 : ℕ) < 2 := by norm_num,
52-
refine is_O.trans_is_o ⟨∥exp x∥, _⟩ (is_o_pow_id this),
52+
refine (is_O.of_bound (∥exp x∥) _).trans_is_o (is_o_pow_id this),
5353
have : metric.ball (0 : ℂ) 1 ∈ nhds (0 : ℂ) := metric.ball_mem_nhds 0 zero_lt_one,
5454
apply filter.mem_sets_of_superset this (λz hz, _),
5555
simp only [metric.mem_ball, dist_zero_right] at hz,

src/analysis/normed_space/bounded_linear_maps.lean

+3-4
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ open asymptotics filter
128128

129129
theorem is_O_id {f : E → F} (h : is_bounded_linear_map 𝕜 f) (l : filter E) :
130130
is_O f (λ x, x) l :=
131-
let ⟨M, hMp, hM⟩ := h.bound in
132-
⟨M, mem_sets_of_superset univ_mem_sets (λ x _, hM x)⟩
131+
let ⟨M, hMp, hM⟩ := h.bound in is_O.of_bound _ (mem_sets_of_superset univ_mem_sets (λ x _, hM x))
133132

134133
theorem is_O_comp {E : Type*} {g : F → G} (hg : is_bounded_linear_map 𝕜 g)
135134
{f : E → F} (l : filter E) : is_O (λ x', g (f x')) f l :=
@@ -222,8 +221,8 @@ variable {f : E × F → G}
222221

223222
protected lemma is_bounded_bilinear_map.is_O (h : is_bounded_bilinear_map 𝕜 f) :
224223
asymptotics.is_O f (λ p : E × F, ∥p.1∥ * ∥p.2∥) ⊤ :=
225-
let ⟨C, Cpos, hC⟩ := h.bound in
226-
⟨C, filter.eventually_of_forall ⊤ $ λ ⟨x, y⟩, by simpa [mul_assoc] using hC x y
224+
let ⟨C, Cpos, hC⟩ := h.bound in asymptotics.is_O.of_bound _ $
225+
filter.eventually_of_forall ⊤ $ λ ⟨x, y⟩, by simpa [mul_assoc] using hC x y
227226

228227
lemma is_bounded_bilinear_map.is_O_comp {α : Type*} (H : is_bounded_bilinear_map 𝕜 f)
229228
{g : α → E} {h : α → F} {l : filter α} :

0 commit comments

Comments
 (0)