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.
Require Import HoTT.Basics Types.Prod Types.Equiv Types.Sigma Types.Universe.Require Import HoTT.Basics Types.Prod Types.Equiv Types.Sigma Types.Universe.LocalOpen Scope path_scope.Generalizable VariablesA B f.(** * Bi-invertible maps *)(** A map is "bi-invertible" if it has both a section and a retraction, not necessarily the same. This definition of equivalence was proposed by Andre Joyal. *)ClassIsBiInv {AB : Type} (e : A -> B) := {
sect_biinv : B -> A ;
retr_biinv : B -> A ;
eisretr_biinv : e o sect_biinv == idmap ;
eissect_biinv : retr_biinv o e == idmap ;
}.Arguments sect_biinv {A B}%_type_scope e%_function_scope {_} _.Arguments retr_biinv {A B}%_type_scope e%_function_scope {_} _.Arguments eisretr_biinv {A B}%_type_scope e%_function_scope {_} _.Arguments eissect_biinv {A B}%_type_scope e%_function_scope {_} _.RecordBiInvAB := {
biinv_fun : A -> B ;
biinv_isbiinv :: IsBiInv biinv_fun
}.Coercionbiinv_fun : BiInv >-> Funclass.Arguments biinv_fun {A B} _ _.Arguments biinv_isbiinv {A B} _.(** If [e] is bi-invertible, then the retraction and the section of [e] are equal. *)
A, B: Type f: A -> B bi: IsBiInv f
sect_biinv f == retr_biinv f
A, B: Type f: A -> B bi: IsBiInv f
sect_biinv f == retr_biinv f
A, B: Type f: A -> B
forallbi : IsBiInv f, sect_biinv f == retr_biinv f
A, B: Type f: A -> B h, g: B -> A r: (funx : B => f (h x)) == idmap s: (funx : A => g (f x)) == idmap
sect_biinv f == retr_biinv f
exact (funy => (s (h y))^ @ ap g (r y)).Defined.
A, B: Type f: A -> B bi: IsBiInv f
f o retr_biinv f == idmap
A, B: Type f: A -> B bi: IsBiInv f
f o retr_biinv f == idmap
A, B: Type f: A -> B bi: IsBiInv f z: B
f (retr_biinv f z) = z
A, B: Type f: A -> B bi: IsBiInv f z: B
f (sect_biinv f z) = z
apply eisretr_biinv.Defined.
A, B: Type f: A -> B bi: IsBiInv f
sect_biinv f o f == idmap
A, B: Type f: A -> B bi: IsBiInv f
sect_biinv f o f == idmap
A, B: Type f: A -> B bi: IsBiInv f z: A
sect_biinv f (f z) = z
A, B: Type f: A -> B bi: IsBiInv f z: A
retr_biinv f (f z) = z
apply eissect_biinv.Defined.(** The record is equivalent to a product type. This is used below in a 'product of contractible types is contractible' argument. *)
A, B: Type f: A -> B
{g : B -> A & g o f == idmap} * {h : B -> A & f o h == idmap} <~> IsBiInv f
A, B: Type f: A -> B
{g : B -> A & g o f == idmap} * {h : B -> A & f o h == idmap} <~> IsBiInv f
make_equiv.Defined.Definitionissig_biinv (AB : Type) : {f : A -> B & IsBiInv f} <~> BiInv A B
:= ltac:(issig).(** From a bi-invertible map, we can construct a half-adjoint equivalence in two ways. Here we take the inverse to be the retraction. *)
A, B: Type f: A -> B bi: IsBiInv f
IsEquiv f
A, B: Type f: A -> B bi: IsBiInv f
IsEquiv f
A, B: Type f: A -> B h, g: B -> A r: (funx : B => f (h x)) == idmap s: (funx : A => g (f x)) == idmap
IsEquiv f
exact (isequiv_adjointify f g
(funx => ap f (ap g (r x)^ @ s (h x)) @ r x)
s).Defined.#[export] Instanceisequiv_isbiinv_retr {AB : Type} (f : A -> B) `{bi : !IsBiInv f}
: IsEquiv (retr_biinv f)
:= isequiv_inverse f.(** Here we take the inverse to be the section. *)
A, B: Type f: A -> B bi: IsBiInv f
IsEquiv f
A, B: Type f: A -> B bi: IsBiInv f
IsEquiv f
A, B: Type f: A -> B bi: IsBiInv f
B -> A
A, B: Type f: A -> B bi: IsBiInv f
f o ?g == idmap
A, B: Type f: A -> B bi: IsBiInv f
?g o f == idmap
A, B: Type f: A -> B bi: IsBiInv f
B -> A
apply (sect_biinv f).
A, B: Type f: A -> B bi: IsBiInv f
f o sect_biinv f == idmap
apply eisretr_biinv. (* We provide proof of eissect, but it gets modified. *)
A, B: Type f: A -> B bi: IsBiInv f
sect_biinv f o f == idmap
A, B: Type f: A -> B bi: IsBiInv f a: A
sect_biinv f (f a) = a
A, B: Type f: A -> B bi: IsBiInv f a: A
retr_biinv f (f a) = a
apply eissect_biinv.Defined.#[export] Instanceisequiv_isbiinv_sect {AB : Type} (f : A -> B) `{bi : !IsBiInv f}
: IsEquiv (sect_biinv f)
:= isequiv_inverse f (feq:=isequiv_isbiinv' f).
A, B: Type f: A -> B
IsEquiv f -> IsBiInv f
A, B: Type f: A -> B
IsEquiv f -> IsBiInv f
A, B: Type f: A -> B g: B -> A s: (funx : B => f (g x)) == idmap r: (funx : A => g (f x)) == idmap adj: forallx : A, s (f x) = ap f (r x)
IsBiInv f
exact (Build_IsBiInv _ _ f g g s r).Defined.
A, B: Type f: A -> B
IsBiInv f <-> IsEquiv f
A, B: Type f: A -> B
IsBiInv f <-> IsEquiv f
A, B: Type f: A -> B
IsBiInv f -> IsEquiv f
A, B: Type f: A -> B
IsEquiv f -> IsBiInv f
A, B: Type f: A -> B
IsBiInv f -> IsEquiv f
apply isequiv_isbiinv.
A, B: Type f: A -> B
IsEquiv f -> IsBiInv f
apply isbiinv_isequiv.Defined.
H: Funext A, B: Type f: A -> B
IsHProp (IsBiInv f)
H: Funext A, B: Type f: A -> B
IsHProp (IsBiInv f)
H: Funext A, B: Type f: A -> B
IsBiInv f -> Contr (IsBiInv f)
H: Funext A, B: Type f: A -> B bif: IsBiInv f
Contr (IsBiInv f)
(* This uses implicitly that the product of contractible types is contractible: *)srapply (contr_equiv' _ (prod_isbiinv A B)).Defined.
H: Funext A, B: Type f: A -> B
IsBiInv f <~> IsEquiv f
H: Funext A, B: Type f: A -> B
IsBiInv f <~> IsEquiv f
apply equiv_iff_hprop_uncurried, iff_isbiinv_isequiv.Defined.(** Some lemmas to send equivalences and biinvertible maps back and forth. *)Definitionequiv_biinvAB (f : BiInv A B) : A <~> B
:= Build_Equiv A B f _.Definitionbiinv_equivAB (e : A <~> B) : BiInv A B
:= Build_BiInv A B e (isbiinv_isequiv e (equiv_isequiv e)).
H: Funext A, B: Type
BiInv A B <~> (A <~> B)
H: Funext A, B: Type
BiInv A B <~> (A <~> B)
H: Funext A, B: Type
{f : A -> B & IsBiInv f} <~> {f : A -> B & IsEquiv f}
by nrefine (Build_BiInv A A idmap (Build_IsBiInv A A idmap idmap idmap _ _)).Defined.(** Assume we have a commutative square [e' o f == g o e] in which [e] and [e'] are bi-invertible. Then [f] and [g] also commute with the retractions and sections, and the homotopies in these new squares each satisfy a coherence condition. *)SectionEquivalenceCompatibility.Context {ABCD : Type}.Context (e : BiInv A B) (e' : BiInv C D) (f : A -> C) (g : B -> D).Lets := sect_biinv e.Letr := retr_biinv e.Letre := eissect_biinv e : r o e == idmap.Letes := eisretr_biinv e : e o s == idmap.Lets' := sect_biinv e'.Letr' := retr_biinv e'.Letre' := eissect_biinv e' : r' o e' == idmap.Letes' := eisretr_biinv e' : e' o s' == idmap.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: e' o f == g o e
r' o g o e == f o r o e
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: e' o f == g o e
r' o g o e == f o r o e
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: e' o f == g o e x: A
r' (g (e x)) = f (r (e x))
exact ((ap r' (pe x))^ @ (re' (f x) @ (ap f (re x))^)).Defined.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: e' o f == g o e
e' o s' o g == e' o f o s
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: e' o f == g o e
e' o s' o g == e' o f o s
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: e' o f == g o e y: B
e' (s' (g y)) = e' (f (s y))
exact (es' (g y) @ (ap g (es y))^ @ (pe (s y))^).Defined.(** The following lemmas express the coherence conditions mentioned above. *)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x)
r' o g == f o r
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x)
r' o g == f o r
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x)
forallx : A, r' (g (e x)) = f (r (e x))
apply (helper_r pe).Defined.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x)
s' o g == f o s
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x)
s' o g == f o s
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x) y: B
s' (g y) = f (s y)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x) y: B
e' (s' (g y)) = e' (f (s y))
apply (helper_s pe).Defined.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx0 : A, e' (f x0) = g (e x0) x: A
re' (f x) = (ap r' (pe x) @ biinv_compat_pr pe (e x)) @ ap f (re x)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx0 : A, e' (f x0) = g (e x0) x: A
re' (f x) = (ap r' (pe x) @ biinv_compat_pr pe (e x)) @ ap f (re x)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx0 : A, e' (f x0) = g (e x0) x: A
re' (f x) =
(ap r' (pe x) @
equiv_ind e (funy : B => r' (g y) = f (r y)) (helper_r pe) (e x)) @
ap f (re x)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx0 : A, e' (f x0) = g (e x0) x: A
re' (f x) = (ap r' (pe x) @ helper_r pe x) @ ap f (re x)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx0 : A, e' (f x0) = g (e x0) x: A
re' (f x) @ (ap f (re x))^ = ap r' (pe x) @ helper_r pe x
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx0 : A, e' (f x0) = g (e x0) x: A
(ap r' (pe x))^ @ (re' (f x) @ (ap f (re x))^) = helper_r pe x
reflexivity.Defined.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x) y: B
es' (g y) = (ap e' (biinv_compat_ps pe y) @ pe (s y)) @ ap g (es y)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x) y: B
es' (g y) = (ap e' (biinv_compat_ps pe y) @ pe (s y)) @ ap g (es y)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x) y: B
es' (g y) = (helper_s pe y @ pe (s y)) @ ap g (es y)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x) y: B
es' (g y) @ (ap g (es y))^ = helper_s pe y @ pe (s y)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D s:= sect_biinv e: B -> A r:= retr_biinv e: B -> A re:= eissect_biinv e: r o e == idmap es:= eisretr_biinv e: e o s == idmap s':= sect_biinv e': D -> C r':= retr_biinv e': D -> C re':= eissect_biinv e': r' o e' == idmap es':= eisretr_biinv e': e' o s' == idmap pe: forallx : A, e' (f x) = g (e x) y: B
(es' (g y) @ (ap g (es y))^) @ (pe (s y))^ = helper_s pe y