diff --git a/lib/ghomfp.gi b/lib/ghomfp.gi index dc2e436af7..6001757229 100644 --- a/lib/ghomfp.gi +++ b/lib/ghomfp.gi @@ -1142,98 +1142,104 @@ end); #InstallMethod(MaximalAbelianQuotient, # "subgroups of fp. abelian rewriting", true, [IsSubgroupFpGroup], 0, -#function(u) -#local aug,r,sec,expwrd,rels,ab,s,m,img,gen,i,j,t1,t2,tn,d,pos; -# if (HasIsWholeFamily(u) and IsWholeFamily(u)) -# # catch trivial case of rank 0 group -# or Length(GeneratorsOfGroup(FamilyObj(u)!.wholeGroup))=0 then -# TryNextMethod(); -# fi; -# -# # get an augmented coset table from the group. Since we don't care about -# # any particular generating set, we let the function chose. -# aug:=AugmentedCosetTableInWholeGroup(u); -# -# aug:=CopiedAugmentedCosetTable(aug); -# -# r:=Length(aug.primaryGeneratorWords); -# Info( InfoFpGroup, 1, "Abelian presentation with ", -# Length(aug.subgroupGenerators), " generators"); -# -# # make vectors -# expwrd:=function(l) -# local v,i; -# v:=ListWithIdenticalEntries(r,0); -# for i in l do -# if i>0 then v:=v+sec[i]; -# else v:=v-sec[-i];fi; -# od; -# return v; -# end; -# -# # do GeneratorTranslation abelianized -# sec:=ShallowCopy(IdentityMat(r,1)); # initialize so next command works -# -# t1:=aug.tree[1]; -# t2:=aug.tree[2]; -# tn:=aug.treeNumbers; -# if Length(tn)>0 then -# for i in [Length(sec)+1..Maximum(tn)] do -# sec[i]:=sec[AbsInt(t1[i])]*SignInt(t1[i]) -# +sec[AbsInt(t2[i])]*SignInt(t2[i]); -# od; -# fi; -# -# sec:=sec{aug.treeNumbers}; -# -# # now make relators abelian -# rels:=[]; -# rels:=RewriteSubgroupRelators( aug, aug.groupRelators); -# rels:=List(rels,expwrd); -# -# rels:=ReducedRelationMat(rels); -# if Length(rels)=0 then -# Add(rels,ListWithIdenticalEntries(r,0)); -# fi; -# s:=NormalFormIntMat(rels,25); # 9+16: SNF with transforms, destructive -# d:=DiagonalOfMat(s.normal); -# pos:=Filtered([1..Length(d)],x->d[x]<>1); -# d:=d{pos}; -# ab:=AbelianGroup(d); -# SetAbelianInvariants(u,d); -# SetAbelianInvariants(ab,d); -# if not IsFinite(ab) then SetReducedMultiplication(ab);fi; -# -# gen:=ListWithIdenticalEntries(Length(rels[1]),One(ab)); -# gen{pos}:=GeneratorsOfGroup(ab); -# -# s:=s.coltrans; -# img:=[]; -# for i in [1..Length(s)] do -# m:=One(ab); -# for j in [1..Length(gen)] do -# m:=m*gen[j]^s[i][j]; -# od; -# Add(img,m); -# od; -# aug.primaryImages:=img; -# if ForAll(img,IsOne) then -# sec:=List(sec,x->img[1]); -# else -# sec:=List(sec,x->LinearCombinationPcgs(img,x)); -# fi; -# aug.secondaryImages:=sec; -# -# m:=List(aug.primaryGeneratorWords,x->ElementOfFpGroup(FamilyObj(One(u)),x)); -# m:=GroupHomomorphismByImagesNC(u,ab,m,img:noassert); -# -# # but give it `aug' as coset table, so we will use rewriting for images -# SetCosetTableFpHom(m,aug); -# -# SetIsSurjective(m,true); -# -# return m; -#end); +BindGlobal("SubFPMaxAbelian", +function(u) +local aug,r,sec,expwrd,rels,ab,s,m,img,gen,i,j,t1,t2,tn,d,pos; + if (HasIsWholeFamily(u) and IsWholeFamily(u)) + # catch trivial case of rank 0 group + or Length(GeneratorsOfGroup(FamilyObj(u)!.wholeGroup))=0 then + TryNextMethod(); + fi; + + # get an augmented coset table from the group. Since we don't care about + # any particular generating set, we let the function chose. + aug:=AugmentedCosetTableInWholeGroup(u); + + aug:=CopiedAugmentedCosetTable(aug); + + r:=Length(aug.primaryGeneratorWords); + Info( InfoFpGroup, 1, "Abelian presentation with ", + Length(aug.subgroupGenerators), " generators"); + + if r=0 then + # no generators, trivial subgroup + s:=AbelianGroup([1]); + return GroupHomomorphismByImagesNC(u,s,[],[]); + fi; + + # make vectors + expwrd:=function(l) + local v,i; + v:=ListWithIdenticalEntries(r,0); + for i in l do + if i>0 then v:=v+sec[i]; + else v:=v-sec[-i];fi; + od; + return v; + end; + + # do GeneratorTranslation abelianized + sec:=ShallowCopy(IdentityMat(r,1)); # initialize so next command works + + t1:=aug.tree[1]; + t2:=aug.tree[2]; + tn:=aug.treeNumbers; + if Length(tn)>0 then + for i in [Length(sec)+1..Maximum(tn)] do + sec[i]:=sec[AbsInt(t1[i])]*SignInt(t1[i]) + +sec[AbsInt(t2[i])]*SignInt(t2[i]); + od; + fi; + + sec:=sec{aug.treeNumbers}; + + # now make relators abelian + rels:=RewriteSubgroupRelators( aug, aug.groupRelators); + rels:=List(rels,expwrd); + + rels:=ReducedRelationMat(rels); + if Length(rels)=0 then + Add(rels,ListWithIdenticalEntries(r,0)); + fi; + s:=NormalFormIntMat(rels,25); # 1+8+16: SNF with transforms, destructive + d:=DiagonalOfMat(s.normal); + pos:=Filtered([1..Length(d)],x->d[x]<>1); + d:=d{pos}; + ab:=AbelianGroup(d); + SetAbelianInvariants(u,AbelianInvariantsOfList(d)); + SetAbelianInvariants(ab,AbelianInvariantsOfList(d)); + if not IsFinite(ab) then SetReducedMultiplication(ab);fi; + + gen:=ListWithIdenticalEntries(r,One(ab)); + gen{pos}:=GeneratorsOfGroup(ab); + + s:=s.coltrans; + img:=[]; + for i in [1..Length(s)] do + m:=One(ab); + for j in [1..Length(gen)] do + m:=m*gen[j]^s[i][j]; + od; + Add(img,m); + od; + aug.primaryImages:=img; + if ForAll(img,IsOne) then + sec:=List(sec,x->img[1]); + else + sec:=List(sec,x->LinearCombinationPcgs(img,x)); + fi; + aug.secondaryImages:=sec; + + m:=List(aug.primaryGeneratorWords,x->ElementOfFpGroup(FamilyObj(One(u)),x)); + m:=GroupHomomorphismByImagesNC(u,ab,m,img:noassert); + + # but give it `aug' as coset table, so we will use rewriting for images + SetCosetTableFpHom(m,aug); + + SetIsSurjective(m,true); + + return m; +end); # u must be a subgroup of the image of home InstallGlobalFunction( @@ -1265,7 +1271,9 @@ local v,aiu,aiv,G,primes,irrel,ma,mao,mau,a,k,gens,imgs,q,dec,deco,piv,co; Filtered(aiu,z->IsInt(z/x))); Info(InfoFpGroup,1,"Larger by factor ",Product(aiv)/Product(aiu)); - ma:=MaximalAbelianQuotient(v); + #ma:=MaximalAbelianQuotient(v); + ma:=SubFPMaxAbelian(v); + mao:=ma; # keep original one, as preimage of subgroup will be easier. a:=Image(ma); k:=List(GeneratorsOfGroup(v),x->ImagesRepresentative(ma,x)); diff --git a/lib/grppcaut.gi b/lib/grppcaut.gi index 8f776a142d..56e9ebfb30 100644 --- a/lib/grppcaut.gi +++ b/lib/grppcaut.gi @@ -1128,9 +1128,9 @@ end ); InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) local spec, weights, first, m, pcgsU, F, pcgsF, A, i, s, n, p, H, pcgsH, pcgsN, N, epi, mats, M, autos, ocr, elms, e, list, imgs, - auto, tmp, hom, gens, P, C, B, D, pcsA, rels, iso, xset, + auto, tmp, hom, gens, P, C, B, D,DP, pcsA, rels, iso, xset, gensA, new,as,somechar,scharorb,asAutom,actbase, - quotimg,eN,field,spaces,sporb,npcgs,nM; + quotimg,eN,field,spaces,sporb,npcgs,nM,eDP,reducegens; asAutom:=function(sub,hom) return Image(hom,sub);end; @@ -1310,6 +1310,34 @@ InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) B:=SubgroupNC(B,SmallGeneratingSet(B)); fi; + reducegens:=function(gp,cnt) + local imgs,sel,i,new; + if Length(GeneratorsOfGroup(gp))<=cnt then return gp;fi; + if eDP=fail then + eDP:=EXPermutationActionPairs(DP); + eDP.dir:=DirectProduct(Image(eDP.p1iso),Image(eDP.p2iso)); + eDP.mapper:=function(elm) + return ImagesRepresentative(Embedding(eDP.dir,1), + ImagesRepresentative(eDP.p1iso,elm[1]))* + ImagesRepresentative(Embedding(eDP.dir,2), + ImagesRepresentative(eDP.p2iso,elm[2])); + end; + fi; + imgs:=List(GeneratorsOfGroup(gp),eDP.mapper); + new:=Group(imgs[1]); + sel:=[1]; + for i in [2..Length(imgs)] do + if not imgs[i] in new then + new:=ClosureGroup(new,imgs[i]); + Add(sel,i); + fi; + od; + gp:=Group(GeneratorsOfGroup(gp){sel}); + SetSize(gp,Size(new)); + return gp; + end; + eDP:=fail; + if weights[s][2] = 1 then #Info( InfoAutGrp, 2,"compute reduced gl "); #B := MormalizingReducedGL( spec, s, n, M ); @@ -1322,13 +1350,13 @@ InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) SetIsGroupOfAutomorphismsFiniteGroup(A,true); fi; - D := DirectProduct( A, B ); + DP := DirectProduct( A, B ); Info( InfoAutGrp, 2,"compute compatible pairs in group of size ", Size(A), " x ",Size(B),", ", - Length(GeneratorsOfGroup(D))," generators"); + Length(GeneratorsOfGroup(DP))," generators"); - if Size(D)>10^10 and Size(A)>4 then + if Size(DP)>10^10 and Size(A)>4 then # translate to different pcgs to make tails A-invariant npcgs:=PcgsCharacteristicTails(F,A); C:=GroupWithGenerators(npcgs); @@ -1338,9 +1366,9 @@ InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) Pcgs(F),M.generators); nM:=rec(field:=M.field,dimension:=M.dimension, generators:=List(npcgs,x->ImagesRepresentative(as,x))); - C:=CompatiblePairs(C,nM,D); + C:=CompatiblePairs(C,nM,DP); else - C := CompatiblePairs( F, M, D ); + C := CompatiblePairs( F, M, DP ); fi; else #Info( InfoAutGrp, 2,"compute reduced gl "); @@ -1354,17 +1382,21 @@ InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) SetSize(A,as); fi; - D := DirectProduct( A, B ); + DP := DirectProduct( A, B ); if weights[s][1] > 1 then Info( InfoAutGrp, 2, "compute compatible pairs in group of size ", Size(A), " x ",Size(B),", ", Length(GeneratorsOfGroup(D))," generators"); - D := CompatiblePairs( F, M, D ); + D := CompatiblePairs( F, M, DP ); + D:=reducegens(D,2); + else + D:=DP; fi; Info( InfoAutGrp,2, "compute inducible pairs in a group of size ", Size( D )); C := InduciblePairs( D, epi, M ); + C:=reducegens(C,20); fi; Unbind(A);Unbind(B);Unbind(D); diff --git a/lib/grppcext.gi b/lib/grppcext.gi index f65bdec547..357ae0a191 100644 --- a/lib/grppcext.gi +++ b/lib/grppcext.gi @@ -445,7 +445,9 @@ local ag, p1iso, agp, p2iso, DP, p1, p2, gens, genimgs, triso,s,i,u,opt, return rec(pairgens:=genimgs, permgens:=gens, isomorphism:=triso, - permgroup:=DP); + permgroup:=DP, + p1iso:=p1iso, + p2iso:=p2iso); else return false; fi;