lean2/hott/algebra/category/constructions/pushout.hlean

499 lines
21 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2016 Floris van Doorn. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Floris van Doorn
The pushout of categories
The morphisms in the pushout of two categories is defined as a quotient on lists of composable
morphisms. For this we use the notion of paths in a graph.
-/
import ..category ..nat_trans hit.set_quotient algebra.relation ..groupoid algebra.graph
.functor
open eq is_trunc functor trunc sum set_quotient relation iso category sigma nat nat_trans
/- we first define the categorical structure on paths in a graph -/
namespace paths
section
parameters {A : Type} {R : A → A → Type}
(Q : Π⦃a a' : A⦄, paths R a a' → paths R a a' → Type)
variables ⦃a a' a₁ a₂ a₃ a₄ : A⦄
definition paths_trel [constructor] (l l' : paths R a a') : Prop :=
∥paths_rel Q l l'∥
local notation `S` := @paths_trel
definition paths_quotient (a a' : A) : Type := set_quotient (@S a a')
local notation `mor` := paths_quotient
local attribute paths_quotient [reducible]
definition is_reflexive_R : is_reflexive (@S a a') :=
begin constructor, intro s, apply tr, constructor end
local attribute is_reflexive_R [instance]
definition paths_compose [unfold 7 8] (g : mor a₂ a₃) (f : mor a₁ a₂) : mor a₁ a₃ :=
begin
refine quotient_binary_map _ _ g f, exact append,
intros, refine trunc_functor2 _ r s, exact rel_respect_append
end
definition paths_id [constructor] (a : A) : mor a a :=
class_of nil
local infix ` ∘∘ `:60 := paths_compose
local notation `p1` := paths_id _
theorem paths_assoc (h : mor a₃ a₄) (g : mor a₂ a₃) (f : mor a₁ a₂) :
h ∘∘ (g ∘∘ f) = (h ∘∘ g) ∘∘ f :=
begin
induction h using set_quotient.rec_prop with h,
induction g using set_quotient.rec_prop with g,
induction f using set_quotient.rec_prop with f,
rewrite [▸*, append_assoc]
end
theorem paths_id_left (f : mor a a') : p1 ∘∘ f = f :=
begin
induction f using set_quotient.rec_prop with f,
reflexivity
end
theorem paths_id_right (f : mor a a') : f ∘∘ p1 = f :=
begin
induction f using set_quotient.rec_prop with f,
rewrite [▸*, append_nil]
end
definition Precategory_paths [constructor] : Precategory :=
precategory.MK A
mor
_
paths_compose
paths_id
paths_assoc
paths_id_left
paths_id_right
/- given a way to reverse edges and some additional properties we can extend this to a
groupoid structure -/
parameters (inv : Π⦃a a' : A⦄, R a a' → R a' a)
(rel_inv : Π⦃a a' : A⦄ {l l' : paths R a a'},
Q l l' → paths_rel Q (reverse inv l) (reverse inv l'))
(li : Π⦃a a' : A⦄ (r : R a a'), paths_rel Q [inv r, r] nil)
(ri : Π⦃a a' : A⦄ (r : R a a'), paths_rel Q [r, inv r] nil)
include rel_inv li ri
definition paths_inv [unfold 8] (f : mor a a') : mor a' a :=
begin
refine quotient_unary_map (reverse inv) _ f,
intros, refine trunc_functor _ _ r, esimp,
intro s, apply rel_respect_reverse inv s rel_inv
end
local postfix `^`:max := paths_inv
theorem paths_left_inv (f : mor a₁ a₂) : f^ ∘∘ f = p1 :=
begin
induction f using set_quotient.rec_prop with f,
esimp, apply eq_of_rel, apply tr,
apply rel_left_inv, apply li
end
theorem paths_right_inv (f : mor a₁ a₂) : f ∘∘ f^ = p1 :=
begin
induction f using set_quotient.rec_prop with f,
esimp, apply eq_of_rel, apply tr,
apply rel_right_inv, apply ri
end
definition Groupoid_paths [constructor] : Groupoid :=
groupoid.MK Precategory_paths
(λa b f, is_iso.mk (paths_inv f) (paths_left_inv f) (paths_right_inv f))
end
end paths
open paths
namespace category
/- We also define the pushout of two groupoids with a type of basepoints, which are surjectively
mapped into C (although we don't need to assume that this mapping is surjective for the
definition) -/
section
inductive bpushout_prehom_index {S : Type} {C D E : Precategory} (k : S → C) (F : C ⇒ D)
(G : C ⇒ E) : D + E → D + E → Type :=
| iD : Π{d d' : D} (f : d ⟶ d'), bpushout_prehom_index k F G (inl d) (inl d')
| iE : Π{e e' : E} (g : e ⟶ e'), bpushout_prehom_index k F G (inr e) (inr e')
| DE : Π(s : S), bpushout_prehom_index k F G (inl (F (k s))) (inr (G (k s)))
| ED : Π(s : S), bpushout_prehom_index k F G (inr (G (k s))) (inl (F (k s)))
open bpushout_prehom_index
definition bpushout_prehom {S : Type} {C D E : Precategory} (k : S → C) (F : C ⇒ D) (G : C ⇒ E) :
D + E → D + E → Type :=
paths (bpushout_prehom_index k F G)
inductive bpushout_hom_rel_index {S : Type} {C D E : Precategory} (k : S → C) (F : C ⇒ D)
(G : C ⇒ E) : Π⦃x x' : D + E⦄,
bpushout_prehom k F G x x' → bpushout_prehom k F G x x' → Type :=
| DD : Π{d₁ d₂ d₃ : D} (g : d₂ ⟶ d₃) (f : d₁ ⟶ d₂),
bpushout_hom_rel_index k F G [iD k F G g, iD k F G f] [iD k F G (g ∘ f)]
| EE : Π{e₁ e₂ e₃ : E} (g : e₂ ⟶ e₃) (f : e₁ ⟶ e₂),
bpushout_hom_rel_index k F G [iE k F G g, iE k F G f] [iE k F G (g ∘ f)]
| DED : Π(s : S), bpushout_hom_rel_index k F G [ED k F G s, DE k F G s] nil
| EDE : Π(s : S), bpushout_hom_rel_index k F G [DE k F G s, ED k F G s] nil
| idD : Π(d : D), bpushout_hom_rel_index k F G [iD k F G (ID d)] nil
| idE : Π(e : E), bpushout_hom_rel_index k F G [iE k F G (ID e)] nil
| cohDE : Π{s₁ s₂ : S} (h : k s₁ ⟶ k s₂),
bpushout_hom_rel_index k F G [iE k F G (G h), DE k F G s₁] [DE k F G s₂, iD k F G (F h)]
| cohED : Π{s₁ s₂ : S} (h : k s₁ ⟶ k s₂),
bpushout_hom_rel_index k F G [ED k F G s₂, iE k F G (G h)] [iD k F G (F h), ED k F G s₁]
open bpushout_hom_rel_index paths.paths_rel
definition Precategory_bpushout [constructor] {S : Type} {C D E : Precategory}
(k : S → C) (F : C ⇒ D) (G : C ⇒ E) : Precategory :=
Precategory_paths (bpushout_hom_rel_index k F G)
parameters {C D E X : Precategory} (F : C ⇒ D) (G : C ⇒ E) (H : D ⇒ X) (K : E ⇒ X)
(η : H ∘f F ≅ K ∘f G)
definition Cpushout [constructor] : Precategory :=
Precategory_bpushout (λc, c) F G
definition Cpushout_inl [constructor] : D ⇒ Cpushout :=
begin
fapply functor.mk,
{ exact inl},
{ intro d d' f, exact class_of [iD (λc, c) F G f]},
{ intro d, refine eq_of_rel (tr (paths_rel_of_Q _)), apply idD},
{ intro d₁ d₂ d₃ g f, refine (eq_of_rel (tr (paths_rel_of_Q _)))⁻¹, apply DD}
end
definition Cpushout_inr [constructor] : E ⇒ Cpushout :=
begin
fapply functor.mk,
{ exact inr},
{ intro e e' f, exact class_of [iE (λc, c) F G f]},
{ intro e, refine eq_of_rel (tr (paths_rel_of_Q _)), apply idE},
{ intro e₁ e₂ e₃ g f, refine (eq_of_rel (tr (paths_rel_of_Q _)))⁻¹, apply EE}
end
definition Cpushout_coh [constructor] : Cpushout_inl ∘f F ≅ Cpushout_inr ∘f G :=
begin
fapply natural_iso.MK,
{ intro c, exact class_of [DE (λ c, c) F G c]},
{ intro c c' f, refine eq_of_rel (tr (paths_rel_of_Q !cohDE))},
{ intro c, exact class_of [ED (λ c, c) F G c]},
{ intro c, refine eq_of_rel (tr (paths_rel_of_Q !DED))},
{ intro c, refine eq_of_rel (tr (paths_rel_of_Q !EDE))},
end
--(class_of [DE (λ c, c) F G s])
variables ⦃x x' x₁ x₂ x₃ : Cpushout⦄
include H K
local notation `R` := bpushout_prehom_index (λ c, c) F G
local notation `Q` := bpushout_hom_rel_index (λ c, c) F G
definition Cpushout_functor_ob [unfold 9] (x : Cpushout) : X :=
begin
induction x with d e,
{ exact H d},
{ exact K e}
end
include η
parameters {F G H K}
definition Cpushout_functor_reduction_rule [unfold 12] (i : R x x') :
Cpushout_functor_ob x ⟶ Cpushout_functor_ob x' :=
begin
induction i,
{ exact H f},
{ exact K g},
{ exact natural_map (to_hom η) s},
{ exact natural_map (to_inv η) s}
end
definition Cpushout_functor_list (l : paths R x x') :
Cpushout_functor_ob x ⟶ Cpushout_functor_ob x' :=
realize _
Cpushout_functor_reduction_rule
(λa, id)
(λa b c g f, f ∘ g) l
definition Cpushout_functor_list_nil (x : Cpushout) :
Cpushout_functor_list (@nil _ _ x) = id :=
idp
definition Cpushout_functor_list_cons (r : R x₂ x₃) (l : paths R x₁ x₂) :
Cpushout_functor_list (r :: l) = Cpushout_functor_reduction_rule r ∘ Cpushout_functor_list l :=
idp
definition Cpushout_functor_list_singleton (r : R x₁ x₂) :
Cpushout_functor_list [r] = Cpushout_functor_reduction_rule r :=
realize_singleton (λa b f, id_right f) r
definition Cpushout_functor_list_pair (r₂ : R x₂ x₃) (r₁ : R x₁ x₂) :
Cpushout_functor_list [r₂, r₁] =
Cpushout_functor_reduction_rule r₂ ∘ Cpushout_functor_reduction_rule r₁ :=
realize_pair (λa b f, id_right f) r₂ r₁
definition Cpushout_functor_list_append (l₂ : paths R x₂ x₃) (l₁ : paths R x₁ x₂) :
Cpushout_functor_list (l₂ ++ l₁) = Cpushout_functor_list l₂ ∘ Cpushout_functor_list l₁ :=
realize_append (λa b c d h g f, assoc f g h) (λa b f, id_left f) l₂ l₁
theorem Cpushout_functor_list_rel {l l' : paths R x x'} (q : Q l l') :
Cpushout_functor_list l = Cpushout_functor_list l' :=
begin
induction q,
{ rewrite [Cpushout_functor_list_pair, Cpushout_functor_list_singleton],
exact (respect_comp H g f)⁻¹},
{ rewrite [Cpushout_functor_list_pair, Cpushout_functor_list_singleton],
exact (respect_comp K g f)⁻¹},
{ rewrite [Cpushout_functor_list_pair, Cpushout_functor_list_nil],
exact ap010 natural_map (to_left_inverse η) s},
{ rewrite [Cpushout_functor_list_pair, Cpushout_functor_list_nil],
exact ap010 natural_map (to_right_inverse η) s},
{ rewrite [Cpushout_functor_list_singleton, Cpushout_functor_list_nil], exact respect_id H d},
{ rewrite [Cpushout_functor_list_singleton, Cpushout_functor_list_nil], exact respect_id K e},
{ rewrite [+Cpushout_functor_list_pair], exact naturality (to_hom η) h},
{ rewrite [+Cpushout_functor_list_pair], exact (naturality (to_inv η) h)⁻¹}
end
definition Cpushout_functor_hom [unfold 12] (f : x ⟶ x') :
Cpushout_functor_ob x ⟶ Cpushout_functor_ob x' :=
begin
induction f with l l l' q,
{ exact Cpushout_functor_list l},
{ esimp at *, induction q with q, refine realize_eq _ _ _ q,
{ intros, apply assoc},
{ intros, apply id_left},
intro a₁ a₂ l₁ l₁ q, exact Cpushout_functor_list_rel q}
end
definition Cpushout_functor [constructor] : Cpushout ⇒ X :=
begin
fapply functor.mk,
{ exact Cpushout_functor_ob},
{ exact Cpushout_functor_hom},
{ intro x, reflexivity},
{ intro x₁ x₂ x₃ g f,
induction g using set_quotient.rec_prop with l₂,
induction f using set_quotient.rec_prop with l₁,
exact Cpushout_functor_list_append l₂ l₁}
end
definition Cpushout_functor_inl [constructor] : Cpushout_functor ∘f Cpushout_inl ≅ H :=
begin
fapply natural_iso.mk,
{ fapply nat_trans.mk,
{ intro d, exact id},
{ intro d d' f, rewrite [▸*, Cpushout_functor_list_singleton], apply comp_id_eq_id_comp}},
esimp, exact _
end
definition Cpushout_functor_inr [constructor] : Cpushout_functor ∘f Cpushout_inr ≅ K :=
begin
fapply natural_iso.mk,
{ fapply nat_trans.mk,
{ intro d, exact id},
{ intro d d' f, rewrite [▸*, Cpushout_functor_list_singleton], apply comp_id_eq_id_comp}},
esimp, exact _
end
definition Cpushout_functor_coh (c : C) : natural_map (to_hom Cpushout_functor_inr) (G c) ∘
Cpushout_functor (natural_map (to_hom Cpushout_coh) c) ∘
natural_map (to_inv Cpushout_functor_inl) (F c) = natural_map (to_hom η) c :=
!id_leftright ⬝ !Cpushout_functor_list_singleton
definition Cpushout_functor_unique_ob [unfold 13] (L : Cpushout ⇒ X) (η₁ : L ∘f Cpushout_inl ≅ H)
(η₂ : L ∘f Cpushout_inr ≅ K) (x : Cpushout) : L x ⟶ Cpushout_functor x :=
begin
induction x with d e,
{ exact natural_map (to_hom η₁) d},
{ exact natural_map (to_hom η₂) e}
end
definition Cpushout_functor_unique_inv_ob [unfold 13] (L : Cpushout ⇒ X)
(η₁ : L ∘f Cpushout_inl ≅ H) (η₂ : L ∘f Cpushout_inr ≅ K) (x : Cpushout) :
Cpushout_functor x ⟶ L x :=
begin
induction x with d e,
{ exact natural_map (to_inv η₁) d},
{ exact natural_map (to_inv η₂) e}
end
definition Cpushout_functor_unique_nat_singleton (L : Cpushout ⇒ X) (η₁ : L ∘f Cpushout_inl ≅ H)
(η₂ : L ∘f Cpushout_inr ≅ K)
(p : Πs, natural_map (to_hom η₂) (to_fun_ob G s) ∘
to_fun_hom L (natural_map (to_hom Cpushout_coh) s) ∘
natural_map (to_inv η₁) (to_fun_ob F s) = natural_map (to_hom η) s) (r : R x x') :
Cpushout_functor_reduction_rule r ∘ Cpushout_functor_unique_ob L η₁ η₂ x =
Cpushout_functor_unique_ob L η₁ η₂ x' ∘ L (class_of [r]) :=
begin
induction r,
{ exact naturality (to_hom η₁) f},
{ exact naturality (to_hom η₂) g},
{ refine ap (λx, x ∘ _) (p s)⁻¹ ⬝ _, refine !assoc' ⬝ _, apply ap (λx, _ ∘ x),
refine !assoc' ⬝ _ ⬝ !id_right, apply ap (λx, _ ∘ x),
exact ap010 natural_map (to_left_inverse η₁) (F s)},
{ apply comp.cancel_left (to_hom (componentwise_iso η s)),
refine !assoc ⬝ _ ⬝ ap (λx, x ∘ _) (p s),
refine ap (λx, x ∘ _) (ap010 natural_map (to_right_inverse η) s) ⬝ _ ⬝ !assoc,
refine !id_left ⬝ !id_right⁻¹ ⬝ _, apply ap (λx, _ ∘ x),
refine _ ⬝ ap (λx, _ ∘ x) (ap (λx, x ∘ _) _⁻¹ ⬝ !assoc') ⬝ !assoc,
rotate 2, exact ap010 natural_map (to_left_inverse η₁) (F s),
refine _⁻¹ ⬝ ap (λx, _ ∘ x) !id_left⁻¹, refine (respect_comp L _ _)⁻¹ ⬝ _ ⬝ respect_id L _,
apply ap (to_fun_hom L), refine eq_of_rel (tr (paths_rel_of_Q _)), apply EDE},
end
definition Cpushout_functor_unique [constructor] (L : Cpushout ⇒ X) (η₁ : L ∘f Cpushout_inl ≅ H)
(η₂ : L ∘f Cpushout_inr ≅ K)
(p : Πs, natural_map (to_hom η₂) (to_fun_ob G s) ∘
to_fun_hom L (natural_map (to_hom Cpushout_coh) s) ∘
natural_map (to_inv η₁) (to_fun_ob F s) = natural_map (to_hom η) s) :
L ≅ Cpushout_functor :=
begin
fapply natural_iso.MK,
{ exact Cpushout_functor_unique_ob L η₁ η₂},
{ intro x x' f, induction f using set_quotient.rec_prop with l,
esimp, induction l with x x₁ x₂ x₃ r l IH,
{ refine !id_left ⬝ !id_right⁻¹ ⬝ _⁻¹, apply ap (λx, _ ∘ x), apply respect_id},
{ rewrite [Cpushout_functor_list_cons, assoc', ▸*, IH, assoc, ▸*,
Cpushout_functor_unique_nat_singleton L η₁ η₂ p r, ▸*, assoc', -respect_comp L]}},
{ exact Cpushout_functor_unique_inv_ob L η₁ η₂},
{ intro x, induction x with d e,
{ exact ap010 natural_map (to_left_inverse η₁) d},
{ exact ap010 natural_map (to_left_inverse η₂) e}},
{ intro x, induction x with d e,
{ exact ap010 natural_map (to_right_inverse η₁) d},
{ exact ap010 natural_map (to_right_inverse η₂) e}},
end
end
open bpushout_prehom_index prod prod.ops is_equiv equiv
definition Cpushout_universal {C D E : Precategory} {X : Category} (F : C ⇒ D) (G : C ⇒ E)
(H : D ⇒ X) (K : E ⇒ X) (η : H ∘f F ≅ K ∘f G) :
is_contr (Σ(L : Cpushout F G ⇒ X) (θ : L ∘f Cpushout_inl F G ≅ H × L ∘f Cpushout_inr F G ≅ K),
Πs, natural_map (to_hom θ.2) (to_fun_ob G s) ∘ to_fun_hom L (class_of [DE (λ c, c) F G s]) ∘
natural_map (to_inv θ.1) (to_fun_ob F s) = natural_map (to_hom η) s) :=
begin
fapply is_contr.mk,
{ exact ⟨Cpushout_functor η, (Cpushout_functor_inl η, Cpushout_functor_inr η),
Cpushout_functor_coh η⟩},
intro v₁, induction v₁ with L v₂, induction v₂ with θ p, induction θ with θ₁ θ₂,
fapply sigma_eq,
{ esimp, apply eq_of_iso, symmetry, exact Cpushout_functor_unique η L θ₁ θ₂ p},
fapply sigma_pathover,
{ apply prod_pathover: esimp,
{ apply iso_pathover,
apply hom_pathover_functor_left_constant_right (precomposition_functor _ _),
apply nat_trans_eq, intro d,
xrewrite [↑[hom_of_eq], to_right_inv !eq_equiv_iso, ▸*],
exact (ap010 natural_map (to_right_inverse θ₁) d)⁻¹},
{ apply iso_pathover,
apply hom_pathover_functor_left_constant_right (precomposition_functor _ _),
apply nat_trans_eq, intro e,
xrewrite [↑[hom_of_eq], to_right_inv !eq_equiv_iso, ▸*],
exact (ap010 natural_map (to_right_inverse θ₂) e)⁻¹}},
apply is_prop.elimo
end
local attribute prod.eq_pr1 prod.eq_pr2 [reducible]
definition Cpushout_equiv {C D E : Precategory} {X : Category} (F : C ⇒ D) (G : C ⇒ E) :
(Cpushout F G ⇒ X) ≃ Σ(H : (D ⇒ X) × (E ⇒ X)), H.1 ∘f F ≅ H.2 ∘f G :=
begin
fapply equiv.MK,
{ intro K, refine ⟨(K ∘f Cpushout_inl F G, K ∘f Cpushout_inr F G), _⟩,
exact !assoc_iso⁻¹ⁱ ⬝i (K ∘fi Cpushout_coh F G) ⬝i !assoc_iso},
{ intro v, cases v with w η, cases w with K L, exact Cpushout_functor η},
{ exact abstract begin intro v, cases v with w η, cases w with K L, esimp at *,
fapply sigma_eq,
{ fapply prod_eq: esimp; apply eq_of_iso,
{ exact Cpushout_functor_inl η},
{ exact Cpushout_functor_inr η}},
esimp, apply iso_pathover, apply hom_pathover,
rewrite [ap_compose' _ pr₁, ap_compose' _ pr₂, prod_eq_pr1, prod_eq_pr2],
rewrite [-+respect_hom_of_eq (precomposition_functor _ _), +hom_of_eq_eq_of_iso],
apply nat_trans_eq, intro c, esimp [category.to_precategory],
rewrite [+id_left, +id_right, Cpushout_functor_list_singleton] end end},
{ exact abstract begin intro K, esimp,
refine eq_base_of_is_prop_sigma _ !is_trunc_succ _ _, rotate 1,
{ refine Cpushout_universal F G (K ∘f Cpushout_inl F G) (K ∘f Cpushout_inr F G) _,
exact !assoc_iso⁻¹ⁱ ⬝i (K ∘fi Cpushout_coh F G) ⬝i !assoc_iso},
{ esimp, fconstructor, esimp, split,
{ fapply natural_iso.mk',
{ intro c, reflexivity},
{ intro c c' f, rewrite [▸*, id_right, Cpushout_functor_list_singleton, id_left]}},
{ fapply natural_iso.mk',
{ intro c, reflexivity},
{ intro c c' f, rewrite [▸*, id_right, Cpushout_functor_list_singleton, id_left]}},
intro c, rewrite [▸*, id_left, id_right, Cpushout_functor_list_singleton]},
{ esimp, fconstructor,
{ split: reflexivity},
intro c, reflexivity} end end}
end
/- Pushout of groupoids with a type of basepoints -/
section
variables {S : Type} {C D E : Groupoid} (k : S → C) (F : C ⇒ D) (G : C ⇒ E)
variables ⦃x x' x₁ x₂ x₃ x₄ : Precategory_bpushout k F G⦄
open bpushout_prehom_index paths.paths_rel bpushout_hom_rel_index
definition bpushout_index_inv [unfold 8] (i : bpushout_prehom_index k F G x x') :
bpushout_prehom_index k F G x' x :=
begin
induction i,
{ exact iD k F G f⁻¹},
{ exact iE k F G g⁻¹},
{ exact ED k F G s},
{ exact DE k F G s},
end
theorem bpushout_index_reverse {l l' : bpushout_prehom k F G x x'}
(q : bpushout_hom_rel_index k F G l l') : paths_rel (bpushout_hom_rel_index k F G)
(reverse (bpushout_index_inv k F G) l) (reverse (bpushout_index_inv k F G) l') :=
begin
induction q: apply paths_rel_of_Q;
try rewrite reverse_singleton; rewrite *reverse_pair; try rewrite reverse_nil; esimp;
try rewrite [comp_inverse]; try rewrite [id_inverse]; rewrite [-*respect_inv]; constructor
end
theorem bpushout_index_li (i : bpushout_prehom_index k F G x x') :
paths_rel (bpushout_hom_rel_index k F G) [bpushout_index_inv k F G i, i] nil :=
begin
induction i: esimp,
{ refine rtrans (paths_rel_of_Q !DD) _,
rewrite [comp.left_inverse], exact paths_rel_of_Q !idD},
{ refine rtrans (paths_rel_of_Q !EE) _,
rewrite [comp.left_inverse], exact paths_rel_of_Q !idE},
{ exact paths_rel_of_Q !DED},
{ exact paths_rel_of_Q !EDE}
end
theorem bpushout_index_ri (i : bpushout_prehom_index k F G x x') :
paths_rel (bpushout_hom_rel_index k F G) [i, bpushout_index_inv k F G i] nil :=
begin
induction i: esimp,
{ refine rtrans (paths_rel_of_Q !DD) _,
rewrite [comp.right_inverse], exact paths_rel_of_Q !idD},
{ refine rtrans (paths_rel_of_Q !EE) _,
rewrite [comp.right_inverse], exact paths_rel_of_Q !idE},
{ exact paths_rel_of_Q !EDE},
{ exact paths_rel_of_Q !DED}
end
definition Groupoid_bpushout [constructor] : Groupoid :=
Groupoid_paths (bpushout_hom_rel_index k F G) (bpushout_index_inv k F G)
(bpushout_index_reverse k F G) (bpushout_index_li k F G) (bpushout_index_ri k F G)
definition Gpushout [constructor] : Groupoid :=
Groupoid_bpushout (λc, c) F G
end
end category