Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  Convex.thy

  Sprache: Isabelle
 

(* Title:      HOL/Analysis/Convex.thy
  Author: L C Paulson, University of Cambridge
  Author: Robert Himmelmann, TU Muenchen
  Author: Bogdan Grechuk, University of Edinburgh
  Author: Armin Heller, TU Muenchen
  Author: Johannes Hoelzl, TU Muenchen
*)

section Convex Sets and Functions

theory Convex
imports
  Affine  "HOL-Library.Set_Algebras"  "HOL-Library.FuncSet"
begin

subsection Convex Sets

definition🍋tag important convex :: "'a::real_vector set ==> bool"
  where "convex s (xs. ys. u0. v0. u + v = 1 u *🪙R x + v *🪙R y s)"

lemma convexI:
  assumes "x y u v. x s ==> y s ==> 0 u ==> 0 v ==> u + v = 1 ==> u *🪙R x + v *🪙R y s"
  shows "convex s"
  by (simp add: assms convex_def)

lemma convexD:
  assumes "convex s" and "x s" and "y s" and "0 u" and "0 v" and "u + v = 1"
  shows "u *🪙R x + v *🪙R y s"
  using assms unfolding convex_def by fast

lemma convex_alt: "convex s (xs. ys. u. 0 u u 1 ((1 - u) *🪙R x + u *🪙R y) s)"
  (is "_ ?alt")
  by (metis convex_def diff_eq_eq diff_ge_0_iff_ge)

lemma convexD_alt:
  assumes "convex s" "a s" "b s" "0 u" "u 1"
  shows "((1 - u) *🪙R a + u *🪙R b) s"
  using assms unfolding convex_alt by auto

lemma mem_convex_alt:
  assumes "convex S" "x S" "y S" "u 0" "v 0" "u + v > 0"
  shows "((u/(u+v)) *🪙R x + (v/(u+v)) *🪙R y) S"
  using assms
  by (simp add: convex_def zero_le_divide_iff add_divide_distrib [symmetric])

lemma convex_empty[intro,simp]: "convex {}"
  unfolding convex_def by simp

lemma convex_singleton[intro,simp]: "convex {a}"
  unfolding convex_def by (auto simp: scaleR_left_distrib[symmetric])

lemma convex_UNIV[intro,simp]: "convex UNIV"
  unfolding convex_def by auto

lemma convex_Inter: "(s. sf ==> convex s) ==> convex(f)"
  unfolding convex_def by auto

lemma convex_Int: "convex s ==> convex t ==> convex (s t)"
  unfolding convex_def by auto

lemma convex_INT: "(i. i A ==> convex (B i)) ==> convex (iA. B i)"
  unfolding convex_def by auto

lemma convex_Times: "convex s ==> convex t ==> convex (s × t)"
  unfolding convex_def by auto

lemma convex_halfspace_le: "convex {x. inner a x b}"
  unfolding convex_def
  by (auto simp: inner_add intro!: convex_bound_le)

