File: Mathlib/CategoryTheory/Sites/IsSheafFor.lean

full_name: CategoryTheory.Presieve.FamilyOfElements
code: /-- A family of elements for a presheaf `P` given a collection of arrows `R` with fixed codomain `X`
consists of an element of `P Y` for every `f : Y ⟶ X` in `R`.
A presheaf is a sheaf (resp, separated) if every *compatible* family of elements has exactly one
(resp, at most one) amalgamation.

This data is referred to as a `family` in [MM92], Chapter III, Section 4. It is also a concrete
version of the elements of the middle object in https://stacks.math.columbia.edu/tag/00VM which is
more useful for direct calculations. It is also used implicitly in Definition C2.1.2 in [Elephant].
-/
def FamilyOfElements (P : Cᵒᵖ ⥤ Type w) (R : Presieve X) 
goal: Type (max (max u₁ w) v₁)

full_name: CategoryTheory.Presieve.instInhabitedFamilyOfElementsBot
code: instance : Inhabited (FamilyOfElements P (⊥ : Presieve X)) 
goal: Inhabited (CategoryTheory.Presieve.FamilyOfElements P ⊥)

full_name: CategoryTheory.Presieve.FamilyOfElements.restrict
code: /-- A family of elements for a presheaf on the presieve `R₂` can be restricted to a smaller presieve
`R₁`.
-/
def FamilyOfElements.restrict {R₁ R₂ : Presieve X} (h : R₁ ≤ R₂) :
    FamilyOfElements P R₂ → FamilyOfElements P R₁ 
goal: CategoryTheory.Presieve.FamilyOfElements P R₂ → CategoryTheory.Presieve.FamilyOfElements P R₁

full_name: CategoryTheory.Presieve.FamilyOfElements.map
code: /-- The image of a family of elements by a morphism of presheaves. -/
def FamilyOfElements.map (p : FamilyOfElements P R) (φ : P ⟶ Q) :
    FamilyOfElements Q R 
goal: CategoryTheory.Presieve.FamilyOfElements Q R

full_name: CategoryTheory.Presieve.FamilyOfElements.map_apply
code: @[simp]
lemma FamilyOfElements.map_apply
    (p : FamilyOfElements P R) (φ : P ⟶ Q) {Y : C} (f : Y ⟶ X) (hf : R f) :
    p.map φ f hf = φ.app _ (p f hf) 
goal: p.map φ f hf = φ.app (Opposite.op Y) (p f hf)

full_name: CategoryTheory.Presieve.FamilyOfElements.restrict_map
code: lemma FamilyOfElements.restrict_map
    (p : FamilyOfElements P R) (φ : P ⟶ Q) {R' : Presieve X} (h : R' ≤ R) :
    (p.restrict h).map φ = (p.map φ).restrict h 
goal: (CategoryTheory.Presieve.FamilyOfElements.restrict h p).map φ =
  CategoryTheory.Presieve.FamilyOfElements.restrict h (p.map φ)

full_name: CategoryTheory.Presieve.FamilyOfElements.Compatible
code: /-- A family of elements for the arrow set `R` is *compatible* if for any `f₁ : Y₁ ⟶ X` and
`f₂ : Y₂ ⟶ X` in `R`, and any `g₁ : Z ⟶ Y₁` and `g₂ : Z ⟶ Y₂`, if the square `g₁ ≫ f₁ = g₂ ≫ f₂`
commutes then the elements of `P Z` obtained by restricting the element of `P Y₁` along `g₁` and
restricting the element of `P Y₂` along `g₂` are the same.

In special cases, this condition can be simplified, see `pullbackCompatible_iff` and
`compatible_iff_sieveCompatible`.

This is referred to as a "compatible family" in Definition C2.1.2 of [Elephant], and on nlab:
https://ncatlab.org/nlab/show/sheaf#GeneralDefinitionInComponents

For a more explicit version in the case where `R` is of the form `Presieve.ofArrows`, see
`CategoryTheory.Presieve.Arrows.Compatible`.
-/
def FamilyOfElements.Compatible (x : FamilyOfElements P R) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.FamilyOfElements.PullbackCompatible
code: /--
If the category `C` has pullbacks, this is an alternative condition for a family of elements to be
compatible: For any `f : Y ⟶ X` and `g : Z ⟶ X` in the presieve `R`, the restriction of the
given elements for `f` and `g` to the pullback agree.
This is equivalent to being compatible (provided `C` has pullbacks), shown in
`pullbackCompatible_iff`.

