Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 7ec4fcc

Browse files
committed
feat(category_theory): connected components of a category (#5425)
1 parent a1ebf54 commit 7ec4fcc

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/-
2+
Copyright (c) 2020 Bhavik Mehta. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Bhavik Mehta
5+
-/
6+
import data.list.chain
7+
import category_theory.punit
8+
import category_theory.is_connected
9+
import category_theory.sigma.basic
10+
import category_theory.full_subcategory
11+
12+
/-!
13+
# Connected components of a category
14+
15+
Defines a type `connected_components J` indexing the connected components of a category, and the
16+
full subcategories giving each connected component: `component j : Type u₁`.
17+
We show that each `component j` is in fact connected.
18+
19+
We show every category can be expressed as a disjoint union of its connected components, in
20+
particular `decomposed J` is the category (definitionally) given by the sigma-type of the connected
21+
components of `J`, and it is shown that this is equivalent to `J`.
22+
-/
23+
24+
universes v₁ v₂ v₃ u₁ u₂
25+
26+
noncomputable theory
27+
28+
open category_theory.category
29+
30+
namespace category_theory
31+
32+
attribute [instance, priority 100] is_connected.is_nonempty
33+
34+
variables {J : Type u₁} [category.{v₁} J]
35+
variables {C : Type u₂} [category.{u₁} C]
36+
37+
/-- This type indexes the connected components of the category `J`. -/
38+
def connected_components (J : Type u₁) [category.{v₁} J] : Type u₁ := quotient (zigzag.setoid J)
39+
40+
instance [inhabited J] : inhabited (connected_components J) := ⟨quotient.mk' (default J)⟩
41+
42+
/-- Given an index for a connected component, produce the actual component as a full subcategory. -/
43+
@[derive category]
44+
def component (j : connected_components J) : Type u₁ := {k : J // quotient.mk' k = j}
45+
46+
/-- The inclusion functor from a connected component to the whole category. -/
47+
@[derive [full, faithful], simps {rhs_md := semireducible}]
48+
def component.ι (j) : component j ⥤ J :=
49+
full_subcategory_inclusion _
50+
51+
/-- Each connected component of the category is nonempty. -/
52+
instance (j : connected_components J) : nonempty (component j) :=
53+
begin
54+
apply quotient.induction_on' j,
55+
intro k,
56+
refine ⟨⟨k, rfl⟩⟩,
57+
end
58+
59+
instance (j : connected_components J) : inhabited (component j) := classical.inhabited_of_nonempty'
60+
61+
/-- Each connected component of the category is connected. -/
62+
instance (j : connected_components J) : is_connected (component j) :=
63+
begin
64+
-- Show it's connected by constructing a zigzag (in `component j`) between any two objects
65+
apply is_connected_of_zigzag,
66+
rintro ⟨j₁, hj₁⟩ ⟨j₂, rfl⟩,
67+
-- We know that the underlying objects j₁ j₂ have some zigzag between them in `J`
68+
have h₁₂ : zigzag j₁ j₂ := quotient.exact' hj₁,
69+
-- Get an explicit zigzag as a list
70+
rcases list.exists_chain_of_relation_refl_trans_gen h₁₂ with ⟨l, hl₁, hl₂⟩,
71+
-- Everything which has a zigzag to j₂ can be lifted to the same component as `j₂`.
72+
let f : Π x, zigzag x j₂ → component (quotient.mk' j₂) := λ x h, ⟨x, quotient.sound' h⟩,
73+
-- Everything in our chosen zigzag from `j₁` to `j₂` has a zigzag to `j₂`.
74+
have hf : ∀ (a : J), a ∈ l → zigzag a j₂,
75+
{ intros i hi,
76+
apply list.chain.induction (λ t, zigzag t j₂) _ hl₁ hl₂ _ _ _ (or.inr hi),
77+
{ intros j k,
78+
apply relation.refl_trans_gen.head },
79+
{ apply relation.refl_trans_gen.refl } },
80+
-- Now lift the zigzag from `j₁` to `j₂` in `J` to the same thing in `component j`.
81+
refine ⟨l.pmap f hf, _, _⟩,
82+
{ refine @@list.chain_pmap_of_chain _ _ _ f (λ x y _ _ h, _) hl₁ h₁₂ _,
83+
exact zag_of_zag_obj (component.ι _) h },
84+
{ erw list.last_pmap _ f (j₁ :: l) (by simpa [h₁₂] using hf) (list.cons_ne_nil _ _),
85+
exact subtype.ext hl₂ },
86+
end
87+
88+
/--
89+
The disjoint union of `J`s connected components, written explicitly as a sigma-type with the
90+
category structure.
91+
This category is equivalent to `J`.
92+
-/
93+
abbreviation decomposed (J : Type u₁) [category.{v₁} J] :=
94+
Σ (j : connected_components J), component j
95+
96+
/--
97+
The inclusion of each component into the decomposed category. This is just `sigma.incl` but having
98+
this abbreviation helps guide typeclass search to get the right category instance on `decomposed J`.
99+
-/
100+
-- This name may cause clashes further down the road, and so might need to be changed.
101+
abbreviation inclusion (j : connected_components J) : component j ⥤ decomposed J :=
102+
sigma.incl _
103+
104+
/-- The forward direction of the equivalence between the decomposed category and the original. -/
105+
@[simps {rhs_md := semireducible}]
106+
def decomposed_to (J : Type u₁) [category.{v₁} J] : decomposed J ⥤ J :=
107+
sigma.desc component.ι
108+
109+
@[simp]
110+
lemma inclusion_comp_decomposed_to (j : connected_components J) :
111+
inclusion j ⋙ decomposed_to J = component.ι j :=
112+
rfl
113+
114+
instance : full (decomposed_to J) :=
115+
{ preimage :=
116+
begin
117+
rintro ⟨j', X, hX⟩ ⟨k', Y, hY⟩ f,
118+
dsimp at f,
119+
have : j' = k',
120+
rw [← hX, ← hY, quotient.eq'],
121+
exact relation.refl_trans_gen.single (or.inl ⟨f⟩),
122+
subst this,
123+
refine sigma.sigma_hom.mk f,
124+
end,
125+
witness' :=
126+
begin
127+
rintro ⟨j', X, hX⟩ ⟨_, Y, rfl⟩ f,
128+
have : quotient.mk' Y = j',
129+
{ rw [← hX, quotient.eq'],
130+
exact relation.refl_trans_gen.single (or.inr ⟨f⟩) },
131+
subst this,
132+
refl,
133+
end }
134+
135+
instance : faithful (decomposed_to J) :=
136+
{ map_injective' :=
137+
begin
138+
rintro ⟨_, j, rfl⟩ ⟨_, k, hY⟩ ⟨_, _, _, f⟩ ⟨_, _, _, g⟩ e,
139+
change f = g at e,
140+
subst e,
141+
end }
142+
143+
instance : ess_surj (decomposed_to J) :=
144+
{ mem_ess_image := λ j, ⟨⟨_, j, rfl⟩, ⟨iso.refl _⟩⟩ }
145+
146+
instance : is_equivalence (decomposed_to J) :=
147+
equivalence.equivalence_of_fully_faithfully_ess_surj _
148+
149+
/-- This gives that any category is equivalent to a disjoint union of connected categories. -/
150+
@[simps functor {rhs_md := semireducible}]
151+
def decomposed_equiv : decomposed J ≌ J :=
152+
(decomposed_to J).as_equivalence
153+
154+
end category_theory

0 commit comments

Comments
 (0)