Library UniMath.Bicategories.ComprehensionCat.ComprehensionEso

Require Import UniMath.Foundations.All.
Require Import UniMath.MoreFoundations.All.
Require Import UniMath.CategoryTheory.Core.Prelude.
Require Import UniMath.CategoryTheory.Equivalences.Core.
Require Import UniMath.CategoryTheory.Limits.Terminal.
Require Import UniMath.CategoryTheory.Limits.Equalizers.
Require Import UniMath.CategoryTheory.Limits.Pullbacks.
Require Import UniMath.CategoryTheory.Limits.Preservation.
Require Import UniMath.CategoryTheory.DisplayedCats.Core.
Require Import UniMath.CategoryTheory.DisplayedCats.Isos.
Require Import UniMath.CategoryTheory.DisplayedCats.Univalence.
Require Import UniMath.CategoryTheory.DisplayedCats.Functors.
Require Import UniMath.CategoryTheory.DisplayedCats.NaturalTransformations.
Require Import UniMath.CategoryTheory.DisplayedCats.Equivalences.
Require Import UniMath.CategoryTheory.DisplayedCats.EquivalenceOverId.
Require Import UniMath.CategoryTheory.DisplayedCats.Fiber.
Require Import UniMath.CategoryTheory.DisplayedCats.Fibrations.
Require Import UniMath.CategoryTheory.DisplayedCats.Fiberwise.FiberwiseTerminal.
Require Import UniMath.CategoryTheory.DisplayedCats.Fiberwise.FiberwiseProducts.
Require Import UniMath.CategoryTheory.DisplayedCats.Fiberwise.FiberwiseEqualizers.
Require Import UniMath.CategoryTheory.DisplayedCats.Fiberwise.DependentSums.
Require Import UniMath.CategoryTheory.DisplayedCats.Codomain.
Require Import UniMath.CategoryTheory.DisplayedCats.FullyFaithfulDispFunctor.
Require Import UniMath.Bicategories.Core.Bicat.
Import Bicat.Notations.
Require Import UniMath.Bicategories.ComprehensionCat.BicatOfCompCat.
Require Import UniMath.Bicategories.ComprehensionCat.CompCatNotations.
Require Import UniMath.Bicategories.ComprehensionCat.DFLCompCat.
Require Import UniMath.Bicategories.ComprehensionCat.DFLCompCatNotations.

Local Open Scope cat.
Local Open Scope comp_cat.

Section ComprehensionEso.
  Context (C : dfl_full_comp_cat).

  Section Eso.
    Context {Γ Δ : C}
            (δ : Δ --> Γ).

    Let Δδ : disp_codomain C Γ := (Δ ,, δ).

We first use democracy to obtain types representing the involved contexts
    Let : ty [] := dfl_con_to_ty Γ.
    Let : ty [] := dfl_con_to_ty Δ.

    Let γΓ : z_iso Γ ([] & )
      := dfl_con_to_z_iso Γ.
    Let γΔ : z_iso Δ ([] & )
      := dfl_con_to_z_iso Δ.

    Let DΔ' : ty Γ
      := [[ TerminalArrow _ Γ ]].
    Let DΓ' : ty (Γ & DΔ')
      := [[ TerminalArrow _ (Γ & DΔ') ]].

Now we have two pullback squares coming from substitution
    Let : Pullback (π ) (TerminalArrow [] Γ)
      := comp_cat_pullback (TerminalArrow _ Γ).

    Let : Pullback (π ) (TerminalArrow [] (Γ & DΔ'))
      := comp_cat_pullback (TerminalArrow _ (Γ & DΔ')).

We define two terms of type `Γ` in context `Γ & DΔ'` Of these terms, we shall take the equalizer
    Local Definition left_mor
      : C Γ & DΔ', (Γ & DΔ') & DΓ' .
    Show proof.
      use (PullbackArrow ).
      - exact (π _ · γΓ).
      - apply identity.
      - apply TerminalArrowEq.

    Local Definition left_tm
      : comp_cat_tm (Γ & DΔ') DΓ'.
    Show proof.
      use make_comp_cat_tm.
      - exact left_mor.
      - abstract
          (exact (PullbackArrow_PullbackPr2 _ _ _ _)).

    Local Lemma left_tm_pr1
      : left_tm · PullbackPr1 = π DΔ' · γΓ.
    Show proof.
      exact (PullbackArrow_PullbackPr1 _ _ _ _).

    Local Lemma left_tm_pr2
      : left_tm · π _ = identity _.
    Show proof.
      exact (PullbackArrow_PullbackPr2 _ _ _ _).

    Local Definition right_mor
      : C Γ & DΔ', (Γ & DΔ') & DΓ' .
    Show proof.
      use (PullbackArrow ).
      - exact (PullbackPr1 · inv_from_z_iso γΔ · δ · γΓ).
      - apply identity.
      - apply TerminalArrowEq.

    Local Definition right_tm
      : comp_cat_tm (Γ & DΔ') DΓ'.
    Show proof.
      use make_comp_cat_tm.
      - exact right_mor.
      - abstract
          (exact (PullbackArrow_PullbackPr2 _ _ _ _)).

    Local Lemma right_tm_pr1
      : right_tm · PullbackPr1
        =
        PullbackPr1 · inv_from_z_iso γΔ · δ · γΓ.
    Show proof.
      exact (PullbackArrow_PullbackPr1 _ _ _ _).

    Local Lemma right_tm_pr2
      : right_tm · π _ = identity _.
    Show proof.
      exact (PullbackArrow_PullbackPr2 _ _ _ _).

    Local Definition comprehension_eso_ty_help
      : ty (Γ & DΔ')
      := EqualizerObject (dfl_ext_identity left_tm right_tm).

Now we define a preimage of the map `δ` (which is needed for essential surjectivity). Intuitively, this type represents the fiber of `δ`. For every `y : Γ`, the inhabitants of this type are elements `x` of `Δ` such that `δ` maps `x` to `y`.
    Definition comprehension_eso_ty
      : ty Γ
      := dfl_sigma_type DΔ' comprehension_eso_ty_help.

    Let fib : ty Γ := comprehension_eso_ty.

Note that since we have strong sigma types, we can make this a context extension with two types. We also give a name to this extended context.
    Let : C := Γ & DΔ' & comprehension_eso_ty_help.

    Definition comprehension_eso_ty_iso
      : z_iso (Γ & fib)
      := dfl_sigma_type_strong DΔ' comprehension_eso_ty_help.

    Definition comprehension_eso_mor_help : --> Δ
      := π _ · PullbackPr1 · inv_from_z_iso γΔ.

    Definition comprehension_eso_inv_mor_help_sub : Δ --> Γ & DΔ'.
    Show proof.
      use (PullbackArrow ).
      - exact γΔ.
      - exact δ.
      - apply TerminalArrowEq.

    Proposition comprehension_eso_inv_mor_help_sub_pr1
      : comprehension_eso_inv_mor_help_sub · PullbackPr1 = γΔ.
    Show proof.
      apply (PullbackArrow_PullbackPr1 ).

    Proposition comprehension_eso_inv_mor_help_sub_pr2
      : comprehension_eso_inv_mor_help_sub · π _ = δ.
    Show proof.
      apply (PullbackArrow_PullbackPr2 ).

    Definition comprehension_eso_inv_mor_help_tm
      : comp_cat_tm
          Δ
          (dfl_ext_identity_type
             (sub_comp_cat_tm
                left_tm
                comprehension_eso_inv_mor_help_sub)
             (sub_comp_cat_tm
                right_tm
                comprehension_eso_inv_mor_help_sub)).
    Show proof.
      use dfl_ext_identity_type_tm.
      use (MorphismsIntoPullbackEqual
             (isPullback_Pullback
                (comp_cat_pullback DΓ' comprehension_eso_inv_mor_help_sub))).
      - rewrite !assoc'.
        rewrite !sub_comp_cat_tm_pr1.
        use (MorphismsIntoPullbackEqual (isPullback_Pullback )).
        + rewrite !assoc'.
          apply maponpaths.
          rewrite left_tm_pr1, right_tm_pr1.
          rewrite !assoc.
          etrans.
          {
            apply maponpaths_2.
            exact comprehension_eso_inv_mor_help_sub_pr2.
          }
          refine (!_).
          etrans.
          {
            do 3 apply maponpaths_2.
            exact comprehension_eso_inv_mor_help_sub_pr1.
          }
          rewrite z_iso_inv_after_z_iso.
          rewrite id_left.
          apply idpath.
        + rewrite !assoc'.
          etrans.
          {
            do 2 apply maponpaths.
            apply left_tm_pr2.
          }
          refine (!_).
          etrans.
          {
            do 2 apply maponpaths.
            apply right_tm_pr2.
          }
          rewrite !id_right.
          apply idpath.
      - rewrite !assoc'.
        etrans.
        {
          apply maponpaths.
          apply sub_comp_cat_tm_pr2.
        }
        refine (!_).
        etrans.
        {
          apply maponpaths.
          apply sub_comp_cat_tm_pr2.
        }
        apply idpath.

    Definition comprehension_eso_inv_mor_help : Δ --> .
    Show proof.
      use sub_to_extension.
      - exact comprehension_eso_inv_mor_help_sub.
      - use dfl_ext_identity_sub_tm.
        exact comprehension_eso_inv_mor_help_tm.

    Definition comprehension_eso_mor
      : Γ & fib --> Δ
      := inv_from_z_iso comprehension_eso_ty_iso · comprehension_eso_mor_help.

    Proposition comprehension_eso_mor_eq
      : comprehension_eso_mor · δ = π fib.
    Show proof.
      unfold comprehension_eso_mor.
      rewrite !assoc'.
      use z_iso_inv_on_right.
      refine (_ @ !(dependent_sum_map_eq _ _ _)).
      unfold comprehension_eso_mor_help.
      use (cancel_z_iso _ _ γΓ).
      rewrite !assoc'.
      pose (maponpaths
              (λ z, z · PullbackPr1 )
              (!(dfl_ext_identity_eq left_tm right_tm))) as p.
      cbn -[left_tm right_tm PullbackPr1] in p.
      rewrite !assoc' in p.
      rewrite left_tm_pr1, right_tm_pr1 in p.
      rewrite !assoc' in p.
      exact p.

    Definition comprehension_eso_inv_mor
      : Δ --> Γ & fib
      := comprehension_eso_inv_mor_help · comprehension_eso_ty_iso.

The two constructed morphisms are inverses
    Proposition comprehension_eso_mor_inv_mor
      : comprehension_eso_mor · comprehension_eso_inv_mor
        =
        identity _.
    Show proof.
      unfold comprehension_eso_mor, comprehension_eso_inv_mor.
      rewrite !assoc'.
      use z_iso_inv_on_right.
      rewrite id_right.
      refine (_ @ id_left _).
      rewrite !assoc.
      apply maponpaths_2.
      unfold comprehension_eso_mor_help, comprehension_eso_inv_mor_help.
      unfold sub_to_extension.
      use eq_sub_to_extension.
      - rewrite id_left.
        rewrite !assoc'.
        etrans.
        {
          do 4 apply maponpaths.
          exact (PullbackSqrCommutes
                   (comp_cat_pullback
                      comprehension_eso_ty_help
                      comprehension_eso_inv_mor_help_sub)).
        }
        etrans.
        {
          do 3 apply maponpaths.
          rewrite !assoc.
          apply maponpaths_2.
          apply comp_cat_tm_eq.
        }
        rewrite id_left.
        unfold comprehension_eso_inv_mor_help_sub.
        refine (_ @ id_right _).
        use (MorphismsIntoPullbackEqual (isPullback_Pullback )).
        + rewrite !assoc'.
          rewrite (PullbackArrow_PullbackPr1 ).
          rewrite z_iso_after_z_iso_inv.
          rewrite id_left, id_right.
          apply idpath.
        + rewrite !assoc'.
          rewrite (PullbackArrow_PullbackPr2 ).
          rewrite id_left.
          use (cancel_z_iso _ _ γΓ).
          rewrite !assoc'.
          pose (maponpaths
                  (λ z, z · PullbackPr1 )
                  (!(dfl_ext_identity_eq left_tm right_tm))) as p.
          cbn -[left_tm right_tm PullbackPr1] in p.
          rewrite !assoc' in p.
          rewrite left_tm_pr1, right_tm_pr1 in p.
          rewrite !assoc' in p.
          cbn in p.
          exact p.
      - apply dfl_eq_subst_equalizer_tm.

    Proposition comprehension_eso_inv_mor_mor
      : comprehension_eso_inv_mor · comprehension_eso_mor
        =
        identity _.
    Show proof.
      unfold comprehension_eso_mor, comprehension_eso_inv_mor.
      rewrite !assoc'.
      etrans.
      {
        apply maponpaths.
        rewrite !assoc.
        rewrite z_iso_inv_after_z_iso.
        apply id_left.
      }
      unfold comprehension_eso_mor_help, comprehension_eso_inv_mor_help.
      unfold sub_to_extension.
      unfold dfl_ext_identity_sub_tm.
      simpl.
      rewrite !assoc'.
      etrans.
      {
        apply maponpaths.
        etrans.
        {
          apply maponpaths.
          rewrite !assoc.
          do 2 apply maponpaths_2.
          exact (PullbackSqrCommutes
                   (comp_cat_pullback
                      comprehension_eso_ty_help
                      comprehension_eso_inv_mor_help_sub)).
        }
        rewrite !assoc.
        etrans.
        {
          do 3 apply maponpaths_2.
          unfold comp_cat_comp_mor.
          apply comprehension_functor_mor_comm.
        }
        rewrite id_right.
        rewrite !assoc'.
        etrans.
        {
          apply maponpaths.
          rewrite !assoc.
          apply maponpaths_2.
          apply comprehension_eso_inv_mor_help_sub_pr1.
        }
        rewrite z_iso_inv_after_z_iso.
        apply id_right.
      }
      apply comp_cat_tm_eq.

    Definition is_z_iso_comprehension_eso_mor
      : is_z_isomorphism comprehension_eso_mor.
    Show proof.
      use make_is_z_isomorphism.
      - exact comprehension_eso_inv_mor.
      - split.
        + exact comprehension_eso_mor_inv_mor.
        + exact comprehension_eso_inv_mor_mor.

    Definition comprehension_eso_cod_mor
      : comp_cat_comprehension C Γ comprehension_eso_ty -->[ identity_z_iso Γ ] Δδ.
    Show proof.
      refine (comprehension_eso_mor ,, _) ; cbn.
      abstract
        (refine (_ @ !(id_right _)) ;
         exact comprehension_eso_mor_eq).

    Definition comprehension_eso_cod_iso
      : z_iso_disp
          (identity_z_iso Γ)
          (comp_cat_comprehension C Γ (comprehension_eso_ty))
          Δδ.
    Show proof.
      refine (comprehension_eso_cod_mor ,, _).
      use is_z_iso_disp_codomain.
      exact is_z_iso_comprehension_eso_mor.
  End Eso.

Now we conclude that the comprehension functor is essentially surjective. Since we are working with full comprehension categories, we immediately obtain that the comprehension functor is an equivalence. In addition, this allows us to conclude that it preserves limits.
  Definition comprehension_eso
    : disp_functor_disp_ess_split_surj (comp_cat_comprehension C)
    := λ Γ Δ,
       comprehension_eso_ty (pr2 Δ)
       ,,
       comprehension_eso_cod_iso (pr2 Δ).

  Definition is_equiv_over_id_comprehension
    : is_equiv_over_id (comp_cat_comprehension C).
  Show proof.

  Definition fiber_functor_comprehension_adj_equiv
             (Γ : C)
    : adj_equivalence_of_cats
        (fiber_functor (comp_cat_comprehension C) Γ)
    := fiber_equiv is_equiv_over_id_comprehension Γ.

  Definition preserves_terminal_fiber_functor_comprehension
             (Γ : C)
    : preserves_terminal (fiber_functor (comp_cat_comprehension C) Γ)
    := right_adjoint_preserves_terminal
         _
         (adj_equivalence_of_cats_inv
            _
            (fiber_functor_comprehension_adj_equiv Γ)).

  Definition preserves_binproduct_fiber_functor_comprehension
             (Γ : C)
    : preserves_binproduct (fiber_functor (comp_cat_comprehension C) Γ)
    := right_adjoint_preserves_binproduct
         _
         (adj_equivalence_of_cats_inv
            _
            (fiber_functor_comprehension_adj_equiv Γ)).

  Definition preserves_equalizer_fiber_functor_comprehension
             (Γ : C)
    : preserves_equalizer (fiber_functor (comp_cat_comprehension C) Γ)
    := right_adjoint_preserves_equalizer
         _
         (adj_equivalence_of_cats_inv
            _
            (fiber_functor_comprehension_adj_equiv Γ)).
End ComprehensionEso.

A property holds for all morphism if it holds for every display map
Proposition dfl_full_comp_cat_mor_ind_iso_help
            (C : dfl_full_comp_cat)
            (P : (Γ Δ : C), Γ --> Δ UU)
            (Pπ : (Γ : C) (A : ty Γ), P _ _ (π A))
            {Γ Γ' Δ : C}
            (p : Γ = Γ')
            {s : Γ --> Δ}
            {s' : Γ' --> Δ}
            (r : s = idtoiso p · s')
            (H : P _ _ s)
  : P _ _ s'.
Show proof.
  induction p.
  cbn in r.
  rewrite id_left in r.
  induction r.
  exact H.

Lemma dfl_full_comp_cat_mor_ind_iso
      (C : dfl_full_comp_cat)
      (P : (Γ Δ : C), Γ --> Δ UU)
      (Pπ : (Γ : C) (A : ty Γ), P _ _ (π A))
      {Γ Γ' Δ : C}
      (i : z_iso Γ Γ')
      {s : Γ --> Δ}
      {s' : Γ' --> Δ}
      (r : s = i · s')
      (H : P _ _ s)
  : P _ _ s'.
Show proof.
  simple refine (dfl_full_comp_cat_mor_ind_iso_help C P Pπ (isotoid _ _ i) _ H).
  - apply univalent_category_is_univalent.
  - rewrite idtoiso_isotoid.
    exact r.

Theorem dfl_full_comp_cat_mor_ind
        (C : dfl_full_comp_cat)
        (P : (Γ Δ : C), Γ --> Δ UU)
        (Pπ : (Γ : C) (A : ty Γ), P _ _ (π A))
        {Γ Δ : C}
        (s : Γ --> Δ)
  : P _ _ s.
Show proof.
  pose (A := comprehension_eso_ty C s).
  assert (s = comprehension_eso_inv_mor C s · π (comprehension_eso_ty C s)) as p.
  {
    rewrite <- comprehension_eso_mor_eq.
    rewrite !assoc.
    rewrite comprehension_eso_inv_mor_mor.
    rewrite id_left.
    apply idpath.
  }
  rewrite p.
  simple refine (dfl_full_comp_cat_mor_ind_iso C P Pπ _ _ (Pπ Δ A)).
  - refine (_ ,, _).
    apply is_z_iso_comprehension_eso_mor.
  - cbn.
    rewrite !assoc.
    refine (!_).
    etrans.
    {
      apply maponpaths_2.
      apply comprehension_eso_mor_inv_mor.
    }
    apply id_left.