|
| 1 | +/- |
| 2 | +Copyright (c) 2020 Bhavik Mehta. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Bhavik Mehta |
| 5 | +-/ |
| 6 | +import category_theory.sites.sheaf_of_types |
| 7 | +import order.closure |
| 8 | + |
| 9 | +/-! |
| 10 | +# Closed sieves |
| 11 | +
|
| 12 | +A natural closure operator on sieves is a closure operator on `sieve X` for each `X` which commutes |
| 13 | +with pullback. |
| 14 | +We show that a Grothendieck topology `J` induces a natural closure operator, and define what the |
| 15 | +closed sieves are. The collection of `J`-closed sieves forms a presheaf which is a sheaf for `J`, |
| 16 | +and further this presheaf can be used to determine the Grothendieck topology from the sheaf |
| 17 | +predicate. |
| 18 | +Finally we show that a natural closure operator on sieves induces a Grothendieck topology, and hence |
| 19 | +that natural closure operators are in bijection with Grothendieck topologies. |
| 20 | +
|
| 21 | +## Main definitions |
| 22 | +
|
| 23 | +* `category_theory.grothendieck_topology.close`: Sends a sieve `S` on `X` to the set of arrows |
| 24 | + which it covers. This has all the usual properties of a closure operator, as well as commuting |
| 25 | + with pullback. |
| 26 | +* `category_theory.grothendieck_topology.closure_operator`: The bundled `closure_operator` given |
| 27 | + by `category_theory.grothendieck_topology.close`. |
| 28 | +* `category_theory.grothendieck_topology.closed`: A sieve `S` on `X` is closed for the topology `J` |
| 29 | + if it contains every arrow it covers. |
| 30 | +* `category_theory.functor.closed_sieves`: The presheaf sending `X` to the collection of `J`-closed |
| 31 | + sieves on `X`. This is additionally shown to be a sheaf for `J`, and if this is a sheaf for a |
| 32 | + different topology `J'`, then `J' ≤ J`. |
| 33 | +* `category_theory.grothendieck_topology.topology_of_closure_operator`: A closure operator on the |
| 34 | + set of sieves on every object which commutes with pullback additionally induces a Grothendieck |
| 35 | + topology, giving a bijection with `category_theory.grothendieck_topology.closure_operator`. |
| 36 | +
|
| 37 | +
|
| 38 | +## Tags |
| 39 | +
|
| 40 | +closed sieve, closure, Grothendieck topology |
| 41 | +
|
| 42 | +## References |
| 43 | +
|
| 44 | +* [S. MacLane, I. Moerdijk, *Sheaves in Geometry and Logic*][MM92] |
| 45 | +-/ |
| 46 | + |
| 47 | +universes v u |
| 48 | + |
| 49 | +namespace category_theory |
| 50 | + |
| 51 | +variables {C : Type u} [small_category C] |
| 52 | + |
| 53 | +variables {P : Cᵒᵖ ⥤ Type u} |
| 54 | +variables (J₁ J₂ : grothendieck_topology C) |
| 55 | + |
| 56 | +namespace grothendieck_topology |
| 57 | + |
| 58 | +/-- The `J`-closure of a sieve is the collection of arrows which it covers. -/ |
| 59 | +@[simps] |
| 60 | +def close {X : C} (S : sieve X) : sieve X := |
| 61 | +{ arrows := λ Y f, J₁.covers S f, |
| 62 | + downward_closed' := λ Y Z f hS, J₁.arrow_stable _ _ hS } |
| 63 | + |
| 64 | +/-- Any sieve is smaller than its closure. -/ |
| 65 | +lemma le_close {X : C} (S : sieve X) : S ≤ J₁.close S := |
| 66 | +λ Y g hg, J₁.covering_of_eq_top (S.pullback_eq_top_of_mem hg) |
| 67 | + |
| 68 | +/-- |
| 69 | +A sieve is closed for the Grothendieck topology if it contains every arrow it covers. |
| 70 | +In the case of the usual topology on a topological space, this means that the open cover contains |
| 71 | +every open set which it covers. |
| 72 | +
|
| 73 | +Note this has no relation to a closed subset of a topological space. |
| 74 | +-/ |
| 75 | +def is_closed {X : C} (S : sieve X) : Prop := |
| 76 | +∀ ⦃Y : C⦄ (f : Y ⟶ X), J₁.covers S f → S f |
| 77 | + |
| 78 | +/-- If `S` is `J₁`-closed, then `S` covers exactly the arrows it contains. -/ |
| 79 | +lemma covers_iff_mem_of_closed {X : C} {S : sieve X} |
| 80 | + (h : J₁.is_closed S) {Y : C} (f : Y ⟶ X) : |
| 81 | + J₁.covers S f ↔ S f := |
| 82 | +⟨h _, J₁.arrow_max _ _⟩ |
| 83 | + |
| 84 | +/-- Being `J`-closed is stable under pullback. -/ |
| 85 | +lemma is_closed_pullback {X Y : C} (f : Y ⟶ X) (S : sieve X) : |
| 86 | + J₁.is_closed S → J₁.is_closed (S.pullback f) := |
| 87 | +λ hS Z g hg, hS (g ≫ f) (by rwa [J₁.covers_iff, sieve.pullback_comp]) |
| 88 | + |
| 89 | +/-- |
| 90 | +The closure of a sieve `S` is the largest closed sieve which contains `S` (justifying the name |
| 91 | +"closure"). |
| 92 | +-/ |
| 93 | +lemma le_close_of_is_closed {X : C} {S T : sieve X} |
| 94 | + (h : S ≤ T) (hT : J₁.is_closed T) : |
| 95 | + J₁.close S ≤ T := |
| 96 | +λ Y f hf, hT _ (J₁.superset_covering (sieve.pullback_monotone f h) hf) |
| 97 | + |
| 98 | +/-- The closure of a sieve is closed. -/ |
| 99 | +lemma close_is_closed {X : C} (S : sieve X) : J₁.is_closed (J₁.close S) := |
| 100 | +λ Y g hg, J₁.arrow_trans g _ S hg (λ Z h hS, hS) |
| 101 | + |
| 102 | +/-- The sieve `S` is closed iff its closure is equal to itself. -/ |
| 103 | +lemma is_closed_iff_close_eq_self {X : C} (S : sieve X) : |
| 104 | + J₁.is_closed S ↔ J₁.close S = S := |
| 105 | +begin |
| 106 | + split, |
| 107 | + { intro h, |
| 108 | + apply le_antisymm, |
| 109 | + { intros Y f hf, |
| 110 | + rw ← J₁.covers_iff_mem_of_closed h, |
| 111 | + apply hf }, |
| 112 | + { apply J₁.le_close } }, |
| 113 | + { intro e, |
| 114 | + rw ← e, |
| 115 | + apply J₁.close_is_closed } |
| 116 | +end |
| 117 | + |
| 118 | +lemma close_eq_self_of_is_closed {X : C} {S : sieve X} (hS : J₁.is_closed S) : |
| 119 | + J₁.close S = S := |
| 120 | +(J₁.is_closed_iff_close_eq_self S).1 hS |
| 121 | + |
| 122 | +/-- Closing under `J` is stable under pullback. -/ |
| 123 | +lemma pullback_close {X Y : C} (f : Y ⟶ X) (S : sieve X) : |
| 124 | + J₁.close (S.pullback f) = (J₁.close S).pullback f := |
| 125 | +begin |
| 126 | + apply le_antisymm, |
| 127 | + { refine J₁.le_close_of_is_closed (sieve.pullback_monotone _ (J₁.le_close S)) _, |
| 128 | + apply J₁.is_closed_pullback _ _ (J₁.close_is_closed _) }, |
| 129 | + { intros Z g hg, |
| 130 | + change _ ∈ J₁ _, |
| 131 | + rw ← sieve.pullback_comp, |
| 132 | + apply hg } |
| 133 | +end |
| 134 | + |
| 135 | +@[mono] |
| 136 | +lemma monotone_close {X : C} : |
| 137 | + monotone (J₁.close : sieve X → sieve X) := |
| 138 | +λ S₁ S₂ h, J₁.le_close_of_is_closed (h.trans (J₁.le_close _)) (J₁.close_is_closed S₂) |
| 139 | + |
| 140 | +@[simp] |
| 141 | +lemma close_close {X : C} (S : sieve X) : |
| 142 | + J₁.close (J₁.close S) = J₁.close S := |
| 143 | +le_antisymm |
| 144 | + (J₁.le_close_of_is_closed (le_refl _) (J₁.close_is_closed S)) |
| 145 | + (J₁.monotone_close (J₁.le_close _)) |
| 146 | + |
| 147 | +/-- |
| 148 | +The sieve `S` is in the topology iff its closure is the maximal sieve. This shows that the closure |
| 149 | +operator determines the topology. |
| 150 | +-/ |
| 151 | +lemma close_eq_top_iff_mem {X : C} (S : sieve X) : |
| 152 | + J₁.close S = ⊤ ↔ S ∈ J₁ X := |
| 153 | +begin |
| 154 | + split, |
| 155 | + { intro h, |
| 156 | + apply J₁.transitive (J₁.top_mem X), |
| 157 | + intros Y f hf, |
| 158 | + change J₁.close S f, |
| 159 | + rwa h }, |
| 160 | + { intro hS, |
| 161 | + rw eq_top_iff, |
| 162 | + intros Y f hf, |
| 163 | + apply J₁.pullback_stable _ hS } |
| 164 | +end |
| 165 | + |
| 166 | +/-- A Grothendieck topology induces a natural family of closure operators on sieves. -/ |
| 167 | +@[simps {rhs_md := semireducible}] |
| 168 | +def closure_operator (X : C) : closure_operator (sieve X) := |
| 169 | +closure_operator.mk' |
| 170 | + J₁.close |
| 171 | + (λ S₁ S₂ h, J₁.le_close_of_is_closed (h.trans (J₁.le_close _)) (J₁.close_is_closed S₂)) |
| 172 | + J₁.le_close |
| 173 | + (λ S, J₁.le_close_of_is_closed (le_refl _) (J₁.close_is_closed S)) |
| 174 | + |
| 175 | +@[simp] |
| 176 | +lemma closed_iff_closed {X : C} (S : sieve X) : |
| 177 | + S ∈ (J₁.closure_operator X).closed ↔ J₁.is_closed S := |
| 178 | +(J₁.is_closed_iff_close_eq_self S).symm |
| 179 | + |
| 180 | +end grothendieck_topology |
| 181 | + |
| 182 | +/-- |
| 183 | +The presheaf sending each object to the set of `J`-closed sieves on it. This presheaf is a `J`-sheaf |
| 184 | +(and will turn out to be a subobject classifier for the category of `J`-sheaves). |
| 185 | +-/ |
| 186 | +@[simps] |
| 187 | +def functor.closed_sieves : Cᵒᵖ ⥤ Type u := |
| 188 | +{ obj := λ X, {S : sieve X.unop // J₁.is_closed S}, |
| 189 | + map := λ X Y f S, ⟨S.1.pullback f.unop, J₁.is_closed_pullback f.unop _ S.2⟩ } |
| 190 | + |
| 191 | +/-- |
| 192 | +The presheaf of `J`-closed sieves is a `J`-sheaf. |
| 193 | +The proof of this is adapted from [MM92], Chatper III, Section 7, Lemma 1. |
| 194 | +-/ |
| 195 | +lemma classifier_is_sheaf : presieve.is_sheaf J₁ (functor.closed_sieves J₁) := |
| 196 | +begin |
| 197 | + intros X S hS, |
| 198 | + rw ← presieve.is_separated_for_and_exists_is_amalgamation_iff_sheaf_for, |
| 199 | + refine ⟨_, _⟩, |
| 200 | + { rintro x ⟨M, hM⟩ ⟨N, hN⟩ hM₂ hN₂, |
| 201 | + ext, |
| 202 | + dsimp only [subtype.coe_mk], |
| 203 | + rw [← J₁.covers_iff_mem_of_closed hM, ← J₁.covers_iff_mem_of_closed hN], |
| 204 | + have q : ∀ ⦃Z : C⦄ (g : Z ⟶ X) (hg : S g), M.pullback g = N.pullback g, |
| 205 | + { intros Z g hg, |
| 206 | + apply congr_arg subtype.val ((hM₂ g hg).trans (hN₂ g hg).symm) }, |
| 207 | + have MSNS : M ⊓ S = N ⊓ S, |
| 208 | + { ext Z g, |
| 209 | + rw [sieve.inter_apply, sieve.inter_apply, and_comm (N g), and_comm], |
| 210 | + apply and_congr_right, |
| 211 | + intro hg, |
| 212 | + rw [sieve.pullback_eq_top_iff_mem, sieve.pullback_eq_top_iff_mem, q g hg] }, |
| 213 | + split, |
| 214 | + { intro hf, |
| 215 | + rw J₁.covers_iff, |
| 216 | + apply J₁.superset_covering (sieve.pullback_monotone f inf_le_left), |
| 217 | + rw ← MSNS, |
| 218 | + apply J₁.arrow_intersect f M S hf (J₁.pullback_stable _ hS) }, |
| 219 | + { intro hf, |
| 220 | + rw J₁.covers_iff, |
| 221 | + apply J₁.superset_covering (sieve.pullback_monotone f inf_le_left), |
| 222 | + rw MSNS, |
| 223 | + apply J₁.arrow_intersect f N S hf (J₁.pullback_stable _ hS) } }, |
| 224 | + { intros x hx, |
| 225 | + rw presieve.compatible_iff_sieve_compatible at hx, |
| 226 | + let M := sieve.bind S (λ Y f hf, (x f hf).1), |
| 227 | + have : ∀ ⦃Y⦄ (f : Y ⟶ X) (hf : S f), M.pullback f = (x f hf).1, |
| 228 | + { intros Y f hf, |
| 229 | + apply le_antisymm, |
| 230 | + { rintro Z u ⟨W, g, f', hf', (hg : (x f' hf').1 _), c⟩, |
| 231 | + rw [sieve.pullback_eq_top_iff_mem, |
| 232 | + ←(show (x (u ≫ f) _).1 = (x f hf).1.pullback u, from congr_arg subtype.val (hx f u hf))], |
| 233 | + simp_rw ← c, |
| 234 | + rw (show (x (g ≫ f') _).1 = _, from congr_arg subtype.val (hx f' g hf')), |
| 235 | + apply sieve.pullback_eq_top_of_mem _ hg }, |
| 236 | + { apply sieve.le_pullback_bind S (λ Y f hf, (x f hf).1) } }, |
| 237 | + refine ⟨⟨_, J₁.close_is_closed M⟩, _⟩, |
| 238 | + { intros Y f hf, |
| 239 | + ext1, |
| 240 | + dsimp, |
| 241 | + rw [← J₁.pullback_close, this _ hf], |
| 242 | + apply le_antisymm (J₁.le_close_of_is_closed (le_refl _) (x f hf).2) (J₁.le_close _) } }, |
| 243 | +end |
| 244 | + |
| 245 | +/-- |
| 246 | +If presheaf of `J₁`-closed sieves is a `J₂`-sheaf then `J₁ ≤ J₂`. Note the converse is true by |
| 247 | +`classifier_is_sheaf` and `is_sheaf_of_le`. |
| 248 | +-/ |
| 249 | +lemma le_topology_of_closed_sieves_is_sheaf {J₁ J₂ : grothendieck_topology C} |
| 250 | + (h : presieve.is_sheaf J₁ (functor.closed_sieves J₂)) : |
| 251 | + J₁ ≤ J₂ := |
| 252 | +λ X S hS, |
| 253 | +begin |
| 254 | + rw ← J₂.close_eq_top_iff_mem, |
| 255 | + have : J₂.is_closed (⊤ : sieve X), |
| 256 | + { intros Y f hf, |
| 257 | + trivial }, |
| 258 | + suffices : (⟨J₂.close S, J₂.close_is_closed S⟩ : subtype _) = ⟨⊤, this⟩, |
| 259 | + { rw subtype.ext_iff at this, |
| 260 | + exact this }, |
| 261 | + apply (h S hS).is_separated_for.ext, |
| 262 | + { intros Y f hf, |
| 263 | + ext1, |
| 264 | + dsimp, |
| 265 | + rw [sieve.pullback_top, ← J₂.pullback_close, S.pullback_eq_top_of_mem hf, |
| 266 | + J₂.close_eq_top_iff_mem], |
| 267 | + apply J₂.top_mem }, |
| 268 | +end |
| 269 | + |
| 270 | +/-- If being a sheaf for `J₁` is equivalent to being a sheaf for `J₂`, then `J₁ = J₂`. -/ |
| 271 | +lemma topology_eq_iff_same_sheaves {J₁ J₂ : grothendieck_topology C} : |
| 272 | + J₁ = J₂ ↔ (∀ P, presieve.is_sheaf J₁ P ↔ presieve.is_sheaf J₂ P) := |
| 273 | +begin |
| 274 | + split, |
| 275 | + { rintro rfl, |
| 276 | + intro P, |
| 277 | + refl }, |
| 278 | + { intro h, |
| 279 | + apply le_antisymm, |
| 280 | + { apply le_topology_of_closed_sieves_is_sheaf, |
| 281 | + rw h, |
| 282 | + apply classifier_is_sheaf }, |
| 283 | + { apply le_topology_of_closed_sieves_is_sheaf, |
| 284 | + rw ← h, |
| 285 | + apply classifier_is_sheaf } } |
| 286 | +end |
| 287 | + |
| 288 | +/-- |
| 289 | +A closure (increasing, inflationary and idempotent) operation on sieves that commutes with pullback |
| 290 | +induces a Grothendieck topology. |
| 291 | +In fact, such operations are in bijection with Grothendieck topologies. |
| 292 | +-/ |
| 293 | +@[simps] |
| 294 | +def topology_of_closure_operator |
| 295 | + (c : Π (X : C), closure_operator (sieve X)) |
| 296 | + (hc : Π ⦃X Y : C⦄ (f : Y ⟶ X) (S : sieve X), c _ (S.pullback f) = (c _ S).pullback f) : |
| 297 | + grothendieck_topology C := |
| 298 | +{ sieves := λ X, {S | c X S = ⊤}, |
| 299 | + top_mem' := λ X, top_unique ((c X).le_closure _), |
| 300 | + pullback_stable' := λ X Y S f hS, |
| 301 | + begin |
| 302 | + rw set.mem_set_of_eq at hS, |
| 303 | + rw [set.mem_set_of_eq, hc, hS, sieve.pullback_top], |
| 304 | + end, |
| 305 | + transitive' := λ X S hS R hR, |
| 306 | + begin |
| 307 | + rw set.mem_set_of_eq at hS, |
| 308 | + rw [set.mem_set_of_eq, ←(c X).idempotent, eq_top_iff, ←hS], |
| 309 | + apply (c X).monotone (λ Y f hf, _), |
| 310 | + rw [sieve.pullback_eq_top_iff_mem, ←hc], |
| 311 | + apply hR hf, |
| 312 | + end } |
| 313 | + |
| 314 | +/-- |
| 315 | +The topology given by the closure operator `J.close` on a Grothendieck topology is the same as `J`. |
| 316 | +-/ |
| 317 | +lemma topology_of_closure_operator_self : |
| 318 | + topology_of_closure_operator J₁.closure_operator (λ X Y, J₁.pullback_close) = J₁ := |
| 319 | +begin |
| 320 | + ext X S, |
| 321 | + apply grothendieck_topology.close_eq_top_iff_mem, |
| 322 | +end |
| 323 | + |
| 324 | +lemma topology_of_closure_operator_close |
| 325 | + (c : Π (X : C), closure_operator (sieve X)) |
| 326 | + (pb : Π ⦃X Y : C⦄ (f : Y ⟶ X) (S : sieve X), c Y (S.pullback f) = (c X S).pullback f) |
| 327 | + (X : C) (S : sieve X) : |
| 328 | + (topology_of_closure_operator c pb).close S = c X S := |
| 329 | +begin |
| 330 | + ext, |
| 331 | + change c _ (sieve.pullback f S) = ⊤ ↔ c _ S f, |
| 332 | + rw [pb, sieve.pullback_eq_top_iff_mem], |
| 333 | +end |
| 334 | + |
| 335 | +end category_theory |
0 commit comments