[GOAL]
X Y Z : TopCat
U : (Opens ↑X)ᵒᵖ
⊢ (map (𝟙 X)).op.obj U = U
[PROOFSTEP]
simp
[GOAL]
X Y Z : TopCat
f : X ⟶ Y
ι : Type u_1
U : ι → Opens ↑Y
⊢ (map f).obj (iSup U) = iSup ((map f).toPrefunctor.obj ∘ U)
[PROOFSTEP]
ext1
[GOAL]
case h
X Y Z : TopCat
f : X ⟶ Y
ι : Type u_1
U : ι → Opens ↑Y
⊢ ↑((map f).obj (iSup U)) = ↑(iSup ((map f).toPrefunctor.obj ∘ U))
[PROOFSTEP]
rw [iSup_def, iSup_def, map_obj]
[GOAL]
case h
X Y Z : TopCat
f : X ⟶ Y
ι : Type u_1
U : ι → Opens ↑Y
⊢ ↑{ carrier := ↑f ⁻¹' ⋃ (i : ι), ↑(U i), is_open' := (_ : IsOpen (↑f ⁻¹' ⋃ (i : ι), ↑(U i))) } =
    ↑{ carrier := ⋃ (i : ι), ↑(((map f).toPrefunctor.obj ∘ U) i),
        is_open' := (_ : IsOpen (⋃ (i : ι), ↑(((map f).toPrefunctor.obj ∘ U) i))) }
[PROOFSTEP]
dsimp
[GOAL]
case h
X Y Z : TopCat
f : X ⟶ Y
ι : Type u_1
U : ι → Opens ↑Y
⊢ ↑f ⁻¹' ⋃ (i : ι), ↑(U i) = ⋃ (i : ι), ↑((map f).obj (U i))
[PROOFSTEP]
rw [Set.preimage_iUnion]
[GOAL]
case h
X Y Z : TopCat
f : X ⟶ Y
ι : Type u_1
U : ι → Opens ↑Y
⊢ ⋃ (i : ι), ↑f ⁻¹' ↑(U i) = ⋃ (i : ι), ↑((map f).obj (U i))
[PROOFSTEP]
rfl
[GOAL]
X Y Z : TopCat
⊢ map (𝟙 X) = 𝟭 (Opens ↑X)
[PROOFSTEP]
rfl
[GOAL]
X Y Z : TopCat
f g : X ⟶ Y
h : f = g
U : Opens ↑Y
⊢ (map f).obj U = (map g).obj U
[PROOFSTEP]
rw [congr_arg map h]
[GOAL]
X Y Z : TopCat
f g : X ⟶ Y
h : f = g
⊢ map f = map g
[PROOFSTEP]
subst h
[GOAL]
X Y Z : TopCat
f : X ⟶ Y
⊢ map f = map f
[PROOFSTEP]
rfl
[GOAL]
X Y Z : TopCat
f g : X ⟶ Y
h : f = g
U : Opens ↑Y
⊢ (map f).obj U = (map g).obj U
[PROOFSTEP]
rw [h]
[GOAL]
X Y Z : TopCat
f g : X ⟶ Y
h : f = g
U : Opens ↑Y
⊢ (map g).obj U = (map f).obj U
[PROOFSTEP]
rw [h]
[GOAL]
X✝ Y✝ Z X Y : TopCat
H : X ≅ Y
U : Opens ↑Y
⊢ (𝟭 (Opens ↑Y)).obj U = (map H.hom ⋙ map H.inv).obj U
[PROOFSTEP]
simp [map, Set.preimage_preimage]
[GOAL]
X✝ Y✝ Z X Y : TopCat
H : X ≅ Y
U : Opens ↑X
⊢ (map H.inv ⋙ map H.hom).obj U = (𝟭 (Opens ↑X)).obj U
[PROOFSTEP]
simp [map, Set.preimage_preimage]
[GOAL]
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
H : Mono f
X✝ Y✝ : Opens ↑X
i : (functor hf).obj X✝ ⟶ (functor hf).obj Y✝
x : ↑X
hx : x ∈ ↑X✝
⊢ x ∈ ↑Y✝
[PROOFSTEP]
obtain ⟨y, hy, eq⟩ := i.le ⟨x, hx, rfl⟩
[GOAL]
case intro.intro
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
H : Mono f
X✝ Y✝ : Opens ↑X
i : (functor hf).obj X✝ ⟶ (functor hf).obj Y✝
x : ↑X
hx : x ∈ ↑X✝
y : (forget TopCat).obj X
hy : y ∈ ↑Y✝
eq : ↑f y = ↑f x
⊢ x ∈ ↑Y✝
[PROOFSTEP]
exact (TopCat.mono_iff_injective f).mp H eq ▸ hy
[GOAL]
X : TopCat
U : Opens ↑X
⊢ (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj ⊤ = U
[PROOFSTEP]
ext1
[GOAL]
case h
X : TopCat
U : Opens ↑X
⊢ ↑((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj ⊤) = ↑U
[PROOFSTEP]
exact Set.image_univ.trans Subtype.range_coe
[GOAL]
X : TopCat
U : Opens ↑X
⊢ (map (inclusion U)).obj U = ⊤
[PROOFSTEP]
ext1
[GOAL]
case h
X : TopCat
U : Opens ↑X
⊢ ↑((map (inclusion U)).obj U) = ↑⊤
[PROOFSTEP]
exact Subtype.coe_preimage_self _
[GOAL]
X : TopCat
U : Opens ↑X
⊢ (map (inclusion U) ⋙ IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj U = (𝟭 (Opens ↑X)).obj U
[PROOFSTEP]
simp
[GOAL]
X : TopCat
⊢ IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤)) = map (inclusionTopIso X).inv
[PROOFSTEP]
refine' CategoryTheory.Functor.ext _ _
[GOAL]
case refine'_1
X : TopCat
⊢ ∀ (X_1 : Opens ↑((toTopCat X).obj ⊤)),
    (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).obj X_1 = (map (inclusionTopIso X).inv).obj X_1
[PROOFSTEP]
intro U
[GOAL]
case refine'_1
X : TopCat
U : Opens ↑((toTopCat X).obj ⊤)
⊢ (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).obj U = (map (inclusionTopIso X).inv).obj U
[PROOFSTEP]
ext x
[GOAL]
case refine'_1.h.h
X : TopCat
U : Opens ↑((toTopCat X).obj ⊤)
x : ↑X
⊢ x ∈ ↑((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).obj U) ↔ x ∈ ↑((map (inclusionTopIso X).inv).obj U)
[PROOFSTEP]
exact ⟨fun ⟨⟨_, _⟩, h, rfl⟩ => h, fun h => ⟨⟨x, trivial⟩, h, rfl⟩⟩
[GOAL]
case refine'_2
X : TopCat
⊢ ∀ (X_1 Y : Opens ↑((toTopCat X).obj ⊤)) (f : X_1 ⟶ Y),
    (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).map f =
      eqToHom (_ : (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).obj X_1 = (map (inclusionTopIso X).inv).obj X_1) ≫
        (map (inclusionTopIso X).inv).map f ≫
          eqToHom (_ : (map (inclusionTopIso X).inv).obj Y = (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).obj Y)
[PROOFSTEP]
intros U V f
[GOAL]
case refine'_2
X : TopCat
U V : Opens ↑((toTopCat X).obj ⊤)
f : U ⟶ V
⊢ (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).map f =
    eqToHom (_ : (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).obj U = (map (inclusionTopIso X).inv).obj U) ≫
      (map (inclusionTopIso X).inv).map f ≫
        eqToHom (_ : (map (inclusionTopIso X).inv).obj V = (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion ⊤))).obj V)
[PROOFSTEP]
apply Subsingleton.elim
[GOAL]
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
U : Opens ↑Y
⊢ (IsOpenMap.functor hf).obj ((map f).obj U) = (IsOpenMap.functor hf).obj ⊤ ⊓ U
[PROOFSTEP]
ext
[GOAL]
case h.h
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
U : Opens ↑Y
x✝ : ↑Y
⊢ x✝ ∈ ↑((IsOpenMap.functor hf).obj ((map f).obj U)) ↔ x✝ ∈ ↑((IsOpenMap.functor hf).obj ⊤ ⊓ U)
[PROOFSTEP]
constructor
[GOAL]
case h.h.mp
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
U : Opens ↑Y
x✝ : ↑Y
⊢ x✝ ∈ ↑((IsOpenMap.functor hf).obj ((map f).obj U)) → x✝ ∈ ↑((IsOpenMap.functor hf).obj ⊤ ⊓ U)
[PROOFSTEP]
rintro ⟨x, hx, rfl⟩
[GOAL]
case h.h.mp.intro.intro
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
U : Opens ↑Y
x : (forget TopCat).obj X
hx : x ∈ ↑((map f).obj U)
⊢ ↑f x ∈ ↑((IsOpenMap.functor hf).obj ⊤ ⊓ U)
[PROOFSTEP]
exact ⟨⟨x, trivial, rfl⟩, hx⟩
[GOAL]
case h.h.mpr
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
U : Opens ↑Y
x✝ : ↑Y
⊢ x✝ ∈ ↑((IsOpenMap.functor hf).obj ⊤ ⊓ U) → x✝ ∈ ↑((IsOpenMap.functor hf).obj ((map f).obj U))
[PROOFSTEP]
rintro ⟨⟨x, -, rfl⟩, hx⟩
[GOAL]
case h.h.mpr.intro.intro.intro
X Y : TopCat
f : X ⟶ Y
hf : IsOpenMap ↑f
U : Opens ↑Y
x : (forget TopCat).obj X
hx : ↑f x ∈ ↑U
⊢ ↑f x ∈ ↑((IsOpenMap.functor hf).obj ((map f).obj U))
[PROOFSTEP]
exact ⟨x, hx, rfl⟩
[GOAL]
X : TopCat
U : Opens ↑X
⊢ Set.range ((forget TopCat).map (inclusion U)) = ↑U
[PROOFSTEP]
ext x
[GOAL]
case h
X : TopCat
U : Opens ↑X
x : (forget TopCat).obj X
⊢ x ∈ Set.range ((forget TopCat).map (inclusion U)) ↔ x ∈ ↑U
[PROOFSTEP]
constructor
[GOAL]
case h.mp
X : TopCat
U : Opens ↑X
x : (forget TopCat).obj X
⊢ x ∈ Set.range ((forget TopCat).map (inclusion U)) → x ∈ ↑U
[PROOFSTEP]
rintro ⟨x, rfl⟩
[GOAL]
case h.mp.intro
X : TopCat
U : Opens ↑X
x : (forget TopCat).obj ((toTopCat X).obj U)
⊢ (forget TopCat).map (inclusion U) x ∈ ↑U
[PROOFSTEP]
exact x.2
[GOAL]
case h.mpr
X : TopCat
U : Opens ↑X
x : (forget TopCat).obj X
⊢ x ∈ ↑U → x ∈ Set.range ((forget TopCat).map (inclusion U))
[PROOFSTEP]
intro h
[GOAL]
case h.mpr
X : TopCat
U : Opens ↑X
x : (forget TopCat).obj X
h : x ∈ ↑U
⊢ x ∈ Set.range ((forget TopCat).map (inclusion U))
[PROOFSTEP]
exact ⟨⟨x, h⟩, rfl⟩
[GOAL]
X : TopCat
U V : Opens ↑X
⊢ (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj ((map (inclusion U)).obj V) = V ⊓ U
[PROOFSTEP]
ext1
[GOAL]
case h
X : TopCat
U V : Opens ↑X
⊢ ↑((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj ((map (inclusion U)).obj V)) = ↑(V ⊓ U)
[PROOFSTEP]
refine' Set.image_preimage_eq_inter_range.trans _
[GOAL]
case h
X : TopCat
U V : Opens ↑X
⊢ (V.1 ∩ Set.range fun x => ↑(inclusion U) x) = ↑(V ⊓ U)
[PROOFSTEP]
erw [set_range_forget_map_inclusion U]
[GOAL]
case h
X : TopCat
U V : Opens ↑X
⊢ V.1 ∩ ↑U = ↑(V ⊓ U)
[PROOFSTEP]
rfl
[GOAL]
X : TopCat
U : Opens ↑X
V : Opens { x // x ∈ U }
⊢ (map (inclusion U) ⋙ IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj
      ((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj V) =
    (𝟭 (Opens ↑X)).obj ((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj V)
[PROOFSTEP]
dsimp
[GOAL]
X : TopCat
U : Opens ↑X
V : Opens { x // x ∈ U }
⊢ (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj
      ((map (inclusion U)).obj ((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj V)) =
    (IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj V
[PROOFSTEP]
rw [map_functor_eq V]
[GOAL]
X : TopCat
U : Opens ↑X
V : Opens { x // x ∈ U }
⊢ NatTrans.app (IsOpenMap.adjunction (_ : IsOpenMap ↑(inclusion U))).counit
      ((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj V) =
    eqToHom
      (_ :
        (map (inclusion U) ⋙ IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj
            ((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj V) =
          (𝟭 (Opens ↑X)).obj ((IsOpenMap.functor (_ : IsOpenMap ↑(inclusion U))).obj V))
[PROOFSTEP]
apply Subsingleton.elim


[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
⊢ HasKernel f
[PROOFSTEP]
have := NatIso.naturality_1 i f
[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : NatTrans.app i.inv X✝ ≫ (F ⋙ G).map f ≫ NatTrans.app i.hom Y✝ = (𝟭 C).map f
⊢ HasKernel f
[PROOFSTEP]
simp at this
[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝ = f
⊢ HasKernel f
[PROOFSTEP]
rw [← this]
[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝ = f
⊢ HasKernel (NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝)
[PROOFSTEP]
haveI : HasKernel (G.map (F.map f) ≫ i.hom.app _) := Limits.hasKernel_comp_mono _ _
[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : PreservesFiniteLimits G
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝ = f
this : HasKernel (G.map (F.map f) ≫ NatTrans.app i.hom Y✝)
⊢ HasKernel (NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝)
[PROOFSTEP]
apply Limits.hasKernel_iso_comp
[GOAL]
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
⊢ HasCokernel f
[PROOFSTEP]
have : PreservesColimits G := adj.leftAdjointPreservesColimits
[GOAL]
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this : PreservesColimits G
⊢ HasCokernel f
[PROOFSTEP]
have := NatIso.naturality_1 i f
[GOAL]
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : PreservesColimits G
this : NatTrans.app i.inv X✝ ≫ (F ⋙ G).map f ≫ NatTrans.app i.hom Y✝ = (𝟭 C).map f
⊢ HasCokernel f
[PROOFSTEP]
simp at this
[GOAL]
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : PreservesColimits G
this : NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝ = f
⊢ HasCokernel f
[PROOFSTEP]
rw [← this]
[GOAL]
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝ : PreservesColimits G
this : NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝ = f
⊢ HasCokernel (NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝)
[PROOFSTEP]
haveI : HasCokernel (G.map (F.map f) ≫ i.hom.app _) := Limits.hasCokernel_comp_iso _ _
[GOAL]
C : Type u₁
inst✝⁴ : Category.{v, u₁} C
inst✝³ : Preadditive C
D : Type u₂
inst✝² : Category.{v, u₂} D
inst✝¹ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
X✝ Y✝ : C
f : X✝ ⟶ Y✝
this✝¹ : PreservesColimits G
this✝ : NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝ = f
this : HasCokernel (G.map (F.map f) ≫ NatTrans.app i.hom Y✝)
⊢ HasCokernel (NatTrans.app i.inv X✝ ≫ G.map (F.map f) ≫ NatTrans.app i.hom Y✝)
[PROOFSTEP]
apply Limits.hasCokernel_epi_comp
[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
⊢ G.obj (cokernel (F.map f)) ≅ cokernel f
[PROOFSTEP]
have : PreservesColimits G := adj.leftAdjointPreservesColimits
[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
this : PreservesColimits G
⊢ G.obj (cokernel (F.map f)) ≅ cokernel f
[PROOFSTEP]
have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
[GOAL]
C : Type u₁
inst✝⁵ : Category.{v, u₁} C
inst✝⁴ : Preadditive C
D : Type u₂
inst✝³ : Category.{v, u₂} D
inst✝² : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝ : HasCokernels C
X Y : C
f : X ⟶ Y
this✝ : PreservesColimits G
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ G.obj (cokernel (F.map f)) ≅ cokernel f
[PROOFSTEP]
calc
  G.obj (cokernel (F.map f)) ≅ cokernel (G.map (F.map f)) := (asIso (cokernelComparison _ G)).symm
  _ ≅ cokernel (i.hom.app X ≫ f ≫ i.inv.app Y) := (cokernelIsoOfEq (NatIso.naturality_2 i f).symm)
  _ ≅ cokernel (f ≫ i.inv.app Y) := (cokernelEpiComp (i.hom.app X) (f ≫ i.inv.app Y))
  _ ≅ cokernel f := cokernelCompIsIso f (i.inv.app Y)
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
⊢ kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f)
[PROOFSTEP]
have : PreservesColimits G := adj.leftAdjointPreservesColimits
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
this : PreservesColimits G
⊢ kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f)
[PROOFSTEP]
have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
this✝ : PreservesColimits G
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f)
[PROOFSTEP]
calc
  kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π (G.map (F.map f)) ≫ cokernelComparison (F.map f) G) :=
    kernelIsoOfEq (π_comp_cokernelComparison _ _).symm
  _ ≅ kernel (cokernel.π (G.map (F.map f))) := (kernelCompMono _ _)
  _ ≅ kernel (cokernel.π (_ ≫ f ≫ _) ≫ (cokernelIsoOfEq _).hom) :=
    (kernelIsoOfEq (π_comp_cokernelIsoOfEq_hom (NatIso.naturality_2 i f)).symm)
  _ ≅ kernel (cokernel.π (_ ≫ f ≫ _)) := (kernelCompMono _ _)
  _ ≅ kernel (cokernel.π (f ≫ i.inv.app Y) ≫ (cokernelEpiComp (i.hom.app X) _).inv) :=
    (kernelIsoOfEq (by simp only [cokernel.π_desc, cokernelEpiComp_inv]))
  _ ≅ kernel (cokernel.π (f ≫ _)) := (kernelCompMono _ _)
  _ ≅ kernel (inv (i.inv.app Y) ≫ cokernel.π f ≫ (cokernelCompIsIso f (i.inv.app Y)).inv) :=
    (kernelIsoOfEq
      (by simp only [cokernel.π_desc, cokernelCompIsIso_inv, Iso.hom_inv_id_app_assoc, NatIso.inv_inv_app]))
  _ ≅ kernel (cokernel.π f ≫ _) := (kernelIsIsoComp _ _)
  _ ≅ kernel (cokernel.π f) := kernelCompMono _ _
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
this✝ : PreservesColimits G
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) =
    cokernel.π (f ≫ NatTrans.app i.inv Y) ≫ (cokernelEpiComp (NatTrans.app i.hom X) (f ≫ NatTrans.app i.inv Y)).inv
[PROOFSTEP]
simp only [cokernel.π_desc, cokernelEpiComp_inv]
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
D : Type u₂
inst✝⁵ : Category.{v, u₂} D
inst✝⁴ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝³ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝² : HasCokernels C
inst✝¹ : HasKernels C
inst✝ : PreservesFiniteLimits G
X Y : C
f : X ⟶ Y
this✝ : PreservesColimits G
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ cokernel.π (f ≫ NatTrans.app i.inv Y) =
    inv (NatTrans.app i.inv Y) ≫ cokernel.π f ≫ (cokernelCompIsIso f (NatTrans.app i.inv Y)).inv
[PROOFSTEP]
simp only [cokernel.π_desc, cokernelCompIsIso_inv, Iso.hom_inv_id_app_assoc, NatIso.inv_inv_app]
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
⊢ Abelian.coimage f ≅ Abelian.image f
[PROOFSTEP]
have : PreservesLimits F := adj.rightAdjointPreservesLimits
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this : PreservesLimits F
⊢ Abelian.coimage f ≅ Abelian.image f
[PROOFSTEP]
haveI : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this✝ : PreservesLimits F
this : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f'
⊢ Abelian.coimage f ≅ Abelian.image f
[PROOFSTEP]
calc
  Abelian.coimage f ≅ cokernel (kernel.ι f) := Iso.refl _
  _ ≅ G.obj (cokernel (F.map (kernel.ι f))) := (cokernelIso _ _ i adj _).symm
  _ ≅ G.obj (cokernel (kernelComparison f F ≫ kernel.ι (F.map f))) := (G.mapIso (cokernelIsoOfEq (by simp)))
  _ ≅ G.obj (cokernel (kernel.ι (F.map f))) := (G.mapIso (cokernelEpiComp _ _))
  _ ≅ G.obj (Abelian.coimage (F.map f)) := (Iso.refl _)
  _ ≅ G.obj (Abelian.image (F.map f)) := (G.mapIso (Abelian.coimageIsoImage _))
  _ ≅ G.obj (kernel (cokernel.π (F.map f))) := (Iso.refl _)
  _ ≅ kernel (G.map (cokernel.π (F.map f))) := (PreservesKernel.iso _ _)
  _ ≅ kernel (cokernel.π f) := (coimageIsoImageAux F G i adj f)
  _ ≅ Abelian.image f := Iso.refl _
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this✝ : PreservesLimits F
this : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f'
⊢ F.map (kernel.ι f) = kernelComparison f F ≫ kernel.ι (F.map f)
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
⊢ (coimageIsoImage F G i adj f).hom = Abelian.coimageImageComparison f
[PROOFSTEP]
have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
⊢ (coimageIsoImage F G i adj f).hom = Abelian.coimageImageComparison f
[PROOFSTEP]
have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasKernel f' := inferInstance
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this✝ : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
this : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasKernel f'
⊢ (coimageIsoImage F G i adj f).hom = Abelian.coimageImageComparison f
[PROOFSTEP]
have : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this✝¹ : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
this✝ : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasKernel f'
this : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f'
⊢ (coimageIsoImage F G i adj f).hom = Abelian.coimageImageComparison f
[PROOFSTEP]
have : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasKernel f' := inferInstance
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this✝² : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
this✝¹ : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasKernel f'
this✝ : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f'
this : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasKernel f'
⊢ (coimageIsoImage F G i adj f).hom = Abelian.coimageImageComparison f
[PROOFSTEP]
dsimp only [coimageIsoImage, Iso.instTransIso_trans, Iso.refl, Iso.trans, Iso.symm, Functor.mapIso, cokernelEpiComp,
  cokernelIso, cokernelCompIsIso_inv, asIso, coimageIsoImageAux, kernelCompMono]
[GOAL]
C : Type u₁
inst✝⁸ : Category.{v, u₁} C
inst✝⁷ : Preadditive C
D : Type u₂
inst✝⁶ : Category.{v, u₂} D
inst✝⁵ : Abelian D
F : C ⥤ D
G : D ⥤ C
inst✝⁴ : Functor.PreservesZeroMorphisms G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
inst✝³ : HasCokernels C
inst✝² : HasKernels C
inst✝¹ : PreservesFiniteLimits G
inst✝ : Functor.PreservesZeroMorphisms F
X Y : C
f : X ⟶ Y
this✝² : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f'
this✝¹ : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasKernel f'
this✝ : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f'
this : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasKernel f'
⊢ ((((((((𝟙 (Abelian.coimage f) ≫
                      cokernel.desc (kernel.ι f) (NatTrans.app i.inv X ≫ cokernel.π (kernel.ι f ≫ NatTrans.app i.inv X))
                          (_ : kernel.ι f ≫ NatTrans.app i.inv X ≫ cokernel.π (kernel.ι f ≫ NatTrans.app i.inv X) = 0) ≫
                        cokernel.desc (kernel.ι f ≫ NatTrans.app i.inv X)
                            (cokernel.π (NatTrans.app i.hom (kernel f) ≫ kernel.ι f ≫ NatTrans.app i.inv X))
                            (_ :
                              (kernel.ι f ≫ NatTrans.app i.inv X) ≫
                                  cokernel.π (NatTrans.app i.hom (kernel f) ≫ kernel.ι f ≫ NatTrans.app i.inv X) =
                                0) ≫
                          (cokernelIsoOfEq
                                (_ :
                                  (F ⋙ G).map (kernel.ι f) =
                                    NatTrans.app i.hom (kernel f) ≫
                                      (𝟭 C).map (kernel.ι f) ≫ NatTrans.app i.inv X)).inv ≫
                            cokernelComparison (F.map (kernel.ι f)) G) ≫
                    G.map (cokernelIsoOfEq (_ : F.map (kernel.ι f) = kernelComparison f F ≫ kernel.ι (F.map f))).hom) ≫
                  G.map
                    (cokernel.desc (kernelComparison f F ≫ kernel.ι (F.map f)) (cokernel.π (kernel.ι (F.map f)))
                      (_ : (kernelComparison f F ≫ kernel.ι (F.map f)) ≫ cokernel.π (kernel.ι (F.map f)) = 0))) ≫
                𝟙 (G.obj (cokernel (kernel.ι (F.map f))))) ≫
              G.map (Abelian.coimageIsoImage (F.map f)).hom) ≫
            𝟙 (G.obj (Abelian.image (F.map f)))) ≫
          (PreservesKernel.iso G (cokernel.π (F.map f))).hom) ≫
        ((((((((kernelIsoOfEq
                            (_ :
                              G.map (cokernel.π (F.map f)) =
                                cokernel.π (G.map (F.map f)) ≫ cokernelComparison (F.map f) G)).hom ≫
                        kernel.lift (cokernel.π (G.map (F.map f)))
                          (kernel.ι (cokernel.π (G.map (F.map f)) ≫ cokernelComparison (F.map f) G))
                          (_ :
                            kernel.ι (cokernel.π (G.map (F.map f)) ≫ cokernelComparison (F.map f) G) ≫
                                cokernel.π (G.map (F.map f)) =
                              0)) ≫
                      (kernelIsoOfEq
                          (_ :
                            cokernel.π ((F ⋙ G).map f) =
                              cokernel.π (NatTrans.app i.hom X ≫ (𝟭 C).map f ≫ NatTrans.app i.inv Y) ≫
                                (cokernelIsoOfEq
                                    (_ :
                                      NatTrans.app i.hom X ≫ (𝟭 C).map f ≫ NatTrans.app i.inv Y =
                                        (F ⋙ G).map f)).hom)).hom) ≫
                    kernel.lift (cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y))
                      (kernel.ι
                        (cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) ≫
                          (cokernelIsoOfEq
                              (_ : NatTrans.app i.hom X ≫ (𝟭 C).map f ≫ NatTrans.app i.inv Y = (F ⋙ G).map f)).hom))
                      (_ :
                        kernel.ι
                              (cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) ≫
                                (cokernelIsoOfEq
                                    (_ :
                                      NatTrans.app i.hom X ≫ (𝟭 C).map f ≫ NatTrans.app i.inv Y = (F ⋙ G).map f)).hom) ≫
                            cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) =
                          0)) ≫
                  (kernelIsoOfEq
                      (_ :
                        cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) =
                          cokernel.π (f ≫ NatTrans.app i.inv Y) ≫
                            cokernel.desc (f ≫ NatTrans.app i.inv Y)
                              (cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y))
                              (_ :
                                (f ≫ NatTrans.app i.inv Y) ≫
                                    cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) =
                                  0))).hom) ≫
                kernel.lift (cokernel.π (f ≫ NatTrans.app i.inv Y))
                  (kernel.ι
                    (cokernel.π (f ≫ NatTrans.app i.inv Y) ≫
                      cokernel.desc (f ≫ NatTrans.app i.inv Y)
                        (cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y))
                        (_ :
                          (f ≫ NatTrans.app i.inv Y) ≫ cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) =
                            0)))
                  (_ :
                    kernel.ι
                          (cokernel.π (f ≫ NatTrans.app i.inv Y) ≫
                            cokernel.desc (f ≫ NatTrans.app i.inv Y)
                              (cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y))
                              (_ :
                                (f ≫ NatTrans.app i.inv Y) ≫
                                    cokernel.π (NatTrans.app i.hom X ≫ f ≫ NatTrans.app i.inv Y) =
                                  0)) ≫
                        cokernel.π (f ≫ NatTrans.app i.inv Y) =
                      0)) ≫
              (kernelIsoOfEq
                  (_ :
                    cokernel.π (f ≫ NatTrans.app i.inv Y) =
                      inv (NatTrans.app i.inv Y) ≫
                        cokernel.π f ≫
                          cokernel.desc f (NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y))
                            (_ : f ≫ NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y) = 0))).hom) ≫
            (kernelIsIsoComp (inv (NatTrans.app i.inv Y))
                (cokernel.π f ≫
                  cokernel.desc f (NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y))
                    (_ : f ≫ NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y) = 0))).hom) ≫
          kernel.lift (cokernel.π f)
            (kernel.ι
              (cokernel.π f ≫
                cokernel.desc f (NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y))
                  (_ : f ≫ NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y) = 0)))
            (_ :
              kernel.ι
                    (cokernel.π f ≫
                      cokernel.desc f (NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y))
                        (_ : f ≫ NatTrans.app i.inv Y ≫ cokernel.π (f ≫ NatTrans.app i.inv Y) = 0)) ≫
                  cokernel.π f =
                0)) ≫
      𝟙 (kernel (cokernel.π f)) =
    Abelian.coimageImageComparison f
[PROOFSTEP]
simpa only [← cancel_mono (Abelian.image.ι f), ← cancel_epi (Abelian.coimage.π f), Category.assoc, Category.id_comp,
  cokernel.π_desc_assoc, π_comp_cokernelIsoOfEq_inv_assoc, PreservesKernel.iso_hom, π_comp_cokernelComparison_assoc, ←
  G.map_comp_assoc, kernel.lift_ι, Abelian.coimage_image_factorisation, lift_comp_kernelIsoOfEq_hom_assoc,
  kernelIsIsoComp_hom, kernel.lift_ι_assoc, kernelIsoOfEq_hom_comp_ι_assoc, kernelComparison_comp_ι_assoc,
  π_comp_cokernelIsoOfEq_hom_assoc, asIso_hom, NatIso.inv_inv_app] using NatIso.naturality_1 i f
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
inst✝⁵ : HasFiniteProducts C
D : Type u₂
inst✝⁴ : Category.{v, u₂} D
inst✝³ : Abelian D
F : C ⥤ D
inst✝² : Functor.PreservesZeroMorphisms F
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
inst✝ : PreservesFiniteLimits G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
⊢ Abelian C
[PROOFSTEP]
haveI := hasKernels F G i
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
inst✝⁵ : HasFiniteProducts C
D : Type u₂
inst✝⁴ : Category.{v, u₂} D
inst✝³ : Abelian D
F : C ⥤ D
inst✝² : Functor.PreservesZeroMorphisms F
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
inst✝ : PreservesFiniteLimits G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
this : HasKernels C
⊢ Abelian C
[PROOFSTEP]
haveI := hasCokernels F G i adj
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
inst✝⁵ : HasFiniteProducts C
D : Type u₂
inst✝⁴ : Category.{v, u₂} D
inst✝³ : Abelian D
F : C ⥤ D
inst✝² : Functor.PreservesZeroMorphisms F
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
inst✝ : PreservesFiniteLimits G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
this✝ : HasKernels C
this : HasCokernels C
⊢ Abelian C
[PROOFSTEP]
have : ∀ {X Y : C} (f : X ⟶ Y), IsIso (Abelian.coimageImageComparison f) :=
  by
  intro X Y f
  rw [← coimageIsoImage_hom F G i adj f]
  infer_instance
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
inst✝⁵ : HasFiniteProducts C
D : Type u₂
inst✝⁴ : Category.{v, u₂} D
inst✝³ : Abelian D
F : C ⥤ D
inst✝² : Functor.PreservesZeroMorphisms F
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
inst✝ : PreservesFiniteLimits G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
this✝ : HasKernels C
this : HasCokernels C
⊢ ∀ {X Y : C} (f : X ⟶ Y), IsIso (Abelian.coimageImageComparison f)
[PROOFSTEP]
intro X Y f
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
inst✝⁵ : HasFiniteProducts C
D : Type u₂
inst✝⁴ : Category.{v, u₂} D
inst✝³ : Abelian D
F : C ⥤ D
inst✝² : Functor.PreservesZeroMorphisms F
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
inst✝ : PreservesFiniteLimits G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
this✝ : HasKernels C
this : HasCokernels C
X Y : C
f : X ⟶ Y
⊢ IsIso (Abelian.coimageImageComparison f)
[PROOFSTEP]
rw [← coimageIsoImage_hom F G i adj f]
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
inst✝⁵ : HasFiniteProducts C
D : Type u₂
inst✝⁴ : Category.{v, u₂} D
inst✝³ : Abelian D
F : C ⥤ D
inst✝² : Functor.PreservesZeroMorphisms F
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
inst✝ : PreservesFiniteLimits G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
this✝ : HasKernels C
this : HasCokernels C
X Y : C
f : X ⟶ Y
⊢ IsIso (coimageIsoImage F G i adj f).hom
[PROOFSTEP]
infer_instance
[GOAL]
C : Type u₁
inst✝⁷ : Category.{v, u₁} C
inst✝⁶ : Preadditive C
inst✝⁵ : HasFiniteProducts C
D : Type u₂
inst✝⁴ : Category.{v, u₂} D
inst✝³ : Abelian D
F : C ⥤ D
inst✝² : Functor.PreservesZeroMorphisms F
G : D ⥤ C
inst✝¹ : Functor.PreservesZeroMorphisms G
inst✝ : PreservesFiniteLimits G
i : F ⋙ G ≅ 𝟭 C
adj : G ⊣ F
this✝¹ : HasKernels C
this✝ : HasCokernels C
this : ∀ {X Y : C} (f : X ⟶ Y), IsIso (Abelian.coimageImageComparison f)
⊢ Abelian C
[PROOFSTEP]
apply Abelian.ofCoimageImageComparisonIsIso


[GOAL]
α : Type u_1
β : Type u_2
inst✝ : Encodable α
x y : α
e : encode x = encode y
⊢ some x = some y
[PROOFSTEP]
rw [← encodek, e, encodek]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝¹ : Encodable α
inst✝ : Inhabited α
x : α
⊢ (fun n => iget (decode n)) (encode x) = x
[PROOFSTEP]
simp_rw [Encodable.encodek]
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : Encodable α
f : β → α
finv : α → Option β
linv : ∀ (b : β), finv (f b) = some b
b : β
⊢ (fun n => Option.bind (decode n) finv) ((fun b => encode (f b)) b) = some b
[PROOFSTEP]
simp [Encodable.encodek, linv]
[GOAL]
α✝ : Type u_1
β✝ : Type u_2
α : Type u_3
β : Type u_4
inst✝ : Encodable α
e : β ≃ α
n : ℕ
⊢ Option.bind (decode n) (some ∘ ↑e.symm) = Option.map (↑e.symm) (decode n)
[PROOFSTEP]
rw [Option.map_eq_bind]
[GOAL]
α : Type u_1
β : Type u_2
x✝ : PUnit
⊢ (fun n => Nat.casesOn n (some PUnit.unit) fun x => none) ((fun x => 0) x✝) = some x✝
[PROOFSTEP]
simp
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
h : Encodable α
o : Option α
⊢ (fun n => Nat.casesOn n (some none) fun m => Option.map some (decode m))
      ((fun o => Option.casesOn o zero fun a => succ (encode a)) o) =
    some o
[PROOFSTEP]
cases o
[GOAL]
case none
α✝ : Type u_1
β : Type u_2
α : Type u_3
h : Encodable α
⊢ (fun n => Nat.casesOn n (some none) fun m => Option.map some (decode m))
      ((fun o => Option.casesOn o zero fun a => succ (encode a)) none) =
    some none
[PROOFSTEP]
dsimp
[GOAL]
case some
α✝ : Type u_1
β : Type u_2
α : Type u_3
h : Encodable α
val✝ : α
⊢ (fun n => Nat.casesOn n (some none) fun m => Option.map some (decode m))
      ((fun o => Option.casesOn o zero fun a => succ (encode a)) (some val✝)) =
    some (some val✝)
[PROOFSTEP]
dsimp
[GOAL]
case some
α✝ : Type u_1
β : Type u_2
α : Type u_3
h : Encodable α
val✝ : α
⊢ Option.map some (decode (encode val✝)) = some (some val✝)
[PROOFSTEP]
simp [encodek, Nat.succ_ne_zero]
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : Encodable α
n : ℕ
a : α
⊢ a ∈ decode₂ α n ↔ a ∈ decode n ∧ encode a = n
[PROOFSTEP]
simp [decode₂]
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : Encodable α
n : ℕ
a : α
⊢ (∃ a_1, decode n = some a_1 ∧ a_1 = a ∧ encode a_1 = n) ↔ decode n = some a ∧ encode a = n
[PROOFSTEP]
exact ⟨fun ⟨_, h₁, rfl, h₂⟩ => ⟨h₁, h₂⟩, fun ⟨h₁, h₂⟩ => ⟨_, h₁, rfl, h₂⟩⟩
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : Encodable α
a : α
⊢ decode₂ α (encode a) = some a
[PROOFSTEP]
ext
[GOAL]
case a
α : Type u_1
β : Type u_2
inst✝ : Encodable α
a a✝ : α
⊢ a✝ ∈ decode₂ α (encode a) ↔ a✝ ∈ some a
[PROOFSTEP]
simp [mem_decode₂, eq_comm, decode₂_eq_some]
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : Encodable α
n : ℕ
⊢ decode₂ α n ≠ none ↔ n ∈ Set.range encode
[PROOFSTEP]
simp_rw [Set.range, Set.mem_setOf_eq, Ne.def, Option.eq_none_iff_forall_not_mem, Encodable.mem_decode₂, not_forall,
  not_not]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x : ℕ
h : isSome (decode₂ α x) = true
⊢ encode (Option.get (decode₂ α x) h) = x
[PROOFSTEP]
rw [← decode₂_is_partial_inv (Option.get _ h), Option.some_get]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x : ℕ
x✝ : (fun x => x ∈ Set.range encode) x
n : α
hn : encode n = x
⊢ isSome (decode₂ α x) = true
[PROOFSTEP]
rw [← hn, encodek₂]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x : ℕ
x✝ : (fun x => x ∈ Set.range encode) x
n : α
hn : encode n = x
⊢ isSome (some n) = true
[PROOFSTEP]
exact rfl
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
n : ↑(Set.range encode)
⊢ isSome (decode₂ α ↑n) = true
[PROOFSTEP]
cases' n.2 with x hx
[GOAL]
case intro
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
n : ↑(Set.range encode)
x : α
hx : encode x = ↑n
⊢ isSome (decode₂ α ↑n) = true
[PROOFSTEP]
rw [← hx, encodek₂]
[GOAL]
case intro
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
n : ↑(Set.range encode)
x : α
hx : encode x = ↑n
⊢ isSome (some x) = true
[PROOFSTEP]
exact rfl
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
a : α
⊢ (fun n => Option.get (decode₂ α ↑n) (_ : isSome (decode₂ α ↑n) = true))
      ((fun a => { val := encode a, property := (_ : encode a ∈ Set.range encode) }) a) =
    a
[PROOFSTEP]
dsimp
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
a : α
⊢ Option.get (decode₂ α (encode a)) (_ : isSome (decode₂ α (encode a)) = true) = a
[PROOFSTEP]
rw [← Option.some_inj, Option.some_get, encodek₂]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
⊢ (fun a => { val := encode a, property := (_ : encode a ∈ Set.range encode) })
      ((fun n => Option.get (decode₂ α ↑n) (_ : isSome (decode₂ α ↑n) = true))
        { val := n, property := (_ : ∃ y, encode y = n) }) =
    { val := n, property := (_ : ∃ y, encode y = n) }
[PROOFSTEP]
apply Subtype.eq
[GOAL]
case a
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
⊢ ↑((fun a => { val := encode a, property := (_ : encode a ∈ Set.range encode) })
        ((fun n => Option.get (decode₂ α ↑n) (_ : isSome (decode₂ α ↑n) = true))
          { val := n, property := (_ : ∃ y, encode y = n) })) =
    ↑{ val := n, property := (_ : ∃ y, encode y = n) }
[PROOFSTEP]
dsimp
[GOAL]
case a
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
⊢ encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = n
[PROOFSTEP]
conv =>
  rhs
  rw [← hx]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
| encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = n
[PROOFSTEP]
  rhs
  rw [← hx]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
| encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = n
[PROOFSTEP]
  rhs
  rw [← hx]
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
| encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = n
[PROOFSTEP]
rhs
[GOAL]
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
| n
[PROOFSTEP]
rw [← hx]
[GOAL]
case a
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
⊢ encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = encode x
[PROOFSTEP]
rw [encode_injective.eq_iff, ← Option.some_inj, Option.some_get, ← hx, encodek₂]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
s : α ⊕ β
⊢ decodeSum (encodeSum s) = some s
[PROOFSTEP]
cases s
[GOAL]
case inl
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
val✝ : α
⊢ decodeSum (encodeSum (Sum.inl val✝)) = some (Sum.inl val✝)
[PROOFSTEP]
simp [encodeSum, div2_val, decodeSum, encodek]
[GOAL]
case inr
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
val✝ : β
⊢ decodeSum (encodeSum (Sum.inr val✝)) = some (Sum.inr val✝)
[PROOFSTEP]
simp [encodeSum, div2_val, decodeSum, encodek]
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ decode n = none
[PROOFSTEP]
suffices decodeSum n = none by
  change (decodeSum n).bind _ = none
  rw [this]
  rfl
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : decodeSum n = none
⊢ decode n = none
[PROOFSTEP]
change (decodeSum n).bind _ = none
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : decodeSum n = none
⊢ Option.bind (decodeSum n) (some ∘ ↑Equiv.boolEquivPUnitSumPUnit.symm) = none
[PROOFSTEP]
rw [this]
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : decodeSum n = none
⊢ Option.bind none (some ∘ ↑Equiv.boolEquivPUnitSumPUnit.symm) = none
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ decodeSum n = none
[PROOFSTEP]
have : 1 ≤ n / 2 := by
  rw [Nat.le_div_iff_mul_le]
  exacts [h, by decide]
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ 1 ≤ n / 2
[PROOFSTEP]
rw [Nat.le_div_iff_mul_le]
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ 1 * 2 ≤ n
α : Type u_1 β : Type u_2 n : ℕ h : 2 ≤ n ⊢ 0 < 2
[PROOFSTEP]
exacts [h, by decide]
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ 0 < 2
[PROOFSTEP]
decide
[GOAL]
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
⊢ decodeSum n = none
[PROOFSTEP]
cases' exists_eq_succ_of_ne_zero (_root_.ne_of_gt this) with m e
[GOAL]
case intro
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ decodeSum n = none
[PROOFSTEP]
simp [decodeSum, div2_val]
[GOAL]
case intro
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ (match (bodd n, n / 2) with
    | (false, m) => Option.map Sum.inl (decode m)
    | (fst, m) => Option.map Sum.inr (decode m)) =
    none
[PROOFSTEP]
cases bodd n
[GOAL]
case intro.false
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ (match (false, n / 2) with
    | (false, m) => Option.map Sum.inl (decode m)
    | (fst, m) => Option.map Sum.inr (decode m)) =
    none
[PROOFSTEP]
simp [e]
[GOAL]
case intro.true
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ (match (true, n / 2) with
    | (false, m) => Option.map Sum.inl (decode m)
    | (fst, m) => Option.map Sum.inr (decode m)) =
    none
[PROOFSTEP]
simp [e]
[GOAL]
α : Type u_1
β : Type u_2
γ : α → Type u_3
inst✝¹ : Encodable α
inst✝ : (a : α) → Encodable (γ a)
x✝ : Sigma γ
a : α
b : γ a
⊢ decodeSigma (encodeSigma { fst := a, snd := b }) = some { fst := a, snd := b }
[PROOFSTEP]
simp [encodeSigma, decodeSigma, unpair_pair, encodek]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ decode n = Option.bind (decode (unpair n).fst) fun a => Option.map (Prod.mk a) (decode (unpair n).snd)
[PROOFSTEP]
simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ Option.map (↑(Equiv.sigmaEquivProd α β))
      (Option.bind (decode (unpair n).fst) fun a => Option.map (Sigma.mk a) (decode (unpair n).snd)) =
    Option.bind (decode (unpair n).fst) fun a => Option.map (Prod.mk a) (decode (unpair n).snd)
[PROOFSTEP]
cases (decode n.unpair.1 : Option α)
[GOAL]
case none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ Option.map (↑(Equiv.sigmaEquivProd α β)) (Option.bind none fun a => Option.map (Sigma.mk a) (decode (unpair n).snd)) =
    Option.bind none fun a => Option.map (Prod.mk a) (decode (unpair n).snd)
[PROOFSTEP]
cases (decode n.unpair.2 : Option β)
[GOAL]
case some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝ : α
⊢ Option.map (↑(Equiv.sigmaEquivProd α β))
      (Option.bind (some val✝) fun a => Option.map (Sigma.mk a) (decode (unpair n).snd)) =
    Option.bind (some val✝) fun a => Option.map (Prod.mk a) (decode (unpair n).snd)
[PROOFSTEP]
cases (decode n.unpair.2 : Option β)
[GOAL]
case none.none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ Option.map (↑(Equiv.sigmaEquivProd α β)) (Option.bind none fun a => Option.map (Sigma.mk a) none) =
    Option.bind none fun a => Option.map (Prod.mk a) none
[PROOFSTEP]
rfl
[GOAL]
case none.some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝ : β
⊢ Option.map (↑(Equiv.sigmaEquivProd α β)) (Option.bind none fun a => Option.map (Sigma.mk a) (some val✝)) =
    Option.bind none fun a => Option.map (Prod.mk a) (some val✝)
[PROOFSTEP]
rfl
[GOAL]
case some.none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝ : α
⊢ Option.map (↑(Equiv.sigmaEquivProd α β)) (Option.bind (some val✝) fun a => Option.map (Sigma.mk a) none) =
    Option.bind (some val✝) fun a => Option.map (Prod.mk a) none
[PROOFSTEP]
rfl
[GOAL]
case some.some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝¹ : α
val✝ : β
⊢ Option.map (↑(Equiv.sigmaEquivProd α β)) (Option.bind (some val✝¹) fun a => Option.map (Sigma.mk a) (some val✝)) =
    Option.bind (some val✝¹) fun a => Option.map (Prod.mk a) (some val✝)
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
β : Type u_2
P : α → Prop
encA : Encodable α
decP : DecidablePred P
x✝ : { a // P a }
v : α
h : P v
⊢ decodeSubtype (encodeSubtype { val := v, property := h }) = some { val := v, property := h }
[PROOFSTEP]
simp [encodeSubtype, decodeSubtype, encodek, h]
[GOAL]
α : Type u_1
β : Type u_2
P : α → Prop
encA : Encodable α
decP : DecidablePred P
a : Subtype P
⊢ encode a = encode ↑a
[PROOFSTEP]
cases a
[GOAL]
case mk
α : Type u_1
β : Type u_2
P : α → Prop
encA : Encodable α
decP : DecidablePred P
val✝ : α
property✝ : P val✝
⊢ encode { val := val✝, property := property✝ } = encode ↑{ val := val✝, property := property✝ }
[PROOFSTEP]
rfl
[GOAL]
⊢ Countable ℕ+
[PROOFSTEP]
delta PNat
[GOAL]
⊢ Countable { n // 0 < n }
[PROOFSTEP]
infer_instance
  -- short-circuit instance search
[GOAL]
α : Type u_1
inst✝ : Encodable α
⊢ DecidableEq (ULower α)
[PROOFSTEP]
delta ULower
[GOAL]
α : Type u_1
inst✝ : Encodable α
⊢ DecidableEq ↑(Set.range Encodable.encode)
[PROOFSTEP]
exact Encodable.decidableEqOfEncodable _
[GOAL]
α : Type u_1
inst✝ : Encodable α
⊢ Encodable (ULower α)
[PROOFSTEP]
delta ULower
[GOAL]
α : Type u_1
inst✝ : Encodable α
⊢ Encodable ↑(Set.range Encodable.encode)
[PROOFSTEP]
infer_instance
[GOAL]
α : Type u_1
inst✝ : Encodable α
a : α
⊢ up (down a) = a
[PROOFSTEP]
simp [up, down, Equiv.left_inv _ _, Equiv.symm_apply_apply]
[GOAL]
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
n : Option α
⊢ Decidable (Encodable.good p n)
[PROOFSTEP]
cases n
[GOAL]
case none
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
⊢ Decidable (Encodable.good p none)
[PROOFSTEP]
unfold good
[GOAL]
case some
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
val✝ : α
⊢ Decidable (Encodable.good p (some val✝))
[PROOFSTEP]
unfold good
[GOAL]
case none
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
⊢ Decidable
    (match none with
    | some a => p a
    | none => False)
[PROOFSTEP]
dsimp
[GOAL]
case some
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
val✝ : α
⊢ Decidable
    (match some val✝ with
    | some a => p a
    | none => False)
[PROOFSTEP]
dsimp
[GOAL]
case none
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
⊢ Decidable False
[PROOFSTEP]
infer_instance
[GOAL]
case some
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
val✝ : α
⊢ Decidable (p val✝)
[PROOFSTEP]
infer_instance
[GOAL]
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
h : ∃ x, p x
w : α
pw : p w
⊢ Encodable.good p (decode (encode w))
[PROOFSTEP]
simp [good, encodek, pw]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
⊢ r (f (Directed.sequence f hf n)) (f (Directed.sequence f hf (n + 1)))
[PROOFSTEP]
dsimp [Directed.sequence]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
⊢ r (f (Directed.sequence f hf n))
    (f
      (match decode n with
      | none =>
        Classical.choose (_ : ∃ z, r (f (Directed.sequence f hf n)) (f z) ∧ r (f (Directed.sequence f hf n)) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f (Directed.sequence f hf n)) (f z) ∧ r (f a) (f z))))
[PROOFSTEP]
generalize hf.sequence f n = p
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
p : α
⊢ r (f p)
    (f
      (match decode n with
      | none => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f p) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f a) (f z))))
