Timings for ClassifyingSpace.v
Require Import Basics Types.
Require Import Pointed WildCat.
Require Import Cubical.DPath Cubical.PathSquare Cubical.DPathSquare.
Require Import Algebra.AbGroups.
Require Import Homotopy.HSpace.Core.
Require Import TruncType.
Require Import Truncations.Core Truncations.Connectedness.
Require Import Homotopy.HomotopyGroup.
Require Import Homotopy.WhiteheadsPrinciple.
Local Open Scope pointed_scope.
Local Open Scope mc_mult_scope.
Local Open Scope path_scope.
(** * Classifying spaces of groups *)
(** We define the classifying space of a group to be the following HIT:
<<
HIT ClassifyingSpace (G : Group) : 1-Type
| bbase : ClassifyingSpace
| bloop : X -> bbase = bbase
| bloop_pp : forall x y, bloop (x * y) = bloop x @ bloop y.
>>
We implement this is a private inductive type. *)
Module Export ClassifyingSpace.
Section ClassifyingSpace.
Private Inductive ClassifyingSpace (G : Group) :=
| bbase : ClassifyingSpace G.
Axiom bloop : G -> bbase G = bbase G.
Global Arguments bbase {_}.
Axiom bloop_pp : forall x y, bloop (x * y) = bloop x @ bloop y.
#[export] Instance istrunc_ClassifyingSpace
: IsTrunc 1 (ClassifyingSpace G).
Arguments bloop {G} _%_mc_mult_scope.
(** Now we can state the expected dependent elimination principle, and derive other versions of the elimination principle from it. *)
Section ClassifyingSpace_ind.
Local Open Scope dpath_scope.
(** Note that since our classifying space is 1-truncated, we can only eliminate into 1-truncated type families. *)
Definition ClassifyingSpace_ind
(P : ClassifyingSpace G -> Type)
`{forall b, IsTrunc 1 (P b)}
(bbase' : P bbase)
(bloop' : forall x, DPath P (bloop x) bbase' bbase')
(bloop_pp' : forall x y, DPathSquare P (sq_G1 (bloop_pp x y))
(bloop' (x * y)) ((bloop' x) @Dp (bloop' y)) 1 1)
(b : ClassifyingSpace G)
: P b
:= match b with
bbase => (fun _ _ => bbase')
end bloop' bloop_pp'.
(** Here we state the computation rule for [ClassifyingSpace_ind] over [bloop] as an axiom. We don't need one for [bloop_pp] since we have a 1-type. We leave this as admitted since the computation rule is an axiom. **)
Definition ClassifyingSpace_ind_beta_bloop
(P : ClassifyingSpace G -> Type)
`{forall b, IsTrunc 1 (P b)}
(bbase' : P bbase) (bloop' : forall x, DPath P (bloop x) bbase' bbase')
(bloop_pp' : forall x y, DPathSquare P (sq_G1 (bloop_pp x y))
(bloop' (x * y)) ((bloop' x) @Dp (bloop' y)) 1 1)
(x : G)
: apD (ClassifyingSpace_ind P bbase' bloop' bloop_pp') (bloop x) = bloop' x.
End ClassifyingSpace_ind.
(** The non-dependent eliminator *)
Definition ClassifyingSpace_rec
(P : Type) `{IsTrunc 1 P} (bbase' : P) (bloop' : G -> bbase' = bbase')
(bloop_pp' : forall x y : G, bloop' (x * y) = bloop' x @ bloop' y)
: ClassifyingSpace G -> P.
srefine (ClassifyingSpace_ind (fun _ => P) bbase' _ _).
1: intro x; apply dp_const, bloop', x.
2: refine (_ @ ap _ (dp_const_pp _ _)).
1,2: symmetry; apply eissect.
(** Computation rule for non-dependent eliminator *)
Definition ClassifyingSpace_rec_beta_bloop
(P : Type) `{IsTrunc 1 P} (bbase' : P) (bloop' : G -> bbase' = bbase')
(bloop_pp' : forall x y : G, bloop' (x * y) = bloop' x @ bloop' y) (x : G)
: ap (ClassifyingSpace_rec P bbase' bloop' bloop_pp') (bloop x) = bloop' x.
lhs_V napply dp_apD_const'.
napply ClassifyingSpace_ind_beta_bloop.
(** Sometimes we want to induct into a set which means we can ignore the bloop_pp arguments. Since this is a routine argument, we turn it into a special case of our induction principle. *)
Definition ClassifyingSpace_ind_hset
(P : ClassifyingSpace G -> Type)
`{forall b, IsTrunc 0 (P b)}
(bbase' : P bbase) (bloop' : forall x, DPath P (bloop x) bbase' bbase')
: forall b, P b.
refine (ClassifyingSpace_ind P bbase' bloop' _).
Definition ClassifyingSpace_rec_hset
(P : Type) `{IsTrunc 0 P} (bbase' : P) (bloop' : G -> bbase' = bbase')
: ClassifyingSpace G -> P.
srapply (ClassifyingSpace_rec P bbase' bloop' _).
intros; apply path_ishprop.
(** Similarly, when eliminating into an hprop, we only have to handle the basepoint. *)
Definition ClassifyingSpace_ind_hprop (P : ClassifyingSpace G -> Type)
`{forall b, IsTrunc (-1) (P b)} (bbase' : P bbase)
: forall b, P b.
refine (ClassifyingSpace_ind_hset P bbase' _).
intros; rapply dp_ishprop.
(** The classifying space is 0-connected. *)
Instance isconnected_classifyingspace {G : Group}
: IsConnected 0 (ClassifyingSpace G).
apply (Build_Contr _ (tr bbase)).
srapply ClassifyingSpace_ind_hprop; reflexivity.
(** The classifying space of a group is pointed. *)
Instance ispointed_classifyingspace (G : Group)
: IsPointed (ClassifyingSpace G)
:= bbase.
Definition pClassifyingSpace (G : Group) := [ClassifyingSpace G, bbase].
(** To use the [B G] notation for [pClassifyingSpace] import this module. *)
Module Import ClassifyingSpaceNotation.
Definition B G := pClassifyingSpace G.
End ClassifyingSpaceNotation.
(** [bloop] takes the unit of the group to reflexivity. *)
Definition bloop_id {G : Group} : bloop (mon_unit : G) = idpath.
apply (cancelL (bloop mon_unit)).
refine (_ @ bloop_pp _ _).
refine (_ @ ap _ (left_identity _)^).
(** [bloop] "preserves inverses" by taking inverses in [G] to inverses of paths in [BG]. *)
Definition bloop_inv {G : Group} (x : G) : bloop x^ = (bloop x)^.
refine (_ @ concat_p1 _).
refine ((bloop_pp _ _)^ @ _).
(** The underlying pointed map of [pequiv_g_loops_bg]. *)
Definition pbloop {G : Group} : G ->* loops (B G).
(** This says that [B] is left adjoint to the loop space functor from pointed 1-types to groups. *)
Definition pClassifyingSpace_rec {G : Group} (P : pType) `{IsTrunc 1 P}
(bloop' : G -> loops P)
(bloop_pp' : forall x y : G, bloop' (x * y) = bloop' x @ bloop' y)
: B G ->* P
:= Build_pMap (ClassifyingSpace_rec P (point P) bloop' bloop_pp') idpath.
(** And this is one of the standard facts about adjoint functors: [(R h') o eta = h], where [h : G -> R P], [h' : L G -> P] is the adjunct, and eta ([bloop]) is the unit. *)
Definition pClassifyingSpace_rec_beta_bloop {G : Group} (P : pType)
`{IsTrunc 1 P} (bloop' : G -> loops P)
(bloop_pp' : forall x y : G, bloop' (x * y) = bloop' x @ bloop' y)
: fmap loops (pClassifyingSpace_rec P bloop' bloop_pp') o bloop == bloop'.
refine (concat_1p _ @ concat_p1 _ @ _).
apply ClassifyingSpace_rec_beta_bloop.
(** Here we prove that [BG] is a delooping of [G], i.e. that [loops BG <~> G]. *)
Context `{Univalence} {G : Group}.
Local Definition codes : B G -> HSet.
srapply ClassifyingSpace_rec.
exact (Build_Equiv _ _ (fun t => t * x) _).
refine (_ @ path_trunctype_pp _ _).
apply ap, path_equiv, path_forall.
Local Definition encode : forall b, bbase = b -> codes b.
exact (transport codes p mon_unit).
Local Definition codes_transport
: forall x y : G, transport codes (bloop x) y = y * x.
lhs napply (transport_idmap_ap _ (bloop x)).
rhs_V rapply (transport_path_universe (.* x)).
napply (transport2 idmap).
lhs napply (ap_compose _ trunctype_type (bloop x)).
rhs_V napply ap_trunctype; apply ap.
napply ClassifyingSpace_rec_beta_bloop.
Local Definition decode : forall (b : B G), codes b -> bbase = b.
srapply ClassifyingSpace_ind_hset.
refine ((bloop_pp _ _)^ @ _).
apply ap, codes_transport.
Local Lemma decode_encode : forall b p, decode b (encode b p) = p.
#[export] Instance isequiv_bloop : IsEquiv (@bloop G).
srapply isequiv_adjointify.
refine (codes_transport _ _ @ _).
(** The defining property of BG. *)
Definition equiv_g_loops_bg : G <~> loops (B G)
:= Build_Equiv _ _ bloop _.
(** Pointed version of the defining property. *)
Definition pequiv_g_loops_bg : G <~>* loops (B G)
:= Build_pEquiv pbloop _.
Definition pequiv_loops_bg_g := pequiv_g_loops_bg^-1*%equiv.
(** We also have that the equivalence is a group isomorphism. *)
(** First we show that the loop space of a pointed 1-type is a group. *)
Definition LoopGroup (X : pType) `{IsTrunc 1 X} : Group
:= Build_Group (loops X) concat idpath inverse
(Build_IsGroup _ _ _ _
(Build_IsMonoid _ _ _
(Build_IsSemiGroup _ _ _ concat_p_pp) concat_1p concat_p1)
concat_Vp concat_pV).
Definition grp_iso_g_loopgroup_bg : GroupIsomorphism G (LoopGroup (B G)).
snapply Build_GroupIsomorphism'.
1: exact equiv_g_loops_bg.
Definition grp_iso_g_pi1_bg : GroupIsomorphism G (Pi1 (B G)).
snapply (transitive_groupisomorphism _ _ _ grp_iso_g_loopgroup_bg).
snapply Build_GroupIsomorphism'.
(* We also record this fact. *)
Definition grp_homo_loops {X Y : pType} `{IsTrunc 1 X} `{IsTrunc 1 Y}
: (X ->** Y) ->* [LoopGroup X $-> LoopGroup Y, grp_homo_const].
snapply Build_GroupHomomorphism.
apply equiv_path_grouphomomorphism.
exact (pointed_htpy fmap_loops_pconst).
(** When [G] is an abelian group, [BG] is an H-space. *)
Definition bg_mul : B G -> B G -> B G.
snapply ClassifyingSpace_rec.
snapply ClassifyingSpace_ind_hset.
refine (concat_pp_p _ _ _ @ _).
refine ((bloop_pp _ _)^ @ _ @ bloop_pp _ _).
srapply ClassifyingSpace_ind_hprop.
Definition bg_mul_symm : forall x y, bg_mul x y = bg_mul y x.
srapply ClassifyingSpace_ind_hset.
srapply ClassifyingSpace_ind_hset.
refine (ap_idmap _ @ _^).
napply ClassifyingSpace_rec_beta_bloop.
snapply ClassifyingSpace_ind_hprop.
napply ClassifyingSpace_rec_beta_bloop.
Definition bg_mul_left_id
: forall b : B G, bg_mul bbase b = b.
Definition bg_mul_right_id
: forall b : B G, bg_mul b bbase = b.
#[export] Instance ishspace_bg : IsHSpace (B G)
:= Build_IsHSpace _
bg_mul
bg_mul_left_id
bg_mul_right_id.
(** Functoriality of B(-) *)
Instance is0functor_pclassifyingspace : Is0Functor B.
snapply pClassifyingSpace_rec.
refine (ap bloop (grp_homo_op f x y) @ _).
Definition bloop_natural (G H : Group) (f : G $-> H)
: fmap loops (fmap B f) o bloop == bloop o f.
napply pClassifyingSpace_rec_beta_bloop.
Lemma pbloop_natural (G K : Group) (f : G $-> K)
: fmap loops (fmap B f) o* pbloop ==* pbloop o* f.
srapply phomotopy_homotopy_hset.
Definition natequiv_g_loops_bg `{Univalence}
: NatEquiv ptype_group (loops o B).
1: intros G; exact pequiv_g_loops_bg.
snapply Build_Is1Natural.
Instance is1functor_pclassifyingspace : Is1Functor B.
snapply ClassifyingSpace_ind_hset.
rewrite 2 ClassifyingSpace_rec_beta_bloop.
(** Preservation of identity *)
snapply ClassifyingSpace_ind_hset.
rewrite ClassifyingSpace_rec_beta_bloop.
(** Preservation of composition *)
snapply ClassifyingSpace_ind_hset.
2: refine (ap_compose (ClassifyingSpace_rec _ _ _ (fun x y =>
ap bloop (grp_homo_op g x y) @ bloop_pp (g x) (g y))) _ (bloop x)
@ ap _ _ @ _).
1-3: napply ClassifyingSpace_rec_beta_bloop.
(** Interestingly, [fmap B] is an equivalence *)
Instance isequiv_fmap_pclassifyingspace `{U : Univalence} (G H : Group)
: IsEquiv (fmap B (a := G) (b := H)).
snapply isequiv_adjointify.
refine (grp_homo_compose (grp_iso_inverse _) (grp_homo_compose _ _)).
1,3: exact grp_iso_g_loopgroup_bg.
exact (grp_homo_loops f).
rapply equiv_path_pforall.
snapply ClassifyingSpace_ind_hset.
rewrite ClassifyingSpace_rec_beta_bloop.
1: symmetry; rapply decode_encode.
symmetry; apply concat_1p.
rapply equiv_path_grouphomomorphism.
rapply (moveR_equiv_V' equiv_g_loops_bg).
napply pClassifyingSpace_rec_beta_bloop.
(** Hence we have that group homomorphisms are equivalent to pointed maps between their deloopings. *)
Theorem equiv_grp_homo_pmap_bg `{U : Univalence} (G H : Group)
: (G $-> H) <~> (B G $-> B H).
2: apply isequiv_fmap_pclassifyingspace.
Instance is1natural_grp_homo_pmap_bg_r {U : Univalence} (G : Group)
: Is1Natural (opyon G) (opyon (B G) o B) (equiv_grp_homo_pmap_bg G).
snapply Build_Is1Natural.
rapply (fmap_comp B h f).
Theorem natequiv_grp_homo_pmap_bg `{U : Univalence} (G : Group)
: NatEquiv (opyon G) (opyon (B G) o B).
(** [B(Pi 1 X) <~>* X] for a 0-connected 1-truncated [X]. *)
Theorem pequiv_pclassifyingspace_pi1 `{Univalence}
(X : pType) `{IsConnected 0 X} `{IsTrunc 1 X}
: B (Pi1 X) <~>* X.
(** The pointed map [f] is the adjunct to the inverse of the natural map [loops X -> Pi1 X]. We define it first, to make the later goals easier to read. *)
transparent assert (f : (B (Pi1 X) ->* X)).
snapply pClassifyingSpace_rec.
1: exact (equiv_tr 0 _)^-1%equiv.
snapply (Build_pEquiv f).
(** [f] is an equivalence since [loops_functor f o bloop == tr^-1], and the other two maps are equivalences. *)
apply isequiv_is0connected_isequiv_loops.
snapply (cancelR_isequiv bloop).
rapply isequiv_homotopic'; symmetry.
napply pClassifyingSpace_rec_beta_bloop.
Lemma natequiv_bg_pi1_adjoint `{Univalence} (X : pType) `{IsConnected 0 X}
: NatEquiv (opyon (Pi1 X)) (opyon X o B).
nrefine (natequiv_compose (G := opyon (Pi1 (pTr 1 X))) _ _).
2: exact (natequiv_opyon_equiv (A:=Group) (grp_iso_inverse (grp_iso_pi_Tr 0 X))).
refine (natequiv_compose _ (natequiv_grp_homo_pmap_bg _)).
refine (natequiv_compose (G := opyon (pTr 1 X) o B) _ _); revgoals.
refine (natequiv_prewhisker _ _).
refine (natequiv_opyon_equiv _^-1$).
rapply pequiv_pclassifyingspace_pi1.
1: intro; exact pequiv_ptr_rec.
exact (is1natural_prewhisker (G:=opyon X) B (opyoneda _ _ _)).
(** The classifying space functor and the fundamental group functor form an adjunction ([pType] needs to be restricted to the subcategory of 0-connected pointed types). Note that the full adjunction should also be natural in [X], but this was not needed yet. *)
Theorem equiv_bg_pi1_adjoint `{Univalence} (X : pType)
`{IsConnected 0 X} (G : Group)
: (Pi 1 X $-> G) <~> (X $-> B G).
rapply natequiv_bg_pi1_adjoint.
Lemma is1natural_equiv_bg_pi1_adjoint_r `{Univalence}
(X : pType) `{IsConnected 0 X}
: Is1Natural (opyon (Pi1 X)) (opyon X o B)
(equiv_bg_pi1_adjoint X).
rapply (is1natural_natequiv (natequiv_bg_pi1_adjoint X)).
(** Why so slow? Fixed by making this opaque. *)
Opaque equiv_bg_pi1_adjoint.
Transparent equiv_bg_pi1_adjoint.