Group homomorphisms
A group homomorphism from a group $G$ to a group $H$ is a map $f$ with domain $G$ and codomain $H$ that respects the group structure, that is, $(g*h)^f = g^f * h^f$ and $(g^{-1})^f = (g^f)^{-1}$ hold for all $g, h \in G$.
Creation of group homomorphisms
A homomorphism from $G$ to $H$ can be defined by prescribing the images of some generators of $G$ (see hom(G::GAPGroup, H::GAPGroup, gensG::Vector, imgs::Vector) or by prescribing a Julia function that maps the elements as required (see hom(G::GAPGroup, H::GAPGroup, img::Function).
For homomorphisms to permutation groups that are defined by the action of $G$ on a set, see action_homomorphism.
For the special cases of an identity mapping between groups or the mapping whose image is a trivial group, use id_hom(G::GAPGroup) and trivial_morphism(G::GAPGroup, H::GAPGroup = G), respectively.
The restriction of a homomorphism to a subgroup of its domain is given by restrict_homomorphism(f::GAPGroupHomomorphism, H::GAPGroup),
hom — Method
hom(G::GAPGroup, H::GAPGroup, img::Function[, preimg::Function])Return the group homomorphism defined by the function img that takes an element x of G as its argument and returns the element of H that is the image of x under the map.
If a second function preimg is given then it takes an element y of H and returns the element of G that is the preimage of y under the map.
It is not checked whether the returned map is actually a group homomorphism.
Examples
julia> S = symmetric_group(4);
julia> x = S[1];
julia> f = hom(S, S, [y^x for y in gens(S)])
Group homomorphism
from symmetric group of degree 4
to symmetric group of degree 4
julia> g = hom(S, S, y -> y^x)
Group homomorphism
from symmetric group of degree 4
to symmetric group of degree 4hom — Method
hom(G::Group, H::Group, gensG::Vector = gens(G), imgs::Vector; check::Bool = true)Return the group homomorphism from Gto H that is defined by mapping gensG[i] -> imgs[i] for every i. For that, the elements of gensG must generate G, and gensG and imgs must have the same length.
If check is set to false then it is not checked whether the mapping defines a group homomorphism. Otherwise an exception is thrown if the input does not define a group homomorphism.
Examples
julia> S = symmetric_group(4);
julia> x = S[1];
julia> f = hom(S, S, [y^x for y in gens(S)])
Group homomorphism
from symmetric group of degree 4
to symmetric group of degree 4
julia> f == hom(S, S, y -> y^x)
truetrivial_morphism — Function
trivial_morphism(G::GAPGroup, H::GAPGroup = G)Return the homomorphism from G to H sending every element of G into the identity of H.
restrict_homomorphism — Method
restrict_homomorphism(f::GAPGroupHomomorphism, H::Group)
restrict_homomorphism(f::GAPGroupEmbedding, H::Group)
restrict_homomorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::T) where T <: GroupReturn the restriction of f to H. An exception is thrown if H is not a subgroup of domain(f).
Examples
julia> S = symmetric_group(4);
julia> x = S[1];
julia> f = hom(S, S, [y^x for y in gens(S)])
Group homomorphism
from symmetric group of degree 4
to symmetric group of degree 4
julia> A = derived_subgroup(S)[1];
julia> restrict_homomorphism(f, A) == hom(A, S, [y^x for y in gens(A)])
trueApplying group homomorphisms
Group homomorphisms can be used to compute images and preimages of elements and subgroups.
For a group homomorphism f and a group element x, the image of x under f can be computed as image(f::GAPGroupHomomorphism, x::GAPGroupElem) or f(x) or x^f, and the preimage of an element y in the image can be computed as preimage(f::GAPGroupHomomorphism, x::GAPGroupElem).
image — Method
image(f::GAPGroupHomomorphism, x::GAPGroupElem)
image(f::GAPGroupEmbedding, x::GAPGroupElem)
(f::GAPGroupHomomorphism)(x::GAPGroupElem)
(f::GAPGroupEmbedding)(x::GAPGroupElem)Return the image f(x) of x under f. The syntax x^f is also supported.
Examples
julia> G = symmetric_group(4);
julia> F, epi = quo(G, pcore(G, 2)[1])
(Pc group of order 6, Hom: G -> F)
julia> x = gen(G, 1)
(1,2,3,4)
julia> img = image(epi, x)
f1*f2
julia> img == epi(x) == x^epi
truepreimage — Method
preimage(f::Union{GAPGroupHomomorphism, GAPGroupEmbedding}, x::GAPGroupElem)Return an element y in the domain of f with the property f(y) == x. See has_preimage_with_preimage(f::GAPGroupHomomorphism, x::GAPGroupElem; check::Bool = true) for a check whether x has such a preimage.
Examples
julia> G = symmetric_group(4);
julia> F, epi = quo(G, pcore(G, 2)[1])
(Pc group of order 6, Hom: G -> F)
julia> x = gen(F, 1)
f1
julia> pre = preimage(epi, x)
(3,4)has_preimage_with_preimage — Method
has_preimage_with_preimage(f::GAPGroupHomomorphism, x::GAPGroupElem; check::Bool = true)
has_preimage_with_preimage(f::GAPGroupEmbedding, x::GAPGroupElem; check::Bool = true)Return (true, y) if there exists y in domain(f) such that f(y) = x holds; otherwise, return (false, o) where o is the identity of domain(f).
If check is set to false then the test whether x is an element of image(f) is omitted.
Examples
julia> G = symmetric_group(4);
julia> F, epi = quo(G, pcore(G, 2)[1])
(Pc group of order 6, Hom: G -> F)
julia> x = gen(F, 1)
f1
julia> has_preimage_with_preimage(epi, x)
(true, (3,4))Operations on homomorphisms
OSCAR supports the following operations on homomorphisms.
inv(f)is the inverse off. An exception is thrown iffis not bijective.f^nis the homomorphismfcomposedntimes with itself. An exception is thrown if the domain and the codomain offdo not coincide (unlessn=1). Ifnis negative, the result is the inverse offcomposedntimes with itself.compose(f, g)is the composition offandg. This works only if the codomain offcoincides with the domain ofg. A shorter equivalent expressions isf*g.
Examples
julia> S = symmetric_group(4)
Symmetric group of degree 4
julia> f = hom(S, S, x->x^S[1])
Group homomorphism
from symmetric group of degree 4
to symmetric group of degree 4
julia> g = hom(S, S, x->x^S[2])
Group homomorphism
from symmetric group of degree 4
to symmetric group of degree 4
julia> f*g == hom(S, S, x->x^(S[1]*S[2]))
true
julia> f == f^-3
trueThe composition operation * has to be read from the right to the left. So, (f*g)(x) is equivalent to g(f(x)).
Properties of homomorphisms
OSCAR implements the following attributes of homomorphisms, in addition to the usual domain and codomain.
is_injective — Method
is_injective(f::GAPGroupHomomorphism)
is_injective(f::GAPGroupEmbedding)Return whether f is injective.
is_surjective — Method
is_surjective(f::GAPGroupHomomorphism)
is_surjective(f::GAPGroupEmbedding)Return whether f is surjective.
is_bijective — Method
is_bijective(f::GAPGroupHomomorphism)
is_bijective(f::GAPGroupEmbedding)Return whether f is bijective.
is_invertible — Method
is_invertible(f::GAPGroupHomomorphism)
is_invertible(f::GAPGroupEmbedding)Return whether f is invertible.
is_invariant — Method
is_invariant(f::GAPGroupHomomorphism, H::GAPGroup)
is_invariant(f::GAPGroupEmbedding, H::GAPGroup)Return whether f(H) == H holds. An exception is thrown if domain(f) and codomain(f) are not equal or if H is not contained in domain(f).
Subgroups described by homomorphisms
The following functions compute subgroups or quotients of either the domain or the codomain. Analogously to the functions described in Sections Subgroups and Quotients, the output consists of a pair (H, g), where H is a subgroup (resp. quotient) and g is its embedding (resp. projection) homomorphism.
cokernel — Method
cokernel(f::Union{GAPGroupHomomorphism, GAPGroupEmbedding})Return the cokernel of f, that is, the quotient of the codomain of f by the normal closure of the image.
cokernel(a::ModuleFPHom)Return the cokernel of a as an object of type SubquoModule.
Examples
julia> R, (x, y, z) = polynomial_ring(QQ, [:x, :y, :z]);
julia> F = free_module(R, 3);
julia> G = free_module(R, 2);
julia> W = R[y 0; x y; 0 z]
[y 0]
[x y]
[0 z]
julia> a = hom(F, G, W);
julia> cokernel(a)
Subquotient of submodule with 2 generators
1: e[1]
2: e[2]
by submodule with 3 generators
1: y*e[1]
2: x*e[1] + y*e[2]
3: z*e[2]julia> R, (x, y, z) = polynomial_ring(QQ, [:x, :y, :z]);
julia> F = free_module(R, 1);
julia> A = R[x; y]
[x]
[y]
julia> B = R[x^2; y^3; z^4]
[x^2]
[y^3]
[z^4]
julia> M = subquotient(F, A, B)
Subquotient of submodule with 2 generators
1: x*e[1]
2: y*e[1]
by submodule with 3 generators
1: x^2*e[1]
2: y^3*e[1]
3: z^4*e[1]
julia> N = M;
julia> V = [y^2*N[1], x*N[2]]
2-element Vector{SubquoModuleElem{QQMPolyRingElem}}:
x*y^2*e[1]
x*y*e[1]
julia> a = hom(M, N, V);
julia> cokernel(a)
Subquotient of submodule with 2 generators
1: x*e[1]
2: y*e[1]
by submodule with 5 generators
1: x^2*e[1]
2: y^3*e[1]
3: z^4*e[1]
4: x*y^2*e[1]
5: x*y*e[1]julia> Rg, (x, y, z) = graded_polynomial_ring(QQ, [:x, :y, :z]);
julia> F = graded_free_module(Rg, 3);
julia> G = graded_free_module(Rg, 2);
julia> W = Rg[y 0; x y; 0 z]
[y 0]
[x y]
[0 z]
julia> a = hom(F, G, W)
Graded module homomorphism of degree [1]
from F
to G
defined by
e[1] -> y*e[1]
e[2] -> x*e[1] + y*e[2]
e[3] -> z*e[2]
julia> M = cokernel(a)
Graded subquotient of graded submodule of G with 2 generators
1: e[1]
2: e[2]
by graded submodule of G with 3 generators
1: y*e[1]
2: x*e[1] + y*e[2]
3: z*e[2]
cokernel(F::FreeMod{R}, A::MatElem{R}) where RReturn the cokernel of A as an object of type SubquoModule with ambient free module F.
Examples
julia> R, (x,y,z) = polynomial_ring(QQ, [:x, :y, :z]);
julia> F = free_module(R, 2)
Free module of rank 2 over R
julia> A = R[x y; 2*x^2 3*y^2]
[ x y]
[2*x^2 3*y^2]
julia> M = cokernel(F, A)
Subquotient of submodule with 2 generators
1: e[1]
2: e[2]
by submodule with 2 generators
1: x*e[1] + y*e[2]
2: 2*x^2*e[1] + 3*y^2*e[2]
julia> ambient_free_module(M) === F
true
julia> Rg, (x, y, z) = graded_polynomial_ring(QQ, [:x, :y, :z]);
julia> F = graded_free_module(Rg, [8,8])
Graded free module Rg^2([-8]) of rank 2 over Rg
julia> A = Rg[x y; 2*x^2 3*y^2]
[ x y]
[2*x^2 3*y^2]
julia> M = cokernel(F, A)
Graded subquotient of graded submodule of F with 2 generators
1: e[1]
2: e[2]
by graded submodule of F with 2 generators
1: x*e[1] + y*e[2]
2: 2*x^2*e[1] + 3*y^2*e[2]
julia> ambient_free_module(M) === F
true
julia> degrees_of_generators(M)
2-element Vector{FinGenAbGroupElem}:
[8]
[8]Group isomorphisms
For all functions that return group isomorphisms, we have the following rule about the direction of the result.
If two groups are given as inputs then the domain of the returned isomorphism is the first given group and the codomain is the second.
If one group is given then the domain of the result is this group, and the codomain is some new group constructed by the function.
is_isomorphic — Method
is_isomorphic(G::Group, H::Group)Return true if G and H are isomorphic groups, and false otherwise.
Examples
julia> is_isomorphic(symmetric_group(3), dihedral_group(6))
trueis_isomorphic_with_map — Method
is_isomorphic_with_map(G::Group, H::Group)Return (true,f) if G and H are isomorphic groups, where f is a group isomorphism. Otherwise, return (false,f), where f is the trivial homomorphism.
Examples
julia> is_isomorphic_with_map(symmetric_group(3), dihedral_group(6))
(true, Hom: Sym(3) -> pc group)isomorphism — Method
isomorphism(G::Group, H::Group)Return a group isomorphism between G and H if they are isomorphic groups. Otherwise throw an exception.
Examples
julia> isomorphism(symmetric_group(3), dihedral_group(6))
Group homomorphism
from symmetric group of degree 3
to pc group of order 6isomorphic_subgroups — Method
isomorphic_subgroups(H::Group, G::Group)Return a vector of injective group homomorphism from H to G, where the images are representatives of those conjugacy classes of subgroups of G that are isomorphic with H.
Examples
julia> isomorphic_subgroups(alternating_group(5), alternating_group(6))
2-element Vector{GAPGroupHomomorphism{PermGroup, PermGroup}}:
Hom: Alt(5) -> Alt(6)
Hom: Alt(5) -> Alt(6)
julia> isomorphic_subgroups(symmetric_group(4), alternating_group(5))
GAPGroupHomomorphism{PermGroup, PermGroup}[]isomorphism — Method
isomorphism(::Type{T}, G::Group; on_gens=false) where T <: GroupReturn an isomorphism from G to a group H of type T. An exception is thrown if no such isomorphism exists.
If on_gens is true then gens(G) is guaranteed to correspond to gens(H); an exception is thrown if this is not possible.
Isomorphisms are usually cached in G, subsequent calls of isomorphism with the same T (and the same value of on_gens) yield identical results.
If only the image of such an isomorphism is needed, use T(G); but this will assume on_gens=false.
isomorphism — Method
isomorphism(::Type{FinGenAbGroup}, G::GAPGroup)Return a map from G to an isomorphic (additive) group of type FinGenAbGroup. An exception is thrown if G is not abelian or not finite.
Technicalities
GAPGroupHomomorphism — Type
GAPGroupHomomorphism{S<:GAPGroup, T<:GAPGroup}An object of the type GAPGroupHomomorphism stores a homomorphism object as its GapObj value, and delegates all computations to it.
GAPGroupEmbedding — Type
GAPGroupEmbedding{S<:GAPGroup, T<:GAPGroup}An object emb of the type GAPGroupEmbedding knows that the corresponding map on the GAP side is the identity map on the GAP object corresponding to domain(emb).
A corresponding homomorphism GapObj(emb) on the GAP side is created only on demand, in many situations this is not needed.
Many natural embeddings between GapGroup objects are realized as GAPGroupEmbedding objects.