Raw File
From HoTT Require Import Basics Types Spaces.Nat WildCat Pointed
                         AbGroups AbSES.

Require Import EquivalenceRelation.

Local Open Scope pointed_scope.
Local Open Scope type_scope.


(** * Length-n exact sequences *)

(** ** The type [ES n] of length [n] exact sequences *)

(** We define the type [ES n] of pairs of exact sequences that can be spliced (when n > 1), of which [Ext n] will be defined as a quotient by a certain equivalence relation. We could start the induction at n=1, but by starting at n=2 we get that [ES 1 B A] is definitionally [AbSES B A], which is preferable. *)
(* NB: [ES n] is not the real n-type of "length-n exact sequences," i.e., the classifying space of the category of such. Rather, it is an approximation which has the correct set-truncation. *)
Fixpoint ES' (n : nat) : AbGroup^op -> AbGroup -> Type
  := match n with
     | 0%nat => GroupHomomorphism
     | 1%nat => AbSES
     | S n => fun B A => exists M, (ES' n M A) * (AbSES B M)
     end.

Global Instance ispointed_es' (n : nat)
  : forall B A, IsPointed (ES' n B A).
Proof.
  induction n as [| [|n] IH].
  - intros; exact grp_homo_const.
  - intros; exact pt.
  - intros; exact (abgroup_trivial; (IH _ _, pt)).
Defined.

Definition ES (n : nat) : AbGroup^op -> AbGroup -> pType
  := fun B A => [ES' n B A, _].

(** *** Functoriality of [ES] *)

(** For proofs related to pushouts we have to quantify over the hypotheses to the right of [:] in order to make the induction go through. The proofs have similar structure, so an abstract approach (or tactic) is be warranted in the future. *)

(** The covariant action on [es] by pushing out. *)
Definition es_pushout `{Univalence} {n : nat}
  : forall {B A A' : AbGroup} (f : A $-> A'), ES n B A -> ES n B A'.
Proof.
  induction n as [| [|n] IH]; intros ? ? ? f.
  - exact (fun g => f $o g).
  - exact (abses_pushout f).
  - intros [M [F E]].
    exact (M; (IH _ _ _ f F, E)).
Defined.

Lemma es_pushout_id `{Univalence} {n : nat}
  : forall {B A : AbGroup} (F : ES n B A), es_pushout grp_homo_id F = F.
Proof.
  induction n as [| [|n] IH]; intros.
  - cbn. by apply equiv_path_grouphomomorphism.
  - nrapply abses_pushout_id.
  - snrapply path_sigma; only 1: reflexivity.
    (* the transport is trivial *)
    refine (path_prod' _ idpath).
    apply IH.
Defined.

Lemma es_pushout_point `{Univalence} {n : nat}
  : forall {B A A' : AbGroup} (g : A $-> A'),
    es_pushout g (pt : ES n B A) = pt.
Proof.
  induction n as [| [|n] IH]; intros ? ? ? g.
  - nrapply equiv_path_grouphomomorphism; intro b; cbn.
    apply grp_homo_unit.
  - nrapply abses_pushout_point.
  - snrapply path_sigma; only 1: reflexivity.
    refine (path_prod' _ idpath).
    apply IH.
Defined.

(** The contravariant action on [es] by pulling back. *)
Definition es_pullback `{Univalence} {n : nat}
  {B B' A : AbGroup} (g : B' $-> B)
  : ES n B A -> ES n B' A.
Proof.
  destruct n as [|[|]] ; cbn.
  - exact (fun phi => grp_homo_compose phi g).
  - exact (abses_pullback g).
  - intros [M [F E]].
    exact (M; (F, abses_pullback g E)).
Defined.

Lemma es_pullback_id `{Univalence} {n : nat}
  {B A : AbGroup} (F : ES n B A)
  : es_pullback grp_homo_id F = F.
Proof.
  induction n as [| [|n] IH].
  - by nrapply equiv_path_grouphomomorphism.
  - nrapply abses_pullback_id.
  - destruct F as [C [S E]]; cbn.
    snrapply path_sigma.
    1: reflexivity.
    unfold transport, pr2.
    exact (path_prod' idpath (abses_pullback_id E)).
Defined.

Lemma es_pullback_point `{Univalence} {n : nat}
  {B B' A : AbGroup} (f : B' $-> B)
  : es_pullback f (pt : ES n B A) = pt.
Proof.
  destruct n as [|[|]].
  - cbn. by nrapply equiv_path_grouphomomorphism.
  - nrapply abses_pullback_point.
  - snrapply path_sigma; only 1: cbn.
    1: reflexivity.
    unfold transport, es_pullback, pr2.
    exact (path_prod' idpath (abses_pullback_point _)).
Defined.

Definition es_pullback_compose `{Univalence} {n : nat}
  {B0 B1 B2 A : AbGroup} (f0 : B1 $-> B0) (f1 : B2 $-> B1)
  : es_pullback (n:=n) (A:=A) f1 o es_pullback f0 == es_pullback (f0 $o f1).
Proof.
  destruct n as [|[|]].
  - intro x; by nrapply equiv_path_grouphomomorphism.
  - cbn. nrapply abses_pullback_compose.
  - intros [M [F E]]; cbn.
    snrapply path_sigma.
    1: reflexivity.
    unfold transport, pr2.
    exact (path_prod' idpath (abses_pullback_compose _ _ _)).
Defined.

Definition es_pullback_homotopic `{Univalence} {n : nat} {B B' A : AbGroup}
  {f f' : B' $-> B} (h : f == f') : es_pullback (n:=n) (A:=A) f == es_pullback f'.
Proof.
  destruct n as [|[|]].
  - intro g; nrapply equiv_path_grouphomomorphism; intro b; cbn.
    exact (ap g (h b)).
  - cbn. by nrapply abses_pullback_homotopic.
  - intros [M [F E]]; cbn.
    snrapply path_sigma.
    1: reflexivity.
    apply path_prod'.
    + reflexivity.
    + by nrapply abses_pullback_homotopic.
Defined.

(** We can splice a longer exact sequence with a short exact sequence. *)
Definition es_abses_splice `{Univalence} {n : nat} {C B A : AbGroup}
  : ES n B A -> AbSES C B -> ES (S n) C A.
Proof.
  intros F E; destruct n.
  - exact (abses_pushout F E).
  - exact (B; (F, E)).
Defined.

Definition es_pushout_pullback_reorder `{Univalence} {n : nat}
  : forall {B B' A A' : AbGroup} (f : A $-> A') (g : B' $-> B) {E : ES n B A},
    es_pushout f (es_pullback g E) = es_pullback g (es_pushout f E).
Proof.
  induction n as [| [|n] IH]; intros.
  - by nrapply equiv_path_grouphomomorphism.
  - nrapply abses_pushout_pullback_reorder.
  - snrapply path_sigma.
    1: reflexivity.
    unfold transport.
    exact (path_prod' idpath idpath).
Defined.

(** We can splice arbitrary [ES]'s. When (n, m = 0) splicing reduces to composition of morphisms, and when (m = 0) it's given by [es_pullback]. *)
Definition es_splice `{Univalence} {n m : nat}
  : forall {C B A}, ES n B A -> ES m C B -> ES (add n m) C A.
Proof.
  induction m as [| [|m] IH]; intros ? ? ? E F.
  (* In the base case, we pull the left factor back. *)
  - rewrite <- nat_add_n_O.
    exact (es_pullback F E).
  - rewrite nat_add_comm. 
    exact (es_abses_splice E F).
  - rewrite <- nat_add_n_Sm.
    destruct F as [D [S T]].
    exact (es_abses_splice (IH _ _ _ E S) T).
Defined.


(** ** The equivalence relation on [ES] *)

(** We define a relation on [ES n] whose set-quotient will be defined to be [Ext n]. *)

(** This is the relation which will generate the equivalence relation we want. *)
Definition es_zig `{Univalence} {n : nat}
  : forall {B A : AbGroup}, Relation (ES n B A).
Proof.
  induction n as [|[|n] IH]; intros B A.
  1,2: exact paths.
  intros [M [F E]] [N [Y X]].
  exact { f : M $-> N & (IH _ _ F (es_pullback f Y)) * (abses_pushout f E = X) }.
Defined.
(* NB: On the inductive step, it might seem like we should have asked for an arbitrary zig-zag relating [E] and [es_pullback f F] above. However, such zig-zags on level [n] can be encoded as zig-zags on level [n+1]. Thus the generated equivalence relation [EqRel es_zig] will be the same. Working with a single zig is simpler, so we've chosen that. (As a sanity check, the function [rap_splice] below shows that splicing respects the generated equivalence relation.) *)

Local Instance reflexive_es_zig `{Univalence} {n : nat}
  : forall B A, Reflexive (@es_zig _ n B A).
Proof.
  induction n as [| [|n] IH]; intros.
  - exact _.
  - exact (fun _ => idpath).
  - intros [M [F E]].
    exists grp_homo_id; split.
    + rewrite es_pullback_id; nrapply IH.
    + nrapply abses_pushout_id.
Defined.

(** [es_zig] is intended to assert exactly this relation. *)
Definition es_morphism_abses_zig `{Univalence} {n : nat}
  {C B B' A : AbGroup} (F : ES n B' A) (phi : B $->  B') (E : ES 1 C B)
  : es_zig
      (es_abses_splice (es_pullback phi F) E)
      (es_abses_splice F (es_pushout phi E)).
Proof.
  destruct n as [|[|]]; only 1,2: cbn.
  - nrapply abses_pushout_compose.
  - exists phi; easy.
  - exists phi.
    nrefine (_, idpath).
    nrapply reflexive_es_zig.
Defined.

(** The equivalence relation generated by [es_zig]. *)
Definition es_eqrel `{Univalence} {n : nat} {B A : AbGroup}
  : Relation (ES n B A)
  := match n with
     | 0%nat => paths
     | 1%nat => paths
     | n => EqRel es_zig
     end.

Notation "E ~ F" := (es_eqrel E F) (at level 93).

Definition es_morphism_abses_eqrel `{Univalence} {n : nat}
  {C B B' A : AbGroup} (E : ES n.+1 B' A) (phi : B $->  B') (F : ES 1 C B)
  : es_abses_splice (es_pullback phi E) F ~
      es_abses_splice E (es_pushout phi F)
  := zig_to_eqrel _ (es_morphism_abses_zig E phi F).

Global Instance reflexive_es_eqrel `{Univalence} {n : nat} {B A : AbGroup}
  : Reflexive (@es_eqrel _ n B A)
  := ltac:(destruct n as [|[|]]; exact _).

Global Instance symmetric_es_eqrel `{Univalence} {n : nat} {B A : AbGroup}
  : Symmetric (@es_eqrel _ n B A)
  := ltac:(destruct n as [|[|]]; exact _).

Global Instance transitive_es_eqrel `{Univalence} {n : nat} {B A : AbGroup}
  : Transitive (@es_eqrel _ n B A)
  := ltac:(destruct n as [|[|]]; exact _).

(** The mere equivalence relation generated by [es_zig]. *)
Definition es_meqrel `{Univalence} {n : nat} {B A : AbGroup}
  : Relation (ES n B A)
  := match n with
     | 0%nat => paths
     | 1%nat => (fun A B => tr (n:=0) A = tr B)
     | n => MEqRel es_zig
     end.

(** *** Properties of the relation [es_zig]. *)

(** Pullback preserves [es_zig]. ("rap" is for "relation ap".) *)
Definition rap_pullback `{Univalence} {n : nat} {B B' A : AbGroup} (g : B' $-> B)
  : forall (F Y : ES n B A), F ~ Y -> es_pullback g F ~ es_pullback g Y.
Proof.
  destruct n as [|[|]].
  1,2: by intros ? ? []. (* path induction *)
  nrapply eqrel_generator; intros F Y [phi [p q]].
  nrefine (phi; (p, _)).
  nrefine (abses_pushout_pullback_reorder _ _ _ @ _).
  by nrapply (ap (abses_pullback g)).
Defined.

(** If you pull back along [grp_homo_const], you get a zig from [pt]. *)
Lemma es_pullback_const_zig `{Univalence} {n : nat}
  : forall {B B' A : AbGroup} (E : ES n B A),
    es_zig (pt : ES n B' A) (es_pullback grp_homo_const E).
Proof.
  induction n as [| [|n] IH]; intros.
  1: symmetry; nrapply equiv_path_grouphomomorphism; intro x; apply grp_homo_unit.
  1: nrapply abses_pullback_const.
  exists grp_homo_const; split.
  + nrapply IH.
  + cbn. exact (abses_pushout_point _ @ abses_pullback_const _).
Defined.

(** To show that pushout preserves the relation we first show, by induction, that it preserves the generating relation. *)
Definition rap_pushout_zig `{Univalence} {n : nat}
  : forall {B A A' : AbGroup} (f : A $-> A') (F Y : ES n B A),
    es_zig F Y -> es_zig (es_pushout f F) (es_pushout f Y).
Proof.
  induction n as [| [|n] IH].
  1,2: by intros ? ? ? ? ? ? []. (* path induction *)
  intros ? ? ? f [? [F0 F1]] [? [Y0 Y1]] [phi [p q]].
  exists phi; split.
  2: exact q.
  nrefine (transport (fun E => es_zig (es_pushout f F0) E) _ _).
  1: exact (es_pushout_pullback_reorder f phi (E:=Y0)).
  by apply IH.
Defined.

Definition rap_pushout `{Univalence} {n : nat} {B A A' : AbGroup}
  (f : A $-> A') (F Y : ES n B A)
  : F ~ Y -> es_pushout f F ~ es_pushout f Y.
Proof.
  induction n as [| [|n] IH].
  1,2: by intros []. (* path induction *)
  apply eqrel_generator, rap_pushout_zig.
Defined.

(** Splicing respects the relation. *)
Definition rap_splice `{Univalence} {n : nat} {C B A : AbGroup}
  (F Y : ES n B A) (E : AbSES C B)
  : F ~ Y -> es_abses_splice F E ~ es_abses_splice Y E.
Proof.
  destruct n as [|[|]].
  1,2: by intros []. (* path induction *)
  revert F Y; apply eqrel_generator; intros F Y zig.
  exists grp_homo_id; split; unfold es_abses_splice.
  - rewrite es_pullback_id; exact zig.
  - apply abses_pushout_id.
Defined.

Definition es_point_splice_abses `{Univalence} {n : nat} {C B A : AbGroup}
  (E : AbSES C B) : es_zig (es_abses_splice (pt : ES n B A) E) pt.
Proof.
  destruct n as [|].
  - cbn. apply abses_pushout_const.
  - exists grp_homo_const; split; unfold es_abses_splice.
    + apply es_pullback_const_zig.
    + apply abses_pushout_const.
Defined.

Definition es_splice_point_abses `{Univalence} {n : nat} {C B A : AbGroup}
  (F : ES n B A) : es_zig pt (es_abses_splice F (pt : AbSES C B)).
Proof.
  destruct n.
  - cbn; symmetry. apply abses_pushout_point.
  - exists grp_homo_const; split; unfold es_abses_splice.
    + nrapply es_pullback_const_zig.
    + apply abses_pushout_const.
Defined.
back to top