Theory Polygon_Convex_Lemmas

theory Polygon_Convex_Lemmas
imports
  Polygon_Lemmas
  Linepath_Collinearity

begin

section "Misc. Convex Polygon Properties"

lemma polygon_path_image_subset_convex:
  assumes "length vts > 0"
  shows "path_image (make_polygonal_path vts) ⊆ convex hull (set vts)" (is "path_image ?p ⊆ ?S")
  using assms
proof(induct vts rule: make_polygonal_path.induct)
  case 1
  then show ?case by simp
next
  case (2 a)
  then show ?case by auto
next
  case (3 a b)
  show ?case (is "path_image ?p ⊆ ?S")
  proof(rule subsetI)
    fix x
    assume x_in_path_image: "x ∈ path_image ?p"
    then have "x ∈ path_image (linepath a b)" by auto
    thus "x ∈ ?S"
      unfolding path_image_def linepath_def
      by (smt (verit, ccfv_SIG) ‹x ∈ path_image (linepath a b)› convex_alt convex_convex_hull hull_subset in_mono in_segment(1) linepath_image_01 list.set_intros(1) path_image_def set_subset_Cons)
  qed
next
  case (4 a b c tl)
  let ?vts = "a # b # c # tl"
  show ?case (is "path_image ?p ⊆ ?S")
  proof(rule subsetI)
    fix x
    assume x_in_path_image: "x ∈ path_image ?p"
    show "x ∈ ?S"
    proof cases
      assume "x ∈ set ?vts"
      thus ?thesis by (simp add: hull_inc)
    next
      assume x_notin: "x ∉ set ?vts"
      obtain u where p_u: "u ∈ {0..1} ∧ ?p u = x"
        using x_in_path_image unfolding path_image_def by auto
      then have p_head_tail: "?p = (linepath a b) +++ make_polygonal_path (b # c # tl)"
        by auto
      have abc_in_S: "set ?vts ⊆ convex hull (set ?vts)" by (simp add: hull_subset)
      { assume u_assm: "u ≤ 1/2"
        then have "?p u = (1 - 2 * u) *R a + (2 * u) *R b"
          using p_head_tail unfolding linepath_def joinpaths_def
          by presburger
        hence "x ∈ ?S"
          using abc_in_S convexD_alt[of ?S a b "2 * u"] u_assm p_u by simp
      } moreover
      { assume u_assm: "u > 1/2"
        then have "x = (make_polygonal_path (b # c # tl) (2 * u - 1))" (is "x = (?p' (2 * u - 1))")
          using p_head_tail p_u unfolding linepath_def joinpaths_def by auto
        moreover have "0 < (2 * u - 1)" using u_assm by linarith
        ultimately have "x ∈ path_image ?p'"
          using p_u by (simp add: path_image_def)
        moreover have "path_image ?p' ⊆ convex hull (set (b # c # tl))" using 4(1) by auto
        moreover have "... ⊆ convex hull (set (a # b # c # tl))"
          by (meson hull_mono set_subset_Cons)
        ultimately have "x ∈ ?S" by auto
      }
      ultimately show ?thesis by linarith
    qed
  qed
qed
  
lemma convex_contains_simple_closed_path_imp_contains_path_inside:
  assumes "convex S"
  assumes "simple_path p ∧ closed_path p"
  assumes "path_image p ⊆ S"
  shows "path_inside p ⊆ S"
  by (metis (no_types, opaque_lifting) Compl_subset_Compl_iff Un_subset_iff assms(1) assms(3) boolean_algebra_class.boolean_algebra.double_compl outside_subset_convex path_inside_def union_with_inside)

lemma convex_polygon_is_convex_hull:
  assumes "polygon p"
  assumes "convex (path_inside p ∪ path_image p)"
  assumes "p = make_polygonal_path vts"
  shows "convex hull (set vts) = path_inside p ∪ path_image p" (is "?hull = ?poly")
proof-
  have "?hull ⊆ ?poly"
  proof(rule subsetI)
    fix x
    assume "x ∈ ?hull"
    moreover have "∀H. (convex H ∧ (set vts) ⊆ H) ⟶ ?hull ⊆ H" by (simp add: hull_minimal)
    moreover have "convex (?poly) ∧ (set vts) ⊆ ?poly"
      using assms(2) assms(3) vertices_on_path_image by auto
    ultimately show "x ∈ ?poly" by auto
  qed
  moreover have "?hull ⊇ ?poly"
  proof(rule subsetI)
    fix x
    assume "x ∈ ?poly"
    moreover have "path_image p ⊆ ?hull"
      using polygon_path_image_subset_convex[of vts] polygon_at_least_3_vertices assms
      by force
    moreover from calculation have "path_inside p ⊆ ?hull"
      using convex_contains_simple_closed_path_imp_contains_path_inside polygon_def assms(1)
      by auto
    ultimately show "x ∈ ?hull" by auto
  qed
  ultimately show ?thesis by auto
qed

lemma convex_polygon_inside_is_convex_hull_interior:
  assumes "polygon p"
  assumes "convex (path_inside p)"
  assumes "p = make_polygonal_path vts"
  shows "interior (convex hull (set vts)) = path_inside p"
  by (metis (no_types, lifting) assms closure_Un_frontier convex_closure convex_interior_closure convex_polygon_is_convex_hull inside_outside_def inside_outside_polygon interior_eq)

lemma convex_polygon_inside_is_convex_hull_interior2:
  assumes "polygon p"
  assumes "convex (path_inside p ∪ path_image p)"
  assumes "p = make_polygonal_path vts"
  shows "interior (convex hull (set vts)) = path_inside p"
  using assms closure_Un_frontier convex_closure convex_interior_closure convex_polygon_is_convex_hull inside_outside_def inside_outside_polygon interior_eq
  by (smt (verit, best) List.finite_set compact_eq_bounded_closed finite_imp_compact_convex_hull frontier_complement inside_frontier_eq_interior outside_inside path_inside_def path_outside_def sup_commute) 

lemma polygon_convex_iff:
  assumes "polygon p"
  shows "convex (path_inside p) ⟷ convex (path_inside p ∪ path_image p)"
  using convex_polygon_inside_is_convex_hull_interior
  using convex_polygon_inside_is_convex_hull_interior2
  by (metis Jordan_inside_outside_real2 closed_path_def assms closure_Un_frontier convex_closure convex_interior convex_polygon_is_convex_hull path_inside_def polygon_def polygon_to_polygonal_path)

lemma convex_polygon_frontier_is_path_image:
  assumes "polygon_of p vts"
  assumes "convex (path_inside p)"
  shows "frontier (convex hull (set vts)) = path_image p"
  using assms
  unfolding frontier_def polygon_of_def
  by (metis (no_types, lifting) Jordan_inside_outside_real2 closed_path_def convex_closure_interior convex_convex_hull convex_polygon_inside_is_convex_hull_interior frontier_def interior_interior path_inside_def polygon_def)

