module Cat.Site.Closure where
Closure properties of sites🔗
module _ {o ℓ ℓs} {C : Precategory o ℓ} (A : Functor (C ^op) (Sets ℓs)) where
open Cat C
open Section
open Patch
open is-sheaf
private module A = Psh A
If is a sheaf on a site then there are quite a few sieves for which is a sheaf but which are not required to be present in Put another way, the collection of sieves for which a given functor is a sheaf enjoys closure properties beyond the basic pullback-stability which we have assumed in the definition of coverage. Closing under these extra constructions does not change the theory of “sheaves on ”, and sometimes they’re quite convenient!
In reality, the first few of these properties don’t even need a site: they work for a completely arbitrary functor We will fix a completely arbitrary functor for the remainder of this section. The first thing we note is that, if a sieve contains the identity, then is a sheaf for
: ∀ {U} {S : Sieve C U} → id ∈ S → is-sheaf₁ A S
is-sheaf-maximal {S = S} id∈S p .centre .whole = p .part id id∈S
is-sheaf-maximal {S = S} id∈S p .centre .glues f hf =
is-sheaf-maximal .part id id∈S ≡⟨ p .patch id id∈S f (subst (_∈ S) (sym (idl f)) hf) ⟩
A ⟪ f ⟫ p .part (id ∘ f) _ ≡⟨ app p (idl f) ⟩
p .part f hf ∎
p {S = S} id∈S p .paths x = ext $
is-sheaf-maximal .part id id∈S ≡˘⟨ x .glues id id∈S ⟩
p .whole ≡⟨ A.F-id ⟩
A ⟪ id ⟫ x .whole ∎ x
Since sieves are closed under composition, this can be extended to any which contains an isomorphism. Intuitively, this is because any sieve on which contains the identity (or an isomorphism) says that global data on can be constructed locally… on all of We can thus just extract this not-actually-local data from a given patch.
: ∀ {V U} {S : Sieve C U} (f : V ≅ U) → f .to ∈ S → is-sheaf₁ A S
is-sheaf-iso {S = S} f hf = is-sheaf-maximal $
is-sheaf-iso (_∈ S) (f .invl) (S .closed hf (f .from)) subst
The second notion we investigate says that the notion of sheaf is, itself, local: If is a sheaf for a sieve and we have some other sieve which we want to show is a sheaf for, it (almost) suffices to show that A is an for every If and are not part of a site, then this condition does not suffice: we also require that be for every
In the Elephant, this lemma appears as C2.1.7. However, Johnstone’s version is incorrect as stated. It can be remedied by assuming that belongs to a site for which is a sheaf, since a sheaf on a site is automatically separated for any pullback of a covering sieve.
is-sheaf-transitive: ∀ {U} {R S : Sieve C U}
→ (∀ {V} (f : Hom V U) (hf : f ∈ S) → is-separated₁ A (pullback f R))
→ (∀ {V} (f : Hom V U) (hf : f ∈ R) → is-sheaf₁ A (pullback f S))
→ is-sheaf₁ A R
→ is-sheaf₁ A S
{U} {R} {S} R*sep S*sheaf Rsheaf p = q where is-sheaf-transitive
The proof is slightly complicated. Note that a patch on can be pulled back to give a patch on for any Since is an at each in there is a unique and a short calculation shows that these give a patch on
: ∀ {V} (f : Hom V U) → Patch A (pullback f S)
p' = pullback-patch f p
p' f
: Patch A R
p'' .part f hf = S*sheaf f hf (p' f) .centre .whole
p'' .patch f hf g hgf = ext $ is-sheaf₁→is-separated₁ A _ (S*sheaf (f ∘ g) hgf) λ h hh →
p'' (A ⟪ g ⟫ (p'' .part f hf)) ≡⟨ A.collapse refl ⟩
A ⟪ h ⟫ (p'' .part f hf) ≡⟨ S*sheaf f hf (p' f) .centre .glues (g ∘ h) (subst (_∈ S) (sym (assoc f g h)) hh) ⟩
A ⟪ g ∘ h ⟫ .part (f ∘ g ∘ h) _ ≡⟨ app p (assoc _ _ _) ⟩
p .part ((f ∘ g) ∘ h) _ ≡˘⟨ S*sheaf (f ∘ g) hgf (p' (f ∘ g)) .centre .glues h hh ⟩
p .₁ h (p'' .part (f ∘ g) hgf) ∎
A
: Section A p''
s = Rsheaf p'' .centre s
By assumption, is an so our patch on glues to give an element — a section of even. We must now show that for Since only agrees with this might be a problem: that’s where the assumption that is comes in (for we can reduce this to showing with We would almost be in trouble again, since is only characterised but we can appeal to separatedness again, this time at This finally allows the calculation to go through:
: is-contr (Section A p)
q .centre .whole = s .whole
q .centre .glues f hf = R*sep f hf λ g hg → is-sheaf₁→is-separated₁ A _ (S*sheaf (f ∘ g) hg) λ h hh →
q (A ⟪ g ⟫ (A ⟪ f ⟫ s .whole)) ≡⟨ A.ap (A.collapse refl ∙ Rsheaf p'' .centre .glues (f ∘ g) hg) ⟩
A ⟪ h ⟫ .part (f ∘ g) hg ≡⟨ S*sheaf (f ∘ g) hg (p' (f ∘ g)) .centre .glues h hh ⟩
A ⟪ h ⟫ p'' .part ((f ∘ g) ∘ h) hh ≡˘⟨ app p (assoc f g h) ⟩
p .part (f ∘ g ∘ h) _ ≡˘⟨ p .patch f hf (g ∘ h) (subst (_∈ S) (sym (assoc f g h)) hh) ⟩
p (p .part f hf) ≡⟨ A.expand refl ⟩
A ⟪ g ∘ h ⟫ (A ⟪ g ⟫ p .part f hf) ∎
A ⟪ h ⟫ .paths x = ext $ ap whole $ Rsheaf p'' .paths
q record { glues = λ f hf → sym $ ap whole (S*sheaf f hf (p' f) .paths
record { glues = λ g hg → A.collapse refl ∙ x .glues (f ∘ g) hg }) }
module
_ {o ℓ ℓs ℓc} {C : Precategory o ℓ} {J : Coverage C ℓc}
{A : Functor (C ^op) (Sets ℓs)} (shf : is-sheaf J A)
where
open Precategory C
open is-sheaf
open Section
open Patch
private
module A = Psh A
module shf = is-sheaf shf
On a site🔗
Now specialising to a site and a functor which is a we can show a few more pedestrian closure properties. First, is a sheaf for any sieve that contains a sieve (call it
is-sheaf-factor: ∀ {U} (s : Sieve C U) (c : J # U)
→ (∀ {V} (f : Hom V U) → f ∈ J .cover c → f ∈ s)
→ is-sheaf₁ A s
= done where
is-sheaf-factor s c c⊆s ps = shf.split (subset→patch c⊆s ps) sec'
If is a patch on and contains we can restrict to a patch on Gluing we obtain a section for Showing this requires using the pullback-stability of though: We must show that for but is only characterised for
: Section A ps
sec .whole = sec' .whole sec
However, by passing to the pullback sieve we’re allowed to show this assuming that we have some with The calculation goes through without problems:
.glues f hf = ∥-∥-out! do
sec (c' , sub) ← J .stable c f
.separate c' λ g hg →
pure $ shf(A ⟪ f ⟫ sec' .whole) ≡⟨ A.collapse refl ⟩
A ⟪ g ⟫ .whole ≡⟨ sec' .glues (f ∘ g) (sub _ hg) ⟩
A ⟪ f ∘ g ⟫ sec' .part (f ∘ g) _ ≡˘⟨ ps .patch f hf g (c⊆s (f ∘ g) (sub g hg)) ⟩
ps .part f hf ∎
A ⟪ g ⟫ ps
: is-contr (Section A ps)
done .centre = sec
done .paths x = ext $ shf.separate c λ f hf →
done .whole ≡⟨ sec' .glues f hf ⟩
A ⟪ f ⟫ sec' .part f _ ≡˘⟨ x .glues f (c⊆s f hf) ⟩
ps .whole ∎ A ⟪ f ⟫ x
As a specialisation of the lemma above, we can show that is a sheaf for the pullback of any sieve. This is sharper than the pullback-stability property, but they differ exactly by the theorem above!
is-sheaf-pullback: ∀ {V U} (c : J # U) (f : Hom V U) → is-sheaf₁ A (pullback f (J .cover c))
= ∥-∥-out! do
is-sheaf-pullback c f p (c' , sub) ← J .stable c f
(is-sheaf-factor (pullback f (J .cover c)) c' sub p) pure
Saturating sites🔗
module _ {o ℓ ℓs} {C : Precategory o ℓ} where
open Precategory C using (Hom ; id ; _∘_)
Putting the two previous batches of lemmas together, given a site
we can define by induction a new site
which definitionally enjoys these extra closure properties, but which
has exactly the same sheaves as
in the code, we refer to this as the Saturation
of
This is actually a pretty simple process:
data _∋_ (J : Coverage C ℓs) : {U : ⌞ C ⌟} → Sieve C U → Type (o ⊔ ℓ ⊔ ℓs) where
: {U : ⌞ C ⌟} (c : J ʻ U) → J ∋ J .cover c
inc
: ∀ {U} {R : Sieve C U} → id ∈ R → J ∋ R
max
local: ∀ {U R} (hr : J ∋ R) {S : Sieve C U}
→ (∀ {V} (f : Hom V U) (hf : f ∈ R) → J ∋ pullback f S)
→ J ∋ S
: ∀ {U V} (h : Hom V U) {R : Sieve C U} (hr : J ∋ R) → J ∋ pullback h R
pull
: ∀ {U} {R : Sieve C U} → is-prop (J ∋ R) squash
In addition to the constructor which ensures that a sieve is each of the constructors corresponds exactly to one of the lemmas above:
max
corresponds tois-sheaf-maximal
;local
corresponds tois-sheaf-transitive
;pull
corresponds tois-sheaf-pullback
.
Note that is-sheaf-factor
can be
derived, instead of being a constructor, as shown below. We also
truncate this type to ensure that a sieve belongs to the saturation in
at most one way.
abstract
incl: ∀ {J : Coverage C ℓs} {U} {R S : Sieve C U}
→ S ⊆ R → J ∋ S → J ∋ R
{J = J} {S = S} sr us = local us λ f hf → subst (J ∋_) refl $
incl (f ∘ id) (S .closed hf id) max $ sr
∋-intersect: ∀ {J : Coverage C ℓs} {U} {R S : Sieve C U}
→ J ∋ R → J ∋ S → J ∋ (R ∩S S)
{J = J} {R = R} {S = S} α β = local β
∋-intersect (λ {V} f hf → subst (J ∋_) (ext (λ h → biimp (λ fhR → fhR , S .closed hf _) fst)) (pull f α))
: Coverage C ℓs → Coverage C (o ⊔ ℓ ⊔ ℓs)
Saturation = from-stable-property (J ∋_) λ f R s → pull f s Saturation J
instance
: ∀ {J : Coverage C ℓs} {U} {S : Sieve C U} {n} → H-Level (J ∋ S) (suc n)
H-Level-∋ = prop-instance squash
H-Level-∋
module _ {o ℓ ℓs ℓp} {C : Precategory o ℓ} {J : Coverage C ℓs} {A : Functor (C ^op) (Sets ℓp)} where
open Cat C
Proving that a
is also a
can be done very straightforwardly, by induction. However, there is a
gotcha: to get the induction hypotheses we need for local
without running afoul of the
termination checker, we must strengthen the motive of induction from
“
is a sheaf for any
sieve” to
“
is a sheaf for any pullback of a
sieve”.
is-sheaf-sat: is-sheaf J A
→ ∀ {V U R} (c : J ∋ R) (h : Hom V U)
→ is-sheaf₁ A (pullback h R)
To compensate for this extra strength, we must use is-sheaf-pullback
at the “leaves” inc
. Other than that, it’s a very
straightforward recursive computation:
(inc x) h = is-sheaf-pullback shf x h
is-sheaf-sat shf
_ (max {R = R} p) h = is-sheaf-maximal A $
is-sheaf-sat (_∈ R) id-comm-sym (R .closed p h)
subst
{V} (local {U} {R} hR {S} x) h =
is-sheaf-sat shf let
: ∀ {W} (f : Hom W V) → h ∘ f ∈ S
rem₁ → is-separated₁ A (pullback f (pullback h R))
= is-sheaf₁→is-separated₁ A _ $
rem₁ f hhf (is-sheaf-sat shf hR (h ∘ f))
subst-is-sheaf₁ A pullback-∘
: ∀ {W} (f : Hom W V) → h ∘ f ∈ R
rem₂ → is-sheaf₁ A (pullback f (pullback h S))
= subst-is-sheaf₁ A (pullback-id ∙ pullback-∘) $
rem₂ f hf (x (h ∘ f) hf) id
is-sheaf-sat shf in is-sheaf-transitive A rem₁ rem₂ (is-sheaf-sat shf hR h)
(pull h {R} hR) g = subst-is-sheaf₁ A pullback-∘ $
is-sheaf-sat shf (h ∘ g)
is-sheaf-sat shf hR
(squash {R} x y i) h p = is-contr-is-prop
is-sheaf-sat shf (is-sheaf-sat shf x h p)
(is-sheaf-sat shf y h p) i
Showing that a is also a is immediate.
: is-sheaf J A ≃ is-sheaf (Saturation J) A
is-sheaf-saturation .fst sheaf = from-is-sheaf₁ λ (R , hR) → subst-is-sheaf₁ A pullback-id $ is-sheaf-sat sheaf hR id
is-sheaf-saturation .snd = biimp-is-equiv! _ λ shf → from-is-sheaf₁ λ c →
is-sheaf-saturation (J .cover c , inc c)
to-is-sheaf₁ shf
module is-sheaf-saturation = Equiv is-sheaf-saturation
module sat {o ℓ ℓs ℓc} {C : Precategory o ℓ} {J : Coverage C ℓc} {A : Functor (C ^op) (Sets ℓs)} (shf : is-sheaf J A) where
private module shf = is-sheaf (is-sheaf-saturation.to shf)
: ∀ {U} {S : Sieve C U} (w : J ∋ S) (p : Patch A S) → A ʻ U
whole = shf.whole (_ , w)
whole w
abstract
: ∀ {U} {S : Sieve C U} (w : J ∋ S) (p : Patch A S) → is-section A (whole w p) p
glues = shf.glues (_ , w)
glues w
: ∀ {U} {S : Sieve C U} (w : J ∋ S) → is-separated₁ A S
separate = shf.separate (_ , w)
separate w
: ∀ {U} {S : Sieve C U} (w : J ∋ S) (p : Patch A S) → Section A p
split .Section.whole = whole w p
split w p .Section.glues = glues w p split w p