diff --git a/lib/ctblfuns.gd b/lib/ctblfuns.gd index ae879e38b1..9249ca63f1 100644 --- a/lib/ctblfuns.gd +++ b/lib/ctblfuns.gd @@ -1013,7 +1013,7 @@ DeclareAttribute( "TrivialCharacter", IsGroup ); ## gap> NaturalCharacter( Group( [ [ 0, -1 ], [ 1, -1 ] ] ) ); ## Character( CharacterTable( Group([ [ [ 0, -1 ], [ 1, -1 ] ] ]) ), ## [ 2, -1, -1 ] ) -## gap> d8:= DihedralGroup( 8 );; hom:= IsomorphismPermGroup( d8 );; +## gap> d8:= DihedralGroup( 8 );; hom:= RegularActionHomomorphism( d8 );; ## gap> NaturalCharacter( hom ); ## Character( CharacterTable( ), ## [ 8, 0, 0, 0, 0 ] ) diff --git a/lib/factgrp.gd b/lib/factgrp.gd index 9be74a06cc..2567571be0 100644 --- a/lib/factgrp.gd +++ b/lib/factgrp.gd @@ -232,11 +232,12 @@ DeclareSynonym( "ImproveOperationDegreeByBlocks", ## called internally might try a degree reduction.) ##

## iso:=RegularActionHomomorphism(SymmetricGroup(4));; ## gap> image:= Image( iso );; NrMovedPoints( image ); ## 24 ## gap> small:= SmallerDegreePermutationRepresentation( image );; ## gap> Image( small ); -## Group([ (2,3), (1,2,3), (1,3)(2,4), (1,2)(3,4) ]) +## Group([ (2,5,4,3), (1,4)(2,6)(3,5) ]) ## gap> g:=Image(IsomorphismPermGroup(GL(4,5)));; ## gap> sm:=SmallerDegreePermutationRepresentation(g:cheap);; ## gap> NrMovedPoints(Range(sm)); diff --git a/lib/ghom.gd b/lib/ghom.gd index 12f8e76c90..d658a5392e 100644 --- a/lib/ghom.gd +++ b/lib/ghom.gd @@ -673,3 +673,5 @@ DeclareAttribute( "ImagesSmallestGenerators", ## <#/GAPDoc> ## DeclareAttribute( "RegularActionHomomorphism", IsGroup ); + +DeclareGlobalName("IsomorphismAbelianGroupViaIndependentGenerators"); diff --git a/lib/ghom.gi b/lib/ghom.gi index 37c1bf98e6..bde77886d3 100644 --- a/lib/ghom.gi +++ b/lib/ghom.gi @@ -1397,6 +1397,10 @@ function ( G ) if not HasIsAbelian( G ) and IsAbelian( G ) then # Redispatch to give the special methods for abelian groups a chance. return IsomorphismPermGroup( G ); + elif (not HasIsSolvableGroup(G)) and IsSolvableGroup(G) then + # Redispatch to give the special methods for solvable groups a chance. + return IsomorphismPermGroup( G ); + # MH: Disabled the following code for now, as computing IsNilpotentGroup # can be very expensive, depending on the group type. We could # re-enable it for e.g. pc groups, but I am not sure whether it is diff --git a/lib/grp.gd b/lib/grp.gd index 684b829ae8..c5c4f7edab 100644 --- a/lib/grp.gd +++ b/lib/grp.gd @@ -4279,10 +4279,9 @@ DeclareAttribute( "IsomorphismSpecialPcGroup", IsGroup ); ## gap> g:=SmallGroup(24,12); ## ## gap> iso:=IsomorphismPermGroup(g); -## +## [ f1, f2, f3, f4 ] -> [ (2,3), (2,3,4), (1,2)(3,4), (1,3)(2,4) ] ## gap> Image(iso,g.3*g.4); -## (1,12)(2,16)(3,19)(4,5)(6,22)(7,8)(9,23)(10,11)(13,24)(14,15)(17, -## 18)(20,21) +## (1,4)(2,3) ## ]]> ##

