Compare commits

...

3 Commits

Author SHA1 Message Date
Leonardo de Moura
818ed30eb2 update test 2025-01-06 08:12:59 -08:00
Kim Morrison
3c2f8193f9 update test 2025-01-06 08:00:54 -08:00
Kim Morrison
f299257c6c feat: grind tests for basic category theory 2025-01-06 08:00:53 -08:00
4 changed files with 161 additions and 10 deletions

View File

@@ -0,0 +1,125 @@
universe v v₁ v₂ v₃ u u₁ u₂ u₃
namespace CategoryTheory
macro "cat_tac" : tactic => `(tactic| (intros; (try ext); grind))
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 cat_tac
/-- Identity morphisms are right identities for composition. -/
comp_id : {X Y : obj} (f : Hom X Y), comp f (id Y) = f := by cat_tac
/-- 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 cat_tac
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
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 cat_tac
/-- A functor preserves composition. -/
map_comp : {X Y Z : C} (f : X Y) (g : Y Z), map (f g) = (map f) (map g) := by cat_tac
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 `cat_tac`.
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
@[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 cat_tac
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
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 `cat_tac`.
@[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
cat_tac
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
cat_tac -- this is done manually in Mathlib!
-- rw [← comp_app]
-- rw [T.naturality f]
-- rw [comp_app]
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]
end CategoryTheory

View File

@@ -1,5 +1,6 @@
set_option trace.grind.ematch.pattern true
grind_pattern Array.size_set => Array.set a i v h
attribute [grind =] Array.size_set
set_option grind.debug true
@@ -21,12 +22,10 @@ example (as bs : Array α) (v : α)
set_option trace.grind.ematch.instance true
grind_pattern Array.get_set_eq => a.set i v h
grind_pattern Array.get_set_ne => (a.set i v hi)[j]
attribute [grind =] Array.get_set_ne
/--
info: [grind.ematch.instance] Array.get_set_eq: (as.set i v ⋯)[i] = v
[grind.ematch.instance] Array.size_set: (as.set i v ⋯).size = as.size
info: [grind.ematch.instance] Array.size_set: (as.set i v ⋯).size = as.size
[grind.ematch.instance] Array.get_set_ne: ∀ (hj : j < as.size), i ≠ j → (as.set i v ⋯)[j] = as[j]
-/
#guard_msgs (info) in

View File

@@ -1,6 +1,4 @@
grind_pattern Array.size_set => Array.set a i v h
grind_pattern Array.get_set_eq => a.set i v h
grind_pattern Array.get_set_ne => (a.set i v hi)[j]
attribute [grind =] Array.size_set Array.get_set_eq Array.get_set_ne
set_option grind.debug true
set_option trace.grind.ematch.pattern true
@@ -57,8 +55,7 @@ example (as bs cs ds : Array α) (v₁ v₂ v₃ : α)
grind
opaque f (a b : α) : α := a
theorem fx : f x (f x x) = x := sorry
grind_pattern fx => f x (f x x)
@[grind =] theorem fx : f x (f x x) = x := sorry
/--
info: [grind.ematch.instance] fx: f a (f a a) = a

View File

@@ -0,0 +1,30 @@
class One (α : Type u) where
one : α
instance (priority := 300) One.toOfNat1 {α} [One α] : OfNat α (nat_lit 1) where
ofNat := One α.1
class Shelf (α : Type u) where
act : α α α
self_distrib : {x y z : α}, act x (act y z) = act (act x y) (act x z)
class UnitalShelf (α : Type u) extends Shelf α, One α where
one_act : a : α, act 1 a = a
act_one : a : α, act a 1 = a
infixr:65 "" => Shelf.act
-- Mathlib proof from UnitalShelf.act_act_self_eq
example {S} [UnitalShelf S] (x y : S) : (x y) x = x y := by
have h : (x y) x = (x y) (x 1) := by rw [UnitalShelf.act_one]
rw [h, Shelf.self_distrib, UnitalShelf.act_one]
attribute [grind =] UnitalShelf.one_act UnitalShelf.act_one
-- We actually want the reverse direction of `Shelf.self_distrib`, so don't use the `grind_eq` attribute.
grind_pattern Shelf.self_distrib => self.act (self.act x y) (self.act x z)
-- Proof using `grind`:
example {S} [UnitalShelf S] (x y : S) : (x y) x = x y := by
have h : (x y) x = (x y) (x 1) := by grind
grind