/
Simple.lean
268 lines (212 loc) · 10.3 KB
/
Simple.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/-
Copyright (c) 2020 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel, Scott Morrison
-/
import Mathlib.CategoryTheory.Limits.Shapes.ZeroMorphisms
import Mathlib.CategoryTheory.Limits.Shapes.Kernels
import Mathlib.CategoryTheory.Abelian.Basic
import Mathlib.CategoryTheory.Subobject.Lattice
import Mathlib.Order.Atoms
#align_import category_theory.simple from "leanprover-community/mathlib"@"4ed0bcaef698011b0692b93a042a2282f490f6b6"
/-!
# Simple objects
We define simple objects in any category with zero morphisms.
A simple object is an object `Y` such that any monomorphism `f : X ⟶ Y`
is either an isomorphism or zero (but not both).
This is formalized as a `Prop` valued typeclass `Simple X`.
In some contexts, especially representation theory, simple objects are called "irreducibles".
If a morphism `f` out of a simple object is nonzero and has a kernel, then that kernel is zero.
(We state this as `kernel.ι f = 0`, but should add `kernel f ≅ 0`.)
When the category is abelian, being simple is the same as being cosimple (although we do not
state a separate typeclass for this).
As a consequence, any nonzero epimorphism out of a simple object is an isomorphism,
and any nonzero morphism into a simple object has trivial cokernel.
We show that any simple object is indecomposable.
-/
noncomputable section
open CategoryTheory.Limits
namespace CategoryTheory
universe v u
variable {C : Type u} [Category.{v} C]
section
variable [HasZeroMorphisms C]
/-- An object is simple if monomorphisms into it are (exclusively) either isomorphisms or zero. -/
class Simple (X : C) : Prop where
mono_isIso_iff_nonzero : ∀ {Y : C} (f : Y ⟶ X) [Mono f], IsIso f ↔ f ≠ 0
#align category_theory.simple CategoryTheory.Simple
/-- A nonzero monomorphism to a simple object is an isomorphism. -/
theorem isIso_of_mono_of_nonzero {X Y : C} [Simple Y] {f : X ⟶ Y} [Mono f] (w : f ≠ 0) : IsIso f :=
(Simple.mono_isIso_iff_nonzero f).mpr w
#align category_theory.is_iso_of_mono_of_nonzero CategoryTheory.isIso_of_mono_of_nonzero
theorem Simple.of_iso {X Y : C} [Simple Y] (i : X ≅ Y) : Simple X :=
{ mono_isIso_iff_nonzero := fun f m => by
haveI : Mono (f ≫ i.hom) := mono_comp _ _
constructor
· intro h w
have j : IsIso (f ≫ i.hom) := by infer_instance
rw [Simple.mono_isIso_iff_nonzero] at j
subst w
simp at j
· intro h
have j : IsIso (f ≫ i.hom) := by
apply isIso_of_mono_of_nonzero
intro w
apply h
simpa using (cancel_mono i.inv).2 w
rw [← Category.comp_id f, ← i.hom_inv_id, ← Category.assoc]
infer_instance }
#align category_theory.simple.of_iso CategoryTheory.Simple.of_iso
theorem Simple.iff_of_iso {X Y : C} (i : X ≅ Y) : Simple X ↔ Simple Y :=
⟨fun _ => Simple.of_iso i.symm, fun _ => Simple.of_iso i⟩
#align category_theory.simple.iff_of_iso CategoryTheory.Simple.iff_of_iso
theorem kernel_zero_of_nonzero_from_simple {X Y : C} [Simple X] {f : X ⟶ Y} [HasKernel f]
(w : f ≠ 0) : kernel.ι f = 0 := by
classical
by_contra h
haveI := isIso_of_mono_of_nonzero h
exact w (eq_zero_of_epi_kernel f)
#align category_theory.kernel_zero_of_nonzero_from_simple CategoryTheory.kernel_zero_of_nonzero_from_simple
-- See also `mono_of_nonzero_from_simple`, which requires `Preadditive C`.
/-- A nonzero morphism `f` to a simple object is an epimorphism
(assuming `f` has an image, and `C` has equalizers).
-/
theorem epi_of_nonzero_to_simple [HasEqualizers C] {X Y : C} [Simple Y] {f : X ⟶ Y} [HasImage f]
(w : f ≠ 0) : Epi f := by
rw [← image.fac f]
haveI : IsIso (image.ι f) := isIso_of_mono_of_nonzero fun h => w (eq_zero_of_image_eq_zero h)
apply epi_comp
#align category_theory.epi_of_nonzero_to_simple CategoryTheory.epi_of_nonzero_to_simple
theorem mono_to_simple_zero_of_not_iso {X Y : C} [Simple Y] {f : X ⟶ Y} [Mono f]
(w : IsIso f → False) : f = 0 := by
classical
by_contra h
exact w (isIso_of_mono_of_nonzero h)
#align category_theory.mono_to_simple_zero_of_not_iso CategoryTheory.mono_to_simple_zero_of_not_iso
theorem id_nonzero (X : C) [Simple.{v} X] : 𝟙 X ≠ 0 :=
(Simple.mono_isIso_iff_nonzero (𝟙 X)).mp (by infer_instance)
#align category_theory.id_nonzero CategoryTheory.id_nonzero
instance (X : C) [Simple.{v} X] : Nontrivial (End X) :=
nontrivial_of_ne 1 _ (id_nonzero X)
section
theorem Simple.not_isZero (X : C) [Simple X] : ¬IsZero X := by
simpa [Limits.IsZero.iff_id_eq_zero] using id_nonzero X
#align category_theory.simple.not_is_zero CategoryTheory.Simple.not_isZero
variable [HasZeroObject C]
open ZeroObject
variable (C)
/-- We don't want the definition of 'simple' to include the zero object, so we check that here. -/
theorem zero_not_simple [Simple (0 : C)] : False :=
(Simple.mono_isIso_iff_nonzero (0 : (0 : C) ⟶ (0 : C))).mp ⟨⟨0, by aesop_cat⟩⟩ rfl
#align category_theory.zero_not_simple CategoryTheory.zero_not_simple
end
end
-- We next make the dual arguments, but for this we must be in an abelian category.
section Abelian
variable [Abelian C]
/-- In an abelian category, an object satisfying the dual of the definition of a simple object is
simple. -/
theorem simple_of_cosimple (X : C) (h : ∀ {Z : C} (f : X ⟶ Z) [Epi f], IsIso f ↔ f ≠ 0) :
Simple X :=
⟨fun {Y} f I => by
classical
fconstructor
· intros
have hx := cokernel.π_of_epi f
by_contra h
subst h
exact (h _).mp (cokernel.π_of_zero _ _) hx
· intro hf
suffices Epi f by exact isIso_of_mono_of_epi _
apply Preadditive.epi_of_cokernel_zero
by_contra h'
exact cokernel_not_iso_of_nonzero hf ((h _).mpr h')⟩
#align category_theory.simple_of_cosimple CategoryTheory.simple_of_cosimple
/-- A nonzero epimorphism from a simple object is an isomorphism. -/
theorem isIso_of_epi_of_nonzero {X Y : C} [Simple X] {f : X ⟶ Y} [Epi f] (w : f ≠ 0) : IsIso f :=
-- `f ≠ 0` means that `kernel.ι f` is not an iso, and hence zero, and hence `f` is a mono.
haveI : Mono f :=
Preadditive.mono_of_kernel_zero (mono_to_simple_zero_of_not_iso (kernel_not_iso_of_nonzero w))
isIso_of_mono_of_epi f
#align category_theory.is_iso_of_epi_of_nonzero CategoryTheory.isIso_of_epi_of_nonzero
theorem cokernel_zero_of_nonzero_to_simple {X Y : C} [Simple Y] {f : X ⟶ Y} (w : f ≠ 0) :
cokernel.π f = 0 := by
classical
by_contra h
haveI := isIso_of_epi_of_nonzero h
exact w (eq_zero_of_mono_cokernel f)
#align category_theory.cokernel_zero_of_nonzero_to_simple CategoryTheory.cokernel_zero_of_nonzero_to_simple
theorem epi_from_simple_zero_of_not_iso {X Y : C} [Simple X] {f : X ⟶ Y} [Epi f]
(w : IsIso f → False) : f = 0 := by
classical
by_contra h
exact w (isIso_of_epi_of_nonzero h)
#align category_theory.epi_from_simple_zero_of_not_iso CategoryTheory.epi_from_simple_zero_of_not_iso
end Abelian
section Indecomposable
variable [Preadditive C] [HasBinaryBiproducts C]
-- There are another three potential variations of this lemma,
-- but as any one suffices to prove `indecomposable_of_simple` we will not give them all.
theorem Biprod.isIso_inl_iff_isZero (X Y : C) : IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ IsZero Y := by
rw [biprod.isIso_inl_iff_id_eq_fst_comp_inl, ← biprod.total, add_right_eq_self]
constructor
· intro h
replace h := h =≫ biprod.snd
simpa [← IsZero.iff_isSplitEpi_eq_zero (biprod.snd : X ⊞ Y ⟶ Y)] using h
· intro h
rw [IsZero.iff_isSplitEpi_eq_zero (biprod.snd : X ⊞ Y ⟶ Y)] at h
rw [h, zero_comp]
#align category_theory.biprod.is_iso_inl_iff_is_zero CategoryTheory.Biprod.isIso_inl_iff_isZero
/-- Any simple object in a preadditive category is indecomposable. -/
theorem indecomposable_of_simple (X : C) [Simple X] : Indecomposable X :=
⟨Simple.not_isZero X, fun Y Z i => by
refine' or_iff_not_imp_left.mpr fun h => _
rw [IsZero.iff_isSplitMono_eq_zero (biprod.inl : Y ⟶ Y ⊞ Z)] at h
change biprod.inl ≠ 0 at h
have : Simple (Y ⊞ Z) := Simple.of_iso i.symm -- Porting note: this instance is needed
rw [← Simple.mono_isIso_iff_nonzero biprod.inl] at h
rwa [Biprod.isIso_inl_iff_isZero] at h⟩
#align category_theory.indecomposable_of_simple CategoryTheory.indecomposable_of_simple
end Indecomposable
section Subobject
variable [HasZeroMorphisms C] [HasZeroObject C]
open ZeroObject
open Subobject
instance {X : C} [Simple X] : Nontrivial (Subobject X) :=
nontrivial_of_not_isZero (Simple.not_isZero X)
instance {X : C} [Simple X] : IsSimpleOrder (Subobject X) where
eq_bot_or_eq_top := by
rintro ⟨⟨⟨Y : C, ⟨⟨⟩⟩, f : Y ⟶ X⟩, m : Mono f⟩⟩
change mk f = ⊥ ∨ mk f = ⊤
by_cases h : f = 0
· exact Or.inl (mk_eq_bot_iff_zero.mpr h)
· refine' Or.inr ((isIso_iff_mk_eq_top _).mp ((Simple.mono_isIso_iff_nonzero f).mpr h))
/-- If `X` has subobject lattice `{⊥, ⊤}`, then `X` is simple. -/
theorem simple_of_isSimpleOrder_subobject (X : C) [IsSimpleOrder (Subobject X)] : Simple X := by
constructor; intros Y f hf; constructor
· intro i
rw [Subobject.isIso_iff_mk_eq_top] at i
intro w
rw [← Subobject.mk_eq_bot_iff_zero] at w
exact IsSimpleOrder.bot_ne_top (w.symm.trans i)
· intro i
rcases IsSimpleOrder.eq_bot_or_eq_top (Subobject.mk f) with (h | h)
· rw [Subobject.mk_eq_bot_iff_zero] at h
exact False.elim (i h)
· exact (Subobject.isIso_iff_mk_eq_top _).mpr h
#align category_theory.simple_of_is_simple_order_subobject CategoryTheory.simple_of_isSimpleOrder_subobject
/-- `X` is simple iff it has subobject lattice `{⊥, ⊤}`. -/
theorem simple_iff_subobject_isSimpleOrder (X : C) : Simple X ↔ IsSimpleOrder (Subobject X) :=
⟨by
intro h
infer_instance, by
intro h
exact simple_of_isSimpleOrder_subobject X⟩
#align category_theory.simple_iff_subobject_is_simple_order CategoryTheory.simple_iff_subobject_isSimpleOrder
/-- A subobject is simple iff it is an atom in the subobject lattice. -/
theorem subobject_simple_iff_isAtom {X : C} (Y : Subobject X) : Simple (Y : C) ↔ IsAtom Y :=
(simple_iff_subobject_isSimpleOrder _).trans
((OrderIso.isSimpleOrder_iff (subobjectOrderIso Y)).trans Set.isSimpleOrder_Iic_iff_isAtom)
#align category_theory.subobject_simple_iff_is_atom CategoryTheory.subobject_simple_iff_isAtom
end Subobject
end CategoryTheory