|
| 1 | +/- |
| 2 | +Copyright (c) 2022 Praneeth Kolichala. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Praneeth Kolichala |
| 5 | +-/ |
| 6 | +import topology.homotopy.product |
| 7 | +import topology.homotopy.equiv |
| 8 | +import category_theory.equivalence |
| 9 | + |
| 10 | +/-! |
| 11 | +# Homotopic maps induce naturally isomorphic functors |
| 12 | +
|
| 13 | +## Main definitions |
| 14 | +
|
| 15 | + - `fundamental_groupoid_functor.homotopic_maps_nat_iso H` The natural isomorphism |
| 16 | + between the induced functors `f : π(X) ⥤ π(Y)` and `g : π(X) ⥤ π(Y)`, given a homotopy |
| 17 | + `H : f ∼ g` |
| 18 | +
|
| 19 | + - `fundamental_groupoid_functor.equiv_of_homotopy_equiv hequiv` The equivalence of the categories |
| 20 | + `π(X)` and `π(Y)` given a homotopy equivalence `hequiv : X ≃ₕ Y` between them. |
| 21 | +
|
| 22 | +## Implementation notes |
| 23 | + - In order to be more universe polymorphic, we define `continuous_map.homotopy.ulift_map` |
| 24 | + which lifts a homotopy from `I × X → Y` to `(Top.of ((ulift I) × X)) → Y`. This is because |
| 25 | + this construction uses `fundamental_groupoid_functor.prod_to_prod_Top` to convert between |
| 26 | + pairs of paths in I and X and the corresponding path after passing through a homotopy `H`. |
| 27 | + But `fundamental_groupoid_functor.prod_to_prod_Top` requires two spaces in the same universe. |
| 28 | +-/ |
| 29 | + |
| 30 | +noncomputable theory |
| 31 | + |
| 32 | +universe u |
| 33 | + |
| 34 | +open fundamental_groupoid |
| 35 | +open category_theory |
| 36 | +open fundamental_groupoid_functor |
| 37 | + |
| 38 | +open_locale fundamental_groupoid |
| 39 | +open_locale unit_interval |
| 40 | + |
| 41 | +namespace unit_interval |
| 42 | + |
| 43 | +/-- The path 0 ⟶ 1 in I -/ |
| 44 | +def path01 : path (0 : I) 1 := { to_fun := id, source' := rfl, target' := rfl } |
| 45 | + |
| 46 | +/-- The path 0 ⟶ 1 in ulift I -/ |
| 47 | +def upath01 : path (ulift.up 0 : ulift.{u} I) (ulift.up 1) := |
| 48 | +{ to_fun := ulift.up, source' := rfl, target' := rfl } |
| 49 | + |
| 50 | +local attribute [instance] path.homotopic.setoid |
| 51 | +/-- The homotopy path class of 0 → 1 in `ulift I` -/ |
| 52 | +def uhpath01 : @from_top (Top.of $ ulift.{u} I) (ulift.up (0 : I)) ⟶ from_top (ulift.up 1) := |
| 53 | +⟦upath01⟧ |
| 54 | + |
| 55 | +end unit_interval |
| 56 | + |
| 57 | +namespace continuous_map.homotopy |
| 58 | +open unit_interval (uhpath01) |
| 59 | + |
| 60 | +local attribute [instance] path.homotopic.setoid |
| 61 | + |
| 62 | +section casts |
| 63 | + |
| 64 | +/-- Abbreviation for `eq_to_hom` that accepts points in a topological space -/ |
| 65 | +abbreviation hcast {X : Top} {x₀ x₁ : X} (hx : x₀ = x₁) : from_top x₀ ⟶ from_top x₁ := eq_to_hom hx |
| 66 | + |
| 67 | +@[simp] lemma hcast_def {X : Top} {x₀ x₁ : X} (hx₀ : x₀ = x₁) : hcast hx₀ = eq_to_hom hx₀ := rfl |
| 68 | + |
| 69 | +variables {X₁ X₂ Y : Top.{u}} {f : C(X₁, Y)} {g : C(X₂, Y)} |
| 70 | + {x₀ x₁ : X₁} {x₂ x₃ : X₂} {p : path x₀ x₁} {q : path x₂ x₃} (hfg : ∀ t, f (p t) = g (q t)) |
| 71 | + |
| 72 | +include hfg |
| 73 | + |
| 74 | +/-- If `f(p(t) = g(q(t))` for two paths `p` and `q`, then the induced path homotopy classes |
| 75 | +`f(p)` and `g(p)` are the same as well, despite having a priori different types -/ |
| 76 | +lemma heq_path_of_eq_image : (πₘ f).map ⟦p⟧ == (πₘ g).map ⟦q⟧ := |
| 77 | +by { simp only [map_eq, ← path.homotopic.map_lift], apply path.homotopic.hpath_hext, exact hfg, } |
| 78 | + |
| 79 | +private lemma start_path : f x₀ = g x₂ := by { convert hfg 0; simp only [path.source], } |
| 80 | +private lemma end_path : f x₁ = g x₃ := by { convert hfg 1; simp only [path.target], } |
| 81 | + |
| 82 | +lemma eq_path_of_eq_image : |
| 83 | + (πₘ f).map ⟦p⟧ = hcast (start_path hfg) ≫ (πₘ g).map ⟦q⟧ ≫ hcast (end_path hfg).symm := |
| 84 | +by { rw functor.conj_eq_to_hom_iff_heq, exact heq_path_of_eq_image hfg } |
| 85 | + |
| 86 | +end casts |
| 87 | + |
| 88 | +/- We let `X` and `Y` be spaces, and `f` and `g` be homotopic maps between them -/ |
| 89 | +variables {X Y : Top.{u}} {f g : C(X, Y)} (H : continuous_map.homotopy f g) |
| 90 | + {x₀ x₁ : X} (p : from_top x₀ ⟶ from_top x₁) |
| 91 | + |
| 92 | +/-! |
| 93 | +These definitions set up the following diagram, for each path `p`: |
| 94 | +
|
| 95 | + f(p) |
| 96 | + *--------* |
| 97 | + | \ | |
| 98 | + H₀ | \ d | H₁ |
| 99 | + | \ | |
| 100 | + *--------* |
| 101 | + g(p) |
| 102 | +
|
| 103 | +Here, `H₀ = H.eval_at x₀` is the path from `f(x₀)` to `g(x₀)`, |
| 104 | +and similarly for `H₁`. Similarly, `f(p)` denotes the |
| 105 | +path in Y that the induced map `f` takes `p`, and similarly for `g(p)`. |
| 106 | +
|
| 107 | +Finally, `d`, the diagonal path, is H(0 ⟶ 1, p), the result of the induced `H` on |
| 108 | +`path.homotopic.prod (0 ⟶ 1) p`, where `(0 ⟶ 1)` denotes the path from `0` to `1` in `I`. |
| 109 | +
|
| 110 | +It is clear that the diagram commutes (`H₀ ≫ g(p) = d = f(p) ≫ H₁`), but unfortunately, |
| 111 | +many of the paths do not have defeq starting/ending points, so we end up needing some casting. |
| 112 | +-/ |
| 113 | + |
| 114 | +/-- Interpret a homotopy `H : C(I × X, Y) as a map C(ulift I × X, Y) -/ |
| 115 | +def ulift_map : C(Top.of (ulift.{u} I × X), Y) := |
| 116 | +⟨λ x, H (x.1.down, x.2), |
| 117 | + H.continuous.comp ((continuous_induced_dom.comp continuous_fst).prod_mk continuous_snd)⟩ |
| 118 | + |
| 119 | +@[simp] lemma ulift_apply (i : ulift.{u} I) (x : X) : H.ulift_map (i, x) = H (i.down, x) := rfl |
| 120 | + |
| 121 | +/-- An abbreviation for `prod_to_prod_Top`, with some types already in place to help the |
| 122 | + typechecker. In particular, the first path should be on the ulifted unit interval. -/ |
| 123 | +abbreviation prod_to_prod_Top_I {a₁ a₂ : Top.of (ulift I)} {b₁ b₂ : X} |
| 124 | + (p₁ : from_top a₁ ⟶ from_top a₂) (p₂ : from_top b₁ ⟶ from_top b₂) := |
| 125 | +@category_theory.functor.map _ _ _ _ (prod_to_prod_Top (Top.of $ ulift I) X) |
| 126 | + (a₁, b₁) (a₂, b₂) (p₁, p₂) |
| 127 | + |
| 128 | +/-- The diagonal path `d` of a homotopy `H` on a path `p` -/ |
| 129 | +def diagonal_path : from_top (H (0, x₀)) ⟶ from_top (H (1, x₁)) := |
| 130 | +(πₘ H.ulift_map).map (prod_to_prod_Top_I uhpath01 p) |
| 131 | + |
| 132 | +/-- The diagonal path, but starting from `f x₀` and going to `g x₁` -/ |
| 133 | +def diagonal_path' : from_top (f x₀) ⟶ from_top (g x₁) := |
| 134 | +hcast (H.apply_zero x₀).symm ≫ (H.diagonal_path p) ≫ hcast (H.apply_one x₁) |
| 135 | + |
| 136 | +/-- Proof that `f(p) = H(0 ⟶ 0, p)`, with the appropriate casts -/ |
| 137 | +lemma apply_zero_path : (πₘ f).map p = hcast (H.apply_zero x₀).symm ≫ |
| 138 | +(πₘ H.ulift_map).map (prod_to_prod_Top_I (𝟙 (ulift.up 0)) p) ≫ |
| 139 | +hcast (H.apply_zero x₁) := |
| 140 | +begin |
| 141 | + apply quotient.induction_on p, |
| 142 | + intro p', |
| 143 | + apply @eq_path_of_eq_image _ _ _ _ H.ulift_map _ _ _ _ _ ((path.refl (ulift.up _)).prod p'), |
| 144 | + simp, |
| 145 | +end |
| 146 | + |
| 147 | +/-- Proof that `g(p) = H(1 ⟶ 1, p)`, with the appropriate casts -/ |
| 148 | +lemma apply_one_path : (πₘ g).map p = hcast (H.apply_one x₀).symm ≫ |
| 149 | +((πₘ H.ulift_map).map (prod_to_prod_Top_I (𝟙 (ulift.up 1)) p)) ≫ |
| 150 | +hcast (H.apply_one x₁) := |
| 151 | +begin |
| 152 | + apply quotient.induction_on p, |
| 153 | + intro p', |
| 154 | + apply @eq_path_of_eq_image _ _ _ _ H.ulift_map _ _ _ _ _ ((path.refl (ulift.up _)).prod p'), |
| 155 | + simp, |
| 156 | +end |
| 157 | + |
| 158 | +/-- Proof that `H.eval_at x = H(0 ⟶ 1, x ⟶ x)`, with the appropriate casts -/ |
| 159 | +lemma eval_at_eq (x : X) : ⟦H.eval_at x⟧ = |
| 160 | + hcast (H.apply_zero x).symm ≫ |
| 161 | +(πₘ H.ulift_map).map (prod_to_prod_Top_I uhpath01 (𝟙 x)) ≫ |
| 162 | +hcast (H.apply_one x).symm.symm := |
| 163 | +begin |
| 164 | + dunfold prod_to_prod_Top_I uhpath01 hcast, |
| 165 | + refine (@functor.conj_eq_to_hom_iff_heq (πₓ Y) _ _ _ _ _ _ _ _ _).mpr _, |
| 166 | + simp only [id_eq_path_refl, prod_to_prod_Top_map, path.homotopic.prod_lift, map_eq, |
| 167 | + ← path.homotopic.map_lift], |
| 168 | + apply path.homotopic.hpath_hext, intro, refl, |
| 169 | +end |
| 170 | + |
| 171 | +/- Finally, we show `d = f(p) ≫ H₁ = H₀ ≫ g(p)` -/ |
| 172 | +lemma eq_diag_path : |
| 173 | + (πₘ f).map p ≫ ⟦H.eval_at x₁⟧ = H.diagonal_path' p ∧ |
| 174 | + (⟦H.eval_at x₀⟧ ≫ (πₘ g).map p : from_top (f x₀) ⟶ from_top (g x₁)) = H.diagonal_path' p := |
| 175 | +begin |
| 176 | + rw [H.apply_zero_path, H.apply_one_path, H.eval_at_eq, H.eval_at_eq], |
| 177 | + dunfold prod_to_prod_Top_I, |
| 178 | + split; { slice_lhs 2 5 { simp [← category_theory.functor.map_comp], }, refl, }, |
| 179 | +end |
| 180 | + |
| 181 | +end continuous_map.homotopy |
| 182 | + |
| 183 | +namespace fundamental_groupoid_functor |
| 184 | +open category_theory |
| 185 | +open_locale fundamental_groupoid |
| 186 | +local attribute [instance] path.homotopic.setoid |
| 187 | + |
| 188 | +variables {X Y : Top.{u}} {f g : C(X, Y)} (H : continuous_map.homotopy f g) |
| 189 | + |
| 190 | +/-- Given a homotopy H : f ∼ g, we have an associated natural isomorphism between the induced |
| 191 | +functors `f` and `g` -/ |
| 192 | +def homotopic_maps_nat_iso : πₘ f ⟶ πₘ g := |
| 193 | +{ app := λ x, ⟦H.eval_at x⟧, |
| 194 | + naturality' := λ x y p, by rw [(H.eq_diag_path p).1, (H.eq_diag_path p).2] } |
| 195 | + |
| 196 | +instance : is_iso (homotopic_maps_nat_iso H) := by apply nat_iso.is_iso_of_is_iso_app |
| 197 | + |
| 198 | +open_locale continuous_map |
| 199 | + |
| 200 | +/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/ |
| 201 | +def equiv_of_homotopy_equiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := |
| 202 | +begin |
| 203 | + apply equivalence.mk |
| 204 | + (πₘ hequiv.to_fun : πₓ X ⥤ πₓ Y) |
| 205 | + (πₘ hequiv.inv_fun : πₓ Y ⥤ πₓ X); |
| 206 | + simp only [Groupoid.hom_to_functor, Groupoid.id_to_functor], |
| 207 | + { convert (as_iso (homotopic_maps_nat_iso hequiv.left_inv.some)).symm, |
| 208 | + exacts [((π).map_id X).symm, ((π).map_comp _ _).symm] }, |
| 209 | + { convert as_iso (homotopic_maps_nat_iso hequiv.right_inv.some), |
| 210 | + exacts [((π).map_comp _ _).symm, ((π).map_id Y).symm] }, |
| 211 | +end |
| 212 | + |
| 213 | +end fundamental_groupoid_functor |
0 commit comments