Polycyclic groups
Introduction
A polycyclic group is a group $G$ which has a subnormal series $G = G_1 > G_2 > \cdots > G_n > G_{n+1} = \{ 1 \}$ such that the factor groups $G_i/G_{i+1}$ are cyclic.
Polycyclic groups are solvable, and every finite solvable group is polycyclic.
Each polycyclic group has a finite presentation with the following structure: Choose elements $g_i \in G_i \setminus G_{i+1}$, for $1 \leq i \leq n$, such that $G_i = \langle G_{i+1}, g_i \rangle$ holds, and let $r_i$ be the index of $G_{i+1}$ in $G_i$ (a positive integer or infinity), the relative order of $g_i$ w.r.t. the given subnormal series. Then each element of $G$ has a unique expression of the form $g_1^{e_1} g_2^{e_2} \cdots g_n^{e_n}$ where the exponent $e_i$ is in the set $\{ 0, 1, \ldots, r_i-1 \}$ if $r_i$ is finite, and $e_i$ is an integer otherwise; this expression is called the normal form of the group element.
The group $G$ has a presentation with generators $g_1, g_2, \ldots, g_n$ and defining relations of the following form, where we define $I$ as the set of indices $i$ for which $r_i$ is a positive integer.
\[ \begin{array}{lcll} g_i^{r_i} & = & g_{i+1}^{a(i,i,i+1)} \cdots g_n^{a(i,i,n)}, & 1 \leq i \leq n, i \in I \\ g_i^{-1} g_j g_i & = & g_{i+1}^{a(i,j,i+1)} \cdots g_n^{a(i,j,n)}, & 1 \leq i < j \leq n. \end{array}\]
For infinite groups, we need additionally
\[ \begin{array}{lcll} g_i^{-1} g_j^{-1} g_i & = & g_{i+1}^{b(i,j,i+1)} \cdots g_n^{b(i,j,n)}, & 1 \leq i < j \leq n, j \not\in I \\ g_i g_j g_i^{-1} & = & g_{i+1}^{c(i,j,i+1)} \cdots g_n^{c(i,j,n)}, & 1 \leq i < j \leq n, i \not\in I \\ g_i g_j^{-1} g_i^{-1} & = & g_{i+1}^{d(i,j,i+1)} \cdots g_n^{d(i,j,n)}, & 1 \leq i < j \leq n, i, j, \not\in I. \end{array}\]
Here we assume that the right hand sides are words in normal form.
This presentation describes a confluent rewriting system, thus it admits the computation of the normal form for each group element. Inverses and products of elements given by their normal forms can be efficiently written in normal form.
Groups which are given by a polycyclic presentation are called polycyclicly presented groups. The rest of this section is about these groups.
Polycyclicly presented groups in Oscar have the type PcGroup
, their elements have the type PcGroupElem
. Analogous to the situation with finitely presented groups and their subgroups, there are the types SubPcGroup
for subgroups and SubPcGroupElem
for their elements.
Basic Creation
One can write down a polycyclic presentation by hand, using a so-called collector, and then creating a group with this presentation.
julia> c = collector(2, Int);
julia> set_relative_orders!(c, [2, 3])
julia> set_conjugate!(c, 2, 1, [2 => 2])
julia> gg = pc_group(c)
Pc group of order 6
julia> describe(gg)
"S3"
Alternatively, one can take a polycyclic group, and let Oscar compute a pc presentation for it.
julia> g = symmetric_group(4)
Sym(4)
julia> iso = isomorphism(PcGroup, g);
julia> h = codomain(iso)
Pc group of order 24
For certain series of groups, one can create the members as pc groups.
julia> dihedral_group(8)
Pc group of order 8
And the groups from the small groups library are represented by pc groups whenever they are solvable.
julia> small_group(24, 12)
Pc group of order 24
Functions for (subgroups of) pc groups and their elements
relators
— Methodrelators(G::PcGroup)
Return a vector of elements in a free group of rank ngens(G)
that describes the defining relators of the underlying polycyclic presentation of G
.
Examples
julia> g = dihedral_group(8)
Pc group of order 8
julia> relators(g)
6-element Vector{FPGroupElem}:
g1^2
g2^-1*g1^-1*g2*g1*g3^-1
g3^-1*g1^-1*g3*g1
g2^2*g3^-1
g3^-1*g2^-1*g3*g2
g3^2
map_word
— Methodmap_word(g::Union{PcGroupElem, SubPcGroupElem}, genimgs::Vector; genimgs_inv::Vector = Vector(undef, length(genimgs)), init = nothing)
If init
is nothing
, return the product $R_1 R_2 \cdots R_n$ that is described by g
. This is a product of the form $g_{i_1}^{e_1} g_{i_2}^{e_2} \cdots g_{i_n}^{e_n}$ where $g_i$ is the $i$-th entry in the defining polycyclic generating sequence of full_group(parent(g))
and the $e_i$ are nonzero integers, and $R_j =$ genimgs[
$i_j$]
$^{e_j}$.
If init
is different from nothing
, return $x g_{i_1}^{e_1} g_{i_2}^{e_2} \cdots g_{i_n}^{e_n}$ where $x =$ init
.
See also: map_word(::Union{FPGroupElem, SubFPGroupElem}, ::Vector)
, `map_word(::WeylGroupElem, ::Vector).
Examples
julia> G = dihedral_group(10)
Pc group of order 10
julia> x, y = gens(G); g = x * y^4
f1*f2^4
julia> map_word(g, gens(free_group(:x, :y)))
x*y^4
julia> map_word(g, [3, 2], init=5)
240
The function full_group(G::T) where T <: Union{SubFPGroup, SubPcGroup}
for finitely presented groups is applicable to polycyclicly presented groups as well.
Series of polycyclic groups
The following functions can be used to create polycyclicly presented groups from certain series of groups.
(In fact, one can request also other types for the results, but PcGroup
is the default type in all cases except abelian_group
.)
abelian_group
— Methodabelian_group(::Type{T} = PcGroup, v::Vector{S}) where T <: Group where S <: IntegerUnion
Return the direct product of cyclic groups of the orders v[1]
, v[2]
, $\ldots$, v[n]
, as an instance of T
. Here, T
must be one of PermGroup
, FPGroup
, SubFPGroup
, PcGroup
, or SubPcGroup
.
The gens
value of the returned group corresponds to v
, that is, the number of generators is equal to length(v)
and the order of the i
-th generator is v[i]
.
The type need to be specified in the input of the function abelian_group
, otherwise a group of type FinGenAbGroup
is returned, which is not a GAP group type. In future versions of Oscar, this may change.
elementary_abelian_group
— Functionelementary_abelian_group(::Type{T} = PcGroup, n::S) where T <: Group where S <: IntegerUnion
Return the elementary abelian group group of order n
, as an instance of T
. Here, T
must be one of PermGroup
, FPGroup
, SubFPGroup
, PcGroup
, SubPcGroup
, or FinGenAbGroup
, and n
must be a prime power or 1.
The gens
vector of the result has minimal length.
Examples
julia> g = elementary_abelian_group(27)
Pc group of order 27
julia> g = elementary_abelian_group(PermGroup, 27)
Permutation group of degree 9 and order 27
cyclic_group
— Functioncyclic_group(::Type{T} = PcGroup, n::IntegerUnion)
cyclic_group(::Type{T} = PcGroup, n::PosInf)
Return the cyclic group of order n
, as an instance of type T
.
Examples
julia> G = cyclic_group(5)
Pc group of order 5
julia> G = cyclic_group(PermGroup, 5)
Permutation group of degree 5 and order 5
julia> G = cyclic_group(PosInf())
Pc group of infinite order
dihedral_group
— Functiondihedral_group(::Type{T} = PcGroup, n::Union{IntegerUnion,PosInf})
Return the dihedral group of order n
, as an instance of T
, where T
is in {PcGroup
, SubPcGroup
, PermGroup
, FPGroup
, SubFPGroup
}.
There are two competing conventions for interpreting the argument n
: In the one we use, the returned group has order n
, and thus n
must always be even. In the other, n
indicates that the group describes the symmetry of an n
-gon, and thus the group has order 2n
.
Examples
julia> dihedral_group(6)
Pc group of order 6
julia> dihedral_group(PermGroup, 6)
Permutation group of degree 3
julia> dihedral_group(PosInf())
Pc group of infinite order
julia> dihedral_group(7)
ERROR: ArgumentError: n must be a positive even integer or infinity
quaternion_group
— Functionquaternion_group(::Type{T} = PcGroup, n::IntegerUnion)
Return the (generalized) quaternion group of order n
, as an instance of T
, where n
is a power of 2 and T
is in {PcGroup
, SubPcGroup
, PermGroup
,FPGroup
, SubFPGroup
}.
Examples
julia> g = quaternion_group(8)
Pc group of order 8
julia> quaternion_group(PermGroup, 8)
Permutation group of degree 8
julia> g = quaternion_group(FPGroup, 8)
Finitely presented group of order 8
julia> relators(g)
3-element Vector{FPGroupElem}:
r^2*s^-2
s^4
r^-1*s*r*s
Collectors for polycyclicly presented groups
The following functions can be used to enter polycyclic presentations by hand, or to create new such presentations from given ones.
collector
— Methodcollector(n::Int, ::Type{T} = ZZRingElem) where T <: IntegerUnion
Return an empty collector object for a pc group with n
generators and exponents of type T
. It describes a free abelian group of rank n
.
Examples
julia> G = pc_group(collector(2))
Pc group of infinite order
julia> is_abelian(G)
true
set_relative_order!
— Methodset_relative_order!(c::Collector{T}, i::Int, relord::T) where T <: IntegerUnion
Set the relative order of the i
-th generator of c
to relord
, which must be either 0
(meaning infinite order) or a positive integer.
Examples
julia> c = collector(2, Int);
julia> set_relative_order!(c, 1, 2)
get_relative_order
— Methodget_relative_order(c::Collector{T}, i::Int) where T <: IntegerUnion
Get the relative order of the i
-th generator of c
.
Examples
julia> c = collector(2, Int);
julia> get_relative_order(c, 1)
0
julia> set_relative_order!(c, 1, 2)
julia> get_relative_order(c, 1)
2
set_relative_orders!
— Methodset_relative_orders!(c::Collector{T}, relords::Vector{T})
Set all relative orders of the generators of c
, where the length of relords
must be equal to the number of generators of c
, and relords[i]
denotes the relative order of the i
-th generator. which must be either 0
(meaning infinite order) or a positive integer.
Examples
julia> c = collector(2);
julia> set_relative_orders!(c, ZZRingElem[2, 0])
get_relative_orders
— Methodget_relative_orders(c::Collector{T})
Get the Vector{T}
of all relative orders of the generators of c
.
Examples
julia> c = collector(2);
julia> get_relative_orders(c)
2-element Vector{ZZRingElem}:
0
0
julia> set_relative_orders!(c, ZZRingElem[2, 0])
julia> get_relative_orders(c)
2-element Vector{ZZRingElem}:
2
0
set_power!
— Methodset_power!(c::Collector{T}, i::Int, rhs::Vector{Pair{Int, T}}) where T <: IntegerUnion
Set the c.relorders[i]
-th power of the i
-th generator of c
to the group element described by rhs
.
Examples
julia> c = collector(2, Int);
julia> set_relative_order!(c, 1, 2)
julia> set_relative_order!(c, 2, 3)
julia> set_power!(c, 1, [2 => 1])
get_power
— Methodget_power(c::Collector{T}, i::Int) where T <: IntegerUnion
Get the Vector{Pair{Int, T}}
that describes the c.relorders[i]
-th power of the i
-th generator of c
.
Examples
julia> c = collector(2, Int);
julia> set_relative_order!(c, 1, 2)
julia> set_relative_order!(c, 2, 3)
julia> get_power(c, 1)
Pair{Int64, Int64}[]
julia> set_power!(c, 1, [2 => 1])
julia> get_power(c, 1)
1-element Vector{Pair{Int64, Int64}}:
2 => 1
set_conjugate!
— Methodset_conjugate!(c::Collector{T}, j::Int, i::Int, rhs::Vector{Pair{Int, T}}) where T <: IntegerUnion
Set the value of the conjugate of the j
-th generator of c
by the i
-th generator of c
, for i < j
, to the group element described by rhs
.
Examples
julia> c = collector(2, Int);
julia> set_relative_orders!(c, [2, 3])
julia> set_conjugate!(c, 2, 1, [2 => 2])
get_conjugate
— Methodget_conjugate(c::Collector{T}, j::Int, i::Int) where T <: IntegerUnion
Get the Vector{Pair{Int, T}}
that describes the conjugate of the j
-th generator of c
by the i
-th generator of c
, for i < j
.
Examples
julia> c = collector(2, Int);
julia> set_relative_orders!(c, [2, 3])
julia> get_conjugate(c, 2, 1)
1-element Vector{Pair{Int64, Int64}}:
2 => 1
julia> set_conjugate!(c, 2, 1, [2 => 2])
julia> get_conjugate(c, 2, 1)
1-element Vector{Pair{Int64, Int64}}:
2 => 2
set_commutator!
— Methodset_commutator!(c::Collector{T}, j::Int, i::Int, rhs::Vector{Pair{Int, T}}) where T <: IntegerUnion
Set the value of the commutator of the i
-th and the j
-th generator of c
, for i < j
, to the group element described by rhs
.
Examples
julia> c = collector(2, Int);
julia> set_relative_orders!(c, [2, 3])
julia> set_commutator!(c, 2, 1, [2 => 1])
pc_group
— Methodpc_group(c::GAP_Collector)
Create a PcGroup
object from c
.
Examples
julia> c = collector(2, Int);
julia> Oscar.set_relative_orders!(c, [2, 3])
julia> Oscar.set_conjugate!(c, 2, 1, [2 => 2])
julia> gg = pc_group(c)
Pc group of order 6
julia> describe(gg)
"S3"
collector
— Methodcollector([::Type{T} = ZZRingElem, ]G::PcGroup) where T <: IntegerUnion
Return a collector object for G
.
Examples
julia> g = small_group(12, 3)
Pc group of order 12
julia> c = collector(g);
julia> gc = pc_group(c)
Pc group of order 12
julia> is_isomorphic(g, gc)
true
Technicalities
PcGroup
— TypePcGroup
Polycyclic group, a group that is defined by a finite presentation of a special kind, a so-called polycyclic presentation. Contrary to arbitrary finitely presented groups (see Finitely presented groups), this presentation allows for efficient computations with the group elements.
For a group G
of type PcGroup
, the elements in gens(G)
satisfy the relators of the underlying presentation.
Functions that compute subgroups of G
return groups of type SubPcGroup
.
Examples
cyclic_group(n::Int)
: cyclic group of ordern
abelian_group(PcGroup, v::Vector{Int})
: direct product of cyclic groups of the ordersv[1]
,v[2]
, ...,v[length(v)]
PcGroupElem
— TypePcGroupElem
Element of a polycyclic group.
The generators of a polycyclic group are displayed as f1
, f2
, f3
, etc., and every element of a polycyclic group is displayed as product of the generators.
Examples
julia> G = abelian_group(PcGroup, [2, 3]);
julia> G[1], G[2]
(f1, f2)
julia> G[2]*G[1]
f1*f2
Note that this does not define Julia variables named f1
, f2
, etc.! To get the generators of the group G
, use gens(G)
; for convenience they can also be accessed as G[1]
, G[2]
, as shown in Section Elements of groups.
SubPcGroup
— TypeSubPcGroup
Subgroup of a polycyclic group, a group that is defined by generators that are elements of a group G
of type PcGroup
. The arithmetic operations with elements are thus performed using the polycyclic presentation of G
.
Operations for computing subgroups of a group of type PcGroup
or SubPcGroup
, such as derived_subgroup
and sylow_subgroup
, return groups of type SubPcGroup
.
SubPcGroupElem
— TypeSubPcGroupElem
Element of a subgroup of a polycyclic group.
The elements are displayed in the same way as the elements of full polycyclic groups, see PcGroupElem
.
Examples
julia> G = abelian_group(SubPcGroup, [4, 2]);
julia> G[1], G[2]
(f1, f3)
julia> G[2]*G[1]
f1*f3