Built with Alectryon, running Coq+SerAPI v8.19.0+0.19.3. 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.
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Export canonical_names.BinOpNotations.Require Import Basics Types Pointed WildCat.Core.Require Import Truncations.Core Truncations.Connectedness.LocalOpen Scope pointed_scope.LocalOpen Scope trunc_scope.LocalOpen Scope mc_mult_scope.LocalOpen Scope path_scope.(** * H-spaces *)(** A (non-coherent) H-space [X] is a pointed type with a binary operation for which the base point is a both a left and a right identity. (See Coherent.v for the notion of a coherent H-space.) We say [X] is left-invertible if left multiplication by any element is an equivalence, and dually for right-invertible. *)ClassIsHSpace (X : pType) := {
hspace_op :: SgOp X;
hspace_left_identity :: LeftIdentity hspace_op pt;
hspace_right_identity :: RightIdentity hspace_op pt;
}.#[export] Instancehspace_mon_unit {X : pType} `{IsHSpace X} : MonUnit X := pt.Definitionissig_ishspace {X : pType}
: { mu : X -> X -> X & prod (forallx, mu pt x = x) (forallx, mu x pt = x) }
<~> IsHSpace X := ltac:(make_equiv).(** Left and right multiplication by the base point is always an equivalence. *)
X: pType H: IsHSpace X
IsEquiv (sg_op pt)
X: pType H: IsHSpace X
IsEquiv (sg_op pt)
X: pType H: IsHSpace X x: X
x = pt * x
exact (left_identity x)^.Defined.
X: pType H: IsHSpace X
IsEquiv (funy : X => y * pt)
X: pType H: IsHSpace X
IsEquiv (funy : X => y * pt)
X: pType H: IsHSpace X x: X
x = x * pt
exact (right_identity x)^.Defined.Definitionequiv_hspace_left_op {X : pType} `{IsHSpace X}
(x : X) `{IsEquiv _ _ (x *.)} : X <~> X
:= Build_Equiv _ _ (x *.) _.Definitionequiv_hspace_right_op {X : pType} `{IsHSpace X}
(x : X) `{IsEquiv _ _ (.* x)} : X <~> X
:= Build_Equiv _ _ (.* x) _.(** Any element of an H-space defines a pointed self-map by left multiplication, in the following sense. *)Definitionpmap_hspace_left_op {X : pType} `{IsHSpace X} (x : X)
: X ->* [X, x] := Build_pMap (x *.) (right_identity x).(** We make [(x *.)] into a pointed equivalence (when possible). In particular, this makes [(pt *.)] into a pointed self-equivalence. We could have also used the left identity to make [(pt *.)] into a pointed self-equivalence, and then we would get a map that's equal to the identity as a pointed map; but without coherence (see Coherent.v) this is not necessarily the case for this map. *)Definitionpequiv_hspace_left_op {X : pType} `{IsHSpace X}
(x : X) `{IsEquiv _ _ (x *.)} : X <~>* [X,x]
:= Build_pEquiv' (equiv_hspace_left_op x) (right_identity x).(** ** Connected H-spaces *)(** For connected H-spaces, left and right multiplication by an element is an equivalence. This is because left and right multiplication by the base point is one, and being an equivalence is a proposition. *)
H: Univalence A: pType H0: IsHSpace A H1: IsConnected (Tr 0) A
foralla : A, IsEquiv (sg_op a)
H: Univalence A: pType H0: IsHSpace A H1: IsConnected (Tr 0) A
foralla : A, IsEquiv (sg_op a)
napply conn_point_elim; exact _.Defined.
H: Univalence A: pType H0: IsHSpace A H1: IsConnected (Tr 0) A
foralla : A, IsEquiv (funy : A => y * a)
H: Univalence A: pType H0: IsHSpace A H1: IsConnected (Tr 0) A
foralla : A, IsEquiv (funy : A => y * a)
napply conn_point_elim; exact _.Defined.(** ** Left-invertible H-spaces are homogeneous *)(** A homogeneous structure on a pointed type [A] gives, for any point [a : A], a self-equivalence of [A] sending the base point to [a]. (This is the same data as a left-invertible right-unital binary operation.) *)ClassIsHomogeneous (A : pType)
:= ishomogeneous : foralla, A <~>* [A, a].(** Any homogeneous structure can be modified so that the base point is mapped to the pointed identity map. *)Definitionhomogeneous_pt_id {A : pType} `{IsHomogeneous A}
: foralla, A <~>* [A,a]
:= funa => ishomogeneous a o*E (ishomogeneous (point A))^-1*.Definitionhomogeneous_pt_id_beta {A : pType} `{IsHomogeneous A}
: homogeneous_pt_id (point A) ==* pequiv_pmap_idmap
:= peisretr _.Definitionhomogeneous_pt_id_beta' `{Funext} {A : pType} `{IsHomogeneous A}
: homogeneous_pt_id (point A) = pequiv_pmap_idmap
:= ltac:(apply path_pequiv, peisretr).(** This modified structure makes any homogeneous type into a (left-invertible) H-space. *)
A: pType H: IsHomogeneous A
IsHSpace A
A: pType H: IsHomogeneous A
IsHSpace A
A: pType H: IsHomogeneous A
SgOp A
A: pType H: IsHomogeneous A
LeftIdentity ?hspace_op pt
A: pType H: IsHomogeneous A
RightIdentity ?hspace_op pt
A: pType H: IsHomogeneous A
SgOp A
exact (funab => homogeneous_pt_id a b).
A: pType H: IsHomogeneous A
LeftIdentity (funab : A => homogeneous_pt_id a b) pt
A: pType H: IsHomogeneous A a: A
ishomogeneous pt ((ishomogeneous pt)^-1 a) = a
apply eisretr.
A: pType H: IsHomogeneous A
RightIdentity (funab : A => homogeneous_pt_id a b)
pt
A: pType H: IsHomogeneous A a: A
homogeneous_pt_id a pt = a
exact (point_eq (homogeneous_pt_id a)).Defined.(** Left-invertible H-spaces are homogeneous, giving a logical equivalence between left-invertible H-spaces and homogeneous types. (In fact, the type of homogeneous types with the base point sent to the pointed identity map is equivalent to the type of left-invertible coherent H-spaces, but we don't prove that here.) See [equiv_iscohhspace_ptd_action] for a closely related result. *)Instanceishomogeneous_hspace {A : pType} `{IsHSpace A}
`{foralla, IsEquiv (a *.)}
: IsHomogeneous A
:= (funa => pequiv_hspace_left_op a).(** ** Promoting unpointed homotopies to pointed homotopies *)(** Two pointed maps [f g : Y ->* X] into an H-space are equal if and only if they are equal as unpointed maps. (Note: This is a logical "iff", not an equivalence of types.) This was first observed by Evan Cavallo for homogeneous types. Below we show a generalization due to Egbert Rijke, which we then specialize to H-spaces. Notably, the specialization does not require left-invertibility. This appears as Lemma 2.6 in https://arxiv.org/abs/2301.02636v1 *)(** First a version that assumes an equality of the unpointed maps. *)
A, B: pType m: foralla : A, pt = pt -> a = a q: m pt == idmap f, g: B ->* A K: f = g
f ==* g
A, B: pType m: foralla : A, pt = pt -> a = a q: m pt == idmap f, g: B ->* A K: f = g
f ==* g
A, B: pType m: foralla : A, pt = pt -> a = a q: m pt == idmap f, g: B ->* A K: f = g
{p : f == g & p pt = dpoint_eq f @ (dpoint_eq g)^}
A, B: pType m: foralla : A, pt = pt -> a = a q: m pt == idmap f: B -> A fpt: f pt = pt g: B -> A gpt: g pt = pt K: f = g
{p : f == g & p pt = fpt @ gpt^}
A, B: pType m: foralla : A, pt = pt -> a = a q: m pt == idmap f: B -> A fpt, gpt: f pt = pt
{p : f == f & p pt = fpt @ gpt^}
A: Type a0: IsPointed A B: pType m: foralla : A, a0 = a0 -> a = a q: m a0 == idmap f: B -> A fpt, gpt: f pt = a0
{p : f == f & p pt = fpt @ gpt^}
A: Type B: pType f: B -> A m: foralla : A, f pt = f pt -> a = a q: m (f pt) == idmap gpt: f pt = f pt
{p : f == f & p pt = 1 @ gpt^}
A: Type B: pType f: B -> A m: foralla : A, f pt = f pt -> a = a q: m (f pt) == idmap gpt: f pt = f pt
m (f pt) (1 @ gpt^) = 1 @ gpt^
apply q.Defined.(** Assuming [Funext], we may take [K] to be a homotopy. With a more elaborate proof, [Funext] could be avoided here and therefore in the next result as well. *)Definitionphomotopy_from_homotopy `{Funext} {A B : pType}
(m : forall (a : A), (point A) = (point A) -> a = a)
(q : m pt == idmap) {f g : B ->* A} (K : f == g)
: f ==* g
:= phomotopy_from_path_arrow m q (path_forall _ _ K).(** We specialize to H-spaces. *)
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g
f ==* g
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g
f ==* g
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g
foralla : A, pt = pt -> a = a
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g
?m pt == idmap
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g
foralla : A, pt = pt -> a = a
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g a: A
pt = pt -> a = a
exact (fmap loops (pmap_hspace_left_op a o* (pequiv_hspace_left_op pt)^-1*)).
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g
(funa : A =>
pointed_fun
(fmap loops
(pmap_hspace_left_op a
o* (pequiv_hspace_left_op pt)^-1*))) pt ==
idmap
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f == g
napply peisretr.Defined.(** A version with actual paths. *)
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f = g
f = g
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f = g
f = g
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f = g
f == g
H: Funext A, B: pType H0: IsHSpace A f, g: B ->* A K: f = g
f = g
exact K.Defined.(** A type equivalent to an H-space is an H-space. *)
X, Y: pType H: IsHSpace Y f: X <~>* Y
IsHSpace X
X, Y: pType H: IsHSpace Y f: X <~>* Y
IsHSpace X
X, Y: pType H: IsHSpace Y f: X <~>* Y
SgOp X
X, Y: pType H: IsHSpace Y f: X <~>* Y
LeftIdentity ?hspace_op pt
X, Y: pType H: IsHSpace Y f: X <~>* Y
RightIdentity ?hspace_op pt
X, Y: pType H: IsHSpace Y f: X <~>* Y
SgOp X
exact (funab => f^-1 (f a * f b)).
X, Y: pType H: IsHSpace Y f: X <~>* Y
LeftIdentity (funab : X => f^-1 (f a * f b)) pt
X, Y: pType H: IsHSpace Y f: X <~>* Y b: X
f^-1 (f pt * f b) = b
X, Y: pType H: IsHSpace Y f: X <~>* Y b: X
f^-1 (f pt * f b) = f^-1 (f b)
X, Y: pType H: IsHSpace Y f: X <~>* Y b: X
f pt * f b = f b
X, Y: pType H: IsHSpace Y f: X <~>* Y b: X
pt * f b = f b
apply left_identity.
X, Y: pType H: IsHSpace Y f: X <~>* Y
RightIdentity (funab : X => f^-1 (f a * f b)) pt
X, Y: pType H: IsHSpace Y f: X <~>* Y a: X
f^-1 (f a * f pt) = a
X, Y: pType H: IsHSpace Y f: X <~>* Y a: X
f^-1 (f a * f pt) = f^-1 (f a)
X, Y: pType H: IsHSpace Y f: X <~>* Y a: X
f a * f pt = f a
X, Y: pType H: IsHSpace Y f: X <~>* Y a: X
f a * pt = f a
apply right_identity.Defined.(** Every loop space is an H-space. Making this an instance breaks CayleyDickson.v because Coq finds this instance rather than the expected one. *)