Convex Analysis (Rockafellar, 1970) -- Chapter 05 -- Section 25 -- Part 2
open scoped Topologyopen scoped Pointwiseopen scoped ConvexAnalysissection Chap05section Section25
Helper for Theorem 25.1: normalizing the displacement from x to a punctured point produces
a direction in the closed unit ball and a radial decomposition of that point.
lemma helperForTheorem_25_1_normalizedDirection_mem_closedUnitBall {n : Nat}
{x z : Fin n β Real} (hzx : z β x) :
0 < βz - xβ β§
((1 / βz - xβ) β’ (z - x)) β Metric.closedBall (0 : Fin n β Real) 1 β§
z = x + βz - xβ β’ ((1 / βz - xβ) β’ (z - x)) := by
have hnormPos : 0 < βz - xβ := by
-- A punctured point has nonzero displacement, hence positive norm.
exact norm_pos_iff.mpr (sub_ne_zero.mpr hzx)
have hunitNorm :
β((1 / βz - xβ) β’ (z - x))β = 1 := by
-- The normalized displacement has norm exactly one.
calc
β((1 / βz - xβ) β’ (z - x))β = |1 / βz - xβ| * βz - xβ := norm_smul _ _
_ = (1 / βz - xβ) * βz - xβ := by
rw [abs_of_nonneg (by positivity)]
_ = 1 := by
field_simp [hnormPos.ne']
have huBall :
((1 / βz - xβ) β’ (z - x)) β Metric.closedBall (0 : Fin n β Real) 1 := by
-- Repackage the norm computation as closed-ball membership.
rw [Metric.mem_closedBall]
simpa [dist_eq_norm] using (show β((1 / βz - xβ) β’ (z - x))β β€ 1 from le_of_eq hunitNorm)
have hsmul :
βz - xβ β’ ((1 / βz - xβ) β’ (z - x)) = z - x := by
have hmul : βz - xβ * (1 / βz - xβ) = 1 := by
field_simp [hnormPos.ne']
-- Scaling the normalized direction by the original norm recovers the displacement.
calc
βz - xβ β’ ((1 / βz - xβ) β’ (z - x)) =
(βz - xβ * (1 / βz - xβ)) β’ (z - x) := by
rw [smul_smul]
_ = (1 : Real) β’ (z - x) := by rw [hmul]
_ = z - x := by simp
refine β¨hnormPos, huBall, ?_β©
-- Add the recovered displacement back to the base point.
calc
z = x + (z - x) := by
simpa [sub_eq_add_neg, add_assoc, add_left_comm, add_comm]
_ = x + βz - xβ β’ ((1 / βz - xβ) β’ (z - x)) := by rw [hsmul]
Helper for Theorem 25.1: after rewriting a punctured nearby point in normalized radial form,
its error quotient lies between 0 and the dyadic remainder at any larger fixed scale.
lemma helperForTheorem_25_1_errorQuotient_le_remainderAt_fixedScale {n : Nat}
{f : (Fin n β Real) β EReal} {x g : Fin n β Real} {Ο : Real}
(hf : ConvexFunction f)
(hxFinite : f x β β€ β§ f x β β₯)
(hsub : IsSubgradientAt f x (dotProductEquiv Real (Fin n) g))
(hΟpos : 0 < Ο) (N : Nat) {z : Fin n β Real} (hzx : z β x)
(hzFinite : f z β β€ β§ f z β β₯)
(hstepFinite :
f (x + helperForTheorem_25_1_dyadicScale Ο N β’ ((1 / βz - xβ) β’ (z - x))) β β€ β§
f (x + helperForTheorem_25_1_dyadicScale Ο N β’ ((1 / βz - xβ) β’ (z - x))) β β₯)
(hzle : βz - xβ β€ helperForTheorem_25_1_dyadicScale Ο N) :
((1 / βz - xβ) β’ (z - x)) β Metric.closedBall (0 : Fin n β Real) 1 β§
0 β€ erealGradientErrorQuotient f x g z β§
erealGradientErrorQuotient f x g z β€
helperForTheorem_25_1_dyadicRemainder f x g Ο N
((1 / βz - xβ) β’ (z - x)) := by
let t : Real := βz - xβ
let u : Fin n β Real := (1 / t) β’ (z - x)
let Ο : Real := helperForTheorem_25_1_dyadicScale Ο N
have hnormData :=
helperForTheorem_25_1_normalizedDirection_mem_closedUnitBall (x := x) (z := z) hzx
rcases hnormData with β¨htPosRaw, huBallRaw, hzreprRawβ©
have htPos : 0 < t := by simpa [t] using htPosRaw
have huBall : u β Metric.closedBall (0 : Fin n β Real) 1 := by
simpa [u, t] using huBallRaw
have hzrepr : z = x + t β’ u := by
simpa [u, t] using hzreprRaw
have hΟPos : 0 < Ο := by
simpa [Ο] using helperForTheorem_25_1_dyadicScale_pos hΟpos N
have hstepFinite' : f (x + Ο β’ u) β β€ β§ f (x + Ο β’ u) β β₯ := by
simpa [Ο, u, t] using hstepFinite
let Qz : Real := ((f z).toReal - (f x).toReal) / t
let QΟ : Real := ((f (x + Ο β’ u)).toReal - (f x).toReal) / Ο
have hQz_eq_quot :
directionalDifferenceQuotientAt f x u t = ((Qz : Real) : EReal) := by
have hzrepr' : x + t β’ u = z := by simpa using hzrepr.symm
-- At the actual point `z`, the directional quotient is finite and matches the real quotient.
simp [Qz, directionalDifferenceQuotientAt, hzrepr', EReal.coe_div, EReal.coe_sub,
EReal.coe_toReal hzFinite.1 hzFinite.2, EReal.coe_toReal hxFinite.1 hxFinite.2]
have hQΟ_eq_quot :
directionalDifferenceQuotientAt f x u Ο = ((QΟ : Real) : EReal) := by
-- The same finite-value rewrite applies at the dyadic comparison point.
simp [QΟ, directionalDifferenceQuotientAt, EReal.coe_div, EReal.coe_sub,
EReal.coe_toReal hstepFinite'.1 hstepFinite'.2, EReal.coe_toReal hxFinite.1 hxFinite.2]
have hmono :
MonotoneOn (directionalDifferenceQuotientAt f x u) (Set.Ioi (0 : Real)) :=
(convex_directionalDerivative_monotone_exists_and_sublinear f hf x hxFinite).1 u |>.1
have hlowerE :
(((g β¬α΅₯ u : Real) : Real) : EReal) β€ directionalDifferenceQuotientAt f x u t :=
helperForTheorem_23_2_differenceQuotient_lowerBound_of_subgradient
f x hxFinite (dotProductEquiv Real (Fin n) g) hsub u htPos
have hlowerReal : g β¬α΅₯ u β€ Qz := by
exact_mod_cast
(show (((g β¬α΅₯ u : Real) : Real) : EReal) β€ ((Qz : Real) : EReal) by
simpa [hQz_eq_quot] using hlowerE)
have hupperE :
directionalDifferenceQuotientAt f x u t β€ directionalDifferenceQuotientAt f x u Ο :=
hmono htPos hΟPos (by simpa [t, Ο] using hzle)
have hupperReal : Qz β€ QΟ := by
exact_mod_cast
(show ((Qz : Real) : EReal) β€ ((QΟ : Real) : EReal) by
simpa [hQz_eq_quot, hQΟ_eq_quot] using hupperE)
have herrorEq :
erealGradientErrorQuotient f x g z = Qz - g β¬α΅₯ u := by
have htNe : t β 0 := ne_of_gt htPos
have htoRealSub :
(f z - f x).toReal = (f z).toReal - (f x).toReal := by
simpa using EReal.toReal_sub hzFinite.1 hzFinite.2 hxFinite.1 hxFinite.2
have hsubrepr : z - x = t β’ u := by
calc
z - x = (x + t β’ u) - x := by rw [hzrepr]
_ = t β’ u := by simp
have hdot : g β¬α΅₯ (z - x) = t * (g β¬α΅₯ u) := by
rw [hsubrepr]
simpa [smul_eq_mul] using (dotProduct_smul t g u)
-- Rewrite the normalized error in terms of the real secant quotient minus `g β¬ u`.
rw [erealGradientErrorQuotient, htoRealSub, hdot]
change (((f z).toReal - (f x).toReal) - t * (g β¬α΅₯ u)) / βz - xβ = Qz - g β¬α΅₯ u
rw [show βz - xβ = t by rfl]
dsimp [Qz]
field_simp [htNe]
have hremainderEq :
helperForTheorem_25_1_dyadicRemainder f x g Ο N u = QΟ - g β¬α΅₯ u := by
have hΟNe : Ο β 0 := ne_of_gt hΟPos
-- Expanding the dyadic remainder gives the same affine correction at the fixed dyadic scale.
calc
helperForTheorem_25_1_dyadicRemainder f x g Ο N u =
((((f (x + Ο β’ u)).toReal - (f x).toReal) - Ο * (g β¬α΅₯ u)) / Ο) := by
simp [helperForTheorem_25_1_dyadicRemainder, Ο]
_ = (((f (x + Ο β’ u)).toReal - (f x).toReal) / Ο) - ((Ο * (g β¬α΅₯ u)) / Ο) := by
rw [sub_div]
_ = (((f (x + Ο β’ u)).toReal - (f x).toReal) / Ο) - g β¬α΅₯ u := by
have hcancel : Ο * (g β¬α΅₯ u) / Ο = g β¬α΅₯ u := by
field_simp [hΟNe]
simpa [div_eq_mul_inv, mul_assoc, mul_left_comm, mul_comm] using congrArg
(fun s : Real => (((f (x + Ο β’ u)).toReal - (f x).toReal) / Ο) - s) hcancel
_ = QΟ - g β¬α΅₯ u := by rfl
refine β¨by simpa [u, t] using huBall, ?_, ?_β©
Β· -- The subgradient lower bound makes the error quotient nonnegative.
rw [herrorEq]
linarith
Β· -- Monotonicity of convex secants transfers the dyadic remainder bound back to `z`.
rw [herrorEq, hremainderEq]
linarith
Helper for Theorem 25.1: a uniform dyadic remainder bound makes the punctured error quotient
eventually Ξ΅-small in the metric neighborhood filter.
lemma helperForTheorem_25_1_uniformBound_implies_errorQuotient_eventually_small {n : Nat}
{f : (Fin n β Real) β EReal} {x g : Fin n β Real} {Ο Ο' eps : Real}
(hf : ConvexFunction f)
(hxFinite : f x β β€ β§ f x β β₯)
(hsub : IsSubgradientAt f x (dotProductEquiv Real (Fin n) g))
(hΟpos : 0 < Ο) (hΟ'pos : 0 < Ο')
(hΟ'finite :
β z : Fin n β Real, z β Metric.closedBall x Ο' β f z β β€ β§ f z β β₯)
(hRuniform :
TendstoUniformlyOn (helperForTheorem_25_1_dyadicRemainder f x g Ο) (fun _ => 0)
Filter.atTop (Metric.closedBall (0 : Fin n β Real) 1))
(heps : 0 < eps) :
βαΆ z in
nhdsWithin x ({z | z β x} β© effectiveDomain (Set.univ : Set (Fin n β Real)) f),
dist (erealGradientErrorQuotient f x g z) 0 < eps := by
let S : Set (Fin n β Real) :=
{z | z β x} β© effectiveDomain (Set.univ : Set (Fin n β Real)) f
have huniform :
βαΆ N in Filter.atTop,
β u β Metric.closedBall (0 : Fin n β Real) 1,
dist (0 : Real) (helperForTheorem_25_1_dyadicRemainder f x g Ο N u) < eps :=
(Metric.tendstoUniformlyOn_iff.mp hRuniform) eps heps
have hΟsmall :
βαΆ N in Filter.atTop, helperForTheorem_25_1_dyadicScale Ο N < Ο' := by
have hdistSmall :
βαΆ N in Filter.atTop, dist (helperForTheorem_25_1_dyadicScale Ο N) 0 < Ο' :=
(Metric.tendsto_nhds.1 (helperForTheorem_25_1_dyadicScale_tendsto_zero (Ο := Ο))) Ο'
hΟ'pos
filter_upwards [hdistSmall] with N hN
have hΟnonneg : 0 β€ helperForTheorem_25_1_dyadicScale Ο N := by
exact le_of_lt (helperForTheorem_25_1_dyadicScale_pos hΟpos N)
simpa [Real.dist_eq, abs_of_nonneg hΟnonneg] using hN
rcases Filter.eventually_atTop.1 (Filter.Eventually.and huniform hΟsmall) with
β¨N, hNtailβ©
have hNboth := hNtail N le_rfl
rcases hNboth with β¨hNuniform, hNΟβ©
let Ο : Real := helperForTheorem_25_1_dyadicScale Ο N
let r : Real := min Ο' Ο
have hrPos : 0 < r := by
-- Choose a punctured ball small enough for both finiteness and the dyadic comparison scale.
dsimp [r, Ο]
exact lt_min hΟ'pos (helperForTheorem_25_1_dyadicScale_pos hΟpos N)
have hbase :
Metric.ball x r β© S β nhdsWithin x S := by
exact Filter.inter_mem
(mem_nhdsWithin_of_mem_nhds (Metric.ball_mem_nhds x hrPos))
self_mem_nhdsWithin
refine Filter.mem_of_superset hbase ?_
intro z hz
rcases hz with β¨hzBall, hzSβ©
rcases hzS with β¨hzx, _hzDomβ©
have hzNormLt : βz - xβ < r := by
simpa [S, r, dist_eq_norm] using (Metric.mem_ball.mp hzBall)
have hzClosed : z β Metric.closedBall x Ο' := by
rw [Metric.mem_closedBall]
exact le_of_lt (lt_of_lt_of_le hzNormLt (min_le_left _ _))
have hzFinite : f z β β€ β§ f z β β₯ := hΟ'finite z hzClosed
let u : Fin n β Real := (1 / βz - xβ) β’ (z - x)
have hnormData :=
helperForTheorem_25_1_normalizedDirection_mem_closedUnitBall (x := x) (z := z) hzx
have huBall : u β Metric.closedBall (0 : Fin n β Real) 1 := by
simpa [u] using hnormData.2.1
have hstepClosed : x + Ο β’ u β Metric.closedBall x Ο' := by
rw [Metric.mem_closedBall, dist_eq_norm]
have huNorm : βuβ β€ 1 := by
simpa [Metric.mem_closedBall, dist_eq_norm] using huBall
have hΟnonneg : 0 β€ Ο := by
dsimp [Ο]
exact le_of_lt (helperForTheorem_25_1_dyadicScale_pos hΟpos N)
-- The normalized direction stays in the unit ball, so the dyadic step stays within radius `Ο'`.
calc
β(x + Ο β’ u) - xβ = βΟ β’ uβ := by simp [sub_eq_add_neg, add_assoc]
_ = |Ο| * βuβ := norm_smul _ _
_ = Ο * βuβ := by rw [abs_of_nonneg hΟnonneg]
_ β€ Ο * 1 := by gcongr
_ = Ο := by ring
_ β€ Ο' := le_of_lt hNΟ
have hstepFinite : f (x + Ο β’ u) β β€ β§ f (x + Ο β’ u) β β₯ := hΟ'finite _ hstepClosed
have hzLe : βz - xβ β€ Ο := by
exact le_of_lt (lt_of_lt_of_le hzNormLt (min_le_right _ _))
have hsqueeze :=
helperForTheorem_25_1_errorQuotient_le_remainderAt_fixedScale
(f := f) (x := x) (g := g) (Ο := Ο) hf hxFinite hsub hΟpos N hzx hzFinite
(by simpa [Ο, u] using hstepFinite) (by simpa [Ο] using hzLe)
rcases hsqueeze with β¨huBall', herrorNonneg, herrorLeβ©
have hRdist :
dist (0 : Real) (helperForTheorem_25_1_dyadicRemainder f x g Ο N u) < eps :=
hNuniform u huBall'
have hRnonneg : 0 β€ helperForTheorem_25_1_dyadicRemainder f x g Ο N u :=
le_trans herrorNonneg herrorLe
have hRlt : helperForTheorem_25_1_dyadicRemainder f x g Ο N u < eps := by
simpa [Real.dist_eq, abs_of_nonneg hRnonneg] using hRdist
have herrorLt : erealGradientErrorQuotient f x g z < eps :=
lt_of_le_of_lt herrorLe hRlt
-- The squeeze converts the uniform dyadic bound into the metric estimate for the error quotient.
simpa [Real.dist_eq, abs_of_nonneg herrorNonneg] using herrorLt
Helper for Theorem 25.1: if the upper directional derivative is already linear on the interior
of the effective domain of a proper convex function, then the first-order error quotient vanishes
and f is differentiable at x.
lemma helperForTheorem_25_1_linearDirectionalDerivative_implies_ERealDifferentiableAt {n : Nat}
{f : (Fin n β Real) β EReal} {x g : Fin n β Real}
(hproper : ProperConvexFunctionOn (Set.univ : Set (Fin n β Real)) f)
(hxInt : x β interior (effectiveDomain (Set.univ : Set (Fin n β Real)) f))
(hdir :
β y : Fin n β Real,
upperDirectionalDerivativeAt f x y = (((g β¬α΅₯ y : Real) : Real) : EReal)) :
ERealDifferentiableAt f x := by
have hf : ConvexFunction f := by
simpa [ConvexFunction] using hproper.1
have hxDom : x β effectiveDomain (Set.univ : Set (Fin n β Real)) f := interior_subset hxInt
have hxFinite : f x β β€ β§ f x β β₯ := by
refine β¨mem_effectiveDomain_imp_ne_top (S := (Set.univ : Set (Fin n β Real))) (f := f) hxDom,
?_β©
exact hproper.2.2 x (by simp)
have hsub :
IsSubgradientAt f x (dotProductEquiv Real (Fin n) g) :=
helperForTheorem_25_1_subgradient_of_linearDirectionalDerivative
(hproper := hproper) (hxInt := hxInt) (hdir := hdir)
rcases helperForTheorem_25_1_exists_closedBall_subset_interior_effectiveDomain
(f := f) (x := x) hxInt with
β¨Ο, hΟpos, hΟsubIntβ©
rcases helperForTheorem_25_1_exists_closedBall_finiteValues
(f := f) (x := x) hproper hxInt with
β¨Ο', hΟ'pos, hΟ'finiteβ©
-- The differentiability witness uses the given candidate gradient `g`.
refine β¨g, ?_, ?_β©
Β· -- The local finiteness is already available; the remaining analytic step is the Chapter 10
-- Route correction: the earlier Chapter 10 convex-family route was too indirect. The current
-- plan fixes the dyadic remainder family on the compact unit ball and reduces the unresolved
-- work to Dini's theorem plus the fixed-scale secant squeeze.
let R : Nat β (Fin n β Real) β Real :=
helperForTheorem_25_1_dyadicRemainder f x g Ο
have hRuniform :
TendstoUniformlyOn R (fun _ => 0) Filter.atTop
(Metric.closedBall (0 : Fin n β Real) 1) :=
helperForTheorem_25_1_remainderSequence_tendstoUniformlyOn_closedUnitBall
(f := f) (x := x) (g := g) (Ο := Ο) hproper hxInt hΟpos hΟsubInt hdir hsub
have hlimit :
Filter.Tendsto (erealGradientErrorQuotient f x g)
(nhdsWithin x
({z | z β x} β© effectiveDomain (Set.univ : Set (Fin n β Real)) f))
(nhds 0) := by
-- The metric formulation reduces to a single eventual `Ξ΅`-estimate on the punctured filter.
rw [Metric.tendsto_nhds]
intro eps heps
exact helperForTheorem_25_1_uniformBound_implies_errorQuotient_eventually_small
(f := f) (x := x) (g := g) (Ο := Ο) (Ο' := Ο') hf hxFinite hsub hΟpos hΟ'pos
hΟ'finite hRuniform heps
exact β¨hxFinite.1, hxFinite.2, hlimitβ©
Β· -- The same closed ball provides eventual punctured finite-valued control.
have hnear :
{z : Fin n β Real |
z β effectiveDomain (Set.univ : Set (Fin n β Real)) f β§ f z β β₯} β nhds x := by
refine Filter.mem_of_superset (Metric.ball_mem_nhds x hΟ'pos) ?_
intro z hz
have hzClosed : z β Metric.closedBall x Ο' := by
exact Metric.mem_closedBall.mpr (le_of_lt hz)
have hzFinite : f z β β€ β§ f z β β₯ := hΟ'finite z hzClosed
have hzDom : z β effectiveDomain (Set.univ : Set (Fin n β Real)) f := by
simpa [effectiveDomain_eq] using (lt_top_iff_ne_top.mpr hzFinite.1)
exact β¨hzDom, hzFinite.2β©
exact mem_nhdsWithin_of_mem_nhds hnear-- Proof sketch: use Theorem 23.2 to convert subgradients into linear minorants of the upper
-- directional derivative, show differentiability identifies that directional derivative with the
-- linear functional given by the chosen gradient witness, and then apply `erealGradient_unique`.
-- For the converse, a unique vector subgradient determines all directional difference quotients,
-- forcing the first-order error term to vanish and hence giving differentiability at `x`.
Theorem 25.1: let f be convex and finite at x. Then differentiability at x makes the
chosen gradient witness the unique Euclidean subgradient of f at x, so in particular
for every z. Conversely, if f has a unique Euclidean
subgradient at x, then f is differentiable at x.
theorem convexFunction_differentiableAt_iff_gradient_is_unique_subgradient {n : Nat}
(f : (Fin n β Real) β EReal) (hf : ConvexFunction f) (x : Fin n β Real)
(hx : f x β β€ β§ f x β β₯) :
(β hdiff : ERealDifferentiableAt f x,
IsSubgradientAt f x (dotProductEquiv Real (Fin n) (erealGradientAt hdiff)) β§
(β z : Fin n β Real,
f z β₯ f x + ((((erealGradientAt hdiff) β¬α΅₯ (z - x)) : Real) : EReal)) β§
β g : Fin n β Real,
IsSubgradientAt f x (dotProductEquiv Real (Fin n) g) β g = erealGradientAt hdiff) β§
((β! g : Fin n β Real, IsSubgradientAt f x (dotProductEquiv Real (Fin n) g)) β
ERealDifferentiableAt f x) := by
constructor
Β· intro hdiff
-- The differentiability witness determines both the directional derivative and the subgradient.
rcases
helperForTheorem_25_1_gradient_gives_subgradient_and_directionalDerivative
(hf := hf) (hdiff := hdiff) with
β¨hdirEq, hsubGradβ©
refine β¨hsubGrad, ?_, ?_β©
Β· -- The explicit affine lower bound is just the subgradient inequality specialized at `z`.
intro z
simpa [dotProduct_comm] using hsubGrad z
Β· intro g hg
have hiffg :=
(subgradient_iff_directionalDerivative_ge_and_closure_eq_subdifferentialSupport
f hf x hx (dotProductEquiv Real (Fin n) g)).1
have hminorG :
β y : Fin n β Real,
((((dotProductEquiv Real (Fin n) g) y : Real) : Real) : EReal) β€
upperDirectionalDerivativeAt f x y :=
hiffg.mp hg
-- Compare both candidate subgradients against the already identified linear derivative.
have hdotEq :
β y : Fin n β Real, g β¬α΅₯ y = erealGradientAt hdiff β¬α΅₯ y := by
intro y
have hyLe :
(((g β¬α΅₯ y : Real) : EReal)) β€
((((erealGradientAt hdiff) β¬α΅₯ y : Real) : EReal)) := by
calc
(((g β¬α΅₯ y : Real) : EReal)) =
((((dotProductEquiv Real (Fin n) g) y : Real) : Real) : EReal) := by
simp
_ β€ upperDirectionalDerivativeAt f x y := hminorG y
_ = ((((erealGradientAt hdiff) β¬α΅₯ y : Real) : Real) : EReal) := hdirEq y
have hnegLe :
((((erealGradientAt hdiff) β¬α΅₯ y : Real) : EReal)) β€
(((g β¬α΅₯ y : Real) : EReal)) := by
have hnegLe' :
(((g β¬α΅₯ (-y) : Real) : EReal)) β€
((((erealGradientAt hdiff) β¬α΅₯ (-y) : Real) : EReal)) := by
calc
(((g β¬α΅₯ (-y) : Real) : EReal)) =
((((dotProductEquiv Real (Fin n) g) (-y) : Real) : Real) : EReal) := by
simp
_ β€ upperDirectionalDerivativeAt f x (-y) := hminorG (-y)
_ = ((((erealGradientAt hdiff) β¬α΅₯ (-y) : Real) : Real) : EReal) := hdirEq (-y)
have hnegReal :
-(g β¬α΅₯ y) β€ -(erealGradientAt hdiff β¬α΅₯ y) := by
simpa [dotProduct_comm] using hnegLe'
have hposReal :
erealGradientAt hdiff β¬α΅₯ y β€ g β¬α΅₯ y := by
linarith
exact (EReal.coe_le_coe_iff).2 hposReal
have hyEq :
(((g β¬α΅₯ y : Real) : EReal)) =
((((erealGradientAt hdiff) β¬α΅₯ y : Real) : EReal)) := le_antisymm hyLe hnegLe
exact (EReal.coe_eq_coe_iff).1 hyEq
exact helperForTheorem_25_1_eq_of_dotProduct_eq hdotEq
Β· intro huniq
-- Route correction: the easy converse reductions are handled now; only the analytic upgrade
-- from linear directional derivative to the full differentiability filter remains isolated in
-- the dedicated helper.
rcases
helperForTheorem_25_1_uniqueSubgradient_implies_linearDirectionalDerivative
(hf := hf) (x := x) hx huniq with
β¨g, hproper, hxInt, hdirβ©
exact
helperForTheorem_25_1_linearDirectionalDerivative_implies_ERealDifferentiableAt
(hproper := hproper) (hxInt := hxInt) (hdir := hdir)
Variant of Theorem 25.1: for a convex function finite at x, differentiability at x is
equivalent to the subtype of Euclidean subgradients g with dotProductEquiv β (Fin n) g β β f x
being a Unique type.
theorem convexFunction_differentiableAt_iff_unique_subgradient_subtype {n : Nat}
(f : (Fin n β Real) β EReal) (hf : ConvexFunction f) (x : Fin n β Real)
(hx : f x β β€ β§ f x β β₯) :
ERealDifferentiableAt f x β
Nonempty (Unique {g : Fin n β Real // dotProductEquiv β (Fin n) g β β f x}) := by
constructor
Β· intro hdiff
rcases
(convexFunction_differentiableAt_iff_gradient_is_unique_subgradient f hf x hx).1 hdiff with
β¨hsub, _hlower, huniqβ©
refine β¨?_β©
refine
{ default := β¨erealGradientAt hdiff, by simpa using hsubβ©
uniq := ?_ }
intro y
apply Subtype.ext
exact huniq y.1 y.2
Β· rintro β¨hUniqueβ©
have hExistsUnique :
β! g : Fin n β Real, dotProductEquiv β (Fin n) g β β f x := by
refine β¨hUnique.default.1, hUnique.default.2, ?_β©
intro g hg
exact congrArg Subtype.val (hUnique.uniq β¨g, hgβ©)
exact
(convexFunction_differentiableAt_iff_gradient_is_unique_subgradient f hf x hx).2
(by simpa using hExistsUnique)-- Proof sketch: apply Theorem 25.1 to obtain the unique subgradient determined by the gradient
-- witness. Its existence makes `f` proper by Theorem 23.3, while the singleton subdifferential is
-- bounded, so Theorem 23.4 yields `x β interior (dom f)`.
Corollary 25.1.1: if f is convex and differentiable at x, then f is proper on β^n and
x lies in the interior of the effective domain dom f.
theorem convexFunction_proper_and_mem_interior_of_differentiableAt {n : Nat}
(f : (Fin n β Real) β EReal) (hf : ConvexFunction f) (x : Fin n β Real)
(hdiff : ERealDifferentiableAt f x) :
ProperConvexFunctionOn (Set.univ : Set (Fin n β Real)) f β§
x β interior (effectiveDomain (Set.univ : Set (Fin n β Real)) f) := by
have hx : f x β β€ β§ f x β β₯ := ERealDifferentiableAt.finiteAt hdiff
have hcore :=
(convexFunction_differentiableAt_iff_gradient_is_unique_subgradient f hf x hx).1 hdiff
have huniq : β! g : Fin n β Real, IsSubgradientAt f x (dotProductEquiv Real (Fin n) g) := by
-- The gradient supplied by differentiability is the unique Euclidean subgradient at `x`.
refine β¨erealGradientAt hdiff, hcore.1, ?_β©
intro g hg
exact hcore.2.2 g hg
-- The Section 25 helper packages the properness and interior conclusions from uniqueness.
rcases
helperForTheorem_25_1_uniqueSubgradient_implies_linearDirectionalDerivative
(hf := hf) (x := x) hx huniq with
β¨g, hproper, hxInt, _hdirβ©
exact β¨hproper, hxIntβ©-- Proof sketch: choose the gradient witness supplied by differentiability, evaluate the
-- first-order expansion along the ray `t β¦ x + t β’ y`, and use `y β 0` so the normalized error
-- term turns into the directional difference quotient converging to the pairing with the gradient.Helper for Theorem 25.1.1: a positive step in a nonzero direction cannot stay at the base point.
lemma helperForTheorem_25_1_1_nonzero_ray_ne {n : Nat} {x y : Fin n β Real}
(hy : y β 0) {t : Real} (ht : 0 < t) :
x + t β’ y β x := by
intro hEq
have hsmul : t β’ y = 0 := by
-- Cancel the common `x` term to isolate the scaled direction vector.
exact add_left_cancel (by simpa using hEq : x + t β’ y = x + 0)
-- A positive scalar cannot annihilate a nonzero vector over `β`.
rcases smul_eq_zero.mp hsmul with ht0 | hy0
Β· exact (ne_of_gt ht) ht0
Β· exact hy hy0
Helper for Theorem 25.1.1: the positive ray tends to x through the
punctured neighborhood when y β 0.
lemma helperForTheorem_25_1_1_tendsto_ray_to_puncturedNeighborhood
{n : Nat} {x y : Fin n β Real} (hy : y β 0) :
Filter.Tendsto (fun t : Real => x + t β’ y)
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhdsWithin x {z | z β x}) := by
have hcont : ContinuousAt (fun t : Real => x + t β’ y) (0 : Real) := by
fun_prop
have hwithin : βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0), x + t β’ y β ({z | z β x} : Set _) := by
filter_upwards [self_mem_nhdsWithin] with t ht
exact helperForTheorem_25_1_1_nonzero_ray_ne (x := x) (y := y) hy ht
refine tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within _ ?_ hwithin
simpa [zero_smul] using (hcont.tendsto.mono_left nhdsWithin_le_nhds)
Helper for Theorem 25.1.1: an eventual positive-ray effective-domain hypothesis upgrades to
eventual membership in the punctured effective-domain set used by HasERealGradientAt.
lemma helperForTheorem_25_1_1_eventually_mem_puncturedEffectiveDomain_of_eventually_mem_effectiveDomain_ray
{n : Nat} {f : (Fin n β Real) β EReal} {x y : Fin n β Real}
(hy : y β 0)
(hray : βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
x + t β’ y β effectiveDomain (Set.univ : Set (Fin n β Real)) f) :
βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
x + t β’ y β
({z | z β x} β© effectiveDomain (Set.univ : Set (Fin n β Real)) f) := by
have hpos : βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0), 0 < t := by
-- The source filter only sees positive parameters.
simpa using
(self_mem_nhdsWithin : Set.Ioi (0 : Real) β nhdsWithin (0 : Real) (Set.Ioi 0))
-- Combine positivity with the assumed eventual effective-domain membership along the ray.
filter_upwards [hpos, hray] with t ht hmem
exact β¨helperForTheorem_25_1_1_nonzero_ray_ne (x := x) (y := y) hy ht, hmemβ©
Helper for Theorem 25.1.1: under the eventual positive-ray effective-domain hypothesis, the
ray parameterization tends to the punctured effective-domain neighborhood of x.
lemma helperForTheorem_25_1_1_tendsto_ray_to_puncturedEffectiveDomain
{n : Nat} {f : (Fin n β Real) β EReal} {x y : Fin n β Real}
(hy : y β 0)
(hray : βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
x + t β’ y β effectiveDomain (Set.univ : Set (Fin n β Real)) f) :
Filter.Tendsto (fun t : Real => x + t β’ y)
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhdsWithin x
({z | z β x} β© effectiveDomain (Set.univ : Set (Fin n β Real)) f)) := by
have hcont : ContinuousAt (fun t : Real => x + t β’ y) (0 : Real) := by
-- The ray map is continuous as an affine function of the scalar parameter.
fun_prop
have hwithin :
βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
x + t β’ y β
({z | z β x} β© effectiveDomain (Set.univ : Set (Fin n β Real)) f) :=
helperForTheorem_25_1_1_eventually_mem_puncturedEffectiveDomain_of_eventually_mem_effectiveDomain_ray
(x := x) (y := y) hy hray
-- The continuous ray map tends to `x`, and `hwithin` upgrades this to a within-limit.
refine tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within _ ?_ hwithin
simpa [zero_smul] using (hcont.tendsto.mono_left nhdsWithin_le_nhds)
Theorem 25.1.1: if f is differentiable at x, then for every nonzero direction y, the
right directional difference quotient converges to .
theorem ERealDifferentiableAt.tendsto_directionalDifferenceQuotient {n : Nat}
{f : (Fin n β Real) β EReal} {x y : Fin n β Real}
(hf : ERealDifferentiableAt f x) (hy : y β 0) :
Filter.Tendsto (directionalDifferenceQuotientAt f x y)
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhds ((((erealGradientAt hf) β¬α΅₯ y : Real) : EReal))) := by
let g : Fin n β Real := erealGradientAt hf
have hg : HasERealGradientAt f x g := by
simpa [g] using ERealDifferentiableAt.hasERealGradientAt (hf := hf)
have hx : f x β β€ β§ f x β β₯ := by
exact ERealDifferentiableAt.finiteAt (hf := hf)
have hfinite :
βαΆ z in nhdsWithin x ({z | z β x}),
z β effectiveDomain (Set.univ : Set (Fin n β Real)) f β§ f z β β₯ :=
ERealDifferentiableAt.eventually_finiteValuedWithin_punctured (hf := hf)
have hfiniteRay :
βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
x + t β’ y β effectiveDomain (Set.univ : Set (Fin n β Real)) f β§
f (x + t β’ y) β β₯ := by
exact
(helperForTheorem_25_1_1_tendsto_ray_to_puncturedNeighborhood (x := x) (y := y) hy).eventually
hfinite
have hray :
βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
x + t β’ y β effectiveDomain (Set.univ : Set (Fin n β Real)) f := by
exact hfiniteRay.mono fun _ ht => ht.1
have hrayInto :
Filter.Tendsto (fun t : Real => x + t β’ y)
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhdsWithin x
({z | z β x} β© effectiveDomain (Set.univ : Set (Fin n β Real)) f)) :=
helperForTheorem_25_1_1_tendsto_ray_to_puncturedEffectiveDomain
(x := x) (y := y) hy hray
have herrorRay :
Filter.Tendsto (fun t : Real => erealGradientErrorQuotient f x g (x + t β’ y))
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhds 0) :=
hg.2.2.comp hrayInto
have hrealEq :
βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
((f (x + t β’ y)).toReal - (f x).toReal) / t =
βyβ * erealGradientErrorQuotient f x g (x + t β’ y) + g β¬α΅₯ y := by
filter_upwards [self_mem_nhdsWithin, hfiniteRay] with t ht htFinite
have htne : t β 0 := ne_of_gt ht
have hyNorm : βyβ β 0 := norm_ne_zero_iff.mpr hy
have htop : f (x + t β’ y) β β€ :=
mem_effectiveDomain_imp_ne_top (S := (Set.univ : Set (Fin n β Real))) (f := f) htFinite.1
have hsub :
x + t β’ y - x = t β’ y := by
simp [sub_eq_add_neg, add_assoc]
have hdot :
g β¬α΅₯ (t β’ y) = t * (g β¬α΅₯ y) := by
simpa [smul_eq_mul] using (dotProduct_smul t g y)
have hnorm :
βt β’ yβ = t * βyβ := by
simpa [Real.norm_of_nonneg (le_of_lt ht)] using norm_smul t y
have htoRealSub :
(f (x + t β’ y) - f x).toReal = (f (x + t β’ y)).toReal - (f x).toReal := by
simpa using EReal.toReal_sub htop htFinite.2 hx.1 hx.2
rw [erealGradientErrorQuotient, hsub, hdot, hnorm, htoRealSub]
field_simp [htne, hyNorm]
ring
have hrealTendsto :
Filter.Tendsto (fun t : Real => ((f (x + t β’ y)).toReal - (f x).toReal) / t)
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhds (g β¬α΅₯ y)) := by
have hAffine :
Filter.Tendsto
(fun t : Real => βyβ * erealGradientErrorQuotient f x g (x + t β’ y) + g β¬α΅₯ y)
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhds (g β¬α΅₯ y)) := by
have hcont : Continuous (fun r : Real => βyβ * r + g β¬α΅₯ y) := by
fun_prop
simpa using hcont.continuousAt.tendsto.comp herrorRay
refine Filter.Tendsto.congr' ?_ hAffine
filter_upwards [hrealEq] with t htEq
exact htEq.symm
have hcoereal :
Filter.Tendsto
(fun t : Real => ((((f (x + t β’ y)).toReal - (f x).toReal) / t : Real) : EReal))
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhds (((g β¬α΅₯ y : Real) : EReal))) := by
exact (EReal.tendsto_coe).2 hrealTendsto
have hcoereal' :
Filter.Tendsto
(fun t : Real => ((((f (x + t β’ y)).toReal - (f x).toReal) / t : Real) : EReal))
(nhdsWithin (0 : Real) (Set.Ioi 0))
(nhds ((((erealGradientAt hf) β¬α΅₯ y : Real) : EReal))) := by
simpa [g] using hcoereal
have hquotEq :
βαΆ t in nhdsWithin (0 : Real) (Set.Ioi 0),
directionalDifferenceQuotientAt f x y t =
((((f (x + t β’ y)).toReal - (f x).toReal) / t : Real) : EReal) := by
filter_upwards [self_mem_nhdsWithin, hfiniteRay] with t ht htFinite
have htop : f (x + t β’ y) β β€ :=
mem_effectiveDomain_imp_ne_top (S := (Set.univ : Set (Fin n β Real))) (f := f) htFinite.1
simp [directionalDifferenceQuotientAt, EReal.coe_div, EReal.coe_sub,
EReal.coe_toReal htop htFinite.2, EReal.coe_toReal hx.1 hx.2]
exact Filter.Tendsto.congr' (by
filter_upwards [hquotEq] with t htEq
exact htEq.symm) hcoereal'
A function has jth coordinate partial derivative L at x when the difference quotient
along the jth standard basis vector Pi.single j 1 tends to L as the scalar parameter tends
to 0 from both sides.
def HasCoordinatePartialDerivativeAt {n : Nat} (f : (Fin n β Real) β EReal)
(x : Fin n β Real) (j : Fin n) (L : EReal) : Prop :=
Filter.Tendsto (directionalDifferenceQuotientAt f x (Pi.single j (1 : Real)))
(π[>] (0 : Real))
(π L) β§
Filter.Tendsto (directionalDifferenceQuotientAt f x (Pi.single j (1 : Real)))
(π[<] (0 : Real))
(π L)
Helper for Theorem 25.1.2: the jth standard basis vector in is nonzero.
lemma helperForTheorem_25_1_2_basisVector_ne_zero {n : Nat} (j : Fin n) :
(Pi.single j (1 : Real) : Fin n β Real) β 0 := by
intro hzero
have hvalue := congrArg (fun v : Fin n β Real => v j) hzero
simp at hvalue-- Proof sketch: apply Theorem 25.1.1 to the directions `e_j` and `-e_j`, then use the
-- bilateral-directional-derivative symmetry from Section 23 to identify the left-hand quotient
-- along `e_j` with the right-hand quotient along `-e_j`; both one-sided limits equal the pairing
-- of the chosen gradient witness with the `j`th standard basis vector.
Theorem 25.1.2: if f is differentiable at x, then for each coordinate index j, the
partial derivative with respect to ΞΎ_j, viewed as the bilateral directional derivative along
the standard basis vector e_j = Pi.single j 1, exists and equals .
theorem ERealDifferentiableAt.hasCoordinatePartialDerivativeAt {n : Nat}
{f : (Fin n β Real) β EReal} {x : Fin n β Real}
(hf : ERealDifferentiableAt f x) (j : Fin n) :
HasCoordinatePartialDerivativeAt f x j
(((((erealGradientAt hf) β¬α΅₯ Pi.single j (1 : Real)) : Real) : EReal)) := by
let e : Fin n β Real := Pi.single j (1 : Real)
have he : e β 0 := helperForTheorem_25_1_2_basisVector_ne_zero j
have hright :
Filter.Tendsto (directionalDifferenceQuotientAt f x e)
(π[>] (0 : Real))
(π ((((erealGradientAt hf) β¬α΅₯ e : Real) : EReal))) :=
ERealDifferentiableAt.tendsto_directionalDifferenceQuotient (hf := hf) (y := e) he
have hnegRight :
Filter.Tendsto (directionalDifferenceQuotientAt f x (-e))
(π[>] (0 : Real))
(π ((((erealGradientAt hf) β¬α΅₯ (-e) : Real) : EReal))) :=
ERealDifferentiableAt.tendsto_directionalDifferenceQuotient
(hf := hf) (y := -e) (by simpa using neg_ne_zero.mpr he)
have hdotNeg :
(erealGradientAt hf) β¬α΅₯ (-e) = -((erealGradientAt hf) β¬α΅₯ e) := by
simpa [smul_eq_mul] using (dotProduct_smul (-1 : Real) (erealGradientAt hf) e)
have hleft :
Filter.Tendsto (directionalDifferenceQuotientAt f x e)
(π[<] (0 : Real))
(π ((((erealGradientAt hf) β¬α΅₯ e : Real) : EReal))) := by
have hleft_from_right :
β L : EReal,
Filter.Tendsto (directionalDifferenceQuotientAt f x (-e)) (π[>] (0 : Real)) (π L) β
Filter.Tendsto (directionalDifferenceQuotientAt f x e) (π[<] (0 : Real)) (π (-L)) :=
(bilateralDirectionalDerivative_iff_exists_neg_direction (f := f) (x := x) (y := e)
(ERealDifferentiableAt.finiteAt (hf := hf))).1
have hnegRight' :
Filter.Tendsto (directionalDifferenceQuotientAt f x (-e))
(π[>] (0 : Real))
(π (-((((erealGradientAt hf) β¬α΅₯ e : Real) : EReal)))) := by
simpa [hdotNeg] using hnegRight
simpa using hleft_from_right (-((((erealGradientAt hf) β¬α΅₯ e : Real) : EReal))) hnegRight'
simpa [e] using And.intro hright hleftend Section25end Chap05