lemma convex_polygon_frontier_is_path_image2:
  assumes "polygon p"
  assumes "convex (path_inside p)"
  shows "frontier (path_image p ∪ path_inside p) = path_image p"
  using assms
  by (simp add: Jordan_inside_outside_real2 closed_path_def path_inside_def polygon_def union_with_inside)

lemma convex_polygon_frontier_is_path_image3:
  assumes "polygon p"
  assumes "convex (path_image p ∪ path_inside p)"
  shows "frontier (path_image p ∪ path_inside p) = path_image p"
  using assms polygon_convex_iff
  by (simp add: convex_polygon_frontier_is_path_image2 sup_commute)

lemma polygon_frontier_is_path_image:
  assumes "polygon p"
  shows "frontier (path_inside p) = path_image p"
  using inside_outside_polygon unfolding inside_outside_def
  using assms by presburger

lemma convex_path_inside_means_convex_polygon:
  assumes "polygon p"
  assumes "frontier (convex hull (set vts)) = path_image p"
  shows "convex (path_inside p)"
  by (metis List.finite_set assms(2) convex_convex_hull convex_interior finite_imp_bounded_convex_hull inside_frontier_eq_interior path_inside_def)

lemma convex_hull_of_polygon_is_convex_hull_of_vts:
 assumes "polygon_of p vts"
 shows "convex hull (path_image p ∪ path_inside p) = convex hull (set vts)"
proof - 
  have len_vts: "length vts > 0"
    by (metis assms card.empty empty_set length_greater_0_conv not_numeral_le_zero polygon_at_least_3_vertices polygon_of_def)
  have "path_image p ∪ path_inside p ⊆ convex hull (set vts)"
    using polygon_path_image_subset_convex[OF len_vts] 
    using assms convex_contains_simple_closed_path_imp_contains_path_inside polygon_def polygon_of_def by auto
  then have subset1: "convex hull (path_image p ∪ path_inside p) ⊆ convex hull (set vts)"
    by (simp add: convex_hull_subset)
  have "set vts ⊆ path_image p ∪ path_inside p" using assms vertices_on_path_image 
    by (simp add: polygon_of_def sup.coboundedI1)
  then have subset2: "convex hull (set vts) ⊆ convex hull (path_image p ∪ path_inside p)"
    by (simp add: hull_mono)
  show ?thesis using subset1 subset2 
    by auto
  qed

lemma convex_hull_frontier_polygon:
  assumes "polygon_of p vts"
  assumes "¬ set vts ⊆ frontier (convex hull (set vts))"
  shows "¬ convex (path_inside p)"
  by (metis assms(1) assms(2) convex_polygon_frontier_is_path_image polygon_of_def vertices_on_path_image)

lemma frontier_int_subset:
  assumes "A ⊆ B"
  shows "(frontier B) ∩ A ⊆ frontier A"
  by (metis assms closure_Un_frontier frontier_Int inf.absorb_iff2 inf_sup_aci(1) subset_Un_eq sup_inf_distrib2)

lemma in_frontier_in_subset:
  assumes "A ⊆ B"
  assumes "x ∈ frontier B"
  assumes "x ∈ A"
  shows "x ∈ frontier A"
  by (metis assms frontier_int_subset IntI in_mono)

lemma in_frontier_in_subset_convex_hull:
  assumes "A ⊆ B"
  assumes "x ∈ frontier (convex hull B)"
  assumes "x ∈ convex hull A"
  shows "x ∈ frontier (convex hull A)"
  by (metis in_frontier_in_subset assms hull_mono)

lemma convex_hull_two_extreme_points:
  fixes S :: "'a::euclidean_space set"
  assumes "finite S"
  assumes "convex hull S ≠ {}"
  assumes "∀x. convex hull S ≠ {x}"
  shows "card {x. x extreme_point_of (convex hull S)} ≥ 2" (is "card ?ep ≥ 2")
proof-
  have "compact (convex hull S)" by (simp add: assms(1) finite_imp_compact_convex_hull)
  then have "convex hull S = convex hull ?ep"
    using Krein_Milman_Minkowski[OF _ convex_convex_hull] by blast
  moreover then obtain x where "x ∈ ?ep" using assms(2) by fastforce
  moreover have "?ep ≠ {x}" using assms(3) calculation(1) by force
  ultimately obtain y where "x ∈ ?ep ∧ y ∈ ?ep ∧ x ≠ y" by blast
  moreover have "finite ?ep" using assms(1) extreme_points_of_convex_hull finite_subset by blast
  ultimately show ?thesis 
    by (metis (no_types, lifting) One_nat_def Orderings.order_eq_iff Suc_1 Suc_leI card_1_singletonE card_gt_0_iff empty_iff insert_Diff not_less_eq_eq singleton_insert_inj_eq)
qed

lemma convex_hull_two_vts_on_frontier:
  fixes S :: "'a::euclidean_space set"
  assumes "card S ≥ 2"
  shows "card (S ∩ frontier (convex hull S)) ≥ 2"
proof-
  have "S ⊆ convex hull S" by (simp add: hull_subset)
  then have "convex hull S ≠ {} ∧ card (convex hull S) ≠ 1"
    by (metis Suc_1 add_leD2 assms card.empty card_1_singletonE convex_hull_eq_empty not_one_le_zero numeral_le_one_iff plus_1_eq_Suc semiring_norm(69) subset_singletonD)
  moreover have "finite S" using assms by (metis Suc_1 Suc_leD card_eq_0_iff not_one_le_zero)
  ultimately have "card {x. x extreme_point_of (convex hull S)} ≥ 2"
    using convex_hull_two_extreme_points by fastforce
  moreover have "{x. x extreme_point_of (convex hull S)} ⊆ S ∩ frontier (convex hull S)"
  proof-
    have "{x. x extreme_point_of (convex hull S)} ⊆ S" by (simp add: extreme_points_of_convex_hull)
    moreover have "{x. x extreme_point_of (convex hull S)} ∩ interior (convex hull S) = {}"
      using extreme_point_not_in_interior by blast
    moreover have "{x. x extreme_point_of (convex hull S)} ⊆ convex hull S"
      using ‹S ⊆ convex hull S› calculation(1) by blast
    moreover have "convex hull S = interior (convex hull S) ∪ frontier (convex hull S)"
      by (metis (no_types, lifting) Diff_empty Suc_1 assms card.infinite closure_Un_frontier closure_convex_hull convex_closure_interior convex_convex_hull empty_subsetI finite_imp_compact frontier_def interior_interior not_less_eq_eq sup_absorb2 zero_less_one_class.zero_le_one)
    ultimately show ?thesis by blast
  qed
  ultimately show ?thesis
    by (smt (verit, del_insts) assms extreme_points_of_convex_hull card_gt_0_iff finite_Int linorder_not_less not_numeral_le_zero order_less_le order_less_le_trans psubset_card_mono)
qed

section "Vertices on Convex Frontier Implies Polygon is Convex"

lemma convex_cut_aux:
  assumes "∀v ∈ S. z ∙ v ≤ 0"
  shows "convex hull S ⊆ {x. z ∙ x ≤ 0}"
  by (simp add: assms convex_halfspace_le hull_minimal subsetI)

lemma convex_cut_aux':
  assumes "∀v ∈ S. z ∙ v ≥ 0"
  shows "convex hull S ⊆ {x. z ∙ x ≥ 0}"
  using convex_cut_aux[of S "-z"] assms by auto

lemma convex_cut:
  assumes "z ≠ 0"
  assumes "{x. z ∙ x = 0} ∩ interior (convex hull S) ≠ {}"
  obtains v1 v2 where "v1 ≠ v2 ∧ {v1, v2} ⊆ S ∧ v1 ∈ {x. z ∙ x < 0} ∧ v2 ∈ {x. z ∙ x > 0}"
proof-
  let ?P1 = "{x. z ∙ x ≤ 0}"
  let ?P2 = "{x. z ∙ x ≥ 0}"
  have "frontier ?P1 = {x. z ∙ x = 0}"
    by (simp add: assms(1) frontier_halfspace_le)
  moreover have "frontier ?P2 = {x. z ∙ x = 0}"
    by (simp add: assms(1) frontier_halfspace_ge)
  ultimately have "¬ convex hull S ⊆ ?P1 ∧ ¬ convex hull S ⊆ ?P2"
    by (smt (verit, ccfv_SIG) DiffE IntE assms(2) disjoint_iff frontier_def inf.absorb_iff2 interior_Int)
  moreover have "(∀v ∈ S. z ∙ v ≤ 0) ⟹ convex hull S ⊆ ?P1" using convex_cut_aux by blast
  moreover have "(∀v ∈ S. z ∙ v ≥ 0) ⟹ convex hull S ⊆ ?P2" using convex_cut_aux' by blast
  ultimately obtain v1 v2 where "{v1, v2} ⊆ S ∧ z ∙ v1 < 0 ∧ z ∙ v2 > 0"
    using linorder_not_le by auto
  thus ?thesis using that by fastforce
qed

lemma affine_2_int_convex:
  fixes S :: "'a::euclidean_space set"
  assumes "{a, b} ⊆ S"
  assumes "{a, b} ⊆ frontier (convex hull S)"
  assumes "affine hull {a, b} ∩ interior (convex hull S) ≠ {}"
  shows "affine hull {a, b} ∩ convex hull S = convex hull {a, b}"
proof-
  let ?H = "convex hull S"
  let ?L = "affine hull {a, b} ∩ ?H"
  have 1: "?L ⊇ convex hull {a, b}"
    by (meson Int_greatest assms(1) convex_hull_subset_affine_hull hull_mono)
  moreover have "?L ⊆ convex hull {a, b}"
  proof(rule subsetI)
    fix x
    assume *: "x ∈ ?L"
    then obtain u v where uv: "x = u *R a + v *R b ∧ u + v = 1" using affine_hull_2 by blast
    
    have "rel_interior ?L ⊆ rel_interior ?H"
      using subset_rel_interior_convex[of ?L ?H]
      by (metis assms(3) convex_affine_hull convex_convex_hull convex_rel_interior_inter_two inf_bot_right inf_le2 rel_interior_affine_hull rel_interior_nonempty_interior)
    moreover have ab_frontier: "a ∈ frontier ?H ∧ b ∈ frontier ?H" using assms by blast
    ultimately have ab_rel_frontier: "a ∈ rel_frontier ?L ∧ b ∈ rel_frontier ?L"
      by (metis IntI affine_affine_hull assms(3) convex_affine_rel_frontier_Int convex_convex_hull hull_subset inf_commute insert_subset)

    { assume **: "u < 0"
      then have "b ∈ open_segment a x"
      proof-
        from uv have "b = (1/v) *R x - (u/v) *R a"
          by (smt (verit, ccfv_threshold) ** divide_inverse_commute inverse_eq_divide real_vector_affinity_eq vector_space_assms(3) Groups.add_ac(2))
        moreover from uv have "1/v - u/v = 1"
          by (metis "**" add.commute add_cancel_right_left diff_divide_distrib divide_self_if eq_diff_eq not_one_less_zero)
        ultimately have "b = (1 - 1/v) *R a + (1/v) *R x" by (simp add: diff_eq_eq)
        moreover from uv ** have "0 < 1/v ∧ 1/v < 1" by simp
        ultimately show ?thesis
          by (metis "1" ab_rel_frontier affine_hull_sing convex_hull_singleton empty_iff equalityI in_segment(2) inf_le1 insert_absorb rel_frontier_sing scaleR_collapse singletonI)
      qed
      then have "b ∈ rel_interior (convex hull {a, x})"
        by (metis empty_iff open_segment_idem rel_interior_closed_segment segment_convex_hull)
      moreover have "x ∈ ?H" using * by blast
      ultimately have "b ∈ interior ?H"
        by (smt (verit, ccfv_threshold) "*" IntD2 Int_empty_right 1 affine_affine_hull affine_hull_affine_Int_nonempty_interior affine_hull_convex_hull assms(3) convex_Int convex_affine_hull convex_convex_hull convex_rel_interior_inter_two hull_hull hull_redundant_eq insert_commute insert_subsetI rel_interior_affine_hull rel_interior_mono rel_interior_nonempty_interior rel_interior_subset subset_hull subset_iff)
      then have False by (metis DiffD2 ab_frontier frontier_def)
    } moreover
    { assume **: "v < 0"
      then have "a ∈ open_segment b x"
      proof-
        from uv have "a = (1/u) *R x - (v/u) *R b"
          by (smt (verit, ccfv_threshold) ** divide_inverse_commute inverse_eq_divide real_vector_affinity_eq vector_space_assms(3) Groups.add_ac(2))
        moreover from uv have "1/u - v/u = 1"
          by (metis "**" add_cancel_right_left diff_divide_distrib divide_self_if eq_diff_eq not_one_less_zero)
        ultimately have "a = (1 - 1/u) *R b + (1/u) *R x" by (simp add: diff_eq_eq)
        moreover from uv ** have "0 < 1/u ∧ 1/u < 1" by simp
        ultimately show ?thesis
          by (metis "1" ab_rel_frontier affine_hull_sing convex_hull_singleton empty_iff equalityI in_segment(2) inf_le1 insert_absorb rel_frontier_sing scaleR_collapse singletonI)
      qed
      then have "a ∈ rel_interior (convex hull {b, x})"
        by (metis empty_iff open_segment_idem rel_interior_closed_segment segment_convex_hull)
      moreover have "x ∈ ?H" using * by blast
      ultimately have "a ∈ interior ?H"
        by (smt (verit, ccfv_threshold) "*" IntD2 Int_empty_right 1 affine_affine_hull affine_hull_affine_Int_nonempty_interior affine_hull_convex_hull assms(3) convex_Int convex_affine_hull convex_convex_hull convex_rel_interior_inter_two hull_hull hull_redundant_eq insert_commute insert_subsetI rel_interior_affine_hull rel_interior_mono rel_interior_nonempty_interior rel_interior_subset subset_hull subset_iff)
      then have False by (metis DiffD2 ab_frontier frontier_def)
    }
    ultimately have "0 ≤ u ∧ u ≤ 1 ∧ 0 ≤ v ∧ v ≤ 1" using uv by argo
    thus "x ∈ convex hull {a, b}" by (simp add: convexD hull_inc uv)
  qed
  ultimately show ?thesis by blast