This is the definition for a "matching" family given in [MM92], Chapter III, Section 4,
Equation (5). Viewing the type `FamilyOfElements` as the middle object of the fork in
https://stacks.math.columbia.edu/tag/00VM, this condition expresses that `pr₀* (x) = pr₁* (x)`,
using the notation defined there.

For a more explicit version in the case where `R` is of the form `Presieve.ofArrows`, see
`CategoryTheory.Presieve.Arrows.PullbackCompatible`.
-/
def FamilyOfElements.PullbackCompatible (x : FamilyOfElements P R) [R.hasPullbacks] : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.pullbackCompatible_iff
code: theorem pullbackCompatible_iff (x : FamilyOfElements P R) [R.hasPullbacks] :
    x.Compatible ↔ x.PullbackCompatible 
goal: x.Compatible ↔ x.PullbackCompatible

full_name: CategoryTheory.Presieve.FamilyOfElements.Compatible.restrict
code: /-- The restriction of a compatible family is compatible. -/
theorem FamilyOfElements.Compatible.restrict {R₁ R₂ : Presieve X} (h : R₁ ≤ R₂)
    {x : FamilyOfElements P R₂} : x.Compatible → (x.restrict h).Compatible 
goal: x.Compatible → (CategoryTheory.Presieve.FamilyOfElements.restrict h x).Compatible

full_name: CategoryTheory.Presieve.FamilyOfElements.sieveExtend
code: /-- Extend a family of elements to the sieve generated by an arrow set.
This is the construction described as "easy" in Lemma C2.1.3 of [Elephant].
-/
noncomputable def FamilyOfElements.sieveExtend (x : FamilyOfElements P R) :
    FamilyOfElements P (generate R : Presieve X) 
goal: CategoryTheory.Presieve.FamilyOfElements P (CategoryTheory.Sieve.generate R).arrows

full_name: CategoryTheory.Presieve.FamilyOfElements.Compatible.sieveExtend
code: /-- The extension of a compatible family to the generated sieve is compatible. -/
theorem FamilyOfElements.Compatible.sieveExtend {x : FamilyOfElements P R} (hx : x.Compatible) :
    x.sieveExtend.Compatible 
goal: x.sieveExtend.Compatible

full_name: CategoryTheory.Presieve.extend_agrees
code: /-- The extension of a family agrees with the original family. -/
theorem extend_agrees {x : FamilyOfElements P R} (t : x.Compatible) {f : Y ⟶ X} (hf : R f) :
    x.sieveExtend f (le_generate R Y hf) = x f hf 
goal: x.sieveExtend f ⋯ = x f hf

full_name: CategoryTheory.Presieve.restrict_extend
code: /-- The restriction of an extension is the original. -/
@[simp]
theorem restrict_extend {x : FamilyOfElements P R} (t : x.Compatible) :
    x.sieveExtend.restrict (le_generate R) = x 
goal: CategoryTheory.Presieve.FamilyOfElements.restrict ⋯ x.sieveExtend = x

full_name: CategoryTheory.Presieve.FamilyOfElements.SieveCompatible
code: /--
If the arrow set for a family of elements is actually a sieve (i.e. it is downward closed) then the
consistency condition can be simplified.
This is an equivalent condition, see `compatible_iff_sieveCompatible`.

This is the notion of "matching" given for families on sieves given in [MM92], Chapter III,
Section 4, Equation 1, and nlab: https://ncatlab.org/nlab/show/matching+family.
See also the discussion before Lemma C2.1.4 of [Elephant].
-/
def FamilyOfElements.SieveCompatible (x : FamilyOfElements P (S : Presieve X)) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.compatible_iff_sieveCompatible
code: theorem compatible_iff_sieveCompatible (x : FamilyOfElements P (S : Presieve X)) :
    x.Compatible ↔ x.SieveCompatible 
goal: x.Compatible ↔ x.SieveCompatible

full_name: CategoryTheory.Presieve.FamilyOfElements.Compatible.to_sieveCompatible
code: theorem FamilyOfElements.Compatible.to_sieveCompatible {x : FamilyOfElements P (S : Presieve X)}
    (t : x.Compatible) : x.SieveCompatible 
goal: x.SieveCompatible

full_name: CategoryTheory.Presieve.extend_restrict
code: /--
Given a family of elements `x` for the sieve `S` generated by a presieve `R`, if `x` is restricted
to `R` and then extended back up to `S`, the resulting extension equals `x`.
-/
@[simp]
theorem extend_restrict {x : FamilyOfElements P (generate R)} (t : x.Compatible) :
    (x.restrict (le_generate R)).sieveExtend = x 
goal: (CategoryTheory.Presieve.FamilyOfElements.restrict ⋯ x).sieveExtend = x

