|
| 1 | +/- |
| 2 | +Copyright (c) 2023 Adam Topaz. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Adam Topaz |
| 5 | +-/ |
| 6 | + |
| 7 | +import Mathlib.CategoryTheory.Sites.SheafOfTypes |
| 8 | + |
| 9 | +/-! |
| 10 | +
|
| 11 | +# Coverages |
| 12 | +
|
| 13 | +A coverage `K` on a category `C` is a set of presieves associated to every object `X : C`, |
| 14 | +called "covering presieves". |
| 15 | +This collection must satisfy a certain "pullback compatibility" condition, saying that |
| 16 | +whenever `S` is a covering presieve on `X` and `f : Y ⟶ X` is a morphism, then there exists |
| 17 | +some covering sieve `T` on `Y` such that `T` factors through `S` along `f`. |
| 18 | +
|
| 19 | +The main difference between a coverage and a Grothendieck pretopology is that we *do not* |
| 20 | +require `C` to have pullbacks. |
| 21 | +This is useful, for example, when we want to consider the Grothendieck topology on the category |
| 22 | +of extremally disconnected sets in the context of condensed mathematics. |
| 23 | +
|
| 24 | +A more concrete example: If `ℬ` is a basis for a topology on a type `X` (in the sense of |
| 25 | +`TopologicalSpace.IsTopologicalBasis`) then it naturally induces a coverage on `Opens X` |
| 26 | +whose associated Grothendieck topology is the one induced by the topology |
| 27 | +on `X` generated by `ℬ`. (Project: Formalize this!) |
| 28 | +
|
| 29 | +## Main Definitions and Results: |
| 30 | +
|
| 31 | +All definitions are in the `CategoryTheory` namespace. |
| 32 | +
|
| 33 | +- `Coverage C`: The type of coverages on `C`. |
| 34 | +- `Coverage.ofGrothendieck C`: A function which associates a coverage to any Grothendieck topology. |
| 35 | +- `Coverage.toGrothendieck C`: A function which associates a Grothendieck topology to any coverage. |
| 36 | +- `Coverage.gi`: The two functions above form a Galois insertion. |
| 37 | +- `Presieve.isSheaf_coverage`: Given `K : Coverage C` with associated |
| 38 | + Grothendieck topology `J`, a `Type _`-valued presheaf on `C` is a sheaf for `K` if and only if |
| 39 | + it is a sheaf for `J`. |
| 40 | +
|
| 41 | +# References |
| 42 | +We don't follow any particular reference, but the arguments can probably be distilled from |
| 43 | +the following sources: |
| 44 | +- [Elephant]: *Sketches of an Elephant*, P. T. Johnstone: C2.1. |
| 45 | +- [nLab, *Coverage*](https://ncatlab.org/nlab/show/coverage) |
| 46 | +-/ |
| 47 | + |
| 48 | +namespace CategoryTheory |
| 49 | + |
| 50 | +variable {C : Type _} [Category C] |
| 51 | + |
| 52 | +namespace Presieve |
| 53 | + |
| 54 | +/-- |
| 55 | +Given a morphism `f : Y ⟶ X`, a presieve `S` on `Y` and presieve `T` on `X`, |
| 56 | +we say that *`S` factors through `T` along `f`*, written `S.FactorsThruAlong T f`, |
| 57 | +provided that for any morphism `g : Z ⟶ Y` in `S`, there exists some |
| 58 | +morphism `e : W ⟶ X` in `T` and some morphism `i : Z ⟶ W` such that the obvious |
| 59 | +square commutes: `i ≫ e = g ≫ f`. |
| 60 | +
|
| 61 | +This is used in the definition of a coverage. |
| 62 | +-/ |
| 63 | +def FactorsThruAlong {X Y : C} (S : Presieve Y) (T : Presieve X) (f : Y ⟶ X) : Prop := |
| 64 | + ∀ ⦃Z : C⦄ ⦃g : Z ⟶ Y⦄, S g → |
| 65 | + ∃ (W : C) (i : Z ⟶ W) (e : W ⟶ X), T e ∧ i ≫ e = g ≫ f |
| 66 | + |
| 67 | +/-- |
| 68 | +Given `S T : Presieve X`, we say that `S` factors through `T` if any morphism in `S` |
| 69 | +factors through some morphism in `T`. |
| 70 | +
|
| 71 | +The lemma `Presieve.isSheafFor_of_factorsThru` gives a *sufficient* condition for a |
| 72 | +presheaf to be a sheaf for a presieve `T`, in terms of `S.FactorsThru T`, provided |
| 73 | +that the presheaf is a sheaf for `S`. |
| 74 | +-/ |
| 75 | +def FactorsThru {X : C} (S T : Presieve X) : Prop := |
| 76 | + ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄, S g → |
| 77 | + ∃ (W : C) (i : Z ⟶ W) (e : W ⟶ X), T e ∧ i ≫ e = g |
| 78 | + |
| 79 | +@[simp] |
| 80 | +lemma factorsThruAlong_id {X : C} (S T : Presieve X) : |
| 81 | + S.FactorsThruAlong T (𝟙 X) ↔ S.FactorsThru T := by |
| 82 | + simp [FactorsThruAlong, FactorsThru] |
| 83 | + |
| 84 | +lemma factorsThru_of_le {X : C} (S T : Presieve X) (h : S ≤ T) : |
| 85 | + S.FactorsThru T := |
| 86 | + fun Y g hg => ⟨Y, 𝟙 _, g, h _ hg, by simp⟩ |
| 87 | + |
| 88 | +lemma le_of_factorsThru_sieve {X : C} (S : Presieve X) (T : Sieve X) (h : S.FactorsThru T) : |
| 89 | + S ≤ T := by |
| 90 | + rintro Y f hf |
| 91 | + obtain ⟨W, i, e, h1, rfl⟩ := h hf |
| 92 | + exact T.downward_closed h1 _ |
| 93 | + |
| 94 | +lemma factorsThru_top {X : C} (S : Presieve X) : S.FactorsThru ⊤ := |
| 95 | + factorsThru_of_le _ _ le_top |
| 96 | + |
| 97 | +lemma isSheafFor_of_factorsThru |
| 98 | + {X : C} {S T : Presieve X} |
| 99 | + (P : Cᵒᵖ ⥤ Type w) |
| 100 | + (H : S.FactorsThru T) (hS : S.IsSheafFor P) |
| 101 | + (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y), |
| 102 | + R.IsSeparatedFor P ∧ R.FactorsThruAlong S f): |
| 103 | + T.IsSheafFor P := by |
| 104 | + simp only [←Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at * |
| 105 | + choose W i e h1 h2 using H |
| 106 | + refine ⟨?_, fun x hx => ?_⟩ |
| 107 | + · intro x y₁ y₂ h₁ h₂ |
| 108 | + refine hS.1.ext (fun Y g hg => ?_) |
| 109 | + simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)] |
| 110 | + let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _)) |
| 111 | + have hy : y.Compatible := by |
| 112 | + intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h |
| 113 | + rw [← types_comp_apply (P.map (i h₁).op) (P.map g₁.op), |
| 114 | + ← types_comp_apply (P.map (i h₂).op) (P.map g₂.op), |
| 115 | + ← P.map_comp, ← op_comp, ← P.map_comp, ← op_comp] |
| 116 | + apply hx |
| 117 | + simp only [h2, h, Category.assoc] |
| 118 | + let ⟨_, h2'⟩ := hS |
| 119 | + obtain ⟨z, hz⟩ := h2' y hy |
| 120 | + refine ⟨z, fun Y g hg => ?_⟩ |
| 121 | + obtain ⟨R, hR1, hR2⟩ := h hg |
| 122 | + choose WW ii ee hh1 hh2 using hR2 |
| 123 | + refine hR1.ext (fun Q t ht => ?_) |
| 124 | + rw [← types_comp_apply (P.map g.op) (P.map t.op), ← P.map_comp, ← op_comp, ← hh2 ht, |
| 125 | + op_comp, P.map_comp, types_comp_apply, hz _ (hh1 _), |
| 126 | + ← types_comp_apply _ (P.map (ii ht).op), ← P.map_comp, ← op_comp] |
| 127 | + apply hx |
| 128 | + simp only [Category.assoc, h2, hh2] |
| 129 | + |
| 130 | + |
| 131 | +end Presieve |
| 132 | + |
| 133 | +variable (C) in |
| 134 | +/-- |
| 135 | +The type `Coverage C` of coverages on `C`. |
| 136 | +A coverage is a collection of *covering* presieves on every object `X : C`, |
| 137 | +which satisfies a *pullback compatibility* condition. |
| 138 | +Explicitly, this condition says that whenever `S` is a covering presieve for `X` and |
| 139 | +`f : Y ⟶ X` is a morphism, then there exists some covering presieve `T` for `Y` |
| 140 | +such that `T` factors through `S` along `f`. |
| 141 | +-/ |
| 142 | +@[ext] |
| 143 | +structure Coverage where |
| 144 | + /-- The collection of covering presieves for an object `X`. -/ |
| 145 | + covering : ∀ (X : C), Set (Presieve X) |
| 146 | + /-- Given any covering sieve `S` on `X` and a morphism `f : Y ⟶ X`, there exists |
| 147 | + some covering sieve `T` on `Y` such that `T` factors through `S` along `f`. -/ |
| 148 | + pullback : ∀ ⦃X Y : C⦄ (f : Y ⟶ X) (S : Presieve X) (_ : S ∈ covering X), |
| 149 | + ∃ (T : Presieve Y), T ∈ covering Y ∧ T.FactorsThruAlong S f |
| 150 | + |
| 151 | +namespace Coverage |
| 152 | + |
| 153 | +instance : CoeFun (Coverage C) (fun _ => (X : C) → Set (Presieve X)) where |
| 154 | + coe := covering |
| 155 | + |
| 156 | +variable (C) in |
| 157 | +/-- |
| 158 | +Associate a coverage to any Grothendieck topology. |
| 159 | +If `J` is a Grothendieck topology, and `K` is the associated coverage, then a presieve |
| 160 | +`S` is a covering presieve for `K` if and only if the sieve that it generates is a |
| 161 | +covering sieve for `J`. |
| 162 | +-/ |
| 163 | +def ofGrothendieck (J : GrothendieckTopology C) : Coverage C where |
| 164 | + covering X := { S | Sieve.generate S ∈ J X } |
| 165 | + pullback := by |
| 166 | + intro X Y f S (hS : Sieve.generate S ∈ J X) |
| 167 | + refine ⟨(Sieve.generate S).pullback f, ?_, fun Z g h => h⟩ |
| 168 | + dsimp |
| 169 | + rw [Sieve.generate_sieve] |
| 170 | + exact J.pullback_stable _ hS |
| 171 | + |
| 172 | +lemma ofGrothendieck_iff {X : C} {S : Presieve X} (J : GrothendieckTopology C) : |
| 173 | + S ∈ ofGrothendieck _ J X ↔ Sieve.generate S ∈ J X := Iff.rfl |
| 174 | + |
| 175 | +/-- |
| 176 | +An auxiliary definition used to define the Grothendieck topology associated to a |
| 177 | +coverage. See `Coverage.toGrothendieck`. |
| 178 | +-/ |
| 179 | +inductive saturate (K : Coverage C) : (X : C) → Sieve X → Prop where |
| 180 | + | of (X : C) (S : Presieve X) (hS : S ∈ K X) : saturate K X (Sieve.generate S) |
| 181 | + | top (X : C) : saturate K X ⊤ |
| 182 | + | transitive (X : C) (R S : Sieve X) : |
| 183 | + saturate K X R → |
| 184 | + (∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, R f → saturate K Y (S.pullback f)) → |
| 185 | + saturate K X S |
| 186 | + |
| 187 | +lemma eq_top_pullback {X Y : C} {S T : Sieve X} (h : S ≤ T) (f : Y ⟶ X) (hf : S f) : |
| 188 | + T.pullback f = ⊤ := by |
| 189 | + ext Z ; intro g |
| 190 | + simp only [Sieve.pullback_apply, Sieve.top_apply, iff_true] |
| 191 | + apply h |
| 192 | + apply S.downward_closed |
| 193 | + exact hf |
| 194 | + |
| 195 | +lemma saturate_of_superset (K : Coverage C) {X : C} {S T : Sieve X} (h : S ≤ T) |
| 196 | + (hS : saturate K X S) : saturate K X T := by |
| 197 | + apply saturate.transitive _ _ _ hS |
| 198 | + intro Y g hg |
| 199 | + rw [eq_top_pullback (h := h)] |
| 200 | + · apply saturate.top |
| 201 | + · assumption |
| 202 | + |
| 203 | +variable (C) in |
| 204 | +/-- |
| 205 | +The Grothendieck topology associated to a coverage `K`. |
| 206 | +It is defined *inductively* as follows: |
| 207 | +1. If `S` is a covering presieve for `K`, then the sieve generated by `S` is a covering |
| 208 | + sieve for the associated Grothendieck topology. |
| 209 | +2. The top sieves are in the associated Grothendieck topology. |
| 210 | +3. Add all sieves required by the *local character* axiom of a Grothendieck topology. |
| 211 | +
|
| 212 | +The pullback compatibility condition for a coverage ensures that the |
| 213 | +associated Grothendieck topology is pullback stable, and so an additional constructor |
| 214 | +in the inductive construction is not needed. |
| 215 | +-/ |
| 216 | +def toGrothendieck (K : Coverage C) : GrothendieckTopology C where |
| 217 | + sieves := saturate K |
| 218 | + top_mem' := .top |
| 219 | + pullback_stable' := by |
| 220 | + intro X Y S f hS |
| 221 | + induction hS generalizing Y with |
| 222 | + | of X S hS => |
| 223 | + obtain ⟨R,hR1,hR2⟩ := K.pullback f S hS |
| 224 | + suffices Sieve.generate R ≤ (Sieve.generate S).pullback f from |
| 225 | + saturate_of_superset _ this (saturate.of _ _ hR1) |
| 226 | + rintro Z g ⟨W, i, e, h1, h2⟩ |
| 227 | + obtain ⟨WW, ii, ee, hh1, hh2⟩ := hR2 h1 |
| 228 | + refine ⟨WW, i ≫ ii, ee, hh1, ?_⟩ |
| 229 | + simp only [hh2, reassoc_of% h2, Category.assoc] |
| 230 | + | top X => apply saturate.top |
| 231 | + | transitive X R S _ hS H1 _ => |
| 232 | + apply saturate.transitive |
| 233 | + apply H1 f |
| 234 | + intro Z g hg |
| 235 | + rw [← Sieve.pullback_comp] |
| 236 | + exact hS hg |
| 237 | + transitive' X S hS R hR := .transitive _ _ _ hS hR |
| 238 | + |
| 239 | +instance : PartialOrder (Coverage C) where |
| 240 | + le A B := A.covering ≤ B.covering |
| 241 | + le_refl A X := le_refl _ |
| 242 | + le_trans A B C h1 h2 X := le_trans (h1 X) (h2 X) |
| 243 | + le_antisymm A B h1 h2 := Coverage.ext A B <| funext <| |
| 244 | + fun X => le_antisymm (h1 X) (h2 X) |
| 245 | + |
| 246 | +variable (C) in |
| 247 | +/-- |
| 248 | +The two constructions `Coverage.toGrothendieck` and `Coverage.ofGrothendieck` form |
| 249 | +a Galois insertion. |
| 250 | +-/ |
| 251 | +def gi : GaloisInsertion (toGrothendieck C) (ofGrothendieck C) where |
| 252 | + choice K _ := toGrothendieck _ K |
| 253 | + choice_eq := fun _ _ => rfl |
| 254 | + le_l_u J X S hS := by |
| 255 | + rw [← Sieve.generate_sieve S] |
| 256 | + apply saturate.of |
| 257 | + dsimp [ofGrothendieck] |
| 258 | + rwa [Sieve.generate_sieve S] |
| 259 | + gc K J := by |
| 260 | + constructor |
| 261 | + · intro H X S hS |
| 262 | + exact H _ <| saturate.of _ _ hS |
| 263 | + · intro H X S hS |
| 264 | + induction hS with |
| 265 | + | of X S hS => exact H _ hS |
| 266 | + | top => apply J.top_mem |
| 267 | + | transitive X R S _ _ H1 H2 => exact J.transitive H1 _ H2 |
| 268 | + |
| 269 | +/-- |
| 270 | +An alternative characterization of the Grothendieck topology associated to a coverage `K`: |
| 271 | +it is the infimum of all Grothendieck topologies whose associated coverage contains `K`. |
| 272 | +-/ |
| 273 | +theorem toGrothendieck_eq_sInf (K : Coverage C) : toGrothendieck _ K = |
| 274 | + sInf {J | K ≤ ofGrothendieck _ J } := by |
| 275 | + apply le_antisymm |
| 276 | + · apply le_sInf ; intro J hJ |
| 277 | + intro X S hS |
| 278 | + induction hS with |
| 279 | + | of X S hS => apply hJ ; assumption |
| 280 | + | top => apply J.top_mem |
| 281 | + | transitive X R S _ _ H1 H2 => exact J.transitive H1 _ H2 |
| 282 | + · apply sInf_le |
| 283 | + intro X S hS |
| 284 | + apply saturate.of _ _ hS |
| 285 | + |
| 286 | +end Coverage |
| 287 | + |
| 288 | +open Coverage |
| 289 | + |
| 290 | +namespace Presieve |
| 291 | + |
| 292 | +/-- |
| 293 | +The main theorem of this file: Given a coverage `K` on `C`, |
| 294 | +a `Type _`-valued presheaf on `C` is a sheaf for `K` if and only if it is a sheaf for |
| 295 | +the assocaited Grothendieck topology. |
| 296 | +-/ |
| 297 | +theorem isSheaf_coverage (K : Coverage C) (P : Cᵒᵖ ⥤ Type w) : |
| 298 | + Presieve.IsSheaf (toGrothendieck _ K) P ↔ |
| 299 | + (∀ {X : C} (R : Presieve X), R ∈ K X → Presieve.IsSheafFor P R) := by |
| 300 | + constructor |
| 301 | + · intro H X R hR |
| 302 | + rw [Presieve.isSheafFor_iff_generate] |
| 303 | + apply H _ <| saturate.of _ _ hR |
| 304 | + · intro H X S hS |
| 305 | + -- This is the key point of the proof: |
| 306 | + -- We must generalize the induction in the correct way. |
| 307 | + suffices ∀ ⦃Y : C⦄ (f : Y ⟶ X), Presieve.IsSheafFor P (S.pullback f).arrows by |
| 308 | + simpa using this (f := 𝟙 _) |
| 309 | + induction hS with |
| 310 | + | of X S hS => |
| 311 | + intro Y f |
| 312 | + obtain ⟨T, hT1, hT2⟩ := K.pullback f S hS |
| 313 | + apply Presieve.isSheafFor_of_factorsThru (S := T) |
| 314 | + · intro Z g hg |
| 315 | + obtain ⟨W, i, e, h1, h2⟩ := hT2 hg |
| 316 | + exact ⟨Z, 𝟙 _, g, ⟨W, i, e, h1, h2⟩, by simp⟩ |
| 317 | + · apply H ; assumption |
| 318 | + · intro Z g _ |
| 319 | + obtain ⟨R, hR1, hR2⟩ := K.pullback g _ hT1 |
| 320 | + refine ⟨R, (H _ hR1).isSeparatedFor, hR2⟩ |
| 321 | + | top => intros ; simpa using Presieve.isSheafFor_top_sieve _ |
| 322 | + | transitive X R S _ _ H1 H2 => |
| 323 | + intro Y f |
| 324 | + simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at * |
| 325 | + choose H1 H1' using H1 |
| 326 | + choose H2 H2' using H2 |
| 327 | + refine ⟨?_, fun x hx => ?_⟩ |
| 328 | + · intro x t₁ t₂ h₁ h₂ |
| 329 | + refine (H1 f).ext (fun Z g hg => ?_) |
| 330 | + refine (H2 hg (𝟙 _)).ext (fun ZZ gg hgg => ?_) |
| 331 | + simp only [Sieve.pullback_id, Sieve.pullback_apply] at hgg |
| 332 | + simp only [← types_comp_apply] |
| 333 | + rw [← P.map_comp, ← op_comp, h₁, h₂] |
| 334 | + simpa only [Sieve.pullback_apply, Category.assoc] using hgg |
| 335 | + let y : ∀ ⦃Z : C⦄ (g : Z ⟶ Y), |
| 336 | + ((S.pullback (g ≫ f)).pullback (𝟙 _)).arrows.FamilyOfElements P := |
| 337 | + fun Z g ZZ gg hgg => x (gg ≫ g) (by simpa using hgg) |
| 338 | + have hy : ∀ ⦃Z : C⦄ (g : Z ⟶ Y), (y g).Compatible := by |
| 339 | + intro Z g Y₁ Y₂ ZZ g₁ g₂ f₁ f₂ h₁ h₂ h |
| 340 | + rw [hx] |
| 341 | + rw [reassoc_of% h] |
| 342 | + choose z hz using fun ⦃Z : C⦄ ⦃g : Z ⟶ Y⦄ (hg : R.pullback f g) => |
| 343 | + H2' hg (𝟙 _) (y g) (hy g) |
| 344 | + let q : (R.pullback f).arrows.FamilyOfElements P := fun Z g hg => z hg |
| 345 | + have hq : q.Compatible := by |
| 346 | + intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h |
| 347 | + apply (H2 h₁ g₁).ext |
| 348 | + intro ZZ gg hgg |
| 349 | + simp only [← types_comp_apply] |
| 350 | + rw [← P.map_comp, ← P.map_comp, ← op_comp, ← op_comp, hz, hz] |
| 351 | + · dsimp ; congr 1 ; simp only [Category.assoc, h] |
| 352 | + · simpa [reassoc_of% h] using hgg |
| 353 | + · simpa using hgg |
| 354 | + obtain ⟨t, ht⟩ := H1' f q hq |
| 355 | + refine ⟨t, fun Z g hg => ?_⟩ |
| 356 | + refine (H1 (g ≫ f)).ext (fun ZZ gg hgg => ?_) |
| 357 | + rw [← types_comp_apply _ (P.map gg.op), ← P.map_comp, ← op_comp, ht] |
| 358 | + swap ; simpa using hgg |
| 359 | + refine (H2 hgg (𝟙 _)).ext (fun ZZZ ggg hggg => ?_) |
| 360 | + rw [← types_comp_apply _ (P.map ggg.op), ← P.map_comp, ← op_comp, hz] |
| 361 | + swap ; simpa using hggg |
| 362 | + refine (H2 hgg ggg).ext (fun ZZZZ gggg _ => ?_) |
| 363 | + rw [← types_comp_apply _ (P.map gggg.op), ← P.map_comp, ← op_comp] |
| 364 | + apply hx |
| 365 | + simp |
| 366 | + |
| 367 | +end Presieve |
| 368 | + |
| 369 | +end CategoryTheory |
0 commit comments