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

tactic: let S := imageSieve f₁ x₁ ⊓ imageSieve f₁ 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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
⊢ equalizerSieve x₁ x₂ ∈ J.sieves X.unop
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ equalizerSieve x₁ x₂ ∈ J.sieves X.unop

tactic: have hS : S ∈ J X.unop := by
  apply J.intersection_covering
  all_goals apply imageSieve_mem
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ equalizerSieve x₁ x₂ ∈ J.sieves X.unop
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
⊢ equalizerSieve x₁ x₂ ∈ J.sieves X.unop

tactic: let T : ∀ ⦃Y : C⦄ (f : Y ⟶ X.unop) (_ : S f), Sieve Y := fun Y f hf =>
  equalizerSieve (localPreimage f₁ x₁ f hf.1) (localPreimage f₁ x₂ f hf.2)
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
⊢ equalizerSieve x₁ x₂ ∈ J.sieves X.unop
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
⊢ equalizerSieve x₁ x₂ ∈ J.sieves X.unop

tactic: refine J.superset_covering ?_ (J.transitive hS (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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
⊢ equalizerSieve x₁ x₂ ∈ J.sieves X.unop
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
⊢ Sieve.bind S.arrows T ≤ equalizerSieve x₁ 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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
⊢ ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X.unop⦄, S.arrows f → Sieve.pullback f (Sieve.bind S.arrows T) ∈ J.sieves Y

tactic: apply J.intersection_covering
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ S ∈ J.sieves X.unop
state_after: case rj
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ imageSieve f₁ x₁ ∈ J.sieves X.unop

case sj
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ imageSieve f₁ x₂ ∈ J.sieves X.unop

tactic: all_goals apply imageSieve_mem
state_before: case rj
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ imageSieve f₁ x₁ ∈ J.sieves X.unop

case sj
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ imageSieve f₁ x₂ ∈ J.sieves X.unop
state_after: no goals

tactic: apply imageSieve_mem
state_before: case sj
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
⊢ imageSieve f₁ x₂ ∈ J.sieves X.unop
state_after: no goals

tactic: rintro Y f ⟨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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
⊢ Sieve.bind S.arrows T ≤ equalizerSieve x₁ 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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y Z : C
a : Y ⟶ Z
g : Z ⟶ X.unop
hg : S.arrows g
ha : (T g hg).arrows a
⊢ (equalizerSieve x₁ x₂).arrows (a ≫ g)

tactic: simpa using congr_arg (f₁.app _) 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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y Z : C
a : Y ⟶ Z
g : Z ⟶ X.unop
hg : S.arrows g
ha : (T g hg).arrows a
⊢ (equalizerSieve x₁ x₂).arrows (a ≫ g)
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
⊢ ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X.unop⦄, S.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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.arrows f
⊢ T f hf ∈ J.sieves Y

tactic: apply equalizerSieve_mem J (f₁ ≫ 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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.arrows f
⊢ ((f₁ ≫ f₂).app { unop := Y }) (localPreimage f₁ x₁ f ⋯) = ((f₁ ≫ f₂).app { unop := Y }) (localPreimage f₁ x₂ f ⋯)

tactic: dsimp
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.arrows f
⊢ ((f₁ ≫ f₂).app { unop := Y }) (localPreimage f₁ x₁ f ⋯) = ((f₁ ≫ f₂).app { unop := Y }) (localPreimage f₁ x₂ f ⋯)
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.arrows f
⊢ (f₁.app { unop := Y } ≫ f₂.app { unop := Y }) (localPreimage f₁ x₁ f ⋯) =
    (f₁.app { unop := Y } ≫ f₂.app { unop := Y }) (localPreimage f₁ x₂ f ⋯)

tactic: rw [comp_apply, comp_apply, app_localPreimage, app_localPreimage,
  NatTrans.naturality_apply, NatTrans.naturality_apply, h]
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✝¹ : IsLocallyInjective J (f₁ ≫ f₂)
inst✝ : IsLocallySurjective J f₁
X : Cᵒᵖ
x₁ x₂ : (forget A).obj (F₂.obj X)
h : (f₂.app X) x₁ = (f₂.app X) x₂
S : Sieve X.unop := imageSieve f₁ x₁ ⊓ imageSieve f₁ x₂
hS : S ∈ J.sieves X.unop
T : ⦃Y : C⦄ → (f : Y ⟶ X.unop) → S.arrows f → Sieve Y :=
  fun Y f hf => equalizerSieve (localPreimage f₁ x₁ f ⋯) (localPreimage f₁ x₂ f ⋯)
Y : C
f : Y ⟶ X.unop
hf : S.arrows f
⊢ (f₁.app { unop := Y } ≫ f₂.app { unop := Y }) (localPreimage f₁ x₁ f ⋯) =
    (f₁.app { unop := Y } ≫ f₂.app { unop := Y }) (localPreimage f₁ x₂ f ⋯)
state_after: no goals