[PROOFSTEP]
cases' h : (decode n : Option α) with a
[GOAL]
case none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
p : α
h : decode n = none
⊢ r (f p)
    (f
      (match none with
      | none => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f p) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f a) (f z))))
[PROOFSTEP]
exact (Classical.choose_spec (hf p p)).1
[GOAL]
case some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
p a : α
h : decode n = some a
⊢ r (f p)
    (f
      (match some a with
      | none => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f p) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f a) (f z))))
[PROOFSTEP]
exact (Classical.choose_spec (hf p a)).1
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
a : α
⊢ r (f a) (f (Directed.sequence f hf (encode a + 1)))
[PROOFSTEP]
simp only [Directed.sequence, add_eq, add_zero, encodek, and_self]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
a : α
⊢ r (f a) (f (Classical.choose (_ : ∃ x, (fun x => r (f (Directed.sequence f hf (encode a))) (f x) ∧ r (f a) (f x)) x)))
[PROOFSTEP]
exact (Classical.choose_spec (hf _ a)).2
[GOAL]
α : Type u_1
s : Setoid α
inst✝¹ : DecidableRel fun x x_1 => x ≈ x_1
inst✝ : Encodable α
⊢ ∀ (a : Quotient s), (fun n => Quotient.mk'' <$> decode n) ((fun q => encode (rep q)) a) = some a
[PROOFSTEP]
rintro ⟨l⟩
[GOAL]
case mk
α : Type u_1
s : Setoid α
inst✝¹ : DecidableRel fun x x_1 => x ≈ x_1
inst✝ : Encodable α
a✝ : Quotient s
l : α
⊢ (fun n => Quotient.mk'' <$> decode n) ((fun q => encode (rep q)) (Quot.mk Setoid.r l)) = some (Quot.mk Setoid.r l)
[PROOFSTEP]
dsimp
[GOAL]
case mk
α : Type u_1
s : Setoid α
inst✝¹ : DecidableRel fun x x_1 => x ≈ x_1
inst✝ : Encodable α
a✝ : Quotient s
l : α
⊢ Option.map Quotient.mk'' (decode (encode (rep (Quot.mk Setoid.r l)))) = some (Quot.mk Setoid.r l)
[PROOFSTEP]
rw [encodek]
[GOAL]
case mk
α : Type u_1
s : Setoid α
inst✝¹ : DecidableRel fun x x_1 => x ≈ x_1
inst✝ : Encodable α
a✝ : Quotient s
l : α
⊢ Option.map Quotient.mk'' (some (rep (Quot.mk Setoid.r l))) = some (Quot.mk Setoid.r l)
[PROOFSTEP]
exact congr_arg some ⟦l⟧.rep_spec