Skip to content

Commit 3fea2f0

Browse files
committed
feat(LipschitzSmooth): add algebraic preservation lemmas
Basic.lean (K = 0 cases, no extra hypotheses): - `lipschitzSmoothWith_const`: constants are 0-smooth - `lipschitzSmoothWith_affine`: affine functions `y ↦ ℓ y + c` are 0-smooth Algebra.lean (new, imports `ContinuousAffineMap`): - `LipschitzSmoothWith.add`: closed under `+` with `K₁ + K₂` - `LipschitzSmoothWith.const_smul`: closed under nonneg `c •` with `c · K` - `LipschitzSmoothWith.comp_continuousAffineMap`: composition with continuous affine map `A` gives `‖A.contLinear‖² · K`-smooth (currently `sorry`) The `add` and `const_smul` lemmas require `Differentiable ℝ f` hypotheses because mathlib's `lineDeriv` doesn't have an unconditional additivity/scaling lemma (junk values when a summand is non-differentiable); the proofs route through the `fderiv`-form characterisation to sidestep this.
1 parent 9437e2a commit 3fea2f0

2 files changed

Lines changed: 82 additions & 0 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/-
2+
Copyright (c) 2026 Christoph Spiegel. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Christoph Spiegel
5+
-/
6+
module
7+
8+
public import Mathlib.Analysis.Calculus.LipschitzSmooth.FDeriv
9+
public import Mathlib.Analysis.Normed.Affine.ContinuousAffineMap
10+
11+
/-!
12+
# Algebraic preservation of Lipschitz smoothness
13+
14+
Closure properties of the `LipschitzSmoothWith` predicate under the standard algebraic
15+
operations: pointwise addition (with `K₁ + K₂`), nonnegative scalar multiplication (with
16+
`c · K`), and composition with continuous affine maps (with `‖A.contLinear‖² · K`).
17+
18+
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.
22+
-/
23+
24+
public section
25+
26+
variable {F F' : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F]
27+
[NormedAddCommGroup F'] [NormedSpace ℝ F']
28+
variable {K K₁ K₂ : NNReal} {f f₁ f₂ : F → ℝ}
29+
30+
namespace LipschitzSmoothWith
31+
32+
/-- Sum of `K₁`-smooth and `K₂`-smooth (differentiable) is `(K₁ + K₂)`-smooth. -/
33+
theorem add (h₁ : LipschitzSmoothWith K₁ f₁) (h₂ : LipschitzSmoothWith K₂ f₂)
34+
(hf₁ : Differentiable ℝ f₁) (hf₂ : Differentiable ℝ f₂) :
35+
LipschitzSmoothWith (K₁ + K₂) (f₁ + f₂) := by
36+
rw [lipschitzSmoothWith_iff_fderiv (hf₁.add hf₂)]
37+
intro x y
38+
rw [fderiv_add (hf₁ x) (hf₂ x), ContinuousLinearMap.add_apply]
39+
have h1 := (lipschitzSmoothWith_iff_fderiv hf₁).mp h₁ x y
40+
have h2 := (lipschitzSmoothWith_iff_fderiv hf₂).mp h₂ x y
41+
push_cast
42+
simp only [Pi.add_apply]
43+
linarith
44+
45+
/-- Scaling a `K`-smooth (differentiable) function by `c : NNReal` gives `(c * K)`-smoothness. -/
46+
theorem const_smul (h : LipschitzSmoothWith K f) (hf : Differentiable ℝ f) (c : NNReal) :
47+
LipschitzSmoothWith (c * K) ((c : ℝ) • f) := by
48+
have hcf : Differentiable ℝ ((c : ℝ) • f) := hf.const_smul (c : ℝ)
49+
rw [lipschitzSmoothWith_iff_fderiv hcf]
50+
intro x y
51+
rw [fderiv_const_smul (hf x) (c : ℝ), ContinuousLinearMap.smul_apply]
52+
have hd := (lipschitzSmoothWith_iff_fderiv hf).mp h x y
53+
push_cast
54+
simp only [Pi.smul_apply, smul_eq_mul]
55+
nlinarith [c.coe_nonneg, sq_nonneg (dist x y)]
56+
57+
/-- Composition of a `K`-smooth `f : F → ℝ` with a continuous affine map `A : F' →ᴬ[ℝ] F`
58+
is `(‖A.contLinear‖² · K)`-smooth on `F'`. -/
59+
theorem comp_continuousAffineMap (h : LipschitzSmoothWith K f) (A : F' →ᴬ[ℝ] F) :
60+
LipschitzSmoothWith (‖A.contLinear‖₊ ^ 2 * K) (f ∘ A) :=
61+
sorry
62+
63+
end LipschitzSmoothWith

Mathlib/Analysis/Calculus/LipschitzSmooth/Basic.lean

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,22 @@ theorem continuous (h : LipschitzSmoothWith K f) : Continuous f :=
121121
sorry
122122

123123
end LipschitzSmoothWith
124+
125+
/-! ### Algebraic preservation -/
126+
127+
/-- A constant function is `0`-smooth. -/
128+
theorem lipschitzSmoothWith_const (c : ℝ) : LipschitzSmoothWith (0 : NNReal) (fun _ : F => c) :=
129+
lipschitzSmoothWith_iff_lineDeriv.mpr fun x y => by
130+
have h : HasFDerivAt (fun _ : F => c) (0 : F →L[ℝ] ℝ) x := hasFDerivAt_const c x
131+
rw [(h.hasLineDerivAt (y - x)).lineDeriv]
132+
simp
133+
134+
/-- An affine function `y ↦ ℓ y + c` is `0`-smooth. -/
135+
theorem lipschitzSmoothWith_affine (ℓ : F →L[ℝ] ℝ) (c : ℝ) :
136+
LipschitzSmoothWith (0 : NNReal) (fun y => ℓ y + c) :=
137+
lipschitzSmoothWith_iff_lineDeriv.mpr fun x y => by
138+
have h : HasFDerivAt (fun y : F => ℓ y + c) ℓ x := ℓ.hasFDerivAt.add_const c
139+
rw [(h.hasLineDerivAt (y - x)).lineDeriv, map_sub]
140+
push_cast
141+
linarith
142+

0 commit comments

Comments
 (0)