Created
April 27, 2021 23:11
-
-
Save dwarn/ef6244115fec07c33a10a45b8a821a14 to your computer and use it in GitHub Desktop.
coproduct of groups as reduced words
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import data.list.chain | |
section monoids | |
-- given a family of monoids, where both the monoids and the indexing set have decidable equality. | |
variables {ι : Type*} (G : Π i : ι, Type*) [Π i, monoid (G i)] | |
[decidable_eq ι] [∀ i, decidable_eq (G i)] | |
-- The coproduct of our monoids. | |
@[derive decidable_eq] | |
def coprod : Type* := { l : list (Σ i, { g : G i // g ≠ 1 }) // (l.map sigma.fst).chain' (≠) } | |
variable {G} | |
-- `w.head_isn't i` says that `i` is not the head of `w`. | |
def coprod.head_isn't (w : coprod G) (i : ι) : Prop := ∀ p ∈ (w.val.map sigma.fst).head', i ≠ p | |
section cases | |
-- here we define a custom eliminator for `coprod`. The idea is we have an index `i`, and | |
-- want to say that every `w : coprod G` either (1) doesn't have `i` as its head, or (2) is `g * w'` | |
-- for some `g : G i`, where `w'` doesn't have `i` as its head. | |
variables {i : ι} {C : coprod G → Sort*} | |
(d1 : Π w : coprod G, w.head_isn't i → C w) | |
(d2 : Π (w : coprod G) (h : w.head_isn't i) (g), C ⟨⟨i, g⟩ :: w.val, w.property.cons' h⟩) | |
include d1 d2 | |
def coprod_cases : Π w : coprod G, C w | |
| w@⟨[], _⟩ := d1 w $ by rintro _ ⟨⟩ | |
| w@⟨⟨j, g⟩ :: ls, h⟩ := if ij : i = j then by { cases ij, exact d2 ⟨ls, h.tail⟩ h.rel_head' g } | |
else d1 w $ by { rintro _ ⟨⟩ ⟨⟩, exact ij rfl } | |
variables {d1 d2} | |
-- computation rule for the first case of our eliminator | |
lemma beta1 : ∀ (w : coprod G) h, (coprod_cases d1 d2 w : C w) = d1 w h | |
| ⟨[], _⟩ h := rfl | |
| ⟨⟨j, g⟩ :: ls, hl⟩ h := by { rw [coprod_cases, dif_neg], exact h j rfl } | |
-- computation rule for the second case of our eliminator | |
lemma beta2 (w : coprod G) (h : w.head_isn't i) (g) {x} : | |
(coprod_cases d1 d2 ⟨⟨i, g⟩ :: w.val, x⟩ : C ⟨⟨i, g⟩ :: w.val, x⟩) = d2 w h g := | |
by { rw [coprod_cases, dif_pos rfl], cases w, refl } | |
end cases | |
-- prepend `g : G i` to `w`, assuming `i` is not the head of `w`. | |
def rcons' {i : ι} (g : G i) (w : coprod G) (h : w.head_isn't i) : coprod G := | |
if g_one : g = 1 then w else ⟨⟨i, g, g_one⟩ :: w.val, w.property.cons' h⟩ | |
-- prepend `g : G i` to `w`. NB this is defined in terms of `rcons'`: this will be a recurring theme. | |
def rcons {i : ι} (g : G i) : coprod G → coprod G := | |
coprod_cases (rcons' g) (λ w h g', rcons' (g * ↑g') w h) | |
-- computation rules for `rcons` | |
lemma rcons_def1 {i : ι} {g : G i} {w : coprod G} (h) : rcons g w = rcons' g w h := beta1 _ _ | |
lemma rcons_def2 {i : ι} {g : G i} {w : coprod G} (h) (g') {x} : | |
rcons g ⟨⟨i, g'⟩ :: w.val, x⟩ = rcons' (g * ↑g') w h := beta2 _ _ _ | |
-- prepending one doesn't change our word | |
lemma rcons_one {i : ι} : ∀ w : coprod G, rcons (1 : G i) w = w := | |
begin | |
apply coprod_cases, | |
{ intros w h, rw [rcons_def1 h, rcons', dif_pos rfl], }, | |
{ rintros w h ⟨g, hg⟩, rw [rcons_def2 h, one_mul, rcons', dif_neg], refl, } | |
end | |
-- preliminary for `rcons_mul` | |
private lemma rcons_mul' {i : ι} {g g' : G i} {w : coprod G} (h : w.head_isn't i) : | |
rcons (g * g') w = rcons g (rcons g' w) := | |
begin | |
rw [rcons_def1 h, rcons_def1 h, rcons', rcons'], | |
split_ifs, | |
{ rw [h_2, mul_one] at h_1, rw [h_1, rcons_one], }, | |
{ rw [rcons_def2 h, rcons', dif_pos], exact h_1, }, | |
{ rw [rcons_def1 h, rcons', dif_neg], { congr, rw [h_2, mul_one], }, simpa [h_2] using h_1, }, | |
{ rw [rcons_def2 h, rcons', dif_neg], refl, }, | |
end | |
-- we can prepend `g * g'` one element at a time. | |
lemma rcons_mul {i : ι} (g : G i) (g' : G i) : ∀ w, rcons (g * g') w = rcons g (rcons g' w) := | |
begin | |
apply coprod_cases, | |
{ apply rcons_mul', }, | |
{ intros w h g'', rw [rcons_def2 h, rcons_def2 h, mul_assoc, | |
←rcons_def1, rcons_mul' h, ←rcons_def1] } | |
end | |
-- Every `G i` thus acts on the coproduct. | |
@[simps] instance bar (i) : mul_action (G i) (coprod G) := | |
{ smul := rcons, one_smul := rcons_one, mul_smul := rcons_mul } | |
-- Prepending a letter to a word means acting on that word. This will be useful for proofs by | |
-- induction on words. | |
lemma cons_as_smul {i} {g} (ls) (hl) : | |
(⟨⟨i, g⟩ :: ls, hl⟩ : coprod G) = (g.val • ⟨ls, hl.tail⟩ : coprod G) := | |
begin | |
rw [bar_to_has_scalar_smul, rcons_def1, rcons', dif_neg g.property], | |
{ congr, ext, refl, }, { exact hl.rel_head', }, | |
end | |
section action | |
-- Given actions of `G i` on `X`, the coproduct also has a scalar action on `X`. We'll use this | |
-- both to define multiplication in the coproduct, and to get its universal property. | |
variables {X : Type*} [∀ i, mul_action (G i) X] | |
instance foo : has_scalar (coprod G) X := ⟨λ g x, g.val.foldr (λ l y, l.snd.val • y) x⟩ | |
-- preliminary for `foobar`. | |
private lemma foobar' {i} {g : G i} {x : X} {w : coprod G} (h : w.head_isn't i) : | |
(rcons g w) • x = g • (w • x) := | |
by { rw [rcons_def1 h, rcons'], split_ifs, { rw [h_1, one_smul], }, { refl, }, } | |
-- (I'm not sure it's worth it to use these typeclasses, since Lean gets a bit confused by them...) | |
instance foobar (i) : is_scalar_tower (G i) (coprod G) X := | |
⟨begin | |
intros g' w x, revert w, | |
apply coprod_cases, | |
{ apply foobar', }, | |
{ intros w h g, rw [bar_to_has_scalar_smul, rcons_def2 h, ←rcons_def1 h, | |
foobar' h, mul_smul], refl, } | |
end⟩ | |
end action | |
instance coprod_monoid : monoid (coprod G) := | |
{ mul := λ x y, x • y, | |
mul_assoc := begin | |
rintros ⟨ls, hl⟩ b c, | |
change (_ • _) • _ = _ • (_ • _), | |
induction ls with p ls ih, | |
{ refl, }, | |
cases p with i g, | |
rw [cons_as_smul, smul_assoc g.val _ b, smul_assoc, ih, smul_assoc], | |
apply_instance, -- ?? | |
end, | |
one := ⟨[], list.chain'_nil⟩, | |
one_mul := λ _, rfl, | |
mul_one := begin | |
rintro ⟨ls, hl⟩, | |
change _ • _ = _, | |
induction ls with p ls ih, | |
{ refl }, | |
cases p with i g, | |
rw [cons_as_smul, smul_assoc, ih], | |
end } | |
def of {i} : G i →* coprod G := | |
{ to_fun := λ g, g • 1, | |
map_one' := rcons_one _, | |
map_mul' := by { intros, change rcons _ _ = _ • _, rw [rcons_mul, smul_assoc], refl } } | |
lemma cons_as_mul {i} {g} (ls) (h) : | |
(⟨⟨i, g⟩ :: ls, h⟩ : coprod G) = (of g.val * ⟨ls, h.tail⟩ : coprod G) := | |
by { convert cons_as_smul ls h, change (_ • _) • _ = _, rw smul_assoc g.val, congr, apply_instance } | |
def ump (X : Type*) [monoid X] : | |
(Π {i}, G i →* X) ≃ (coprod G →* X) := | |
{ to_fun := λ fi, begin | |
letI : ∀ i, mul_action (G i) X := λ i, mul_action.comp_hom _ fi, | |
refine { to_fun := λ g, g • 1, map_one' := rfl, map_mul' := _ }, | |
rintros ⟨ls, hl⟩ b, | |
change (_ • _) • _ = _, | |
induction ls with p ls ih, | |
{ exact (one_mul _).symm }, | |
cases p with i g, | |
rw [cons_as_smul, smul_assoc g.val _ b, smul_assoc, ih, smul_assoc], | |
{ symmetry, apply mul_assoc, }, | |
{ apply_instance }, | |
end, | |
inv_fun := λ f i, f.comp of, | |
left_inv := begin | |
intro fi, letI : ∀ i, mul_action (G i) X := λ i, mul_action.comp_hom _ fi, | |
ext i g, change (g • (1 : coprod G)) • (1 : X) = fi g, | |
rw smul_assoc, apply mul_one, | |
end, | |
right_inv := begin | |
intro f, | |
ext w, | |
cases w with ls hl, | |
change _ • 1 = f ⟨ls, hl⟩, | |
induction ls with p ls ih, | |
{ exact f.map_one.symm }, | |
cases p with i g, | |
conv_rhs { rw [cons_as_mul, f.map_mul] }, | |
letI : ∀ i, mul_action (G i) X := λ i, mul_action.comp_hom _ (f.comp of), | |
rw [cons_as_smul, smul_assoc, ih], refl | |
end } | |
lemma prod_eq_self (w : coprod G) : list.prod (w.val.map (λ l, of l.snd.val)) = w := | |
begin | |
cases w with ls hl, induction ls with p ls ih, | |
{ refl, }, { cases p, rw [list.map_cons, list.prod_cons, ih hl.tail, cons_as_mul], }, | |
end | |
end monoids | |
-- we now do the case of groups. | |
variables {ι : Type*} {G : Π i : ι, Type*} [Π i, group (G i)] | |
[decidable_eq ι] [∀ i, decidable_eq (G i)] | |
@[simps] | |
instance coprod_inv : has_inv (coprod G) := | |
⟨λ w, ⟨list.reverse (w.val.map $ λ l, ⟨l.fst, l.snd.val⁻¹, inv_ne_one.mpr l.snd.property⟩), | |
begin | |
rw [list.map_reverse, list.chain'_reverse, list.map_map, function.comp], | |
convert w.property, ext, exact ne_comm, | |
end⟩⟩ | |
instance : group (coprod G) := | |
{ mul_left_inv := begin | |
intro w, -- possibly this should all be deduced from some more general result | |
conv_lhs { congr, rw ←prod_eq_self w⁻¹, skip, rw ←prod_eq_self w }, | |
cases w with ls junk, | |
rw [subtype.val_eq_coe, coprod_inv_inv_coe, list.map_reverse, list.map_map], | |
dsimp only, clear junk, | |
induction ls with p ls ih, | |
{ apply mul_one, }, | |
rw [list.map_cons, list.reverse_cons, list.prod_append, list.map_cons, list.prod_cons, | |
list.prod_nil, mul_one, function.comp_apply, mul_assoc, list.prod_cons, | |
←mul_assoc _ (of p.snd.val), ←of.map_mul, mul_left_inv, of.map_one, one_mul, ih], | |
end, | |
..coprod_inv, | |
..coprod_monoid } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment