Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/HOL/Analysis/   (Beweissystem Isabelle Version 2025-1©)  Datei vom 16.11.2025 mit Größe 186 kB image not shown  

Quelle  Path_Connected.thy

  Sprache: Isabelle
 

(*  Title:      HOL/Analysis/Path_Connected.thy
  Authors: LC Paulson and Robert Himmelmann (TU Muenchen), based on material from HOL Light
*)

section Path-Connectedness

theory Path_Connected
imports
  Starlike
  T1_Spaces
begin

subsection Paths and Arcs

definition🍋tag important path :: "(real ==> 'a::topological_space) ==> bool"
  where "path g continuous_on {0..1} g"

definition🍋tag important pathstart :: "(real ==> 'a::topological_space) ==> 'a"
  where "pathstart g g 0"

definition🍋tag important pathfinish :: "(real ==> 'a::topological_space) ==> 'a"
  where "pathfinish g g 1"

definition🍋tag important path_image :: "(real ==> 'a::topological_space) ==> 'a set"
  where "path_image g g ` {0 .. 1}"

definition🍋tag important reversepath :: "(real ==> 'a::topological_space) ==> real ==> 'a"
  where "reversepath g (λx. g(1 - x))"

definition🍋tag important joinpaths :: "(real ==> 'a::topological_space) ==> (real ==> 'a) ==> real ==> 'a"
    (infixr +++ 75)
  where "g1 +++ g2 (λx. if x 1/2 then g1 (2 * x) else g2 (2 * x - 1))"

definition🍋tag important loop_free :: "(real ==> 'a::topological_space) ==> bool"
  where "loop_free g x{0..1}. y{0..1}. g x = g y x = y x = 0 y = 1 x = 1 y = 0"

definition🍋tag important simple_path :: "(real ==> 'a::topological_space) ==> bool"
  where "simple_path g path g loop_free g"

definition🍋tag important arc :: "(real ==> 'a :: topological_space) ==> bool"
  where "arc g path g inj_on g {0..1}"


subsection🍋tag unimportant\<open>Invariance theorems

lemma path_eq: "path p ==> (t. t {0..1} ==> p t = q t) ==> path q"
  using continuous_on_eq path_def by blast

lemma path_continuous_image: "path g ==> continuous_on (path_image g) f ==> path(f g)"
  unfolding path_def path_image_def
  using continuous_on_compose by blast

lemma path_translation_eq:
  fixes g :: "real ==> 'a :: real_normed_vector"
  shows "path((λx. a + x) g) = path g"
  using continuous_on_translation_eq path_def by blast

lemma path_linear_image_eq:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
   assumes "linear f" "inj f"
     shows "path(f g) = path g"
proof -
  from linear_injective_left_inverse [OF assms]
  obtain h where h: "linear h" "h f = id"
    by blast
  with assms show ?thesis
    by (metis comp_assoc id_comp linear_continuous_on linear_linear path_continuous_image)
qed

lemma pathstart_translation: "pathstart((λx. a + x) g) = a + pathstart g"
  by (simp add: pathstart_def)

lemma pathstart_linear_image_eq: "linear f ==> pathstart(f g) = f(pathstart g)"
  by (simp add: pathstart_def)

lemma pathfinish_translation: "pathfinish((λx. a + x) g) = a + pathfinish g"
  by (simp add: pathfinish_def)

lemma pathfinish_linear_image: "linear f ==> pathfinish(f g) = f(pathfinish g)"
  by (simp add: pathfinish_def)

lemma path_image_translation: "path_image((λx. a + x) g) = (λx. a + x) ` (path_image g)"
  by (simp add: image_comp path_image_def)

lemma path_image_linear_image: "linear f ==> path_image(f g) = f ` (path_image g)"
  by (simp add: image_comp path_image_def)

lemma reversepath_translation: "reversepath((λx. a + x) g) = (λx. a + x) reversepath g"
  by (rule ext) (simp add: reversepath_def)

lemma reversepath_linear_image: "linear f ==> reversepath(f g) = f reversepath g"
  by (rule ext) (simp add: reversepath_def)

lemma joinpaths_translation:
    "((λx. a + x) g1) +++ ((λx. a + x) g2) = (λx. a + x) (g1 +++ g2)"
  by (rule ext) (simp add: joinpaths_def)

lemma joinpaths_linear_image: "linear f ==> (f g1) +++ (f g2) = f (g1 +++ g2)"
  by (rule ext) (simp add: joinpaths_def)

lemma loop_free_translation_eq:
  fixes g :: "real ==> 'a::euclidean_space"
  shows "loop_free((λx. a + x) g) = loop_free g"
  by (simp add: loop_free_def)

lemma simple_path_translation_eq:
  fixes g :: "real ==> 'a::euclidean_space"
  shows "simple_path((λx. a + x) g) = simple_path g"
  by (simp add: simple_path_def loop_free_translation_eq path_translation_eq)

lemma loop_free_linear_image_eq:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "linear f" "inj f"
    shows "loop_free(f g) = loop_free g"
  using assms inj_on_eq_iff [of f] by (auto simp: loop_free_def)

lemma simple_path_linear_image_eq:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "linear f" "inj f"
    shows "simple_path(f g) = simple_path g"
  using assms
  by (simp add: loop_free_linear_image_eq path_linear_image_eq simple_path_def)

lemma simple_pathI [intro?]:
  assumes "path p"
  assumes "x y. 0 x ==> x < y ==> y 1 ==> p x = p y ==> x = 0 y = 1"
  shows   "simple_path p"
  unfolding simple_path_def loop_free_def
proof (intro ballI conjI impI)
  fix x y assume "x {0..1}" "y {0..1}" "p x = p y"
  thus "x = y x = 0 y = 1 x = 1 y = 0"
    by (metis assms(2) atLeastAtMost_iff linorder_less_linear)
qed fact+

lemma arcD: "arc p ==> p x = p y ==> x {0..1} ==> y {0..1} ==> x = y"
  by (auto simp: arc_def inj_on_def)

lemma arc_translation_eq:
  fixes g :: "real ==> 'a::euclidean_space"
  shows "arc((λx. a + x) g) arc g"
  by (auto simp: arc_def inj_on_def path_translation_eq)

lemma arc_linear_image_eq:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
   assumes "linear f" "inj f"
     shows  "arc(f g) = arc g"
  using assms inj_on_eq_iff [of f]
  by (auto simp: arc_def inj_on_def path_linear_image_eq)


subsection🍋tag unimportant\<open>Basic lemmas about paths

lemma path_of_real: "path complex_of_real" 
  unfolding path_def by (intro continuous_intros)

lemma path_const: "path (λt. a)" for a::"'a::real_normed_vector"
  unfolding path_def by (intro continuous_intros)

lemma path_minus: "path g ==> path (λt. - g t)" for g::"real==>'a::real_normed_vector"
  unfolding path_def by (intro continuous_intros)

lemma path_add: "[path f; path g] ==> path (λt. f t + g t)" for f::"real==>'a::real_normed_vector"
  unfolding path_def by (intro continuous_intros)

lemma path_diff: "[path f; path g] ==> path (λt. f t - g t)" for f::"real==>'a::real_normed_vector"
  unfolding path_def by (intro continuous_intros)

lemma path_mult: "[path f; path g] ==> path (λt. f t * g t)" for f::"real==>'a::real_normed_field"
  unfolding path_def by (intro continuous_intros)

lemma pathin_iff_path_real [simp]: "pathin euclideanreal g path g"
  by (simp add: pathin_def path_def)

lemma continuous_on_path: "path f ==> t {0..1} ==> continuous_on t f"
  using continuous_on_subset path_def by blast

lemma inj_on_imp_loop_free: "inj_on g {0..1} ==> loop_free g"
  by (simp add: inj_onD loop_free_def)

lemma arc_imp_simple_path: "arc g ==> simple_path g"
  by (simp add: arc_def inj_on_imp_loop_free simple_path_def)

lemma arc_imp_path: "arc g ==> path g"
  using arc_def by blast

lemma arc_imp_inj_on: "arc g ==> inj_on g {0..1}"
  by (auto simp: arc_def)

lemma simple_path_imp_path: "simple_path g ==> path g"
  using simple_path_def by blast

lemma loop_free_cases: "loop_free g ==> inj_on g {0..1} pathfinish g = pathstart g"
  by (force simp: inj_on_def loop_free_def pathfinish_def pathstart_def)

lemma simple_path_cases: "simple_path g ==> arc g pathfinish g = pathstart g"
  using arc_def loop_free_cases simple_path_def by blast

lemma simple_path_imp_arc: "simple_path g ==> pathfinish g pathstart g ==> arc g"
  using simple_path_cases by auto

lemma arc_distinct_ends: "arc g ==> pathfinish g pathstart g"
  unfolding arc_def inj_on_def pathfinish_def pathstart_def
  by fastforce

lemma arc_simple_path: "arc g simple_path g pathfinish g pathstart g"
  using arc_distinct_ends arc_imp_simple_path simple_path_cases by blast

lemma simple_path_eq_arc: "pathfinish g pathstart g ==> (simple_path g = arc g)"
  by (simp add: arc_simple_path)

lemma path_image_const [simp]: "path_image (λt. a) = {a}"
  by (force simp: path_image_def)

lemma path_image_nonempty [simp]: "path_image g {}"
  unfolding path_image_def image_is_empty box_eq_empty
  by auto

lemma pathstart_in_path_image[intro]: "pathstart g path_image g"
  unfolding pathstart_def path_image_def
  by auto

lemma pathfinish_in_path_image[intro]: "pathfinish g path_image g"
  unfolding pathfinish_def path_image_def
  by auto

lemma connected_path_image[intro]: "path g ==> connected (path_image g)"
  unfolding path_def path_image_def
  using connected_continuous_image connected_Icc by blast

lemma compact_path_image[intro]: "path g ==> compact (path_image g)"
  unfolding path_def path_image_def
  using compact_continuous_image connected_Icc by blast

lemma reversepath_reversepath[simp]: "reversepath (reversepath g) = g"
  unfolding reversepath_def
  by auto

lemma pathstart_reversepath[simp]: "pathstart (reversepath g) = pathfinish g"
  unfolding pathstart_def reversepath_def pathfinish_def
  by auto

lemma pathfinish_reversepath[simp]: "pathfinish (reversepath g) = pathstart g"
  unfolding pathstart_def reversepath_def pathfinish_def
  by auto

lemma reversepath_o: "reversepath g = g (-)1"
  by (auto simp: reversepath_def)

lemma pathstart_join[simp]: "pathstart (g1 +++ g2) = pathstart g1"
  unfolding pathstart_def joinpaths_def pathfinish_def
  by auto

lemma pathfinish_join[simp]: "pathfinish (g1 +++ g2) = pathfinish g2"
  unfolding pathstart_def joinpaths_def pathfinish_def
  by auto

lemma path_image_reversepath[simp]: "path_image (reversepath g) = path_image g"
  by (metis cancel_comm_monoid_add_class.diff_cancel diff_zero image_comp 
      image_diff_atLeastAtMost path_image_def reversepath_o)

lemma path_reversepath [simp]: "path (reversepath g) path g"
  by (metis continuous_on_compose continuous_on_op_minus image_comp image_ident path_def path_image_def path_image_reversepath reversepath_o reversepath_reversepath)

lemma arc_reversepath:
  assumes "arc g" shows "arc(reversepath g)"
proof -
  have injg: "inj_on g {0..1}"
    using assms
    by (simp add: arc_def)
  have **: "x y::real. 1-x = 1-y ==> x = y"
    by simp
  show ?thesis
    using assms  by (clarsimp simp: arc_def intro!: inj_onI) (simp add: inj_onD reversepath_def **)
qed

lemma loop_free_reversepath:
  assumes "loop_free g" shows "loop_free(reversepath g)"
  using assms by (simp add: reversepath_def loop_free_def Ball_def) (smt (verit))

lemma simple_path_reversepath: "simple_path g ==> simple_path (reversepath g)"
  by (simp add: loop_free_reversepath simple_path_def)

lemmas reversepath_simps =
  path_reversepath path_image_reversepath pathstart_reversepath pathfinish_reversepath

lemma path_join[simp]:
  assumes "pathfinish g1 = pathstart g2"
  shows "path (g1 +++ g2) path g1 path g2"
  unfolding path_def pathfinish_def pathstart_def
proof safe
  assume cont: "continuous_on {0..1} (g1 +++ g2)"
  have g1: "continuous_on {0..1} g1 continuous_on {0..1} ((g1 +++ g2) (λx. x / 2))"
    by (intro continuous_on_cong refl) (auto simp: joinpaths_def)
  have g2: "continuous_on {0..1} g2 continuous_on {0..1} ((g1 +++ g2) (λx. x / 2 + 1/2))"
    using assms
    by (intro continuous_on_cong refl) (auto simp: joinpaths_def pathfinish_def pathstart_def)
  show "continuous_on {0..1} g1" and "continuous_on {0..1} g2"
    unfolding g1 g2
    by (auto intro!: continuous_intros continuous_on_subset[OF cont] simp del: o_apply)
next
  assume g1g2: "continuous_on {0..1} g1" "continuous_on {0..1} g2"
  have 01: "{0 .. 1} = {0..1/2} {1/2 .. 1::real}"
    by auto
  {
    fix x :: real
    assume "0 x" and "x 1"
    then have "x (λx. x * 2) ` {0..1 / 2}"
      by (intro image_eqI[where x="x/2"]) auto
  }
  note 1 = this
  {
    fix x :: real
    assume "0 x" and "x 1"
    then have "x (λx. x * 2 - 1) ` {1 / 2..1}"
      by (intro image_eqI[where x="x/2 + 1/2"]) auto
  }
  note 2 = this
  show "continuous_on {0..1} (g1 +++ g2)"
    using assms
    unfolding joinpaths_def 01
    apply (intro continuous_on_cases closed_atLeastAtMost g1g2[THEN continuous_on_compose2] continuous_intros)
    apply (auto simp: field_simps pathfinish_def pathstart_def intro!: 1 2)
    done
qed


subsection🍋tag unimportant Path Images

lemma bounded_path_image: "path g ==> bounded(path_image g)"
  by (simp add: compact_imp_bounded compact_path_image)

lemma closed_path_image:
  fixes g :: "real ==> 'a::t2_space"
  shows "path g ==> closed(path_image g)"
  by (metis compact_path_image compact_imp_closed)

lemma connected_simple_path_image: "simple_path g ==> connected(path_image g)"
  by (metis connected_path_image simple_path_imp_path)

lemma compact_simple_path_image: "simple_path g ==> compact(path_image g)"
  by (metis compact_path_image simple_path_imp_path)

lemma bounded_simple_path_image: "simple_path g ==> bounded(path_image g)"
  by (metis bounded_path_image simple_path_imp_path)

lemma closed_simple_path_image:
  fixes g :: "real ==> 'a::t2_space"
  shows "simple_path g ==> closed(path_image g)"
  by (metis closed_path_image simple_path_imp_path)

lemma connected_arc_image: "arc g ==> connected(path_image g)"
  by (metis connected_path_image arc_imp_path)

lemma compact_arc_image: "arc g ==> compact(path_image g)"
  by (metis compact_path_image arc_imp_path)

lemma bounded_arc_image: "arc g ==> bounded(path_image g)"
  by (metis bounded_path_image arc_imp_path)

lemma closed_arc_image:
  fixes g :: "real ==> 'a::t2_space"
  shows "arc g ==> closed(path_image g)"
  by (metis closed_path_image arc_imp_path)

lemma path_image_join_subset: "path_image (g1 +++ g2) path_image g1 path_image g2"
  unfolding path_image_def joinpaths_def
  by auto

lemma subset_path_image_join:
  assumes "path_image g1 S" and "path_image g2 S"
  shows "path_image (g1 +++ g2) S"
  using path_image_join_subset[of g1 g2] and assms
  by auto

lemma path_image_join:
  assumes "pathfinish g1 = pathstart g2"
  shows "path_image(g1 +++ g2) = path_image g1 path_image g2"
proof -
  have "path_image g1 path_image (g1 +++ g2)"
  proof (clarsimp simp: path_image_def joinpaths_def)
    fix u::real
    assume "0 u" "u 1"
    then show "g1 u (λx. g1 (2 * x)) ` ({0..1} {x. x * 2 1})"
      by (rule_tac x="u/2" in image_eqI) auto
  qed
  moreover 
  have 🍋"g2 u (λx. g2 (2 * x - 1)) ` ({0..1} {x. ¬ x * 2 1})" 
    if "0 < u" "u 1" for u
    using that assms
    by (rule_tac x="(u+1)/2" in image_eqI) (auto simp: field_simps pathfinish_def pathstart_def)
  have "g2 0 (λx. g1 (2 * x)) ` ({0..1} {x. x * 2 1})"
    using assms
    by (rule_tac x="1/2" in image_eqI) (auto simp: pathfinish_def pathstart_def)
  then have "path_image g2 path_image (g1 +++ g2)"
    by (auto simp: path_image_def joinpaths_def intro!: 🍋)
  ultimately show ?thesis
    using path_image_join_subset by blast
qed

lemma not_in_path_image_join:
  assumes "x path_image g1" and "x path_image g2"
  shows "x path_image (g1 +++ g2)"
  using assms and path_image_join_subset[of g1 g2]
  by auto

lemma pathstart_compose: "pathstart(f p) = f(pathstart p)"
  by (simp add: pathstart_def)

lemma pathfinish_compose: "pathfinish(f p) = f(pathfinish p)"
  by (simp add: pathfinish_def)

lemma path_image_compose: "path_image (f p) = f ` (path_image p)"
  by (simp add: image_comp path_image_def)

lemma path_compose_join: "f (p +++ q) = (f p) +++ (f q)"
  by (rule ext) (simp add: joinpaths_def)

lemma path_compose_reversepath: "f reversepath p = reversepath(f p)"
  by (rule ext) (simp add: reversepath_def)

