|
| 1 | +/- |
| 2 | +Copyright (c) 2022 Rémi Bottinelli. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Rémi Bottinelli |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module category_theory.groupoid.free_groupoid |
| 7 | +! leanprover-community/mathlib commit 706d88f2b8fdfeb0b22796433d7a6c1a010af9f2 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.CategoryTheory.Category.Basic |
| 12 | +import Mathlib.CategoryTheory.Functor.Basic |
| 13 | +import Mathlib.CategoryTheory.Groupoid |
| 14 | +import Mathlib.Tactic.NthRewrite |
| 15 | +import Mathlib.CategoryTheory.PathCategory |
| 16 | +import Mathlib.CategoryTheory.Quotient |
| 17 | +import Mathlib.Combinatorics.Quiver.Symmetric |
| 18 | + |
| 19 | +/-! |
| 20 | +# Free groupoid on a quiver |
| 21 | +
|
| 22 | +This file defines the free groupoid on a quiver, the lifting of a prefunctor to its unique |
| 23 | +extension as a functor from the free groupoid, and proves uniqueness of this extension. |
| 24 | +
|
| 25 | +## Main results |
| 26 | +
|
| 27 | +Given the type `V` and a quiver instance on `V`: |
| 28 | +
|
| 29 | +- `free_groupoid V`: a type synonym for `V`. |
| 30 | +- `free_groupoid_groupoid`: the `groupoid` instance on `free_groupoid V`. |
| 31 | +- `lift`: the lifting of a prefunctor from `V` to `V'` where `V'` is a groupoid, to a functor. |
| 32 | + `free_groupoid V ⥤ V'`. |
| 33 | +- `lift_spec` and `lift_unique`: the proofs that, respectively, `lift` indeed is a lifting |
| 34 | + and is the unique one. |
| 35 | +
|
| 36 | +## Implementation notes |
| 37 | +
|
| 38 | +The free groupoid is first defined by symmetrifying the quiver, taking the induced path category |
| 39 | +and finally quotienting by the reducibility relation. |
| 40 | +
|
| 41 | +-/ |
| 42 | + |
| 43 | + |
| 44 | +open Set Classical Function |
| 45 | + |
| 46 | +attribute [local instance] propDecidable |
| 47 | + |
| 48 | +namespace CategoryTheory |
| 49 | + |
| 50 | +namespace Groupoid |
| 51 | + |
| 52 | +namespace Free |
| 53 | + |
| 54 | +universe u v u' v' u'' v'' |
| 55 | + |
| 56 | +variable {V : Type u} [Quiver.{v + 1} V] |
| 57 | + |
| 58 | +/-- Shorthand for the "forward" arrow corresponding to `f` in `paths $ symmetrify V` -/ |
| 59 | +abbrev _root_.Quiver.Hom.toPosPath {X Y : V} (f : X ⟶ Y) : |
| 60 | + (CategoryTheory.Paths.categoryPaths <| Quiver.Symmetrify V).Hom X Y := |
| 61 | + f.toPos.toPath |
| 62 | +#align category_theory.groupoid.free.quiver.hom.to_pos_path Quiver.Hom.toPosPath |
| 63 | + |
| 64 | +/-- Shorthand for the "forward" arrow corresponding to `f` in `paths $ symmetrify V` -/ |
| 65 | +abbrev _root_.Quiver.Hom.toNegPath {X Y : V} (f : X ⟶ Y) : |
| 66 | + (CategoryTheory.Paths.categoryPaths <| Quiver.Symmetrify V).Hom Y X := |
| 67 | + f.toNeg.toPath |
| 68 | +#align category_theory.groupoid.free.quiver.hom.to_neg_path Quiver.Hom.toNegPath |
| 69 | + |
| 70 | +/-- The "reduction" relation -/ |
| 71 | +inductive redStep : HomRel (Paths (Quiver.Symmetrify V)) |
| 72 | + | step (X Z : Quiver.Symmetrify V) (f : X ⟶ Z) : |
| 73 | + redStep (𝟙 (Paths.of.obj X)) (f.toPath ≫ (Quiver.reverse f).toPath) |
| 74 | +#align category_theory.groupoid.free.red_step CategoryTheory.Groupoid.Free.redStep |
| 75 | + |
| 76 | +/-- The underlying vertices of the free groupoid -/ |
| 77 | +def _root_.CategoryTheory.FreeGroupoid (V) [Q : Quiver V] := |
| 78 | + Quotient (@redStep V Q) |
| 79 | +#align category_theory.free_groupoid CategoryTheory.FreeGroupoid |
| 80 | + |
| 81 | +instance {V} [Quiver V] [Nonempty V] : Nonempty (FreeGroupoid V) := by |
| 82 | + inhabit V; exact ⟨⟨@default V _⟩⟩ |
| 83 | + |
| 84 | +theorem congr_reverse {X Y : Paths <| Quiver.Symmetrify V} (p q : X ⟶ Y) : |
| 85 | + Quotient.CompClosure redStep p q → Quotient.CompClosure redStep p.reverse q.reverse := by |
| 86 | + rintro ⟨XW, pp, qq, WY, _, Z, f⟩ |
| 87 | + have : Quotient.CompClosure redStep (WY.reverse ≫ 𝟙 _ ≫ XW.reverse) |
| 88 | + (WY.reverse ≫ (f.toPath ≫ (Quiver.reverse f).toPath) ≫ XW.reverse) := by |
| 89 | + constructor |
| 90 | + constructor |
| 91 | + simpa only [CategoryStruct.comp, CategoryStruct.id, Quiver.Path.reverse, Quiver.Path.nil_comp, |
| 92 | + Quiver.Path.reverse_comp, Quiver.reverse_reverse, Quiver.Path.reverse_toPath, |
| 93 | + Quiver.Path.comp_assoc] using this |
| 94 | +#align category_theory.groupoid.free.congr_reverse CategoryTheory.Groupoid.Free.congr_reverse |
| 95 | + |
| 96 | +theorem congr_comp_reverse {X Y : Paths <| Quiver.Symmetrify V} (p : X ⟶ Y) : |
| 97 | + Quot.mk (@Quotient.CompClosure _ _ redStep _ _) (p ≫ p.reverse) = |
| 98 | + Quot.mk (@Quotient.CompClosure _ _ redStep _ _) (𝟙 X) := by |
| 99 | + apply Quot.EqvGen_sound |
| 100 | + induction' p with a b q f ih |
| 101 | + · apply EqvGen.refl |
| 102 | + · simp only [Quiver.Path.reverse] |
| 103 | + fapply EqvGen.trans |
| 104 | + -- Porting note : `Quiver.Path.*` and `Quiver.Hom.*` notation not working |
| 105 | + · exact q ≫ Quiver.Path.reverse q |
| 106 | + · apply EqvGen.symm |
| 107 | + apply EqvGen.rel |
| 108 | + have : Quotient.CompClosure redStep (q ≫ 𝟙 _ ≫ Quiver.Path.reverse q) |
| 109 | + (q ≫ (Quiver.Hom.toPath f ≫ Quiver.Hom.toPath (Quiver.reverse f)) ≫ |
| 110 | + Quiver.Path.reverse q) := by |
| 111 | + apply Quotient.CompClosure.intro |
| 112 | + apply redStep.step |
| 113 | + simp only [Category.assoc, Category.id_comp] at this ⊢ |
| 114 | + -- Porting note : `simp` cannot see how `Quiver.Path.comp_assoc` is relevant, so change to |
| 115 | + -- category notation |
| 116 | + change Quotient.CompClosure redStep (q ≫ Quiver.Path.reverse q) |
| 117 | + (Quiver.Path.cons q f ≫ (Quiver.Hom.toPath (Quiver.reverse f)) ≫ (Quiver.Path.reverse q)) |
| 118 | + simp only [←Category.assoc] at this ⊢ |
| 119 | + exact this |
| 120 | + · exact ih |
| 121 | +#align category_theory.groupoid.free.congr_comp_reverse CategoryTheory.Groupoid.Free.congr_comp_reverse |
| 122 | + |
| 123 | +theorem congr_reverse_comp {X Y : Paths <| Quiver.Symmetrify V} (p : X ⟶ Y) : |
| 124 | + Quot.mk (@Quotient.CompClosure _ _ redStep _ _) (p.reverse ≫ p) = |
| 125 | + Quot.mk (@Quotient.CompClosure _ _ redStep _ _) (𝟙 Y) := by |
| 126 | + nth_rw 2 [← Quiver.Path.reverse_reverse p] |
| 127 | + apply congr_comp_reverse |
| 128 | +#align category_theory.groupoid.free.congr_reverse_comp CategoryTheory.Groupoid.Free.congr_reverse_comp |
| 129 | + |
| 130 | +instance : Category (FreeGroupoid V) := |
| 131 | + Quotient.category redStep |
| 132 | + |
| 133 | +/-- The inverse of an arrow in the free groupoid -/ |
| 134 | +def quotInv {X Y : FreeGroupoid V} (f : X ⟶ Y) : Y ⟶ X := |
| 135 | + Quot.liftOn f (fun pp => Quot.mk _ <| pp.reverse) fun pp qq con => |
| 136 | + Quot.sound <| congr_reverse pp qq con |
| 137 | +#align category_theory.groupoid.free.quot_inv CategoryTheory.Groupoid.Free.quotInv |
| 138 | + |
| 139 | +instance : Groupoid (FreeGroupoid V) where |
| 140 | + inv := quotInv |
| 141 | + inv_comp p := Quot.inductionOn p fun pp => congr_reverse_comp pp |
| 142 | + comp_inv p := Quot.inductionOn p fun pp => congr_comp_reverse pp |
| 143 | + |
| 144 | +/-- The inclusion of the quiver on `V` to the underlying quiver on `free_groupoid V`-/ |
| 145 | +def of (V) [Quiver V] : V ⥤q FreeGroupoid V where |
| 146 | + obj X := ⟨X⟩ |
| 147 | + map f := Quot.mk _ f.toPosPath |
| 148 | +#align category_theory.groupoid.free.of CategoryTheory.Groupoid.Free.of |
| 149 | + |
| 150 | +theorem of_eq : |
| 151 | + of V = (Quiver.Symmetrify.of ⋙q Paths.of).comp |
| 152 | + (Quotient.functor <| @redStep V _).toPrefunctor := rfl |
| 153 | +#align category_theory.groupoid.free.of_eq CategoryTheory.Groupoid.Free.of_eq |
| 154 | + |
| 155 | +section UniversalProperty |
| 156 | + |
| 157 | +variable {V' : Type u'} [Groupoid V'] (φ : V ⥤q V') |
| 158 | + |
| 159 | +/-- The lift of a prefunctor to a groupoid, to a functor from `free_groupoid V` -/ |
| 160 | +def lift (φ : V ⥤q V') : FreeGroupoid V ⥤ V' := |
| 161 | + Quotient.lift _ (Paths.lift <| Quiver.Symmetrify.lift φ) <| by |
| 162 | + rintro _ _ _ _ ⟨X, Y, f⟩ |
| 163 | + -- Porting note: `simp` does not work, so manually `rewrite` |
| 164 | + erw [Paths.lift_nil, Paths.lift_cons, Quiver.Path.comp_nil, Paths.lift_toPath, |
| 165 | + Quiver.Symmetrify.lift_reverse] |
| 166 | + symm |
| 167 | + apply Groupoid.comp_inv |
| 168 | +#align category_theory.groupoid.free.lift CategoryTheory.Groupoid.Free.lift |
| 169 | + |
| 170 | +theorem lift_spec (φ : V ⥤q V') : of V ⋙q (lift φ).toPrefunctor = φ := by |
| 171 | + rw [of_eq, Prefunctor.comp_assoc, Prefunctor.comp_assoc, Functor.toPrefunctor_comp] |
| 172 | + dsimp [lift] |
| 173 | + rw [Quotient.lift_spec, Paths.lift_spec, Quiver.Symmetrify.lift_spec] |
| 174 | +#align category_theory.groupoid.free.lift_spec CategoryTheory.Groupoid.Free.lift_spec |
| 175 | + |
| 176 | +theorem lift_unique (φ : V ⥤q V') (Φ : FreeGroupoid V ⥤ V') (hΦ : of V ⋙q Φ.toPrefunctor = φ) : |
| 177 | + Φ = lift φ := by |
| 178 | + apply Quotient.lift_unique |
| 179 | + apply Paths.lift_unique |
| 180 | + fapply @Quiver.Symmetrify.lift_unique _ _ _ _ _ _ _ _ _ |
| 181 | + · rw [← Functor.toPrefunctor_comp] |
| 182 | + exact hΦ |
| 183 | + · rintro X Y f |
| 184 | + simp only [← Functor.toPrefunctor_comp, Prefunctor.comp_map, Paths.of_map, inv_eq_inv] |
| 185 | + change Φ.map (inv ((Quotient.functor redStep).toPrefunctor.map f.toPath)) = |
| 186 | + inv (Φ.map ((Quotient.functor redStep).toPrefunctor.map f.toPath)) |
| 187 | + have := Functor.map_inv Φ ((Quotient.functor redStep).toPrefunctor.map f.toPath) |
| 188 | + convert this <;> simp only [inv_eq_inv] |
| 189 | +#align category_theory.groupoid.free.lift_unique CategoryTheory.Groupoid.Free.lift_unique |
| 190 | + |
| 191 | +end UniversalProperty |
| 192 | + |
| 193 | +section Functoriality |
| 194 | + |
| 195 | +variable {V' : Type u'} [Quiver.{v' + 1} V'] {V'' : Type u''} [Quiver.{v'' + 1} V''] |
| 196 | + |
| 197 | +/-- The functor of free groupoid induced by a prefunctor of quivers -/ |
| 198 | +def _root_.CategoryTheory.freeGroupoidFunctor (φ : V ⥤q V') : FreeGroupoid V ⥤ FreeGroupoid V' := |
| 199 | + lift (φ ⋙q of V') |
| 200 | +#align category_theory.free_groupoid_functor CategoryTheory.freeGroupoidFunctor |
| 201 | + |
| 202 | +theorem freeGroupoidFunctor_id : |
| 203 | + freeGroupoidFunctor (Prefunctor.id V) = Functor.id (FreeGroupoid V) := by |
| 204 | + dsimp only [freeGroupoidFunctor]; symm |
| 205 | + apply lift_unique; rfl |
| 206 | +#align category_theory.groupoid.free.free_groupoid_functor_id CategoryTheory.Groupoid.Free.freeGroupoidFunctor_id |
| 207 | + |
| 208 | +theorem freeGroupoidFunctor_comp (φ : V ⥤q V') (φ' : V' ⥤q V'') : |
| 209 | + freeGroupoidFunctor (φ ⋙q φ') = freeGroupoidFunctor φ ⋙ freeGroupoidFunctor φ' := by |
| 210 | + dsimp only [freeGroupoidFunctor]; symm |
| 211 | + apply lift_unique; rfl |
| 212 | +#align category_theory.groupoid.free.free_groupoid_functor_comp CategoryTheory.Groupoid.Free.freeGroupoidFunctor_comp |
| 213 | + |
| 214 | +end Functoriality |
| 215 | + |
| 216 | +end Free |
| 217 | + |
| 218 | +end Groupoid |
| 219 | + |
| 220 | +end CategoryTheory |
0 commit comments