Theorem: CategoryTheory.Functor.IsCoverDense.Types.pushforwardFamily_compatible
File: Mathlib/CategoryTheory/Sites/DenseSubsite.lean

tactic: intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ e
state_before: C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
⊢ (pushforwardFamily α x).Compatible
state_after: C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
⊢ ℱ'.val.map g₁.op (pushforwardFamily α x f₁ h₁) = ℱ'.val.map g₂.op (pushforwardFamily α x f₂ h₂)

tactic: apply IsCoverDense.ext G
state_before: C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
⊢ ℱ'.val.map g₁.op (pushforwardFamily α x f₁ h₁) = ℱ'.val.map g₂.op (pushforwardFamily α x f₂ h₂)
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
⊢ ∀ ⦃Y : C⦄ (f : G.obj Y ⟶ Z),
    ℱ'.val.map f.op (ℱ'.val.map g₁.op (pushforwardFamily α x f₁ h₁)) =
      ℱ'.val.map f.op (ℱ'.val.map g₂.op (pushforwardFamily α x f₂ h₂))

tactic: intro Y f
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
⊢ ∀ ⦃Y : C⦄ (f : G.obj Y ⟶ Z),
    ℱ'.val.map f.op (ℱ'.val.map g₁.op (pushforwardFamily α x f₁ h₁)) =
      ℱ'.val.map f.op (ℱ'.val.map g₂.op (pushforwardFamily α x f₂ h₂))
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ'.val.map f.op (ℱ'.val.map g₁.op (pushforwardFamily α x f₁ h₁)) =
    ℱ'.val.map f.op (ℱ'.val.map g₂.op (pushforwardFamily α x f₂ h₂))

tactic: simp only [pushforwardFamily, ← FunctorToTypes.map_comp_apply, ← op_comp]
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ'.val.map f.op (ℱ'.val.map g₁.op (pushforwardFamily α x f₁ h₁)) =
    ℱ'.val.map f.op (ℱ'.val.map g₂.op (pushforwardFamily α x f₂ h₂))
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ'.val.map (f ≫ g₁ ≫ (Nonempty.some h₁).lift).op
      (α.app { unop := (Nonempty.some h₁).1 } (ℱ.map (Nonempty.some h₁).map.op x)) =
    ℱ'.val.map (f ≫ g₂ ≫ (Nonempty.some h₂).lift).op
      (α.app { unop := (Nonempty.some h₂).1 } (ℱ.map (Nonempty.some h₂).map.op x))

tactic: change (ℱ.map _ ≫ α.app (op _) ≫ ℱ'.val.map _) _ = (ℱ.map _ ≫ α.app (op _) ≫ ℱ'.val.map _) _
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ'.val.map (f ≫ g₁ ≫ (Nonempty.some h₁).lift).op
      (α.app { unop := (Nonempty.some h₁).1 } (ℱ.map (Nonempty.some h₁).map.op x)) =
    ℱ'.val.map (f ≫ g₂ ≫ (Nonempty.some h₂).lift).op
      (α.app { unop := (Nonempty.some h₂).1 } (ℱ.map (Nonempty.some h₂).map.op x))
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        α.app { unop := (Nonempty.some h₁).1 } ≫ ℱ'.val.map (f ≫ g₁ ≫ (Nonempty.some h₁).lift).op)
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (f ≫ g₂ ≫ (Nonempty.some h₂).lift).op)
      x

tactic: rw [← G.map_preimage (f ≫ g₁ ≫ _)]
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        α.app { unop := (Nonempty.some h₁).1 } ≫ ℱ'.val.map (f ≫ g₁ ≫ (Nonempty.some h₁).lift).op)
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (f ≫ g₂ ≫ (Nonempty.some h₂).lift).op)
      x
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        α.app { unop := (Nonempty.some h₁).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift))).op)
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (f ≫ g₂ ≫ (Nonempty.some h₂).lift).op)
      x

tactic: rw [← G.map_preimage (f ≫ g₂ ≫ _)]
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        α.app { unop := (Nonempty.some h₁).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift))).op)
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (f ≫ g₂ ≫ (Nonempty.some h₂).lift).op)
      x
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        α.app { unop := (Nonempty.some h₁).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift))).op)
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift))).op)
      x