lemma convex_halfspace_ge: "convex {x. inner a x b}"
proof -
  have *: "{x. inner a x b} = {x. inner (-a) x -b}"
    by auto
  show ?thesis
    unfolding * using convex_halfspace_le[of "-a" "-b"by auto
qed

lemma convex_halfspace_abs_le: "convex {x. inner a x b}"
proof -
  have *: "{x. inner a x b} = {x. inner a x b} {x. -b inner a x}"
    by auto
  show ?thesis
    unfolding * by (simp add: convex_Int convex_halfspace_ge convex_halfspace_le)
qed

lemma convex_hyperplane: "convex {x. inner a x = b}"
proof -
  have *: "{x. inner a x = b} = {x. inner a x b} {x. inner a x b}"
    by auto
  show ?thesis using convex_halfspace_le convex_halfspace_ge
    by (auto intro!: convex_Int simp: *)
qed

lemma convex_halfspace_lt: "convex {x. inner a x < b}"
  unfolding convex_def
  by (auto simp: convex_bound_lt inner_add)

lemma convex_halfspace_gt: "convex {x. inner a x > b}"
  using convex_halfspace_lt[of "-a" "-b"by auto

lemma convex_halfspace_Re_ge: "convex {x. Re x b}"
  using convex_halfspace_ge[of b "1::complex"by simp

lemma convex_halfspace_Re_le: "convex {x. Re x b}"
  using convex_halfspace_le[of "1::complex" b] by simp

lemma convex_halfspace_Im_ge: "convex {x. Im x b}"
  using convex_halfspace_ge[of b iby simp

lemma convex_halfspace_Im_le: "convex {x. Im x b}"
  using convex_halfspace_le[of i b] by simp

lemma convex_halfspace_Re_gt: "convex {x. Re x > b}"
  using convex_halfspace_gt[of b "1::complex"by simp

lemma convex_halfspace_Re_lt: "convex {x. Re x < b}"
  using convex_halfspace_lt[of "1::complex" b] by simp

lemma convex_halfspace_Im_gt: "convex {x. Im x > b}"
  using convex_halfspace_gt[of b iby simp

lemma convex_halfspace_Im_lt: "convex {x. Im x < b}"
  using convex_halfspace_lt[of i b] by simp

lemma convex_real_interval [iff]:
  fixes a b :: "real"
  shows "convex {a..}" and "convex {..b}"
    and "convex {a<..}" and "convex {..
    and "convex {a..b}" and "convex {a<..b}"
    and "convex {a.. and "convex {a<..
proof -
  have "{a..} = {x. a inner 1 x}"
    by auto
  then show 1: "convex {a..}"
    by (simp only: convex_halfspace_ge)
  have "{..b} = {x. inner 1 x b}"
    by auto
  then show 2: "convex {..b}"
    by (simp only: convex_halfspace_le)
  have "{a<..} = {x. a < inner 1 x}"
    by auto
  then show 3: "convex {a<..}"
    by (simp only: convex_halfspace_gt)
  have "{..
    by auto
  then show 4: "convex {..
    by (simp only: convex_halfspace_lt)
  have "{a..b} = {a..} {..b}"
    by auto
  then show "convex {a..b}"
    by (simp only: convex_Int 1 2)
  have "{a<..b} = {a<..} {..b}"
    by auto
  then show "convex {a<..b}"
    by (simp only: convex_Int 3 2)
  have "{a.. {..
    by auto
  then show "convex {a..
    by (simp only: convex_Int 1 4)
  have "{a<.. {..
    by auto
  then show "convex {a<..
    by (simp only: convex_Int 3 4)
qed

lemma convex_Reals: "convex "
  by (simp add: convex_def scaleR_conv_of_real)


subsection🍋tag unimportant Explicit expressions for convexity in terms of arbitrary sums

lemma convex_sum:
  fixes C :: "'a::real_vector set"
  assumes "finite S"
    and "convex C"
    and a: "( i S. a i) = 1" "i. i S ==> a i 0"
    and C: "i. i S ==> y i C"
  shows "( j S. a j *🪙R y j) C"
  using finite S a C
proof (induction arbitrary: a set: finite)
  case empty
  then show ?case by simp
next
  case (insert i S) 
  then have "0 sum a S"
    by (simp add: sum_nonneg)
  have "a i *🪙R y i + (jS. a j *🪙R y j) C"
  proof (cases "sum a S = 0")
    case True with insert show ?thesis
      by (simp add: sum_nonneg_eq_0_iff)
  next
    case False
    with 0 sum a S have "0 < sum a S"
      by simp
    then have "(jS. (a j / sum a S) *🪙R y j) C"
      using insert
      by (simp add: insert.IH flip: sum_divide_distrib)
    with convex C insert 0 sum a S
    have "a i *🪙R y i + sum a S *🪙R (jS. (a j / sum a S) *🪙R y j) C"
      by (simp add: convex_def)
    then show ?thesis
      by (simp add: scaleR_sum_right False)
  qed
  then show ?case using finite S and i S
    by simp
qed

lemma convex:
  "convex S

    ((k::nat) u x. (i. 1i ik 0 u i x i S) (sum u {1..k} = 1)

       sum (λi. u i *🪙R x i) {1..k} S)"  
  (is "?lhs = ?rhs")
proof
  show "?lhs ==> ?rhs"
    by (metis (full_types) atLeastAtMost_iff convex_sum finite_atLeastAtMost)
  assume *: "k u x. ( i :: nat. 1 i i k 0 u i x i S) sum u {1..k} = 1

     (i = 1..k. u i *🪙R (x i :: 'a)) S"
  {
    fix μ :: real
    fix x y :: 'a
    assume xy: "x S" "y S"
    assume mu:  0"  1"
    let ?u = "λi. if (i :: nat) = 1 then μ else 1 - μ"
    let ?x = "λi. if (i :: nat) = 1 then x else y"
    have "{1 :: nat .. 2} - {x. x = 1} = {2}"
      by auto
    then have S: "(j {1..2}. ?u j *🪙R ?x j) S"
      using sum.If_cases[of "{(1 :: nat) .. 2}" "λx. x = 1" "λx. μ" "λx. 1 - μ"]
      using mu xy "*" by auto
    have grarr: "(j {Suc (Suc 0)..2}. ?u j *🪙R ?x j) = (1 - μ) *🪙R y"
      using sum.atLeast_Suc_atMost[of "Suc (Suc 0)" 2 "λ j. (1 - μ) *🪙R y"by auto
    with sum.atLeast_Suc_atMost
    have "(j {1..2}. ?u j *🪙R ?x j) = μ *🪙R x + (1 - μ) *🪙R y"
      by (smt (verit, best) Suc_1 Suc_eq_plus1 add_0 le_add1)
    then have "(1 - μ) *🪙R y + μ *🪙R x S"
      using S by (auto simp: add.commute)
  }
  then show "convex S"
    unfolding convex_alt by auto
qed


lemma convex_explicit:
  fixes S :: "'a::real_vector set"
  shows "convex S

    (t u. finite t t S (xt. 0 u x) sum u t = 1 sum (λx. u x *🪙R x) t S)"
proof safe
  fix t
  fix u :: "'a ==> real"
  assume "convex S"
    and "finite t"
    and "t S" "xt. 0 u x" "sum u t = 1"
  then show "(xt. u x *🪙R x) S"
    by (simp add: convex_sum subsetD)
next
  assume *: "t. u. finite t t S (xt. 0 u x)

    sum u t = 1 (xt. u x *🪙R x) S"
  show "convex S"
    unfolding convex_alt
  proof safe
    fix x y
    fix μ :: real
    assume **: "x S" "y S" "0 μ"  1"
    show "(1 - μ) *🪙R x + μ *🪙R y S"
    proof (cases "x = y")
      case False
      then show ?thesis
        using *[rule_format, of "{x, y}" "λ z. if z = x then 1 - μ else μ"] **
        by auto
    next
      case True
      then show ?thesis
        by (simp add: "**")
    qed
  qed
qed

lemma convex_finite:
  assumes "finite S"
  shows "convex S (u. (xS. 0 u x) sum u S = 1 sum (λx. u x *🪙R x) S S)"
       (is "?lhs = ?rhs")
proof 
  { have if_distrib_arg: "P f g x. (if P then f else g) x = (if P then f x else g x)"
      by simp
    fix T :: "'a set" and u :: "'a ==> real"
    assume sum: "u. (xS. 0 u x) sum u S = 1 (xS. u x *🪙R x) S"
    assume *: "xT. 0 u x" "sum u T = 1"
    assume "T S"
    then have "S T = T" by auto
    with sum[THEN spec[where x="λx. if xT then u x else 0"]] *
    have "(xT. u x *🪙R x) S"
      by (auto simp: assms sum.If_cases if_distrib if_distrib_arg) }
  moreover assume ?rhs
  ultimately show ?lhs
    unfolding convex_explicit by auto
qed (auto simp: convex_explicit assms)

subsection Convex Functions on a Set

definition🍋tag important convex_on :: "'a::real_vector set ==> ('a ==> real) ==> bool"
  where "convex_on S f convex S

    (xS. yS. u0. v0. u + v = 1 f (u *🪙R x + v *🪙R y) u * f x + v * f y)"

definition🍋tag important concave_on :: "'a::real_vector set ==> ('a ==> real) ==> bool"
  where "concave_on S f convex_on S (λx. - f x)"

lemma convex_on_iff_concave: "convex_on S f = concave_on S (λx. - f x)"
  by (simp add: concave_on_def)

lemma concave_on_iff:
  "concave_on S f convex S

    (xS. yS. u0. v0. u + v = 1 f (u *🪙R x + v *🪙R y) u * f x + v * f y)"
  by (auto simp: concave_on_def convex_on_def algebra_simps)

lemma concave_onD:
  assumes "concave_on A f"
  shows "t x y. t 0 ==> t 1 ==> x A ==> y A ==>
    f ((1 - t) *🪙R x + t *🪙R y) (1 - t) * f x + t * f y"
  using assms by (auto simp: concave_on_iff)

lemma convex_onI [intro?]:
  assumes "t x y. t > 0 ==> t < 1 ==> x A ==> y A ==>
    f ((1 - t) *🪙R x + t *🪙R y) (1 - t) * f x + t * f y"
    and "convex A"
  shows "convex_on A f"
  unfolding convex_on_def
  by (smt (verit, del_insts) assms mult_cancel_right1 mult_eq_0_iff scaleR_collapse scaleR_eq_0_iff)

lemma convex_onD:
  assumes "convex_on A f"
  shows "t x y. t 0 ==> t 1 ==> x A ==> y A ==>
    f ((1 - t) *🪙R x + t *🪙R y) (1 - t) * f x + t * f y"
  using assms by (auto simp: convex_on_def)

lemma convex_on_linorderI [intro?]:
  fixes A :: "('a::{linorder,real_vector}) set"
  assumes "t x y. t > 0 ==> t < 1 ==> x A ==> y A ==> x < y ==>
    f ((1 - t) *🪙R x + t *🪙R y) (1 - t) * f x + t * f y"
    and "convex A"
  shows "convex_on A f"
  by (smt (verit, best) add.commute assms convex_onI distrib_left linorder_cases mult.commute mult_cancel_left2 scaleR_collapse)

lemma concave_on_linorderI [intro?]:
  fixes A :: "('a::{linorder,real_vector}) set"
  assumes "t x y. t > 0 ==> t < 1 ==> x A ==> y A ==> x < y ==>
    f ((1 - t) *🪙R x + t *🪙R y) (1 - t) * f x + t * f y"
    and "convex A"
  shows "concave_on A f"
  by (smt (verit) assms concave_on_def convex_on_linorderI mult_minus_right)

lemma convex_on_imp_convex: "convex_on A f ==> convex A"
  by (auto simp: convex_on_def)

lemma concave_on_imp_convex: "concave_on A f ==> convex A"
  by (simp add: concave_on_def convex_on_imp_convex)

lemma convex_onD_Icc:
  assumes "convex_on {x..y} f" "x (y :: _ :: {real_vector,preorder})"
  shows "t. t 0 ==> t 1 ==>
    f ((1 - t) *🪙R x + t *🪙R y) (1 - t) * f x + t * f y"
  using assms(2) by (intro convex_onD [OF assms(1)]) simp_all

lemma convex_on_subset: "[convex_on T f; S T; convex S] ==> convex_on S f"
  by (simp add: convex_on_def subset_iff)

lemma convex_on_add [intro]:
  assumes "convex_on S f"
    and "convex_on S g"
  shows "convex_on S (λx. f x + g x)"
proof -
  {
    fix x y
    assume "x S" "y S"
    moreover
    fix u v :: real
    assume "0 u" "0 v" "u + v = 1"
    ultimately
    have "f (u *🪙R x + v *🪙R y) + g (u *🪙R x + v *🪙R y) (u * f x + v * f y) + (u * g x + v * g y)"
      using assms unfolding convex_on_def by (auto simp: add_mono)
    then have "f (u *🪙R x + v *🪙R y) + g (u *🪙R x + v *🪙R y) u * (f x + g x) + v * (f y + g y)"
      by (simp add: field_simps)
  }
  with assms show ?thesis
    unfolding convex_on_def by auto
qed

lemma convex_on_ident: "convex_on S (λx. x) convex S"
  by (simp add: convex_on_def)

lemma concave_on_ident: "concave_on S (λx. x) convex S"
  by (simp add: concave_on_iff)

lemma convex_on_const: "convex_on S (λx. a) convex S"
  by (simp add: convex_on_def flip: distrib_right)

lemma concave_on_const: "concave_on S (λx. a) convex S"
  by (simp add: concave_on_iff flip: distrib_right)

lemma convex_on_diff:
  assumes "convex_on S f" and "concave_on S g"
  shows "convex_on S (λx. f x - g x)"
  using assms concave_on_def convex_on_add by fastforce

lemma concave_on_diff:
  assumes "concave_on S f"
    and "convex_on S g"
  shows "concave_on S (λx. f x - g x)"
  using convex_on_diff assms concave_on_def by fastforce

lemma concave_on_add:
  assumes "concave_on S f"
    and "concave_on S g"
  shows "concave_on S (λx. f x + g x)"
  using assms convex_on_iff_concave concave_on_diff concave_on_def by fastforce

lemma convex_on_mul:
  fixes S::"real set"
  assumes "convex_on S f" "convex_on S g"
  assumes "mono_on S f" "mono_on S g"
  assumes fty: "f S {0..}" and gty: "g S {0..}"
  shows "convex_on S (λx. f x*g x)"
proof (intro convex_on_linorderI)
  show "convex S"
    using assms convex_on_imp_convex by auto
  fix t::real and x y
  assume t: "0 < t" "t < 1" and xy: "x S" "y S" "x
  have *: "t*(1-t) * f x * g y + t*(1-t) * f y * g x t*(1-t) * f x * g x + t*(1-t) * f y * g y"
    using t mono_on S f mono_on S g xy
    by (smt (verit, ccfv_SIG) left_diff_distrib mono_onD mult_left_less_imp_less zero_le_mult_iff)
  have inS: "(1-t)*x + t*y S"
    using t xy convex S by (simp add: convex_alt)
  then have "f ((1-t)*x + t*y) * g ((1-t)*x + t*y) ((1-t) * f x + t * f y)*g ((1-t)*x + t*y)"
    using convex_onD [OF convex_on S f, of t x y] t xy fty gty
    by (intro mult_mono add_nonneg_nonneg) (auto simp: Pi_iff zero_le_mult_iff)
  also have " ((1-t) * f x + t * f y) * ((1-t)*g x + t*g y)"
    using convex_onD [OF convex_on S g, of t x y] t xy fty gty inS
    by (intro mult_mono add_nonneg_nonneg) (auto simp: Pi_iff zero_le_mult_iff)
  also have " (1-t) * (f x*g x) + t * (f y*g y)"
    using * by (simp add: algebra_simps)
  finally show "f ((1-t) *🪙R x + t *🪙R y) * g ((1-t) *🪙R x + t *🪙R y) (1-t)*(f x*g x) + t*(f y*g y)" 
    by simp
qed

lemma convex_on_cmul [intro]:
  fixes c :: real
  assumes "0 c"
    and "convex_on S f"
  shows "convex_on S (λx. c * f x)"
proof -
  have *: "u * (c * fx) + v * (c * fy) = c * (u * fx + v * fy)"
    for u c fx v fy :: real
    by (simp add: field_simps)
  show ?thesis using assms(2) and mult_left_mono [OF _ assms(1)]
    unfolding convex_on_def and * by auto
qed

lemma convex_on_cdiv [intro]:
  fixes c :: real
  assumes "0 c" and "convex_on S f"
  shows "convex_on S (λx. f x / c)"
  unfolding divide_inverse
  using convex_on_cmul [of "inverse c" S f] by (simp add: mult.commute assms)

lemma convex_lower:
  assumes "convex_on S f"
    and "x S"
    and "y S"
    and "0 u"
    and "0 v"
    and "u + v = 1"
  shows "f (u *🪙R x + v *🪙R y) max (f x) (f y)"
proof -
  let ?m = "max (f x) (f y)"
  have "u * f x + v * f y u * max (f x) (f y) + v * max (f x) (f y)"
    using assms(4,5) by (auto simp: mult_left_mono add_mono)
  also have " = max (f x) (f y)"
    using assms(6) by (simp add: distrib_right [symmetric])
  finally show ?thesis
    using assms unfolding convex_on_def by fastforce
qed

lemma convex_on_dist [intro]:
  fixes S :: "'a::real_normed_vector set"
  assumes "convex S"
  shows "convex_on S (λx. dist a x)"
unfolding convex_on_def dist_norm
proof (intro conjI strip)
  fix x y
  assume "x S" "y S"
  fix u v :: real
  assume "0 u"
  assume "0 v"
  assume "u + v = 1"
  have "a = u *🪙R a + v *🪙R a"
    by (metis u + v = 1 scaleR_left.add scaleR_one)
  then have "a - (u *🪙R x + v *🪙R y) = (u *🪙R (a - x)) + (v *🪙R (a - y))"
    by (auto simp: algebra_simps)
  then show "norm (a - (u *🪙R x + v *🪙R y)) u * norm (a - x) + v * norm (a - y)"
    by (smt (verit, best) 0 u 0 v norm_scaleR norm_triangle_ineq)
qed (use assms in auto)

lemma concave_on_mul:
  fixes S::"real set"
  assumes f: "concave_on S f" and g: "concave_on S g"
  assumes "mono_on S f" "antimono_on S g"
  assumes fty: "f S {0..}" and gty: "g S {0..}"
  shows "concave_on S (λx. f x * g x)"
proof (intro concave_on_linorderI)
  show "convex S"
    using concave_on_imp_convex f by blast
  fix t::real and x y
  assume t: "0 < t" "t < 1" and xy: "x S" "y S" "x
  have inS: "(1-t)*x + t*y S"
    using t xy convex S by (simp add: convex_alt)
  have "f x * g y + f y * g x f x * g x + f y * g y"
    using mono_on S f antimono_on S g
    unfolding monotone_on_def by (smt (verit, best) left_diff_distrib mult_left_mono xy)
  with t have *: "t*(1-t) * f x * g y + t*(1-t) * f y * g x t*(1-t) * f x * g x + t*(1-t) * f y * g y"
    by (smt (verit, ccfv_SIG) distrib_left mult_left_mono diff_ge_0_iff_ge mult.assoc)
  have "(1 - t) * (f x * g x) + t * (f y * g y) ((1-t) * f x + t * f y) * ((1-t) * g x + t * g y)"
    using * by (simp add: algebra_simps)
  also have " ((1-t) * f x + t * f y)*g ((1-t)*x + t*y)"
    using concave_onD [OF concave_on S g, of t x y] t xy fty gty inS
    by (intro mult_mono add_nonneg_nonneg) (auto simp: Pi_iff zero_le_mult_iff)
  also have " f ((1-t)*x + t*y) * g ((1-t)*x + t*y)"
    using concave_onD [OF concave_on S f, of t x y] t xy fty gty inS
    by (intro mult_mono add_nonneg_nonneg) (auto simp: Pi_iff zero_le_mult_iff)
  finally show "(1 - t) * (f x * g x) + t * (f y * g y)

            f ((1 - t) *🪙R x + t *🪙R y) * g ((1 - t) *🪙R x + t *🪙R y)" 
    by simp
qed

lemma concave_on_cmul [intro]:
  fixes c :: real
  assumes "0 c" and "concave_on S f"
  shows "concave_on S (λx. c * f x)"
  using assms convex_on_cmul [of c S "λx. - f x"]
  by (auto simp: concave_on_def)

lemma concave_on_cdiv [intro]:
  fixes c :: real
  assumes "0 c" and "concave_on S f"
  shows "concave_on S (λx. f x / c)"
  unfolding divide_inverse
  using concave_on_cmul [of "inverse c" S f] by (simp add: mult.commute assms)

subsection🍋tag unimportant Arithmetic operations on sets preserve convexity

lemma convex_linear_image:
  assumes "linear f" and "convex S"
  shows "convex (f ` S)"
proof -
  interpret f: linear f by fact
  from convex S show "convex (f ` S)"
    by (simp add: convex_def f.scaleR [symmetric] f.add [symmetric])
qed

lemma convex_linear_vimage:
  assumes "linear f" and "convex S"
  shows "convex (f -` S)"
proof -
  interpret f: linear f by fact
  from convex S show "convex (f -` S)"
    by (simp add: convex_def f.add f.scaleR)
qed

lemma convex_scaling:
  assumes "convex S"
  shows "convex ((λx. c *🪙R x) ` S)"
  by (simp add: assms convex_linear_image)

lemma convex_scaled:
  assumes "convex S"
  shows "convex ((λx. x *🪙R c) ` S)"
  by (simp add: assms convex_linear_image)

lemma convex_negations:
  assumes "convex S"
  shows "convex ((λx. - x) ` S)"
  by (simp add: assms convex_linear_image module_hom_uminus)

lemma convex_sums:
  assumes "convex S"
    and "convex T"
  shows "convex (x S. y T. {x + y})"
proof -
  have "linear (λ(x, y). x + y)"
    by (auto intro: linearI simp: scaleR_add_right)
  with assms have "convex ((λ(x, y). x + y) ` (S × T))"
    by (intro convex_linear_image convex_Times)
  also have "((λ(x, y). x + y) ` (S × T)) = (x S. y T. {x + y})"
    by auto
  finally show ?thesis .
qed

lemma convex_differences:
  assumes "convex S" "convex T"
  shows "convex (x S. y T. {x - y})"
proof -
  have "{x - y| x y. x S y T} = {x + y |x y. x S y uminus ` T}"
    by (auto simp: diff_conv_add_uminus simp del: add_uminus_conv_diff)
  then show ?thesis
    using convex_sums[OF assms(1) convex_negations[OF assms(2)]] by auto
qed

lemma convex_translation:
  "convex ((+) a ` S)" if "convex S"
  using convex_sums [OF convex_singleton [of a] that]
  by (simp add: UNION_singleton_eq_range)

lemma convex_translation_subtract:
  "convex ((λb. b - a) ` S)" if "convex S"
  using convex_translation [of S "- a"] that by (simp cong: image_cong_simp)

lemma convex_affinity:
  assumes "convex S"
  shows "convex ((λx. a + c *🪙R x) ` S)"
proof -
  have "(λx. a + c *🪙R x) ` S = (+) a ` (*🪙R) c ` S"
    by auto
  then show ?thesis
    using convex_translation[OF convex_scaling[OF assms], of a c] by auto
qed

lemma convex_on_sum:
  fixes a :: "'a ==> real"
    and y :: "'a ==> 'b::real_vector"
    and f :: "'b ==> real"
  assumes "finite S" "S {}"
    and "convex_on C f"
    and "( i S. a i) = 1"
    and "i. i S ==> a i 0"
    and "i. i S ==> y i C"
  shows "f ( i S. a i *🪙R y i) ( i S. a i * f (y i))"
  using assms
proof (induct S arbitrary: a rule: finite_ne_induct)
  case (singleton i)
  then show ?case
    by auto
next
  case (insert i S)
  then have yai: "y i C" "a i 0"
    by auto
  with insert have conv: "x y μ. x C ==> y C ==> 0 μ ==> μ 1 ==>

      f (μ *🪙R x + (1 - μ) *🪙R y) μ * f x + (1 - μ) * f y"
    by (simp add: convex_on_def)
  show ?case
  proof (cases "a i = 1")
    case True
    with insert have "( j S. a j) = 0"
      by auto
    with insert show ?thesis
      by (simp add: sum_nonneg_eq_0_iff)
  next
    case False
    then have ai1: "a i < 1"
      using sum_nonneg_leq_bound[of "insert i S" a] insert by force
    then have i0: "1 - a i > 0"
      by auto
    let ?a = "λj. a j / (1 - a i)"
    have a_nonneg: "?a j 0" if "j S" for j
      using i0 insert that by fastforce
    have "( j insert i S. a j) = 1"
      using insert by auto
    then have "( j S. a j) = 1 - a i"
      using sum.insert insert by fastforce
    then have "( j S. a j) / (1 - a i) = 1"
      using i0 by auto
    then have a1: "( j S. ?a j) = 1"
      unfolding sum_divide_distrib by simp
    have "convex C"
      using convex_on C f by (simp add: convex_on_def)
    have asum: "( j S. ?a j *🪙R y j) C"
      using insert convex_sum [OF finite S convex C a1 a_nonneg] by auto
    have asum_le: "f ( j S. ?a j *🪙R y j) ( j S. ?a j * f (y j))"
      using a_nonneg a1 insert by blast
    have "f ( j insert i S. a j *🪙R y j) = f (( j S. a j *🪙R y j) + a i *🪙R y i)"
      by (simp add: add.commute insert.hyps)
    also have " = f (((1 - a i) * inverse (1 - a i)) *🪙R ( j S. a j *🪙R y j) + a i *🪙R y i)"
      using i0 by auto
    also have " = f ((1 - a i) *🪙R ( j S. (a j * inverse (1 - a i)) *🪙R y j) + a i *🪙R y i)"
      using scaleR_right.sum[of "inverse (1 - a i)" "λ j. a j *🪙R y j" S, symmetric]
      by (auto simp: algebra_simps)
    also have " = f ((1 - a i) *🪙R ( j S. ?a j *🪙R y j) + a i *🪙R y i)"
      by (auto simp: divide_inverse)
    also have " (1 - a i) *🪙R f (( j S. ?a j *🪙R y j)) + a i * f (y i)"
      using ai1 by (smt (verit) asum conv real_scaleR_def yai)
    also have " (1 - a i) * ( j S. ?a j * f (y j)) + a i * f (y i)"
      using asum_le i0 by fastforce
    also have " = ( j S. a j * f (y j)) + a i * f (y i)"
      using i0 by (auto simp: sum_distrib_left)
    finally show ?thesis
      using insert by auto
  qed
qed

lemma concave_on_sum:
  fixes a :: "'a ==> real"
    and y :: "'a ==> 'b::real_vector"
    and f :: "'b ==> real"
  assumes "finite S" "S {}"
    and "concave_on C f" 
    and "(i S. a i) = 1"
    and "i. i S ==> a i 0"
    and "i. i S ==> y i C"
  shows "f (i S. a i *🪙R y i) (i S. a i * f (y i))"
proof -
  have "(uminus f) (iS. a i *🪙R y i) (iS. a i * (uminus f) (y i))"
  proof (intro convex_on_sum)
    show "convex_on C (uminus f)"
      by (simp add: assms convex_on_iff_concave)
  qed (use assms in auto)
  then show ?thesis
    by (simp add: sum_negf o_def)
qed

lemma convex_on_alt:
  fixes C :: "'a::real_vector set"
  shows "convex_on C f convex C
         (x C. y C. μ :: real. μ 0 μ 1
          f (μ *🪙R x + (1 - μ) *🪙R y) μ * f x + (1 - μ) * f y)"
  by (smt (verit) convex_on_def)

lemma convex_on_slope_le:
  fixes f :: "real ==> real"
  assumes f: "convex_on I f"
    and I: "x I" "y I"
    and t: "x < t" "t < y"
  shows "(f x - f t) / (x - t) (f x - f y) / (x - y)"
    and "(f x - f y) / (x - y) (f t - f y) / (t - y)"
proof -
  define a where "a (t - y) / (x - y)"
  with t have "0 a" "0 1 - a"
    by (auto simp: field_simps)
  with f x I y I have cvx: "f (a * x + (1 - a) * y) a * f x + (1 - a) * f y"
    by (auto simp: convex_on_def)
  have "a * x + (1 - a) * y = a * (x - y) + y"
    by (simp add: field_simps)
  also have " = t"
    unfolding a_def using x 🚫 t 🚫 by simp
  finally have "f t a * f x + (1 - a) * f y"
    using cvx by simp
  also have " = a * (f x - f y) + f y"
    by (simp add: field_simps)
  finally have "f t - f y a * (f x - f y)"
    by simp
  with t show "(f x - f t) / (x - t) (f x - f y) / (x - y)"
    by (simp add: le_divide_eq divide_le_eq field_simps a_def)
  with t show "(f x - f y) / (x - y) (f t - f y) / (t - y)"
    by (simp add: le_divide_eq divide_le_eq field_simps)
qed

lemma pos_convex_function:
  fixes f :: "real ==> real"
  assumes "convex C"
    and leq: "x y. x C ==> y C ==> f' x * (y - x) f y - f x"
  shows "convex_on C f"
  unfolding convex_on_alt
  using assms
proof safe
  fix x y μ :: real
  let ?x = "μ *🪙R x + (1 - μ) *🪙R y"
  assume *: "convex C" "x C" "y C"  0"  1"
  then have "1 - μ 0" by auto
  then have xpos: "?x C"
    using * unfolding convex_alt by fastforce
  have geq: "μ * (f x - f ?x) + (1 - μ) * (f y - f ?x)
      μ * f' ?x * (x - ?x) + (1 - μ) * f' ?x * (y - ?x)"
    using add_mono [OF mult_left_mono [OF leq [OF xpos *(2)] μ 0]
        mult_left_mono [OF leq [OF xpos *(3)] 1 - μ 0]]
    by auto
  then have "μ * f x + (1 - μ) * f y - f ?x 0"
    by (auto simp: field_simps)
  then show "f (μ *🪙R x + (1 - μ) *🪙R y) μ * f x + (1 - μ) * f y"
    by auto
qed

lemma atMostAtLeast_subset_convex:
  fixes C :: "real set"
  assumes "convex C"
    and "x C" "y C" "x < y"
  shows "{x .. y} C"
proof safe
  fix z assume z: "z {x .. y}"
  have less: "z C" if *: "x < z" "z < y"
  proof -
    let ?μ = "(y - z) / (y - x)"
    have "0 ?μ" "?μ 1"
      using assms * by (auto simp: field_simps)
    then have comb: "?μ * x + (1 - ?μ) * y C"
      using assms iffD1[OF convex_alt, rule_format, of C y x ?μ]
      by (simp add: algebra_simps)
    have "?μ * x + (1 - ?μ) * y = (y - z) * x / (y - x) + (1 - (y - z) / (y - x)) * y"
      by (auto simp: field_simps)
    also have " = ((y - z) * x + (y - x - (y - z)) * y) / (y - x)"
      using assms by (simp only: add_divide_distrib) (auto simp: field_simps)
    also have " = z"
      using assms by (auto simp: field_simps)
    finally show ?thesis
      using comb by auto
  qed
  show "z C"
    using z less assms by (auto simp: le_less)
qed

lemma f''_imp_f':
  fixes f :: "real ==> real"
  assumes "convex C"
    and f': "x. x C ==> DERIV f x :> (f' x)"
    and f'': "x. x C ==> DERIV f' x :> (f'' x)"
    and pos: "x. x C ==> f'' x 0"
    and x: "x C"
    and y: "y C"
  shows "f' x * (y - x) f y - f x"
  using assms
proof -
  have "f y - f x f' x * (y - x)" "f' y * (x - y) f x - f y"
    if *: "x C" "y C" "y > x" for x y :: real
  proof -
    from * have ge: "y - x > 0" "y - x 0" and le: "x - y < 0" "x - y 0"
      by auto
    then obtain z1 where z1: "z1 > x" "z1 < y" "f y - f x = (y - x) * f' z1"
      using subsetD[OF atMostAtLeast_subset_convex[OF convex C x C y C x 🚫],
          THEN f', THEN MVT2[OF x 🚫, rule_format, unfolded atLeastAtMost_iff[symmetric]]]
      by auto
    then have "z1 C"
      using atMostAtLeast_subset_convex convex C x C y C x 🚫
      by fastforce
    obtain z2 where z2: "z2 > x" "z2 < z1" "f' z1 - f' x = (z1 - x) * f'' z2"
      using subsetD[OF atMostAtLeast_subset_convex[OF convex C x C z1 C x 🚫],
          THEN f'', THEN MVT2[OF x 🚫, rule_format, unfolded atLeastAtMost_iff[symmetric]]] z1
      by auto
    obtain z3 where z3: "z3 > z1" "z3 < y" "f' y - f' z1 = (y - z1) * f'' z3"
      using subsetD[OF atMostAtLeast_subset_convex[OF convex C z1 C y C z1 🚫],
          THEN f'', THEN MVT2[OF z1 🚫, rule_format, unfolded atLeastAtMost_iff[symmetric]]] z1
      by auto
    from z1 have "f x - f y = (x - y) * f' z1"
      by (simp add: field_simps)
    then have cool': "f' y - (f x - f y) / (x - y) = (y - z1) * f'' z3"
      using le(1) z3(3) by auto
    have "z3 C"
      using z3 * atMostAtLeast_subset_convex convex C x C z1 C x 🚫
      by fastforce
    then have B': "f'' z3 0"
      using assms by auto
    with cool' have "f' y - (f x - f y) / (x - y) 0"
      using z1 by auto
    then have res: "f' y * (x - y) f x - f y"
      by (meson diff_ge_0_iff_ge le(1) neg_divide_le_eq)
    have cool: "(f y - f x) / (y - x) - f' x = (z1 - x) * f'' z2"
      using le(1) z1(3) z2(3) by auto
    have "z2 C"
      using z2 z1 * atMostAtLeast_subset_convex convex C z1 C y C z1 🚫
      by fastforce
    with z1 assms have "(z1 - x) * f'' z2 0"
      by auto
    then show "f y - f x f' x * (y - x)" "f' y * (x - y) f x - f y"
      using that(3) z1(3) res cool by auto
  qed
  then show ?thesis
    using x y by fastforce
qed

lemma f''_ge0_imp_convex:
  fixes f :: "real ==> real"
  assumes "convex C"
    and "x. x C ==> DERIV f x :> (f' x)"
    and "x. x C ==> DERIV f' x :> (f'' x)"
    and "x. x C ==> f'' x 0"
  shows "convex_on C f"
  by (metis assms f''_imp_f' pos_convex_function)

lemma f''_le0_imp_concave:
  fixes f :: "real ==> real"
  assumes "convex C"
    and "x. x C ==> DERIV f x :> (f' x)"
    and "x. x C ==> DERIV f' x :> (f'' x)"
    and "x. x C ==> f'' x 0"
  shows "concave_on C f"
  unfolding concave_on_def
  by (rule assms f''_ge0_imp_convex derivative_eq_intros | simp)+

lemma convex_power_even:
  assumes "even n"
  shows "convex_on (UNIV::real set) (λx. x^n)"
proof (intro f''_ge0_imp_convex)
  show "((λx. x ^ n) has_real_derivative of_nat n * x^(n-1)) (at x)" for x
    by (rule derivative_eq_intros | simp)+
  show "((λx. of_nat n * x^(n-1)) has_real_derivative of_nat n * of_nat (n-1) * x^(n-2)) (at x)" for x
    by (rule derivative_eq_intros | simp add: eval_nat_numeral)+
  show "x. 0 real n * real (n - 1) * x ^ (n - 2)"
    using assms by (auto simp: zero_le_mult_iff zero_le_even_power)
qed auto

lemma convex_power_odd:
  assumes "odd n"
  shows "convex_on {0::real..} (λx. x^n)"
proof (intro f''_ge0_imp_convex)
  show "((λx. x ^ n) has_real_derivative of_nat n * x^(n-1)) (at x)" for x
    by (rule derivative_eq_intros | simp)+
  show "((λx. of_nat n * x^(n-1)) has_real_derivative of_nat n * of_nat (n-1) * x^(n-2)) (at x)" for x
    by (rule derivative_eq_intros | simp add: eval_nat_numeral)+
  show "x. x {0::real..} ==> 0 real n * real (n - 1) * x ^ (n - 2)"
    using assms by (auto simp: zero_le_mult_iff zero_le_even_power)
qed auto

lemma convex_power2: "convex_on (UNIV::real set) power2"
  by (simp add: convex_power_even)

lemma log_concave:
  fixes b :: real
  assumes "b > 1"
  shows "concave_on {0<..} (λ x. log b x)"
  using assms
  by (intro f''_le0_imp_concave derivative_eq_intros | simp)+

lemma ln_concave: "concave_on {0<..} ln"
  unfolding log_ln by (simp add: log_concave)

lemma minus_log_convex:
  fixes b :: real
  assumes "b > 1"
  shows "convex_on {0 <..} (λ x. - log b x)"
  using assms concave_on_def log_concave by blast

lemma powr_convex: 
  assumes "p 1" shows "convex_on {0<..} (λx. x powr p)"
  using assms
  by (intro f''_ge0_imp_convex derivative_eq_intros | simp)+

lemma exp_convex: "convex_on UNIV exp"
  by (intro f''_ge0_imp_convex derivative_eq_intros | simp)+

text The AM-GM inequality: the arithmetic mean exceeds the geometric mean.
lemma arith_geom_mean:
  fixes x :: "'a ==> real"
  assumes "finite S" "S {}"
    and x: "i. i S ==> x i 0"
  shows "(i S. x i / card S) (i S. x i) powr (1 / card S)"
proof (cases "iS. x i = 0")
  case True
  then have "(i S. x i) = 0"
    by (simp add: finite S)
  moreover have "(i S. x i / card S) 0"
    by (simp add: sum_nonneg x)
  ultimately show ?thesis
    by simp
next
  case False
  have "ln (i S. (1 / card S) *🪙R x i) (i S. (1 / card S) * ln (x i))"
  proof (intro concave_on_sum)
    show "concave_on {0<..} ln"
      by (simp add: ln_concave)
    show "i. iS ==> x i {0<..}"
      using False x by fastforce
  qed (use assms False in auto)
  moreover have "(i S. (1 / card S) *🪙R x i) > 0"
    using False assms by (simp add: card_gt_0_iff less_eq_real_def sum_pos)
  ultimately have "(i S. (1 / card S) *🪙R x i) exp (i S. (1 / card S) * ln (x i))"
    using ln_ge_iff by blast
  then have "(i S. x i / card S) exp (i S. ln (x i) / card S)"
    by (simp add: divide_simps)
  then show ?thesis
    using assms False
    by (smt (verit, ccfv_SIG) divide_inverse exp_ln exp_powr_real exp_sum inverse_eq_divide prod.cong prod_powr_distrib) 
qed

subsection🍋tag unimportant Convexity of real functions

lemma convex_on_realI:
  assumes "connected A"
    and "x. x A ==> (f has_real_derivative f' x) (at x)"
    and "x y. x A ==> y A ==> x y ==> f' x f' y"
  shows "convex_on A f"
proof (rule convex_on_linorderI)
  show "convex A"
    using connected A convex_real_interval interval_cases
    by (smt (verit, ccfv_SIG) connectedD_interval convex_UNIV convex_empty)
      🍋 the equivalence of "connected" and "convex" for real intervals is proved later
next
  fix t x y :: real
  assume t: "t > 0" "t < 1"
  assume xy: "x A" "y A" "x < y"
  define z where "z = (1 - t) * x + t * y"
  with connected A and xy have ivl: "{x..y} A"
    using connected_contains_Icc by blast

  from xy t have xz: "z > x"
    by (simp add: z_def algebra_simps)
  have "y - z = (1 - t) * (y - x)"
    by (simp add: z_def algebra_simps)
  also from xy t have " > 0"
    by (intro mult_pos_pos) simp_all
  finally have yz: "z < y"
    by simp

  from assms xz yz ivl t have "ξ. ξ > x ξ < z f z - f x = (z - x) * f' ξ"
    by (intro MVT2) (auto intro!: assms(2))
  then obtain ξ where ξ: "ξ > x" "ξ < z" "f' ξ = (f z - f x) / (z - x)"
    by auto
  from assms xz yz ivl t have "🪙. 🪙 > z 🪙 < y f y - f z = (y - z) * f' 🪙"
    by (intro MVT2) (auto intro!: assms(2))
  then obtain 🪙 where 🪙"🪙 > z" "🪙 < y" "f' 🪙 = (f y - f z) / (y - z)"
    by auto

  from 🪙(3) have "(f y - f z) / (y - z) = f' 🪙" ..
  also from ξ 🪙 ivl have  A" "🪙 A"
    by auto
  with ξ 🪙 have "f' 🪙 f' ξ"
    by (intro assms(3)) auto
  also from ξ(3) have "f' ξ = (f z - f x) / (z - x)" .
  finally have "(f y - f z) * (z - x) (f z - f x) * (y - z)"
    using xz yz by (simp add: field_simps)
  also have "z - x = t * (y - x)"
    by (simp add: z_def algebra_simps)
  also have "y - z = (1 - t) * (y - x)"
    by (simp add: z_def algebra_simps)
  finally have "(f y - f z) * t (f z - f x) * (1 - t)"
    using xy by simp
  then show "(1 - t) * f x + t * f y f ((1 - t) *🪙R x + t *🪙R y)"
    by (simp add: z_def algebra_simps)
qed

lemma convex_on_inverse:
  fixes A :: "real set"
  assumes "A {0<..}" "convex A"
  shows "convex_on A inverse"
proof -
  have "convex_on {0::real<..} inverse"
  proof (intro convex_on_realI)
    fix u v :: real
    assume "u {0<..}" "v {0<..}" "u v"
    with assms show "-inverse (u^2) -inverse (v^2)"
      by simp
  next
    show "x. x {0<..} ==> (inverse has_real_derivative - inverse (x🪙2)) (at x)"
      by (rule derivative_eq_intros | simp add: power2_eq_square)+
  qed auto
  then show ?thesis
    using assms convex_on_subset by blast
qed

lemma convex_onD_Icc':
  assumes "convex_on {x..y} f" "c {x..y}"
  defines "d y - x"
  shows "f c (f y - f x) / d * (c - x) + f x"
proof (cases x y rule: linorder_cases)
  case less
  then have d: "d > 0"
    by (simp add: d_def)
  from assms(2) less have A: "0 (c - x) / d" "(c - x) / d 1"
    by (simp_all add: d_def field_split_simps)
  have "f c = f (x + (c - x) * 1)"
    by simp
  also from less have "1 = ((y - x) / d)"
    by (simp add: d_def)
  also from d have "x + (c - x) * = (1 - (c - x) / d) *🪙R x + ((c - x) / d) *🪙R y"
    by (simp add: field_simps)
  also have "f (1 - (c - x) / d) * f x + (c - x) / d * f y"
    using assms less by (intro convex_onD_Icc) simp_all
  also from d have " = (f y - f x) / d * (c - x) + f x"
    by (simp add: field_simps)
  finally show ?thesis .
qed (use assms in auto)

lemma convex_onD_Icc'':
  assumes "convex_on {x..y} f" "c {x..y}"
  defines "d y - x"
  shows "f c (f x - f y) / d * (y - c) + f y"
proof (cases x y rule: linorder_cases)
  case less
  then have d: "d > 0"
    by (simp add: d_def)
  from assms(2) less have A: "0 (y - c) / d" "(y - c) / d 1"
    by (simp_all add: d_def field_split_simps)
  have "f c = f (y - (y - c) * 1)"
    by simp
  also from less have "1 = ((y - x) / d)"
    by (simp add: d_def)
  also from d have "y - (y - c) * = (1 - (1 - (y - c) / d)) *🪙R x + (1 - (y - c) / d) *🪙R y"
    by (simp add: field_simps)
  also have "f (1 - (1 - (y - c) / d)) * f x + (1 - (y - c) / d) * f y"
    using assms less by (intro convex_onD_Icc) (simp_all add: field_simps)
  also from d have " = (f x - f y) / d * (y - c) + f y"
    by (simp add: field_simps)
  finally show ?thesis .
qed (use assms in auto)

lemma concave_onD_Icc:
  assumes "concave_on {x..y} f" "x (y :: _ :: {real_vector,preorder})"
  shows "t. t 0 ==> t 1 ==>
    f ((1 - t) *🪙R x + t *🪙R y) (1 - t) * f x + t * f y"
  using assms(2) by (intro concave_onD [OF assms(1)]) simp_all

lemma concave_onD_Icc':
  assumes "concave_on {x..y} f" "c {x..y}"
  defines "d y - x"
  shows "f c (f y - f x) / d * (c - x) + f x"
proof -
  have "- f c (f x - f y) / d * (c - x) - f x"
    using assms convex_onD_Icc' [of x y "λx. - f x" c]
    by (simp add: concave_on_def)
  then show ?thesis
    by (smt (verit, best) divide_minus_left mult_minus_left)
qed

lemma concave_onD_Icc'':
  assumes "concave_on {x..y} f" "c {x..y}"
  defines "d y - x"
  shows "f c (f x - f y) / d * (y - c) + f y"
proof -
  have "- f c (f y - f x) / d * (y - c) - f y"
    using assms convex_onD_Icc'' [of x y "λx. - f x" c]
    by (simp add: concave_on_def)
  then show ?thesis
    by (smt (verit, best) divide_minus_left mult_minus_left)
qed

lemma convex_on_le_max:
  fixes a::real
  assumes "convex_on {x..y} f" and a: "a {x..y}"
  shows "f a max (f x) (f y)"
proof -
  have *: "(f y - f x) * (a - x) (f y - f x) * (y - x)" if "f x f y"
    using a that by (intro mult_left_mono) auto
  have "f a (f y - f x) / (y - x) * (a - x) + f x" 
    using assms convex_onD_Icc' by blast
  also have " max (f x) (f y)"
    using a *
    by (simp add: divide_le_0_iff mult_le_0_iff zero_le_mult_iff max_def add.commute mult.commute scaling_mono)
  finally show ?thesis .
qed

lemma concave_on_ge_min:
  fixes a::real
  assumes "concave_on {x..y} f" and a: "a {x..y}"
  shows "f a min (f x) (f y)"
proof -
  have *: "(f y - f x) * (a - x) (f y - f x) * (y - x)" if "f x f y"
    using a that by (intro mult_left_mono_neg) auto
  have "min (f x) (f y) (f y - f x) / (y - x) * (a - x) + f x"
    using a * apply (simp add: zero_le_divide_iff mult_le_0_iff zero_le_mult_iff min_def)
    by (smt (verit, best) nonzero_eq_divide_eq pos_divide_le_eq)
  also have " f a"
    using assms concave_onD_Icc' by blast
  finally show ?thesis .
qed

subsection Convexity of the generalised binomial

lemma mono_on_mul:
  fixes f::"'a::ord ==> 'b::ordered_semiring"
  assumes "mono_on S f" "mono_on S g"
  assumes fty: "f S {0..}" and gty: "g S {0..}"
  shows "mono_on S (λx. f x * g x)"
  using assms by (auto simp: Pi_iff monotone_on_def intro!: mult_mono)

lemma mono_on_prod:
  fixes f::"'i ==> 'a::ord ==> 'b::linordered_idom"
  assumes "i. i I ==> mono_on S (f i)" 
  assumes "i. i I ==> f i S {0..}" 
  shows "mono_on S (λx. prod (λi. f i x) I)"
  using assms
  by (induction I rule: infinite_finite_induct)
     (auto simp: mono_on_const Pi_iff prod_nonneg mono_on_mul mono_onI)

lemma convex_gchoose_aux: "convex_on {k-1..} (λa. prod (λi. a - of_nat i) {0..
proof (induction k)
  case 0
  then show ?case 
    by (simp add: convex_on_def)
next
  case (Suc k)
  have "convex_on {real k..} (λa. (i = 0..
  proof (intro convex_on_mul convex_on_diff)
    show "convex_on {real k..} (λx. i = 0..
      using Suc convex_on_subset by fastforce
    show "mono_on {real k..} (λx. i = 0..
      by (force simp: monotone_on_def intro!: prod_mono)
  next
    show "(λx. i = 0.. {real k..} {0..}"

      by (auto intro!: prod_nonneg)
  qed (auto simp: convex_on_ident concave_on_const mono_onI)
  then show ?case
    by simp
qed

lemma convex_gchoose: "convex_on {k-1..} (λx. x gchoose k)"
  by (simp add: gbinomial_prod_rev convex_on_cdiv convex_gchoose_aux)

subsection Some inequalities: Applications of convexity

lemma Youngs_inequality_0:
  fixes a::real
  assumes "0 α" "0 β" "α+β = 1" "a>0" "b>0"
  shows "a powr α * b powr β α*a + β*b"
proof -
  have "α * ln a + β * ln b ln (α * a + β * b)"
    using assms ln_concave by (simp add: concave_on_iff)
  moreover have "0 < α * a + β * b"
    using assms by (smt (verit) mult_pos_pos split_mult_pos_le)
  ultimately show ?thesis
    using assms by (simp add: powr_def mult_exp_exp flip: ln_ge_iff)
qed

lemma Youngs_inequality:
  fixes p::real
  assumes "p>1" "q>1" "1/p + 1/q = 1" "a0" "b0"
  shows "a * b a powr p / p + b powr q / q"
proof (cases "a=0 b=0")
  case False
  then show ?thesis 
  using Youngs_inequality_0 [of "1/p" "1/q" "a powr p" "b powr q"] assms
  by (simp add: powr_powr)
qed (use assms in auto)

lemma Cauchy_Schwarz_ineq_sum:
  fixes a :: "'a ==> 'b::linordered_field"
  shows "(iI. a i * b i)🪙2 (iI. (a i)🪙2) * (iI. (b i)🪙2)"
proof (cases "(iI. (b i)🪙2) > 0")
  case False
  then consider "i. iI ==> b i = 0" | "infinite I"
    by (metis (mono_tags, lifting) sum_pos2 zero_le_power2 zero_less_power2)
  thus ?thesis
    by fastforce
next
  case True
  define r where "r (iI. a i * b i) / (iI. (b i)🪙2)"
  have "0 (iI. (a i - r * b i)🪙2)"
    by (simp add: sum_nonneg)
  also have "... = (iI. (a i)🪙2) - 2 * r * (iI. a i * b i) + r🪙2 * (iI. (b i)🪙2)"
    by (simp add: algebra_simps power2_eq_square sum_distrib_left flip: sum.distrib)
  also have " = (iI. (a i)🪙2) - ((iI. a i * b i))🪙2 / (iI. (b i)🪙2)"
    by (simp add: r_def power2_eq_square)
  finally have "0 (iI. (a i)🪙2) - ((iI. a i * b i))🪙2 / (iI. (b i)🪙2)" .
  hence "((iI. a i * b i))🪙2 / (iI. (b i)🪙2) (iI. (a i)🪙2)"
    by (simp add: le_diff_eq)
  thus "((iI. a i * b i))🪙2 (iI. (a i)🪙2) * (iI. (b i)🪙2)"
    by (simp add: pos_divide_le_eq True)
qed

text The inequality between the arithmetic mean and the root mean square
lemma sum_squared_le_sum_of_squares:
  fixes f :: "'a ==> real"
  shows "(iI. f i)🪙2 (yI. (f y)🪙2) * card I"
proof (cases "finite I I {}")
  case True
  then have "(iI. f i / of_nat (card I))🪙2 (iI. (f i)🪙2 / of_nat (card I))"
    using convex_on_sum [OF _ _ convex_power2, where a = "λx. 1 / of_nat(card I)" and S=I]
    by simp
  with True show ?thesis
    by (simp add: divide_simps power2_eq_square split: if_split_asm flip: sum_divide_distrib)
qed auto

lemma sum_squared_le_sum_of_squares_2:
  "(x+y)/2 sqrt ((x🪙2 + y🪙2) / 2)"
proof -
  have "(x + y)🪙2 / 2^2 (x🪙2 + y🪙2) / 2"
    using sum_squared_le_sum_of_squares [of "λb. if b then x else y" UNIV]
    by (simp add: UNIV_bool add.commute)
  then show ?thesis
    by (metis power_divide real_le_rsqrt)
qed

subsection Misc related lemmas

lemma convex_translation_eq [simp]:
  "convex ((+) a ` s) convex s"
  by (metis convex_translation translation_galois)

lemma convex_translation_subtract_eq [simp]:
  "convex ((λb. b - a) ` s) convex s"
  using convex_translation_eq [of "- a"by (simp cong: image_cong_simp)

lemma convex_linear_image_eq [simp]:
    fixes f :: "'a::real_vector ==> 'b::real_vector"
    shows "[linear f; inj f] ==> convex (f ` s) convex s"
    by (metis (no_types) convex_linear_image convex_linear_vimage inj_vimage_image_eq)

lemma vector_choose_size:
  assumes "0 c"
  obtains x :: "'a::{real_normed_vector, perfect_space}" where "norm x = c"
proof -
  obtain a::'a where "a 0"
    using UNIV_not_singleton UNIV_eq_I set_zero singletonI by fastforce
  show ?thesis
  proof
    show "norm (scaleR (c / norm a) a) = c"
      by (simp add: a 0 assms)
  qed
qed

lemma vector_choose_dist:
  assumes "0 c"
  obtains y :: "'a::{real_normed_vector, perfect_space}" where "dist x y = c"
by (metis add_diff_cancel_left' assms dist_commute dist_norm vector_choose_size)

lemma sum_delta'':
  fixes s::"'a::real_vector set"
  assumes "finite s"
  shows "(xs. (if y = x then f x else 0) *🪙R x) = (if ys then (f y) *🪙R y else 0)"
proof -
  have *: "x y. (if y = x then f x else (0::real)) *🪙R x = (if x=y then (f x) *🪙R x else 0)"
    by auto
  show ?thesis
    unfolding * using sum.delta[OF assms, of y "λx. f x *🪙R x"by auto
qed


subsection Cones

definition🍋tag important cone :: "'a::real_vector set ==> bool"
  where "cone s (xs. c0. c *🪙R x s)"

lemma cone_empty[intro, simp]: "cone {}"
  unfolding cone_def by auto

lemma cone_univ[intro, simp]: "cone UNIV"
  unfolding cone_def by auto

lemma cone_Inter[intro]: "sf. cone s ==> cone (f)"
  unfolding cone_def by auto

lemma subspace_imp_cone: "subspace S ==> cone S"
  by (simp add: cone_def subspace_scale)


subsubsection Conic hull

lemma cone_cone_hull: "cone (cone hull S)"
  unfolding hull_def by auto

lemma cone_hull_eq: "cone hull S = S cone S"
  by (metis cone_cone_hull hull_same)

lemma mem_cone:
  assumes "cone S" "x S" "c 0"
  shows "c *🪙R x S"
  using assms cone_def[of S] by auto

lemma cone_contains_0:
  assumes "cone S"
  shows "S {} 0 S"
  using assms mem_cone by fastforce

lemma cone_0: "cone {0}"
  unfolding cone_def by auto

lemma cone_Union[intro]: "(sf. cone s) cone (f)"
  unfolding cone_def by blast

lemma cone_iff:
  assumes "S {}"
  shows "cone S 0 S (c. c > 0 ((*🪙R) c) ` S = S)"  (is "_ = ?rhs")
proof 
  assume "cone S"
  {
    fix c :: real
    assume "c > 0"
    have "x ((*🪙R) c) ` S" if "x S" for x
        using cone S c>0 mem_cone[of S x "1/c"] that
          exI[of "(λt. t S x = c *🪙R t)" "(1 / c) *🪙R x"]
        by auto
    then have "((*🪙R) c) ` S = S" 
        using 0 🚫 cone S mem_cone by fastforce
  }
  then show "0 S (c. c > 0 ((*🪙R) c) ` S = S)"
    using cone S cone_contains_0[of S] assms by auto
next
  show "?rhs ==> cone S"
    by (metis Convex.cone_def imageI order_neq_le_trans scaleR_zero_left)
qed

lemma cone_hull_empty: "cone hull {} = {}"
  by (metis cone_empty cone_hull_eq)

lemma cone_hull_empty_iff: "S = {} cone hull S = {}"
  by (metis cone_hull_empty hull_subset subset_empty)

lemma cone_hull_contains_0: "S {} 0 cone hull S"
  by (metis cone_cone_hull cone_contains_0 cone_hull_empty_iff)

lemma mem_cone_hull:
  assumes "x S" "c 0"
  shows "c *🪙R x cone hull S"
  by (metis assms cone_cone_hull hull_inc mem_cone)

proposition cone_hull_expl: "cone hull S = {c *🪙R x | c x. c 0 x S}"
  (is "?lhs = ?rhs")
proof 
  have "?rhs Collect cone"
    using Convex.cone_def by fastforce
  moreover have "S ?rhs"
    by (smt (verit) mem_Collect_eq scaleR_one subsetI)
  ultimately show "?lhs ?rhs"
    using hull_minimal by blast
qed (use mem_cone_hull in auto)

lemma convex_cone:
  "convex S cone S (xS. yS. (x + y) S) (xS. c0. (c *🪙R x) S)"
  (is "?lhs = ?rhs")
proof -
  {
    fix x y
    assume "xS" "yS" and ?lhs
    then have "2 *🪙R x S" "2 *🪙R y S" "convex S"
      unfolding cone_def by auto
    then have "x + y S"
      using convexD [OF convex S, of "2*🪙R x" "2*🪙R y"]
      by (smt (verit, ccfv_threshold) field_sum_of_halves scaleR_2 scaleR_half_double)
  }
  then show ?thesis
    unfolding convex_def cone_def by blast
qed


subsection🍋tag unimportant Connectedness of convex sets

lemma convex_connected:
  fixes S :: "'a::real_normed_vector set"
  assumes "convex S"
  shows "connected S"
proof (rule connectedI)
  fix A B
  assume "open A" "open B" "A B S = {}" "S A B"
  moreover
  assume "A S {}" "B S {}"
  then obtain a b where a: "a A" "a S" and b: "b B" "b S" by auto
  define f where [abs_def]: "f u = u *🪙R a + (1 - u) *🪙R b" for u
  then have "continuous_on {0 .. 1} f"
    by (auto intro!: continuous_intros)
  then have "connected (f ` {0 .. 1})"
    by (auto intro!: connected_continuous_image)
  note connectedD[OF this, of A B]
  moreover have "a A f ` {0 .. 1}"
    using a by (auto intro!: image_eqI[of _ _ 1] simp: f_def)
  moreover have "b B f ` {0 .. 1}"
    using b by (auto intro!: image_eqI[of _ _ 0] simp: f_def)
  moreover have "f ` {0 .. 1} S"
    using convex S a b unfolding convex_def f_def by auto
  ultimately show False by auto
qed

corollary%unimportant connected_UNIV[intro]: "connected (UNIV :: 'a::real_normed_vector set)"
  by (simp add: convex_connected)

lemma convex_prod:
  assumes "i. i Basis ==> convex {x. P i x}"
  shows "convex {x. iBasis. P i (xi)}"
  using assms by (auto simp: inner_add_left convex_def)

lemma convex_positive_orthant: "convex {x::'a::euclidean_space. (iBasis. 0 xi)}"
by (rule convex_prod) (simp flip: atLeast_def)

subsection Convex hull

lemma convex_convex_hull [iff]: "convex (convex hull s)"
  by (metis (mono_tags) convex_Inter hull_def mem_Collect_eq)

lemma convex_hull_subset:
    "s convex hull t ==> convex hull s convex hull t"
  by (simp add: subset_hull)

lemma convex_hull_eq: "convex hull s = s convex s"
  by (metis convex_convex_hull hull_same)

subsubsection🍋tag unimportant Convex hull is "preserved" by a linear function

lemma convex_hull_linear_image:
  assumes f: "linear f"
  shows "f ` (convex hull S) = convex hull (f ` S)"
proof
  show "convex hull (f ` S) f ` (convex hull S)"
    by (intro hull_minimal image_mono hull_subset convex_linear_image assms convex_convex_hull)
  show "f ` (convex hull S) convex hull (f ` S)"
    by (meson convex_convex_hull convex_linear_vimage f hull_minimal hull_subset image_subset_iff_subset_vimage)
qed

lemma in_convex_hull_linear_image:
  assumes "linear f" "x convex hull S"
  shows "f x convex hull (f ` S)"
  using assms convex_hull_linear_image image_eqI by blast

lemma convex_hull_Times:
  "convex hull (S × T) = (convex hull S) × (convex hull T)"
proof
  show "convex hull (S × T) (convex hull S) × (convex hull T)"
    by (intro hull_minimal Sigma_mono hull_subset convex_Times convex_convex_hull)
  have "(x, y) convex hull (S × T)" if x: "x convex hull S" and y: "y convex hull T" for x y
  proof (rule hull_induct [OF x], rule hull_induct [OF y])
    fix x y assume "x S" and "y T"
    then show "(x, y) convex hull (S × T)"
      by (simp add: hull_inc)
  next
    fix x let ?S = "((λy. (0, y)) -` (λp. (- x, 0) + p) ` (convex hull S × T))"
    have "convex ?S"
      by (intro convex_linear_vimage convex_translation convex_convex_hull,
        simp add: linear_iff)
    also have "?S = {y. (x, y) convex hull (S × T)}"
      by (auto simp: image_def Bex_def)
    finally show "convex {y. (x, y) convex hull (S × T)}" .
  next
    show "convex {x. (x, y) convex hull S × T}"
    proof -
      fix y let ?S = "((λx. (x, 0)) -` (λp. (0, - y) + p) ` (convex hull S × T))"
      have "convex ?S"
      by (intro convex_linear_vimage convex_translation convex_convex_hull,
        simp add: linear_iff)
      also have "?S = {x. (x, y) convex hull (S × T)}"
        by (auto simp: image_def Bex_def)
      finally show "convex {x. (x, y) convex hull (S × T)}" .
    qed
  qed
  then show "(convex hull S) × (convex hull T) convex hull (S × T)"
    unfolding subset_eq split_paired_Ball_Sigma by blast
qed


subsubsection🍋tag unimportant Stepping theorems for convex hulls of finite sets

lemma convex_hull_empty[simp]: "convex hull {} = {}"
  by (simp add: hull_same)

lemma convex_hull_singleton[simp]: "convex hull {a} = {a}"
  by (simp add: hull_same)

lemma convex_hull_insert:
  fixes S :: "'a::real_vector set"
  assumes "S {}"
  shows "convex hull (insert a S) =

         {x. u0. v0. b. (u + v = 1) b (convex hull S) (x = u *🪙R a + v *🪙R b)}"
  (is "_ = ?hull")
proof (intro equalityI hull_minimal subsetI)
  fix x
  assume "x insert a S"
  then show "x ?hull"
  unfolding insert_iff
  proof
    assume "x = a"
    then show ?thesis
      by (smt (verit, del_insts) add.right_neutral assms ex_in_conv hull_inc mem_Collect_eq scaleR_one scaleR_zero_left)
  next
    assume "x S"
    with hull_subset show ?thesis
      by force
  qed
next
  fix x
  assume "x ?hull"
  then obtain u v b where obt: "u0" "v0" "u + v = 1" "b convex hull S" "x = u *🪙R a + v *🪙R b"
    by auto
  have "a convex hull insert a S" "b convex hull insert a S"
    using hull_mono[of S "insert a S" convex] hull_mono[of "{a}" "insert a S" convex] and obt(4)
    by auto
  then show "x convex hull insert a S"
    unfolding obt(5) using obt(1-3)
    by (rule convexD [OF convex_convex_hull])
next
  show "convex ?hull"
  proof (rule convexI)
    fix x y u v
    assume as: "(0::real) u" "0 v" "u + v = 1" and x: "x ?hull" and y: "y ?hull"
    from x obtain u1 v1 b1 where
      obt1: "u10" "v10" "u1 + v1 = 1" "b1 convex hull S" and xeq: "x = u1 *🪙R a + v1 *🪙R b1"
      by auto
    from y obtain u2 v2 b2 where
      obt2: "u20" "v20" "u2 + v2 = 1" "b2 convex hull S" and yeq: "y = u2 *🪙R a + v2 *🪙R b2"
      by auto
    have *: "(x::'a) s1 s2. x - s1 *🪙R x - s2 *🪙R x = ((1::real) - (s1 + s2)) *🪙R x"
      by (auto simp: algebra_simps)
    have "b convex hull S. u *🪙R x + v *🪙R y =

      (u * u1) *🪙R a + (v * u2) *🪙R a + (b - (u * u1) *🪙R b - (v * u2) *🪙R b)"
    proof (cases "u * v1 + v * v2 = 0")
      case True
      have *: "(x::'a) s1 s2. x - s1 *🪙R x - s2 *🪙R x = ((1::real) - (s1 + s2)) *🪙R x"
        by (auto simp: algebra_simps)
      have eq0: "u * v1 = 0" "v * v2 = 0"
        using True mult_nonneg_nonneg[OF u0 v10] mult_nonneg_nonneg[OF v0 v20]
        by arith+
      then have "u * u1 + v * u2 = 1"
        using as(3) obt1(3) obt2(3) by auto
      then show ?thesis
        using "*" eq0 as obt1(4) xeq yeq by auto
    next
      case False
      have "1 - (u * u1 + v * u2) = (u + v) - (u * u1 + v * u2)"
        by (simp add: as(3))
      also have " = u * v1 + v * v2"
        by (smt (verit, ccfv_SIG) distrib_left mult_cancel_left1 obt1(3) obt2(3))
      finally have **:"1 - (u * u1 + v * u2) = u * v1 + v * v2" .
      let ?b = "((u * v1) / (u * v1 + v * v2)) *🪙R b1 + ((v * v2) / (u * v1 + v * v2)) *🪙R b2"
      have zeroes: "0 u * v1 + v * v2" "0 u * v1" "0 u * v1 + v * v2" "0 v * v2"
        using as obt1 obt2 by auto
      show ?thesis
      proof
        show "u *🪙R x + v *🪙R y = (u * u1) *🪙R a + (v * u2) *🪙R a + (?b - (u * u1) *??R ?b - (v * u2) *🪙R ?b)"
          unfolding xeq yeq * **
          using False by (auto simp: scaleR_left_distrib scaleR_right_distrib)
        show "?b convex hull S"
          using False mem_convex_alt obt1(4) obt2(4) zeroes(2) zeroes(4) by fastforce
      qed
    qed
    then obtain b where b: "b convex hull S" 
       "u *🪙R x + v *🪙R y = (u * u1) *🪙R a + (v * u2) *🪙R a + (b - (u * u1) *🪙R b - (v * u2) *🪙R b)" ..
    obtain u1: "u1 1" and u2: "u2 1"
      using obt1 obt2 by auto
    have "u1 * u + u2 * v max u1 u2 * u + max u1 u2 * v"
      by (smt (verit, ccfv_SIG) as mult_right_mono)
    also have " 1"
      unfolding distrib_left[symmetric] and as(3) using u1 u2 by auto
    finally have le1: "u1 * u + u2 * v 1" .    
    show "u *🪙R x + v *🪙R y ?hull"
    proof (intro CollectI exI conjI)
      show "0 u * u1 + v * u2"
        by (simp add: as obt1(1) obt2(1))
      show "0 1 - u * u1 - v * u2"
        by (simp add: le1 diff_diff_add mult.commute)
    qed (use b in auto simp: algebra_simps)
  qed
qed

lemma convex_hull_insert_alt:
   "convex hull (insert a S) =

     (if S = {} then {a}
      else {(1 - u) *🪙R a + u *🪙R x |x u. 0 u u 1 x convex hull S})"
  apply (simp add: convex_hull_insert)
  using diff_add_cancel diff_ge_0_iff_ge
  by (smt (verit, del_insts) Collect_cong) 

subsubsection🍋tag unimportant Explicit expression for convex hull

proposition convex_hull_indexed:
  fixes S :: "'a::real_vector set"
  shows "convex hull S =
    {y. k u x. (i{1::nat .. k}. 0 u i x i S)
                (sum u {1..k} = 1) (i = 1..k. u i *🪙R x i) = y}"
    (is "?xyz = ?hull")
proof (rule hull_unique [OF _ convexI])
  show "S ?hull" 
    by (clarsimp, rule_tac x=1 in exI, rule_tac x="λx. 1" in exI, auto)
next
  fix T
  assume "S T" "convex T"
  then show "?hull T"
    by (blast intro: convex_sum)
next
  fix x y u v
  assume uv: "0 u" "0 v" "u + v = (1::real)"
  assume xy: "x ?hull" "y ?hull"
  from xy obtain k1 u1 x1 where
    x [rule_format]: "i{1::nat..k1}. 0u1 i x1 i S" 
                      "sum u1 {Suc 0..k1} = 1" "(i = Suc 0..k1. u1 i *🪙R x1 i) = x"
    by auto
  from xy obtain k2 u2 x2 where
    y [rule_format]: "i{1::nat..k2}. 0u2 i x2 i S" 
                     "sum u2 {Suc 0..k2} = 1" "(i = Suc 0..k2. u2 i *🪙R x2 i) = y"
    by auto
  have *: "P (x::'a) y s t i. (if P i then s else t) *🪙R (if P i then x else y) = (if P i then s *🪙R x else t *🪙R y)"
          "{1..k1 + k2} {1..k1} = {1..k1}" "{1..k1 + k2} - {1..k1} = (λi. i + k1) ` {1..k2}"
    by auto
  have inj: "inj_on (λi. i + k1) {1..k2}"
    unfolding inj_on_def by auto
  let ?uu = "λi. if i {1..k1} then u * u1 i else v * u2 (i - k1)"
  let ?xx = "λi. if i {1..k1} then x1 i else x2 (i - k1)"
  show "u *🪙R x + v *🪙R y ?hull"
  proof (intro CollectI exI conjI ballI)
    show "0 ?uu i" "?xx i S" if "i {1..k1+k2}" for i
      using that by (auto simp add: le_diff_conv uv(1) x(1) uv(2) y(1))
    show "(i = 1..k1 + k2. ?uu i) = 1"  "(i = 1..k1 + k2. ?uu i *🪙R ?xx i) = u *🪙R x + v *🪙R y"
      unfolding * sum.If_cases[OF finite_atLeastAtMost[of 1 "k1 + k2"]]
        sum.reindex[OF inj] Collect_mem_eq o_def
      unfolding scaleR_scaleR[symmetric] scaleR_right.sum [symmetric] sum_distrib_left[symmetric]
      by (simp_all add: sum_distrib_left[symmetric]  x(2,3) y(2,3) uv(3))
  qed 
qed

lemma convex_hull_finite:
  fixes S :: "'a::real_vector set"
  assumes "finite S"
  shows "convex hull S = {y. u. (xS. 0 u x) sum u S = 1 sum (λx. u x *🪙R x) S = y}"
  (is "?HULL = _")
proof (rule hull_unique [OF _ convexI]; clarify)
  fix x
  assume "x S"
  then show "u. (xS. 0 u x) sum u S = 1 (xS. u x *🪙R x) = x"
    by (rule_tac x="λy. if x=y then 1 else 0" in exI) (auto simp: sum.delta'[OF assms] sum_delta''[OF assms])
next
  fix u v :: real
  assume uv: "0 u" "0 v" "u + v = 1"
  fix ux assume ux [rule_format]: "xS. 0 ux x" "sum ux S = (1::real)"
  fix uy assume uy [rule_format]: "xS. 0 uy x" "sum uy S = (1::real)"
  have "0 u * ux x + v * uy x" if "xS" for x
    by (simp add: that uv ux(1) uy(1))
  moreover
  have "(xS. u * ux x + v * uy x) = 1"
    unfolding sum.distrib and sum_distrib_left[symmetric] ux(2) uy(2)
    using uv(3) by auto
  moreover
  have "(xS. (u * ux x + v * uy x) *🪙R x) = u *🪙R (xS. ux x *🪙R x) + v *🪙R (xS. uy x *🪙R x)"
    unfolding scaleR_left_distrib sum.distrib scaleR_scaleR[symmetric] scaleR_right.sum [symmetric]
    by auto
  ultimately
  show "uc. (xS. 0 uc x) sum uc S = 1
             (xS. uc x *🪙R x) = u *🪙R (xS. ux x *🪙R x) + v *🪙R (xS. uy x *🪙R x)"
    by (rule_tac x="λx. u * ux x + v * uy x" in exI, auto)
qed (use assms in auto simp: convex_explicit)


subsubsection🍋tag unimportant Another formulation

text "Formalized by Lars Schewe."

lemma convex_hull_explicit:
  fixes p :: "'a::real_vector set"
  shows "convex hull p =
    {y. S u. finite S S p (xS. 0 u x) sum u S = 1 sum (λv. u v *🪙R v) S = y}"
  (is "?lhs = ?rhs")
proof (intro subset_antisym subsetI)
  fix x
  assume "x convex hull p"
  then obtain k u y where
    obt: "i{1::nat..k}. 0 u i y i p" "sum u {1..k} = 1" "(i = 1..k. u i *🪙R y i) = x"
    unfolding convex_hull_indexed by auto
  have fin: "finite {1..k}" by auto
  {
    fix j
    assume "j{1..k}"
    then have "y j p 0 sum u {i. Suc 0 i i k y i = y j}"
      by (metis (mono_tags, lifting) One_nat_def atLeastAtMost_iff mem_Collect_eq obt(1) sum_nonneg)
  }
  moreover have "(vy ` {1..k}. sum u {i {1..k}. y i = v}) = 1"
    unfolding sum.image_gen[OF fin, symmetric] using obt(2) by auto
  moreover have "(vy ` {1..k}. sum u {i {1..k}. y i = v} *🪙R v) = x"
    using sum.image_gen[OF fin, of "λi. u i *🪙R y i" y, symmetric]
    unfolding scaleR_left.sum using obt(3) by auto
  ultimately
  have "S u. finite S S p (xS. 0 u x) sum u S = 1 (vS. u v *🪙R v) = x"
    by (smt (verit, ccfv_SIG) imageE mem_Collect_eq obt(1) subsetI sum.cong sum.infinite sum_nonneg)
  then show "x ?rhs" by auto
next
  fix y
  assume "y ?rhs"
  then obtain S u where
    S: "finite S" "S p" "xS. 0 u x" "sum u S = 1" "(vS. u v *🪙R v) = y"
    by auto
  obtain f where f: "inj_on f {1..card S}" "f ` {1..card S} = S"
    using ex_bij_betw_nat_finite_1[OF S(1)] unfolding bij_betw_def by auto
  then have "0 u (f i)" "f i p" if "i {1..card S}" for i
    using S i {1..card S} by blast+
  moreover 
  {
    fix y
    assume "yS"
    then obtain i where "i{1..card S}" "f i = y"
      by (metis f(2) image_iff)
    then have "{x. Suc 0 x x card S f x = y} = {i}"
      using f(1) inj_onD by fastforce
    then have "(x{x {1..card S}. f x = y}. u (f x)) = u y"
      "(x{x {1..card S}. f x = y}. u (f x) *🪙R f x) = u y *🪙R y"
      by (simp_all add: sum_constant_scaleR f i = y)
  }
  then have "(x = 1..card S. u (f x)) = 1" "(i = 1..card S. u (f i) *🪙R f i) = y"
    by (metis (mono_tags, lifting) S(4,5) f sum.reindex_cong)+
  ultimately
  show "y convex hull p"
    unfolding convex_hull_indexed
    by (smt (verit, del_insts) mem_Collect_eq sum.cong)
qed


subsubsection🍋tag unimportant A stepping theorem for that expansion

lemma convex_hull_finite_step:
  fixes S :: "'a::real_vector set"
  assumes "finite S"
  shows
    "(u. (xinsert a S. 0 u x) sum u (insert a S) = w sum (λx. u x *🪙R x) (insert a S) = y)
       (v0. u. (xS. 0 u x) sum u S = w - v sum (λx. u x *🪙R x) S = y - v *🪙R a)"
  (is "?lhs = ?rhs")
proof (cases "a S")
  case True
  then have *: "insert a S = S" by auto
  show ?thesis
  proof
    assume ?lhs
    then show ?rhs
      unfolding * by force
  next
    have fin: "finite (insert a S)" using assms by auto
    assume ?rhs
    then obtain v u where uv: "v0" "xS. 0 u x" "sum u S = w - v" "(xS. u x *🪙R x) = y - v *🪙R a"
      by auto
    then show ?lhs
      using uv True assms
      apply (rule_tac x = "λx. (if a = x then v else 0) + u x" in exI)
      apply (auto simp: sum_clauses scaleR_left_distrib sum.distrib sum_delta''[OF fin])
      done
  qed
next
  case False
  show ?thesis
  proof
    assume ?lhs
    then obtain u where u: "xinsert a S. 0 u x" "sum u (insert a S) = w" "(xinsert a S. u x *🪙R x) = y"
      by auto
    then show ?rhs
      using u aS by (rule_tac x="u a" in exI) (auto simp: sum_clauses assms)
  next
    assume ?rhs
    then obtain v u where uv: "v0" "xS. 0 u x" "sum u S = w - v" "(xS. u x *🪙R x) = y - v *🪙R a"
      by auto
    moreover
    have "(xS. if a = x then v else u x) = sum u S"  "(xS. (if a = x then v else u x) *🪙R x) = (xS. u x *🪙R x)"
      using False by (auto intro!: sum.cong)
    ultimately show ?lhs
      using False by (rule_tac x="λx. if a = x then v else u x" in exI) (auto simp: sum_clauses(2)[OF assms])
  qed
qed


subsubsection🍋tag unimportant Hence some special cases

lemma convex_hull_2: "convex hull {a,b} = {u *🪙R a + v *🪙R b | u v. 0 u 0 v u + v = 1}"
       (is "?lhs = ?rhs")
proof -
  have **: "finite {b}" by auto
  have "x v u. [0 v; v 1; (1 - v) *🪙R b = x - v *🪙R a]
                ==> u v. x = u *🪙R a + v *🪙R b 0 u 0 v u + v = 1"
    by (metis add.commute diff_add_cancel diff_ge_0_iff_ge)
  moreover
  have "u v. [0 u; 0 v; u + v = 1]
               ==> p0. q. 0 q b q b = 1 - p q b *🪙R b = u *🪙R a + v *🪙R b - p *🪙R a"
    apply (rule_tac x=u in exI, simp)
    apply (rule_tac x="λx. v" in exI, simp)
    done
  ultimately show ?thesis
    using convex_hull_finite_step[OF **, of a 1]
    by (auto simp add: convex_hull_finite)
qed

lemma convex_hull_2_alt: "convex hull {a,b} = {a + u *🪙R (b - a) | u. 0 u u 1}"
  unfolding convex_hull_2
proof (rule Collect_cong)
  have *: "x y ::real. x + y = 1 x = 1 - y"
    by auto
  fix x
  show "(v u. x = v *🪙R a + u *🪙R b 0 v 0 u v + u = 1)
    (u. x = a + u *🪙R (b - a) 0 u u 1)"
    apply (simp add: *)
    by (rule ex_cong1) (auto simp: algebra_simps)
qed

lemma convex_hull_3:
  "convex hull {a,b,c} = { u *🪙R a + v *🪙R b + w *🪙R c | u v w. 0 u 0 v 0 w u + v + w = 1}"
proof -
  have fin: "finite {a,b,c}" "finite {b,c}" "finite {c}"
    by auto
  have *: "x y z ::real. x + y + z = 1 x = 1 - y - z"
    by (auto simp: field_simps)
  show ?thesis
    unfolding convex_hull_finite[OF fin(1)] and convex_hull_finite_step[OF fin(2)] and *
    unfolding convex_hull_finite_step[OF fin(3)]
    apply (rule Collect_cong, simp)
    apply auto
    apply (rule_tac x=va in exI)
    apply (rule_tac x="u c" in exI, simp)
    apply (rule_tac x="1 - v - w" in exI, simp)
    apply (rule_tac x=v in exI, simp)
    apply (rule_tac x="λx. w" in exI, simp)
    done
qed

lemma convex_hull_3_alt:
  "convex hull {a,b,c} = {a + u *🪙R (b - a) + v *🪙R (c - a) | u v. 0 u 0 v u + v 1}"
proof -
  have *: "x y z ::real. x + y + z = 1 x = 1 - y - z"
    by auto
  show ?thesis
    unfolding convex_hull_3
    apply (auto simp: *)
    apply (rule_tac x=v in exI)
    apply (rule_tac x=w in exI)
    apply (simp add: algebra_simps)
    apply (rule_tac x=u in exI)
    apply (rule_tac x=v in exI)
    apply (simp add: algebra_simps)
    done
qed


subsection🍋tag unimportant Relations among closure notions and corresponding hulls

lemma affine_imp_convex: "affine s ==> convex s"
  unfolding affine_def convex_def by auto

lemma convex_affine_hull [simp]: "convex (affine hull S)"
  by (simp add: affine_imp_convex)

lemma subspace_imp_convex: "subspace s ==> convex s"
  using subspace_imp_affine affine_imp_convex by auto

lemma convex_hull_subset_span: "(convex hull s) (span s)"
  by (metis hull_minimal span_superset subspace_imp_convex subspace_span)

lemma convex_hull_subset_affine_hull: "(convex hull s) (affine hull s)"
  by (metis affine_affine_hull affine_imp_convex hull_minimal hull_subset)

lemma aff_dim_convex_hull:
  fixes S :: "'n::euclidean_space set"
  shows "aff_dim (convex hull S) = aff_dim S"
  by (smt (verit) aff_dim_affine_hull aff_dim_subset convex_hull_subset_affine_hull hull_subset)


subsection Caratheodory's theorem

lemma convex_hull_caratheodory_aff_dim:
  fixes p :: "('a::euclidean_space) set"
  shows "convex hull p =
    {y. S u. finite S S p card S aff_dim p + 1
        (xS. 0 u x) sum u S = 1 sum (λv. u v *🪙R v) S = y}"
  unfolding convex_hull_explicit set_eq_iff mem_Collect_eq
proof (intro allI iffI)
  fix y
  let ?P = "λn. S u. finite S card S = n S p (xS. 0 u x)
    sum u S = 1 (vS. u v *🪙R v) = y"
  assume "S u. finite S S p (xS. 0 u x) sum u S = 1 (vS. u v *🪙R v) = y"
  then obtain N where "?P N" by auto
  then have "nN. (k¬ ?P k) ?P n"
    by (rule_tac ex_least_nat_le, auto)
  then obtain n where "?P n" and smallest: "k¬ ?P k"
    by blast
  then obtain S u where S: "finite S" "card S = n" "Sp" 
    and u: "xS. 0 u x" "sum u S = 1"  "(vS. u v *🪙R v) = y" by auto

  have "card S aff_dim p + 1"
  proof (rule ccontr, simp only: not_le)
    assume "aff_dim p + 1 < card S"
    then have "affine_dependent S"
      by (smt (verit) independent_card_le_aff_dim S(3))
    then obtain w v where wv: "sum w S = 0" "vS" "w v 0" "(vS. w v *🪙R v) = 0"
      using affine_dependent_explicit_finite[OF S(1)] by auto
    define i where "i = (λv. (u v) / (- w v)) ` {vS. w v < 0}"
    define t where "t = Min i"
    have "xS. w x < 0"
      by (smt (verit, best) S(1) sum_pos2 wv)
    then have "i {}" unfolding i_def by auto
    then have "t 0"
      using Min_ge_iff[of i 0] and S(1) u[unfolded le_less]
      unfolding t_def i_def
      by (auto simp: divide_le_0_iff)
    have t: "vS. u v + t * w v 0"
    proof
      fix v
      assume "v S"
      then have v: "0 u v"
        using u(1) by blast
      show "0 u v + t * w v"
      proof (cases "w v < 0")
        case False
        thus ?thesis using v t0 by auto
      next
        case True
        then have "t u v / (- w v)"
          using vSunfolding t_def i_def by (auto intro: Min_le)
        then show ?thesis
          unfolding real_0_le_add_iff
          using True neg_le_minus_divide_eq by auto
      qed
    qed
    obtain a where "a S" and "t = (λv. (u v) / (- w v)) a" and "w a < 0"
      using Min_in[OF _ i{}and S(1) unfolding i_def t_def by auto
    then have a: "a S" "u a + t * w a = 0" by auto
    have *: "f. sum f (S - {a}) = sum f S - ((f a)::'b::ab_group_add)"
      unfolding sum.remove[OF S(1) aSby auto
    have "(vS. u v + t * w v) = 1"
      by (metis add.right_neutral mult_zero_right sum.distrib sum_distrib_left u(2) wv(1))
    moreover have "(vS. u v *🪙R v + (t * w v) *🪙R v) - (u a *🪙R a + (t * w a) *🪙R a) = y"
      unfolding sum.distrib u(3) scaleR_scaleR[symmetric] scaleR_right.sum [symmetric] wv(4)
      using a(2) [THEN eq_neg_iff_add_eq_0 [THEN iffD2]] by simp
    ultimately have "?P (n - 1)"
      apply (rule_tac x="(S - {a})" in exI)
      apply (rule_tac x="λv. u v + t * w v" in exI)
      using S t a
      apply (auto simp: * scaleR_left_distrib)
      done
    then show False
      using smallest[THEN spec[where x="n - 1"]] by auto
  qed
  then show "S u. finite S S p card S aff_dim p + 1
      (xS. 0 u x) sum u S = 1 (vS. u v *🪙R v) = y"
    using S u by auto
qed auto

lemma caratheodory_aff_dim:
  fixes p :: "('a::euclidean_space) set"
  shows "convex hull p = {x. S. finite S S p card S aff_dim p + 1 x convex hull S}"
        (is "?lhs = ?rhs")
proof
  have "x S u. [finite S; S p; int (card S) aff_dim p + 1; xS. 0 u x; sum u S = 1]
                ==> (vS. u v *🪙R v) convex hull S"
    by (metis (mono_tags, lifting) convex_convex_hull convex_explicit hull_subset)
  then show "?lhs ?rhs"
    by (subst convex_hull_caratheodory_aff_dim, auto)
qed (use hull_mono in auto)

lemma convex_hull_caratheodory:
  fixes p :: "('a::euclidean_space) set"
  shows "convex hull p =
            {y. S u. finite S S p card S DIM('a) + 1
              (xS. 0 u x) sum u S = 1 sum (λv. u v *🪙R v) S = y}"
        (is "?lhs = ?rhs")
proof (intro set_eqI iffI)
  fix x
  assume "x ?lhs" then show "x ?rhs"
    unfolding convex_hull_caratheodory_aff_dim 
    using aff_dim_le_DIM [of p] by fastforce
qed (auto simp: convex_hull_explicit)

theorem caratheodory:
  "convex hull p =
    {x::'a::euclidean_space. S. finite S S p card S DIM('a) + 1 x convex hull S}"
proof safe
  fix x
  assume "x convex hull p"
  then obtain S u where "finite S" "S p" "card S DIM('a) + 1"
    "xS. 0 u x" "sum u S = 1" "(vS. u v *🪙R v) = x"
    unfolding convex_hull_caratheodory by auto
  then show "S. finite S S p card S DIM('a) + 1 x convex hull S"
    using convex_hull_finite by fastforce
qed (use hull_mono in force)

subsection🍋tag unimportant\<open>Some Properties of subset of standard basis

lemma affine_hull_substd_basis:
  assumes "d Basis"
  shows "affine hull (insert 0 d) = {x::'a::euclidean_space. iBasis. i d xi = 0}"
  (is "affine hull (insert 0 ?A) = ?B")
proof -
  have *: "A. (+) (0::'a) ` A = A" "A. (+) (- (0::'a)) ` A = A"
    by auto
  show ?thesis
    unfolding affine_hull_insert_span_gen span_substd_basis[OF assms,symmetric] * ..
qed

lemma affine_hull_convex_hull [simp]: "affine hull (convex hull S) = affine hull S"
  by (metis Int_absorb1 Int_absorb2 convex_hull_subset_affine_hull hull_hull hull_mono hull_subset)


subsection🍋tag unimportant Moving and scaling convex hulls

lemma convex_hull_set_plus:
  "convex hull (S + T) = convex hull S + convex hull T"
  by (simp add: set_plus_image linear_iff scaleR_right_distrib convex_hull_Times 
        flip: convex_hull_linear_image)

lemma translation_eq_singleton_plus: "(λx. a + x) ` T = {a} + T"
  unfolding set_plus_def by auto

lemma convex_hull_translation:
  "convex hull ((λx. a + x) ` S) = (λx. a + x) ` (convex hull S)"
  by (simp add: convex_hull_set_plus translation_eq_singleton_plus)

lemma convex_hull_scaling:
  "convex hull ((λx. c *🪙R x) ` S) = (λx. c *🪙R x) ` (convex hull S)"
  by (simp add: convex_hull_linear_image)

lemma convex_hull_affinity:
  "convex hull ((λx. a + c *🪙R x) ` S) = (λx. a + c *🪙R x) ` (convex hull S)"
  by (metis convex_hull_scaling convex_hull_translation image_image)


subsection🍋tag unimportant Convexity of cone hulls

lemma convex_cone_hull:
  assumes "convex S"
  shows "convex (cone hull S)"
proof (rule convexI)
  fix x y
  assume xy: "x cone hull S" "y cone hull S"
  then have "S {}"
    using cone_hull_empty_iff[of S] by auto
  fix u v :: real
  assume uv: "u 0" "v 0" "u + v = 1"
  then have *: "u *🪙R x cone hull S" "v *🪙R y cone hull S"
    by (simp_all add: cone_cone_hull mem_cone uv xy)
  then obtain cx :: real and xx
      and cy :: real and yy  where x: "u *🪙R x = cx *🪙R xx" "cx 0" "xx S" 
      and y: "v *🪙R y = cy *🪙R yy" "cy 0" "yy S"
    using cone_hull_expl[of S] by auto

  have "u *🪙R x + v *🪙R y cone hull S" if "cx + cy 0"
    using "*"(1) nless_le that x(2) y by fastforce
  moreover
  have "u *🪙R x + v *🪙R y cone hull S" if "cx + cy > 0"
  proof -
    have "(cx / (cx + cy)) *🪙R xx + (cy / (cx + cy)) *🪙R yy S"
      using assms mem_convex_alt[of S xx yy cx cy] x y that by auto
    then have "cx *🪙R xx + cy *🪙R yy cone hull S"
      using mem_cone_hull[of "(cx/(cx+cy)) *🪙R xx + (cy/(cx+cy)) *🪙R yy" S "cx+cy"cx+cy>0
      by (auto simp: scaleR_right_distrib)
    then show ?thesis
      using x y by auto
  qed
  moreover have "cx + cy 0 cx + cy > 0" by auto
  ultimately show "u *🪙R x + v *🪙R y cone hull S" by blast
qed

lemma cone_convex_hull:
  assumes "cone S"
  shows "cone (convex hull S)"
  by (metis (no_types, lifting) affine_hull_convex_hull affine_hull_eq_empty assms cone_iff convex_hull_scaling hull_inc)

section Conic sets and conic hull

definition conic :: "'a::real_vector set ==> bool"
  where "conic S x c. x S 0 c (c *🪙R x) S"

lemma conicD: "[conic S; x S; 0 c] ==> (c *🪙R x) S"
  by (meson conic_def)

lemma subspace_imp_conic: "subspace S ==> conic S"
  by (simp add: conic_def subspace_def)

lemma conic_empty [simp]: "conic {}"
  using conic_def by blast

lemma conic_UNIV: "conic UNIV"
  by (simp add: conic_def)

lemma conic_Inter: "(S. S F ==> conic S) ==> conic(F)"
  by (simp add: conic_def)

lemma conic_linear_image:
   "[conic S; linear f] ==> conic(f ` S)"
  by (smt (verit) conic_def image_iff linear.scaleR)

lemma conic_linear_image_eq:
   "[linear f; inj f] ==> conic (f ` S) conic S"
  by (smt (verit) conic_def conic_linear_image inj_image_mem_iff linear_cmul)

lemma conic_mul: "[conic S; x S; 0 c] ==> (c *🪙R x) S"
  using conic_def by blast

lemma conic_conic_hull: "conic(conic hull S)"
  by (metis (no_types, lifting) conic_Inter hull_def mem_Collect_eq)

lemma conic_hull_eq: "(conic hull S = S) conic S"
  by (metis conic_conic_hull hull_same)

lemma conic_hull_UNIV [simp]: "conic hull UNIV = UNIV"
  by simp

lemma conic_negations: "conic S ==> conic (image uminus S)"
  by (auto simp: conic_def image_iff)

lemma conic_span [iff]: "conic(span S)"
  by (simp add: subspace_imp_conic)

lemma conic_hull_explicit:
   "conic hull S = {c *🪙R x| c x. 0 c x S}"
  proof (rule hull_unique)
    show "S {c *🪙R x |c x. 0 c x S}"
      by (metis (no_types) cone_hull_expl hull_subset)
  show "conic {c *🪙R x |c x. 0 c x S}"
    using mult_nonneg_nonneg by (force simp: conic_def)
qed (auto simp: conic_def)

lemma conic_hull_as_image:
   "conic hull S = (λz. fst z *🪙R snd z) ` ({0..} × S)"
  by (force simp: conic_hull_explicit)

lemma conic_hull_linear_image:
   "linear f ==> conic hull f ` S = f ` (conic hull S)"
  by (force simp: conic_hull_explicit image_iff set_eq_iff linear_scale) 

lemma conic_hull_image_scale:
  assumes "x. x S ==> 0 < c x"
  shows   "conic hull (λx. c x *🪙R x) ` S = conic hull S"
proof
  show "conic hull (λx. c x *🪙R x) ` S conic hull S"
  proof (rule hull_minimal)
    show "(λx. c x *🪙R x) ` S conic hull S"
      using assms conic_hull_explicit by fastforce
  qed (simp add: conic_conic_hull)
  show "conic hull S conic hull (λx. c x *🪙R x) ` S"
  proof (rule hull_minimal)
    show "S conic hull (λx. c x *🪙R x) ` S"
    proof clarsimp
      fix x
      assume "x S"
      then have "x = inverse(c x) *🪙R c x *🪙R x"
        using assms by fastforce
      then show "x conic hull (λx. c x *🪙R x) ` S"
        by (smt (verit, best) x S assms conic_conic_hull conic_mul hull_inc image_eqI inverse_nonpositive_iff_nonpositive)
    qed
  qed (simp add: conic_conic_hull)
qed

lemma convex_conic_hull:
  assumes "convex S"
  shows "convex (conic hull S)"
proof (clarsimp simp add: conic_hull_explicit convex_alt)
  fix c x d y and u :: real
  assume 🍋"(0::real) c" "x S" "(0::real) d" "y S" "0 u" "u 1"
  show "c'' x''. ((1 - u) * c) *🪙R x + (u * d) *🪙R y = c'' *🪙R x'' 0 c'' x'' S"
  proof (cases "(1 - u) * c = 0")
    case True
    with 0 d y S\<open>0  u  
    show ?thesis by force
  next
    case False
    define ξ where  (1 - u) * c + u * d"
    have *: "c * u c"
      by (simp add: "🍋" mult_left_le)
    have "ξ > 0"
      using False 🍋 by (smt (verit, best) ξ_def split_mult_pos_le)
    then have **: "c + d * u = ξ + c * u"
      by (simp add: ξ_def mult.commute right_diff_distrib')
    show ?thesis
    proof (intro exI conjI)
      show "0 ξ"
        using 0 🚫ξ by auto
      show "((1 - u) * c) *🪙R x + (u * d) *🪙R y = ξ *🪙R (((1 - u) * c / ξ) *🪙R x + (u * d / ξ) *🪙R y)"
        using ξ > 0 by (simp add: algebra_simps diff_divide_distrib)
      show "((1 - u) * c / ξ) *🪙R x + (u * d / ξ) *🪙R y S"
        using 0 🚫ξ
        by (intro convexD [OF assms]) (auto simp: 🍋 field_split_simps * **)
    qed
  qed
qed

lemma conic_halfspace_le: "conic {x. a x 0}"
  by (auto simp: conic_def mult_le_0_iff)

lemma conic_halfspace_ge: "conic {x. a x 0}"
  by (auto simp: conic_def mult_le_0_iff)

lemma conic_hull_empty [simp]: "conic hull {} = {}"
  by (simp add: conic_hull_eq)

lemma conic_contains_0: "conic S ==> (0 S S {})"
  by (simp add: Convex.cone_def cone_contains_0 conic_def)

lemma conic_hull_eq_empty: "conic hull S = {} (S = {})"
  using conic_hull_explicit by fastforce

lemma conic_sums: "[conic S; conic T] ==> conic (x S. y T. {x + y})"
  by (simp add: conic_def) (metis scaleR_right_distrib)

lemma conic_Times: "[conic S; conic T] ==> conic(S × T)"
  by (auto simp: conic_def)

lemma conic_Times_eq:
   "conic(S × T) S = {} T = {} conic S conic T" (is "?lhs = ?rhs")
proof
  show "?lhs ==> ?rhs"
    by (force simp: conic_def)
  show "?rhs ==> ?lhs"
    by (force simp: conic_Times)
qed

lemma conic_hull_0 [simp]: "conic hull {0} = {0}"
  by (simp add: conic_hull_eq subspace_imp_conic)

lemma conic_hull_contains_0 [simp]: "0 conic hull S (S {})"
  by (simp add: conic_conic_hull conic_contains_0 conic_hull_eq_empty)

lemma conic_hull_eq_sing:
  "conic hull S = {x} S = {0} x = 0"
proof
  show "conic hull S = {x} ==> S = {0} x = 0"
    by (metis conic_conic_hull conic_contains_0 conic_def conic_hull_eq hull_inc insert_not_empty singleton_iff)
qed simp

lemma conic_hull_Int_affine_hull:
  assumes "T S" "0 affine hull S"
  shows "(conic hull T) (affine hull S) = T"
proof -
  have TaffS: "T affine hull S"
    using T S hull_subset by fastforce
  moreover
  have "conic hull T affine hull S T"
  proof (clarsimp simp: conic_hull_explicit)
    fix c x
    assume "c *🪙R x affine hull S"
      and "0 c"
      and "x T"
    show "c *🪙R x T"
    proof (cases "c=1")
      case True
      then show ?thesis
        by (simp add: x T)
    next
      case False
      then have "x /🪙R (1 - c) = x + (c * inverse (1 - c)) *🪙R x"
        by (smt (verit, ccfv_SIG) diff_add_cancel mult.commute real_vector_affinity_eq scaleR_collapse scaleR_scaleR)
      then have "0 = inverse(1 - c) *🪙R c *🪙R x + (1 - inverse(1 - c)) *🪙R x"
        by (simp add: algebra_simps)
      then have "0 affine hull S"
        by (smt (verit) c *🪙R x affine hull S x T affine_affine_hull TaffS in_mono mem_affine)
      then show ?thesis
        using assms by auto        
    qed
  qed
  ultimately show ?thesis
    by (auto simp: hull_inc)
qed


section Convex cones and corresponding hulls

definition convex_cone :: "'a::real_vector set ==> bool"
  where "convex_cone λS. S {} convex S conic S"

lemma convex_cone_iff:
   "convex_cone S
        0 S (x S. y S. x + y S) (x S. c0. c *🪙R x S)"
    by (metis cone_def conic_contains_0 conic_def convex_cone convex_cone_def)

lemma convex_cone_add: "[convex_cone S; x S; y S] ==> x+y S"
  by (simp add: convex_cone_iff)

lemma convex_cone_scaleR: "[convex_cone S; 0 c; x S] ==> c *🪙R x S"
  by (simp add: convex_cone_iff)

lemma convex_cone_nonempty: "convex_cone S ==> S {}"
  by (simp add: convex_cone_def)

lemma convex_cone_linear_image:
   "convex_cone S linear f ==> convex_cone(f ` S)"
  by (simp add: conic_linear_image convex_cone_def convex_linear_image)

lemma convex_cone_linear_image_eq:
   "[linear f; inj f] ==> (convex_cone(f ` S) convex_cone S)"
  by (simp add: conic_linear_image_eq convex_cone_def)

lemma convex_cone_halfspace_ge: "convex_cone {x. a x 0}"
  by (simp add: convex_cone_iff inner_simps(2))

lemma convex_cone_halfspace_le: "convex_cone {x. a x 0}"
  by (simp add: convex_cone_iff inner_right_distrib mult_nonneg_nonpos)

lemma convex_cone_contains_0: "convex_cone S ==> 0 S"
  using convex_cone_iff by blast

lemma convex_cone_Inter:
   "(S. S f ==> convex_cone S) ==> convex_cone( f)"
  by (simp add: convex_cone_iff)

lemma convex_cone_convex_cone_hull: "convex_cone(convex_cone hull S)"
  by (metis (no_types, lifting) convex_cone_Inter hull_def mem_Collect_eq)

lemma convex_convex_cone_hull: "convex(convex_cone hull S)"
  by (meson convex_cone_convex_cone_hull convex_cone_def)

lemma conic_convex_cone_hull: "conic(convex_cone hull S)"
  by (metis convex_cone_convex_cone_hull convex_cone_def)

lemma convex_cone_hull_nonempty: "convex_cone hull S {}"
  by (simp add: convex_cone_convex_cone_hull convex_cone_nonempty)

lemma convex_cone_hull_contains_0: "0 convex_cone hull S"
  by (simp add: convex_cone_contains_0 convex_cone_convex_cone_hull)

lemma convex_cone_hull_add:
   "[x convex_cone hull S; y convex_cone hull S] ==> x + y convex_cone hull S"
  by (simp add: convex_cone_add convex_cone_convex_cone_hull)

lemma convex_cone_hull_mul:
   "[x convex_cone hull S; 0 c] ==> (c *🪙R x) convex_cone hull S"
  by (simp add: conic_convex_cone_hull conic_mul)

thm convex_sums
lemma convex_cone_sums:
   "[convex_cone S; convex_cone T] ==> convex_cone (x S. y T. {x + y})"
  by (simp add: convex_cone_def conic_sums convex_sums)

lemma convex_cone_Times:
   "[convex_cone S; convex_cone T] ==> convex_cone(S × T)"
  by (simp add: conic_Times convex_Times convex_cone_def)

lemma convex_cone_Times_D1: "convex_cone (S × T) ==> convex_cone S"
  by (metis Times_empty conic_Times_eq convex_cone_def convex_convex_hull convex_hull_Times hull_same times_eq_iff)

lemma convex_cone_Times_eq:
   "convex_cone(S × T) convex_cone S convex_cone T" 
proof (cases "S={} T={}")
  case True
  then show ?thesis 
    by (auto dest: convex_cone_nonempty)
next
  case False
  then have "convex_cone (S × T) ==> convex_cone T"
    by (metis conic_Times_eq convex_cone_def convex_convex_hull convex_hull_Times hull_same times_eq_iff)
  then show ?thesis
    using convex_cone_Times convex_cone_Times_D1 by blast 
qed


lemma convex_cone_hull_Un:
  "convex_cone hull(S T) = (x convex_cone hull S. y convex_cone hull T. {x + y})"
  (is "?lhs = ?rhs")
proof
  show "?lhs ?rhs"
  proof (rule hull_minimal)
    show "S T (xconvex_cone hull S. yconvex_cone hull T. {x + y})"
      apply (clarsimp simp: subset_iff)
      by (metis add_0 convex_cone_hull_contains_0 group_cancel.rule0 hull_inc)
    show "convex_cone (xconvex_cone hull S. yconvex_cone hull T. {x + y})"
      by (simp add: convex_cone_convex_cone_hull convex_cone_sums)
  qed
next
  show "?rhs ?lhs"
    by clarify (metis convex_cone_hull_add hull_mono le_sup_iff subsetD subsetI)
qed

lemma convex_cone_singleton [iff]: "convex_cone {0}"
  by (simp add: convex_cone_iff)

lemma convex_hull_subset_convex_cone_hull:
   "convex hull S convex_cone hull S"
  by (simp add: convex_convex_cone_hull hull_minimal hull_subset)

lemma conic_hull_subset_convex_cone_hull:
   "conic hull S convex_cone hull S"
  by (simp add: conic_convex_cone_hull hull_minimal hull_subset)

lemma subspace_imp_convex_cone: "subspace S ==> convex_cone S"
  by (simp add: convex_cone_iff subspace_def)

lemma convex_cone_span: "convex_cone(span S)"
  by (simp add: subspace_imp_convex_cone)

lemma convex_cone_negations:
   "convex_cone S ==> convex_cone (image uminus S)"
  by (simp add: convex_cone_linear_image module_hom_uminus)

lemma subspace_convex_cone_symmetric:
   "subspace S convex_cone S (x S. -x S)"
  by (smt (verit) convex_cone_iff scaleR_left.minus subspace_def subspace_neg)

lemma convex_cone_hull_separate_nonempty:
  assumes "S {}"
  shows "convex_cone hull S = conic hull (convex hull S)"   (is "?lhs = ?rhs")
proof
  show "?lhs ?rhs"
    by (metis assms conic_conic_hull convex_cone_def convex_conic_hull convex_convex_hull hull_subset subset_empty subset_hull)
  show "?rhs ?lhs"
    by (simp add: conic_convex_cone_hull convex_hull_subset_convex_cone_hull subset_hull)
qed

lemma convex_cone_hull_empty [simp]: "convex_cone hull {} = {0}"
  by (metis convex_cone_hull_contains_0 convex_cone_singleton hull_redundant hull_same)

lemma convex_cone_hull_separate:
   "convex_cone hull S = insert 0 (conic hull (convex hull S))"
proof(cases "S={}")
  case False
  then show ?thesis
    using convex_cone_hull_contains_0 convex_cone_hull_separate_nonempty by blast
qed auto

lemma convex_cone_hull_convex_hull_nonempty:
   "S {} ==> convex_cone hull S = (x convex hull S. c{0..}. {c *🪙R x})"
  by (force simp: convex_cone_hull_separate_nonempty conic_hull_as_image)

lemma convex_cone_hull_convex_hull:
   "convex_cone hull S = insert 0 (x convex hull S. c{0..}. {c *🪙R x})"
  by (force simp: convex_cone_hull_separate conic_hull_as_image)

lemma convex_cone_hull_linear_image:
   "linear f ==> convex_cone hull (f ` S) = image f (convex_cone hull S)"
  by (metis (no_types, lifting) conic_hull_linear_image convex_cone_hull_separate convex_hull_linear_image image_insert linear_0)

subsection Radon's theorem

text "Formalized by Lars Schewe."

lemma Radon_ex_lemma:
  assumes "finite c" "affine_dependent c"
  shows "u. sum u c = 0 (vc. u v 0) sum (λv. u v *🪙R v) c = 0"
  using affine_dependent_explicit_finite assms by blast

lemma Radon_s_lemma:
  assumes "finite S"
    and "sum f S = (0::real)"
  shows "sum f {xS. 0 < f x} = - sum f {xS. f x < 0}"
proof -
  have "x. (if f x < 0 then f x else 0) + (if 0 < f x then f x else 0) = f x"
    by auto
  then show ?thesis
    using assms by (simp add: sum.inter_filter flip: sum.distrib add_eq_0_iff)
qed

lemma Radon_v_lemma:
  assumes "finite S"
    and "sum f S = 0"
    and "x. g x = (0::real) f x = (0::'a::euclidean_space)"
  shows "(sum f {xS. 0 < g x}) = - sum f {xS. g x < 0}"
proof -
  have "x. (if 0 < g x then f x else 0) + (if g x < 0 then f x else 0) = f x"
    using assms by auto
  then show ?thesis
    using assms by (simp add: sum.inter_filter eq_neg_iff_add_eq_0 flip: sum.distrib add_eq_0_iff)
qed

lemma Radon_partition:
  assumes "finite C" "affine_dependent C"
  shows "M P. M P = {} M P = C (convex hull M) (convex hull P) {}"
proof -
  obtain u v where uv: "sum u C = 0" "vC" "u v 0"  "(vC. u v *🪙R v) = 0"
    using Radon_ex_lemma[OF assms] by auto
  have fin: "finite {x C. 0 < u x}" "finite {x C. 0 > u x}"
    using assms(1) by auto
  define z  where "z = inverse (sum u {xC. u x > 0}) *🪙R sum (λx. u x *🪙R x) {xC. u x > 0}"
  have "sum u {x C. 0 < u x} 0"
  proof (cases "u v 0")
    case False
    then have "u v < 0" by auto
    then show ?thesis
      by (smt (verit) assms(1) fin(1) mem_Collect_eq sum.neutral_const sum_mono_inv uv)
  next
    case True
    with fin uv show "sum u {x C. 0 < u x} 0"
      by (smt (verit) fin(1) mem_Collect_eq sum_nonneg_eq_0_iff uv)
  qed
  then have *: "sum u {xC. u x > 0} > 0"
    unfolding less_le by (metis (no_types, lifting) mem_Collect_eq sum_nonneg)
  moreover have "sum u ({x C. 0 < u x} {x C. u x < 0}) = sum u C"
    "(x{x C. 0 < u x} {x C. u x < 0}. u x *🪙R x) = (xC. u x *🪙R x)"
    using assms(1)
    by (rule_tac[!] sum.mono_neutral_left, auto)
  then have "sum u {x C. 0 < u x} = - sum u {x C. 0 > u x}"
    "(x{x C. 0 < u x}. u x *🪙R x) = - (x{x C. 0 > u x}. u x *🪙R x)"
    unfolding eq_neg_iff_add_eq_0
    using uv(1,4)
    by (auto simp: sum.union_inter_neutral[OF fin, symmetric])
  moreover have "x{v C. u v < 0}. 0 inverse (sum u {x C. 0 < u x}) * - u x"
    using * by (fastforce intro: mult_nonneg_nonneg)
  ultimately have "z convex hull {v C. u v 0}"
    unfolding convex_hull_explicit mem_Collect_eq
    apply (rule_tac x="{v C. u v < 0}" in exI)
    apply (rule_tac x="λy. inverse (sum u {xC. u x > 0}) * - u y" in exI)
    using assms(1) unfolding scaleR_scaleR[symmetric] scaleR_right.sum [symmetric] 
    by (auto simp: z_def sum_negf sum_distrib_left[symmetric])
  moreover have "x{v C. 0 < u v}. 0 inverse (sum u {x C. 0 < u x}) * u x"
    using * by (fastforce intro: mult_nonneg_nonneg)
  then have "z convex hull {v C. u v > 0}"
    unfolding convex_hull_explicit mem_Collect_eq
    apply (rule_tac x="{v C. 0 < u v}" in exI)
    apply (rule_tac x="λy. inverse (sum u {xC. u x > 0}) * u y" in exI)
    using assms(1)
    unfolding scaleR_scaleR[symmetric] scaleR_right.sum [symmetric]
    using * by (auto simp: z_def sum_negf sum_distrib_left[symmetric])
  ultimately show ?thesis
    apply (rule_tac x="{vC. u v 0}" in exI)
    apply (rule_tac x="{vC. u v > 0}" in exI, auto)
    done
qed

theorem Radon:
  assumes "affine_dependent c"
  obtains M P where "M c" "P c" "M P = {}" "(convex hull M) (convex hull P) {}"
  by (smt (verit) Radon_partition affine_dependent_explicit affine_dependent_explicit_finite assms le_sup_iff)


subsection Helly's theorem

lemma Helly_induct:
  fixes F :: "'a::euclidean_space set set"
  assumes "card F = n"
    and "n DIM('a) + 1"
    and "SF. convex S" "TF. card T = DIM('a) + 1 T {}"
  shows "F {}"
  using assms
proof (induction n arbitrary: F)
  case 0
  then show ?case by auto
next
  case (Suc n)
  have "finite F"
    using card F = Suc n by (auto intro: card_ge_0_finite)
  show "F {}"
  proof (cases "n = DIM('a)")
    case True
    then show ?thesis
      by (simp add: Suc.prems)
  next
    case False
    have "(F - {S}) {}" if "S F" for S
    proof (rule Suc.IH[rule_format])
      show "card (F - {S}) = n"
        by (simp add: Suc.prems(1) finite F that)
      show "DIM('a) + 1 n"
        using False Suc.prems(2) by linarith
      show "t. [t F - {S}; card t = DIM('a) + 1] ==> t {}"
        by (simp add: Suc.prems(4) subset_Diff_insert)
    qed (use Suc in auto)
    then have "SF. x. x (F - {S})"
      by blast
    then obtain X where X: "S. SF ==> X S (F - {S})"
      by metis
    show ?thesis
    proof (cases "inj_on X F")
      case False
      then obtain S T where "ST" and st: "SF" "TF" "X S = X T"
        unfolding inj_on_def by auto
      then have *: "F = (F - {S}) (F - {T})" by auto
      show ?thesis
        by (metis "*" X disjoint_iff_not_equal st)
    next
      case True
      then obtain M P where mp: "M P = {}" "M P = X ` F" "convex hull M convex hull P {}"
        using Radon_partition[of "X ` F"and affine_dependent_biggerset[of "X ` F"]
        unfolding card_image[OF True] and card F = Suc n
        using Suc(3) finite F and False
        by auto
      have "M X ` F" "P X ` F"
        using mp(2) by auto
      then obtain G H where gh:"M = X ` G" "P = X ` H" "G F" "H F"
        unfolding subset_image_iff by auto
      then have "F (G H) = F" by auto
      then have F"F = G H"
        using inj_on_Un_image_eq_iff[of X F "G H"and True
        unfolding mp(2)[unfolded image_Un[symmetric] gh]
        by auto
      have *: "G H = {}"
        using gh local.mp(1) by blast
      have "convex hull (X ` H) G" "convex hull (X ` G) H"
        by (rule hull_minimal; use X * F in auto simp: Suc.prems(3) convex_Inter)+
      then show ?thesis
        unfolding F using mp(3)[unfolded gh] by blast
    qed
  qed 
qed

theorem Helly:
  fixes F :: "'a::euclidean_space set set"
  assumes "card F DIM('a) + 1" "sF. convex s"
    and "t. [tF; card t = DIM('a) + 1] ==> t {}"
  shows "F {}"
  using Helly_induct assms by blast

subsection Epigraphs of convex functions

definition🍋tag important "epigraph S (f :: _ ==> real) = {xy. fst xy S f (fst xy) snd xy}"

lemma mem_epigraph: "(x, y) epigraph S f x S f x y"
  unfolding epigraph_def by auto

lemma convex_epigraph: "convex (epigraph S f) convex_on S f"
proof safe
  assume L: "convex (epigraph S f)"
  then show "convex_on S f"
    by (fastforce simp: convex_def convex_on_def epigraph_def)
next
  assume "convex_on S f"
  then show "convex (epigraph S f)"
    unfolding convex_def convex_on_def epigraph_def
    apply safe
     apply (rule_tac [2] y="u * f a + v * f aa" in order_trans)
      apply (auto intro!:mult_left_mono add_mono)
    done
qed

lemma convex_epigraphI: "convex_on S f ==> convex (epigraph S f)"
  unfolding convex_epigraph by auto

lemma convex_epigraph_convex: "convex_on S f convex(epigraph S f)"
  by (simp add: convex_epigraph)


subsubsection🍋tag unimportant Use this to derive general bound property of convex function

lemma convex_on:
  assumes "convex S"
  shows "convex_on S f
    (k u x. (i{1..k::nat}. 0 u i x i S) sum u {1..k} = 1
      f (sum (λi. u i *🪙R x i) {1..k}) sum (λi. u i * f(x i)) {1..k})"
  (is "?lhs = (k u x. ?rhs k u x)")
proof
  assume ?lhs 
  then have 🍋"convex {xy. fst xy S f (fst xy) snd xy}"
    by (metis assms convex_epigraph epigraph_def)
  show "k u x. ?rhs k u x"
  proof (intro allI)
    fix k u x
    show "?rhs k u x"
      using 🍋
      unfolding  convex mem_Collect_eq fst_sum snd_sum 
      apply safe
      apply (drule_tac x=k in spec)
      apply (drule_tac x=u in spec)
      apply (drule_tac x="λi. (x i, f (x i))" in spec)
      apply simp
      done
  qed
next
  assume "k u x. ?rhs k u x"
  then show ?lhs
  unfolding convex_epigraph_convex convex epigraph_def Ball_def mem_Collect_eq fst_sum snd_sum
  using assms[unfolded convex] apply clarsimp
  apply (rule_tac y="i = 1..k. u i * f (fst (x i))" in order_trans)
  by (auto simp add: mult_left_mono intro: sum_mono)
qed


subsection🍋tag unimportant A bound within a convex hull

lemma convex_on_convex_hull_bound:
  assumes "convex_on (convex hull S) f"
    and "xS. f x b"
  shows "x convex hull S. f x b"
proof
  fix x
  assume "x convex hull S"
  then obtain k u v where
    u: "i{1..k::nat}. 0 u i v i S" "sum u {1..k} = 1" "(i = 1..k. u i *🪙R v i) = x"
    unfolding convex_hull_indexed mem_Collect_eq by auto
  have "(i = 1..k. u i * f (v i)) b"
    using sum_mono[of "{1..k}" "λi. u i * f (v i)" "λi. u i * b"]
    unfolding sum_distrib_right[symmetric] u(2) mult_1
    using assms(2) mult_left_mono u(1) by blast
  then show "f x b"
    using assms(1)[unfolded convex_on[OF convex_convex_hull], rule_format, of k u v]
    using hull_inc u by fastforce
qed

lemma convex_set_plus:
  assumes "convex S" and "convex T" shows "convex (S + T)"
  by (metis assms convex_hull_eq convex_hull_set_plus)

lemma convex_set_sum:
  assumes "i. i A ==> convex (B i)"
  shows "convex (iA. B i)"
  using assms
  by (induction A rule: infinite_finite_induct) (auto simp: convex_set_plus)

lemma finite_set_sum:
  assumes "iA. finite (B i)" shows "finite (iA. B i)"
  using assms
  by (induction A rule: infinite_finite_induct) (auto simp: finite_set_plus)

lemma box_eq_set_sum_Basis:
  "{x. iBasis. xi B i} = (iBasis. (λx. x *🪙R i) ` (B i))" (is "?lhs = ?rhs")
proof -
  have "x. iBasis. x i B i ==>
         s. x = sum s Basis (iBasis. s i (λx. x *🪙R i) ` B i)"
    by (metis (mono_tags, lifting) euclidean_representation image_iff)
  moreover
  have "sum f Basis i B i" if "i Basis" and f: "iBasis. f i (λx. x *🪙R i) ` B i" for i f
  proof -
    have "(xBasis - {i}. f x i) = 0"
    proof (intro strip sum.neutral)
      show "f x i = 0" if "x Basis - {i}" for x
        using that f i Basis inner_Basis that by fastforce
    qed
    then have "(xBasis. f x i) = f i i"
      by (metis (no_types) i Basis add.right_neutral sum.remove [OF finite_Basis])
    then have "(xBasis. f x i) B i"
      using f that(1) by auto
    then show ?thesis
      by (simp add: inner_sum_left)
  qed
  ultimately show ?thesis
    by (subst set_sum_alt [OF finite_Basis]) auto
qed

lemma convex_hull_set_sum:
  "convex hull (iA. B i) = (iA. convex hull (B i))"
  by (induction A rule: infinite_finite_induct) (auto simp: convex_hull_set_plus)

end

Messung V0.5 in Prozent
C=95 H=68 G=82

¤ Dauer der Verarbeitung: 0.112 Sekunden  (vorverarbeitet am  2026-04-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge