Isomorphisms

Contents

• isomorphisms: iso, isiso f := isweq f)
• Equivalence relation identifying isomorphic objects
• Isomorphisms in a category z_iso
• Definition: is_z_iso f := g, ...
• Relationship between z_iso and iso
• Properties of 0-isomorphisms
• uniqueness of inverse, composition etc.
• stability under composition
• Analogue to isweq_iso: is_iso_qinv

Require Import UniMath.Foundations.PartA.
Require Import UniMath.Foundations.Propositions.
Require Import UniMath.Foundations.Sets.
Require Import UniMath.MoreFoundations.Tactics.

Require Import UniMath.CategoryTheory.Core.Categories.

Local Open Scope cat.

A morphism f: a --> b in a precategory is an isomorphism is_iso(f), if for any c: C, precomposition with f yields an equivalence (b --> c -> a --> c]. Definition suggested by V. Voevodsky

Definition precomp_with {C : precategory_data} {a b : C} (f : a --> b) {c} (g : b --> c): a --> c :=
f · g.

Definition is_iso {C : precategory_data} {a b : C} (f : a --> b) :=
c, isweq (precomp_with f (c:=c)).

Lemma isaprop_is_iso {C : precategory_data}(a b : C) (f : a --> b) : isaprop (is_iso f).
Proof.
apply impred; intro.
apply isapropisweq.
Qed.

Definition iso {C: precategory_data}(a b : C) := total2 (fun f : a --> bis_iso f).
Definition morphism_from_iso {C:precategory_data} {a b : C} (f : iso a b) : a --> b := pr1 f.
Coercion morphism_from_iso : iso >-> precategory_morphisms.

Definition iso_is_iso {C: precategory_data} {a b : C} (f : iso a b) : is_iso f := pr2 f.

Definition make_iso {C: precategory_data}{a b : C} (f : a --> b) (fiso: is_iso f) : iso a b :=
tpair _ f fiso.

Definition inv_from_iso {C:precategory_data}{a b : C} (f : iso a b) : b --> a :=
invmap (make_weq (precomp_with f) (pr2 f a)) (identity _ ).

Definition iso_inv_after_iso {C : precategory_data} {a b : C} (f: iso a b) :
f · inv_from_iso f = identity _ .
Proof.
set (T:=homotweqinvweq (make_weq (precomp_with f) (pr2 f a ))).
simpl in ×.
apply T.
Defined.

