Skip to content

Instantly share code, notes, and snippets.

@fingolfin
Created July 5, 2011 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fingolfin/1064722 to your computer and use it in GitHub Desktop.
Save fingolfin/1064722 to your computer and use it in GitHub Desktop.
GAP fun with group homomorphisms
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