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

Add MinimalNormalSubgroups and Socle for all nilpotent groups #606

Merged
merged 1 commit into from
Mar 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 137 additions & 25 deletions lib/grp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1626,43 +1626,87 @@ end );

#############################################################################
##
#M Socle( <G> ) . . . . . . . . . . . . . . . . for finite nilpotent groups
#M Socle( <G> ) . . . . . . . . . . . . . . . . . . . . . for simple groups
##
InstallMethod( Socle, "for finite nilpotent groups",
InstallMethod( Socle, "for simple groups",
[ IsGroup and IsSimpleGroup ], SUM_FLAGS, IdFunc );

#############################################################################
##
#M Socle( <G> ) . . . . . . . . . . . . . . . for elementary abelian groups
##
InstallMethod( Socle, "for elementary abelian groups",
[ IsGroup and IsElementaryAbelian ], SUM_FLAGS, IdFunc );

#############################################################################
##
#M Socle( <G> ) . . . . . . . . . . . . . . . . . . . . for nilpotent groups
##
InstallMethod( Socle, "for nilpotent groups",
[ IsGroup ],
RankFilter( IsGroup and CanComputeSize and IsFinite and
IsNilpotentGroup ) - RankFilter( IsGroup ),
RankFilter( IsGroup and IsNilpotentGroup and IsFinite )
- RankFilter( IsGroup ),
function(G)
local H, prodH;
local P, C, size, gen, abinv, indgen, i, p, q, soc;

if not CanComputeSize(G) or not IsFinite(G)
or not IsNilpotentGroup(G) then
# IsNilpotent check might error for fp-groups
if not IsAbelian(G) and not IsNilpotentGroup(G) then
TryNextMethod();
fi;

prodH := TrivialSubgroup(G);
# now socle is the product of Omega of the Sylow subgroups of the center
for H in SylowSystem(Center(G)) do
prodH := ClosureSubgroupNC(prodH, Omega(H, PrimePGroup(H)));
od;
# for finite groups the usual methods are faster
# for SylowSystem and Omega
if ( CanComputeSize(G) or HasIsFinite(G) ) and IsFinite(G) then
soc := TrivialSubgroup(G);
# now socle is the product of Omega of Sylow subgroups of the center
for P in SylowSystem(Center(G)) do
soc := ClosureSubgroupNC(soc, Omega(P, PrimePGroup(P)));
od;
else
# compute generators for the torsion Omega p-subgroups of the center
C := Center(G);
gen := [ ];
abinv := [ ];
indgen := [ ];
size := 1;
for i in [1..Length(AbelianInvariants(C))] do
q := AbelianInvariants(C)[i];
if q<>0 then
p := SmallestRootInt(q);
if not IsBound(gen[p]) then
gen[p] := [ IndependentGeneratorsOfAbelianGroup(C)[i]^(q/p) ];
else
Add(gen[p], IndependentGeneratorsOfAbelianGroup(C)[i]^(q/p));
fi;
size := size * p;
Add(abinv, p);
Add(indgen, IndependentGeneratorsOfAbelianGroup(C)[i]^(q/p));
fi;
od;
# Socle is the product of the torsion Omega p-groups of the center
soc := Subgroup(G, Concatenation(Compacted(gen)));
SetSize(soc, size);
SetAbelianInvariants(soc, abinv);
SetIndependentGeneratorsOfAbelianGroup(soc, indgen);
fi;

# Socle is central in G, set some properties and attributes accordingly
SetIsAbelian(prodH, true);
if not HasParent(prodH) then
SetParent(prodH, G);
SetCentralizerInParent(prodH, G);
SetIsNormalInParent(prodH, true);
elif CanComputeIsSubset(G, Parent(prodH))
and IsSubgroup(G, Parent(prodH)) then
SetCentralizerInParent(prodH, Parent(prodH));
SetIsNormalInParent(prodH, true);
elif CanComputeIsSubset(G, Parent(prodH))
and IsSubgroup(Parent(prodH), G) and IsNormal(Parent(prodH), G) then
SetIsAbelian(soc, true);
if not HasParent(soc) then
SetParent(soc, G);
SetCentralizerInParent(soc, G);
SetIsNormalInParent(soc, true);
elif CanComputeIsSubset(G, Parent(soc))
and IsSubgroup(G, Parent(soc)) then
SetCentralizerInParent(soc, Parent(soc));
SetIsNormalInParent(soc, true);
elif CanComputeIsSubset(G, Parent(soc))
and IsSubgroup(Parent(soc), G) and IsNormal(Parent(soc), G) then
# characteristic subgroup of a normal subgroup is normal
SetIsNormalInParent(prodH, true);
SetIsNormalInParent(soc, true);
fi;

return prodH;
return soc;
end);

#############################################################################
Expand Down Expand Up @@ -4323,6 +4367,74 @@ InstallMethod (MinimalNormalSubgroups,
end);


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


#############################################################################
##
#M MinimalNormalSubgroups (<G>)
##
InstallMethod( MinimalNormalSubgroups, "for nilpotent groups",
[ IsGroup ], RankFilter( IsGroup and IsFinite and IsNilpotentGroup ) - RankFilter( IsGroup ),
function(G)
local soc, i, p, primes, gen, min, MinimalSubgroupsOfPGroupByGenerators;

# IsNilpotent check might error for fp-groups
if not IsAbelian(G) and not IsNilpotentGroup(G) then
TryNextMethod();
fi;

MinimalSubgroupsOfPGroupByGenerators := function(G, p, gen)
# G is the big group
# p is the prime p
# gens is the generators by which the p-group is given
local min, tuples, g, h, k;

min := [ ];
if Length(gen[p])=1 then
Add(min, Subgroup(G, gen[p]));
else
g := Remove(gen[p]);
for tuples in IteratorOfTuples([0..p-1], Length(gen[p])) do
h := g;
for i in [1..Length(tuples)] do
h := h*gen[p][i]^tuples[i];
od;
Add(min, Subgroup(G, [h]));
od;
Append(min, MinimalSubgroupsOfPGroupByGenerators(G, p, gen));
fi;

return min;
end;

soc := Socle(G);
primes := [ ];
gen := [ ];
min := [ ];
for i in [1..Length(AbelianInvariants(soc))] do
p := AbelianInvariants(soc)[i];
AddSet(primes, p);
if not IsBound(gen[p]) then
gen[p] := [ IndependentGeneratorsOfAbelianGroup(soc)[i] ];
else
Add(gen[p], IndependentGeneratorsOfAbelianGroup(soc)[i]);
fi;
od;

for p in primes do
Append(min, MinimalSubgroupsOfPGroupByGenerators(G, p, gen));
od;
return min;
end);


#############################################################################
##
#M SmallGeneratingSet(<G>)
Expand Down
126 changes: 126 additions & 0 deletions tst/testinstall/opers/MinimalNormalSubgroups.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
gap> START_TEST("Socle.tst");
gap> MinimalNormalSubgroups(Group(()));
[ ]
gap> G := Group(());; NormalSubgroups(G);; MinimalNormalSubgroups(G);
[ ]
gap> D := DihedralGroup(8);;
gap> MinimalNormalSubgroups(D) = [ Center(D) ];
true
gap> List(MinimalNormalSubgroups(D), IdGroup);
[ [ 2, 1 ] ]
gap> D := DihedralGroup(IsFpGroup, 8);;
gap> MinimalNormalSubgroups(D) = [ Center(D) ];
true
gap> List(MinimalNormalSubgroups(D), IdGroup);
[ [ 2, 1 ] ]
gap> D := DihedralGroup(IsPcpGroup, 8);;
gap> MinimalNormalSubgroups(D) = [ Center(D) ];
true
gap> List(MinimalNormalSubgroups(D), IdGroup);
[ [ 2, 1 ] ]
gap> D := Group((1,3),(1,2,3,4));;
gap> MinimalNormalSubgroups(D) = [ Center(D) ];
true
gap> List(MinimalNormalSubgroups(D), IdGroup);
[ [ 2, 1 ] ]
gap> DDD := DirectProduct(D, D, D);;
gap> List(MinimalNormalSubgroups(DDD), IdGroup);
[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ] ]
gap> Q := QuaternionGroup(8);;
gap> MinimalNormalSubgroups(Q) = [ Center(Q) ];
true
gap> List(MinimalNormalSubgroups(Q), IdGroup);
[ [ 2, 1 ] ]
gap> MinimalNormalSubgroups(SymmetricGroup(4)) = [ Group((1,2)(3,4),(1,3)(2,4)) ];
true
gap> List(MinimalNormalSubgroups(SymmetricGroup(5)), IdGroup);
[ [ 60, 5 ] ]
gap> List(MinimalNormalSubgroups(AlternatingGroup(5)), IdGroup);
[ [ 60, 5 ] ]
gap> G := Group((1,2),(3,4),(5,6),(7,8));;
gap> IsElementaryAbelian(G);
true
gap> Size(MinimalNormalSubgroups(G));
15
gap> MinimalNormalSubgroups(PrimitiveGroup(8,3)) = [ Group([ (1,7)(2,8)(3,5)(4,6), (1,3)(2,4)(5,7)(6,8), (1,2)(3,4)(5,6)(7,8) ]) ];
true
gap> k := 5;; P := SylowSubgroup(SymmetricGroup(4*k), 2);; A := Group((4*k+1, 4*k+2, 4*k+3));; G := ClosureGroup(P, A);;
gap> Set(MinimalNormalSubgroups(G)) = Set([ Group([ (1,2)(3,4)(5,6)(7,8)(9,10)(11,12)(13,14)(15,16) ]), Group([ (17,18)(19,20) ]), Group([ (1,2)(3,4)(5,6)(7,8)(9,10)(11,12)(13,14)(15,16)(17,18)(19,20) ]), Group([ (21,22,23) ]) ]);
true
gap> A := DihedralGroup(16);;
gap> B := SmallGroup(27, 3);;
gap> C := SmallGroup(125, 4);;
gap> D := DirectProduct(A, B, C, SmallGroup(1536, 2));;
gap> List(MinimalNormalSubgroups(D), IdGroup);
[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ],
[ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ],
[ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ],
[ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 2, 1 ],
[ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ],
[ 5, 1 ] ]
gap> G := Group([ (4,8)(6,10), (4,6,10,8,12), (2,4,12)(6,10,8), (3,9)(4,6,10,8,12)(7,11), (3,5)(4,6,10,8,12)(9,11), (1,3,11,9,5)(4,6,10,8,12) ]);;
gap> MinimalNormalSubgroups(G) = Set([ Group([ (6,12)(8,10), (2,10)(4,12), (2,12)(6,10) ]), Group([ (5,11)(7,9), (3,9)(7,11), (1,9,5,11,7) ]) ]);
true
gap> F := AbelianPcpGroup([0,0,0]);;
gap> G := F / Subgroup(F, [(F.1*F.2)^180, (F.1*F.2^5)^168]);;
gap> MinimalNormalSubgroups(G);
[ Pcp-group with orders [ 2 ], Pcp-group with orders [ 2 ],
Pcp-group with orders [ 2 ], Pcp-group with orders [ 3 ],
Pcp-group with orders [ 3 ], Pcp-group with orders [ 3 ],
Pcp-group with orders [ 3 ], Pcp-group with orders [ 5 ],
Pcp-group with orders [ 7 ] ]
gap> F := FreeGroup("x", "y", "z");;
gap> x := F.1;; y := F.2;; z := F.3;;
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];;
gap> Size(MinimalNormalSubgroups(G));
9
gap> MinimalNormalSubgroups(HeisenbergPcpGroup(3));
[ ]
gap> for G in AllGroups(60) do NormalSubgroups(G);; Print(Collected(List(Set(MinimalNormalSubgroups(G)), IdGroup)), "\n"); od;
[ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 60, 5 ], 1 ] ]
[ [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 4, 2 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 2, 1 ], 1 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
[ [ [ 2, 1 ], 3 ], [ [ 3, 1 ], 1 ], [ [ 5, 1 ], 1 ] ]
gap> G := SmallGroup(120,5);; List(MinimalNormalSubgroups(G), IdGroup);
[ [ 2, 1 ] ]
gap> G := SmallGroup(120,34);; List(MinimalNormalSubgroups(G), IdGroup);
[ [ 60, 5 ] ]
gap> G := SmallGroup(120,35);; List(MinimalNormalSubgroups(G), IdGroup);
[ [ 2, 1 ], [ 60, 5 ] ]
gap> for G in AllGroups(240) do if not IsSolvable(G) then NormalSubgroups(G);; Print(List(MinimalNormalSubgroups(G), IdGroup), "\n"); fi; od;
[ [ 2, 1 ] ]
[ [ 2, 1 ] ]
[ [ 2, 1 ], [ 60, 5 ] ]
[ [ 2, 1 ], [ 60, 5 ] ]
[ [ 2, 1 ] ]
[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ] ]
[ [ 2, 1 ], [ 60, 5 ] ]
[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ], [ 60, 5 ] ]
gap> for G in AllGroups(360) do if not IsSolvable(G) then NormalSubgroups(G);; Print(List(MinimalNormalSubgroups(G), IdGroup), "\n"); fi; od;
[ [ 2, 1 ], [ 3, 1 ] ]
[ [ 360, 118 ] ]
[ [ 3, 1 ], [ 60, 5 ] ]
[ [ 3, 1 ], [ 60, 5 ] ]
[ [ 3, 1 ], [ 60, 5 ] ]
[ [ 2, 1 ], [ 3, 1 ], [ 60, 5 ] ]
gap> G := AbelianGroup([2, 3, 4, 5, 6, 7, 8, 9, 10]);;
gap> Collected(List(Set(MinimalNormalSubgroups(G)), Size));
[ [ 2, 31 ], [ 3, 13 ], [ 5, 6 ], [ 7, 1 ] ]
gap> G := ElementaryAbelianGroup(2^10);;
gap> Collected(List(Set(MinimalNormalSubgroups(G)), Size));
[ [ 2, 1023 ] ]
gap> G := ElementaryAbelianGroup(7^4);;
gap> Collected(List(Set(MinimalNormalSubgroups(G)), Size));
[ [ 7, 400 ] ]
gap> STOP_TEST("Socle.tst", 10000);
36 changes: 36 additions & 0 deletions tst/testinstall/opers/Socle.tst
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
gap> START_TEST("Socle.tst");
gap> Socle(Group(()));
Group(())
gap> D := DihedralGroup(8);;
gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup)));
true
gap> IdGroup(Socle(D));
[ 2, 1 ]
gap> Socle(D) = Center(D);
true
gap> D := DihedralGroup(IsFpGroup, 8);;
gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup)));
true
gap> IdGroup(Socle(D));
[ 2, 1 ]
gap> Socle(D) = Center(D);
true
gap> D := DihedralGroup(IsPcpGroup, 8);;
gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup)));
true
gap> IdGroup(Socle(D));
[ 2, 1 ]
gap> Socle(D) = Center(D);
true
gap> D := Group((1,3),(1,2,3,4));;
gap> Socle(D) = ClosureSubgroup(TrivialSubgroup(D), Union(Set(MinimalNormalSubgroups(D), GeneratorsOfGroup)));
true
Expand All @@ -31,6 +47,13 @@ gap> Socle(SymmetricGroup(4)) = Group((1,2)(3,4),(1,3)(2,4));
true
gap> IdGroup(Socle(SymmetricGroup(5)));
[ 60, 5 ]
gap> IdGroup(Socle(AlternatingGroup(5)));
[ 60, 5 ]
gap> G := Group((1,2),(3,4),(5,6),(7,8));;
gap> IsElementaryAbelian(G);
true
gap> Socle(G)=G;
true
gap> Socle(PrimitiveGroup(8,3)) = Group([ (1,7)(2,8)(3,5)(4,6), (1,3)(2,4)(5,7)(6,8), (1,2)(3,4)(5,6)(7,8) ]);
true
gap> k := 5;; P := SylowSubgroup(SymmetricGroup(4*k), 2);; A := Group((4*k+1, 4*k+2, 4*k+3));; G := ClosureGroup(P, A);;
Expand All @@ -44,8 +67,21 @@ gap> IdGroup(Socle(D));
[ 1440, 5958 ]
gap> Socle(D) = Center(D);
true
gap> Socle(FittingSubgroup(SymmetricGroup(4)));
Group([ (1,4)(2,3), (1,3)(2,4) ])
gap> G := Group([ (4,8)(6,10), (4,6,10,8,12), (2,4,12)(6,10,8), (3,9)(4,6,10,8,12)
> (7,11), (3,5)(4,6,10,8,12)(9,11), (1,3,11,9,5)(4,6,10,8,12) ]);;
gap> Socle(G) = Group([ (3,7)(5,9), (5,11)(7,9), (1,5,3)(7,11,9), (2,8,10)(4,6,12), (4,6)(10,12) ]);
true
gap> F := AbelianPcpGroup([0,0,0]);;
gap> G := F / Subgroup(F, [(F.1*F.2)^180, (F.1*F.2^5)^168]);;
gap> Socle(G);
Pcp-group with orders [ 6, 210 ]
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];;
gap> Size(Socle(G));
1260
gap> Socle(HeisenbergPcpGroup(3));
Pcp-group with orders [ ]
gap> STOP_TEST("Socle.tst", 10000);