Built with Alectryon. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use ⌘ instead of Ctrl.
From HoTT Require Import Basics Types Pointed HSet.From HoTT Require Import Basics Types Pointed HSet.Require Import Modalities.Modality Modalities.Identity.Require Import Truncations.Core Truncations.SeparatedTrunc
Truncations.Connectedness.Require Import Algebra.AbGroups.AbelianGroup.Require Import Spaces.Finite.Tactics.Require Import Homotopy.SuccessorStructure Homotopy.ExactSequence.From HoTT.WildCat Require Import Core UniverseEquiv.LocalOpen Scope nat_scope.LocalOpen Scope pointed_scope.LocalOpen Scope path_scope.(** The type that the nth homotopy group will have. *)DefinitionHomotopyGroup_type (n : nat) : Type
:= match n with
| 0 => pType
| n.+1 => Group
end.(** Every homotopy group is, in particular, a pointed type. *)DefinitionHomotopyGroup_type_ptype (n : nat) : HomotopyGroup_type n -> pType
:= match n return HomotopyGroup_type n -> pType with
| 0 => funX => X
(* This works because [ptype_group] is already a coercion. *)
| n.+1 => funG => G
end.CoercionHomotopyGroup_type_ptype : HomotopyGroup_type >-> pType.(** We construct the wildcat structure on [HomotopyGroup_type] in the obvious way. *)Instanceisgraph_homotopygroup_type (n : nat)
: IsGraph (HomotopyGroup_type n) := ltac:(destruct n; exact _).Instanceis2graph_homotopygroup_type (n : nat)
: Is2Graph (HomotopyGroup_type n) := ltac:(destruct n; exact _).Instanceis01cat_homotopygroup_type (n : nat)
: Is01Cat (HomotopyGroup_type n) := ltac:(destruct n; exact _).Instanceis1cat_homotopygroup_type (n : nat)
: Is1Cat (HomotopyGroup_type n) := ltac:(destruct n; exact _).Instancehasequivs_homotopygroup_type (n : nat)
: HasEquivs (HomotopyGroup_type n) := ltac:(destruct n; exact _).Instanceis0functor_homotopygroup_type_ptype (n : nat)
: Is0Functor (HomotopyGroup_type_ptype n)
:= ltac:(destruct n; exact _).Instanceis1functor_homotopygroup_type_ptype (n : nat)
: Is1Functor (HomotopyGroup_type_ptype n)
:= ltac:(destruct n; exact _).(** We first define [Pi 1 X], and use this to define [Pi n X]. The reason is to make it easier for Coq to see that [Pi (n.+1) X] is definitionally equal to [Pi 1 (iterated_loops n X)] *)
apply concat_pV.Defined.(** Definition of the nth homotopy group *)
n: nat X: pType
HomotopyGroup_type n
n: nat X: pType
HomotopyGroup_type n
X: pType
HomotopyGroup_type 0
n: nat X: pType
HomotopyGroup_type n.+1
n: nat X: pType
HomotopyGroup_type n.+1
exact (Pi1 (iterated_loops n X)).Defined.(** See [pi_loops] below for an alternate unfolding. *)Definitionpi_succnX : Pi n.+1 X $<~> Pi 1 (iterated_loops n X)
:= grp_iso_id.ModulePiUtf8.Notation"'π'" := Pi.EndPiUtf8.Instanceishset_pi {n : nat} {X : pType}
: IsHSet (Pi n X)
:= ltac:(destruct n; exact _).(** When n >= 2 we have that the nth homotopy group is an abelian group. Note that we don't actually define it as an abelian group but merely show that it is one. This would cause lots of complications with the typechecker. *)
n: nat X: pType
Commutative sg_op
n: nat X: pType
Commutative sg_op
n: nat X: pType x, y: Pi n.+2 X
sg_op x y = sg_op y x
n: nat X: pType y, x: loops (iterated_loops n.+1 X)
sg_op (tr x) (tr y) = sg_op (tr y) (tr x)
n: nat X: pType y, x: loops (iterated_loops n.+1 X)
x @ y = y @ x
apply eckmann_hilton.Defined.(** For the same reason as above, we make [Pi1] a functor before making [Pi] a functor. *)
(** The conditions for [Pi1] to be a 1-functor only involve equalities of maps between groups, which reduce to equalities of maps between types. Type inference shows that [Tr 0 o loops] is a 1-functor, and so it follows that [Pi1] is a 1-functor. *)
apply Build_Is1Functor; intros;
[ by rapply (fmap2 _ (is1functor_F := is1f))
| by rapply (fmap_id _ (is1functor_F := is1f))
| by rapply (fmap_comp _ (is1functor_F := is1f)) ].Defined.Instanceis1functor_pi (n : nat) : Is1Functor (Pi n)
:= ltac:(destruct n; exact _).(** Sometimes it is convenient to regard [Pi n] as landing in pointed types. On objects, this is handled by the coercion [HomotopyGroup_type_ptype], but on morphisms it doesn't seem possible to define a coercion. So we explicitly name the composite functor. *)DefinitionpPi (n : nat) : pType -> pType := HomotopyGroup_type_ptype n o Pi n.Instanceis0functor_ppi (n : nat) : Is0Functor (pPi n) := _.Instanceis1functor_ppi (n : nat) : Is1Functor (pPi n) := _.(** [pPi] is equal to a more explicit map. These are definitional for [n = 0] and [n] a successor; it would be nice to make them definitional for generic [n]. *)Definitionppi_ptr_iterated_loops (n : nat)
: pPi n = pTr 0 o iterated_loops n
:= ltac:(destruct n; reflexivity).(** Here is the associated object-wise equivalence, which is the identity map for [0] and successors. *)Definitionpequiv_ppi_ptr_iterated_loops (n : nat) (X : pType)
: pPi n X <~>* pTr 0 (iterated_loops n X)
:= ltac:(destruct n; exact pequiv_pmap_idmap).(** These equivalences are natural. Put another way, we can compute [fmap Pi] in terms of the composite functor, up to the equivalences above. For [n = 0] or [n] a successor, we can omit the equivalences; for [n = 0], the induced maps are definitionally equal as pointed maps; for [n] a successfor the underlying unpointed maps are definitionally equal, but the pointedness proofs are not, and this is handled by [phomotopy_homotopy_hset]. *)
n: nat X, Y: pType f: X ->* Y
pequiv_ppi_ptr_iterated_loops n Y o* fmap (pPi n) f ==*
fmap (pTr 0) (fmap (iterated_loops n) f) o* pequiv_ppi_ptr_iterated_loops n X
n: nat X, Y: pType f: X ->* Y
pequiv_ppi_ptr_iterated_loops n Y o* fmap (pPi n) f ==*
fmap (pTr 0) (fmap (iterated_loops n) f) o* pequiv_ppi_ptr_iterated_loops n X
srapply phomotopy_homotopy_hset; reflexivity.Defined.(** For a successor, the equivalences above are the identity, so the previous result simplifies to a pointed homotopy between the two induced maps. *)
srapply phomotopy_homotopy_hset; reflexivity.Defined.(** [Pi n.+1] sends equivalences to group isomorphisms. *)Definitiongroupiso_pi_functor (n : nat) {XY : pType} (e : X <~>* Y)
: Pi n.+1 X $<~> Pi n.+1 Y
:= emap (Pi n.+1) e.(** The homotopy groups of a loop space are those of the space shifted. *)
n: nat X: pType
Pi n.+1 X <~>* Pi n (loops X)
n: nat X: pType
Pi n.+1 X <~>* Pi n (loops X)
X: pType
Pi 1 X <~>* Pi 0 (loops X)
n: nat X: pType
Pi n.+2 X <~>* Pi n.+1 (loops X)
n: nat X: pType
Pi n.+2 X <~>* Pi n.+1 (loops X)
n: nat X: pType
iterated_loops n.+1 X $<~> iterated_loops n (loops X)
apply unfold_iterated_loops'.Defined.(** Except in the lowest case, this can be expressed as an isomorphism of groups. *)
n: nat X: pType
Pi n.+2 X $<~> Pi n.+1 (loops X)
n: nat X: pType
Pi n.+2 X $<~> Pi n.+1 (loops X)
n: nat X: pType
[pt = pt, 1] <~>* iterated_loops n (loops X)
apply unfold_iterated_loops'.Defined.(** Naturality of [pi_loops]. *)
n: nat X, Y: pType f: X ->* Y
pi_loops n Y o* fmap (Pi n.+1) f ==* fmap (pPi n o loops) f o* pi_loops n X
n: nat X, Y: pType f: X ->* Y
pi_loops n Y o* fmap (Pi n.+1) f ==* fmap (pPi n o loops) f o* pi_loops n X
X, Y: pType f: X ->* Y x: Pi 1 X
(pi_loops 0 Y o* fmap (Pi 1) f) x =
(fmap (pPi 0 o loops) f o* pi_loops 0 X) x
n: nat X, Y: pType f: X ->* Y x: Pi n.+2 X
(pi_loops n.+1 Y o* fmap (Pi n.+2) f) x =
(fmap (pPi n.+1 o loops) f o* pi_loops n.+1 X) x
n: nat X, Y: pType f: X ->* Y x: Pi n.+2 X
(pi_loops n.+1 Y o* fmap (Pi n.+2) f) x =
(fmap (pPi n.+1 o loops) f o* pi_loops n.+1 X) x
exact (pointed_htpy (unfold_iterated_fmap_loops n.+1 f)).Defined.(** Homotopy groups preserve products. This is a direct proof, but below we give a second proof whose underlying map is the natural one. *)
n: nat X, Y: pType
pPi n (X * Y) <~>* pPi n X * pPi n Y
n: nat X, Y: pType
pPi n (X * Y) <~>* pPi n X * pPi n Y
(* First we re-express this in terms of the composite [pTr 0 o iterated_loops n]. *)
n: nat X, Y: pType
pTr 0 (iterated_loops n (X * Y)) <~>* pPi n X * pPi n Y
n: nat X, Y: pType
pTr 0 (iterated_loops n (X * Y)) <~>*
pTr 0 (iterated_loops n X) * pTr 0 (iterated_loops n Y)
(* For this composite, the proof is straightforward. *)
n: nat X, Y: pType
iterated_loops n (X * Y) <~>* ?Goal
n: nat X, Y: pType
pTr 0?Goal <~>* pTr 0 (iterated_loops n X) * pTr 0 (iterated_loops n Y)
n: nat X, Y: pType
pTr 0 (iterated_loops n X * iterated_loops n Y) <~>*
pTr 0 (iterated_loops n X) * pTr 0 (iterated_loops n Y)
n: nat X, Y: pType
Trunc 0 (iterated_loops n X * iterated_loops n Y) <~>
Trunc 0 (iterated_loops n X) * Trunc 0 (iterated_loops n Y)
n: nat X, Y: pType
?Goal (tr ispointed_prod) = ispointed_prod
n: nat X, Y: pType
Trunc 0 (iterated_loops n X * iterated_loops n Y) <~>
Trunc 0 (iterated_loops n X) * Trunc 0 (iterated_loops n Y)
exact (equiv_O_prod_cmp 0 _ _).
n: nat X, Y: pType
equiv_O_prod_cmp (Tr 0%nat) (iterated_loops n X) (iterated_loops n Y)
(tr ispointed_prod) =
ispointed_prod
reflexivity.Defined.(** The pointed map from left-to-right below, coming from functoriality, is an equivalence. *)
n: nat X, Y: pType
pPi n (X * Y) <~>* pPi n X * pPi n Y
n: nat X, Y: pType
pPi n (X * Y) <~>* pPi n X * pPi n Y
n: nat X, Y: pType
pPi n (X * Y) ->* pPi n X * pPi n Y
n: nat X, Y: pType
IsEquiv ?pointed_equiv_fun
(* This describes the natural map. *)
n: nat X, Y: pType
pPi n (X * Y) ->* pPi n X * pPi n Y
n: nat X, Y: pType
pPi n (X * Y) ->* pPi n X
n: nat X, Y: pType
pPi n (X * Y) ->* pPi n Y
n: nat X, Y: pType
pPi n (X * Y) ->* pPi n X
exact (fmap (pPi n) (@pfst X Y)).
n: nat X, Y: pType
pPi n (X * Y) ->* pPi n Y
exact (fmap (pPi n) (@psnd X Y)).(* To see that it is an equivalence, we show that it is homotopic to [pi_prod']. *)
n: nat X, Y: pType
IsEquiv
(equiv_pprod_coind (pfam_const (pPi n X)) (pfam_const (pPi n Y))
(fmap (pPi n) pfst, fmap (pPi n) psnd))
n: nat X, Y: pType
pi_prod' X Y ==
equiv_pprod_coind (pfam_const (pPi n X)) (pfam_const (pPi n Y))
(fmap (pPi n) pfst, fmap (pPi n) psnd)
n: nat X, Y: pType xy: pPi n (X * Y)
pi_prod' X Y xy =
equiv_pprod_coind (pfam_const (pPi n X)) (pfam_const (pPi n Y))
(fmap (pPi n) pfst, fmap (pPi n) psnd) xy
exact (equiv_isequiv (pi_prod X Y (n:=n.+1))).Defined.(** Homotopy groups of truncations *)(** An [n]-connected map induces an equivalence on the nth homotopy group. We first state this for [pTr 0 o iterated_loops n], since the proof works for general [n], and then we deduce the result for [pPi n] afterwards. *)
H: Univalence n: nat X, Y: pType f: X ->* Y IsConnMap0: IsConnMap (Tr n) f
H: Univalence n: nat X, Y: pType f: X ->* Y IsConnMap0: IsConnMap (Tr n) f
IsConnMap (Tr 0) (fmap (iterated_loops n) f)
H: Univalence n: nat X, Y: pType f: X ->* Y IsConnMap0: IsConnMap (Tr n) f
IsConnMap (Tr (trunc_index_inc' 0 n)) f
H: Univalence n: nat X, Y: pType f: X ->* Y IsConnMap0: IsConnMap (Tr n) f
IsConnMap (Tr (trunc_index_inc' (-2) n).+2) f
H: Univalence n: nat X, Y: pType f: X ->* Y IsConnMap0: IsConnMap (Tr n) f
IsConnMap (Tr (trunc_index_inc (-2) n).+2) f
assumption.Defined.(** The same holds for [pPi n]. *)
H: Univalence n: nat X, Y: pType f: X ->* Y IsConnMap0: IsConnMap (Tr n) f
IsEquiv (fmap (pPi n) f)
H: Univalence n: nat X, Y: pType f: X ->* Y IsConnMap0: IsConnMap (Tr n) f
IsEquiv (fmap (pPi n) f)
(* For [n = 0] and [n] a successor, [fmap (pPi n) f] is definitionally equal to the map in the previous result as a map of types. *)destruct n; tapply isequiv_pi_connmap'.Defined.Definitionpequiv_pi_connmap `{Univalence} (n : nat) {X Y : pType} (f : X ->* Y)
`{!IsConnMap n f}
: Pi n X <~>* Pi n Y
:= Build_pEquiv (fmap (pPi n) f) _.(** For positive [n], it is a group isomorphism. *)Definitiongrp_iso_pi_connmap `{Univalence} (n : nat) {X Y : pType} (f : X ->* Y)
`{!IsConnMap n.+1 f}
: GroupIsomorphism (Pi n.+1 X) (Pi n.+1 Y)
:= Build_GroupIsomorphism _ _ (fmap (Pi n.+1) f) (isequiv_pi_connmap n.+1 f).(** As a consequence, the truncation map [ptr : X -> pTr n X] induces an equivalence on [Pi n]. We don't make this an instance, since it is found by typeclass search. *)Definitionisequiv_pi_Tr `{Univalence} (n : nat) (X : pType)
: IsEquiv (fmap (pPi n) ptr : Pi n X -> Pi n (pTr n X))
:= _.Definitionpequiv_pi_Tr `{Univalence} (n : nat) (X : pType)
: Pi n X <~>* Pi n (pTr n X)
:= Build_pEquiv (fmap (pPi n) ptr) _.(** For positive [n], it is a group isomorphism. *)Definitiongrp_iso_pi_Tr `{Univalence} (n : nat) (X : pType)
: GroupIsomorphism (Pi n.+1 X) (Pi n.+1 (pTr n.+1 X))
:= grp_iso_pi_connmap n ptr.(** An [n]-connected map induces a surjection on [n+1]-fold loop spaces and [Pi (n+1)]. *)
H: Univalence n: nat X, Y: pType f: X ->* Y C: IsConnMap (Tr n) f
byapply issurj_iterated_loops_connmap.Defined.(** The [n.+2]-nd homotopy group of an [n.+1]-truncated type vanishes. *)
H: Univalence n: nat X: pType IsTrunc0: IsTrunc n.+1 X
Contr (Pi n.+2 X)
H: Univalence n: nat X: pType IsTrunc0: IsTrunc n.+1 X
Contr (Pi n.+2 X)
H: Univalence n: nat X: pType IsTrunc0: IsTrunc n.+1 X
Contr (loops (iterated_loops n.+1 X))
rapply (equiv_istrunc_contr_iterated_loops n.+2).Defined.(** An [n.+1]-truncated pointed [0]-connected type whose [n.+1]-st homotopy group vanishes is [n]-truncated. *)
H: Univalence n: nat X: pType H0: IsConnected (Tr 0%nat) X IsTrunc0: IsTrunc n.+1 X c: Contr (Pi n.+1 X)
IsTrunc n X
H: Univalence n: nat X: pType H0: IsConnected (Tr 0%nat) X IsTrunc0: IsTrunc n.+1 X c: Contr (Pi n.+1 X)
IsTrunc n X
H: Univalence n: nat X: pType H0: IsConnected (Tr 0%nat) X IsTrunc0: IsTrunc n.+1 X c: Contr (Pi n.+1 X)
foralla : X, Contr (iterated_loops n.+1 [X, a])
H: Univalence n: nat X: pType H0: IsConnected (Tr 0%nat) X IsTrunc0: IsTrunc n.+1 X c: Contr (Pi n.+1 X)
n: nat X, Y: pType s: X ->* Y r: Y ->* X k: r o* s ==* pmap_idmap
IsEmbedding (fmap (pPi n) s)
n: nat X, Y: pType s: X ->* Y r: Y ->* X k: r o* s ==* pmap_idmap
IsEmbedding (fmap (pPi n) s)
n: nat X, Y: pType s: X ->* Y r: Y ->* X k: r o* s ==* pmap_idmap
IsInjective (fmap (pPi n) s)
n: nat X, Y: pType s: X ->* Y r: Y ->* X k: r o* s ==* pmap_idmap
(funx : pPi n X => fmap (pPi n) r (fmap (pPi n) s x)) == idmap
n: nat X, Y: pType s: X ->* Y r: Y ->* X k: r o* s ==* pmap_idmap x: pPi n X
fmap (pPi n) r (fmap (pPi n) s x) = x
n: nat X, Y: pType s: X ->* Y r: Y ->* X k: r o* s ==* pmap_idmap x: pPi n X
fmap (pPi n) (r $o s) x = x
n: nat X, Y: pType s: X ->* Y r: Y ->* X k: r o* s ==* pmap_idmap x: pPi n X
fmap (pPi n) pmap_idmap x = x
exact (fmap_id (pPi n) X x).Defined.(** ** The long exact sequence of homotopy groups *)(** A fiber sequence [F -> X -> Y] gives rise to a long exact sequence of homotopy groups. [Pi_les_pset] already provides one, but its maps are expressed using the composite [pTr 0 o iterated_loops n] instead of [pPi n]. We build the equivalent sequence whose maps are [fmap (pPi n)] and the connecting maps, giving each ingredient a name so that the terms of the sequence are transparent. When [n] is destructed, the objects of the two sequences are definitionally equal, and the only difference between the morphisms is in their pointedness proofs. The new sequence also definitionally lands in groups for successor indices. *)SectionPiLES.LocalOpen Scope succ_scope.Context `{Univalence} {F X Y : pType} (i : F ->* X) (f : X ->* Y)
`{IsExact purely F X Y i f}.(** The types appearing in the sequence. *)Definitionpi_carrier (n : N3) : pType :=
match n with
| (n, inl (inl (inl x))) => Empty_ind _ x
| (n, inl (inl (inr tt))) => pPi n Y
| (n, inl (inr tt)) => pPi n X
| (n, inr tt) => pPi n F
end.(** They are pointed equivalent to the types appearing in [Pi_les_pset], by the identity map in each case. *)
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: N3
pi_carrier n <~>* pTr 0 (loops_carrier F X Y n)
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: N3
pi_carrier n <~>* pTr 0 (loops_carrier F X Y n)
destruct n as [n x]; FinIndOn x; exact (pequiv_ppi_ptr_iterated_loops _ _).Defined.(** The connecting map [Pi n.+1 Y -> Pi n F] of the fiber sequence. *)Definitionpi_connecting_map (n : nat)
: pPi n.+1 Y ->* pPi n F
:= (pequiv_ppi_ptr_iterated_loops n F)^-1*
o* fmap (pTr 0) (connecting_map (fmap (iterated_loops n) i)
(fmap (iterated_loops n) f)).(** The maps appearing in the sequence. *)
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: N3
pi_carrier n.+1 ->* pi_carrier n
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: N3
pi_carrier n.+1 ->* pi_carrier n
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: +N
exact (pi_connecting_map n).Defined.(** They agree with the maps of [Pi_les_pset] under the equivalences above. For the first two this is [fmap_ppi_ptr_iterated_loops]; for the connecting map it is the cancellation of an equivalence with its inverse. *)
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: N3
pequiv_pi_carrier n o* pi_les_fn n ==*
les_fn (Pi_les_pset i f) n o* pequiv_pi_carrier n.+1
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: N3
pequiv_pi_carrier n o* pi_les_fn n ==*
les_fn (Pi_les_pset i f) n o* pequiv_pi_carrier n.+1
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: +N
H: Univalence F, X, Y: pType i: F ->* X f: X ->* Y H0: IsExact purely i f n: +N x: pi_carrier (n, inr tt).+1
pequiv_ppi_ptr_iterated_loops n F
((pequiv_ppi_ptr_iterated_loops n F)^-1
(Trunc_rec
(funx0 : pt = pt =>
tr
(O_rec idmap
(center
(hfiber
(funx1 : (fix F0 (m : nat) : pType :=
match m with
| 0 => F
| m'.+1%nat => loops (F0 m')
end)
n =>
(fmap (iterated_loops n) i x1; cx_isexact x1))
((pfiber2_loops (fmap (iterated_loops n) f))^-1 x0).1))).1)
x)) =
Trunc_rec
(funx0 : pt = pt =>
tr
(O_rec idmap
(center
(hfiber
(funx1 : (fix F0 (m : nat) : pType :=
match m with
| 0 => F
| m'.+1%nat => loops (F0 m')
end)
n =>
(fmap (iterated_loops n) i x1; cx_isexact x1))
((pfiber2_loops (fmap (iterated_loops n) f))^-1 x0).1))).1)
x
apply eisretr.Defined.(** The long exact sequence of homotopy groups of a fiber sequence. *)DefinitionPi_les : LongExactSequence (Tr (-1)) N3
:= les_pequiv (Pi_les_pset i f) pi_carrier
pequiv_pi_carrier pi_les_fn pi_les_square.(** Each level of [Pi_les] contributes three exactness statements, which we record separately to save the reader from the indexing of [N3]. They are named after the space whose homotopy group sits in the middle of the sequence, and are listed in the order in which they occur. *)(** [Pi_les] is exact at [Pi n F], the homotopy group of the fiber. The map into it is the connecting map. *)Definitionisexact_pi_fiber (n : nat)
: IsExact (Tr (-1)) (pi_connecting_map n) (fmap (pPi n) i)
:= les_isexact _ _ Pi_les (n, inl (inr tt)).(** [Pi_les] is exact at [Pi n X], the homotopy group of the total space. *)Definitionisexact_pi_total (n : nat)
: IsExact (Tr (-1)) (fmap (pPi n) i) (fmap (pPi n) f)
:= les_isexact _ _ Pi_les (n, inl (inl (inr tt))).(** [Pi_les] is exact at [Pi n.+1 Y], the homotopy group of the base. The map out of it is the connecting map. *)Definitionisexact_pi_base (n : nat)
: IsExact (Tr (-1)) (fmap (pPi n.+1) f) (pi_connecting_map n)
:= les_isexact _ _ Pi_les (n, inr tt).EndPiLES.(** [F], [X] and [Y] cannot be inferred from the index, so we make them explicit, as they are in [loops_carrier]. *)Arguments pi_carrier F X Y n : clear implicits.Arguments pequiv_pi_carrier F X Y n : clear implicits.