diff --git a/doc/ref/groups.xml b/doc/ref/groups.xml index 003c6706b0..648d59ef5c 100644 --- a/doc/ref/groups.xml +++ b/doc/ref/groups.xml @@ -476,6 +476,7 @@ the series without destroying the properties of the series. <#Include Label="LowLayerSubgroups"> <#Include Label="ContainedConjugates"> <#Include Label="ContainingConjugates"> +<#Include Label="MinimalFaithfulPermutationDegree"> <#Include Label="RepresentativesPerfectSubgroups"> <#Include Label="ConjugacyClassesPerfectSubgroups"> <#Include Label="Zuppos"> diff --git a/doc/ref/grpfp.xml b/doc/ref/grpfp.xml index a4ad0e62a6..36a7827506 100644 --- a/doc/ref/grpfp.xml +++ b/doc/ref/grpfp.xml @@ -283,7 +283,7 @@ gap> f := FreeGroup( "a", "b" ); gap> g := f / [ f.1^2, f.2^3, (f.1*f.2)^5 ]; gap> h := IsomorphismPermGroup( g ); -[ a, b ] -> [ (1,2)(3,5), (2,3,4) ] +[ a, b ] -> [ (1,2)(4,5), (2,3,4) ] gap> u:=Subgroup(g,[g.1*g.2]);;rt:=RightTransversal(g,u); RightTransversal(,Group([ a*b ])) diff --git a/lib/claspcgs.gi b/lib/claspcgs.gi index 88f691b09e..a9916bc9f6 100644 --- a/lib/claspcgs.gi +++ b/lib/claspcgs.gi @@ -606,7 +606,7 @@ local G, home, # the group and the home pcgs cent:=false; elif IsPrimePowerInt(Size(G)) then - p:=FactorsInt(Size(G))[1]; + p:=PrimePGroup(G); home:=PcgsPCentralSeriesPGroup(G); eas:=PCentralNormalSeriesByPcgsPGroup(home); @@ -1107,7 +1107,7 @@ local G, home, # the group and the home pcgs (InducedPcgs(home,cl.centralizer), c -> Comm(k, c) in L)); end; elif IsPrimePowerInt(Size(G)) then - p:=FactorsInt(Size(G))[1]; + p:=PrimePGroup(G); home:=PcgsPCentralSeriesPGroup(G); eas:=PCentralNormalSeriesByPcgsPGroup(home); diff --git a/lib/ctbl.gi b/lib/ctbl.gi index a7532a32bd..4efb2d3f03 100644 --- a/lib/ctbl.gi +++ b/lib/ctbl.gi @@ -1251,7 +1251,7 @@ InstallGlobalFunction( CharacterTable_IsNilpotentNormalSubgroup, orders:= OrdersClassRepresentatives( tbl ); ppow:= Filtered( N, i -> IsPrimePowerInt( orders[i] ) ); - for part in Collected( FactorsInt( Sum( classlengths{ N }, 0 ) ) ) do + for part in Collected( Factors(Integers, Sum( classlengths{ N }, 0 ) ) ) do # Check whether the Sylow p subgroup of `N' is normal in `N', # i.e., whether the number of elements of p-power is equal to @@ -2903,7 +2903,7 @@ InstallMethod( PrimeBlocksOp, if d = ppart then d:= 0; else - d:= Length( FactorsInt( ppart / d ) ); # the defect + d:= Length( Factors(Integers, ppart / d ) ); # the defect fi; Add( primeblocks.defect, d ); @@ -4923,7 +4923,7 @@ BindGlobal( "CharacterTableDisplayDefault", function( tbl, options ) elif centralizers = true then Print( "\n" ); for i in [col..col+acol-1] do - fak:= FactorsInt( tbl_centralizers[classes[i]] ); + fak:= Factors(Integers, tbl_centralizers[classes[i]] ); for prime in Set( fak ) do cen[prime][i]:= Number( fak, x -> x = prime ); od; @@ -5279,8 +5279,8 @@ InstallMethod( CharacterTableDirectProduct, # Compute power maps for all prime divisors of the result order. vals_direct:= ComputedPowerMaps( direct ); - for k in Union( FactorsInt( Size( tbl1 ) ), - FactorsInt( Size( tbl2 ) ) ) do + for k in Union( Factors(Integers, Size( tbl1 ) ), + Factors(Integers, Size( tbl2 ) ) ) do powermap_k:= []; vals1:= PowerMap( tbl1, k ); vals2:= PowerMap( tbl2, k ); diff --git a/lib/ctblfuns.gi b/lib/ctblfuns.gi index 341455c244..52f3ab9757 100644 --- a/lib/ctblfuns.gi +++ b/lib/ctblfuns.gi @@ -775,7 +775,7 @@ InstallMethod( CorrespondingPermutations, # Note that if we have taken away a union of orbits such that the # number of remaining points is smaller than the smallest prime # divisor of the order of `g' then all these points must be fixed. - min:= FactorsInt( Order( g ) )[1]; + min:= Factors(Integers, Order( g ) )[1]; images:= []; for list in part do @@ -942,7 +942,7 @@ InstallOtherMethod( CorrespondingPermutations, # Note that if we have taken away a union of orbits such that the # number of remaining points is smaller than the smallest prime # divisor of the order of `g' then all these points must be fixed. - min:= FactorsInt( Order( g ) )[1]; + min:= Factors(Integers, Order( g ) )[1]; images:= []; for list in part do diff --git a/lib/ctblmaps.gi b/lib/ctblmaps.gi index bcbf328926..0d7c8b4296 100644 --- a/lib/ctblmaps.gi +++ b/lib/ctblmaps.gi @@ -167,7 +167,7 @@ InstallOtherMethod( PowerMapOp, fi; image:= class; - for i in FactorsInt( n ) do + for i in Factors(Integers, n ) do # Here we use that `n' is a small integer. if not IsBound( powermap[i] ) then @@ -3368,7 +3368,7 @@ InstallGlobalFunction( ConsiderSmallerPowerMaps, function( arg ) for i in omega do - factors:= FactorsInt( prime mod tbl_orders[i] ); + factors:= Factors(Integers, prime mod tbl_orders[i] ); if factors = [ 1 ] or factors = [ 0 ] then factors:= []; fi; if ForAll( Set( factors ), x -> IsBound( tbl_powermap[x] ) ) then diff --git a/lib/ctblmono.gi b/lib/ctblmono.gi index 09844eeab5..6b5549d211 100644 --- a/lib/ctblmono.gi +++ b/lib/ctblmono.gi @@ -941,7 +941,7 @@ InstallMethod( IsMonomialNumber, pair2, # loop over `collect' ord; # multiplicative order - factors := FactorsInt( n ); + factors := Factors(Integers, n ); collect := Collected( factors ); # Get $\nu_2(n)$. @@ -1120,7 +1120,7 @@ InstallMethod( TestMonomialQuick, if IsSolvableGroup( G ) then pi := PrimeDivisors( codegree ); - hall := Product( Filtered( FactorsInt( factsize ), x -> x in pi ), 1 ); + hall := Product( Filtered( Factors(Integers, factsize ), x -> x in pi ), 1 ); if factsize / hall = chi[1] then @@ -1967,7 +1967,7 @@ InstallMethod( IsMinimalNonmonomial, factsize:= Index( K, F ); # The Fitting subgroup of a minimal nomonomial group is a $p$-group. - facts:= FactorsInt( Size( F ) ); + facts:= Factors(Integers, Size( F ) ); p:= Set( facts ); if 1 < Length( p ) then return false; diff --git a/lib/ctblpope.gi b/lib/ctblpope.gi index 1a1fb327b3..b8ecac6b3d 100644 --- a/lib/ctblpope.gi +++ b/lib/ctblpope.gi @@ -1888,7 +1888,7 @@ InstallGlobalFunction( PermCandidatesFaithful, od; # `primes': prime divisors of $|U|$ for which there is only one $G$-family # of that element order in $UN$: - factors:= FactorsInt( tbl_size / torso[1] ); + factors:= Factors(Integers, tbl_size / torso[1] ); primes:= Set( factors ); orbits:= List( primes, p -> [] ); for i in [ 1 .. nccl ] do diff --git a/lib/cyclotom.gi b/lib/cyclotom.gi index a6e7c66664..91fcff7d61 100644 --- a/lib/cyclotom.gi +++ b/lib/cyclotom.gi @@ -264,7 +264,7 @@ InstallGlobalFunction( CoeffsCyc, function( z, N ) # must be equal, and the negative of this value is put at the # position of the $p$-th element of this congruence class. if second > 1 then - for p in FactorsInt( second ) do + for p in Factors(Integers, second ) do nn:= n / p; newcoeffs:= ListWithIdenticalEntries( nn, 0 ); for k in [ 1 .. n ] do @@ -1245,7 +1245,7 @@ InstallGlobalFunction( Quadratic, function( arg ) fi; coeffs:= ExtRepOfObj( cyc ); - facts:= FactorsInt( Length( coeffs ) ); + facts:= Factors(Integers, Length( coeffs ) ); factsset:= Set( facts ); two_part:= Number( facts, x -> x = 2 ); diff --git a/lib/ffe.gi b/lib/ffe.gi index c7da2966b7..75382896df 100644 --- a/lib/ffe.gi +++ b/lib/ffe.gi @@ -819,7 +819,7 @@ InstallMethod( Order, p := Characteristic(z); d := DegreeFFE(z); ord := p^d-1; - facs := Collected(FactorsInt(ord)); + facs := Collected(Factors(Integers,ord)); for f in facs do for i in [1..f[2]] do o := ord/f[1]; diff --git a/lib/ffeconway.gi b/lib/ffeconway.gi index 24ab129d0f..f4ae0d4800 100644 --- a/lib/ffeconway.gi +++ b/lib/ffeconway.gi @@ -518,7 +518,7 @@ FFECONWAY.WriteOverSmallestField := function(x) return x![3]; fi; d := x![2]; - f := Collected(FactorsInt(d)); + f := Collected(Factors(Integers,d)); for fac in f do l := fac[1]; d1 := d/l; @@ -1355,7 +1355,7 @@ FFECONWAY.DoLogFFE := fi; # use rho method - f:=FactorsInt(q-1:quiet); # Quick factorization, don't stop if its too hard + f:=Factors(Integers,q-1:quiet); # Quick factorization, don't stop if its too hard return FFECONWAY.DoLogFFERho(y,z,q-1,f,q); end; @@ -1392,7 +1392,7 @@ InstallMethod( Order, p := Characteristic(z); d := DegreeFFE(z); ord := p^d-1; - facs := Collected(FactorsInt(ord)); + facs := Collected(Factors(Integers,ord)); for f in facs do for i in [1..f[2]] do o := ord/f[1]; diff --git a/lib/fldabnum.gi b/lib/fldabnum.gi index d8a8c33d02..ba4609f869 100644 --- a/lib/fldabnum.gi +++ b/lib/fldabnum.gi @@ -823,7 +823,7 @@ InstallGlobalFunction( ZumbroichBase, function( n, m ) Error( " must be a divisor of " ); fi; - factsn:= FactorsInt( n ); + factsn:= Factors(Integers, n ); primes:= Set( factsn ); exponsn:= List( primes, x -> 0 ); # Product(List( [1..Length(primes)], # x->primes[i]^exponsn[i]))=n @@ -837,7 +837,7 @@ InstallGlobalFunction( ZumbroichBase, function( n, m ) exponsn[ pos ]:= exponsn[ pos ] + 1; od; - factsm:= FactorsInt( m ); + factsm:= Factors(Integers, m ); exponsm:= List( primes, x -> 0 ); # Product(List( [1..Length(primes)], # x->primes[i]^exponsm[i]))=m if m <> 1 then @@ -960,7 +960,7 @@ InstallGlobalFunction( LenstraBase, function( n, stabilizer, supergroup, m ) m:= m / 2; fi; - factors := FactorsInt( n ); + factors := Factors(Integers, n ); primes := Set( factors ); coprimes := Filtered( primes, x -> m mod x <> 0 ); nprime := Product( Filtered( factors, x -> m mod x <> 0 ) ); diff --git a/lib/ghomfp.gd b/lib/ghomfp.gd index b396378ea8..df8c4de115 100644 --- a/lib/ghomfp.gd +++ b/lib/ghomfp.gd @@ -325,6 +325,34 @@ DeclareAttribute("EpimorphismFromFreeGroup",IsGroup); ## DeclareGlobalFunction("LargerQuotientBySubgroupAbelianization"); +############################################################################# +## +#F ProcessEpimorphismToNewFpGroup( ) +## +## <#GAPDoc Label="ProcessHomomorphismToNewFpGroup"> +## +## +## +## +## Let hom a homomorphism from a group G to a newly created +## finitely presented group F (in which no calculation yet has taken +## place) such that the inverse of hom can be appied to elements of +## $F$. This function endows F (or, more +## correctly, its elements family) with information (in the form of an +## FPFaithHom) about G that can be +## used to obtain a faithful representation for F. This can be in the +## form of G itself being a permutation/matrix or fp group. It also can +## be if G is finitely presented but (its family) has an +## FPFaithHom. (However it will not apply if G is a subgroup +## of an fp group.) The result of this is make higher level calculations in +## F more efficient. +## This is an internal function that does not test its arguments and the +## result is undefined if calling the function on any other object. +## +## +## <#/GAPDoc> +## +DeclareGlobalFunction("ProcessEpimorphismToNewFpGroup"); ############################################################################# ## diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index 4fb6536eba..de748b10b1 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -953,6 +953,7 @@ local H, pres,map,mapi,opt; SetIsBijective(map,true); SetInverseGeneralMapping(map,mapi); SetInverseGeneralMapping(mapi,map); + ProcessEpimorphismToNewFpGroup(map); return map; end ); @@ -1228,6 +1229,46 @@ local F,str; GroupHomomorphismByImagesNC(F,G,GeneratorsOfGroup(F),GeneratorsOfGroup(G)); end); +InstallGlobalFunction(ProcessEpimorphismToNewFpGroup, +function(hom) +local s,r,fam,fas,fpf,mapi; + if not (HasIsSurjective(hom) and IsSurjective(hom)) then + Info(InfoWarning,1,"fp eipimorphism is created in strange way, bail out"); + return; # hom might be ill defined. + fi; + s:=Source(hom); + r:=Range(hom); + mapi:=MappingGeneratorsImages(hom); + if mapi[2]<>GeneratorsOfGroup(r) then + return; # the method does not apply here. One could try to deal with the + #extra generators separately, but that is too much work for what is + #intended as a minor hint. + fi; + s:=SubgroupNC(s,mapi[1]); + fam:=FamilyObj(One(r)); + fas:=FamilyObj(One(s)); + if IsPermCollection(s) or IsMatrixCollection(s) + or IsPcGroup(s) or CanEasilyCompareElements(s) then + # in the long run this should be the inverse of the source restricted + # mapping (or the corestricted inverse) but that does not work well with + # current homomorphism code, thus build new map. + #fpf:=InverseGeneralMapping(hom); + fpf:=GroupHomomorphismByImagesNC(r,s,mapi[2],mapi[1]); + elif IsFpGroup(s) and HasFPFaithHom(fas) then + #fpf:=InverseGeneralMapping(hom)*FPFaithHom(fas); + fpf:=GroupHomomorphismByImagesNC(r,s,mapi[2],List(mapi[1],x->Image(FPFaithHom(fas),x))); + else + fpf:=fail; + fi; + if fpf<>fail then + SetEpimorphismFromFreeGroup(ImagesSource(fpf),fpf); + SetFPFaithHom(fam,fpf); + SetFPFaithHom(r,fpf); + if IsPermGroup(s) then SetIsomorphismPermGroup(r,fpf);fi; + if IsPcGroup(s) then SetIsomorphismPcGroup(r,fpf);fi; + fi; +end); + ############################################################################# ## #E diff --git a/lib/gpfpiso.gi b/lib/gpfpiso.gi index 30fd03ed6b..ed3ef0d1fe 100644 --- a/lib/gpfpiso.gi +++ b/lib/gpfpiso.gi @@ -89,7 +89,9 @@ local l,iso,fp,stbc,gens; stbc:=StabChainMutable(G); gens:=StrongGeneratorsStabChain(stbc); - return IsomorphismFpGroupByGeneratorsNC( G, gens, str:chunk ); + iso:=IsomorphismFpGroupByGeneratorsNC( G, gens, str:chunk ); + ProcessEpimorphismToNewFpGroup(iso); + return iso; end); ############################################################################# @@ -224,6 +226,7 @@ function( G, str ) iso := GroupHomomorphismByImagesNC( G, F, imgsF, gensF ); SetIsBijective( iso, true ); SetKernelOfMultiplicativeGeneralMapping( iso, TrivialSubgroup( G ) ); + ProcessEpimorphismToNewFpGroup(iso); return iso; end ); @@ -442,6 +445,7 @@ function(g,str,N) hom!.decompinfo:=MakeImmutable(di); SetIsWordDecompHomomorphism(hom,true); + ProcessEpimorphismToNewFpGroup(hom); return hom; end); @@ -719,6 +723,7 @@ function( G, gens, str ) Length( relators ), " rels of total length ", Sum( List( relators, rel -> Length( rel ) ) ) ); fi; + ProcessEpimorphismToNewFpGroup(iso); return iso; end ); @@ -742,6 +747,7 @@ function( G, gens, str ) fi; SetIsBijective( iso, true ); SetKernelOfMultiplicativeGeneralMapping( iso, TrivialSubgroup(G) ); + ProcessEpimorphismToNewFpGroup(iso); return iso; end ); @@ -849,6 +855,7 @@ function( G, series, str ) iso := GroupHomomorphismByImagesNC( G, F, imgsF, gensF ); SetIsBijective( iso, true ); SetKernelOfMultiplicativeGeneralMapping( iso, TrivialSubgroup( G ) ); + ProcessEpimorphismToNewFpGroup(iso); return iso; end); diff --git a/lib/gpprmsya.gi b/lib/gpprmsya.gi index f4ccf36f57..5a68b416aa 100644 --- a/lib/gpprmsya.gi +++ b/lib/gpprmsya.gi @@ -346,6 +346,7 @@ local F, # free group # return the isomorphism to the finitely presented group hom:= GroupHomomorphismByImagesNC(G,F,imgs,GeneratorsOfGroup(F)); SetIsBijective( hom, true ); + ProcessEpimorphismToNewFpGroup(hom); return hom; end); @@ -1364,7 +1365,7 @@ syll, act, typ, sel, bas, wdom, comp, lperm, other, away, i, j,b0,opg,bp; if not issym then pg:=AlternatingSubgroup(pg); fi; - if IsSolvableGroup(pg) then + if (Size(pg)/Size(u))>10000 and IsSolvableGroup(pg) then perm:=IsomorphismPcGroup(pg); pg:=PreImage(perm,Normalizer(Image(perm,pg),Image(perm,u))); fi; @@ -1778,6 +1779,7 @@ local F, # free group # return the isomorphism to the finitely presented group hom:= GroupHomomorphismByImagesNC(G,F,imgs,GeneratorsOfGroup(F)); SetIsBijective( hom, true ); + ProcessEpimorphismToNewFpGroup(hom); return hom; end); diff --git a/lib/grp.gd b/lib/grp.gd index 35b00f6173..de6dd5cdf0 100644 --- a/lib/grp.gd +++ b/lib/grp.gd @@ -4176,12 +4176,14 @@ DeclareAttribute( "IsomorphismFpGroup", IsGroup ); ## SetInfoLevel( InfoFpGroup, 1 ); ## gap> iso := IsomorphismFpGroupByGenerators( g, [ (1,2), (1,2,3,4,5) ] ); -## #I the image group has 2 gens and 5 rels of total length 39 +## #I the image group has 2 gens and 4 rels of total length 50 ## [ (1,2), (1,2,3,4,5) ] -> [ F1, F2 ] ## gap> fp := Image( iso ); ## ## gap> RelatorsOfFpGroup( fp ); -## [ F1^2, F2^5, (F2^-1*F1)^4, (F1*F2^-1*F1*F2)^3, (F1*F2^2*F1*F2^-2)^2 ] +## [ F1^2, (F2*F1*F2^-2*F1)^3, +## F2*F1*F2^-1*(F1*F2)^2*F2^2*(F1*F2^-1)^2*F2^-1*F1, +## (F2*F1*F2^-1*F1)^2*F2^-1*F1*F2^2*F1*F2^-2*F1*F2*F1 ] ## ]]> ##

