l3lab/ntp-mathlib huggingface dataset:
/-- Whiskering by an equivalence gives an equivalence between categories of cones.
-/
@[simps]
def whiskeringEquivalence (e : K ≌ J) : Cone F ≌ Cone (e.functor ⋙ F) where
  functor := whiskering e.functor
  inverse := whiskering e.inverse ⋙ postcompose (e.invFunIdAssoc F).hom
  unitIso := NatIso.ofComponents fun s => Cones.ext (Iso.refl _)
  counitIso :=
    NatIso.ofComponents
      fun s =>
        Cones.ext (Iso.refl _)
          (by
            

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
e : K ≌ J
s : Cone (e.functor ⋙ F)
⊢ ∀ (j : K),
    (((whiskering e.inverse ⋙ postcompose (Equivalence.invFunIdAssoc e F).hom) ⋙ whiskering e.functor).obj s).π.app j =
      (Iso.refl
            (((whiskering e.inverse ⋙ postcompose (Equivalence.invFunIdAssoc e F).hom) ⋙ whiskering e.functor).obj
                s).pt).hom ≫
        ((𝟭 (Cone (e.functor ⋙ F))).obj s).π.app j

Next tactic:
intro k
/-- Whiskering by an equivalence gives an equivalence between categories of cones.
-/
@[simps]
def whiskeringEquivalence (e : K ≌ J) : Cone F ≌ Cone (e.functor ⋙ F) where
  functor := whiskering e.functor
  inverse := whiskering e.inverse ⋙ postcompose (e.invFunIdAssoc F).hom
  unitIso := NatIso.ofComponents fun s => Cones.ext (Iso.refl _)
  counitIso :=
    NatIso.ofComponents
      fun s =>
        Cones.ext (Iso.refl _)
          (by
            intro k
            

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
e : K ≌ J
s : Cone (e.functor ⋙ F)
k : K
⊢ (((whiskering e.inverse ⋙ postcompose (Equivalence.invFunIdAssoc e F).hom) ⋙ whiskering e.functor).obj s).π.app k =
    (Iso.refl
          (((whiskering e.inverse ⋙ postcompose (Equivalence.invFunIdAssoc e F).hom) ⋙ whiskering e.functor).obj
              s).pt).hom ≫
      ((𝟭 (Cone (e.functor ⋙ F))).obj s).π.app k

Next tactic:
simpa [e.counit_app_functor] using s.w (e.unitInv.app k)
/-- A functor `G : C ⥤ D` sends cones over `F` to cones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cone F ⥤ Cone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      π :=
        { app := fun j => G.map (A.π.app j)
          naturality := by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
A : Cone F
⊢ ∀ ⦃X Y : J⦄ (f : X ⟶ Y),
    ((const J).obj (G.obj A.pt)).map f ≫ (fun j => G.map (A.π.app j)) Y = (fun j => G.map (A.π.app j)) X ≫ (F ⋙ G).map f

Next tactic:
intros
/-- A functor `G : C ⥤ D` sends cones over `F` to cones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cone F ⥤ Cone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      π :=
        { app := fun j => G.map (A.π.app j)
          naturality := by intros; 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
A : Cone F
X✝ Y✝ : J
f✝ : X✝ ⟶ Y✝
⊢ ((const J).obj (G.obj A.pt)).map f✝ ≫ (fun j => G.map (A.π.app j)) Y✝ =
    (fun j => G.map (A.π.app j)) X✝ ≫ (F ⋙ G).map f✝

Next tactic:
erw [← G.map_comp]
/-- A functor `G : C ⥤ D` sends cones over `F` to cones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cone F ⥤ Cone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      π :=
        { app := fun j => G.map (A.π.app j)
          naturality := by intros; erw [← G.map_comp]; 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
A : Cone F
X✝ Y✝ : J
f✝ : X✝ ⟶ Y✝
⊢ ((const J).obj (G.obj A.pt)).map f✝ ≫ (fun j => G.map (A.π.app j)) Y✝ = G.map (A.π.app X✝ ≫ F.map f✝)

Next tactic:
aesop_cat
/-- A functor `G : C ⥤ D` sends cones over `F` to cones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cone F ⥤ Cone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      π :=
        { app := fun j => G.map (A.π.app j)
          naturality := by intros; erw [← G.map_comp]; aesop_cat } }
  map f :=
    { hom := G.map f.hom
      w := fun j => by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
X✝ Y✝ : Cone F
f : X✝ ⟶ Y✝
j : J
⊢ G.map f.hom ≫ ((fun A => { pt := G.obj A.pt, π := NatTrans.mk fun j => G.map (A.π.app j) }) Y✝).π.app j =
    ((fun A => { pt := G.obj A.pt, π := NatTrans.mk fun j => G.map (A.π.app j) }) X✝).π.app j

Next tactic:
simp [-ConeMorphism.w, ← f.w j]
instance functorialityFull [Full G] [Faithful G] : Full (functoriality F G) where
  preimage t :=
    { hom := G.preimage t.hom
      w := fun j => G.map_injective (by 

Proof state:
J : Type u₁
inst✝⁵ : Category.{v₁, u₁} J
K : Type u₂
inst✝⁴ : Category.{v₂, u₂} K
C : Type u₃
inst✝³ : Category.{v₃, u₃} C
D : Type u₄
inst✝² : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝¹ : Full G
inst✝ : Faithful G
X✝ Y✝ : Cone F
t : (functoriality F G).obj X✝ ⟶ (functoriality F G).obj Y✝
j : J
⊢ G.map (G.preimage t.hom ≫ Y✝.π.app j) = G.map (X✝.π.app j)

Next tactic:
simpa using t.w j
instance functorialityFaithful [Faithful G] : Faithful (Cones.functoriality F G) where
  map_injective {c} {c'} f g e := by
    

Proof state:
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K : Type u₂
inst✝³ : Category.{v₂, u₂} K
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝ : Faithful G
c c' : Cone F
f g : c ⟶ c'
e : (functoriality F G).map f = (functoriality F G).map g
⊢ f = g

Next tactic:
apply ConeMorphism.ext f g
instance functorialityFaithful [Faithful G] : Faithful (Cones.functoriality F G) where
  map_injective {c} {c'} f g e := by
    apply ConeMorphism.ext f g
    

Proof state:
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K : Type u₂
inst✝³ : Category.{v₂, u₂} K
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝ : Faithful G
c c' : Cone F
f g : c ⟶ c'
e : (functoriality F G).map f = (functoriality F G).map g
⊢ f.hom = g.hom

Next tactic:
let f := ConeMorphism.mk.inj e
instance functorialityFaithful [Faithful G] : Faithful (Cones.functoriality F G) where
  map_injective {c} {c'} f g e := by
    apply ConeMorphism.ext f g
    let f := ConeMorphism.mk.inj e
    

Proof state:
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K : Type u₂
inst✝³ : Category.{v₂, u₂} K
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝ : Faithful G
c c' : Cone F
f✝ g : c ⟶ c'
e : (functoriality F G).map f✝ = (functoriality F G).map g
f : G.map f✝.hom = G.map g.hom := ConeMorphism.mk.inj e
⊢ f✝.hom = g.hom

Next tactic:
apply G.map_injective f
/-- If `F` reflects isomorphisms, then `Cones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cones.functoriality K F) := by
  

Proof state:
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝³ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
K : J ⥤ C
⊢ ReflectsIsomorphisms (functoriality K F)

Next tactic:
constructor
/-- If `F` reflects isomorphisms, then `Cones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cones.functoriality K F) := by
  constructor
  

Proof state:
case reflects
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝³ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
K : J ⥤ C
⊢ ∀ {A B : Cone K} (f : A ⟶ B) [inst : IsIso ((functoriality K F).map f)], IsIso f

Next tactic:
intro A B f _
/-- If `F` reflects isomorphisms, then `Cones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cones.functoriality K F) := by
  constructor
  intro A B f _
  

Proof state:
case reflects
J : Type u₁
inst✝⁵ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝⁴ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝³ : Category.{v₃, u₃} C
D : Type u₄
inst✝² : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝¹ : ReflectsIsomorphisms F
K : J ⥤ C
A B : Cone K
f : A ⟶ B
inst✝ : IsIso ((functoriality K F).map f)
⊢ IsIso f

Next tactic:
haveI : IsIso (F.map f.hom) :=
    (Cones.forget (K ⋙ F)).map_isIso ((Cones.functoriality K F).map f)
/-- If `F` reflects isomorphisms, then `Cones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cones.functoriality K F) := by
  constructor
  intro A B f _
  haveI : IsIso (F.map f.hom) :=
    (Cones.forget (K ⋙ F)).map_isIso ((Cones.functoriality K F).map f)
  

Proof state:
case reflects
J : Type u₁
inst✝⁵ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝⁴ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝³ : Category.{v₃, u₃} C
D : Type u₄
inst✝² : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝¹ : ReflectsIsomorphisms F
K : J ⥤ C
A B : Cone K
f : A ⟶ B
inst✝ : IsIso ((functoriality K F).map f)
this : IsIso (F.map f.hom)
⊢ IsIso f

Next tactic:
haveI := ReflectsIsomorphisms.reflects F f.hom
/-- If `F` reflects isomorphisms, then `Cones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cones.functoriality K F) := by
  constructor
  intro A B f _
  haveI : IsIso (F.map f.hom) :=
    (Cones.forget (K ⋙ F)).map_isIso ((Cones.functoriality K F).map f)
  haveI := ReflectsIsomorphisms.reflects F f.hom
  

Proof state:
case reflects
J : Type u₁
inst✝⁵ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝⁴ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝³ : Category.{v₃, u₃} C
D : Type u₄
inst✝² : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝¹ : ReflectsIsomorphisms F
K : J ⥤ C
A B : Cone K
f : A ⟶ B
inst✝ : IsIso ((functoriality K F).map f)
this✝ : IsIso (F.map f.hom)
this : IsIso f.hom
⊢ IsIso f

Next tactic:
apply cone_iso_of_hom_iso
@[ext]
theorem CoconeMorphism.ext {c c' : Cocone F} (f g : c ⟶ c') (w : f.hom = g.hom) : f = g := by
  

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c c' : Cocone F
f g : c ⟶ c'
w : f.hom = g.hom
⊢ f = g

Next tactic:
cases f
@[ext]
theorem CoconeMorphism.ext {c c' : Cocone F} (f g : c ⟶ c') (w : f.hom = g.hom) : f = g := by
  cases f
  

Proof state:
case mk
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c c' : Cocone F
g : c ⟶ c'
hom✝ : c.pt ⟶ c'.pt
w✝ : ∀ (j : J), c.ι.app j ≫ hom✝ = c'.ι.app j
w : (mk hom✝).hom = g.hom
⊢ mk hom✝ = g

Next tactic:
cases g
@[ext]
theorem CoconeMorphism.ext {c c' : Cocone F} (f g : c ⟶ c') (w : f.hom = g.hom) : f = g := by
  cases f
  cases g
  

Proof state:
case mk.mk
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c c' : Cocone F
hom✝¹ : c.pt ⟶ c'.pt
w✝¹ : ∀ (j : J), c.ι.app j ≫ hom✝¹ = c'.ι.app j
hom✝ : c.pt ⟶ c'.pt
w✝ : ∀ (j : J), c.ι.app j ≫ hom✝ = c'.ι.app j
w : (mk hom✝¹).hom = (mk hom✝).hom
⊢ mk hom✝¹ = mk hom✝

Next tactic:
congr
/-- Given a cocone morphism whose object part is an isomorphism, produce an
isomorphism of cocones.
-/
theorem cocone_iso_of_hom_iso {K : J ⥤ C} {c d : Cocone K} (f : c ⟶ d) [i : IsIso f.hom] :
    IsIso f :=
  ⟨⟨{ hom := inv f.hom
      w := fun j => (asIso f.hom).comp_inv_eq.2 (f.w j).symm }, by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝² : Category.{v₂, u₂} K✝
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F K : J ⥤ C
c d : Cocone K
f : c ⟶ d
i : IsIso f.hom
⊢ f ≫ CoconeMorphism.mk (inv f.hom) = 𝟙 c ∧ CoconeMorphism.mk (inv f.hom) ≫ f = 𝟙 d

Next tactic:
aesop_cat
/-- Whiskering by an equivalence gives an equivalence between categories of cones.
-/
@[simps]
def whiskeringEquivalence (e : K ≌ J) : Cocone F ≌ Cocone (e.functor ⋙ F) where
  functor := whiskering e.functor
  inverse :=
    whiskering e.inverse ⋙
      precompose
        ((Functor.leftUnitor F).inv ≫
          whiskerRight e.counitIso.inv F ≫ (Functor.associator _ _ _).inv)
  unitIso := NatIso.ofComponents fun s => Cocones.ext (Iso.refl _)
  counitIso := NatIso.ofComponents fun s =>
    Cocones.ext (Iso.refl _) fun k => by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
e : K ≌ J
s : Cocone (e.functor ⋙ F)
k : K
⊢ (((whiskering e.inverse ⋙
                    precompose
                      ((leftUnitor F).inv ≫ whiskerRight e.counitIso.inv F ≫ (associator e.inverse e.functor F).inv)) ⋙
                  whiskering e.functor).obj
              s).ι.app
        k ≫
      (Iso.refl
          (((whiskering e.inverse ⋙
                    precompose
                      ((leftUnitor F).inv ≫ whiskerRight e.counitIso.inv F ≫ (associator e.inverse e.functor F).inv)) ⋙
                  whiskering e.functor).obj
              s).pt).hom =
    ((𝟭 (Cocone (e.functor ⋙ F))).obj s).ι.app k

Next tactic:
simpa [e.counitInv_app_functor k] using s.w (e.unit.app k)
/-- A functor `G : C ⥤ D` sends cocones over `F` to cocones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cocone F ⥤ Cocone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      ι :=
        { app := fun j => G.map (A.ι.app j)
          naturality := by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
A : Cocone F
⊢ ∀ ⦃X Y : J⦄ (f : X ⟶ Y),
    (F ⋙ G).map f ≫ (fun j => G.map (A.ι.app j)) Y = (fun j => G.map (A.ι.app j)) X ≫ ((const J).obj (G.obj A.pt)).map f

Next tactic:
intros
/-- A functor `G : C ⥤ D` sends cocones over `F` to cocones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cocone F ⥤ Cocone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      ι :=
        { app := fun j => G.map (A.ι.app j)
          naturality := by intros; 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
A : Cocone F
X✝ Y✝ : J
f✝ : X✝ ⟶ Y✝
⊢ (F ⋙ G).map f✝ ≫ (fun j => G.map (A.ι.app j)) Y✝ =
    (fun j => G.map (A.ι.app j)) X✝ ≫ ((const J).obj (G.obj A.pt)).map f✝

Next tactic:
erw [← G.map_comp]
/-- A functor `G : C ⥤ D` sends cocones over `F` to cocones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cocone F ⥤ Cocone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      ι :=
        { app := fun j => G.map (A.ι.app j)
          naturality := by intros; erw [← G.map_comp]; 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
A : Cocone F
X✝ Y✝ : J
f✝ : X✝ ⟶ Y✝
⊢ G.map (F.map f✝ ≫ A.ι.app Y✝) = (fun j => G.map (A.ι.app j)) X✝ ≫ ((const J).obj (G.obj A.pt)).map f✝

Next tactic:
aesop_cat
/-- A functor `G : C ⥤ D` sends cocones over `F` to cocones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cocone F ⥤ Cocone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      ι :=
        { app := fun j => G.map (A.ι.app j)
          naturality := by intros; erw [← G.map_comp]; aesop_cat } }
  map f :=
    { hom := G.map f.hom
      w := by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
X✝ Y✝ : Cocone F
f : X✝ ⟶ Y✝
⊢ ∀ (j : J),
    ((fun A => { pt := G.obj A.pt, ι := NatTrans.mk fun j => G.map (A.ι.app j) }) X✝).ι.app j ≫ G.map f.hom =
      ((fun A => { pt := G.obj A.pt, ι := NatTrans.mk fun j => G.map (A.ι.app j) }) Y✝).ι.app j

Next tactic:
intros
/-- A functor `G : C ⥤ D` sends cocones over `F` to cocones over `F ⋙ G` functorially. -/
@[simps]
def functoriality : Cocone F ⥤ Cocone (F ⋙ G) where
  obj A :=
    { pt := G.obj A.pt
      ι :=
        { app := fun j => G.map (A.ι.app j)
          naturality := by intros; erw [← G.map_comp]; aesop_cat } }
  map f :=
    { hom := G.map f.hom
      w := by intros; 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
X✝ Y✝ : Cocone F
f : X✝ ⟶ Y✝
j✝ : J
⊢ ((fun A => { pt := G.obj A.pt, ι := NatTrans.mk fun j => G.map (A.ι.app j) }) X✝).ι.app j✝ ≫ G.map f.hom =
    ((fun A => { pt := G.obj A.pt, ι := NatTrans.mk fun j => G.map (A.ι.app j) }) Y✝).ι.app j✝

Next tactic:
rw [← Functor.map_comp, CoconeMorphism.w]
instance functorialityFull [Full G] [Faithful G] : Full (functoriality F G) where
  preimage t :=
    { hom := G.preimage t.hom
      w := fun j => G.map_injective (by 

Proof state:
J : Type u₁
inst✝⁵ : Category.{v₁, u₁} J
K : Type u₂
inst✝⁴ : Category.{v₂, u₂} K
C : Type u₃
inst✝³ : Category.{v₃, u₃} C
D : Type u₄
inst✝² : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝¹ : Full G
inst✝ : Faithful G
X✝ Y✝ : Cocone F
t : (functoriality F G).obj X✝ ⟶ (functoriality F G).obj Y✝
j : J
⊢ G.map (X✝.ι.app j ≫ G.preimage t.hom) = G.map (Y✝.ι.app j)

Next tactic:
simpa using t.w j
instance functoriality_faithful [Faithful G] : Faithful (functoriality F G) where
  map_injective {X} {Y} f g e := by
    

Proof state:
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K : Type u₂
inst✝³ : Category.{v₂, u₂} K
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝ : Faithful G
X Y : Cocone F
f g : X ⟶ Y
e : (functoriality F G).map f = (functoriality F G).map g
⊢ f = g

Next tactic:
apply CoconeMorphism.ext
instance functoriality_faithful [Faithful G] : Faithful (functoriality F G) where
  map_injective {X} {Y} f g e := by
    apply CoconeMorphism.ext
    

Proof state:
case w
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K : Type u₂
inst✝³ : Category.{v₂, u₂} K
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝ : Faithful G
X Y : Cocone F
f g : X ⟶ Y
e : (functoriality F G).map f = (functoriality F G).map g
⊢ f.hom = g.hom

Next tactic:
let h := CoconeMorphism.mk.inj e
instance functoriality_faithful [Faithful G] : Faithful (functoriality F G) where
  map_injective {X} {Y} f g e := by
    apply CoconeMorphism.ext
    let h := CoconeMorphism.mk.inj e
    

Proof state:
case w
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K : Type u₂
inst✝³ : Category.{v₂, u₂} K
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
inst✝ : Faithful G
X Y : Cocone F
f g : X ⟶ Y
e : (functoriality F G).map f = (functoriality F G).map g
h : G.map f.hom = G.map g.hom := CoconeMorphism.mk.inj e
⊢ f.hom = g.hom

Next tactic:
apply G.map_injective h
/-- If `e : C ≌ D` is an equivalence of categories, then `functoriality F e.functor` induces an
equivalence between cocones over `F` and cocones over `F ⋙ e.functor`.
-/
@[simps]
def functorialityEquivalence (e : C ≌ D) : Cocone F ≌ Cocone (F ⋙ e.functor) :=
  let f : (F ⋙ e.functor) ⋙ e.inverse ≅ F :=
    Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ e.unitIso.symm ≪≫ Functor.rightUnitor _
  { functor := functoriality F e.functor
    inverse := functoriality (F ⋙ e.functor) e.inverse ⋙ (precomposeEquivalence f.symm).functor
    unitIso := NatIso.ofComponents fun c => Cocones.ext (e.unitIso.app _)
    counitIso :=
      NatIso.ofComponents fun c => Cocones.ext (e.counitIso.app _)
        (fun j =>
          -- Unfortunately this doesn't work by `aesop_cat`.
          -- In this configuration `simp` reaches a dead-end and needs help.
          by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
G : C ⥤ D
e : C ≌ D
f : (F ⋙ e.functor) ⋙ e.inverse ≅ F :=
  associator F e.functor e.inverse ≪≫ isoWhiskerLeft F e.unitIso.symm ≪≫ rightUnitor F
c : Cocone (F ⋙ e.functor)
j : J
⊢ (((functoriality (F ⋙ e.functor) e.inverse ⋙ (precomposeEquivalence f.symm).functor) ⋙ functoriality F e.functor).obj
              c).ι.app
        j ≫
      (e.counitIso.app c.pt).hom =
    ((𝟭 (Cocone (F ⋙ e.functor))).obj c).ι.app j

Next tactic:
simp [← Equivalence.counitInv_app_functor]
/-- If `F` reflects isomorphisms, then `Cocones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cocone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cocones.functoriality K F) := by
  

Proof state:
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝³ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
K : J ⥤ C
⊢ ReflectsIsomorphisms (functoriality K F)

Next tactic:
constructor
/-- If `F` reflects isomorphisms, then `Cocones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cocone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cocones.functoriality K F) := by
  constructor
  

Proof state:
case reflects
J : Type u₁
inst✝⁴ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝³ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝² : Category.{v₃, u₃} C
D : Type u₄
inst✝¹ : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
K : J ⥤ C
⊢ ∀ {A B : Cocone K} (f : A ⟶ B) [inst : IsIso ((functoriality K F).map f)], IsIso f

Next tactic:
intro A B f _
/-- If `F` reflects isomorphisms, then `Cocones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cocone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cocones.functoriality K F) := by
  constructor
  intro A B f _
  

Proof state:
case reflects
J : Type u₁
inst✝⁵ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝⁴ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝³ : Category.{v₃, u₃} C
D : Type u₄
inst✝² : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝¹ : ReflectsIsomorphisms F
K : J ⥤ C
A B : Cocone K
f : A ⟶ B
inst✝ : IsIso ((functoriality K F).map f)
⊢ IsIso f

Next tactic:
haveI : IsIso (F.map f.hom) :=
    (Cocones.forget (K ⋙ F)).map_isIso ((Cocones.functoriality K F).map f)
/-- If `F` reflects isomorphisms, then `Cocones.functoriality F` reflects isomorphisms
as well.
-/
instance reflects_cocone_isomorphism (F : C ⥤ D) [ReflectsIsomorphisms F] (K : J ⥤ C) :
    ReflectsIsomorphisms (Cocones.functoriality K F) := by
  constructor
  intro A B f _
  haveI : IsIso (F.map f.hom) :=
    (Cocones.forget (K ⋙ F)).map_isIso ((Cocones.functoriality K F).map f)
  

Proof state:
case reflects
J : Type u₁
inst✝⁵ : Category.{v₁, u₁} J
K✝ : Type u₂
inst✝⁴ : Category.{v₂, u₂} K✝
C : Type u₃
inst✝³ : Category.{v₃, u₃} C
D : Type u₄
inst✝² : Category.{v₄, u₄} D
F✝ : J ⥤ C
G F : C ⥤ D
inst✝¹ : ReflectsIsomorphisms F
K : J ⥤ C
A B : Cocone K
f : A ⟶ B
inst✝ : IsIso ((functoriality K F).map f)
this : IsIso (F.map f.hom)
⊢ IsIso f

Next tactic:
haveI := ReflectsIsomorphisms.reflects F f.hom