Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18536License: APACHE
/- Copyright (c) 2019 Alexander Bentkamp. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Alexander Bentkamp, Yury Kudriashov -/ import data.complex.basic import data.set.intervals import tactic.interactive import tactic.linarith import linear_algebra.basic import ring_theory.algebra import algebra.pointwise /-! # Convex sets and functions on real vector spaces In a real vector space, we define the following objects and properties. * `segment x y` is the closed segment joining `x` and `y`. * A set `s` is `convex` if for any two points `x y ∈ s` it includes `segment x y`; * A function `f` is `convex_on` a set `s` if `s` is itself a convex set, and for any two points `x y ∈ s` the segment joining `(x, f x)` to `(y, f y)` is (non-strictly) above the graph of `f`; equivalently, `convex_on f s` means that the epigraph `{p : E × ℝ | p.1 ∈ s ∧ f p.1 ≤ p.2}` is a convex set; * Center mass of a finite set of points with prescribed weights. * Convex hull of a set `s` is the minimal convex set that includes `s`. * Standard simplex `std_simplex ι [fintype ι]` is the intersection of the positive quadrant with the hyperplane `s.sum = 1` in the space `ι → ℝ`. We also provide various equivalent versions of the definitions above, prove that some specific sets are convex, and prove Jensen's inequality. ## Notations We use the following local notations: * `I = Icc (0:ℝ) 1`; * `[x, y] = segment x y`. They are defined using `local notation`, so they are not available outside of this file. -/ universes u' u v w x variables {E : Type u} {F : Type v} {ι : Type w} {ι' : Type x} [add_comm_group E] [vector_space ℝ E] [add_comm_group F] [vector_space ℝ F] {s : set E} open set open_locale classical local notation `I` := (Icc 0 1 : set ℝ) local attribute [instance] set.pointwise_add set.smul_set section sets /-! ### Segment -/ /-- Segments in a vector space -/ def segment (x y : E) : set E := {z : E | ∃ (a b : ℝ) (ha : 0 ≤ a) (hb : 0 ≤ b) (hab : a + b = 1), a • x + b • y = z} local notation `[`x `, ` y `]` := segment x y lemma segment_symm (x y : E) : [x, y] = [y, x] := set.ext $ λ z, ⟨λ ⟨a, b, ha, hb, hab, H⟩, ⟨b, a, hb, ha, (add_comm _ _).trans hab, (add_comm _ _).trans H⟩, λ ⟨a, b, ha, hb, hab, H⟩, ⟨b, a, hb, ha, (add_comm _ _).trans hab, (add_comm _ _).trans H⟩⟩ lemma left_mem_segment (x y : E) : x ∈ [x, y] := ⟨1, 0, zero_le_one, le_refl 0, add_zero 1, by rw [zero_smul, one_smul, add_zero]⟩ lemma right_mem_segment (x y : E) : y ∈ [x, y] := segment_symm y x ▸ left_mem_segment y x lemma segment_same (x : E) : [x, x] = {x} := set.ext $ λ z, ⟨λ ⟨a, b, ha, hb, hab, hz⟩, by simpa only [(add_smul _ _ _).symm, mem_singleton_iff, hab, one_smul, eq_comm] using hz, λ h, mem_singleton_iff.1 h ▸ left_mem_segment z z⟩ lemma segment_eq_image (x y : E) : segment x y = (λ (θ : ℝ), (1 - θ) • x + θ • y) '' I := set.ext $ λ z, ⟨λ ⟨a, b, ha, hb, hab, hz⟩, ⟨b, ⟨hb, hab ▸ le_add_of_nonneg_left ha⟩, hab ▸ hz ▸ by simp only [add_sub_cancel]⟩, λ ⟨θ, ⟨hθ₀, hθ₁⟩, hz⟩, ⟨1-θ, θ, sub_nonneg.2 hθ₁, hθ₀, sub_add_cancel _ _, hz⟩⟩ lemma segment_eq_image' (x y : E) : segment x y = (λ (θ : ℝ), x + θ • (y - x)) '' I := by { convert segment_eq_image x y, ext θ, simp only [smul_sub, sub_smul, one_smul], abel } lemma segment_eq_image₂ (x y : E) : segment x y = (λ p:ℝ×ℝ, p.1 • x + p.2 • y) '' {p | 0 ≤ p.1 ∧ 0 ≤ p.2 ∧ p.1 + p.2 = 1} := by simp only [segment, image, prod.exists, mem_set_of_eq, exists_prop, and_assoc] lemma segment_eq_Icc {a b : ℝ} (h : a ≤ b) : [a, b] = Icc a b := begin rw [segment_eq_image'], show (((+) a) ∘ (λ t, t * (b - a))) '' Icc 0 1 = Icc a b, rw [image_comp, image_mul_right_Icc (@zero_le_one ℝ _) (sub_nonneg.2 h), image_add_left_Icc], simp end lemma segment_eq_Icc' (a b : ℝ) : [a, b] = Icc (min a b) (max a b) := by cases le_total a b; [skip, rw segment_symm]; simp [segment_eq_Icc, *] lemma segment_eq_interval (a b : ℝ) : segment a b = interval a b := segment_eq_Icc' _ _ lemma mem_segment_translate (a : E) {x b c} : a + x ∈ [a + b, a + c] ↔ x ∈ [b, c] := begin rw [segment_eq_image', segment_eq_image'], refine exists_congr (λ θ, and_congr iff.rfl _), simp only [add_sub_add_left_eq_sub, add_assoc, add_left_inj] end lemma segment_translate_preimage (a b c : E) : (λ x, a + x) ⁻¹' [a + b, a + c] = [b, c] := set.ext $ λ x, mem_segment_translate a lemma segment_translate_image (a b c: E) : (λx, a + x) '' [b, c] = [a + b, a + c] := segment_translate_preimage a b c ▸ image_preimage_eq $ add_left_surjective a /-! ### Convexity of sets -/ /-- Convexity of sets -/ def convex (s : set E) := ∀ ⦃x y : E⦄, x ∈ s → y ∈ s → ∀ ⦃a b : ℝ⦄, 0 ≤ a → 0 ≤ b → a + b = 1 → a • x + b • y ∈ s lemma convex_iff_segment_subset : convex s ↔ ∀ ⦃x y⦄, x ∈ s → y ∈ s → [x, y] ⊆ s := by simp only [convex, segment_eq_image₂, subset_def, ball_image_iff, prod.forall, mem_set_of_eq, and_imp] lemma convex.segment_subset (h : convex s) {x y:E} (hx : x ∈ s) (hy : y ∈ s) : [x, y] ⊆ s := convex_iff_segment_subset.1 h hx hy /-- Alternative definition of set convexity, in terms of pointwise set operations. -/ lemma convex_iff_pointwise_add_subset: convex s ↔ ∀ ⦃a b : ℝ⦄, 0 ≤ a → 0 ≤ b → a + b = 1 → a • s + b • s ⊆ s := iff.intro begin rintros hA a b ha hb hab w ⟨au, ⟨u, hu, rfl⟩, bv, ⟨v, hv, rfl⟩, rfl⟩, exact hA hu hv ha hb hab end (λ h x y hx hy a b ha hb hab, (h ha hb hab) (set.add_mem_pointwise_add ⟨_, hx, rfl⟩ ⟨_, hy, rfl⟩)) /-- Alternative definition of set convexity, using division -/ lemma convex_iff_div: convex s ↔ ∀ ⦃x y : E⦄, x ∈ s → y ∈ s → ∀ ⦃a b : ℝ⦄, 0 ≤ a → 0 ≤ b → 0 < a + b → (a/(a+b)) • x + (b/(a+b)) • y ∈ s := ⟨begin assume h x y hx hy a b ha hb hab, apply h hx hy, have ha', from mul_le_mul_of_nonneg_left ha (le_of_lt (inv_pos hab)), rwa [mul_zero, ←div_eq_inv_mul] at ha', have hb', from mul_le_mul_of_nonneg_left hb (le_of_lt (inv_pos hab)), rwa [mul_zero, ←div_eq_inv_mul] at hb', rw [←add_div], exact div_self (ne_of_lt hab).symm end, begin assume h x y hx hy a b ha hb hab, have h', from h hx hy ha hb, rw [hab, div_one, div_one] at h', exact h' zero_lt_one end⟩ /-! ### Examples of convex sets -/ lemma convex_empty : convex (∅ : set E) := by finish lemma convex_singleton (c : E) : convex ({c} : set E) := begin intros x y hx hy a b ha hb hab, rw [set.eq_of_mem_singleton hx, set.eq_of_mem_singleton hy, ←add_smul, hab, one_smul], exact mem_singleton c end lemma convex_univ : convex (set.univ : set E) := λ _ _ _ _ _ _ _ _ _, trivial lemma convex.inter {t : set E} (hs: convex s) (ht: convex t) : convex (s ∩ t) := λ x y (hx : x ∈ s ∩ t) (hy : y ∈ s ∩ t) a b (ha : 0 ≤ a) (hb : 0 ≤ b) (hab : a + b = 1), ⟨hs hx.left hy.left ha hb hab, ht hx.right hy.right ha hb hab⟩ lemma convex_sInter {S : set (set E)} (h : ∀ s ∈ S, convex s) : convex (⋂₀ S) := assume x y hx hy a b ha hb hab s hs, h s hs (hx s hs) (hy s hs) ha hb hab lemma convex_Inter {ι : Sort*} {s: ι → set E} (h: ∀ i : ι, convex (s i)) : convex (⋂ i, s i) := (sInter_range s) ▸ convex_sInter $ forall_range_iff.2 h lemma convex.prod {s : set E} {t : set F} (hs : convex s) (ht : convex t) : convex (s.prod t) := begin intros x y hx hy a b ha hb hab, apply mem_prod.2, exact ⟨hs (mem_prod.1 hx).1 (mem_prod.1 hy).1 ha hb hab, ht (mem_prod.1 hx).2 (mem_prod.1 hy).2 ha hb hab⟩ end lemma convex.is_linear_image (hs : convex s) {f : E → F} (hf : is_linear_map ℝ f) : convex (f '' s) := begin rintros _ _ ⟨x, hx, rfl⟩ ⟨y, hy, rfl⟩ a b ha hb hab, exact ⟨a • x + b • y, hs hx hy ha hb hab, by simp only [hf.add,hf.smul]⟩ end lemma convex.linear_image (hs : convex s) (f : E →ₗ[ℝ] F) : convex (image f s) := hs.is_linear_image f.is_linear lemma convex.is_linear_preimage {s : set F} (hs : convex s) {f : E → F} (hf : is_linear_map ℝ f) : convex (preimage f s) := begin intros x y hx hy a b ha hb hab, convert hs hx hy ha hb hab, simp only [mem_preimage, hf.add, hf.smul] end lemma convex.linear_preimage {s : set F} (hs : convex s) (f : E →ₗ[ℝ] F) : convex (preimage f s) := hs.is_linear_preimage f.is_linear lemma convex.neg (hs : convex s) : convex ((λ z, -z) '' s) := hs.is_linear_image is_linear_map.is_linear_map_neg lemma convex.neg_preimage (hs : convex s) : convex ((λ z, -z) ⁻¹' s) := hs.is_linear_preimage is_linear_map.is_linear_map_neg lemma convex.smul (c : ℝ) (hs : convex s) : convex (c • s) := begin rw smul_set_eq_image, exact hs.is_linear_image (is_linear_map.is_linear_map_smul c) end lemma convex.smul_preimage (c : ℝ) (hs : convex s) : convex ((λ z, c • z) ⁻¹' s) := hs.is_linear_preimage (is_linear_map.is_linear_map_smul c) lemma convex.add {t : set E} (hs : convex s) (ht : convex t) : convex (s + t) := by { rw pointwise_add_eq_image, exact (hs.prod ht).is_linear_image is_linear_map.is_linear_map_add } lemma convex.sub {t : set E} (hs : convex s) (ht : convex t) : convex ((λx : E × E, x.1 - x.2) '' (s.prod t)) := (hs.prod ht).is_linear_image is_linear_map.is_linear_map_sub lemma convex.translate (hs : convex s) (z : E) : convex ((λx, z + x) '' s) := begin convert (convex_singleton z).add hs, ext x, simp [set.mem_image, mem_pointwise_add, eq_comm] end lemma convex.affinity (hs : convex s) (z : E) (c : ℝ) : convex ((λx, z + c • x) '' s) := begin convert (hs.smul c).translate z using 1, erw [smul_set_eq_image, ←image_comp] end lemma convex_real_iff {s : set ℝ} : convex s ↔ ∀ {x y}, x ∈ s → y ∈ s → Icc x y ⊆ s := begin simp only [convex_iff_segment_subset, segment_eq_Icc'], split; intros h x y hx hy, { cases le_or_lt x y with hxy hxy, { simpa [hxy] using h hx hy }, { simp [hxy] } }, { apply h; cases le_total x y; simp [*] } end lemma convex_Iio (r : ℝ) : convex (Iio r) := convex_real_iff.2 $ λ x y hx hy z hz, lt_of_le_of_lt hz.2 hy lemma convex_Ioi (r : ℝ) : convex (Ioi r) := convex_real_iff.2 $ λ x y hx hy z hz, lt_of_lt_of_le hx hz.1 lemma convex_Iic (r : ℝ) : convex (Iic r) := convex_real_iff.2 $ λ x y hx hy z hz, le_trans hz.2 hy lemma convex_Ici (r : ℝ) : convex (Ici r) := convex_real_iff.2 $ λ x y hx hy z hz, le_trans hx hz.1 lemma convex_Ioo (r : ℝ) (s : ℝ) : convex (Ioo r s) := (convex_Ioi _).inter (convex_Iio _) lemma convex_Ico (r : ℝ) (s : ℝ) : convex (Ico r s) := (convex_Ici _).inter (convex_Iio _) lemma convex_Ioc (r : ℝ) (s : ℝ) : convex (Ioc r s) := (convex_Ioi _).inter (convex_Iic _) lemma convex_Icc (r : ℝ) (s : ℝ) : convex (Icc r s) := (convex_Ici _).inter (convex_Iic _) lemma convex_segment (a b : E) : convex [a, b] := begin have : (λ (t : ℝ), a + t • (b - a)) = (λz : E, a + z) ∘ (λt:ℝ, t • (b - a)) := rfl, rw [segment_eq_image', this, image_comp], refine ((convex_Icc _ _).is_linear_image _).translate _, exact is_linear_map.is_linear_map_smul' _ end lemma convex_halfspace_lt {f : E → ℝ} (h : is_linear_map ℝ f) (r : ℝ) : convex {w | f w < r} := (convex_Iio r).is_linear_preimage h lemma convex_halfspace_le {f : E → ℝ} (h : is_linear_map ℝ f) (r : ℝ) : convex {w | f w ≤ r} := (convex_Iic r).is_linear_preimage h lemma convex_halfspace_gt {f : E → ℝ} (h : is_linear_map ℝ f) (r : ℝ) : convex {w | r < f w} := (convex_Ioi r).is_linear_preimage h lemma convex_halfspace_ge {f : E → ℝ} (h : is_linear_map ℝ f) (r : ℝ) : convex {w | r ≤ f w} := (convex_Ici r).is_linear_preimage h lemma convex_hyperplane {f : E → ℝ} (h : is_linear_map ℝ f) (r : ℝ) : convex {w | f w = r} := begin show convex (f ⁻¹' {p | p = r}), rw set_of_eq_eq_singleton, exact (convex_singleton r).is_linear_preimage h end lemma convex_halfspace_re_lt (r : ℝ) : convex {c : ℂ | c.re < r} := convex_halfspace_lt (is_linear_map.mk complex.add_re complex.smul_re) _ lemma convex_halfspace_re_le (r : ℝ) : convex {c : ℂ | c.re ≤ r} := convex_halfspace_le (is_linear_map.mk complex.add_re complex.smul_re) _ lemma convex_halfspace_re_gt (r : ℝ) : convex {c : ℂ | r < c.re } := convex_halfspace_gt (is_linear_map.mk complex.add_re complex.smul_re) _ lemma convex_halfspace_re_lge (r : ℝ) : convex {c : ℂ | r ≤ c.re} := convex_halfspace_ge (is_linear_map.mk complex.add_re complex.smul_re) _ lemma convex_halfspace_im_lt (r : ℝ) : convex {c : ℂ | c.im < r} := convex_halfspace_lt (is_linear_map.mk complex.add_im complex.smul_im) _ lemma convex_halfspace_im_le (r : ℝ) : convex {c : ℂ | c.im ≤ r} := convex_halfspace_le (is_linear_map.mk complex.add_im complex.smul_im) _ lemma convex_halfspace_im_gt (r : ℝ) : convex {c : ℂ | r < c.im } := convex_halfspace_gt (is_linear_map.mk complex.add_im complex.smul_im) _ lemma convex_halfspace_im_lge (r : ℝ) : convex {c : ℂ | r ≤ c.im} := convex_halfspace_ge (is_linear_map.mk complex.add_im complex.smul_im) _ section submodule open submodule lemma submodule.convex (K : submodule ℝ E) : convex (↑K : set E) := by { repeat {intro}, refine add_mem _ (smul_mem _ _ _) (smul_mem _ _ _); assumption } lemma subspace.convex (K : subspace ℝ E) : convex (↑K : set E) := K.convex end submodule end sets section functions local notation `[`x `, ` y `]` := segment x y /-! ### Convex functions -/ /-- Convexity of functions -/ def convex_on (s : set E) (f : E → ℝ) : Prop := convex s ∧ ∀ ⦃x y : E⦄, x ∈ s → y ∈ s → ∀ ⦃a b : ℝ⦄, 0 ≤ a → 0 ≤ b → a + b = 1 → f (a • x + b • y) ≤ a * f x + b * f y variables {t : set E} {f g : E → ℝ} lemma convex_on_iff_div: convex_on s f ↔ convex s ∧ ∀ ⦃x y : E⦄, x ∈ s → y ∈ s → ∀ ⦃a b : ℝ⦄, 0 ≤ a → 0 ≤ b → 0 < a + b → f ((a/(a+b)) • x + (b/(a+b)) • y) ≤ (a/(a+b)) * f x + (b/(a+b)) * f y := and_congr iff.rfl ⟨begin intros h x y hx hy a b ha hb hab, apply h hx hy (div_nonneg ha hab) (div_nonneg hb hab), rw [←add_div], exact div_self (ne_of_gt hab) end, begin intros h x y hx hy a b ha hb hab, simpa [hab, zero_lt_one] using h hx hy ha hb, end⟩ /-- For a function on a convex set in a linear ordered space, in order to prove that it is convex it suffices to verify the inequality `f (a • x + b • y) ≤ a * f x + b * f y` only for `x < y` and positive `a`, `b`. The main use case is `E = ℝ` however one can apply it, e.g., to `ℝ^n` with lexicographic order. -/ lemma linear_order.convex_on_of_lt [linear_order E] (hs : convex s) (hf : ∀ ⦃x y : E⦄, x ∈ s → y ∈ s → x < y → ∀ ⦃a b : ℝ⦄, 0 < a → 0 < b → a + b = 1 → f (a • x + b • y) ≤ a * f x + b * f y) : convex_on s f := begin use hs, intros x y hx hy a b ha hb hab, wlog hxy : x<=y using [x y a b, y x b a], { exact le_total _ _ }, { cases eq_or_lt_of_le hxy with hxy hxy, by { subst y, rw [← add_smul, ← add_mul, hab, one_smul, one_mul] }, cases eq_or_lt_of_le ha with ha ha, by { subst a, rw [zero_add] at hab, subst b, simp }, cases eq_or_lt_of_le hb with hb hb, by { subst b, rw [add_zero] at hab, subst a, simp }, exact hf hx hy hxy ha hb hab } end /-- For a function `f` defined on a convex subset `D` of `ℝ`, if for any three points `x<y<z` the slope of the secant line of `f` on `[x, y]` is less than or equal to the slope of the secant line of `f` on `[x, z]`, then `f` is convex on `D`. This way of proving convexity of a function is used in the proof of convexity of a function with a monotone derivative. -/ lemma convex_on_real_of_slope_mono_adjacent {s : set ℝ} (hs : convex s) {f : ℝ → ℝ} (hf : ∀ {x y z : ℝ}, x ∈ s → z ∈ s → x < y → y < z → (f y - f x) / (y - x) ≤ (f z - f y) / (z - y)) : convex_on s f := linear_order.convex_on_of_lt hs begin assume x z hx hz hxz a b ha hb hab, let y := a * x + b * z, have hxy : x < y, { rw [← one_mul x, ← hab, add_mul], exact add_lt_add_left ((mul_lt_mul_left hb).2 hxz) _ }, have hyz : y < z, { rw [← one_mul z, ← hab, add_mul], exact add_lt_add_right ((mul_lt_mul_left ha).2 hxz) _ }, have : (f y - f x) * (z - y) ≤ (f z - f y) * (y - x), from (div_le_div_iff (sub_pos.2 hxy) (sub_pos.2 hyz)).1 (hf hx hz hxy hyz), have A : z - y + (y - x) = z - x, by abel, have B : 0 < z - x, from sub_pos.2 (lt_trans hxy hyz), rw [sub_mul, sub_mul, sub_le_iff_le_add', ← add_sub_assoc, le_sub_iff_add_le, ← mul_add, A, ← le_div_iff B, add_div, mul_div_assoc, mul_div_assoc, mul_comm (f x), mul_comm (f z)] at this, rw [eq_comm, ← sub_eq_iff_eq_add] at hab; subst a, convert this; symmetry; simp only [div_eq_iff (ne_of_gt B), y]; ring end lemma convex_on.subset (h_convex_on : convex_on t f) (h_subset : s ⊆ t) (h_convex : convex s) : convex_on s f := begin apply and.intro h_convex, intros x y hx hy, exact h_convex_on.2 (h_subset hx) (h_subset hy), end lemma convex_on.add (hf : convex_on s f) (hg : convex_on s g) : convex_on s (λx, f x + g x) := begin apply and.intro hf.1, intros x y hx hy a b ha hb hab, calc f (a • x + b • y) + g (a • x + b • y) ≤ (a * f x + b * f y) + (a * g x + b * g y) : add_le_add (hf.2 hx hy ha hb hab) (hg.2 hx hy ha hb hab) ... = a * f x + a * g x + b * f y + b * g y : by linarith ... = a * (f x + g x) + b * (f y + g y) : by simp [mul_add] end lemma convex_on.smul {c : ℝ} (hc : 0 ≤ c) (hf : convex_on s f) : convex_on s (λx, c * f x) := begin apply and.intro hf.1, intros x y hx hy a b ha hb hab, calc c * f (a • x + b • y) ≤ c * (a * f x + b * f y) : mul_le_mul_of_nonneg_left (hf.2 hx hy ha hb hab) hc ... = a * (c * f x) + b * (c * f y) : by rw mul_add; ac_refl end lemma convex_on.le_on_segment' {x y : E} {a b : ℝ} (hf : convex_on s f) (hx : x ∈ s) (hy : y ∈ s) (ha : 0 ≤ a) (hb : 0 ≤ b) (hab : a + b = 1) : f (a • x + b • y) ≤ max (f x) (f y) := calc f (a • x + b • y) ≤ a * f x + b * f y : hf.2 hx hy ha hb hab ... ≤ a * max (f x) (f y) + b * max (f x) (f y) : add_le_add (mul_le_mul_of_nonneg_left (le_max_left _ _) ha) (mul_le_mul_of_nonneg_left (le_max_right _ _) hb) ... ≤ max (f x) (f y) : by rw [←add_mul, hab, one_mul] lemma convex_on.le_on_segment (hf : convex_on s f) {x y z : E} (hx : x ∈ s) (hy : y ∈ s) (hz : z ∈ [x, y]) : f z ≤ max (f x) (f y) := let ⟨a, b, ha, hb, hab, hz⟩ := hz in hz ▸ hf.le_on_segment' hx hy ha hb hab lemma convex_on.convex_le (hf : convex_on s f) (r : ℝ) : convex {x ∈ s | f x ≤ r} := convex_iff_segment_subset.2 $ λ x y hx hy z hz, ⟨hf.1.segment_subset hx.1 hy.1 hz, le_trans (hf.le_on_segment hx.1 hy.1 hz) $ max_le hx.2 hy.2⟩ lemma convex_on.convex_lt (hf : convex_on s f) (r : ℝ) : convex {x ∈ s | f x < r} := convex_iff_segment_subset.2 $ λ x y hx hy z hz, ⟨hf.1.segment_subset hx.1 hy.1 hz, lt_of_le_of_lt (hf.le_on_segment hx.1 hy.1 hz) $ max_lt hx.2 hy.2⟩ lemma convex_on.convex_epigraph (hf : convex_on s f) : convex {p : E × ℝ | p.1 ∈ s ∧ f p.1 ≤ p.2} := begin rintros ⟨x, r⟩ ⟨y, t⟩ ⟨hx, hr⟩ ⟨hy, ht⟩ a b ha hb hab, refine ⟨hf.1 hx hy ha hb hab, _⟩, calc f (a • x + b • y) ≤ a * f x + b * f y : hf.2 hx hy ha hb hab ... ≤ a * r + b * t : add_le_add (mul_le_mul_of_nonneg_left hr ha) (mul_le_mul_of_nonneg_left ht hb) end lemma convex_on_iff_convex_epigraph : convex_on s f ↔ convex {p : E × ℝ | p.1 ∈ s ∧ f p.1 ≤ p.2} := begin refine ⟨convex_on.convex_epigraph, λ h, ⟨_, _⟩⟩, { assume x y hx hy a b ha hb hab, exact (@h (x, f x) (y, f y) ⟨hx, le_refl _⟩ ⟨hy, le_refl _⟩ a b ha hb hab).1 }, { assume x y hx hy a b ha hb hab, exact (@h (x, f x) (y, f y) ⟨hx, le_refl _⟩ ⟨hy, le_refl _⟩ a b ha hb hab).2 } end end functions section center_mass /-- Center mass of a finite collection of points with prescribed weights. Note that we require neither `0 ≤ w i` nor `∑ w = 1`. -/ noncomputable def finset.center_mass (t : finset ι) (w : ι → ℝ) (z : ι → E) : E := (t.sum w)⁻¹ • (t.sum (λ i, w i • z i)) variables (i j : ι) (c : ℝ) (t : finset ι) (w : ι → ℝ) (z : ι → E) open finset (hiding singleton) lemma finset.center_mass_empty : (∅ : finset ι).center_mass w z = 0 := by simp only [center_mass, sum_empty, smul_zero] lemma finset.center_mass_pair (hne : i ≠ j) : ({i, j} : finset ι).center_mass w z = (w i / (w i + w j)) • z i + (w j / (w i + w j)) • z j := by simp only [center_mass, sum_pair hne, smul_add, (mul_smul _ _ _).symm, div_eq_inv_mul] variable {w} lemma finset.center_mass_insert (ha : i ∉ t) (hw : t.sum w ≠ 0) : (insert i t).center_mass w z = (w i / (w i + t.sum w)) • z i + (t.sum w / (w i + t.sum w)) • t.center_mass w z := begin simp only [center_mass, sum_insert ha, smul_add, (mul_smul _ _ _).symm], congr' 2, { apply mul_comm }, { rw [div_mul_eq_mul_div, mul_inv_cancel hw, one_div_eq_inv] } end lemma finset.center_mass_singleton (hw : w i ≠ 0) : (finset.singleton i).center_mass w z = z i := by rw [center_mass, sum_singleton, sum_singleton, ← mul_smul, inv_mul_cancel hw, one_smul] lemma finset.center_mass_eq_of_sum_1 (hw : t.sum w = 1) : t.center_mass w z = t.sum (λ i, w i • z i) := by simp only [finset.center_mass, hw, inv_one, one_smul] lemma finset.center_mass_smul : t.center_mass w (λ i, c • z i) = c • t.center_mass w z := by simp only [finset.center_mass, finset.smul_sum, (mul_smul _ _ _).symm, mul_comm c, mul_assoc] /-- A convex combination of two centers of mass is a center of mass as well. This version deals with two different index types. -/ lemma finset.center_mass_segment' (s : finset ι) (t : finset ι') (ws : ι → ℝ) (zs : ι → E) (wt : ι' → ℝ) (zt : ι' → E) (hws : s.sum ws = 1) (hwt : t.sum wt = 1) (a b : ℝ) (hab : a + b = 1): a • s.center_mass ws zs + b • t.center_mass wt zt = (s.image sum.inl ∪ t.image sum.inr).center_mass (sum.elim (λ i, a * ws i) (λ j, b * wt j)) (sum.elim zs zt) := begin rw [s.center_mass_eq_of_sum_1 _ hws, t.center_mass_eq_of_sum_1 _ hwt, smul_sum, smul_sum, ← finset.sum_sum_elim, finset.center_mass_eq_of_sum_1], { congr, ext i, cases i; simp only [sum.elim_inl, sum.elim_inr, mul_smul] }, { rw [sum_sum_elim, ← mul_sum, ← mul_sum, hws, hwt, mul_one, mul_one, hab] } end /-- A convex combination of two centers of mass is a center of mass as well. This version works if two centers of mass share the set of original points. -/ lemma finset.center_mass_segment (s : finset ι) (w₁ w₂ : ι → ℝ) (z : ι → E) (hw₁ : s.sum w₁ = 1) (hw₂ : s.sum w₂ = 1) (a b : ℝ) (hab : a + b = 1): a • s.center_mass w₁ z + b • s.center_mass w₂ z = s.center_mass (λ i, a * w₁ i + b * w₂ i) z := have hw : s.sum (λ i, a * w₁ i + b * w₂ i) = 1, by simp only [mul_sum.symm, sum_add_distrib, mul_one, *], by simp only [finset.center_mass_eq_of_sum_1, smul_sum, sum_add_distrib, add_smul, mul_smul, *] lemma finset.center_mass_ite_eq (hi : i ∈ t) : t.center_mass (λ j, if (i = j) then 1 else 0) z = z i := begin rw [finset.center_mass_eq_of_sum_1], transitivity t.sum (λ j, if (i = j) then z i else 0), { congr, ext i, split_ifs, exacts [h ▸ one_smul _ _, zero_smul _ _] }, { rw [sum_ite_eq, if_pos hi] }, { rw [sum_ite_eq, if_pos hi] } end variables {t w} lemma finset.center_mass_subset {t' : finset ι} (ht : t ⊆ t') (h : ∀ i ∈ t', i ∉ t → w i = 0) : t.center_mass w z = t'.center_mass w z := begin rw [center_mass, sum_subset ht h, smul_sum, center_mass, smul_sum], apply sum_subset ht, assume i hit' hit, rw [h i hit' hit, zero_smul, smul_zero] end lemma finset.center_mass_filter_ne_zero : (t.filter (λ i, w i ≠ 0)).center_mass w z = t.center_mass w z := finset.center_mass_subset z (filter_subset _) $ λ i hit hit', by simpa only [hit, mem_filter, true_and, ne.def, not_not] using hit' variable {z} /-- Center mass of a finite subset of a convex set belongs to the set provided that all weights are non-negative, and the total weight is positive. -/ lemma convex.center_mass_mem (hs : convex s) : (∀ i ∈ t, 0 ≤ w i) → (0 < t.sum w) → (∀ i ∈ t, z i ∈ s) → t.center_mass w z ∈ s := begin refine finset.induction (by simp [lt_irrefl]) (λ i t hi ht h₀ hpos hmem, _) t, have zi : z i ∈ s, from hmem _ (mem_insert_self _ _), have hs₀ : ∀ j ∈ t, 0 ≤ w j, from λ j hj, h₀ j $ mem_insert_of_mem hj, rw [sum_insert hi] at hpos, by_cases hsum_t : t.sum w = 0, { have ws : ∀ j ∈ t, w j = 0, from (sum_eq_zero_iff_of_nonneg hs₀).1 hsum_t, have wz : t.sum (λ j, w j • z j) = 0, from sum_eq_zero (λ i hi, by simp [ws i hi]), simp only [center_mass, sum_insert hi, wz, hsum_t, add_zero], simp only [hsum_t, add_zero] at hpos, rw [← mul_smul, inv_mul_cancel (ne_of_gt hpos), one_smul], exact zi }, { rw [finset.center_mass_insert _ _ _ hi hsum_t], refine convex_iff_div.1 hs zi (ht hs₀ _ _) _ (sum_nonneg hs₀) hpos, { exact lt_of_le_of_ne (sum_nonneg hs₀) (ne.symm hsum_t) }, { intros j hj, exact hmem j (mem_insert_of_mem hj) }, { exact h₀ _ (mem_insert_self _ _) } } end lemma convex.sum_mem (hs : convex s) (h₀ : ∀ i ∈ t, 0 ≤ w i) (h₁ : t.sum w = 1) (hz : ∀ i ∈ t, z i ∈ s) : t.sum (λ i, w i • z i) ∈ s := by simpa only [h₁, center_mass, inv_one, one_smul] using hs.center_mass_mem h₀ (h₁.symm ▸ zero_lt_one) hz lemma convex_iff_sum_mem : convex s ↔ (∀ (t : finset E) (w : E → ℝ), (∀ i ∈ t, 0 ≤ w i) → t.sum w = 1 → (∀ x ∈ t, x ∈ s) → t.sum (λx, w x • x) ∈ s ) := begin refine ⟨λ hs t w hw₀ hw₁ hts, hs.sum_mem hw₀ hw₁ hts, _⟩, intros h x y hx hy a b ha hb hab, by_cases h_cases: x = y, { rw [h_cases, ←add_smul, hab, one_smul], exact hy }, { convert h {x, y} (λ z, if z = y then b else a) _ _ _, { simp only [sum_pair h_cases, if_neg h_cases, if_pos rfl] }, { simp_intros i hi, cases hi; subst i; simp [ha, hb, if_neg h_cases] }, { simp only [sum_pair h_cases, if_neg h_cases, if_pos rfl, hab] }, { simp_intros i hi, cases hi; subst i; simp [hx, hy, if_neg h_cases] } } end /-- Jensen's inequality, `finset.center_mass` version. -/ lemma convex_on.map_center_mass_le {f : E → ℝ} (hf : convex_on s f) (h₀ : ∀ i ∈ t, 0 ≤ w i) (hpos : 0 < t.sum w) (hmem : ∀ i ∈ t, z i ∈ s) : f (t.center_mass w z) ≤ t.center_mass w (f ∘ z) := begin have hmem' : ∀ i ∈ t, (z i, (f ∘ z) i) ∈ {p : E × ℝ | p.1 ∈ s ∧ f p.1 ≤ p.2}, from λ i hi, ⟨hmem i hi, le_refl _⟩, convert (hf.convex_epigraph.center_mass_mem h₀ hpos hmem').2; simp only [center_mass, function.comp, prod.smul_fst, prod.fst_sum, prod.smul_snd, prod.snd_sum] end /-- Jensen's inequality, `finset.sum` version. -/ lemma convex_on.map_sum_le {f : E → ℝ} (hf : convex_on s f) (h₀ : ∀ i ∈ t, 0 ≤ w i) (h₁ : t.sum w = 1) (hmem : ∀ i ∈ t, z i ∈ s) : f (t.sum (λ i, w i • z i)) ≤ t.sum (λ i, w i * (f (z i))) := by simpa only [center_mass, h₁, inv_one, one_smul] using hf.map_center_mass_le h₀ (h₁.symm ▸ zero_lt_one) hmem /-- If a function `f` is convex on `s` takes value `y` at the center mass of some points `z i ∈ s`, then for some `i` we have `y ≤ f (z i)`. -/ lemma convex_on.exists_ge_of_center_mass {f : E → ℝ} (h : convex_on s f) (hw₀ : ∀ i ∈ t, 0 ≤ w i) (hws : 0 < t.sum w) (hz : ∀ i ∈ t, z i ∈ s) : ∃ i ∈ t, f (t.center_mass w z) ≤ f (z i) := begin set y := t.center_mass w z, have : f y ≤ t.center_mass w (f ∘ z) := h.map_center_mass_le hw₀ hws hz, rw ← sum_filter_ne_zero at hws, rw [← finset.center_mass_filter_ne_zero (f ∘ z), center_mass, smul_eq_mul, ← div_eq_inv_mul, le_div_iff hws, mul_sum] at this, replace : ∃ i ∈ t.filter (λ i, w i ≠ 0), f y * w i ≤ w i • (f ∘ z) i := exists_le_of_sum_le (nonempty_of_sum_ne_zero (ne_of_gt hws)) this, rcases this with ⟨i, hi, H⟩, rw [mem_filter] at hi, use [i, hi.1], simp only [smul_eq_mul, mul_comm (w i)] at H, refine (mul_le_mul_right _).1 H, exact lt_of_le_of_ne (hw₀ i hi.1) hi.2.symm end end center_mass section convex_hull variable {t : set E} /-- Convex hull of a set `s` is the minimal convex set that includes `s` -/ def convex_hull (s : set E) : set E := ⋂ (t : set E) (hst : s ⊆ t) (ht : convex t), t variable (s) lemma subset_convex_hull : s ⊆ convex_hull s := set.subset_Inter $ λ t, set.subset_Inter $ λ hst, set.subset_Inter $ λ ht, hst lemma convex_convex_hull : convex (convex_hull s) := convex_Inter $ λ t, convex_Inter $ λ ht, convex_Inter id variable {s} lemma convex_hull_min (hst : s ⊆ t) (ht : convex t) : convex_hull s ⊆ t := set.Inter_subset_of_subset t $ set.Inter_subset_of_subset hst $ set.Inter_subset _ ht lemma convex_hull_mono (hst : s ⊆ t) : convex_hull s ⊆ convex_hull t := convex_hull_min (set.subset.trans hst $ subset_convex_hull t) (convex_convex_hull t) lemma convex.convex_hull_eq {s : set E} (hs : convex s) : convex_hull s = s := set.subset.antisymm (convex_hull_min (set.subset.refl _) hs) (subset_convex_hull s) lemma is_linear_map.image_convex_hull {f : E → F} (hf : is_linear_map ℝ f) : f '' (convex_hull s) = convex_hull (f '' s) := begin refine set.subset.antisymm _ _, { rw [set.image_subset_iff], exact convex_hull_min (set.image_subset_iff.1 $ subset_convex_hull $ f '' s) ((convex_convex_hull (f '' s)).is_linear_preimage hf) }, { exact convex_hull_min (set.image_subset _ $ subset_convex_hull s) ((convex_convex_hull s).is_linear_image hf) } end lemma linear_map.image_convex_hull (f : E →ₗ[ℝ] F) : f '' (convex_hull s) = convex_hull (f '' s) := f.is_linear.image_convex_hull lemma finset.center_mass_mem_convex_hull (t : finset ι) {w : ι → ℝ} (hw₀ : ∀ i ∈ t, 0 ≤ w i) (hws : 0 < t.sum w) {z : ι → E} (hz : ∀ i ∈ t, z i ∈ s) : t.center_mass w z ∈ convex_hull s := (convex_convex_hull s).center_mass_mem hw₀ hws (λ i hi, subset_convex_hull s $ hz i hi) -- TODO : Do we need other versions of the next lemma? /-- Convex hull of `s` is equal to the set of all centers of masses of `finset`s `t`, `z '' t ⊆ s`. This version allows finsets in any type in any universe. -/ lemma convex_hull_eq (s : set E) : convex_hull s = {x : E | ∃ (ι : Type u') (t : finset ι) (w : ι → ℝ) (z : ι → E) (hw₀ : ∀ i ∈ t, 0 ≤ w i) (hw₁ : t.sum w = 1) (hz : ∀ i ∈ t, z i ∈ s) , t.center_mass w z = x} := begin refine subset.antisymm (convex_hull_min _ _) _, { intros x hx, use [punit, finset.singleton punit.star, λ _, 1, λ _, x, λ _ _, zero_le_one, finset.sum_singleton, λ _ _, hx], simp only [finset.center_mass, finset.sum_singleton, inv_one, one_smul] }, { rintros x y ⟨ι, sx, wx, zx, hwx₀, hwx₁, hzx, rfl⟩ ⟨ι', sy, wy, zy, hwy₀, hwy₁, hzy, rfl⟩ a b ha hb hab, rw [finset.center_mass_segment' _ _ _ _ _ _ hwx₁ hwy₁ _ _ hab], refine ⟨_, _, _, _, _, _, _, rfl⟩, { rintros i hi, rw [finset.mem_union, finset.mem_image, finset.mem_image] at hi, rcases hi with ⟨j, hj, rfl⟩|⟨j, hj, rfl⟩; simp only [sum.elim_inl, sum.elim_inr]; apply_rules [mul_nonneg, hwx₀, hwy₀] }, { simp [finset.sum_sum_elim, finset.mul_sum.symm, *] }, { intros i hi, rw [finset.mem_union, finset.mem_image, finset.mem_image] at hi, rcases hi with ⟨j, hj, rfl⟩|⟨j, hj, rfl⟩; simp only [sum.elim_inl, sum.elim_inr]; apply_rules [hzx, hzy] } }, { rintros _ ⟨ι, t, w, z, hw₀, hw₁, hz, rfl⟩, exact t.center_mass_mem_convex_hull hw₀ (hw₁.symm ▸ zero_lt_one) hz } end /-- Maximum principle for convex functions. If a function `f` is convex on the convex hull of `s`, then `f` can't have a maximum on `convex_hull s` outside of `s`. -/ lemma convex_on.exists_ge_of_mem_convex_hull {f : E → ℝ} (hf : convex_on (convex_hull s) f) {x} (hx : x ∈ convex_hull s) : ∃ y ∈ s, f x ≤ f y := begin rw convex_hull_eq at hx, rcases hx with ⟨α, t, w, z, hw₀, hw₁, hz, rfl⟩, rcases hf.exists_ge_of_center_mass hw₀ (hw₁.symm ▸ zero_lt_one) (λ i hi, subset_convex_hull s (hz i hi)) with ⟨i, hit, Hi⟩, exact ⟨z i, hz i hit, Hi⟩ end lemma set.finite.convex_hull_eq {s : set E} (hs : finite s) : convex_hull s = {x : E | ∃ (w : E → ℝ) (hw₀ : ∀ y ∈ s, 0 ≤ w y) (hw₁ : hs.to_finset.sum w = 1), hs.to_finset.center_mass w id = x} := begin refine subset.antisymm (convex_hull_min _ _) _, { intros x hx, replace hx : x ∈ hs.to_finset, from finite.mem_to_finset.2 hx, refine ⟨_, _, _, finset.center_mass_ite_eq _ _ _ hx⟩, { intros, split_ifs, exacts [zero_le_one, le_refl 0] }, { rw [finset.sum_ite_eq, if_pos hx] } }, { rintros x y ⟨wx, hwx₀, hwx₁, rfl⟩ ⟨wy, hwy₀, hwy₁, rfl⟩ a b ha hb hab, rw [finset.center_mass_segment _ _ _ _ hwx₁ hwy₁ _ _ hab], refine ⟨_, _, _, rfl⟩, { rintros i hi, apply_rules [add_nonneg, mul_nonneg, hwx₀, hwy₀], }, { simp only [finset.sum_add_distrib, finset.mul_sum.symm, mul_one, *] } }, { rintros _ ⟨w, hw₀, hw₁, rfl⟩, exact hs.to_finset.center_mass_mem_convex_hull (λ x hx, hw₀ _ $ finite.mem_to_finset.1 hx) (hw₁.symm ▸ zero_lt_one) (λ x hx, finite.mem_to_finset.1 hx) } end lemma is_linear_map.convex_hull_image {f : E → F} (hf : is_linear_map ℝ f) (s : set E) : convex_hull (f '' s) = f '' convex_hull s := set.subset.antisymm (convex_hull_min (image_subset _ (subset_convex_hull s)) $ (convex_convex_hull s).is_linear_image hf) (image_subset_iff.2 $ convex_hull_min (image_subset_iff.1 $ subset_convex_hull _) ((convex_convex_hull _).is_linear_preimage hf)) lemma linear_map.convex_hull_image (f : E →ₗ[ℝ] F) (s : set E) : convex_hull (f '' s) = f '' convex_hull s := f.is_linear.convex_hull_image s end convex_hull /-! ### Simplex -/ section simplex variables (ι) [fintype ι] {f : ι → ℝ} /-- Standard simplex in the space of functions `ι → ℝ` is the set of vectors with non-negative coordinates with total sum `1`. -/ def std_simplex (ι : Type*) [fintype ι] : set (ι → ℝ) := { f | (∀ x, 0 ≤ f x) ∧ finset.univ.sum f = 1 } lemma std_simplex_eq_inter : std_simplex ι = (⋂ x, {f | 0 ≤ f x}) ∩ {f | finset.univ.sum f = 1} := by { ext f, simp only [std_simplex, set.mem_inter_eq, set.mem_Inter, set.mem_set_of_eq] } lemma convex_std_simplex : convex (std_simplex ι) := begin refine λ f g hf hg a b ha hb hab, ⟨λ x, _, _⟩, { apply_rules [add_nonneg, mul_nonneg, hf.1, hg.1] }, { erw [finset.sum_add_distrib, ← finset.smul_sum, ← finset.smul_sum, hf.2, hg.2, smul_eq_mul, smul_eq_mul, mul_one, mul_one], exact hab } end variable {ι} lemma ite_eq_mem_std_simplex (i : ι) : (λ j, ite (i = j) (1:ℝ) 0) ∈ std_simplex ι := ⟨λ j, by simp only []; split_ifs; norm_num, by rw [finset.sum_ite_eq, if_pos (finset.mem_univ _)] ⟩ /-- `std_simplex ι` is the convex hull of the canonical basis in `ι → ℝ`. -/ lemma convex_hull_basis_eq_std_simplex : convex_hull (range $ λ(i j:ι), if i = j then (1:ℝ) else 0) = std_simplex ι := begin refine subset.antisymm (convex_hull_min _ (convex_std_simplex ι)) _, { rintros _ ⟨i, rfl⟩, exact ite_eq_mem_std_simplex i }, { rintros w ⟨hw₀, hw₁⟩, rw [pi_eq_sum_univ w, ← finset.univ.center_mass_eq_of_sum_1 _ hw₁], exact finset.univ.center_mass_mem_convex_hull (λ i hi, hw₀ i) (hw₁.symm ▸ zero_lt_one) (λ i hi, mem_range_self i) } end variable {ι} /-- Convex hull of a finite set is the image of the standard simplex in `s → ℝ` under the linear map sending each function `w` to `s.sum (λ x, w x • x)`. Since we have no sums over finite sets, we use sum over `@finset.univ _ hs.fintype`. The map is defined in terms of operations on `(s → ℝ) →ₗ[ℝ] ℝ` so that later we will not need to prove that this map is linear. -/ lemma set.finite.convex_hull_eq_image {s : set E} (hs : finite s) : convex_hull s = (⇑((@finset.univ _ hs.fintype).sum (λ x, (linear_map.proj x : (s → ℝ) →ₗ[ℝ] ℝ).smul_right x.1))) '' (@std_simplex _ hs.fintype) := begin rw [← convex_hull_basis_eq_std_simplex, ← linear_map.convex_hull_image, ← range_comp, (∘)], apply congr_arg, convert (subtype.range_val s).symm, ext x, simp [linear_map.sum_apply, ite_smul, finset.sum_ite _ _ (λ x, x), finset.filter_eq] end /-- All values of a function `f ∈ std_simplex ι` belong to `[0, 1]`. -/ lemma mem_Icc_of_mem_std_simplex (hf : f ∈ std_simplex ι) (x) : f x ∈ I := ⟨hf.1 x, hf.2 ▸ finset.single_le_sum (λ y hy, hf.1 y) (finset.mem_univ x)⟩ end simplex