## The main task of the function @@ -4208,9 +4210,9 @@ DeclareAttribute( "IsomorphismFpGroup", IsGroup ); ## (1,12)(2,11)(3,6)(4,8)(5,9)(7,10) ]) ## gap> gens := GeneratorsOfGroup( M12 );; ## gap> iso := IsomorphismFpGroupByGenerators( M12, gens );; -## #I the image group has 3 gens and 20 rels of total length 464 +## #I the image group has 3 gens and 20 rels of total length 554 ## gap> iso := IsomorphismFpGroupByGenerators( M12, gens );; -## #I the image group has 3 gens and 19 rels of total length 491 +## #I the image group has 3 gens and 19 rels of total length 427 ## ]]> ##

## Also in the case of a permutation group G, the function @@ -4259,7 +4261,7 @@ DeclareAttribute( "IsomorphismFpGroup", IsGroup ); ## #I the image group has 3 gens and 11 rels of total length 92 ## gap> iso := IsomorphismFpGroupByGenerators( M12, gens : ## > method := "fast" );; -## #I the image group has 3 gens and 179 rels of total length 4099 +## #I the image group has 3 gens and 136 rels of total length 3215 ## ]]> ##

## Though the option method := "regular" is only checked in the case @@ -4281,7 +4283,7 @@ DeclareAttribute( "IsomorphismFpGroup", IsGroup ); ## [ [ 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 0 ], ## [ 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1 ] ] ] ## gap> iso := IsomorphismFpGroupByGenerators( G, gens );; -## #I the image group has 2 gens and 9 rels of total length 94 +## #I the image group has 2 gens and 10 rels of total length 126 ## gap> iso := IsomorphismFpGroupByGenerators( G, gens : ## > method := "regular");; ## #I the image group has 2 gens and 6 rels of total length 56 @@ -4293,15 +4295,7 @@ DeclareAttribute( "IsomorphismFpGroup", IsGroup ); ## , 0, 0, 0, 1 ] ] ]->[ F1, F2 ]> ## gap> ConstituentsCompositionMapping(iso); ## [ , -## [ (2,3,5,9,16,29)(4,7,13,24,19,32)(6,11,20,34,40,57)(8,15,28,46,42, -## 59)(10,18,25,41,49,67)(12,22,37,53,48,66)(14,26,31)(17,30,35, -## 50,58,38)(21,36,33)(23,39,56)(27,44,61,72,43,60)(45,62,51,68, -## 54,70)(47,64,73)(52,69)(55,71,75,78,77,76)(65,74), -## (1,2,4,8)(3,6,12,23)(5,10,19,33)(7,14,27,45)(9,17,18,31)(11,21, -## 16,28)(13,25,42,57)(20,35,51,67)(22,38,55,70)(24,40,26,43)(29, -## 37,54,39)(30,47,65,68)(32,48)(34,49,36,52)(41,58,56,61)(44,50, -## 53,64)(46,63,69,59)(60,66,75,79)(62,73,72,77)(71,76,80,74) -## ] -> [ F1, F2 ] ] +## [ (2,3,4)(5,6)(8,9,10), (1,2,3,5)(6,7,8,9) ] -> [ F1, F2 ] ] ## ]]> ##

