From 50b1fbbeeed80563c4b5c70d957f39ee378fc75c Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Mon, 1 Jan 2018 09:29:23 -0700 Subject: [PATCH] ENHANCE: When computing an isom. to a new fp group from a finite group with `IsomorphismFpGroup`, store the *inverse* of this isomorphism as a known faithful map to a better behaved group, thus avoiding such a searched renewed if any "finite group" calculation is done in the FpGroup (not that this is advisable, but users do it). Ditto translate a known faithful map after calling `(Isomorphism)SimplifiedFpGroup`. This is suggested by #2020 also bail out in complicated case instead of trying hard The output of a `Random` call in test file has changed. REBASE: Comment cleanup --- lib/ghomfp.gd | 28 +++++++++++++++++++++++++ lib/ghomfp.gi | 41 +++++++++++++++++++++++++++++++++++++ lib/gpfpiso.gi | 9 +++++++- lib/gpprmsya.gi | 2 ++ lib/grpfp.gi | 15 ++++++++++++-- lib/grpnice.gi | 2 ++ lib/grppcfp.gi | 1 + lib/tietze.gi | 27 +++++++++++++++++++----- tst/testinstall/semigrp.tst | 2 +- 9 files changed, 118 insertions(+), 9 deletions(-) diff --git a/lib/ghomfp.gd b/lib/ghomfp.gd index b396378ea86..df8c4de1152 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 4fb6536eba9..de748b10b13 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 30fd03ed6be..ed3ef0d1fe7 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 f4ccf36f570..c41c551ca11 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); @@ -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/grpfp.gi b/lib/grpfp.gi index be6a7855dba..415e446cea5 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -3722,7 +3722,8 @@ 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))], + #Product([1..Random([2,3])],i->Random(gens)^Random([1,-1]))], Filtered(gens,j->UnderlyingElement(j)<>UnderlyingElement(t))); # recursive search (via smaller and smaller partitions) for a finite index @@ -4937,7 +4938,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/grpnice.gi b/lib/grpnice.gi index 5b78712b303..ecc8922f2fc 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 11016515039..4d4dbe806a6 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 ); diff --git a/lib/tietze.gi b/lib/tietze.gi index 96a2383d0e8..e7ee1cfaf54 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 80acea69ec8..7b3d53e5c7e 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