Definition iso_after_iso_inv {C : precategory} {a b : C} (f : iso a b) :
inv_from_iso f · f = identity _ .
Proof.
set (T:= invmaponpathsweq (make_weq (precomp_with f) (pr2 f b))).
apply T; clear T; simpl.
unfold precomp_with.
intermediate_path ((f· inv_from_iso ff).
- apply assoc.
- apply remove_id_left.
+ apply iso_inv_after_iso.
+ apply (!(id_right _ )).
Defined.

Definition is_iso_inv_from_iso {C:precategory}{a b : C} (f : iso a b) : is_iso (inv_from_iso f).
Proof.
intro c.
apply (isweq_iso _ (precomp_with f)).
- intro g.
unfold precomp_with.
intermediate_path ((f · inv_from_iso f) · g).
+ apply assoc.
+ apply remove_id_left. apply iso_inv_after_iso. apply idpath.
- intro g.
unfold precomp_with.
intermediate_path ((inv_from_iso f·fg).
+ apply assoc.
+ apply remove_id_left. apply iso_after_iso_inv. apply idpath.
Defined.

Definition iso_inv_from_iso {C:precategory}{a b : C} (f : iso a b) : iso b a :=
tpair _ _ (is_iso_inv_from_iso f).

Lemma eq_iso {C: precategory_data} {a b : C} (f g : iso a b) : pr1 f = pr1 g f = g.
Proof.
intro H.
apply subtypePath.
- intros t. apply isaprop_is_iso.
- apply H.
Defined.

Lemma isaset_iso {C : precategory_data} (hs: has_homsets C) (a b :ob C) :
isaset (iso a b).
Proof.
change isaset with (isofhlevel 2).
apply isofhleveltotal2.
- apply hs.
- intro f.
apply isasetaprop.
apply isaprop_is_iso.
Qed.

Lemma identity_is_iso (C : precategory) (a : ob C) : is_iso (identity a).
Proof.
intros c.
set (T:=@isweqhomot (a --> c) (a --> c) (λ t, t) (precomp_with (identity a))).
apply T.
- intro g. apply pathsinv0. apply id_left.
- apply idisweq.
Defined.

Definition identity_iso {C : precategory} (a : ob C) :
iso a a := tpair _ _ (identity_is_iso C a).

Definition iso_inv_from_is_iso {C : precategory} {a b : ob C}
(f : a --> b) (H : is_iso f) : iso b a :=
iso_inv_from_iso (tpair _ f H).

Lemma iso_inv_on_right (C : precategory) (a b c: ob C)
(f : iso a b) (g : b --> c) (h : a --> c) (H : h = f·g) :
inv_from_iso f · h = g.
Proof.
apply (invmaponpathsweq (make_weq (precomp_with f) (pr2 f c))).
unfold precomp_with; simpl.
intermediate_path ((f·inv_from_iso fh).
- apply assoc.
- apply remove_id_left.
+ apply iso_inv_after_iso.
+ assumption.
Defined.

Lemma iso_inv_on_left (C : precategory) (a b c: ob C)
(f : a --> b) (g : iso b c) (h : a --> c) (H : h = f·g) :
f = h · inv_from_iso g.
Proof.
assert (H2 : h · inv_from_iso g =
(f· g) · inv_from_iso g).
rewrite H. apply idpath.
rewrite <- assoc in H2.
rewrite iso_inv_after_iso in H2.
rewrite id_right in H2.
apply pathsinv0.
assumption.
Qed.

Lemma iso_inv_to_left (C : precategory) (a b c: ob C)
(f : iso a b) (g : b --> c) (h : a --> c) :
inv_from_iso f · h = g h = f · g.
Proof.
intro H.
transitivity (f· inv_from_iso f· h).
- rewrite iso_inv_after_iso, id_left; apply idpath.
- rewrite <- assoc. rewrite H. apply idpath.
Qed.

Lemma iso_inv_to_right (C : precategory) (a b c: ob C)
(f : a --> b) (g : iso b c) (h : a --> c) :
f = h · inv_from_iso g f · g = h.
Proof.
intro H.
transitivity (h· inv_from_iso g· g).
- rewrite H. apply idpath.
- rewrite <- assoc, iso_after_iso_inv, id_right. apply idpath.
Qed.

Properties of isomorphisms

Stability under composition, inverses etc

Definition isweqhomot' {X Y} (f g : X Y) (H : isweq f)
(homot : x, f x = g x) : isweq g.
Proof.
apply (isweqhomot f g homot H).
Defined.

Lemma is_iso_comp_of_isos {C : precategory} {a b c : ob C}
(f : iso a b) (g : iso b c) : is_iso (f · g).
Proof.
simpl.
intro d.
set (T:=twooutof3c (precomp_with g) (precomp_with f(c:=d)) (pr2 g d) (pr2 f _)).
apply (isweqhomot' _ _ T).
intro h. apply assoc.
Defined.

Lemma is_iso_comp_of_is_isos {C : precategory} {a b c : ob C}
(f : a --> b) (g : b --> c) (H1 : is_iso f) (H2 : is_iso g) : is_iso (f · g).
Proof.
set (i1 := make_iso f H1).
set (i2 := make_iso g H2).
exact (is_iso_comp_of_isos i1 i2).
Qed.

Definition iso_comp {C : precategory} {a b c : ob C}
(f : iso a b) (g : iso b c) : iso a c.
Proof.
(f · g).
apply is_iso_comp_of_isos.
Defined.

Lemma inv_iso_unique (C : precategory) (a b : C) (f : iso a b) (g : iso b a) :
precomp_with f g = identity _ g = iso_inv_from_iso f.
Proof.
intro H.
apply eq_iso. simpl.
set (T:=invmaponpathsweq (make_weq (precomp_with f) (pr2 f a ))).
apply T; simpl.
intermediate_path (identity a ).
+ assumption.
+ apply pathsinv0. apply iso_inv_after_iso.
Defined.

Lemma inv_iso_unique' (C : precategory) (a b : C) (f : iso a b) (g : b --> a) :
precomp_with f g = identity _ g = inv_from_iso f.
Proof.
intro H.
set (T:=invmaponpathsweq (make_weq (precomp_with f) (pr2 f a ))).
apply T; simpl.
intermediate_path (identity a ).
+ assumption.
+ apply pathsinv0. apply iso_inv_after_iso.
Defined.

Lemma iso_inv_of_iso_comp (C : precategory) (a b c : ob C)
(f : iso a b) (g : iso b c) :
iso_inv_from_iso (iso_comp f g) = iso_comp (iso_inv_from_iso g) (iso_inv_from_iso f).
Proof.
apply pathsinv0.
apply inv_iso_unique. simpl. unfold precomp_with.
intermediate_path (f · (g·inv_from_iso g) · inv_from_iso f).
- repeat rewrite assoc. apply idpath.
- rewrite iso_inv_after_iso. rewrite id_right.
apply iso_inv_after_iso.
Qed.

Lemma iso_inv_of_iso_id (C : precategory) (a : ob C) :
iso_inv_from_iso (identity_iso a) = identity_iso a.
Proof.
apply eq_iso.
apply idpath.
Qed.

Lemma iso_inv_iso_inv (C : precategory) (a b : ob C) (f : iso a b) :
iso_inv_from_iso (iso_inv_from_iso f) = f.
Proof.
apply eq_iso. simpl.
apply pathsinv0.
apply inv_iso_unique'.
apply iso_after_iso_inv.
Defined.

Lemma pre_comp_with_iso_is_inj (C : precategory_data) (a b c : ob C)
(f : a --> b) (H : is_iso f) (g h : b --> c) : f · g = f · h g = h.
Proof.
intro X.
apply (invmaponpathsweq (make_weq (precomp_with f) (H _ ))).
apply X.
Qed.

Lemma post_comp_with_iso_is_inj (C : precategory) (b c : ob C)
(h : b --> c) (H : is_iso h)
(a : ob C) (f g : a --> b) : f · h = g · h f = g.
Proof.
intro HH.
set (T:=iso_inv_after_iso (tpair _ h H)). simpl in T.
intermediate_path (f · (h · inv_from_iso (tpair _ h H))).
- rewrite T. clear T.
apply pathsinv0, id_right.
- rewrite assoc. rewrite HH.
rewrite <- assoc. rewrite T.
apply id_right.
Qed.

Lemma iso_comp_right_isweq {C:precategory_data} {a b:ob C} (h:iso a b) (c:C) :
isweq (fun f : b --> ch · f).
Proof.
apply (pr2 h _ ).
Defined.

Definition iso_comp_right_weq {C:precategory_data} {a b:C} (h:iso a b) (c:C) :
(b --> c) (a --> c) := make_weq _ (iso_comp_right_isweq h c).

Lemma iso_comp_left_isweq {C:precategory} {a b:ob C} (h:iso a b) (c:C) :
isweq (fun f : c --> af · h).
Proof.
intros. apply (isweq_iso _ (λ g, g · inv_from_iso h)).
- intro x. rewrite <- assoc. apply remove_id_right.
apply iso_inv_after_iso. apply idpath.
- intro y. rewrite <- assoc. apply remove_id_right.
apply iso_after_iso_inv. apply idpath.
Defined.

Definition postcomp_with {C : precategory_data}{b c : C}(h : b --> c) {a : C}
(f : a --> b) : a --> c := f · h.

Definition is_iso' {C : precategory} {b c : C} (f : b --> c) :=
a, isweq (postcomp_with f (a:=a)).

Definition is_inverse_in_precat {C : precategory_data} {a b : C}
(f : a --> b) (g : b --> a) :=
dirprod (f · g = identity a)
(g · f = identity b).

Definition make_is_inverse_in_precat {C : precategory_data} {a b : C} {f : a --> b} {g : b --> a}
(H1 : f · g = identity a) (H2 : g · f = identity b) :
is_inverse_in_precat f g := (H1,,H2).

Definition is_inverse_in_precat1 {C : precategory_data} {a b : C} {f : a --> b} {g : b --> a}
(H : is_inverse_in_precat f g) :
f · g = identity a := dirprod_pr1 H.

Definition is_inverse_in_precat2 {C : precategory_data} {a b : C} {f : a --> b} {g : b --> a}
(H : is_inverse_in_precat f g) :
g · f = identity b := dirprod_pr2 H.

Definition is_inverse_in_precat_inv {C : precategory_data} {a b : C} {f : a --> b} {g : b --> a}
(H : is_inverse_in_precat f g) : is_inverse_in_precat g f :=
make_dirprod (is_inverse_in_precat2 H) (is_inverse_in_precat1 H).

Definition is_inverse_in_precat_comp {C : precategory} {a b c : C} {f1 : a --> b} {f2 : b --> c}
{g1 : b --> a} {g2 : c --> b} (H1 : is_inverse_in_precat f1 g1)
(H2 : is_inverse_in_precat f2 g2) : is_inverse_in_precat (f1 · f2) (g2 · g1).
Proof.
use make_is_inverse_in_precat.
- rewrite assoc. rewrite <- (assoc _ f2). rewrite (is_inverse_in_precat1 H2). rewrite id_right.
rewrite (is_inverse_in_precat1 H1). apply idpath.
- rewrite assoc. rewrite <- (assoc _ g1). rewrite (is_inverse_in_precat2 H1). rewrite id_right.
rewrite (is_inverse_in_precat2 H2). apply idpath.
Qed.

Definition is_inverse_in_precat_identity {C : precategory} (c : C) :
is_inverse_in_precat (identity c) (identity c).
Proof.
use make_is_inverse_in_precat.
- apply id_left.
- apply id_left.
Qed.

Definition is_iso_qinv {C:precategory} {a b : C} (f : a --> b) (g : b --> a) :
is_inverse_in_precat f g is_iso f.
Proof.
intros H c.
apply (isweq_iso _ (precomp_with g)).
- intro h. unfold precomp_with.
rewrite assoc.
apply remove_id_left.
apply (pr2 H). apply idpath.
- intro h. unfold precomp_with. rewrite assoc.
apply remove_id_left.
apply (pr1 H). apply idpath.
Defined.

Definition iso_comp_left_weq {C:precategory} {a b:C} (h:iso a b) (c:C) :
(c --> a) (c --> b) := make_weq _ (iso_comp_left_isweq h c).

Definition iso_conjug_weq {C:precategory} {a b:C} (h:iso a b) :
(a --> a) (b --> b) := weqcomp (iso_comp_left_weq h _ ) (iso_comp_right_weq (iso_inv_from_iso h) _ ).

Equivalence relation identifying isomorphic objects

Section are_isomorphic.

Context (C : precategory).

a and b are related if there merely exists an iso between them
Definition are_isomorphic : hrel C := λ a b, iso a b.

Lemma iseqrel_are_isomorphic : iseqrel are_isomorphic.
Proof.
repeat split.
- intros x y z h1.
apply hinhuniv; intros h2; generalize h1; clear h1.
now apply hinhuniv; intros h1; apply hinhpr, (iso_comp h1 h2).
- now intros x; apply hinhpr, identity_iso.
- now intros x y; apply hinhuniv; intro h1; apply hinhpr, iso_inv_from_iso.
Qed.

Definition iso_eqrel : eqrel C := (are_isomorphic,,iseqrel_are_isomorphic).

End are_isomorphic.

Isomorphisms in a category z_iso

In a precategory with hom-sets, we can give the usual definition of isomorphism, called z_iso in the following.

Lemma isaprop_is_inverse_in_precat (C : precategory_data) (hs: has_homsets C) (a b : ob C)
(f : a --> b) (g : b --> a) : isaprop (is_inverse_in_precat f g).
Proof.
apply isapropdirprod; apply hs.
Qed.

Lemma inverse_unique_precat (C : precategory) (a b : ob C)
(f : a --> b) (g g': b --> a) (H : is_inverse_in_precat f g)
(H' : is_inverse_in_precat f g') : g = g'.
Proof.
destruct H as [eta eps].
destruct H' as [eta' eps'].
assert (H : g = identity b · g).
rewrite id_left; apply idpath.
apply (pathscomp0 H).
rewrite <- eps'.
rewrite <- assoc.
rewrite eta.
apply id_right.
Qed.

Definition is_z_isomorphism {C : precategory_data} {a b : ob C}
(f : a --> b) := total2 (λ g, is_inverse_in_precat f g).

Definition make_is_z_isomorphism {C : precategory_data} {a b : C} (f : a --> b)
(g : b --> a) (H : is_inverse_in_precat f g) : is_z_isomorphism f := (g,,H).

Definition is_z_isomorphism_mor {C : precategory_data} {a b : C} {f : a --> b}
(I : is_z_isomorphism f) : b --> a := pr1 I.

Definition is_z_isomorphism_is_inverse_in_precat {C : precategory_data} {a b : C}
{f : a --> b} (I : is_z_isomorphism f) :
is_inverse_in_precat f (is_z_isomorphism_mor I) := pr2 I.
Coercion is_z_isomorphism_is_inverse_in_precat : is_z_isomorphism >-> is_inverse_in_precat.

Definition is_z_isomorphism_inv {C : precategory_data} {a b : C} {f : a --> b}
(I : is_z_isomorphism f) : is_z_isomorphism (is_z_isomorphism_mor I).
Proof.
use make_is_z_isomorphism.
- exact f.
- exact (is_inverse_in_precat_inv I).
Defined.

Definition is_z_isomorphism_comp {C : precategory} {a b c : C} {f1 : a --> b} {f2 : b --> c}
(H1 : is_z_isomorphism f1) (H2 : is_z_isomorphism f2) :
is_z_isomorphism (f1 · f2).
Proof.
use make_is_z_isomorphism.
- exact (is_z_isomorphism_mor H2 · is_z_isomorphism_mor H1).
- exact (is_inverse_in_precat_comp H1 H2).
Defined.

Definition is_z_isomorphism_identity {C : precategory} (c : C) : is_z_isomorphism (identity c).
Proof.
use make_is_z_isomorphism.
- exact (identity c).
- exact (is_inverse_in_precat_identity c).
Defined.

Lemma isaprop_is_z_isomorphism {C : precategory} {a b : ob C} (hs: has_homsets C)
(f : a --> b) : isaprop (is_z_isomorphism f).
Proof.
apply invproofirrelevance.
intros g g'.
set (Hpr1 := inverse_unique_precat _ _ _ _ _ _ (pr2 g) (pr2 g')).
apply (total2_paths_f Hpr1).
destruct g as [g [eta eps]].
destruct g' as [g' [eta' eps']].
simpl in ×.
apply isapropdirprod; apply hs.
Qed.

Lemma is_z_isomorphism_mor_eq {C : precategory} {a b : C} {f g : a --> b}
(e : f = g) (I1 : is_z_isomorphism f) (I2 : is_z_isomorphism g) :
is_z_isomorphism_mor I1 = is_z_isomorphism_mor I2.
Proof.
use inverse_unique_precat.
- exact f.
- exact I1.
- rewrite e. exact I2.
Qed.

Definition z_iso {C : precategory_data} (a b :ob C) := total2
(fun f : a --> bis_z_isomorphism f).

Definition make_z_iso {C : precategory_data} {a b : C} (f : a --> b) (g : b --> a)
(H : is_inverse_in_precat f g) : z_iso a b := (f,,make_is_z_isomorphism f g H).

Definition z_iso_mor {C : precategory_data} {a b : ob C} (f : z_iso a b) : a --> b := pr1 f.
Coercion z_iso_mor : z_iso >-> precategory_morphisms.

Definition z_iso_inv_mor {C : precategory_data} {a b : C} (i : z_iso a b) : b --> a :=
is_z_isomorphism_mor (pr2 i).

Definition z_iso_is_inverse_in_precat {C : precategory_data} {a b : C} (i : z_iso a b) :
is_inverse_in_precat i (z_iso_inv_mor i) := pr2 i.
Coercion z_iso_is_inverse_in_precat : z_iso >-> is_inverse_in_precat.

Definition z_iso_inv {C : precategory_data} {a b : C} (I : z_iso a b) : z_iso b a.
Proof.
use make_z_iso.
- exact (z_iso_inv_mor I).
- exact I.
- exact (is_inverse_in_precat_inv I).
Defined.

Definition z_iso_comp {C : precategory} {a b c : C} (I1 : z_iso a b) (I2 : z_iso b c) :
z_iso a c.
Proof.
use make_z_iso.
- exact (I1 · I2).
- exact ((z_iso_inv_mor I2) · (z_iso_inv_mor I1)).
- exact (is_inverse_in_precat_comp I1 I2).
Defined.

Definition z_iso_identity {C : precategory} (c : C) : z_iso c c.
Proof.
use make_z_iso.
- exact (identity c).
- exact (identity c).
- exact (is_inverse_in_precat_identity c).
Defined.

Definition z_iso_is_z_isomorphism1 {C : precategory} {a b : C} (I : z_iso a b) :
is_z_isomorphism I.
Proof.
use make_is_z_isomorphism.
- exact (z_iso_inv_mor I).
- exact I.
Defined.

Definition z_iso_is_z_isomorphism2 {C : precategory} {a b : C} (I : z_iso a b) :
is_z_isomorphism (z_iso_inv_mor I).
Proof.
use make_is_z_isomorphism.
- exact I.
- exact (is_inverse_in_precat_inv I).
Defined.

Lemma post_comp_with_z_iso_is_inj {C : precategory} {a' a b : C} {f : a --> b} {g : b --> a}
(i : is_inverse_in_precat f g) : (f' g' : a' --> a), f' · f = g' · f f' = g'.
Proof.
intros f' g' H.
apply (maponpaths (postcompose g)) in H. unfold postcompose in H.
rewrite <- assoc in H. rewrite <- assoc in H.
rewrite (is_inverse_in_precat1 i) in H. rewrite id_right in H. rewrite id_right in H.
exact H.
Qed.

Lemma post_comp_with_z_iso_inv_is_inj {C : precategory} {a b b' : C} {f : a --> b} {g : b --> a}
(i : is_inverse_in_precat f g) : (f' g' : b' --> b), f' · g = g' · g f' = g'.
Proof.
intros f' g' H.
apply (maponpaths (postcompose f)) in H. unfold postcompose in H.
rewrite <- assoc in H. rewrite <- assoc in H.
rewrite (is_inverse_in_precat2 i) in H. rewrite id_right in H. rewrite id_right in H.
exact H.
Qed.

Lemma pre_comp_with_z_iso_is_inj {C : precategory} {a b b' : C} {f : a --> b} {g : b --> a}
(i : is_inverse_in_precat f g) : (f' g' : b --> b'), f · f' = f · g' f' = g'.
Proof.
intros f' g' H.
apply (maponpaths (compose g)) in H.
rewrite assoc in H. rewrite assoc in H.
rewrite (is_inverse_in_precat2 i) in H. rewrite id_left in H. rewrite id_left in H.
exact H.
Qed.

Lemma pre_comp_with_z_iso_inv_is_inj {C : precategory} {a' a b : C} {f : a --> b} {g : b --> a}
(i : is_inverse_in_precat f g) : (f' g' : a --> a'), g · f' = g · g' f' = g'.
Proof.
intros f' g' H.
apply (maponpaths (compose f)) in H.
rewrite assoc in H. rewrite assoc in H.
rewrite (is_inverse_in_precat1 i) in H. rewrite id_left in H. rewrite id_left in H.
exact H.
Qed.

Lemma z_iso_eq {C : category} {a b : C} (i i' : z_iso a b) (e : z_iso_mor i = z_iso_mor i') :
i = i'.
Proof.
use total2_paths_f.
- exact e.
- use proofirrelevance. apply isaprop_is_z_isomorphism. apply homset_property.
Qed.

Lemma z_iso_eq_inv {C : category} {a b : C} (i i' : z_iso a b)
(e2 : z_iso_inv_mor i = z_iso_inv_mor i') : i = i'.
Proof.
use z_iso_eq.
assert (H : is_inverse_in_precat (z_iso_inv_mor i) i').
{
use make_is_inverse_in_precat.
- rewrite e2. exact (is_inverse_in_precat2 i').
- rewrite e2. exact (is_inverse_in_precat1 i').
}
exact (inverse_unique_precat _ _ _ _ _ _ (z_iso_inv i) H).
Qed.

Lemma eq_z_iso (C : precategory)(hs: has_homsets C) (a b : ob C)
(f g : z_iso a b) : pr1 f = pr1 g f = g.
Proof.
intro H.
apply (total2_paths_f H).
apply proofirrelevance.
apply isaprop_is_z_isomorphism, hs.
Defined.

Definition morphism_from_z_iso (C : precategory_data)(a b : ob C)
(f : z_iso a b) : a --> b := pr1 f.
Coercion morphism_from_z_iso : z_iso >-> precategory_morphisms.

Lemma isaset_z_iso {C : precategory} (hs: has_homsets C) (a b :ob C) : isaset (z_iso a b).
Proof.
change isaset with (isofhlevel 2).
apply isofhleveltotal2.
apply hs.
intro f.
apply isasetaprop.
apply isaprop_is_z_isomorphism, hs.
Qed.

Lemma identity_is_z_iso (C : precategory) (a : ob C) :
is_z_isomorphism (identity a).
Proof.
(identity a).
simpl; split;
apply id_left.
Defined.

Definition identity_z_iso {C : precategory} (a : ob C) :
z_iso a a := tpair _ _ (identity_is_z_iso C a).

Definition inv_from_z_iso {C : precategory_data} {a b : ob C}
(f : z_iso a b) : b --> a := pr1 (pr2 f).

Lemma is_z_iso_inv_from_z_iso {C : precategory_data} (a b : ob C)
(f : z_iso a b) : is_z_isomorphism (inv_from_z_iso f).
Proof.
(pr1 f).
simpl; split; simpl.
- apply (pr2 (pr2 (pr2 f))).
- apply (pr1 (pr2 (pr2 f))).
Defined.

Definition z_iso_inv_from_z_iso {C : precategory_data} {a b : ob C}
(f : z_iso a b) : z_iso b a.
Proof.
(inv_from_z_iso f).
apply is_z_iso_inv_from_z_iso.
Defined.

Definition z_iso_inv_from_is_z_iso {C : precategory_data} {a b : ob C}
(f : a --> b) (H : is_z_isomorphism f) : z_iso b a :=
z_iso_inv_from_z_iso (tpair _ f H).

Definition z_iso_inv_after_z_iso (C : precategory_data) (a b : ob C)
(f : z_iso a b) : f· inv_from_z_iso f = identity _ :=
pr1 (pr2 (pr2 f)).

Definition z_iso_after_z_iso_inv (C : precategory_data) (a b : ob C)
(f : z_iso a b) : inv_from_z_iso f · f = identity _ :=
pr2 (pr2 (pr2 f)).

Lemma z_iso_inv_on_right (C : precategory) (a b c: ob C)
(f : z_iso a b) (g : b --> c) (h : a --> c) (H : h = f·g) :
inv_from_z_iso f · h = g.
Proof.
assert (H2 : inv_from_z_iso f· h =
inv_from_z_iso f· (f · g)).
apply maponpaths; assumption.
rewrite assoc in H2.
rewrite H2.
rewrite z_iso_after_z_iso_inv.
apply id_left.
Qed.

Lemma z_iso_inv_on_left (C : precategory) (a b c: ob C)
(f : a --> b) (g : z_iso b c) (h : a --> c) (H : h = f·g) :
f = h · inv_from_z_iso g.
Proof.
assert (H2 : h · inv_from_z_iso g =
(f· g) · inv_from_z_iso g).
rewrite H. apply idpath.
rewrite <- assoc in H2.
rewrite z_iso_inv_after_z_iso in H2.
rewrite id_right in H2.
apply pathsinv0.
assumption.
Qed.

Lemma z_iso_inv_to_left (C : precategory) (a b c: ob C)
(f : z_iso a b) (g : b --> c) (h : a --> c) :
inv_from_z_iso f · h = g h = f · g.
Proof.
intro H.
transitivity (f· inv_from_z_iso f· h).
- rewrite z_iso_inv_after_z_iso, id_left; apply idpath.
- rewrite <- assoc. rewrite H. apply idpath.
Qed.

Lemma z_iso_inv_to_right (C : precategory) (a b c: ob C)
(f : a --> b) (g : z_iso b c) (h : a --> c) :
f = h · inv_from_z_iso g f · g = h.
Proof.
intro H.
transitivity (h· inv_from_z_iso g· g).
- rewrite H. apply idpath.
- rewrite <- assoc, z_iso_after_z_iso_inv, id_right. apply idpath.
Qed.

Lemma wrap_inverse {M:precategory} {x y : M} (g : x --> x) (f : z_iso x y) :
g = identity x z_iso_inv f · g · f = identity y.
Proof.
intros e. rewrite e. rewrite id_right. apply z_iso_after_z_iso_inv.
Defined.

Lemma wrap_inverse' {M:precategory} {x y : M} (g : x --> x) (f : z_iso y x) :
g = identity x f · g · z_iso_inv f = identity y.
Proof.
intros e. rewrite e. rewrite id_right. apply z_iso_inv_after_z_iso.
Defined.

Lemma cancel_z_iso {M:precategory} {x y z : M} (f f' : x --> y) (g : z_iso y z) :
f · g = f' · g f = f'.
Proof.
intros e.
refine (_ @ maponpaths (λ k, k · z_iso_inv g) e @ _).
- rewrite assoc'. rewrite z_iso_inv_after_z_iso. rewrite id_right. reflexivity.
- rewrite assoc'. rewrite z_iso_inv_after_z_iso. rewrite id_right. reflexivity.
Qed.

Lemma cancel_z_iso' {M:precategory} {w x y : M} (g : z_iso w x) (f f' : x --> y) :
g · f = g · f' f = f'.
Proof.
intros e.
refine (_ @ maponpaths (λ k, z_iso_inv g · k) e @ _).
- rewrite assoc. rewrite z_iso_inv_after_z_iso. rewrite id_left. reflexivity.
- rewrite assoc. rewrite z_iso_inv_after_z_iso. rewrite id_left. reflexivity.
Qed.

Properties of 0-isomorphisms

Stability under composition, inverses etc

Lemma are_inverse_comp_of_inverses (C : precategory) (a b c : C)
(f : z_iso a b) (g : z_iso b c) :
is_inverse_in_precat (f· g) (inv_from_z_iso g· inv_from_z_iso f).
Proof.
simpl; split; simpl;
unfold inv_from_iso; simpl.
destruct f as [f [f' Hf]]. simpl in ×.
destruct g as [g [g' Hg]]; simpl in ×.
intermediate_path ((f · (g · g')) · f').
repeat rewrite assoc; apply idpath.
rewrite (pr1 Hg).
rewrite id_right.
rewrite (pr1 Hf).
apply idpath.

destruct f as [f [f' Hf]]. simpl in ×.
destruct g as [g [g' Hg]]; simpl in ×.
intermediate_path ((g' · (f' · f)) · g).
repeat rewrite assoc; apply idpath.
rewrite (pr2 Hf).
rewrite id_right.
rewrite (pr2 Hg).
apply idpath.
Qed.

Lemma inv_z_iso_unique (C : precategory) (hs: has_homsets C) (a b : ob C)
(f : z_iso a b) (g : z_iso b a) :
is_inverse_in_precat f g g = z_iso_inv_from_z_iso f.
Proof.
intro H.
apply eq_z_iso.
apply hs.
apply (inverse_unique_precat _ _ _ f).
assumption.
split.
apply z_iso_inv_after_z_iso.
set (h := z_iso_after_z_iso_inv _ _ _ f).
apply h.
Qed.

Lemma z_iso_inv_of_z_iso_comp (C : precategory) (hs: has_homsets C) (a b c : ob C)
(f : z_iso a b) (g : z_iso b c) :
z_iso_inv_from_z_iso (z_iso_comp f g) =
z_iso_comp (z_iso_inv_from_z_iso g) (z_iso_inv_from_z_iso f).
Proof.
apply eq_z_iso.
apply hs.
reflexivity.
Defined.

Lemma z_iso_inv_of_z_iso_id (C : precategory) (hs: has_homsets C) (a : ob C) :
z_iso_inv_from_z_iso (identity_z_iso a) = identity_z_iso a.
Proof.
apply eq_z_iso.
apply hs.
apply idpath.
Qed.

Lemma z_iso_inv_z_iso_inv (C : precategory) (hs: has_homsets C) (a b : ob C) (f : z_iso a b) :
z_iso_inv_from_z_iso (z_iso_inv_from_z_iso f) = f.
Proof.
apply eq_z_iso.
apply hs.
reflexivity.
Defined.

Lemma z_iso_comp_right_isweq {C:precategory} {a b:ob C} (h:z_iso a b) (c:C) :
isweq (fun f : b --> ch · f).
Proof.
intros. apply (isweq_iso _ (λ g, inv_from_z_iso h · g)).
{ intros f. use (_ @ maponpaths (λ m, m · f) (pr2 (pr2 (pr2 h))) @ _).
{ apply assoc. } { apply id_left. } }
{ intros g. use (_ @ maponpaths (λ m, m · g) (pr1 (pr2 (pr2 h))) @ _).
{ apply assoc. } { apply id_left. } }
Defined.

Definition z_iso_comp_right_weq {C:precategory} {a b:C} (h:z_iso a b) (c:C) :
(b --> c) (a --> c) := make_weq _ (z_iso_comp_right_isweq h c).

Lemma z_iso_comp_left_isweq {C:precategory} {a b:ob C} (h:z_iso a b) (c:C) :
isweq (fun f : c --> af · h).
Proof.
intros. apply (isweq_iso _ (λ g, g · inv_from_z_iso h)).
{ intros f. use (_ @ maponpaths (λ m, f·m) (pr1 (pr2 (pr2 h))) @ _).
{ apply pathsinv0. apply assoc. } { apply id_right. } }
{ intros g. use (_ @ maponpaths (λ m, g·m) (pr2 (pr2 (pr2 h))) @ _).
{ apply pathsinv0, assoc. } { apply id_right. } }
Defined.
Definition z_iso_comp_left_weq {C:precategory} {a b:C} (h:z_iso a b) (c:C) :
(c --> a) (c --> b) := make_weq _ (z_iso_comp_left_isweq h c).

Definition z_iso_conjug_weq {C:precategory} {a b:C} (h:z_iso a b) :
(a --> a) (b --> b) := weqcomp (z_iso_comp_left_weq h _ )
(z_iso_comp_right_weq (z_iso_inv_from_z_iso h) _ ).

Lemma is_iso_from_is_z_iso {C: precategory}{a b : C} (f: a --> b) :
is_z_isomorphism f is_iso f.
Proof.
intro H.
apply (is_iso_qinv _ (pr1 H)).
apply (pr2 H).
Defined.

Definition z_iso_to_iso {C : precategory} {b c : C} (f : z_iso b c) : iso b c
:= pr1 f ,, is_iso_from_is_z_iso (pr1 f) (pr2 f).

Lemma is_z_iso_from_is_iso {C: precategory}{a b : C} (f: a --> b):
is_iso f is_z_isomorphism f.
Proof.
intro H.
set (fiso:= make_iso f H).
(inv_from_iso fiso).
split.
- set (H2:= iso_inv_after_iso fiso).
simpl in H2. apply H2.
- set (H2:=iso_after_iso_inv fiso).
simpl in H2. apply H2.
Defined.

Lemma is_z_iso_from_is_iso' (C : precategory) {b c : C} (f : b --> c) :
is_iso' f is_z_isomorphism f.
Proof.
intros i.
assert (Q := i c (identity c)). induction Q as [[g E] _]. unfold postcomp_with in E.
g. split.
2 : { exact E. }
assert (X := id_left _ : postcomp_with f (identity _) = f).
assert (Y := ! assoc _ _ _ @ maponpaths (precomp_with f) E @ id_right _
: postcomp_with f (f · g) = f).
clear E.
set (x := (_,,X) : hfiber (postcomp_with f) f).
set (y := (_,,Y) : hfiber (postcomp_with f) f).
exact (maponpaths pr1 ((proofirrelevance _ (isapropifcontr (i b f))) y x)).
Defined.

Definition iso_to_z_iso {C : precategory} {b c : C} : iso b c z_iso b c
:= λ f, pr1 f ,, is_z_iso_from_is_iso (pr1 f) (pr2 f).

The right inverse of an invertible morphism must be equal to the known (two-sided) inverse. TODO: Did I switch up right and left here vis a vis the conventional use?
Lemma right_inverse_of_iso_is_inverse {C : precategory} {c c' : C}
(f : c --> c')
(g : c' --> c) (H : is_inverse_in_precat f g)
(h : c' --> c) (HH : f · h = identity _) :
h = g.
Proof.
refine (!id_left _ @ _).
refine (maponpaths (fun zz · h) (!is_inverse_in_precat2 H) @ _).
refine (!assoc _ _ _ @ _).
refine (maponpaths (fun zg · z) HH @ _).
apply id_right.
Qed.

Lemma left_inverse_of_iso_is_inverse {C : precategory} {c c' : C}
(f : c --> c')
(g : c' --> c) (H : is_inverse_in_precat f g)
(h : c' --> c) (HH : h · f = identity _) :
h = g.
Proof.
refine (!id_right _ @ _).
refine (maponpaths (fun zh · z) (!is_inverse_in_precat1 H) @ _).
refine (assoc _ _ _ @ _).
refine (maponpaths (fun zz · g) HH @ _).
apply id_left.
Qed.