## Since &GAP; cannot decompose elements of a matrix group into generators, diff --git a/lib/grp.gi b/lib/grp.gi index f9740a4326..2324202bff 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -659,7 +659,7 @@ InstallMethod( AbelianInvariants, G := H; gns := GeneratorsOfGroup( G ); if r <> 1 then - Add( ranks, Length(FactorsInt(r)) ); + Add( ranks, Length(Factors(Integers,r)) ); fi; until r = 1; Info( InfoGroup, 2, @@ -1625,7 +1625,7 @@ InstallGlobalFunction( SupersolvableResiduumDefault, function( G ) # `df' is the commutator factor group `oldssr / ssr'. df:= Range( dh ); SetIsAbelian( df, true ); - fs:= FactorsInt( Size( df ) ); + fs:= Factors(Integers, Size( df ) ); # `gen' collects the generators for the next candidate gen := ShallowCopy( GeneratorsOfGroup( df ) ); @@ -3643,8 +3643,8 @@ IsomorphismTypeInfoFiniteSimpleGroup_fun:= function( G ) # from now on we deal with groups of Lie-type # calculate the dominant prime of size - q := Maximum( List( Collected( FactorsInt( size ) ), s -> s[1]^s[2] ) ); - p := FactorsInt( q )[1]; + q := Maximum( List( Collected( Factors(Integers, size ) ), s -> s[1]^s[2] ) ); + p := Factors(Integers, q )[1]; # test if is the Chevalley group A(1,7) ~ A(2,2) if size = 168 then @@ -4570,7 +4570,7 @@ function( g ) if o = 1 then return []; fi; # start to split - f := FactorsInt( o ); + f := Factors(Integers, o ); if Length( Set( f ) ) = 1 then return [ g ]; else @@ -4599,7 +4599,7 @@ function( g, p ) o := Order( g ); if o = 1 then return g; fi; - f := FactorsInt( o ); + f := Factors(Integers, o ); x := Number( f, x -> x = p ); if x = 0 then return g^o; fi; diff --git a/lib/grpffmat.gi b/lib/grpffmat.gi index ef66e4c248..2e32f7f18c 100644 --- a/lib/grpffmat.gi +++ b/lib/grpffmat.gi @@ -150,16 +150,21 @@ end ); InstallMethod( NiceMonomorphism, "falling back on GL", true, [ IsFFEMatrixGroup and IsFinite ], 0, function( grp ) +local tt; # is it GL? if (HasIsNaturalGL( grp ) and IsNaturalGL( grp )) or (HasIsNaturalSL( grp ) and IsNaturalSL( grp )) then return NicomorphismFFMatGroupOnFullSpace(grp); fi; - # is the GL domain small enough to simply use it? + # is the GL domain small enough in comparison to the group to simply use it? + tt:=2000; + if HasSize(grp) and Size(grp)2000 then + or Size(FieldOfMatrixGroup(Parent(grp)))^DimensionOfMatrixGroup(grp)>tt + then # if the permutation image would be too large, compute the orbit. TryNextMethod(); fi; @@ -515,7 +520,7 @@ end); ## PSL(n,q), SU(n,q) and PSU(n,q) ## InstallGlobalFunction(Phi2, -n -> n^2 * Product(Set(Filtered(FactorsInt(n), m -> m <> 1)), +n -> n^2 * Product(Set(Filtered(Factors(Integers,n), m -> m <> 1)), p -> (1 - 1/p^2))); ############################################################################# diff --git a/lib/grpfp.gd b/lib/grpfp.gd index 97ba2cab58..5aa3c5feb4 100644 --- a/lib/grpfp.gd +++ b/lib/grpfp.gd @@ -689,9 +689,11 @@ DeclareGlobalFunction("TracedCosetFpGroup"); ## ## ## -## takes a family fpfam of an FpGroup and a coset table tab +## takes a family fpfam of an FpGroup and a standardized coset +## table tab ## and returns the subgroup of fpfam!.wholeGroup defined by -## this coset table. +## this coset table. The function will not check whether the coset table is +## standardized. ## See also . ## ## @@ -1346,6 +1348,9 @@ DeclareGlobalFunction("ParseRelators"); ## DeclareGlobalFunction("StringFactorizationWord"); +# used to test whether abeliniazation can be mapped in GQuotients +DeclareGlobalFunction("CanMapFiniteAbelianInvariants"); + # used in homomorphisms DeclareGlobalVariable("TRIVIAL_FP_GROUP"); diff --git a/lib/grpfp.gi b/lib/grpfp.gi index be6a7855db..99ab5f54e8 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -3722,7 +3722,7 @@ local fgens,grels,max,gens,t,Attempt; t:=MostFrequentGeneratorFpGroup(G); gens:=Concatenation([t, #pseudorandom element - try if it works - Product([1..Random([2,3])],i->Random(gens)^Random([1,-1]))], + PseudoRandom(G:radius:=Random(2,3))], Filtered(gens,j->UnderlyingElement(j)<>UnderlyingElement(t))); # recursive search (via smaller and smaller partitions) for a finite index @@ -4360,6 +4360,43 @@ local A,B,Q,gens,int,i,fam; return rec(subgroups:=B,inclusions:=int.inclusions); end); +# test whether abelian invariants can be mapped +InstallGlobalFunction(CanMapFiniteAbelianInvariants,function(from,to) +local pf,pt,fp,tp,p,i,f; + # first get primes and then run for each prime + pf:=Union(List(from,Factors)); + pt:=Union(List(to,Factors)); + if not IsSubset(pf,pt) then + return false; + fi; + for p in pf do + fp:=[]; + for i in from do + f:=Filtered(Factors(i),x->x=p); + if Length(f)>0 then + Add(fp,Product(f)); + fi; + od; + tp:=[]; + for i in to do + f:=Filtered(Factors(i),x->x=p); + if Length(f)>0 then + Add(tp,Product(f)); + fi; + od; + #Print(fp,tp,"\n"); + if Length(fp)fp[i],) . . . . . epimorphisms from F onto G up to conjugacy @@ -4377,6 +4414,9 @@ local Fgens, # generators of F val, # its value i,j, # loop ma, + dp,emb1,emb2, # direct product + sameKernel, + A,bigG,Gmap,opt, h; # epis Fgens:=GeneratorsOfGroup(F); @@ -4410,16 +4450,36 @@ local Fgens, # generators of F fi; # try abelian part first - if not IsAbelian(G) and not IsPerfectGroup(G) then - ma:=MaximalAbelianQuotient(F); - if IsFinite(Image(ma)) then - if Length(GQuotients(Image(ma),G/DerivedSubgroup(G)))=0 then - return []; - fi; + if not IsPerfectGroup(G) then + ma:=ShallowCopy(AbelianInvariants(F)); + for i in [1..Length(ma)] do + if ma[i]=0 then ma[i]:=Size(G);fi; # the largest interesting bit + od; + if CanMapFiniteAbelianInvariants(ma,AbelianInvariants(G))=false then + return []; fi; fi; - cl:=ConjugacyClasses(G); + bigG:=G; # generic settings + Gmap:=fail; + + # try to reduce with automorphisms + if IsSolvableGroup(G) and Length(Fgens)>2 + and ValueOption("noauto")<>true then + A:=AutomorphismGroup(G); + if (IsSolvableGroup(A) or Size(G)<10000) and + not ForAll(GeneratorsOfGroup(A),IsInnerAutomorphism) then + + # could decide based on HasGeneralizedPcgs...SemidirectProduct(A,G); + i:=IsomorphismPermGroup(A); # IsomorphismPc might be composition + bigG:=SemidirectProduct(Image(i),InverseGeneralMapping(i),G); + Gmap:=Embedding(bigG,2); + G:=Image(Gmap); + Gmap:=InverseGeneralMapping(Gmap); + fi; + fi; + + cl:=Filtered(ConjugacyClasses(bigG),x->Representative(x) in G); # search relators in only one generator rels:=ListWithIdenticalEntries(Length(Fgens),false); @@ -4467,25 +4527,51 @@ local Fgens, # generators of F val:=Product(pimgs,i->Sum(i,Size)); Info(InfoMorph,1,List(pimgs,Length)," possibilities, Value: ",val); - if ValueOption("findall")=false then - h:=MorClassLoop(G,pimgs, rec(gens:=Fgens,to:=G,from:=F, - free:=FreeGeneratorsOfFpGroup(F), - rels:=List(RelatorsOfFpGroup(F),i->[i,1])),5); - if not IsList(h) then h:=[h];fi; + val:=1; + opt:=rec(gens:=Fgens,to:=bigG, + from:=F, free:=FreeGeneratorsOfFpGroup(F), + rels:=List(RelatorsOfFpGroup(F),i->[i,1])); + + if G=bigG then + val:=val+4; # surjective else - h:=MorClassLoop(G,pimgs, rec(gens:=Fgens,to:=G,from:=F, - free:=FreeGeneratorsOfFpGroup(F), - rels:=List(RelatorsOfFpGroup(F),i->[i,1])),13); + opt.condition:=hom->Size(Image(hom))=Size(G); + fi; + + if ValueOption("findall")<>false then + val:=val+8; # onlyone fi; + h:=MorClassLoop(bigG,pimgs,opt,val); + if not IsList(h) then h:=[h];fi; + + #if ForAny(h,x->opt.condition(x)=false) then Error("CRAP");fi; + Info(InfoMorph,1,"Found ",Length(h)," maps, test kernels"); + + dp:=DirectProduct(G,G); + emb1:=Embedding(dp,1); + emb2:=Embedding(dp,2); + sameKernel:=function(m1,m2) + local a; + m1:=MappingGeneratorsImages(m1)[2]; + m2:=MappingGeneratorsImages(m2)[2]; + a:=List([1..Length(Fgens)],i-> + ImagesRepresentative(emb1,m1[i])*ImagesRepresentative(emb2,m2[i])); + return Size(SubgroupNC(dp,a))=Size(G); + end; + imgos:=[]; cl:=[]; u:=[]; for i in h do imgo:=List(Fgens,j->Image(i,j)); imgo:=Concatenation(imgo,MorFroWords(imgo)); - imgo:=List(imgo,Order); + # fingerprint: Order of fros and commuting indication + imgo:=Concatenation(List(imgo,Order), + Concatenation(List([1..Length(imgo)], + a->Filtered([a+1..Length(imgo)],x->IsOne(Comm(imgo[a],imgo[x])))))); sel:=Filtered([1..Length(imgos)],i->imgos[i]=imgo); + #Info(InfoMorph,3,"|sel|=",Length(sel)); if Length(sel)=0 then Add(imgos,imgo); Add(cl,i); @@ -4496,17 +4582,20 @@ local Fgens, # generators of F fi; od; - e:=KernelOfMultiplicativeGeneralMapping(i); - if not ForAny(u{sel},x->IsSubset(e,x)) then + #e:=KernelOfMultiplicativeGeneralMapping(i); + if not ForAny(cl{sel},x->sameKernel(x,i)) then Add(imgos,imgo); Add(cl,i); - u[Length(cl)]:=e; + #u[Length(cl)]:=e; fi; fi; od; Info(InfoMorph,1,Length(h)," found -> ",Length(cl)," homs"); + if Gmap<>fail then + cl:=List(cl,x->x*Gmap); + fi; return cl; end); @@ -4937,7 +5026,17 @@ local iso,k,id,f; # first try whether the group is ``small'' iso:=FPFaithHom(fam); if iso<>fail and Size(Image(iso))<50000 then - k:=Image(iso); + k:=ImagesSource(iso); + #return function(w) + # if not w in FreeGroupOfFpGroup(Source(iso)) then Error("flasch");fi; + # w:=ElementOfFpGroup(fam,w); + # Print("wa=",w,"\n"); + # w:=ImageElm(iso,w); + # Print("wb=",w,"\n"); + # w:=Factorization(k,w); + # Print("wc=",w,"\n"); + # return UnderlyingElement(w); + #end; return w->UnderlyingElement(Factorization(k,Image(iso,ElementOfFpGroup(fam,w)))); fi; iso:=IsomorphismFpMonoidGeneratorsFirst(CollectionsFamily(fam)!.wholeGroup); diff --git a/lib/grplatt.gd b/lib/grplatt.gd index f35d73db53..1d8910ece2 100644 --- a/lib/grplatt.gd +++ b/lib/grplatt.gd @@ -495,6 +495,29 @@ DeclareSynonym("EmbeddedConjugates",ContainedConjugates); DeclareOperation("ContainingConjugates",[IsGroup,IsGroup,IsGroup]); DeclareSynonym("EmbeddingConjugates",ContainingConjugates); +############################################################################# +## +#O MinimalFaithfulPermutationDegree() +## +## <#GAPDoc Label="MinimalFaithfulPermutationDegree"> +## +## +## +## +## For a finite group G this operation calculates the least +## positive integer n=\mu(G) such that G is isomorphic to a +## subgroup of the symmetric group of degree n. +## This can require calculating the whole subgroup lattice. +## MinimalFaithfulPermutationDegree(SmallGroup(96,3)); +## 12 +## ]]> +## +## +## <#/GAPDoc> +## +DeclareOperation("MinimalFaithfulPermutationDegree",[IsGroup and IsFinite]); + ############################################################################# ## #E diff --git a/lib/grplatt.gi b/lib/grplatt.gi index 64b5c2c2bd..13011dae8b 100644 --- a/lib/grplatt.gi +++ b/lib/grplatt.gi @@ -2806,6 +2806,23 @@ InstallGlobalFunction("SubgroupsTrivialFitting",function(G) local s,a,n,fac,iso,types,t,p,i,map,go,gold,nf,tom,sub,len; n:=DirectFactorsFittingFreeSocle(G); + + # is it almost simple and stored? + if Length(n)=1 then + tom:=TomDataAlmostSimpleRecognition(G); + if tom<>fail and + ValueOption(NO_PRECOMPUTED_DATA_OPTION)<>true then + Info(InfoPerformance,2,"Using Table of Marks Library"); + go:=ImagesSource(tom[1]); + tom:=tom[2]; + Info(InfoLattice,1, "Fetching subgroups of simple ", + Identifier(tom)," from table of marks"); + len:=LengthsTom(tom); + sub:=List([1..Length(len)],x->RepresentativeTom(tom,x)); + return sub; + fi; + fi; + s:=Socle(G); a:=TrivialSubgroup(G); @@ -3219,3 +3236,71 @@ local l,N,t,gens,i,c,o,rep,r,sub,gen; fi; end); +InstallMethod(MinimalFaithfulPermutationDegree,"use lattice",true, + [IsGroup and IsFinite],0, +function(G) +local c,n,deg,ind,core,i,j,sum; + if Size(G)=1 then + # option allows to calculate actual representation -- maybe access under + # different name + if ValueOption("representation")<>true then + return 1; + else + return GroupHomomorphismByImages(G,Group(()),[One(G)],[()]); + fi; + fi; + c:=ConjugacyClassesSubgroups(G); + # sort by reversed order to get core by inclusion test + c:=ShallowCopy(c); # allow sorting + SortBy(c,x->-Size(Representative(x))); + n:=Filtered(c,x->Size(x)=1); # normals + n:=List(n,Representative); + c:=List(c,Representative); # reps of classes + + + deg:=List(n,x->[IndexNC(G,x),[Position(c,x)]]); # best known degrees for + # factors of each of n and how. + + # determine minimal degrees by descending through lattice + for i in [2..Length(c)-1] do # exclude trivial subgroup and whole group + ind:=IndexNC(G,c[i]); + + if indIsSubset(c[i],n[x])); # position of core + if indtrue then + return deg[Length(n)][1]; # smallest degree + fi; + # calculate the representation + deg:=deg[Length(n)][2]; # the subgroups needed + deg:=List(deg,x->FactorCosetAction(G,c[x])); + + sum:=List(GeneratorsOfGroup(G),x->Image(deg[1],x)); + for i in [2..Length(deg)] do + sum:=SubdirectDiagonalPerms(sum,List(GeneratorsOfGroup(G), + x->Image(deg[i],x))); + od; + + ind:=Group(sum); SetSize(ind,Size(G)); + + return GroupHomomorphismByImages(G,ind,GeneratorsOfGroup(G),sum); + +end); + diff --git a/lib/grpnice.gi b/lib/grpnice.gi index 5b78712b30..ecc8922f2f 100644 --- a/lib/grpnice.gi +++ b/lib/grpnice.gi @@ -633,6 +633,7 @@ local mon,iso; mon:=mon*iso; SetIsInjective(mon,true); SetIsSurjective(mon,true); + ProcessEpimorphismToNewFpGroup(mon); return mon; fi; end); @@ -653,6 +654,7 @@ local mon,iso; iso:=mon*iso; SetIsInjective(iso,true); SetIsSurjective(iso,true); + ProcessEpimorphismToNewFpGroup(iso); mon:=MappingGeneratorsImages(iso); SetName(iso,Concatenation("",String(mon[2]),">")); diff --git a/lib/grppcfp.gi b/lib/grppcfp.gi index 1101651503..423f293c5d 100644 --- a/lib/grppcfp.gi +++ b/lib/grppcfp.gi @@ -75,6 +75,7 @@ InstallGlobalFunction( IsomorphismFpGroupByPcgs, function( pcgs, str ) GeneratorsOfGroup( H ) ); SetIsBijective( phi, true ); + ProcessEpimorphismToNewFpGroup(phi); return phi; end ); @@ -158,7 +159,7 @@ gensA, relsA, gensG, imgs, prei, i, j, k, l, norm, index, diag, n,genu; # compute pc presentation for the finite quotient n := Filtered( diag, x -> x <> 1 ); - n := Length( Flat( List( n, x -> FactorsInt( x ) ) ) ); + n := Length( Flat( List( n, x -> Factors(Integers, x ) ) ) ); A := FreeGroup(IsSyllableWordsFamily, n ); gensA := GeneratorsOfGroup( A ); @@ -169,7 +170,7 @@ gensA, relsA, gensG, imgs, prei, i, j, k, l, norm, index, diag, n,genu; for i in [ 1..ng ] do if D[i][i] <> 1 then index[i] := g; - pf[i] := TransposedMat( Collected( FactorsInt( D[i][i] ) ) ); + pf[i] := TransposedMat( Collected( Factors(Integers, D[i][i] ) ) ); pf[i] := rec( factors := pf[i][1], powers := pf[i][2] ); for j in [ 1..Length( pf[i].factors ) ] do @@ -843,7 +844,7 @@ local G, epi, tup, lift, i, found, fac, j, p, iso; i := primes / Size( G ); found := true; while i > 1 and found do - fac := Collected( FactorsInt( i ) ); + fac := Collected( Factors(Integers, i ) ); found := false; j := 1; while not found and j <= Length( fac ) do diff --git a/lib/grpperm.gi b/lib/grpperm.gi index d25dfa9394..08af86ef2c 100644 --- a/lib/grpperm.gi +++ b/lib/grpperm.gi @@ -1542,7 +1542,7 @@ InstallMethod( Socle,"for permgrp", true, [ IsPermGroup ], 0, elif deg < 12960000 then shortcut := true; if deg >= 3125 then - coll := Collected( FactorsInt( deg ) ); + coll := Collected( Factors(Integers, deg ) ); d := Gcd( List( coll, c -> c[ 2 ] ) ); if d mod 5 = 0 then m := 1; @@ -1560,7 +1560,7 @@ InstallMethod( Socle,"for permgrp", true, [ IsPermGroup ], 0, fi; fi; - coll := Collected( FactorsInt( Size( G ) ) ); + coll := Collected( Factors(Integers, Size( G ) ) ); if deg < 78125 then p := coll[ Length( coll ) ][ 1 ]; else diff --git a/lib/grpprmcs.gi b/lib/grpprmcs.gi index 61a93eaf70..7b93290fad 100644 --- a/lib/grpprmcs.gi +++ b/lib/grpprmcs.gi @@ -279,7 +279,7 @@ InstallGlobalFunction( NonPerfectCSPG, i; # loop variables # number of primes in factor / - listlength := Length(FactorsInt(top)); + listlength := Length(Factors(Integers,top)); indexup := index+listlength; oldworkup := D; @@ -294,7 +294,7 @@ InstallGlobalFunction( NonPerfectCSPG, x->(x^g in oldworkup) )); workup := ClosureGroup(oldworkup, g); order := Size(workup)/Size(oldworkup); - orderlist := FactorsInt(order); + orderlist := Factors(Integers,order); for i in [1..Length(orderlist)] do # h is the power of g which adds prime length factors @@ -405,7 +405,7 @@ InstallGlobalFunction( PerfectCSPG, OnTuples); if IsTrivial(stab2) then - prime := FactorsInt(whichcase[2])[1]; + prime := Factors(Integers,whichcase[2])[1]; N:=Group(One(K)); repeat kerelement:=Random(K); @@ -431,7 +431,7 @@ InstallGlobalFunction( PerfectCSPG, L := Orbit( H, StabChainMutable( H ).orbit[1] ); tchom := ActionHomomorphism(H,L,"surjective"); op := Image( tchom ); - H := PreImage(tchom,PCore(op,FactorsInt(whichcase[2])[1])); + H := PreImage(tchom,PCore(op,Factors(Integers,whichcase[2])[1])); H := Centre(H); SetIsAbelian( H, true ); fi; @@ -519,7 +519,7 @@ InstallGlobalFunction( CasesCSPG, function(G) fi; # degree is not prime power - primes := FactorsInt(degree); + primes := Factors(Integers,degree); if primes[1] < primes[Length(primes)] then output[1] := 1; # only case when index of primitive group in socle is not 2*prime @@ -659,7 +659,7 @@ InstallGlobalFunction( FindRegularNormalCSPG, function ( G, H, whichcase ) # case of abelian normal subgroup if whichcase[1] <> 2 then - core := PCore( H, FactorsInt(whichcase[2])[1] ); + core := PCore( H, Factors(Integers, whichcase[2])[1] ); chain:=StabChainOp(core,rec(base:=BaseOfGroup(G),reduced:=false)); cosetrep := chain.transversal[chain.orbit[2]]; candidates := AsList(Stabilizer(core,BaseOfGroup(G)[1]))*cosetrep; @@ -1670,7 +1670,7 @@ InstallMethod( RadicalGroup, # subgroup; kernel is abelian normal. # Take image at this action, and repeat while index > 0 do - primes := FactorsInt(factorsize[index]); + primes := Factors(Integers,factorsize[index]); # if the factor group is not cyclic, no chance for nontrivial radical if Length(primes) > 1 then diff --git a/lib/integer.gi b/lib/integer.gi index 5ac8871f5d..cde6bcb6ac 100644 --- a/lib/integer.gi +++ b/lib/integer.gi @@ -474,7 +474,7 @@ InstallGlobalFunction(DivisorsInt,function ( n ) if n <= Length(DivisorsIntCache) then return DivisorsIntCache[n]; fi; - factors := FactorsInt( n ); + factors := Factors(Integers, n ); # recursive function to compute the divisors divs := function ( i, m ) diff --git a/lib/matrix.gi b/lib/matrix.gi index 42695ca8c9..0c9595339c 100644 --- a/lib/matrix.gi +++ b/lib/matrix.gi @@ -3268,7 +3268,7 @@ InstallGlobalFunction( NullspaceModQ, function( E, q ) j, i,k; # factorize q - facs := FactorsInt( q ); + facs := Factors(Integers, q ); p := facs[1]; n := Length( facs ); field := GF(p); diff --git a/lib/morpheus.gd b/lib/morpheus.gd index 993f63314e..215782cb95 100644 --- a/lib/morpheus.gd +++ b/lib/morpheus.gd @@ -507,7 +507,7 @@ DeclareGlobalFunction("IsomorphismGroups"); ## gap> h:=Group((1,2,3),(1,2)); ## Group([ (1,2,3), (1,2) ]) ## gap> quo:=GQuotients(g,h); -## [ [ (1,3,2,4), (1,2,3) ] -> [ (2,3), (1,2,3) ] ] +## [ [ (1,2,3,4), (1,3,4) ] -> [ (2,3), (1,2,3) ] ] ## ]]> ## ## diff --git a/lib/morpheus.gi b/lib/morpheus.gi index f8551d1d82..c08dd2f72c 100644 --- a/lib/morpheus.gi +++ b/lib/morpheus.gi @@ -253,6 +253,18 @@ v, val, o, i, comb, best,actbase; if not IsFinite(g) then Error("can't do!"); + elif IsFpGroup(g) then + # no sane person should work with automorphism groups of fp groups, but + # if someone really does this is a shortcut that avoids canonization + # issues. + c:=Filtered(Elements(g),x->not IsOne(x)); + hom:=ActionHomomorphism(au,c, + function(e,a) return Image(a,e);end,"surjective"); + SetFilterObj(hom,IsNiceMonomorphism); + SetNiceMonomorphism(au,hom); + SetIsHandledByNiceMonomorphism(au,true); + return; + elif IsAbelian(g) then SetIsFinite(au,true); @@ -1486,6 +1498,12 @@ local i,j,k,l,m,o,nl,nj,max,r,e,au,p,gens,offs; od; od; od; + + if IsFpGroup(G) and IsWholeFamily(G) then + # rewrite to standard generators + gens:=GeneratorsOfGroup(G); + au:=List(au,x->GroupHomomorphismByImagesNC(G,G,gens,List(gens,y->Image(x,y)))); + fi; for i in au do SetIsBijective(i,true); @@ -2182,6 +2200,12 @@ local Fgens, # generators of F fi; fi; + if IsFinite(F) and not IsPerfectGroup(G) and + CanMapFiniteAbelianInvariants(AbelianInvariants(F), + AbelianInvariants(G))=false then + return []; + fi; + if IsAbelian(G) then fak:=5; else diff --git a/lib/numtheor.gi b/lib/numtheor.gi index 8ab48f7219..ac8d7bfb67 100644 --- a/lib/numtheor.gi +++ b/lib/numtheor.gi @@ -288,7 +288,7 @@ InstallGlobalFunction( GeneratorsPrimeResidues, function( n ) ); fi; - factors:= Collected( FactorsInt( n ) ); + factors:= Collected( Factors(Integers, n ) ); primes := []; exponents := []; @@ -1200,7 +1200,7 @@ local c, p,f,l; a:=a mod n; if IsPrime(n) and Gcd(a,n)=1 then # use rho method - f:=FactorsInt(n-1:quiet); # Quick factorization, don't stop if its too hard + f:=Factors(Integers,n-1:quiet); # Quick factorization, don't stop if its too hard l:=DoLogModRho(b,a,n-1,f,n); if l<>fail then return l; @@ -1305,7 +1305,7 @@ InstallGlobalFunction( MoebiusMu, function ( n ) if n = 0 then Error("MoebiusMu: must be nonzero"); fi; if n = 1 then return 1; fi; - factors := FactorsInt( n ); + factors := Factors(Integers, n ); if factors <> Set( factors ) then return 0; fi; return (-1) ^ Length(factors); end ); diff --git a/lib/oprtperm.gi b/lib/oprtperm.gi index 9a21698192..8379678afe 100644 --- a/lib/oprtperm.gi +++ b/lib/oprtperm.gi @@ -935,7 +935,7 @@ InstallMethod( Earns, "G, ints, gens, perms, act", true, # fi; # fi; - fac := FactorsInt( n ); p := fac[ 1 ]; d := Length( fac ); + fac := Factors(Integers, n ); p := fac[ 1 ]; d := Length( fac ); alpha := BasePoint( StabChainMutable( G ) ); G1 := Stabilizer( G, alpha ); diff --git a/lib/pcgs.gi b/lib/pcgs.gi index 06d97e5dca..6aeba23bf7 100644 --- a/lib/pcgs.gi +++ b/lib/pcgs.gi @@ -20,7 +20,7 @@ InstallGlobalFunction( PcgsByIndependentGeneratorsOfAbelianGroup, function( A ) pcs := [ ]; rel := [ ]; for gen in IndependentGeneratorsOfAbelianGroup( A ) do - for f in FactorsInt( Order( gen ) ) do + for f in Factors(Integers, Order( gen ) ) do Add( pcs, gen ); Add( rel, f ); gen := gen ^ f; @@ -283,7 +283,7 @@ function( G ) ord := []; map := []; for i in [1..Length(pcgs)] do - facs := FactorsInt( rels[i] ); + facs := Factors(Integers, rels[i] ); g := pcgs[i]; for f in facs do Add( new, g ); diff --git a/lib/pcgspcg.gi b/lib/pcgspcg.gi index fc701c81a4..29756b8741 100644 --- a/lib/pcgspcg.gi +++ b/lib/pcgspcg.gi @@ -1376,7 +1376,7 @@ local pcgs, g,ord,cord,ppc,q,r,gcd,p1,p2,i,j,e1,pows,exps,rord; g:=el; ppc:=[]; - cord:=Collected(FactorsInt(ord)); + cord:=Collected(Factors(Integers,ord)); for i in [1..Length(cord)-1] do q:=cord[i][1]^cord[i][2]; r:=ord/q; diff --git a/lib/pcgsperm.gi b/lib/pcgsperm.gi index 19d9f9d46a..3d0a518302 100644 --- a/lib/pcgsperm.gi +++ b/lib/pcgsperm.gi @@ -79,7 +79,7 @@ InstallGlobalFunction( AddNormalizingElementPcgs, function( G, z ) A := A.stabilizer; f := 1; - for p in FactorsInt( m ) do + for p in Factors(Integers, m ) do if relord <> false then Add( relord, p, pos ); fi; @@ -203,7 +203,7 @@ InstallGlobalFunction( ExtendSeriesPermGroup, function( ord := gcd; fi; fi; - p := FactorsInt( ord )[ 1 ]; + p := Factors(Integers, ord )[ 1 ]; fi; # Loop over all conjugates of . @@ -368,14 +368,14 @@ InstallGlobalFunction(TryPcgsPermGroup,function(arg) # class of is at most Max( log_p(d)-1 ). deg := NrMovedPoints( grp ); if cent then - bound := Maximum( List( Collected( FactorsInt( deg ) ), p -> + bound := Maximum( List( Collected( Factors(Integers, deg ) ), p -> p[ 1 ] ^ ( LogInt( deg, p[ 1 ] ) ) ) ); else bound := Int( LogInt( deg ^ 5, 3 ) / 2 ); fi; if HasSize( grp ) - and Length( FactorsInt( Size( grp ) ) ) < bound then - bound := Length( FactorsInt( Size( grp ) ) ); + and Length( Factors(Integers, Size( grp ) ) ) < bound then + bound := Length( Factors(Integers, Size( grp ) ) ); fi; for step in Reversed( [ 1 .. Length( G ) - 1 ] ) do @@ -545,8 +545,8 @@ local grp, pcgs, U, oldlen, series, y, w, # class of is at most Max( log_p(d)-1 ). deg := NrMovedPoints( grp ); bound := Int( LogInt( deg ^ 5, 3 ) / 2 ); - if HasSize( grp ) and Length( FactorsInt( Size( grp ) ) ) < bound then - bound:=Length( FactorsInt( Size( grp ) ) ); + if HasSize( grp ) and Length( Factors(Integers, Size( grp ) ) ) < bound then + bound:=Length( Factors(Integers, Size( grp ) ) ); fi; pcseq:=Reversed(pcseq); # build up @@ -938,8 +938,8 @@ InstallGlobalFunction( SolvableNormalClosurePermGroup, function( G, H ) # The derived length of is at most (5 log_3(deg()))/2 (Dixon). bound := Int( LogInt( Maximum(1,NrMovedPoints( G ) ^ 5), 3 ) / 2 ); if HasSize( G ) - and Length( FactorsInt( Size( G ) ) ) < bound then - bound := Length( FactorsInt( Size( G ) ) ); + and Length( Factors(Integers, Size( G ) ) ) < bound then + bound := Length( Factors(Integers, Size( G ) ) ); fi; if IsGroup( H ) then diff --git a/lib/randiso.gi b/lib/randiso.gi index 05edb37ca0..bef48a2387 100644 --- a/lib/randiso.gi +++ b/lib/randiso.gi @@ -145,7 +145,7 @@ RelatorsCode := function( code, size, gens ) t, j, z, z2; # get indices - f := FactorsInt( size ); + f := Factors(Integers, size ); l := Length( f ); mi := Maximum( f ) - 1; n := ShallowCopy( code ); @@ -224,7 +224,7 @@ InstallGlobalFunction( PcGroupCode, function( code, size ) fi; # create free group - F := FreeGroup(IsSyllableWordsFamily, Length( FactorsInt( size ) ) ); + F := FreeGroup(IsSyllableWordsFamily, Length( Factors(Integers, size ) ) ); gens := GeneratorsOfGroup( F ); # usual case diff --git a/lib/randiso2.gi b/lib/randiso2.gi index 68de79d2e7..207d924499 100644 --- a/lib/randiso2.gi +++ b/lib/randiso2.gi @@ -286,7 +286,7 @@ IsomorphismSolvableSmallGroups := function( g, h ) lmin := Length( MinimalGeneratingSet( G ) ); qual := size ^ lmin; poses := fail; - i := - Length( FactorsInt( size ) ) * 5 - lcoc * 8 - lmin * 12; + i := - Length( Factors(Integers, size ) ) * 5 - lcoc * 8 - lmin * 12; Info( InfoRandIso, 3, "testing ", -i, " generating strategies" ); while poses = fail or i < 0 do i := i + 1; diff --git a/lib/string.gi b/lib/string.gi index ed570e0e22..116635c678 100644 --- a/lib/string.gi +++ b/lib/string.gi @@ -248,7 +248,7 @@ InstallGlobalFunction(StringPP, function( n ) str := ""; fi; - facs := Collected( FactorsInt( n ) ); + facs := Collected( Factors(Integers, n ) ); for i in [ 1 .. Length( facs ) ] do if i > 1 then Append( str, "*" ); fi; Append( str, String( facs[ i ][ 1 ] ) ); diff --git a/lib/tietze.gi b/lib/tietze.gi index 96a2383d0e..e7ee1cfaf5 100644 --- a/lib/tietze.gi +++ b/lib/tietze.gi @@ -1190,7 +1190,7 @@ end ); ## InstallGlobalFunction( SimplifiedFpGroup, function ( G ) - local H, T; + local H, T,map,mapi; # check the given argument to be a finitely presented group. if not ( IsSubgroupFpGroup( G ) and IsGroupOfFamily( G ) ) then @@ -1201,13 +1201,30 @@ InstallGlobalFunction( SimplifiedFpGroup, function ( G ) T := PresentationFpGroup( G, 0 ); # perform Tietze transformations. + TzInitGeneratorImages(T); TzGo( T ); - # reconvert the Tietze presentation to a group presentation. - H := FpGroupPresentation( T ); + # reconvert the Tietze presentation to a group presentation. + H := FpGroupPresentation( T ); - # return the resulting group record. - return H; + # translate info + map:=GroupHomomorphismByImagesNC(G,H,GeneratorsOfGroup(G), + List(TzImagesOldGens(T), + i->MappedWord(i,GeneratorsOfPresentation(T), + GeneratorsOfGroup(H)))); + + mapi:=GroupHomomorphismByImagesNC(H,G,GeneratorsOfGroup(H), + List(TzPreImagesNewGens(T), + i->MappedWord(i,OldGeneratorsOfPresentation(T), + GeneratorsOfGroup(G)))); + + SetIsBijective(map,true); + SetInverseGeneralMapping(map,mapi); + SetInverseGeneralMapping(mapi,map); + ProcessEpimorphismToNewFpGroup(map); + + # return the resulting group. + return H; end ); diff --git a/tst/testinstall/semigrp.tst b/tst/testinstall/semigrp.tst index 80acea69ec..7b3d53e5c7 100644 --- a/tst/testinstall/semigrp.tst +++ b/tst/testinstall/semigrp.tst @@ -477,7 +477,7 @@ true # test the methods for Random gap> S := FreeSemigroup(3);; gap> Random(S); -s3*s1 +s1*s2 gap> Random(GlobalRandomSource, S); s3*s2^2