tactic: erw [← α.naturality (G.preimage _).op]
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        α.app { unop := (Nonempty.some h₁).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift))).op)
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift))).op)
      x
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        (G.op ⋙ ℱ).map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift)).op ≫ α.app { unop := Y })
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift))).op)
      x

tactic: erw [← α.naturality (G.preimage _).op]
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        (G.op ⋙ ℱ).map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift)).op ≫ α.app { unop := Y })
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        α.app { unop := (Nonempty.some h₂).1 } ≫ ℱ'.val.map (G.map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift))).op)
      x
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        (G.op ⋙ ℱ).map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift)).op ≫ α.app { unop := Y })
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        (G.op ⋙ ℱ).map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift)).op ≫ α.app { unop := Y })
      x

tactic: refine congr_fun ?_ x
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ (ℱ.map (Nonempty.some h₁).map.op ≫
        (G.op ⋙ ℱ).map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift)).op ≫ α.app { unop := Y })
      x =
    (ℱ.map (Nonempty.some h₂).map.op ≫
        (G.op ⋙ ℱ).map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift)).op ≫ α.app { unop := Y })
      x
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ.map (Nonempty.some h₁).map.op ≫
      (G.op ⋙ ℱ).map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift)).op ≫ α.app { unop := Y } =
    ℱ.map (Nonempty.some h₂).map.op ≫
      (G.op ⋙ ℱ).map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift)).op ≫ α.app { unop := Y }

tactic: simp only [Functor.comp_map, ← Category.assoc, Functor.op_map, Quiver.Hom.unop_op,
  ← ℱ.map_comp, ← op_comp, G.map_preimage]
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ.map (Nonempty.some h₁).map.op ≫
      (G.op ⋙ ℱ).map (G.preimage (f ≫ g₁ ≫ (Nonempty.some h₁).lift)).op ≫ α.app { unop := Y } =
    ℱ.map (Nonempty.some h₂).map.op ≫
      (G.op ⋙ ℱ).map (G.preimage (f ≫ g₂ ≫ (Nonempty.some h₂).lift)).op ≫ α.app { unop := Y }
state_after: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ.map (((f ≫ g₁) ≫ (Nonempty.some h₁).lift) ≫ (Nonempty.some h₁).map).op ≫ α.app { unop := Y } =
    ℱ.map (((f ≫ g₂) ≫ (Nonempty.some h₂).lift) ≫ (Nonempty.some h₂).map).op ≫ α.app { unop := Y }

tactic: congr 3
state_before: case h
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ℱ.map (((f ≫ g₁) ≫ (Nonempty.some h₁).lift) ≫ (Nonempty.some h₁).map).op ≫ α.app { unop := Y } =
    ℱ.map (((f ≫ g₂) ≫ (Nonempty.some h₂).lift) ≫ (Nonempty.some h₂).map).op ≫ α.app { unop := Y }
state_after: case h.e_a.e_a.e_f
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ((f ≫ g₁) ≫ (Nonempty.some h₁).lift) ≫ (Nonempty.some h₁).map =
    ((f ≫ g₂) ≫ (Nonempty.some h₂).lift) ≫ (Nonempty.some h₂).map

tactic: simp [e]
state_before: case h.e_a.e_a.e_f
C : Type u_1
inst✝⁵ : Category.{u_6, u_1} C
D : Type u_2
inst✝⁴ : Category.{u_5, u_2} D
E : Type u_3
inst✝³ : Category.{?u.28919, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.28971, u_4} A
G : C ⥤ D
inst✝¹ : G.IsCoverDense K
inst✝ : G.Full
ℱ : Dᵒᵖ ⥤ Type v
ℱ' : SheafOfTypes K
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
X : D
x : ℱ.obj { unop := X }
Y₁ Y₂ Z : D
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : coverByImage G X f₁
h₂ : coverByImage G X f₂
e : g₁ ≫ f₁ = g₂ ≫ f₂
Y : C
f : G.obj Y ⟶ Z
⊢ ((f ≫ g₁) ≫ (Nonempty.some h₁).lift) ≫ (Nonempty.some h₁).map =
    ((f ≫ g₂) ≫ (Nonempty.some h₂).lift) ≫ (Nonempty.some h₂).map
state_after: no goals