src/HOL/Analysis/Homotopy.thy
changeset 71745 ad84f8a712b4
parent 71633 07bec530f02e
child 71746 da0e18db1517
equal deleted inserted replaced
71744:63eb6b3ebcfc 71745:ad84f8a712b4
     9 begin
     9 begin
    10 
    10 
    11 definition\<^marker>\<open>tag important\<close> homotopic_with
    11 definition\<^marker>\<open>tag important\<close> homotopic_with
    12 where
    12 where
    13  "homotopic_with P X Y f g \<equiv>
    13  "homotopic_with P X Y f g \<equiv>
    14    (\<exists>h. continuous_map (prod_topology (subtopology euclideanreal {0..1}) X) Y h \<and>
    14    (\<exists>h. continuous_map (prod_topology (top_of_set {0..1::real}) X) Y h \<and>
    15        (\<forall>x. h(0, x) = f x) \<and>
    15        (\<forall>x. h(0, x) = f x) \<and>
    16        (\<forall>x. h(1, x) = g x) \<and>
    16        (\<forall>x. h(1, x) = g x) \<and>
    17        (\<forall>t \<in> {0..1}. P(\<lambda>x. h(t,x))))"
    17        (\<forall>t \<in> {0..1}. P(\<lambda>x. h(t,x))))"
    18 
    18 
    19 text\<open>\<open>p\<close>, \<open>q\<close> are functions \<open>X \<rightarrow> Y\<close>, and the property \<open>P\<close> restricts all intermediate maps.
    19 text\<open>\<open>p\<close>, \<open>q\<close> are functions \<open>X \<rightarrow> Y\<close>, and the property \<open>P\<close> restricts all intermediate maps.
    44   by (fast intro: continuous_intros elim!: continuous_on_subset)
    44   by (fast intro: continuous_intros elim!: continuous_on_subset)
    45 
    45 
    46 lemma continuous_map_o_Pair: 
    46 lemma continuous_map_o_Pair: 
    47   assumes h: "continuous_map (prod_topology X Y) Z h" and t: "t \<in> topspace X"
    47   assumes h: "continuous_map (prod_topology X Y) Z h" and t: "t \<in> topspace X"
    48   shows "continuous_map Y Z (h \<circ> Pair t)"
    48   shows "continuous_map Y Z (h \<circ> Pair t)"
    49   apply (intro continuous_map_compose [OF _ h] continuous_map_id [unfolded id_def] continuous_intros)
    49   by (intro continuous_map_compose [OF _ h] continuous_intros; simp add: t)
    50   apply (simp add: t)
       
    51   done
       
    52 
    50 
    53 subsection\<^marker>\<open>tag unimportant\<close>\<open>Trivial properties\<close>
    51 subsection\<^marker>\<open>tag unimportant\<close>\<open>Trivial properties\<close>
    54 
    52 
    55 text \<open>We often want to just localize the ending function equality or whatever.\<close>
    53 text \<open>We often want to just localize the ending function equality or whatever.\<close>
    56 text\<^marker>\<open>tag important\<close> \<open>%whitespace\<close>
    54 text\<^marker>\<open>tag important\<close> \<open>%whitespace\<close>
    72 
    70 
    73 lemma homotopic_with_mono:
    71 lemma homotopic_with_mono:
    74   assumes hom: "homotopic_with P X Y f g"
    72   assumes hom: "homotopic_with P X Y f g"
    75     and Q: "\<And>h. \<lbrakk>continuous_map X Y h; P h\<rbrakk> \<Longrightarrow> Q h"
    73     and Q: "\<And>h. \<lbrakk>continuous_map X Y h; P h\<rbrakk> \<Longrightarrow> Q h"
    76   shows "homotopic_with Q X Y f g"
    74   shows "homotopic_with Q X Y f g"
    77   using hom
    75   using hom unfolding homotopic_with_def
    78   apply (simp add: homotopic_with_def)
    76   by (force simp: o_def dest: continuous_map_o_Pair intro: Q)
    79   apply (erule ex_forward)
       
    80   apply (force simp: o_def dest: continuous_map_o_Pair intro: Q)
       
    81   done
       
    82 
    77 
    83 lemma homotopic_with_imp_continuous_maps:
    78 lemma homotopic_with_imp_continuous_maps:
    84     assumes "homotopic_with P X Y f g"
    79     assumes "homotopic_with P X Y f g"
    85     shows "continuous_map X Y f \<and> continuous_map X Y g"
    80     shows "continuous_map X Y f \<and> continuous_map X Y g"
    86 proof -
    81 proof -
    87   obtain h
    82   obtain h :: "real \<times> 'a \<Rightarrow> 'b"
    88     where conth: "continuous_map (prod_topology (subtopology euclideanreal {0..1}) X) Y h"
    83     where conth: "continuous_map (prod_topology (top_of_set {0..1}) X) Y h"
    89       and h: "\<forall>x. h (0, x) = f x" "\<forall>x. h (1, x) = g x"
    84       and h: "\<forall>x. h (0, x) = f x" "\<forall>x. h (1, x) = g x"
    90     using assms by (auto simp: homotopic_with_def)
    85     using assms by (auto simp: homotopic_with_def)
    91   have *: "t \<in> {0..1} \<Longrightarrow> continuous_map X Y (h \<circ> (\<lambda>x. (t,x)))" for t
    86   have *: "t \<in> {0..1} \<Longrightarrow> continuous_map X Y (h \<circ> (\<lambda>x. (t,x)))" for t
    92     by (rule continuous_map_compose [OF _ conth]) (simp add: o_def continuous_map_pairwise)
    87     by (rule continuous_map_compose [OF _ conth]) (simp add: o_def continuous_map_pairwise)
    93   show ?thesis
    88   show ?thesis
   113   assumes "P f" "P g" and contf: "continuous_map X Y f" and fg: "\<And>x. x \<in> topspace X \<Longrightarrow> f x = g x"
   108   assumes "P f" "P g" and contf: "continuous_map X Y f" and fg: "\<And>x. x \<in> topspace X \<Longrightarrow> f x = g x"
   114   shows "homotopic_with P X Y f g"
   109   shows "homotopic_with P X Y f g"
   115   unfolding homotopic_with_def
   110   unfolding homotopic_with_def
   116 proof (intro exI conjI allI ballI)
   111 proof (intro exI conjI allI ballI)
   117   let ?h = "\<lambda>(t::real,x). if t = 1 then g x else f x"
   112   let ?h = "\<lambda>(t::real,x). if t = 1 then g x else f x"
   118   show "continuous_map (prod_topology (subtopology euclideanreal {0..1}) X) Y ?h"
   113   show "continuous_map (prod_topology (top_of_set {0..1}) X) Y ?h"
   119   proof (rule continuous_map_eq)
   114   proof (rule continuous_map_eq)
   120     show "continuous_map (prod_topology (subtopology euclideanreal {0..1}) X) Y (f \<circ> snd)"
   115     show "continuous_map (prod_topology (top_of_set {0..1}) X) Y (f \<circ> snd)"
   121       by (simp add: contf continuous_map_of_snd)
   116       by (simp add: contf continuous_map_of_snd)
   122   qed (auto simp: fg)
   117   qed (auto simp: fg)
   123   show "P (\<lambda>x. ?h (t, x))" if "t \<in> {0..1}" for t
   118   show "P (\<lambda>x. ?h (t, x))" if "t \<in> {0..1}" for t
   124     by (cases "t = 1") (simp_all add: assms)
   119     by (cases "t = 1") (simp_all add: assms)
   125 qed auto
   120 qed auto
   132      "homotopic_with_canon P X Y f g \<Longrightarrow> g ` X \<subseteq> Y"
   127      "homotopic_with_canon P X Y f g \<Longrightarrow> g ` X \<subseteq> Y"
   133   by (simp add: homotopic_with_def image_subset_iff) (metis atLeastAtMost_iff order_refl zero_le_one)
   128   by (simp add: homotopic_with_def image_subset_iff) (metis atLeastAtMost_iff order_refl zero_le_one)
   134 
   129 
   135 lemma homotopic_with_subset_left:
   130 lemma homotopic_with_subset_left:
   136      "\<lbrakk>homotopic_with_canon P X Y f g; Z \<subseteq> X\<rbrakk> \<Longrightarrow> homotopic_with_canon P Z Y f g"
   131      "\<lbrakk>homotopic_with_canon P X Y f g; Z \<subseteq> X\<rbrakk> \<Longrightarrow> homotopic_with_canon P Z Y f g"
   137   apply (simp add: homotopic_with_def)
   132   unfolding homotopic_with_def by (auto elim!: continuous_on_subset ex_forward)
   138   apply (fast elim!: continuous_on_subset ex_forward)
       
   139   done
       
   140 
   133 
   141 lemma homotopic_with_subset_right:
   134 lemma homotopic_with_subset_right:
   142      "\<lbrakk>homotopic_with_canon P X Y f g; Y \<subseteq> Z\<rbrakk> \<Longrightarrow> homotopic_with_canon P X Z f g"
   135      "\<lbrakk>homotopic_with_canon P X Y f g; Y \<subseteq> Z\<rbrakk> \<Longrightarrow> homotopic_with_canon P X Z f g"
   143   apply (simp add: homotopic_with_def)
   136   unfolding homotopic_with_def by (auto elim!: continuous_on_subset ex_forward)
   144   apply (fast elim!: continuous_on_subset ex_forward)
       
   145   done
       
   146 
   137 
   147 subsection\<open>Homotopy with P is an equivalence relation\<close>
   138 subsection\<open>Homotopy with P is an equivalence relation\<close>
   148 
   139 
   149 text \<open>(on continuous functions mapping X into Y that satisfy P, though this only affects reflexivity)\<close>
   140 text \<open>(on continuous functions mapping X into Y that satisfy P, though this only affects reflexivity)\<close>
   150 
   141 
   156       shows "homotopic_with P X Y g f"
   147       shows "homotopic_with P X Y g f"
   157 proof -
   148 proof -
   158   let ?I01 = "subtopology euclideanreal {0..1}"
   149   let ?I01 = "subtopology euclideanreal {0..1}"
   159   let ?j = "\<lambda>y. (1 - fst y, snd y)"
   150   let ?j = "\<lambda>y. (1 - fst y, snd y)"
   160   have 1: "continuous_map (prod_topology ?I01 X) (prod_topology euclideanreal X) ?j"
   151   have 1: "continuous_map (prod_topology ?I01 X) (prod_topology euclideanreal X) ?j"
   161     apply (intro continuous_intros)
   152     by (intro continuous_intros; simp add: continuous_map_subtopology_fst prod_topology_subtopology)
   162     apply (simp_all add: prod_topology_subtopology continuous_map_from_subtopology [OF continuous_map_fst])
       
   163     done
       
   164   have *: "continuous_map (prod_topology ?I01 X) (prod_topology ?I01 X) ?j"
   153   have *: "continuous_map (prod_topology ?I01 X) (prod_topology ?I01 X) ?j"
   165   proof -
   154   proof -
   166     have "continuous_map (prod_topology ?I01 X) (subtopology (prod_topology euclideanreal X) ({0..1} \<times> topspace X)) ?j"
   155     have "continuous_map (prod_topology ?I01 X) (subtopology (prod_topology euclideanreal X) ({0..1} \<times> topspace X)) ?j"
   167       by (simp add: continuous_map_into_subtopology [OF 1] image_subset_iff)
   156       by (simp add: continuous_map_into_subtopology [OF 1] image_subset_iff)
   168     then show ?thesis
   157     then show ?thesis
   169       by (simp add: prod_topology_subtopology(1))
   158       by (simp add: prod_topology_subtopology(1))
   170   qed
   159   qed
   171   show ?thesis
   160   show ?thesis
   172     using assms
   161     using assms
   173     apply (clarsimp simp add: homotopic_with_def)
   162     apply (clarsimp simp add: homotopic_with_def)
   174     apply (rename_tac h)
   163     subgoal for h
   175     apply (rule_tac x="h \<circ> (\<lambda>y. (1 - fst y, snd y))" in exI)
   164       by (rule_tac x="h \<circ> (\<lambda>y. (1 - fst y, snd y))" in exI) (simp add: continuous_map_compose [OF *])
   176     apply (simp add: continuous_map_compose [OF *])
       
   177     done
   165     done
   178 qed
   166 qed
   179 
   167 
   180 lemma homotopic_with_sym:
   168 lemma homotopic_with_sym:
   181    "homotopic_with P X Y f g \<longleftrightarrow> homotopic_with P X Y g f"
   169    "homotopic_with P X Y f g \<longleftrightarrow> homotopic_with P X Y g f"
   207         using continuous_map_fst continuous_map_in_subtopology by blast
   195         using continuous_map_fst continuous_map_in_subtopology by blast
   208       show "continuous_map ?X01 euclideanreal (\<lambda>x. 1/2)"
   196       show "continuous_map ?X01 euclideanreal (\<lambda>x. 1/2)"
   209         by simp
   197         by simp
   210       show "continuous_map (subtopology ?X01 {y \<in> topspace ?X01. fst y \<le> 1/2}) Y
   198       show "continuous_map (subtopology ?X01 {y \<in> topspace ?X01. fst y \<le> 1/2}) Y
   211                (k1 \<circ> (\<lambda>x. (2 *\<^sub>R fst x, snd x)))"
   199                (k1 \<circ> (\<lambda>x. (2 *\<^sub>R fst x, snd x)))"
   212         apply (rule fst continuous_map_compose [OF _ contk1] continuous_intros continuous_map_into_subtopology | simp)+
   200         apply (intro fst continuous_map_compose [OF _ contk1] continuous_intros continuous_map_into_subtopology fst continuous_map_from_subtopology | simp)+
   213           apply (intro continuous_intros fst continuous_map_from_subtopology)
   201         by (force simp: prod_topology_subtopology)
   214          apply (force simp: prod_topology_subtopology)
       
   215         using continuous_map_snd continuous_map_from_subtopology by blast
       
   216       show "continuous_map (subtopology ?X01 {y \<in> topspace ?X01. 1/2 \<le> fst y}) Y
   202       show "continuous_map (subtopology ?X01 {y \<in> topspace ?X01. 1/2 \<le> fst y}) Y
   217                (k2 \<circ> (\<lambda>x. (2 *\<^sub>R fst x -1, snd x)))"
   203                (k2 \<circ> (\<lambda>x. (2 *\<^sub>R fst x -1, snd x)))"
   218         apply (rule fst continuous_map_compose [OF _ contk2] continuous_intros continuous_map_into_subtopology | simp)+
   204         apply (intro fst continuous_map_compose [OF _ contk2] continuous_intros continuous_map_into_subtopology fst continuous_map_from_subtopology | simp)+
   219           apply (rule continuous_intros fst continuous_map_from_subtopology | simp)+
   205         by (force simp: prod_topology_subtopology)
   220          apply (force simp: prod_topology_subtopology)
       
   221         using continuous_map_snd  continuous_map_from_subtopology by blast
       
   222       show "(k1 \<circ> (\<lambda>x. (2 *\<^sub>R fst x, snd x))) y = (k2 \<circ> (\<lambda>x. (2 *\<^sub>R fst x -1, snd x))) y"
   206       show "(k1 \<circ> (\<lambda>x. (2 *\<^sub>R fst x, snd x))) y = (k2 \<circ> (\<lambda>x. (2 *\<^sub>R fst x -1, snd x))) y"
   223         if "y \<in> topspace ?X01" and "fst y = 1/2" for y
   207         if "y \<in> topspace ?X01" and "fst y = 1/2" for y
   224         using that by (simp add: keq)
   208         using that by (simp add: keq)
   225     qed
   209     qed
   226     show "\<forall>x. k (0, x) = f x"
   210     show "\<forall>x. k (0, x) = f x"
   227       by (simp add: k12 k_def)
   211       by (simp add: k12 k_def)
   228     show "\<forall>x. k (1, x) = h x"
   212     show "\<forall>x. k (1, x) = h x"
   229       by (simp add: k12 k_def)
   213       by (simp add: k12 k_def)
   230     show "\<forall>t\<in>{0..1}. P (\<lambda>x. k (t, x))"
   214     show "\<forall>t\<in>{0..1}. P (\<lambda>x. k (t, x))"
   231       using P
   215     proof 
   232       apply (clarsimp simp add: k_def)
   216       fix t show "t\<in>{0..1} \<Longrightarrow> P (\<lambda>x. k (t, x))"
   233       apply (case_tac "t \<le> 1/2", auto)
   217         by (cases "t \<le> 1/2") (auto simp add: k_def P)
   234       done
   218     qed
   235   qed
   219   qed
   236 qed
   220 qed
   237 
   221 
   238 lemma homotopic_with_id2: 
   222 lemma homotopic_with_id2: 
   239   "(\<And>x. x \<in> topspace X \<Longrightarrow> g (f x) = x) \<Longrightarrow> homotopic_with (\<lambda>x. True) X X (g \<circ> f) id"
   223   "(\<And>x. x \<in> topspace X \<Longrightarrow> g (f x) = x) \<Longrightarrow> homotopic_with (\<lambda>x. True) X X (g \<circ> f) id"
   244 lemma homotopic_with_compose_continuous_map_left:
   228 lemma homotopic_with_compose_continuous_map_left:
   245   "\<lbrakk>homotopic_with p X1 X2 f g; continuous_map X2 X3 h; \<And>j. p j \<Longrightarrow> q(h \<circ> j)\<rbrakk>
   229   "\<lbrakk>homotopic_with p X1 X2 f g; continuous_map X2 X3 h; \<And>j. p j \<Longrightarrow> q(h \<circ> j)\<rbrakk>
   246    \<Longrightarrow> homotopic_with q X1 X3 (h \<circ> f) (h \<circ> g)"
   230    \<Longrightarrow> homotopic_with q X1 X3 (h \<circ> f) (h \<circ> g)"
   247   unfolding homotopic_with_def
   231   unfolding homotopic_with_def
   248   apply clarify
   232   apply clarify
   249   apply (rename_tac k)
   233   subgoal for k
   250   apply (rule_tac x="h \<circ> k" in exI)
   234     by (rule_tac x="h \<circ> k" in exI) (rule conjI continuous_map_compose | simp add: o_def)+
   251   apply (rule conjI continuous_map_compose | simp add: o_def)+
       
   252   done
   235   done
   253 
       
   254 lemma homotopic_compose_continuous_map_left:
       
   255    "\<lbrakk>homotopic_with (\<lambda>k. True) X1 X2 f g; continuous_map X2 X3 h\<rbrakk>
       
   256         \<Longrightarrow> homotopic_with (\<lambda>k. True) X1 X3 (h \<circ> f) (h \<circ> g)"
       
   257   by (simp add: homotopic_with_compose_continuous_map_left)
       
   258 
   236 
   259 lemma homotopic_with_compose_continuous_map_right:
   237 lemma homotopic_with_compose_continuous_map_right:
   260   assumes hom: "homotopic_with p X2 X3 f g" and conth: "continuous_map X1 X2 h"
   238   assumes hom: "homotopic_with p X2 X3 f g" and conth: "continuous_map X1 X2 h"
   261     and q: "\<And>j. p j \<Longrightarrow> q(j \<circ> h)"
   239     and q: "\<And>j. p j \<Longrightarrow> q(j \<circ> h)"
   262   shows "homotopic_with q X1 X3 (f \<circ> h) (g \<circ> h)"
   240   shows "homotopic_with q X1 X3 (f \<circ> h) (g \<circ> h)"
   279     show "q (\<lambda>x. ?h (t, x))" if "t \<in> {0..1}" for t
   257     show "q (\<lambda>x. ?h (t, x))" if "t \<in> {0..1}" for t
   280       using q [OF p [OF that]] by (simp add: o_def)
   258       using q [OF p [OF that]] by (simp add: o_def)
   281   qed (auto simp: k)
   259   qed (auto simp: k)
   282 qed
   260 qed
   283 
   261 
   284 lemma homotopic_compose_continuous_map_right:
       
   285    "\<lbrakk>homotopic_with (\<lambda>k. True) X2 X3 f g; continuous_map X1 X2 h\<rbrakk>
       
   286         \<Longrightarrow> homotopic_with (\<lambda>k. True) X1 X3 (f \<circ> h) (g \<circ> h)"
       
   287   by (meson homotopic_with_compose_continuous_map_right)
       
   288 
       
   289 corollary homotopic_compose:
   262 corollary homotopic_compose:
   290       shows "\<lbrakk>homotopic_with (\<lambda>x. True) X Y f f'; homotopic_with (\<lambda>x. True) Y Z g g'\<rbrakk>
   263   assumes "homotopic_with (\<lambda>x. True) X Y f f'" "homotopic_with (\<lambda>x. True) Y Z g g'"
   291              \<Longrightarrow> homotopic_with (\<lambda>x. True) X Z (g \<circ> f) (g' \<circ> f')"
   264   shows "homotopic_with (\<lambda>x. True) X Z (g \<circ> f) (g' \<circ> f')"
   292   apply (rule homotopic_with_trans [where g = "g \<circ> f'"])
   265 proof (rule homotopic_with_trans [where g = "g \<circ> f'"])
   293   apply (simp add: homotopic_compose_continuous_map_left homotopic_with_imp_continuous_maps)
   266   show "homotopic_with (\<lambda>x. True) X Z (g \<circ> f) (g \<circ> f')"
   294   by (simp add: homotopic_compose_continuous_map_right homotopic_with_imp_continuous_maps)
   267     using assms by (simp add: homotopic_with_compose_continuous_map_left homotopic_with_imp_continuous_maps)
   295 
   268   show "homotopic_with (\<lambda>x. True) X Z (g \<circ> f') (g' \<circ> f')"
   296 
   269     using assms by (simp add: homotopic_with_compose_continuous_map_right homotopic_with_imp_continuous_maps)
       
   270 qed
   297 
   271 
   298 proposition homotopic_with_compose_continuous_right:
   272 proposition homotopic_with_compose_continuous_right:
   299     "\<lbrakk>homotopic_with_canon (\<lambda>f. p (f \<circ> h)) X Y f g; continuous_on W h; h ` W \<subseteq> X\<rbrakk>
   273     "\<lbrakk>homotopic_with_canon (\<lambda>f. p (f \<circ> h)) X Y f g; continuous_on W h; h ` W \<subseteq> X\<rbrakk>
   300      \<Longrightarrow> homotopic_with_canon p W Y (f \<circ> h) (g \<circ> h)"
   274      \<Longrightarrow> homotopic_with_canon p W Y (f \<circ> h) (g \<circ> h)"
   301   apply (clarsimp simp add: homotopic_with_def)
   275   apply (clarsimp simp add: homotopic_with_def)
   302   apply (rename_tac k)
   276   apply (rename_tac k)
   303   apply (rule_tac x="k \<circ> (\<lambda>y. (fst y, h (snd y)))" in exI)
   277   apply (rule_tac x="k \<circ> (\<lambda>y. (fst y, h (snd y)))" in exI)
   304   apply (rule conjI continuous_intros continuous_on_compose [where f=snd and g=h, unfolded o_def] | simp)+
   278   apply (rule conjI continuous_intros continuous_on_compose2 [where f=snd and g=h] | simp)+
   305   apply (erule continuous_on_subset)
   279   apply (fastforce simp: o_def elim: continuous_on_subset)+
   306   apply (fastforce simp: o_def)+
       
   307   done
   280   done
   308 
       
   309 proposition homotopic_compose_continuous_right:
       
   310      "\<lbrakk>homotopic_with_canon (\<lambda>f. True) X Y f g; continuous_on W h; h ` W \<subseteq> X\<rbrakk>
       
   311       \<Longrightarrow> homotopic_with_canon (\<lambda>f. True) W Y (f \<circ> h) (g \<circ> h)"
       
   312   using homotopic_with_compose_continuous_right by fastforce
       
   313 
   281 
   314 proposition homotopic_with_compose_continuous_left:
   282 proposition homotopic_with_compose_continuous_left:
   315      "\<lbrakk>homotopic_with_canon (\<lambda>f. p (h \<circ> f)) X Y f g; continuous_on Y h; h ` Y \<subseteq> Z\<rbrakk>
   283      "\<lbrakk>homotopic_with_canon (\<lambda>f. p (h \<circ> f)) X Y f g; continuous_on Y h; h ` Y \<subseteq> Z\<rbrakk>
   316       \<Longrightarrow> homotopic_with_canon p X Z (h \<circ> f) (h \<circ> g)"
   284       \<Longrightarrow> homotopic_with_canon p X Z (h \<circ> f) (h \<circ> g)"
   317   apply (clarsimp simp add: homotopic_with_def)
   285   apply (clarsimp simp add: homotopic_with_def)
   318   apply (rename_tac k)
   286   apply (rename_tac k)
   319   apply (rule_tac x="h \<circ> k" in exI)
   287   apply (rule_tac x="h \<circ> k" in exI)
   320   apply (rule conjI continuous_intros continuous_on_compose [where f=snd and g=h, unfolded o_def] | simp)+
   288   apply (rule conjI continuous_intros continuous_on_compose [where f=snd and g=h, unfolded o_def] | simp)+
   321   apply (erule continuous_on_subset)
   289   apply (fastforce simp: o_def elim: continuous_on_subset)+
   322   apply (fastforce simp: o_def)+
       
   323   done
   290   done
   324 
       
   325 proposition homotopic_compose_continuous_left:
       
   326    "\<lbrakk>homotopic_with_canon (\<lambda>_. True) X Y f g;
       
   327      continuous_on Y h; h ` Y \<subseteq> Z\<rbrakk>
       
   328     \<Longrightarrow> homotopic_with_canon (\<lambda>f. True) X Z (h \<circ> f) (h \<circ> g)"
       
   329   using homotopic_with_compose_continuous_left by fastforce
       
   330 
   291 
   331 lemma homotopic_from_subtopology:
   292 lemma homotopic_from_subtopology:
   332    "homotopic_with P X X' f g \<Longrightarrow> homotopic_with P (subtopology X s) X' f g"
   293    "homotopic_with P X X' f g \<Longrightarrow> homotopic_with P (subtopology X s) X' f g"
   333   unfolding homotopic_with_def
   294   unfolding homotopic_with_def
   334   apply (erule ex_forward)
   295   by (force simp add: continuous_map_from_subtopology prod_topology_subtopology(2) elim!: ex_forward)
   335   by (simp add: continuous_map_from_subtopology prod_topology_subtopology(2))
       
   336 
   296 
   337 lemma homotopic_on_emptyI:
   297 lemma homotopic_on_emptyI:
   338     assumes "topspace X = {}" "P f" "P g"
   298     assumes "topspace X = {}" "P f" "P g"
   339     shows "homotopic_with P X X' f g"
   299     shows "homotopic_with P X X' f g"
   340   unfolding homotopic_with_def
   300   unfolding homotopic_with_def
   363     obtain h :: "real \<times> 'a \<Rightarrow> 'b"
   323     obtain h :: "real \<times> 'a \<Rightarrow> 'b"
   364       where conth: "continuous_map (prod_topology (top_of_set {0..1}) X) X' h"
   324       where conth: "continuous_map (prod_topology (top_of_set {0..1}) X) X' h"
   365         and h: "\<And>x. h (0, x) = a" "\<And>x. h (1, x) = b"
   325         and h: "\<And>x. h (0, x) = a" "\<And>x. h (1, x) = b"
   366       using hom by (auto simp: homotopic_with_def)
   326       using hom by (auto simp: homotopic_with_def)
   367     have cont: "continuous_map (top_of_set {0..1}) X' (h \<circ> (\<lambda>t. (t, c)))"
   327     have cont: "continuous_map (top_of_set {0..1}) X' (h \<circ> (\<lambda>t. (t, c)))"
   368       apply (rule continuous_map_compose [OF _ conth])
   328       by (rule continuous_map_compose [OF _ conth] continuous_intros c | simp)+
   369       apply (rule continuous_intros c | simp)+
       
   370       done
       
   371     then show ?thesis
   329     then show ?thesis
   372       by (force simp: h)
   330       by (force simp: h)
   373   qed
   331   qed
   374   moreover have "homotopic_with (\<lambda>x. True) X X' (\<lambda>x. g 0) (\<lambda>x. g 1)"
   332   moreover have "homotopic_with (\<lambda>x. True) X X' (\<lambda>x. g 0) (\<lambda>x. g 1)"
   375     if "x \<in> topspace X" "a = g 0" "b = g 1" "continuous_map (top_of_set {0..1}) X' g"
   333     if "x \<in> topspace X" "a = g 0" "b = g 1" "continuous_map (top_of_set {0..1}) X' g"
   447     unfolding homotopic_with_def
   405     unfolding homotopic_with_def
   448   proof (intro conjI allI exI)
   406   proof (intro conjI allI exI)
   449     let ?h = "\<lambda>(t,z). \<lambda>i\<in>I. h i (t,z i)"
   407     let ?h = "\<lambda>(t,z). \<lambda>i\<in>I. h i (t,z i)"
   450     have "continuous_map (prod_topology (subtopology euclideanreal {0..1}) (product_topology X I))
   408     have "continuous_map (prod_topology (subtopology euclideanreal {0..1}) (product_topology X I))
   451                          (Y i) (\<lambda>x. h i (fst x, snd x i))" if "i \<in> I" for i
   409                          (Y i) (\<lambda>x. h i (fst x, snd x i))" if "i \<in> I" for i
   452       unfolding continuous_map_pairwise case_prod_unfold
   410     proof -
   453       apply (intro conjI that  continuous_intros continuous_map_compose [OF _ h, unfolded o_def])
   411       have \<section>: "continuous_map (prod_topology (top_of_set {0..1}) (product_topology X I)) (X i) (\<lambda>x. snd x i)"
   454       using continuous_map_componentwise continuous_map_snd that apply fastforce
   412         using continuous_map_componentwise continuous_map_snd that by fastforce
   455       done
   413       show ?thesis
       
   414         unfolding continuous_map_pairwise case_prod_unfold
       
   415         by (intro conjI that \<section> continuous_intros continuous_map_compose [OF _ h, unfolded o_def])
       
   416     qed
   456     then show "continuous_map (prod_topology (subtopology euclideanreal {0..1}) (product_topology X I))
   417     then show "continuous_map (prod_topology (subtopology euclideanreal {0..1}) (product_topology X I))
   457          (product_topology Y I) ?h"
   418          (product_topology Y I) ?h"
   458       by (auto simp: continuous_map_componentwise case_prod_beta)
   419       by (auto simp: continuous_map_componentwise case_prod_beta)
   459     show "?h (0, x) = (\<lambda>i\<in>I. f i (x i))" "?h (1, x) = (\<lambda>i\<in>I. g i (x i))" for x
   420     show "?h (0, x) = (\<lambda>i\<in>I. f i (x i))" "?h (1, x) = (\<lambda>i\<in>I. g i (x i))" for x
   460       by (auto simp: case_prod_beta h0 h1)
   421       by (auto simp: case_prod_beta h0 h1)
   568     using assms homotopic_paths_def homotopic_with_trans by blast
   529     using assms homotopic_paths_def homotopic_with_trans by blast
   569 qed
   530 qed
   570 
   531 
   571 proposition homotopic_paths_eq:
   532 proposition homotopic_paths_eq:
   572      "\<lbrakk>path p; path_image p \<subseteq> s; \<And>t. t \<in> {0..1} \<Longrightarrow> p t = q t\<rbrakk> \<Longrightarrow> homotopic_paths s p q"
   533      "\<lbrakk>path p; path_image p \<subseteq> s; \<And>t. t \<in> {0..1} \<Longrightarrow> p t = q t\<rbrakk> \<Longrightarrow> homotopic_paths s p q"
   573   apply (simp add: homotopic_paths_def)
   534   unfolding homotopic_paths_def
   574   apply (rule homotopic_with_eq)
   535   by (rule homotopic_with_eq)
   575   apply (auto simp: path_def pathstart_def pathfinish_def path_image_def elim: continuous_on_eq)
   536      (auto simp: path_def pathstart_def pathfinish_def path_image_def elim: continuous_on_eq)
   576   done
       
   577 
   537 
   578 proposition homotopic_paths_reparametrize:
   538 proposition homotopic_paths_reparametrize:
   579   assumes "path p"
   539   assumes "path p"
   580       and pips: "path_image p \<subseteq> s"
   540       and pips: "path_image p \<subseteq> s"
   581       and contf: "continuous_on {0..1} f"
   541       and contf: "continuous_on {0..1} f"
   618 
   578 
   619 
   579 
   620 text\<open> A slightly ad-hoc but useful lemma in constructing homotopies.\<close>
   580 text\<open> A slightly ad-hoc but useful lemma in constructing homotopies.\<close>
   621 lemma homotopic_join_lemma:
   581 lemma homotopic_join_lemma:
   622   fixes q :: "[real,real] \<Rightarrow> 'a::topological_space"
   582   fixes q :: "[real,real] \<Rightarrow> 'a::topological_space"
   623   assumes p: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>y. p (fst y) (snd y))"
   583   assumes p: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>y. p (fst y) (snd y))" (is "continuous_on ?A ?p")
   624       and q: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>y. q (fst y) (snd y))"
   584       and q: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>y. q (fst y) (snd y))" (is "continuous_on ?A ?q")
   625       and pf: "\<And>t. t \<in> {0..1} \<Longrightarrow> pathfinish(p t) = pathstart(q t)"
   585       and pf: "\<And>t. t \<in> {0..1} \<Longrightarrow> pathfinish(p t) = pathstart(q t)"
   626     shows "continuous_on ({0..1} \<times> {0..1}) (\<lambda>y. (p(fst y) +++ q(fst y)) (snd y))"
   586     shows "continuous_on ({0..1} \<times> {0..1}) (\<lambda>y. (p(fst y) +++ q(fst y)) (snd y))"
   627 proof -
   587 proof -
   628   have 1: "(\<lambda>y. p (fst y) (2 * snd y)) = (\<lambda>y. p (fst y) (snd y)) \<circ> (\<lambda>y. (fst y, 2 * snd y))"
   588   have \<section>: "(\<lambda>t. p (fst t) (2 * snd t)) = ?p \<circ> (\<lambda>y. (fst y, 2 * snd y))"
   629     by (rule ext) (simp)
   589           "(\<lambda>t. q (fst t) (2 * snd t - 1)) = ?q \<circ> (\<lambda>y. (fst y, 2 * snd y - 1))"
   630   have 2: "(\<lambda>y. q (fst y) (2 * snd y - 1)) = (\<lambda>y. q (fst y) (snd y)) \<circ> (\<lambda>y. (fst y, 2 * snd y - 1))"
   590     by force+
   631     by (rule ext) (simp)
       
   632   show ?thesis
   591   show ?thesis
   633     apply (simp add: joinpaths_def)
   592     unfolding joinpaths_def
   634     apply (rule continuous_on_cases_le)
   593   proof (rule continuous_on_cases_le)
   635     apply (simp_all only: 1 2)
   594     show "continuous_on {y \<in> ?A. snd y \<le> 1/2} (\<lambda>t. p (fst t) (2 * snd t))" 
   636     apply (rule continuous_intros continuous_on_subset [OF p] continuous_on_subset [OF q] | force)+
   595          "continuous_on {y \<in> ?A. 1/2 \<le> snd y} (\<lambda>t. q (fst t) (2 * snd t - 1))"
   637     using pf
   596          "continuous_on ?A snd"
   638     apply (auto simp: mult.commute pathstart_def pathfinish_def)
   597       unfolding \<section>
   639     done
   598       by (rule continuous_intros continuous_on_subset [OF p] continuous_on_subset [OF q] | force)+
       
   599   qed (use pf in \<open>auto simp: mult.commute pathstart_def pathfinish_def\<close>)
   640 qed
   600 qed
   641 
   601 
   642 text\<open> Congruence properties of homotopy w.r.t. path-combining operations.\<close>
   602 text\<open> Congruence properties of homotopy w.r.t. path-combining operations.\<close>
   643 
   603 
   644 lemma homotopic_paths_reversepath_D:
   604 lemma homotopic_paths_reversepath_D:
   656   using homotopic_paths_reversepath_D by force
   616   using homotopic_paths_reversepath_D by force
   657 
   617 
   658 
   618 
   659 proposition homotopic_paths_join:
   619 proposition homotopic_paths_join:
   660     "\<lbrakk>homotopic_paths s p p'; homotopic_paths s q q'; pathfinish p = pathstart q\<rbrakk> \<Longrightarrow> homotopic_paths s (p +++ q) (p' +++ q')"
   620     "\<lbrakk>homotopic_paths s p p'; homotopic_paths s q q'; pathfinish p = pathstart q\<rbrakk> \<Longrightarrow> homotopic_paths s (p +++ q) (p' +++ q')"
   661   apply (simp add: homotopic_paths_def homotopic_with_def, clarify)
   621   apply (clarsimp simp add: homotopic_paths_def homotopic_with_def)
   662   apply (rename_tac k1 k2)
   622   apply (rename_tac k1 k2)
   663   apply (rule_tac x="(\<lambda>y. ((k1 \<circ> Pair (fst y)) +++ (k2 \<circ> Pair (fst y))) (snd y))" in exI)
   623   apply (rule_tac x="(\<lambda>y. ((k1 \<circ> Pair (fst y)) +++ (k2 \<circ> Pair (fst y))) (snd y))" in exI)
   664   apply (rule conjI continuous_intros homotopic_join_lemma)+
   624   apply (intro conjI continuous_intros homotopic_join_lemma; force simp: joinpaths_def pathstart_def pathfinish_def path_image_def)
   665   apply (auto simp: joinpaths_def pathstart_def pathfinish_def path_image_def)
       
   666   done
   625   done
   667 
   626 
   668 proposition homotopic_paths_continuous_image:
   627 proposition homotopic_paths_continuous_image:
   669     "\<lbrakk>homotopic_paths s f g; continuous_on s h; h ` s \<subseteq> t\<rbrakk> \<Longrightarrow> homotopic_paths t (h \<circ> f) (h \<circ> g)"
   628     "\<lbrakk>homotopic_paths s f g; continuous_on s h; h ` s \<subseteq> t\<rbrakk> \<Longrightarrow> homotopic_paths t (h \<circ> f) (h \<circ> g)"
   670   unfolding homotopic_paths_def
   629   unfolding homotopic_paths_def
   674 subsection\<open>Group properties for homotopy of paths\<close>
   633 subsection\<open>Group properties for homotopy of paths\<close>
   675 
   634 
   676 text\<^marker>\<open>tag important\<close>\<open>So taking equivalence classes under homotopy would give the fundamental group\<close>
   635 text\<^marker>\<open>tag important\<close>\<open>So taking equivalence classes under homotopy would give the fundamental group\<close>
   677 
   636 
   678 proposition homotopic_paths_rid:
   637 proposition homotopic_paths_rid:
   679     "\<lbrakk>path p; path_image p \<subseteq> s\<rbrakk> \<Longrightarrow> homotopic_paths s (p +++ linepath (pathfinish p) (pathfinish p)) p"
   638   assumes "path p" "path_image p \<subseteq> s"
   680   apply (subst homotopic_paths_sym)
   639   shows "homotopic_paths s (p +++ linepath (pathfinish p) (pathfinish p)) p"
   681   apply (rule homotopic_paths_reparametrize [where f = "\<lambda>t. if  t \<le> 1 / 2 then 2 *\<^sub>R t else 1"])
   640 proof -
   682   apply (simp_all del: le_divide_eq_numeral1)
   641   have \<section>: "continuous_on {0..1} (\<lambda>t::real. if t \<le> 1/2 then 2 *\<^sub>R t else 1)"
   683   apply (subst split_01)
   642     unfolding split_01
   684   apply (rule continuous_on_cases continuous_intros | force simp: pathfinish_def joinpaths_def)+
   643     by (rule continuous_on_cases continuous_intros | force simp: pathfinish_def joinpaths_def)+
   685   done
   644   show ?thesis
       
   645     using assms
       
   646     apply (subst homotopic_paths_sym)
       
   647      apply (rule homotopic_paths_reparametrize [where f = "\<lambda>t. if t \<le> 1/2 then 2 *\<^sub>R t else 1"])
       
   648            apply (rule \<section> continuous_on_cases continuous_intros | force simp: pathfinish_def joinpaths_def)+
       
   649     done
       
   650 qed
   686 
   651 
   687 proposition homotopic_paths_lid:
   652 proposition homotopic_paths_lid:
   688    "\<lbrakk>path p; path_image p \<subseteq> s\<rbrakk> \<Longrightarrow> homotopic_paths s (linepath (pathstart p) (pathstart p) +++ p) p"
   653    "\<lbrakk>path p; path_image p \<subseteq> s\<rbrakk> \<Longrightarrow> homotopic_paths s (linepath (pathstart p) (pathstart p) +++ p) p"
   689   using homotopic_paths_rid [of "reversepath p" s]
   654   using homotopic_paths_rid [of "reversepath p" s]
   690   by (metis homotopic_paths_reversepath path_image_reversepath path_reversepath pathfinish_linepath
   655   by (metis homotopic_paths_reversepath path_image_reversepath path_reversepath pathfinish_linepath
   694    "\<lbrakk>path p; path_image p \<subseteq> s; path q; path_image q \<subseteq> s; path r; path_image r \<subseteq> s; pathfinish p = pathstart q;
   659    "\<lbrakk>path p; path_image p \<subseteq> s; path q; path_image q \<subseteq> s; path r; path_image r \<subseteq> s; pathfinish p = pathstart q;
   695      pathfinish q = pathstart r\<rbrakk>
   660      pathfinish q = pathstart r\<rbrakk>
   696     \<Longrightarrow> homotopic_paths s (p +++ (q +++ r)) ((p +++ q) +++ r)"
   661     \<Longrightarrow> homotopic_paths s (p +++ (q +++ r)) ((p +++ q) +++ r)"
   697   apply (subst homotopic_paths_sym)
   662   apply (subst homotopic_paths_sym)
   698   apply (rule homotopic_paths_reparametrize
   663   apply (rule homotopic_paths_reparametrize
   699            [where f = "\<lambda>t. if  t \<le> 1 / 2 then inverse 2 *\<^sub>R t
   664            [where f = "\<lambda>t. if  t \<le> 1/2 then inverse 2 *\<^sub>R t
   700                            else if  t \<le> 3 / 4 then t - (1 / 4)
   665                            else if  t \<le> 3 / 4 then t - (1 / 4)
   701                            else 2 *\<^sub>R t - 1"])
   666                            else 2 *\<^sub>R t - 1"])
   702   apply (simp_all del: le_divide_eq_numeral1)
   667   apply (simp_all del: le_divide_eq_numeral1)
   703   apply (simp add: subset_path_image_join)
   668   apply (simp add: subset_path_image_join)
   704   apply (rule continuous_on_cases_1 continuous_intros)+
   669   apply (rule continuous_on_cases_1 continuous_intros | auto simp: joinpaths_def)+
   705   apply (auto simp: joinpaths_def)
       
   706   done
   670   done
   707 
   671 
   708 proposition homotopic_paths_rinv:
   672 proposition homotopic_paths_rinv:
   709   assumes "path p" "path_image p \<subseteq> s"
   673   assumes "path p" "path_image p \<subseteq> s"
   710     shows "homotopic_paths s (p +++ reversepath p) (linepath (pathstart p) (pathstart p))"
   674     shows "homotopic_paths s (p +++ reversepath p) (linepath (pathstart p) (pathstart p))"
   711 proof -
   675 proof -
   712   have "continuous_on ({0..1} \<times> {0..1}) (\<lambda>x. (subpath 0 (fst x) p +++ reversepath (subpath 0 (fst x) p)) (snd x))"
   676   have p: "continuous_on {0..1} p" 
   713     using assms
   677     using assms by (auto simp: path_def)
   714     apply (simp add: joinpaths_def subpath_def reversepath_def path_def del: le_divide_eq_numeral1)
   678   let ?A = "{0..1} \<times> {0..1}"
   715     apply (rule continuous_on_cases_le)
   679   have "continuous_on ?A (\<lambda>x. (subpath 0 (fst x) p +++ reversepath (subpath 0 (fst x) p)) (snd x))"
   716     apply (rule_tac [2] continuous_on_compose [of _ _ p, unfolded o_def])
   680     unfolding joinpaths_def subpath_def reversepath_def path_def add_0_right diff_0_right
   717     apply (rule continuous_on_compose [of _ _ p, unfolded o_def])
   681   proof (rule continuous_on_cases_le)
   718     apply (auto intro!: continuous_intros simp del: eq_divide_eq_numeral1)
   682     show "continuous_on {x \<in> ?A. snd x \<le> 1/2} (\<lambda>t. p (fst t * (2 * snd t)))"
   719     apply (force elim!: continuous_on_subset simp add: mult_le_one)+
   683          "continuous_on {x \<in> ?A. 1/2 \<le> snd x} (\<lambda>t. p (fst t * (1 - (2 * snd t - 1))))"
   720     done
   684          "continuous_on ?A snd"
       
   685       by (intro continuous_on_compose2 [OF p] continuous_intros; auto simp add: mult_le_one)+
       
   686   qed (auto simp add: algebra_simps)
   721   then show ?thesis
   687   then show ?thesis
   722     using assms
   688     using assms
   723     apply (subst homotopic_paths_sym_eq)
   689     apply (subst homotopic_paths_sym_eq)
   724     unfolding homotopic_paths_def homotopic_with_def
   690     unfolding homotopic_paths_def homotopic_with_def
   725     apply (rule_tac x="(\<lambda>y. (subpath 0 (fst y) p +++ reversepath(subpath 0 (fst y) p)) (snd y))" in exI)
   691     apply (rule_tac x="(\<lambda>y. (subpath 0 (fst y) p +++ reversepath(subpath 0 (fst y) p)) (snd y))" in exI)
   726     apply (simp add: path_defs joinpaths_def subpath_def reversepath_def)
   692     apply (force simp: mult_le_one path_defs joinpaths_def subpath_def reversepath_def)
   727     apply (force simp: mult_le_one)
       
   728     done
   693     done
   729 qed
   694 qed
   730 
   695 
   731 proposition homotopic_paths_linv:
   696 proposition homotopic_paths_linv:
   732   assumes "path p" "path_image p \<subseteq> s"
   697   assumes "path p" "path_image p \<subseteq> s"
   784 
   749 
   785 proposition homotopic_loops_eq:
   750 proposition homotopic_loops_eq:
   786    "\<lbrakk>path p; path_image p \<subseteq> s; pathfinish p = pathstart p; \<And>t. t \<in> {0..1} \<Longrightarrow> p(t) = q(t)\<rbrakk>
   751    "\<lbrakk>path p; path_image p \<subseteq> s; pathfinish p = pathstart p; \<And>t. t \<in> {0..1} \<Longrightarrow> p(t) = q(t)\<rbrakk>
   787           \<Longrightarrow> homotopic_loops s p q"
   752           \<Longrightarrow> homotopic_loops s p q"
   788   unfolding homotopic_loops_def
   753   unfolding homotopic_loops_def
   789   apply (rule homotopic_with_eq)
   754   apply (rule homotopic_with_eq [OF homotopic_with_refl [where f = p, THEN iffD2]])
   790   apply (rule homotopic_with_refl [where f = p, THEN iffD2])
       
   791   apply (simp_all add: path_image_def path_def pathstart_def pathfinish_def)
   755   apply (simp_all add: path_image_def path_def pathstart_def pathfinish_def)
   792   done
   756   done
   793 
   757 
   794 proposition homotopic_loops_continuous_image:
   758 proposition homotopic_loops_continuous_image:
   795    "\<lbrakk>homotopic_loops s f g; continuous_on s h; h ` s \<subseteq> t\<rbrakk> \<Longrightarrow> homotopic_loops t (h \<circ> f) (h \<circ> g)"
   759    "\<lbrakk>homotopic_loops s f g; continuous_on s h; h ` s \<subseteq> t\<rbrakk> \<Longrightarrow> homotopic_loops t (h \<circ> f) (h \<circ> g)"
   808     shows "homotopic_paths s p (linepath (pathstart p) (pathstart p))"
   772     shows "homotopic_paths s p (linepath (pathstart p) (pathstart p))"
   809 proof -
   773 proof -
   810   have "path p" by (metis assms homotopic_loops_imp_path)
   774   have "path p" by (metis assms homotopic_loops_imp_path)
   811   have ploop: "pathfinish p = pathstart p" by (metis assms homotopic_loops_imp_loop)
   775   have ploop: "pathfinish p = pathstart p" by (metis assms homotopic_loops_imp_loop)
   812   have pip: "path_image p \<subseteq> s" by (metis assms homotopic_loops_imp_subset)
   776   have pip: "path_image p \<subseteq> s" by (metis assms homotopic_loops_imp_subset)
   813   obtain h where conth: "continuous_on ({0..1::real} \<times> {0..1}) h"
   777   let ?A = "{0..1::real} \<times> {0..1::real}"
   814              and hs: "h ` ({0..1} \<times> {0..1}) \<subseteq> s"
   778   obtain h where conth: "continuous_on ?A h"
       
   779              and hs: "h ` ?A \<subseteq> s"
   815              and [simp]: "\<And>x. x \<in> {0..1} \<Longrightarrow> h(0,x) = p x"
   780              and [simp]: "\<And>x. x \<in> {0..1} \<Longrightarrow> h(0,x) = p x"
   816              and [simp]: "\<And>x. x \<in> {0..1} \<Longrightarrow> h(1,x) = a"
   781              and [simp]: "\<And>x. x \<in> {0..1} \<Longrightarrow> h(1,x) = a"
   817              and ends: "\<And>t. t \<in> {0..1} \<Longrightarrow> pathfinish (h \<circ> Pair t) = pathstart (h \<circ> Pair t)"
   782              and ends: "\<And>t. t \<in> {0..1} \<Longrightarrow> pathfinish (h \<circ> Pair t) = pathstart (h \<circ> Pair t)"
   818     using assms by (auto simp: homotopic_loops homotopic_with)
   783     using assms by (auto simp: homotopic_loops homotopic_with)
   819   have conth0: "path (\<lambda>u. h (u, 0))"
   784   have conth0: "path (\<lambda>u. h (u, 0))"
   820     unfolding path_def
   785     unfolding path_def
   821     apply (rule continuous_on_compose [of _ _ h, unfolded o_def])
   786   proof (rule continuous_on_compose [of _ _ h, unfolded o_def])
   822     apply (force intro: continuous_intros continuous_on_subset [OF conth])+
   787     show "continuous_on ((\<lambda>x. (x, 0)) ` {0..1}) h"
   823     done
   788       by (force intro: continuous_on_subset [OF conth])
       
   789   qed (force intro: continuous_intros)
   824   have pih0: "path_image (\<lambda>u. h (u, 0)) \<subseteq> s"
   790   have pih0: "path_image (\<lambda>u. h (u, 0)) \<subseteq> s"
   825     using hs by (force simp: path_image_def)
   791     using hs by (force simp: path_image_def)
   826   have c1: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>x. h (fst x * snd x, 0))"
   792   have c1: "continuous_on ?A (\<lambda>x. h (fst x * snd x, 0))"
   827     apply (rule continuous_on_compose [of _ _ h, unfolded o_def])
   793   proof (rule continuous_on_compose [of _ _ h, unfolded o_def])
   828     apply (force simp: mult_le_one intro: continuous_intros continuous_on_subset [OF conth])+
   794     show "continuous_on ((\<lambda>x. (fst x * snd x, 0)) ` ?A) h"
   829     done
   795       by (force simp: mult_le_one intro: continuous_on_subset [OF conth])
   830   have c2: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>x. h (fst x - fst x * snd x, 0))"
   796   qed (force intro: continuous_intros)+
   831     apply (rule continuous_on_compose [of _ _ h, unfolded o_def])
   797   have c2: "continuous_on ?A (\<lambda>x. h (fst x - fst x * snd x, 0))"
   832     apply (force simp: mult_left_le mult_le_one intro: continuous_intros continuous_on_subset [OF conth])+
   798   proof (rule continuous_on_compose [of _ _ h, unfolded o_def])
   833     apply (rule continuous_on_subset [OF conth])
   799     show "continuous_on ((\<lambda>x. (fst x - fst x * snd x, 0)) ` ?A) h"
   834     apply (auto simp: algebra_simps add_increasing2 mult_left_le)
   800       by (auto simp: algebra_simps add_increasing2 mult_left_le intro: continuous_on_subset [OF conth])
   835     done
   801   qed (force intro: continuous_intros)
   836   have [simp]: "\<And>t. \<lbrakk>0 \<le> t \<and> t \<le> 1\<rbrakk> \<Longrightarrow> h (t, 1) = h (t, 0)"
   802   have [simp]: "\<And>t. \<lbrakk>0 \<le> t \<and> t \<le> 1\<rbrakk> \<Longrightarrow> h (t, 1) = h (t, 0)"
   837     using ends by (simp add: pathfinish_def pathstart_def)
   803     using ends by (simp add: pathfinish_def pathstart_def)
   838   have adhoc_le: "c * 4 \<le> 1 + c * (d * 4)" if "\<not> d * 4 \<le> 3" "0 \<le> c" "c \<le> 1" for c d::real
   804   have adhoc_le: "c * 4 \<le> 1 + c * (d * 4)" if "\<not> d * 4 \<le> 3" "0 \<le> c" "c \<le> 1" for c d::real
   839   proof -
   805   proof -
   840     have "c * 3 \<le> c * (d * 4)" using that less_eq_real_def by auto
   806     have "c * 3 \<le> c * (d * 4)" using that less_eq_real_def by auto
   852   moreover have "homotopic_paths s (p +++ linepath (pathfinish p) (pathfinish p))
   818   moreover have "homotopic_paths s (p +++ linepath (pathfinish p) (pathfinish p))
   853                                    (linepath (pathstart p) (pathstart p) +++ p +++ linepath (pathfinish p) (pathfinish p))"
   819                                    (linepath (pathstart p) (pathstart p) +++ p +++ linepath (pathfinish p) (pathfinish p))"
   854     apply (rule homotopic_paths_sym)
   820     apply (rule homotopic_paths_sym)
   855     using homotopic_paths_lid [of "p +++ linepath (pathfinish p) (pathfinish p)" s]
   821     using homotopic_paths_lid [of "p +++ linepath (pathfinish p) (pathfinish p)" s]
   856     by (metis 1 homotopic_paths_imp_path homotopic_paths_imp_pathstart homotopic_paths_imp_subset)
   822     by (metis 1 homotopic_paths_imp_path homotopic_paths_imp_pathstart homotopic_paths_imp_subset)
   857   moreover have "homotopic_paths s (linepath (pathstart p) (pathstart p) +++ p +++ linepath (pathfinish p) (pathfinish p))
   823   moreover 
       
   824   have "homotopic_paths s (linepath (pathstart p) (pathstart p) +++ p +++ linepath (pathfinish p) (pathfinish p))
   858                                    ((\<lambda>u. h (u, 0)) +++ linepath a a +++ reversepath (\<lambda>u. h (u, 0)))"
   825                                    ((\<lambda>u. h (u, 0)) +++ linepath a a +++ reversepath (\<lambda>u. h (u, 0)))"
   859     apply (simp add: homotopic_paths_def homotopic_with_def)
   826     unfolding homotopic_paths_def homotopic_with_def
   860     apply (rule_tac x="\<lambda>y. (subpath 0 (fst y) (\<lambda>u. h (u, 0)) +++ (\<lambda>u. h (Pair (fst y) u)) +++ subpath (fst y) 0 (\<lambda>u. h (u, 0))) (snd y)" in exI)
   827   proof (intro exI strip conjI)
   861     apply (simp add: subpath_reversepath)
   828     let ?h = "\<lambda>y. (subpath 0 (fst y) (\<lambda>u. h (u, 0)) +++ (\<lambda>u. h (Pair (fst y) u)) +++ subpath (fst y) 0 (\<lambda>u. h (u, 0))) (snd y)" 
   862     apply (intro conjI homotopic_join_lemma)
   829     show "continuous_map (prod_topology (top_of_set {0..1}) (top_of_set {0..1}))
   863     using ploop
   830                          (top_of_set s) ?h"
   864     apply (simp_all add: path_defs joinpaths_def o_def subpath_def conth c1 c2)
   831       apply (simp add: subpath_reversepath)
   865     apply (force simp: algebra_simps mult_le_one mult_left_le intro: hs [THEN subsetD] adhoc_le)
   832       apply (intro conjI homotopic_join_lemma; simp add: path_defs joinpaths_def subpath_def conth c1 c2)
   866     done
   833       apply (force simp: algebra_simps mult_le_one mult_left_le intro: hs [THEN subsetD] adhoc_le)
       
   834       done
       
   835   qed (use ploop in \<open>simp_all add: reversepath_def path_defs joinpaths_def o_def subpath_def conth c1 c2\<close>)
   867   moreover have "homotopic_paths s ((\<lambda>u. h (u, 0)) +++ linepath a a +++ reversepath (\<lambda>u. h (u, 0)))
   836   moreover have "homotopic_paths s ((\<lambda>u. h (u, 0)) +++ linepath a a +++ reversepath (\<lambda>u. h (u, 0)))
   868                                    (linepath (pathstart p) (pathstart p))"
   837                                    (linepath (pathstart p) (pathstart p))"
   869     apply (rule *)
   838     apply (rule *)
   870     apply (simp add: pih0 pathstart_def pathfinish_def conth0)
   839     apply (simp add: pih0 pathstart_def pathfinish_def conth0)
   871     apply (simp add: reversepath_def joinpaths_def)
   840     apply (simp add: reversepath_def joinpaths_def)
   880       and papp: "pathfinish p = pathstart q" and qloop: "pathfinish q = pathstart q"
   849       and papp: "pathfinish p = pathstart q" and qloop: "pathfinish q = pathstart q"
   881     shows "homotopic_loops s (p +++ q +++ reversepath p) q"
   850     shows "homotopic_loops s (p +++ q +++ reversepath p) q"
   882 proof -
   851 proof -
   883   have contp: "continuous_on {0..1} p"  using \<open>path p\<close> [unfolded path_def] by blast
   852   have contp: "continuous_on {0..1} p"  using \<open>path p\<close> [unfolded path_def] by blast
   884   have contq: "continuous_on {0..1} q"  using \<open>path q\<close> [unfolded path_def] by blast
   853   have contq: "continuous_on {0..1} q"  using \<open>path q\<close> [unfolded path_def] by blast
   885   have c1: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>x. p ((1 - fst x) * snd x + fst x))"
   854   let ?A = "{0..1::real} \<times> {0..1::real}"
   886     apply (rule continuous_on_compose [of _ _ p, unfolded o_def])
   855   have c1: "continuous_on ?A (\<lambda>x. p ((1 - fst x) * snd x + fst x))"
   887     apply (force simp: mult_le_one intro!: continuous_intros)
   856   proof (rule continuous_on_compose [of _ _ p, unfolded o_def])
   888     apply (rule continuous_on_subset [OF contp])
   857     show "continuous_on ((\<lambda>x. (1 - fst x) * snd x + fst x) ` ?A) p"
   889     apply (auto simp: algebra_simps add_increasing2 mult_right_le_one_le sum_le_prod1)
   858       by (auto intro: continuous_on_subset [OF contp] simp: algebra_simps add_increasing2 mult_right_le_one_le sum_le_prod1)
   890     done
   859   qed (force intro: continuous_intros)
   891   have c2: "continuous_on ({0..1} \<times> {0..1}) (\<lambda>x. p ((fst x - 1) * snd x + 1))"
   860   have c2: "continuous_on ?A (\<lambda>x. p ((fst x - 1) * snd x + 1))"
   892     apply (rule continuous_on_compose [of _ _ p, unfolded o_def])
   861   proof (rule continuous_on_compose [of _ _ p, unfolded o_def])
   893     apply (force simp: mult_le_one intro!: continuous_intros)
   862     show "continuous_on ((\<lambda>x. (fst x - 1) * snd x + 1) ` ?A) p"
   894     apply (rule continuous_on_subset [OF contp])
   863       by (auto intro: continuous_on_subset [OF contp] simp: algebra_simps add_increasing2 mult_left_le_one_le)
   895     apply (auto simp: algebra_simps add_increasing2 mult_left_le_one_le)
   864   qed (force intro: continuous_intros)
   896     done
   865 
   897   have ps1: "\<And>a b. \<lbrakk>b * 2 \<le> 1; 0 \<le> b; 0 \<le> a; a \<le> 1\<rbrakk> \<Longrightarrow> p ((1 - a) * (2 * b) + a) \<in> s"
   866   have ps1: "\<And>a b. \<lbrakk>b * 2 \<le> 1; 0 \<le> b; 0 \<le> a; a \<le> 1\<rbrakk> \<Longrightarrow> p ((1 - a) * (2 * b) + a) \<in> s"
   898     using sum_le_prod1
   867     using sum_le_prod1
   899     by (force simp: algebra_simps add_increasing2 mult_left_le intro: pip [unfolded path_image_def, THEN subsetD])
   868     by (force simp: algebra_simps add_increasing2 mult_left_le intro: pip [unfolded path_image_def, THEN subsetD])
   900   have ps2: "\<And>a b. \<lbrakk>\<not> 4 * b \<le> 3; b \<le> 1; 0 \<le> a; a \<le> 1\<rbrakk> \<Longrightarrow> p ((a - 1) * (4 * b - 3) + 1) \<in> s"
   869   have ps2: "\<And>a b. \<lbrakk>\<not> 4 * b \<le> 3; b \<le> 1; 0 \<le> a; a \<le> 1\<rbrakk> \<Longrightarrow> p ((a - 1) * (4 * b - 3) + 1) \<in> s"
   901     apply (rule pip [unfolded path_image_def, THEN subsetD])
   870     apply (rule pip [unfolded path_image_def, THEN subsetD])
  1078     apply (cases "w = u")
  1047     apply (cases "w = u")
  1079     using homotopic_paths_rinv [of "subpath u v g" "path_image g"]
  1048     using homotopic_paths_rinv [of "subpath u v g" "path_image g"]
  1080     apply (force simp: closed_segment_eq_real_ivl image_mono path_image_def subpath_refl)
  1049     apply (force simp: closed_segment_eq_real_ivl image_mono path_image_def subpath_refl)
  1081       apply (rule homotopic_paths_sym)
  1050       apply (rule homotopic_paths_sym)
  1082       apply (rule homotopic_paths_reparametrize
  1051       apply (rule homotopic_paths_reparametrize
  1083              [where f = "\<lambda>t. if  t \<le> 1 / 2
  1052              [where f = "\<lambda>t. if  t \<le> 1/2
  1084                              then inverse((w - u)) *\<^sub>R (2 * (v - u)) *\<^sub>R t
  1053                              then inverse((w - u)) *\<^sub>R (2 * (v - u)) *\<^sub>R t
  1085                              else inverse((w - u)) *\<^sub>R ((v - u) + (w - v) *\<^sub>R (2 *\<^sub>R t - 1))"])
  1054                              else inverse((w - u)) *\<^sub>R ((v - u) + (w - v) *\<^sub>R (2 *\<^sub>R t - 1))"])
  1086       using \<open>path g\<close> path_subpath u w apply blast
  1055       using \<open>path g\<close> path_subpath u w apply blast
  1087       using \<open>path g\<close> path_image_subpath_subset u w(1) apply blast
  1056       using \<open>path g\<close> path_image_subpath_subset u w(1) apply blast
  1088       apply simp_all
  1057       apply simp_all
  1399     obtains c where "homotopic_with_canon (\<lambda>h. True) S U (g \<circ> f) (\<lambda>x. c)"
  1368     obtains c where "homotopic_with_canon (\<lambda>h. True) S U (g \<circ> f) (\<lambda>x. c)"
  1400 proof -
  1369 proof -
  1401   obtain b where b: "homotopic_with_canon (\<lambda>x. True) T T id (\<lambda>x. b)"
  1370   obtain b where b: "homotopic_with_canon (\<lambda>x. True) T T id (\<lambda>x. b)"
  1402     using assms by (force simp: contractible_def)
  1371     using assms by (force simp: contractible_def)
  1403   have "homotopic_with_canon (\<lambda>f. True) T U (g \<circ> id) (g \<circ> (\<lambda>x. b))"
  1372   have "homotopic_with_canon (\<lambda>f. True) T U (g \<circ> id) (g \<circ> (\<lambda>x. b))"
  1404     by (metis Abstract_Topology.continuous_map_subtopology_eu b g homotopic_compose_continuous_map_left)
  1373     by (metis Abstract_Topology.continuous_map_subtopology_eu b g homotopic_with_compose_continuous_map_left)
  1405   then have "homotopic_with_canon (\<lambda>f. True) S U (g \<circ> id \<circ> f) (g \<circ> (\<lambda>x. b) \<circ> f)"
  1374   then have "homotopic_with_canon (\<lambda>f. True) S U (g \<circ> id \<circ> f) (g \<circ> (\<lambda>x. b) \<circ> f)"
  1406     by (simp add: f homotopic_with_compose_continuous_map_right)
  1375     by (simp add: f homotopic_with_compose_continuous_map_right)
  1407   then show ?thesis
  1376   then show ?thesis
  1408     by (simp add: comp_def that)
  1377     by (simp add: comp_def that)
  1409 qed
  1378 qed
  3541                  and g2: "continuous_map U Y g2"
  3510                  and g2: "continuous_map U Y g2"
  3542                  and hom2: "homotopic_with (\<lambda>x. True) Y Y (g2 \<circ> f2) id"
  3511                  and hom2: "homotopic_with (\<lambda>x. True) Y Y (g2 \<circ> f2) id"
  3543                            "homotopic_with (\<lambda>x. True) U U (f2 \<circ> g2) id"
  3512                            "homotopic_with (\<lambda>x. True) U U (f2 \<circ> g2) id"
  3544     using 2 by (auto simp: homotopy_equivalent_space_def)
  3513     using 2 by (auto simp: homotopy_equivalent_space_def)
  3545   have "homotopic_with (\<lambda>f. True) X Y (g2 \<circ> f2 \<circ> f1) (id \<circ> f1)"
  3514   have "homotopic_with (\<lambda>f. True) X Y (g2 \<circ> f2 \<circ> f1) (id \<circ> f1)"
  3546     using f1 hom2(1) homotopic_compose_continuous_map_right by blast
  3515     using f1 hom2(1) homotopic_with_compose_continuous_map_right by metis
  3547   then have "homotopic_with (\<lambda>f. True) X Y (g2 \<circ> (f2 \<circ> f1)) (id \<circ> f1)"
  3516   then have "homotopic_with (\<lambda>f. True) X Y (g2 \<circ> (f2 \<circ> f1)) (id \<circ> f1)"
  3548     by (simp add: o_assoc)
  3517     by (simp add: o_assoc)
  3549   then have "homotopic_with (\<lambda>x. True) X X
  3518   then have "homotopic_with (\<lambda>x. True) X X
  3550          (g1 \<circ> (g2 \<circ> (f2 \<circ> f1))) (g1 \<circ> (id \<circ> f1))"
  3519          (g1 \<circ> (g2 \<circ> (f2 \<circ> f1))) (g1 \<circ> (id \<circ> f1))"
  3551     by (simp add: g1 homotopic_compose_continuous_map_left)
  3520     by (simp add: g1 homotopic_with_compose_continuous_map_left)
  3552   moreover have "homotopic_with (\<lambda>x. True) X X (g1 \<circ> id \<circ> f1) id"
  3521   moreover have "homotopic_with (\<lambda>x. True) X X (g1 \<circ> id \<circ> f1) id"
  3553     using hom1 by simp
  3522     using hom1 by simp
  3554   ultimately have SS: "homotopic_with (\<lambda>x. True) X X (g1 \<circ> g2 \<circ> (f2 \<circ> f1)) id"
  3523   ultimately have SS: "homotopic_with (\<lambda>x. True) X X (g1 \<circ> g2 \<circ> (f2 \<circ> f1)) id"
  3555     apply (simp add: o_assoc)
  3524     apply (simp add: o_assoc)
  3556     apply (blast intro: homotopic_with_trans)
  3525     apply (blast intro: homotopic_with_trans)
  3605     show "\<exists>r. homotopic_with (\<lambda>x. True) X X id r \<and> retraction_maps X (subtopology X S) r id"
  3574     show "\<exists>r. homotopic_with (\<lambda>x. True) X X id r \<and> retraction_maps X (subtopology X S) r id"
  3606     proof (intro exI conjI)
  3575     proof (intro exI conjI)
  3607       have "homotopic_with (\<lambda>x. True) X X f r"
  3576       have "homotopic_with (\<lambda>x. True) X X f r"
  3608         proof (rule homotopic_with_eq)
  3577         proof (rule homotopic_with_eq)
  3609           show "homotopic_with (\<lambda>x. True) X X (r \<circ> f) (r \<circ> id)"
  3578           show "homotopic_with (\<lambda>x. True) X X (r \<circ> f) (r \<circ> id)"
  3610             using homotopic_with_symD continuous_map_into_fulltopology f homotopic_compose_continuous_map_left r by blast
  3579             by (metis continuous_map_into_fulltopology f homotopic_with_compose_continuous_map_left homotopic_with_symD r)
  3611           show "f x = (r \<circ> f) x" if "x \<in> topspace X" for x
  3580           show "f x = (r \<circ> f) x" if "x \<in> topspace X" for x
  3612             using that fS req by auto
  3581             using that fS req by auto
  3613         qed auto
  3582         qed auto
  3614       then show "homotopic_with (\<lambda>x. True) X X id r"
  3583       then show "homotopic_with (\<lambda>x. True) X X id r"
  3615         by (rule homotopic_with_trans [OF f])
  3584         by (rule homotopic_with_trans [OF f])
  3635 lemma contractible_space_top_of_set [simp]:"contractible_space (top_of_set S) \<longleftrightarrow> contractible S"
  3604 lemma contractible_space_top_of_set [simp]:"contractible_space (top_of_set S) \<longleftrightarrow> contractible S"
  3636   by (auto simp: contractible_space_def contractible_def)
  3605   by (auto simp: contractible_space_def contractible_def)
  3637 
  3606 
  3638 lemma contractible_space_empty:
  3607 lemma contractible_space_empty:
  3639    "topspace X = {} \<Longrightarrow> contractible_space X"
  3608    "topspace X = {} \<Longrightarrow> contractible_space X"
  3640   apply (simp add: contractible_space_def homotopic_with_def)
  3609   unfolding contractible_space_def homotopic_with_def
  3641   apply (rule_tac x=undefined in exI)
  3610   apply (rule_tac x=undefined in exI)
  3642   apply (rule_tac x="\<lambda>(t,x). if t = 0 then x else undefined" in exI)
  3611   apply (rule_tac x="\<lambda>(t,x). if t = 0 then x else undefined" in exI)
  3643   apply (auto simp: continuous_map_on_empty)
  3612   apply (auto simp: continuous_map_on_empty)
  3644   done
  3613   done
  3645 
  3614 
  3646 lemma contractible_space_singleton:
  3615 lemma contractible_space_singleton:
  3647   "topspace X = {a} \<Longrightarrow> contractible_space X"
  3616   "topspace X = {a} \<Longrightarrow> contractible_space X"
  3648   apply (simp add: contractible_space_def homotopic_with_def)
  3617   unfolding contractible_space_def homotopic_with_def
  3649   apply (rule_tac x=a in exI)
  3618   apply (rule_tac x=a in exI)
  3650   apply (rule_tac x="\<lambda>(t,x). if t = 0 then x else a" in exI)
  3619   apply (rule_tac x="\<lambda>(t,x). if t = 0 then x else a" in exI)
  3651   apply (auto intro: continuous_map_eq [where f = "\<lambda>z. a"])
  3620   apply (auto intro: continuous_map_eq [where f = "\<lambda>z. a"])
  3652   done
  3621   done
  3653 
  3622 
  3664         topspace X = {} \<or>
  3633         topspace X = {} \<or>
  3665         (\<exists>a \<in> topspace X. homotopic_with (\<lambda>x. True) X X id (\<lambda>x. a))"
  3634         (\<exists>a \<in> topspace X. homotopic_with (\<lambda>x. True) X X id (\<lambda>x. a))"
  3666 proof (cases "topspace X = {}")
  3635 proof (cases "topspace X = {}")
  3667   case False
  3636   case False
  3668   then show ?thesis
  3637   then show ?thesis
  3669     apply (auto simp: contractible_space_def)
  3638     using homotopic_with_imp_continuous_maps  by (fastforce simp: contractible_space_def)
  3670     using homotopic_with_imp_continuous_maps by fastforce
       
  3671 qed (simp add: contractible_space_empty)
  3639 qed (simp add: contractible_space_empty)
  3672 
  3640 
  3673 lemma contractible_imp_path_connected_space:
  3641 lemma contractible_imp_path_connected_space:
  3674   assumes "contractible_space X" shows "path_connected_space X"
  3642   assumes "contractible_space X" shows "path_connected_space X"
  3675 proof (cases "topspace X = {}")
  3643 proof (cases "topspace X = {}")
  3678     if "a \<in> topspace X" and conth: "continuous_map (prod_topology (top_of_set {0..1}) X) X h"
  3646     if "a \<in> topspace X" and conth: "continuous_map (prod_topology (top_of_set {0..1}) X) X h"
  3679       and h: "\<forall>x. h (0, x) = x" "\<forall>x. h (1, x) = a"
  3647       and h: "\<forall>x. h (0, x) = x" "\<forall>x. h (1, x) = a"
  3680     for a and h :: "real \<times> 'a \<Rightarrow> 'a"
  3648     for a and h :: "real \<times> 'a \<Rightarrow> 'a"
  3681   proof -
  3649   proof -
  3682     have "path_component_of X b a" if "b \<in> topspace X" for b
  3650     have "path_component_of X b a" if "b \<in> topspace X" for b
  3683       using that unfolding path_component_of_def
  3651       unfolding path_component_of_def
  3684       apply (rule_tac x="h \<circ> (\<lambda>x. (x,b))" in exI)
  3652     proof (intro exI conjI)
  3685       apply (simp add: h pathin_def)
  3653       let ?g = "h \<circ> (\<lambda>x. (x,b))"
  3686       apply (rule continuous_map_compose [OF _ conth])
  3654       show "pathin X ?g"
  3687       apply (auto simp: continuous_map_pairwise intro!: continuous_intros continuous_map_compose continuous_map_id [unfolded id_def])
  3655         unfolding pathin_def
  3688       done
  3656         apply (rule continuous_map_compose [OF _ conth])
       
  3657         using that
       
  3658         apply (auto simp: continuous_map_pairwise intro!: continuous_intros continuous_map_compose continuous_map_id [unfolded id_def])
       
  3659         done
       
  3660     qed (use h in auto)
  3689   then show ?thesis
  3661   then show ?thesis
  3690     by (metis path_component_of_equiv path_connected_space_iff_path_component)
  3662     by (metis path_component_of_equiv path_connected_space_iff_path_component)
  3691   qed
  3663   qed
  3692   show ?thesis
  3664   show ?thesis
  3693     using assms False by (auto simp: contractible_space homotopic_with_def *)
  3665     using assms False by (auto simp: contractible_space homotopic_with_def *)
  3704   then obtain a where a: "homotopic_with (\<lambda>x. True) X X id (\<lambda>x. a)"
  3676   then obtain a where a: "homotopic_with (\<lambda>x. True) X X id (\<lambda>x. a)"
  3705     by (auto simp: contractible_space_def)
  3677     by (auto simp: contractible_space_def)
  3706   show ?rhs
  3678   show ?rhs
  3707   proof
  3679   proof
  3708     show "homotopic_with (\<lambda>x. True) X X id (\<lambda>x. b)" if "b \<in> topspace X" for b
  3680     show "homotopic_with (\<lambda>x. True) X X id (\<lambda>x. b)" if "b \<in> topspace X" for b
  3709       apply (rule homotopic_with_trans [OF a])
  3681     proof (rule homotopic_with_trans [OF a])
  3710       using homotopic_constant_maps path_connected_space_imp_path_component_of
  3682       show "homotopic_with (\<lambda>x. True) X X (\<lambda>x. a) (\<lambda>x. b)"
  3711       by (metis (full_types) X a continuous_map_const contractible_imp_path_connected_space homotopic_with_imp_continuous_maps that)
  3683         using homotopic_constant_maps path_connected_space_imp_path_component_of
       
  3684         by (metis (full_types) X a continuous_map_const contractible_imp_path_connected_space homotopic_with_imp_continuous_maps that)
       
  3685     qed
  3712   qed
  3686   qed
  3713 next
  3687 next
  3714   assume R: ?rhs
  3688   assume R: ?rhs
  3715   then show ?lhs
  3689   then show ?lhs
  3716     apply (simp add: contractible_space_def)
  3690     unfolding contractible_space_def by (metis equals0I homotopic_on_emptyI)
  3717     by (metis equals0I homotopic_on_emptyI)
       
  3718 qed
  3691 qed
  3719 
  3692 
  3720 
  3693 
  3721 lemma compose_const [simp]: "f \<circ> (\<lambda>x. a) = (\<lambda>x. f a)" "(\<lambda>x. a) \<circ> g = (\<lambda>x. a)"
  3694 lemma compose_const [simp]: "f \<circ> (\<lambda>x. a) = (\<lambda>x. f a)" "(\<lambda>x. a) \<circ> g = (\<lambda>x. a)"
  3722   by (simp_all add: o_def)
  3695   by (simp_all add: o_def)
  3726   obtains c where "homotopic_with (\<lambda>h. True) X Z (g \<circ> f) (\<lambda>x. c)"
  3699   obtains c where "homotopic_with (\<lambda>h. True) X Z (g \<circ> f) (\<lambda>x. c)"
  3727 proof -
  3700 proof -
  3728   obtain b where b: "homotopic_with (\<lambda>x. True) Y Y id (\<lambda>x. b)"
  3701   obtain b where b: "homotopic_with (\<lambda>x. True) Y Y id (\<lambda>x. b)"
  3729     using Y by (auto simp: contractible_space_def)
  3702     using Y by (auto simp: contractible_space_def)
  3730   show thesis
  3703   show thesis
  3731     using homotopic_compose_continuous_map_right
  3704     using homotopic_with_compose_continuous_map_right
  3732            [OF homotopic_compose_continuous_map_left [OF b g] f]
  3705            [OF homotopic_with_compose_continuous_map_left [OF b g] f]
  3733     by (simp add: that)
  3706     by (force simp add: that)
  3734 qed
  3707 qed
  3735 
  3708 
  3736 lemma nullhomotopic_into_contractible_space:
  3709 lemma nullhomotopic_into_contractible_space:
  3737   assumes f: "continuous_map X Y f" and Y: "contractible_space Y"
  3710   assumes f: "continuous_map X Y f" and Y: "contractible_space Y"
  3738   obtains c where "homotopic_with (\<lambda>h. True) X Y f (\<lambda>x. c)"
  3711   obtains c where "homotopic_with (\<lambda>h. True) X Y f (\<lambda>x. c)"
  3751   shows "contractible_space Y"
  3724   shows "contractible_space Y"
  3752 proof -
  3725 proof -
  3753   obtain c where c: "homotopic_with (\<lambda>h. True) X Y f (\<lambda>x. c)"
  3726   obtain c where c: "homotopic_with (\<lambda>h. True) X Y f (\<lambda>x. c)"
  3754     using nullhomotopic_from_contractible_space [OF f X] .
  3727     using nullhomotopic_from_contractible_space [OF f X] .
  3755   have "homotopic_with (\<lambda>x. True) Y Y (f \<circ> g) (\<lambda>x. c)"
  3728   have "homotopic_with (\<lambda>x. True) Y Y (f \<circ> g) (\<lambda>x. c)"
  3756     using homotopic_compose_continuous_map_right [OF c g] by fastforce
  3729     using homotopic_with_compose_continuous_map_right [OF c g] by fastforce
  3757   then have "homotopic_with (\<lambda>x. True) Y Y id (\<lambda>x. c)"
  3730   then have "homotopic_with (\<lambda>x. True) Y Y id (\<lambda>x. c)"
  3758     using homotopic_with_trans [OF _ hom] homotopic_with_symD by blast
  3731     using homotopic_with_trans [OF _ hom] homotopic_with_symD by blast
  3759   then show ?thesis
  3732   then show ?thesis
  3760     unfolding contractible_space_def ..
  3733     unfolding contractible_space_def ..
  3761 qed
  3734 qed
  3806   obtain a where a: "homotopic_with (\<lambda>x. True) X X id (\<lambda>x. a)"
  3779   obtain a where a: "homotopic_with (\<lambda>x. True) X X id (\<lambda>x. a)"
  3807     using X by (auto simp: contractible_space_def)
  3780     using X by (auto simp: contractible_space_def)
  3808   have "homotopic_with (\<lambda>x. True) Y Y id (\<lambda>x. f a)"
  3781   have "homotopic_with (\<lambda>x. True) Y Y id (\<lambda>x. f a)"
  3809   proof (rule homotopic_with_eq)
  3782   proof (rule homotopic_with_eq)
  3810     show "homotopic_with (\<lambda>x. True) Y Y (f \<circ> id \<circ> g) (f \<circ> (\<lambda>x. a) \<circ> g)"
  3783     show "homotopic_with (\<lambda>x. True) Y Y (f \<circ> id \<circ> g) (f \<circ> (\<lambda>x. a) \<circ> g)"
  3811       using f g a homotopic_compose_continuous_map_left homotopic_compose_continuous_map_right by metis
  3784       using f g a homotopic_with_compose_continuous_map_left homotopic_with_compose_continuous_map_right by metis
  3812   qed (use fg in auto)
  3785   qed (use fg in auto)
  3813   then show ?thesis
  3786   then show ?thesis
  3814     unfolding contractible_space_def by blast
  3787     unfolding contractible_space_def by blast
  3815 qed
  3788 qed
  3816 
  3789 
  3905     then obtain z where "z \<in> S"
  3878     then obtain z where "z \<in> S"
  3906       by blast
  3879       by blast
  3907     show ?thesis
  3880     show ?thesis
  3908       unfolding contractible_space_def homotopic_with_def
  3881       unfolding contractible_space_def homotopic_with_def
  3909     proof (intro exI conjI allI)
  3882     proof (intro exI conjI allI)
       
  3883       note \<section> = convexD [OF \<open>convex S\<close>, simplified]
  3910       show "continuous_map (prod_topology (top_of_set {0..1}) (top_of_set S)) (top_of_set S)
  3884       show "continuous_map (prod_topology (top_of_set {0..1}) (top_of_set S)) (top_of_set S)
  3911                            (\<lambda>(t,x). (1 - t) * x + t * z)"
  3885                            (\<lambda>(t,x). (1 - t) * x + t * z)"
  3912         apply (auto simp: case_prod_unfold)
  3886         using  \<open>z \<in> S\<close> 
  3913          apply (intro continuous_intros)
  3887         by (auto simp add: case_prod_unfold intro!: continuous_intros \<section>)
  3914         using  \<open>z \<in> S\<close> apply (auto intro: convexD [OF \<open>convex S\<close>, simplified])
       
  3915         done
       
  3916     qed auto
  3888     qed auto
  3917   qed (simp add: contractible_space_empty)
  3889   qed (simp add: contractible_space_empty)
  3918 qed
  3890 qed
  3919 
  3891 
  3920 
  3892 
  3945 
  3917 
  3946 lemma homotopy_eqv_inj_linear_image:
  3918 lemma homotopy_eqv_inj_linear_image:
  3947   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  3919   fixes f :: "'a::euclidean_space \<Rightarrow> 'b::euclidean_space"
  3948   assumes "linear f" "inj f"
  3920   assumes "linear f" "inj f"
  3949     shows "(f ` S) homotopy_eqv S"
  3921     shows "(f ` S) homotopy_eqv S"
  3950 apply (rule homeomorphic_imp_homotopy_eqv)
  3922   by (metis assms homeomorphic_sym homeomorphic_imp_homotopy_eqv linear_homeomorphic_image)
  3951 using assms homeomorphic_sym linear_homeomorphic_image by auto
       
  3952 
  3923 
  3953 lemma homotopy_eqv_translation:
  3924 lemma homotopy_eqv_translation:
  3954     fixes S :: "'a::real_normed_vector set"
  3925     fixes S :: "'a::real_normed_vector set"
  3955     shows "(+) a ` S homotopy_eqv S"
  3926     shows "(+) a ` S homotopy_eqv S"
  3956   apply (rule homeomorphic_imp_homotopy_eqv)
  3927   using homeomorphic_imp_homotopy_eqv homeomorphic_translation homeomorphic_sym by blast
  3957   using homeomorphic_translation homeomorphic_sym by blast
       
  3958 
  3928 
  3959 lemma homotopy_eqv_homotopic_triviality_imp:
  3929 lemma homotopy_eqv_homotopic_triviality_imp:
  3960   fixes S :: "'a::real_normed_vector set"
  3930   fixes S :: "'a::real_normed_vector set"
  3961     and T :: "'b::real_normed_vector set"
  3931     and T :: "'b::real_normed_vector set"
  3962     and U :: "'c::real_normed_vector set"
  3932     and U :: "'c::real_normed_vector set"
  3972                and k: "continuous_on T k" "k ` T \<subseteq> S"
  3942                and k: "continuous_on T k" "k ` T \<subseteq> S"
  3973                and hom: "homotopic_with_canon (\<lambda>x. True) S S (k \<circ> h) id"
  3943                and hom: "homotopic_with_canon (\<lambda>x. True) S S (k \<circ> h) id"
  3974                         "homotopic_with_canon (\<lambda>x. True) T T (h \<circ> k) id"
  3944                         "homotopic_with_canon (\<lambda>x. True) T T (h \<circ> k) id"
  3975     using assms by (auto simp: homotopy_equivalent_space_def)
  3945     using assms by (auto simp: homotopy_equivalent_space_def)
  3976   have "homotopic_with_canon (\<lambda>f. True) U S (k \<circ> f) (k \<circ> g)"
  3946   have "homotopic_with_canon (\<lambda>f. True) U S (k \<circ> f) (k \<circ> g)"
  3977     apply (rule homUS)
  3947   proof (rule homUS)
  3978     using f g k
  3948     show "continuous_on U (k \<circ> f)" "continuous_on U (k \<circ> g)"
  3979     apply (safe intro!: continuous_on_compose h k f elim!: continuous_on_subset)
  3949       using continuous_on_compose continuous_on_subset f g k by blast+
  3980     apply (force simp: o_def)+
  3950   qed (use f g k in \<open>(force simp: o_def)+\<close> )
  3981     done
       
  3982   then have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> (k \<circ> f)) (h \<circ> (k \<circ> g))"
  3951   then have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> (k \<circ> f)) (h \<circ> (k \<circ> g))"
  3983     apply (rule homotopic_with_compose_continuous_left)
  3952     by (rule homotopic_with_compose_continuous_left; simp add: h)
  3984     apply (simp_all add: h)
       
  3985     done
       
  3986   moreover have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> k \<circ> f) (id \<circ> f)"
  3953   moreover have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> k \<circ> f) (id \<circ> f)"
  3987     apply (rule homotopic_with_compose_continuous_right [where X=T and Y=T])
  3954     by (rule homotopic_with_compose_continuous_right [where X=T and Y=T]; simp add: hom f)
  3988     apply (auto simp: hom f)
       
  3989     done
       
  3990   moreover have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> k \<circ> g) (id \<circ> g)"
  3955   moreover have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> k \<circ> g) (id \<circ> g)"
  3991     apply (rule homotopic_with_compose_continuous_right [where X=T and Y=T])
  3956     by (rule homotopic_with_compose_continuous_right [where X=T and Y=T]; simp add: hom g)
  3992     apply (auto simp: hom g)
       
  3993     done
       
  3994   ultimately show "homotopic_with_canon (\<lambda>x. True) U T f g"
  3957   ultimately show "homotopic_with_canon (\<lambda>x. True) U T f g"
  3995     apply (simp add: o_assoc)
  3958     unfolding o_assoc
  3996     using homotopic_with_trans homotopic_with_sym by blast
  3959     by (metis homotopic_with_trans homotopic_with_sym id_comp) 
  3997 qed
  3960 qed
  3998 
  3961 
  3999 lemma homotopy_eqv_homotopic_triviality:
  3962 lemma homotopy_eqv_homotopic_triviality:
  4000   fixes S :: "'a::real_normed_vector set"
  3963   fixes S :: "'a::real_normed_vector set"
  4001     and T :: "'b::real_normed_vector set"
  3964     and T :: "'b::real_normed_vector set"
  4036                and k: "continuous_on T k" "k ` T \<subseteq> S"
  3999                and k: "continuous_on T k" "k ` T \<subseteq> S"
  4037                and hom: "homotopic_with_canon (\<lambda>x. True) S S (k \<circ> h) id"
  4000                and hom: "homotopic_with_canon (\<lambda>x. True) S S (k \<circ> h) id"
  4038                         "homotopic_with_canon (\<lambda>x. True) T T (h \<circ> k) id"
  4001                         "homotopic_with_canon (\<lambda>x. True) T T (h \<circ> k) id"
  4039     using assms by (auto simp: homotopy_equivalent_space_def)
  4002     using assms by (auto simp: homotopy_equivalent_space_def)
  4040   obtain c where "homotopic_with_canon (\<lambda>x. True) S U (f \<circ> h) (\<lambda>x. c)"
  4003   obtain c where "homotopic_with_canon (\<lambda>x. True) S U (f \<circ> h) (\<lambda>x. c)"
  4041     apply (rule exE [OF homSU [of "f \<circ> h"]])
  4004   proof (rule exE [OF homSU])
  4042     apply (intro continuous_on_compose h)
  4005     show "continuous_on S (f \<circ> h)"
  4043     using h f  apply (force elim!: continuous_on_subset)+
  4006       using continuous_on_compose continuous_on_subset f h by blast
  4044     done
  4007   qed (use f h in force)
  4045   then have "homotopic_with_canon (\<lambda>x. True) T U ((f \<circ> h) \<circ> k) ((\<lambda>x. c) \<circ> k)"
  4008   then have "homotopic_with_canon (\<lambda>x. True) T U ((f \<circ> h) \<circ> k) ((\<lambda>x. c) \<circ> k)"
  4046     apply (rule homotopic_with_compose_continuous_right [where X=S])
  4009     by (rule homotopic_with_compose_continuous_right [where X=S]) (use k in auto)
  4047     using k by auto
       
  4048   moreover have "homotopic_with_canon (\<lambda>x. True) T U (f \<circ> id) (f \<circ> (h \<circ> k))"
  4010   moreover have "homotopic_with_canon (\<lambda>x. True) T U (f \<circ> id) (f \<circ> (h \<circ> k))"
  4049     apply (rule homotopic_with_compose_continuous_left [where Y=T])
  4011     by (rule homotopic_with_compose_continuous_left [where Y=T])
  4050       apply (simp add: hom homotopic_with_symD)
  4012        (use f in \<open>auto simp add: hom homotopic_with_symD\<close>)
  4051      using f apply auto
       
  4052     done
       
  4053   ultimately show ?thesis
  4013   ultimately show ?thesis
  4054     apply (rule_tac c=c in that)
  4014     apply (rule_tac c=c in that)
  4055     apply (simp add: o_def)
  4015     apply (simp add: o_def)
  4056     using homotopic_with_trans by blast
  4016     using homotopic_with_trans by blast
  4057 qed
  4017 qed
  4063   assumes "S homotopy_eqv T"
  4023   assumes "S homotopy_eqv T"
  4064     shows "(\<forall>f. continuous_on S f \<and> f ` S \<subseteq> U
  4024     shows "(\<forall>f. continuous_on S f \<and> f ` S \<subseteq> U
  4065                 \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) S U f (\<lambda>x. c))) \<longleftrightarrow>
  4025                 \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) S U f (\<lambda>x. c))) \<longleftrightarrow>
  4066            (\<forall>f. continuous_on T f \<and> f ` T \<subseteq> U
  4026            (\<forall>f. continuous_on T f \<and> f ` T \<subseteq> U
  4067                 \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) T U f (\<lambda>x. c)))"
  4027                 \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) T U f (\<lambda>x. c)))"
  4068 apply (rule iffI)
  4028 by (rule iffI; metis assms homotopy_eqv_cohomotopic_triviality_null_imp homotopy_equivalent_space_sym)
  4069 apply (metis assms homotopy_eqv_cohomotopic_triviality_null_imp)
  4029 
  4070 by (metis assms homotopy_eqv_cohomotopic_triviality_null_imp homotopy_equivalent_space_sym)
  4030 text \<open>Similar to the proof above\<close>
  4071 
       
  4072 lemma homotopy_eqv_homotopic_triviality_null_imp:
  4031 lemma homotopy_eqv_homotopic_triviality_null_imp:
  4073   fixes S :: "'a::real_normed_vector set"
  4032   fixes S :: "'a::real_normed_vector set"
  4074     and T :: "'b::real_normed_vector set"
  4033     and T :: "'b::real_normed_vector set"
  4075     and U :: "'c::real_normed_vector set"
  4034     and U :: "'c::real_normed_vector set"
  4076   assumes "S homotopy_eqv T"
  4035   assumes "S homotopy_eqv T"
  4083                and k: "continuous_on T k" "k ` T \<subseteq> S"
  4042                and k: "continuous_on T k" "k ` T \<subseteq> S"
  4084                and hom: "homotopic_with_canon (\<lambda>x. True) S S (k \<circ> h) id"
  4043                and hom: "homotopic_with_canon (\<lambda>x. True) S S (k \<circ> h) id"
  4085                         "homotopic_with_canon (\<lambda>x. True) T T (h \<circ> k) id"
  4044                         "homotopic_with_canon (\<lambda>x. True) T T (h \<circ> k) id"
  4086     using assms by (auto simp: homotopy_equivalent_space_def)
  4045     using assms by (auto simp: homotopy_equivalent_space_def)
  4087   obtain c::'a where "homotopic_with_canon (\<lambda>x. True) U S (k \<circ> f) (\<lambda>x. c)"
  4046   obtain c::'a where "homotopic_with_canon (\<lambda>x. True) U S (k \<circ> f) (\<lambda>x. c)"
  4088     apply (rule exE [OF homSU [of "k \<circ> f"]])
  4047   proof (rule exE [OF homSU [of "k \<circ> f"]])
  4089     apply (intro continuous_on_compose h)
  4048     show "continuous_on U (k \<circ> f)"
  4090     using k f  apply (force elim!: continuous_on_subset)+
  4049       using continuous_on_compose continuous_on_subset f k by blast
  4091     done
  4050   qed (use f k in force)
  4092   then have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> (k \<circ> f)) (h \<circ> (\<lambda>x. c))"
  4051   then have "homotopic_with_canon (\<lambda>x. True) U T (h \<circ> (k \<circ> f)) (h \<circ> (\<lambda>x. c))"
  4093     apply (rule homotopic_with_compose_continuous_left [where Y=S])
  4052     by (rule homotopic_with_compose_continuous_left [where Y=S]) (use h in auto)
  4094     using h by auto
       
  4095   moreover have "homotopic_with_canon (\<lambda>x. True) U T (id \<circ> f) ((h \<circ> k) \<circ> f)"
  4053   moreover have "homotopic_with_canon (\<lambda>x. True) U T (id \<circ> f) ((h \<circ> k) \<circ> f)"
  4096     apply (rule homotopic_with_compose_continuous_right [where X=T])
  4054     by (rule homotopic_with_compose_continuous_right [where X=T])
  4097       apply (simp add: hom homotopic_with_symD)
  4055        (use f in \<open>auto simp add: hom homotopic_with_symD\<close>)
  4098      using f apply auto
       
  4099     done
       
  4100   ultimately show ?thesis
  4056   ultimately show ?thesis
  4101     using homotopic_with_trans by (fastforce simp add: o_def)
  4057     using homotopic_with_trans by (fastforce simp add: o_def)
  4102 qed
  4058 qed
  4103 
  4059 
  4104 lemma homotopy_eqv_homotopic_triviality_null:
  4060 lemma homotopy_eqv_homotopic_triviality_null:
  4108   assumes "S homotopy_eqv T"
  4064   assumes "S homotopy_eqv T"
  4109     shows "(\<forall>f. continuous_on U f \<and> f ` U \<subseteq> S
  4065     shows "(\<forall>f. continuous_on U f \<and> f ` U \<subseteq> S
  4110                   \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) U S f (\<lambda>x. c))) \<longleftrightarrow>
  4066                   \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) U S f (\<lambda>x. c))) \<longleftrightarrow>
  4111            (\<forall>f. continuous_on U f \<and> f ` U \<subseteq> T
  4067            (\<forall>f. continuous_on U f \<and> f ` U \<subseteq> T
  4112                   \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) U T f (\<lambda>x. c)))"
  4068                   \<longrightarrow> (\<exists>c. homotopic_with_canon (\<lambda>x. True) U T f (\<lambda>x. c)))"
  4113 apply (rule iffI)
  4069 by (rule iffI; metis assms homotopy_eqv_homotopic_triviality_null_imp homotopy_equivalent_space_sym)
  4114 apply (metis assms homotopy_eqv_homotopic_triviality_null_imp)
       
  4115 by (metis assms homotopy_eqv_homotopic_triviality_null_imp homotopy_equivalent_space_sym)
       
  4116 
  4070 
  4117 lemma homotopy_eqv_contractible_sets:
  4071 lemma homotopy_eqv_contractible_sets:
  4118   fixes S :: "'a::real_normed_vector set"
  4072   fixes S :: "'a::real_normed_vector set"
  4119     and T :: "'b::real_normed_vector set"
  4073     and T :: "'b::real_normed_vector set"
  4120   assumes "contractible S" "contractible T" "S = {} \<longleftrightarrow> T = {}"
  4074   assumes "contractible S" "contractible T" "S = {} \<longleftrightarrow> T = {}"