Theorem: CategoryTheory.Presheaf.isLocallySurjective_of_isLocallySurjective_of_isLocallyInjective
File: Mathlib/CategoryTheory/Sites/LocallySurjective.lean

tactic: let S := imageSieve (f₁ ≫ f₂) (f₂.app _ x)
state_before: C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
⊢ imageSieve f₁ x ∈ J.sieves X
state_after: C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
⊢ imageSieve f₁ x ∈ J.sieves X

tactic: let T : ∀ ⦃Y : C⦄ (f : Y ⟶ X) (_ : S f), Sieve Y := fun Y f hf =>
  equalizerSieve (f₁.app _ (localPreimage (f₁ ≫ f₂) (f₂.app _ x) f hf)) (F₂.map f.op x)
state_before: C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
⊢ imageSieve f₁ x ∈ J.sieves X
state_after: C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
⊢ imageSieve f₁ x ∈ J.sieves X

tactic: refine J.superset_covering ?_ (J.transitive (imageSieve_mem J (f₁ ≫ f₂) (f₂.app _ x))
  (Sieve.bind S.1 T) ?_)
state_before: C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
⊢ imageSieve f₁ x ∈ J.sieves X
state_after: case refine_1
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
⊢ Sieve.bind S.arrows T ≤ imageSieve f₁ x

case refine_2
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
⊢ ∀ ⦃Y : C⦄ ⦃f : Y ⟶ { unop := X }.unop⦄,
    (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f → Sieve.pullback f (Sieve.bind S.arrows T) ∈ J.sieves Y

tactic: rintro Y _ ⟨Z, a, g, hg, ha, rfl⟩
state_before: case refine_1
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
⊢ Sieve.bind S.arrows T ≤ imageSieve f₁ x
state_after: case refine_1.intro.intro.intro.intro.intro
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y Z : C
a : Y ⟶ Z
g : Z ⟶ { unop := X }.unop
hg : S.arrows g
ha : (T g hg).arrows a
⊢ (imageSieve f₁ x).arrows (a ≫ g)

tactic: exact ⟨F₁.map a.op (localPreimage (f₁ ≫ f₂) _ _ hg), by simpa using ha⟩
state_before: case refine_1.intro.intro.intro.intro.intro
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y Z : C
a : Y ⟶ Z
g : Z ⟶ { unop := X }.unop
hg : S.arrows g
ha : (T g hg).arrows a
⊢ (imageSieve f₁ x).arrows (a ≫ g)
state_after: no goals

tactic: simpa using ha
state_before: C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y Z : C
a : Y ⟶ Z
g : Z ⟶ { unop := X }.unop
hg : S.arrows g
ha : (T g hg).arrows a
⊢ (f₁.app { unop := Y }) ((F₁.map a.op) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) g hg)) =
    (F₂.map (a ≫ g).op) x
state_after: no goals

tactic: intro Y f hf
state_before: case refine_2
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
⊢ ∀ ⦃Y : C⦄ ⦃f : Y ⟶ { unop := X }.unop⦄,
    (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f → Sieve.pullback f (Sieve.bind S.arrows T) ∈ J.sieves Y
state_after: case refine_2
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y : C
f : Y ⟶ { unop := X }.unop
hf : (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f
⊢ Sieve.pullback f (Sieve.bind S.arrows T) ∈ J.sieves Y

tactic: apply J.superset_covering (Sieve.le_pullback_bind _ _ _ hf)
state_before: case refine_2
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y : C
f : Y ⟶ { unop := X }.unop
hf : (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f
⊢ Sieve.pullback f (Sieve.bind S.arrows T) ∈ J.sieves Y
state_after: case refine_2
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y : C
f : Y ⟶ { unop := X }.unop
hf : (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f
⊢ T f hf ∈ J.sieves Y

tactic: apply equalizerSieve_mem J f₂
state_before: case refine_2
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y : C
f : Y ⟶ { unop := X }.unop
hf : (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f
⊢ T f hf ∈ J.sieves Y
state_after: case refine_2.h
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y : C
f : Y ⟶ { unop := X }.unop
hf : (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f
⊢ (f₂.app { unop := Y }) ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) =
    (f₂.app { unop := Y }) ((F₂.map f.op) x)

tactic: rw [NatTrans.naturality_apply, ← app_localPreimage (f₁ ≫ f₂) _ _ hf,
  NatTrans.comp_app, comp_apply]
state_before: case refine_2.h
C : Type u
inst✝⁴ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝³ : Category.{v', u'} A
inst✝² : ConcreteCategory A
F₁ F₂ F₃ : Cᵒᵖ ⥤ A
f₁ : F₁ ⟶ F₂
f₂ : F₂ ⟶ F₃
inst✝¹ : IsLocallySurjective J (f₁ ≫ f₂)
inst✝ : IsLocallyInjective J f₂
X : C
x : (forget A).obj (F₂.obj { unop := X })
S : Sieve X := imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)
T : ⦃Y : C⦄ → (f : Y ⟶ X) → S.arrows f → Sieve Y :=
  fun Y f hf =>
    equalizerSieve ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) ((F₂.map f.op) x)
Y : C
f : Y ⟶ { unop := X }.unop
hf : (imageSieve (f₁ ≫ f₂) ((f₂.app { unop := X }) x)).arrows f
⊢ (f₂.app { unop := Y }) ((f₁.app { unop := Y }) (localPreimage (f₁ ≫ f₂) ((f₂.app { unop := X }) x) f hf)) =
    (f₂.app { unop := Y }) ((F₂.map f.op) x)
state_after: no goals