Built with Alectryon, running Coq+SerAPI v8.18.0+0.18.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]
LocalOpen Scope mc_scope.LocalOpen Scope mc_mult_scope.(** [IsFreeGroup] is defined in Group.v. In this file we construct free groups and and prove properties about them. *)(** We construct the free group on a type [A] as a higher inductive type. This construction is due to Kraus-Altenkirch 2018 arXiv:1805.02069. Their construction is actually more general, but we set-truncate it to suit our needs which is the free group as a set. This is a very simple HIT in a similar manner to the abelianization HIT used in Algebra.AbGroup.Abelianization. *)SectionReduction.Universeu.Context (A : Type@{u}).(** We define words (with inverses) on A to be lists of marked elements of A *)Local DefinitionWords : Type@{u} := list (A + A).(** Given a marked element of A we can change its mark *)Local Definitionchange_sign : A + A -> A + A := equiv_sum_symm A A.(** We introduce a local notation for [change_sign]. It is only defined in this section however. *)LocalNotation"x ^" := (change_sign x).(** Changing sign is an involution *)
A: Type a: (A + A)%type
(a^)^ = a
A: Type a: (A + A)%type
(a^)^ = a
bydestruct a.Defined.(** We can concatenate words using list concatenation *)Local Definitionword_concat : Words -> Words -> Words := @app _.(** We introduce a local notation for word_concat. *)LocalInfix"@" := word_concat.
A: Type x: Words
x @ nil = x
A: Type x: Words
x @ nil = x
A: Type a: (A + A)%type x: list (A + A) IHx: x @ nil = x
(a :: x)%list @ nil = (a :: x)%list
cbn; f_ap.Defined.
A: Type x, y, z: Words
x @ (y @ z) = (x @ y) @ z
A: Type x, y, z: Words
x @ (y @ z) = (x @ y) @ z
apply app_assoc.Defined.(** Singleton word *)Local Definitionword_sing (x : A + A) : Words := (cons x nil).LocalNotation"[ x ]" := (word_sing x).(** Now we wish to define the free group on A as the following HIT: HIT N(A) : hSet | eta : Words -> N(A) | tau (x : Words) (a : A + A) (y : Words) : eta (x @ [a] @ [a^] @ y) = eta (x @ y). Since we cannot write our HITs directly like this (without resorting to private inductive types), we will construct this HIT out of HITs we know. In fact, we can define N(A) as a coequalizer. *)
A: Type
Words * (A + A) * Words -> Words
A: Type
Words * (A + A) * Words -> Words
A: Type x: Words a: (A + A)%type y: Words
Words
exact (x @ [a] @ [a^] @ y).Defined.
A: Type
Words * (A + A) * Words -> Words
A: Type
Words * (A + A) * Words -> Words
A: Type x: Words a: (A + A)%type y: Words
Words
exact (x @ y).Defined.(** Now we can define the underlying type of the free group as the 0-truncated coequalizer of these two maps *)Definitionfreegroup_type : Type := Tr 0 (Coeq map1 map2).(** This is the point constructor *)Definitionfreegroup_eta : Words -> freegroup_type := tr o coeq.(** This is the path constructor *)
exact ((cglue (x, a, y))).Defined.(** The group operation *)
A: Type
SgOp freegroup_type
A: Type
SgOp freegroup_type
A: Type x, y: freegroup_type
freegroup_type
A: Type y, x: Coeq map1 map2
freegroup_type
A: Type y: Coeq map1 map2
Words -> freegroup_type
A: Type y: Coeq map1 map2
forallb : Words * (A + A) * Words,
?coeq' (map1 b) = ?coeq' (map2 b)
A: Type y: Coeq map1 map2
Words -> freegroup_type
A: Type x: Words
Coeq map1 map2 -> freegroup_type
A: Type x: Words
Words -> freegroup_type
A: Type x: Words
forallb : Words * (A + A) * Words,
?coeq' (map1 b) = ?coeq' (map2 b)
A: Type x: Words
Words -> freegroup_type
A: Type x, y: Words
freegroup_type
exact (freegroup_eta (x @ y)).
A: Type x: Words
forallb : Words * (A + A) * Words,
(funy : Words => freegroup_eta (x @ y)) (map1 b) =
(funy : Words => freegroup_eta (x @ y)) (map2 b)
A: Type x, y: Words a: (A + A)%type z: Words
freegroup_eta
(x @
(((y @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end]) @ z)) = freegroup_eta (x @ (y @ z))
A: Type x, y: Words a: (A + A)%type z: Words
x @
(((y @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end]) @ z) = ?Goal
A: Type x, y: Words a: (A + A)%type z: Words
freegroup_eta ?Goal = freegroup_eta (x @ (y @ z))
A: Type x, y: Words a: (A + A)%type z: Words
x @
(((y @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end]) @ z) = ?Goal
A: Type x, y: Words a: (A + A)%type z: Words
(x @
((y @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end])) @ z = ?Goal
A: Type x, y: Words a: (A + A)%type z: Words
x @
((y @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end]) = ?Goal0
A: Type x, y: Words a: (A + A)%type z: Words
(x @ (y @ [a])) @
[match a with
| inl a => inr a
| inr b => inl b
end] = ?Goal0
A: Type x, y: Words a: (A + A)%type z: Words
x @ (y @ [a]) = ?Goal0
refine (word_concat_w_ww _ _ _).
A: Type x, y: Words a: (A + A)%type z: Words
freegroup_eta
((((x @ y) @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end]) @ z) = freegroup_eta (x @ (y @ z))
A: Type x, y: Words a: (A + A)%type z: Words
freegroup_eta
((((x @ y) @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end]) @ z) = freegroup_eta ?Goal0
A: Type x, y: Words a: (A + A)%type z: Words
x @ (y @ z) = ?Goal0
A: Type x, y: Words a: (A + A)%type z: Words
freegroup_eta
((((x @ y) @ [a]) @
[match a with
| inl a => inr a
| inr b => inl b
end]) @ z) = freegroup_eta ((x @ y) @ z)
apply freegroup_tau.
A: Type y: Coeq map1 map2
forallb : Words * (A + A) * Words,
(funx : Words =>
Coeq_rec freegroup_type
(funy : Words => freegroup_eta (x @ y))
(funb0 : Words * (A + A) * Words =>
(funfst : Words * (A + A) =>
(fun (y : Words) (a : A + A) (z : Words) =>
(ap freegroup_eta
(word_concat_w_ww x
(word_concat (word_concat y [a])
[match a with
| inl a0 => inr a0
| inr b1 => inl b1
end]) z @
ap (funt : Words => word_concat t z)
(word_concat_w_ww x (word_concat y [a])
[match ... with
| ... => inr a0
| ... => inl b1
end] @
ap (fun ... => word_concat t [...])
(word_concat_w_ww x y [a]))) @
(freegroup_tau (word_concat x y) a z @
ap freegroup_eta (word_concat_w_ww x y z)^))%path
:
freegroup_eta (x @ map1 (y, a, z)) =
freegroup_eta (x @ map2 (y, a, z)))
(Overture.fst fst) (snd fst)) (fst b0) (snd b0))
y) (map1 b) =
(funx : Words =>
Coeq_rec freegroup_type
(funy : Words => freegroup_eta (x @ y))
(funb0 : Words * (A + A) * Words =>
(funfst : Words * (A + A) =>
(fun (y : Words) (a : A + A) (z : Words) =>
(ap freegroup_eta
(word_concat_w_ww x
(word_concat (word_concat y [a])
[match a with
| inl a0 => inr a0
| inr b1 => inl b1
end]) z @
ap (funt : Words => word_concat t z)
(word_concat_w_ww x (word_concat y [a])
[match ... with
| ... => inr a0
| ... => inl b1
end] @
ap (fun ... => word_concat t [...])
(word_concat_w_ww x y [a]))) @
(freegroup_tau (word_concat x y) a z @
ap freegroup_eta (word_concat_w_ww x y z)^))%path
:
freegroup_eta (x @ map1 (y, a, z)) =
freegroup_eta (x @ map2 (y, a, z)))
(Overture.fst fst) (snd fst)) (fst b0) (snd b0))
y) (map2 b)
A: Type y: Coeq map1 map2 c: Words b: (A + A)%type d: Words
Coeq_rec freegroup_type
(funy : Words => freegroup_eta (map1 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(word_concat
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map1 (c, b, d))
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map1 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) y =
Coeq_rec freegroup_type
(funy : Words => freegroup_eta (map2 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(word_concat
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map2 (c, b, d))
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map2 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) y
A: Type y: Coeq map1 map2 c: Words b: (A + A)%type d: Words
Coeq_rec freegroup_type
(funy : Words => freegroup_eta (map1 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(word_concat
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map1 (c, b, d))
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map1 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) y =
Coeq_rec freegroup_type
(funy : Words => freegroup_eta (map2 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(word_concat
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map2 (c, b, d))
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map2 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) y
A: Type c: Words b: (A + A)%type d: Words
forally : Coeq map1 map2,
Coeq_rec freegroup_type
(funy0 : Words =>
freegroup_eta (map1 (c, b, d) @ y0))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(word_concat
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map1 (c, b, d))
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map1 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) y =
Coeq_rec freegroup_type
(funy0 : Words =>
freegroup_eta (map2 (c, b, d) @ y0))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(word_concat
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map2 (c, b, d))
(word_concat (fst (fst b0)) [snd (fst b0)])
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map2 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) y
A: Type c: Words b: (A + A)%type d: Words
foralla : Words,
(funw : Coeq map1 map2 =>
Coeq_rec freegroup_type
(funy : Words =>
freegroup_eta (map1 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(word_concat
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map1 (c, b, d))
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end])
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map1 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) w =
Coeq_rec freegroup_type
(funy : Words =>
freegroup_eta (map2 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(word_concat
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map2 (c, b, d))
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end])
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map2 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) w)
(coeq a)
A: Type c: Words b: (A + A)%type d: Words
forallb0 : Words * (A + A) * Words,
transport
(funw : Coeq map1 map2 =>
Coeq_rec freegroup_type
(funy : Words =>
freegroup_eta (map1 (c, b, d) @ y))
(funb1 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(word_concat
(word_concat (fst (fst b1))
[snd (fst b1)])
[match snd (fst b1) with
| inl a => inr a
| inr b => inl b
end]) (snd b1) @
ap (funt : Words => word_concat t (snd b1))
(word_concat_w_ww (map1 (c, b, d))
(word_concat (fst (fst b1))
[snd (fst b1)])
[match snd (fst b1) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (...) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b1)) [snd (fst b1)]))) @
(freegroup_tau
(word_concat (map1 (c, b, d)) (fst (fst b1)))
(snd (fst b1)) (snd b1) @
ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b1)) (snd b1))^))%path) w =
Coeq_rec freegroup_type
(funy : Words =>
freegroup_eta (map2 (c, b, d) @ y))
(funb1 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(word_concat
(word_concat (fst (fst b1))
[snd (fst b1)])
[match snd (fst b1) with
| inl a => inr a
| inr b => inl b
end]) (snd b1) @
ap (funt : Words => word_concat t (snd b1))
(word_concat_w_ww (map2 (c, b, d))
(word_concat (fst (fst b1))
[snd (fst b1)])
[match snd (fst b1) with
| inl a => inr a
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (...) with
| inl a => inr a
| inr b => inl b
end])
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b1)) [snd (fst b1)]))) @
(freegroup_tau
(word_concat (map2 (c, b, d)) (fst (fst b1)))
(snd (fst b1)) (snd b1) @
ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b1)) (snd b1))^))%path) w)
(cglue b0) (?coeq' (map1 b0)) = ?coeq' (map2 b0)
A: Type c: Words b: (A + A)%type d: Words
foralla : Words,
(funw : Coeq map1 map2 =>
Coeq_rec freegroup_type
(funy : Words =>
freegroup_eta (map1 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(word_concat
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map1 (c, b, d))
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end])
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map1 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map1 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) w =
Coeq_rec freegroup_type
(funy : Words =>
freegroup_eta (map2 (c, b, d) @ y))
(funb0 : Words * (A + A) * Words =>
(ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(word_concat
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end]) (snd b0) @
ap (funt : Words => word_concat t (snd b0))
(word_concat_w_ww (map2 (c, b, d))
(word_concat (fst (fst b0))
[snd (fst b0)])
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end] @
ap
(funt : Words =>
word_concat t
[match snd (fst b0) with
| inl a0 => inr a0
| inr b => inl b
end])
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) [snd (fst b0)]))) @
(freegroup_tau
(word_concat (map2 (c, b, d)) (fst (fst b0)))
(snd (fst b0)) (snd b0) @
ap freegroup_eta
(word_concat_w_ww (map2 (c, b, d))
(fst (fst b0)) (snd b0))^))%path) w)
(coeq a)
A: Type c: Words b: (A + A)%type d: Words
foralla : Words,
freegroup_eta (map1 (c, b, d) @ a) =
freegroup_eta (map2 (c, b, d) @ a)
A: Type c: Words b: (A + A)%type d, a: Words
freegroup_eta (map1 (c, b, d) @ a) =
freegroup_eta (map2 (c, b, d) @ a)
apply word_concat_Vw.Defined.(** Negation is defined by changing the order of a word that appears in eta. Most of the work here is checking that it is agreeable with the path constructor. *)
A: Type
Negate freegroup_type
A: Type
Negate freegroup_type
A: Type x: freegroup_type
freegroup_type
A: Type x: Coeq map1 map2
freegroup_type
A: Type
Words -> freegroup_type
A: Type
forallb : Words * (A + A) * Words,
?coeq' (map1 b) = ?coeq' (map2 b)
A: Type
Words -> freegroup_type
A: Type x: Words
freegroup_type
A: Type x: Words
Words
exact (word_change_sign x).
A: Type
forallb : Words * (A + A) * Words,
(funx : Words => freegroup_eta (word_change_sign x))
(map1 b) =
(funx : Words => freegroup_eta (word_change_sign x))
(map2 b)
A: Type b: Words a: (A + A)%type c: Words
freegroup_eta (word_change_sign (map1 (b, a, c))) =
freegroup_eta (word_change_sign (map2 (b, a, c)))
word_change_sign ([a] @ [a^]) @ word_change_sign b =
?y
A: Type b: Words a: (A + A)%type c: Words
word_change_sign ([a] @ [a^]) = ?Goal0
apply word_change_sign_ww.
A: Type b: Words a: (A + A)%type c: Words
freegroup_eta
(word_change_sign c @
((word_change_sign [a^] @ word_change_sign [a]) @
word_change_sign b)) =
freegroup_eta
(word_change_sign c @ word_change_sign b)
A: Type b: Words a: (A + A)%type c: Words
freegroup_eta
(word_change_sign c @
((word_change_sign [a^] @ word_change_sign [a]) @
word_change_sign b)) =
freegroup_eta
(((word_change_sign c @ [a]) @ [a^]) @
word_change_sign b)
A: Type b: Words a: (A + A)%type c: Words
word_change_sign c @
((word_change_sign [a^] @ word_change_sign [a]) @
word_change_sign b) =
((word_change_sign c @ [a]) @ [a^]) @
word_change_sign b
A: Type b: Words a: (A + A)%type c: Words
word_change_sign c @
(word_change_sign [a^] @ word_change_sign [a]) =
(word_change_sign c @ [a]) @ [a^]
A: Type b: Words a: (A + A)%type c: Words
word_change_sign c @ word_change_sign [a^] =
word_change_sign c @ [a]
A: Type b: Words a: (A + A)%type c: Words
matchmatch a with
| inl a => inr a
| inr b => inl b
endwith
| inl a => inr a
| inr b => inl b
end = a
apply change_sign_inv.Defined.(** Now we can start to prove the group laws. Since these are hprops we can ignore what happens with the path constructor. *)(** Our operation is associative *)
A: Type
Associative sg_op
A: Type
Associative sg_op
A: Type x, y, z: freegroup_type
x * (y * z) = x * y * z
A: Type z, y, x: Coeq map1 map2
tr x * (tr y * tr z) = tr x * tr y * tr z
A: Type z, y: Coeq map1 map2 x: Words
(funw : Coeq map1 map2 =>
tr w * (tr y * tr z) = tr w * tr y * tr z) (coeq x)
A: Type G: Group s: A -> G x: (A + A)%type xs: list (A + A) IHxs: G
G
A: Type G: Group s: A -> G x: (A + A)%type xs: list (A + A) IHxs: G
G
A: Type G: Group s: A -> G x: (A + A)%type xs: list (A + A) IHxs: G
G
A: Type G: Group s: A -> G x: A xs: list (A + A) IHxs: G
G
A: Type G: Group s: A -> G x: A xs: list (A + A) IHxs: G
G
A: Type G: Group s: A -> G x: A xs: list (A + A) IHxs: G
G
exact (- s x).Defined.
A: Type G: Group s: A -> G x, y: Words
words_rec G s (x @ y) =
words_rec G s x * words_rec G s y
A: Type G: Group s: A -> G x, y: Words
words_rec G s (x @ y) =
words_rec G s x * words_rec G s y
A: Type G: Group s: A -> G y: Words
words_rec G s (nil @ y) =
words_rec G s nil * words_rec G s y
A: Type G: Group s: A -> G a: (A + A)%type x: list (A + A) y: Words IHx: words_rec G s (x @ y) = words_rec G s x * words_rec G s y
words_rec G s ((a :: x)%list @ y) =
words_rec G s (a :: x)%list * words_rec G s y
A: Type G: Group s: A -> G a: (A + A)%type x: list (A + A) y: Words IHx: words_rec G s (x @ y) = words_rec G s x * words_rec G s y
words_rec G s ((a :: x)%list @ y) =
words_rec G s (a :: x)%list * words_rec G s y
A: Type G: Group s: A -> G a: (A + A)%type x: list (A + A) y: Words IHx: words_rec G s (x @ y) = words_rec G s x * words_rec G s y
match a with
| inl a => s a
| inr a => - s a
end *
list_rect (A + A) (fun_ : list (A + A) => G) mon_unit
(fun (x : A + A) (_ : list (A + A)) (IHxs : G) =>
match x with
| inl a => s a
| inr a => - s a
end * IHxs) (x @ y) =
match a with
| inl a => s a
| inr a => - s a
end *
(list_rect (A + A) (fun_ : list (A + A) => G)
mon_unit
(fun (x : A + A) (_ : list (A + A)) (IHxs : G) =>
match x with
| inl a => s a
| inr a => - s a
end * IHxs) x * words_rec G s y)
f_ap.Defined.
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s (map1 (b, a, c)) =
words_rec G s (map2 (b, a, c))
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s (map1 (b, a, c)) =
words_rec G s (map2 (b, a, c))
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s (((b @ [a]) @ [a^]) @ c) =
words_rec G s (b @ c)
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s (((b @ [a]) @ [a^]) @ c) =
words_rec G s b * words_rec G s c
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s ((b @ [a]) @ [a^]) = words_rec G s b
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s ((b @ [a]) @ [a^]) =
words_rec G s b * mon_unit
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s (b @ ([a] @ [a^])) =
words_rec G s b * mon_unit
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
words_rec G s ([a] @ [a^]) = mon_unit
A: Type G: Group s: A -> G a: (A + A)%type b, c: Words
match a with
| inl a => s a
| inr a => - s a
end *
match a^ with
| inl a => s a
| inr a => - s a
end * mon_unit = mon_unit * mon_unit
A: Type G: Group s: A -> G a: A b, c: Words
s a * - s a = mon_unit
A: Type G: Group s: A -> G a: A b, c: Words
- s a * s a = mon_unit
A: Type G: Group s: A -> G a: A b, c: Words
s a * - s a = mon_unit
apply right_inverse.
A: Type G: Group s: A -> G a: A b, c: Words
- s a * s a = mon_unit
apply left_inverse.Defined.(** Given a group [G] we can construct a group homomorphism [FreeGroup A -> G] if we have a map [A -> G] *)
A: Type G: Group s: A -> G
GroupHomomorphism FreeGroup G
A: Type G: Group s: A -> G
GroupHomomorphism FreeGroup G
A: Type G: Group s: A -> G
FreeGroup -> G
A: Type G: Group s: A -> G
IsSemiGroupPreserving ?f
A: Type G: Group s: A -> G
FreeGroup -> G
A: Type G: Group s: A -> G
Coeq map1 map2 -> G
A: Type G: Group s: A -> G
Words -> G
A: Type G: Group s: A -> G
forallb : Words * (A + A) * Words,
?coeq' (map1 b) = ?coeq' (map2 b)
A: Type G: Group s: A -> G
forallb : Words * (A + A) * Words,
words_rec G s (map1 b) = words_rec G s (map2 b)
A: Type G: Group s: A -> G b: Words a: (A + A)%type c: Words
words_rec G s (map1 (b, a, c)) =
words_rec G s (map2 (b, a, c))
apply words_rec_coh.
A: Type G: Group s: A -> G
IsSemiGroupPreserving
(Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
(funfst : Words * (A + A) =>
(fun (b : Words) (a : A + A) (c : Words) =>
words_rec_coh G s a b c) (Overture.fst fst)
(snd fst)) (fst b0) (snd b0))))
A: Type G: Group s: A -> G y, x: Coeq map1 map2
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr x * tr y) =
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr x) *
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr y)
A: Type G: Group s: A -> G y: Coeq map1 map2 x: Words
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr (coeq x) * tr y) =
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr (coeq x)) *
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr y)
A: Type G: Group s: A -> G x, y: Words
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr (coeq x) * tr (coeq y)) =
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr (coeq x)) *
Trunc_rec
(Coeq_rec G (words_rec G s)
(funb0 : Words * (A + A) * Words =>
words_rec_coh G s (snd (fst b0)) (fst (fst b0))
(snd b0))) (tr (coeq y))
A: Type G: Group s: A -> G x, y: Words
words_rec G s (x @ y) =
words_rec G s x * words_rec G s y
apply words_rec_pp.Defined.(** Now we need to prove that the free group satisifes the unviersal property of the free group. *)(** TODO: remove funext from here and universal property of free group *)
A: Type H: Funext
IsFreeGroupOn A FreeGroup
(freegroup_eta o word_sing o inl)
A: Type H: Funext
IsFreeGroupOn A FreeGroup
(freegroup_eta o word_sing o inl)
A: Type H: Funext G: Group f: A -> G
Contr
(FactorsThroughFreeGroup A FreeGroup
(funx : A => freegroup_eta [inl x]) G f)
A: Type H: Funext G: Group f: A -> G
FactorsThroughFreeGroup A FreeGroup
(funx : A => freegroup_eta [inl x]) G f
A: Type H: Funext G: Group f: A -> G
forally : FactorsThroughFreeGroup A FreeGroup
(funx : A => freegroup_eta [inl x]) G f,
?center = y
A: Type H: Funext G: Group f: A -> G
FactorsThroughFreeGroup A FreeGroup
(funx : A => freegroup_eta [inl x]) G f
A: Type H: Funext G: Group f: A -> G
GroupHomomorphism FreeGroup G
A: Type H: Funext G: Group f: A -> G
(funx : A => ?Goal (freegroup_eta [inl x])) == f
A: Type H: Funext G: Group f: A -> G
(funx : A =>
FreeGroup_rec G f (freegroup_eta [inl x])) == f
A: Type H: Funext G: Group f: A -> G x: A
f x * mon_unit = f x
apply right_identity.
A: Type H: Funext G: Group f: A -> G
forally : FactorsThroughFreeGroup A FreeGroup
(funx : A => freegroup_eta [inl x]) G f,
(FreeGroup_rec G f : FreeGroup $-> G;
((funx : A =>
right_identity (f x)
:
FreeGroup_rec G f (freegroup_eta [inl x]) = f x)
:
(funx : A =>
FreeGroup_rec G f (freegroup_eta [inl x])) == f)
:
(funf0 : FreeGroup $-> G =>
f0 o (funx : A => freegroup_eta [inl x]) == f)
(FreeGroup_rec G f : FreeGroup $-> G)) = y
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f
(FreeGroup_rec G f; funx : A => right_identity (f x)) =
(g; h)
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f
(FreeGroup_rec G f; funx : A => right_identity (f x)).1 =
(g; h).1
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f
FreeGroup_rec G f = g
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f
FreeGroup_rec G f == g
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f x: FreeGroup
FreeGroup_rec G f x = g x
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f x: FreeGroup
FreeGroup_rec G
(funx : A => g (freegroup_eta [inl x])) x = g x
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f
forallx : Coeq map1 map2,
FreeGroup_rec G
(funx0 : A => g (freegroup_eta [inl x0])) (tr x) =
g (tr x)
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f x: Words
(funw : Coeq map1 map2 =>
FreeGroup_rec G
(funx : A => g (freegroup_eta [inl x])) (tr w) =
g (tr w)) (coeq x)
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f x: Words
g (tr (coeq x)) =
FreeGroup_rec G
(funx : A => g (freegroup_eta [inl x]))
(tr (coeq x))
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f
g (tr (coeq nil)) =
FreeGroup_rec G
(funx : A => g (freegroup_eta [inl x]))
(tr (coeq nil))
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: (A + A)%type x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (tr (coeq (a :: x)%list)) =
FreeGroup_rec G
(funx : A => g (freegroup_eta [inl x]))
(tr (coeq (a :: x)%list))
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: (A + A)%type x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (tr (coeq (a :: x)%list)) =
FreeGroup_rec G
(funx : A => g (freegroup_eta [inl x]))
(tr (coeq (a :: x)%list))
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: (A + A)%type x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (freegroup_eta [a]) * g (freegroup_eta x) =
FreeGroup_rec G
(funx : A => g (freegroup_eta [inl x]))
(tr (coeq (a :: x)%list))
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: (A + A)%type x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (freegroup_eta [a]) * g (freegroup_eta x) =
match a with
| inl a => g (freegroup_eta [inl a])
| inr a => - g (freegroup_eta [inl a])
end *
words_rec G (funx : A => g (freegroup_eta [inl x])) x
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: (A + A)%type x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (freegroup_eta [a]) =
match a with
| inl a => g (freegroup_eta [inl a])
| inr a => - g (freegroup_eta [inl a])
end
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: A x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (freegroup_eta [inl a]) = g (freegroup_eta [inl a])
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: A x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (freegroup_eta [inr a]) =
- g (freegroup_eta [inl a])
A: Type H: Funext G: Group f: A -> G g: FreeGroup $-> G h: (funx : A => g (freegroup_eta [inl x])) == f a: A x: list (A + A) IHx: g (tr (coeq x)) =
FreeGroup_rec G (funx : A => g (freegroup_eta [inl x])) (tr (coeq x))
g (freegroup_eta [inr a]) =
- g (freegroup_eta [inl a])
exact (grp_homo_inv g (freegroup_eta [inl a])).Defined.(** Typeclass search can already find this but we leave it here as a definition for reference. *)Definitionisfreegroup_freegroup `{Funext} : IsFreeGroup FreeGroup := _.Definitionfreegroup_in : A -> FreeGroup
:= freegroup_eta o word_sing o inl.
A: Type G: Group f: A -> G
FreeGroup_rec G f o freegroup_in == f
A: Type G: Group f: A -> G
FreeGroup_rec G f o freegroup_in == f
A: Type G: Group f: A -> G x: A
FreeGroup_rec G f (freegroup_in x) = f x
apply grp_unit_r.Defined.Coercionfreegroup_in : A >-> group_type.EndReduction.Arguments freegroup_eta {A}.Arguments freegroup_in {A}.(** Properties of free groups *)(* Given a function on the generators, there is an induced group homomorphism from the free group. *)Definitionisfreegroupon_rec {S : Type} {F_S : Group}
{i : S -> F_S} `{IsFreeGroupOn S F_S i}
{G : Group} (f : S -> G) : F_S $-> G
:= (center (FactorsThroughFreeGroup S F_S i G f)).1.(* The propositional computation rule for the recursor. *)Definitionisfreegroupon_rec_beta
{S : Type} {F_S : Group} {i : S -> F_S} `{IsFreeGroupOn S F_S i}
{G : Group} (f : S -> G)
: isfreegroupon_rec f o i == f
:= (center (FactorsThroughFreeGroup S F_S i G f)).2.(* Two homomorphisms from a free group are equal if they agree on the generators. *)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i G: Group f, g: F_S $-> G K: f o i == g o i
f = g
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i G: Group f, g: F_S $-> G K: f o i == g o i
f = g
(* By assumption, the type [FactorsThroughFreeGroup S F_S i G (g o i)] of factorizations of [g o i] through [i] is contractible. Therefore the two elements we have are equal. Therefore, their first components are equal. *)exact (path_contr (f; K) (g; funx => idpath))..1.Defined.
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group
IsEquiv isfreegroupon_rec
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group
IsEquiv isfreegroupon_rec
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group
(funx : F_S $-> G =>
isfreegroupon_rec (funx0 : S => x (i x0))) == idmap
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group
(fun (x : S -> G) (x0 : S) =>
isfreegroupon_rec x (i x0)) == idmap
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group
(funx : F_S $-> G =>
isfreegroupon_rec (funx0 : S => x (i x0))) == idmap
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group f: F_S $-> G
isfreegroupon_rec (funx : S => f (i x)) = f
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group f: F_S $-> G
(funx : S =>
isfreegroupon_rec (funx0 : S => f (i x0)) (i x)) ==
(funx : S => f (i x))
apply isfreegroupon_rec_beta.
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group
(fun (x : S -> G) (x0 : S) =>
isfreegroupon_rec x (i x0)) == idmap
H: Funext S: Type F_S: Group i: S -> F_S H0: IsFreeGroupOn S F_S i G: Group f: S -> G
(funx : S => isfreegroupon_rec f (i x)) = f
(* here we need [Funext]: *)apply path_arrow, isfreegroupon_rec_beta.Defined.(** The universal property of a free group. *)Definitionequiv_isfreegroupon_rec `{Funext} {G F : Group} {A : Type}
{i : A -> F} `{IsFreeGroupOn A F i}
: (A -> G) <~> (F $-> G) := Build_Equiv _ _ isfreegroupon_rec _.(** The above theorem is true regardless of the implementation of free groups. This lets us state the more specific theorem about the canonical free groups. This can be read as [FreeGroup] is left adjoint to the forgetful functor [group_type]. *)Definitionequiv_freegroup_rec `{Funext} (G : Group) (A : Type)
: (A -> G) <~> (FreeGroup A $-> G)
:= equiv_isfreegroupon_rec.
H: Funext F: Group A: Type i: A -> F
IsHProp (IsFreeGroupOn A F i)
H: Funext F: Group A: Type i: A -> F
IsHProp (IsFreeGroupOn A F i)
H: Funext F: Group A: Type i: A -> F
IsHProp
(forall (A0 : Group) (g : A -> A0),
Contr (FactorsThroughFreeGroup A F i A0 g))
apply istrunc_forall.Defined.(** Both ways of stating the universal property are equivalent. *)
H: Funext F: Group A: Type i: A -> F
IsFreeGroupOn A F i <~>
(forallG : Group, IsEquiv (funf : F $-> G => f o i))
H: Funext F: Group A: Type i: A -> F
IsFreeGroupOn A F i <~>
(forallG : Group, IsEquiv (funf : F $-> G => f o i))
H: Funext F: Group A: Type i: A -> F
IsFreeGroupOn A F i ->
forallG : Group, IsEquiv (funf : F $-> G => f o i)
H: Funext F: Group A: Type i: A -> F
(forallG : Group, IsEquiv (funf : F $-> G => f o i)) ->
IsFreeGroupOn A F i
H: Funext F: Group A: Type i: A -> F
(forallG : Group, IsEquiv (funf : F $-> G => f o i)) ->
IsFreeGroupOn A F i
H: Funext F: Group A: Type i: A -> F k: forallG : Group,
IsEquiv (funf : F $-> G => f o i) G: Group g: A -> G
Contr (FactorsThroughFreeGroup A F i G g)
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
Contr (FactorsThroughFreeGroup A F i G g)
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
Type
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
?A <~> FactorsThroughFreeGroup A F i G g
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
Contr ?A
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
hfiber
(fun (f : GroupHomomorphism F G) (x : A) => f (i x))
g <~> FactorsThroughFreeGroup A F i G g
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
Contr
(hfiber
(fun (f : GroupHomomorphism F G) (x : A) =>
f (i x)) g)
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
hfiber
(fun (f : GroupHomomorphism F G) (x : A) => f (i x))
g <~> FactorsThroughFreeGroup A F i G g
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
foralla : GroupHomomorphism F G,
(funx : A => a (i x)) = g <~>
(funx : A => a (i x)) == g
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G y: GroupHomomorphism F G
(funx : A => y (i x)) == g <~>
(funx : A => y (i x)) = g
apply equiv_path_forall.
H: Funext F: Group A: Type i: A -> F G: Group k: IsEquiv (funf : F $-> G => f o i) g: A -> G
Contr
(hfiber
(fun (f : GroupHomomorphism F G) (x : A) =>
f (i x)) g)
exact _.Defined.(** ** Subgroups of free groups *)(* We say that a group [G] is generated by a subtype [X] if the natural map from the subgroup generated by [X] to [G] is a surjection. One could equivalently say [IsEquiv (subgroup_incl (subgroup_generated X))], [forall g, subgroup_generated X g], or [subgroup_generated X = maximal_subgroup], but the definition using surjectivity is convenient later. *)Definitionisgeneratedby (G : Group) (X : G -> Type)
:= IsSurjection (subgroup_incl (subgroup_generated X)).SectionFreeGroupGenerated.(* In this Section, we prove that the free group [F_S] on a type [S] is generated in the above sense by the image of [S]. We conclude that the inclusion map is an equivalence, and that the free group is isomorphic as a group to the subgroup. We show that the inclusion is a surjection by showing that it is split epi in the category of groups. *)Context {S : Type} {F_S : Group} {i : S -> F_S} `{IsFreeGroupOn S F_S i}.(* We define a group homomorphism from [F_S] to the subgroup [G] generated by [S] by sending a generator [s] to "itself". This map will be a section of the inclusion map. *)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
F_S $-> subgroup_generated (hfiber i)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
F_S $-> subgroup_generated (hfiber i)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
S -> subgroup_generated (hfiber i)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i s: S
subgroup_generated (hfiber i)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i s: S
F_S
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i s: S
hfiber i ?g
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i s: S
F_S
exact (i s).
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i s: S
hfiber i (i s)
exact (s; idpath).Defined.(* We record the computation rule that [to_subgroup_generated] satisfies. *)Local Definitionto_subgroup_generated_beta (s : S)
: to_subgroup_generated (i s) = subgroup_generated_gen_incl (i s) (s; idpath)
:= isfreegroupon_rec_beta _ _.(* It follows that [to_subgroup_generated] is a section of the inclusion map from [G] to [F_S]. *)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
(funx : S => (to_subgroup_generated (i x)).1) ==
(funx : S => i x)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i s: S
(to_subgroup_generated (i s)).1 = i s
exact (ap pr1 (to_subgroup_generated_beta s)).Defined.(* It follows that the inclusion map is a surjection, i.e., that [F_S] is generated by the image of [S]. *)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
isgeneratedby F_S (hfiber i)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
isgeneratedby F_S (hfiber i)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i
F_S -> subgroup_generated (hfiber i)
S: Type F_S: Group i: S -> F_S H: IsFreeGroupOn S F_S i