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 Cubical.DPath WildCat.Require Import Colimits.Coeq.Require Import Algebra.AbGroups.AbelianGroup.Require Import Modalities.ReflectiveSubuniverse.(** * Abelianization *)(** In this file we define what it means for a group homomorphism [G -> H] into an abelian group [H] to be an abelianization. We then construct an example of an abelianization. *)LocalOpen Scope mc_scope.LocalOpen Scope mc_mult_scope.LocalOpen Scope wc_iso_scope.(** ** Definition of abelianization. A "unit" homomorphism [eta : G -> G_ab], with [G_ab] abelian, is considered an abelianization if and only if for all homomorphisms [G -> A], where [A] is abelian, there exists a unique [g : G_ab -> A] such that [h == g o eta X]. We express this in funext-free form by saying that precomposition with [eta] in the wild 1-category [Group] induces an equivalence of hom 0-groupoids, in the sense of WildCat/EquivGpd. Unfortunately, if [eta : GroupHomomorphism G G_ab] and we write [cat_precomp A eta] then Coq is unable to guess that the relevant 1-category is [Group]. Even writing [cat_precomp (A := Group) A eta] isn't good enough, I guess because the typeclass inference that finds the instance [is01cat_group] doesn't happen until after the type of [eta] would have to be resolved to a [Hom] in some wild category. However, with the following auxiliary definition we can force the typeclass inference to happen first. (It would be worth thinking about whether the design of the wild categories library could be improved to avoid this.) *)Definitiongroup_precomp {ab} := @cat_precomp Group _ _ a b.ClassIsAbelianization {G : Group} (G_ab : AbGroup)
(eta : GroupHomomorphism G G_ab)
:= issurjinj_isabel :: forall (A : AbGroup),
IsSurjInj (group_precomp A eta).
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
IsEquiv (group_precomp A eta)
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
IsEquiv (group_precomp A eta)
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
(G $-> A) -> G_ab $-> A
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
group_precomp A eta o ?g == idmap
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
?g o group_precomp A eta == idmap
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
(G $-> A) -> G_ab $-> A
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup g: G $-> A
G_ab $-> A
exact (surjinj_inv (group_precomp A eta) g).
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
group_precomp A eta
o (fung : G $-> A =>
surjinj_inv (group_precomp A eta) g) == idmap
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup f: G $-> A
group_precomp A eta
(surjinj_inv (group_precomp A eta) f) = f
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup f: G $-> A
group_precomp A eta
(surjinj_inv (group_precomp A eta) f) == f
exact (eisretr0gpd_inv (group_precomp A eta) f).
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup
(fung : G $-> A =>
surjinj_inv (group_precomp A eta) g)
o group_precomp A eta == idmap
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup f: G_ab $-> A
surjinj_inv (group_precomp A eta)
(group_precomp A eta f) = f
H: Funext G: Group G_ab: AbGroup eta: GroupHomomorphism G G_ab IsAbelianization0: IsAbelianization G_ab eta A: AbGroup f: G_ab $-> A
surjinj_inv (group_precomp A eta)
(group_precomp A eta f) == f
exact (eissect0gpd_inv (group_precomp A eta) f).Defined.Definitionequiv_group_precomp_isabelianization `{Funext}
{G : Group} {G_ab : AbGroup} (eta : GroupHomomorphism G G_ab)
`{!IsAbelianization G_ab eta} (A : AbGroup)
: (G_ab $-> A) <~> (G $-> A)
:= Build_Equiv _ _ _ (isequiv_group_precomp_isabelianization eta A).(** Here we define abelianization as a HIT. Specifically as a set-coequalizer of the following two maps [fun '(a, b, c) => a * (b * c)] and [fun '(a, b, c) => a * (c * b)].From this we can show that Abel G is an abelian group.In fact this models the following HIT:<<HIT Abel (G : Group) := | abel_in : G -> Abel G | abel_in_comm : forall x y z, abel_in (x * (y * z)) = abel_in (x * (z * y)).>>We also derive [abel_in] and [abel_in_comm] from our coequalizer definition, and even prove the induction and computation rules for this HIT.This HIT was suggested by Dan Christensen. *)SectionAbel.(** Let G be a group. *)Context (G : Group).(** We locally define a map uncurry2 that lets us uncurry [A * B * C -> D] twice. *)Local Definitionuncurry2 {ABCD : Type}
: (A -> B -> C -> D) -> A * B * C -> D
:= funf '(a, b, c) => f a b c.(** The type [Abel] is defined to be the set coequalizer of the following maps [G^3 -> G]. *)DefinitionAbel
:= Tr 0 (Coeq
(uncurry2 (funabc : G => a * (b * c)))
(uncurry2 (funabc : G => a * (c * b)))).(** We have a natural map from [G] to [Abel G]. *)Definitionabel_in : G -> Abel := tr o coeq.(** This map satisfies the condition [ab_comm]. It's a form of commutativity in a right factor. *)Definitionabel_in_commabc
: abel_in (a * (b * c)) = abel_in (a * (c * b))
:= ap tr (cglue (a, b, c)).(** It is clear that Abel is a set. *)Definitionistrunc_abel : IsHSet Abel := _.(** We can derive the induction principle from the ones for truncation and the coequalizer. *)
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y))
forallx : Abel, P x
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y))
forallx : Abel, P x
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y))
foralla : Coeq (uncurry2 (funabc : G => a * (b * c)))
(uncurry2 (funabc : G => a * (c * b))),
P (tr a)
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y))
foralla : G,
(funw : Coeq
(uncurry2 (funa0bc : G => a0 * (b * c)))
(uncurry2 (funa0bc : G => a0 * (c * b)))
=> P (tr w)) (coeq a)
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y))
forallb : G * G * G,
transport
(funw : Coeq
(uncurry2 (funab0c : G => a * (b0 * c)))
(uncurry2 (funab0c : G => a * (c * b0)))
=> P (tr w)) (cglue b)
(?coeq'
(uncurry2 (funab0c : G => a * (b0 * c)) b)) =
?coeq' (uncurry2 (funab0c : G => a * (c * b0)) b)
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y))
forallb : G * G * G,
transport
(funw : Coeq
(uncurry2 (funab0c : G => a * (b0 * c)))
(uncurry2 (funab0c : G => a * (c * b0)))
=> P (tr w)) (cglue b)
(a (uncurry2 (funab0c : G => a * (b0 * c)) b)) =
a (uncurry2 (funab0c : G => a * (c * b0)) b)
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y)) x, y, z: G
transport
(funw : Coeq
(uncurry2 (funabc : G => a * (b * c)))
(uncurry2 (funabc : G => a * (c * b)))
=> P (tr w)) (cglue (x, y, z))
(a
(uncurry2 (funabc : G => a * (b * c))
(x, y, z))) =
a (uncurry2 (funabc : G => a * (c * b)) (x, y, z))
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y)) x, y, z: G
transport P (ap tr (cglue (x, y, z)))
(a
(uncurry2 (funabc : G => a * (b * c))
(x, y, z))) =
a (uncurry2 (funabc : G => a * (c * b)) (x, y, z))
apply c.Defined.(** The computation rule on point constructors holds definitionally. *)DefinitionAbel_ind_beta_abel_in (P : Abel -> Type) `{forallx, IsHSet (P x)}
(a : forallx, P (abel_in x))
(c : forallxyz, DPath P (abel_in_comm x y z) (a (x * (y * z))) (a (x * (z * y))))
(x : G)
: Abel_ind P a c (abel_in x) = a x
:= idpath.(** The computation rule on paths. *)
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y)) x, y, z: G
apD (Abel_ind P a c) (abel_in_comm x y z) = c x y z
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y)) x, y, z: G
apD (Abel_ind P a c) (abel_in_comm x y z) = c x y z
G: Group P: Abel -> Type H: forallx : Abel, IsHSet (P x) a: forallx : G, P (abel_in x) c: forallxyz : G,
transport P (abel_in_comm x y z) (a (x * (y * z))) =
a (x * (z * y)) x, y, z: G
apD
(funx : Coeq
(uncurry2 (funabc : G => a * (b * c)))
(uncurry2 (funabc : G => a * (c * b)))
=> Abel_ind P a c (tr x)) (cglue (x, y, z)) =
transport_compose P tr (cglue (x, y, z))
(Abel_ind P a c (tr (coeq (x * (y * z))))) @ c x y z
rapply Coeq_ind_beta_cglue.Defined.(** We also have a recursion principle. *)
G: Group P: Type IsHSet0: IsHSet P a: G -> P c: forallxyz : G,
a (x * (y * z)) = a (x * (z * y))
Abel -> P
G: Group P: Type IsHSet0: IsHSet P a: G -> P c: forallxyz : G,
a (x * (y * z)) = a (x * (z * y))
Abel -> P
G: Group P: Type IsHSet0: IsHSet P a: G -> P c: forallxyz : G,
a (x * (y * z)) = a (x * (z * y))
forallxyz : G,
transport (fun_ : Abel => P) (abel_in_comm x y z)
(a (x * (y * z))) = a (x * (z * y))
intros; apply dp_const, c.Defined.(** Here is a simpler version of [Abel_ind] when our target is an [HProp]. This lets us discard all the higher paths. *)
G: Group P: Abel -> Type H: forallx : Abel, IsHProp (P x) a: forallx : G, P (abel_in x)
forallx : Abel, P x
G: Group P: Abel -> Type H: forallx : Abel, IsHProp (P x) a: forallx : G, P (abel_in x)
forallx : Abel, P x
G: Group P: Abel -> Type H: forallx : Abel, IsHProp (P x) a: forallx : G, P (abel_in x)
foralla : Coeq (uncurry2 (funabc : G => a * (b * c)))
(uncurry2 (funabc : G => a * (c * b))),
P (tr a)
G: Group P: Abel -> Type H: forallx : Abel, IsHProp (P x) a: forallx : G, P (abel_in x)
foralla : G,
(funx : Coeq
(uncurry2 (funa0bc : G => a0 * (b * c)))
(uncurry2 (funa0bc : G => a0 * (c * b)))
=> P (tr x)) (coeq a)
exact a.Defined.EndAbel.(** The [IsHProp] argument of [Abel_ind_hprop] can usually be found by typeclass resolution, but [srapply] is slow, so we use this tactic instead. *)Local LtacAbel_ind_hprop x := snapply Abel_ind_hprop; [exact _ | intro x].(** We make sure that [G] is implicit in the arguments of [abel_in] and [abel_in_comm]. *)Arguments abel_in {_} g%_mc_mult_scope.Arguments abel_in_comm {_} (a b c)%_mc_mult_scope.(** Now we can show that [Abel G] is in fact an abelian group. We will denote the operation in [Abel G] by the multiplicative [*] notation even though it is later shown to be commutative. *)SectionAbelGroup.Context (G : Group).(** Firstly we define the operation on [Abel G]. This is defined as follows:<< abel_in x * abel_in y := abel_in (x * y)>> But we need to also check that it preserves [ab_comm] in the appropriate way. *)
forallxyz : G,
(funa : G => abel_in (a * b)) (x * (y * z)) =
(funa : G => abel_in (a * b)) (x * (z * y))
G: Group b, a, c, d: G
abel_in (a * (c * d) * b) = abel_in (a * (d * c) * b)
(* The pattern seems to be to alternate [associativity] and [ab_comm]. *)
G: Group b, a, c, d: G
abel_in (a * (c * d * b)) = abel_in (a * (d * c) * b)
G: Group b, a, c, d: G
abel_in (a * (b * (c * d))) =
abel_in (a * (d * c) * b)
G: Group b, a, c, d: G
abel_in (a * b * (c * d)) = abel_in (a * (d * c) * b)
G: Group b, a, c, d: G
abel_in (a * b * (d * c)) = abel_in (a * (d * c) * b)
G: Group b, a, c, d: G
abel_in (a * (b * (d * c))) =
abel_in (a * (d * c) * b)
G: Group b, a, c, d: G
abel_in (a * (d * c * b)) = abel_in (a * (d * c) * b)
exact (ap _ (associativity _ _ _)).
G: Group a: Abel G
forallxyz : G,
(funb : G =>
Abel_rec G (Abel G) (funa : G => abel_in (a * b))
(funacd : G =>
ap abel_in (associativity a (c * d) b)^ @
(abel_in_comm a (c * d) b @
(ap abel_in (associativity a b (c * d)) @
(abel_in_comm (a * b) c d @
(ap abel_in (associativity a b (d * c))^ @
(abel_in_comm a b (d * c) @
ap abel_in (associativity a (d * c) b))))))
:
(funa0 : G => abel_in (a0 * b)) (a * (c * d)) =
(funa0 : G => abel_in (a0 * b)) (a * (d * c))) a)
(x * (y * z)) =
(funb : G =>
Abel_rec G (Abel G) (funa : G => abel_in (a * b))
(funacd : G =>
ap abel_in (associativity a (c * d) b)^ @
(abel_in_comm a (c * d) b @
(ap abel_in (associativity a b (c * d)) @
(abel_in_comm (a * b) c d @
(ap abel_in (associativity a b (d * c))^ @
(abel_in_comm a b (d * c) @
ap abel_in (associativity a (d * c) b))))))
:
(funa0 : G => abel_in (a0 * b)) (a * (c * d)) =
(funa0 : G => abel_in (a0 * b)) (a * (d * c))) a)
(x * (z * y))
G: Group a: Abel G b, c, d: G
(funb : G =>
Abel_rec G (Abel G) (funa : G => abel_in (a * b))
(funacd : G =>
ap abel_in (associativity a (c * d) b)^ @
(abel_in_comm a (c * d) b @
(ap abel_in (associativity a b (c * d)) @
(abel_in_comm (a * b) c d @
(ap abel_in (associativity a b (d * c))^ @
(abel_in_comm a b (d * c) @
ap abel_in (associativity a (d * c) b))))))
:
(funa0 : G => abel_in (a0 * b)) (a * (c * d)) =
(funa0 : G => abel_in (a0 * b)) (a * (d * c))) a)
(b * (c * d)) =
(funb : G =>
Abel_rec G (Abel G) (funa : G => abel_in (a * b))
(funacd : G =>
ap abel_in (associativity a (c * d) b)^ @
(abel_in_comm a (c * d) b @
(ap abel_in (associativity a b (c * d)) @
(abel_in_comm (a * b) c d @
(ap abel_in (associativity a b (d * c))^ @
(abel_in_comm a b (d * c) @
ap abel_in (associativity a (d * c) b))))))
:
(funa0 : G => abel_in (a0 * b)) (a * (c * d)) =
(funa0 : G => abel_in (a0 * b)) (a * (d * c))) a)
(b * (d * c))
G: Group b, c, d: G
foralla : Abel G,
(funb : G =>
Abel_rec G (Abel G) (funa0 : G => abel_in (a0 * b))
(funa0cd : G =>
ap abel_in (associativity a0 (c * d) b)^ @
(abel_in_comm a0 (c * d) b @
(ap abel_in (associativity a0 b (c * d)) @
(abel_in_comm (a0 * b) c d @
(ap abel_in (associativity a0 b (d * c))^ @
(abel_in_comm a0 b (d * c) @
ap abel_in (associativity a0 (d * c) b))))))
:
(funa1 : G => abel_in (a1 * b)) (a0 * (c * d)) =
(funa1 : G => abel_in (a1 * b)) (a0 * (d * c))) a)
(b * (c * d)) =
(funb : G =>
Abel_rec G (Abel G) (funa0 : G => abel_in (a0 * b))
(funa0cd : G =>
ap abel_in (associativity a0 (c * d) b)^ @
(abel_in_comm a0 (c * d) b @
(ap abel_in (associativity a0 b (c * d)) @
(abel_in_comm (a0 * b) c d @
(ap abel_in (associativity a0 b (d * c))^ @
(abel_in_comm a0 b (d * c) @
ap abel_in (associativity a0 (d * c) b))))))
:
(funa1 : G => abel_in (a1 * b)) (a0 * (c * d)) =
(funa1 : G => abel_in (a1 * b)) (a0 * (d * c))) a)
(b * (d * c))
G: Group b, c, d, a: G
abel_in (a * (b * (c * d))) =
abel_in (a * (b * (d * c)))
G: Group b, c, d, a: G
abel_in (a * b * (c * d)) =
abel_in (a * (b * (d * c)))
G: Group b, c, d, a: G
abel_in (a * b * (d * c)) =
abel_in (a * (b * (d * c)))
exact (ap _ (associativity _ _ _)^).Defined.(** We can now easily show that this operation is associative by [associativity] in [G] and the fact that being associative is a proposition. *)
G: Group
Associative sg_op
G: Group
Associative sg_op
G: Group x, y: Abel G
forallz : Abel G, x * (y * z) = x * y * z
G: Group x: Abel G z: G
forally : Abel G,
(funx0 : Abel G => x * (y * x0) = x * y * x0)
(abel_in z)
G: Group z, y: G
forallx : Abel G,
(funx0 : Abel G =>
(funx1 : Abel G => x * (x0 * x1) = x * x0 * x1)
(abel_in z)) (abel_in y)
G: Group z, y, x: G
abel_in x * (abel_in y * abel_in z) =
abel_in x * abel_in y * abel_in z
napply (ap abel_in); apply associativity.Defined.(** From this we know that [Abel G] is a semigroup. *)#[export] Instanceissemigroup_abel : IsSemiGroup (Abel G) := {}.(** We define the group unit as [abel_in] of the unit of [G] *)#[export] Instancemonunit_abel_zero : MonUnit (Abel G) := abel_in mon_unit.(** By using Abel_ind_hprop we can prove the left and right identity laws. *)
G: Group
LeftIdentity sg_op 1
G: Group
LeftIdentity sg_op 1
G: Group x: G
1 * abel_in x = abel_in x
napply (ap abel_in); apply left_identity.Defined.
G: Group
RightIdentity sg_op 1
G: Group
RightIdentity sg_op 1
G: Group x: G
abel_in x * 1 = abel_in x
napply (ap abel_in); apply right_identity.Defined.(** Hence [Abel G] is a monoid *)#[export] Instanceismonoid_abel : IsMonoid (Abel G) := {}.(** We can also prove that the operation is commutative! This will come in handy later. *)
G: Group
Commutative sg_op
G: Group
Commutative sg_op
G: Group x: Abel G
forally : Abel G, x * y = y * x
G: Group x: Abel G y: G
(funx0 : Abel G => x * x0 = x0 * x) (abel_in y)
G: Group y: G
forallx : Abel G,
(funx0 : Abel G => x * x0 = x0 * x) (abel_in y)
G: Group y, x: G
abel_in x * abel_in y = abel_in y * abel_in x
G: Group y, x: G
abel_in (1 * (x * y)) = abel_in y * abel_in x
G: Group y, x: G
abel_in (1 * (x * y)) = abel_in (1 * (y * x))
apply abel_in_comm.Defined.(** Now we can define the inverse operation. This is just<< (abel_in g)^ := abel_in g^>> However when checking that it respects [ab_comm] we have to show the following:<< abel_in (z^ * y^ * x^) = abel_in (y^ * z^ * x^)>> there is no obvious way to do this, but we note that [abel_in (x * y)] is exactly the definition of [abel_in x * abel_in y]! Hence by [commutativity] we can show this. *)
G: Group
Inverse (Abel G)
G: Group
Inverse (Abel G)
G: Group
forallxyz : G,
(abel_in o inv) (x * (y * z)) =
(abel_in o inv) (x * (z * y))
exact (commutativity (abel_in z^) (abel_in y^)).Defined.(** Again by [Abel_ind_hprop] and the corresponding laws for [G] we can prove the left and right inverse laws. *)
G: Group
LeftInverse sg_op inv 1
G: Group
LeftInverse sg_op inv 1
G: Group x: G
(abel_in x)^ * abel_in x = 1
napply (ap abel_in); apply left_inverse.Defined.
G: Group
RightInverse sg_op inv 1
G: Group
RightInverse sg_op inv 1
G: Group x: G
abel_in x * (abel_in x)^ = 1
napply (ap abel_in); apply right_inverse.Defined.(** Thus [Abel G] is a group *)#[export] Instanceisgroup_abel : IsGroup (Abel G) := {}.(** And furthermore, since the operation is commutative, it is an abelian group. *)#[export] Instanceisabgroup_abel : IsAbGroup (Abel G) := {}.(** By definition, the map [abel_in] is also a group homomorphism. *)
G: Group
IsSemiGroupPreserving abel_in
G: Group
IsSemiGroupPreserving abel_in
byunfold IsSemiGroupPreserving.Defined.EndAbelGroup.(** We can easily prove that [abel_in] is a surjection. *)
G: Group
IsConnMap (Tr (-1)) abel_in
G: Group
IsConnMap (Tr (-1)) abel_in
G: Group
forallb : Abel G, merely (hfiber abel_in b)
G: Group x: G
merely (hfiber abel_in (abel_in x))
G: Group x: G
hfiber abel_in (abel_in x)
G: Group x: G
abel_in x = abel_in x
reflexivity.Defined.(** Now we finally check that our definition of abelianization satisfies the universal property of being an abelianization. *)(** We define [abel] to be the abelianization of a group. This is a map from [Group] to [AbGroup]. *)
Group -> AbGroup
Group -> AbGroup
G: Group
AbGroup
G: Group
Group
G: Group
Commutative sg_op
G: Group
Group
srapply (Build_Group (Abel G)).
G: Group
Commutative sg_op
exact _.Defined.(** We don't wish for [abel G] to be unfolded when using [simpl] or [cbn]. *)Arguments abel G : simpl never.(** The unit of this map is the map [abel_in] which typeclasses can pick up to be a homomorphism. We write it out explicitly here. *)Definitionabel_unit {G : Group} : G $-> abel G
:= @Build_GroupHomomorphism G (abel G) abel_in _.
G: Group A: AbGroup f: G $-> A
abel G $-> A
G: Group A: AbGroup f: G $-> A
abel G $-> A
G: Group A: AbGroup f: G $-> A
abel G -> A
G: Group A: AbGroup f: G $-> A
IsSemiGroupPreserving ?grp_homo_map
G: Group A: AbGroup f: G $-> A
abel G -> A
G: Group A: AbGroup f: G $-> A
forallxyz : G, f (x * (y * z)) = f (x * (z * y))
G: Group A: AbGroup f: G $-> A x, y, z: G
f (x * (y * z)) = f (x * (z * y))
G: Group A: AbGroup f: G $-> A x, y, z: G
f (y * z) = f (z * y)
G: Group A: AbGroup f: G $-> A x, y, z: G
f y * f z = f z * f y
apply commutativity.
G: Group A: AbGroup f: G $-> A
IsSemiGroupPreserving
(Abel_rec G A f
(funxyz : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y z @
commutativity (f y) (f z)) @
(grp_homo_op f z y)^)))
G: Group A: AbGroup f: G $-> A y: abel G
forally0 : abel G,
Abel_rec G A f
(funxyz : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y z @ commutativity (f y) (f z)) @
(grp_homo_op f z y)^)) (y * y0) =
Abel_rec G A f
(funxyz : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y z @ commutativity (f y) (f z)) @
(grp_homo_op f z y)^)) y *
Abel_rec G A f
(funxyz : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y z @ commutativity (f y) (f z)) @
(grp_homo_op f z y)^)) y0
G: Group A: AbGroup f: G $-> A x: G
forally : abel G,
(funx : Abel G =>
Abel_rec G A f
(funx0y0z : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y0 z @
commutativity (f y0) (f z)) @
(grp_homo_op f z y0)^)) (y * x) =
Abel_rec G A f
(funx0y0z : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y0 z @
commutativity (f y0) (f z)) @
(grp_homo_op f z y0)^)) y *
Abel_rec G A f
(funx0y0z : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y0 z @
commutativity (f y0) (f z)) @
(grp_homo_op f z y0)^)) x) (abel_in x)
G: Group A: AbGroup f: G $-> A x, y: G
(funx0 : Abel G =>
(funx : Abel G =>
Abel_rec G A f
(funx1yz : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y z @ commutativity (f y) (f z)) @
(grp_homo_op f z y)^)) (x0 * x) =
Abel_rec G A f
(funx1yz : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y z @ commutativity (f y) (f z)) @
(grp_homo_op f z y)^)) x0 *
Abel_rec G A f
(funx1yz : G =>
grp_homo_op_agree f f 1
((grp_homo_op f y z @ commutativity (f y) (f z)) @
(grp_homo_op f z y)^)) x) (abel_in x))
(abel_in y)
apply grp_homo_op.Defined.
G, H: Group f, g: abel G $-> H p: f $o abel_unit $== g $o abel_unit
f $== g
G, H: Group f, g: abel G $-> H p: f $o abel_unit $== g $o abel_unit
f $== g
G, H: Group f, g: abel G $-> H p: f $o abel_unit $== g $o abel_unit
forallx : G, f (abel_in x) = g (abel_in x)
exact p.Defined.(** Finally we can prove that our construction abel is an abelianization. *)
G: Group
IsAbelianization (abel G) abel_unit
G: Group
IsAbelianization (abel G) abel_unit
G: Group A: AbGroup
IsSurjInj (group_precomp A abel_unit)
G: Group A: AbGroup
SplEssSurj (group_precomp A abel_unit)
G: Group A: AbGroup
forallxy : abel G $-> A,
group_precomp A abel_unit x $==
group_precomp A abel_unit y -> x $== y
G: Group A: AbGroup
SplEssSurj (group_precomp A abel_unit)
G: Group A: AbGroup h: G $-> A
{a : abel G $-> A & group_precomp A abel_unit a $== h}
G: Group A: AbGroup h: G $-> A
(funa : abel G $-> A =>
group_precomp A abel_unit a $== h)
(grp_homo_abel_rec h)
G: Group A: AbGroup h: G $-> A
(funx : G =>
Coeq_ind
(fun_ : Coeq
(uncurry2 (funabc : G => a * (b * c)))
(uncurry2 (funabc : G => a * (c * b)))
=> A) h
(funb : G * G * G =>
transport_compose
(fun_ : Trunc 0
(Coeq
(uncurry2
(funab0c : G => a * (b0 * c)))
(uncurry2
(funab0c : G => a * (c * b0))))
=> A) tr
(cglue (fst (fst b), snd (fst b), snd b))
(h
(uncurry2 (funab0c : G => a * (b0 * c))
(fst (fst b), snd (fst b), snd b))) @
dp_const
(grp_homo_op_agree h h 1
((grp_homo_op h (snd (fst b)) (snd b) @
commutativity (h (snd (fst b))) (h (snd b))) @
(grp_homo_op h (snd b) (snd (fst b)))^)))
(coeq x)) == h
reflexivity.
G: Group A: AbGroup
forallxy : abel G $-> A,
group_precomp A abel_unit x $==
group_precomp A abel_unit y -> x $== y
G: Group A: AbGroup g, h: abel G $-> A p: group_precomp A abel_unit g $==
group_precomp A abel_unit h
g $== h
G: Group A: AbGroup g, h: abel G $-> A p: group_precomp A abel_unit g $==
group_precomp A abel_unit h x: G
(funx : Abel G =>
(grp_homo_map
:
GroupHomomorphism (abel G) A -> abel G $-> A) g x =
(grp_homo_map
:
GroupHomomorphism (abel G) A -> abel G $-> A) h x)
(abel_in x)
exact (p x).Defined.
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2
A ≅ B
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2
A ≅ B
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2
A ≅ B
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
A ≅ B
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
IsEquiv a
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
a o b == idmap
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
b o a == idmap
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
a o b == idmap
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
group_precomp B eta2 (a $o b) $==
group_precomp B eta2 (Id B)
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: GroupHomomorphism A B ac: (funx : G => a (eta1 x)) == eta2 b: GroupHomomorphism B A bc: (funx : G => b (eta2 x)) == eta1 x: G
a (b (eta2 x)) = eta2 x
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: GroupHomomorphism A B ac: (funx : G => a (eta1 x)) == eta2 b: GroupHomomorphism B A bc: (funx : G => b (eta2 x)) == eta1 x: G
a (b (eta2 x)) = a (eta1 x)
apply ap, bc.
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
b o a == idmap
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
b o a == idmap
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: A $-> B ac: group_precomp B eta1 a $== eta2 b: B $-> A bc: group_precomp A eta2 b $== eta1
group_precomp A eta1 (b $o a) $==
group_precomp A eta1 (Id A)
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: GroupHomomorphism A B ac: (funx : G => a (eta1 x)) == eta2 b: GroupHomomorphism B A bc: (funx : G => b (eta2 x)) == eta1 x: G
b (a (eta1 x)) = eta1 x
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 a: GroupHomomorphism A B ac: (funx : G => a (eta1 x)) == eta2 b: GroupHomomorphism B A bc: (funx : G => b (eta2 x)) == eta1 x: G
b (a (eta1 x)) = b (eta2 x)
apply ap, ac.}Defined.
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2
eta2 ==
grp_homo_compose
(groupiso_isabelianization A B eta1 eta2) eta1
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2
eta2 ==
grp_homo_compose
(groupiso_isabelianization A B eta1 eta2) eta1
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 x: G
eta2 x =
grp_homo_compose
(groupiso_isabelianization A B eta1 eta2) eta1 x
G: Group A, B: AbGroup eta1: GroupHomomorphism G A eta2: GroupHomomorphism G B isab1: IsAbelianization A eta1 isab2: IsAbelianization B eta2 x: G
grp_homo_compose
(groupiso_isabelianization A B eta1 eta2) eta1 x =
eta2 x
exact ((esssurj (group_precomp B eta1) eta2).2 x).Defined.(** Hence any abelianization is surjective. *)
G: Group A: AbGroup eta: GroupHomomorphism G A
IsAbelianization A eta -> IsConnMap (Tr (-1)) eta
G: Group A: AbGroup eta: GroupHomomorphism G A
IsAbelianization A eta -> IsConnMap (Tr (-1)) eta
G: Group A: AbGroup eta: GroupHomomorphism G A k: IsAbelianization A eta
IsConnMap (Tr (-1)) eta
G: Group A: AbGroup eta: GroupHomomorphism G A k: IsAbelianization A eta p:= homotopic_isabelianization A (abel G) eta abel_unit: abel_unit ==
grp_homo_compose
(groupiso_isabelianization A (abel G) eta
abel_unit) eta