This PR sets up the new integrated test/bench suite. It then migrates all benchmarks and some related tests to the new suite. There's also some documentation and some linting. For now, a lot of the old tests are left alone so this PR doesn't become even larger than it already is. Eventually, all tests should be migrated to the new suite though so there isn't a confusing mix of two systems.
653 lines
22 KiB
Text
653 lines
22 KiB
Text
module
|
||
@[expose] public section
|
||
universe v v₁ v₂ v₃ u u₁ u₂ u₃
|
||
|
||
namespace CategoryTheory
|
||
|
||
section Mathlib.CategoryTheory.Category.Basic
|
||
|
||
class Category (obj : Type u) : Type max u (v + 1) where
|
||
Hom : obj → obj → Type v
|
||
/-- The identity morphism on an object. -/
|
||
id : ∀ X : obj, Hom X X
|
||
/-- Composition of morphisms in a category, written `f ≫ g`. -/
|
||
comp : ∀ {X Y Z : obj}, (Hom X Y) → (Hom Y Z) → (Hom X Z)
|
||
/-- Identity morphisms are left identities for composition. -/
|
||
id_comp : ∀ {X Y : obj} (f : Hom X Y), comp (id X) f = f := by grind
|
||
/-- Identity morphisms are right identities for composition. -/
|
||
comp_id : ∀ {X Y : obj} (f : Hom X Y), comp f (id Y) = f := by grind
|
||
/-- Composition in a category is associative. -/
|
||
assoc : ∀ {W X Y Z : obj} (f : Hom W X) (g : Hom X Y) (h : Hom Y Z), comp (comp f g) h = comp f (comp g h) := by grind
|
||
|
||
infixr:10 " ⟶ " => Category.Hom
|
||
scoped notation "𝟙" => Category.id -- type as \b1
|
||
scoped infixr:80 " ≫ " => Category.comp
|
||
|
||
attribute [simp] Category.id_comp Category.comp_id Category.assoc
|
||
|
||
attribute [grind =] Category.id_comp Category.comp_id
|
||
attribute [grind _=_] Category.assoc
|
||
|
||
end Mathlib.CategoryTheory.Category.Basic
|
||
|
||
section Mathlib.CategoryTheory.Functor.Basic
|
||
|
||
structure Functor (C : Type u₁) [Category.{v₁} C] (D : Type u₂) [Category.{v₂} D] : Type max v₁ v₂ u₁ u₂ where
|
||
/-- The action of a functor on objects. -/
|
||
obj : C → D
|
||
/-- The action of a functor on morphisms. -/
|
||
map : ∀ {X Y : C}, (X ⟶ Y) → ((obj X) ⟶ (obj Y))
|
||
/-- A functor preserves identity morphisms. -/
|
||
map_id : ∀ X : C, map (𝟙 X) = 𝟙 (obj X) := by grind
|
||
/-- A functor preserves composition. -/
|
||
map_comp : ∀ {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z), map (f ≫ g) = (map f) ≫ (map g) := by grind
|
||
|
||
scoped infixr:26 " ⥤ " => Functor
|
||
|
||
attribute [simp] Functor.map_id Functor.map_comp
|
||
|
||
attribute [grind =] Functor.map_id
|
||
attribute [grind _=_] Functor.map_comp
|
||
|
||
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] {E : Type u₃} [Category.{v₃} E]
|
||
variable {F G H : Functor C D}
|
||
|
||
namespace Functor
|
||
|
||
def comp (F : Functor C D) (G : Functor D E) : Functor C E where
|
||
obj X := G.obj (F.obj X)
|
||
map f := G.map (F.map f)
|
||
-- Note `map_id` and `map_comp` are handled by `grind`.
|
||
|
||
infixr:80 " ⋙ " => Functor.comp
|
||
|
||
variable {X Y : C} {G : Functor D E}
|
||
|
||
@[simp, grind =] theorem comp_obj : (F.comp G).obj X = G.obj (F.obj X) := rfl
|
||
@[simp, grind =] theorem comp_map (f : X ⟶ Y) : (F.comp G).map f = G.map (F.map f) := rfl
|
||
|
||
end Functor
|
||
|
||
end Mathlib.CategoryTheory.Functor.Basic
|
||
|
||
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] {E : Type u₃} [Category.{v₃} E] {E' : Type u₄} [Category.{v₄} E']
|
||
variable {F G H : Functor C D}
|
||
|
||
section Mathlib.CategoryTheory.NatTrans
|
||
|
||
@[ext]
|
||
structure NatTrans [Category.{v₁, u₁} C] [Category.{v₂, u₂} D] (F G : Functor C D) : Type max u₁ v₂ where
|
||
/-- The component of a natural transformation. -/
|
||
app : ∀ X : C, F.obj X ⟶ G.obj X
|
||
/-- The naturality square for a given morphism. -/
|
||
naturality : ∀ ⦃X Y : C⦄ (f : X ⟶ Y), F.map f ≫ app Y = app X ≫ G.map f := by grind
|
||
|
||
-- In the following examples `[grind ext] NatTrans.ext` is more effective than
|
||
-- `[grind ext] NatTrans` which only applies eta-extension because it will allows
|
||
-- chaining with function extensionality
|
||
attribute [grind ext] NatTrans.ext
|
||
|
||
attribute [simp, grind _=_] NatTrans.naturality
|
||
|
||
namespace NatTrans
|
||
|
||
variable {X : C}
|
||
|
||
protected def id (F : Functor C D) : NatTrans F F where app X := 𝟙 (F.obj X)
|
||
|
||
@[simp, grind =] theorem id_app' : (NatTrans.id F).app X = 𝟙 (F.obj X) := rfl
|
||
|
||
protected def vcomp (α : NatTrans F G) (β : NatTrans G H) : NatTrans F H where
|
||
app X := α.app X ≫ β.app X
|
||
-- `naturality` is now handled by `grind`; in Mathlib this relies on `@[reassoc]` attributes.
|
||
-- Manual proof:
|
||
-- rw [← Category.assoc]
|
||
-- rw [α.naturality f]
|
||
-- rw [Category.assoc]
|
||
-- rw [β.naturality f]
|
||
-- rw [← Category.assoc]
|
||
|
||
@[simp, grind =] theorem vcomp_app (α : NatTrans F G) (β : NatTrans G H) (X : C) :
|
||
(α.vcomp β).app X = α.app X ≫ β.app X := rfl
|
||
|
||
end NatTrans
|
||
|
||
end Mathlib.CategoryTheory.NatTrans
|
||
|
||
section Mathlib.CategoryTheory.Iso
|
||
|
||
structure Iso {C : Type u} [Category.{v} C] (X Y : C) where
|
||
hom : X ⟶ Y
|
||
inv : Y ⟶ X
|
||
hom_inv_id : hom ≫ inv = 𝟙 X := by grind
|
||
inv_hom_id : inv ≫ hom = 𝟙 Y := by grind
|
||
|
||
attribute [simp, grind =] Iso.hom_inv_id Iso.inv_hom_id
|
||
|
||
/-- Notation for an isomorphism in a category. -/
|
||
infixr:10 " ≅ " => Iso -- type as \cong or \iso
|
||
|
||
variable {C : Type u} [Category.{v} C] {X Y Z : C}
|
||
|
||
namespace Iso
|
||
|
||
@[ext, grind ext]
|
||
theorem ext ⦃α β : X ≅ Y⦄ (w : α.hom = β.hom) : α = β :=
|
||
suffices α.inv = β.inv by grind [Iso]
|
||
calc
|
||
α.inv = α.inv ≫ β.hom ≫ β.inv := by grind
|
||
_ = β.inv := by grind
|
||
|
||
/-- Inverse isomorphism. -/
|
||
@[symm]
|
||
def symm (I : X ≅ Y) : Y ≅ X where
|
||
hom := I.inv
|
||
inv := I.hom
|
||
|
||
@[simp, grind =]
|
||
theorem symm_hom (α : X ≅ Y) : α.symm.hom = α.inv :=
|
||
rfl
|
||
|
||
@[simp, grind =]
|
||
theorem symm_inv (α : X ≅ Y) : α.symm.inv = α.hom :=
|
||
rfl
|
||
|
||
@[simp, grind =]
|
||
theorem symm_mk {X Y : C} (hom : X ⟶ Y) (inv : Y ⟶ X) (hom_inv_id) (inv_hom_id) :
|
||
Iso.symm { hom, inv, hom_inv_id := hom_inv_id, inv_hom_id := inv_hom_id } =
|
||
{ hom := inv, inv := hom, hom_inv_id := inv_hom_id, inv_hom_id := hom_inv_id } :=
|
||
rfl
|
||
|
||
@[simp, grind =]
|
||
theorem symm_symm_eq {X Y : C} (α : X ≅ Y) : α.symm.symm = α := rfl
|
||
|
||
/-- Identity isomorphism. -/
|
||
@[refl]
|
||
def refl (X : C) : X ≅ X where
|
||
hom := 𝟙 X
|
||
inv := 𝟙 X
|
||
|
||
@[simp, grind =]
|
||
theorem refl_hom (X : C) : (Iso.refl X).hom = 𝟙 X := rfl
|
||
@[simp, grind =]
|
||
theorem refl_inv (X : C) : (Iso.refl X).inv = 𝟙 X := rfl
|
||
|
||
instance : Inhabited (X ≅ X) := ⟨Iso.refl X⟩
|
||
|
||
/-- Composition of two isomorphisms -/
|
||
def trans (α : X ≅ Y) (β : Y ≅ Z) : X ≅ Z where
|
||
hom := α.hom ≫ β.hom
|
||
inv := β.inv ≫ α.inv
|
||
|
||
/-- Notation for composition of isomorphisms. -/
|
||
infixr:80 " ≪≫ " => Iso.trans
|
||
|
||
@[grind =] theorem trans_hom (α : X ≅ Y) (β : Y ≅ Z) : (α ≪≫ β).hom = α.hom ≫ β.hom := rfl
|
||
@[grind =] theorem trans_inv (α : X ≅ Y) (β : Y ≅ Z) : (α ≪≫ β).inv = β.inv ≫ α.inv := rfl
|
||
|
||
instance instTransIso : Trans (α := C) (· ≅ ·) (· ≅ ·) (· ≅ ·) where
|
||
trans := trans
|
||
|
||
/-- `LeftInverse g f` means that g is a left inverse to f. That is, `g ∘ f = id`. -/
|
||
def Function.LeftInverse (g : β → α) (f : α → β) : Prop :=
|
||
∀ x, g (f x) = x
|
||
|
||
/-- `RightInverse g f` means that g is a right inverse to f. That is, `f ∘ g = id`. -/
|
||
def Function.RightInverse (g : β → α) (f : α → β) : Prop :=
|
||
LeftInverse f g
|
||
|
||
open Function
|
||
|
||
/-- `α ≃ β` is the type of functions from `α → β` with a two-sided inverse. -/
|
||
structure Equiv (α : Sort _) (β : Sort _) where
|
||
protected toFun : α → β
|
||
protected invFun : β → α
|
||
protected left_inv : LeftInverse invFun toFun := by grind
|
||
protected right_inv : RightInverse invFun toFun := by grind
|
||
|
||
@[inherit_doc]
|
||
infixl:25 " ≃ " => Equiv
|
||
|
||
attribute [local grind] Function.LeftInverse Function.RightInverse in
|
||
/-- The bijection `(Z ⟶ X) ≃ (Z ⟶ Y)` induced by `α : X ≅ Y`. -/
|
||
def homToEquiv (α : X ≅ Y) {Z : C} : (Z ⟶ X) ≃ (Z ⟶ Y) where
|
||
toFun f := f ≫ α.hom
|
||
invFun g := g ≫ α.inv
|
||
|
||
end Iso
|
||
|
||
/-- `IsIso` typeclass expressing that a morphism is invertible. -/
|
||
class IsIso (f : X ⟶ Y) : Prop where
|
||
/-- The existence of an inverse morphism. -/
|
||
out : ∃ inv : Y ⟶ X, f ≫ inv = 𝟙 X ∧ inv ≫ f = 𝟙 Y
|
||
|
||
/-- The inverse of a morphism `f` when we have `[IsIso f]`.
|
||
-/
|
||
noncomputable def inv (f : X ⟶ Y) [I : IsIso f] : Y ⟶ X :=
|
||
Classical.choose I.1
|
||
|
||
namespace IsIso
|
||
|
||
@[simp, grind =]
|
||
theorem hom_inv_id (f : X ⟶ Y) [I : IsIso f] : f ≫ inv f = 𝟙 X :=
|
||
(Classical.choose_spec I.1).left
|
||
|
||
@[simp, grind =]
|
||
theorem inv_hom_id (f : X ⟶ Y) [I : IsIso f] : inv f ≫ f = 𝟙 Y :=
|
||
(Classical.choose_spec I.1).right
|
||
|
||
end IsIso
|
||
|
||
theorem Iso.isIso_hom (e : X ≅ Y) : IsIso e.hom :=
|
||
⟨e.inv, by simp, by simp⟩
|
||
|
||
theorem Iso.isIso_inv (e : X ≅ Y) : IsIso e.inv :=
|
||
⟨e.hom, by simp, by simp⟩
|
||
|
||
attribute [instance] Iso.isIso_hom Iso.isIso_inv
|
||
|
||
open IsIso
|
||
|
||
/-- Reinterpret a morphism `f` with an `IsIso f` instance as an `Iso`. -/
|
||
noncomputable def asIso (f : X ⟶ Y) [IsIso f] : X ≅ Y :=
|
||
⟨f, inv f, hom_inv_id f, inv_hom_id f⟩
|
||
|
||
@[simp, grind =]
|
||
theorem asIso_hom (f : X ⟶ Y) {_ : IsIso f} : (asIso f).hom = f :=
|
||
rfl
|
||
|
||
@[simp, grind =]
|
||
theorem asIso_inv (f : X ⟶ Y) {_ : IsIso f} : (asIso f).inv = inv f :=
|
||
rfl
|
||
|
||
namespace IsIso
|
||
|
||
@[grind ←=]
|
||
theorem inv_eq_of_hom_inv_id {f : X ⟶ Y} [IsIso f] {g : Y ⟶ X} (hom_inv_id : f ≫ g = 𝟙 X) :
|
||
inv f = g := by
|
||
have := congrArg (inv f ≫ ·) hom_inv_id
|
||
grind
|
||
|
||
theorem inv_eq_of_inv_hom_id {f : X ⟶ Y} [IsIso f] {g : Y ⟶ X} (inv_hom_id : g ≫ f = 𝟙 Y) :
|
||
inv f = g := by
|
||
have := congrArg (· ≫ inv f) inv_hom_id
|
||
grind
|
||
|
||
theorem eq_inv_of_hom_inv_id {f : X ⟶ Y} [IsIso f] {g : Y ⟶ X} (hom_inv_id : f ≫ g = 𝟙 X) :
|
||
g = inv f :=
|
||
(inv_eq_of_hom_inv_id hom_inv_id).symm
|
||
|
||
theorem eq_inv_of_inv_hom_id {f : X ⟶ Y} [IsIso f] {g : Y ⟶ X} (inv_hom_id : g ≫ f = 𝟙 Y) :
|
||
g = inv f :=
|
||
(inv_eq_of_inv_hom_id inv_hom_id).symm
|
||
|
||
instance inv_isIso {f : X ⟶ Y} [IsIso f] : IsIso (inv f) :=
|
||
{ out := ⟨f, by simp, by simp⟩ }
|
||
|
||
end IsIso
|
||
|
||
namespace Iso
|
||
|
||
variable (e : X ≅ Y)
|
||
|
||
@[grind =]
|
||
theorem map_hom_inv_id (F : C ⥤ D) :
|
||
F.map e.hom ≫ F.map e.inv = 𝟙 _ := by grind
|
||
|
||
@[grind =]
|
||
theorem map_inv_hom_id (F : C ⥤ D) :
|
||
F.map e.inv ≫ F.map e.hom = 𝟙 _ := by grind
|
||
|
||
end Iso
|
||
|
||
namespace Functor
|
||
|
||
variable {D : Type u₂}
|
||
variable [Category.{v₂} D]
|
||
|
||
/-- A functor `F : C ⥤ D` sends isomorphisms `i : X ≅ Y` to isomorphisms `F.obj X ≅ F.obj Y` -/
|
||
def mapIso (F : C ⥤ D) {X Y : C} (i : X ≅ Y) : F.obj X ≅ F.obj Y where
|
||
hom := F.map i.hom
|
||
inv := F.map i.inv
|
||
|
||
@[simp, grind =]
|
||
theorem mapIso_hom (F : C ⥤ D) {X Y : C} (i : X ≅ Y) : (F.mapIso i).hom = F.map i.hom := rfl
|
||
@[simp, grind =]
|
||
theorem mapIso_inv (F : C ⥤ D) {X Y : C} (i : X ≅ Y) : (F.mapIso i).inv = F.map i.inv := rfl
|
||
|
||
@[simp]
|
||
theorem mapIso_symm (F : C ⥤ D) {X Y : C} (i : X ≅ Y) : F.mapIso i.symm = (F.mapIso i).symm :=
|
||
rfl
|
||
|
||
@[simp]
|
||
theorem mapIso_trans (F : C ⥤ D) {X Y Z : C} (i : X ≅ Y) (j : Y ≅ Z) :
|
||
F.mapIso (i ≪≫ j) = F.mapIso i ≪≫ F.mapIso j := by
|
||
ext; apply Functor.map_comp
|
||
|
||
@[simp]
|
||
theorem mapIso_refl (F : C ⥤ D) (X : C) : F.mapIso (Iso.refl X) = Iso.refl (F.obj X) :=
|
||
Iso.ext <| F.map_id X
|
||
|
||
instance map_isIso (F : C ⥤ D) (f : X ⟶ Y) [IsIso f] : IsIso (F.map f) :=
|
||
(F.mapIso (asIso f)).isIso_hom
|
||
|
||
@[simp]
|
||
theorem map_inv (F : C ⥤ D) {X Y : C} (f : X ⟶ Y) [IsIso f] : F.map (inv f) = inv (F.map f) := by
|
||
apply eq_inv_of_hom_inv_id
|
||
simp [← F.map_comp]
|
||
|
||
theorem map_hom_inv (F : C ⥤ D) {X Y : C} (f : X ⟶ Y) [IsIso f] :
|
||
F.map f ≫ F.map (inv f) = 𝟙 (F.obj X) := by simp
|
||
|
||
theorem map_inv_hom (F : C ⥤ D) {X Y : C} (f : X ⟶ Y) [IsIso f] :
|
||
F.map (inv f) ≫ F.map f = 𝟙 (F.obj Y) := by simp
|
||
|
||
end Functor
|
||
|
||
end Mathlib.CategoryTheory.Iso
|
||
|
||
section Mathlib.CategoryTheory.Functor.Category
|
||
|
||
instance Functor.category : Category.{max u₁ v₂} (Functor C D) where
|
||
Hom F G := NatTrans F G
|
||
id F := NatTrans.id F
|
||
comp α β := NatTrans.vcomp α β
|
||
-- Here we're okay: all the proofs are handled by `grind`.
|
||
|
||
namespace NatTrans
|
||
|
||
@[ext, grind ext]
|
||
theorem ext' {α β : F ⟶ G} (w : α.app = β.app) : α = β := NatTrans.ext w
|
||
|
||
@[simp, grind =]
|
||
theorem id_app (F : Functor C D) (X : C) : (𝟙 F : F ⟶ F).app X = 𝟙 (F.obj X) := rfl
|
||
|
||
@[simp, grind _=_]
|
||
theorem comp_app {F G H : Functor C D} (α : F ⟶ G) (β : G ⟶ H) (X : C) :
|
||
(α ≫ β).app X = α.app X ≫ β.app X := rfl
|
||
|
||
theorem app_naturality {F G : Functor C (Functor D E)} (T : F ⟶ G) (X : C) {Y Z : D} (f : Y ⟶ Z) :
|
||
(F.obj X).map f ≫ (T.app X).app Z = (T.app X).app Y ≫ (G.obj X).map f := by
|
||
grind
|
||
|
||
theorem naturality_app {F G : Functor C (Functor D E)} (T : F ⟶ G) (Z : D) {X Y : C} (f : X ⟶ Y) :
|
||
(F.map f).app Z ≫ (T.app Y).app Z = (T.app X).app Z ≫ (G.map f).app Z := by
|
||
grind -- this is done manually in Mathlib!
|
||
-- rw [← comp_app]
|
||
-- rw [T.naturality f]
|
||
-- rw [comp_app]
|
||
|
||
@[simp]
|
||
theorem vcomp_eq_comp (α : F ⟶ G) (β : G ⟶ H) : NatTrans.vcomp α β = α ≫ β := rfl
|
||
|
||
theorem vcomp_app' (α : F ⟶ G) (β : G ⟶ H) (X : C) : (α ≫ β).app X = α.app X ≫ β.app X := rfl
|
||
|
||
theorem congr_app {α β : F ⟶ G} (h : α = β) (X : C) : α.app X = β.app X := by grind
|
||
|
||
open Category Functor NatTrans
|
||
|
||
def hcomp {H I : Functor D E} (α : F ⟶ G) (β : H ⟶ I) : F.comp H ⟶ G.comp I where
|
||
app := fun X : C => β.app (F.obj X) ≫ I.map (α.app X)
|
||
-- `grind` can now handle `naturality`, while Mathlib does this manually:
|
||
-- rw [Functor.comp_map, Functor.comp_map, ← assoc, naturality, assoc, ← I.map_comp, naturality,
|
||
-- map_comp, assoc]
|
||
|
||
/-- Notation for horizontal composition of natural transformations. -/
|
||
infixl:80 " ◫ " => hcomp
|
||
|
||
@[simp] theorem hcomp_app {H I : Functor D E} (α : F ⟶ G) (β : H ⟶ I) (X : C) :
|
||
(α ◫ β).app X = β.app (F.obj X) ≫ I.map (α.app X) := rfl
|
||
|
||
attribute [grind =] hcomp_app
|
||
|
||
theorem hcomp_id_app {H : D ⥤ E} (α : F ⟶ G) (X : C) : (α ◫ 𝟙 H).app X = H.map (α.app X) := by
|
||
grind
|
||
|
||
theorem id_hcomp_app {H : E ⥤ C} (α : F ⟶ G) (X : E) : (𝟙 H ◫ α).app X = α.app _ := by
|
||
grind
|
||
|
||
-- Note that we don't yet prove a `hcomp_assoc` lemma here: even stating it is painful, because we
|
||
-- need to use associativity of functor composition. (It's true without the explicit associator,
|
||
-- because functor composition is definitionally associative,
|
||
-- but relying on the definitional equality causes bad problems with elaboration later.)
|
||
theorem exchange {I J K : D ⥤ E} (α : F ⟶ G) (β : G ⟶ H) (γ : I ⟶ J) (δ : J ⟶ K) :
|
||
(α ≫ β) ◫ (γ ≫ δ) = (α ◫ γ) ≫ β ◫ δ := by
|
||
grind
|
||
|
||
theorem naturality_app_app {F G : C ⥤ D ⥤ E ⥤ E'}
|
||
(α : F ⟶ G) {X₁ Y₁ : C} (f : X₁ ⟶ Y₁) (X₂ : D) (X₃ : E) :
|
||
((F.map f).app X₂).app X₃ ≫ ((α.app Y₁).app X₂).app X₃ =
|
||
((α.app X₁).app X₂).app X₃ ≫ ((G.map f).app X₂).app X₃ := by
|
||
grind
|
||
|
||
end NatTrans
|
||
|
||
namespace Functor
|
||
|
||
/-- Flip the arguments of a bifunctor. See also `Currying.lean`. -/
|
||
protected def flip (F : C ⥤ D ⥤ E) : D ⥤ C ⥤ E where
|
||
obj k :=
|
||
{ obj := fun j => (F.obj j).obj k,
|
||
map := fun f => (F.map f).app k, }
|
||
map f := { app := fun j => (F.obj j).map f }
|
||
|
||
@[simp] theorem flip_obj_obj (F : C ⥤ D ⥤ E) (k : D) : (F.flip.obj k).obj = fun j => (F.obj j).obj k := rfl
|
||
@[simp] theorem flip_obj_map (F : C ⥤ D ⥤ E) (k : D) {X Y : C}(f : X ⟶ Y) : (F.flip.obj k).map f = (F.map f).app k := rfl
|
||
@[simp] theorem flip_map_app (F : C ⥤ D ⥤ E) {X Y : D} (f : X ⟶ Y) (k : C) : (F.flip.map f).app k = (F.obj k).map f := rfl
|
||
|
||
attribute [grind =] flip_obj_obj flip_obj_map flip_map_app
|
||
|
||
end Functor
|
||
|
||
variable (C D E) in
|
||
/-- The functor `(C ⥤ D ⥤ E) ⥤ D ⥤ C ⥤ E` which flips the variables. -/
|
||
def flipFunctor : (C ⥤ D ⥤ E) ⥤ D ⥤ C ⥤ E where
|
||
obj F := F.flip
|
||
map {F₁ F₂} φ := { app := fun Y => { app := fun X => (φ.app X).app Y } }
|
||
|
||
namespace Iso
|
||
|
||
@[simp]
|
||
theorem map_hom_inv_id_app {X Y : C} (e : X ≅ Y) (F : C ⥤ D ⥤ E) (Z : D) :
|
||
(F.map e.hom).app Z ≫ (F.map e.inv).app Z = 𝟙 _ := by
|
||
grind
|
||
|
||
@[simp]
|
||
theorem map_inv_hom_id_app {X Y : C} (e : X ≅ Y) (F : C ⥤ D ⥤ E) (Z : D) :
|
||
(F.map e.inv).app Z ≫ (F.map e.hom).app Z = 𝟙 _ := by
|
||
grind
|
||
|
||
end Iso
|
||
|
||
end Mathlib.CategoryTheory.Functor.Category
|
||
|
||
section Mathlib.CategoryTheory.NatIso
|
||
|
||
|
||
open NatTrans
|
||
|
||
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] {E : Type u₃}
|
||
[Category.{v₃} E] {E' : Type u₄} [Category.{v₄} E']
|
||
|
||
namespace Iso
|
||
|
||
/-- The application of a natural isomorphism to an object. We put this definition in a different
|
||
namespace, so that we can use `α.app` -/
|
||
def app {F G : C ⥤ D} (α : F ≅ G) (X : C) :
|
||
F.obj X ≅ G.obj X where
|
||
hom := α.hom.app X
|
||
inv := α.inv.app X
|
||
hom_inv_id := by rw [← comp_app, Iso.hom_inv_id]; rfl
|
||
inv_hom_id := by rw [← comp_app, Iso.inv_hom_id]; rfl
|
||
|
||
@[simp, grind =] theorem app_hom {F G : C ⥤ D} (α : F ≅ G) (X : C) : (α.app X).hom = α.hom.app X := rfl
|
||
@[simp, grind =] theorem app_inv {F G : C ⥤ D} (α : F ≅ G) (X : C) : (α.app X).inv = α.inv.app X := rfl
|
||
|
||
@[simp, grind =]
|
||
theorem hom_inv_id_app {F G : C ⥤ D} (α : F ≅ G) (X : C) :
|
||
α.hom.app X ≫ α.inv.app X = 𝟙 (F.obj X) :=
|
||
congrFun (congrArg NatTrans.app α.hom_inv_id) X
|
||
|
||
@[simp, grind =]
|
||
theorem inv_hom_id_app {F G : C ⥤ D} (α : F ≅ G) (X : C) :
|
||
α.inv.app X ≫ α.hom.app X = 𝟙 (G.obj X) :=
|
||
congrFun (congrArg NatTrans.app α.inv_hom_id) X
|
||
|
||
@[simp]
|
||
theorem hom_inv_id_app_app {F G : C ⥤ D ⥤ E} (e : F ≅ G) (X₁ : C) (X₂ : D) :
|
||
(e.hom.app X₁).app X₂ ≫ (e.inv.app X₁).app X₂ = 𝟙 _ := by
|
||
rw [← NatTrans.comp_app, Iso.hom_inv_id_app, NatTrans.id_app]
|
||
|
||
@[simp]
|
||
theorem inv_hom_id_app_app {F G : C ⥤ D ⥤ E} (e : F ≅ G) (X₁ : C) (X₂ : D) :
|
||
(e.inv.app X₁).app X₂ ≫ (e.hom.app X₁).app X₂ = 𝟙 _ := by
|
||
rw [← NatTrans.comp_app, Iso.inv_hom_id_app, NatTrans.id_app]
|
||
|
||
@[simp]
|
||
theorem hom_inv_id_app_app_app {F G : C ⥤ D ⥤ E ⥤ E'} (e : F ≅ G)
|
||
(X₁ : C) (X₂ : D) (X₃ : E) :
|
||
((e.hom.app X₁).app X₂).app X₃ ≫ ((e.inv.app X₁).app X₂).app X₃ = 𝟙 _ := by
|
||
rw [← NatTrans.comp_app, ← NatTrans.comp_app, Iso.hom_inv_id_app,
|
||
NatTrans.id_app, NatTrans.id_app]
|
||
|
||
@[simp]
|
||
theorem inv_hom_id_app_app_app {F G : C ⥤ D ⥤ E ⥤ E'} (e : F ≅ G)
|
||
(X₁ : C) (X₂ : D) (X₃ : E) :
|
||
((e.inv.app X₁).app X₂).app X₃ ≫ ((e.hom.app X₁).app X₂).app X₃ = 𝟙 _ := by
|
||
rw [← NatTrans.comp_app, ← NatTrans.comp_app, Iso.inv_hom_id_app,
|
||
NatTrans.id_app, NatTrans.id_app]
|
||
|
||
end Iso
|
||
|
||
namespace NatIso
|
||
|
||
open CategoryTheory.Category CategoryTheory.Functor
|
||
|
||
@[simp]
|
||
theorem trans_app {F G H : C ⥤ D} (α : F ≅ G) (β : G ≅ H) (X : C) :
|
||
(α ≪≫ β).app X = α.app X ≪≫ β.app X :=
|
||
rfl
|
||
|
||
variable {F G : C ⥤ D}
|
||
|
||
instance hom_app_isIso (α : F ≅ G) (X : C) : IsIso (α.hom.app X) :=
|
||
⟨⟨α.inv.app X, ⟨by grind, by grind⟩⟩⟩
|
||
|
||
instance inv_app_isIso (α : F ≅ G) (X : C) : IsIso (α.inv.app X) :=
|
||
⟨⟨α.hom.app X, ⟨by grind, by grind⟩⟩⟩
|
||
|
||
section
|
||
|
||
variable (α : F ≅ G)
|
||
|
||
@[simp]
|
||
theorem inv_inv_app {F G : C ⥤ D} (e : F ≅ G) (X : C) : inv (e.inv.app X) = e.hom.app X := by
|
||
grind
|
||
|
||
end
|
||
|
||
variable {X Y : C}
|
||
|
||
theorem naturality_1 (α : F ≅ G) (f : X ⟶ Y) : α.inv.app X ≫ F.map f ≫ α.hom.app Y = G.map f := by
|
||
grind
|
||
|
||
theorem naturality_2 (α : F ≅ G) (f : X ⟶ Y) : α.hom.app X ≫ G.map f ≫ α.inv.app Y = F.map f := by
|
||
grind
|
||
|
||
theorem naturality_1' (α : F ⟶ G) (f : X ⟶ Y) {_ : IsIso (α.app X)} :
|
||
inv (α.app X) ≫ F.map f ≫ α.app Y = G.map f := by grind
|
||
|
||
@[simp]
|
||
theorem naturality_2' (α : F ⟶ G) (f : X ⟶ Y) {_ : IsIso (α.app Y)} :
|
||
α.app X ≫ G.map f ≫ inv (α.app Y) = F.map f := by
|
||
grind
|
||
|
||
/-- The components of a natural isomorphism are isomorphisms.
|
||
-/
|
||
instance isIso_app_of_isIso (α : F ⟶ G) [IsIso α] (X) : IsIso (α.app X) :=
|
||
⟨⟨(inv α).app X, ⟨by grind, by grind⟩⟩⟩
|
||
|
||
@[simp]
|
||
theorem isIso_inv_app (α : F ⟶ G) {_ : IsIso α} (X) : (inv α).app X = inv (α.app X) := by
|
||
grind
|
||
|
||
@[simp]
|
||
theorem inv_map_inv_app (F : C ⥤ D ⥤ E) {X Y : C} (e : X ≅ Y) (Z : D) :
|
||
inv ((F.map e.inv).app Z) = (F.map e.hom).app Z := by
|
||
grind
|
||
|
||
/-- Construct a natural isomorphism between functors by giving object level isomorphisms,
|
||
and checking naturality only in the forward direction.
|
||
-/
|
||
def ofComponents (app : ∀ X : C, F.obj X ≅ G.obj X)
|
||
(naturality : ∀ {X Y : C} (f : X ⟶ Y),
|
||
F.map f ≫ (app Y).hom = (app X).hom ≫ G.map f := by grind) :
|
||
F ≅ G where
|
||
hom := { app := fun X => (app X).hom }
|
||
inv :=
|
||
{ app := fun X => (app X).inv,
|
||
naturality := fun X Y f => by
|
||
have h := congrArg (fun f => (app X).inv ≫ f ≫ (app Y).inv) (naturality f).symm
|
||
grind }
|
||
hom_inv_id := by
|
||
grind
|
||
inv_hom_id := by
|
||
grind
|
||
|
||
@[simp, grind =]
|
||
theorem ofComponents_hom_app (app : ∀ X : C, F.obj X ≅ G.obj X) (naturality) (X : C) :
|
||
(ofComponents app naturality).hom.app X = (app X).hom := rfl
|
||
@[simp, grind =]
|
||
theorem ofComponents_inv_app (app : ∀ X : C, F.obj X ≅ G.obj X) (naturality) (X : C) :
|
||
(ofComponents app naturality).inv.app X = (app X).inv := rfl
|
||
|
||
theorem ofComponents_app (app : ∀ X : C, F.obj X ≅ G.obj X) (naturality) (X : C) :
|
||
(ofComponents app naturality).app X = app X := by
|
||
grind
|
||
|
||
@[simp]
|
||
theorem ofComponents.app (app : ∀ X : C, F.obj X ≅ G.obj X) (naturality) (X) :
|
||
(ofComponents app naturality).app X = app X := by grind
|
||
|
||
-- Making this an instance would cause a typeclass inference loop with `isIso_app_of_isIso`.
|
||
/-- A natural transformation is an isomorphism if all its components are isomorphisms.
|
||
-/
|
||
theorem isIso_of_isIso_app (α : F ⟶ G) [∀ X : C, IsIso (α.app X)] : IsIso α :=
|
||
(ofComponents (fun X => asIso (α.app X)) (by simp)).isIso_hom
|
||
|
||
/-- Horizontal composition of natural isomorphisms. -/
|
||
def hcomp {F G : C ⥤ D} {H I : D ⥤ E} (α : F ≅ G) (β : H ≅ I) : F ⋙ H ≅ G ⋙ I := by
|
||
refine ⟨α.hom ◫ β.hom, α.inv ◫ β.inv, ?_, ?_⟩
|
||
· ext
|
||
rw [← NatTrans.exchange]
|
||
simp
|
||
· ext
|
||
rw [← NatTrans.exchange]
|
||
simp
|
||
|
||
@[simp]
|
||
theorem hcomp_hom {F G : C ⥤ D} {H I : D ⥤ E} (α : F ≅ G) (β : H ≅ I) :
|
||
(hcomp α β).hom = α.hom ◫ β.hom := rfl
|
||
@[simp]
|
||
theorem hcomp_inv {F G : C ⥤ D} {H I : D ⥤ E} (α : F ≅ G) (β : H ≅ I) :
|
||
(hcomp α β).inv = α.inv ◫ β.inv := rfl
|
||
|
||
theorem isIso_map_iff {F₁ F₂ : C ⥤ D} (e : F₁ ≅ F₂) {X Y : C} (f : X ⟶ Y) :
|
||
IsIso (F₁.map f) ↔ IsIso (F₂.map f) := by
|
||
revert F₁ F₂
|
||
suffices ∀ {F₁ F₂ : C ⥤ D} (_ : F₁ ≅ F₂) (_ : IsIso (F₁.map f)), IsIso (F₂.map f) by
|
||
exact fun F₁ F₂ e => ⟨this e, this e.symm⟩
|
||
intro F₁ F₂ e hf
|
||
refine IsIso.mk ⟨e.inv.app Y ≫ inv (F₁.map f) ≫ e.hom.app X, ?_, ?_⟩
|
||
· grind (ematch := 6)
|
||
· grind (ematch := 7)
|
||
|
||
end NatIso
|
||
|
||
theorem NatTrans.isIso_iff_isIso_app {F G : C ⥤ D} (τ : F ⟶ G) :
|
||
IsIso τ ↔ ∀ X, IsIso (τ.app X) :=
|
||
⟨fun _ ↦ inferInstance, fun _ ↦ NatIso.isIso_of_isIso_app _⟩
|
||
|
||
end Mathlib.CategoryTheory.NatIso
|
||
|
||
end CategoryTheory
|