Built with Alectryon, running Coq+SerAPI v8.19.0+0.19.3. 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.
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Require Import Colimits.Pushout.Require Import Colimits.SpanPushout.Require Import Homotopy.Suspension.Require Import Limits.Pullback.Require Import Homotopy.Join.Core.Require Import Truncations.(** * The Generalized Blakers-Massey Theorem *)(** This file follows the paper "A Generalized Blakers-Massey Theorem" (https://arxiv.org/abs/1703.09050) by Mathieu Anel, Georg Biedermann, Eric Finster, André Joyal, hereafter referred to as ABFJ. We also follow "A Mechanization of the Blakers-Massey Connectivity Theorem in Homotopy Type Theory" by Favonia, Eric Finster, Dan Licata, and Peter LeFanu Lumsdaine, hereafter referred to as HFLL. *)(** ** Path algebra helper lemma *)(** Here is a strange-looking path algebra helper lemma that is easier to prove by lifting to a general case and doing a path-induction blast. It says something about what happens when we transport from the center of a based path-space to some other point, assuming we know a particular way to "compute" the action of the type family in question. *)
H: Univalence A: Type x: A B: forally : A, x = y -> Type y: A p: x = y u: B x 1 f: forallq : x = x, B x q <~> B y (q @ p) ev: ap10 (apD B p) p =
transport_arrow_toconst p (B x) p @
path_universe_uncurried
(equiv_transport (B y) (concat_pV_p p p)
oE f (p @ p^)
oE equiv_transport (B x)
(transport_paths_r p^ p))
transport (funyp : {y : A & x = y} => B yp.1 yp.2)
(path_contr (x; 1) (y; p)) u =
transport (B y) (concat_1p p) (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type y: A p: x = y u: B x 1 f: forallq : x = x, B x q <~> B y (q @ p) ev: ap10 (apD B p) p =
transport_arrow_toconst p (B x) p @
path_universe_uncurried
(equiv_transport (B y) (concat_pV_p p p)
oE f (p @ p^)
oE equiv_transport (B x)
(transport_paths_r p^ p))
transport (funyp : {y : A & x = y} => B yp.1 yp.2)
(path_contr (x; 1) (y; p)) u =
transport (B y) (concat_1p p) (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type u: B x 1 f: forallq : x = x, B x q <~> B x (q @ 1) ev: 1 =
1 @
path_universe_uncurried
(equiv_transport (B x) 1 oE f 1%path
oE equiv_transport (B x) 1)
u = transport (B x) 1 (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type u: B x 1 f: forallq : x = x, B x q <~> B x (q @ 1) ev: 1 =
path_universe_uncurried
(equiv_transport (B x) 1 oE f 1%path
oE equiv_transport (B x) 1)
u = transport (B x) 1 (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type u: B x 1 f: forallq : x = x, B x q <~> B x (q @ 1) ev: ((equiv_path (B x 1) (B x 1))^-1 o idmap)^-11 =
equiv_transport (B x) 1 oE f 1%path
oE equiv_transport (B x) 1
u = transport (B x) 1 (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type u: B x 1 f: forallq : x = x, B x q <~> B x (q @ 1) ev: ((equiv_path (B x 1) (B x 1))^-1 o idmap)^-11 =
equiv_transport (B x) 1 oE f 1%path
oE equiv_transport (B x) 1
u = transport (B x) 1 (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type u: B x 1 f: forallq : x = x, B x q <~> B x (q @ 1) ev: ((equiv_path (B x 1) (B x 1))^-1 o idmap)^-11 ==
equiv_transport (B x) 1 oE f 1%path
oE equiv_transport (B x) 1
u = transport (B x) 1 (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type u: B x 1 f: forallq : x = x, B x q <~> B x (q @ 1) ev: ((equiv_path (B x 1) (B x 1))^-1 o idmap)^-11 u =
(equiv_transport (B x) 1 oE f 1%path
oE equiv_transport (B x) 1) u
u = transport (B x) 1 (f 1 u)
H: Univalence A: Type x: A B: forally : A, x = y -> Type u: B x 1 f: forallq : x = x, B x q <~> B x (q @ 1) ev: u = transport (B x) 1 (f 1 u)
u = transport (B x) 1 (f 1 u)
exact ev.Defined.(** ** Setup *)SectionGBM.Context {XY : Type} (Q : X -> Y -> Type).(** Here's the hypothesis of ABFJ's generalized Blakers-Massey. It works for any reflective subuniverse, not only modalities! *)Context (O : ReflectiveSubuniverse).Context
(isconnected_cogap :
forall (x1x3 : X) (y2y4 : Y)
(q12 : Q x1 y2) (q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O (Join ((x1;q12) = (x3;q32) :> {x:X & Q x y2})
((y2;q32) = (y4;q34) :> {y:Y & Q x3 y}))).LetP := SPushout Q.Local Notationleft := (spushl Q).Local Notationright := (spushr Q).Local Notationglue := (spglue Q).(** Here's a lemma that's a sort of "singleton contractibility" equivalence, but expressed in a particularly strange way. As we'll see, this form of the lemma comes up naturally *twice* in the proof, and proving it once here to use in both places is crucial so that the two uses can be identified later on. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
{q0 : Q x0 y &
{_ : transport (funx : X => Q x y) s q0 = q1 &
glue q0 @ (glue q1)^ = r}} <~> ap left s = r
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
{q0 : Q x0 y &
{_ : transport (funx : X => Q x y) s q0 = q1 &
glue q0 @ (glue q1)^ = r}} <~> ap left s = r
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
{ap
: {a : Q x0 y &
transport (funx : X => Q x y) s a = q1} &
glue ap.1 @ (glue q1)^ = r} <~> ap left s = r
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
{qt
: {q0 : Q x0 y &
q0 = transport (funx : X => Q x y) s^ q1} &
glue qt.1 @ (glue q1)^ = r} <~> ap left s = r
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
glue (transport (funx : X => Q x y) s^ q1) @
(glue q1)^ = r <~> ap left s = r
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
transport (funx : X => left x = right y) s^ (glue q1) @
(glue q1)^ = r <~> ap left s = r
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
(((ap left s^)^ @ glue q1) @
ap (fun_ : X => right y) s^) @ (glue q1)^ = r <~>
ap left s = r
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y: Y q1: Q x1 y
(ap left s @ glue q1) @ (glue q1)^ = r <~>
ap left s = r
exact (equiv_concat_l (concat_pp_V _ _)^ _).(** Although we proved this lemma with [rewrite], we make it transparent, not so that *we* can reason about it, but so that Coq can evaluate it. *)Defined.(* But except in one place, we don't want it to try (otherwise things get really slow). *)Opaque frobnicate.(** ** Codes *)(** *** Right-hand codes *)(** The right-hand codes family is easy. *)Definitioncoderight {x0 : X} {y : Y} (r : left x0 = right y) : Type
:= O (hfiber glue r).(** *** Left-hand codes *)(** We enhance the HFLL and ABFJ theorems by defining a version of code-left that doesn't depend on one map being surjective. *)SectionCodeLeft.Context {x0x1 : X} (r : left x0 = left x1).(** The left codes are themselves a pushout, of what is morally also a dependent span, but we formulate it as an ordinary pushout of projections between iterated Sigma-types, most of which we express as records for performance reasons. The span is [codeleft1] <- [codeleft0] -> [codeleft2]. *)Definitioncodeleft1 : Type
:= { s : x0 = x1 &
(* v : *) ap left s = r}.Recordcodeleft2
:= { codeleft2_y0 : Y ;
codeleft2_q00 : Q x0 codeleft2_y0 ;
codeleft2_q10 : Q x1 codeleft2_y0 ;
codeleft2_u : glue codeleft2_q00 @ (glue codeleft2_q10)^ = r }.Recordcodeleft0
:= { codeleft0_s : x0 = x1 ;
codeleft0_y0 : Y ;
codeleft0_v : ap left codeleft0_s = r ;
codeleft0_q00 : Q x0 codeleft0_y0 ;
codeleft0_q10 : Q x1 codeleft0_y0 ;
codeleft0_w : transport (funx => Q x codeleft0_y0) codeleft0_s codeleft0_q00
= codeleft0_q10 ;
codeleft0_u : glue codeleft0_q00 @ (glue codeleft0_q10)^ = r ;
(** Note the first use of frobnicate here. *)
codeleft0_d : frobnicate r codeleft0_s codeleft0_y0 codeleft0_q10
(codeleft0_q00 ; codeleft0_w ; codeleft0_u) = codeleft0_v }.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1
codeleft0 -> codeleft1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1
codeleft0 -> codeleft1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y0: Y v: ap left s = r q00: Q x0 y0 q10: Q x1 y0 w: transport (funx : X => Q x y0) s q00 = q10 u: glue q00 @ (glue q10)^ = r d: frobnicate r s y0 q10 (q00; w; u) = v
codeleft1
exact (s;v).Defined.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1
codeleft0 -> codeleft2
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1
codeleft0 -> codeleft2
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 s: x0 = x1 y0: Y v: ap left s = r q00: Q x0 y0 q10: Q x1 y0 w: transport (funx : X => Q x y0) s q00 = q10 u: glue q00 @ (glue q10)^ = r d: frobnicate r s y0 q10 (q00; w; u) = v
codeleft2
exact (Build_codeleft2 y0 q00 q10 u).Defined.Definitioncodeleft : Type
:= O (Pushout codeleft01 codeleft02).(** *** Codes for glue *)SectionCodeGlue.Context {y1 : Y} (q11 : Q x1 y1).(** We prove that codes respect glue as a chain of equivalences between types built from pushouts and double-pushouts. The first step is to add the data of our hypothesized-to-be-connected type inside [codeleft2]. *)Definitioncodeleft2plus :=
{yqqu : codeleft2 &
Join ((x0; codeleft2_q00 yqqu) = (x1; codeleft2_q10 yqqu)
:> {x:X & Q x (codeleft2_y0 yqqu)})
((codeleft2_y0 yqqu; codeleft2_q10 yqqu) = (y1; q11)
:> {y:Y & Q x1 y})}.(** Since this connected type is itself a join, hence a pushout, the second step is to distribute this and re-express the whole thing as another pushout of iterated Sigma-types (again mostly expressed as records for performance reasons). *)RecordOcodeleft2b
:= { Ocodeleft2b_s : x0 = x1 ;
Ocodeleft2b_y0 : Y ;
Ocodeleft2b_q00 : Q x0 Ocodeleft2b_y0 ;
Ocodeleft2b_q10 : Q x1 Ocodeleft2b_y0 ;
Ocodeleft2b_w : transport (funx => Q x Ocodeleft2b_y0) Ocodeleft2b_s Ocodeleft2b_q00
= Ocodeleft2b_q10 ;
Ocodeleft2b_u : glue Ocodeleft2b_q00 @ (glue Ocodeleft2b_q10)^ = r }.DefinitionOcodeleft2c
:= { q01 : Q x0 y1 &
(* u: *) glue q01 @ (glue q11)^ = r }.RecordOcodeleft2a
:= { Ocodeleft2a_s : x0 = x1 ;
Ocodeleft2a_q01 : Q x0 y1 ;
Ocodeleft2a_w : transport (funx => Q x y1) Ocodeleft2a_s Ocodeleft2a_q01 = q11 ;
Ocodeleft2a_u : glue Ocodeleft2a_q01 @ (glue q11)^ = r }.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a -> Ocodeleft2b
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a -> Ocodeleft2b
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1 s: x0 = x1 q01: Q x0 y1 w: transport (funx : X => Q x y1) s q01 = q11 u: glue q01 @ (glue q11)^ = r
Ocodeleft2b
exact (Build_Ocodeleft2b s y1 q01 q11 w u).Defined.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a -> Ocodeleft2c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a -> Ocodeleft2c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1 s: x0 = x1 q01: Q x0 y1 w: transport (funx : X => Q x y1) s q01 = q11 u: glue q01 @ (glue q11)^ = r
Ocodeleft2c
exact (q01;u).Defined.(** This proof is basically just rearranging Sigma-types/records and paths in Sigma-types and contracting based path spaces. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
rapply equiv_sigma_contr.Defined.(** The next step is to reassociate the resulting double-pushout and "contract" both of them, one after the other, because they are pushouts along equivalences. In order to do this, we need first of all to know that the resulting map from [codeleft0] to the above pushout factors through [Ocodeleft2b] via an equivalence. Here's the equivalence: *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
codeleft0 <~> Ocodeleft2b
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
rapply Ocodeleft02plus_02b.Qed.(** Thus, our pushout in which one vertex is itself a pushout can be written as a "double pushout"[codeleft1] <- [codeleft0] -> [codeleft2b] <- [codeleft2a] -> [codeleft2c].Since the map [codeleft0] -> [codeleft2b] is an equivalence, the pushout of the left-hand span is equivalent to [codeleft1], and thus the whole thing is equivalent to a pushout[codeleft1] <- [codeleft2a] -> [codeleft2c]Now we claim that the left-hand map of this span is also an equivalence. Rather than showing this directly, it seems to be much easier to first construct *an* equivalence from [codeleft2a] to [codeleft1] and then show that it is equal (as a function) to the induced one. Here's the equivalence: *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a <~> codeleft1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a <~> codeleft1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a <~> ?Goal
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
?Goal <~> codeleft1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
?Goal <~> codeleft1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1 s: x0 = x1
?Goal0 s <~> ap left s = r
(** Here's frobnicate showing up again! *)apply frobnicate.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a <~>
{s : x0 = x1 &
{q0 : Q x0 ?y &
{_ : transport (funx : X => Q x ?y) s q0 = ?q1 &
glue q0 @ (glue ?q1)^ = r}}}
make_equiv.Defined.(** And now we check that the two are equal. Because we used the same proof of [frobnicate] in two places, this equality becomes definitional after simply decomposing up a Sigma-type! *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a1 ==
codeleft01 o Ocodeleft02b^-1 o Ocodeleft2ab
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
Ocodeleft2a1 ==
codeleft01 o Ocodeleft02b^-1 o Ocodeleft2ab
intros; reflexivity.Defined.(** Now we're finally ready to prove the glue equivalence. Since later on we'll have to compute its action on inputs from [codeleft1], we decompose it into seven steps, each of which with a corresponding computation lemma. (These lemmas seem to be much easier to prove step-by-step than all at once if we proved the whole equivalence in a big shebang.) *)Definitioncodeglue1
: codeleft <~> O (Pushout (O_functor O codeleft01)
(O_functor O codeleft02))
:= equiv_O_pushout O _ _.Definitioncodeglue1_pushl (s : x0 = x1) (v : ap left s = r)
: codeglue1 (to O _ (pushl (s;v))) =
to O _ (pushl (to O _ (s; v)))
:= equiv_O_pushout_to_O_pushl _ _ _ _.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
O
(Pushout (O_functor O codeleft01)
(O_functor O codeleft02)) <~>
O
(Pushout (O_functor O codeleft01)
(O_functor O Ocodeleft02))
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
O
(Pushout (O_functor O codeleft01)
(O_functor O codeleft02)) <~>
O
(Pushout (O_functor O codeleft01)
(O_functor O Ocodeleft02))
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
1%equiv o O_functor O codeleft01 ==
O_functor O codeleft01 o 1%equiv
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
equiv_Ocodeleft2 o O_functor O Ocodeleft02 ==
O_functor O codeleft02 o 1%equiv
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
1%equiv o O_functor O codeleft01 ==
O_functor O codeleft01 o 1%equiv
intros x; reflexivity.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
equiv_Ocodeleft2 o O_functor O Ocodeleft02 ==
O_functor O codeleft02 o 1%equiv
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1 x: codeleft0
equiv_Ocodeleft2
(O_functor O Ocodeleft02 (to O codeleft0 x)) =
O_functor O codeleft02 (1%equiv (to O codeleft0 x))
abstract (rewrite !to_O_natural; apply Ocodeleft02_02b).Defined.Definitioncodeglue2_pushl (s : x0 = x1) (v : ap left s = r)
: codeglue2 (to O _ (pushl (to O _ (s;v))))
= to O _ (pushl (to O _ (s;v)))
:= to_O_equiv_natural _ _ _.Definitioncodeglue3
: O (Pushout (O_functor O codeleft01) (O_functor O Ocodeleft02))
<~> O (Pushout codeleft01 Ocodeleft02)
:= equiv_inverse (equiv_O_pushout O _ _).Definitioncodeglue3_pushl (s : x0 = x1) (v : ap left s = r)
: codeglue3 (to O _ (pushl (to O _ (s;v))))
= to O _ (pushl (s;v))
:= inverse_equiv_O_pushout_to_O_pushl _ _ _ _.Definitioncodeglue4
: O (Pushout codeleft01 Ocodeleft02)
<~> O (Pushout
(funx : Ocodeleft2a =>
pushr' codeleft01 Ocodeleft02b (Ocodeleft2ab x))
Ocodeleft2ac)
:= equiv_O_functor O (equiv_inverse (equiv_pushout_assoc _ _ _ _)).Definitioncodeglue4_pushl (s : x0 = x1) (v : ap left s = r)
: codeglue4 (to O _ (pushl (s;v)))
= to O _ (pushl (pushl (s;v)))
:= to_O_equiv_natural _ _ _.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
O
(Pushout
(funx : Ocodeleft2a =>
pushr' codeleft01 Ocodeleft02b (Ocodeleft2ab x))
Ocodeleft2ac) <~>
O (Pushout Ocodeleft2a1 Ocodeleft2ac)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
O
(Pushout
(funx : Ocodeleft2a =>
pushr' codeleft01 Ocodeleft02b (Ocodeleft2ab x))
Ocodeleft2ac) <~>
O (Pushout Ocodeleft2a1 Ocodeleft2ac)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
codeleft1 <~> Pushout codeleft01 Ocodeleft02b
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
?eB o Ocodeleft2a1 ==
(funx : Ocodeleft2a =>
pushr' codeleft01 Ocodeleft02b (Ocodeleft2ab x))
o 1%equiv
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
1%equiv o Ocodeleft2ac == Ocodeleft2ac o 1%equiv
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
1%equiv o Ocodeleft2ac == Ocodeleft2ac o 1%equiv
intros x; reflexivity.Defined.Definitioncodeglue5_pushl (s : x0 = x1) (v : ap left s = r)
: codeglue5 (to O _ (pushl (pushl (s;v))))
= to O _ (pushl (s;v))
:= to_O_equiv_natural _ _ _.Definitioncodeglue6
: O (Pushout Ocodeleft2a1 Ocodeleft2ac) <~> O Ocodeleft2c
:= equiv_O_functor
O (equiv_inverse
(Build_Equiv _ _ (pushr' Ocodeleft2a1 Ocodeleft2ac) _)).Definitioncodeglue6_pushl (s : x0 = x1) (v : ap left s = r)
: codeglue6 (to O _ (pushl (s;v)))
= letz := (frobnicate r s y1 q11)^-1 v in
to O Ocodeleft2c (Ocodeleft2ac (Build_Ocodeleft2a s z.1 z.2.1 z.2.2))
:= to_O_equiv_natural _ _ _.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
O Ocodeleft2c <~> coderight (r @ glue q11)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
O Ocodeleft2c <~> coderight (r @ glue q11)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type x0, x1: X r: left x0 = left x1 y1: Y q11: Q x1 y1 q01: Q x0 y1
glue q01 @ (glue q11)^ = r <~> glue q01 = r @ glue q11
apply equiv_moveL_pM.Defined.Definitioncodeglue7_to_O
(q01 : Q x0 y1) (u : glue q01 @ (glue q11)^ = r)
: codeglue7 (to O _ (q01;u))
= to O (hfiber glue (r @ glue q11))
(q01 ; moveL_pM (glue q11) (glue q01) r u)
:= to_O_equiv_natural _ _ _.Definitioncodeglue
: codeleft <~> coderight (r @ glue q11)
:= codeglue7 oE
codeglue6 oE
codeglue5 oE
codeglue4 oE
codeglue3 oE
codeglue2 oE
codeglue1.EndCodeGlue.EndCodeLeft.(** *** Completion of codes *)Context `{Univalence}.Context (x0 : X).(** The equivalence [codeglue] requires a bit of massaging to put it into the form needed by the actual definition of [code] from pushout-induction and univalence. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0, x1: X y1: Y q11: Q x1 y1
transport (funp : SPushout Q => left x0 = p -> Type)
(glue q11) codeleft = coderight
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0, x1: X y1: Y q11: Q x1 y1
transport (funp : SPushout Q => left x0 = p -> Type)
(glue q11) codeleft = coderight
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0, x1: X y1: Y q11: Q x1 y1 z: left x0 = right y1
transport (funp : SPushout Q => left x0 = p -> Type)
(glue q11) codeleft z = coderight z
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0, x1: X y1: Y q11: Q x1 y1 z: left x0 = right y1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0, x1: X y1: Y q11: Q x1 y1 z: left x0 = right y1
(z @ (glue q11)^) @ glue q11 = z
exact (concat_pV_p z (glue q11)).Defined.(** Here's the final definition of [code]. *)Definitioncode (p : P) (r : left x0 = p) : Type
:= spushout_ind Q (funp => left x0 = p -> Type)
(@codeleft x0) (@coderight x0)
ap_code_glue p r.(** When we compute with [code], we'll need to extract from it the actual behavior of the function [codeglue]. Here's the mess of path algebra that we "naturally" get out when we try to do that; later we'll see how to deal with it. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0, x1: X y1: Y q11: Q x1 y1 r: left x0 = right y1
exact (ap10_path_arrow _ _ _ _).Defined.(** ** Contractibility of codes *)(** To construct a center for every type of codes, we construct one in an easy case and transport it around. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X
code (left x0) 1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X
code (left x0) 1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X
codeleft 1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X
O (Pushout (codeleft01 1) (codeleft02 1))
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X
codeleft1 1
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X
{s : x0 = x0 & ap left s = 1}
exact (idpath; idpath).Defined.Definitioncenter_code (p : P) (r : left x0 = p) : code p r
:= transport (fun (pr : {p : P & left x0 = p}) => code pr.1 pr.2)
(path_contr (A := {p : P & left x0 = p})
(left x0; idpath) (p;r))
center_code1.(** As in HFLL, we first construct a contraction in the "partially general" case of an arbitrary path from left to right. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y r: left x0 = right y1 c: code (right y1) r
center_code (right y1) r = c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y r: left x0 = right y1 c: code (right y1) r
center_code (right y1) r = c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y r: left x0 = right y1 c: coderight r
center_code (right y1) r = c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y r: left x0 = right y1 c: O (hfiber glue r)
center_code (right y1) r = c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y r: left x0 = right y1 q01: Q x0 y1 t: glue q01 = r
center_code (right y1) r =
to O (hfiber glue r) (q01; t)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y r: left x0 = right y1 q01: Q x0 y1 t: glue q01 = r
transport
(funpr : {p : P & left x0 = p} => code pr.1 pr.2)
(path_contr (left x0; 1) (right y1; r))
(to O (Pushout (codeleft01 1) (codeleft02 1))
(pushl (1; 1))) = to O (hfiber glue r) (q01; t)
(** Here's how we use the apparently-unmanageable [code_beta_glue]. First we destruct the path [t] to make things simpler. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y q01: Q x0 y1
transport
(funpr : {p : P & left x0 = p} => code pr.1 pr.2)
(path_contr (left x0; 1) (right y1; glue q01))
(to O (Pushout (codeleft01 1) (codeleft02 1))
(pushl (1; 1))) =
to O (hfiber glue (glue q01)) (q01; 1)
(** Then we notice that if we tried rewriting with [code_beta_glue] here, the unmanageable-looking result is actually fully general over the path [glue q01], so we can prove by path induction that it equals the nicer expression we'd like to see. This is the purpose of the lemma [transport_singleton]. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y q01: Q x0 y1
transport (code (right y1)) (concat_1p (glue q01))
(codeglue 1 q01
(to O (Pushout (codeleft01 1) (codeleft02 1))
(pushl (1; 1)))) =
to O (hfiber glue (glue q01)) (q01; 1)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y q01: Q x0 y1
(** Finally, we have another terrible-looking thing involving [frobnicate]. However, there are enough identity paths that [frobnicate] evaluates to something we can prove with path-induction. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y1: Y q01: Q x0 y1
destruct (glue q01); reflexivity.Qed.(** It should be possible to prove an analogous [contraction_code_left] directly, but for now we follow HFLL and ABFJ by introducing a surjectivity assumption. *)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y0: Y q00: Q x0 y0 pr: {p : P & left x0 = p} c: code pr.1 pr.2
center_code pr.1 pr.2 = c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y0: Y q00: Q x0 y0 pr: {p : P & left x0 = p} c: code pr.1 pr.2
center_code pr.1 pr.2 = c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y0: Y q00: Q x0 y0 pr: {p : P & left x0 = p}
forallc : code pr.1 pr.2, center_code pr.1 pr.2 = c
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y0: Y q00: Q x0 y0 pr: {p : P & left x0 = p}
(funpr' : {p : P & left x0 = p} =>
forallc : code pr'.1 pr'.2,
center_code pr'.1 pr'.2 = c) (right y0; glue q00)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X y0: Y q00: Q x0 y0 c: code (right y0) (glue q00)
center_code (right y0) (glue q00) = c
apply contraction_code_right.Defined.
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X inh: merely {y0 : Y & Q x0 y0} p: P r: left x0 = p
Contr (code p r)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X inh: merely {y0 : Y & Q x0 y0} p: P r: left x0 = p
Contr (code p r)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X p: P r: left x0 = p inh: {y0 : Y & Q x0 y0}
Contr (code p r)
X, Y: Type Q: X -> Y -> Type O: ReflectiveSubuniverse isconnected_cogap: forall (x1x3 : X)
(y2y4 : Y) (q12 : Q x1 y2)
(q32 : Q x3 y2) (q34 : Q x3 y4),
IsConnected O
(Join ((x1; q12) = (x3; q32))
((y2; q32) = (y4; q34))) P:= SPushout Q: Type H: Univalence x0: X p: P r: left x0 = p y0: Y q00: Q x0 y0
Contr (code p r)
exact (Build_Contr _ (center_code p r) (contraction_code q00 (p;r))).Defined.(** This version is sufficient for the classical Blakers-Massey theorem, as we'll see below, since its leg-wise connectivity hypothesis implies the above surjectivity assumption. Anel-Biedermann-Finster-Joyal have a different method for eliminating the surjectivity assumption using a lemma about pushouts of monos also being pullbacks, though it seems to only work for coderight. *)EndGBM.(** ** The classical Blakers-Massey Theorem *)
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y
IsConnMap (Tr (m +2+ n)) (spglue Q)
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y
IsConnMap (Tr (m +2+ n)) (spglue Q)
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y r: spushl Q x = spushr Q y
IsConnected (Tr (m +2+ n)) (hfiber (spglue Q) r)
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y r: spushl Q x = spushr Q y
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y r: spushl Q x = spushr Q y
IsConnected (Tr n.+1) {y0 : Y & Q x y0}
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y r: spushl Q x = spushr Q y x1, x3: X y2, y4: Y q12: Q x1 y2 q32: Q x3 y2 q34: Q x3 y4
IsConnected (Tr m) ((x1; q12) = (x3; q32))
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y r: spushl Q x = spushr Q y x1, x3: X y2, y4: Y q12: Q x1 y2 q32: Q x3 y2 q34: Q x3 y4
IsConnected (Tr n) ((y2; q32) = (y4; q34))
H: Univalence m, n: trunc_index X, Y: Type Q: X -> Y -> Type H0: forally : Y,
IsConnected (Tr m.+1) {x : X & Q x y} H1: forallx : X,
IsConnected (Tr n.+1) {y : Y & Q x y} x: X y: Y r: spushl Q x = spushr Q y
IsConnected (Tr n.+1) {y0 : Y & Q x y0}
all: exact _.Defined.(** A sigma functor is connected if its fibers are, so we have the following. *)Definitionblakers_massey_total_map `{Univalence} (m n : trunc_index)
{X Y : Type} (Q : X -> Y -> Type)
`{forally, IsConnected m.+1 { x : X & Q x y } }
`{forallx, IsConnected n.+1 { y : Y & Q x y } }
: IsConnMap (Tr (m +2+ n)) (spushout_sjoin_map Q)
:= _.
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g
IsConnMap (Tr (m +2+ n)) (pullback_corec pglue)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g
IsConnMap (Tr (m +2+ n)) (pullback_corec pglue)
(** We postcompose our map with an equivalence from the the pullback of the pushout of [f] and [g] to the pullback of an equivalent [SPushout] over a family [Q]. *)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
IsConnMap (Tr (m +2+ n)) (pullback_corec pglue)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
Type
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
Pullback pushl pushr <~> ?C
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
IsConnMap (Tr (m +2+ n)) (?g o pullback_corec pglue)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
IsConnMap (Tr (m +2+ n)) (?g o pullback_corec pglue)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
IsConnMap (Tr (m +2+ n))
(equiv_pullback (equiv_pushout_spushout f g) 11
(funx0 : Y => 1) (funx0 : Z => 1)
o pullback_corec pglue)
(** Next we precompose with the equivalence from the total space of [Q] to [X]. *)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
IsConnMap (Tr (m +2+ n))
(funx : {y : Y &
{z : Z & {x : X & (f x = y) * (g x = z)}}} =>
equiv_pullback (equiv_pushout_spushout f g) 11
(funx0 : Y => 1) (funx0 : Z => 1)
(pullback_corec pglue
((equiv_double_fibration_replacement f g)^-1%equiv
x)))
(** Next we prove that this composition is homotopic to [spushout_sjoin_map Q]. *)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
spushout_sjoin_map Q ==
(funx : {y : Y &
{z : Z & {x : X & (f x = y) * (g x = z)}}} =>
equiv_pullback (equiv_pushout_spushout f g) 11
(funx0 : Y => 1) (funx0 : Z => 1)
(pullback_corec pglue
((equiv_double_fibration_replacement f g)^-1%equiv
x)))
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
IsConnMap (Tr (m +2+ n)) (spushout_sjoin_map Q)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
spushout_sjoin_map Q ==
(funx : {y : Y &
{z : Z & {x : X & (f x = y) * (g x = z)}}} =>
equiv_pullback (equiv_pushout_spushout f g) 11
(funx0 : Y => 1) (funx0 : Z => 1)
(pullback_corec pglue
((equiv_double_fibration_replacement f g)^-1%equiv
x)))
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y z: Z x: X
spushout_sjoin_map Q (f x; g x; x; (1, 1)) =
equiv_pullback (equiv_pushout_spushout f g) 11
(funx0 : Y => 1) (funx0 : Z => 1)
(pullback_corec pglue
((equiv_double_fibration_replacement f g)^-1%equiv
(f x; g x; x; (1, 1))))
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y z: Z x: X
match
ap
(functor_coeq
(funx : X => ((f x, g x); x; (1, 1)))
(functor_sum idmap idmap) (funx : X => 1)
(funx : X => 1)) (pglue x) @ 1in (_ = a)
return (spushl Q (f x) = a)
with
| 1 => 1end = spglue Q (x; (1, 1))
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y z: Z x: X
ap
(functor_coeq (funx : X => ((f x, g x); x; (1, 1)))
(functor_sum idmap idmap) (funx : X => 1)
(funx : X => 1)) (pglue x) @ 1 =
spglue Q (x; (1, 1))
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y z: Z x: X
ap
(functor_coeq (funx : X => ((f x, g x); x; (1, 1)))
(functor_sum idmap idmap) (funx : X => 1)
(funx : X => 1)) (pglue x) =
spglue Q (x; (1, 1))
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y z: Z x: X
(ap coeq 1 @ cglue ((f x, g x); x; (1, 1))) @
ap coeq 1^ = spglue Q (x; (1, 1))
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y z: Z x: X
ap coeq 1 @ cglue ((f x, g x); x; (1, 1)) =
spglue Q (x; (1, 1))
napply concat_1p.
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
IsConnMap (Tr (m +2+ n)) (spushout_sjoin_map Q)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
forally : Z, IsConnected (Tr m.+1) {x : Y & Q x y}
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
forallx : Y, IsConnected (Tr n.+1) {y : Z & Q x y}
(** What's left is to check that the partial total spaces of [Q] are connected, which we get since [f] and [g] are connected maps. We just have to strip off the irrelevant parts of [Q] to get the hfiber in each case. *)
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
forally : Z, IsConnected (Tr m.+1) {x : Y & Q x y}
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type z: Z
IsConnected (Tr m.+1) {x : Y & Q x z}
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type z: Z
hfiber g z <~> {x : Y & Q x z}
make_equiv_contr_basedpaths.
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type
forallx : Y, IsConnected (Tr n.+1) {y : Z & Q x y}
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y
IsConnected (Tr n.+1) {y0 : Z & Q y y0}
H: Univalence m, n: trunc_index X, Y, Z: Type f: X -> Y g: X -> Z H1: IsConnMap (Tr n.+1) f H2: IsConnMap (Tr m.+1) g Q:= fun (y : Y) (z : Z) =>
{x : X & (f x = y) * (g x = z)}: Y -> Z -> Type y: Y
hfiber f y <~> {y0 : Z & Q y y0}
make_equiv_contr_basedpaths.Defined.(** ** The Freudenthal Suspension Theorem *)(** The Freudenthal suspension theorem is a fairly trivial corollary of the Blakers-Massey theorem. It says that [merid : X -> North = South] is highly connected. *)
H: Univalence n: trunc_index X: Type H0: IsConnected (Tr n.+1) X
IsConnMap (Tr (n +2+ n)) merid
H: Univalence n: trunc_index X: Type H0: IsConnected (Tr n.+1) X
IsConnMap (Tr (n +2+ n)) merid
(* If we post-compose [merid : X -> North = South] with an equivalence [North = South <~> P], where [P] is the pullback of the inclusions [Unit -> Susp X] hitting [North] and [South], we get the canonical comparison map [X -> P] whose connectivity follows from the Blakers-Massey theorem. *)
H: Univalence n: trunc_index X: Type H0: IsConnected (Tr n.+1) X