1-- Conjugation and normal subgroups: conjugation by a fixed element is an2-- automorphism, kernels are normal, every subgroup of an abelian group is3-- normal, and a subgroup is normal exactly when its left and right cosets4-- agree5-- Part of Cumulus, the Grace17 mathematics library.6-- Copyright (c) 2026 Grant Passmore.7-- Released under the Apache License 2.0. See LICENSE in the repository root.8-- Authors: Grant Passmore910module Grace.Cumulus.Algebra.Group.Normal11import Kernel12import Coset1314-- The conjugate g * x * g⁻¹ of x by g.15def conjugate (G g x : Set) : Set:= G.mul(G.mul(g, x), G.inv(g))1617theorem conjugate.value (G g x : Set)18shows conjugate(G, g, x) = G.mul(G.mul(g, x), G.inv(g))19proof20simp [conjugate]2122section Conjugation23variable (G : Set)24hypothesis group : Group(G)2526instance conjugate.mem (g x : G)27shows conjugate(G, g, x) ∈ G28proof29rw conjugate.value30typecheck3132theorem conjugate.one (g : G)33shows conjugate(G, g, G.one) = G.one34proof35simp [conjugate.value, mul_one, Group.mul_inv]3637theorem conjugate.by_one (x : G)38shows conjugate(G, G.one, x) = x39proof40simp [conjugate.value, one_mul, inv_one, mul_one]4142theorem conjugate.mul (g x y : G)43shows conjugate(G, g, x * y) = conjugate(G, g, x) * conjugate(G, g, y)44proof45rw [conjugate.value, conjugate.value, conjugate.value]46 group_simp4748theorem conjugate.inv (g x : G)49shows conjugate(G, g, x⁻¹) = conjugate(G, g, x)⁻¹50proof51simp [conjugate.value, mul_inv_rev, inv_inv, mul_assoc]5253theorem conjugate.conjugate (g h x : G)54shows conjugate(G, g, conjugate(G, h, x)) = conjugate(G, g * h, x)55proof56simp [conjugate.value, mul_inv_rev, mul_assoc]5758theorem conjugate.cancel (g x : G)59shows conjugate(G, g⁻¹, conjugate(G, g, x)) = x60proof61rw [conjugate.value, conjugate.value]62 group_simp6364theorem conjugate.injective (g x y : G)65requires equal : conjugate(G, g, x) = conjugate(G, g, y)66shows x = y67proof68have cancelX : conjugate(G, g⁻¹, conjugate(G, g, x)) = x := conjugate.cancel with*69have cancelY : conjugate(G, g⁻¹, conjugate(G, g, y)) = y := conjugate.cancel with*70cc7172theorem conjugate.of_commute (g x : G)73requires commute : g * x = x * g74shows conjugate(G, g, x) = x75proof76rw [conjugate.value, commute, mul_inv_cancel_right]77rfl7879theorem conjugate.commute_of_fixed (g x : G)80requires fixed : conjugate(G, g, x) = x81shows g * x = x * g82proof83rw conjugate.value at fixed84have criterion : g * x * g⁻¹ = x ↔ g * x = x * g := mul_inv_eq_iff_eq_mul with*85exact criterion.forward with fixed8687end Conjugation8889-- Conjugation by g as a function on the carrier.90defgraph conjugation (G g : Set) (x ∈ G.carrier) : G.carrier := conjugate(G, g, x)91requires group : Group(G)92requires hg : g ∈ G.carrier93proof94exact conjugate.mem with group, hg, member9596section ConjugationMap97variable (G : Set)98hypothesis group : Group(G)99100theorem conjugation.hom (g : G)101shows conjugation(G, g) : G →* G102proof103have function := conjugation.function at G, g with*104apply GroupHom.mk with group, group, function105intros x hx y hy106have closed : x * y ∈ G bytypecheck107have vx := conjugation.value at G, g, x with*108have vy := conjugation.value at G, g, y with*109have output := conjugation.value at G, g, x * y with*110have merged : conjugate(G, g, x * y) = conjugate(G, g, x) * conjugate(G, g, y) := conjugate.mul with*111cc112113theorem conjugation.injective (g : G)114shows InjectiveBetween(conjugation(G, g), G.carrier, G.carrier)115proof116have function := conjugation.function at G, g with*117constructor118 . exact function119 . intros x hx y hy z hz hxz hyz120have vx := FunctionBetween.apply_value with function, hx, hxz121have vy := FunctionBetween.apply_value with function, hy, hyz122have cx := conjugation.value at G, g, x with*123have cy := conjugation.value at G, g, y with*124have equal : conjugate(G, g, x) = conjugate(G, g, y) bycc125exact conjugate.injective with*126127theorem conjugation.surjective (g : G)128shows SurjectiveBetween(conjugation(G, g), G.carrier, G.carrier)129proof130have function := conjugation.function at G, g with*131constructor132 . exact function133 . intros y hy134have preimage : conjugate(G, g⁻¹, y) ∈ G bytypecheck135have cancel : conjugate(G, (g⁻¹)⁻¹, conjugate(G, g⁻¹, y)) = y := conjugate.cancel with*136rw inv_inv at cancel137have value := conjugation.value at G, g, conjugate(G, g⁻¹, y) with*138have edge := FunctionBetween.relates_apply with function, preimage139refine⟨conjugate(G, g⁻¹, y), preimage, ?_⟩140rw [value, cancel] at edge141exact edge142143theorem conjugation.bijective (g : G)144shows BijectiveBetween(conjugation(G, g), G.carrier, G.carrier)145proof146constructor147 . exact conjugation.injective with*148 . exact conjugation.surjective with*149150end ConjugationMap151152-- NormalSubgroup(N, G): a subgroup closed under conjugation by every153-- element of G.154predicate NormalSubgroup (N G : Set) :=155 Subgroup(N, G) ∧ (∀ g ∈ G.carrier, ∀ n ∈ N, conjugate(G, g, n) ∈ N)156157notationinfixl70"*"=> call2(G.mul, _, _) viahypothesis NormalSubgroup(N, G) for N158notationpostfix90"⁻¹"=>apply(G.inv, _) viahypothesis NormalSubgroup(N, G) for N159notationinfixr80"^"=> groupPow(G, _, _) viahypothesis NormalSubgroup(N, G) for N160161theorem NormalSubgroup.subgroup (N G : Set)162requires normal : NormalSubgroup(N, G)163shows Subgroup(N, G)164proof165exact normal.left166167theorem NormalSubgroup.conjugate_mem (N G g n : Set)168requires normal : NormalSubgroup(N, G)169requires hg : g ∈ G.carrier170requires hn : n ∈ N171shows conjugate(G, g, n) ∈ N172proof173exact normal.right with g, hg, n, hn174175theorem NormalSubgroup.mk (N G : Set)176requires subgroup : Subgroup(N, G)177requires closed : ∀ g ∈ G.carrier, ∀ n ∈ N, conjugate(G, g, n) ∈ N178shows NormalSubgroup(N, G)179proof180unfold NormalSubgroup181exact⟨subgroup, closed⟩182183section NormalLaws184variable (G N : Set)185hypothesis group : Group(G)186hypothesis normal : NormalSubgroup(N, G)187188theorem NormalSubgroup.mul_mem (g : G) (n : N)189shows g * n * g⁻¹ ∈ N190proof191have member : conjugate(G, g, n) ∈ N := NormalSubgroup.conjugate_mem with*192 rwa conjugate.value at member193194theorem NormalSubgroup.inv_mul_mem (g : G) (n : N)195shows g⁻¹ * n * g ∈ N196proof197have member : conjugate(G, g⁻¹, n) ∈ N := NormalSubgroup.conjugate_mem with*198rw [conjugate.value, inv_inv] at member199exact member200201-- Normality through cosets: left and right cosets coincide.202theorem NormalSubgroup.left_eq_right (g : G)203shows leftCoset(G, g, N) = rightCoset(G, g, N)204proof205have subgroup := NormalSubgroup.subgroup with normal206ext y207constructor208 . intro hy209obtain⟨yIn, n, hn, yEq⟩:= leftCoset.membership.forward with hy210have conj : g * n * g⁻¹ ∈ N := NormalSubgroup.mul_mem with*211apply rightCoset.membership.backward212refine⟨yIn, g * n * g⁻¹, conj, ?_⟩213rw [yEq, inv_mul_cancel_right]214rfl215 . intro hy216obtain⟨yIn, n, hn, yEq⟩:= rightCoset.membership.forward with hy217have conj : g⁻¹ * n * g ∈ N := NormalSubgroup.inv_mul_mem with*218apply leftCoset.membership.backward219refine⟨yIn, g⁻¹ * n * g, conj, ?_⟩220rw [yEq, ← mul_assoc, mul_inv_cancel_left]221rfl222223-- In a normal subgroup the order of a product does not matter for224-- membership.225theorem NormalSubgroup.mul_mem_comm (x y : G)226requires member : x * y ∈ N227shows y * x ∈ N228proof229have conj : y * (x * y) * y⁻¹ ∈ N := NormalSubgroup.mul_mem with*230rw [← mul_assoc, mul_inv_cancel_right] at conj231exact conj232233end NormalLaws234235section NormalConstructions236variable (G : Set)237hypothesis group : Group(G)238239theorem NormalSubgroup.whole240shows NormalSubgroup(G.carrier, G)241proof242have subgroup := Subgroup.whole with group243apply NormalSubgroup.mk with subgroup244intros g hg n hn245typecheck246247theorem NormalSubgroup.trivial248shows NormalSubgroup({G.one}, G)249proof250have subgroup := Subgroup.trivial with group251apply NormalSubgroup.mk with subgroup252intros g hg n hn253have equal := singleton.membership.forward with hn254have fixed : conjugate(G, g, G.one) = G.one := conjugate.one with*255rw [equal, fixed]256exact singleton.self257258theorem NormalSubgroup.intersection (N M : Set)259requires normalN : NormalSubgroup(N, G)260requires normalM : NormalSubgroup(M, G)261shows NormalSubgroup(N ∩ M, G)262proof263have subgroup := Subgroup.intersection with group, (NormalSubgroup.subgroup with normalN), (NormalSubgroup.subgroup with normalM)264apply NormalSubgroup.mk with subgroup265intros g hg n hn266obtain⟨nN, nM⟩:= intersection.membership.forward with hn267have inN : conjugate(G, g, n) ∈ N := NormalSubgroup.conjugate_mem with*268have inM : conjugate(G, g, n) ∈ M := NormalSubgroup.conjugate_mem with*269exact intersection.membership.backward with⟨inN, inM⟩270271theorem NormalSubgroup.of_left_eq_right (N : Set)272requires subgroup : Subgroup(N, G)273requires cosets : ∀ g ∈ G, leftCoset(G, g, N) = rightCoset(G, g, N)274shows NormalSubgroup(N, G)275proof276apply NormalSubgroup.mk with subgroup277intros g hg n hn278have gn : g * n ∈ leftCoset(G, g, N) := leftCoset.mul_mem with*279have equal := cosets with g, hg280rw equal at gn281obtain⟨gnIn, m, hm, gnEq⟩:= rightCoset.membership.forward with gn282rw [conjugate.value, gnEq, mul_inv_cancel_right]283exact hm284285theorem NormalSubgroup.iff_left_eq_right (N : Set)286requires subgroup : Subgroup(N, G)287shows NormalSubgroup(N, G) ↔∀ g ∈ G, leftCoset(G, g, N) = rightCoset(G, g, N)288proof289constructor290 . intros normal g hg291exact NormalSubgroup.left_eq_right with*292 . intro cosets293exact NormalSubgroup.of_left_eq_right with*294295end NormalConstructions296297theorem NormalSubgroup.of_abelian (G N : Set)298requires abelian : AbelianGroup(G)299requires subgroup : Subgroup(N, G)300shows NormalSubgroup(N, G)301proof302have group := AbelianGroup.to_group with abelian303apply NormalSubgroup.mk with subgroup304intros g hg n hn305have nIn : n ∈ G.carrier := Subgroup.mem_carrier with*306have commute : g * n = n * g := mul_comm with*307have fixed : conjugate(G, g, n) = n := conjugate.of_commute with*308 rwa fixed309310section NormalHoms311variable (f G H : Set)312hypothesis hom : f : G →* H313314theorem GroupHom.kernel_normal315shows NormalSubgroup(ker(f), G)316proof317have group := GroupHom.source with hom318have target := GroupHom.target with hom319have subgroup := GroupHom.kernel_subgroup with hom320apply NormalSubgroup.mk with subgroup321intros g hg n hn322obtain⟨nIn, vn⟩:= kernel.membership.forward with hn323have vanishes : f(conjugate(G, g, n)) = H.one324rw [conjugate.value, GroupHom.map_mul, GroupHom.map_mul, GroupHom.map_inv, vn, mul_one, Group.mul_inv]325rfl326exact kernel.of_value with (conjugate.mem with*), vanishes327328theorem NormalSubgroup.preimage (K : Set)329requires normal : NormalSubgroup(K, H)330shows NormalSubgroup(functionPreimage(f, G.carrier, K), G)331proof332have group := GroupHom.source with hom333have target := GroupHom.target with hom334have subgroup := GroupHom.preimage_subgroup with hom, (NormalSubgroup.subgroup with normal)335apply NormalSubgroup.mk with subgroup336intros g hg n hn337have parts := functionPreimage.membership.forward with hn338have nIn := parts.left339have conj : conjugate(H, f(g), f(n)) ∈ K := NormalSubgroup.conjugate_mem with normal, (GroupHom.map_mem with*), parts.right340have value : f(conjugate(G, g, n)) ∈ K341rw [conjugate.value, GroupHom.map_mul, GroupHom.map_mul, GroupHom.map_inv]342 rwa conjugate.value at conj343exact functionPreimage.of_apply with (conjugate.mem with*), value344345theorem NormalSubgroup.image_of_surjective (N : Set)346requires surjective : SurjectiveBetween(f, G.carrier, H.carrier)347requires normal : NormalSubgroup(N, G)348shows NormalSubgroup(functionImage(f, N, H.carrier), H)349proof350have group := GroupHom.source with hom351have target := GroupHom.target with hom352have function := GroupHom.function with hom353have subgroupN := NormalSubgroup.subgroup with normal354have subgroup := GroupHom.image_subgroup with hom, subgroupN355apply NormalSubgroup.mk with subgroup356intros h hh y hy357obtain⟨yIn, n, hn, yEq⟩:= functionImage.membership.forward with hy358obtain⟨g, hg, edge⟩:= surjective.right with h, hh359have hEq := FunctionBetween.apply_value with function, hg, edge360have nIn : n ∈ G := Subgroup.mem_carrier with*361have conj : conjugate(G, g, n) ∈ N := NormalSubgroup.conjugate_mem with*362have closed : conjugate(H, h, y) ∈ H bytypecheck363apply functionImage.membership.backward364refine⟨closed, conjugate(G, g, n), conj, ?_⟩365rw [conjugate.value, conjugate.value, GroupHom.map_mul, GroupHom.map_mul, GroupHom.map_inv, hEq, yEq]366rfl367368end NormalHoms369