Skip to content

Commit 3ed2362

Browse files
committed
refactor(LipschitzSmooth/Algebra): rewrite hypothesis-free under abs predicate
The two-sided abs form of `LipschitzSmoothWith` (predicated on the weakest form `lineDeriv`) implies line-differentiability everywhere via `LipschitzSmoothWith.hasLineDerivAt`, so the algebraic preservation lemmas no longer require any `Differentiable ℝ f` hypothesis: - `add` works in pure `lineDeriv` form by computing `HasLineDerivAt (f₁ + f₂)` from the two pointwise `hasLineDerivAt` witnesses (via `HasDerivAt.add`), then chaining the triangle inequality with the two abs bounds. - `const_smul` analogously via `HasDerivAt.const_smul` and `abs_mul` plus `abs_of_nonneg` (since `c : NNReal ≥ 0`). - `neg` becomes trivial under the abs predicate (it was not provable under the old one-sided descent form), with the *same* constant `K`. Also fix the `lipschitzSmoothWith_affine` proof in `Basic.lean` (the post-`map_sub` goal is now `|0| ≤ 0` rather than the old descent `linarith`-trivial goal, so the closing tactic switches to `simp`). The module docstring is updated to drop the (now-false) "not closed under negation" caveat — that was a consequence of the one-sided form and disappears in the two-sided form. The deferred-follow-up sorry on `comp_continuousAffineMap` is unchanged.
1 parent 14e35a2 commit 3ed2362

2 files changed

Lines changed: 55 additions & 29 deletions

File tree

Mathlib/Analysis/Calculus/LipschitzSmooth/Algebra.lean

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ public import Mathlib.Analysis.Normed.Affine.ContinuousAffineMap
1313
1414
Closure properties of the `LipschitzSmoothWith` predicate under the standard algebraic
1515
operations: pointwise addition (with `K₁ + K₂`), nonnegative scalar multiplication (with
16-
`c · K`), and composition with continuous affine maps (with `‖A.contLinear‖² · K`).
16+
`c · K`), and composition with continuous affine maps (with `‖A.contLinear‖² · K`). The
17+
two-sided abs-form of the predicate also makes it closed under negation (same `K`) and so
18+
under scaling by arbitrary real `c` (with `|c| · K`).
1719
1820
The basic K = 0 cases for constants and affine functions live in
19-
`Mathlib.Analysis.Calculus.LipschitzSmooth.Basic`. Note that `LipschitzSmoothWith` is *not*
20-
closed under negation or negative scaling — the descent inequality is one-sided, mirroring
21-
the asymmetry of concavity.
21+
`Mathlib.Analysis.Calculus.LipschitzSmooth.Basic`. None of the lemmas here require any
22+
differentiability hypothesis — `LipschitzSmoothWith` implies line-differentiability
23+
everywhere via `LipschitzSmoothWith.hasLineDerivAt`.
2224
-/
2325

2426
public section
@@ -36,30 +38,55 @@ theorem lipschitzSmoothWith_continuousAffineMap (A : F →ᴬ[ℝ] ℝ) :
3638

3739
namespace LipschitzSmoothWith
3840

39-
/-- Sum of `K₁`-smooth and `K₂`-smooth (differentiable) is `(K₁ + K₂)`-smooth. -/
40-
theorem add (h₁ : LipschitzSmoothWith K₁ f₁) (h₂ : LipschitzSmoothWith K₂ f₂)
41-
(hf₁ : Differentiable ℝ f₁) (hf₂ : Differentiable ℝ f₂) :
42-
LipschitzSmoothWith (K₁ + K₂) (f₁ + f₂) := by
43-
rw [lipschitzSmoothWith_iff_fderiv (hf₁.add hf₂)]
44-
intro x y
45-
rw [fderiv_add (hf₁ x) (hf₂ x), ContinuousLinearMap.add_apply]
46-
have h1 := (lipschitzSmoothWith_iff_fderiv hf₁).mp h₁ x y
47-
have h2 := (lipschitzSmoothWith_iff_fderiv hf₂).mp h₂ x y
48-
push_cast
49-
simp only [Pi.add_apply]
50-
linarith
41+
/-- Sum of `K₁`-smooth and `K₂`-smooth is `(K₁ + K₂)`-smooth. No differentiability hypothesis
42+
needed: each summand is line-differentiable everywhere (`hasLineDerivAt`), so the sum is too,
43+
with line-derivative the sum of line-derivatives. -/
44+
theorem add (h₁ : LipschitzSmoothWith K₁ f₁) (h₂ : LipschitzSmoothWith K₂ f₂) :
45+
LipschitzSmoothWith (K₁ + K₂) (f₁ + f₂) := lipschitzSmoothWith_iff_lineDeriv.mpr fun x y => by
46+
have hd : HasLineDerivAt ℝ (f₁ + f₂)
47+
(lineDeriv ℝ f₁ x (y - x) + lineDeriv ℝ f₂ x (y - x)) x (y - x) :=
48+
HasDerivAt.add (h₁.hasLineDerivAt x (y - x)) (h₂.hasLineDerivAt x (y - x))
49+
rw [hd.lineDeriv]
50+
have h1 := h₁.lineDeriv_abs_le x y
51+
have h2 := h₂.lineDeriv_abs_le x y
52+
calc |(f₁ + f₂) y - (f₁ + f₂) x - (lineDeriv ℝ f₁ x (y - x) + lineDeriv ℝ f₂ x (y - x))|
53+
= |(f₁ y - f₁ x - lineDeriv ℝ f₁ x (y - x))
54+
+ (f₂ y - f₂ x - lineDeriv ℝ f₂ x (y - x))| := by
55+
simp only [Pi.add_apply]; ring_nf
56+
_ ≤ |f₁ y - f₁ x - lineDeriv ℝ f₁ x (y - x)|
57+
+ |f₂ y - f₂ x - lineDeriv ℝ f₂ x (y - x)| := abs_add_le _ _
58+
_ ≤ ↑(K₁ + K₂) / 2 * (dist x y) ^ 2 := by push_cast; linarith
5159

