|
| 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