Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat: Lipschitz extensions of maps into l^infty #5107

Closed
wants to merge 16 commits into from
Closed
43 changes: 42 additions & 1 deletion Mathlib/Analysis/NormedSpace/lpSpace.lean
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issu

noncomputable section

open scoped NNReal ENNReal BigOperators
open scoped NNReal ENNReal BigOperators Function

variable {α : Type _} {E : α → Type _} {p q : ℝ≥0∞} [∀ i, NormedAddCommGroup (E i)]

Expand Down Expand Up @@ -325,6 +325,9 @@ def lp (E : α → Type _) [∀ i, NormedAddCommGroup (E i)] (p : ℝ≥0∞) :
neg_mem' := Memℓp.neg
#align lp lp

scoped[lp] notation "ℓ^∞(" ι ", " E ")" => lp (fun i : ι => E) ∞
scoped[lp] notation "ℓ^∞(" ι ")" => lp (fun i : ι => ℝ) ∞

namespace lp

-- Porting note: was `Coe`
Expand Down Expand Up @@ -1217,3 +1220,41 @@ instance completeSpace : CompleteSpace (lp E p) :=
end Topology

end lp

section Lipschitz

open ENNReal lp

lemma LipschitzWith.uniformly_bounded [PseudoMetricSpace α] (g : α → ι → ℝ) {K : ℝ≥0}
(hg : ∀ i, LipschitzWith K (g · i)) (a₀ : α) (hga₀b : Memℓp (g a₀) ∞) (a : α) :
Memℓp (g a) ∞ := by
rcases hga₀b with ⟨M, hM⟩
use ↑K * dist a a₀ + M
rintro - ⟨i, rfl⟩
calc
|g a i| = |g a i - g a₀ i + g a₀ i| := by simp
_ ≤ |g a i - g a₀ i| + |g a₀ i| := abs_add _ _
_ ≤ ↑K * dist a a₀ + M := by
gcongr
. exact lipschitzWith_iff_dist_le_mul.1 (hg i) a a₀
. exact hM ⟨i, rfl⟩

theorem LipschitzOnWith.coordinate [PseudoMetricSpace α] (f : α → ℓ^∞(ι)) (s : Set α) (K : ℝ≥0) :
LipschitzOnWith K f s ↔ ∀ i : ι, LipschitzOnWith K (fun a : α ↦ f a i) s := by
simp_rw [lipschitzOnWith_iff_dist_le_mul]
constructor
· intro hfl i x hx y hy
calc
dist (f x i) (f y i) ≤ dist (f x) (f y) := lp.norm_apply_le_norm top_ne_zero (f x - f y) i
_ ≤ K * dist x y := hfl x hx y hy
· intro hgl x hx y hy
apply lp.norm_le_of_forall_le; positivity
intro i
apply hgl i x hx y hy

theorem LipschitzWith.coordinate [PseudoMetricSpace α] {f : α → ℓ^∞(ι)} (K : ℝ≥0) :
LipschitzWith K f ↔ ∀ i : ι, LipschitzWith K (fun a : α ↦ f a i) := by
simp_rw [← lipschitz_on_univ]
apply LipschitzOnWith.coordinate

end Lipschitz
66 changes: 51 additions & 15 deletions Mathlib/Topology/MetricSpace/Kuratowski.lean
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,33 @@ import Mathlib.Topology.Sets.Compacts
/-!
# The Kuratowski embedding

Any separable metric space can be embedded isometrically in `ℓ^∞(ℝ)`.
Any separable metric space can be embedded isometrically in `ℓ^∞(ℕ, ℝ)`.
Any partially defined Lipschitz map into `ℓ^∞` can be extended to the whole space.

-/


noncomputable section

set_option linter.uppercaseLean3 false

open Set Metric TopologicalSpace

open scoped ENNReal

local notation "ℓ_infty_ℝ" => lp (fun n : ℕ => ℝ) ∞
open Set Metric TopologicalSpace NNReal ENNReal lp Function

universe u v w

variable {α : Type u} {β : Type v} {γ : Type w}

namespace KuratowskiEmbedding

/-! ### Any separable metric space can be embedded isometrically in ℓ^∞(ℝ) -/
/-! ### Any separable metric space can be embedded isometrically in ℓ^∞(ℕ, ℝ) -/
chriscamano marked this conversation as resolved.
Show resolved Hide resolved


variable {f g : ℓ_infty_ℝ} {n : ℕ} {C : ℝ} [MetricSpace α] (x : ℕ → α) (a b : α)
variable {f g : ℓ^∞(ℕ)} {n : ℕ} {C : ℝ} [MetricSpace α] (x : ℕ → α) (a b : α)

/-- A metric space can be embedded in `l^∞(ℝ)` via the distances to points in
a fixed countable set, if this set is dense. This map is given in `kuratowskiEmbedding`,
without density assumptions. -/
def embeddingOfSubset : ℓ_infty_ℝ :=
def embeddingOfSubset : ℓ^∞(ℕ) :=
⟨fun n => dist a (x n) - dist (x 0) (x n), by
apply memℓp_infty
use dist a (x 0)
Expand Down Expand Up @@ -93,9 +91,9 @@ theorem embeddingOfSubset_isometry (H : DenseRange x) : Isometry (embeddingOfSub
simpa [dist_comm] using this
#align Kuratowski_embedding.embedding_of_subset_isometry KuratowskiEmbedding.embeddingOfSubset_isometry

/-- Every separable metric space embeds isometrically in `ℓ_infty_ℝ`. -/
/-- Every separable metric space embeds isometrically in `ℓ^∞(ℕ)`. -/
theorem exists_isometric_embedding (α : Type u) [MetricSpace α] [SeparableSpace α] :
∃ f : α → ℓ_infty_ℝ, Isometry f := by
∃ f : α → ℓ^∞(ℕ), Isometry f := by
cases' (univ : Set α).eq_empty_or_nonempty with h h
· use fun _ => 0; intro x; exact absurd h (Nonempty.ne_empty ⟨x, mem_univ x⟩)
· -- We construct a map x : ℕ → α with dense image
Expand All @@ -112,21 +110,59 @@ end KuratowskiEmbedding

open TopologicalSpace KuratowskiEmbedding

/-- The Kuratowski embedding is an isometric embedding of a separable metric space in `ℓ^∞(ℝ)`. -/
def kuratowskiEmbedding (α : Type u) [MetricSpace α] [SeparableSpace α] : α → ℓ_infty_ℝ :=
/-- The Kuratowski embedding is an isometric embedding of a separable metric space in `ℓ^∞(ℕ, ℝ)`.
-/
def kuratowskiEmbedding (α : Type u) [MetricSpace α] [SeparableSpace α] : α → ℓ^∞(ℕ) :=
Classical.choose (KuratowskiEmbedding.exists_isometric_embedding α)
#align Kuratowski_embedding kuratowskiEmbedding

/-- The Kuratowski embedding is an isometry. -/
/--
The Kuratowski embedding is an isometry.
Theorem 2.1 of [Assaf Naor, *Metric Embeddings and Lipschitz Extensions*][Naor-2015]. -/
protected theorem kuratowskiEmbedding.isometry (α : Type u) [MetricSpace α] [SeparableSpace α] :
Isometry (kuratowskiEmbedding α) :=
Classical.choose_spec (exists_isometric_embedding α)
#align Kuratowski_embedding.isometry kuratowskiEmbedding.isometry

/-- Version of the Kuratowski embedding for nonempty compacts -/
nonrec def NonemptyCompacts.kuratowskiEmbedding (α : Type u) [MetricSpace α] [CompactSpace α]
[Nonempty α] : NonemptyCompacts ℓ_infty_ℝ where
[Nonempty α] : NonemptyCompacts ℓ^∞(ℕ) where
carrier := range (kuratowskiEmbedding α)
isCompact' := isCompact_range (kuratowskiEmbedding.isometry α).continuous
nonempty' := range_nonempty _
#align nonempty_compacts.Kuratowski_embedding NonemptyCompacts.kuratowskiEmbedding

/--
A function `f : α → ℓ^∞(ι, ℝ)` which is `K`-Lipschitz on a subset `s` admits a `K`-Lipschitz
extension to the whole space.

Theorem 2.2 of [Assaf Naor, *Metric Embeddings and Lipschitz Extensions*][Naor-2015]

The same result for the case of a finite type `ι` is implemented in
`LipschitzOnWith.extend_pi`.
-/
theorem LipschitzOnWith.extend_lp_infty [PseudoMetricSpace α] {s : Set α} {f : α → ℓ^∞(ι)}
{K : ℝ≥0} (hfl : LipschitzOnWith K f s): ∃ g : α → ℓ^∞(ι), LipschitzWith K g ∧ EqOn f g s := by
chriscamano marked this conversation as resolved.
Show resolved Hide resolved
-- Construct the coordinate-wise extensions
rw [LipschitzOnWith.coordinate] at hfl
have : ∀ i : ι, ∃ g : α → ℝ, LipschitzWith K g ∧ EqOn (fun x => f x i) g s
· intro i
exact LipschitzOnWith.extend_real (hfl i) -- use the nonlinear Hahn-Banach theorem here!
choose g hgl hgeq using this
rcases s.eq_empty_or_nonempty with rfl | ⟨a₀, ha₀_in_s⟩
. exact ⟨0, LipschitzWith.const' 0, by simp⟩
· -- Show that the extensions are uniformly bounded
have hf_extb : ∀ a : α, Memℓp (swap g a) ∞
. apply LipschitzWith.uniformly_bounded (swap g) hgl a₀
use ‖f a₀‖
rintro - ⟨i, rfl⟩
simp_rw [←hgeq i ha₀_in_s]
exact lp.norm_apply_le_norm top_ne_zero (f a₀) i
-- Construct witness by bundling the function with its certificate of membership in ℓ^∞
let f_ext' : α → ℓ^∞(ι) := fun i ↦ ⟨swap g i, hf_extb i⟩
refine ⟨f_ext', ?_, ?_⟩
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you write refine' ⟨fun i ↦ ⟨swap g i, _⟩, _, _⟩, then you can move hf_extb as an extra goal from the refine.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the other two refactors, but I think that it is clearer if we explicitly name our witness and show how it is constructed. I think it would take longer for someone to go through the proof if they have to make the realization themself that swap g i is the desired extension. One sticking point in the proof for us was also this translation back and forth between functions from alpha to iota to R and functions from alpha to l^infty(iota, R). Here it is clear that we get from a function from alpha to iota to R to one from alpha to l^infty(iota, R) by bundling it with a certificate that it is bound. If we instead leave it as inferred and it pops up as an extra goal I think that is more confusing. Also, with no explicit mention of f_ext the term hf_extb ("hypothesis that f_ext is bounded") would have to be changed and given that I cannot think of a meaningful way to name it I think that that is strong evidence that the way the proof is structured now is fairly natural.

However, I am very new and if I've completely misunderstood this suggestion or there is a general consensus on this type of issue I'm certainly open to the change.

Now that we have replaced all mentions of f_ext with swap g i, I do think we should replace f_ext' with f_ext.

Copy link
Collaborator

@tb65536 tb65536 Jun 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You wouldn't have to choose a new name for hf_extb, since it would just become an extra goal:

    refine' ⟨fun i ↦ ⟨swap g i, _⟩, _, _⟩
    . apply LipschitzWith.uniformly_bounded (swap g) hgl a₀
      use ‖f a₀‖
      rintro - ⟨i, rfl⟩
      simp_rw [←hgeq i ha₀_in_s]
      exact lp.norm_apply_le_norm top_ne_zero (f a₀) i
    · rw [LipschitzWith.coordinate]
      exact hgl
    · intro a hyp
      ext i
      exact (hgeq i) hyp

But I do see what you're saying about how it's nice to make it clear what the extension is, and I'm fine with keeping the current proof structure. I do like renaming f_ext' to f_ext, and using refine' rather than refine:

    let f_ext : α → ℓ^∞(ι) := fun i ↦ ⟨swap g i, hf_extb i⟩
    refine' ⟨f_ext, _, _⟩

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see! Thanks for all the helpful comments!

· rw [LipschitzWith.coordinate]
exact hgl
· intro a hyp
ext i
exact (hgeq i) hyp
8 changes: 5 additions & 3 deletions Mathlib/Topology/MetricSpace/Lipschitz.lean
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ protected theorem const (b : β) : LipschitzWith 0 fun _ : α => b := fun x y =>
simp only [edist_self, zero_le]
#align lipschitz_with.const LipschitzWith.const

protected theorem const' (b : β) {K : ℝ≥0} : LipschitzWith K fun _ : α => b := fun x y => by
simp only [edist_self, zero_le]

protected theorem id : LipschitzWith 1 (@id α) :=
LipschitzWith.of_edist_le fun _ _ => le_rfl
#align lipschitz_with.id LipschitzWith.id
Expand Down Expand Up @@ -669,9 +672,8 @@ theorem LipschitzOnWith.extend_real [PseudoMetricSpace α] {f : α → ℝ} {s :
#align lipschitz_on_with.extend_real LipschitzOnWith.extend_real

/-- A function `f : α → (ι → ℝ)` which is `K`-Lipschitz on a subset `s` admits a `K`-Lipschitz
extension to the whole space.
TODO: state the same result (with the same proof) for the space `ℓ^∞ (ι, ℝ)` over a possibly
infinite type `ι`. -/
extension to the whole space. The same result for the space `ℓ^∞ (ι, ℝ)` over a possibly infinite
type `ι` is implemented in `LipschitzOnWith.extend_lp_infty`.-/
theorem LipschitzOnWith.extend_pi [PseudoMetricSpace α] [Fintype ι] {f : α → ι → ℝ} {s : Set α}
{K : ℝ≥0} (hf : LipschitzOnWith K f s) : ∃ g : α → ι → ℝ, LipschitzWith K g ∧ EqOn f g s := by
have : ∀ i, ∃ g : α → ℝ, LipschitzWith K g ∧ EqOn (fun x => f x i) g s := fun i => by
Expand Down
7 changes: 7 additions & 0 deletions docs/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -1832,6 +1832,13 @@ @Article{ MR577178
url = {https://doi.org/10.1007/BF00417500}
}

@Unpublished{ Naor-2015,
author = {Assaf Naor},
title = {Metric Embeddings and Lipschitz Extensions},
year = {2015},
url = {https://web.math.princeton.edu/~naor/homepage%20files/embeddings_extensions.pdf}
}

@Article{ Nash-Williams63,
title = {On well-quasi-ordering finite trees},
volume = {59},
Expand Down