52-
/-- Scaling a `K`-smooth (differentiable) function by `c : NNReal` gives `(c * K)`-smoothness. -/
53-
theorem const_smul (h : LipschitzSmoothWith K f) (hf : Differentiable ℝ f) (c : NNReal) :
54-
LipschitzSmoothWith (c * K) ((c : ℝ) • f) := by
55-
have hcf : Differentiable ℝ ((c : ℝ) • f) := hf.const_smul (c : ℝ)
56-
rw [lipschitzSmoothWith_iff_fderiv hcf]
57-
intro x y
58-
rw [fderiv_const_smul (hf x) (c : ℝ), ContinuousLinearMap.smul_apply]
59-
have hd := (lipschitzSmoothWith_iff_fderiv hf).mp h x y
60-
push_cast
61-
simp only [Pi.smul_apply, smul_eq_mul]
62-
nlinarith [c.coe_nonneg, sq_nonneg (dist x y)]
60+
/-- Negation preserves `K`-smoothness with the same constant. Trivial under the two-sided
61+
abs form of the predicate. -/
62+
theorem neg (h : LipschitzSmoothWith K f) : LipschitzSmoothWith K (-f) :=
63+
lipschitzSmoothWith_iff_lineDeriv.mpr fun x y => by
64+
have hd : HasLineDerivAt ℝ (-f) (-lineDeriv ℝ f x (y - x)) x (y - x) :=
65+
HasDerivAt.neg (h.hasLineDerivAt x (y - x))
66+
rw [hd.lineDeriv]
67+
have habs := h.lineDeriv_abs_le x y
68+
rw [show ((-f) y - (-f) x - -lineDeriv ℝ f x (y - x))
69+
= -(f y - f x - lineDeriv ℝ f x (y - x)) from by simp; ring, abs_neg]
70+
exact habs
71+
72+
/-- Scaling a `K`-smooth function by `c : NNReal` gives `(c * K)`-smoothness. No
73+
differentiability hypothesis needed: line-differentiability follows from `hasLineDerivAt`. -/
74+
theorem const_smul (h : LipschitzSmoothWith K f) (c : NNReal) :
75+
LipschitzSmoothWith (c * K) ((c : ℝ) • f) := lipschitzSmoothWith_iff_lineDeriv.mpr fun x y => by
76+
have hd : HasLineDerivAt ℝ ((c : ℝ) • f) ((c : ℝ) • lineDeriv ℝ f x (y - x)) x (y - x) :=
77+
(h.hasLineDerivAt x (y - x)).const_smul (c : ℝ)
78+
rw [hd.lineDeriv]
79+
have habs := h.lineDeriv_abs_le x y
80+
have hc : (0 : ℝ) ≤ c := c.coe_nonneg
81+
calc |((c : ℝ) • f) y - ((c : ℝ) • f) x - (c : ℝ) • lineDeriv ℝ f x (y - x)|
82+
= (c : ℝ) * |f y - f x - lineDeriv ℝ f x (y - x)| := by
83+
simp only [Pi.smul_apply, smul_eq_mul]
84+
rw [show (c : ℝ) * f y - (c : ℝ) * f x - (c : ℝ) * lineDeriv ℝ f x (y - x)
85+
= (c : ℝ) * (f y - f x - lineDeriv ℝ f x (y - x)) from by ring,
86+
abs_mul, abs_of_nonneg hc]
87+
_ ≤ ↑(c * K) / 2 * (dist x y) ^ 2 := by
88+
push_cast
89+
nlinarith [sq_nonneg (dist x y), K.coe_nonneg]
6390

6491
/-- Composition of a `K`-smooth `f : F → ℝ` with a continuous affine map `A : F' →ᴬ[ℝ] F`
6592
is `(‖A.contLinear‖² · K)`-smooth on `F'`. -/

Mathlib/Analysis/Calculus/LipschitzSmooth/Basic.lean

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ theorem lipschitzSmoothWith_affine (ℓ : F →L[ℝ] ℝ) (c : ℝ) :
130130
lipschitzSmoothWith_iff_lineDeriv.mpr fun x y => by
131131
have h : HasFDerivAt (fun y : F => ℓ y + c) ℓ x := ℓ.hasFDerivAt.add_const c
132132
rw [(h.hasLineDerivAt (y - x)).lineDeriv, map_sub]
133-
push_cast
134-
linarith
133+
simp
135134

136135
/-- A constant function is `0`-smooth. Special case of `lipschitzSmoothWith_affine` with `ℓ = 0`. -/
137136
theorem lipschitzSmoothWith_const (c : ℝ) : LipschitzSmoothWith (0 : NNReal) (fun _ : F => c) := by

0 commit comments

Comments
 (0)