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.Basics Require Import Overture Equivalences Tactics Iff Trunc.From HoTT.Basics Require Import Overture Equivalences Tactics Iff Trunc.From HoTT.Basics Require Import PathGroupoids.From HoTT.Types Require Import Sigma Prod Equiv.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} _.(** 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).(** If [e] is bi-invertible, then the retraction and the section of [e] are homotopic. *)
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.(** From a bi-invertible map, we can construct a half-adjoint equivalence in two ways. Here we take the inverse to be the retraction. Note that [isequiv_adjointify] modifies the last field provided. So in order that [eissect_biinv f] not be modified, we first use [isequiv_adjointify] to prove that [retr_biinv f] is an equivalence, and then use [isequiv_inverse] to deduce that [f] is an equivalence. *)
A, B: Type f: A -> B bi: IsBiInv f
IsEquiv (retr_biinv f)
A, B: Type f: A -> B bi: IsBiInv f
IsEquiv (retr_biinv f)
A, B: Type f: A -> B bi: IsBiInv f b: B
f (retr_biinv f b) = b
(* This inlined proof will be modified by [isequiv_adjointify]: *)exact (ap f (sect_retr_homotopic_isbiinv f b)^ @ eisretr_biinv f b).Defined.#[export] Instanceisequiv_isbiinv {AB : Type} (f : A -> B) `{bi : !IsBiInv f}
: IsEquiv f
:= isequiv_inverse (retr_biinv f).(** Now we extract the proof generated by [isequiv_adjointify]; it will satisfy the adjoint law [eisadj]. *)Definitionretr_is_sect_isbiinv {AB : Type} (f : A -> B) `{bi : !IsBiInv f}
: f o retr_biinv f == idmap
:= eisretr f.(** [f] is an equivalence in a second way. Here we take the inverse to be the section. Again, the last field we provide is modified, and we extract it. *)
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 a: A
sect_biinv f (f a) = a
exact (sect_retr_homotopic_isbiinv f (f a) @ eissect_biinv f a).Defined.Definitionsect_is_retr_isbiinv {AB : Type} (f : A -> B) `{bi : !IsBiInv f}
: sect_biinv f o f == idmap
:= eissect f (IsEquiv:=isequiv_isbiinv' f).#[export] Instanceisequiv_sect_biinv {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 [g o e == e' o f] 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).Context (pe : g o e == e' o f).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.(** 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 pe: g o e == e' o f 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
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 pe: g o e == e' o f 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
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 pe: g o e == e' o f 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
forallx : A, r' (g (e x)) = f (r (e x))
exact (funa => ap r' (pe a) @ (re' (f a) @ (ap f (re a))^)).Defined.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D pe: g o e == e' o f 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
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 pe: g o e == e' o f 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
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 pe: g o e == e' o f 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 b: B
s' (g b) = f (s b)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D pe: g o e == e' o f 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 b: B
e' (s' (g b)) = e' (f (s b))
exact (es' (g b) @ (ap g (es b))^ @ pe (s b)).Defined.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D pe: g o e == e' o f 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 x: A
re' (f x) = (ap r' (pe x))^ @ biinv_compat_pr (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 pe: g o e == e' o f 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 x: A
re' (f x) = (ap r' (pe x))^ @ biinv_compat_pr (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 pe: g o e == e' o f 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 x: A
re' (f x) =
(ap r' (pe x))^ @
equiv_ind e (funy : B => r' (g y) = f (r y))
(funa : A => ap r' (pe a) @ (re' (f a) @ (ap f (re a))^))
(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 pe: g o e == e' o f 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 x: A
re' (f x) =
(ap r' (pe x))^ @ (ap r' (pe x) @ (re' (f x) @ (ap f (re x))^)) @ ap f (re x)
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D pe: g o e == e' o f 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 x: A
re' (f x) @ (ap f (re x))^ =
(ap r' (pe x))^ @ (ap r' (pe x) @ (re' (f x) @ (ap f (re x))^))
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D pe: g o e == e' o f 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 x: A
ap r' (pe x) @ (re' (f x) @ (ap f (re x))^) =
ap r' (pe x) @ (re' (f x) @ (ap f (re x))^)
reflexivity.Defined.
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D pe: g o e == e' o f 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 y: B
es' (g y) = ap e' (biinv_compat_ps 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 pe: g o e == e' o f 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 y: B
es' (g y) = ap e' (biinv_compat_ps 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 pe: g o e == e' o f 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 y: B
es' (g y) = es' (g y) @ (ap g (es y))^ @ pe (s 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 pe: g o e == e' o f 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 y: B
es' (g y) @ (ap g (es y))^ =
es' (g y) @ (ap g (es y))^ @ pe (s y) @ (pe (s y))^
A, B, C, D: Type e: BiInv A B e': BiInv C D f: A -> C g: B -> D pe: g o e == e' o f 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 y: B
es' (g y) @ (ap g (es y))^ @ pe (s y) = es' (g y) @ (ap g (es y))^ @ pe (s y)