## In many cases the permutation representation constructed by diff --git a/lib/grppc.gi b/lib/grppc.gi index 286c7fd9cf..85a73c19ef 100644 --- a/lib/grppc.gi +++ b/lib/grppc.gi @@ -2876,3 +2876,134 @@ local pcgs; factorhom:=NaturalHomomorphismByNormalSubgroupNC(G,G)); end ); + +############################################################################# +## +#M IsomorphismPermGroup( ) . . . . . . . . . for solvable group +## +InstallMethod( IsomorphismPermGroup, + "solvable groups, e.g. Hall action", + [ IsGroup and IsFinite and IsSolvableGroup and CanEasilyComputePcgs ], +function ( G ) +local d,i,j,a,iso,ims,gens,s,p,abovent; + if IsAbelian(G) then + # force redispatch on abelian group + return IsomorphismAbelianGroupViaIndependentGenerators(IsPermGroup,G); + elif Size(G)<=100 and Size(G)<>64 then + # for these orders the optimal degree is fast enough + iso:=MinimalFaithfulPermutationRepresentation(G); + Info(InfoPcGroup,1,"Use optimal degree ", + Size(G),":",NrMovedPoints(Range(iso))); + return iso; + fi; + + # can be subdirect? + d:=MinimalNormalSubgroups(G); + if Length(d)>1 then + # it can -- find a nice decomposition in two + + # take two largest + d:=ShallowCopy(d); + SortBy(d,x->-Size(x)); + abovent:=function(a,b) + local hom,n; + hom:=NaturalHomomorphismByNormalSubgroupNC(G,a); + b:=Image(hom,b); + n:=NormalSubgroups(Image(hom,a)); + n:=Filtered(n,x->not IsSubset(x,b)); + SortBy(n,x->-Size(x)); # descending order + return List(n,x->PreImage(hom,x)); + end; + + d:=[abovent(d[1],d[2]),abovent(d[2],d[1])]; + if Size(d[2][1])>Size(d[1][1]) then d:=Reversed(d);fi; + d:=[d[1][1],First(d[2],x->Size(Intersection(x,d[1][1]))=1)]; + Info(InfoPcGroup,1,"Subdirect ",List(d,x->Size(G)/Size(x))); + iso:=List(d,x->NaturalHomomorphismByNormalSubgroupNC(G,x)); + d:=List(iso,x->IsomorphismPermGroup(Image(x,G))); + ims:=List([1,2],x->List(GeneratorsOfGroup(G), + y->ImagesRepresentative(d[x],ImagesRepresentative(iso[x],y)))); + ims:=SubdirectDiagonalPerms(ims[1],ims[2]); + d:=Group(ims); + UseIsomorphismRelation(G,d); + s:=SmallerDegreePermutationRepresentation(d:cheap); + if NrMovedPoints(Range(s))ImagesRepresentative(s,x)); + d:=Image(s); + UseIsomorphismRelation(G,d); + fi; + iso:=GroupHomomorphismByImagesNC(G,d,GeneratorsOfGroup(G),ims); + Assert(1,IsBijective(iso)); + SetIsBijective(iso,true); + return iso; + fi; + + p:=Collected(Factors(Size(G))); + if Length(p)>1 then + d:=Combinations(p); + SortBy(d,x->-Product(x,y->y[1]^y[2])); + for i in d do + s:=HallSubgroup(G,List(i,x->x[1])); + if Size(Core(G,s))=1 then + Info(InfoPcGroup,1,"Hall ",List(i,x->x[1])); + + # try normalizer quotient + d:=Normalizer(G,s); + if Size(Core(G,d))=1 then + s:=d; + else + d:=ShallowCopy(IntermediateSubgroups(d,s).subgroups); + SortBy(d,x->-Size(x)); + a:=First(d,x->Size(Core(G,x))=1); + if a<>fail then s:=a;fi; + fi; + + iso:=FactorCosetAction(G,s); + Assert(1,IsBijective(iso)); + SetIsBijective(iso,true); + d:=Image(iso); + UseIsomorphismRelation(G,d); + return iso; + fi; + od; + + else + # p-group, one minimal: try to go from factor permrep + d:=MinimalNormalSubgroups(G)[1]; + ims:=NaturalHomomorphismByNormalSubgroupNC(G,d); + iso:=IsomorphismPermGroup(Image(ims,G)); + ims:=ims*iso; + a:=Image(ims,G); + Info(InfoPcGroup,1,"Factor ",List(Orbits(a,MovedPoints(a)),Length)); + s:=List(Orbits(a,MovedPoints(a)),x->Stabilizer(a,x[1])); + s:=List(s,x->PreImage(ims,x)); + SortBy(s,x->-Size(x)); + for j in [1..Length(Factors(Size(s[1])))] do + for i in [1..Length(s)] do + p:=LowLayerSubgroups(s[i],j); + p:=Filtered(p,x->not IsSubset(x,d)); + if Length(p)>0 then + d:=Maximum(List(p,Size)); + iso:=FactorCosetAction(G,First(p,x->Size(x)=d)); + ims:=[List(GeneratorsOfGroup(G),x->ImagesRepresentative(iso,x)), + List(GeneratorsOfGroup(G),x->ImagesRepresentative(ims,x))]; + ims:=SubdirectDiagonalPerms(ims[1],ims[2]); + d:=Group(ims); + UseIsomorphismRelation(G,d); + s:=SmallerDegreePermutationRepresentation(d:cheap); + if NrMovedPoints(Range(s))ImagesRepresentative(s,x)); + d:=Image(s); + UseIsomorphismRelation(G,d); + fi; + iso:=GroupHomomorphismByImagesNC(G,d,GeneratorsOfGroup(G),ims); + Assert(1,IsBijective(iso)); + SetIsBijective(iso,true); + return iso; + fi; + od; + od; + + Error("should never happen"); + fi; +end);