qed

lemma halfplane_frontier_affine_hull:
  fixes b v :: "real^2"
  assumes "b ≠ 0"
  assumes "v ≠ 0"
  assumes "b ∈ {x. v ∙ x = 0}"
  shows "{x. v ∙ x = 0} = affine hull {0, b}"
proof-
  let ?F = "{x. v ∙ x = 0}"
  let ?A = "affine hull {0, b}"
  have "?F ⊆ ?A"
  proof(rule subsetI)
    fix y
    assume *: "y ∈ ?F"
    have "y ∈ ?A" if "y = 0" by (simp add: assms(2) hull_inc that)
    moreover have "y ∈ ?A" if "b$1 ≠ 0"
    proof-
      have "v ∙ y = 0" using * by fast
      moreover have "v ∙ b = 0" using assms by force
      moreover have "v ∙ y = v$1 * y$1 + v$2 * y$2" by (simp add: inner_vec_def sum_2 real_2_inner)
      moreover have "v ∙ b = v$1 * b$1 + v$2 * b$2" by (simp add: inner_vec_def sum_2 real_2_inner)
      ultimately have 0: "v$1 * y$1 + v$2 * y$2 = 0 ∧ 0 = v$1 * b$1 + v$2 * b$2" by auto
      moreover obtain c where c: "y$1 = c * b$1" using ‹b$1 ≠ 0›
        by (metis hyperplane_eq_Ex inner_real_def mult.commute)
      ultimately have "v$1 * y$1 + v$2 * y$2 = 0 ∧ 0 = c * v$1 * b$1 + c * v$2 * b$2" by algebra
      then have "v$1 * y$1 + v$2 * y$2 = v$1 * y$1 + c * v$2 * b$2" using c by algebra
      then have "v$2 * y$2 = c * v$2 * b$2" by argo
      then have "y$2 = c * b$2"
        by (smt (verit, ccfv_threshold) 0 exhaust_2 mult.commute mult.left_commute mult_cancel_left that assms vec_eq_iff zero_index)
      then have "y = c *R b" using c
        by (smt (verit) exhaust_2 real_scaleR_def vec_eq_iff vector_scaleR_component)
      then have "y ∈ span {0, b}" by (meson insert_subset span_mul span_superset)
      thus "y ∈ ?A"
        by (simp add: affine_hull_span_0 assms(2) hull_inc)
    qed
    moreover have "y ∈ ?A" if "b$2 ≠ 0"
    proof-
      have "v ∙ y = 0" using * by fast
      moreover have "v ∙ b = 0" using assms by force
      moreover have "v ∙ y = v$1 * y$1 + v$2 * y$2" by (simp add: inner_vec_def sum_2 real_2_inner)
      moreover have "v ∙ b = v$1 * b$1 + v$2 * b$2" by (simp add: inner_vec_def sum_2 real_2_inner)
      ultimately have 0: "v$1 * y$1 + v$2 * y$2 = 0 ∧ 0 = v$1 * b$1 + v$2 * b$2" by auto
      moreover obtain c where c: "y$2 = c * b$2" using ‹b$2 ≠ 0›
        by (metis hyperplane_eq_Ex inner_real_def mult.commute)
      ultimately have "v$1 * y$1 + v$2 * y$2 = 0 ∧ 0 = c * v$1 * b$1 + c * v$2 * b$2" by algebra
      then have "v$1 * y$1 + v$2 * y$2 = 0 ∧ 0 = c * v$1 * b$1 + v$2 * y$2" using c by algebra
      then have "v$1 * y$1 = c * v$1 * b$1" by argo
      then have "y$1 = c * b$1"
        by (smt (verit, ccfv_threshold) 0 exhaust_2 mult.commute mult.left_commute mult_cancel_left that assms vec_eq_iff zero_index)
      then have "y = c *R b" using c
        by (smt (verit) exhaust_2 real_scaleR_def vec_eq_iff vector_scaleR_component)
      then have "y ∈ span {0, b}" by (meson insert_subset span_mul span_superset)
      thus "y ∈ ?A"
        by (simp add: affine_hull_span_0 assms(2) hull_inc)
    qed
    ultimately show "y ∈ ?A"
      by (metis (mono_tags, opaque_lifting) assms(1) exhaust_2 vec_eq_iff zero_index)
  qed
  moreover have "?A ⊆ ?F"
  proof(rule subsetI)
    fix x
    assume "x ∈ ?A"
    then obtain α β where "x = α *R 0 + β *R b ∧ α + β = 1" using affine_hull_2 by blast
    then have "v ∙ x = α * (v ∙ 0) + β * (v ∙ b)" by (simp add: assms(1))
    then have "v ∙ x = 0" using assms(3) by auto
    thus "x ∈ ?F" by fast
  qed
  ultimately show ?thesis by blast
qed

lemma vts_on_convex_frontier_aux:
  assumes "polygon_of p vts"
  assumes "vts!0 = 0"
  assumes "set vts ⊆ frontier (convex hull (set vts))"
  shows "path_image (linepath (vts!0) (vts!1)) ⊆ frontier (convex hull (set vts))"
