diff --git a/lib/grp.gi b/lib/grp.gi index 990227654a..6e47e7ad1c 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -417,6 +417,10 @@ InstallImmediateMethod( IsPerfectGroup, 0, grp -> not IsAbelian( grp ) ); +InstallMethod( IsPerfectGroup, "for groups having abelian invariants", + [ IsGroup and HasAbelianInvariants ], + grp -> Length( AbelianInvariants( grp ) ) = 0 ); + InstallMethod( IsPerfectGroup, "method for finite groups", [ IsGroup and IsFinite ], @@ -533,13 +537,22 @@ InstallMethod( IsSolvableGroup, "generic method for groups", [ IsGroup ], function ( G ) - local S; # derived series of + local S, # derived series of + isAbelian, # true if is abelian + isSolvable; # true if is solvable # compute the derived series of S := DerivedSeriesOfGroup( G ); # the group is solvable if the derived series reaches the trivial group - return IsTrivial( S[ Length( S ) ] ); + isSolvable := IsTrivial( S[ Length( S ) ] ); + + # set IsAbelian filter + isAbelian := isSolvable and Length( S ) <= 2; + Assert(3, IsAbelian(G) = isAbelian); + SetIsAbelian(G, isAbelian); + + return isSolvable; end ); @@ -900,16 +913,35 @@ InstallMethod( DerivedSeriesOfGroup, D := DerivedSubgroup( G ); while - # we don't know that the group has no generators - (not HasGeneratorsOfGroup(S[Length(S)]) or - Length(GeneratorsOfGroup(S[Length(S)]))>0) and - ( (not HasAbelianInvariants(S[Length(S)]) and D <> S[ Length(S) ]) or - Length(AbelianInvariants(S[Length(S)]))>0) do + (not HasIsTrivial(S[Length(S)]) or + not IsTrivial(S[Length(S)])) and + ( + (not HasIsPerfectGroup(S[Length(S)]) and + not HasAbelianInvariants(S[Length(S)]) and D <> S[ Length(S) ]) or + (HasIsPerfectGroup(S[Length(S)]) and not IsPerfectGroup(S[Length(S)])) + or (HasAbelianInvariants(S[Length(S)]) + and Length(AbelianInvariants(S[Length(S)])) > 0) + ) do Add( S, D ); Info( InfoGroup, 2, "DerivedSeriesOfGroup: step ", Length(S) ); D := DerivedSubgroup( D ); od; + # set filters if the last term is known to be trivial + if HasIsTrivial(S[Length(S)]) and IsTrivial(S[Length(S)]) then + SetIsSolvableGroup(G, true); + if Length(S) <=2 then + Assert(2, IsAbelian(G)); + SetIsAbelian(G, true); + fi; + fi; + + # set IsAbelian filter if length of derived series is more than 2 + if Length(S) > 2 then + Assert(2, not IsAbelian(G)); + SetIsAbelian(G, false); + fi; + # return the series when it becomes stable return S; end ); diff --git a/tst/testinstall/opers/IsSolvableGroup.tst b/tst/testinstall/opers/IsSolvableGroup.tst new file mode 100644 index 0000000000..24781007be --- /dev/null +++ b/tst/testinstall/opers/IsSolvableGroup.tst @@ -0,0 +1,56 @@ +gap> START_TEST("IsSolvableGroup.tst"); +gap> List(AllGroups(120), IsSolvableGroup); +[ true, true, true, true, false, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, false, false, true, + true, true, true, true, true, true, true, true, true, true, true ] +gap> List(AllTransitiveGroups(DegreeAction, 8), IsSolvable); +[ true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, + false, true, true, true, true, true, false, true, true, true, true, false, + false, false ] +gap> IsSolvable(DihedralGroup(24)); +true +gap> IsSolvable(DihedralGroup(IsFpGroup,24)); +true +gap> DerivedSeries(Group(())); +[ Group(()) ] +gap> G := Group((6,7,8,9,10),(8,9,10),(1,2)(6,7),(1,2,3,4)(6,7,8,9));; +gap> Length(DerivedSeriesOfGroup(G)); +4 +gap> HasIsSolvableGroup(G) and not IsSolvable(G) and HasIsAbelian(G) and not IsAbelian(G); +true +gap> IsSolvableGroup(AbelianGroup([2,3,4,5,6,7,8,9,10])); +true +gap> HasIsSolvableGroup(AbelianGroup(IsFpGroup,[2,3,4,5,6,7,8,9,10])); +true +gap> IsSolvableGroup(AbelianGroup(IsFpGroup,[2,3,4,5,6,7,8,9,10])); +true +gap> IsSolvableGroup(Group(())); +true +gap> A := AbelianGroup([3,3,3]);; H := AutomorphismGroup(A);; +gap> B := SylowSubgroup(H, 13);; G := SemidirectProduct(B, A);; +gap> HasIsSolvableGroup(G) and IsSolvable(G); +true + +## some fp-groups +## The following four tests check whether the current IsSolvable method using +## DerivedSeriesOfGroup indeed adds IsAbelian whenever it is appropriate. If +## later new methods for IsSolvable are added, these tests may fail. Then +## these four tests need to be modified accordingly. +gap> F := FreeGroup("r", "s");; r := F.1;; s := F.2;; +gap> G := F/[s^2, s*r*s*r];; +gap> IsSolvable(G) and HasIsAbelian(G) and not IsAbelian(G); +true +gap> F := FreeGroup("a", "b", "c", "d");; a := F.1;; b := F.2;; c := F.3;; d:= F.4;; +gap> G := F/[ a^2, b^2, a*b*a^(-1)*b^(-1), c, d ];; +gap> IsSolvable(G) and HasIsAbelian(G) and IsAbelian(G); +true +gap> G := F/[ a^2, b^2, c^2, (a*b)^3, (b*c)^3, (a*c)^2, d ];; +gap> IsSolvable(G) and HasIsAbelian(G) and not IsAbelian(G); +true +gap> G := F/[ a^2, b^2, c^2, d^2, (a*b)^3, (b*c)^3, (c*d)^3, (a*c)^2, (a*d)^2, (b*d)^2 ];; +gap> not IsSolvable(G) and HasIsAbelian(G) and not IsAbelian(G); +true +gap> STOP_TEST("IsSolvableGroup.tst", 10000);