Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit f97c17d

Browse files
committed
feat(analysis/ODE/picard_lindelof): Add corollaries to ODE solution existence theorem (#16348)
We add some corollaries to the existence theorem of solutions to autonomous ODEs (Picard-Lindelöf / Cauchy-Lipschitz theorem). * `is_picard_lindelof`: Predicate for the very long hypotheses of the Picard-Lindelöf theorem. * When applying `exists_forall_deriv_within_Icc_eq_of_lipschitz_of_continuous` directly to unite with a goal, Lean introduces a long list of goals with many meta-variables. The predicate makes the proof of these hypotheses more manageable. * Certain variables in the hypotheses, such as the Lipschitz constant, are often obtained from other facts non-constructively, so it is less convenient to directly use them to satisfy hypotheses (needing `Exists.some`). We avoid this problem by stating these non-`Prop` hypotheses under `∃`. * Solution `f` exists on any subset `s` of some closed interval, where the derivative of `f` is defined by the value of `f` within `s` only. * Solution `f` exists on any open subset `s` of some closed interval. * There exists `ε > 0` such that a solution `f` exists on `(t₀ - ε, t₀ + ε)`. * As a simple example, we show that time-independent, locally continuously differentiable ODEs satisfy `is_picard_lindelof` and hence a solution exists within some open interval.
1 parent a3240c4 commit f97c17d

File tree

2 files changed

+133
-31
lines changed

2 files changed

+133
-31
lines changed

docs/undergrad.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ Multivariable calculus:
463463
inverse function theorem: 'has_strict_deriv_at.to_local_inverse'
464464
implicit function theorem: 'implicit_function_data.implicit_function'
465465
Differential equations:
466-
Cauchy-Lipschitz Theorem: 'exists_forall_deriv_within_Icc_eq_of_lipschitz_of_continuous'
466+
Cauchy-Lipschitz Theorem: 'exists_forall_deriv_within_Icc_eq_of_is_picard_lindelof'
467467
maximal solutions: ''
468468
Grönwall lemma: 'norm_le_gronwall_bound_of_norm_deriv_right_le'
469469
exit theorem of a compact subspace: ''

src/analysis/ODE/picard_lindelof.lean

Lines changed: 132 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/-
22
Copyright (c) 2021 Yury G. Kudryashov. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Yury G. Kudryashov
4+
Authors: Yury G. Kudryashov, Winston Yin
55
-/
66
import analysis.special_functions.integrals
77
import topology.metric_space.contracting
@@ -11,13 +11,18 @@ import topology.metric_space.contracting
1111
1212
In this file we prove that an ordinary differential equation $\dot x=v(t, x)$ such that $v$ is
1313
Lipschitz continuous in $x$ and continuous in $t$ has a local solution, see
14-
`exists_forall_deriv_within_Icc_eq_of_lipschitz_of_continuous`.
14+
`exists_forall_deriv_within_Icc_eq_of_is_picard_lindelof`.
15+
16+
As a corollary, we prove that a time-independent locally continuously differentiable ODE has a
17+
local solution.
1518
1619
## Implementation notes
1720
1821
In order to split the proof into small lemmas, we introduce a structure `picard_lindelof` that holds
1922
all assumptions of the main theorem. This structure and lemmas in the `picard_lindelof` namespace
20-
should be treated as private implementation details.
23+
should be treated as private implementation details. This is not to be confused with the `Prop`-
24+
valued structure `is_picard_lindelof`, which holds the long hypotheses of the Picard-Lindelöf
25+
theorem for actual use as part of the public API.
2126
2227
We only prove existence of a solution in this file. For uniqueness see `ODE_solution_unique` and
2328
related theorems in `analysis.ODE.gronwall`.
@@ -35,19 +40,35 @@ noncomputable theory
3540

3641
variables {E : Type*} [normed_add_comm_group E] [normed_space ℝ E]
3742

38-
/-- This structure holds arguments of the Picard-Lipschitz (Cauchy-Lipschitz) theorem. Unless you
39-
want to use one of the auxiliary lemmas, use
40-
`exists_forall_deriv_within_Icc_eq_of_lipschitz_of_continuous` instead of using this structure. -/
43+
/-- `Prop` structure holding the hypotheses of the Picard-Lindelöf theorem.
44+
45+
The similarly named `picard_lindelof` structure is part of the internal API for convenience, so as
46+
not to constantly invoke choice, but is not intended for public use. -/
47+
structure is_picard_lindelof
48+
{E : Type*} [normed_add_comm_group E] (v : ℝ → E → E) (t_min t₀ t_max : ℝ) (x₀ : E)
49+
(L : ℝ≥0) (R C : ℝ) : Prop :=
50+
(ht₀ : t₀ ∈ Icc t_min t_max)
51+
(hR : 0 ≤ R)
52+
(lipschitz : ∀ t ∈ Icc t_min t_max, lipschitz_on_with L (v t) (closed_ball x₀ R))
53+
(cont : ∀ x ∈ closed_ball x₀ R, continuous_on (λ (t : ℝ), v t x) (Icc t_min t_max))
54+
(norm_le : ∀ (t ∈ Icc t_min t_max) (x ∈ closed_ball x₀ R), ∥v t x∥ ≤ C)
55+
(C_mul_le_R : (C : ℝ) * linear_order.max (t_max - t₀) (t₀ - t_min) ≤ R)
56+
57+
/-- This structure holds arguments of the Picard-Lipschitz (Cauchy-Lipschitz) theorem. It is part of
58+
the internal API for convenience, so as not to constantly invoke choice. Unless you want to use one
59+
of the auxiliary lemmas, use `exists_forall_deriv_within_Icc_eq_of_lipschitz_of_continuous` instead
60+
of using this structure.
61+
62+
The similarly named `is_picard_lindelof` is a bundled `Prop` holding the long hypotheses of the
63+
Picard-Lindelöf theorem as named arguments. It is used as part of the public API.
64+
-/
4165
structure picard_lindelof (E : Type*) [normed_add_comm_group E] [normed_space ℝ E] :=
4266
(to_fun : ℝ → E → E)
4367
(t_min t_max : ℝ)
4468
(t₀ : Icc t_min t_max)
4569
(x₀ : E)
4670
(C R L : ℝ≥0)
47-
(lipschitz' : ∀ t ∈ Icc t_min t_max, lipschitz_on_with L (to_fun t) (closed_ball x₀ R))
48-
(cont : ∀ x ∈ closed_ball x₀ R, continuous_on (λ t, to_fun t x) (Icc t_min t_max))
49-
(norm_le' : ∀ (t ∈ Icc t_min t_max) (x ∈ closed_ball x₀ R), ∥to_fun t x∥ ≤ C)
50-
(C_mul_le_R : (C : ℝ) * max (t_max - t₀) (t₀ - t_min) ≤ R)
71+
(is_pl : is_picard_lindelof to_fun t_min t₀ t_max x₀ L R C)
5172

5273
namespace picard_lindelof
5374

@@ -56,27 +77,31 @@ variables (v : picard_lindelof E)
5677
instance : has_coe_to_fun (picard_lindelof E) (λ _, ℝ → E → E) := ⟨to_fun⟩
5778

5879
instance : inhabited (picard_lindelof E) :=
59-
⟨⟨0, 0, 0, ⟨0, le_rfl, le_rfl⟩, 0, 0, 0, 0, λ t ht, (lipschitz_with.const 0).lipschitz_on_with _,
60-
λ _ _, by simpa only [pi.zero_apply] using continuous_on_const, λ t ht x hx, norm_zero.le,
61-
(zero_mul _).le⟩⟩
80+
⟨⟨0, 0, 0, ⟨0, le_rfl, le_rfl⟩, 0, 0, 0, 0,
81+
{ ht₀ := by { rw [subtype.coe_mk, Icc_self], exact mem_singleton _ },
82+
hR := by refl,
83+
lipschitz := λ t ht, (lipschitz_with.const 0).lipschitz_on_with _,
84+
cont := λ _ _, by simpa only [pi.zero_apply] using continuous_on_const,
85+
norm_le := λ t ht x hx, norm_zero.le,
86+
C_mul_le_R := (zero_mul _).le }⟩⟩
6287

6388
lemma t_min_le_t_max : v.t_min ≤ v.t_max := v.t₀.2.1.trans v.t₀.2.2
6489

6590
protected lemma nonempty_Icc : (Icc v.t_min v.t_max).nonempty := nonempty_Icc.2 v.t_min_le_t_max
6691

6792
protected lemma lipschitz_on_with {t} (ht : t ∈ Icc v.t_min v.t_max) :
6893
lipschitz_on_with v.L (v t) (closed_ball v.x₀ v.R) :=
69-
v.lipschitz' t ht
94+
v.is_pl.lipschitz t ht
7095

7196
protected lemma continuous_on :
7297
continuous_on (uncurry v) (Icc v.t_min v.t_max ×ˢ closed_ball v.x₀ v.R) :=
7398
have continuous_on (uncurry (flip v)) (closed_ball v.x₀ v.R ×ˢ Icc v.t_min v.t_max),
74-
from continuous_on_prod_of_continuous_on_lipschitz_on _ v.L v.cont v.lipschitz',
99+
from continuous_on_prod_of_continuous_on_lipschitz_on _ v.L v.is_pl.cont v.is_pl.lipschitz,
75100
this.comp continuous_swap.continuous_on preimage_swap_prod.symm.subset
76101

77102
lemma norm_le {t : ℝ} (ht : t ∈ Icc v.t_min v.t_max) {x : E} (hx : x ∈ closed_ball v.x₀ v.R) :
78103
∥v t x∥ ≤ v.C :=
79-
v.norm_le' _ ht _ hx
104+
v.is_pl.norm_le _ ht _ hx
80105

81106
/-- The maximum of distances from `t₀` to the endpoints of `[t_min, t_max]`. -/
82107
def t_dist : ℝ := max (v.t_max - v.t₀) (v.t₀ - v.t_min)
@@ -150,7 +175,7 @@ protected lemma mem_closed_ball (t : Icc v.t_min v.t_max) : f t ∈ closed_ball
150175
calc dist (f t) v.x₀ = dist (f t) (f.to_fun v.t₀) : by rw f.map_t₀'
151176
... ≤ v.C * dist t v.t₀ : f.lipschitz.dist_le_mul _ _
152177
... ≤ v.C * v.t_dist : mul_le_mul_of_nonneg_left (v.dist_t₀_le _) v.C.2
153-
... ≤ v.R : v.C_mul_le_R
178+
... ≤ v.R : v.is_pl.C_mul_le_R
154179

155180
/-- Given a curve $γ \colon [t_{\min}, t_{\max}] → E$, `v_comp` is the function
156181
$F(t)=v(π t, γ(π t))$, where `π` is the projection $ℝ → [t_{\min}, t_{\max}]$. The integral of this
@@ -295,7 +320,8 @@ let ⟨N, K, hK⟩ := exists_contracting_iterate v in ⟨_, hK.is_fixed_pt_fixed
295320

296321
end
297322

298-
/-- Picard-Lindelöf (Cauchy-Lipschitz) theorem. -/
323+
/-- Picard-Lindelöf (Cauchy-Lipschitz) theorem. Use
324+
`exists_forall_deriv_within_Icc_eq_of_is_picard_lindelof` instead for the public API. -/
299325
lemma exists_solution :
300326
∃ f : ℝ → E, f v.t₀ = v.x₀ ∧ ∀ t ∈ Icc v.t_min v.t_max,
301327
has_deriv_within_at f (v t (f t)) (Icc v.t_min v.t_max) t :=
@@ -310,21 +336,97 @@ end
310336

311337
end picard_lindelof
312338

339+
lemma is_picard_lindelof.norm_le₀ {E : Type*} [normed_add_comm_group E]
340+
{v : ℝ → E → E} {t_min t₀ t_max : ℝ} {x₀ : E} {C R : ℝ} {L : ℝ≥0}
341+
(hpl : is_picard_lindelof v t_min t₀ t_max x₀ L R C) : ∥v t₀ x₀∥ ≤ C :=
342+
hpl.norm_le t₀ hpl.ht₀ x₀ $ mem_closed_ball_self hpl.hR
343+
313344
/-- Picard-Lindelöf (Cauchy-Lipschitz) theorem. -/
314-
lemma exists_forall_deriv_within_Icc_eq_of_lipschitz_of_continuous
315-
[complete_space E]
316-
{v : ℝ → E → E} {t_min t₀ t_max : ℝ} (ht₀ : t₀ ∈ Icc t_min t_max)
317-
(x₀ : E) {C R : ℝ} (hR : 0 ≤ R) {L : ℝ≥0}
318-
(Hlip : ∀ t ∈ Icc t_min t_max, lipschitz_on_with L (v t) (closed_ball x₀ R))
319-
(Hcont : ∀ x ∈ closed_ball x₀ R, continuous_on (λ t, v t x) (Icc t_min t_max))
320-
(Hnorm : ∀ (t ∈ Icc t_min t_max) (x ∈ closed_ball x₀ R), ∥v t x∥ ≤ C)
321-
(Hmul_le : C * max (t_max - t₀) (t₀ - t_min) ≤ R) :
345+
theorem exists_forall_deriv_within_Icc_eq_of_is_picard_lindelof
346+
[complete_space E] {v : ℝ → E → E} {t_min t₀ t_max : ℝ} (x₀ : E) {C R : ℝ} {L : ℝ≥0}
347+
(hpl : is_picard_lindelof v t_min t₀ t_max x₀ L R C) :
322348
∃ f : ℝ → E, f t₀ = x₀ ∧ ∀ t ∈ Icc t_min t_max,
323349
has_deriv_within_at f (v t (f t)) (Icc t_min t_max) t :=
324350
begin
325-
lift C to ℝ≥0 using ((norm_nonneg _).trans $ Hnorm t₀ ht₀ x₀ (mem_closed_ball_self hR)),
326-
lift R to ℝ≥0 using hR,
327-
lift t₀ to Icc t_min t_max using ht₀,
351+
lift C to ℝ≥0 using (norm_nonneg _).trans hpl.norm_le₀,
352+
lift t₀ to Icc t_min t_max using hpl.ht₀,
328353
exact picard_lindelof.exists_solution
329-
⟨v, t_min, t_max, t₀, x₀, C, R, L, Hlip, Hcont, Hnorm, Hmul_le
354+
⟨v, t_min, t_max, t₀, x₀, C, R, hpl.hR⟩, L, { ht₀ := t₀.property, ..hpl }
330355
end
356+
357+
variables [proper_space E] {v : E → E} (t₀ : ℝ) (x₀ : E)
358+
359+
/-- A time-independent, locally continuously differentiable ODE satisfies the hypotheses of the
360+
Picard-Lindelöf theorem. -/
361+
lemma exists_is_picard_lindelof_const_of_cont_diff_on_nhds
362+
{s : set E} (hv : cont_diff_on ℝ 1 v s) (hs : s ∈ 𝓝 x₀) :
363+
∃ (ε > (0 : ℝ)) L R C, is_picard_lindelof (λ t, v) (t₀ - ε) t₀ (t₀ + ε) x₀ L R C :=
364+
begin
365+
-- extract Lipschitz constant
366+
obtain ⟨L, s', hs', hlip⟩ := cont_diff_at.exists_lipschitz_on_with
367+
((hv.cont_diff_within_at (mem_of_mem_nhds hs)).cont_diff_at hs),
368+
-- radius of closed ball in which v is bounded
369+
obtain ⟨r, hr : 0 < r, hball⟩ := metric.mem_nhds_iff.mp (inter_sets (𝓝 x₀) hs hs'),
370+
have hr' := (half_pos hr).le,
371+
obtain ⟨C, hC⟩ := (is_compact_closed_ball x₀ (r / 2)).bdd_above_image -- uses proper_space E
372+
(hv.continuous_on.norm.mono (subset_inter_iff.mp
373+
((closed_ball_subset_ball (half_lt_self hr)).trans hball)).left),
374+
have hC' : 0 ≤ C,
375+
{ apply (norm_nonneg (v x₀)).trans,
376+
apply hC,
377+
exact ⟨x₀, ⟨mem_closed_ball_self hr', rfl⟩⟩ },
378+
set ε := if C = 0 then 1 else (r / 2 / C) with hε,
379+
have0 : 0 < ε,
380+
{ rw hε,
381+
split_ifs,
382+
{ exact zero_lt_one },
383+
{ exact div_pos (half_pos hr) (lt_of_le_of_ne hC' (ne.symm h)) } },
384+
refine ⟨ε, hε0, L, r / 2, C, _⟩,
385+
exact { ht₀ := by {rw ←real.closed_ball_eq_Icc, exact mem_closed_ball_self hε0.le},
386+
hR := (half_pos hr).le,
387+
lipschitz := λ t ht, hlip.mono (subset_inter_iff.mp
388+
(subset_trans (closed_ball_subset_ball (half_lt_self hr)) hball)).2,
389+
cont := λ x hx, continuous_on_const,
390+
norm_le := λ t ht x hx, hC ⟨x, hx, rfl⟩,
391+
C_mul_le_R := begin
392+
rw [add_sub_cancel', sub_sub_cancel, max_self, mul_ite, mul_one],
393+
split_ifs,
394+
{ rwa ← h at hr' },
395+
{ exact (mul_div_cancel' (r / 2) h).le }
396+
end }
397+
end
398+
399+
/-- A time-independent, locally continuously differentiable ODE admits a solution in some open
400+
interval. -/
401+
theorem exists_forall_deriv_at_Ioo_eq_of_cont_diff_on_nhds
402+
{s : set E} (hv : cont_diff_on ℝ 1 v s) (hs : s ∈ 𝓝 x₀) :
403+
∃ (ε > (0 : ℝ)) (f : ℝ → E), f t₀ = x₀ ∧
404+
∀ t ∈ Ioo (t₀ - ε) (t₀ + ε), f t ∈ s ∧ has_deriv_at f (v (f t)) t :=
405+
begin
406+
obtain ⟨ε, hε, L, R, C, hpl⟩ := exists_is_picard_lindelof_const_of_cont_diff_on_nhds t₀ x₀ hv hs,
407+
obtain ⟨f, hf1, hf2⟩ := exists_forall_deriv_within_Icc_eq_of_is_picard_lindelof x₀ hpl,
408+
have hf2' : ∀ t ∈ Ioo (t₀ - ε) (t₀ + ε), has_deriv_at f (v (f t)) t :=
409+
λ t ht, (hf2 t (Ioo_subset_Icc_self ht)).has_deriv_at (Icc_mem_nhds ht.1 ht.2),
410+
have h : (f ⁻¹' s) ∈ 𝓝 t₀,
411+
{ have := (hf2' t₀ (mem_Ioo.mpr ⟨sub_lt_self _ hε, lt_add_of_pos_right _ hε⟩)),
412+
apply continuous_at.preimage_mem_nhds this.continuous_at,
413+
rw hf1,
414+
exact hs },
415+
rw metric.mem_nhds_iff at h,
416+
obtain ⟨r, hr1, hr2⟩ := h,
417+
refine ⟨min r ε, lt_min hr1 hε, f, hf1, λ t ht,
418+
⟨_, hf2' t (mem_of_mem_of_subset ht (Ioo_subset_Ioo
419+
(sub_le_sub_left (min_le_right _ _) _) (add_le_add_left (min_le_right _ _) _)))⟩⟩,
420+
rw ←set.mem_preimage,
421+
apply set.mem_of_mem_of_subset _ hr2,
422+
apply set.mem_of_mem_of_subset ht,
423+
rw ←real.ball_eq_Ioo,
424+
exact (metric.ball_subset_ball (min_le_left _ _))
425+
end
426+
427+
/-- A time-independent, continuously differentiable ODE admits a solution in some open interval. -/
428+
theorem exists_forall_deriv_at_Ioo_eq_of_cont_diff
429+
(hv : cont_diff ℝ 1 v) : ∃ (ε > (0 : ℝ)) (f : ℝ → E), f t₀ = x₀ ∧
430+
∀ t ∈ Ioo (t₀ - ε) (t₀ + ε), has_deriv_at f (v (f t)) t :=
431+
let ⟨ε, hε, f, hf1, hf2⟩ := exists_forall_deriv_at_Ioo_eq_of_cont_diff_on_nhds t₀ x₀ hv.cont_diff_on
432+
(is_open.mem_nhds is_open_univ (mem_univ _)) in ⟨ε, hε, f, hf1, λ t ht, (hf2 t ht).2

0 commit comments

Comments
 (0)