proof-
  let ?H = "convex hull (set vts)"
  let ?a = "vts!0"
  let ?b = "vts!1"
  let ?l = "linepath ?a ?b"
  let ?L = "path_image ?l"
  let ?A = "affine hull {?a, ?b}"
  let ?x = "?b - ?a"

  obtain v where v: "v ∙ ?x = 0 ∧ v ≠ 0"
  proof-
    let ?v = "(vector [?x$2, -?x$1])::(real^2)"
    have "?a ≠ ?b"
      by (smt (verit, best) Cons_nth_drop_Suc One_nat_def Suc_le_eq arc_distinct_ends assms(1) assms(2) card.empty drop0 empty_set length_greater_0_conv list.sel(1) list.sel(3) make_polygonal_path.elims make_polygonal_path.simps(1) make_polygonal_path.simps(2) nth_drop pathfinish_linepath pathstart_linepath plus_1_eq_Suc polygon_at_least_3_vertices polygon_def polygon_of_def polygon_pathstart rel_simps(28) simple_path_joinE)
    then have "?x ≠ 0" by simp
    then have "?v ∙ ?x = 0 ∧ ?v ≠ 0"
    proof-
      have "?v ∙ ?x = (?x$2 * ?x$1) + (-?x$1 * ?x$2)"
        by (simp add: inner_vec_def sum_2 real_2_inner)
      then have "?v ∙ ?x = 0" by argo
      moreover have "?v ≠ 0"
        by (smt (verit, best) ‹?x ≠ 0› exhaust_2 vec_eq_iff vector_2(1) vector_2(2) zero_index)
      ultimately show ?thesis by blast
    qed
    thus ?thesis using that by blast
  qed

  let ?P1 = "{x. v ∙ x ≤ 0}"
  let ?P2 = "{x. v ∙ x ≥ 0}"
  let ?P1_int = "{x. v ∙ x < 0}"
  let ?P2_int = "{x. v ∙ x > 0}"
  let ?F = "{x. v ∙ x = 0}"

  have "?b ≠ 0"
    by (smt (verit) Cons_nth_drop_Suc One_nat_def Suc_le_eq Suc_le_length_iff arc_distinct_ends assms(1) assms(2) card.empty drop0 drop_eq_Nil empty_set le_numeral_extra(4) length_greater_0_conv list.inject make_polygonal_path.elims make_polygonal_path.simps(2) nat_less_le pathfinish_linepath pathstart_linepath polygon_at_least_3_vertices polygon_def polygon_of_def polygon_pathstart rel_simps(28) simple_path_joinE)
  moreover have "?b ∈ ?F" using assms(2) v by auto
  ultimately have F: "?F = ?A"
    using halfplane_frontier_affine_hull[of ?b v] v assms(2) by presburger
  moreover have "?L ⊆ ?A" by (simp add: convex_hull_subset_affine_hull segment_convex_hull)
  ultimately have L_subset_F: "?L ⊆ ?F" by blast
  have L_subset_H: "?L ⊆ ?H"
    by (metis (no_types, lifting) add_gr_0 assms(1) card.empty convex_contains_segment convex_convex_hull diff_less empty_set hull_subset leD length_greater_0_conv less_numeral_extra(1) nth_mem numeral_3_eq_3 path_image_linepath plus_1_eq_Suc polygon_at_least_3_vertices polygon_of_def rotate_polygon_vertices_same_set rotated_polygon_vertices_helper(2) subset_code(1))

  have frontier_P1: "frontier ?P1 = ?F" by (simp add: v frontier_halfspace_le)
  have frontier_P2: "frontier ?P2 = ?F" by (simp add: v frontier_halfspace_ge)
  have interior_P1: "interior ?P1 = ?P1_int" by (simp add: v)
  have interior_P2: "interior ?P2 = ?P2_int" by (simp add: v)
  have convex_P1: "convex ?P1" by (simp add: convex_halfspace_le)
  have convex_P2: "convex ?P2" by (simp add: convex_halfspace_ge)
  have P1_int_P2: "?P1 ∩ ?P2 = ?F" by (simp add: halfspace_Int_eq(1))
  
  let ?H1 = "?H ∩ ?P1"  
  let ?H2 = "?H ∩ ?P2"

  have "¬ collinear (set vts)" using polygon_vts_not_collinear assms(1) by simp
  then have nonempty_interior_H: "interior ?H ≠ {}"
    by (smt (verit, ccfv_SIG) Jordan_inside_outside_real2 closed_path_def Un_Int_eq(4) assms(1) convex_hull_of_polygon_is_convex_hull_of_vts disjoint_iff hull_subset inf.orderE interior_Int interior_eq interior_subset path_inside_def polygon_def polygon_of_def)

  have convex_H1: "convex ?H1" by (simp add: convex_Int convex_P1)
  have convex_H2: "convex ?H2" by (simp add: convex_Int convex_P2)

  have "?H ⊆ ?P1 ∨ ?H ⊆ ?P2"
  proof(rule ccontr)
    assume *: "¬ (?H ⊆ ?P1 ∨ ?H ⊆ ?P2)"
    moreover have "interior ?H ⊆ ?P1 ⟹ ?H ⊆ ?P1"
      by (metis (no_types, lifting) Int_Un_eq(3) Krein_Milman_frontier List.finite_set P1_int_P2 closure_Un_frontier closure_convex_hull closure_mono compact_frontier convex_closure_interior convex_convex_hull finite_imp_compact_convex_hull frontier_P1 nonempty_interior_H)
    moreover have "interior ?H ⊆ ?P2 ⟹ ?H ⊆ ?P2"
      by (metis (no_types, lifting) Int_Un_eq(3) Krein_Milman_frontier List.finite_set P1_int_P2 calculation(1) calculation(2) closure_Un_frontier closure_convex_hull closure_mono compact_frontier convex_closure_interior convex_convex_hull emptyE finite_imp_compact_convex_hull frontier_P2 inf_commute subsetI)
    ultimately have "interior ?H ∩ ?P1 ≠ {} ∧ interior ?H ∩ -?P1 ≠ {}" by force
    moreover have "path_connected (interior ?H)" by (simp add: convex_imp_path_connected)
    ultimately have F_int_interior_H: "?F ∩ interior ?H ≠ {}"
      by (metis (no_types, lifting) path_connected_frontier ComplD disjoint_eq_subset_Compl frontier_P1 subset_eq)
    then obtain v1 v2 where v1v2: "v1 ≠ v2 ∧ {v1, v2} ⊆ set vts
        ∧ v1 ∈ interior ?P1 ∧ v2 ∈ interior ?P2"
      using convex_cut frontier_P1 interior_P1 interior_P2 v by metis
    then obtain i j where ij: "vts!i = v1" "vts!j = v2"
        "2 ≤ i" "2 ≤ j" "i ≠ j" "i < length vts - 1" "j < length vts - 1"
    proof-
      obtain i j where "vts!i = v1 ∧ vts!j = v2 ∧ i ≠ j ∧ i < length vts ∧ j < length vts"
        by (metis in_set_conv_nth insert_subset v1v2)
      moreover have "2 ≤ i"
      proof-
        { assume "i = 0 ∨ i = 1"
          then have "vts!i = ?a ∨ vts!i = ?b" by blast
          then have "vts!i ∈ ?F" by (simp add: F hull_inc)
          then have False using calculation(1) interior_P1 v1v2 by auto
        }
        thus ?thesis by presburger
      qed
      moreover have "2 ≤ j"
      proof-
        { assume "j = 0 ∨ j = 1"
          then have "vts!j = ?a ∨ vts!j = ?b" by blast
          then have "vts!j ∈ ?F" by (simp add: F hull_inc)
          then have False using calculation(1) interior_P2 v1v2 by auto
        }
        thus ?thesis by presburger
      qed
      moreover have False if "i = length vts - 1"
        by (metis (no_types, lifting) F assms(1) calculation(1) frontier_P1 frontier_def have_wraparound_vertex hull_subset insertCI insert_Diff last_conv_nth last_snoc less_nat_zero_code list.size(3) polygon_of_def subset_Diff_insert that v1v2)
      moreover have False if "j = length vts - 1"
        by (metis (no_types, lifting) F assms(1) calculation(1) frontier_P2 frontier_def have_wraparound_vertex hull_subset insertCI insert_Diff last_conv_nth last_snoc less_nat_zero_code list.size(3) polygon_of_def subset_Diff_insert that v1v2)
      ultimately show ?thesis using that by fastforce
    qed

    let ?i' = "min i j"
    let ?j' = "max i j"
    let ?vts' = "take (?j' - ?i' + 1) (drop ?i' vts)"
    let ?p' = "make_polygonal_path ?vts'"
    have vts'_sublist: "sublist ?vts' vts" using sublist_order.order.trans by blast
    then have vts'_sublist_tl: "sublist ?vts' (tl vts)"
      by (metis Suc_1 Suc_eq_plus1 drop_Suc ij max_def min_def nat_minus_add_max not_less_eq_eq sublist_drop sublist_order.dual_order.trans sublist_take)

    have p'_start_finish: "{pathstart ?p', pathfinish ?p'} = {v1, v2}"
    proof-
      have "?vts'!0 = vts!?i'" using ij by force
      moreover have "?vts'!(?j' - ?i') = vts!?j'"
        using diff_is_0_eq diff_zero ij less_numeral_extra(1) max.cobounded1 min_absorb2 min_def nth_drop nth_take order_less_imp_le
        by fastforce
      moreover have "(vts!?i' = v1 ∧ vts!?j' = v2) ∨ (vts!?i' = v2 ∧ vts!?j' = v1)"
        using ij by linarith
      moreover have "pathstart ?p' = ?vts'!0 ∧ pathfinish ?p' = ?vts'!(?j' - ?i')"
      proof -
        have "?vts' ≠ []"
          using ij(6) by auto
        moreover have "?p' = make_polygonal_path ?vts'" ..
        ultimately have "pathstart ?p' = ?vts' ! 0" and "pathfinish ?p' = ?vts' ! (length ?vts' - 1)"
          by (rule polygon_pathstart polygon_pathfinish)+
        moreover have "length ?vts' - 1 = ?j' - ?i'"
          using ij(6,7) by simp
        ultimately show ?thesis
          by metis
      qed
      ultimately show ?thesis by auto
    qed
    then have "path_image ?p' ∩ interior ?P2 ≠ {} ∧ path_image ?p' ∩ interior ?P1 ≠ {}"
      by (metis v1v2 IntI doubleton_eq_iff empty_iff pathfinish_in_path_image pathstart_in_path_image)
    then have "path_image ?p' ∩ -?P1 ≠ {} ∧ path_image ?p' ∩ ?P1 ≠ {}"
      using interior_P2
      by (smt (verit, best) disjoint_iff_not_equal in_mono inf_shunt interior_P1 mem_Collect_eq)
    moreover have "path_connected (path_image ?p')"
      using make_polygonal_path_gives_path path_connected_path_image by blast
    ultimately obtain z where z: "z ∈ path_image ?p' ∩ ?F"
      by (smt (verit, del_insts) path_connected_frontier DiffE Diff_triv all_not_in_conv frontier_P1)
    moreover have "path_image ?p' ⊆ ?H"
    proof-
      have "path_image p ⊆ ?H"
        by (metis assms(1) insert_subset length_pos_if_in_set polygon_of_def polygon_path_image_subset_convex v1v2)
      moreover have "path_image ?p' ⊆ path_image p"
        by (metis (no_types, lifting) vts'_sublist sublist_path_image_subset One_nat_def Suc_leI p'_start_finish assms(1) doubleton_eq_iff length_greater_0_conv make_polygonal_path.simps(1) pathfinish_linepath pathstart_linepath polygon_of_def v1v2)
      ultimately show ?thesis by blast
    qed
    ultimately have "z ∈ path_image ?p' ∩ (?H ∩ ?F)" by blast
    moreover have "?H ∩ ?F = ?L" 
      using affine_2_int_convex[of ?a ?b "set vts"]
      by (smt (verit, best) assms(3) F F_int_interior_H inf_commute segment_convex_hull path_image_linepath Suc_1 add_leD2 assms(1) empty_subsetI insert_subset length_greater_0_conv lessI nat_neq_iff nth_mem numeral_Bit0 order.strict_iff_not plus_1_eq_Suc polygon_of_def polygon_vertices_length_at_least_4 take_all_iff take_eq_Nil IntE inf.orderE)
    ultimately have "z ∈ ?L ∩ path_image ?p'" by blast
    moreover have "?L ∩ path_image ?p' ⊆ {?a, ?b}"
    proof-
      let ?p_tl = "make_polygonal_path (tl vts)"
      have "p = make_polygonal_path vts ∧ loop_free p"
        using assms unfolding polygon_of_def polygon_def simple_path_def by blast
      moreover have "[?a, ?b] = take 2 vts"
        by (metis Cons_nth_drop_Suc One_nat_def Suc_1 append_Cons append_Nil calculation constant_linepath_is_not_loop_free drop0 drop_eq_Nil insert_subset length_pos_if_in_set linorder_not_le make_polygonal_path.simps(2) take0 take_Suc_conv_app_nth v1v2)
      moreover have "tl vts = drop (2 - 1) vts" by (simp add: drop_Suc)
      moreover have "?l = make_polygonal_path [?a, ?b]" using make_polygonal_path.simps by simp
      moreover have "length vts > 2" using ij by linarith
      moreover have "pathstart ?l = ?a ∧ pathstart ?p_tl = ?b"
        using calculation(3) calculation(5) polygon_pathstart by auto
      ultimately have "?L ∩ path_image ?p_tl ⊆ {?a, ?b}"
        using loop_free_split_int[of p vts "[?a, ?b]" 2 "tl vts" ?l ?p_tl "length vts"] by auto
      moreover have "path_image ?p' ⊆ path_image ?p_tl"
        using sublist_path_image_subset
        by (metis add.commute ij le_add2 length_drop length_take less_diff_conv min.absorb4 min.cobounded1 min_def vts'_sublist_tl)
      ultimately show ?thesis by blast
    qed
    ultimately have *: "z = ?a ∨ z = ?b" by blast

    let ?𝔦 = "?i'"
    let ?𝔧 = "?j' - ?i' + 1"
    let ?𝔨 = "?𝔦 + ?𝔧"
    let ?x1 = "(2^?𝔦 - 1)/(2^?𝔦)::real"
    let ?x2 = "(2^(?𝔨-1) - 1)/(2^(?𝔨-1))::real"

    have "?vts' = take ?𝔧 (drop ?𝔦 vts)" by blast
    moreover have "?𝔨 ≤ length vts - 1 ∧ 2 ≤ ?𝔧" using ij by linarith
    ultimately have "path_image ?p' = p`{?x1..?x2}"
      using vts_sublist_path_image assms(1) unfolding polygon_of_def by metis
    moreover have x1x2: "?x1 > 1/2 ∧ ?x2 < 1"
    proof-
      have "?i' ≥ 2" using ij by linarith
      then have "(1::real) < 2^?i' - 1"
        by (smt (z3) dual_order.strict_trans1 linorder_le_less_linear numeral_le_one_iff power_one_right power_strict_increasing semiring_norm(69))
      thus ?thesis by simp
    qed
    moreover have "p 0 ∉ p`{?x1..?x2} ∧ p (1/2) ∉ p`{?x1..?x2}"
    proof-
      have False if *: "p 0 ∈ p`{?x1..?x2}"
      proof-
        obtain t where t: "t ∈ {?x1..?x2} ∧ p t = p 0" using * by auto
        then have "t ≥ ?x1 ∧ t ≤ ?x2" by presburger
        then have "1/2 < t ∧ t < 1" using x1x2 by argo
        thus False
          using t assms(1) unfolding polygon_of_def polygon_def simple_path_def loop_free_def
          by force
      qed
      moreover have False if *: "p (1/2) ∈ p`{?x1..?x2}"
      proof-
        obtain t where t: "t ∈ {?x1..?x2} ∧ p t = p (1/2)" using * by auto
        then have "t ≥ ?x1 ∧ t ≤ ?x2" by presburger
        then have "1/2 < t ∧ t < 1" using x1x2 by argo
        thus False
          using t assms(1) unfolding polygon_of_def polygon_def simple_path_def loop_free_def
          by fastforce
      qed
      ultimately show ?thesis by fast
    qed
    moreover have "?a = p 0"
      by (metis assms(1) card.empty empty_set not_numeral_le_zero pathstart_def polygon_at_least_3_vertices polygon_of_def polygon_pathstart)
    moreover have "?b = p (1/2)"
    proof-
      have "p = ?l +++ (make_polygonal_path (tl vts))"
        by (smt (verit, best) One_nat_def Suc_1 assms(1) ij length_Cons length_greater_0_conv length_tl less_imp_le_nat list.sel(3) list.size(3) make_polygonal_path.elims nth_Cons_0 nth_tl order_less_le_trans polygon_of_def pos2 zero_less_diff)
      then have "p (1/2) = ?l 1"
        unfolding joinpaths_def by simp
      thus ?thesis by (simp add: linepath_1')
    qed
    ultimately have "?a ∉ path_image ?p' ∧ ?b ∉ path_image ?p'" by presburger
    thus False using z * by blast
  qed
  then have "frontier ?P1 ∩ ?H ⊆ frontier ?H ∨ frontier ?P2 ∩ ?H ⊆ frontier ?H"
    using frontier_int_subset by auto
  moreover have "?L ⊆ frontier ?P1 ∧ ?L ⊆ frontier ?P2"
    using frontier_P1 frontier_P2 L_subset_F by presburger
  ultimately show ?thesis using L_subset_H by fast
qed

lemma vts_on_convex_frontier_aux':
  assumes "polygon_of p vts"
  assumes "set vts ⊆ frontier (convex hull (set vts))"
  shows "path_image (linepath (vts!0) (vts!1)) ⊆ frontier (convex hull (set vts))"
proof-
  let ?a = "vts!0"
  let ?f = "λv. v + (-?a)"
  let ?vts' = "map ?f vts"
  let ?p' = "make_polygonal_path ?vts'"

  have len_vts: "length vts ≥ 2"
    using assms(1) polygon_of_def polygon_vertices_length_at_least_4 by fastforce
  then have p': "?p' = ?f ∘ p"
    using make_polygonal_path_translate[of vts "-?a"] assms unfolding polygon_of_def by presburger
  then have 0: "?vts'!0 = 0"
    by (metis len_vts neg_eq_iff_add_eq_0 nth_map order_less_le_trans pos2)
  moreover have vts': "set ?vts' = ?f ` (set vts)" by simp
  ultimately have "convex hull (set ?vts') = ?f ` (convex hull (set vts))"
    using convex_hull_translation[of "-?a" "set vts"] by force
  then have "frontier (convex hull (set ?vts')) = frontier (?f ` (convex hull (set vts)))"
    by auto
  then have frontier_translation: 
      "frontier (convex hull (set ?vts')) = ?f ` (frontier ((convex hull (set vts))))"
    using frontier_translation[of "-?a" "convex hull (set vts)"] by simp

  have "?f (vts!0) = ?vts'!0 ∧ ?f (vts!1) = ?vts'!1" using 0 len_vts by auto
  then have linepath_translation:
      "?f ` path_image (linepath (vts!0) (vts!1)) = path_image (linepath (?vts'!0) (?vts'!1))"
    using linepath_translation[of ?a "-?a" "vts!1"] by (simp add: path_image_compose)

  have "polygon_of ?p' ?vts'" using translation_is_polygon assms(1) p' by presburger 
  moreover have "set ?vts' ⊆ frontier (convex hull (set ?vts'))"
  proof-
    have "frontier (convex hull (set ?vts')) = frontier (convex hull (?f ` (set vts)))"
      using vts' by presburger
    then have "frontier (convex hull (set ?vts')) = ?f ` (frontier (convex hull (set vts)))"
      using frontier_translation by presburger
    thus ?thesis using vts' assms(2) by auto
  qed
  ultimately have "path_image (linepath (?vts'!0) (?vts'!1)) ⊆ frontier (convex hull (set ?vts'))"
    using vts_on_convex_frontier_aux assms 0 by blast
  then have "?f ` path_image (linepath (vts!0) (vts!1)) ⊆ ?f ` (frontier ((convex hull (set vts))))"
    using linepath_translation frontier_translation by argo
  thus ?thesis by force
qed

lemma vts_on_convex_frontier:
  assumes "polygon_of p vts"
  assumes "set vts ⊆ frontier (convex hull (set vts))"
  assumes "i < length vts - 1"
  shows "path_image (linepath (vts!i) (vts!(i+1))) ⊆ frontier (convex hull (set vts))"
proof-
  let ?vts' = "rotate_polygon_vertices vts i"
  let ?p' = "make_polygonal_path ?vts'"
  have "polygon_of ?p' ?vts'"
    using assms(1) polygon_of_def rotation_is_polygon by blast
  moreover have "set ?vts' ⊆ frontier (convex hull (set ?vts'))"
    using assms(1) assms(2) polygon_of_def rotate_polygon_vertices_same_set by auto
  ultimately have "path_image (linepath (?vts'!0) (?vts'!1)) ⊆ frontier (convex hull (set ?vts'))"
    using vts_on_convex_frontier_aux' by presburger
  moreover have "?vts'!0 = vts!i ∧ ?vts'!1 = vts!(i+1)"
    using assms(3)
    using rotated_polygon_vertices[of ?vts' vts i "i+1"]
    using rotated_polygon_vertices[of ?vts' vts i "i"]
    by (smt (verit, best) Suc_leI add.commute add.right_neutral add_2_eq_Suc' add_diff_cancel_left' add_lessD1 assms(1) have_wraparound_vertex hd_Nil_eq_last hd_conv_nth last_snoc le_add1 less_diff_conv plus_1_eq_Suc polygon_of_def)
  moreover have "frontier (convex hull (set ?vts')) = frontier (convex hull (set vts))"
    by (metis assms(1) polygon_of_def rotate_polygon_vertices_same_set)
  ultimately show ?thesis by argo
qed

lemma vts_on_frontier_means_path_image_on_frontier:
  assumes "polygon_of p vts"
  assumes "set vts ⊆ frontier (convex hull (set vts))"
  shows "path_image p ⊆ frontier (convex hull (set vts))"
proof(rule subsetI)
  let ?H = "convex hull (set vts)"
  fix x assume "x ∈ path_image p"
  moreover have "path_image p = (⋃ {path_image (linepath (vts!i) (vts!(i+1))) | i. i ≤ (length vts) - 2})"
    using polygonal_path_image_linepath_union assms unfolding polygon_of_def
    by (metis (no_types, lifting) add_leD2 numeral_Bit0 polygon_vertices_length_at_least_4)
  ultimately obtain i where "i ≤ (length vts) - 2 ∧ x ∈ path_image (linepath (vts!i) (vts!(i+1)))"
    by blast
  thus "x ∈ frontier ?H"
    by (smt (verit, ccfv_SIG) One_nat_def Suc_diff_Suc add.commute add_2_eq_Suc' assms(1) assms(2) in_mono le_add1 le_zero_eq less_Suc_eq_le less_diff_conv linorder_not_less plus_1_eq_Suc vts_on_convex_frontier vts_on_convex_frontier_aux')
qed

lemma vts_on_convex_frontier_interior:
  assumes "polygon_of p vts"
  assumes "set vts ⊆ frontier (convex hull (set vts))"
  shows "path_inside p = interior (convex hull (set vts))"
proof-
  let ?H = "convex hull (set vts)"

  have "path_inside p ⊆ interior (convex hull (set vts))"
    by (metis (no_types, lifting) Un_empty assms(1) convex_contains_simple_closed_path_imp_contains_path_inside convex_convex_hull convex_hull_eq_empty convex_hull_of_polygon_is_convex_hull_of_vts empty_set inside_outside_def inside_outside_polygon interior_maximal length_greater_0_conv polygon_def polygon_of_def polygon_path_image_subset_convex)
  moreover have "interior (convex hull (set vts)) ⊆ path_inside p"
  proof(rule ccontr)
    assume *: "¬ interior (convex hull (set vts)) ⊆ path_inside p"
    then obtain x where x: "x ∈ interior (convex hull (set vts)) - path_inside p" by blast
    obtain y where y: "y ∈ path_inside p"
      using inside_outside_polygon assms unfolding inside_outside_def polygon_of_def by fastforce

    let ?l = "linepath x y"
    have 1: "path_image ?l ⊆ interior ?H"
      by (metis (no_types, lifting) DiffE calculation convex_contains_segment convex_convex_hull convex_interior in_mono linepath_image_01 path_defs(4) x y)
    have "path_image ?l ∩ frontier (path_inside p) ≠ {}"
      using inside_outside_polygon assms unfolding inside_outside_def polygon_of_def
      by (smt (verit) "*" Diff_disjoint Diff_eq_empty_iff Int_Un_eq(2) Int_assoc Un_Int_eq(3) assms(1) calculation connected_Int_frontier convex_connected convex_convex_hull convex_interior frontier_def inf.absorb_iff2 vts_on_frontier_means_path_image_on_frontier)
    then have 2: "path_image ?l ∩ path_image p ≠ {}"
      using inside_outside_polygon assms unfolding inside_outside_def polygon_of_def by blast

    show False
      using 1 2 vts_on_frontier_means_path_image_on_frontier
      using Diff_disjoint Int_lower2 Int_subset_iff assms(1) assms(2) frontier_def inf_le1
      by fastforce
  qed
  ultimately show ?thesis by blast
qed

lemma vts_subset_frontier:
  assumes "polygon_of p vts"
  assumes "set vts ⊆ frontier (convex hull (set vts))"
  shows "convex (path_image p ∪ path_inside p)"
  by (metis assms(1) assms(2) vts_on_convex_frontier_interior convex_convex_hull convex_interior polygon_convex_iff polygon_of_def sup_commute)

lemma convex_hull_of_nonconvex_polygon_strict_subset_ep:
  assumes "polygon_of p vts"
  assumes "¬ (convex (path_image p ∪ path_inside p))"
  shows "{v. v extreme_point_of (convex hull (set vts))} ⊂ set vts"
proof-
  let ?ep = "{v. v extreme_point_of (convex hull (set vts))}"
  let ?H = "convex hull (set vts)"
  have "?ep ⊆ frontier ?H"
    by (metis Krein_Milman_frontier List.finite_set convex_convex_hull extreme_point_of_convex_hull finite_imp_compact_convex_hull mem_Collect_eq subsetI)
  thus ?thesis using assms vts_subset_frontier extreme_points_of_convex_hull by force
qed

lemma convex_hull_of_nonconvex_polygon_strict_subset:
  assumes "polygon_of p vts"
  assumes "¬ (convex (path_image p ∪ path_inside p))"
  shows "∃v ∈ set vts. v ∈ interior (convex hull (set vts))"
  using assms vts_subset_frontier
  by (smt (verit) Diff_iff UnCI closure_Un_frontier frontier_def hull_inc subsetI)

lemma convex_polygon_means_linepaths_inside:
  fixes p :: "R_to_R2"
  assumes "polygon_of p vts"
  assumes convex_is: "convex hull (set vts) = (path_inside p ∪ path_image p)"
  assumes a_in: "a ∈ (path_inside p ∪ path_image p)"
  assumes b_in: "b ∈ (path_inside p ∪ path_image p)"
  shows "path_image (linepath a b) ⊆ (path_inside p ∪ path_image p)"
proof - 
  let ?conv = "path_inside p ∪ path_image p"
  have "∀u≥0. ∀v≥0. u + v = 1 ⟶ u *R a + v *R b ∈ ?conv"
    using convex_is a_in b_in unfolding convex_def 
    by (metis (no_types, lifting) convexD convex_convex_hull convex_is)
  then have "(1 - x) *R a + x *R b ∈ ?conv" if x_in: "x ∈ {0..1}" for x
    using x_in by auto
  then show ?thesis unfolding linepath_def path_image_def 
    by fast
qed

end