Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance MaximalNormalSubgroups for finite solvable groups #552

Merged
merged 8 commits into from
Mar 28, 2016
9 changes: 9 additions & 0 deletions lib/grp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -4232,6 +4232,15 @@ InstallMethod( MaximalNormalSubgroups,

end);

#############################################################################
##
#M MaximalNormalSubgroups( <G> )
##
InstallMethod( MaximalNormalSubgroups, "for simple groups",
[ IsGroup and IsSimpleGroup ], SUM_FLAGS,
function(G) return [ TrivialSubgroup(G) ]; end);


##############################################################################
##
#F MinimalNormalSubgroups(<G>)
Expand Down
43 changes: 43 additions & 0 deletions lib/grppcatr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,49 @@ function( G )
end );


#############################################################################
##
#M MaximalNormalSubgroups( <G> )
##
InstallMethod( MaximalNormalSubgroups, "for solvable groups",
[ IsGroup ],
RankFilter( IsGroup and IsSolvableGroup )
- RankFilter( IsGroup ),

function( G )
local Gf, # FactorGroup of G
hom, # homomorphism from G to Gf
MaxGf; # MaximalNormalSubgroups of Gf

if 0 in AbelianInvariants(G) then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you method is actually called for arbitrary groups (not just solvable ones), and you assume that you can compute AbelianInvaits, IsAbelian, IsSolvableGroup "cheaply". Hmm

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well..... yes. My gut says that if for a group we cannot even compute AbelianInvariants, IsAbelian and IsSolvableGroup cheaply, then we have little chance of computing the maximal normal subgroups cheaply by any other method. But I did not verify this feeling in any way.

# (p) is a maximal normal subgroup in Z for every prime p
Error("number of maximal normal subgroups is infinity");
elif IsAbelian(G) then
if not IsPcGroup(G) then
# convert it to an Abelian PcGroup with same invariants
Gf := AbelianGroup(IsPcGroup, AbelianInvariants(G));
hom := IsomorphismGroups(G, Gf);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsomorphismGroups is potentially expensive -- Why construct a new group and not work in the old one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hulpke NormalMaximalSubgroups needs CanEasilyComputePcgs. I would think that finite Abelian groups should get this, but currently they do not:

gap> F := FreeGroup("x", "y", "z");;
gap> x := F.1;; y := F.2;; z := F.3;;
gap> G := F/[x^(-1)*y^(-1)*x*y, x^(-1)*z^(-1)*x*z, z^(-1)*y^(-1)*z*y, (x*y)^180, (x*y^5)^168, z];
<fp group on the generators [ x, y, z ]>
gap> IsAbelian(G); time; 
true
4
gap> AbelianInvariants(G); time;
[ 3, 4, 5, 7, 9, 32 ]
4
gap> HasSize(G);
true
gap> CanEasilyComputePcgs(G); 
false
gap> NormalMaximalSubgroups(G);; time;
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 2nd choice method found for `NormalMaximalSubgroups' on 1 arguments called from
<function "HANDLE_METHOD_NOT_FOUND">( <arguments> )
 called from read-eval loop at line 24 of *stdin*
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk> 

On the other hand, IsomorphismGroups at least finishes, though really slowly....

gap> Gf := AbelianGroup(IsPcGroup, AbelianInvariants(G));; time; 
4
gap> hom := IsomorphismGroups(G, Gf);; time;
80
gap> MaxGf := NormalMaximalSubgroups(Gf);; time;
24
gap> List(MaxGf, N -> PreImage(hom, N));; time;
15256

I would prefer not to use isomorphism (or do it with NiceMonomorphism, but I do not understand properly their implementations), but that would need some work on the Abelian groups that you collected in #596

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole purpose of CanEasilyComputePcgs is that a group might know to be solvable (say because a flag has been set by the user) but there still is no good method for computing a PCGS. FpGroup are exactly of this form, unless an isomorphism to a solvable group has already been constructed.

It is not a good idea to use expensive functions (such as potentially IsomorphismGroups) just because the context is not clear (and no -- this is not really what the NiceMonomorophisms are intended for).
For FpGroups there is for example MaximalAbelianQuotient which is probably as efficient as one could hope for.

I'm slightly confused by NormalMaximalSubgroups. Aren't we talking about MaximalNormalSubgroups?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hulpke NormalMaximalSubgroups computes all maximal subgroups that are actually normal. In abelian groups they are the same as MaximalNormalSubgroups, and also the same as MaximalSubgroups. The code of the latter looked to me exactly the same as NormalMaximalSubgroups except that some extra checks are done in that one (which are unnecessary in the abelian case). That is why I used NormalMaximalSubgroups, instead.

Would you prefer that I wrote a general algorithm for abelian groups using independent generators and drop the whole isomorphism route? (I did not want to do that because an algorithm exists already, but if you think that would be the proper way, I will do that.)

BTW, again I can only stress that some of these algorithms are incredibly slow for abelian groups. After having independent generators, nothing should be slow anymore, not even isomorphisms....

About MaximalAbelianQuotient: hm, looking at the code it looks like this is the one to go for all the time, and not CommutatorFactorGroup. However, I am now slightly confused about why CommutatorFactorGroup exists at all.....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced CommutatorFactorGroup by MaximalAbelianQuotient

MaxGf := MaximalNormalSubgroups(Gf);
return List(MaxGf, N -> PreImage(hom, N));
else
# for abelian pc groups return all maximal subgroups
# NormalMaximalSubgroups seems to omit some unnecessary checks,
# hence faster than MaximalSubgroups
return NormalMaximalSubgroups(G);
fi;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If NormalMaximalSubgroups is faster, then why don't you use it above, on Gf, which is a pc group, too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fingolfin Thanks, corrected.

elif IsSolvableGroup(G) then
# every maximal normal subgroup is above the derived subgroup
Gf := CommutatorFactorGroup(G);
hom := NaturalHomomorphism(Gf);
MaxGf := MaximalNormalSubgroups(Gf);
return List(MaxGf, N -> PreImage(hom, N));
else
# not solvable group
TryNextMethod();
fi;
end);


#############################################################################
##
#F ModifyMinGens( <pcgsG>, <pcgsS>, <pcgsL>, <min> )
Expand Down
50 changes: 50 additions & 0 deletions tst/testinstall/opers/MaximalNormalSubgroups.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
gap> START_TEST("MaximalNormalSubgroups.tst");
gap> G := SymmetricGroup(4);; MaximalNormalSubgroups(G)=[DerivedSubgroup(G)];
true
gap> G := SymmetricGroup(5);; MaximalNormalSubgroups(G)=[DerivedSubgroup(G)];
true
gap> G := AlternatingGroup(5);; Size(MaximalNormalSubgroups(G))=1 and IsTrivial(MaximalNormalSubgroups(G)[1]);
true
gap> l := [2,4,8,3,9,5,25,7];; G := DirectProduct(List(l, CyclicGroup));;
gap> List(MaximalNormalSubgroups(G),N ->List(MinimalGeneratingSet(N),Order));
[ [ 2, 60, 6300 ], [ 2, 30, 12600 ], [ 2, 30, 12600 ], [ 60, 12600 ],
[ 60, 12600 ], [ 60, 12600 ], [ 60, 12600 ], [ 2, 60, 4200 ],
[ 2, 20, 12600 ], [ 2, 20, 12600 ], [ 2, 20, 12600 ], [ 2, 60, 2520 ],
[ 2, 12, 12600 ], [ 2, 12, 12600 ], [ 2, 12, 12600 ], [ 2, 12, 12600 ],
[ 2, 12, 12600 ], [ 2, 60, 1800 ] ]
gap> A := AbelianGroup(IsFpGroup, [2,4,8,3,9,5,25,7]);;
gap> List(MaximalNormalSubgroups(A),N -> AbelianInvariants(N));
[ [ 2, 3, 4, 4, 5, 7, 9, 25 ], [ 2, 2, 3, 5, 7, 8, 9, 25 ],
[ 2, 2, 3, 5, 7, 8, 9, 25 ], [ 3, 4, 5, 7, 8, 9, 25 ],
[ 3, 4, 5, 7, 8, 9, 25 ], [ 3, 4, 5, 7, 8, 9, 25 ],
[ 3, 4, 5, 7, 8, 9, 25 ], [ 2, 3, 3, 4, 5, 7, 8, 25 ],
[ 2, 4, 5, 7, 8, 9, 25 ], [ 2, 4, 5, 7, 8, 9, 25 ],
[ 2, 4, 5, 7, 8, 9, 25 ], [ 2, 3, 4, 5, 5, 7, 8, 9 ],
[ 2, 3, 4, 7, 8, 9, 25 ], [ 2, 3, 4, 7, 8, 9, 25 ],
[ 2, 3, 4, 7, 8, 9, 25 ], [ 2, 3, 4, 7, 8, 9, 25 ],
[ 2, 3, 4, 7, 8, 9, 25 ], [ 2, 3, 4, 5, 8, 9, 25 ] ]
gap> ForAll(MaximalNormalSubgroups(A), N -> IsSubgroup(A, N) and IsNormal(A, N));
true
gap> D1 := DihedralGroup(Factorial(10));;
gap> List(MaximalNormalSubgroups(D1), StructureDescription);
[ "D1814400", "C1814400", "D1814400" ]
gap> D2 := DihedralGroup(IsFpGroup, 360);;
gap> List(MaximalNormalSubgroups(D2), StructureDescription);
[ "C180", "D180", "D180" ]
gap> ForAll(MaximalNormalSubgroups(D2), N -> IsSubgroup(D2, N) and IsNormal(D2, N));
true

# some infinite fp-groups
gap> F := FreeGroup("r", "s");; r := F.1;; s := F.2;;
gap> G := F/[r^(-1)*s^(-1)*r*s, r^18, s^24];;
gap> Length(MaximalNormalSubgroups(G));
7
gap> G := F/[s^2, s*r*s*r];;

# currently IsSolvable(G) would not run, will be remedied later
gap> IsAbelian(DerivedSubgroup(G));
true
gap> SetIsSolvableGroup(G, true);
gap> Length(MaximalNormalSubgroups(G));
3
gap> STOP_TEST("MaximalNormalSubgroups.tst", 10000);