Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18536License: APACHE
/- Copyright (c) 2019 Gabriel Ebner. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner, Sébastien Gouëzel -/ import analysis.calculus.fderiv /-! # One-dimensional derivatives This file defines the derivative of a function `f : 𝕜 → F` where `𝕜` is a normed field and `F` is a normed space over this field. The derivative of such a function `f` at a point `x` is given by an element `f' : F`. The theory is developed analogously to the [Fréchet derivatives](./fderiv.lean). We first introduce predicates defined in terms of the corresponding predicates for Fréchet derivatives: - `has_deriv_at_filter f f' x L` states that the function `f` has the derivative `f'` at the point `x` as `x` goes along the filter `L`. - `has_deriv_within_at f f' s x` states that the function `f` has the derivative `f'` at the point `x` within the subset `s`. - `has_deriv_at f f' x` states that the function `f` has the derivative `f'` at the point `x`. For the last two notions we also define a functional version: - `deriv_within f s x` is a derivative of `f` at `x` within `s`. If the derivative does not exist, then `deriv_within f s x` equals zero. - `deriv f x` is a derivative of `f` at `x`. If the derivative does not exist, then `deriv f x` equals zero. The theorems `fderiv_within_deriv_within` and `fderiv_deriv` show that the one-dimensional derivatives coincide with the general Fréchet derivatives. We also show the existence and compute the derivatives of: - constants - the identity function - linear maps - addition - negation - subtraction - multiplication - inverse `x → x⁻¹` - multiplication of two functions in `𝕜 → 𝕜` - multiplication of a function in `𝕜 → 𝕜` and of a function in `𝕜 → E` - composition of a function in `𝕜 → F` with a function in `𝕜 → 𝕜` - composition of a function in `F → E` with a function in `𝕜 → F` - division - polynomials For most binary operations we also define `const_op` and `op_const` theorems for the cases when the first or second argument is a constant. This makes writing chains of `has_deriv_at`'s easier, and they more frequently lead to the desired result. ## Implementation notes Most of the theorems are direct restatements of the corresponding theorems for Fréchet derivatives. -/ universes u v w noncomputable theory open_locale classical topological_space open filter asymptotics set open continuous_linear_map (smul_right smul_right_one_eq_iff) set_option class.instance_max_depth 100 variables {𝕜 : Type u} [nondiscrete_normed_field 𝕜] section variables {F : Type v} [normed_group F] [normed_space 𝕜 F] variables {E : Type w} [normed_group E] [normed_space 𝕜 E] /-- `f` has the derivative `f'` at the point `x` as `x` goes along the filter `L`. That is, `f x' = f x + (x' - x) • f' + o(x' - x)` where `x'` converges along the filter `L`. -/ def has_deriv_at_filter (f : 𝕜 → F) (f' : F) (x : 𝕜) (L : filter 𝕜) := has_fderiv_at_filter f (smul_right 1 f' : 𝕜 →L[𝕜] F) x L /-- `f` has the derivative `f'` at the point `x` within the subset `s`. That is, `f x' = f x + (x' - x) • f' + o(x' - x)` where `x'` converges to `x` inside `s`. -/ def has_deriv_within_at (f : 𝕜 → F) (f' : F) (s : set 𝕜) (x : 𝕜) := has_deriv_at_filter f f' x (nhds_within x s) /-- `f` has the derivative `f'` at the point `x`. That is, `f x' = f x + (x' - x) • f' + o(x' - x)` where `x'` converges to `x`. -/ def has_deriv_at (f : 𝕜 → F) (f' : F) (x : 𝕜) := has_deriv_at_filter f f' x (𝓝 x) /-- Derivative of `f` at the point `x` within the set `s`, if it exists. Zero otherwise. If the derivative exists (i.e., `∃ f', has_deriv_within_at f f' s x`), then `f x' = f x + (x' - x) • deriv_within f s x + o(x' - x)` where `x'` converges to `x` inside `s`. -/ def deriv_within (f : 𝕜 → F) (s : set 𝕜) (x : 𝕜) := (fderiv_within 𝕜 f s x : 𝕜 →L[𝕜] F) 1 /-- Derivative of `f` at the point `x`, if it exists. Zero otherwise. If the derivative exists (i.e., `∃ f', has_deriv_at f f' x`), then `f x' = f x + (x' - x) • deriv f x + o(x' - x)` where `x'` converges to `x`. -/ def deriv (f : 𝕜 → F) (x : 𝕜) := (fderiv 𝕜 f x : 𝕜 →L[𝕜] F) 1 variables {f f₀ f₁ g : 𝕜 → F} variables {f' f₀' f₁' g' : F} variables {x : 𝕜} variables {s t : set 𝕜} variables {L L₁ L₂ : filter 𝕜} /-- Expressing `has_fderiv_at_filter f f' x L` in terms of `has_deriv_at_filter` -/ lemma has_fderiv_at_filter_iff_has_deriv_at_filter {f' : 𝕜 →L[𝕜] F} : has_fderiv_at_filter f f' x L ↔ has_deriv_at_filter f (f' 1) x L := by simp [has_deriv_at_filter] /-- Expressing `has_fderiv_within_at f f' s x` in terms of `has_deriv_within_at` -/ lemma has_fderiv_within_at_iff_has_deriv_within_at {f' : 𝕜 →L[𝕜] F} : has_fderiv_within_at f f' s x ↔ has_deriv_within_at f (f' 1) s x := by simp [has_deriv_within_at, has_deriv_at_filter, has_fderiv_within_at] /-- Expressing `has_deriv_within_at f f' s x` in terms of `has_fderiv_within_at` -/ lemma has_deriv_within_at_iff_has_fderiv_within_at {f' : F} : has_deriv_within_at f f' s x ↔ has_fderiv_within_at f (smul_right 1 f' : 𝕜 →L[𝕜] F) s x := iff.rfl /-- Expressing `has_fderiv_at f f' x` in terms of `has_deriv_at` -/ lemma has_fderiv_at_iff_has_deriv_at {f' : 𝕜 →L[𝕜] F} : has_fderiv_at f f' x ↔ has_deriv_at f (f' 1) x := by simp [has_deriv_at, has_deriv_at_filter, has_fderiv_at] /-- Expressing `has_deriv_at f f' x` in terms of `has_fderiv_at` -/ lemma has_deriv_at_iff_has_fderiv_at {f' : F} : has_deriv_at f f' x ↔ has_fderiv_at f (smul_right 1 f' : 𝕜 →L[𝕜] F) x := iff.rfl lemma deriv_within_zero_of_not_differentiable_within_at (h : ¬ differentiable_within_at 𝕜 f s x) : deriv_within f s x = 0 := by { unfold deriv_within, rw fderiv_within_zero_of_not_differentiable_within_at, simp, assumption } lemma deriv_zero_of_not_differentiable_at (h : ¬ differentiable_at 𝕜 f x) : deriv f x = 0 := by { unfold deriv, rw fderiv_zero_of_not_differentiable_at, simp, assumption } theorem unique_diff_within_at.eq_deriv (s : set 𝕜) (H : unique_diff_within_at 𝕜 s x) (h : has_deriv_within_at f f' s x) (h₁ : has_deriv_within_at f f₁' s x) : f' = f₁' := smul_right_one_eq_iff.mp $ unique_diff_within_at.eq H h h₁ theorem has_deriv_at_filter_iff_tendsto : has_deriv_at_filter f f' x L ↔ tendsto (λ x' : 𝕜, ∥x' - x∥⁻¹ * ∥f x' - f x - (x' - x) • f'∥) L (𝓝 0) := has_fderiv_at_filter_iff_tendsto theorem has_deriv_within_at_iff_tendsto : has_deriv_within_at f f' s x ↔ tendsto (λ x', ∥x' - x∥⁻¹ * ∥f x' - f x - (x' - x) • f'∥) (nhds_within x s) (𝓝 0) := has_fderiv_at_filter_iff_tendsto theorem has_deriv_at_iff_tendsto : has_deriv_at f f' x ↔ tendsto (λ x', ∥x' - x∥⁻¹ * ∥f x' - f x - (x' - x) • f'∥) (𝓝 x) (𝓝 0) := has_fderiv_at_filter_iff_tendsto /-- If the domain has dimension one, then Fréchet derivative is equivalent to the classical definition with a limit. In this version we have to take the limit along the subset `-{x}`, because for `y=x` the slope equals zero due to the convention `0⁻¹=0`. -/ lemma has_deriv_at_filter_iff_tendsto_slope {x : 𝕜} {L : filter 𝕜} : has_deriv_at_filter f f' x L ↔ tendsto (λ y, (y - x)⁻¹ • (f y - f x)) (L ⊓ principal (-{x})) (𝓝 f') := begin conv_lhs { simp only [has_deriv_at_filter_iff_tendsto, (normed_field.norm_inv _).symm, (norm_smul _ _).symm, tendsto_zero_iff_norm_tendsto_zero.symm] }, conv_rhs { rw [← nhds_translation f', tendsto_comap_iff] }, refine (tendsto_inf_principal_nhds_iff_of_forall_eq $ by simp).symm.trans (tendsto_congr' _), rw mem_inf_principal, refine univ_mem_sets' (λ z hz, _), have : z ≠ x, by simpa [function.comp] using hz, simp only [mem_set_of_eq], rw [smul_sub, ← mul_smul, inv_mul_cancel (sub_ne_zero.2 this), one_smul] end lemma has_deriv_within_at_iff_tendsto_slope {x : 𝕜} {s : set 𝕜} : has_deriv_within_at f f' s x ↔ tendsto (λ y, (y - x)⁻¹ • (f y - f x)) (nhds_within x (s \ {x})) (𝓝 f') := begin simp only [has_deriv_within_at, nhds_within, diff_eq, lattice.inf_assoc.symm, inf_principal.symm], exact has_deriv_at_filter_iff_tendsto_slope end lemma has_deriv_within_at_iff_tendsto_slope' {x : 𝕜} {s : set 𝕜} (hs : x ∉ s) : has_deriv_within_at f f' s x ↔ tendsto (λ y, (y - x)⁻¹ • (f y - f x)) (nhds_within x s) (𝓝 f') := begin convert ← has_deriv_within_at_iff_tendsto_slope, exact diff_singleton_eq_self hs end lemma has_deriv_at_iff_tendsto_slope {x : 𝕜} : has_deriv_at f f' x ↔ tendsto (λ y, (y - x)⁻¹ • (f y - f x)) (nhds_within x (-{x})) (𝓝 f') := has_deriv_at_filter_iff_tendsto_slope theorem has_deriv_at_iff_is_o_nhds_zero : has_deriv_at f f' x ↔ is_o (λh, f (x + h) - f x - h • f') (λh, h) (𝓝 0) := has_fderiv_at_iff_is_o_nhds_zero theorem has_deriv_at_filter.mono (h : has_deriv_at_filter f f' x L₂) (hst : L₁ ≤ L₂) : has_deriv_at_filter f f' x L₁ := has_fderiv_at_filter.mono h hst theorem has_deriv_within_at.mono (h : has_deriv_within_at f f' t x) (hst : s ⊆ t) : has_deriv_within_at f f' s x := has_fderiv_within_at.mono h hst theorem has_deriv_at.has_deriv_at_filter (h : has_deriv_at f f' x) (hL : L ≤ 𝓝 x) : has_deriv_at_filter f f' x L := has_fderiv_at.has_fderiv_at_filter h hL theorem has_deriv_at.has_deriv_within_at (h : has_deriv_at f f' x) : has_deriv_within_at f f' s x := has_fderiv_at.has_fderiv_within_at h lemma has_deriv_within_at.differentiable_within_at (h : has_deriv_within_at f f' s x) : differentiable_within_at 𝕜 f s x := has_fderiv_within_at.differentiable_within_at h lemma has_deriv_at.differentiable_at (h : has_deriv_at f f' x) : differentiable_at 𝕜 f x := has_fderiv_at.differentiable_at h @[simp] lemma has_deriv_within_at_univ : has_deriv_within_at f f' univ x ↔ has_deriv_at f f' x := has_fderiv_within_at_univ theorem has_deriv_at_unique (h₀ : has_deriv_at f f₀' x) (h₁ : has_deriv_at f f₁' x) : f₀' = f₁' := smul_right_one_eq_iff.mp $ has_fderiv_at_unique h₀ h₁ lemma has_deriv_within_at_inter' (h : t ∈ nhds_within x s) : has_deriv_within_at f f' (s ∩ t) x ↔ has_deriv_within_at f f' s x := has_fderiv_within_at_inter' h lemma has_deriv_within_at_inter (h : t ∈ 𝓝 x) : has_deriv_within_at f f' (s ∩ t) x ↔ has_deriv_within_at f f' s x := has_fderiv_within_at_inter h lemma has_deriv_within_at.union (hs : has_deriv_within_at f f' s x) (ht : has_deriv_within_at f f' t x) : has_deriv_within_at f f' (s ∪ t) x := begin simp only [has_deriv_within_at, nhds_within_union], exact hs.join ht, end lemma has_deriv_within_at.nhds_within (h : has_deriv_within_at f f' s x) (ht : s ∈ nhds_within x t) : has_deriv_within_at f f' t x := (has_deriv_within_at_inter' ht).1 (h.mono (inter_subset_right _ _)) lemma has_deriv_within_at.has_deriv_at (h : has_deriv_within_at f f' s x) (hs : s ∈ 𝓝 x) : has_deriv_at f f' x := has_fderiv_within_at.has_fderiv_at h hs lemma differentiable_within_at.has_deriv_within_at (h : differentiable_within_at 𝕜 f s x) : has_deriv_within_at f (deriv_within f s x) s x := show has_fderiv_within_at _ _ _ _, by { convert h.has_fderiv_within_at, simp [deriv_within] } lemma differentiable_at.has_deriv_at (h : differentiable_at 𝕜 f x) : has_deriv_at f (deriv f x) x := show has_fderiv_at _ _ _, by { convert h.has_fderiv_at, simp [deriv] } lemma has_deriv_at.deriv (h : has_deriv_at f f' x) : deriv f x = f' := has_deriv_at_unique h.differentiable_at.has_deriv_at h lemma has_deriv_within_at.deriv_within (h : has_deriv_within_at f f' s x) (hxs : unique_diff_within_at 𝕜 s x) : deriv_within f s x = f' := hxs.eq_deriv _ h.differentiable_within_at.has_deriv_within_at h lemma fderiv_within_deriv_within : (fderiv_within 𝕜 f s x : 𝕜 → F) 1 = deriv_within f s x := rfl lemma deriv_within_fderiv_within : smul_right 1 (deriv_within f s x) = fderiv_within 𝕜 f s x := by simp [deriv_within] lemma fderiv_deriv : (fderiv 𝕜 f x : 𝕜 → F) 1 = deriv f x := rfl lemma deriv_fderiv : smul_right 1 (deriv f x) = fderiv 𝕜 f x := by simp [deriv] lemma differentiable_at.deriv_within (h : differentiable_at 𝕜 f x) (hxs : unique_diff_within_at 𝕜 s x) : deriv_within f s x = deriv f x := by { unfold deriv_within deriv, rw h.fderiv_within hxs } lemma deriv_within_subset (st : s ⊆ t) (ht : unique_diff_within_at 𝕜 s x) (h : differentiable_within_at 𝕜 f t x) : deriv_within f s x = deriv_within f t x := ((differentiable_within_at.has_deriv_within_at h).mono st).deriv_within ht @[simp] lemma deriv_within_univ : deriv_within f univ = deriv f := by { ext, unfold deriv_within deriv, rw fderiv_within_univ } lemma deriv_within_inter (ht : t ∈ 𝓝 x) (hs : unique_diff_within_at 𝕜 s x) : deriv_within f (s ∩ t) x = deriv_within f s x := by { unfold deriv_within, rw fderiv_within_inter ht hs } section congr /-! ### Congruence properties of derivatives -/ theorem has_deriv_at_filter_congr_of_mem_sets (hx : f₀ x = f₁ x) (h₀ : ∀ᶠ x in L, f₀ x = f₁ x) (h₁ : f₀' = f₁') : has_deriv_at_filter f₀ f₀' x L ↔ has_deriv_at_filter f₁ f₁' x L := has_fderiv_at_filter_congr_of_mem_sets hx h₀ (by simp [h₁]) lemma has_deriv_at_filter.congr_of_mem_sets (h : has_deriv_at_filter f f' x L) (hL : ∀ᶠ x in L, f₁ x = f x) (hx : f₁ x = f x) : has_deriv_at_filter f₁ f' x L := by rwa has_deriv_at_filter_congr_of_mem_sets hx hL rfl lemma has_deriv_within_at.congr_mono (h : has_deriv_within_at f f' s x) (ht : ∀x ∈ t, f₁ x = f x) (hx : f₁ x = f x) (h₁ : t ⊆ s) : has_deriv_within_at f₁ f' t x := has_fderiv_within_at.congr_mono h ht hx h₁ lemma has_deriv_within_at.congr (h : has_deriv_within_at f f' s x) (hs : ∀x ∈ s, f₁ x = f x) (hx : f₁ x = f x) : has_deriv_within_at f₁ f' s x := h.congr_mono hs hx (subset.refl _) lemma has_deriv_within_at.congr_of_mem_nhds_within (h : has_deriv_within_at f f' s x) (h₁ : ∀ᶠ y in nhds_within x s, f₁ y = f y) (hx : f₁ x = f x) : has_deriv_within_at f₁ f' s x := has_deriv_at_filter.congr_of_mem_sets h h₁ hx lemma has_deriv_at.congr_of_mem_nhds (h : has_deriv_at f f' x) (h₁ : ∀ᶠ y in 𝓝 x, f₁ y = f y) : has_deriv_at f₁ f' x := has_deriv_at_filter.congr_of_mem_sets h h₁ (mem_of_nhds h₁ : _) lemma deriv_within_congr_of_mem_nhds_within (hs : unique_diff_within_at 𝕜 s x) (hL : ∀ᶠ y in nhds_within x s, f₁ y = f y) (hx : f₁ x = f x) : deriv_within f₁ s x = deriv_within f s x := by { unfold deriv_within, rw fderiv_within_congr_of_mem_nhds_within hs hL hx } lemma deriv_within_congr (hs : unique_diff_within_at 𝕜 s x) (hL : ∀y∈s, f₁ y = f y) (hx : f₁ x = f x) : deriv_within f₁ s x = deriv_within f s x := by { unfold deriv_within, rw fderiv_within_congr hs hL hx } lemma deriv_congr_of_mem_nhds (hL : ∀ᶠ y in 𝓝 x, f₁ y = f y) : deriv f₁ x = deriv f x := by { unfold deriv, rwa fderiv_congr_of_mem_nhds } end congr section id /-! ### Derivative of the identity -/ variables (s x L) theorem has_deriv_at_filter_id : has_deriv_at_filter id 1 x L := (is_o_zero _ _).congr_left $ by simp theorem has_deriv_within_at_id : has_deriv_within_at id 1 s x := has_deriv_at_filter_id _ _ theorem has_deriv_at_id : has_deriv_at id 1 x := has_deriv_at_filter_id _ _ lemma deriv_id : deriv id x = 1 := has_deriv_at.deriv (has_deriv_at_id x) @[simp] lemma deriv_id' : deriv (@id 𝕜) = λ _, 1 := funext deriv_id lemma deriv_within_id (hxs : unique_diff_within_at 𝕜 s x) : deriv_within id s x = 1 := by { unfold deriv_within, rw fderiv_within_id, simp, assumption } end id section const /-! ### Derivative of constant functions -/ variables (c : F) (s x L) theorem has_deriv_at_filter_const : has_deriv_at_filter (λ x, c) 0 x L := (is_o_zero _ _).congr_left $ λ _, by simp [continuous_linear_map.zero_apply, sub_self] theorem has_deriv_within_at_const : has_deriv_within_at (λ x, c) 0 s x := has_deriv_at_filter_const _ _ _ theorem has_deriv_at_const : has_deriv_at (λ x, c) 0 x := has_deriv_at_filter_const _ _ _ lemma deriv_const : deriv (λ x, c) x = 0 := has_deriv_at.deriv (has_deriv_at_const x c) @[simp] lemma deriv_const' : deriv (λ x:𝕜, c) = λ x, 0 := funext (λ x, deriv_const x c) lemma deriv_within_const (hxs : unique_diff_within_at 𝕜 s x) : deriv_within (λ x, c) s x = 0 := by { rw (differentiable_at_const _).deriv_within hxs, apply deriv_const } end const section is_linear_map /-! ### Derivative of linear maps -/ variables (s x L) [is_linear_map 𝕜 f] lemma is_linear_map.has_deriv_at_filter : has_deriv_at_filter f (f 1) x L := (is_o_zero _ _).congr_left begin intro y, simp [add_smul], rw ← is_linear_map.smul f x, rw ← is_linear_map.smul f y, simp end lemma is_linear_map.has_deriv_within_at : has_deriv_within_at f (f 1) s x := is_linear_map.has_deriv_at_filter _ _ lemma is_linear_map.has_deriv_at : has_deriv_at f (f 1) x := is_linear_map.has_deriv_at_filter _ _ lemma is_linear_map.differentiable_at : differentiable_at 𝕜 f x := (is_linear_map.has_deriv_at _).differentiable_at lemma is_linear_map.differentiable_within_at : differentiable_within_at 𝕜 f s x := (is_linear_map.differentiable_at _).differentiable_within_at @[simp] lemma is_linear_map.deriv : deriv f x = f 1 := has_deriv_at.deriv (is_linear_map.has_deriv_at _) lemma is_linear_map.deriv_within (hxs : unique_diff_within_at 𝕜 s x) : deriv_within f s x = f 1 := begin rw differentiable_at.deriv_within (is_linear_map.differentiable_at _) hxs, apply is_linear_map.deriv, assumption end lemma is_linear_map.differentiable : differentiable 𝕜 f := λ x, is_linear_map.differentiable_at _ lemma is_linear_map.differentiable_on : differentiable_on 𝕜 f s := is_linear_map.differentiable.differentiable_on end is_linear_map section add /-! ### Derivative of the sum of two functions -/ theorem has_deriv_at_filter.add (hf : has_deriv_at_filter f f' x L) (hg : has_deriv_at_filter g g' x L) : has_deriv_at_filter (λ y, f y + g y) (f' + g') x L := (hf.add hg).congr_left $ by simp [add_smul, smul_add] theorem has_deriv_within_at.add (hf : has_deriv_within_at f f' s x) (hg : has_deriv_within_at g g' s x) : has_deriv_within_at (λ y, f y + g y) (f' + g') s x := hf.add hg theorem has_deriv_at.add (hf : has_deriv_at f f' x) (hg : has_deriv_at g g' x) : has_deriv_at (λ x, f x + g x) (f' + g') x := hf.add hg lemma deriv_within_add (hxs : unique_diff_within_at 𝕜 s x) (hf : differentiable_within_at 𝕜 f s x) (hg : differentiable_within_at 𝕜 g s x) : deriv_within (λy, f y + g y) s x = deriv_within f s x + deriv_within g s x := (hf.has_deriv_within_at.add hg.has_deriv_within_at).deriv_within hxs lemma deriv_add (hf : differentiable_at 𝕜 f x) (hg : differentiable_at 𝕜 g x) : deriv (λy, f y + g y) x = deriv f x + deriv g x := (hf.has_deriv_at.add hg.has_deriv_at).deriv theorem has_deriv_at_filter.add_const (hf : has_deriv_at_filter f f' x L) (c : F) : has_deriv_at_filter (λ y, f y + c) f' x L := add_zero f' ▸ hf.add (has_deriv_at_filter_const x L c) theorem has_deriv_within_at.add_const (hf : has_deriv_within_at f f' s x) (c : F) : has_deriv_within_at (λ y, f y + c) f' s x := hf.add_const c theorem has_deriv_at.add_const (hf : has_deriv_at f f' x) (c : F) : has_deriv_at (λ x, f x + c) f' x := hf.add_const c lemma deriv_within_add_const (hxs : unique_diff_within_at 𝕜 s x) (hf : differentiable_within_at 𝕜 f s x) (c : F) : deriv_within (λy, f y + c) s x = deriv_within f s x := (hf.has_deriv_within_at.add_const c).deriv_within hxs lemma deriv_add_const (hf : differentiable_at 𝕜 f x) (c : F) : deriv (λy, f y + c) x = deriv f x := (hf.has_deriv_at.add_const c).deriv theorem has_deriv_at_filter.const_add (c : F) (hf : has_deriv_at_filter f f' x L) : has_deriv_at_filter (λ y, c + f y) f' x L := zero_add f' ▸ (has_deriv_at_filter_const x L c).add hf theorem has_deriv_within_at.const_add (c : F) (hf : has_deriv_within_at f f' s x) : has_deriv_within_at (λ y, c + f y) f' s x := hf.const_add c theorem has_deriv_at.const_add (c : F) (hf : has_deriv_at f f' x) : has_deriv_at (λ x, c + f x) f' x := hf.const_add c lemma deriv_within_const_add (hxs : unique_diff_within_at 𝕜 s x) (c : F) (hf : differentiable_within_at 𝕜 f s x) : deriv_within (λy, c + f y) s x = deriv_within f s x := (hf.has_deriv_within_at.const_add c).deriv_within hxs lemma deriv_const_add (c : F) (hf : differentiable_at 𝕜 f x) : deriv (λy, c + f y) x = deriv f x := (hf.has_deriv_at.const_add c).deriv end add section mul_vector /-! ### Derivative of the multiplication of a scalar function and a vector function -/ variables {c : 𝕜 → 𝕜} {c' : 𝕜} theorem has_deriv_within_at.smul (hc : has_deriv_within_at c c' s x) (hf : has_deriv_within_at f f' s x) : has_deriv_within_at (λ y, c y • f y) (c x • f' + c' • f x) s x := begin show has_fderiv_within_at _ _ _ _, convert has_fderiv_within_at.smul hc hf, ext, simp [smul_add, (mul_smul _ _ _).symm, mul_comm] end theorem has_deriv_at.smul (hc : has_deriv_at c c' x) (hf : has_deriv_at f f' x) : has_deriv_at (λ y, c y • f y) (c x • f' + c' • f x) x := begin rw [← has_deriv_within_at_univ] at *, exact hc.smul hf end lemma deriv_within_smul (hxs : unique_diff_within_at 𝕜 s x) (hc : differentiable_within_at 𝕜 c s x) (hf : differentiable_within_at 𝕜 f s x) : deriv_within (λ y, c y • f y) s x = c x • deriv_within f s x + (deriv_within c s x) • f x := (hc.has_deriv_within_at.smul hf.has_deriv_within_at).deriv_within hxs lemma deriv_smul (hc : differentiable_at 𝕜 c x) (hf : differentiable_at 𝕜 f x) : deriv (λ y, c y • f y) x = c x • deriv f x + (deriv c x) • f x := (hc.has_deriv_at.smul hf.has_deriv_at).deriv theorem has_deriv_within_at.smul_const (hc : has_deriv_within_at c c' s x) (f : F) : has_deriv_within_at (λ y, c y • f) (c' • f) s x := begin have := hc.smul (has_deriv_within_at_const x s f), rwa [smul_zero, zero_add] at this end theorem has_deriv_at.smul_const (hc : has_deriv_at c c' x) (f : F) : has_deriv_at (λ y, c y • f) (c' • f) x := begin rw [← has_deriv_within_at_univ] at *, exact hc.smul_const f end lemma deriv_within_smul_const (hxs : unique_diff_within_at 𝕜 s x) (hc : differentiable_within_at 𝕜 c s x) (f : F) : deriv_within (λ y, c y • f) s x = (deriv_within c s x) • f := (hc.has_deriv_within_at.smul_const f).deriv_within hxs lemma deriv_smul_const (hc : differentiable_at 𝕜 c x) (f : F) : deriv (λ y, c y • f) x = (deriv c x) • f := (hc.has_deriv_at.smul_const f).deriv theorem has_deriv_within_at.const_smul (c : 𝕜) (hf : has_deriv_within_at f f' s x) : has_deriv_within_at (λ y, c • f y) (c • f') s x := begin convert (has_deriv_within_at_const x s c).smul hf, rw [zero_smul, add_zero] end theorem has_deriv_at.const_smul (c : 𝕜) (hf : has_deriv_at f f' x) : has_deriv_at (λ y, c • f y) (c • f') x := begin rw [← has_deriv_within_at_univ] at *, exact hf.const_smul c end lemma deriv_within_const_smul (hxs : unique_diff_within_at 𝕜 s x) (c : 𝕜) (hf : differentiable_within_at 𝕜 f s x) : deriv_within (λ y, c • f y) s x = c • deriv_within f s x := (hf.has_deriv_within_at.const_smul c).deriv_within hxs lemma deriv_const_smul (c : 𝕜) (hf : differentiable_at 𝕜 f x) : deriv (λ y, c • f y) x = c • deriv f x := (hf.has_deriv_at.const_smul c).deriv end mul_vector section neg /-! ### Derivative of the negative of a function -/ theorem has_deriv_at_filter.neg (h : has_deriv_at_filter f f' x L) : has_deriv_at_filter (λ x, -f x) (-f') x L := h.neg.congr (by simp) (by simp) theorem has_deriv_within_at.neg (h : has_deriv_within_at f f' s x) : has_deriv_within_at (λ x, -f x) (-f') s x := h.neg theorem has_deriv_at.neg (h : has_deriv_at f f' x) : has_deriv_at (λ x, -f x) (-f') x := h.neg lemma deriv_within_neg (hxs : unique_diff_within_at 𝕜 s x) (h : differentiable_within_at 𝕜 f s x) : deriv_within (λy, -f y) s x = - deriv_within f s x := h.has_deriv_within_at.neg.deriv_within hxs lemma deriv_neg : deriv (λy, -f y) x = - deriv f x := if h : differentiable_at 𝕜 f x then h.has_deriv_at.neg.deriv else have ¬differentiable_at 𝕜 (λ y, -f y) x, from λ h', by simpa only [neg_neg] using h'.neg, by simp only [deriv_zero_of_not_differentiable_at h, deriv_zero_of_not_differentiable_at this, neg_zero] @[simp] lemma deriv_neg' : deriv (λy, -f y) = (λ x, - deriv f x) := funext $ λ x, deriv_neg end neg section sub /-! ### Derivative of the difference of two functions -/ theorem has_deriv_at_filter.sub (hf : has_deriv_at_filter f f' x L) (hg : has_deriv_at_filter g g' x L) : has_deriv_at_filter (λ x, f x - g x) (f' - g') x L := hf.add hg.neg theorem has_deriv_within_at.sub (hf : has_deriv_within_at f f' s x) (hg : has_deriv_within_at g g' s x) : has_deriv_within_at (λ x, f x - g x) (f' - g') s x := hf.sub hg theorem has_deriv_at.sub (hf : has_deriv_at f f' x) (hg : has_deriv_at g g' x) : has_deriv_at (λ x, f x - g x) (f' - g') x := hf.sub hg lemma deriv_within_sub (hxs : unique_diff_within_at 𝕜 s x) (hf : differentiable_within_at 𝕜 f s x) (hg : differentiable_within_at 𝕜 g s x) : deriv_within (λy, f y - g y) s x = deriv_within f s x - deriv_within g s x := (hf.has_deriv_within_at.sub hg.has_deriv_within_at).deriv_within hxs lemma deriv_sub (hf : differentiable_at 𝕜 f x) (hg : differentiable_at 𝕜 g x) : deriv (λ y, f y - g y) x = deriv f x - deriv g x := (hf.has_deriv_at.sub hg.has_deriv_at).deriv theorem has_deriv_at_filter.is_O_sub (h : has_deriv_at_filter f f' x L) : is_O (λ x', f x' - f x) (λ x', x' - x) L := has_fderiv_at_filter.is_O_sub h theorem has_deriv_at_filter.sub_const (hf : has_deriv_at_filter f f' x L) (c : F) : has_deriv_at_filter (λ x, f x - c) f' x L := hf.add_const (-c) theorem has_deriv_within_at.sub_const (hf : has_deriv_within_at f f' s x) (c : F) : has_deriv_within_at (λ x, f x - c) f' s x := hf.sub_const c theorem has_deriv_at.sub_const (hf : has_deriv_at f f' x) (c : F) : has_deriv_at (λ x, f x - c) f' x := hf.sub_const c lemma deriv_within_sub_const (hxs : unique_diff_within_at 𝕜 s x) (hf : differentiable_within_at 𝕜 f s x) (c : F) : deriv_within (λy, f y - c) s x = deriv_within f s x := (hf.has_deriv_within_at.sub_const c).deriv_within hxs lemma deriv_sub_const (c : F) (hf : differentiable_at 𝕜 f x) : deriv (λ y, f y - c) x = deriv f x := (hf.has_deriv_at.sub_const c).deriv theorem has_deriv_at_filter.const_sub (c : F) (hf : has_deriv_at_filter f f' x L) : has_deriv_at_filter (λ x, c - f x) (-f') x L := hf.neg.const_add c theorem has_deriv_within_at.const_sub (c : F) (hf : has_deriv_within_at f f' s x) : has_deriv_within_at (λ x, c - f x) (-f') s x := hf.const_sub c theorem has_deriv_at.const_sub (c : F) (hf : has_deriv_at f f' x) : has_deriv_at (λ x, c - f x) (-f') x := hf.const_sub c lemma deriv_within_const_sub (hxs : unique_diff_within_at 𝕜 s x) (c : F) (hf : differentiable_within_at 𝕜 f s x) : deriv_within (λy, c - f y) s x = -deriv_within f s x := (hf.has_deriv_within_at.const_sub c).deriv_within hxs lemma deriv_const_sub (c : F) (hf : differentiable_at 𝕜 f x) : deriv (λ y, c - f y) x = -deriv f x := (hf.has_deriv_at.const_sub c).deriv end sub section continuous /-! ### Continuity of a function admitting a derivative -/ theorem has_deriv_at_filter.tendsto_nhds (hL : L ≤ 𝓝 x) (h : has_deriv_at_filter f f' x L) : tendsto f L (𝓝 (f x)) := has_fderiv_at_filter.tendsto_nhds hL h theorem has_deriv_within_at.continuous_within_at (h : has_deriv_within_at f f' s x) : continuous_within_at f s x := has_deriv_at_filter.tendsto_nhds lattice.inf_le_left h theorem has_deriv_at.continuous_at (h : has_deriv_at f f' x) : continuous_at f x := has_deriv_at_filter.tendsto_nhds (le_refl _) h end continuous section cartesian_product /-! ### Derivative of the cartesian product of two functions -/ variables {G : Type w} [normed_group G] [normed_space 𝕜 G] variables {f₂ : 𝕜 → G} {f₂' : G} lemma has_deriv_at_filter.prod (hf₁ : has_deriv_at_filter f₁ f₁' x L) (hf₂ : has_deriv_at_filter f₂ f₂' x L) : has_deriv_at_filter (λ x, (f₁ x, f₂ x)) (f₁', f₂') x L := show has_fderiv_at_filter _ _ _ _, by convert has_fderiv_at_filter.prod hf₁ hf₂ lemma has_deriv_within_at.prod (hf₁ : has_deriv_within_at f₁ f₁' s x) (hf₂ : has_deriv_within_at f₂ f₂' s x) : has_deriv_within_at (λ x, (f₁ x, f₂ x)) (f₁', f₂') s x := hf₁.prod hf₂ lemma has_deriv_at.prod (hf₁ : has_deriv_at f₁ f₁' x) (hf₂ : has_deriv_at f₂ f₂' x) : has_deriv_at (λ x, (f₁ x, f₂ x)) (f₁', f₂') x := hf₁.prod hf₂ end cartesian_product section composition /-! ### Derivative of the composition of a vector valued function and a scalar function -/ variables {h : 𝕜 → 𝕜} {h' : 𝕜} /- For composition lemmas, we put x explicit to help the elaborator, as otherwise Lean tends to get confused since there are too many possibilities for composition -/ variable (x) theorem has_deriv_at_filter.comp (hg : has_deriv_at_filter g g' (h x) (L.map h)) (hh : has_deriv_at_filter h h' x L) : has_deriv_at_filter (g ∘ h) (h' • g') x L := have (smul_right 1 g' : 𝕜 →L[𝕜] _).comp (smul_right 1 h' : 𝕜 →L[𝕜] _) = smul_right 1 (h' • g'), by { ext, simp [mul_smul] }, begin unfold has_deriv_at_filter, rw ← this, exact has_fderiv_at_filter.comp x hg hh, end theorem has_deriv_within_at.comp {t : set 𝕜} (hg : has_deriv_within_at g g' t (h x)) (hh : has_deriv_within_at h h' s x) (hst : s ⊆ h ⁻¹' t) : has_deriv_within_at (g ∘ h) (h' • g') s x := begin apply has_deriv_at_filter.comp _ (has_deriv_at_filter.mono hg _) hh, calc map h (nhds_within x s) ≤ nhds_within (h x) (h '' s) : hh.continuous_within_at.tendsto_nhds_within_image ... ≤ nhds_within (h x) t : nhds_within_mono _ (image_subset_iff.mpr hst) end /-- The chain rule. -/ theorem has_deriv_at.comp (hg : has_deriv_at g g' (h x)) (hh : has_deriv_at h h' x) : has_deriv_at (g ∘ h) (h' • g') x := (hg.mono hh.continuous_at).comp x hh theorem has_deriv_at.comp_has_deriv_within_at (hg : has_deriv_at g g' (h x)) (hh : has_deriv_within_at h h' s x) : has_deriv_within_at (g ∘ h) (h' • g') s x := begin rw ← has_deriv_within_at_univ at hg, exact has_deriv_within_at.comp x hg hh subset_preimage_univ end lemma deriv_within.comp (hg : differentiable_within_at 𝕜 g t (h x)) (hh : differentiable_within_at 𝕜 h s x) (hs : s ⊆ h ⁻¹' t) (hxs : unique_diff_within_at 𝕜 s x) : deriv_within (g ∘ h) s x = deriv_within h s x • deriv_within g t (h x) := begin apply has_deriv_within_at.deriv_within _ hxs, exact has_deriv_within_at.comp x (hg.has_deriv_within_at) (hh.has_deriv_within_at) hs end lemma deriv.comp (hg : differentiable_at 𝕜 g (h x)) (hh : differentiable_at 𝕜 h x) : deriv (g ∘ h) x = deriv h x • deriv g (h x) := begin apply has_deriv_at.deriv, exact has_deriv_at.comp x hg.has_deriv_at hh.has_deriv_at end end composition section composition_vector /-! ### Derivative of the composition of a function between vector spaces and of a function defined on `𝕜` -/ variables {l : F → E} {l' : F →L[𝕜] E} variable (x) /-- The composition `l ∘ f` where `l : F → E` and `f : 𝕜 → F`, has a derivative within a set equal to the Fréchet derivative of `l` applied to the derivative of `f`. -/ theorem has_fderiv_within_at.comp_has_deriv_within_at {t : set F} (hl : has_fderiv_within_at l l' t (f x)) (hf : has_deriv_within_at f f' s x) (hst : s ⊆ f ⁻¹' t) : has_deriv_within_at (l ∘ f) (l' (f')) s x := begin rw has_deriv_within_at_iff_has_fderiv_within_at, convert has_fderiv_within_at.comp x hl hf hst, ext, simp end /-- The composition `l ∘ f` where `l : F → E` and `f : 𝕜 → F`, has a derivative equal to the Fréchet derivative of `l` applied to the derivative of `f`. -/ theorem has_fderiv_at.comp_has_deriv_at (hl : has_fderiv_at l l' (f x)) (hf : has_deriv_at f f' x) : has_deriv_at (l ∘ f) (l' (f')) x := begin rw has_deriv_at_iff_has_fderiv_at, convert has_fderiv_at.comp x hl hf, ext, simp end theorem has_fderiv_at.comp_has_deriv_within_at (hl : has_fderiv_at l l' (f x)) (hf : has_deriv_within_at f f' s x) : has_deriv_within_at (l ∘ f) (l' (f')) s x := begin rw ← has_fderiv_within_at_univ at hl, exact has_fderiv_within_at.comp_has_deriv_within_at x hl hf subset_preimage_univ end lemma fderiv_within.comp_deriv_within {t : set F} (hl : differentiable_within_at 𝕜 l t (f x)) (hf : differentiable_within_at 𝕜 f s x) (hs : s ⊆ f ⁻¹' t) (hxs : unique_diff_within_at 𝕜 s x) : deriv_within (l ∘ f) s x = (fderiv_within 𝕜 l t (f x) : F → E) (deriv_within f s x) := begin apply has_deriv_within_at.deriv_within _ hxs, exact (hl.has_fderiv_within_at).comp_has_deriv_within_at x (hf.has_deriv_within_at) hs end lemma fderiv.comp_deriv (hl : differentiable_at 𝕜 l (f x)) (hf : differentiable_at 𝕜 f x) : deriv (l ∘ f) x = (fderiv 𝕜 l (f x) : F → E) (deriv f x) := begin apply has_deriv_at.deriv _, exact (hl.has_fderiv_at).comp_has_deriv_at x (hf.has_deriv_at) end end composition_vector section mul /-! ### Derivative of the multiplication of two scalar functions -/ variables {c d : 𝕜 → 𝕜} {c' d' : 𝕜} theorem has_deriv_within_at.mul (hc : has_deriv_within_at c c' s x) (hd : has_deriv_within_at d d' s x) : has_deriv_within_at (λ y, c y * d y) (c' * d x + c x * d') s x := begin convert hc.smul hd using 1, rw [smul_eq_mul, smul_eq_mul, add_comm] end theorem has_deriv_at.mul (hc : has_deriv_at c c' x) (hd : has_deriv_at d d' x) : has_deriv_at (λ y, c y * d y) (c' * d x + c x * d') x := begin rw [← has_deriv_within_at_univ] at *, exact hc.mul hd end lemma deriv_within_mul (hxs : unique_diff_within_at 𝕜 s x) (hc : differentiable_within_at 𝕜 c s x) (hd : differentiable_within_at 𝕜 d s x) : deriv_within (λ y, c y * d y) s x = deriv_within c s x * d x + c x * deriv_within d s x := (hc.has_deriv_within_at.mul hd.has_deriv_within_at).deriv_within hxs lemma deriv_mul (hc : differentiable_at 𝕜 c x) (hd : differentiable_at 𝕜 d x) : deriv (λ y, c y * d y) x = deriv c x * d x + c x * deriv d x := (hc.has_deriv_at.mul hd.has_deriv_at).deriv theorem has_deriv_within_at.mul_const (hc : has_deriv_within_at c c' s x) (d : 𝕜) : has_deriv_within_at (λ y, c y * d) (c' * d) s x := begin convert hc.mul (has_deriv_within_at_const x s d), rw [mul_zero, add_zero] end theorem has_deriv_at.mul_const (hc : has_deriv_at c c' x) (d : 𝕜) : has_deriv_at (λ y, c y * d) (c' * d) x := begin rw [← has_deriv_within_at_univ] at *, exact hc.mul_const d end lemma deriv_within_mul_const (hxs : unique_diff_within_at 𝕜 s x) (hc : differentiable_within_at 𝕜 c s x) (d : 𝕜) : deriv_within (λ y, c y * d) s x = deriv_within c s x * d := (hc.has_deriv_within_at.mul_const d).deriv_within hxs lemma deriv_mul_const (hc : differentiable_at 𝕜 c x) (d : 𝕜) : deriv (λ y, c y * d) x = deriv c x * d := (hc.has_deriv_at.mul_const d).deriv theorem has_deriv_within_at.const_mul (c : 𝕜) (hd : has_deriv_within_at d d' s x) : has_deriv_within_at (λ y, c * d y) (c * d') s x := begin convert (has_deriv_within_at_const x s c).mul hd, rw [zero_mul, zero_add] end theorem has_deriv_at.const_mul (c : 𝕜) (hd : has_deriv_at d d' x) : has_deriv_at (λ y, c * d y) (c * d') x := begin rw [← has_deriv_within_at_univ] at *, exact hd.const_mul c end lemma deriv_within_const_mul (hxs : unique_diff_within_at 𝕜 s x) (c : 𝕜) (hd : differentiable_within_at 𝕜 d s x) : deriv_within (λ y, c * d y) s x = c * deriv_within d s x := (hd.has_deriv_within_at.const_mul c).deriv_within hxs lemma deriv_const_mul (c : 𝕜) (hd : differentiable_at 𝕜 d x) : deriv (λ y, c * d y) x = c * deriv d x := (hd.has_deriv_at.const_mul c).deriv end mul section inverse /-! ### Derivative of `x ↦ x⁻¹` -/ lemma has_deriv_at_inv_one : has_deriv_at (λx, x⁻¹) (-1) (1 : 𝕜) := begin rw has_deriv_at_iff_is_o_nhds_zero, have : is_o (λ (h : 𝕜), h^2 * (1 + h)⁻¹) (λ (h : 𝕜), h * 1) (𝓝 0), { have : tendsto (λ (h : 𝕜), (1 + h)⁻¹) (𝓝 0) (𝓝 (1 + 0)⁻¹) := ((tendsto_const_nhds).add tendsto_id).inv' (by norm_num), exact is_o.mul_is_O (is_o_pow_id one_lt_two) (is_O_one_of_tendsto _ this) }, apply this.congr' _ _, { have : metric.ball (0 : 𝕜) 1 ∈ 𝓝 (0 : 𝕜), from metric.ball_mem_nhds 0 zero_lt_one, filter_upwards [this], assume h hx, have : 0 < ∥1 + h∥ := calc 0 < ∥(1:𝕜)∥ - ∥-h∥ : by rwa [norm_neg, sub_pos, ← dist_zero_right h, normed_field.norm_one] ... ≤ ∥1 - -h∥ : norm_sub_norm_le _ _ ... = ∥1 + h∥ : by simp, have : 1 + h ≠ 0 := (norm_pos_iff (1 + h)).mp this, simp only [mem_set_of_eq, smul_eq_mul, inv_one], field_simp [this, -add_comm], ring }, { exact univ_mem_sets' mul_one } end theorem has_deriv_at_inv (x_ne_zero : x ≠ 0) : has_deriv_at (λy, y⁻¹) (-(x^2)⁻¹) x := begin have A : has_deriv_at (λy, y⁻¹) (-1) (x⁻¹ * x : 𝕜), by { simp only [inv_mul_cancel x_ne_zero, has_deriv_at_inv_one] }, have B : has_deriv_at (λy, x⁻¹ * y) (x⁻¹) x, by simpa only [mul_one] using (has_deriv_at_id x).const_mul x⁻¹, convert (A.comp x B : _).const_mul x⁻¹, { ext y, rw [function.comp_apply, mul_inv', inv_inv', mul_comm, mul_assoc, mul_inv_cancel x_ne_zero, mul_one] }, { rw [pow_two, mul_inv', smul_eq_mul, mul_neg_one, neg_mul_eq_mul_neg] } end theorem has_deriv_within_at_inv (x_ne_zero : x ≠ 0) (s : set 𝕜) : has_deriv_within_at (λx, x⁻¹) (-(x^2)⁻¹) s x := (has_deriv_at_inv x_ne_zero).has_deriv_within_at lemma differentiable_at_inv (x_ne_zero : x ≠ 0) : differentiable_at 𝕜 (λx, x⁻¹) x := (has_deriv_at_inv x_ne_zero).differentiable_at lemma differentiable_within_at_inv (x_ne_zero : x ≠ 0) : differentiable_within_at 𝕜 (λx, x⁻¹) s x := (differentiable_at_inv x_ne_zero).differentiable_within_at lemma differentiable_on_inv : differentiable_on 𝕜 (λx:𝕜, x⁻¹) {x | x ≠ 0} := λx hx, differentiable_within_at_inv hx lemma deriv_inv (x_ne_zero : x ≠ 0) : deriv (λx, x⁻¹) x = -(x^2)⁻¹ := (has_deriv_at_inv x_ne_zero).deriv lemma deriv_within_inv (x_ne_zero : x ≠ 0) (hxs : unique_diff_within_at 𝕜 s x) : deriv_within (λx, x⁻¹) s x = -(x^2)⁻¹ := begin rw differentiable_at.deriv_within (differentiable_at_inv x_ne_zero) hxs, exact deriv_inv x_ne_zero end lemma has_fderiv_at_inv (x_ne_zero : x ≠ 0) : has_fderiv_at (λx, x⁻¹) (smul_right 1 (-(x^2)⁻¹) : 𝕜 →L[𝕜] 𝕜) x := has_deriv_at_inv x_ne_zero lemma has_fderiv_within_at_inv (x_ne_zero : x ≠ 0) : has_fderiv_within_at (λx, x⁻¹) (smul_right 1 (-(x^2)⁻¹) : 𝕜 →L[𝕜] 𝕜) s x := (has_fderiv_at_inv x_ne_zero).has_fderiv_within_at lemma fderiv_inv (x_ne_zero : x ≠ 0) : fderiv 𝕜 (λx, x⁻¹) x = smul_right 1 (-(x^2)⁻¹) := (has_fderiv_at_inv x_ne_zero).fderiv lemma fderiv_within_inv (x_ne_zero : x ≠ 0) (hxs : unique_diff_within_at 𝕜 s x) : fderiv_within 𝕜 (λx, x⁻¹) s x = smul_right 1 (-(x^2)⁻¹) := begin rw differentiable_at.fderiv_within (differentiable_at_inv x_ne_zero) hxs, exact fderiv_inv x_ne_zero end end inverse section division /-! ### Derivative of `x ↦ c x / d x` -/ variables {c d : 𝕜 → 𝕜} {c' d' : 𝕜} lemma has_deriv_within_at.div (hc : has_deriv_within_at c c' s x) (hd : has_deriv_within_at d d' s x) (hx : d x ≠ 0) : has_deriv_within_at (λ y, c y / d y) ((c' * d x - c x * d') / (d x)^2) s x := begin have A : (d x)⁻¹ * (d x)⁻¹ * (c' * d x) = (d x)⁻¹ * c', by rw [← mul_assoc, mul_comm, ← mul_assoc, ← mul_assoc, mul_inv_cancel hx, one_mul], convert hc.mul ((has_deriv_at_inv hx).comp_has_deriv_within_at x hd), simp [div_eq_inv_mul, pow_two, mul_inv', mul_add, A], ring end lemma has_deriv_at.div (hc : has_deriv_at c c' x) (hd : has_deriv_at d d' x) (hx : d x ≠ 0) : has_deriv_at (λ y, c y / d y) ((c' * d x - c x * d') / (d x)^2) x := begin rw ← has_deriv_within_at_univ at *, exact hc.div hd hx end lemma differentiable_within_at.div (hc : differentiable_within_at 𝕜 c s x) (hd : differentiable_within_at 𝕜 d s x) (hx : d x ≠ 0) : differentiable_within_at 𝕜 (λx, c x / d x) s x := ((hc.has_deriv_within_at).div (hd.has_deriv_within_at) hx).differentiable_within_at lemma differentiable_at.div (hc : differentiable_at 𝕜 c x) (hd : differentiable_at 𝕜 d x) (hx : d x ≠ 0) : differentiable_at 𝕜 (λx, c x / d x) x := ((hc.has_deriv_at).div (hd.has_deriv_at) hx).differentiable_at lemma differentiable_on.div (hc : differentiable_on 𝕜 c s) (hd : differentiable_on 𝕜 d s) (hx : ∀ x ∈ s, d x ≠ 0) : differentiable_on 𝕜 (λx, c x / d x) s := λx h, (hc x h).div (hd x h) (hx x h) lemma differentiable.div (hc : differentiable 𝕜 c) (hd : differentiable 𝕜 d) (hx : ∀ x, d x ≠ 0) : differentiable 𝕜 (λx, c x / d x) := λx, (hc x).div (hd x) (hx x) lemma deriv_within_div (hc : differentiable_within_at 𝕜 c s x) (hd : differentiable_within_at 𝕜 d s x) (hx : d x ≠ 0) (hxs : unique_diff_within_at 𝕜 s x) : deriv_within (λx, c x / d x) s x = ((deriv_within c s x) * d x - c x * (deriv_within d s x)) / (d x)^2 := ((hc.has_deriv_within_at).div (hd.has_deriv_within_at) hx).deriv_within hxs lemma deriv_div (hc : differentiable_at 𝕜 c x) (hd : differentiable_at 𝕜 d x) (hx : d x ≠ 0) : deriv (λx, c x / d x) x = ((deriv c x) * d x - c x * (deriv d x)) / (d x)^2 := ((hc.has_deriv_at).div (hd.has_deriv_at) hx).deriv end division end namespace polynomial /-! ### Derivative of a polynomial -/ variables {x : 𝕜} {s : set 𝕜} variable (p : polynomial 𝕜) /-- The derivative (in the analysis sense) of a polynomial `p` is given by `p.derivative`. -/ protected lemma has_deriv_at (x : 𝕜) : has_deriv_at (λx, p.eval x) (p.derivative.eval x) x := begin apply p.induction_on, { simp [has_deriv_at_const] }, { assume p q hp hq, convert hp.add hq; simp }, { assume n a h, convert h.mul (has_deriv_at_id x), { ext y, simp [pow_add, mul_assoc] }, { simp [pow_add], ring } } end protected theorem has_deriv_within_at (x : 𝕜) (s : set 𝕜) : has_deriv_within_at (λx, p.eval x) (p.derivative.eval x) s x := (p.has_deriv_at x).has_deriv_within_at protected lemma differentiable_at : differentiable_at 𝕜 (λx, p.eval x) x := (p.has_deriv_at x).differentiable_at protected lemma differentiable_within_at : differentiable_within_at 𝕜 (λx, p.eval x) s x := p.differentiable_at.differentiable_within_at protected lemma differentiable : differentiable 𝕜 (λx, p.eval x) := λx, p.differentiable_at protected lemma differentiable_on : differentiable_on 𝕜 (λx, p.eval x) s := p.differentiable.differentiable_on @[simp] protected lemma deriv : deriv (λx, p.eval x) x = p.derivative.eval x := (p.has_deriv_at x).deriv protected lemma deriv_within (hxs : unique_diff_within_at 𝕜 s x) : deriv_within (λx, p.eval x) s x = p.derivative.eval x := begin rw differentiable_at.deriv_within p.differentiable_at hxs, exact p.deriv end protected lemma continuous : continuous (λx, p.eval x) := p.differentiable.continuous protected lemma continuous_on : continuous_on (λx, p.eval x) s := p.continuous.continuous_on protected lemma continuous_at : continuous_at (λx, p.eval x) x := p.continuous.continuous_at protected lemma continuous_within_at : continuous_within_at (λx, p.eval x) s x := p.continuous_at.continuous_within_at protected lemma has_fderiv_at (x : 𝕜) : has_fderiv_at (λx, p.eval x) (smul_right 1 (p.derivative.eval x) : 𝕜 →L[𝕜] 𝕜) x := by simpa [has_deriv_at_iff_has_fderiv_at] using p.has_deriv_at x protected lemma has_fderiv_within_at (x : 𝕜) : has_fderiv_within_at (λx, p.eval x) (smul_right 1 (p.derivative.eval x) : 𝕜 →L[𝕜] 𝕜) s x := (p.has_fderiv_at x).has_fderiv_within_at @[simp] protected lemma fderiv : fderiv 𝕜 (λx, p.eval x) x = smul_right 1 (p.derivative.eval x) := (p.has_fderiv_at x).fderiv protected lemma fderiv_within (hxs : unique_diff_within_at 𝕜 s x) : fderiv_within 𝕜 (λx, p.eval x) s x = smul_right 1 (p.derivative.eval x) := begin rw differentiable_at.fderiv_within p.differentiable_at hxs, exact p.fderiv end end polynomial section pow /-! ### Derivative of `x ↦ x^n` for `n : ℕ` -/ variables {x : 𝕜} {s : set 𝕜} variable {n : ℕ } lemma has_deriv_at_pow (n : ℕ) (x : 𝕜) : has_deriv_at (λx, x^n) ((n : 𝕜) * x^(n-1)) x := begin convert (polynomial.C 1 * (polynomial.X)^n).has_deriv_at x, { simp }, { rw [polynomial.derivative_monomial], simp } end theorem has_deriv_within_at_pow (n : ℕ) (x : 𝕜) (s : set 𝕜) : has_deriv_within_at (λx, x^n) ((n : 𝕜) * x^(n-1)) s x := (has_deriv_at_pow n x).has_deriv_within_at lemma differentiable_at_pow : differentiable_at 𝕜 (λx, x^n) x := (has_deriv_at_pow n x).differentiable_at lemma differentiable_within_at_pow : differentiable_within_at 𝕜 (λx, x^n) s x := differentiable_at_pow.differentiable_within_at lemma differentiable_pow : differentiable 𝕜 (λx:𝕜, x^n) := λx, differentiable_at_pow lemma differentiable_on_pow : differentiable_on 𝕜 (λx, x^n) s := differentiable_pow.differentiable_on lemma deriv_pow : deriv (λx, x^n) x = (n : 𝕜) * x^(n-1) := (has_deriv_at_pow n x).deriv @[simp] lemma deriv_pow' : deriv (λx, x^n) = λ x, (n : 𝕜) * x^(n-1) := funext $ λ x, deriv_pow lemma deriv_within_pow (hxs : unique_diff_within_at 𝕜 s x) : deriv_within (λx, x^n) s x = (n : 𝕜) * x^(n-1) := by rw [differentiable_at_pow.deriv_within hxs, deriv_pow] end pow /-! ### Upper estimates on liminf and limsup -/ section real variables {f : ℝ → ℝ} {f' : ℝ} {s : set ℝ} {x : ℝ} {r : ℝ} lemma has_deriv_within_at.limsup_slope_le (hf : has_deriv_within_at f f' s x) (hr : f' < r) : ∀ᶠ z in nhds_within x (s \ {x}), (z - x)⁻¹ * (f z - f x) < r := has_deriv_within_at_iff_tendsto_slope.1 hf (mem_nhds_sets is_open_Iio hr) lemma has_deriv_within_at.limsup_slope_le' (hf : has_deriv_within_at f f' s x) (hs : x ∉ s) (hr : f' < r) : ∀ᶠ z in nhds_within x s, (z - x)⁻¹ * (f z - f x) < r := (has_deriv_within_at_iff_tendsto_slope' hs).1 hf (mem_nhds_sets is_open_Iio hr) lemma has_deriv_within_at.liminf_right_slope_le (hf : has_deriv_within_at f f' (Ioi x) x) (hr : f' < r) : ∃ᶠ z in nhds_within x (Ioi x), (z - x)⁻¹ * (f z - f x) < r := (hf.limsup_slope_le' (lt_irrefl x) hr).frequently (nhds_within_Ioi_self_ne_bot x) end real section real_space open metric variables {E : Type u} [normed_group E] [normed_space ℝ E] {f : ℝ → E} {f' : E} {s : set ℝ} {x r : ℝ} /-- If `f` has derivative `f'` within `s` at `x`, then for any `r > ∥f'∥` the ratio `∥f z - f x∥ / ∥z - x∥` is less than `r` in some neighborhood of `x` within `s`. In other words, the limit superior of this ratio as `z` tends to `x` along `s` is less than or equal to `∥f'∥`. -/ lemma has_deriv_within_at.limsup_norm_slope_le (hf : has_deriv_within_at f f' s x) (hr : ∥f'∥ < r) : ∀ᶠ z in nhds_within x s, ∥z - x∥⁻¹ * ∥f z - f x∥ < r := begin have hr₀ : 0 < r, from lt_of_le_of_lt (norm_nonneg f') hr, have A : ∀ᶠ z in nhds_within x (s \ {x}), ∥(z - x)⁻¹ • (f z - f x)∥ ∈ Iio r, from (has_deriv_within_at_iff_tendsto_slope.1 hf).norm (mem_nhds_sets is_open_Iio hr), have B : ∀ᶠ z in nhds_within x {x}, ∥(z - x)⁻¹ • (f z - f x)∥ ∈ Iio r, from mem_sets_of_superset self_mem_nhds_within (singleton_subset_iff.2 $ by simp [hr₀]), have C := mem_sup_sets.2 ⟨A, B⟩, rw [← nhds_within_union, diff_union_self, nhds_within_union, mem_sup_sets] at C, filter_upwards [C.1], simp only [mem_set_of_eq, norm_smul, mem_Iio, normed_field.norm_inv], exact λ _, id end /-- If `f` has derivative `f'` within `s` at `x`, then for any `r > ∥f'∥` the ratio `(∥f z∥ - ∥f x∥) / ∥z - x∥` is less than `r` in some neighborhood of `x` within `s`. In other words, the limit superior of this ratio as `z` tends to `x` along `s` is less than or equal to `∥f'∥`. This lemma is a weaker version of `has_deriv_within_at.limsup_norm_slope_le` where `∥f z∥ - ∥f x∥` is replaced by `∥f z - f x∥`. -/ lemma has_deriv_within_at.limsup_slope_norm_le (hf : has_deriv_within_at f f' s x) (hr : ∥f'∥ < r) : ∀ᶠ z in nhds_within x s, ∥z - x∥⁻¹ * (∥f z∥ - ∥f x∥) < r := begin apply (hf.limsup_norm_slope_le hr).mono, assume z hz, refine lt_of_le_of_lt (mul_le_mul_of_nonneg_left (norm_sub_norm_le _ _) _) hz, exact inv_nonneg.2 (norm_nonneg _) end /-- If `f` has derivative `f'` within `(x, +∞)` at `x`, then for any `r > ∥f'∥` the ratio `∥f z - f x∥ / ∥z - x∥` is frequently less than `r` as `z → x+0`. In other words, the limit inferior of this ratio as `z` tends to `x+0` is less than or equal to `∥f'∥`. See also `has_deriv_within_at.limsup_norm_slope_le` for a stronger version using limit superior and any set `s`. -/ lemma has_deriv_within_at.liminf_right_norm_slope_le (hf : has_deriv_within_at f f' (Ioi x) x) (hr : ∥f'∥ < r) : ∃ᶠ z in nhds_within x (Ioi x), ∥z - x∥⁻¹ * ∥f z - f x∥ < r := (hf.limsup_norm_slope_le hr).frequently (nhds_within_Ioi_self_ne_bot x) /-- If `f` has derivative `f'` within `(x, +∞)` at `x`, then for any `r > ∥f'∥` the ratio `(∥f z∥ - ∥f x∥) / (z - x)` is frequently less than `r` as `z → x+0`. In other words, the limit inferior of this ratio as `z` tends to `x+0` is less than or equal to `∥f'∥`. See also * `has_deriv_within_at.limsup_norm_slope_le` for a stronger version using limit superior and any set `s`; * `has_deriv_within_at.liminf_right_norm_slope_le` for a stronger version using `∥f z - f x∥` instead of `∥f z∥ - ∥f x∥`. -/ lemma has_deriv_within_at.liminf_right_slope_norm_le (hf : has_deriv_within_at f f' (Ioi x) x) (hr : ∥f'∥ < r) : ∃ᶠ z in nhds_within x (Ioi x), (z - x)⁻¹ * (∥f z∥ - ∥f x∥) < r := begin have := (hf.limsup_slope_norm_le hr).frequently (nhds_within_Ioi_self_ne_bot x), refine this.mp (eventually.mono self_mem_nhds_within _), assume z hxz hz, rwa [real.norm_eq_abs, abs_of_pos (sub_pos_of_lt hxz)] at hz end end real_space