/- Copyright (c) 2024 Wanyi He. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Wanyi He, Chenyi Li -/ import Mathlib.Topology.MetricSpace.Basic import Mathlib.Topology.Basic import Mathlib.Order.Filter.Extr import Mathlib.Analysis.Calculus.Gradient.Basic import Mathlib.Analysis.Calculus.LineDeriv.Basic import Mathlib.Data.Real.Sign import Optlib.Convex.BanachSubgradient import Optlib.Convex.ConvexFunction /-! # Subgradient of convex functions The file defines subgradient for convex functions in E and proves some basic properties. Let `f : E → ℝ` be a convex function on `s` and `g : E`, where `s` is a set of `E`. `g` is a subgradient of `f` at `x` if for any `y ∈ s`, we have `f y ≥ f x + inner g (y - x)`. The insight comes from the first order condition of convex function. ## Main declarations * `HasSubgradientAt f g x`: The function `f` has subgradient `g` at `x`. * `HasSubgradientWithinAt f g s x`: The function `f` has subgradient `g` at `x` within `s`. * `SubderivAt f x`: The subderiv of `f` at `x` is the collection of all possible subgradients of `f` at `x`. * `SubderivWithinAt f s x`: The subderiv of `f` at `x` within `s` is the collection of all possible subgradients of `f` at `x` within `s`. ## Main results * `SubderivWithinAt_eq_gradient`: The subderiv of differentiable convex functions is the singleton of its gradient. * `HasSubgradientAt_zero_iff_isMinOn`: `0` is a subgradient of `f` at `x` if and only if `x` is a minimizer of `f`. -/ open Filter Topology Set InnerProductSpace local notation gradient "∇*" => (toDualMap ℝ _) gradient local notation "⟪" x ", " y "⟫" => @inner ℝ _ _ x y section variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] variable {f : E → ℝ} {g : E} {x : E} {s : Set E} noncomputable section /-- Subgradient of functions --/ def HasSubgradientAt (f : E → ℝ) (g x : E) : Prop := ∀ y, f y ≥ f x + ⟪g, y - x⟫ def HasSubgradientWithinAt (f : E → ℝ) (g : E) (s : Set E) (x : E) : Prop := ∀ y ∈ s, f y ≥ f x + ⟪g, y - x⟫ /-- Subderiv of functions --/ def SubderivAt (f : E → ℝ) (x : E) : Set E := {g : E| HasSubgradientAt f g x} def SubderivWithinAt (f : E → ℝ) (s : Set E) (x : E) : Set E := {g : E| HasSubgradientWithinAt f g s x} @[simp] theorem mem_SubderivAt : HasSubgradientAt f g x ↔ g ∈ SubderivAt f x := ⟨id, id⟩ @[simp] theorem hasSubgradientWithinAt_univ : HasSubgradientWithinAt f g univ x ↔ HasSubgradientAt f g x := ⟨fun h y => h y trivial, fun h y _ => h y⟩ theorem HasSubgradientAt.hasSubgradientWithinAt : HasSubgradientAt f g x → HasSubgradientWithinAt f g s x := fun h y _ => h y theorem SubderivAt_SubderivWithinAt : SubderivAt f x = SubderivWithinAt f univ x := by simp only [SubderivAt, SubderivWithinAt, hasSubgradientWithinAt_univ] end section variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] [CompleteSpace E] variable {f : E → ℝ} {g : E} {x : E} {s : Set E} theorem HasSubgradientAt_HasBanachSubgradientAt {f : E → ℝ} {g : E} {x : E} : HasSubgradientAt f g x ↔ Banach_HasSubgradientAt f (toDual ℝ E g) x := by constructor · intro h z unfold HasSubgradientAt at h obtain hz := h z simp; linarith intro h z unfold Banach_HasSubgradientAt at h obtain hz := h z; simp at hz linarith theorem HasBanachSubgradientAt_HasSubgradientAt {f : E → ℝ} {g : E →L[ℝ] ℝ} {x : E} : Banach_HasSubgradientAt f g x ↔ HasSubgradientAt f ((toDual ℝ E).symm g) x := by constructor · intro h z unfold Banach_HasSubgradientAt at h obtain hz := h z simp; rw [← ContinuousLinearMap.map_sub]; linarith intro h z unfold HasSubgradientAt at h obtain hz := h z; simp at hz rw [ContinuousLinearMap.map_sub]; linarith theorem HasSubgradientWithinAt_HasBanachSubgradientWithinAt {f : E → ℝ} {g : E} {x : E} : HasSubgradientWithinAt f g s x ↔ Banach_HasSubgradientWithinAt f (toDual ℝ E g) s x := by constructor · intro h z hz unfold HasSubgradientAt at h obtain hz := h z hz simp; linarith intro h z hz unfold Banach_HasSubgradientAt at h obtain hz := h z hz; simp at hz linarith theorem HasBanachSubgradientWithinAt_HasSubgradientWithinAt {f : E → ℝ} {g : E →L[ℝ] ℝ} {x : E} : Banach_HasSubgradientWithinAt f g s x ↔ HasSubgradientWithinAt f ((toDual ℝ E).symm g) s x := by constructor · intro h z hz unfold Banach_HasSubgradientAt at h obtain hz := h z hz simp; rw [← ContinuousLinearMap.map_sub]; linarith intro h z hz unfold HasSubgradientAt at h obtain hz := h z hz; simp at hz rw [ContinuousLinearMap.map_sub]; linarith end /-! ### Congruence properties of the `Subderiv` -/ section congr variable {f₁ f₂ : E → ℝ} {t s : Set E} theorem SubderivAt.congr (h : f₁ = f₂) : SubderivAt f₁ x = SubderivAt f₂ x := by ext g; rw [h] theorem SubderivWithinAt.congr (h : ∀ y ∈ s, f₁ y = f₂ y) (hf : f₁ x = f₂ x): SubderivWithinAt f₁ s x = SubderivWithinAt f₂ s x := by ext g exact ⟨fun hg y ys => by rw [← h y ys, ← hf]; exact hg y ys, fun hg y ys => by rw [h y ys, hf]; exact hg y ys⟩ theorem SubderivWithinAt.congr_of_mem (xs : x ∈ s) (h : ∀ y ∈ s, f₁ y = f₂ y) : SubderivWithinAt f₁ s x = SubderivWithinAt f₂ s x := congr h (h x xs) theorem SubderivAt.congr_mono (h : ∀ y ∈ s, f₁ y = f₂ y) (hx : f₁ x = f₂ x) (h₁ : t ⊆ s) : SubderivWithinAt f₁ t x = SubderivWithinAt f₂ t x := SubderivWithinAt.congr (fun y a => h y (h₁ a)) hx /-- The subderiv of `f` at `x` is a closed set. --/ theorem SubderivAt.isClosed : ∀ x, IsClosed (SubderivAt f x) := by intro x by_cases e : SubderivAt f x = ∅ · apply Eq.subst (Eq.symm e) isClosed_empty rw [← isSeqClosed_iff_isClosed] intro g g' hg cg y obtain cg' := Tendsto.const_add (f x) (Filter.Tendsto.inner cg tendsto_const_nhds) apply le_of_tendsto_of_tendsto' cg' tendsto_const_nhds (fun n => hg n y) theorem SubderivWithinAt.isClosed : ∀ x, IsClosed (SubderivWithinAt f s x) := by intro x by_cases e : SubderivWithinAt f s x = ∅ · apply Eq.subst (Eq.symm e) isClosed_empty rw [← isSeqClosed_iff_isClosed] intro g g' hg cg y ys obtain cg' := Tendsto.const_add (f x) (Filter.Tendsto.inner cg tendsto_const_nhds) apply le_of_tendsto_of_tendsto' cg' tendsto_const_nhds (fun n => hg n y ys) /-- The subderiv of `f` at `x` is a convex set. --/ theorem SubderivAt.convex : ∀ x, Convex ℝ (SubderivAt f x) := by intro x by_cases e : SubderivAt f x = ∅ · apply Eq.subst (Eq.symm e) convex_empty intro g₁ h1 g₂ h2 a b lea leb abeq y have ineq1 : a • f y ≥ a • f x + a • ⟪g₁, y - x⟫ := by rw [← smul_add] apply smul_le_smul_of_nonneg_left (h1 y) lea have ineq2 : b • f y ≥ b • f x + b • inner g₂ (y - x) := by rw [← smul_add] apply smul_le_smul_of_nonneg_left (h2 y) leb have eq : (a • f x + a • inner g₁ (y - x)) + (b • f x + b • inner g₂ (y - x)) = f x + inner (a • g₁ + b • g₂) (y - x) := by rw [add_add_add_comm, ← Eq.symm (Convex.combo_self abeq (f x))] apply congrArg (HAdd.hAdd (f x)) rw [inner_add_left, inner_smul_left, inner_smul_left]; rfl rw [Eq.symm (Convex.combo_self abeq (f y)), ← eq] apply add_le_add ineq1 ineq2 theorem SubderivWithinAt.convex : ∀ x ∈ s, Convex ℝ (SubderivWithinAt f s x) := by intro x _ by_cases e : SubderivWithinAt f s x = ∅ · apply Eq.subst (Eq.symm e) convex_empty intro g₁ h1 g₂ h2 a b lea leb abeq y ys have ineq1 : a • f y ≥ a • f x + a • ⟪g₁, y - x⟫ := by rw [← smul_add] apply smul_le_smul_of_nonneg_left (h1 y ys) lea have ineq2 : b • f y ≥ b • f x + b • inner g₂ (y - x) := by rw [← smul_add] apply smul_le_smul_of_nonneg_left (h2 y ys) leb have eq : (a • f x + a • inner g₁ (y - x)) + (b • f x + b • inner g₂ (y - x)) = f x + inner (a • g₁ + b • g₂) (y - x) := by rw [add_add_add_comm, ← Eq.symm (Convex.combo_self abeq (f x))] apply congrArg (HAdd.hAdd (f x)) rw [inner_add_left, inner_smul_left, inner_smul_left]; rfl rw [Eq.symm (Convex.combo_self abeq (f y)), ← eq] apply add_le_add ineq1 ineq2 /-- Monotonicity of subderiv--/ theorem subgradientAt_mono {u v : E} {f : E → ℝ}{y : E} (hu : u ∈ SubderivAt f x) (hv : v ∈ SubderivAt f y) : ⟪u - v, x - y⟫ ≥ (0 : ℝ):= by specialize hu y; specialize hv x have ineq1 : ⟪u, x - y⟫ ≥ f x - f y := by rw [congrArg (inner u) (Eq.symm (neg_sub y x)), inner_neg_right]; linarith have _ : inner v (x - y) ≤ f x - f y := Iff.mpr le_sub_iff_add_le' hv rw [inner_sub_left]; linarith end congr /-! ### Basic properties about `Subderiv` -/ section Basic_properties variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] [CompleteSpace E] variable {f : E → ℝ} {g : E} {x y : E} {s : Set E} open Bornology /- The subderiv of `f` at interior point `x` is a nonempty set -/ theorem SubderivWithinAt.Nonempty (hf : ConvexOn ℝ s f) (hc : ContinuousOn f (interior s)): ∀ x ∈ interior s, (SubderivWithinAt f s x).Nonempty := by intro x hx obtain h := Banach_SubderivWithinAt.Nonempty hf hc hx unfold Set.Nonempty at h ⊢ rcases h with ⟨g, hg⟩; unfold Banach_SubderivWithinAt at hg simp at hg rw [HasBanachSubgradientWithinAt_HasSubgradientWithinAt] at hg; use (toDual ℝ E).symm g; unfold SubderivWithinAt simp [hg] theorem SubderivAt.nonempty (hf : ConvexOn ℝ univ f) (hc : ContinuousOn f univ) : ∀ x, Nonempty (SubderivAt f x) := by intro x rw [SubderivAt_SubderivWithinAt] have : x ∈ interior univ := by simp rw [← interior_univ] at hc obtain h := SubderivWithinAt.Nonempty hf hc x this simp [h] rcases h with ⟨a, ha⟩ exact ⟨a, ha⟩ end Basic_properties /-! ### Calculation of `Subderiv` -/ section equivalence variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] [CompleteSpace E] variable {f : E → ℝ} {g : E} {x y : E} {s : Set E} open Pointwise /-- Subderiv of differentiable convex functions --/ theorem SubderivWithinAt_eq_gradient {f'x : E} (hx : x ∈ interior s) (hf : ConvexOn ℝ s f) (h : HasGradientAt f (f'x) x) : SubderivWithinAt f s x = {f'x} := by obtain h' := hasGradientAt_iff_hasFDerivAt.mp h let g := f'x rw [Set.eq_singleton_iff_nonempty_unique_mem] constructor · use g; intro y ys apply Convex_first_order_condition' h hf (interior_subset hx) y ys intro g' hg'; by_contra neq apply not_le_of_lt (norm_sub_pos_iff.mpr neq) let v := g' - g; obtain vneq := sub_ne_zero.mpr neq have : Tendsto (fun (t : ℝ) => (f (x + t • v) - f x - ⟪g, t • v⟫) * ‖t • v‖⁻¹) (𝓝[>] 0) (𝓝 0) := by rw [Metric.tendsto_nhdsWithin_nhds]; intro ε εpos unfold HasFDerivAt at h' rw [hasFDerivAtFilter_iff_tendsto, Metric.tendsto_nhds_nhds] at h' obtain ⟨δ, δpos, hδ⟩ := h' ε εpos use (δ * ‖v‖⁻¹) obtain pos := mul_pos δpos (inv_pos.mpr (norm_pos_iff.mpr vneq)) constructor · exact pos intro t _ ht; rw [dist_eq_norm] at ht; rw [dist_eq_norm] have : dist (x + t • v) x < δ := by rw [dist_eq_norm, add_sub_cancel_left, norm_smul, ← (sub_zero t)] apply lt_of_lt_of_eq ((mul_lt_mul_right (norm_sub_pos_iff.mpr neq)).mpr ht) rw [mul_assoc, inv_mul_cancel₀ (norm_ne_zero_iff.mpr vneq), mul_one] specialize hδ this; rw [dist_eq_norm] at hδ have eq1 : ‖‖x + t • v - x‖⁻¹‖ = ‖t • v‖⁻¹ := by rw [add_sub_cancel_left, norm_inv, norm_norm] have eq2 : (g ∇*) (x + t • v - x) = ⟪g, t • v⟫ := by rw [add_sub_cancel_left]; exact rfl have eq3 : ‖(f (x + t • v) - f x - ⟪g, t • v⟫) * ‖t • v‖⁻¹ - 0‖ = ‖f (x + t • v) - f x - ⟪g, t • v⟫‖ * ‖t • v‖⁻¹ := by rw [sub_zero, norm_mul, norm_inv, norm_norm] have eq : ‖‖x + t • v - x‖⁻¹ * ‖f (x + t • v) - f x - (g ∇*) (x + t • v - x)‖ - 0‖ = ‖(f (x + t • v) - f x - ⟪g, t • v⟫) * ‖t • v‖⁻¹ - 0‖ := by rw [sub_zero, norm_mul, norm_norm, mul_comm, eq1, eq2, ← eq3] apply Eq.trans_lt (Eq.symm eq) hδ apply ge_of_tendsto this rw [Filter.Eventually, Metric.mem_nhdsWithin_iff] rw [mem_interior_iff_mem_nhds, Metric.mem_nhds_iff] at hx obtain ⟨ε, εpos, ballmem⟩ := hx obtain pos := mul_pos εpos (inv_pos.mpr (norm_pos_iff.mpr vneq)) use (ε * ‖v‖⁻¹); use pos; intro t ht have tball := ht.1; have tlt : t > 0 := ht.2 have tvpos : ‖t • v‖⁻¹ > 0 := by apply inv_pos.mpr; rw [norm_smul] apply smul_pos (abs_pos_of_pos tlt) (norm_sub_pos_iff.mpr neq) have mems : x + t • v ∈ s := by apply ballmem rw [mem_ball_iff_norm, sub_zero] at tball rw [mem_ball_iff_norm, add_sub_cancel_left, norm_smul] have : ‖t‖ * ‖v‖ < ε * ‖v‖⁻¹ * ‖v‖ := by apply (mul_lt_mul_right (norm_sub_pos_iff.mpr neq)).mpr tball rwa [mul_assoc, inv_mul_cancel₀ (norm_ne_zero_iff.mpr vneq), mul_one] at this obtain ineq1 := hg' (x + t • v); rw [add_sub_cancel_left] at ineq1 have eq1 : ‖v‖ = (⟪g', t • v⟫ - ⟪g, t • v⟫) * ‖t • v‖⁻¹ := by have eq2 : ‖v‖ = ⟪v, v⟫ * ‖v‖⁻¹ := by rw [real_inner_self_eq_norm_sq] apply (div_eq_iff _).mp · rw [div_inv_eq_mul, pow_two] exact inv_ne_zero (norm_ne_zero_iff.mpr vneq) have eq3 : ⟪v, v⟫ * ‖v‖⁻¹ = ⟪v, t • v⟫ * ‖t • v‖⁻¹ := by have : ⟪v, t • v⟫ = ⟪v, v⟫ * t := by rw [inner_smul_right, mul_comm] rw [this, mul_assoc] have : ‖v‖⁻¹ = t * ‖t • v‖⁻¹ := by have : t * ‖t • v‖⁻¹ = t / ‖t • v‖ := rfl rw [this, inv_eq_one_div] have : t = ‖t‖ := by have : ‖t‖ = |t| := rfl rw [this, abs_of_pos tlt] rw [this, norm_smul, norm_norm, div_mul_eq_div_div, div_self] rw [norm_ne_zero_iff] exact ne_of_gt tlt rw [this] rw [eq2, eq3, mul_eq_mul_right_iff]; left; rw [inner_sub_left] rw [mem_setOf, eq1, mul_le_mul_right tvpos] apply sub_le_sub_right (le_sub_iff_add_le'.mpr (ineq1 mems)) /-- Alternarive version for FDeriv --/ theorem SubderivWithinAt_eq_FDeriv {f' : E → (E →L[ℝ] ℝ)} (hx : x ∈ interior s) (hf : ConvexOn ℝ s f) (h : HasFDerivAt f (f' x) x) : SubderivWithinAt f s x = {(toDual ℝ E).symm (f' x)} := by have h₁ : HasFDerivAt f ((toDual ℝ E) ((LinearIsometryEquiv.symm (toDual ℝ E)) (f' x))) x := by simp [h] obtain h' := hasGradientAt_iff_hasFDerivAt.mpr h₁ apply SubderivWithinAt_eq_gradient hx hf exact h' theorem SubderivAt_eq_gradient {f'x : E} (hf : ConvexOn ℝ univ f) (h : HasGradientAt f (f'x) x) : SubderivAt f x = {f'x} := by rw [SubderivAt_SubderivWithinAt] apply SubderivWithinAt_eq_gradient _ hf h · simp only [interior_univ, mem_univ] end equivalence /-! ### Optimality Theory for Unconstrained Nondifferentiable Problems -/ section optimality_theory theorem HasSubgradientAt_zero_of_isMinOn (h : IsMinOn f univ x) : HasSubgradientAt f 0 x := fun y => le_of_le_of_eq' (h trivial) (by rw [inner_zero_left, add_zero]) theorem isMinOn_of_HasSubgradentAt_zero (h : HasSubgradientAt f 0 x) : IsMinOn f univ x := by intro y _; specialize h y rwa [inner_zero_left, add_zero] at h /-- `x'` minimize `f` if and only if `0` is a subgradient of `f` at `x'` --/ theorem HasSubgradientAt_zero_iff_isMinOn : HasSubgradientAt f 0 x ↔ IsMinOn f univ x := ⟨isMinOn_of_HasSubgradentAt_zero, HasSubgradientAt_zero_of_isMinOn⟩ theorem HasSubgradientWithinAt_zero_of_isMinOn (h : IsMinOn f s x) : HasSubgradientWithinAt f 0 s x := fun y ys => le_of_le_of_eq' (h ys) (by rw [inner_zero_left, add_zero]) theorem isMinOn_of_HasSubgradentWithinAt_zero (h : HasSubgradientWithinAt f 0 s x) : IsMinOn f s x := by intro y ys; specialize h y ys rwa [inner_zero_left, add_zero] at h theorem HasSubgradientWithinAt_zero_iff_isMinOn : HasSubgradientWithinAt f 0 s x ↔ IsMinOn f s x := ⟨isMinOn_of_HasSubgradentWithinAt_zero, HasSubgradientWithinAt_zero_of_isMinOn⟩ lemma SubderivAt_zero (xm : E) : 0 ∈ SubderivAt f xm ↔ ∀ y, f y ≥ f xm + ⟪0, y - xm⟫:= by rfl theorem first_order_convex_iff_subgradient (f : E → ℝ) (xm : E) : IsMinOn f univ xm ↔ 0 ∈ SubderivAt f xm := by rw [SubderivAt_zero xm ,isMinOn_iff] constructor · intro h y simp only [inner_zero_left, add_zero, ge_iff_le] apply h y simp only [mem_univ] · intro h x _ have := h x simp only [inner_zero_left, add_zero, ge_iff_le] at this exact this end optimality_theory /-! ### Computing `Subderiv` -/ section computation open Pointwise variable {f : E → ℝ} {g : E} {x : E} {s : Set E} /-- Multiplication by a Positive Scalar--/ theorem HasSubgradientAt.pos_smul {c : ℝ} (h : HasSubgradientAt f g x) (hc : 0 < c) : HasSubgradientAt (c • f) (c • g) x := by intro y; rw [inner_smul_left] have ineq : c * f y ≥ c * (f x + inner g (y - x)) := (mul_le_mul_left hc).mpr (h y) have eq : c * (f x + inner g (y - x)) = c * f x + c * inner g (y - x) := mul_add c (f x) (inner g (y - x)) exact Eq.trans_le (id eq.symm) ineq theorem SubderivAt.pos_smul {c : ℝ} (hc : 0 < c) : SubderivAt (c • f) x = c • (SubderivAt f x) := by ext g constructor · intro hg; use (c⁻¹ • g) constructor · intro y; have neq : c ≠ 0 := ne_of_gt hc calc f y = c⁻¹ * (c * f y) := (eq_inv_mul_iff_mul_eq₀ neq).mpr rfl _ ≥ c⁻¹ * (c * f x + inner g (y - x)) := mul_le_mul_of_nonneg_left (hg y) (inv_nonneg.mpr (le_of_lt hc)) _ = f x + inner (c⁻¹ • g) (y - x) := by rw [mul_add, inner_smul_left, ← ((eq_inv_mul_iff_mul_eq₀ neq).mpr rfl)] rfl exact smul_inv_smul₀ (ne_of_gt hc) g rintro ⟨gg, hgg, eq⟩; intro y calc c * f y ≥ c * (f x + inner gg (y - x)) := (mul_le_mul_left hc).mpr (hgg y) _ = c * f x + c * inner gg (y - x) := mul_add c (f x) (inner gg (y - x)) _ = c * f x + inner (c • gg) (y - x) := by rw [inner_smul_left]; exact rfl _ = c * f x + inner g (y - x) := by rw [← eq] /-- Subderivatives of the sum of two functions is a subset of the sum of the subderivatives of the two functions --/ theorem SubderivAt.add_subset {f₁ f₂ : E → ℝ} : ∀ (x : E), SubderivAt f₁ x + SubderivAt f₂ x ⊆ SubderivAt (f₁ + f₂) x := by intro x y hy y' obtain ⟨y₁, hy₁, y₂, hy₂, eq⟩ := Set.mem_add.mpr hy have eq' : y₁ + y₂ = y := eq have : (f₁ + f₂) y' ≥ (f₁ x + ⟪y₁, y' - x⟫) + (f₂ x + ⟪y₂, y' - x⟫) := add_le_add (hy₁ y') (hy₂ y') rwa [add_add_add_comm, ← inner_add_left, eq'] at this private lemma leq_tendsto_zero {a : ℝ} (h : ∀ t > 0, 0 < a + t) : 0 ≤ a := by by_contra h'; push_neg at h'; specialize h (- a / 2) (by linarith) linarith end computation section variable [CompleteSpace E] open Pointwise theorem SubderivAt.add {f₁ f₂ : E → ℝ} (h₁ : ConvexOn ℝ univ f₁) (h₂: ConvexOn ℝ univ f₂) (hcon : ContinuousOn f₁ univ) : ∀ (x : E), SubderivAt f₁ x + SubderivAt f₂ x = SubderivAt (f₁ + f₂) x := by intro x₀ apply Subset.antisymm (SubderivAt.add_subset x₀) rw [SubderivAt, SubderivAt, SubderivAt, Set.subset_def] intro g hg rw [Set.mem_setOf] at hg; rw [Set.mem_add] let S₁ := {(x, y) : E × ℝ | y > f₁ (x + x₀) - f₁ x₀ - inner g x} let S₂ := {(x, y) : E × ℝ | y ≤ f₂ x₀ - f₂ (x + x₀)} have hs1 : Convex ℝ S₁ := by rw [convex_iff_forall_pos]; intro i hi j hj a b ha hb hab rw [Set.mem_setOf] at hi hj ⊢; simp at hi hj ⊢ rw [← mul_lt_mul_iff_of_pos_left ha] at hi rw [← mul_lt_mul_iff_of_pos_left hb] at hj rw [inner_add_right, inner_smul_right, inner_smul_right, ← sub_sub] have : x₀ = (1 : ℝ) • x₀ := by simp only [one_smul] have : a • i.1 + b • j.1 + x₀ = a • (i.1 + x₀) + b • (j.1 + x₀) := by nth_rw 1 [this]; rw [smul_add, smul_add, ← hab, add_smul]; rw [← add_assoc, ← add_assoc]; simp; rw [add_assoc, add_comm (b • j.1), ← add_assoc] have : f₁ (a • i.1 + b • j.1 + x₀) ≤ a * f₁ (i.1 + x₀) + b * f₁ (j.1 + x₀) := by rw [this] rw [convexOn_iff_forall_pos] at h₁; rcases h₁ with ⟨_, h₁⟩ specialize @h₁ (i.1 + x₀) (by trivial) (j.1 + x₀) (by trivial) a b ha hb hab simp at h₁; simp; linarith apply lt_of_lt_of_le' (b := a * f₁ (i.1 + x₀) + b * f₁ (j.1 + x₀) - f₁ x₀ - a * ⟪g, i.1⟫_ℝ - b * ⟪g, j.1⟫_ℝ) · have : f₁ x₀ = (1 : ℝ) • (f₁ x₀) := by simp rw [this, ← hab, add_smul, ← sub_sub, smul_eq_mul, smul_eq_mul]; linarith · simp [this]; have hs2 : Convex ℝ S₂ := by rw [convex_iff_forall_pos]; intro i hi j hj a b ha hb hab rw [Set.mem_setOf] at hi hj ⊢; simp at hi hj ⊢ rw [← mul_le_mul_iff_of_pos_left ha] at hi rw [← mul_le_mul_iff_of_pos_left hb] at hj have : x₀ = (1 : ℝ) • x₀ := by simp only [one_smul] have : a • i.1 + b • j.1 + x₀ = a • (i.1 + x₀) + b • (j.1 + x₀) := by nth_rw 1 [this]; rw [smul_add, smul_add, ← hab, add_smul]; rw [← add_assoc, ← add_assoc]; simp; rw [add_assoc, add_comm (b • j.1), ← add_assoc] have ineq : f₂ (a • i.1 + b • j.1 + x₀) ≤ a * f₂ (i.1 + x₀) + b * f₂ (j.1 + x₀) := by rw [this] rw [convexOn_iff_forall_pos] at h₂; rcases h₂ with ⟨_, h₂⟩ specialize @h₂ (i.1 + x₀) (by trivial) (j.1 + x₀) (by trivial) a b ha hb hab simp at h₂; simp; linarith have eq : f₂ x₀ = a * f₂ x₀ + b * f₂ x₀ := by rw [← add_mul, hab, one_mul] obtain hh := sub_le_sub_left ineq (a * f₂ x₀ + b * f₂ x₀) have eq' : a * (f₂ x₀ - f₂ (i.1 + x₀)) + b * (f₂ x₀ - f₂ (j.1 + x₀)) = a * f₂ x₀ + b * f₂ x₀ - (a * f₂ (i.1 + x₀) + b * f₂ (j.1 + x₀)) := by ring rw [← eq'] at hh; rw [eq] apply le_trans (add_le_add hi hj) hh have hint : Disjoint S₁ S₂ := by rw [disjoint_iff]; by_contra joint obtain ⟨⟨x, y⟩, ⟨hp1, hp2⟩⟩ := nmem_singleton_empty.mp joint rw [Set.mem_setOf] at hp1 hp2 specialize hg (x + x₀); rw [← add_sub, sub_self, add_zero] at hg apply not_le_of_gt ?_ hg obtain ineq := add_lt_add_of_le_of_lt hp2 (neg_lt_neg hp1) simp at ineq have hh : ∀ x : E, (f₁ + f₂) x = f₁ x + f₂ x := fun x => rfl apply lt_of_sub_pos have eq : f₂ x₀ - f₂ (x + x₀) + (⟪g, x⟫_ℝ - (f₁ (x + x₀) - f₁ x₀)) = f₁ x₀ + f₂ x₀ + ⟪g, x⟫_ℝ - (f₁ (x + x₀) + f₂ (x + x₀)) := by ring rwa [hh x₀, hh (x + x₀), ← eq] have hso : IsOpen S₁ := by apply Continuous_epi_open (f₁ := fun x ↦ f₁ (x + x₀) - f₁ x₀ - inner g x) apply ContinuousOn.sub · apply ContinuousOn.sub · apply ContinuousOn.comp (g := f₁) (f := fun x ↦ x + x₀) (t := univ) hcon · apply ContinuousOn.add continuousOn_id continuousOn_const · simp apply continuousOn_const apply ContinuousOn.inner continuousOn_const continuousOn_id obtain ⟨f, c, ⟨hsl, hsr⟩⟩ := geometric_hahn_banach_open hs1 hso hs2 hint have eq : ∃ a : E, ∃ b : ℝ, ∀ (p : E × ℝ), f p = inner a p.1 + b * p.2 := by let f1 := ContinuousLinearMap.comp f (ContinuousLinearMap.inl ℝ E ℝ) let f2 := ContinuousLinearMap.comp f (ContinuousLinearMap.inr ℝ E ℝ) use (toDual ℝ E).symm f1 use (toDual ℝ ℝ).symm f2 intro p have : ((toDual ℝ ℝ).symm f2) * p.2 = inner (((toDual ℝ ℝ).symm f2)) p.2 := by simp [f2] have : ((toDual ℝ ℝ).symm f2) * p.2 = f2 p.2 := by rw [this] simp only [toDual_symm_apply, ContinuousLinearMap.coe_comp', Function.comp_apply, ContinuousLinearMap.inl_apply, ContinuousLinearMap.inr_apply] rw [this]; simp [f1, f2] have : (p.1, (0 : ℝ)) + ((0 : E), p.2) = p := by simp nth_rw 1 [← this]; rw [ContinuousLinearMap.map_add] rcases eq with ⟨a, b, hab⟩ have hin : (0, 0) ∈ S₂ := by rw [Set.mem_setOf]; simp obtain hc0 := hsr (0, 0) hin rw [hab (0, 0)] at hc0; simp at hc0 have hin1 : ∀ t > 0, (0, t) ∈ S₁ := by intro t ht; rw [Set.mem_setOf]; simp; linarith have htp : ∀ t > 0, b * t < c := by intro t ht; obtain hin1 := hin1 t ht specialize hsl (0, t) hin1; specialize hab (0, t); simp at hab linarith have ceq0 : c = 0 := by by_contra hc; push_neg at hc; have hc : c < 0 := lt_of_le_of_ne hc0 hc by_cases hb : b ≥ 0 · specialize htp 1 (by linarith); rw [mul_one] at htp linarith push_neg at hb have pos : (c / (2 * b)) > 0 := by apply div_pos_of_neg_of_neg hc (by linarith) specialize (htp (c / (2 * b)) pos); field_simp [hb] at htp have eq : b * c / (2 * b) = c / 2 := by ring_nf; simp; field_simp [hb] rw [mul_div_right_comm, div_self (by linarith), one_mul] rw [eq] at htp; linarith have bleq0 : b < 0 := by rw [ceq0] at htp specialize htp 1 (by linarith); rw [mul_one] at htp; linarith let hata := - (1 / b) • a have g1 : g + hata ∈ {g | HasSubgradientAt f₁ g x₀} := by rw [Set.mem_setOf]; unfold HasSubgradientAt; intro x simp [hata] have hin1 : ∀ t > 0, (x - x₀, f₁ x - f₁ x₀ - ⟪g, x - x₀⟫_ℝ + t) ∈ S₁ := by intro t ht rw [Set.mem_setOf]; simp; exact ht have ineq : ∀ t > 0, 0 < b⁻¹ * ⟪a, x - x₀⟫_ℝ + f₁ x - f₁ x₀ - ⟪g, x - x₀⟫_ℝ + t := by intro t ht specialize hsl (x - x₀, f₁ x - f₁ x₀ - ⟪g, x - x₀⟫_ℝ + t) (hin1 t ht) rw [ceq0, hab (x - x₀, f₁ x - f₁ x₀ - ⟪g, x - x₀⟫_ℝ + t)] at hsl; simp at hsl obtain ineq := (mul_lt_mul_left_of_neg (inv_lt_zero.mpr bleq0)).mpr hsl simp at ineq rw [mul_add, ← mul_assoc, inv_mul_cancel₀ (ne_of_lt bleq0), one_mul] at ineq rw [← add_assoc, add_sub, add_sub] at ineq; exact ineq rw [inner_add_left, inner_neg_left, real_inner_smul_left] rw [← add_assoc]; simp have : b⁻¹ * ⟪a, x - x₀⟫_ℝ + f₁ x - f₁ x₀ - ⟪g, x - x₀⟫_ℝ ≥ 0 := leq_tendsto_zero ineq linarith have g2 : - hata ∈ {g | HasSubgradientAt f₂ g x₀} := by rw [Set.mem_setOf]; unfold HasSubgradientAt; intro x simp [hata]; have hin2 : (x - x₀, f₂ x₀ - f₂ x) ∈ S₂ := by rw [Set.mem_setOf]; simp specialize hsr (x - x₀, f₂ x₀ - f₂ x) hin2 rw [ceq0, hab (x - x₀, f₂ x₀ - f₂ x)] at hsr; simp at hsr obtain ineq := (mul_le_mul_left_of_neg (inv_lt_zero.mpr bleq0)).mpr hsr rw [mul_add, ← real_inner_smul_left, mul_zero, ← mul_assoc, inv_mul_cancel₀ (ne_of_lt bleq0), one_mul] at ineq linarith use (g + hata); constructor; exact g1 use (- hata); constructor; exact g2; simp end /-! ### Examples of `Subderiv` -/ section theorem SubderivAt_of_norm_at_zero : SubderivAt (fun (x : E) => ‖x‖) 0 = {g | ‖g‖ ≤ 1} := by ext g constructor · intro hg; by_contra h have hg' : ‖g‖ > 1 := not_le.mp h specialize hg g simp only [sub_zero, norm_zero, zero_add, real_inner_self_eq_norm_mul_norm] at hg have : ‖g‖ * ‖g‖ > 1 * ‖g‖ := mul_lt_mul_of_pos_right hg' (by linarith) simp only [one_mul] at this apply not_lt.mpr hg this intro hg y calc ‖(0 : E)‖ + inner g (y - 0) = inner g y := by simp only [norm_zero, zero_add, sub_zero] _ ≤ ‖g‖ * ‖y‖ := real_inner_le_norm g y _ ≤ 1 * ‖y‖ := mul_le_mul_of_nonneg_right hg (norm_nonneg y) _ = ‖y‖ := by simp only [one_mul] theorem SubderivAt_abs (x : ℝ) : SubderivAt abs x = if x = 0 then Icc (-1) 1 else {Real.sign x} := by rw [eq_ite_iff] by_cases h : x = 0 · left; constructor · exact h have h2 : Icc (-1 : ℝ) 1 = {g | ‖g‖ ≤ 1} := by ext y; simp only [Icc, mem_setOf, norm] have : |y| ≤ 1 ↔ -1 ≤ y ∧ y ≤ 1 := by apply abs_le exact (Iff.symm this) rw [h2, h] apply SubderivAt_of_norm_at_zero right constructor · exact h ext g constructor · intro hg by_cases hx : x > 0 · by_contra gne by_cases glt : g < 1 · specialize hg 0 have ineq : (0 : ℝ) < 0 := by calc 0 ≥ x + g * (-x):= by simp only [abs_zero, zero_sub, abs_pos_of_pos, abs_of_pos hx] at hg have : inner g (-x) = g * (-x) := by rfl rwa [this] at hg _ = x * (1 - g) := by ring _ > 0 := mul_pos hx (by linarith) exact LT.lt.false ineq specialize hg (x + 1) have : x + 1 > 0 := by linarith simp only [abs_of_pos hx, abs_of_pos this, add_le_add_iff_left, add_sub_cancel_left] at hg apply glt have h1: g ≤ 1 := by calc g = inner g 1 := by simp _ ≤ 1 := hg simp only [Real.sign_of_pos hx] at gne exact Ne.lt_of_le gne h1 have hx : x < 0 := Ne.lt_of_le h (not_lt.mp hx) rw [Real.sign_of_neg hx] by_contra gne by_cases glt : g < -1 · specialize hg (x - 1) have : x - 1 < 0 := by linarith simp only [abs_of_neg this, abs_of_neg hx, abs_zero, zero_sub] at hg have : -g ≤ 1 := by calc -g = inner g (x - 1 - x) := by simp _ ≤ 1 := by linarith [hg] linarith specialize hg 0 have eq1 : inner g (-x) = g * (-x) := rfl have eq2 : -x + g * -x = -x * (1 + g) := by ring simp only [abs_zero, zero_sub, abs_of_neg hx, eq1, eq2] at hg have : -x * (1 + g) > 0 := by apply mul_pos (by linarith) have : g > -1 := Ne.lt_of_le' gne (not_lt.mp glt) linarith linarith intro hg y by_cases hx : x > 0 · simp only [Real.sign_of_pos hx] at hg calc |x| + inner g (y - x) = x + inner 1 (y - x) := by rw [abs_of_pos hx, hg] _ = y := by simp _ ≤ |y| := le_abs_self y have hx : x < 0 := Ne.lt_of_le h (not_lt.mp hx) simp only [Real.sign_of_neg hx] at hg calc |x| + inner g (y - x) = -x + inner (-1) (y - x) := by rw [abs_of_neg hx, hg] _ = -y := by simp; ring _ ≤ |y| := neg_le_abs y end