lemma joinpaths_eq:
  "(t. t {0..1} ==> p t = p' t) ==>
   (t. t {0..1} ==> q t = q' t)
   ==> t {0..1} ==> (p +++ q) t = (p' +++ q') t"
  by (auto simp: joinpaths_def)

lemma loop_free_inj_on: "loop_free g ==> inj_on g {0<..<1}"
  by (force simp: inj_on_def loop_free_def)

lemma simple_path_inj_on: "simple_path g ==> inj_on g {0<..<1}"
  using loop_free_inj_on simple_path_def by auto


subsection🍋tag unimportant\<open>Simple paths with the endpoints removed

lemma simple_path_endless:
  assumes "simple_path c"
  shows "path_image c - {pathstart c,pathfinish c} = c ` {0<..<1}" (is "?lhs = ?rhs")
proof
  show "?lhs ?rhs"
    using less_eq_real_def by (auto simp: path_image_def pathstart_def pathfinish_def)
  show "?rhs ?lhs"
    using assms 
    apply (simp add: image_subset_iff path_image_def pathstart_def pathfinish_def simple_path_def loop_free_def Ball_def)
    by (smt (verit))
qed

lemma connected_simple_path_endless:
  assumes "simple_path c"
  shows "connected(path_image c - {pathstart c,pathfinish c})"
proof -
  have "continuous_on {0<..<1} c"
    using assms by (simp add: simple_path_def continuous_on_path path_def subset_iff)
  then have "connected (c ` {0<..<1})"
    using connected_Ioo connected_continuous_image by blast
  then show ?thesis
    using assms by (simp add: simple_path_endless)
qed

lemma nonempty_simple_path_endless:
    "simple_path c ==> path_image c - {pathstart c,pathfinish c} {}"
  by (simp add: simple_path_endless)

lemma simple_path_continuous_image:
  assumes "simple_path f" "continuous_on (path_image f) g" "inj_on g (path_image f)"
  shows   "simple_path (g f)"
  unfolding simple_path_def
proof
  show "path (g f)"
    using assms unfolding simple_path_def by (intro path_continuous_image) auto
  from assms have [simp]: "g (f x) = g (f y) f x = f y" if "x {0..1}" "y {0..1}" for x y
    unfolding inj_on_def path_image_def using that by fastforce
  show "loop_free (g f)"
    using assms(1) by (auto simp: loop_free_def simple_path_def)
qed

subsection🍋tag unimportant\<open>The operations on paths

lemma path_image_subset_reversepath: "path_image(reversepath g) path_image g"
  by simp

lemma path_imp_reversepath: "path g ==> path(reversepath g)"
  by simp

lemma half_bounded_equal: "1 x * 2 ==> x * 2 1 x = (1/2::real)"
  by simp

lemma continuous_on_joinpaths:
  assumes "continuous_on {0..1} g1" "continuous_on {0..1} g2" "pathfinish g1 = pathstart g2"
    shows "continuous_on {0..1} (g1 +++ g2)"
  using assms path_def path_join by blast

lemma path_join_imp: "[path g1; path g2; pathfinish g1 = pathstart g2] ==> path(g1 +++ g2)"
  by simp

lemma arc_join:
  assumes "arc g1" "arc g2"
          "pathfinish g1 = pathstart g2"
          "path_image g1 path_image g2 {pathstart g2}"
    shows "arc(g1 +++ g2)"
proof -
  have injg1: "inj_on g1 {0..1}" and injg2: "inj_on g2 {0..1}" 
     and g11: "g1 1 = g2 0" and sb: "g1 ` {0..1} g2 ` {0..1} {g2 0}"
    using assms
    by (auto simp: arc_def pathfinish_def pathstart_def path_image_def)
  { fix x and y::real
    assume xy: "g2 (2 * x - 1) = g1 (2 * y)" "x 1" "0 y" " y * 2 1" "¬ x * 2 1"
    then have "g1 (2 * y) = g2 0"
      using sb by force
    then have False
      using xy inj_onD injg2 by fastforce
   } note * = this
  have "inj_on (g1 +++ g2) {0..1}"
    using inj_onD [OF injg1] inj_onD [OF injg2] *
    by (simp add: inj_on_def joinpaths_def Ball_def) (smt (verit))
  then show ?thesis
    using arc_def assms path_join_imp by blast
qed

lemma simple_path_join_loop:
  assumes "arc g1" "arc g2"
          "pathfinish g1 = pathstart g2"  "pathfinish g2 = pathstart g1"
          "path_image g1 path_image g2 {pathstart g1, pathstart g2}"
        shows "simple_path(g1 +++ g2)"
proof -
  have injg1: "inj_on g1 {0..1}" and injg2: "inj_on g2 {0..1}"
    using assms by (auto simp add: arc_def)
  have g12: "g1 1 = g2 0"
   and g21: "g2 1 = g1 0"
   and sb:  "g1 ` {0..1} g2 ` {0..1} {g1 0, g2 0}"
    using assms
    by (simp_all add: arc_def pathfinish_def pathstart_def path_image_def)
  { fix x and y::real
    assume g2_eq: "g2 (2 * x - 1) = g1 (2 * y)"
      and xyI: "x 1 y 0"
      and xy: "x 1" "0 y" " y * 2 1" "¬ x * 2 1" 
    then consider "g1 (2 * y) = g1 0" | "g1 (2 * y) = g2 0"
      using sb by force
    then have False
    proof cases
      case 1
      then have "y = 0"
        using xy g2_eq by (auto dest!: inj_onD [OF injg1])
      then show ?thesis
        using xy g2_eq xyI by (auto dest: inj_onD [OF injg2] simp flip: g21)
    next
      case 2
      then have "2*x = 1"
        using g2_eq g12 inj_onD [OF injg2] atLeastAtMost_iff xy(1) xy(4) by fastforce
      with xy show False by auto
    qed
  } note * = this 
  have "loop_free(g1 +++ g2)"
    using inj_onD [OF injg1] inj_onD [OF injg2] *
    by (simp add: loop_free_def joinpaths_def Ball_def) (smt (verit))
  then show ?thesis
    by (simp add: arc_imp_path assms simple_path_def)
qed

lemma reversepath_joinpaths:
    "pathfinish g1 = pathstart g2 ==> reversepath(g1 +++ g2) = reversepath g2 +++ reversepath g1"
  unfolding reversepath_def pathfinish_def pathstart_def joinpaths_def
  by (rule ext) (auto simp: mult.commute)


subsection🍋tag unimportant\<open>Some reversed and "if and only if" versions of joining theorems

lemma path_join_path_ends:
  fixes g1 :: "real ==> 'a::metric_space"
  assumes "path(g1 +++ g2)" "path g2"
    shows "pathfinish g1 = pathstart g2"
proof (rule ccontr)
  define e where "e = dist (g1 1) (g2 0)"
  assume Neg: "pathfinish g1 pathstart g2"
  then have "0 < dist (pathfinish g1) (pathstart g2)"
    by auto
  then have "e > 0"
    by (metis e_def pathfinish_def pathstart_def)
  then have "e>0. d>0. x'{0..1}. dist x' 0 < d dist (g2 x') (g2 0) < e"
    using path g2 atLeastAtMost_iff zero_le_one unfolding path_def continuous_on_iff
    by blast
  then obtain d1 where "d1 > 0"
       and d1: "x'. [x'{0..1}; norm x' < d1] ==> dist (g2 x') (g2 0) < e/2"
    by (metis 0 🚫 half_gt_zero_iff norm_conv_dist)
  obtain d2 where "d2 > 0"
       and d2: "x'. [x'{0..1}; dist x' (1/2) < d2]
                      ==> dist ((g1 +++ g2) x') (g1 1) < e/2"
    using assms(1) e > 0 unfolding path_def continuous_on_iff
    apply (drule_tac x="1/2" in bspec, simp)
    apply (drule_tac x="e/2" in spec, force simp: joinpaths_def)
    done
  have int01_1: "min (1/2) (min d1 d2) / 2 {0..1}"
    using d1 > 0 d2 > 0 by (simp add: min_def)
  have dist1: "norm (min (1 / 2) (min d1 d2) / 2) < d1"
    using d1 > 0 d2 > 0 by (simp add: min_def dist_norm)
  have int01_2: "1/2 + min (1/2) (min d1 d2) / 4 {0..1}"
    using d1 > 0 d2 > 0 by (simp add: min_def)
  have dist2: "dist (1 / 2 + min (1 / 2) (min d1 d2) / 4) (1 / 2) < d2"
    using d1 > 0 d2 > 0 by (simp add: min_def dist_norm)
  have [simp]: "¬ min (1 / 2) (min d1 d2) 0"
    using d1 > 0 d2 > 0 by (simp add: min_def)
  have "dist (g2 (min (1 / 2) (min d1 d2) / 2)) (g1 1) < e/2"
       "dist (g2 (min (1 / 2) (min d1 d2) / 2)) (g2 0) < e/2"
    using d1 [OF int01_1 dist1] d2 [OF int01_2 dist2] by (simp_all add: joinpaths_def)
  then have "dist (g1 1) (g2 0) < e/2 + e/2"
    using dist_triangle_half_r e_def by blast
  then show False
    by (simp add: e_def [symmetric])
qed

lemma path_join_eq [simp]:
  fixes g1 :: "real ==> 'a::metric_space"
  assumes "path g1" "path g2"
    shows "path(g1 +++ g2) pathfinish g1 = pathstart g2"
  using assms by (metis path_join_path_ends path_join_imp)

lemma simple_path_joinE:
  assumes "simple_path(g1 +++ g2)" and "pathfinish g1 = pathstart g2"
  obtains "arc g1" "arc g2"
          "path_image g1 path_image g2 {pathstart g1, pathstart g2}"
proof -
  have *: "x y. [0 x; x 1; 0 y; y 1; (g1 +++ g2) x = (g1 +++ g2) y]
               ==> x = y x = 0 y = 1 x = 1 y = 0"
    using assms by (simp add: simple_path_def loop_free_def)
  have "path g1"
    using assms path_join simple_path_imp_path by blast
  moreover have "inj_on g1 {0..1}"
  proof (clarsimp simp: inj_on_def)
    fix x y
    assume "g1 x = g1 y" "0 x" "x 1" "0 y" "y 1"
    then show "x = y"
      using * [of "x/2" "y/2"by (simp add: joinpaths_def split_ifs)
  qed
  ultimately have "arc g1"
    using assms  by (simp add: arc_def)
  have [simp]: "g2 0 = g1 1"
    using assms by (metis pathfinish_def pathstart_def)
  have "path g2"
    using assms path_join simple_path_imp_path by blast
  moreover have "inj_on g2 {0..1}"
  proof (clarsimp simp: inj_on_def)
    fix x y
    assume "g2 x = g2 y" "0 x" "x 1" "0 y" "y 1"
    then show "x = y"
      using * [of "(x+1) / 2" "(y+1) / 2"]
      by (force simp: joinpaths_def split_ifs field_split_simps)
  qed
  ultimately have "arc g2"
    using assms  by (simp add: arc_def)
  have "g2 y = g1 0 g2 y = g1 1"
       if "g1 x = g2 y" "0 x" "x 1" "0 y" "y 1" for x y
      using * [of "x / 2" "(y + 1) / 2"] that
      by (auto simp: joinpaths_def split_ifs field_split_simps)
  then have "path_image g1 path_image g2 {pathstart g1, pathstart g2}"
    by (fastforce simp: pathstart_def pathfinish_def path_image_def)
  with arc g1 arc g2 show ?thesis using that by blast
qed

lemma simple_path_join_loop_eq:
  assumes "pathfinish g2 = pathstart g1" "pathfinish g1 = pathstart g2"
  shows "simple_path(g1 +++ g2)
             arc g1 arc g2 path_image g1 path_image g2 {pathstart g1, pathstart g2}"
  by (metis assms simple_path_joinE simple_path_join_loop)

lemma arc_join_eq:
  assumes "pathfinish g1 = pathstart g2"
    shows "arc(g1 +++ g2)
           arc g1 arc g2 path_image g1 path_image g2 {pathstart g2}"
           (is "?lhs = ?rhs")
proof
  assume ?lhs then show ?rhs 
    using reversepath_simps assms
    by (smt (verit, best) Int_commute arc_reversepath arc_simple_path in_mono insertE pathstart_join 
          reversepath_joinpaths simple_path_joinE subsetI)
next
  assume ?rhs then show ?lhs
    using assms
    by (fastforce simp: pathfinish_def pathstart_def intro!: arc_join)
qed

lemma arc_join_eq_alt:
  "pathfinish g1 = pathstart g2
   ==> arc(g1 +++ g2) arc g1 arc g2 path_image g1 path_image g2 = {pathstart g2}"
  using pathfinish_in_path_image by (fastforce simp: arc_join_eq)


subsubsection🍋tag unimportant\<open>Symmetry and loops

lemma path_sym:
  "[pathfinish p = pathstart q; pathfinish q = pathstart p] ==> path(p +++ q) path(q +++ p)"
  by auto

lemma simple_path_sym:
  "[pathfinish p = pathstart q; pathfinish q = pathstart p]
     ==> simple_path(p +++ q) simple_path(q +++ p)"
  by (metis (full_types) inf_commute insert_commute simple_path_joinE simple_path_join_loop)

lemma path_image_sym:
  "[pathfinish p = pathstart q; pathfinish q = pathstart p]
     ==> path_image(p +++ q) = path_image(q +++ p)"
  by (simp add: path_image_join sup_commute)

lemma simple_path_joinI:
  assumes "arc p1" "arc p2" "pathfinish p1 = pathstart p2"
  assumes "path_image p1 path_image p2
         insert (pathstart p2) (if pathstart p1 = pathfinish p2 then {pathstart p1} else {})"
  shows   "simple_path (p1 +++ p2)"
  by (smt (verit, best) Int_commute arc_imp_simple_path arc_join assms insert_commute simple_path_join_loop simple_path_sym)

lemma simple_path_join3I:
  assumes "arc p1" "arc p2" "arc p3"
  assumes "path_image p1 path_image p2 {pathstart p2}"
  assumes "path_image p2 path_image p3 {pathstart p3}"
  assumes "path_image p1 path_image p3 {pathstart p1} {pathfinish p3}"
  assumes "pathfinish p1 = pathstart p2" "pathfinish p2 = pathstart p3"
  shows   "simple_path (p1 +++ p2 +++ p3)"
  using assms by (intro simple_path_joinI arc_join) (auto simp: path_image_join)

subsection🍋tag unimportant\<open>The joining of paths is associative

lemma path_assoc:
  "[pathfinish p = pathstart q; pathfinish q = pathstart r]
     ==> path(p +++ (q +++ r)) path((p +++ q) +++ r)"
  by simp

lemma simple_path_assoc:
  assumes "pathfinish p = pathstart q" "pathfinish q = pathstart r"
    shows "simple_path (p +++ (q +++ r)) simple_path ((p +++ q) +++ r)"
proof (cases "pathstart p = pathfinish r")
  case True show ?thesis
  proof
    assume "simple_path (p +++ q +++ r)"
    with assms True show "simple_path ((p +++ q) +++ r)"
      by (fastforce simp add: simple_path_join_loop_eq arc_join_eq path_image_join
                    dest: arc_distinct_ends [of r])
  next
    assume 0: "simple_path ((p +++ q) +++ r)"
    with assms True have q: "pathfinish r path_image q"
      using arc_distinct_ends
      by (fastforce simp add: simple_path_join_loop_eq arc_join_eq path_image_join)
    have "pathstart r path_image p"
      using assms
      by (metis 0 IntI arc_distinct_ends arc_join_eq_alt empty_iff insert_iff
              pathfinish_in_path_image pathfinish_join simple_path_joinE)
    with assms 0 q True show "simple_path (p +++ q +++ r)"
      by (auto simp: simple_path_join_loop_eq arc_join_eq path_image_join
               dest!: subsetD [OF _ IntI])
  qed
next
  case False
  { fix x :: 'a
    assume a: "path_image p path_image q {pathstart q}"
              "(path_image p path_image q) path_image r {pathstart r}"
              "x path_image p" "x path_image r"
    have "pathstart r path_image q"
      by (metis assms(2) pathfinish_in_path_image)
    with a have "x = pathstart q"
      by blast
  }
  with False assms show ?thesis
    by (auto simp: simple_path_eq_arc simple_path_join_loop_eq arc_join_eq path_image_join)
qed

lemma arc_assoc:
     "[pathfinish p = pathstart q; pathfinish q = pathstart r]
      ==> arc(p +++ (q +++ r)) arc((p +++ q) +++ r)"
by (simp add: arc_simple_path simple_path_assoc)


subsectionSubpath

definition🍋tag important subpath :: "real ==> real ==> (real ==> 'a) ==> real ==> 'a::real_normed_vector"
  where "subpath a b g λx. g((b - a) * x + a)"

lemma path_image_subpath_gen:
  fixes g :: "_ ==> 'a::real_normed_vector"
  shows "path_image(subpath u v g) = g ` (closed_segment u v)"
  by (auto simp add: closed_segment_real_eq path_image_def subpath_def)

lemma path_image_subpath:
  fixes g :: "real ==> 'a::real_normed_vector"
  shows "path_image(subpath u v g) = (if u v then g ` {u..v} else g ` {v..u})"
  by (simp add: path_image_subpath_gen closed_segment_eq_real_ivl)

lemma path_image_subpath_commute:
  fixes g :: "real ==> 'a::real_normed_vector"
  shows "path_image(subpath u v g) = path_image(subpath v u g)"
  by (simp add: path_image_subpath_gen closed_segment_eq_real_ivl)

lemma path_subpath [simp]:
  fixes g :: "real ==> 'a::real_normed_vector"
  assumes "path g" "u {0..1}" "v {0..1}"
    shows "path(subpath u v g)"
proof -
  have "continuous_on {u..v} g" "continuous_on {v..u} g"
    using assms continuous_on_path by fastforce+
  then have "continuous_on {0..1} (g (λx. ((v-u) * x+ u)))"
    by (intro continuous_intros; simp add: image_affinity_atLeastAtMost [where c=u])
  then show ?thesis
    by (simp add: path_def subpath_def)
qed

lemma pathstart_subpath [simp]: "pathstart(subpath u v g) = g(u)"
  by (simp add: pathstart_def subpath_def)

lemma pathfinish_subpath [simp]: "pathfinish(subpath u v g) = g(v)"
  by (simp add: pathfinish_def subpath_def)

lemma subpath_trivial [simp]: "subpath 0 1 g = g"
  by (simp add: subpath_def)

lemma subpath_reversepath: "subpath 1 0 g = reversepath g"
  by (simp add: reversepath_def subpath_def)

lemma reversepath_subpath: "reversepath(subpath u v g) = subpath v u g"
  by (simp add: reversepath_def subpath_def algebra_simps)

lemma subpath_translation: "subpath u v ((λx. a + x) g) = (λx. a + x) subpath u v g"
  by (rule ext) (simp add: subpath_def)

lemma subpath_image: "subpath u v (f g) = f subpath u v g"
  by (rule ext) (simp add: subpath_def)

lemma affine_ineq:
  fixes x :: "'a::linordered_idom"
  assumes "x 1" "v u"
    shows "v + x * u u + x * v"
proof -
  have "(1-x)*(u-v) 0"
    using assms by auto
  then show ?thesis
    by (simp add: algebra_simps)
qed

lemma sum_le_prod1:
  fixes a::real shows "[a 1; b 1] ==> a + b 1 + a * b"
  by (metis add.commute affine_ineq mult.right_neutral)

lemma simple_path_subpath_eq:
  "simple_path(subpath u v g)
     path(subpath u v g) uv
     (x y. x closed_segment u v y closed_segment u v g x = g y
                 x = y x = u y = v x = v y = u)"
    (is "?lhs = ?rhs")
proof 
  assume ?lhs
  then have p: "path (λx. g ((v - u) * x + u))"
        and sim: "(x y. [x{0..1}; y{0..1}; g ((v - u) * x + u) = g ((v - u) * y + u)]
                  ==> x = y x = 0 y = 1 x = 1 y = 0)"
    by (auto simp: simple_path_def loop_free_def subpath_def)
  { fix x y
    assume "x closed_segment u v" "y closed_segment u v" "g x = g y"
    then have "x = y x = u y = v x = v y = u"
      using sim [of "(x-u)/(v-u)" "(y-u)/(v-u)"] p
      by (auto split: if_split_asm simp add: closed_segment_real_eq image_affinity_atLeastAtMost)
        (simp_all add: field_split_simps)
  } moreover
  have "path(subpath u v g) uv"
    using sim [of "1/3" "2/3"] p
    by (auto simp: subpath_def)
  ultimately show ?rhs
    by metis
next
  assume ?rhs
  then
  have d1: "x y. [g x = g y; u x; x v; u y; y v] ==> x = y x = u y = v x = v y = u"
   and d2: "x y. [g x = g y; v x; x u; v y; y u] ==> x = y x = u y = v x = v y = u"
   and ne: "u < v v < u"
   and psp: "path (subpath u v g)"
    by (auto simp: closed_segment_real_eq image_affinity_atLeastAtMost)
  have [simp]: "x. u + x * v = v + x * u u=v x=1"
    by algebra
  show ?lhs using psp ne
    unfolding simple_path_def loop_free_def subpath_def
    by (fastforce simp add: algebra_simps affine_ineq mult_left_mono crossproduct_eq dest: d1 d2)
qed

lemma arc_subpath_eq:
  "arc(subpath u v g) path(subpath u v g) uv inj_on g (closed_segment u v)"
  by (smt (verit, best) arc_simple_path closed_segment_commute ends_in_segment(2) inj_on_def pathfinish_subpath pathstart_subpath simple_path_subpath_eq)


lemma simple_path_subpath:
  assumes "simple_path g" "u {0..1}" "v {0..1}" "u v"
  shows "simple_path(subpath u v g)"
  using assms
  unfolding simple_path_subpath_eq
  by (force simp:  simple_path_def loop_free_def closed_segment_real_eq image_affinity_atLeastAtMost)

lemma arc_simple_path_subpath:
    "[simple_path g; u {0..1}; v {0..1}; g u g v] ==> arc(subpath u v g)"
  by (force intro: simple_path_subpath simple_path_imp_arc)

lemma arc_subpath_arc:
    "[arc g; u {0..1}; v {0..1}; u v] ==> arc(subpath u v g)"
  by (meson arc_def arc_imp_simple_path arc_simple_path_subpath inj_onD)

lemma arc_simple_path_subpath_interior:
    "[simple_path g; u {0..1}; v {0..1}; u v; u-v < 1] ==> arc(subpath u v g)"
  by (force simp: simple_path_def loop_free_def intro: arc_simple_path_subpath)

lemma path_image_subpath_subset:
    "[u {0..1}; v {0..1}] ==> path_image(subpath u v g) path_image g"
  by (metis atLeastAtMost_iff atLeastatMost_subset_iff path_image_def path_image_subpath subset_image_iff)

lemma join_subpaths_middle: "subpath (0) ((1 / 2)) p +++ subpath ((1 / 2)) 1 p = p"
  by (rule ext) (simp add: joinpaths_def subpath_def field_split_simps)


subsection🍋tag unimportant\<open>There is a subpath to the frontier

lemma subpath_to_frontier_explicit:
    fixes S :: "'a::metric_space set"
    assumes g: "path g" and "pathfinish g S"
    obtains u where "0 u" "u 1"
                "x. 0 x x < u ==> g x interior S"
                "(g u interior S)" "(u = 0 g u closure S)"
proof -
  have gcon: "continuous_on {0..1} g"     
    using g by (simp add: path_def)
  moreover have "bounded ({u. g u closure (- S)} {0..1})"
    using compact_eq_bounded_closed by fastforce
  ultimately have com: "compact ({0..1} {u. g u closure (- S)})"
    using closed_vimage_Int
    by (metis (full_types) Int_commute closed_atLeastAtMost closed_closure compact_eq_bounded_closed vimage_def)
  have "1 {u. g u closure (- S)}"
    using assms by (simp add: pathfinish_def closure_def)
  then have dis: "{0..1} {u. g u closure (- S)} {}"
    using atLeastAtMost_iff zero_le_one by blast
  then obtain u where "0 u" "u 1" and gu: "g u closure (- S)"
                  and umin: "t. [0 t; t 1; g t closure (- S)] ==> u t"
    using compact_attains_inf [OF com dis] by fastforce
  then have umin': "t. [0 t; t 1; t < u] ==> g t S"
    using closure_def by fastforce
  have 🍋"g u closure S" if "u 0"
  proof -
    have "u > 0" using that 0 u by auto
    { fix e::real assume "e > 0"
      obtain d where "d>0" and d: "x'. [x' {0..1}; dist x' u d] ==> dist (g x') (g u) < e"
        using continuous_onE [OF gcon _ e > 00 _ _ 1 atLeastAtMost_iff by auto
      have *: "dist (max 0 (u - d / 2)) u d"
        using 0 u u 1 d > 0 by (simp add: dist_real_def)
      have "yS. dist y (g u) < e"
        using 0 🚫 u 1 d > 0
        by (force intro: d [OF _ *] umin')
    }
    then show ?thesis
      by (simp add: frontier_def closure_approachable)
  qed
  show ?thesis
  proof
    show "x. 0 x x < u ==> g x interior S"
      using u 1 interior_closure umin by fastforce
    show "g u interior S"
      by (simp add: gu interior_closure)
  qed (use 0 u u 1 🍋 in auto)
qed

lemma subpath_to_frontier_strong:
    assumes g: "path g" and "pathfinish g S"
    obtains u where "0 u" "u 1" "g u interior S"
                    "u = 0 (x. 0 x x < 1 subpath 0 u g x interior S) g u closure S"
proof -
  obtain u where "0 u" "u 1"
             and gxin: "x. 0 x x < u ==> g x interior S"
             and gunot: "(g u interior S)" and u0: "(u = 0 g u closure S)"
    using subpath_to_frontier_explicit [OF assms] by blast
  show ?thesis
  proof
    show "g u interior S"
      using gunot by blast
  qed (use 0 u u 1 u0 in (force simp: subpath_def gxin)+)
qed

lemma subpath_to_frontier:
    assumes g: "path g" and g0: "pathstart g closure S" and g1: "pathfinish g S"
    obtains u where "0 u" "u 1" "g u frontier S" "path_image(subpath 0 u g) - {g u} interior S"
proof -
  obtain u where "0 u" "u 1"
             and notin: "g u interior S"
             and disj: "u = 0
                        (x. 0 x x < 1 subpath 0 u g x interior S) g u closure S"
                       (is "_ ?P")
    using subpath_to_frontier_strong [OF g g1] by blast
  show ?thesis
  proof
    show "g u frontier S"
      by (metis DiffI disj frontier_def g0 notin pathstart_def)
    show "path_image (subpath 0 u g) - {g u} interior S"
      using disj
    proof
      assume "u = 0"
      then show ?thesis
        by (simp add: path_image_subpath)
    next
      assume P: ?P
      show ?thesis
      proof (clarsimp simp add: path_image_subpath_gen)
        fix y
        assume y: "y closed_segment 0 u" "g y interior S"
        with 0 u have "0 y" "y u" 
          by (auto simp: closed_segment_eq_real_ivl split: if_split_asm)
        then have "y=u subpath 0 u g (y/u) interior S"
          using P less_eq_real_def by force
        then show "g y = g u"
          using y by (auto simp: subpath_def split: if_split_asm)
      qed
    qed
  qed (use 0 u u 1 in auto)
qed

lemma exists_path_subpath_to_frontier:
    fixes S :: "'a::real_normed_vector set"
    assumes "path g" "pathstart g closure S" "pathfinish g S"
    obtains h where "path h" "pathstart h = pathstart g" "path_image h path_image g"
                    "path_image h - {pathfinish h} interior S"
                    "pathfinish h frontier S"
proof -
  obtain u where u: "0 u" "u 1" "g u frontier S" "(path_image(subpath 0 u g) - {g u}) interior S"
    using subpath_to_frontier [OF assms] by blast
  show ?thesis
  proof
    show "path_image (subpath 0 u g) path_image g"
      by (simp add: path_image_subpath_subset u)
    show "pathstart (subpath 0 u g) = pathstart g"
      by (metis pathstart_def pathstart_subpath)
  qed (use assms u in auto simp: path_image_subpath)
qed

lemma exists_path_subpath_to_frontier_closed:
    fixes S :: "'a::real_normed_vector set"
    assumes S: "closed S" and g: "path g" and g0: "pathstart g S" and g1: "pathfinish g S"
    obtains h where "path h" "pathstart h = pathstart g" "path_image h path_image g S"
                    "pathfinish h frontier S"
  by (smt (verit, del_insts) Diff_iff Int_iff S closure_closed exists_path_subpath_to_frontier 
      frontier_def g g0 g1 interior_subset singletonD subset_eq)


subsection Shift Path to Start at Some Given Point

definition🍋tag important shiftpath :: "real ==> (real ==> 'a::topological_space) ==> real ==> 'a"
  where "shiftpath a f = (λx. if (a + x) 1 then f (a + x) else f (a + x - 1))"

lemma shiftpath_alt_def: "shiftpath a f = (λx. if x 1-a then f (a + x) else f (a + x - 1))"
  by (auto simp: shiftpath_def)

lemma pathstart_shiftpath: "a 1 ==> pathstart (shiftpath a g) = g a"
  unfolding pathstart_def shiftpath_def by auto

lemma pathfinish_shiftpath:
  assumes "0 a"
    and "pathfinish g = pathstart g"
  shows "pathfinish (shiftpath a g) = g a"
  using assms
  unfolding pathstart_def pathfinish_def shiftpath_def
  by auto

lemma endpoints_shiftpath:
  assumes "pathfinish g = pathstart g"
    and "a {0 .. 1}"
  shows "pathfinish (shiftpath a g) = g a"
    and "pathstart (shiftpath a g) = g a"
  using assms
  by (simp_all add: pathstart_shiftpath pathfinish_shiftpath)

lemma closed_shiftpath:
  assumes "pathfinish g = pathstart g"
    and "a {0..1}"
  shows "pathfinish (shiftpath a g) = pathstart (shiftpath a g)"
  using endpoints_shiftpath[OF assms]
  by auto

lemma path_shiftpath:
  assumes "path g"
    and "pathfinish g = pathstart g"
    and "a {0..1}"
  shows "path (shiftpath a g)"
proof -
  have *: "{0 .. 1} = {0 .. 1-a} {1-a .. 1}"
    using assms(3) by auto
  have **: "x. x + a = 1 ==> g (x + a - 1) = g (x + a)"
    by (smt (verit, best) assms(2) pathfinish_def pathstart_def)
  show ?thesis
    unfolding path_def shiftpath_def *
  proof (rule continuous_on_closed_Un)
    have contg: "continuous_on {0..1} g"
      using path g path_def by blast
    show "continuous_on {0..1-a} (λx. if a + x 1 then g (a + x) else g (a + x - 1))"
    proof (rule continuous_on_eq)
      show "continuous_on {0..1-a} (g (+) a)"
        by (intro continuous_intros continuous_on_subset [OF contg]) (use a {0..1} in auto)
    qed auto
    show "continuous_on {1-a..1} (λx. if a + x 1 then g (a + x) else g (a + x - 1))"
    proof (rule continuous_on_eq)
      show "continuous_on {1-a..1} (g (+) (a - 1))"
        by (intro continuous_intros continuous_on_subset [OF contg]) (use a {0..1} in auto)
    qed (auto simp: "**" add.commute add_diff_eq)
  qed auto
qed

lemma shiftpath_shiftpath:
  assumes "pathfinish g = pathstart g"
    and "a {0..1}"
    and "x {0..1}"
  shows "shiftpath (1 - a) (shiftpath a g) x = g x"
  using assms
  unfolding pathfinish_def pathstart_def shiftpath_def
  by auto

lemma path_image_shiftpath:
  assumes a: "a {0..1}"
    and "pathfinish g = pathstart g"
  shows "path_image (shiftpath a g) = path_image g"
proof -
  { fix x
    assume g: "g 1 = g 0" "x {0..1::real}" and gne: "y. y{0..1} {x. ¬ a + x 1} ==> g x g (a + y - 1)"
    then have "y{0..1} {x. a + x 1}. g x = g (a + y)"
    proof (cases "a x")
      case False
      then show ?thesis
        apply (rule_tac x="1 + x - a" in bexI)
        using g gne[of "1 + x - a"] a by (force simp: field_simps)+
    next
      case True
      then show ?thesis
        using g a  by (rule_tac x="x - a" in bexI) (auto simp: field_simps)
    qed
  }
  then show ?thesis
    using assms
    unfolding shiftpath_def path_image_def pathfinish_def pathstart_def
    by (auto simp: image_iff)
qed

lemma loop_free_shiftpath:
  assumes "loop_free g" "pathfinish g = pathstart g" and a: "0 a" "a 1"
    shows "loop_free (shiftpath a g)"
  unfolding loop_free_def
proof (intro conjI impI ballI)
  show "x = y x = 0 y = 1 x = 1 y = 0"
    if "x {0..1}" "y {0..1}" "shiftpath a g x = shiftpath a g y" for x y
    using that a assms unfolding shiftpath_def loop_free_def
    by (smt (verit, ccfv_threshold) atLeastAtMost_iff)
qed

lemma simple_path_shiftpath:
  assumes "simple_path g" "pathfinish g = pathstart g" and a: "0 a" "a 1"
  shows "simple_path (shiftpath a g)"
  using assms loop_free_shiftpath path_shiftpath simple_path_def by fastforce


subsection Straight-Line Paths

definition🍋tag important linepath :: "'a::real_normed_vector ==> 'a ==> real ==> 'a"
  where "linepath a b = (λx. (1 - x) *🪙R a + x *🪙R b)"

lemma pathstart_linepath[simp]: "pathstart (linepath a b) = a"
  unfolding pathstart_def linepath_def
  by auto

lemma pathfinish_linepath[simp]: "pathfinish (linepath a b) = b"
  unfolding pathfinish_def linepath_def
  by auto

lemma linepath_inner: "linepath a b x v = linepath (a v) (b v) x"
  by (simp add: linepath_def algebra_simps)

lemma Re_linepath': "Re (linepath a b x) = linepath (Re a) (Re b) x"
  by (simp add: linepath_def)

lemma Im_linepath': "Im (linepath a b x) = linepath (Im a) (Im b) x"
  by (simp add: linepath_def)

lemma linepath_0': "linepath a b 0 = a"
  by (simp add: linepath_def)

lemma linepath_1': "linepath a b 1 = b"
  by (simp add: linepath_def)

lemma continuous_linepath_at[intro]: "continuous (at x) (linepath a b)"
  unfolding linepath_def
  by (intro continuous_intros)

lemma continuous_on_linepath [intro,continuous_intros]: "continuous_on s (linepath a b)"
  using continuous_linepath_at
  by (auto intro!: continuous_at_imp_continuous_on)

lemma path_linepath[iff]: "path (linepath a b)"
  unfolding path_def
  by (rule continuous_on_linepath)

lemma path_image_linepath[simp]: "path_image (linepath a b) = closed_segment a b"
  unfolding path_image_def segment linepath_def
  by auto

lemma reversepath_linepath[simp]: "reversepath (linepath a b) = linepath b a"
  unfolding reversepath_def linepath_def
  by auto

lemma linepath_0 [simp]: "linepath 0 b x = x *🪙R b"
  by (simp add: linepath_def)

lemma linepath_cnj: "cnj (linepath a b x) = linepath (cnj a) (cnj b) x"
  by (simp add: linepath_def)

lemma arc_linepath:
  assumes "a b" shows [simp]: "arc (linepath a b)"
proof -
  {
    fix x y :: "real"
    assume "x *🪙R b + y *🪙R a = x *🪙R a + y *🪙R b"
    then have "(x - y) *🪙R a = (x - y) *🪙R b"
      by (simp add: algebra_simps)
    with assms have "x = y"
      by simp
  }
  then show ?thesis
    unfolding arc_def inj_on_def
    by (fastforce simp: algebra_simps linepath_def)
qed

lemma simple_path_linepath[intro]: "a b ==> simple_path (linepath a b)"
  by (simp add: arc_imp_simple_path)

lemma linepath_trivial [simp]: "linepath a a x = a"
  by (simp add: linepath_def real_vector.scale_left_diff_distrib)

lemma linepath_refl: "linepath a a = (λx. a)"
  by auto

lemma subpath_refl: "subpath a a g = linepath (g a) (g a)"
  by (simp add: subpath_def linepath_def algebra_simps)

lemma linepath_of_real: "(linepath (of_real a) (of_real b) x) = of_real ((1 - x)*a + x*b)"
  by (simp add: scaleR_conv_of_real linepath_def)

lemma of_real_linepath: "of_real (linepath a b x) = linepath (of_real a) (of_real b) x"
  by (metis linepath_of_real mult.right_neutral of_real_def real_scaleR_def)

lemma inj_on_linepath:
  assumes "a b" shows "inj_on (linepath a b) {0..1}"
  using arc_imp_inj_on arc_linepath assms by blast

lemma linepath_le_1:
  fixes a::"'a::linordered_idom" shows "[a 1; b 1; 0 u; u 1] ==> (1 - u) * a + u * b 1"
  using mult_left_le [of a "1-u"] mult_left_le [of b u] by auto

lemma linepath_in_path:
  shows "x {0..1} ==> linepath a b x closed_segment a b"
  by (auto simp: segment linepath_def)

lemma linepath_image_01: "linepath a b ` {0..1} = closed_segment a b"
  by (auto simp: segment linepath_def)

lemma linepath_in_convex_hull:
  fixes x::real
  assumes "a convex hull S"
    and "b convex hull S"
    and "0x" "x1"
  shows "linepath a b x convex hull S"
  by (meson assms atLeastAtMost_iff convex_contains_segment convex_convex_hull linepath_in_path subset_eq)

lemma Re_linepath: "Re(linepath (of_real a) (of_real b) x) = (1 - x)*a + x*b"
  by (simp add: linepath_def)

lemma Im_linepath: "Im(linepath (of_real a) (of_real b) x) = 0"
  by (simp add: linepath_def)

lemma
  assumes "x closed_segment y z"
  shows in_closed_segment_imp_Re_in_closed_segment: "Re x closed_segment (Re y) (Re z)" (is ?th1)
    and in_closed_segment_imp_Im_in_closed_segment: "Im x closed_segment (Im y) (Im z)" (is ?th2)
proof -
  from assms obtain t where t: "t {0..1}" "x = linepath y z t"
    by (metis imageE linepath_image_01)
  have "Re x = linepath (Re y) (Re z) t" "Im x = linepath (Im y) (Im z) t"
    by (simp_all add: t Re_linepath' Im_linepath')
  with t(1) show ?th1 ?th2
    using linepath_in_path[of t "Re y" "Re z"] linepath_in_path[of t "Im y" "Im z"by simp_all
qed

lemma linepath_in_open_segment: "t {0<..<1} ==> x y ==> linepath x y t open_segment x y"
  unfolding greaterThanLessThan_iff by (metis in_segment(2) linepath_def)

lemma in_open_segment_imp_Re_in_open_segment:
  assumes "x open_segment y z" "Re y Re z"
  shows   "Re x open_segment (Re y) (Re z)"
proof -
  from assms obtain t where t: "t {0<..<1}" "x = linepath y z t"
    by (metis greaterThanLessThan_iff in_segment(2) linepath_def)
  have "Re x = linepath (Re y) (Re z) t"
    by (simp_all add: t Re_linepath')
  with t(1) show ?thesis
    using linepath_in_open_segment[of t "Re y" "Re z"] assms by auto
qed

lemma in_open_segment_imp_Im_in_open_segment:
  assumes "x open_segment y z" "Im y Im z"
  shows   "Im x open_segment (Im y) (Im z)"
proof -
  from assms obtain t where t: "t {0<..<1}" "x = linepath y z t"
    by (metis greaterThanLessThan_iff in_segment(2) linepath_def)
  have "Im x = linepath (Im y) (Im z) t"
    by (simp_all add: t Im_linepath')
  with t(1) show ?thesis
    using linepath_in_open_segment[of t "Im y" "Im z"] assms by auto
qed

lemma bounded_linear_linepath:
  assumes "bounded_linear f"
  shows   "f (linepath a b x) = linepath (f a) (f b) x"
proof -
  interpret f: bounded_linear f by fact
  show ?thesis by (simp add: linepath_def f.add f.scale)
qed

lemma bounded_linear_linepath':
  assumes "bounded_linear f"
  shows   "f linepath a b = linepath (f a) (f b)"
  using bounded_linear_linepath[OF assms] by (simp add: fun_eq_iff)

lemma linepath_cnj': "cnj linepath a b = linepath (cnj a) (cnj b)"
  by (simp add: linepath_def fun_eq_iff)

lemma differentiable_linepath [intro]: "linepath a b differentiable at x within A"
  by (auto simp: linepath_def)

lemma has_vector_derivative_linepath_within:
    "(linepath a b has_vector_derivative (b - a)) (at x within S)"
  by (force intro: derivative_eq_intros simp add: linepath_def has_vector_derivative_def algebra_simps)

lemma linepath_real_ge_left:
  fixes x y :: real
  assumes "x y" "t 0"
  shows   "linepath x y t x"
proof -
  have "x + 0 x + t *🪙R (y - x)"
    using assms by (intro add_left_mono) auto
  also have " = linepath x y t"
    by (simp add: linepath_def algebra_simps)
  finally show ?thesis by simp
qed

lemma linepath_real_le_right:
  fixes x y :: real
  assumes "x y" "t 1"
  shows   "linepath x y t y"
proof -
  have "y + 0 y + (1 - t) *🪙R (x - y)"
    using assms by (intro add_left_mono) (auto intro: mult_nonneg_nonpos)
  also have "y + (1 - t) *🪙R (x - y) = linepath x y t"
    by (simp add: linepath_def algebra_simps)
  finally show ?thesis by simp
qed

lemma linepath_translate: "(+) c linepath a b = linepath (a + c) (b + c)"
  by (auto simp: linepath_def algebra_simps)


subsection🍋tag unimportant\<open>Segments via convex hulls

lemma segments_subset_convex_hull:
    "closed_segment a b (convex hull {a,b,c})"
    "closed_segment a c (convex hull {a,b,c})"
    "closed_segment b c (convex hull {a,b,c})"
    "closed_segment b a (convex hull {a,b,c})"
    "closed_segment c a (convex hull {a,b,c})"
    "closed_segment c b (convex hull {a,b,c})"
by (auto simp: segment_convex_hull linepath_of_real  elim!: rev_subsetD [OF _ hull_mono])

lemma midpoints_in_convex_hull:
  assumes "x convex hull s" "y convex hull s"
    shows "midpoint x y convex hull s"
  using assms closed_segment_subset_convex_hull csegment_midpoint_subset by blast

lemma not_in_interior_convex_hull_3:
  fixes a :: "complex"
  shows "a interior(convex hull {a,b,c})"
        "b interior(convex hull {a,b,c})"
        "c interior(convex hull {a,b,c})"
  by (auto simp: card_insert_le_m1 not_in_interior_convex_hull)

lemma midpoint_in_closed_segment [simp]: "midpoint a b closed_segment a b"
  using midpoints_in_convex_hull segment_convex_hull by blast

lemma midpoint_in_open_segment [simp]: "midpoint a b open_segment a b a b"
  by (simp add: open_segment_def)

lemma continuous_IVT_local_extremum:
  fixes f :: "'a::euclidean_space ==> real"
  assumes contf: "continuous_on (closed_segment a b) f"
      and ab: "a b" "f a = f b"
  obtains z where "z open_segment a b"
                  "(w closed_segment a b. (f w) (f z))
                   (w closed_segment a b. (f z) (f w))"
proof -
  obtain c where "c closed_segment a b" and c: "y. y closed_segment a b ==> f y f c"
    using continuous_attains_sup [of "closed_segment a b" f] contf by auto
  moreover
  obtain d where "d closed_segment a b" and d: "y. y closed_segment a b ==> f d f y"
    using continuous_attains_inf [of "closed_segment a b" f] contf by auto
  ultimately show ?thesis
    by (smt (verit) UnE ab closed_segment_eq_open empty_iff insert_iff midpoint_in_open_segment that)
qed

textAn injective map into R is also an open map w.r.T. the universe, and conversely.
proposition injective_eq_1d_open_map_UNIV:
  fixes f :: "real ==> real"
  assumes contf: "continuous_on S f" and S: "is_interval S"
    shows "inj_on f S (T. open T T S open(f ` T))"
          (is "?lhs = ?rhs")
proof safe
  fix T
  assume injf: ?lhs and "open T" and "T S"
  have "U. open U f x U U f ` T" if "x T" for x
  proof -
    obtain δ where "δ > 0" and δ: "cball x δ T"
      using open T x T open_contains_cball_eq by blast
    show ?thesis
    proof (intro exI conjI)
      have "closed_segment (x-δ) (x+δ) = {x-δ..x+δ}"
        using 0 🚫δ by (auto simp: closed_segment_eq_real_ivl)
      also have " S"
        using δ T S by (auto simp: dist_norm subset_eq)
      finally have "f ` (open_segment (x-δ) (x+δ)) = open_segment (f (x-δ)) (f (x+δ))"
        using continuous_injective_image_open_segment_1
        by (metis continuous_on_subset [OF contf] inj_on_subset [OF injf])
      then show "open (f ` {x-δ<..
        using 0 🚫δ by (simp add: open_segment_eq_real_ivl)
      show "f x f ` {x - δ<..
        by (auto simp: δ > 0)
      show "f ` {x - δ<.. f ` T"

        using δ by (auto simp: dist_norm subset_iff)
    qed
  qed
  with open_subopen show "open (f ` T)"
    by blast
next
  assume R: ?rhs
  have False if xy: "x S" "y S" and "f x = f y" "x y" for x y
  proof -
    have "open (f ` open_segment x y)"
      using R
      by (metis S convex_contains_open_segment is_interval_convex open_greaterThanLessThan open_segment_eq_real_ivl xy)
    moreover
    have "continuous_on (closed_segment x y) f"
      by (meson S closed_segment_subset contf continuous_on_subset is_interval_convex that)
    then obtain ξ where  open_segment x y"
                    and ξ: "(w closed_segment x y. (f w) (f ξ))

                            (w closed_segment x y. (f ξ) (f w))"
      using continuous_IVT_local_extremum [of x y f] f x = f y x y by blast
    ultimately obtain e where "e>0" and e: "u. dist u (f ξ) < e ==> u f ` open_segment x y"
      using open_dist by (metis image_eqI)
    have fin: "f ξ + (e/2) f ` open_segment x y" "f ξ - (e/2) f ` open_segment x y"
      using e [of "f ξ + (e/2)"] e [of "f ξ - (e/2)"e > 0 by (auto simp: dist_norm)
    show ?thesis
      using ξ 0 🚫 fin open_closed_segment by fastforce
  qed
  then show ?lhs
    by (force simp: inj_on_def)
qed


subsection🍋tag unimportant Bounding a point away from a path

lemma not_on_path_ball:
  fixes g :: "real ==> 'a::heine_borel"
  assumes "path g"
    and z: "z path_image g"
  shows "e > 0. ball z e path_image g = {}"
proof -
  have "closed (path_image g)"
    by (simp add: path g closed_path_image)
  then obtain a where "a path_image g" "y path_image g. dist z a dist z y"
    by (auto intro: distance_attains_inf[OF _ path_image_nonempty, of g z])
  then show ?thesis
    by (rule_tac x="dist z a" in exI) (use dist_commute z in auto)
qed

lemma not_on_path_cball:
  fixes g :: "real ==> 'a::heine_borel"
  assumes "path g"
    and "z path_image g"
  shows "e>0. cball z e (path_image g) = {}"
  by (smt (verit, ccfv_threshold) open_ball assms centre_in_ball inf.orderE inf_assoc
      inf_bot_right not_on_path_ball open_contains_cball_eq)

subsection Path component

text Original formalization by Tom Hales

definition🍋tag important "path_component S x y
  (g. path g path_image g S pathstart g = x pathfinish g = y)"

abbreviation🍋tag important
  "path_component_set S x Collect (path_component S x)"

lemmas path_defs = path_def pathstart_def pathfinish_def path_image_def path_component_def

lemma path_component_mem:
  assumes "path_component S x y"
  shows "x S" and "y S"
  using assms
  unfolding path_defs
  by auto

lemma path_component_refl:
  assumes "x S"
  shows "path_component S x x"
  using assms
  unfolding path_defs
  by (metis (full_types) assms continuous_on_const image_subset_iff path_image_def)

lemma path_component_refl_eq: "path_component S x x x S"
  by (auto intro!: path_component_mem path_component_refl)

lemma path_component_sym: "path_component S x y ==> path_component S y x"
  unfolding path_component_def
  by (metis (no_types) path_image_reversepath path_reversepath pathfinish_reversepath pathstart_reversepath)

lemma path_component_trans:
  assumes "path_component S x y" and "path_component S y z"
  shows "path_component S x z"
  using assms
  unfolding path_component_def
  by (metis path_join pathfinish_join pathstart_join subset_path_image_join)

lemma path_component_of_subset: "S T ==> path_component S x y ==> path_component T x y"
  unfolding path_component_def by auto

lemma path_component_linepath:
    fixes S :: "'a::real_normed_vector set"
    shows "closed_segment a b S ==> path_component S a b"
  unfolding path_component_def by fastforce

subsubsection🍋tag unimportant Path components as sets

lemma path_component_set:
  "path_component_set S x =
    {y. (g. path g path_image g S pathstart g = x pathfinish g = y)}"
  by (auto simp: path_component_def)

lemma path_component_subset: "path_component_set S x S"
  by (auto simp: path_component_mem(2))

lemma path_component_eq_empty: "path_component_set S x = {} x S"
  using path_component_mem path_component_refl_eq
    by fastforce

lemma path_component_mono:
     "S T ==> (path_component_set S x) (path_component_set T x)"
  by (simp add: Collect_mono path_component_of_subset)

lemma path_component_eq:
   "y path_component_set S x ==> path_component_set S y = path_component_set S x"
by (metis (no_types, lifting) Collect_cong mem_Collect_eq path_component_sym path_component_trans)


subsection Path connectedness of a space

definition🍋tag important "path_connected S
  (xS. yS. g. path g path_image g S pathstart g = x pathfinish g = y)"

lemma path_connectedin_iff_path_connected_real [simp]:
     "path_connectedin euclideanreal S path_connected S"
  by (simp add: path_connectedin path_connected_def path_defs image_subset_iff_funcset) 

lemma path_connected_component: "path_connected S (xS. yS. path_component S x y)"
  unfolding path_connected_def path_component_def by auto

lemma path_connected_component_set: "path_connected S (xS. path_component_set S x = S)"
  unfolding path_connected_component path_component_subset
  using path_component_mem by blast

lemma path_component_maximal:
     "[x T; path_connected T; T S] ==> T (path_component_set S x)"
  by (metis path_component_mono path_connected_component_set)

lemma convex_imp_path_connected:
  fixes S :: "'a::real_normed_vector set"
  assumes "convex S"
  shows "path_connected S"
  unfolding path_connected_def
  using assms convex_contains_segment by fastforce

lemma path_connected_UNIV [iff]: "path_connected (UNIV :: 'a::real_normed_vector set)"
  by (simp add: convex_imp_path_connected)

lemma path_component_UNIV: "path_component_set UNIV x = (UNIV :: 'a::real_normed_vector set)"
  using path_connected_component_set by auto

lemma path_connected_imp_connected:
  assumes "path_connected S"
  shows "connected S"
proof (rule connectedI)
  fix e1 e2
  assume as: "open e1" "open e2" "S e1 e2" "e1 e2 S = {}" "e1 S {}" "e2 S {}"
  then obtain x1 x2 where obt:"x1 e1 S" "x2 e2 S"
    by auto
  then obtain g where g: "path g" "path_image g S" and pg: "pathstart g = x1" "pathfinish g = x2"
    using assms[unfolded path_connected_def,rule_format,of x1 x2] by auto
  have *: "connected {0..1::real}"
    by (auto intro!: convex_connected)
  have "{0..1} {x {0..1}. g x e1} {x {0..1}. g x e2}"
    using as(3) g(2)[unfolded path_defs] by blast
  moreover have "{x {0..1}. g x e1} {x {0..1}. g x e2} = {}"
    using as(4) g(2)[unfolded path_defs]
    unfolding subset_eq
    by auto
  moreover have "{x {0..1}. g x e1} {} {x {0..1}. g x e2} {}"
    by (smt (verit, ccfv_threshold) IntE atLeastAtMost_iff empty_iff pg mem_Collect_eq obt pathfinish_def pathstart_def)
  ultimately show False
    using *[unfolded connected_local not_ex, rule_format,
      of "{0..1} g -` e1" "{0..1} g -` e2"]
    using continuous_openin_preimage_gen[OF g(1)[unfolded path_def] as(1)]
    using continuous_openin_preimage_gen[OF g(1)[unfolded path_def] as(2)]
    by auto
qed

lemma open_path_component:
  fixes S :: "'a::real_normed_vector set"
  assumes "open S"
  shows "open (path_component_set S x)"
  unfolding open_contains_ball
  by (metis assms centre_in_ball convex_ball convex_imp_path_connected equals0D openE 
      path_component_eq path_component_eq_empty path_component_maximal)

lemma open_non_path_component:
  fixes S :: "'a::real_normed_vector set"
  assumes "open S"
  shows "open (S - path_component_set S x)"
  unfolding open_contains_ball
proof
  fix y
  assume y: "y S - path_component_set S x"
  then obtain e where e: "e > 0" "ball y e S"
    using assms openE by auto
  show "e>0. ball y e S - path_component_set S x"
  proof (intro exI conjI subsetI DiffI notI)
    show "x. x ball y e ==> x S"
      using e by blast
    show False if "z ball y e" "z path_component_set S x" for z
      by (metis (no_types, lifting) Diff_iff centre_in_ball convex_ball convex_imp_path_connected  
          path_component_eq path_component_maximal subsetD that y e)
  qed (use e in auto)
qed

lemma connected_open_path_connected:
  fixes S :: "'a::real_normed_vector set"
  assumes "open S"
    and "connected S"
  shows "path_connected S"
  unfolding path_connected_component_set
proof (rule, rule, rule path_component_subset, rule)
  fix x y
  assume "x S" and "y S"
  show "y path_component_set S x"
  proof (rule ccontr)
    assume "¬ ?thesis"
    moreover have "path_component_set S x S {}"
      using x S path_component_eq_empty path_component_subset[of S x]
      by auto
    ultimately
    show False
      using y S open_non_path_component[OF open S] open_path_component[OF open S]
      using connected S[unfolded connected_def not_ex, rule_format,
        of "path_component_set S x" "S - path_component_set S x"]
      by auto
  qed
qed

lemma path_connected_continuous_image:
  assumes contf: "continuous_on S f"
    and "path_connected S"
  shows "path_connected (f ` S)"
  unfolding path_connected_def
proof clarsimp
  fix x y 
  assume x: "x S" and y: "y S" 
  with path_connected S
  show "g. path g path_image g f ` S pathstart g = f x pathfinish g = f y"
    unfolding path_defs path_connected_def
    using continuous_on_subset[OF contf]
    by (smt (verit, ccfv_threshold) continuous_on_compose2 image_eqI image_subset_iff)
qed

lemma path_connected_translationI:
  fixes a :: "'a :: topological_group_add"
  assumes "path_connected S" shows "path_connected ((λx. a + x) ` S)"
  by (intro path_connected_continuous_image assms continuous_intros)

lemma path_connected_translation:
  fixes a :: "'a :: topological_group_add"
  shows "path_connected ((λx. a + x) ` S) = path_connected S"
proof -
  have "x y. (+) (x::'a) ` (+) (0 - x) ` y = y"
    by (simp add: image_image)
  then show ?thesis
    by (metis (no_types) path_connected_translationI)
qed

lemma path_connected_segment [simp]:
    fixes a :: "'a::real_normed_vector"
    shows "path_connected (closed_segment a b)"
  by (simp add: convex_imp_path_connected)

lemma path_connected_open_segment [simp]:
    fixes a :: "'a::real_normed_vector"
    shows "path_connected (open_segment a b)"
  by (simp add: convex_imp_path_connected)

lemma homeomorphic_path_connectedness:
  "S homeomorphic T ==> path_connected S path_connected T"
  unfolding homeomorphic_def homeomorphism_def by (metis path_connected_continuous_image)

lemma path_connected_empty [simp]: "path_connected {}"
  unfolding path_connected_def by auto

lemma path_connected_singleton [simp]: "path_connected {a}"
  unfolding path_connected_def pathstart_def pathfinish_def path_image_def
  using path_def by fastforce

lemma path_connected_Un:
  assumes "path_connected S"
    and "path_connected T"
    and "S T {}"
  shows "path_connected (S T)"
  unfolding path_connected_component
proof (intro ballI)
  fix x y
  assume x: "x S T" and y: "y S T"
  from assms obtain z where z: "z S" "z T"
    by auto
  with x y show "path_component (S T) x y"
    by (smt (verit) assms(1,2) in_mono mem_Collect_eq path_component_eq path_component_maximal 
        sup.bounded_iff sup.cobounded2 sup_ge1)
qed

lemma path_connected_UNION:
  assumes "i. i A ==> path_connected (S i)"
    and "i. i A ==> z S i"
  shows "path_connected (iA. S i)"
  unfolding path_connected_component
proof clarify
  fix x i y j
  assume *: "i A" "x S i" "j A" "y S j"
  then have "path_component (S i) x z" and "path_component (S j) z y"
    using assms by (simp_all add: path_connected_component)
  then have "path_component (iA. S i) x z" and "path_component (iA. S i) z y"
    using *(1,3) by (meson SUP_upper path_component_of_subset)+
  then show "path_component (iA. S i) x y"
    by (rule path_component_trans)
qed

lemma path_component_path_image_pathstart:
  assumes p: "path p" and x: "x path_image p"
  shows "path_component (path_image p) (pathstart p) x"
proof -
  obtain y where x: "x = p y" and y: "0 y" "y 1"
    using x by (auto simp: path_image_def)
  show ?thesis
    unfolding path_component_def 
  proof (intro exI conjI)
    have "continuous_on ((*) y ` {0..1}) p"
      by (simp add: continuous_on_path image_mult_atLeastAtMost_if p y)
    then have "continuous_on {0..1} (p ((*) y))"
      using continuous_on_compose continuous_on_mult_const by blast
    then show "path (λu. p (y * u))"
      by (simp add: path_def)
    show "path_image (λu. p (y * u)) path_image p"
      using y mult_le_one by (fastforce simp: path_image_def image_iff)
  qed (auto simp: pathstart_def pathfinish_def x)
qed

lemma path_connected_path_image: "path p ==> path_connected(path_image p)"
  unfolding path_connected_component
  by (meson path_component_path_image_pathstart path_component_sym path_component_trans)

lemma path_connected_path_component [simp]:
  "path_connected (path_component_set S x)"
  by (smt (verit) mem_Collect_eq path_component_def path_component_eq path_component_maximal 
      path_connected_component path_connected_path_image pathstart_in_path_image)

lemma path_component: 
  "path_component S x y (t. path_connected t t S x t y t)"
    (is "?lhs = ?rhs")
proof 
  assume ?lhs then show ?rhs
    by (metis path_component_def path_connected_path_image pathfinish_in_path_image pathstart_in_path_image)
next
  assume ?rhs then show ?lhs
    by (meson path_component_of_subset path_connected_component)
qed

lemma path_component_path_component [simp]:
   "path_component_set (path_component_set S x) x = path_component_set S x"
  by (metis (full_types) mem_Collect_eq path_component_eq_empty path_component_refl path_connected_component_set path_connected_path_component)

lemma path_component_subset_connected_component:
   "(path_component_set S x) (connected_component_set S x)"
proof (cases "x S")
  case True show ?thesis
    by (simp add: True connected_component_maximal path_component_refl path_component_subset path_connected_imp_connected)
next
  case False then show ?thesis
    using path_component_eq_empty by auto
qed


subsection🍋tag unimportant\<open>Lemmas about path-connectedness

lemma path_connected_linear_image:
  fixes f :: "'a::real_normed_vector ==> 'b::real_normed_vector"
  assumes "path_connected S" "bounded_linear f"
  shows "path_connected(f ` S)"
  by (auto simp: linear_continuous_on assms path_connected_continuous_image)

lemma is_interval_path_connected: "is_interval S ==> path_connected S"
  by (simp add: convex_imp_path_connected is_interval_convex)

lemma path_connected_Ioi[simp]: "path_connected {a<..}" for a :: real
  by (simp add: convex_imp_path_connected)

lemma path_connected_Ici[simp]: "path_connected {a..}" for a :: real
  by (simp add: convex_imp_path_connected)

lemma path_connected_Iio[simp]: "path_connected {.. for a :: real
  by (simp add: convex_imp_path_connected)

lemma path_connected_Iic[simp]: "path_connected {..a}" for a :: real
  by (simp add: convex_imp_path_connected)

lemma path_connected_Ioo[simp]: "path_connected {a<.. for a b :: real
  by (simp add: convex_imp_path_connected)

lemma path_connected_Ioc[simp]: "path_connected {a<..b}" for a b :: real
  by (simp add: convex_imp_path_connected)

lemma path_connected_Ico[simp]: "path_connected {a.. for a b :: real
  by (simp add: convex_imp_path_connected)

lemma path_connectedin_path_image:
  assumes "pathin X g" shows "path_connectedin X (g ` ({0..1}))"
  unfolding pathin_def
proof (rule path_connectedin_continuous_map_image)
  show "continuous_map (subtopology euclideanreal {0..1}) X g"
    using assms pathin_def by blast
qed (auto simp: is_interval_1 is_interval_path_connected)

lemma path_connected_space_subconnected:
     "path_connected_space X

      (x topspace X. y topspace X. S. path_connectedin X S x S y S)"
  by (metis path_connectedin path_connectedin_topspace path_connected_space_def)


lemma connectedin_path_image: "pathin X g ==> connectedin X (g ` ({0..1}))"
  by (simp add: path_connectedin_imp_connectedin path_connectedin_path_image)

lemma compactin_path_image: "pathin X g ==> compactin X (g ` ({0..1}))"
  unfolding pathin_def
  by (rule image_compactin [of "top_of_set {0..1}"]) auto

lemma linear_homeomorphism_image:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "linear f" "inj f"
  obtains g where "homeomorphism (f ` S) S g f"
proof -
  obtain g where "linear g" "g f = id"
    using assms linear_injective_left_inverse by blast
  then have "homeomorphism (f ` S) S g f"
    using assms unfolding homeomorphism_def
    by (auto simp: eq_id_iff [symmetric] image_comp linear_conv_bounded_linear linear_continuous_on)
  then show thesis ..
qed

lemma linear_homeomorphic_image:
  fixes f :: "'a::euclidean_space ==> 'b::euclidean_space"
  assumes "linear f" "inj f"
  shows "S homeomorphic f ` S"
  by (meson homeomorphic_def homeomorphic_sym linear_homeomorphism_image [OF assms])

lemma path_connected_Times:
  assumes "path_connected s" "path_connected t"
    shows "path_connected (s × t)"
proof (simp add: path_connected_def Sigma_def, clarify)
  fix x1 y1 x2 y2
  assume "x1 s" "y1 t" "x2 s" "y2 t"
  obtain g where "path g" and g: "path_image g s" and gs: "pathstart g = x1" and gf: "pathfinish g = x2"
    using x1 s x2 s assms by (force simp: path_connected_def)
  obtain h where "path h" and h: "path_image h t" and hs: "pathstart h = y1" and hf: "pathfinish h = y2"
    using y1 t y2 t assms by (force simp: path_connected_def)
  have "path (λz. (x1, h z))"
    using path h
    unfolding path_def
    by (intro continuous_intros continuous_on_compose2 [where g = "Pair _"]; force)
  moreover have "path (λz. (g z, y2))"
    using path g
    unfolding path_def
    by (intro continuous_intros continuous_on_compose2 [where g = "Pair _"]; force)
  ultimately have 1: "path ((λz. (x1, h z)) +++ (λz. (g z, y2)))"
    by (metis hf gs path_join_imp pathstart_def pathfinish_def)
  have "path_image ((λz. (x1, h z)) +++ (λz. (g z, y2))) path_image (λz. (x1, h z)) path_image (λz. (g z, y2))"
    by (rule Path_Connected.path_image_join_subset)
  also have " (xs. x1t. {(x, x1)})"
    using g h x1 s y2 t by (force simp: path_image_def)
  finally have 2: "path_image ((λz. (x1, h z)) +++ (λz. (g z, y2))) (xs. x1t. {(x, x1)})" .
  show "g. path g path_image g (xs. x1t. {(x, x1)})

            pathstart g = (x1, y1) pathfinish g = (x2, y2)"
    using 1 2 gf hs
    by (metis (no_types, lifting) pathfinish_def pathfinish_join pathstart_def pathstart_join)
qed

lemma is_interval_path_connected_1:
  fixes s :: "real set"
  shows "is_interval s path_connected s"
  using is_interval_connected_1 is_interval_path_connected path_connected_imp_connected by blast


subsection🍋tag unimportant\<open>Path components


lemma Union_path_component [simp]:
   "Union {path_component_set S x |x. x S} = S"
  using path_component_subset path_component_refl by blast

lemma path_component_disjoint:
   "disjnt (path_component_set S a) (path_component_set S b)
    (a path_component_set S b)"
  unfolding disjnt_iff
  using path_component_sym path_component_trans by blast

lemma path_component_eq_eq:
   "path_component S x = path_component S y
        (x S) (y S) x S y S path_component S x y"
    (is "?lhs = ?rhs")
proof 
  assume ?lhs then show ?rhs
    by (metis (no_types) path_component_mem(1) path_component_refl)
next
  assume ?rhs then show ?lhs
  proof
    assume "x S y S" then show ?lhs
      by (metis Collect_empty_eq_bot path_component_eq_empty)
  next
    assume S: "x S y S path_component S x y" show ?lhs
      by (rule ext) (metis S path_component_trans path_component_sym)
  qed
qed

lemma path_component_unique:
  assumes "x C" "C S" "path_connected C"
          "C'. [x C'; C' S; path_connected C'] ==> C' C"
        shows "path_component_set S x = C"
  by (smt (verit, best) Collect_cong assms path_component path_component_of_subset path_connected_component_set)

lemma path_component_intermediate_subset:
  "path_component_set U a T T U
        ==> path_component_set T a = path_component_set U a"
  by (metis (no_types) path_component_mono path_component_path_component subset_antisym)

lemma complement_path_component_Union:
  fixes x :: "'a :: topological_space"
  shows "S - path_component_set S x =
         ({path_component_set S y| y. y S} - {path_component_set S x})"
proof -
  have *: "(x. x S - {a} ==> disjnt a x) ==> S - a = (S - {a})"
    for a::"'a set" and S
    by (auto simp: disjnt_def)
  have "y. y {path_component_set S x |x. x S} - {path_component_set S x}
            ==> disjnt (path_component_set S x) y"
    using path_component_disjoint path_component_eq by fastforce
  then have "{path_component_set S x |x. x S} - path_component_set S x =
             ({path_component_set S y |y. y S} - {path_component_set S x})"
    by (meson *)
  then show ?thesis by simp
qed


subsectionPath components

definition path_component_of
  where "path_component_of X x y g. pathin X g g 0 = x g 1 = y"

abbreviation path_component_of_set
  where "path_component_of_set X x Collect (path_component_of X x)"

definition path_components_of :: "'a topology ==> 'a set set"
  where "path_components_of X path_component_of_set X ` topspace X"

lemma pathin_canon_iff: "pathin (top_of_set T) g path g g {0..1} T"
  by (simp add: path_def pathin_def image_subset_iff_funcset)

lemma path_component_of_canon_iff [simp]:
  "path_component_of (top_of_set T) a b path_component T a b"
  by (simp add: path_component_of_def pathin_canon_iff path_defs image_subset_iff_funcset)

lemma path_component_in_topspace:
   "path_component_of X x y ==> x topspace X y topspace X"
  by (auto simp: path_component_of_def pathin_def continuous_map_def)

lemma path_component_of_refl:
   "path_component_of X x x x topspace X"
  by (metis path_component_in_topspace path_component_of_def pathin_const)

lemma path_component_of_sym:
  assumes "path_component_of X x y"
  shows "path_component_of X y x"
  using assms
  apply (clarsimp simp: path_component_of_def pathin_def)
  apply (rule_tac x="g (λt. 1 - t)" in exI)
  apply (auto intro!: continuous_map_compose simp: continuous_map_in_subtopology continuous_on_op_minus)
  done

lemma path_component_of_sym_iff:
   "path_component_of X x y path_component_of X y x"
  by (metis path_component_of_sym)

lemma continuous_map_cases_le:
  assumes contp: "continuous_map X euclideanreal p"
    and contq: "continuous_map X euclideanreal q"
    and contf: "continuous_map (subtopology X {x. x topspace X p x q x}) Y f"
    and contg: "continuous_map (subtopology X {x. x topspace X q x p x}) Y g"
    and fg: "x. [x topspace X; p x = q x] ==> f x = g x"
  shows "continuous_map X Y (λx. if p x q x then f x else g x)"
proof -
  have "continuous_map X Y (λx. if q x - p x {0..} then f x else g x)"
  proof (rule continuous_map_cases_function)
    show "continuous_map X euclideanreal (λx. q x - p x)"
      by (intro contp contq continuous_intros)
    show "continuous_map (subtopology X {x topspace X. q x - p x euclideanreal closure_of {0..}}) Y f"
      by (simp add: contf)
    show "continuous_map (subtopology X {x topspace X. q x - p x euclideanreal closure_of (topspace euclideanreal - {0..})}) Y g"
      by (simp add: contg flip: Compl_eq_Diff_UNIV)
  qed (auto simp: fg)
  then show ?thesis
    by simp
qed

lemma continuous_map_cases_lt:
  assumes contp: "continuous_map X euclideanreal p"
    and contq: "continuous_map X euclideanreal q"
    and contf: "continuous_map (subtopology X {x. x topspace X p x q x}) Y f"
    and contg: "continuous_map (subtopology X {x. x topspace X q x p x}) Y g"
    and fg: "x. [x topspace X; p x = q x] ==> f x = g x"
  shows "continuous_map X Y (λx. if p x < q x then f x else g x)"
proof -
  have "continuous_map X Y (λx. if q x - p x {0<..} then f x else g x)"
  proof (rule continuous_map_cases_function)
    show "continuous_map X euclideanreal (λx. q x - p x)"
      by (intro contp contq continuous_intros)
    show "continuous_map (subtopology X {x topspace X. q x - p x euclideanreal closure_of {0<..}}) Y f"
      by (simp add: contf)
    show "continuous_map (subtopology X {x topspace X. q x - p x euclideanreal closure_of (topspace euclideanreal - {0<..})}) Y g"
      by (simp add: contg flip: Compl_eq_Diff_UNIV)
  qed (auto simp: fg)
  then show ?thesis
    by simp
qed

lemma path_component_of_trans:
  assumes "path_component_of X x y" and "path_component_of X y z"
  shows "path_component_of X x z"
  unfolding path_component_of_def pathin_def
proof -
  let ?T01 = "top_of_set {0..1::real}"
  obtain g1 g2 where g1: "continuous_map ?T01 X g1" "x = g1 0" "y = g1 1"
    and g2: "continuous_map ?T01 X g2" "g2 0 = g1 1" "z = g2 1"
    using assms unfolding path_component_of_def pathin_def by blast
  let ?g = "λx. if x 1/2 then (g1 (λt. 2 * t)) x else (g2 (λt. 2 * t -1)) x"
  show "g. continuous_map ?T01 X g g 0 = x g 1 = z"
  proof (intro exI conjI)
    show "continuous_map (subtopology euclideanreal {0..1}) X ?g"
    proof (intro continuous_map_cases_le continuous_map_compose, force, force)
      show "continuous_map (subtopology ?T01 {x topspace ?T01. x 1/2}) ?T01 ((*) 2)"
        by (auto simp: continuous_map_in_subtopology continuous_map_from_subtopology)
      have "continuous_map
             (subtopology (top_of_set {0..1}) {x. 0 x x 1 1 x * 2})
             euclideanreal (λt. 2 * t - 1)"
        by (intro continuous_intros) (force intro: continuous_map_from_subtopology)
      then show "continuous_map (subtopology ?T01 {x topspace ?T01. 1/2 x}) ?T01 (λt. 2 * t - 1)"
        by (force simp: continuous_map_in_subtopology)
      show "(g1 (*) 2) x = (g2 (λt. 2 * t - 1)) x" if "x topspace ?T01" "x = 1/2" for x
        using that by (simp add: g2(2) mult.commute continuous_map_from_subtopology)
    qed (auto simp: g1 g2)
  qed (auto simp: g1 g2)
qed

lemma path_component_of_mono:
   "[path_component_of (subtopology X S) x y; S T] ==> path_component_of (subtopology X T) x y"
  unfolding path_component_of_def
  by (metis subsetD pathin_subtopology)

lemma path_component_of:
  "path_component_of X x y (T. path_connectedin X T x T y T)"
    (is "?lhs = ?rhs")
proof 
  assume ?lhs then show ?rhs
    by (metis atLeastAtMost_iff image_eqI order_refl path_component_of_def path_connectedin_path_image zero_le_one)
next
  assume ?rhs then show ?lhs
    by (metis path_component_of_def path_connectedin)
qed

lemma path_component_of_set:
   "path_component_of X x y (g. pathin X g g 0 = x g 1 = y)"
  by (auto simp: path_component_of_def)

lemma path_component_of_subset_topspace:
   "Collect(path_component_of X x) topspace X"
  using path_component_in_topspace by fastforce

lemma path_component_of_eq_empty:
   "Collect(path_component_of X x) = {} (x topspace X)"
  using path_component_in_topspace path_component_of_refl by fastforce

lemma path_connected_space_iff_path_component:
   "path_connected_space X (x topspace X. y topspace X. path_component_of X x y)"
  by (simp add: path_component_of path_connected_space_subconnected)

lemma path_connected_space_imp_path_component_of:
   "[path_connected_space X; a topspace X; b topspace X]
        ==> path_component_of X a b"
  by (simp add: path_connected_space_iff_path_component)

lemma path_connected_space_path_component_set:
   "path_connected_space X (x topspace X. Collect(path_component_of X x) = topspace X)"
  using path_component_of_subset_topspace path_connected_space_iff_path_component by fastforce

lemma path_component_of_maximal:
   "[path_connectedin X s; x s] ==> s Collect(path_component_of X x)"
  using path_component_of by fastforce

lemma path_component_of_equiv:
   "path_component_of X x y x topspace X y topspace X path_component_of X x = path_component_of X y"
    (is "?lhs = ?rhs")
proof
  assume ?lhs
  then show ?rhs
    unfolding fun_eq_iff path_component_in_topspace
    by (metis path_component_in_topspace path_component_of_sym path_component_of_trans)
qed (simp add: path_component_of_refl)

lemma path_component_of_disjoint:
     "disjnt (Collect (path_component_of X x)) (Collect (path_component_of X y))
      ~(path_component_of X x y)"
  by (force simp: disjnt_def path_component_of_eq_empty path_component_of_equiv)

lemma path_component_of_eq:
   "path_component_of X x = path_component_of X y
        (x topspace X) (y topspace X)
        x topspace X y topspace X path_component_of X x y"
  by (metis Collect_empty_eq_bot path_component_of_eq_empty path_component_of_equiv)

lemma path_component_of_aux:
  "path_component_of X x y
        ==> path_component_of (subtopology X (Collect (path_component_of X x))) x y"
    by (meson path_component_of path_component_of_maximal path_connectedin_subtopology)

lemma path_connectedin_path_component_of:
  "path_connectedin X (Collect (path_component_of X x))"
proof -
  have "topspace (subtopology X (path_component_of_set X x)) = path_component_of_set X x"
    by (meson path_component_of_subset_topspace topspace_subtopology_subset)
  then have "path_connected_space (subtopology X (path_component_of_set X x))"
    by (metis mem_Collect_eq path_component_of_aux path_component_of_equiv path_connected_space_iff_path_component)
  then show ?thesis
    by (simp add: path_component_of_subset_topspace path_connectedin_def)
qed

lemma path_connectedin_euclidean [simp]:
   "path_connectedin euclidean S path_connected S"
  by (auto simp: path_connectedin_def path_connected_space_iff_path_component path_connected_component)

lemma path_connected_space_euclidean_subtopology [simp]:
   "path_connected_space(subtopology euclidean S) path_connected S"
  using path_connectedin_topspace by force

lemma Union_path_components_of:
     "(path_components_of X) = topspace X"
  by (auto simp: path_components_of_def path_component_of_equiv)

lemma path_components_of_maximal:
   "[C path_components_of X; path_connectedin X S; ~disjnt C S] ==> S C"
  by (smt (verit, ccfv_SIG) disjnt_iff imageE mem_Collect_eq path_component_of_equiv 
      path_component_of_maximal path_components_of_def)

lemma pairwise_disjoint_path_components_of:
     "pairwise disjnt (path_components_of X)"
  by (auto simp: path_components_of_def pairwise_def path_component_of_disjoint path_component_of_equiv)

lemma complement_path_components_of_Union:
   "C path_components_of X ==> topspace X - C = (path_components_of X - {C})"
  by (metis Union_path_components_of bot.extremum ccpo_Sup_singleton diff_Union_pairwise_disjoint 
        insert_subsetI pairwise_disjoint_path_components_of)

lemma nonempty_path_components_of:
  assumes "C path_components_of X" shows "C {}"
  by (metis assms imageE path_component_of_eq_empty path_components_of_def)

lemma path_components_of_subset: "C path_components_of X ==> C topspace X"
  by (auto simp: path_components_of_def path_component_of_equiv)

lemma path_connectedin_path_components_of:
   "C path_components_of X ==> path_connectedin X C"
  by (auto simp: path_components_of_def path_connectedin_path_component_of)

lemma path_component_in_path_components_of:
  "Collect (path_component_of X a) path_components_of X a topspace X"
  by (metis imageI nonempty_path_components_of path_component_of_eq_empty path_components_of_def)

lemma path_connectedin_Union:
  assumes A"S. S A ==> path_connectedin X S" and "A {}"
  shows "path_connectedin X (A)"
proof -
  obtain a where "S. S A ==> a S"
    using assms by blast
  then have "x. x topspace (subtopology X (A)) ==> path_component_of (subtopology X (A)) a x"
    unfolding topspace_subtopology path_component_of
    by (metis (full_types) IntD2 Union_iff Union_upper A path_connectedin_subtopology)
  then show ?thesis
    using A unfolding path_connectedin_def
    by (metis Sup_le_iff path_component_of_equiv path_connected_space_iff_path_component)
qed

lemma path_connectedin_Un:
   "[path_connectedin X S; path_connectedin X T; S T {}]
    ==> path_connectedin X (S T)"
  by (blast intro: path_connectedin_Union [of "{S,T}", simplified])

lemma path_connected_space_iff_components_eq:
  "path_connected_space X
    (C path_components_of X. C' path_components_of X. C = C')"
  unfolding path_components_of_def
proof (intro iffI ballI)
  assume "C path_component_of_set X ` topspace X.
             C' path_component_of_set X ` topspace X. C = C'"
  then show "path_connected_space X"
    using path_component_of_refl path_connected_space_iff_path_component by fastforce
qed (auto simp: path_connected_space_path_component_set)

lemma path_components_of_eq_empty:
   "path_components_of X = {} X = trivial_topology"
  by (metis image_is_empty path_components_of_def subtopology_eq_discrete_topology_empty)

lemma path_components_of_empty_space:
   "path_components_of trivial_topology = {}"
  by (simp add: path_components_of_eq_empty)

lemma path_components_of_subset_singleton:
  "path_components_of X {S}
        path_connected_space X (topspace X = {} topspace X = S)"
proof (cases "topspace X = {}")
  case True
  then show ?thesis
    by (auto simp: path_components_of_empty_space path_connected_space_topspace_empty)
next
  case False
  have "(path_components_of X = {S}) (path_connected_space X topspace X = S)"
    by (metis False Set.set_insert ex_in_conv insert_iff path_component_in_path_components_of 
        path_connected_space_iff_components_eq path_connected_space_path_component_set)
  with False show ?thesis
    by (simp add: path_components_of_eq_empty subset_singleton_iff)
qed

lemma path_connected_space_iff_components_subset_singleton:
   "path_connected_space X (a. path_components_of X {a})"
  by (simp add: path_components_of_subset_singleton)

lemma path_components_of_eq_singleton:
   "path_components_of X = {S} path_connected_space X topspace X {} S = topspace X"
  by (metis cSup_singleton insert_not_empty path_components_of_subset_singleton subset_singleton_iff)

lemma path_components_of_path_connected_space:
   "path_connected_space X ==> path_components_of X = (if topspace X = {} then {} else {topspace X})"
  by (simp add: path_components_of_eq_empty path_components_of_eq_singleton)

lemma path_component_subset_connected_component_of:
   "path_component_of_set X x connected_component_of_set X x"
proof (cases "x topspace X")
  case True
  then show ?thesis
    by (simp add: connected_component_of_maximal path_component_of_refl path_connectedin_imp_connectedin path_connectedin_path_component_of)
next
  case False
  then show ?thesis
    using path_component_of_eq_empty by fastforce
qed

lemma exists_path_component_of_superset:
  assumes S: "path_connectedin X S" and ne: "topspace X {}"
  obtains C where "C path_components_of X" "S C"
    by (metis S ne ex_in_conv path_component_in_path_components_of path_component_of_maximal path_component_of_subset_topspace subset_eq that)

lemma path_component_of_eq_overlap:
   "path_component_of X x = path_component_of X y
      (x topspace X) (y topspace X)
      Collect (path_component_of X x) Collect (path_component_of X y) {}"
  by (metis disjnt_def empty_iff inf_bot_right mem_Collect_eq path_component_of_disjoint path_component_of_eq path_component_of_eq_empty)

lemma path_component_of_nonoverlap:
   "Collect (path_component_of X x) Collect (path_component_of X y) = {}
    (x topspace X) (y topspace X)
    path_component_of X x path_component_of X y"
  by (metis inf.idem path_component_of_eq_empty path_component_of_eq_overlap)

lemma path_component_of_overlap:
   "Collect (path_component_of X x) Collect (path_component_of X y) {}
    x topspace X y topspace X path_component_of X x = path_component_of X y"
  by (meson path_component_of_nonoverlap)

lemma path_components_of_disjoint:
     "[C path_components_of X; C' path_components_of X] ==> disjnt C C' C C'"
  by (auto simp: path_components_of_def path_component_of_disjoint path_component_of_equiv)

lemma path_components_of_overlap:
    "[C path_components_of X; C' path_components_of X] ==> C C' {} C = C'"
  by (auto simp: path_components_of_def path_component_of_equiv)

lemma path_component_of_unique:
   "[x C; path_connectedin X C; C'. [x C'; path_connectedin X C'] ==> C' C]
        ==> Collect (path_component_of X x) = C"
  by (meson subsetD eq_iff path_component_of_maximal path_connectedin_path_component_of)

lemma path_component_of_discrete_topology [simp]:
  "Collect (path_component_of (discrete_topology U) x) = (if x U then {x} else {})"
proof -
  have "C'. [x C'; path_connectedin (discrete_topology U) C'] ==> C' {x}"
    by (metis path_connectedin_discrete_topology subsetD singletonD)
  then have "x U ==> Collect (path_component_of (discrete_topology U) x) = {x}"
    by (simp add: path_component_of_unique)
  then show ?thesis
    using path_component_in_topspace by fastforce
qed

lemma path_component_of_discrete_topology_iff [simp]:
  "path_component_of (discrete_topology U) x y x U y=x"
  by (metis empty_iff insertI1 mem_Collect_eq path_component_of_discrete_topology singletonD)

lemma path_components_of_discrete_topology [simp]:
   "path_components_of (discrete_topology U) = (λx. {x}) ` U"
  by (auto simp: path_components_of_def image_def fun_eq_iff)

lemma homeomorphic_map_path_component_of:
  assumes f: "homeomorphic_map X Y f" and x: "x topspace X"
  shows "Collect (path_component_of Y (f x)) = f ` Collect(path_component_of X x)"
proof -
  obtain g where g: "homeomorphic_maps X Y f g"
    using f homeomorphic_map_maps by blast
  show ?thesis
  proof
    have "Collect (path_component_of Y (f x)) topspace Y"
      by (simp add: path_component_of_subset_topspace)
    moreover have "g ` Collect(path_component_of Y (f x)) Collect (path_component_of X (g (f x)))"
      using f g x unfolding homeomorphic_maps_def
      by (metis image_Collect_subsetI image_eqI mem_Collect_eq path_component_of_equiv path_component_of_maximal 
          path_connectedin_continuous_map_image path_connectedin_path_component_of)
    ultimately show "Collect (path_component_of Y (f x)) f ` Collect (path_component_of X x)"
      using g x unfolding homeomorphic_maps_def continuous_map_def image_iff subset_iff
      by metis
    show "f ` Collect (path_component_of X x) Collect (path_component_of Y (f x))"
    proof (rule path_component_of_maximal)
      show "path_connectedin Y (f ` Collect (path_component_of X x))"
        by (meson f homeomorphic_map_path_connectedness_eq path_connectedin_path_component_of)
    qed (simp add: path_component_of_refl x)
  qed
qed

lemma homeomorphic_map_path_components_of:
  assumes "homeomorphic_map X Y f"
  shows "path_components_of Y = (image f) ` (path_components_of X)"
  unfolding path_components_of_def homeomorphic_imp_surjective_map [OF assms, symmetric]
  using assms homeomorphic_map_path_component_of by fastforce


subsectionPaths and path-connectedness

lemma path_connected_space_quotient_map_image:
   "[quotient_map X Y q; path_connected_space X] ==> path_connected_space Y"
  by (metis path_connectedin_continuous_map_image path_connectedin_topspace quotient_imp_continuous_map quotient_imp_surjective_map)

lemma path_connected_space_retraction_map_image:
   "[retraction_map X Y r; path_connected_space X] ==> path_connected_space Y"
  using path_connected_space_quotient_map_image retraction_imp_quotient_map by blast

lemma path_connected_space_prod_topology:
  "path_connected_space(prod_topology X Y)
        topspace(prod_topology X Y) = {} path_connected_space X path_connected_space Y"
proof (cases "topspace(prod_topology X Y) = {}")
  case True
  then show ?thesis
    using path_connected_space_topspace_empty by force
next
  case False
  have "path_connected_space (prod_topology X Y)" 
    if X: "path_connected_space X" and Y: "path_connected_space Y"
  proof (clarsimp simp: path_connected_space_def)
    fix x y x' y'
    assume "x topspace X" and "y topspace Y" and "x' topspace X" and "y' topspace Y"
    obtain f where "pathin X f" "f 0 = x" "f 1 = x'"
      by (meson X x topspace X x' topspace X path_connected_space_def)
    obtain g where "pathin Y g" "g 0 = y" "g 1 = y'"
      by (meson Y y topspace Y y' topspace Y path_connected_space_def)
    show "h. pathin (prod_topology X Y) h h 0 = (x,y) h 1 = (x',y')"
    proof (intro exI conjI)
      show "pathin (prod_topology X Y) (λt. (f t, g t))"
        using pathin X f pathin Y g by (simp add: continuous_map_paired pathin_def)
      show "(λt. (f t, g t)) 0 = (x, y)"
        using f 0 = x g 0 = y by blast
      show "(λt. (f t, g t)) 1 = (x', y')"
        using f 1 = x' g 1 = y' by blast
    qed
  qed
  then show ?thesis
    by (metis False path_connected_space_quotient_map_image prod_topology_trivial1 prod_topology_trivial2 
        quotient_map_fst quotient_map_snd topspace_discrete_topology)
qed

lemma path_connectedin_Times:
   "path_connectedin (prod_topology X Y) (S × T)
        S = {} T = {} path_connectedin X S path_connectedin Y T"
  by (auto simp add: path_connectedin_def subtopology_Times path_connected_space_prod_topology)


subsectionPath components

lemma path_component_of_subtopology_eq:
  "path_component_of (subtopology X U) x = path_component_of X x path_component_of_set X x U"  
  (is "?lhs = ?rhs")
proof
  show "?lhs ==> ?rhs"
    by (metis path_connectedin_path_component_of path_connectedin_subtopology)
next
  show "?rhs ==> ?lhs"
    unfolding fun_eq_iff
    by (metis path_connectedin_subtopology path_component_of path_component_of_aux path_component_of_mono)
qed

lemma path_components_of_subtopology:
  assumes "C path_components_of X" "C U"
  shows "C path_components_of (subtopology X U)"
  using assms path_component_of_refl path_component_of_subtopology_eq topspace_subtopology
  by (smt (verit) imageE path_component_in_path_components_of path_components_of_def)

lemma path_imp_connected_component_of:
   "path_component_of X x y ==> connected_component_of X x y"
  by (metis in_mono mem_Collect_eq path_component_subset_connected_component_of)

lemma finite_path_components_of_finite:
   "finite(topspace X) ==> finite(path_components_of X)"
  by (simp add: Union_path_components_of finite_UnionD)

lemma path_component_of_continuous_image:
  "[continuous_map X X' f; path_component_of X x y] ==> path_component_of X' (f x) (f y)"
  by (meson image_eqI path_component_of path_connectedin_continuous_map_image)

lemma path_component_of_pair [simp]:
   "path_component_of_set (prod_topology X Y) (x,y) =
    path_component_of_set X x × path_component_of_set Y y"   (is "?lhs = ?rhs")
proof (cases "?lhs = {}")
  case True
  then show ?thesis
    by (metis Sigma_empty1 Sigma_empty2 mem_Sigma_iff path_component_of_eq_empty topspace_prod_topology) 
next
  case False
  then have "path_component_of X x x" "path_component_of Y y y"
    using path_component_of_eq_empty path_component_of_refl by fastforce+
  moreover
  have "path_connectedin (prod_topology X Y) (path_component_of_set X x × path_component_of_set Y y)"
    by (metis path_connectedin_Times path_connectedin_path_component_of)
  moreover have "path_component_of X x a" "path_component_of Y y b"
    if "(x, y) C'" "(a,b) C'" and "path_connectedin (prod_topology X Y) C'" for C' a b
    by (smt (verit, best) that continuous_map_fst continuous_map_snd fst_conv snd_conv path_component_of path_component_of_continuous_image)+
  ultimately show ?thesis
    by (intro path_component_of_unique) auto
qed

lemma path_components_of_prod_topology:
   "path_components_of (prod_topology X Y) =
    (λ(C,D). C × D) ` (path_components_of X × path_components_of Y)"
  by (force simp add: image_iff path_components_of_def)

lemma path_components_of_prod_topology':
   "path_components_of (prod_topology X Y) =
    {C × D |C D. C path_components_of X D path_components_of Y}"
  by (auto simp: path_components_of_prod_topology)

lemma path_component_of_product_topology:
   "path_component_of_set (product_topology X I) f =
    (if f extensional I then PiE I (λi. path_component_of_set (X i) (f i)) else {})"
    (is "?lhs = ?rhs")
proof (cases "path_component_of_set (product_topology X I) f = {}")
  case True
  then show ?thesis
    by (smt (verit) PiE_eq_empty_iff PiE_iff path_component_of_eq_empty topspace_product_topology)
next
  case False
  then have [simp]: "f extensional I"
    by (auto simp: path_component_of_eq_empty PiE_iff path_component_of_equiv)
  show ?thesis
  proof (intro path_component_of_unique)
    show "f ?rhs"
      using False path_component_of_eq_empty path_component_of_refl by force
    show "path_connectedin (product_topology X I) (if f extensional I then Π🪙E iI. path_component_of_set (X i) (f i) else {})"
      by (simp add: path_connectedin_PiE path_connectedin_path_component_of)
    fix C'
    assume "f C'" and C': "path_connectedin (product_topology X I) C'" 
    show "C' ?rhs"
    proof -
      have "C' extensional I"
        using PiE_def C' path_connectedin_subset_topspace by fastforce
      with f C' C' show ?thesis
        apply (clarsimp simp: PiE_iff subset_iff)
        by (smt (verit, ccfv_threshold) continuous_map_product_projection path_component_of path_component_of_continuous_image)
    qed   
  qed
qed

lemma path_components_of_product_topology:
  "path_components_of (product_topology X I) =
    {PiE I B |B. i I. B i path_components_of(X i)}"  (is "?lhs=?rhs")
proof
  show "?lhs ?rhs"
    unfolding path_components_of_def image_subset_iff
    by (smt (verit) image_iff mem_Collect_eq path_component_of_product_topology topspace_product_topology_alt)
next
  show "?rhs ?lhs"
  proof
    fix F
    assume "F ?rhs"
    then obtain B where B: "F = Pi🪙E I B"
      and "iI. xtopspace (X i). B i = path_component_of_set (X i) x"
      by (force simp add: path_components_of_def image_iff)
    then obtain f where ftop: "i. i I ==> f i topspace (X i)"
      and BF: "i. i I ==> B i = path_component_of_set (X i) (f i)"
      by metis
    then have "F = path_component_of_set (product_topology X I) (restrict f I)"
      by (metis (mono_tags, lifting) B PiE_cong path_component_of_product_topology restrict_apply' restrict_extensional)
    then show "F ?lhs"
      by (simp add: ftop path_component_in_path_components_of)
  qed
qed

subsection Sphere is path-connected

lemma path_connected_punctured_universe:
  assumes "2 DIM('a::euclidean_space)"
  shows "path_connected (- {a::'a})"
proof -
  let ?A = "{x::'a. iBasis. x i < a i}"
  let ?B = "{x::'a. iBasis. a i < x i}"

  have A: "path_connected ?A"
    unfolding Collect_bex_eq
  proof (rule path_connected_UNION)
    fix i :: 'a
    assume "i Basis"
    then show "(iBasis. (a i - 1)*🪙R i) {x::'a. x i < a i}"
      by simp
    show "path_connected {x. x i < a i}"
      using convex_imp_path_connected [OF convex_halfspace_lt, of i "a i"]
      by (simp add: inner_commute)
  qed
  have B: "path_connected ?B"
    unfolding Collect_bex_eq
  proof (rule path_connected_UNION)
    fix i :: 'a
    assume "i Basis"
    then show "(iBasis. (a i + 1) *🪙R i) {x::'a. a i < x i}"
      by simp
    show "path_connected {x. a i < x i}"
      using convex_imp_path_connected [OF convex_halfspace_gt, of "a i" i]
      by (simp add: inner_commute)
  qed
  obtain S :: "'a set" where "S Basis" and "card S = Suc (Suc 0)"
    using obtain_subset_with_card_n[OF assms] by (force simp add: eval_nat_numeral)
  then obtain b0 b1 :: 'a where "b0 Basis" and "b1 Basis" and "b0 b1"
    unfolding card_Suc_eq by auto
  then have "a + b0 - b1 ?A ?B"
    by (auto simp: inner_simps inner_Basis)
  then have "?A ?B {}"
    by fast
  with A B have "path_connected (?A ?B)"
    by (rule path_connected_Un)
  also have "?A ?B = {x. iBasis. x i a i}"
    unfolding neq_iff bex_disj_distrib Collect_disj_eq ..
  also have " = {x. x a}"
    unfolding euclidean_eq_iff [where 'a='a]
    by (simp add: Bex_def)
  also have " = - {a}"
    by auto
  finally show ?thesis .
qed

corollary connected_punctured_universe:
  "2 DIM('N::euclidean_space) ==> connected(- {a::'N})"
  by (simp add: path_connected_punctured_universe path_connected_imp_connected)

proposition path_connected_sphere:
  fixes a :: "'a :: euclidean_space"
  assumes "2 DIM('a)"
  shows "path_connected(sphere a r)"
proof (cases r "0::real" rule: linorder_cases)
  case greater
  then have eq: "(sphere (0::'a) r) = (λx. (r / norm x) *🪙R x) ` (- {0::'a})"
    by (force simp: image_iff split: if_split_asm)
  have "continuous_on (- {0::'a}) (λx. (r / norm x) *🪙R x)"
    by (intro continuous_intros) auto
  then have "path_connected ((λx. (r / norm x) *🪙R x) ` (- {0::'a}))"
    by (intro path_connected_continuous_image path_connected_punctured_universe assms)
  with eq have "path_connected((+) a ` (sphere (0::'a) r))"
    by (simp add: path_connected_translation)
  then show ?thesis
    by (metis add.right_neutral sphere_translation)
qed auto

lemma connected_sphere:
    fixes a :: "'a :: euclidean_space"
    assumes "2 DIM('a)"
      shows "connected(sphere a r)"
  using path_connected_sphere [OF assms]
  by (simp add: path_connected_imp_connected)


corollary path_connected_complement_bounded_convex:
    fixes S :: "'a :: euclidean_space set"
    assumes "bounded S" "convex S" and 2: "2 DIM('a)"
    shows "path_connected (- S)"
proof (cases "S = {}")
  case True then show ?thesis
    using convex_imp_path_connected by auto
next
  case False
  then obtain a where "a S" by auto
  have 🍋 [rule_format]: "yS. u. 0 u u 1 (1 - u) *🪙R a + u *🪙R y S"
    using convex S a S by (simp add: convex_alt)
  { fix x y assume "x S" "y S"
    then have "x a" "y a" using a S by auto
    then have bxy: "bounded(insert x (insert y S))"
      by (simp add: bounded S)
    then obtain B::real where B: "0 < B" and Bx: "norm (a - x) < B" and By"norm (a - y) < B"
                          and "S ball a B"
      using bounded_subset_ballD [OF bxy, of a] by (auto simp: dist_norm)
    define C where "C = B / norm(x - a)"
    let ?Cxa = "a + C *🪙R (x - a)"
    { fix u
      assume u: "(1 - u) *🪙R x + u *🪙R ?Cxa S" and "0 u" "u 1"
      have CC: "1 1 + (C - 1) * u"
        using x a 0 u Bx
        by (auto simp add: C_def norm_minus_commute)
      have *: "v. (1 - u) *🪙R x + u *🪙R (a + v *🪙R (x - a)) = a + (1 + (v - 1) * u) *🪙R (x - a)"
        by (simp add: algebra_simps)
      have "a + ((1 / (1 + C * u - u)) *🪙R x + ((u / (1 + C * u - u)) *🪙R a + (C * u / (1 + C * u - u)) *🪙R x)) =
            (1 + (u / (1 + C * u - u))) *🪙R a + ((1 / (1 + C * u - u)) + (C * u / (1 + C * u - u))) *🪙R x"
        by (simp add: algebra_simps)
      also have " = (1 + (u / (1 + C * u - u))) *🪙R a + (1 + (u / (1 + C * u - u))) *??R x"
        using CC by (simp add: field_simps)
      also have " = x + (1 + (u / (1 + C * u - u))) *🪙R a + (u / (1 + C * u - u)) *🪙R x"
        by (simp add: algebra_simps)
      also have " = x + ((1 / (1 + C * u - u)) *🪙R a +
              ((u / (1 + C * u - u)) *🪙R x + (C * u / (1 + C * u - u)) *🪙R a))"
        using CC by (simp add: field_simps) (simp add: add_divide_distrib scaleR_add_left)
      finally have xeq: "(1 - 1 / (1 + (C - 1) * u)) *🪙R a + (1 / (1 + (C - 1) * u)) *🪙R (a + (1 + (C - 1) * u) *🪙R (x - a)) = x"
        by (simp add: algebra_simps)
      have False
        using 🍋 [of "a + (1 + (C - 1) * u) *🪙R (x - a)" "1 / (1 + (C - 1) * u)"]
        using u x a x S 0 u CC
        by (auto simp: xeq *)
    }
    then have pcx: "path_component (- S) x ?Cxa"
      by (force simp: closed_segment_def intro!: path_component_linepath)
    define D where "D = B / norm(y - a)"  🍋 massive duplication with the proof above
    let ?Dya = "a + D *🪙R (y - a)"
    { fix u
      assume u: "(1 - u) *🪙R y + u *🪙R ?Dya S" and "0 u" "u 1"
      have DD: "1 1 + (D - 1) * u"
        using y a 0 u By
        by (auto simp add: D_def norm_minus_commute)
      have *: "v. (1 - u) *🪙R y + u *🪙R (a + v *🪙R (y - a)) = a + (1 + (v - 1) * u) *🪙R (y - a)"
        by (simp add: algebra_simps)
      have "a + ((1 / (1 + D * u - u)) *🪙R y + ((u / (1 + D * u - u)) *🪙R a + (D * u / (1 + D * u - u)) *🪙R y)) =
            (1 + (u / (1 + D * u - u))) *🪙R a + ((1 / (1 + D * u - u)) + (D * u / (1 + D * u - u))) *🪙R y"
        by (simp add: algebra_simps)
      also have " = (1 + (u / (1 + D * u - u))) *🪙R a + (1 + (u / (1 + D * u - u))) *??R y"
        using DD by (simp add: field_simps)
      also have " = y + (1 + (u / (1 + D * u - u))) *🪙R a + (u / (1 + D * u - u)) *🪙R y"
        by (simp add: algebra_simps)
      also have " = y + ((1 / (1 + D * u - u)) *🪙R a +
              ((u / (1 + D * u - u)) *🪙R y + (D * u / (1 + D * u - u)) *🪙R a))"
        using DD by (simp add: field_simps) (simp add: add_divide_distrib scaleR_add_left)
      finally have xeq: "(1 - 1 / (1 + (D - 1) * u)) *🪙R a + (1 / (1 + (D - 1) * u)) *🪙R (a + (1 + (D - 1) * u) *🪙R (y - a)) = y"
        by (simp add: algebra_simps)
      have False
        using 🍋 [of "a + (1 + (D - 1) * u) *🪙R (y - a)" "1 / (1 + (D - 1) * u)"]
        using u y a y S 0 u DD
        by (auto simp: xeq *)
    }
    then have pdy: "path_component (- S) y ?Dya"
      by (force simp: closed_segment_def intro!: path_component_linepath)
    have pyx: "path_component (- S) ?Dya ?Cxa"
    proof (rule path_component_of_subset)
      show "sphere a B - S"
        using S ball a B by (force simp: ball_def dist_norm norm_minus_commute)
      have aB: "?Dya sphere a B" "?Cxa sphere a B"
        using x a using y aby (auto simp: dist_norm C_def D_def)
      then show "path_component (sphere a B) ?Dya ?Cxa"
        using path_connected_sphere [OF 2] path_connected_component by blast
    qed
    have "path_component (- S) x y"
      by (metis path_component_trans path_component_sym pcx pdy pyx)
  }
  then show ?thesis
    by (auto simp: path_connected_component)
qed

lemma connected_complement_bounded_convex:
    fixes S :: "'a :: euclidean_space set"
    assumes "bounded S" "convex S" "2 DIM('a)"
      shows  "connected (- S)"
  using path_connected_complement_bounded_convex [OF assms] path_connected_imp_connected by blast

lemma connected_diff_ball:
    fixes S :: "'a :: euclidean_space set"
    assumes "connected S" "cball a r S" "2 DIM('a)"
      shows "connected (S - ball a r)"
proof (rule connected_diff_open_from_closed [OF ball_subset_cball])
  show "connected (cball a r - ball a r)"
    using assms connected_sphere by (auto simp: cball_diff_eq_sphere)
qed (auto simp: assms dist_norm)

proposition connected_open_delete:
  assumes "open S" "connected S" and 2: "2 DIM('N::euclidean_space)"
    shows "connected(S - {a::'N})"
proof (cases "a S")
  case True
  with open S obtain ε where "ε > 0" and ε: "cball a ε S"
    using open_contains_cball_eq by blast
  define b where "b a + ε *🪙R (SOME i. i Basis)"
  have "dist a b = ε"
    by (simp add: b_def dist_norm SOME_Basis 0 🚫ε less_imp_le)
  with ε have "b {S - ball a r |r. 0 < r r < ε}"
    by auto
  then have nonemp: "({S - ball a r |r. 0 < r r < ε}) = {} ==> False"
    by auto
  have con: "r. r < ε ==> connected (S - ball a r)"
    using ε by (force intro: connected_diff_ball [OF connected S _ 2])
  have "x {S - ball a r |r. 0 < r r < ε}" if "x S - {a}" for x
     using that 0 🚫ε
     by (intro UnionI [of "S - ball a (min ε (dist a x) / 2)"]) auto
  then have "S - {a} = {S - ball a r | r. 0 < r r < ε}"
    by auto
  then show ?thesis
    by (auto intro: connected_Union con dest!: nonemp)
next
  case False then show ?thesis
    by (simp add: connected S)
qed

corollary path_connected_open_delete:
  assumes "open S" "connected S" and 2: "2 DIM('N::euclidean_space)"
  shows "path_connected(S - {a::'N})"
  by (simp add: assms connected_open_delete connected_open_path_connected open_delete)

corollary path_connected_punctured_ball:
  "2 DIM('N::euclidean_space) ==> path_connected(ball a r - {a::'N})"
  by (simp add: path_connected_open_delete)

corollary connected_punctured_ball:
  "2 DIM('N::euclidean_space) ==> connected(ball a r - {a::'N})"
  by (simp add: connected_open_delete)

corollary connected_open_delete_finite:
  fixes S T::"'a::euclidean_space set"
  assumes S: "open S" "connected S" and 2: "2 DIM('a)" and "finite T"
  shows "connected(S - T)"
  using finite T S
proof (induct T)
  case empty
  show ?case using connected S by simp
next
  case (insert x T)
  then have "connected (S-T)" 
    by auto
  moreover have "open (S - T)" 
    using finite_imp_closed[OF finite Topen S by auto
  ultimately have "connected (S - T - {x})" 
    using connected_open_delete[OF _ _ 2] by auto
  thus ?case by (metis Diff_insert)
qed

lemma sphere_1D_doubleton_zero:
  assumes 1: "DIM('a) = 1" and "r > 0"
  obtains x y::"'a::euclidean_space"
    where "sphere 0 r = {x,y} dist x y = 2*r"
proof -
  obtain b::'a where b: "Basis = {b}"
    using 1 card_1_singletonE by blast
  show ?thesis
  proof (intro that conjI)
    have "x = norm x *🪙R b x = - norm x *🪙R b" if "r = norm x" for x
    proof -
      have xb: "(x b) *🪙R b = x"
        using euclidean_representation [of x, unfolded b] by force
      then have "norm ((x b) *🪙R b) = norm x"
        by simp
      with b have "x b = norm x"
        using norm_Basis by (simp add: b)
      with xb show ?thesis
        by (metis (mono_tags, opaque_lifting) abs_eq_iff abs_norm_cancel)
    qed
    with r > 0show "sphere 0 r = {r *🪙R b, - r *🪙R b}"
      by (force simp: sphere_def dist_norm)
    have "dist (r *🪙R b) (- r *🪙R b) = norm (r *🪙R b + r *🪙R b)"
      by (simp add: dist_norm)
    also have " = norm ((2*r) *🪙R b)"
      by (metis mult_2 scaleR_add_left)
    also have " = 2*r"
      using r > 0 b norm_Basis by fastforce
    finally show "dist (r *🪙R b) (- r *🪙R b) = 2*r" .
  qed
qed

lemma sphere_1D_doubleton:
  fixes a :: "'a :: euclidean_space"
  assumes "DIM('a) = 1" and "r > 0"
  obtains x y where "sphere a r = {x,y} dist x y = 2*r"
  using sphere_1D_doubleton_zero [OF assms] dist_add_cancel image_empty image_insert
  by (metis (no_types, opaque_lifting) add.right_neutral sphere_translation)

lemma psubset_sphere_Compl_connected:
  fixes S :: "'a::euclidean_space set"
  assumes S: "S sphere a r" and "0 < r" and 2: "2 DIM('a)"
  shows "connected(- S)"
proof -
  have "S sphere a r"
    using S by blast
  obtain b where "dist a b = r" and "b S"
    using S mem_sphere by blast
  have CS: "- S = {x. dist a x r (x S)} {x. r dist a x (x S)}"
    by auto
  have "{x. dist a x r x S} {x. r dist a x x S} {}"
    using b S dist a b = r by blast
  moreover have "connected {x. dist a x r x S}"
    using assms
    by (force intro: connected_intermediate_closure [of "ball a r"])
  moreover have "connected {x. r dist a x x S}"
  proof (rule connected_intermediate_closure [of "- cball a r"])
    show "{x. r dist a x x S} closure (- cball a r)"
      using interior_closure by (force intro: connected_complement_bounded_convex)
  qed (use assms connected_complement_bounded_convex in auto)
  ultimately show ?thesis
    by (simp add: CS connected_Un)
qed


subsectionEvery annulus is a connected set

lemma path_connected_2DIM_I:
  fixes a :: "'N::euclidean_space"
  assumes 2: "2 DIM('N)" and pc: "path_connected {r. 0 r P r}"
  shows "path_connected {x. P(norm(x - a))}"
proof -
  have "{x. P(norm(x - a))} = (+) a ` {x. P(norm x)}"
    by force
  moreover have "path_connected {x::'N. P(norm x)}"
  proof -
    let ?D = "{x. 0 x P x} × sphere (0::'N) 1"
    have "x (λz. fst z *🪙R snd z) ` ?D"
      if "P (norm x)" for x::'N
    proof (cases "x=0")
      case True
      with that show ?thesis
        apply (simp add: image_iff)
        by (metis (no_types) mem_sphere_0 order_refl vector_choose_size zero_le_one)
    next
      case False
      with that show ?thesis
        by (rule_tac x="(norm x, x /🪙R norm x)" in image_eqI) auto
    qed
    then have *: "{x::'N. P(norm x)} = (λz. fst z *🪙R snd z) ` ?D"
      by auto
    have "continuous_on ?D (λz:: real×'N. fst z *🪙R snd z)"
      by (intro continuous_intros)
    moreover have "path_connected ?D"
      by (metis path_connected_Times [OF pc] path_connected_sphere 2)
    ultimately show ?thesis
      by (simp add: "*" path_connected_continuous_image)
  qed
  ultimately show ?thesis
    using path_connected_translation by metis
qed

proposition path_connected_annulus:
  fixes a :: "'N::euclidean_space"
  assumes "2 DIM('N)"
  shows "path_connected {x. r1 < norm(x - a) norm(x - a) < r2}"
        "path_connected {x. r1 < norm(x - a) norm(x - a) r2}"
        "path_connected {x. r1 norm(x - a) norm(x - a) < r2}"
        "path_connected {x. r1 norm(x - a) norm(x - a) r2}"
  by (auto simp: is_interval_def intro!: is_interval_convex convex_imp_path_connected path_connected_2DIM_I [OF assms])

proposition connected_annulus:
  fixes a :: "'N::euclidean_space"
  assumes "2 DIM('N::euclidean_space)"
  shows "connected {x. r1 < norm(x - a) norm(x - a) < r2}"
        "connected {x. r1 < norm(x - a) norm(x - a) r2}"
        "connected {x. r1 norm(x - a) norm(x - a) < r2}"
        "connected {x. r1 norm(x - a) norm(x - a) r2}"
  by (auto simp: path_connected_annulus [OF assms] path_connected_imp_connected)


subsection🍋tag unimportant\<open>Relations between components and path components

lemma open_connected_component:
  fixes S :: "'a::real_normed_vector set"
  assumes "open S"
  shows "open (connected_component_set S x)"
proof (clarsimp simp: open_contains_ball)
  fix y
  assume xy: "connected_component S x y"
  then obtain e where "e>0" "ball y e S"
    using assms connected_component_in openE by blast
  then show "e>0. ball y e connected_component_set S x"
    by (metis xy centre_in_ball connected_ball connected_component_eq_eq connected_component_in connected_component_maximal)
qed

corollary open_components:
    fixes S :: "'a::real_normed_vector set"
    shows "[open u; S components u] ==> open S"
  by (simp add: components_iff) (metis open_connected_component)

lemma in_closure_connected_component:
  fixes S :: "'a::real_normed_vector set"
  assumes x: "x S" and S: "open S"
  shows "x closure (connected_component_set S y) x connected_component_set S y"
proof -
  have "x islimpt connected_component_set S y ==> connected_component S y x"
    by (metis (no_types, lifting) S connected_component_eq connected_component_refl islimptE mem_Collect_eq open_connected_component x)
  then show ?thesis
    by (auto simp: closure_def)
qed

lemma connected_disjoint_Union_open_pick:
  assumes "pairwise disjnt B"
          "S. S A ==> connected S S {}"
          "S. S B ==> open S"
          "A B"
          "S A"
  obtains T where "T B" "S T" "S (B - {T}) = {}"
proof -
  have "S B" "connected S" "S {}"
    using assms S A by blast+
  then obtain T where "T B" "S T {}"
    by (metis Sup_inf_eq_bot_iff inf.absorb_iff2 inf_commute)
  have 1: "open T" by (simp add: T B assms)
  have 2: "open ((B-{T}))" using assms by blast
  have 3: "S T (B - {T})" using S B by blast
  have "T (B - {T}) = {}" using T B pairwise disjnt B
    by (auto simp: pairwise_def disjnt_def)
  then have 4: "T (B - {T}) S = {}" by auto
  from connectedD [OF connected S 1 2 4 3]
  have "S (B-{T}) = {}"
    by (auto simp: Int_commute S T {})
  with T B 3 that show ?thesis
    by (metis IntI UnE empty_iff subsetD subsetI)
qed

lemma connected_disjoint_Union_open_subset:
  assumes A: "pairwise disjnt A" and B: "pairwise disjnt B"
      and SA: "S. S A ==> open S connected S S {}"
      and SB: "S. S B ==> open S connected S S {}"
      and eq [simp]: "A = B"
    shows "A B"
proof
  fix S
  assume "S A"
  obtain T where "T B" "S T" "S (B - {T}) = {}"
    using SA SB S A connected_disjoint_Union_open_pick [OF B, of A] eq order_refl by blast
  moreover obtain S' where "S' A" "T S'" "T (A - {S'}) = {}"
    using SA SB T B connected_disjoint_Union_open_pick [OF A, of B] eq order_refl by blast
  ultimately have "S' = S"
    by (metis A Int_subset_iff SA S A disjnt_def inf.orderE pairwise_def)
  with T S' have "T S" by simp
  with S T have "S = T" by blast
  with T B show "S B" by simp
qed

lemma connected_disjoint_Union_open_unique:
  assumes A: "pairwise disjnt A" and B: "pairwise disjnt B"
      and SA: "S. S A ==> open S connected S S {}"
      and SB: "S. S B ==> open S connected S S {}"
      and eq [simp]: "A = B"
    shows "A = B"
by (metis subset_antisym connected_disjoint_Union_open_subset assms)

proposition components_open_unique:
 fixes S :: "'a::real_normed_vector set"
  assumes "pairwise disjnt A" "A = S"
          "X. X A ==> open X connected X X {}"
    shows "components S = A"
proof -
  have "open S" using assms by blast
  show ?thesis
  proof (rule connected_disjoint_Union_open_unique)
    show "disjoint (components S)"
      by (simp add: components_eq disjnt_def pairwise_def)
  qed (use open S in simp_all add: assms open_components in_components_connected in_components_nonempty)
qed


subsection🍋tag unimportant\<open>Existence of unbounded components

lemma cobounded_unbounded_component:
    fixes S :: "'a :: euclidean_space set"
    assumes "bounded (-S)"
      shows "x. x S ¬ bounded (connected_component_set S x)"
proof -
  obtain i::'a where i: "i Basis"
    using nonempty_Basis by blast
  obtain B where B: "B>0" "-S ball 0 B"
    using bounded_subset_ballD [OF assms, of 0] by auto
  then have *: "x. B norm x ==> x S"
    by (force simp: ball_def dist_norm)
  have unbounded_inner: "¬ bounded {x. inner i x B}"
  proof (clarsimp simp: bounded_def dist_norm)
    fix e x
    show "y. B i y ¬ norm (x - y) e"
      using i
      by (rule_tac x="x + (max B e + 1 + i x) *🪙R i" in exI) (auto simp: inner_right_distrib)
  qed
  have 🍋"x. B i x ==> x S"
    using * Basis_le_norm [OF i] by (metis abs_ge_self inner_commute order_trans)
  have "{x. B i x} connected_component_set S (B *🪙R i)"
    by (intro connected_component_maximal) (auto simp: i intro: convex_connected convex_halfspace_ge [of B] 🍋)
  then have "¬ bounded (connected_component_set S (B *🪙R i))"
    using bounded_subset unbounded_inner by blast
  moreover have "B *🪙R i S"
    by (rule *) (simp add: norm_Basis [OF i])
  ultimately show ?thesis
    by blast
qed

lemma cobounded_unique_unbounded_component:
    fixes S :: "'a :: euclidean_space set"
    assumes bs: "bounded (-S)" and "2 DIM('a)"
        and bo: "¬ bounded(connected_component_set S x)"
                "¬ bounded(connected_component_set S y)"
      shows "connected_component_set S x = connected_component_set S y"
proof -
  obtain i::'a where i: "i Basis"
    using nonempty_Basis by blast
  obtain B where "B>0" and B: "-S ball 0 B"
    using bounded_subset_ballD [OF bs, of 0] by auto
  then have *: "x. B norm x ==> x S"
    by (force simp: ball_def dist_norm)
  obtain x' y' where x': "connected_component S x x'" "norm x' > B"
  and  y': "connected_component S y y'" "norm y' > B"
    using B>0 bo bounded_pos by (metis linorder_not_le mem_Collect_eq) 
  have x'y': "connected_component S x' y'"
    unfolding connected_component_def
  proof (intro exI conjI)
    show "connected (- ball 0 B :: 'a set)"
      using assms by (auto intro: connected_complement_bounded_convex)
  qed (use x' y' dist_norm * in auto)
  show ?thesis
      using x' y' x'y'
      by (metis connected_component_eq mem_Collect_eq)
qed

lemma cobounded_unbounded_components:
    fixes S :: "'a :: euclidean_space set"
    shows "bounded (-S) ==> c. c components S ¬bounded c"
  by (metis cobounded_unbounded_component components_def imageI)

lemma cobounded_unique_unbounded_components:
    fixes S :: "'a :: euclidean_space set"
    shows  "[bounded (- S); c components S; ¬ bounded c; c' components S; ¬ bounded c'; 2 DIM('a)] ==> c' = c"
  unfolding components_iff
  by (metis cobounded_unique_unbounded_component)

lemma cobounded_has_bounded_component:
  fixes S :: "'a :: euclidean_space set"
  assumes "bounded (- S)" "¬ connected S" "2 DIM('a)"
  obtains C where "C components S" "bounded C"
  by (meson cobounded_unique_unbounded_components connected_eq_connected_components_eq assms)


subsectionThe inside and outside of a Set

text🍋tag important\<open>The inside comprises the points in a bounded connected component of the set's complement.
  The outside comprises the points in unbounded connected component of the complement.

definition🍋tag important inside where
  "inside S {x. (x S) bounded(connected_component_set ( - S) x)}"

definition🍋tag important outside where
  "outside S -S {x. ¬ bounded(connected_component_set (- S) x)}"

lemma outside: "outside S = {x. ¬ bounded(connected_component_set (- S) x)}"
  by (auto simp: outside_def) (metis Compl_iff bounded_empty connected_component_eq_empty)

lemma inside_no_overlap [simp]: "inside S S = {}"
  by (auto simp: inside_def)

lemma outside_no_overlap [simp]:
   "outside S S = {}"
  by (auto simp: outside_def)

lemma inside_Int_outside [simp]: "inside S outside S = {}"
  by (auto simp: inside_def outside_def)

lemma inside_Un_outside [simp]: "inside S outside S = (- S)"
  by (auto simp: inside_def outside_def)

lemma inside_eq_outside:
   "inside S = outside S S = UNIV"
  by (auto simp: inside_def outside_def)

lemma inside_outside: "inside S = (- (S outside S))"
  by (force simp: inside_def outside)

lemma outside_inside: "outside S = (- (S inside S))"
  by (auto simp: inside_outside) (metis IntI equals0D outside_no_overlap)

lemma union_with_inside: "S inside S = - outside S"
  by (auto simp: inside_outside) (simp add: outside_inside)

lemma union_with_outside: "S outside S = - inside S"
  by (simp add: inside_outside)

lemma outside_mono: "S T ==> outside T outside S"
  by (auto simp: outside bounded_subset connected_component_mono)

lemma inside_mono: "S T ==> inside S - T inside T"
  by (auto simp: inside_def bounded_subset connected_component_mono)

lemma segment_bound_lemma:
  fixes u::real
  assumes "x B" "y B" "0 u" "u 1"
  shows "(1 - u) * x + u * y B"
  by (smt (verit) assms convex_bound_le ge_iff_diff_ge_0 minus_add_distrib 
      mult_minus_right neg_le_iff_le)

lemma cobounded_outside:
  fixes S :: "'a :: real_normed_vector set"
  assumes "bounded S" shows "bounded (- outside S)"
proof -
  obtain B where B: "B>0" "S ball 0 B"
    using bounded_subset_ballD [OF assms, of 0] by auto
  { fix x::'a and C::real
    assume Bno: "B norm x" and C: "0 < C"
    have "y. connected_component (- S) x y norm y > C"
    proof (cases "x = 0")
      case True with B Bno show ?thesis by force
    next
      case False 
      have "closed_segment x (((B + C) / norm x) *🪙R x) - ball 0 B"
      proof
        fix w
        assume "w closed_segment x (((B + C) / norm x) *🪙R x)"
        then obtain u where
          w: "w = (1 - u + u * (B + C) / norm x) *🪙R x" "0 u" "u 1"
          by (auto simp add: closed_segment_def real_vector_class.scaleR_add_left [symmetric])
        with False B C have "B (1 - u) * norm x + u * (B + C)"
          using segment_bound_lemma [of B "norm x" "B + C" u] Bno
          by simp
        with False B C show "w - ball 0 B"
          using distrib_right [of _ _ "norm x"]
          by (simp add: ball_def w not_less)
      qed
      also have "... -S"
        by (simp add: B)
      finally have "T. connected T T - S x T ((B + C) / norm x) *🪙R x T"
        by (rule_tac x="closed_segment x (((B+C)/norm x) *🪙R x)" in exI) simp
      with False B
      show ?thesis
        by (rule_tac x="((B+C)/norm x) *🪙R x" in exI) (simp add: connected_component_def)
    qed
  }
  then show ?thesis
    apply (simp add: outside_def assms)
    apply (rule bounded_subset [OF bounded_ball [of 0 B]])
    apply (force simp: dist_norm not_less bounded_pos)
    done
qed

lemma unbounded_outside:
    fixes S :: "'a::{real_normed_vector, perfect_space} set"
    shows "bounded S ==> ¬ bounded(outside S)"
  using cobounded_imp_unbounded cobounded_outside by blast

lemma bounded_inside:
    fixes S :: "'a::{real_normed_vector, perfect_space} set"
    shows "bounded S ==> bounded(inside S)"
  by (simp add: bounded_Int cobounded_outside inside_outside)

lemma connected_outside:
    fixes S :: "'a::euclidean_space set"
    assumes "bounded S" "2 DIM('a)"
    shows "connected(outside S)"
  apply (clarsimp simp add: connected_iff_connected_component outside)
  apply (rule_tac S="connected_component_set (- S) x" in connected_component_of_subset)
  apply (metis (no_types) assms cobounded_unbounded_component cobounded_unique_unbounded_component connected_component_eq_eq connected_component_idemp double_complement mem_Collect_eq)
  by (simp add: Collect_mono connected_component_eq)

lemma outside_connected_component_lt:
  "outside S = {x. B. y. B < norm(y) connected_component (- S) x y}"
proof -
  have "x B. x outside S ==> y. B < norm y connected_component (- S) x y"
    by (metis boundedI linorder_not_less mem_Collect_eq outside)
  moreover
  have "x. B. y. B < norm y connected_component (- S) x y ==> x outside S"
    by (metis bounded_pos linorder_not_less mem_Collect_eq outside)
  ultimately show ?thesis by auto
qed

lemma outside_connected_component_le:
  "outside S = {x. B. y. B norm(y) connected_component (- S) x y}"
  apply (simp add: outside_connected_component_lt Set.set_eq_iff)
  by (meson gt_ex leD le_less_linear less_imp_le order.trans)

lemma not_outside_connected_component_lt:
    fixes S :: "'a::euclidean_space set"
    assumes S: "bounded S" and "2 DIM('a)"
      shows "- (outside S) = {x. B. y. B < norm(y) ¬ connected_component (- S) x y}"
proof -
  obtain B::real where B: "0 < B" and Bno: "x. x S ==> norm x B"
    using S [simplified bounded_pos] by auto
  have cyz: "connected_component (- S) y z" 
    if yz: "B < norm z" "B < norm y" for y::'a and z::'a
  proof -
    have "connected_component (- cball 0 B) y z"
      using assms yz
      by (force simp: dist_norm intro: connected_componentI [OF _ subset_refl] connected_complement_bounded_convex)
    then show ?thesis
      by (metis connected_component_of_subset Bno Compl_anti_mono mem_cball_0 subset_iff)
  qed
  show ?thesis
    apply (auto simp: outside bounded_pos)
    apply (metis Compl_iff bounded_iff cobounded_imp_unbounded mem_Collect_eq not_le)
    by (metis B connected_component_trans cyz not_le)
qed

lemma not_outside_connected_component_le:
  fixes S :: "'a::euclidean_space set"
  assumes S: "bounded S"  "2 DIM('a)"
  shows "- (outside S) = {x. B. y. B norm(y) ¬ connected_component (- S) x y}"
  unfolding not_outside_connected_component_lt [OF assms]
  by (metis (no_types, opaque_lifting) dual_order.strict_trans1 gt_ex pinf(8))

lemma inside_connected_component_lt:
    fixes S :: "'a::euclidean_space set"
    assumes S: "bounded S"  "2 DIM('a)"
      shows "inside S = {x. (x S) (B. y. B < norm(y) ¬ connected_component (- S) x y)}"
  by (auto simp: inside_outside not_outside_connected_component_lt [OF assms])

lemma inside_connected_component_le:
    fixes S :: "'a::euclidean_space set"
    assumes S: "bounded S"  "2 DIM('a)"
      shows "inside S = {x. (x S) (B. y. B norm(y) ¬ connected_component (- S) x y)}"
  by (auto simp: inside_outside not_outside_connected_component_le [OF assms])

lemma inside_subset:
  assumes "connected U" and "¬ bounded U" and "T U = - S"
  shows "inside S T"
  using bounded_subset [of "connected_component_set (- S) _" U] assms
  by (metis (no_types, lifting) ComplI Un_iff connected_component_maximal inside_def mem_Collect_eq subsetI)

lemma frontier_not_empty:
  fixes S :: "'a :: real_normed_vector set"
  shows "[S {}; S UNIV] ==> frontier S {}"
    using connected_Int_frontier [of UNIV S] by auto

lemma frontier_eq_empty:
  fixes S :: "'a :: real_normed_vector set"
  shows "frontier S = {} S = {} S = UNIV"
using frontier_UNIV frontier_empty frontier_not_empty by blast

lemma frontier_of_connected_component_subset:
  fixes S :: "'a::real_normed_vector set"
  shows "frontier(connected_component_set S x) frontier S"
proof -
  { fix y
    assume y1: "y closure (connected_component_set S x)"
       and y2: "y interior (connected_component_set S x)"
    have "y closure S"
      using y1 closure_mono connected_component_subset by blast
    moreover have "z interior (connected_component_set S x)"
          if "0 < e" "ball y e interior S" "dist y z < e" for e z
    proof -
      have "ball y e connected_component_set S y"
        using connected_component_maximal that interior_subset 
        by (metis centre_in_ball connected_ball subset_trans)
      then show ?thesis
        using y1 apply (simp add: closure_approachable open_contains_ball_eq [OF open_interior])
        by (metis connected_component_eq dist_commute mem_Collect_eq mem_ball mem_interior subsetD 0 🚫 y2)
    qed
    then have "y interior S"
      using y2 by (force simp: open_contains_ball_eq [OF open_interior])
    ultimately have "y frontier S"
      by (auto simp: frontier_def)
  }
  then show ?thesis by (auto simp: frontier_def)
qed

lemma frontier_Union_subset_closure:
  fixes F :: "'a::real_normed_vector set set"
  shows "frontier(F) closure(t F. frontier t)"
proof -
  have "yF. yfrontier y. dist y x < e"
       if "T F" "y T" "dist y x < e"
          "x interior (F)" "0 < e" for x y e T
  proof (cases "x T")
    case True with that show ?thesis
      by (metis Diff_iff Sup_upper closure_subset contra_subsetD dist_self frontier_def interior_mono)
  next
    case False
    have 🍋"closed_segment x y T {}" "closed_segment x y - T {}"
      using y T False by blast+
    obtain c where "c closed_segment x y" "c frontier T"
       using False connected_Int_frontier [OF connected_segment 🍋by auto
     with that show ?thesis
       by (smt (verit) dist_norm segment_bound1)
  qed
  then show ?thesis
    by (fastforce simp add: frontier_def closure_approachable)
qed

lemma frontier_Union_subset:
  fixes F :: "'a::real_normed_vector set set"
  shows "finite F ==> frontier(F) (t F. frontier t)"
  by (metis closed_UN closure_closed frontier_Union_subset_closure frontier_closed)

lemma frontier_of_components_subset:
  fixes S :: "'a::real_normed_vector set"
  shows "C components S ==> frontier C frontier S"
  by (metis Path_Connected.frontier_of_connected_component_subset components_iff)

lemma frontier_of_components_closed_complement:
  fixes S :: "'a::real_normed_vector set"
  shows "[closed S; C components (- S)] ==> frontier C S"
  using frontier_complement frontier_of_components_subset frontier_subset_eq by blast

lemma frontier_minimal_separating_closed:
  fixes S :: "'a::real_normed_vector set"
  assumes "closed S"
      and nconn: "¬ connected(- S)"
      and C: "C components (- S)"
      and conn: "T. [closed T; T S] ==> connected(- T)"
    shows "frontier C = S"
proof (rule ccontr)
  assume "frontier C S"
  then have "frontier C S"
    using frontier_of_components_closed_complement [OF closed S C] by blast
  then have "connected(- (frontier C))"
    by (simp add: conn)
  have "¬ connected(- (frontier C))"
    unfolding connected_def not_not
  proof (intro exI conjI)
    show "open C"
      using C closed S open_components by blast
    show "open (- closure C)"
      by blast
    show "C - closure C - frontier C = {}"
      using closure_subset by blast
    show "C - frontier C {}"
      using C open C components_eq frontier_disjoint_eq by fastforce
    show "- frontier C C - closure C"
      by (simp add: open C closed_Compl frontier_closures)
    then show "- closure C - frontier C {}"
      by (metis C Compl_Diff_eq Un_Int_eq(4) Un_commute frontier C S open C compl_le_compl_iff frontier_def in_components_subset interior_eq leD sup_bot.right_neutral)
  qed
  then show False
    using connected (- frontier C) by blast
qed

lemma connected_component_UNIV [simp]:
  fixes x :: "'a::real_normed_vector"
  shows "connected_component_set UNIV x = UNIV"
  using connected_iff_eq_connected_component_set [of "UNIV::'a set"] connected_UNIV
  by auto

lemma connected_component_eq_UNIV:
    fixes x :: "'a::real_normed_vector"
    shows "connected_component_set s x = UNIV s = UNIV"
  using connected_component_in connected_component_UNIV by blast

lemma components_UNIV [simp]: "components UNIV = {UNIV :: 'a::real_normed_vector set}"
  by (auto simp: components_eq_sing_iff)

lemma interior_inside_frontier:
    fixes S :: "'a::real_normed_vector set"
    assumes "bounded S"
      shows "interior S inside (frontier S)"
proof -
  { fix x y
    assume x: "x interior S" and y: "y S"
       and cc: "connected_component (- frontier S) x y"
    have "connected_component_set (- frontier S) x frontier S {}"
    proof (rule connected_Int_frontier; simp add: set_eq_iff)
      show "u. connected_component (- frontier S) x u u S"
        by (meson cc connected_component_in connected_component_refl_eq interior_subset subsetD x)
      show "u. connected_component (- frontier S) x u u S"
        using y cc by blast
    qed
    then have "bounded (connected_component_set (- frontier S) x)"
      using connected_component_in by auto
  }
  then show ?thesis
    using bounded_subset [OF assms]
    by (metis (no_types, lifting) Diff_iff frontier_def inside_def mem_Collect_eq subsetI)
qed

lemma inside_empty [simp]: "inside {} = ({} :: 'a :: {real_normed_vector, perfect_space} set)"
  by (simp add: inside_def)

lemma outside_empty [simp]: "outside {} = (UNIV :: 'a :: {real_normed_vector, perfect_space} set)"
  using inside_empty inside_Un_outside by blast

lemma inside_same_component:
   "[connected_component (- S) x y; x inside S] ==> y inside S"
  using connected_component_eq connected_component_in
  by (fastforce simp add: inside_def)

lemma outside_same_component:
   "[connected_component (- S) x y; x outside S] ==> y outside S"
  using connected_component_eq connected_component_in
  by (fastforce simp add: outside_def)

lemma convex_in_outside:
  fixes S :: "'a :: {real_normed_vector, perfect_space} set"
  assumes S: "convex S" and z: "z S"
    shows "z outside S"
proof (cases "S={}")
  case True then show ?thesis by simp
next
  case False then obtain a where "a S" by blast
  with z have zna: "z a" by auto
  { assume "bounded (connected_component_set (- S) z)"
    with bounded_pos_less obtain B where "B>0" and B: "x. connected_component (- S) z x ==> norm x < B"
      by (metis mem_Collect_eq)
    define C where "C = (B + 1 + norm z) / norm (z-a)"
    have "C > 0"
      using 0 🚫 zna by (simp add: C_def field_split_simps add_strict_increasing)
    have "norm (z + C *🪙R (z-a)) - norm (C *🪙R (z-a)) norm z"
      by (metis add_diff_cancel norm_triangle_ineq3)
    moreover have "norm (C *🪙R (z-a)) > norm z + B"
      using zna B>0 by (simp add: C_def le_max_iff_disj)
    ultimately have C: "norm (z + C *🪙R (z-a)) > B" by linarith
    { fix u::real
      assume u: "0u" "u1" and ins: "(1 - u) *🪙R z + u *🪙R (z + C *🪙R (z - a)) S"
      then have Cpos: "1 + u * C > 0"
        by (meson 0 🚫 add_pos_nonneg less_eq_real_def zero_le_mult_iff zero_less_one)
      then have *: "(1 / (1 + u * C)) *🪙R z + (u * C / (1 + u * C)) *🪙R z = z"
        by (simp add: scaleR_add_left [symmetric] field_split_simps)
      then have False
        using convexD_alt [OF S a S ins, of "1/(u*C + 1)"C>0 z S Cpos u
        by (simp add: * field_split_simps)
    } note contra = this
    have "connected_component (- S) z (z + C *🪙R (z-a))"
    proof (rule connected_componentI [OF connected_segment])
      show "closed_segment z (z + C *🪙R (z - a)) - S"
        using contra by (force simp add: closed_segment_def)
    qed auto
    then have False
      using zna B [of "z + C *🪙R (z-a)"] C
      by (auto simp: field_split_simps max_mult_distrib_right)
  }
  then show ?thesis
    by (auto simp: outside_def z)
qed

lemma outside_convex:
  fixes S :: "'a :: {real_normed_vector, perfect_space} set"
  assumes "convex S"
    shows "outside S = - S"
  by (metis ComplD assms convex_in_outside equalityI inside_Un_outside subsetI sup.cobounded2)

lemma outside_singleton [simp]:
  fixes x :: "'a :: {real_normed_vector, perfect_space}"
  shows "outside {x} = -{x}"
  by (auto simp: outside_convex)

lemma inside_convex:
  fixes S :: "'a :: {real_normed_vector, perfect_space} set"
  shows "convex S ==> inside S = {}"
  by (simp add: inside_outside outside_convex)

lemma inside_singleton [simp]:
  fixes x :: "'a :: {real_normed_vector, perfect_space}"
  shows "inside {x} = {}"
  by (auto simp: inside_convex)

lemma outside_subset_convex:
  fixes S :: "'a :: {real_normed_vector, perfect_space} set"
  shows "[convex T; S T] ==> - T outside S"
  using outside_convex outside_mono by blast

lemma outside_Un_outside_Un:
  fixes S :: "'a::real_normed_vector set"
  assumes "S outside(T U) = {}"
  shows "outside(T U) outside(T S)"
proof
  fix x
  assume x: "x outside (T U)"
  have "Y - S" if "connected Y" "Y - T" "Y - U" "x Y" "u Y" for u Y
  proof -
    have "Y connected_component_set (- (T U)) x"
      by (simp add: connected_component_maximal that)
    also have " outside(T U)"
      by (metis (mono_tags, lifting) Collect_mono mem_Collect_eq outside outside_same_component x)
    finally have "Y outside(T U)" .
    with assms show ?thesis by auto
  qed
  with x show "x outside (T S)"
    by (simp add: outside_connected_component_lt connected_component_def) meson
qed

lemma outside_frontier_misses_closure:
    fixes S :: "'a::real_normed_vector set"
    assumes "bounded S"
    shows  "outside(frontier S) - closure S"
  using assms frontier_def interior_inside_frontier outside_inside by fastforce

lemma outside_frontier_eq_complement_closure:
  fixes S :: "'a :: {real_normed_vector, perfect_space} set"
    assumes "bounded S" "convex S"
      shows "outside(frontier S) = - closure S"
by (metis Diff_subset assms convex_closure frontier_def outside_frontier_misses_closure
          outside_subset_convex subset_antisym)

lemma inside_frontier_eq_interior:
     fixes S :: "'a :: {real_normed_vector, perfect_space} set"
     shows "[bounded S; convex S] ==> inside(frontier S) = interior S"
  unfolding inside_outside outside_frontier_eq_complement_closure
  using closure_subset interior_subset by (auto simp: frontier_def)

lemma open_inside:
    fixes S :: "'a::real_normed_vector set"
    assumes "closed S"
      shows "open (inside S)"
proof -
  { fix x assume x: "x inside S"
    have "open (connected_component_set (- S) x)"
      using assms open_connected_component by blast
    then obtain e where e: "e>0" and e: "y. dist y x < e connected_component (- S) x y"
      using dist_not_less_zero
      apply (simp add: open_dist)
      by (metis (no_types, lifting) Compl_iff connected_component_refl_eq inside_def mem_Collect_eq x)
    then have "e>0. ball x e inside S"
      by (metis e dist_commute inside_same_component mem_ball subsetI x)
  }
  then show ?thesis
    by (simp add: open_contains_ball)
qed

lemma open_outside:
    fixes S :: "'a::real_normed_vector set"
    assumes "closed S"
      shows "open (outside S)"
proof -
  { fix x assume x: "x outside S"
    have "open (connected_component_set (- S) x)"
      using assms open_connected_component by blast
    then obtain e where e: "e>0" and e: "y. dist y x < e connected_component (- S) x y"
      using dist_not_less_zero x
      by (auto simp add: open_dist outside_def intro: connected_component_refl)
    then have "e>0. ball x e outside S"
      by (metis e dist_commute outside_same_component mem_ball subsetI x)
  }
  then show ?thesis
    by (simp add: open_contains_ball)
qed

lemma closure_inside_subset:
  fixes S :: "'a::real_normed_vector set"
  assumes "closed S"
  shows "closure(inside S) S inside S"
  by (metis assms closure_minimal open_closed open_outside sup.cobounded2 union_with_inside)

lemma frontier_inside_subset:
    fixes S :: "'a::real_normed_vector set"
    assumes "closed S"
      shows "frontier(inside S) S"
  using assms closure_inside_subset frontier_closures frontier_disjoint_eq open_inside by fastforce

lemma closure_outside_subset:
    fixes S :: "'a::real_normed_vector set"
    assumes "closed S"
      shows "closure(outside S) S outside S"
  by (metis assms closed_open closure_minimal inside_outside open_inside sup_ge2)

lemma closed_path_image_Un_inside:
  fixes g :: "real ==> 'a :: real_normed_vector"
  assumes "path g"
  shows   "closed (path_image g inside (path_image g))"
  by (simp add: assms closed_Compl closed_path_image open_outside union_with_inside)

lemma frontier_outside_subset:
  fixes S :: "'a::real_normed_vector set"
  assumes "closed S"
  shows "frontier(outside S) S"
  unfolding frontier_def
  by (metis Diff_subset_conv assms closure_outside_subset interior_eq open_outside sup_aci(1))

lemma inside_complement_unbounded_connected_empty:
     "[connected (- S); ¬ bounded (- S)] ==> inside S = {}"
  using inside_subset by blast

lemma inside_bounded_complement_connected_empty:
    fixes S :: "'a::{real_normed_vector, perfect_space} set"
    shows "[connected (- S); bounded S] ==> inside S = {}"
  by (metis inside_complement_unbounded_connected_empty cobounded_imp_unbounded)

lemma inside_inside:
    assumes "S inside T"
    shows "inside S - T inside T"
unfolding inside_def
proof clarify
  fix x
  assume x: "x T" "x S" and bo: "bounded (connected_component_set (- S) x)"
  show "bounded (connected_component_set (- T) x)"
  proof (cases "S connected_component_set (- T) x = {}")
    case True then show ?thesis
      by (metis bounded_subset [OF bo] compl_le_compl_iff connected_component_idemp connected_component_mono disjoint_eq_subset_Compl double_compl)
  next
    case False 
    then obtain y where y: "y S" "y connected_component_set (- T) x"
      by (meson disjoint_iff)
    then have "bounded (connected_component_set (- T) y)"
      using assms [unfolded inside_def] by blast
    with y show ?thesis
      by (metis connected_component_eq)
  qed
qed

lemma inside_inside_subset: "inside(inside S) S"
  using inside_inside union_with_outside by fastforce

lemma inside_outside_intersect_connected:
      "[connected T; inside S T {}; outside S T {}] ==> S T {}"
  apply (simp add: inside_def outside_def ex_in_conv [symmetric] disjoint_eq_subset_Compl, clarify)
  by (metis compl_le_swap1 connected_componentI connected_component_eq mem_Collect_eq)

lemma outside_bounded_nonempty:
  fixes S :: "'a :: {real_normed_vector, perfect_space} set"
  assumes "bounded S" shows "outside S {}"
  using assms unbounded_outside by force

lemma outside_compact_in_open:
    fixes S :: "'a :: {real_normed_vector,perfect_space} set"
    assumes S: "compact S" and T: "open T" and "S T" "T {}"
      shows "outside S T {}"
proof -
  have "outside S {}"
    by (simp add: compact_imp_bounded outside_bounded_nonempty S)
  with assms obtain a b where a: "a outside S" and b: "b T" by auto
  show ?thesis
  proof (cases "a T")
    case True with a show ?thesis by blast
  next
    case False
      have front: "frontier T - S"
        using S T frontier_disjoint_eq T by auto
      { fix γ
        assume "path γ" and pimg_sbs: "path_image γ - {pathfinish γ} interior (- T)"
           and pf: "pathfinish γ frontier T" and ps: "pathstart γ = a"
        define c where "c = pathfinish γ"
        have "c -S" unfolding c_def using front pf by blast
        moreover have "open (-S)" using S compact_imp_closed by blast
        ultimately obtain ε::real where "ε > 0" and ε: "cball c ε -S"
          using open_contains_cball[of "-S"] S by blast
        then obtain d where "d T" and d: "dist d c < ε"
          using closure_approachable [of c T] pf unfolding c_def
          by (metis Diff_iff frontier_def)
        then have "d -S" using ε
          using dist_commute by (metis contra_subsetD mem_cball not_le not_less_iff_gr_or_eq)
        have pimg_sbs_cos: "path_image γ -S"
          using c - S S T c_def interior_subset pimg_sbs by fastforce
        have "closed_segment c d cball c ε"
          by (metis 0 🚫ε centre_in_cball closed_segment_subset convex_cball d dist_commute less_eq_real_def mem_cball)
        with ε have "closed_segment c d -S" by blast
        moreover have con_gcd: "connected (path_image γ closed_segment c d)"
          by (rule connected_Un) (auto simp: c_def path γ connected_path_image)
        ultimately have "connected_component (- S) a d"
          unfolding connected_component_def using pimg_sbs_cos ps by blast
        then have "outside S T {}"
          using outside_same_component [OF _ a]  by (metis IntI d T empty_iff)
      } note * = this
      have pal: "pathstart (linepath a b) closure (- T)"
        by (auto simp: False closure_def)
      show ?thesis
        by (rule exists_path_subpath_to_frontier [OF path_linepath pal _ *]) (auto simp: b)
  qed
qed

lemma inside_inside_compact_connected:
    fixes S :: "'a :: euclidean_space set"
    assumes S: "closed S" and T: "compact T" and "connected T" "S inside T"
      shows "inside S inside T"
proof (cases "inside T = {}")
  case True with assms show ?thesis by auto
next
  case False
  consider "DIM('a) = 1" | "DIM('a) 2"
    using antisym not_less_eq_eq by fastforce
  then show ?thesis
  proof cases
    case 1 then show ?thesis
             using connected_convex_1_gen assms False inside_convex by blast
  next
    case 2
    have "bounded S"
      using assms by (meson bounded_inside bounded_subset compact_imp_bounded)
    then have coms: "compact S"
      by (simp add: S compact_eq_bounded_closed)
    then have bst: "bounded (S T)"
      by (simp add: compact_imp_bounded T)
    then obtain r where "0 < r" and r: "S T ball 0 r"
      using bounded_subset_ballD by blast
    have outst: "outside S outside T {}"
      by (metis bounded_Un bounded_subset bst cobounded_outside disjoint_eq_subset_Compl unbounded_outside)
    have "S T = {}" using assms
      by (metis disjoint_iff_not_equal inside_no_overlap subsetCE)
    moreover have "outside S inside T {}"
      by (meson False assms(4) compact_eq_bounded_closed coms open_inside outside_compact_in_open T)
    ultimately have "inside S T = {}"
      using inside_outside_intersect_connected [OF connected T, of S]
      by (metis "2" compact_eq_bounded_closed coms connected_outside inf.commute inside_outside_intersect_connected outst)
    then show ?thesis
      using inside_inside [OF S inside Tby blast
  qed
qed

lemma connected_with_inside:
    fixes S :: "'a :: real_normed_vector set"
    assumes S: "closed S" and cons: "connected S"
      shows "connected(S inside S)"
proof (cases "S inside S = UNIV")
  case True with assms show ?thesis by auto
next
  case False
  then obtain b where b: "b S" "b inside S" by blast
  have *: "y T. y S connected T a T y T T (S inside S)" 
    if "a S inside S" for a
    using that 
  proof
    assume "a S" then show ?thesis
      using cons by blast
  next
    assume a: "a inside S"
    then have ain: "a closure (inside S)"
      by (simp add: closure_def)
    obtain h where h: "path h" "pathstart h = a" 
                   "path_image h - {pathfinish h} interior (inside S)"
                   "pathfinish h frontier (inside S)"
      using ain b
      by (metis exists_path_subpath_to_frontier path_linepath pathfinish_linepath pathstart_linepath)
    moreover
    have h1S: "pathfinish h S"  
      using S h frontier_inside_subset by blast
    moreover 
    have "path_image h S inside S"
      using IntD1 S h1S h interior_eq open_inside by fastforce
    ultimately show ?thesis by blast
  qed
  show ?thesis
    apply (simp add: connected_iff_connected_component)
    apply (clarsimp simp add: connected_component_def dest!: *)
    subgoal for x y u u' T t'
      by (rule_tac x = "S T t'" in exI) (auto intro!: connected_Un cons)
    done
qed

textThe proof is virtually the same as that above.
lemma connected_with_outside:
    fixes S :: "'a :: real_normed_vector set"
    assumes S: "closed S" and cons: "connected S"
      shows "connected(S outside S)"
proof (cases "S outside S = UNIV")
  case True with assms show ?thesis by auto
next
  case False
  then obtain b where b: "b S" "b outside S" by blast
  have *: "y T. y S connected T a T y T T (S outside S)" if "a (S outside S)" for a
  using that proof
    assume "a S" then show ?thesis
      by (rule_tac x=a in exI, rule_tac x="{a}" in exI, simp)
  next
    assume a: "a outside S"
    then have ain: "a closure (outside S)"
      by (simp add: closure_def)
    obtain h where h: "path h" "pathstart h = a" 
                   "path_image h - {pathfinish h} interior (outside S)"
                   "pathfinish h frontier (outside S)"
      using ain b
      by (metis exists_path_subpath_to_frontier path_linepath pathfinish_linepath pathstart_linepath)
    moreover 
    have h1S: "pathfinish h S"
      using S frontier_outside_subset h(4) by blast
    moreover 
    have "path_image h S outside S"
      using IntD1 S h1S h interior_eq open_outside by fastforce
    ultimately show ?thesis
      by blast
  qed
  show ?thesis
    apply (simp add: connected_iff_connected_component)
    apply (clarsimp simp add: connected_component_def dest!: *)
    subgoal for x y u u' T t'
      by (rule_tac x="(S T t')" in exI) (auto intro!: connected_Un cons)
    done
qed

lemma inside_inside_eq_empty [simp]:
    fixes S :: "'a :: {real_normed_vector, perfect_space} set"
    assumes S: "closed S" and cons: "connected S"
    shows "inside (inside S) = {}"
proof -
  have "connected (- inside S)"
    by (metis S connected_with_outside cons union_with_outside)
  then show ?thesis
    by (metis bounded_Un inside_complement_unbounded_connected_empty unbounded_outside union_with_outside)
qed

lemma inside_in_components:
     "inside S components (- S) connected(inside S) inside S {}" (is "?lhs = ?rhs")
proof 
  assume R: ?rhs
  then have "x. [x S; x inside S] ==> ¬ connected (inside S)"
    by (simp add: inside_outside)
  with R show ?lhs
    unfolding in_components_maximal
    by (auto intro: inside_same_component connected_componentI)
qed (simp add: in_components_maximal)

textThe proof is like that above.
lemma outside_in_components:
     "outside S components (- S) connected(outside S) outside S {}" (is "?lhs = ?rhs")
proof 
  assume R: ?rhs
  then have "x. [x S; x outside S] ==> ¬ connected (outside S)"
    by (meson disjoint_iff outside_no_overlap)
  with R show ?lhs
    unfolding in_components_maximal
    by (auto intro: outside_same_component connected_componentI)
qed (simp add: in_components_maximal)

lemma bounded_unique_outside:
  fixes S :: "'a :: euclidean_space set"
  assumes "bounded S" "DIM('a) 2"
  shows "(c components (- S) ¬ bounded c) c = outside S" 
  using assms
  by (metis cobounded_unique_unbounded_components connected_outside double_compl outside_bounded_nonempty
      outside_in_components unbounded_outside)


subsectionCondition for an open map's image to contain a ball

proposition ball_subset_open_map_image:
  fixes f :: "'a::heine_borel ==> 'b :: {real_normed_vector,heine_borel}"
  assumes contf: "continuous_on (closure S) f"
      and oint: "open (f ` interior S)"
      and le_no: "z. z frontier S ==> r norm(f z - f a)"
      and "bounded S" "a S" "0 < r"
    shows "ball (f a) r f ` S"
proof (cases "f ` S = UNIV")
  case True then show ?thesis by simp
next
  case False
  then have "closed (frontier (f ` S))" "frontier (f ` S) {}"
    using a S by (auto simp: frontier_eq_empty)
  then obtain w where w: "w frontier (f ` S)"
    and dw_le: "y. y frontier (f ` S) ==> norm (f a - w) norm (f a - y)"
    by (auto simp add: dist_norm intro: distance_attains_inf [of "frontier(f ` S)" "f a"])
  then obtain ξ where ξ: "n. ξ n f ` S" and tendsw: <---- w"
    by (metis Diff_iff frontier_def closure_sequential)
    then have "n. x S. ξ n = f x" by force
    then obtain z where zs: "n. z n S" and fz: "n. ξ n = f (z n)"
      by metis
    then obtain y K where y: "y closure S" and "strict_mono (K :: nat ==> nat)" 
                      and Klim: "(z K) <---- y"
      using bounded S
      unfolding compact_closure [symmetric] compact_def by (meson closure_subset subset_iff)
    then have ftendsw: "((λn. f (z n)) K) <---- w"
      by (metis LIMSEQ_subseq_LIMSEQ fun.map_cong0 fz tendsw)
    have zKs: "n. (z K) n S" by (simp add: zs)
    have fz: "f z = ξ"  "(λn. f (z n)) = ξ"
      using fz by auto
    then have "(ξ K) <---- f y"
      by (metis (no_types) Klim zKs y contf comp_assoc continuous_on_closure_sequentially)
    with fz have wy: "w = f y" using fz LIMSEQ_unique ftendsw by auto
    have "r norm (f y - f a)"
    proof (rule le_no)
      show "y frontier S"
        using w wy oint by (force simp: imageI image_mono interiorI interior_subset frontier_def y)
    qed
    then have "y. [norm (f a - y) < r; y frontier (f ` S)] ==> False"
      by (metis dw_le norm_minus_commute not_less order_trans wy)
    then have "ball (f a) r frontier (f ` S) = {}"
      by (metis disjoint_iff_not_equal dist_norm mem_ball)
    moreover
    have "ball (f a) r f ` S {}"
      using a S 0 🚫 centre_in_ball by blast
    ultimately show ?thesis
      by (meson connected_Int_frontier connected_ball diff_shunt_var)
qed


subsubsectionSpecial characterizations of classes of functions into and out of R.

lemma Hausdorff_space_euclidean [simp]: "Hausdorff_space (euclidean :: 'a::metric_space topology)"
proof -
  have "U V. open U open V x U y V disjnt U V"
    if "x y" for x y :: 'a
  proof (intro exI conjI)
    let ?r = "dist x y / 2"
    have [simp]: "?r > 0"
      by (simp add: that)
    show "open (ball x ?r)" "open (ball y ?r)" "x (ball x ?r)" "y (ball y ?r)"
      by (auto simp add: that)
    show "disjnt (ball x ?r) (ball y ?r)"
      unfolding disjnt_def by (simp add: disjoint_ballI)
  qed
  then show ?thesis
    by (simp add: Hausdorff_space_def)
qed

proposition embedding_map_into_euclideanreal:
  assumes "path_connected_space X"
  shows "embedding_map X euclideanreal f
         continuous_map X euclideanreal f inj_on f (topspace X)"
  proof safe
  show "continuous_map X euclideanreal f"
    if "embedding_map X euclideanreal f"
    using continuous_map_in_subtopology homeomorphic_imp_continuous_map that
    unfolding embedding_map_def by blast
  show "inj_on f (topspace X)"
    if "embedding_map X euclideanreal f"
    using that homeomorphic_imp_injective_map
    unfolding embedding_map_def by blast
  show "embedding_map X euclideanreal f"
    if cont: "continuous_map X euclideanreal f" and inj: "inj_on f (topspace X)"
  proof -
    obtain g where gf: "x. x topspace X ==> g (f x) = x"
      using inv_into_f_f [OF inj] by auto
    show ?thesis
      unfolding embedding_map_def homeomorphic_map_maps homeomorphic_maps_def
    proof (intro exI conjI)
      show "continuous_map X (top_of_set (f ` topspace X)) f"
        by (simp add: cont continuous_map_in_subtopology)
      let ?S = "f ` topspace X"
      have eq: "{x ?S. g x U} = f ` U" if "openin X U" for U
        using openin_subset [OF that] by (auto simp: gf)
      have 1: "g ` ?S topspace X"
        using eq by blast
      have "openin (top_of_set ?S) {x ?S. g x T}"
        if "openin X T" for T
      proof -
        have "T topspace X"
          by (simp add: openin_subset that)
        have RR: "x ?S g -` T. d>0. x' ?S ball x d. g x' T"
        proof (clarsimp simp add: gf)
          have pcS: "path_connectedin euclidean ?S"
            using assms cont path_connectedin_continuous_map_image path_connectedin_topspace by blast
          show "d>0. x'f ` topspace X ball (f x) d. g x' T"
            if "x T" for x
          proof -
            have x: "x topspace X"
              using T topspace X x T by blast
            obtain u v d where "0 < d" "u topspace X" "v topspace X"
                         and sub_fuv: "?S {f x - d .. f x + d} {f u..f v}"
            proof (cases "u topspace X. f u < f x")
              case True
              then obtain u where u: "u topspace X" "f u < f x" ..
              show ?thesis
              proof (cases "v topspace X. f x < f v")
                case True
                then obtain v where v: "v topspace X" "f x < f v" ..
                show ?thesis
                proof
                  let ?d = "min (f x - f u) (f v - f x)"
                  show "0 < ?d"
                    by (simp add: f u 🚫 x f x 🚫 v)
                  show "f ` topspace X {f x - ?d..f x + ?d} {f u..f v}"
                    by fastforce
                qed (auto simp: u v)
              next
                case False
                show ?thesis
                proof
                  let ?d = "f x - f u"
                  show "0 < ?d"
                    by (simp add: u)
                  show "f ` topspace X {f x - ?d..f x + ?d} {f u..f x}"
                    using x u False by auto
                qed (auto simp: x u)
              qed
            next
              case False
              note no_u = False
              show ?thesis
              proof (cases "v topspace X. f x < f v")
                case True
                then obtain v where v: "v topspace X" "f x < f v" ..
                show ?thesis
                proof
                  let ?d = "f v - f x"
                  show "0 < ?d"
                    by (simp add: v)
                  show "f ` topspace X {f x - ?d..f x + ?d} {f x..f v}"
                    using False by auto
                qed (auto simp: x v)
              next
                case False
                show ?thesis
                proof
                  show "f ` topspace X {f x - 1..f x + 1} {f x..f x}"
                    using False no_u by fastforce
                qed (auto simp: x)
              qed
            qed
            then obtain h where "pathin X h" "h 0 = u" "h 1 = v"
              using assms unfolding path_connected_space_def by blast
            obtain C where "compactin X C" "connectedin X C" "u C" "v C"
            proof
              show "compactin X (h ` {0..1})"
                using that by (simp add: pathin X h compactin_path_image)
              show "connectedin X (h ` {0..1})"
                using pathin X h connectedin_path_image by blast
            qed (use h 0 = u h 1 = v in auto)
            have "continuous_map (subtopology euclideanreal (?S {f x - d .. f x + d})) (subtopology X C) g"
            proof (rule continuous_inverse_map)
              show "compact_space (subtopology X C)"
                using compactin X C compactin_subspace by blast
              show "continuous_map (subtopology X C) euclideanreal f"
                by (simp add: cont continuous_map_from_subtopology)
              have "{f u .. f v} f ` topspace (subtopology X C)"
              proof (rule connected_contains_Icc)
                show "connected (f ` topspace (subtopology X C))"
                  using connectedin_continuous_map_image [OF cont]
                  by (simp add: compactin X C connectedin X C compactin_subset_topspace inf_absorb2)
                show "f u f ` topspace (subtopology X C)"
                  by (simp add: u C u topspace X)
                show "f v f ` topspace (subtopology X C)"
                  by (simp add: v C v topspace X)
              qed
              then show "f ` topspace X {f x - d..f x + d} f ` topspace (subtopology X C)"
                using sub_fuv by blast
            qed (auto simp: gf)
            then have contg: "continuous_map (subtopology euclideanreal (?S {f x - d .. f x + d})) X g"
              using continuous_map_in_subtopology by blast
            have "e>0. x ?S {f x - d .. f x + d} ball (f x) e. g x T"
              using openin_continuous_map_preimage [OF contg openin X T] x x T 0 🚫
              unfolding openin_euclidean_subtopology_iff
              by (force simp: gf dist_commute)
            then obtain e where "e > 0 (xf ` topspace X {f x - d..f x + d} ball (f x) e. g x T)"
              by metis
            with 0 🚫 have "min d e > 0" "u. u topspace X f x - f u < min d e u T"
              using dist_real_def gf by force+
            then show ?thesis
              by (metis (full_types) Int_iff dist_real_def image_iff mem_ball gf)
          qed
        qed
        then obtain d where d: "r. r ?S g -` T ==>
                d r > 0 (x ?S ball r (d r). g x T)"
          by metis
        show ?thesis
          unfolding openin_subtopology
        proof (intro exI conjI)
          show "{x ?S. g x T} = (r ?S g -` T. ball r (d r)) f ` topspace X"
            using d by (auto simp: gf)
        qed auto
      qed
      then show "continuous_map (top_of_set ?S) X g"
        by (simp add: "1" continuous_map)
    qed (auto simp: gf)
  qed
qed

subsubsection An injective function into R is a homeomorphism and so an open map.

lemma injective_into_1d_eq_homeomorphism:
  fixes f :: "'a::topological_space ==> real"
  assumes f: "continuous_on S f" and S: "path_connected S"
  shows "inj_on f S (g. homeomorphism S (f ` S) f g)"
proof
  show "g. homeomorphism S (f ` S) f g"
    if "inj_on f S"
  proof -
    have "embedding_map (top_of_set S) euclideanreal f"
      using that embedding_map_into_euclideanreal [of "top_of_set S" f] assms by auto
    then show ?thesis
      unfolding embedding_map_def topspace_euclidean_subtopology
      by (metis f homeomorphic_map_closedness_eq homeomorphism_injective_closed_map that)
  qed
qed (metis homeomorphism_def inj_onI)

lemma injective_into_1d_imp_open_map:
  fixes f :: "'a::topological_space ==> real"
  assumes "continuous_on S f" "path_connected S" "inj_on f S" "openin (subtopology euclidean S) T"
  shows "openin (subtopology euclidean (f ` S)) (f ` T)"
  using assms homeomorphism_imp_open_map injective_into_1d_eq_homeomorphism by blast

lemma homeomorphism_into_1d:
  fixes f :: "'a::topological_space ==> real"
  assumes "path_connected S" "continuous_on S f" "f ` S = T" "inj_on f S"
  shows "g. homeomorphism S T f g"
  using assms injective_into_1d_eq_homeomorphism by blast

subsection🍋tag unimportant Rectangular paths

definition🍋tag unimportant rectpath where
  "rectpath a1 a3 = (let a2 = Complex (Re a3) (Im a1); a4 = Complex (Re a1) (Im a3)
                      in linepath a1 a2 +++ linepath a2 a3 +++ linepath a3 a4 +++ linepath a4 a1)"

lemma path_rectpath [simp, intro]: "path (rectpath a b)"
  by (simp add: Let_def rectpath_def)

lemma pathstart_rectpath [simp]: "pathstart (rectpath a1 a3) = a1"
  by (simp add: rectpath_def Let_def)

lemma pathfinish_rectpath [simp]: "pathfinish (rectpath a1 a3) = a1"
  by (simp add: rectpath_def Let_def)

lemma simple_path_rectpath [simp, intro]:
  assumes "Re a1 Re a3" "Im a1 Im a3"
  shows   "simple_path (rectpath a1 a3)"
  unfolding rectpath_def Let_def using assms
  by (intro simple_path_join_loop arc_join arc_linepath)
     (auto simp: complex_eq_iff path_image_join closed_segment_same_Re closed_segment_same_Im)

lemma path_image_rectpath:
  assumes "Re a1 Re a3" "Im a1 Im a3"
  shows "path_image (rectpath a1 a3) =
           {z. Re z {Re a1, Re a3} Im z {Im a1..Im a3}}
           {z. Im z {Im a1, Im a3} Re z {Re a1..Re a3}}" (is "?lhs = ?rhs")
proof -
  define a2 a4 where "a2 = Complex (Re a3) (Im a1)" and "a4 = Complex (Re a1) (Im a3)"
  have "?lhs = closed_segment a1 a2 closed_segment a2 a3
                  closed_segment a4 a3 closed_segment a1 a4"
    by (simp_all add: rectpath_def Let_def path_image_join closed_segment_commute
                      a2_def a4_def Un_assoc)
  also have " = ?rhs" using assms
    by (auto simp: rectpath_def Let_def path_image_join a2_def a4_def
          closed_segment_same_Re closed_segment_same_Im closed_segment_eq_real_ivl)
  finally show ?thesis .
qed

lemma path_image_rectpath_subset_cbox:
  assumes "Re a Re b" "Im a Im b"
  shows   "path_image (rectpath a b) cbox a b"
  using assms by (auto simp: path_image_rectpath in_cbox_complex_iff)

lemma path_image_rectpath_inter_box:
  assumes "Re a Re b" "Im a Im b"
  shows   "path_image (rectpath a b) box a b = {}"
  using assms by (auto simp: path_image_rectpath in_box_complex_iff)

lemma path_image_rectpath_cbox_minus_box:
  assumes "Re a Re b" "Im a Im b"
  shows   "path_image (rectpath a b) = cbox a b - box a b"
  using assms by (auto simp: path_image_rectpath in_cbox_complex_iff in_box_complex_iff)

end

Messung V0.5 in Prozent
C=95 H=86 G=90

¤ Dauer der Verarbeitung: 0.181 Sekunden  (vorverarbeitet am  2026-05-03) ¤

*© 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.