Created
July 5, 2011 12:06
-
-
Save fingolfin/1064722 to your computer and use it in GitHub Desktop.
GAP fun with group homomorphisms
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
First three examples that create groups G, K and a homomorphism hom | |
between them. | |
In the fourth section there is some generic test code... | |
Example abelian direct product: | |
------------------------------- | |
# G = any abelian group; for this one with a "complicated" | |
# representation. | |
F:=FreeGroup(2); | |
A:=F/[F.1^15,F.2^10,Comm(F.1,F.2)]; | |
B:=AbelianPcpGroup([7,35]); | |
G:=DirectProduct(A,B); | |
IsAbelian(G); | |
# Map G into an isomorphic permutation group K | |
gens:=IndependentGeneratorsOfAbelianGroup(G); | |
imgs:=[]; | |
off := 0; | |
for i in [1..Length(gens)] do | |
n := Order( gens[i] ); | |
g := PermList( Concatenation( [1..off], [off+2..off+n], [off+1] ) ); | |
off := off + n; | |
Add( imgs, g ); | |
od; | |
K := Group( imgs ); | |
# The map from G to K as a *function* | |
myFun := function (g) | |
local exps; | |
exps := IndependentGeneratorExponents(G,g); | |
return Product(List([1..Length(exps)],i-> | |
imgs[i]^exps[i])); | |
end; | |
# Several ways to turn myFun into a GAP group homomorphism: | |
if false then | |
# Version 1: Just with a function | |
# This will cause an error upon "PreImage(hom, k)" | |
hom := GroupHomomorphismByFunction( G, K, myFun ); | |
# Note: Running "IsInjective(hom)" at this point is super slow, as | |
# it tries to compute the normalizer of one subgroup of the the | |
# direct product K in another subgroup, and does so by enumerating | |
# the elements. | |
# Which is esp. silly since the subgroup being normalized is the | |
# trivial one... (looking at CoKernelOfMultiplicativeGeneralMapping | |
# method in ghomperm.gi:956) | |
# | |
# However, we can avoid this by first doing the following: | |
SetIsFinite(G,true); | |
# The reason is that GAP now knows that we are computing | |
# NormalClosure in a subgroup of a finite group, whence in a finite | |
# group, which affects ClosureGroup(Default) amongst other things | |
# This is not so surprising; subgroups of generic direct product | |
# groups simply *are* tricky. | |
elif true then | |
# Version 2: With a function and an inverse | |
# This works great and seems like the best solution overall | |
my_hom_inv := GroupHomomorphismByImages( K, G, imgs, gens ); | |
hom := GroupHomomorphismByFunction( G, K, myFun, k -> k^my_hom_inv ); | |
elif true then | |
# Version 3: Using ActionHomomorphism | |
# For this, "k = PreImage(inv, g);" still is a bottleneck | |
myAct := function(pnt,elm) return pnt^myFun(elm); end; | |
hom := ActionHomomorphism(G,MovedPoints(K),myAct,"surjective"); | |
fi; | |
Example FGA: | |
------------ | |
LoadPackage("FGA"); | |
g:=FreeGroup(3); | |
G:=AutomorphismGroup(g); | |
hom:=IsomorphismFpGroup(G); | |
K := Image(hom); | |
# *Before* the addition of TransferMappingPropertiesToInverse, the | |
# following two checks caused problems; now, only the second one does | |
# (due to comparing elements in an FpGroups | |
inv:=InverseGeneralMapping(hom); | |
IsOne(hom * inv); | |
IsOne(inv * hom); # hangs in coset enumeration triggered by FpElmEqualityMethod | |
Example matrix determinant (not injective) | |
------------------------------------------ | |
R:=Integers mod (3^3*5^2); | |
G:=GL(3,R); | |
if false then | |
myFun := DeterminantMat; | |
K:=Units(R); | |
iso:=IdentityMapping(K); | |
else | |
iso:=IsomorphismPermGroup(Units(R)); | |
K:=Image(iso); | |
myFun := g -> ImageElm(iso, DeterminantMat(g)); | |
fi; | |
if false then | |
# Version 1: Just with a function | |
# Problematic: | |
# - IsInjective runs forever (trying to find perm rep of G) | |
# - testing anything about inv runs forever | |
hom := GroupHomomorphismByFunction( G, K, myFun ); | |
elif true then | |
# Version 2: With a function and a preimage map | |
# | |
myPrefun := function (k) | |
# Finding a preimage; for simplicity we cheat and use that G = GL | |
local mat; | |
mat := IdentityMat(3,R); | |
mat[1][1]:=PreImageElm(iso,k); | |
return mat; | |
end; | |
hom := GroupHomomorphismByFunction( G, K, myFun, false, myPrefun ); | |
elif true then | |
# Version 3: Using ActionHomomorphism. | |
# Overall second best solution; it works mostly fine, but computing | |
# "PreImageElm(inv, g);" is a severe bottleneck: It uses | |
# MakeMapping to compute all images.. ouch | |
myAct := function(pnt,elm) return pnt^myFun(elm); end; | |
hom := ActionHomomorphism(G,MovedPoints(K),myAct,"surjective"); | |
fi; | |
# It helps to tell GAP that the function is *not* injective | |
SetIsInjective(hom,false); | |
General | |
------- | |
# This is the test code I was putting the homomorphisms through | |
#hom := ... G -> K ... | |
G = Source(hom); | |
K = Image(hom); | |
IsSurjective(hom); | |
IsInjective(hom); | |
inv:=InverseGeneralMapping(hom); | |
IsOne(hom * inv); | |
IsOne(inv * hom); | |
if IsInjective(hom) then | |
if true then | |
k:=PseudoRandom(K : radius:=20); | |
g:=ImageElm(inv, k); | |
#g := PreImageElm(hom, k); | |
#g:=PreImagesRepresentative(hom,k); | |
else | |
g:=PseudoRandom(G : radius:=20); | |
k := ImageElm(hom, g); | |
fi; | |
g = ImageElm(inv, k); | |
k = ImageElm(hom, g); # comparing elements might not terminate if K is an Fp group | |
g = PreImageElm(hom, k); | |
k = PreImageElm(inv, g); | |
else | |
k:=PseudoRandom(K : radius:=20); | |
ImageElm(hom,ImagesRepresentative(inv, k)) = k; | |
ImageElm(hom,PreImagesRepresentative(hom, k)) = k; | |
fi; | |
hom2:=InverseGeneralMapping(inv); | |
hom = hom2; | |
IsIdenticalObj(hom, hom2); | |
if not IsIdenticalObj(hom, hom2) then | |
IsGroupGeneralMappingByImages(hom); | |
IsGroupGeneralMappingByImages(hom2); | |
# Test if hom2 can compute an image... | |
k = ImageElm(hom2, g); | |
fi; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment