Skip to content

Commit dccac13

Browse files
committed
feat(Algebra/Category/Ring/Colimits): category of (possibly non-commutative ring) has colimits (#14413)
We already have that category of commutative rings has colimits, the same construction works for category of rings.
1 parent bce175d commit dccac13

File tree

1 file changed

+280
-0
lines changed

1 file changed

+280
-0
lines changed

Mathlib/Algebra/Category/Ring/Colimits.lean

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,286 @@ open CategoryTheory
2424

2525
open CategoryTheory.Limits
2626

27+
28+
namespace RingCat.Colimits
29+
30+
/-!
31+
We build the colimit of a diagram in `RingCat` by constructing the
32+
free ring on the disjoint union of all the rings in the diagram,
33+
then taking the quotient by the ring laws within each ring,
34+
and the identifications given by the morphisms in the diagram.
35+
-/
36+
37+
38+
variable {J : Type v} [SmallCategory J] (F : J ⥤ RingCat.{v})
39+
40+
/-- An inductive type representing all ring expressions (without Relations)
41+
on a collection of types indexed by the objects of `J`.
42+
-/
43+
inductive Prequotient -- There's always `of`
44+
| of : ∀ (j : J) (_ : F.obj j), Prequotient -- Then one generator for each operation
45+
| zero : Prequotient
46+
| one : Prequotient
47+
| neg : Prequotient → Prequotient
48+
| add : Prequotient → Prequotient → Prequotient
49+
| mul : Prequotient → Prequotient → Prequotient
50+
set_option linter.uppercaseLean3 false
51+
52+
instance : Inhabited (Prequotient F) :=
53+
⟨Prequotient.zero⟩
54+
55+
open Prequotient
56+
57+
/-- The Relation on `Prequotient` saying when two expressions are equal
58+
because of the ring laws, or
59+
because one element is mapped to another by a morphism in the diagram.
60+
-/
61+
inductive Relation : Prequotient F → Prequotient F → Prop -- Make it an equivalence Relation:
62+
| refl : ∀ x, Relation x x
63+
| symm : ∀ (x y) (_ : Relation x y), Relation y x
64+
| trans : ∀ (x y z) (_ : Relation x y) (_ : Relation y z), Relation x z
65+
-- There's always a `map` Relation
66+
| map : ∀ (j j' : J) (f : j ⟶ j') (x : F.obj j),
67+
Relation (Prequotient.of j' (F.map f x))
68+
(Prequotient.of j x)
69+
-- Then one Relation per operation, describing the interaction with `of`
70+
| zero : ∀ j, Relation (Prequotient.of j 0) zero
71+
| one : ∀ j, Relation (Prequotient.of j 1) one
72+
| neg : ∀ (j) (x : F.obj j), Relation (Prequotient.of j (-x)) (neg (Prequotient.of j x))
73+
| add : ∀ (j) (x y : F.obj j), Relation (Prequotient.of j (x + y))
74+
(add (Prequotient.of j x) (Prequotient.of j y))
75+
| mul : ∀ (j) (x y : F.obj j),
76+
Relation (Prequotient.of j (x * y))
77+
(mul (Prequotient.of j x) (Prequotient.of j y))
78+
-- Then one Relation per argument of each operation
79+
| neg_1 : ∀ (x x') (_ : Relation x x'), Relation (neg x) (neg x')
80+
| add_1 : ∀ (x x' y) (_ : Relation x x'), Relation (add x y) (add x' y)
81+
| add_2 : ∀ (x y y') (_ : Relation y y'), Relation (add x y) (add x y')
82+
| mul_1 : ∀ (x x' y) (_ : Relation x x'), Relation (mul x y) (mul x' y)
83+
| mul_2 : ∀ (x y y') (_ : Relation y y'), Relation (mul x y) (mul x y')
84+
-- And one Relation per axiom
85+
| zero_add : ∀ x, Relation (add zero x) x
86+
| add_zero : ∀ x, Relation (add x zero) x
87+
| one_mul : ∀ x, Relation (mul one x) x
88+
| mul_one : ∀ x, Relation (mul x one) x
89+
| add_left_neg : ∀ x, Relation (add (neg x) x) zero
90+
| add_comm : ∀ x y, Relation (add x y) (add y x)
91+
| add_assoc : ∀ x y z, Relation (add (add x y) z) (add x (add y z))
92+
| mul_assoc : ∀ x y z, Relation (mul (mul x y) z) (mul x (mul y z))
93+
| left_distrib : ∀ x y z, Relation (mul x (add y z)) (add (mul x y) (mul x z))
94+
| right_distrib : ∀ x y z, Relation (mul (add x y) z) (add (mul x z) (mul y z))
95+
| zero_mul : ∀ x, Relation (mul zero x) zero
96+
| mul_zero : ∀ x, Relation (mul x zero) zero
97+
98+
/-- The setoid corresponding to commutative expressions modulo monoid Relations and identifications.
99+
-/
100+
def colimitSetoid : Setoid (Prequotient F) where
101+
r := Relation F
102+
iseqv := ⟨Relation.refl, Relation.symm _ _, Relation.trans _ _ _⟩
103+
104+
attribute [instance] colimitSetoid
105+
106+
/-- The underlying type of the colimit of a diagram in `CommRingCat`.
107+
-/
108+
def ColimitType : Type v :=
109+
Quotient (colimitSetoid F)
110+
111+
instance ColimitType.instZero : Zero (ColimitType F) where zero := Quotient.mk _ zero
112+
113+
instance ColimitType.instAdd : Add (ColimitType F) where
114+
add := Quotient.map₂ add <| fun _x x' rx y _y' ry =>
115+
Setoid.trans (Relation.add_1 _ _ y rx) (Relation.add_2 x' _ _ ry)
116+
117+
instance ColimitType.instNeg : Neg (ColimitType F) where
118+
neg := Quotient.map neg Relation.neg_1
119+
120+
instance ColimitType.AddGroup : AddGroup (ColimitType F) where
121+
neg := Quotient.map neg Relation.neg_1
122+
zero_add := Quotient.ind <| fun _ => Quotient.sound <| Relation.zero_add _
123+
add_zero := Quotient.ind <| fun _ => Quotient.sound <| Relation.add_zero _
124+
add_left_neg := Quotient.ind <| fun _ => Quotient.sound <| Relation.add_left_neg _
125+
add_assoc := Quotient.ind <| fun _ => Quotient.ind₂ <| fun _ _ =>
126+
Quotient.sound <| Relation.add_assoc _ _ _
127+
nsmul := nsmulRec
128+
zsmul := zsmulRec
129+
130+
-- Porting note: failed to derive `Inhabited` instance
131+
instance InhabitedColimitType : Inhabited <| ColimitType F where
132+
default := 0
133+
134+
instance ColimitType.AddGroupWithOne : AddGroupWithOne (ColimitType F) :=
135+
{ ColimitType.AddGroup F with one := Quotient.mk _ one }
136+
137+
instance : Ring (ColimitType.{v} F) :=
138+
{ ColimitType.AddGroupWithOne F with
139+
mul := Quot.map₂ Prequotient.mul Relation.mul_2 Relation.mul_1
140+
one_mul := fun x => Quot.inductionOn x fun x => Quot.sound <| Relation.one_mul _
141+
mul_one := fun x => Quot.inductionOn x fun x => Quot.sound <| Relation.mul_one _
142+
add_comm := fun x y => Quot.induction_on₂ x y fun x y => Quot.sound <| Relation.add_comm _ _
143+
mul_assoc := fun x y z => Quot.induction_on₃ x y z fun x y z => by
144+
simp only [(· * ·)]
145+
exact Quot.sound (Relation.mul_assoc _ _ _)
146+
mul_zero := fun x => Quot.inductionOn x fun x => Quot.sound <| Relation.mul_zero _
147+
zero_mul := fun x => Quot.inductionOn x fun x => Quot.sound <| Relation.zero_mul _
148+
left_distrib := fun x y z => Quot.induction_on₃ x y z fun x y z => by
149+
simp only [(· + ·), (· * ·), Add.add]
150+
exact Quot.sound (Relation.left_distrib _ _ _)
151+
right_distrib := fun x y z => Quot.induction_on₃ x y z fun x y z => by
152+
simp only [(· + ·), (· * ·), Add.add]
153+
exact Quot.sound (Relation.right_distrib _ _ _) }
154+
155+
@[simp]
156+
theorem quot_zero : Quot.mk Setoid.r zero = (0 : ColimitType F) :=
157+
rfl
158+
159+
@[simp]
160+
theorem quot_one : Quot.mk Setoid.r one = (1 : ColimitType F) :=
161+
rfl
162+
163+
@[simp]
164+
theorem quot_neg (x : Prequotient F) :
165+
-- Porting note: Lean can't see `Quot.mk Setoid.r x` is a `ColimitType F` even with type
166+
-- annotation unless we use `by exact` to change the elaboration order.
167+
(by exact Quot.mk Setoid.r (neg x) : ColimitType F) = -(by exact Quot.mk Setoid.r x) :=
168+
rfl
169+
170+
-- Porting note: Lean can't see `Quot.mk Setoid.r x` is a `ColimitType F` even with type annotation
171+
-- unless we use `by exact` to change the elaboration order.
172+
@[simp]
173+
theorem quot_add (x y) :
174+
(by exact Quot.mk Setoid.r (add x y) : ColimitType F) =
175+
(by exact Quot.mk _ x) + (by exact Quot.mk _ y) :=
176+
rfl
177+
178+
-- Porting note: Lean can't see `Quot.mk Setoid.r x` is a `ColimitType F` even with type annotation
179+
-- unless we use `by exact` to change the elaboration order.
180+
@[simp]
181+
theorem quot_mul (x y) :
182+
(by exact Quot.mk Setoid.r (mul x y) : ColimitType F) =
183+
(by exact Quot.mk _ x) * (by exact Quot.mk _ y) :=
184+
rfl
185+
186+
/-- The bundled ring giving the colimit of a diagram. -/
187+
def colimit : RingCat :=
188+
RingCat.of (ColimitType F)
189+
190+
/-- The function from a given ring in the diagram to the colimit ring. -/
191+
def coconeFun (j : J) (x : F.obj j) : ColimitType F :=
192+
Quot.mk _ (Prequotient.of j x)
193+
194+
/-- The ring homomorphism from a given ring in the diagram to the colimit
195+
ring. -/
196+
def coconeMorphism (j : J) : F.obj j ⟶ colimit F where
197+
toFun := coconeFun F j
198+
map_one' := by apply Quot.sound; apply Relation.one
199+
map_mul' := by intros; apply Quot.sound; apply Relation.mul
200+
map_zero' := by apply Quot.sound; apply Relation.zero
201+
map_add' := by intros; apply Quot.sound; apply Relation.add
202+
203+
@[simp]
204+
theorem cocone_naturality {j j' : J} (f : j ⟶ j') :
205+
F.map f ≫ coconeMorphism F j' = coconeMorphism F j := by
206+
ext
207+
apply Quot.sound
208+
apply Relation.map
209+
210+
@[simp]
211+
theorem cocone_naturality_components (j j' : J) (f : j ⟶ j') (x : F.obj j) :
212+
(coconeMorphism F j') (F.map f x) = (coconeMorphism F j) x := by
213+
rw [← cocone_naturality F f, comp_apply]
214+
215+
/-- The cocone over the proposed colimit ring. -/
216+
def colimitCocone : Cocone F where
217+
pt := colimit F
218+
ι := { app := coconeMorphism F }
219+
220+
/-- The function from the free ring on the diagram to the cone point of any other
221+
cocone. -/
222+
@[simp]
223+
def descFunLift (s : Cocone F) : Prequotient F → s.pt
224+
| Prequotient.of j x => (s.ι.app j) x
225+
| zero => 0
226+
| one => 1
227+
| neg x => -descFunLift s x
228+
| add x y => descFunLift s x + descFunLift s y
229+
| mul x y => descFunLift s x * descFunLift s y
230+
231+
/-- The function from the colimit ring to the cone point of any other cocone. -/
232+
def descFun (s : Cocone F) : ColimitType F → s.pt := by
233+
fapply Quot.lift
234+
· exact descFunLift F s
235+
· intro x y r
236+
induction r with
237+
| refl => rfl
238+
| symm x y _ ih => exact ih.symm
239+
| trans x y z _ _ ih1 ih2 => exact ih1.trans ih2
240+
| map j j' f x => exact RingHom.congr_fun (s.ι.naturality f) x
241+
| zero j => simp
242+
| one j => simp
243+
| neg j x => simp
244+
| add j x y => simp
245+
| mul j x y => simp
246+
| neg_1 x x' r ih => dsimp; rw [ih]
247+
| add_1 x x' y r ih => dsimp; rw [ih]
248+
| add_2 x y y' r ih => dsimp; rw [ih]
249+
| mul_1 x x' y r ih => dsimp; rw [ih]
250+
| mul_2 x y y' r ih => dsimp; rw [ih]
251+
| zero_add x => dsimp; rw [zero_add]
252+
| add_zero x => dsimp; rw [add_zero]
253+
| one_mul x => dsimp; rw [one_mul]
254+
| mul_one x => dsimp; rw [mul_one]
255+
| add_left_neg x => dsimp; rw [add_left_neg]
256+
| add_comm x y => dsimp; rw [add_comm]
257+
| add_assoc x y z => dsimp; rw [add_assoc]
258+
| mul_assoc x y z => dsimp; rw [mul_assoc]
259+
| left_distrib x y z => dsimp; rw [mul_add]
260+
| right_distrib x y z => dsimp; rw [add_mul]
261+
| zero_mul x => dsimp; rw [zero_mul]
262+
| mul_zero x => dsimp; rw [mul_zero]
263+
264+
/-- The ring homomorphism from the colimit ring to the cone point of any other
265+
cocone. -/
266+
def descMorphism (s : Cocone F) : colimit F ⟶ s.pt where
267+
toFun := descFun F s
268+
map_one' := rfl
269+
map_zero' := rfl
270+
map_add' x y := by
271+
refine Quot.induction_on₂ x y fun a b => ?_
272+
dsimp [descFun]
273+
rw [← quot_add]
274+
rfl
275+
map_mul' x y := by exact Quot.induction_on₂ x y fun a b => rfl
276+
277+
/-- Evidence that the proposed colimit is the colimit. -/
278+
def colimitIsColimit : IsColimit (colimitCocone F) where
279+
desc s := descMorphism F s
280+
uniq s m w := RingHom.ext fun x => by
281+
change (colimitCocone F).pt →+* s.pt at m
282+
refine Quot.inductionOn x ?_
283+
intro x
284+
induction x with
285+
| zero => erw [quot_zero, map_zero (f := m), (descMorphism F s).map_zero]
286+
| one => erw [quot_one, map_one (f := m), (descMorphism F s).map_one]
287+
-- extra rfl with leanprover/lean4#2644
288+
| neg x ih => erw [quot_neg, map_neg (f := m), (descMorphism F s).map_neg, ih]; rfl
289+
| of j x =>
290+
exact congr_fun (congr_arg (fun f : F.obj j ⟶ s.pt => (f : F.obj j → s.pt)) (w j)) x
291+
| add x y ih_x ih_y =>
292+
-- extra rfl with leanprover/lean4#2644
293+
erw [quot_add, map_add (f := m), (descMorphism F s).map_add, ih_x, ih_y]; rfl
294+
| mul x y ih_x ih_y =>
295+
-- extra rfl with leanprover/lean4#2644
296+
erw [quot_mul, map_mul (f := m), (descMorphism F s).map_mul, ih_x, ih_y]; rfl
297+
298+
instance hasColimits_ringCat : HasColimits RingCat where
299+
has_colimits_of_shape _ _ :=
300+
{ has_colimit := fun F =>
301+
HasColimit.mk
302+
{ cocone := colimitCocone F
303+
isColimit := colimitIsColimit F } }
304+
305+
end RingCat.Colimits
306+
27307
-- [ROBOT VOICE]:
28308
-- You should pretend for now that this file was automatically generated.
29309
-- It follows the same template as colimits in Mon.

0 commit comments

Comments
 (0)