Skip to content

Commit

Permalink
ENHANCE: MinimalGeneratingSet method
Browse files Browse the repository at this point in the history
for arbitrary finite groups
  • Loading branch information
hulpke committed Oct 28, 2022
1 parent f2e93f5 commit 618b058
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 8 deletions.
10 changes: 4 additions & 6 deletions lib/grp.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2181,12 +2181,10 @@ DeclareAttribute( "LargestElementGroup", IsGroup );
## <Description>
## returns a generating set of <A>G</A> of minimal possible length.
## <P/>
## Note that &ndash;apart from special cases&ndash; currently there are only
## efficient methods known to compute minimal generating sets of finite
## solvable groups and of finitely generated nilpotent groups.
## Hence so far these are the only cases for which methods are available.
## The former case is covered by a method implemented in the &GAP; library,
## while the second case requires the package <Package>Polycyclic</Package>.
## Note that only methods for finite groups, solvable groups, or finitely
## generated nilpotent groups are available (the latter through the
## <Package>Polycyclic</Package> package) and that
## calculations for nonsolvable finite groups of higher rank can be expensive.
## <P/>
## If you do not really need a minimal generating set, but are satisfied
## with getting a reasonably small set of generators, you better use
Expand Down
90 changes: 90 additions & 0 deletions lib/grp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,96 @@ function(G)
fi;
end);

InstallOtherMethod(MinimalGeneratingSet,"finite groups",true,
[IsGroup and IsFinite],0,
function(g)
local r,i,j,u,f,q,n,lim,sel,nat,ok,mi;
if not HasIsSolvableGroup(g) and IsSolvableGroup(g) and
CanEasilyComputePcgs(g) then
return MinimalGeneratingSet(g);
fi;
# start at rank 2/abelian rank
n:=AbelianInvariants(g);
if Length(n)>0 then
r:=Maximum(List(Set(List(n,SmallestPrimeDivisor)),
x->Number(n,y->y mod x=0)));
else r:=0; fi;
r:=Maximum(r,2);
n:=false;
repeat
if Length(GeneratorsOfGroup(g))=r then
return GeneratorsOfGroup(g);
fi;
for i in [1..10^r] do
u:=SubgroupNC(g,List([1..r],x->Random(g)));
if Size(u)=Size(g) then return GeneratorsOfGroup(u);fi; # found
od;
f:=FreeGroup(r);
ok:=false;
if IsPerfectGroup(g) then
if n=false then
n:=ShallowCopy(NormalSubgroups(g));
# all perfect groups of order <15360 *are* 2-generated
lim:=15360;
n:=Filtered(n,x->IndexNC(g,x)>=lim and Size(x)>1);
SortBy(n,x->-Size(x));
mi:=MinimalInclusionsGroups(n);
fi;
i:=1;
while i<=Length(n) do
ok:=false;
# is factor randomly r-generated?
q:=2^r;
while ok=false and q>0 do
u:=n[i];
for j in [1..r] do
u:=ClosureGroup(u,Random(g));
od;
ok:=Size(u)=Size(g);
q:=q-1;
od;

if not ok then
# is factor a nonsplit extension with minimal normal -- if so rank
# stays the same, no new test

# minimal overnormals
sel:=List(Filtered(mi,x->x[1]=i),x->x[2]);
if Length(sel)>0 then
nat:=NaturalHomomorphismByNormalSubgroupNC(g,n[i]);
for j in sel do
if not ok then
# nonsplit extension (so pre-images will still generate)?
ok:=0=Length(
ComplementClassesRepresentatives(Image(nat),Image(nat,n[j])));
fi;
od;
fi;
fi;

if not ok then
q:=GQuotients(f,g/n[i]:findall:=false);
if Length(q)=0 then
# fail in quotient
i:=Length(n)+10;
Info(InfoGroup,2,"Rank ",r," fails in quotient\n");
fi;
fi;

i:=i+1;
od;

fi;
if n=false or i<=Length(n)+1 then
# still try group
q:=GQuotients(f,g:findall:=false);
if Length(q)>0 then return r;fi; # found
fi;
r:=r+1;
until false;
end);


#############################################################################
##
#M IsElementaryAbelian(<G>) . . . . . test if a group is elementary abelian
Expand Down
6 changes: 6 additions & 0 deletions lib/grplatt.gd
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,9 @@ DeclareOperation("MinimalFaithfulPermutationRepresentation",
DeclareGlobalFunction("DescSubgroupIterator");

DeclareGlobalFunction("SubgroupConditionAbove");

# Utility function
# MinimalInclusionsGroups(l)
# returns a list of all inclusion indices [a,b] where l[a] is maximal subgroup
# of l[b].
DeclareGlobalFunction("MinimalInclusionsGroups");
33 changes: 33 additions & 0 deletions lib/grplatt.gi
Original file line number Diff line number Diff line change
Expand Up @@ -3737,3 +3737,36 @@ local divs,limit,mode,l,process,done,bound,maxer,prime;
end));
end);

# Utility function
# MinimalInclusionsGroups(l)
# returns a list of all inclusion indices [a,b] where l[a] is maximal subgroup
# of l[b].
InstallGlobalFunction(MinimalInclusionsGroups,function(l)
local s,p,incl,cont,i,j,done;
# sort increasing size
s:=List(l,Size);
p:=Sortex(s);
l:=Permuted(l,p);
s:=List(l,Size);
incl:=[];
cont:=[];
for i in [Length(l),Length(l)-1..1] do
# those we know it will be in
done:=[i];
for j in [i+1..Length(l)] do
if not j in done and s[j]>s[i] and s[j] mod s[i]=0 then
if IsSubset(l[j],l[i]) then
Add(incl,[i,j]);
done:=Union(done,cont[j]);
fi;
fi;
od;
cont[i]:=done;
od;
p:=p^-1;
incl:=List(incl,x->OnTuples(x,p));
Sort(incl);
return incl;
end);


3 changes: 1 addition & 2 deletions tst/testbugfix/2022-09-09-MinimalGeneratingSet.tst
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
gap> G:=Group((1,2),(2,3),(3,4));;
gap> H:=Image(IsomorphismFpGroup(G));;
gap> MinimalGeneratingSet(H);
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 4th choice method found for `MinimalGeneratingSet' on 1 arguments
[ F1^-1*F2*F1^-1*F3^-1, F1^-1*F2^-1*F3^-1 ]
5 changes: 5 additions & 0 deletions tst/teststandard/permgrp.tst
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,10 @@ true
gap> Length(ConjugacyClasses(PSL(2,64)));
65

# MinimalGeneratingSet
gap> AllTransitiveGroups(NrMovedPoints,12,
> x->Length(MinimalGeneratingSet(x)),4);
[ [3^4:2^3]E(4) ]

#
gap> STOP_TEST( "permgrp.tst", 1);

0 comments on commit 618b058

Please sign in to comment.