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
Path: Maths_Challenges / _target / deps / mathlib / src / analysis / calculus / times_cont_diff.lean
Views: 18536License: APACHE
/- Copyright (c) 2019 SΓ©bastien GouΓ«zel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: SΓ©bastien GouΓ«zel -/ import analysis.calculus.fderiv /-! # Higher differentiability A function is `C^1` on a domain if it is differentiable there, and its derivative is continuous. By induction, it is `C^n` if it is `C^{n-1}` and its (n-1)-th derivative is `C^1` there or, equivalently, if it is `C^1` and its derivative is `C^{n-1}`. Finally, it is `C^β` if it is `C^n` for all n. We formalize these notions by defining iteratively the n-th derivative of a function at the (n-1)-th derivative of the derivative. It is called `iterated_fderiv π n f x` where `π` is the field, `n` is the number of iterations, `f` is the function and `x` is the point. We also define a version `iterated_fderiv_within` relative to a domain, as well as predicates `times_cont_diff π n f` and `times_cont_diff_on π n f s` saying that the function is `C^n`, respectively in the whole space or on the set `s`. We prove basic properties of these notions. ## Implementation notes The n-th derivative of a function belongs to the space E βL[π] (E βL[π] (E ... F)...))), where there are n iterations of `E βL[π]`. We define this space inductively, call it `iterated_continuous_linear_map π n E F`, and denote it by `E [Γn]βL[π] F`. We can define it inductively either from the left (i.e., saying that the (n+1)-th space S_{n+1} is E βL[π] S_n) or from the right (i.e., saying that the (n+1)-th space associated to F, denoted by S_{n+1} (F), is equal to S_n (E βL[π] F)). For proofs, it turns out to be more convenient to use the latter approach (from the right), as it means to prove things at the (n+1)-th step we only need to understand well enough the derivative in E βL[π] F (contrary to the approach from the left, where one would need to know enough on the n-th derivative to deduce things on the (n+1)-th derivative). In other words, one could define the (n+1)-th derivative either as the derivative of the n-th derivative, or as the n-th derivative of the derivative. We use the latter definition. A difficulty is related to universes: the first and second spaces in the sequence, for n=0 and 1, are F and E βL[π] F. If E has universe u and F has universe v, then the first one lives in v and the second one in max v u. Since they should live in the same universe (as all the other spaces in the construction), it means that at the 0-th step we should not use F, but ulift it to universe max v u. But we should also ulift its vector space structure and its normed space structure. This can certainly be done, but I decided it was not worth it for now. Therefore, the definition is only made when E and F live in the same universe. Regarding the definition of `C^n` functions, there are two equivalent definitions: * require by induction that the function is differentiable, and that its derivative is C^{n-1} * or require that, for all m β€ n, the m-th derivative is continuous, and for all m < n the m-th derivative is differentiable. The first definition is more efficient for many proofs by induction. The second definition is more satisfactory as it gives concrete information about the n-th derivative (contrary to the first point of view), and moreover it also makes sense for n = β. Therefore, we give (and use) both definitions, named respectively `times_cont_diff_rec` and `times_cont_diff` (as well as relativized versions on a set). We show that they are equivalent. The first one is mainly auxiliary: in applications, one should always use `times_cont_diff` (but the proofs below use heavily the equivalence to show that `times_cont_diff` is well behaved). ## Tags derivative, differentiability, higher derivative, C^n -/ noncomputable theory local attribute [instance, priority 10] classical.decidable_inhabited classical.prop_decidable universes u v w open set open_locale topological_space variables {π : Type*} [nondiscrete_normed_field π] {E : Type u} [normed_group E] [normed_space π E] {F : Type u} [normed_group F] [normed_space π F] {G : Type u} [normed_group G] [normed_space π G] {s sβ u : set E} {f fβ : E β F} {f' fβ' : E βL[π] F} {fβ : E β G} {fβ' : E βL[π] G} {g : F β G} {x : E} {c : F} {L : filter E} {t : set F} {b : E Γ F β G} {sb : set (E Γ F)} {p : E Γ F} {n : β} include π /-- The space `iterated_continuous_linear_map π n E F` is the space E βL[π] (E βL[π] (E ... F)...))), defined inductively over `n`. This is the space to which the `n`-th derivative of a function naturally belongs. It is only defined when `E` and `F` live in the same universe. -/ def iterated_continuous_linear_map (π : Type w) [nondiscrete_normed_field π] : Ξ (n : β) (E : Type u) [gE : normed_group E] [@normed_space π E _ gE] (F : Type u) [gF : normed_group F] [@normed_space π F _ gF], Type u | 0 E _ _ F _ _ := F | (n+1) E _ _ F _ _ := by { resetI, exact iterated_continuous_linear_map n E (E βL[π] F) } notation E `[Γ`:25 n `]βL[`:25 π `] ` F := iterated_continuous_linear_map π n E F /-- Define by induction a normed group structure on the space of iterated continuous linear maps. To avoid `resetI` in the statement, use the @ version with all parameters. As the equation compiler chokes on this one, we use the `nat.rec_on` version. -/ def iterated_continuous_linear_map.normed_group_rec (π : Type w) [hπ : nondiscrete_normed_field π] (n : β) (E : Type u) [gE : normed_group E] [sE : normed_space π E] : β(F : Type u) [nF : normed_group F] [sF : @normed_space π F _ nF], normed_group (@iterated_continuous_linear_map π hπ n E gE sE F nF sF) := nat.rec_on n (Ξ»F nF sF, nF) (Ξ»n aux_n F nF sF, by { resetI, apply aux_n }) /-- Define by induction a normed space structure on the space of iterated continuous linear maps. To avoid `resetI` in the statement, use the @ version with all parameters. As the equation compiler chokes on this one, we use the `nat.rec_on` version. -/ def iterated_continuous_linear_map.normed_space_rec (π : Type w) [hπ : nondiscrete_normed_field π] (n : β) (E : Type u) [gE : normed_group E] [sE : normed_space π E] : β(F : Type u) [nF : normed_group F] [sF : @normed_space π F _ nF], @normed_space π (@iterated_continuous_linear_map π hπ n E gE sE F nF sF) _ (@iterated_continuous_linear_map.normed_group_rec π hπ n E gE sE F nF sF) := nat.rec_on n (Ξ»F nF sF, sF) (Ξ»n aux_n F nF sF, by { resetI, apply aux_n }) /-- Explicit normed group structure on the space of iterated continuous linear maps. -/ instance iterated_continuous_linear_map.normed_group (n : β) (π : Type w) [hπ : nondiscrete_normed_field π] (E : Type u) [gE : normed_group E] [sE : normed_space π E] (F : Type u) [gF : normed_group F] [sF : normed_space π F] : normed_group (E [Γn]βL[π] F) := iterated_continuous_linear_map.normed_group_rec π n E F instance : inhabited (E [Γn]βL[π] F) := β¨0β© /-- Explicit normed space structure on the space of iterated continuous linear maps. -/ instance iterated_continuous_linear_map.normed_space (n : β) (π : Type w) [hπ : nondiscrete_normed_field π] (E : Type u) [gE : normed_group E] [sE : normed_space π E] (F : Type u) [gF : normed_group F] [sF : normed_space π F] : normed_space π (E [Γn]βL[π] F) := iterated_continuous_linear_map.normed_space_rec π n E F /-- The n-th derivative of a function, defined inductively by saying that the (n+1)-th derivative of f is the n-th derivative of the derivative of f. -/ def iterated_fderiv (π : Type w) [hπ : nondiscrete_normed_field π] (n : β) {E : Type u} [gE : normed_group E] [sE : normed_space π E] : β{F : Type u} [gF : normed_group F] [sF : @normed_space π F _ gF] (f : E β F), E β @iterated_continuous_linear_map π hπ n E gE sE F gF sF := nat.rec_on n (Ξ»F gF sF f, f) (Ξ»n rec F gF sF f, by { resetI, exact rec (fderiv π f) }) @[simp] lemma iterated_fderiv_zero : iterated_fderiv π 0 f = f := rfl @[simp] lemma iterated_fderiv_succ : iterated_fderiv π (n+1) f = (iterated_fderiv π n (Ξ»x, fderiv π f x) : _) := rfl /-- The n-th derivative of a function along a set, defined inductively by saying that the (n+1)-th derivative of f is the n-th derivative of the derivative of f. -/ def iterated_fderiv_within (π : Type w) [hπ :nondiscrete_normed_field π] (n : β) {E : Type u} [gE : normed_group E] [sE : normed_space π E] : β{F : Type u} [gF : normed_group F] [sF : @normed_space π F _ gF] (f : E β F) (s : set E), E β @iterated_continuous_linear_map π hπ n E gE sE F gF sF := nat.rec_on n (Ξ»F gF sF f s, f) (Ξ»n rec F gF sF f s, by { resetI, exact rec (fderiv_within π f s) s}) @[simp] lemma iterated_fderiv_within_zero : iterated_fderiv_within π 0 f s = f := rfl @[simp] lemma iterated_fderiv_within_succ : iterated_fderiv_within π (n+1) f s = (iterated_fderiv_within π n (Ξ»x, fderiv_within π f s x) s : _) := rfl theorem iterated_fderiv_within_univ {n : β} : iterated_fderiv_within π n f univ = iterated_fderiv π n f := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F, { refl }, { simp [IH] } end /-- If two functions coincide on a set `s` of unique differentiability, then their iterated differentials within this set coincide. -/ lemma iterated_fderiv_within_congr (hs : unique_diff_on π s) (hL : βyβs, fβ y = f y) (hx : x β s) : iterated_fderiv_within π n fβ s x = iterated_fderiv_within π n f s x := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f x, { simp [hL x hx] }, { simp only [iterated_fderiv_within_succ], refine IH (Ξ»y hy, _) hx, apply fderiv_within_congr (hs y hy) hL (hL y hy) } end /-- The iterated differential within a set `s` at a point `x` is not modified if one intersects `s` with an open set containing `x`. -/ lemma iterated_fderiv_within_inter_open (xu : x β u) (hu : is_open u) (xs : x β s) (hs : unique_diff_on π (s β© u)) : iterated_fderiv_within π n f (s β© u) x = iterated_fderiv_within π n f s x := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f, { simp }, { simp, rw β IH, apply iterated_fderiv_within_congr hs (Ξ»y hy, _) β¨xs, xuβ©, apply fderiv_within_inter (mem_nhds_sets hu hy.2), have := hs y hy, rwa unique_diff_within_at_inter (mem_nhds_sets hu hy.2) at this } end /-- The iterated differential within a set `s` at a point `x` is not modified if one intersects `s` with a neighborhood of `x`. -/ lemma iterated_fderiv_within_inter (hu : u β π x) (xs : x β s) (hs : unique_diff_on π s) : iterated_fderiv_within π n f (s β© u) x = iterated_fderiv_within π n f s x := begin rcases mem_nhds_sets_iff.1 hu with β¨v, vu, v_open, xvβ©, have A : (s β© u) β© v = s β© v, { apply subset.antisymm (inter_subset_inter (inter_subset_left _ _) (subset.refl _)), exact Ξ» y β¨ys, yvβ©, β¨β¨ys, vu yvβ©, yvβ© }, have : iterated_fderiv_within π n f (s β© v) x = iterated_fderiv_within π n f s x := iterated_fderiv_within_inter_open xv v_open xs (hs.inter v_open), rw β this, have : iterated_fderiv_within π n f ((s β© u) β© v) x = iterated_fderiv_within π n f (s β© u) x, { refine iterated_fderiv_within_inter_open xv v_open β¨xs, mem_of_nhds huβ© _, rw A, exact hs.inter v_open }, rw A at this, rw β this end /-- Auxiliary definition defining `C^n` functions by induction over `n`. In applications, use `times_cont_diff` instead. -/ def times_cont_diff_rec (π : Type w) [nondiscrete_normed_field π] : Ξ (n : β) {E : Type u} [gE : normed_group E] [@normed_space π E _ gE] {F : Type u} [gF : normed_group F] [@normed_space π F _ gF] (f : E β F), Prop | 0 E _ _ F _ _ f := by { resetI, exact continuous f } | (n+1) E _ _ F _ _ f := by { resetI, exact differentiable π f β§ times_cont_diff_rec n (fderiv π f) } @[simp] lemma times_cont_diff_rec_zero : times_cont_diff_rec π 0 f β continuous f := by refl @[simp] lemma times_cont_diff_rec_succ : times_cont_diff_rec π n.succ f β differentiable π f β§ times_cont_diff_rec π n (Ξ»x, fderiv π f x) := by refl lemma times_cont_diff_rec.of_succ (h : times_cont_diff_rec π n.succ f) : times_cont_diff_rec π n f := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F, { exact h.1.continuous }, { rw times_cont_diff_rec_succ at h β’, exact β¨h.1, IH h.2β© } end lemma times_cont_diff_rec.continuous (h : times_cont_diff_rec π n f) : continuous (iterated_fderiv π n f) := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f, { exact h }, { rw iterated_fderiv_succ, exact IH (times_cont_diff_rec_succ.1 h).2 } end lemma times_cont_diff_rec.differentiable (h : times_cont_diff_rec π (n+1) f) : differentiable π (iterated_fderiv π n f) := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f, { exact h.1 }, { rw iterated_fderiv_succ, apply IH h.2 } end /-- Auxiliary definition defining `C^n` functions on a set by induction over `n`. In applications, use `times_cont_diff_on` instead. -/ def times_cont_diff_on_rec (π : Type w) [nondiscrete_normed_field π] : Ξ (n : β) {E : Type u} [gE : normed_group E] [@normed_space π E _ gE] {F : Type u} [gF : normed_group F] [@normed_space π F _ gF] (f : E β F) (s : set E), Prop | 0 E _ _ F _ _ f s := by { resetI, exact continuous_on f s } | (n+1) E _ _ F _ _ f s := by { resetI, exact differentiable_on π f s β§ times_cont_diff_on_rec n (fderiv_within π f s) s} @[simp] lemma times_cont_diff_on_rec_zero : times_cont_diff_on_rec π 0 f s β continuous_on f s := by refl @[simp] lemma times_cont_diff_on_rec_succ : times_cont_diff_on_rec π n.succ f s β differentiable_on π f s β§ times_cont_diff_on_rec π n (Ξ»x, fderiv_within π f s x) s := by refl lemma times_cont_diff_on_rec.of_succ (h : times_cont_diff_on_rec π n.succ f s) : times_cont_diff_on_rec π n f s := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F, { exact h.1.continuous_on }, { rw times_cont_diff_on_rec_succ at h β’, exact β¨h.1, IH h.2β© } end lemma times_cont_diff_on_rec.continuous_on_iterated_fderiv_within (h : times_cont_diff_on_rec π n f s) : continuous_on (iterated_fderiv_within π n f s) s := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f, { exact h }, { rw iterated_fderiv_within_succ, exact IH (times_cont_diff_on_rec_succ.1 h).2 } end lemma times_cont_diff_on_rec.differentiable_on (h : times_cont_diff_on_rec π (n+1) f s) : differentiable_on π (iterated_fderiv_within π n f s) s := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f, { exact h.1 }, { rw iterated_fderiv_within_succ, apply IH h.2 } end lemma times_cont_diff_on_rec_univ : times_cont_diff_on_rec π n f univ β times_cont_diff_rec π n f := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f, { rw [times_cont_diff_on_rec_zero, times_cont_diff_rec_zero, continuous_iff_continuous_on_univ] }, { rw [times_cont_diff_on_rec_succ, times_cont_diff_rec_succ, differentiable_on_univ, fderiv_within_univ, IH] } end /-- A function is `C^n` on a set, for `n : with_top β`, if its derivatives of order at most `n` are all well defined and continuous. -/ def times_cont_diff_on (π : Type w) [nondiscrete_normed_field π] (n : with_top β) {E F : Type u} [normed_group E] [normed_space π E] [normed_group F] [normed_space π F] (f : E β F) (s : set E) := (βm:β, (m : with_top β) β€ n β continuous_on (iterated_fderiv_within π m f s) s) β§ (βm:β, (m : with_top β) < n β differentiable_on π (iterated_fderiv_within π m f s) s) @[simp] lemma times_cont_diff_on_zero : times_cont_diff_on π 0 f s β continuous_on f s := by simp [times_cont_diff_on] /-- The two definitions of `C^n` functions on domains, directly in terms of continuity of all derivatives, or by induction, are equivalent. -/ theorem times_cont_diff_on_iff_times_cont_diff_on_rec : times_cont_diff_on π n f s β times_cont_diff_on_rec π n f s := begin tactic.unfreeze_local_instances, induction n with n IH generalizing F f, { rw [with_top.coe_zero, times_cont_diff_on_rec_zero, times_cont_diff_on_zero] }, { split, { assume H, rw times_cont_diff_on_rec_succ, refine β¨H.2 0 (by simp only [with_top.zero_lt_coe, with_top.coe_zero, nat.succ_pos n]), _β©, rw β IH, split, { assume m hm, have : (m.succ : with_top nat) β€ n.succ := with_top.coe_le_coe.2 (nat.succ_le_succ (with_top.coe_le_coe.1 hm)), exact H.1 _ this }, { assume m hm, have : (m.succ : with_top nat) < n.succ := with_top.coe_lt_coe.2 (nat.succ_le_succ (with_top.coe_lt_coe.1 hm)), exact H.2 _ this } }, { assume H, split, { assume m hm, simp only [with_top.coe_le_coe] at hm, cases nat.of_le_succ hm with h h, { have := H.of_succ, rw β IH at this, exact this.1 _ (with_top.coe_le_coe.2 h) }, { rw h, simp at H, exact H.2.continuous_on_iterated_fderiv_within } }, { assume m hm, simp only [with_top.coe_lt_coe] at hm, cases nat.of_le_succ hm with h h, { have := H.of_succ, rw β IH at this, exact this.2 _ (with_top.coe_lt_coe.2 h) }, { rw nat.succ_inj h, exact H.differentiable_on } } } }, end /- Next lemma is marked as a simp lemma as `C^(n+1)` functions appear mostly in inductions. -/ @[simp] lemma times_cont_diff_on_succ : times_cont_diff_on π n.succ f s β differentiable_on π f s β§ times_cont_diff_on π n (Ξ»x, fderiv_within π f s x) s := by simp [times_cont_diff_on_iff_times_cont_diff_on_rec] lemma times_cont_diff_on.of_le {m n : with_top β} (h : times_cont_diff_on π n f s) (le : m β€ n) : times_cont_diff_on π m f s := β¨Ξ»p hp, h.1 p (le_trans hp le), Ξ»p hp, h.2 p (lt_of_lt_of_le hp le)β© lemma times_cont_diff_on.of_succ (h : times_cont_diff_on π n.succ f s) : times_cont_diff_on π n f s := h.of_le (with_top.coe_le_coe.2 (nat.le_succ n)) lemma times_cont_diff_on.continuous_on {n : with_top β} (h : times_cont_diff_on π n f s) : continuous_on f s := h.1 0 (by simp) lemma times_cont_diff_on.continuous_on_fderiv_within {n : with_top β} (h : times_cont_diff_on π n f s) (hn : 1 β€ n) : continuous_on (fderiv_within π f s) s := h.1 1 hn /-- If a function is at least C^1 on a set, it is differentiable there. -/ lemma times_cont_diff_on.differentiable_on {n : with_top β} (h : times_cont_diff_on π n f s) (hn : 1 β€ n) : differentiable_on π f s := begin refine h.2 0 _, refine lt_of_lt_of_le _ hn, change ((0 : β) : with_top β) < (1 : β), rw with_top.coe_lt_coe, exact zero_lt_one end set_option class.instance_max_depth 50 /-- If a function is at least `C^1`, its bundled derivative (mapping `(x, v)` to `Df(x) v`) is continuous. -/ lemma times_cont_diff_on.continuous_on_fderiv_within_apply {n : with_top β} (h : times_cont_diff_on π n f s) (hn : 1 β€ n) : continuous_on (Ξ»p : E Γ E, (fderiv_within π f s p.1 : E β F) p.2) (set.prod s univ) := begin have A : continuous (Ξ»q : (E βL[π] F) Γ E, q.1 q.2) := is_bounded_bilinear_map_apply.continuous, have B : continuous_on (Ξ»p : E Γ E, (fderiv_within π f s p.1, p.2)) (set.prod s univ), { apply continuous_on.prod _ continuous_snd.continuous_on, exact continuous_on.comp (h.continuous_on_fderiv_within hn) continuous_fst.continuous_on (prod_subset_preimage_fst _ _) }, exact A.comp_continuous_on B end lemma times_cont_diff_on_top : times_cont_diff_on π β€ f s β (βn:β, times_cont_diff_on π n f s) := begin split, { assume h n, exact h.of_le lattice.le_top }, { assume h, split, { exact Ξ»m hm, (h m).1 m (le_refl _) }, { exact Ξ» m hm, (h m.succ).2 m (with_top.coe_lt_coe.2 (lt_add_one m)) } } end lemma times_cont_diff_on_fderiv_within_nat {m n : β} (hf : times_cont_diff_on π n f s) (h : m + 1 β€ n) : times_cont_diff_on π m (Ξ»x, fderiv_within π f s x) s := begin have : times_cont_diff_on π m.succ f s := hf.of_le (with_top.coe_le_coe.2 h), exact (times_cont_diff_on_succ.1 this).2 end lemma times_cont_diff_on_fderiv_within {m n : with_top β} (hf : times_cont_diff_on π n f s) (h : m + 1 β€ n) : times_cont_diff_on π m (Ξ»x, fderiv_within π f s x) s := begin cases m, { change β€ + 1 β€ n at h, have : n = β€, by simpa using h, rw this at hf, change times_cont_diff_on π β€ (Ξ» (x : E), fderiv_within π f s x) s, rw times_cont_diff_on_top at β’ hf, exact Ξ»m, times_cont_diff_on_fderiv_within_nat (hf (m + 1)) (le_refl _) }, { have : times_cont_diff_on π (m + 1) f s := hf.of_le h, exact times_cont_diff_on_fderiv_within_nat this (le_refl _) } end lemma times_cont_diff_on.congr_mono {n : with_top β} (H : times_cont_diff_on π n f s) (hs : unique_diff_on π sβ) (h : βx β sβ, fβ x = f x) (hβ : sβ β s) : times_cont_diff_on π n fβ sβ := begin tactic.unfreeze_local_instances, induction n using with_top.nat_induction with n IH Itop generalizing F, { rw times_cont_diff_on_zero at H β’, exact continuous_on.congr_mono H h hβ }, { rw times_cont_diff_on_succ at H β’, refine β¨differentiable_on.congr_mono H.1 h hβ, IH H.2 (Ξ»x hx, _)β©, apply differentiable_within_at.fderiv_within_congr_mono (H.1 x (hβ hx)) h (h x hx) (hs x hx) hβ }, { rw times_cont_diff_on_top at H β’, assume n, exact Itop n (H n) h } end lemma times_cont_diff_on.congr {n : with_top β} {s : set E} (H : times_cont_diff_on π n f s) (hs : unique_diff_on π s) (h : βx β s, fβ x = f x) : times_cont_diff_on π n fβ s := times_cont_diff_on.congr_mono H hs h (subset.refl _) lemma times_cont_diff_on.congr_mono' {n m : with_top β} {s : set E} (H : times_cont_diff_on π n f s) (hs : unique_diff_on π sβ) (h : βx β sβ, fβ x = f x) (hβ : sβ β s) (le : m β€ n) : times_cont_diff_on π m fβ sβ := times_cont_diff_on.of_le (H.congr_mono hs h hβ) le lemma times_cont_diff_on.mono {n : with_top β} {s t : set E} (h : times_cont_diff_on π n f t) (hst : s β t) (hs : unique_diff_on π s) : times_cont_diff_on π n f s := times_cont_diff_on.congr_mono h hs (Ξ»x hx, rfl) hst /-- Being `C^n` is a local property. -/ lemma times_cont_diff_on_of_locally_times_cont_diff_on {n : with_top β} {s : set E} (hs : unique_diff_on π s) (h : βxβs, βu, is_open u β§ x β u β§ times_cont_diff_on π n f (s β© u)) : times_cont_diff_on π n f s := begin split, { assume m hm, apply continuous_on_of_locally_continuous_on (Ξ»x hx, _), rcases h x hx with β¨u, u_open, xu, huβ©, refine β¨u, u_open, xu,_β©, apply continuous_on.congr_mono (hu.1 m hm) (Ξ»y hy, _) (subset.refl _), symmetry, exact iterated_fderiv_within_inter_open hy.2 u_open hy.1 (hs.inter u_open) }, { assume m hm, apply differentiable_on_of_locally_differentiable_on (Ξ»x hx, _), rcases h x hx with β¨u, u_open, xu, huβ©, refine β¨u, u_open, xu,_β©, apply differentiable_on.congr_mono (hu.2 m hm) (Ξ»y hy, _) (subset.refl _), symmetry, exact iterated_fderiv_within_inter_open hy.2 u_open hy.1 (hs.inter u_open) } end /-- A function is `C^n`, for `n : with_top β`, if its derivatives of order at most `n` are all well defined and continuous. -/ def times_cont_diff (π : Type w) [nondiscrete_normed_field π] (n : with_top β) {E F : Type u} [normed_group E] [normed_space π E] [normed_group F] [normed_space π F] (f : E β F) := (βm:β, (m : with_top β) β€ n β continuous (iterated_fderiv π m f )) β§ (βm:β, (m : with_top β) < n β differentiable π (iterated_fderiv π m f)) lemma times_cont_diff_on_univ {n : with_top β} : times_cont_diff_on π n f univ β times_cont_diff π n f := by simp [times_cont_diff_on, times_cont_diff, iterated_fderiv_within_univ, continuous_iff_continuous_on_univ, differentiable_on_univ] @[simp] lemma times_cont_diff_zero : times_cont_diff π 0 f β continuous f := by simp [times_cont_diff] theorem times_cont_diff_iff_times_cont_diff_rec : times_cont_diff π n f β times_cont_diff_rec π n f := by simp [times_cont_diff_on_univ.symm, times_cont_diff_on_rec_univ.symm, times_cont_diff_on_iff_times_cont_diff_on_rec] @[simp] lemma times_cont_diff_succ : times_cont_diff π n.succ f β differentiable π f β§ times_cont_diff π n (Ξ»x, fderiv π f x) := by simp [times_cont_diff_iff_times_cont_diff_rec] lemma times_cont_diff.of_le {m n : with_top β} (h : times_cont_diff π n f) (le : m β€ n) : times_cont_diff π m f := β¨Ξ»p hp, h.1 p (le_trans hp le), Ξ»p hp, h.2 p (lt_of_lt_of_le hp le)β© lemma times_cont_diff.of_succ (h : times_cont_diff π n.succ f) : times_cont_diff π n f := h.of_le (with_top.coe_le_coe.2 (nat.le_succ n)) lemma times_cont_diff.continuous {n : with_top β} (h : times_cont_diff π n f) : continuous f := h.1 0 (by simp) lemma times_cont_diff.continuous_fderiv {n : with_top β} (h : times_cont_diff π n f) (hn : 1 β€ n) : continuous (fderiv π f) := h.1 1 hn lemma times_cont_diff.continuous_fderiv_apply {n : with_top β} (h : times_cont_diff π n f) (hn : 1 β€ n) : continuous (Ξ»p : E Γ E, (fderiv π f p.1 : E β F) p.2) := begin have A : continuous (Ξ»q : (E βL[π] F) Γ E, q.1 q.2) := is_bounded_bilinear_map_apply.continuous, have B : continuous (Ξ»p : E Γ E, (fderiv π f p.1, p.2)), { apply continuous.prod_mk _ continuous_snd, exact continuous.comp (h.continuous_fderiv hn) continuous_fst }, exact A.comp B end lemma times_cont_diff_top : times_cont_diff π β€ f β (βn:β, times_cont_diff π n f) := by simp [times_cont_diff_on_univ.symm, times_cont_diff_on_rec_univ.symm, times_cont_diff_on_top] lemma times_cont_diff.times_cont_diff_on {n : with_top β} {s : set E} (h : times_cont_diff π n f) (hs : unique_diff_on π s) : times_cont_diff_on π n f s := by { rw β times_cont_diff_on_univ at h, apply times_cont_diff_on.mono h (subset_univ _) hs } /-- Constants are C^β. -/ lemma times_cont_diff_const {n : with_top β} {c : F} : times_cont_diff π n (Ξ»x : E, c) := begin tactic.unfreeze_local_instances, induction n using with_top.nat_induction with n IH Itop generalizing F, { rw times_cont_diff_zero, apply continuous_const }, { refine times_cont_diff_succ.2 β¨differentiable_const _, _β©, simp [fderiv_const], exact IH }, { rw times_cont_diff_top, assume n, apply Itop } end lemma times_cont_diff_on_const {n : with_top β} {c : F} {s : set E} (hs : unique_diff_on π s) : times_cont_diff_on π n (Ξ»x : E, c) s := times_cont_diff_const.times_cont_diff_on hs /-- Linear functions are C^β. -/ lemma is_bounded_linear_map.times_cont_diff {n : with_top β} (hf : is_bounded_linear_map π f) : times_cont_diff π n f := begin induction n using with_top.nat_induction with n IH Itop, { rw times_cont_diff_zero, exact hf.continuous }, { refine times_cont_diff_succ.2 β¨hf.differentiable, _β©, simp [hf.fderiv], exact times_cont_diff_const }, { rw times_cont_diff_top, apply Itop } end /-- The first projection in a product is C^β. -/ lemma times_cont_diff_fst {n : with_top β} : times_cont_diff π n (prod.fst : E Γ F β E) := is_bounded_linear_map.times_cont_diff is_bounded_linear_map.fst /-- The second projection in a product is C^β. -/ lemma times_cont_diff_snd {n : with_top β} : times_cont_diff π n (prod.snd : E Γ F β F) := is_bounded_linear_map.times_cont_diff is_bounded_linear_map.snd /-- The identity is C^β. -/ lemma times_cont_diff_id {n : with_top β} : times_cont_diff π n (id : E β E) := is_bounded_linear_map.id.times_cont_diff /-- Bilinear functions are C^β. -/ lemma is_bounded_bilinear_map.times_cont_diff {n : with_top β} (hb : is_bounded_bilinear_map π b) : times_cont_diff π n b := begin induction n using with_top.nat_induction with n IH Itop, { rw times_cont_diff_zero, exact hb.continuous }, { refine times_cont_diff_succ.2 β¨hb.differentiable, _β©, simp [hb.fderiv], exact hb.is_bounded_linear_map_deriv.times_cont_diff }, { rw times_cont_diff_top, apply Itop } end /-- Composition by bounded linear maps preserves `C^n` functions on domains. -/ lemma times_cont_diff_on.comp_is_bounded_linear {n : with_top β} {s : set E} {f : E β F} {g : F β G} (hf : times_cont_diff_on π n f s) (hg : is_bounded_linear_map π g) (hs : unique_diff_on π s) : times_cont_diff_on π n (Ξ»x, g (f x)) s := begin tactic.unfreeze_local_instances, induction n using with_top.nat_induction with n IH Itop generalizing F G, { have : continuous_on g univ := hg.continuous.continuous_on, rw times_cont_diff_on_zero at hf β’, apply continuous_on.comp this hf (subset_univ _) }, { rw times_cont_diff_on_succ at hf β’, refine β¨differentiable_on.comp hg.differentiable_on hf.1 subset_preimage_univ, _β©, let Ξ¦ : (E βL[π] F) β (E βL[π] G) := Ξ»u, continuous_linear_map.comp (hg.to_continuous_linear_map) u, have : βxβs, fderiv_within π (g β f) s x = Ξ¦ (fderiv_within π f s x), { assume x hx, rw [fderiv_within.comp x _ (hf.1 x hx) subset_preimage_univ (hs x hx), fderiv_within_univ, hg.fderiv], rw differentiable_within_at_univ, exact hg.differentiable_at }, apply times_cont_diff_on.congr_mono _ hs this (subset.refl _), simp only [times_cont_diff_on_succ] at hf, exact IH hf.2 hg.to_continuous_linear_map.is_bounded_linear_map_comp_left }, { rw times_cont_diff_on_top at hf β’, assume n, apply Itop n (hf n) hg } end /-- Composition by bounded linear maps preserves `C^n` functions. -/ lemma times_cont_diff.comp_is_bounded_linear {n : with_top β} {f : E β F} {g : F β G} (hf : times_cont_diff π n f) (hg : is_bounded_linear_map π g) : times_cont_diff π n (Ξ»x, g (f x)) := times_cont_diff_on_univ.1 $ times_cont_diff_on.comp_is_bounded_linear (times_cont_diff_on_univ.2 hf) hg is_open_univ.unique_diff_on /-- The cartesian product of `C^n` functions on domains is `C^n`. -/ lemma times_cont_diff_on.prod {n : with_top β} {s : set E} {f : E β F} {g : E β G} (hf : times_cont_diff_on π n f s) (hg : times_cont_diff_on π n g s) (hs : unique_diff_on π s) : times_cont_diff_on π n (Ξ»x:E, (f x, g x)) s := begin tactic.unfreeze_local_instances, induction n using with_top.nat_induction with n IH Itop generalizing F G, { rw times_cont_diff_on_zero at hf hg β’, exact continuous_on.prod hf hg }, { rw times_cont_diff_on_succ at hf hg β’, refine β¨differentiable_on.prod hf.1 hg.1, _β©, let Fβ := Ξ»x : E, (fderiv_within π f s x, fderiv_within π g s x), let Ξ¦ : ((E βL[π] F) Γ (E βL[π] G)) β (E βL[π] (F Γ G)) := Ξ»p, continuous_linear_map.prod p.1 p.2, have : times_cont_diff_on π n (Ξ¦ β Fβ) s := times_cont_diff_on.comp_is_bounded_linear (IH hf.2 hg.2) is_bounded_linear_map_prod_iso hs, apply times_cont_diff_on.congr_mono this hs (Ξ»x hx, _) (subset.refl _), apply differentiable_at.fderiv_within_prod (hf.1 x hx) (hg.1 x hx) (hs x hx) }, { rw times_cont_diff_on_top at hf hg β’, assume n, apply Itop n (hf n) (hg n) } end /-- The cartesian product of `C^n` functions is `C^n`. -/ lemma times_cont_diff.prod {n : with_top β} {f : E β F} {g : E β G} (hf : times_cont_diff π n f) (hg : times_cont_diff π n g) : times_cont_diff π n (Ξ»x:E, (f x, g x)) := times_cont_diff_on_univ.1 $ times_cont_diff_on.prod (times_cont_diff_on_univ.2 hf) (times_cont_diff_on_univ.2 hg) is_open_univ.unique_diff_on /-- The composition of `C^n` functions on domains is `C^n`. -/ lemma times_cont_diff_on.comp {n : with_top β} {s : set E} {t : set F} {g : F β G} {f : E β F} (hg : times_cont_diff_on π n g t) (hf : times_cont_diff_on π n f s) (hs : unique_diff_on π s) (st : s β f β»ΒΉ' t) : times_cont_diff_on π n (g β f) s := begin tactic.unfreeze_local_instances, induction n using with_top.nat_induction with n IH Itop generalizing E F G, { rw times_cont_diff_on_zero at hf hg β’, exact continuous_on.comp hg hf st }, { rw times_cont_diff_on_succ at hf hg β’, /- We have to show that the derivative of g β f is C^n, given that g and f are C^(n+1). By the chain rule, this derivative is Dg(f x) β¬ Df(x). This is the composition of x β¦ (Dg (f x), Df (x)) with the product of bounded linear maps, which is bilinear and therefore C^β. By the induction assumption, it suffices to show that x β¦ (Dg (f x), Df (x)) is C^n. It is even enough to show that each component is C^n. This follows from the assumptions on f and g, and the inductive assumption. -/ refine β¨differentiable_on.comp hg.1 hf.1 st, _β©, have : βxβs, fderiv_within π (g β f) s x = continuous_linear_map.comp (fderiv_within π g t (f x)) (fderiv_within π f s x), { assume x hx, apply fderiv_within.comp x _ (hf.1 x hx) st (hs x hx), exact hg.1 _ (st hx) }, apply times_cont_diff_on.congr _ hs this, have A : times_cont_diff_on π n (Ξ»x, fderiv_within π g t (f x)) s := IH hg.2 (times_cont_diff_on_succ.2 hf).of_succ hs st, have B : times_cont_diff_on π n (Ξ»x, fderiv_within π f s x) s := hf.2, have C : times_cont_diff_on π n (Ξ»x:E, (fderiv_within π f s x, fderiv_within π g t (f x))) s := times_cont_diff_on.prod B A hs, have D : times_cont_diff_on π n (Ξ»(p : (E βL[π] F) Γ (F βL[π] G)), p.2.comp p.1) univ := is_bounded_bilinear_map_comp.times_cont_diff.times_cont_diff_on is_open_univ.unique_diff_on, exact IH D C hs (subset_univ _) }, { rw times_cont_diff_on_top at hf hg β’, assume n, apply Itop n (hg n) (hf n) hs st } end /-- The composition of a C^n function on domain with a C^n function is C^n. -/ lemma times_cont_diff.comp_times_cont_diff_on {n : with_top β} {s : set E} {g : F β G} {f : E β F} (hg : times_cont_diff π n g) (hf : times_cont_diff_on π n f s) (hs : unique_diff_on π s) : times_cont_diff_on π n (g β f) s := (times_cont_diff_on_univ.2 hg).comp hf hs subset_preimage_univ /-- The composition of `C^n` functions is `C^n`. -/ lemma times_cont_diff.comp {n : with_top β} {g : F β G} {f : E β F} (hg : times_cont_diff π n g) (hf : times_cont_diff π n f) : times_cont_diff π n (g β f) := times_cont_diff_on_univ.1 $ times_cont_diff_on.comp (times_cont_diff_on_univ.2 hg) (times_cont_diff_on_univ.2 hf) is_open_univ.unique_diff_on (subset_univ _) /-- The bundled derivative of a `C^{n+1}` function is `C^n`. -/ lemma times_cont_diff_on_fderiv_within_apply {m n : with_top β} {s : set E} {f : E β F} (hf : times_cont_diff_on π n f s) (hs : unique_diff_on π s) (hmn : m + 1 β€ n) : times_cont_diff_on π m (Ξ»p : E Γ E, (fderiv_within π f s p.1 : E βL[π] F) p.2) (set.prod s (univ : set E)) := begin have U : unique_diff_on π (set.prod s (univ : set E)) := hs.prod unique_diff_on_univ, have A : times_cont_diff π m (Ξ»p : (E βL[π] F) Γ E, p.1 p.2), { apply is_bounded_bilinear_map.times_cont_diff, exact is_bounded_bilinear_map_apply }, have B : times_cont_diff_on π m (Ξ» (p : E Γ E), ((fderiv_within π f s p.fst), p.snd)) (set.prod s univ), { apply times_cont_diff_on.prod _ _ U, { have I : times_cont_diff_on π m (Ξ» (x : E), fderiv_within π f s x) s := times_cont_diff_on_fderiv_within hf hmn, have J : times_cont_diff_on π m (Ξ» (x : E Γ E), x.1) (set.prod s univ) := times_cont_diff_fst.times_cont_diff_on U, exact times_cont_diff_on.comp I J U (prod_subset_preimage_fst _ _) }, { apply times_cont_diff.times_cont_diff_on _ U, apply is_bounded_linear_map.times_cont_diff, apply is_bounded_linear_map.snd } }, exact A.comp_times_cont_diff_on B U end /-- The bundled derivative of a `C^{n+1}` function is `C^n`. -/ lemma times_cont_diff.times_cont_diff_fderiv_apply {n m : with_top β} {s : set E} {f : E β F} (hf : times_cont_diff π n f) (hmn : m + 1 β€ n) : times_cont_diff π m (Ξ»p : E Γ E, (fderiv π f p.1 : E βL[π] F) p.2) := begin rw β times_cont_diff_on_univ at β’ hf, rw [β fderiv_within_univ, β univ_prod_univ], exact times_cont_diff_on_fderiv_within_apply hf unique_diff_on_univ hmn end /-- The sum of two C^n functions on a domain is C^n. -/ lemma times_cont_diff_on.add {n : with_top β} {s : set E} {f g : E β F} (hf : times_cont_diff_on π n f s) (hg : times_cont_diff_on π n g s) (hs : unique_diff_on π s) : times_cont_diff_on π n (Ξ»x, f x + g x) s := begin have : times_cont_diff π n (Ξ»p : F Γ F, p.1 + p.2), { apply is_bounded_linear_map.times_cont_diff, exact is_bounded_linear_map.add is_bounded_linear_map.fst is_bounded_linear_map.snd }, exact this.comp_times_cont_diff_on (hf.prod hg hs) hs end /-- The sum of two C^n functions is C^n. -/ lemma times_cont_diff.add {n : with_top β} {f g : E β F} (hf : times_cont_diff π n f) (hg : times_cont_diff π n g) : times_cont_diff π n (Ξ»x, f x + g x) := begin have : times_cont_diff π n (Ξ»p : F Γ F, p.1 + p.2), { apply is_bounded_linear_map.times_cont_diff, exact is_bounded_linear_map.add is_bounded_linear_map.fst is_bounded_linear_map.snd }, exact this.comp (hf.prod hg) end /-- The negative of a C^n function on a domain is C^n. -/ lemma times_cont_diff_on.neg {n : with_top β} {s : set E} {f : E β F} (hf : times_cont_diff_on π n f s) (hs : unique_diff_on π s) : times_cont_diff_on π n (Ξ»x, -f x) s := begin have : times_cont_diff π n (Ξ»p : F, -p), { apply is_bounded_linear_map.times_cont_diff, exact is_bounded_linear_map.neg is_bounded_linear_map.id }, exact this.comp_times_cont_diff_on hf hs end /-- The negative of a C^n function is C^n. -/ lemma times_cont_diff.neg {n : with_top β} {f : E β F} (hf : times_cont_diff π n f) : times_cont_diff π n (Ξ»x, -f x) := begin have : times_cont_diff π n (Ξ»p : F, -p), { apply is_bounded_linear_map.times_cont_diff, exact is_bounded_linear_map.neg is_bounded_linear_map.id }, exact this.comp hf end /-- The difference of two C^n functions on a domain is C^n. -/ lemma times_cont_diff_on.sub {n : with_top β} {s : set E} {f g : E β F} (hf : times_cont_diff_on π n f s) (hg : times_cont_diff_on π n g s) (hs : unique_diff_on π s) : times_cont_diff_on π n (Ξ»x, f x - g x) s := hf.add (hg.neg hs) hs /-- The difference of two C^n functions is C^n. -/ lemma times_cont_diff.sub {n : with_top β} {f g : E β F} (hf : times_cont_diff π n f) (hg : times_cont_diff π n g) : times_cont_diff π n (Ξ»x, f x - g x) := hf.add hg.neg