l3lab/ntp-mathlib huggingface dataset:
/-- Construct a pseudofunctor from an oplax functor whose `mapId` and `mapComp` are isomorphisms.
-/
@[simps]
noncomputable def mkOfOplax' (F : OplaxFunctor B C) [∀ a, IsIso (F.mapId a)]
    [∀ {a b c} (f : a ⟶ b) (g : b ⟶ c), IsIso (F.mapComp f g)] : Pseudofunctor B C :=
  { (F : PrelaxFunctor B C) with
    mapId := fun a => asIso (F.mapId a)
    mapComp := fun f g => asIso (F.mapComp f g)
    map₂_whisker_left := fun f g h η => by
      dsimp
      rw [← assoc, IsIso.eq_comp_inv, F.mapComp_naturality_right]
    map₂_whisker_right := fun η h => by
      dsimp
      rw [← assoc, IsIso.eq_comp_inv, F.mapComp_naturality_left]
    map₂_associator := fun f g h => by
      dsimp
      simp only [← assoc]
      

Proof state:
B : Type u₁
inst✝⁴ : Bicategory B
C : Type u₂
inst✝³ : Bicategory C
D : Type u₃
inst✝² : Bicategory D
F✝ : Pseudofunctor B C
F : OplaxFunctor B C
inst✝¹ : ∀ (a : B), IsIso (OplaxFunctor.mapId F a)
inst✝ : ∀ {a b c : B} (f : a ⟶ b) (g : b ⟶ c), IsIso (OplaxFunctor.mapComp F f g)
src✝ : PrelaxFunctor B C := F.toPrelaxFunctor
a✝ b✝ c✝ d✝ : B
f : a✝ ⟶ b✝
g : b✝ ⟶ c✝
h : c✝ ⟶ d✝
⊢ PrelaxFunctor.map₂ F.toPrelaxFunctor (α_ f g h).hom =
    (((OplaxFunctor.mapComp F (f ≫ g) h ≫ OplaxFunctor.mapComp F f g ▷ (↑F.toPrelaxFunctor).map h) ≫
          (α_ ((↑F.toPrelaxFunctor).map f) ((↑F.toPrelaxFunctor).map g) ((↑F.toPrelaxFunctor).map h)).hom) ≫
        (↑F.toPrelaxFunctor).map f ◁ inv (OplaxFunctor.mapComp F g h)) ≫
      inv (OplaxFunctor.mapComp F f (g ≫ h))

Next tactic:
rw [IsIso.eq_comp_inv, ← inv_whiskerLeft, IsIso.eq_comp_inv]
/-- Construct a pseudofunctor from an oplax functor whose `mapId` and `mapComp` are isomorphisms.
-/
@[simps]
noncomputable def mkOfOplax' (F : OplaxFunctor B C) [∀ a, IsIso (F.mapId a)]
    [∀ {a b c} (f : a ⟶ b) (g : b ⟶ c), IsIso (F.mapComp f g)] : Pseudofunctor B C :=
  { (F : PrelaxFunctor B C) with
    mapId := fun a => asIso (F.mapId a)
    mapComp := fun f g => asIso (F.mapComp f g)
    map₂_whisker_left := fun f g h η => by
      dsimp
      rw [← assoc, IsIso.eq_comp_inv, F.mapComp_naturality_right]
    map₂_whisker_right := fun η h => by
      dsimp
      rw [← assoc, IsIso.eq_comp_inv, F.mapComp_naturality_left]
    map₂_associator := fun f g h => by
      dsimp
      simp only [← assoc]
      rw [IsIso.eq_comp_inv, ← inv_whiskerLeft, IsIso.eq_comp_inv]
      

Proof state:
B : Type u₁
inst✝⁴ : Bicategory B
C : Type u₂
inst✝³ : Bicategory C
D : Type u₃
inst✝² : Bicategory D
F✝ : Pseudofunctor B C
F : OplaxFunctor B C
inst✝¹ : ∀ (a : B), IsIso (OplaxFunctor.mapId F a)
inst✝ : ∀ {a b c : B} (f : a ⟶ b) (g : b ⟶ c), IsIso (OplaxFunctor.mapComp F f g)
src✝ : PrelaxFunctor B C := F.toPrelaxFunctor
a✝ b✝ c✝ d✝ : B
f : a✝ ⟶ b✝
g : b✝ ⟶ c✝
h : c✝ ⟶ d✝
⊢ (PrelaxFunctor.map₂ F.toPrelaxFunctor (α_ f g h).hom ≫ OplaxFunctor.mapComp F f (g ≫ h)) ≫
      (↑F.toPrelaxFunctor).map f ◁ OplaxFunctor.mapComp F g h =
    (OplaxFunctor.mapComp F (f ≫ g) h ≫ OplaxFunctor.mapComp F f g ▷ (↑F.toPrelaxFunctor).map h) ≫
      (α_ ((↑F.toPrelaxFunctor).map f) ((↑F.toPrelaxFunctor).map g) ((↑F.toPrelaxFunctor).map h)).hom

Next tactic:
simp only [assoc, F.map₂_associator]
/-- The abelian coimage in a functor category can be calculated componentwise. -/
@[simps!]
def coimageObjIso : (Abelian.coimage α).obj X ≅ Abelian.coimage (α.app X) :=
  PreservesCokernel.iso ((evaluation C D).obj X) _ ≪≫
    cokernel.mapIso _ _ (PreservesKernel.iso ((evaluation C D).obj X) _) (Iso.refl _)
      (by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ ((evaluation C D).obj X).map (kernel.ι α) ≫ (Iso.refl (((evaluation C D).obj X).obj F)).hom =
    (PreservesKernel.iso ((evaluation C D).obj X) α).hom ≫ kernel.ι (α.app X)

Next tactic:
dsimp
/-- The abelian coimage in a functor category can be calculated componentwise. -/
@[simps!]
def coimageObjIso : (Abelian.coimage α).obj X ≅ Abelian.coimage (α.app X) :=
  PreservesCokernel.iso ((evaluation C D).obj X) _ ≪≫
    cokernel.mapIso _ _ (PreservesKernel.iso ((evaluation C D).obj X) _) (Iso.refl _)
      (by
        dsimp
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (kernel.ι α).app X ≫ 𝟙 (F.obj X) = (PreservesKernel.iso ((evaluation C D).obj X) α).hom ≫ kernel.ι (α.app X)

Next tactic:
simp only [Category.comp_id, PreservesKernel.iso_hom]
/-- The abelian coimage in a functor category can be calculated componentwise. -/
@[simps!]
def coimageObjIso : (Abelian.coimage α).obj X ≅ Abelian.coimage (α.app X) :=
  PreservesCokernel.iso ((evaluation C D).obj X) _ ≪≫
    cokernel.mapIso _ _ (PreservesKernel.iso ((evaluation C D).obj X) _) (Iso.refl _)
      (by
        dsimp
        simp only [Category.comp_id, PreservesKernel.iso_hom]
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (kernel.ι α).app X = kernelComparison α ((evaluation C D).obj X) ≫ kernel.ι (α.app X)

Next tactic:
exact (kernelComparison_comp_ι _ ((evaluation C D).obj X)).symm
/-- The abelian image in a functor category can be calculated componentwise. -/
@[simps!]
def imageObjIso : (Abelian.image α).obj X ≅ Abelian.image (α.app X) :=
  PreservesKernel.iso ((evaluation C D).obj X) _ ≪≫
    kernel.mapIso _ _ (Iso.refl _) (PreservesCokernel.iso ((evaluation C D).obj X) _)
      (by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ ((evaluation C D).obj X).map (cokernel.π α) ≫ (PreservesCokernel.iso ((evaluation C D).obj X) α).hom =
    (Iso.refl (((evaluation C D).obj X).obj G)).hom ≫ cokernel.π (α.app X)

Next tactic:
apply (cancel_mono (PreservesCokernel.iso ((evaluation C D).obj X) α).inv).1
/-- The abelian image in a functor category can be calculated componentwise. -/
@[simps!]
def imageObjIso : (Abelian.image α).obj X ≅ Abelian.image (α.app X) :=
  PreservesKernel.iso ((evaluation C D).obj X) _ ≪≫
    kernel.mapIso _ _ (Iso.refl _) (PreservesCokernel.iso ((evaluation C D).obj X) _)
      (by
        apply (cancel_mono (PreservesCokernel.iso ((evaluation C D).obj X) α).inv).1
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (((evaluation C D).obj X).map (cokernel.π α) ≫ (PreservesCokernel.iso ((evaluation C D).obj X) α).hom) ≫
      (PreservesCokernel.iso ((evaluation C D).obj X) α).inv =
    ((Iso.refl (((evaluation C D).obj X).obj G)).hom ≫ cokernel.π (α.app X)) ≫
      (PreservesCokernel.iso ((evaluation C D).obj X) α).inv

Next tactic:
simp only [Category.assoc, Iso.hom_inv_id]
/-- The abelian image in a functor category can be calculated componentwise. -/
@[simps!]
def imageObjIso : (Abelian.image α).obj X ≅ Abelian.image (α.app X) :=
  PreservesKernel.iso ((evaluation C D).obj X) _ ≪≫
    kernel.mapIso _ _ (Iso.refl _) (PreservesCokernel.iso ((evaluation C D).obj X) _)
      (by
        apply (cancel_mono (PreservesCokernel.iso ((evaluation C D).obj X) α).inv).1
        simp only [Category.assoc, Iso.hom_inv_id]
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ ((evaluation C D).obj X).map (cokernel.π α) ≫ 𝟙 (((evaluation C D).obj X).obj (cokernel α)) =
    (Iso.refl (((evaluation C D).obj X).obj G)).hom ≫
      cokernel.π (α.app X) ≫ (PreservesCokernel.iso ((evaluation C D).obj X) α).inv

Next tactic:
dsimp
/-- The abelian image in a functor category can be calculated componentwise. -/
@[simps!]
def imageObjIso : (Abelian.image α).obj X ≅ Abelian.image (α.app X) :=
  PreservesKernel.iso ((evaluation C D).obj X) _ ≪≫
    kernel.mapIso _ _ (Iso.refl _) (PreservesCokernel.iso ((evaluation C D).obj X) _)
      (by
        apply (cancel_mono (PreservesCokernel.iso ((evaluation C D).obj X) α).inv).1
        simp only [Category.assoc, Iso.hom_inv_id]
        dsimp
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (cokernel.π α).app X ≫ 𝟙 ((cokernel α).obj X) =
    𝟙 (G.obj X) ≫ cokernel.π (α.app X) ≫ (PreservesCokernel.iso ((evaluation C D).obj X) α).inv

Next tactic:
simp only [PreservesCokernel.iso_inv, Category.id_comp, Category.comp_id]
/-- The abelian image in a functor category can be calculated componentwise. -/
@[simps!]
def imageObjIso : (Abelian.image α).obj X ≅ Abelian.image (α.app X) :=
  PreservesKernel.iso ((evaluation C D).obj X) _ ≪≫
    kernel.mapIso _ _ (Iso.refl _) (PreservesCokernel.iso ((evaluation C D).obj X) _)
      (by
        apply (cancel_mono (PreservesCokernel.iso ((evaluation C D).obj X) α).inv).1
        simp only [Category.assoc, Iso.hom_inv_id]
        dsimp
        simp only [PreservesCokernel.iso_inv, Category.id_comp, Category.comp_id]
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (cokernel.π α).app X = cokernel.π (α.app X) ≫ cokernelComparison α ((evaluation C D).obj X)

Next tactic:
exact (π_comp_cokernelComparison _ ((evaluation C D).obj X)).symm
theorem coimageImageComparison_app :
    coimageImageComparison (α.app X) =
      (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ coimageImageComparison (α.app X) = (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom

Next tactic:
ext
theorem coimageImageComparison_app :
    coimageImageComparison (α.app X) =
      (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom := by
  ext
  

Proof state:
case h.h
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (coequalizer.π (kernel.ι (α.app X)) 0 ≫ coimageImageComparison (α.app X)) ≫ equalizer.ι (cokernel.π (α.app X)) 0 =
    (coequalizer.π (kernel.ι (α.app X)) 0 ≫
        (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom) ≫
      equalizer.ι (cokernel.π (α.app X)) 0

Next tactic:
dsimp
theorem coimageImageComparison_app :
    coimageImageComparison (α.app X) =
      (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom := by
  ext
  dsimp
  

Proof state:
case h.h
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (cokernel.π (kernel.ι (α.app X)) ≫ coimageImageComparison (α.app X)) ≫ kernel.ι (cokernel.π (α.app X)) =
    (cokernel.π (kernel.ι (α.app X)) ≫
        (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom) ≫
      kernel.ι (cokernel.π (α.app X))

Next tactic:
dsimp [imageObjIso, coimageObjIso, cokernel.map]
theorem coimageImageComparison_app :
    coimageImageComparison (α.app X) =
      (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom := by
  ext
  dsimp
  dsimp [imageObjIso, coimageObjIso, cokernel.map]
  

Proof state:
case h.h
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (cokernel.π (kernel.ι (α.app X)) ≫ coimageImageComparison (α.app X)) ≫ kernel.ι (cokernel.π (α.app X)) =
    (cokernel.π (kernel.ι (α.app X)) ≫
        (cokernel.desc (kernel.ι (α.app X)) (𝟙 (F.obj X) ≫ cokernel.π ((kernel.ι α).app X))
              (_ : kernel.ι (α.app X) ≫ 𝟙 (F.obj X) ≫ cokernel.π ((kernel.ι α).app X) = 0) ≫
            (PreservesCokernel.iso ((evaluation C D).obj X) (kernel.ι α)).inv) ≫
          (coimageImageComparison α).app X ≫
            (PreservesKernel.iso ((evaluation C D).obj X) (cokernel.π α)).hom ≫
              kernel.map ((cokernel.π α).app X) (cokernel.π (α.app X)) (𝟙 (G.obj X))
                (PreservesCokernel.iso ((evaluation C D).obj X) α).hom
                (_ :
                  ((evaluation C D).obj X).map (cokernel.π α) ≫ (PreservesCokernel.iso ((evaluation C D).obj X) α).hom =
                    (Iso.refl (((evaluation C D).obj X).obj G)).hom ≫ cokernel.π (α.app X))) ≫
      kernel.ι (cokernel.π (α.app X))

Next tactic:
simp only [coimage_image_factorisation, PreservesKernel.iso_hom, Category.assoc,
    kernel.lift_ι, Category.comp_id, PreservesCokernel.iso_inv,
    cokernel.π_desc_assoc, Category.id_comp]
theorem coimageImageComparison_app :
    coimageImageComparison (α.app X) =
      (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom := by
  ext
  dsimp
  dsimp [imageObjIso, coimageObjIso, cokernel.map]
  simp only [coimage_image_factorisation, PreservesKernel.iso_hom, Category.assoc,
    kernel.lift_ι, Category.comp_id, PreservesCokernel.iso_inv,
    cokernel.π_desc_assoc, Category.id_comp]
  

Proof state:
case h.h
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ α.app X =
    cokernel.π ((kernel.ι α).app X) ≫
      cokernelComparison (kernel.ι α) ((evaluation C D).obj X) ≫
        (coimageImageComparison α).app X ≫
          kernelComparison (cokernel.π α) ((evaluation C D).obj X) ≫ kernel.ι ((cokernel.π α).app X)

Next tactic:
erw [kernelComparison_comp_ι _ ((evaluation C D).obj X),
    π_comp_cokernelComparison_assoc _ ((evaluation C D).obj X)]
theorem coimageImageComparison_app :
    coimageImageComparison (α.app X) =
      (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom := by
  ext
  dsimp
  dsimp [imageObjIso, coimageObjIso, cokernel.map]
  simp only [coimage_image_factorisation, PreservesKernel.iso_hom, Category.assoc,
    kernel.lift_ι, Category.comp_id, PreservesCokernel.iso_inv,
    cokernel.π_desc_assoc, Category.id_comp]
  erw [kernelComparison_comp_ι _ ((evaluation C D).obj X),
    π_comp_cokernelComparison_assoc _ ((evaluation C D).obj X)]
  

Proof state:
case h.h
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ α.app X =
    ((evaluation C D).obj X).map (cokernel.π (kernel.ι α)) ≫
      (coimageImageComparison α).app X ≫ ((evaluation C D).obj X).map (kernel.ι (cokernel.π α))

Next tactic:
conv_lhs => rw [← coimage_image_factorisation α]
theorem coimageImageComparison_app :
    coimageImageComparison (α.app X) =
      (coimageObjIso α X).inv ≫ (coimageImageComparison α).app X ≫ (imageObjIso α X).hom := by
  ext
  dsimp
  dsimp [imageObjIso, coimageObjIso, cokernel.map]
  simp only [coimage_image_factorisation, PreservesKernel.iso_hom, Category.assoc,
    kernel.lift_ι, Category.comp_id, PreservesCokernel.iso_inv,
    cokernel.π_desc_assoc, Category.id_comp]
  erw [kernelComparison_comp_ι _ ((evaluation C D).obj X),
    π_comp_cokernelComparison_assoc _ ((evaluation C D).obj X)]
  conv_lhs => 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
| α.app X

Next tactic:
rw [← coimage_image_factorisation α]
theorem coimageImageComparison_app' :
    (coimageImageComparison α).app X =
      (coimageObjIso α X).hom ≫ coimageImageComparison (α.app X) ≫ (imageObjIso α X).inv := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ (coimageImageComparison α).app X = (coimageObjIso α X).hom ≫ coimageImageComparison (α.app X) ≫ (imageObjIso α X).inv

Next tactic:
simp only [coimageImageComparison_app, Iso.hom_inv_id_assoc, Iso.hom_inv_id, Category.assoc,
    Category.comp_id]
instance functor_category_isIso_coimageImageComparison :
    IsIso (Abelian.coimageImageComparison α) := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ IsIso (coimageImageComparison α)

Next tactic:
have : ∀ X : C, IsIso ((Abelian.coimageImageComparison α).app X) := by
    intros
    rw [coimageImageComparison_app']
    infer_instance
instance functor_category_isIso_coimageImageComparison :
    IsIso (Abelian.coimageImageComparison α) := by
  have : ∀ X : C, IsIso ((Abelian.coimageImageComparison α).app X) := by
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
⊢ ∀ (X : C), IsIso ((coimageImageComparison α).app X)

Next tactic:
intros
instance functor_category_isIso_coimageImageComparison :
    IsIso (Abelian.coimageImageComparison α) := by
  have : ∀ X : C, IsIso ((Abelian.coimageImageComparison α).app X) := by
    intros
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X X✝ : C
⊢ IsIso ((coimageImageComparison α).app X✝)

Next tactic:
rw [coimageImageComparison_app']
instance functor_category_isIso_coimageImageComparison :
    IsIso (Abelian.coimageImageComparison α) := by
  have : ∀ X : C, IsIso ((Abelian.coimageImageComparison α).app X) := by
    intros
    rw [coimageImageComparison_app']
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X X✝ : C
⊢ IsIso ((coimageObjIso α X✝).hom ≫ coimageImageComparison (α.app X✝) ≫ (imageObjIso α X✝).inv)

Next tactic:
infer_instance
instance functor_category_isIso_coimageImageComparison :
    IsIso (Abelian.coimageImageComparison α) := by
  have : ∀ X : C, IsIso ((Abelian.coimageImageComparison α).app X) := by
    intros
    rw [coimageImageComparison_app']
    infer_instance
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type w
inst✝¹ : Category.{z, w} D
inst✝ : Abelian D
F G : C ⥤ D
α : F ⟶ G
X : C
this : ∀ (X : C), IsIso ((coimageImageComparison α).app X)
⊢ IsIso (coimageImageComparison α)

Next tactic:
apply NatIso.isIso_of_isIso_app
/-- `I × J` as an ideal of `R × S`. -/
def prod : Ideal (R × S) where
  carrier := { x | x.fst ∈ I ∧ x.snd ∈ J }
  zero_mem' := by simp
  add_mem' := by
    

Proof state:
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I I' : Ideal R
J J' : Ideal S
⊢ ∀ {a b : R × S}, a ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → a + b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J}

Next tactic:
rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨ha₁, ha₂⟩ ⟨hb₁, hb₂⟩
/-- `I × J` as an ideal of `R × S`. -/
def prod : Ideal (R × S) where
  carrier := { x | x.fst ∈ I ∧ x.snd ∈ J }
  zero_mem' := by simp
  add_mem' := by
    rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨ha₁, ha₂⟩ ⟨hb₁, hb₂⟩
    

Proof state:
case mk.mk.intro.intro
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I I' : Ideal R
J J' : Ideal S
a₁ : R
a₂ : S
b₁ : R
b₂ : S
ha₁ : (a₁, a₂).1 ∈ I
ha₂ : (a₁, a₂).2 ∈ J
hb₁ : (b₁, b₂).1 ∈ I
hb₂ : (b₁, b₂).2 ∈ J
⊢ (a₁, a₂) + (b₁, b₂) ∈ {x | x.1 ∈ I ∧ x.2 ∈ J}

Next tactic:
exact ⟨I.add_mem ha₁ hb₁, J.add_mem ha₂ hb₂⟩
/-- `I × J` as an ideal of `R × S`. -/
def prod : Ideal (R × S) where
  carrier := { x | x.fst ∈ I ∧ x.snd ∈ J }
  zero_mem' := by 

Proof state:
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I I' : Ideal R
J J' : Ideal S
⊢ 0 ∈
    { carrier := {x | x.1 ∈ I ∧ x.2 ∈ J},
        add_mem' :=
          (_ :
            ∀ {a b : R × S},
              a ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → a + b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J}) }.carrier

Next tactic:
simp
/-- `I × J` as an ideal of `R × S`. -/
def prod : Ideal (R × S) where
  carrier := { x | x.fst ∈ I ∧ x.snd ∈ J }
  zero_mem' := by simp
  add_mem' := by
    rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨ha₁, ha₂⟩ ⟨hb₁, hb₂⟩
    exact ⟨I.add_mem ha₁ hb₁, J.add_mem ha₂ hb₂⟩
  smul_mem' := by
    

Proof state:
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I I' : Ideal R
J J' : Ideal S
⊢ ∀ (c : R × S) {x : R × S},
    x ∈
        {
              toAddSubsemigroup :=
                { carrier := {x | x.1 ∈ I ∧ x.2 ∈ J},
                  add_mem' :=
                    (_ :
                      ∀ {a b : R × S},
                        a ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → a + b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J}) },
              zero_mem' := (_ : 0 ∈ I ∧ 0 ∈ J) }.toAddSubsemigroup.carrier →
      c • x ∈
        {
              toAddSubsemigroup :=
                { carrier := {x | x.1 ∈ I ∧ x.2 ∈ J},
                  add_mem' :=
                    (_ :
                      ∀ {a b : R × S},
                        a ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → a + b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J}) },
              zero_mem' := (_ : 0 ∈ I ∧ 0 ∈ J) }.toAddSubsemigroup.carrier

Next tactic:
rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨hb₁, hb₂⟩
/-- `I × J` as an ideal of `R × S`. -/
def prod : Ideal (R × S) where
  carrier := { x | x.fst ∈ I ∧ x.snd ∈ J }
  zero_mem' := by simp
  add_mem' := by
    rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨ha₁, ha₂⟩ ⟨hb₁, hb₂⟩
    exact ⟨I.add_mem ha₁ hb₁, J.add_mem ha₂ hb₂⟩
  smul_mem' := by
    rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨hb₁, hb₂⟩
    

Proof state:
case mk.mk.intro
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I I' : Ideal R
J J' : Ideal S
a₁ : R
a₂ : S
b₁ : R
b₂ : S
hb₁ : (b₁, b₂).1 ∈ I
hb₂ : (b₁, b₂).2 ∈ J
⊢ (a₁, a₂) • (b₁, b₂) ∈
    {
          toAddSubsemigroup :=
            { carrier := {x | x.1 ∈ I ∧ x.2 ∈ J},
              add_mem' :=
                (_ :
                  ∀ {a b : R × S},
                    a ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J} → a + b ∈ {x | x.1 ∈ I ∧ x.2 ∈ J}) },
          zero_mem' := (_ : 0 ∈ I ∧ 0 ∈ J) }.toAddSubsemigroup.carrier

Next tactic:
exact ⟨I.mul_mem_left _ hb₁, J.mul_mem_left _ hb₂⟩
@[simp]
theorem prod_top_top : prod (⊤ : Ideal R) (⊤ : Ideal S) = ⊤ :=
  Ideal.ext <| by 

Proof state:
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I I' : Ideal R
J J' : Ideal S
⊢ ∀ (x : R × S), x ∈ prod ⊤ ⊤ ↔ x ∈ ⊤

Next tactic:
simp
/-- Every ideal of the product ring is of the form `I × J`, where `I` and `J` can be explicitly
    given as the image under the projection maps. -/
theorem ideal_prod_eq (I : Ideal (R × S)) :
    I = Ideal.prod (map (RingHom.fst R S) I : Ideal R) (map (RingHom.snd R S) I) := by
  

Proof state:
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I✝ I' : Ideal R
J J' : Ideal S
I : Ideal (R × S)
⊢ I = prod (map (RingHom.fst R S) I) (map (RingHom.snd R S) I)

Next tactic:
apply Ideal.ext
/-- Every ideal of the product ring is of the form `I × J`, where `I` and `J` can be explicitly
    given as the image under the projection maps. -/
theorem ideal_prod_eq (I : Ideal (R × S)) :
    I = Ideal.prod (map (RingHom.fst R S) I : Ideal R) (map (RingHom.snd R S) I) := by
  apply Ideal.ext
  

Proof state:
case h
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I✝ I' : Ideal R
J J' : Ideal S
I : Ideal (R × S)
⊢ ∀ (x : R × S), x ∈ I ↔ x ∈ prod (map (RingHom.fst R S) I) (map (RingHom.snd R S) I)

Next tactic:
rintro ⟨r, s⟩
/-- Every ideal of the product ring is of the form `I × J`, where `I` and `J` can be explicitly
    given as the image under the projection maps. -/
theorem ideal_prod_eq (I : Ideal (R × S)) :
    I = Ideal.prod (map (RingHom.fst R S) I : Ideal R) (map (RingHom.snd R S) I) := by
  apply Ideal.ext
  rintro ⟨r, s⟩
  

Proof state:
case h.mk
R : Type u
S : Type v
inst✝¹ : Semiring R
inst✝ : Semiring S
I✝ I' : Ideal R
J J' : Ideal S
I : Ideal (R × S)
r : R
s : S
⊢ (r, s) ∈ I ↔ (r, s) ∈ prod (map (RingHom.fst R S) I) (map (RingHom.snd R S) I)

Next tactic:
rw [mem_prod, mem_map_iff_of_surjective (RingHom.fst R S) Prod.fst_surjective,
    mem_map_iff_of_surjective (RingHom.snd R S) Prod.snd_surjective]