diff --git a/doc/manualbib.xml b/doc/manualbib.xml index 810e115dc8d..15fb7fe24f1 100644 --- a/doc/manualbib.xml +++ b/doc/manualbib.xml @@ -2233,6 +2233,34 @@ 225 +
+ + PhilipHall + + A contribution to the theory of groups of prime-power order + Proceedings of the London Mathematical Society + 1934 + s2-36 + 1 + 29–95 + https://doi.org/10.1112/plms/s2-36.1.29 + 10.1112/plms/s2-36.1.29 +
+ +
+ + PhilipHall + + On a Theorem of Frobenius + Proceedings of the London Mathematical Society + 1936 + s2-40 + 1 + 468–501 + https://doi.org/10.1112/plms/s2-40.1.468 + 10.1112/plms/s2-40.1.468 +
+
PhilipHall diff --git a/doc/ref/groups.xml b/doc/ref/groups.xml index f6a84d264e9..6638a8b9ad3 100644 --- a/doc/ref/groups.xml +++ b/doc/ref/groups.xml @@ -351,6 +351,7 @@ as they depend on a parameter. <#Include Label="IsSubsetLocallyFiniteGroup"> <#Include Label="IsPGroup"> <#Include Label="IsPowerfulPGroup"> +<#Include Label="IsRegularPGroup"> <#Include Label="PrimePGroup"> <#Include Label="PClassPGroup"> <#Include Label="RankPGroup"> diff --git a/lib/grp.gd b/lib/grp.gd index 175fe203c5e..37de1ac8aec 100644 --- a/lib/grp.gd +++ b/lib/grp.gd @@ -439,11 +439,8 @@ DeclareOperation( "KnowsHowToDecompose", [ IsGroup, IsList ] ); DeclareProperty( "IsPGroup", IsGroup ); InstallTrueMethod( IsGroup, IsPGroup ); -InstallSubsetMaintenance( IsPGroup, - IsGroup and IsPGroup, IsGroup ); - -InstallFactorMaintenance( IsPGroup, - IsGroup and IsPGroup, IsObject, IsGroup ); +InstallSubsetMaintenance( IsPGroup, IsPGroup, IsGroup ); +InstallFactorMaintenance( IsPGroup, IsPGroup, IsObject, IsGroup ); InstallTrueMethod( IsPGroup, IsGroup and IsTrivial ); InstallTrueMethod( IsPGroup, IsGroup and IsElementaryAbelian ); @@ -458,7 +455,7 @@ InstallTrueMethod( IsPGroup, IsGroup and IsElementaryAbelian ); ## ## ## Powerful p-group -## A finite p-group G is said to be a powerful p-group +## A finite p-group G is said to be a powerful p-group ## if the commutator subgroup [G,G] is contained in ## G^{p} if the prime p is odd, or if ## [G,G] is contained in G^{4} @@ -475,12 +472,42 @@ InstallTrueMethod( IsPGroup, IsGroup and IsElementaryAbelian ); DeclareProperty( "IsPowerfulPGroup", IsGroup ); InstallTrueMethod( IsPGroup, IsPowerfulPGroup ); -#Quotients of powerful of powerful p groups are powerful +#Quotients of powerful p-groups are powerful InstallFactorMaintenance( IsPowerfulPGroup, IsPowerfulPGroup, IsGroup, IsGroup ); #abelian p-groups are powerful InstallTrueMethod( IsPowerfulPGroup, IsFinite and IsPGroup and IsAbelian ); -InstallTrueMethod( IsPGroup, IsPowerfulPGroup ); + +############################################################################# +## +#P IsRegularPGroup( ) . . . . . . . . . . is a group a regular p-group ? +## +## <#GAPDoc Label="IsRegularPGroup"> +## +## +## +## +## Regular p-group +## A finite p-group G is said to be a regular p-group +## if for all a,b in G, one has a^p b^p = (ab^p) c^p +## where c is an element of the derived subgroup of the group generated +## by a and b (see ). +## returns true if G is a +## regular p-group, and false otherwise. +## Note: This function returns true if G is the trivial +## group. +## +## +## <#/GAPDoc> +## +DeclareProperty( "IsRegularPGroup", IsGroup ); +InstallTrueMethod( IsPGroup, IsRegularPGroup ); + +InstallSubsetMaintenance( IsRegularPGroup, IsRegularPGroup, IsGroup ); +InstallFactorMaintenance( IsPGroup, IsRegularPGroup, IsObject, IsGroup ); + +#abelian p-groups are regular +InstallTrueMethod( IsRegularPGroup, IsFinite and IsPGroup and IsAbelian ); ############################################################################# ## diff --git a/lib/grp.gi b/lib/grp.gi index 822fc4ab108..e308e311b62 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -428,6 +428,93 @@ InstallMethod( IsPowerfulPGroup, end); +############################################################################# +## +#M IsRegularPGroup( ) . . . . . . . . . . is a group a regular p-group ? +## +InstallMethod( IsRegularPGroup, + [ IsGroup ], +function( G ) +local p, hom, reps, a, b, ap_bp, ab_p, H; + + if not IsPGroup(G) then + return false; + fi; + + p:=PrimePGroup(G); + if p = 2 then + # see [Hup67, Satz 10.3 a)] + return IsAbelian(G); + elif p = 3 and DerivedLength(G) > 2 then + # see [Hup67, Satz 10.3 b)] + return false; + elif Size(G) <= p^p then + # see [Hal34, Corollary 14.14], [Hall, p. 183], [Hup67, Satz 10.2 b)] + return true; + elif NilpotencyClassOfGroup(G) < p then + # see [Hal34, Corollary 14.13], [Hall, p. 183], [Hup67, Satz 10.2 a)] + return true; + elif IsCyclic(DerivedSubgroup(G)) then + # see [Hup67, Satz 10.2 c)] + return true; + elif Exponent(G) = p then + # see [Hup67, Satz 10.2 d)] + return true; + elif p = 3 and RankPGroup(G) = 2 then + # see [Hup67, Satz 10.3 b)]: at this point we know that the derived + # subgroup is not cyclic, hence G is not regular + return false; + elif Size(G) < p^p * Size(Agemo(G,p)) then + # see [Hal36, Theorem 2.3], [Hup67, Satz 10.13] + return true; + elif Index(DerivedSubgroup(G),Agemo(DerivedSubgroup(G),p)) < p^(p-1) then + # see [Hal36, Theorem 2.3], [Hup67, Satz 10.13] + return true; + fi; + + # Fallback to actually check the defining criterion, i.e.: + # for all a,b in G, we must have that a^p*b^p/(a*b)^p in (')^p + + # It suffices to pick 'a' among conjugacy class representatives. + # Moreover, if 'a' is central then the criterion automatically holds. + # For z,z'\in Z(G), if the criterion holds for (a,b) iff it holds for (az,bz'). + # We thus choose 'a' among lifts of conjugacy class representatives in G/Z(G). + hom := NaturalHomomorphismByNormalSubgroup(G, Center(G)); + reps := ConjugacyClasses(Image(hom)); + reps := List(reps, Representative); + reps := Filtered(reps, g -> not IsOne(g)); + reps := List(reps, g -> PreImagesRepresentative(hom, g)); + + for b in Image(hom) do + b := PreImagesRepresentative(hom, b); + for a in reps do + # if a and b commute the regularity condition automatically holds + if a*b = b*a then continue; fi; + + # regularity is also automatic if a^p * b^p = (a*b)^p + ap_bp := a^p * b^p; + ab_p := (a*b)^p; + if ap_bp = ab_p then continue; fi; + + # if the subgroup generated H by a and b is itself regular, we are also + # done. However we don't use recursion, here, as H may be equal to G; + # and also we have to be careful to not be use too expensive code here. + # But a quick size check is certainly fine. + H := Subgroup(G, [a,b]); + if Size(H) <= p^p then continue; fi; + + # finally the full check + H := DerivedSubgroup(H); + if not (ap_bp / ab_p) in Agemo(H, p) then + return false; + fi; + od; + od; + return true; + +end); + + ############################################################################# ## #M PrimePGroup . . . . . . . . . . . . . . . . . . . . . prime of a p-group diff --git a/tst/testinstall/pgroups.tst b/tst/testinstall/pgroups.tst index ce83000bfb6..78d7edbe252 100644 --- a/tst/testinstall/pgroups.tst +++ b/tst/testinstall/pgroups.tst @@ -168,19 +168,35 @@ true gap> JenningsSeries(CyclicGroup(4)); [ , Group([ f2 ]), Group([ of ... ]) ] + +# gap> G:=CyclicGroup(9);; gap> HasIsPowerfulPGroup(G); true gap> IsPowerfulPGroup(G); true +gap> HasIsRegularPGroup(G); +true +gap> IsRegularPGroup(G); +true + +# gap> G:=CyclicGroup(10);; gap> IsPowerfulPGroup(G); false +gap> IsRegularPGroup(G); +false + +# gap> G:=SmallGroup(243,11);; gap> HasIsPowerfulPGroup(G); false gap> IsPowerfulPGroup(G); true +gap> HasIsRegularPGroup(G); +false +gap> IsRegularPGroup(G); +true gap> N:=NormalSubgroups(G)[3];; gap> H:=FactorGroup(G,N);; gap> HasIsPowerfulPGroup(H); @@ -188,17 +204,23 @@ true gap> IsPowerfulPGroup(H); true gap> myList:=AllSmallGroups(5^4);; -gap> Number(myList,g->IsPowerfulPGroup(g)); +gap> Number(myList,IsPowerfulPGroup); 9 +gap> Number(myList,IsRegularPGroup); +15 gap> newList:=AllSmallGroups(5^4);; gap> for g in newList do > RankPGroup(g); > Agemo(g,5); > od; -gap> Number(newList,g->IsPowerfulPGroup(g)); +gap> Number(newList,IsPowerfulPGroup); 9 gap> myList:=AllSmallGroups(2^4);; -gap> Number(myList,g->IsPowerfulPGroup(g)); +gap> Number(myList,IsPowerfulPGroup); +6 +gap> Number(myList,IsPowerfulPGroup); 6 gap> g:=AbelianGroup(ListWithIdenticalEntries(2000,2));; + +# gap> STOP_TEST("pgroups.tst", 1);