full_name: CategoryTheory.Presieve.restrict_inj
code: /--
Two compatible families on the sieve generated by a presieve `R` are equal if and only if they are
equal when restricted to `R`.
-/
theorem restrict_inj {x₁ x₂ : FamilyOfElements P (generate R)} (t₁ : x₁.Compatible)
    (t₂ : x₂.Compatible) : x₁.restrict (le_generate R) = x₂.restrict (le_generate R) → x₁ = x₂ 
goal: CategoryTheory.Presieve.FamilyOfElements.restrict ⋯ x₁ = CategoryTheory.Presieve.FamilyOfElements.restrict ⋯ x₂ →
  x₁ = x₂

full_name: CategoryTheory.Presieve.compatibleEquivGenerateSieveCompatible_apply_coe
code: /-- Compatible families of elements for a presheaf of types `P` and a presieve `R`
    are in 1-1 correspondence with compatible families for the same presheaf and
    the sieve generated by `R`, through extension and restriction. -/
@[simps]
noncomputable def compatibleEquivGenerateSieveCompatible :
    { x : FamilyOfElements P R // x.Compatible } ≃
      { x : FamilyOfElements P (generate R : Presieve X) // x.Compatible } 
goal: ↑(CategoryTheory.Presieve.compatibleEquivGenerateSieveCompatible x) = (↑x).sieveExtend

full_name: CategoryTheory.Presieve.compatibleEquivGenerateSieveCompatible
code: /-- Compatible families of elements for a presheaf of types `P` and a presieve `R`
    are in 1-1 correspondence with compatible families for the same presheaf and
    the sieve generated by `R`, through extension and restriction. -/
@[simps]
noncomputable def compatibleEquivGenerateSieveCompatible :
    { x : FamilyOfElements P R // x.Compatible } ≃
      { x : FamilyOfElements P (generate R : Presieve X) // x.Compatible } 
goal: { x // x.Compatible } ≃ { x // x.Compatible }

full_name: CategoryTheory.Presieve.compatibleEquivGenerateSieveCompatible_symm_apply_coe
code: /-- Compatible families of elements for a presheaf of types `P` and a presieve `R`
    are in 1-1 correspondence with compatible families for the same presheaf and
    the sieve generated by `R`, through extension and restriction. -/
@[simps]
noncomputable def compatibleEquivGenerateSieveCompatible :
    { x : FamilyOfElements P R // x.Compatible } ≃
      { x : FamilyOfElements P (generate R : Presieve X) // x.Compatible } 
goal: ↑(CategoryTheory.Presieve.compatibleEquivGenerateSieveCompatible.symm x) =
  CategoryTheory.Presieve.FamilyOfElements.restrict ⋯ ↑x

full_name: CategoryTheory.Presieve.FamilyOfElements.comp_of_compatible
code: theorem FamilyOfElements.comp_of_compatible (S : Sieve X) {x : FamilyOfElements P S}
    (t : x.Compatible) {f : Y ⟶ X} (hf : S f) {Z} (g : Z ⟶ Y) :
    x (g ≫ f) (S.downward_closed hf g) = P.map g.op (x f hf) 
goal: x (CategoryTheory.CategoryStruct.comp g f) ⋯ = P.map g.op (x f hf)

full_name: CategoryTheory.Presieve.FamilyOfElements.functorPullback
code: /--
Given a family of elements of a sieve `S` on `F(X)`, we can realize it as a family of elements of
`S.functorPullback F`.
-/
def FamilyOfElements.functorPullback (x : FamilyOfElements P T) :
    FamilyOfElements (F.op ⋙ P) (T.functorPullback F) 
goal: CategoryTheory.Presieve.FamilyOfElements (F.op.comp P) (CategoryTheory.Presieve.functorPullback F T)

full_name: CategoryTheory.Presieve.FamilyOfElements.Compatible.functorPullback
code: theorem FamilyOfElements.Compatible.functorPullback (h : x.Compatible) :
    (x.functorPullback F).Compatible 
goal: (CategoryTheory.Presieve.FamilyOfElements.functorPullback F x).Compatible

full_name: CategoryTheory.Presieve.FamilyOfElements.functorPushforward
code: /-- Given a family of elements of a sieve `S` on `X` whose values factors through `F`, we can
realize it as a family of elements of `S.functorPushforward F`. Since the preimage is obtained by
choice, this is not well-defined generally.
-/
noncomputable def FamilyOfElements.functorPushforward {D : Type u₂} [Category.{v₂} D] (F : D ⥤ C)
    {X : D} {T : Presieve X} (x : FamilyOfElements (F.op ⋙ P) T) :
    FamilyOfElements P (T.functorPushforward F) 
goal: CategoryTheory.Presieve.FamilyOfElements P (CategoryTheory.Presieve.functorPushforward F T)

full_name: CategoryTheory.Presieve.FamilyOfElements.pullback
code: /-- Given a family of elements of a sieve `S` on `X`, and a map `Y ⟶ X`, we can obtain a
family of elements of `S.pullback f` by taking the same elements.
-/
def FamilyOfElements.pullback (f : Y ⟶ X) (x : FamilyOfElements P (S : Presieve X)) :
    FamilyOfElements P (S.pullback f : Presieve Y) 
goal: CategoryTheory.Presieve.FamilyOfElements P (CategoryTheory.Sieve.pullback f S).arrows

full_name: CategoryTheory.Presieve.FamilyOfElements.Compatible.pullback
code: theorem FamilyOfElements.Compatible.pullback (f : Y ⟶ X) {x : FamilyOfElements P S}
    (h : x.Compatible) : (x.pullback f).Compatible 
goal: (CategoryTheory.Presieve.FamilyOfElements.pullback f x).Compatible

full_name: CategoryTheory.Presieve.FamilyOfElements.compPresheafMap
code: /-- Given a morphism of presheaves `f : P ⟶ Q`, we can take a family of elements valued in `P` to a
family of elements valued in `Q` by composing with `f`.
-/
def FamilyOfElements.compPresheafMap (f : P ⟶ Q) (x : FamilyOfElements P R) :
    FamilyOfElements Q R 
goal: CategoryTheory.Presieve.FamilyOfElements Q R

full_name: CategoryTheory.Presieve.FamilyOfElements.compPresheafMap_id
code: @[simp]
theorem FamilyOfElements.compPresheafMap_id (x : FamilyOfElements P R) :
    x.compPresheafMap (𝟙 P) = x 
goal: CategoryTheory.Presieve.FamilyOfElements.compPresheafMap (CategoryTheory.CategoryStruct.id P) x = x

full_name: CategoryTheory.Presieve.FamilyOfElements.compPresheafMap_comp
code: @[simp]
theorem FamilyOfElements.compPresheafMap_comp (x : FamilyOfElements P R) (f : P ⟶ Q)
    (g : Q ⟶ U) : (x.compPresheafMap f).compPresheafMap g = x.compPresheafMap (f ≫ g) 
goal: CategoryTheory.Presieve.FamilyOfElements.compPresheafMap g
    (CategoryTheory.Presieve.FamilyOfElements.compPresheafMap f x) =
  CategoryTheory.Presieve.FamilyOfElements.compPresheafMap (CategoryTheory.CategoryStruct.comp f g) x

full_name: CategoryTheory.Presieve.FamilyOfElements.Compatible.compPresheafMap
code: theorem FamilyOfElements.Compatible.compPresheafMap (f : P ⟶ Q) {x : FamilyOfElements P R}
    (h : x.Compatible) : (x.compPresheafMap f).Compatible 
goal: (CategoryTheory.Presieve.FamilyOfElements.compPresheafMap f x).Compatible

full_name: CategoryTheory.Presieve.FamilyOfElements.IsAmalgamation
code: /--
The given element `t` of `P.obj (op X)` is an *amalgamation* for the family of elements `x` if every
restriction `P.map f.op t = x_f` for every arrow `f` in the presieve `R`.

This is the definition given in https://ncatlab.org/nlab/show/sheaf#GeneralDefinitionInComponents,
and https://ncatlab.org/nlab/show/matching+family, as well as [MM92], Chapter III, Section 4,
equation (2).
-/
def FamilyOfElements.IsAmalgamation (x : FamilyOfElements P R) (t : P.obj (op X)) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.FamilyOfElements.IsAmalgamation.compPresheafMap
code: theorem FamilyOfElements.IsAmalgamation.compPresheafMap {x : FamilyOfElements P R} {t} (f : P ⟶ Q)
    (h : x.IsAmalgamation t) : (x.compPresheafMap f).IsAmalgamation (f.app (op X) t) 
goal: (CategoryTheory.Presieve.FamilyOfElements.compPresheafMap f x).IsAmalgamation (f.app (Opposite.op X) t)

full_name: CategoryTheory.Presieve.is_compatible_of_exists_amalgamation
code: theorem is_compatible_of_exists_amalgamation (x : FamilyOfElements P R)
    (h : ∃ t, x.IsAmalgamation t) : x.Compatible 
goal: x.Compatible

full_name: CategoryTheory.Presieve.isAmalgamation_restrict
code: theorem isAmalgamation_restrict {R₁ R₂ : Presieve X} (h : R₁ ≤ R₂) (x : FamilyOfElements P R₂)
    (t : P.obj (op X)) (ht : x.IsAmalgamation t) : (x.restrict h).IsAmalgamation t 
goal: (CategoryTheory.Presieve.FamilyOfElements.restrict h x).IsAmalgamation t

full_name: CategoryTheory.Presieve.isAmalgamation_sieveExtend
code: theorem isAmalgamation_sieveExtend {R : Presieve X} (x : FamilyOfElements P R) (t : P.obj (op X))
    (ht : x.IsAmalgamation t) : x.sieveExtend.IsAmalgamation t 
goal: x.sieveExtend.IsAmalgamation t

full_name: CategoryTheory.Presieve.IsSeparatedFor
code: /-- A presheaf is separated for a presieve if there is at most one amalgamation. -/
def IsSeparatedFor (P : Cᵒᵖ ⥤ Type w) (R : Presieve X) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.IsSeparatedFor.ext
code: theorem IsSeparatedFor.ext {R : Presieve X} (hR : IsSeparatedFor P R) {t₁ t₂ : P.obj (op X)}
    (h : ∀ ⦃Y⦄ ⦃f : Y ⟶ X⦄ (_ : R f), P.map f.op t₁ = P.map f.op t₂) : t₁ = t₂ 
goal: t₁ = t₂

full_name: CategoryTheory.Presieve.isSeparatedFor_iff_generate
code: theorem isSeparatedFor_iff_generate :
    IsSeparatedFor P R ↔ IsSeparatedFor P (generate R : Presieve X) 
goal: CategoryTheory.Presieve.IsSeparatedFor P R ↔
  CategoryTheory.Presieve.IsSeparatedFor P (CategoryTheory.Sieve.generate R).arrows

full_name: CategoryTheory.Presieve.isSeparatedFor_top
code: theorem isSeparatedFor_top (P : Cᵒᵖ ⥤ Type w) : IsSeparatedFor P (⊤ : Presieve X) 
goal: CategoryTheory.Presieve.IsSeparatedFor P ⊤

full_name: CategoryTheory.Presieve.IsSheafFor
code: /-- We define `P` to be a sheaf for the presieve `R` if every compatible family has a unique
amalgamation.

This is the definition of a sheaf for the given presieve given in C2.1.2 of [Elephant], and
https://ncatlab.org/nlab/show/sheaf#GeneralDefinitionInComponents.
Using `compatible_iff_sieveCompatible`,
this is equivalent to the definition of a sheaf in [MM92], Chapter III, Section 4.
-/
def IsSheafFor (P : Cᵒᵖ ⥤ Type w) (R : Presieve X) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.YonedaSheafCondition
code: /-- This is an equivalent condition to be a sheaf, which is useful for the abstraction to local
operators on elementary toposes. However this definition is defined only for sieves, not presieves.
The equivalence between this and `IsSheafFor` is given in `isSheafFor_iff_yonedaSheafCondition`.
This version is also useful to establish that being a sheaf is preserved under isomorphism of
presheaves.

See the discussion before Equation (3) of [MM92], Chapter III, Section 4. See also C2.1.4 of
[Elephant]. This is also a direct reformulation of <https://stacks.math.columbia.edu/tag/00Z8>.
-/
def YonedaSheafCondition (P : Cᵒᵖ ⥤ Type v₁) (S : Sieve X) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.natTransEquivCompatibleFamily
code: /-- (Implementation). This is a (primarily internal) equivalence between natural transformations
and compatible families.

Cf the discussion after Lemma 7.47.10 in <https://stacks.math.columbia.edu/tag/00YW>. See also
the proof of C2.1.4 of [Elephant], and the discussion in [MM92], Chapter III, Section 4.
-/
def natTransEquivCompatibleFamily {P : Cᵒᵖ ⥤ Type v₁} :
    (S.functor ⟶ P) ≃ { x : FamilyOfElements P (S : Presieve X) // x.Compatible } 
goal: (S.functor ⟶ P) ≃ { x // x.Compatible }

full_name: CategoryTheory.Presieve.extension_iff_amalgamation
code: /-- (Implementation). A lemma useful to prove `isSheafFor_iff_yonedaSheafCondition`. -/
theorem extension_iff_amalgamation {P : Cᵒᵖ ⥤ Type v₁} (x : S.functor ⟶ P) (g : yoneda.obj X ⟶ P) :
    S.functorInclusion ≫ g = x ↔
      (natTransEquivCompatibleFamily x).1.IsAmalgamation (yonedaEquiv g) 
goal: CategoryTheory.CategoryStruct.comp S.functorInclusion g = x ↔
  (↑(CategoryTheory.Presieve.natTransEquivCompatibleFamily x)).IsAmalgamation (CategoryTheory.yonedaEquiv g)

full_name: CategoryTheory.Presieve.isSheafFor_iff_yonedaSheafCondition
code: /-- The yoneda version of the sheaf condition is equivalent to the sheaf condition.

C2.1.4 of [Elephant].
-/
theorem isSheafFor_iff_yonedaSheafCondition {P : Cᵒᵖ ⥤ Type v₁} :
    IsSheafFor P (S : Presieve X) ↔ YonedaSheafCondition P S 
goal: CategoryTheory.Presieve.IsSheafFor P S.arrows ↔ CategoryTheory.Presieve.YonedaSheafCondition P S

full_name: CategoryTheory.Presieve.IsSheafFor.extend
code: /--
If `P` is a sheaf for the sieve `S` on `X`, a natural transformation from `S` (viewed as a functor)
to `P` can be (uniquely) extended to all of `yoneda.obj X`.

      f
   S  →  P
   ↓  ↗
   yX

-/
noncomputable def IsSheafFor.extend {P : Cᵒᵖ ⥤ Type v₁} (h : IsSheafFor P (S : Presieve X))
    (f : S.functor ⟶ P) : yoneda.obj X ⟶ P 
goal: CategoryTheory.yoneda.obj X ⟶ P

full_name: CategoryTheory.Presieve.IsSheafFor.functorInclusion_comp_extend
code: /--
Show that the extension of `f : S.functor ⟶ P` to all of `yoneda.obj X` is in fact an extension, ie
that the triangle below commutes, provided `P` is a sheaf for `S`

      f
   S  →  P
   ↓  ↗
   yX

-/
@[reassoc (attr := simp)]
theorem IsSheafFor.functorInclusion_comp_extend {P : Cᵒᵖ ⥤ Type v₁} (h : IsSheafFor P S)
    (f : S.functor ⟶ P) : S.functorInclusion ≫ h.extend f = f 
goal: CategoryTheory.CategoryStruct.comp S.functorInclusion (h.extend f) = f

full_name: CategoryTheory.Presieve.IsSheafFor.unique_extend
code: /-- The extension of `f` to `yoneda.obj X` is unique. -/
theorem IsSheafFor.unique_extend {P : Cᵒᵖ ⥤ Type v₁} (h : IsSheafFor P S) {f : S.functor ⟶ P}
    (t : yoneda.obj X ⟶ P) (ht : S.functorInclusion ≫ t = f) : t = h.extend f 
goal: t = h.extend f

full_name: CategoryTheory.Presieve.IsSheafFor.hom_ext
code: /--
If `P` is a sheaf for the sieve `S` on `X`, then if two natural transformations from `yoneda.obj X`
to `P` agree when restricted to the subfunctor given by `S`, they are equal.
-/
theorem IsSheafFor.hom_ext {P : Cᵒᵖ ⥤ Type v₁} (h : IsSheafFor P (S : Presieve X))
    (t₁ t₂ : yoneda.obj X ⟶ P) (ht : S.functorInclusion ≫ t₁ = S.functorInclusion ≫ t₂) :
    t₁ = t₂ 
goal: t₁ = t₂

full_name: CategoryTheory.Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor
code: /-- `P` is a sheaf for `R` iff it is separated for `R` and there exists an amalgamation. -/
theorem isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor :
    (IsSeparatedFor P R ∧ ∀ x : FamilyOfElements P R, x.Compatible → ∃ t, x.IsAmalgamation t) ↔
      IsSheafFor P R 
goal: (CategoryTheory.Presieve.IsSeparatedFor P R ∧
    ∀ (x : CategoryTheory.Presieve.FamilyOfElements P R), x.Compatible → ∃ t, x.IsAmalgamation t) ↔
  CategoryTheory.Presieve.IsSheafFor P R

full_name: CategoryTheory.Presieve.IsSeparatedFor.isSheafFor
code: /-- If `P` is separated for `R` and every family has an amalgamation, then `P` is a sheaf for `R`.
-/
theorem IsSeparatedFor.isSheafFor (t : IsSeparatedFor P R) :
    (∀ x : FamilyOfElements P R, x.Compatible → ∃ t, x.IsAmalgamation t) → IsSheafFor P R 
goal: (∀ (x : CategoryTheory.Presieve.FamilyOfElements P R), x.Compatible → ∃ t, x.IsAmalgamation t) →
  CategoryTheory.Presieve.IsSheafFor P R

full_name: CategoryTheory.Presieve.IsSheafFor.isSeparatedFor
code: /-- If `P` is a sheaf for `R`, it is separated for `R`. -/
theorem IsSheafFor.isSeparatedFor : IsSheafFor P R → IsSeparatedFor P R 
goal: CategoryTheory.Presieve.IsSheafFor P R → CategoryTheory.Presieve.IsSeparatedFor P R

full_name: CategoryTheory.Presieve.IsSheafFor.amalgamate
code: /-- Get the amalgamation of the given compatible family, provided we have a sheaf. -/
noncomputable def IsSheafFor.amalgamate (t : IsSheafFor P R) (x : FamilyOfElements P R)
    (hx : x.Compatible) : P.obj (op X) 
goal: P.obj (Opposite.op X)

full_name: CategoryTheory.Presieve.IsSheafFor.isAmalgamation
code: theorem IsSheafFor.isAmalgamation (t : IsSheafFor P R) {x : FamilyOfElements P R}
    (hx : x.Compatible) : x.IsAmalgamation (t.amalgamate x hx) 
goal: x.IsAmalgamation (t.amalgamate x hx)

full_name: CategoryTheory.Presieve.IsSheafFor.valid_glue
code: @[simp]
theorem IsSheafFor.valid_glue (t : IsSheafFor P R) {x : FamilyOfElements P R} (hx : x.Compatible)
    (f : Y ⟶ X) (Hf : R f) : P.map f.op (t.amalgamate x hx) = x f Hf 
goal: P.map f.op (t.amalgamate x hx) = x f Hf

full_name: CategoryTheory.Presieve.isSheafFor_iff_generate
code: /-- C2.1.3 in [Elephant] -/
theorem isSheafFor_iff_generate (R : Presieve X) :
    IsSheafFor P R ↔ IsSheafFor P (generate R : Presieve X) 
goal: CategoryTheory.Presieve.IsSheafFor P R ↔ CategoryTheory.Presieve.IsSheafFor P (CategoryTheory.Sieve.generate R).arrows

full_name: CategoryTheory.Presieve.isSheafFor_singleton_iso
code: /-- Every presheaf is a sheaf for the family {𝟙 X}.

[Elephant] C2.1.5(i)
-/
theorem isSheafFor_singleton_iso (P : Cᵒᵖ ⥤ Type w) : IsSheafFor P (Presieve.singleton (𝟙 X)) 
goal: CategoryTheory.Presieve.IsSheafFor P (CategoryTheory.Presieve.singleton (CategoryTheory.CategoryStruct.id X))

full_name: CategoryTheory.Presieve.isSheafFor_top_sieve
code: /-- Every presheaf is a sheaf for the maximal sieve.

[Elephant] C2.1.5(ii)
-/
theorem isSheafFor_top_sieve (P : Cᵒᵖ ⥤ Type w) : IsSheafFor P ((⊤ : Sieve X) : Presieve X) 
goal: CategoryTheory.Presieve.IsSheafFor P ⊤.arrows

full_name: CategoryTheory.Presieve.isSheafFor_iso
code: /-- If `P` is a sheaf for `S`, and it is iso to `P'`, then `P'` is a sheaf for `S`. This shows that
"being a sheaf for a presieve" is a mathematical or hygienic property.
-/
theorem isSheafFor_iso {P' : Cᵒᵖ ⥤ Type w} (i : P ≅ P') : IsSheafFor P R → IsSheafFor P' R 
goal: CategoryTheory.Presieve.IsSheafFor P R → CategoryTheory.Presieve.IsSheafFor P' R

full_name: CategoryTheory.Presieve.isSheafFor_subsieve_aux
code: /-- If a presieve `R` on `X` has a subsieve `S` such that:

* `P` is a sheaf for `S`.
* For every `f` in `R`, `P` is separated for the pullback of `S` along `f`,

then `P` is a sheaf for `R`.

This is closely related to [Elephant] C2.1.6(i).
-/
theorem isSheafFor_subsieve_aux (P : Cᵒᵖ ⥤ Type w) {S : Sieve X} {R : Presieve X}
    (h : (S : Presieve X) ≤ R) (hS : IsSheafFor P (S : Presieve X))
    (trans : ∀ ⦃Y⦄ ⦃f : Y ⟶ X⦄, R f → IsSeparatedFor P (S.pullback f : Presieve Y)) :
    IsSheafFor P R 
goal: CategoryTheory.Presieve.IsSheafFor P R

full_name: CategoryTheory.Presieve.isSheafFor_subsieve
code: /--
If `P` is a sheaf for every pullback of the sieve `S`, then `P` is a sheaf for any presieve which
contains `S`.
This is closely related to [Elephant] C2.1.6.
-/
theorem isSheafFor_subsieve (P : Cᵒᵖ ⥤ Type w) {S : Sieve X} {R : Presieve X}
    (h : (S : Presieve X) ≤ R) (trans : ∀ ⦃Y⦄ (f : Y ⟶ X),
      IsSheafFor P (S.pullback f : Presieve Y)) :
    IsSheafFor P R 
goal: CategoryTheory.Presieve.IsSheafFor P R

full_name: CategoryTheory.Presieve.Arrows.Compatible
code: /--
A more explicit version of `FamilyOfElements.Compatible` for a `Presieve.ofArrows`.
-/
def Arrows.Compatible (x : (i : I) → P.obj (op (X i))) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.FamilyOfElements.isAmalgamation_iff_ofArrows
code: lemma FamilyOfElements.isAmalgamation_iff_ofArrows (x : FamilyOfElements P (ofArrows X π))
    (t : P.obj (op B)) :
    x.IsAmalgamation t ↔ ∀ (i : I), P.map (π i).op t = x _ (ofArrows.mk i) 
goal: x.IsAmalgamation t ↔ ∀ (i : I), P.map (π i).op t = x (π i) ⋯

full_name: CategoryTheory.Presieve.Arrows.Compatible.exists_familyOfElements
code: theorem exists_familyOfElements (hx : Compatible P π x) :
    ∃ (x' : FamilyOfElements P (ofArrows X π)), ∀ (i : I), x' _ (ofArrows.mk i) = x i 
goal: ∃ x', ∀ (i : I), x' (π i) ⋯ = x i

full_name: CategoryTheory.Presieve.Arrows.Compatible.familyOfElements
code: /--
A `FamilyOfElements` associated to an explicit family of elements.
-/
noncomputable
def familyOfElements : FamilyOfElements P (ofArrows X π) 
goal: CategoryTheory.Presieve.FamilyOfElements P (CategoryTheory.Presieve.ofArrows X π)

full_name: CategoryTheory.Presieve.Arrows.Compatible.familyOfElements_ofArrows_mk
code: @[simp]
theorem familyOfElements_ofArrows_mk (i : I) :
    hx.familyOfElements _ (ofArrows.mk i) = x i 
goal: hx.familyOfElements (π i) ⋯ = x i

full_name: CategoryTheory.Presieve.Arrows.Compatible.familyOfElements_compatible
code: theorem familyOfElements_compatible : hx.familyOfElements.Compatible 
goal: hx.familyOfElements.Compatible

full_name: CategoryTheory.Presieve.isSheafFor_arrows_iff
code: theorem isSheafFor_arrows_iff : (ofArrows X π).IsSheafFor P ↔
    (∀ (x : (i : I) → P.obj (op (X i))), Arrows.Compatible P π x →
    ∃! t, ∀ i, P.map (π i).op t = x i) 
goal: CategoryTheory.Presieve.IsSheafFor P (CategoryTheory.Presieve.ofArrows X π) ↔
  ∀ (x : (i : I) → P.obj (Opposite.op (X i))),
    CategoryTheory.Presieve.Arrows.Compatible P π x → ∃! t, ∀ (i : I), P.map (π i).op t = x i

full_name: CategoryTheory.Presieve.Arrows.PullbackCompatible
code: /--
A more explicit version of `FamilyOfElements.PullbackCompatible` for a `Presieve.ofArrows`.
-/
def Arrows.PullbackCompatible (x : (i : I) → P.obj (op (X i))) : Prop 
goal: Prop

full_name: CategoryTheory.Presieve.Arrows.pullbackCompatible_iff
code: theorem Arrows.pullbackCompatible_iff (x : (i : I) → P.obj (op (X i))) :
    Compatible P π x ↔ PullbackCompatible P π x 
goal: CategoryTheory.Presieve.Arrows.Compatible P π x ↔ CategoryTheory.Presieve.Arrows.PullbackCompatible P π x

full_name: CategoryTheory.Presieve.isSheafFor_arrows_iff_pullbacks
code: theorem isSheafFor_arrows_iff_pullbacks : (ofArrows X π).IsSheafFor P ↔
    (∀ (x : (i : I) → P.obj (op (X i))), Arrows.PullbackCompatible P π x →
    ∃! t, ∀ i, P.map (π i).op t = x i) 
goal: CategoryTheory.Presieve.IsSheafFor P (CategoryTheory.Presieve.ofArrows X π) ↔
  ∀ (x : (i : I) → P.obj (Opposite.op (X i))),
    CategoryTheory.Presieve.Arrows.PullbackCompatible P π x → ∃! t, ∀ (i : I), P.map (π i).op t = x i