# Finitely presented groups

`FPGroup`

— Type`FPGroup`

Finitely presented group. Such groups can be constructed a factors of free groups, see `free_group`

.

For a group `G`

of type `FPGroup`

, the elements in `gens(G)`

satisfy the relators of the underlying presentation.

Functions that compute subgroups of `G`

return groups of type `SubFPGroup`

.

`FPGroupElem`

— Type`FPGroupElem`

Element of a finitely presented group.

The generators of a finitely presented group are displayed as `f1`

, `f2`

, `f3`

, etc., and every element of a finitely presented group is displayed as product of the generators.

`SubFPGroup`

— Type`SubFPGroup`

Subgroup of a finitely presented group, a group that is defined by generators that are elements of a group `G`

of type `FPGroup`

.

Operations for computing subgroups of a group of type `FPGroup`

or `SubFPGroup`

, such as `derived_subgroup`

and `sylow_subgroup`

, return groups of type `SubFPGroup`

.

Note that functions such as `relators`

do not make sense for proper subgroups of a finitely presented group.

`SubFPGroupElem`

— Type`SubFPGroupElem`

Element of a subgroup of a finitely presented group.

The elements are displayed in the same way as the elements of full finitely presented groups, see `FPGroupElem`

.

`free_group`

— Function```
free_group(n::Int, s::VarName = :f; eltype::Symbol = :letter) -> FPGroup
free_group(L::VarName... ; eltype::Symbol = :letter) -> FPGroup
free_group(varnames_specifiers... ; eltype::Symbol = :letter) -> FPGroup
```

Return a free group.

The first form returns a free group of rank `n`

, where the generators are printed as `"$s1"`

, `"$s2"`

, ..., the default being `f1`

, `f2`

, ...

The second form returns a free group of rank `n`

, where `n`

is the length of `L`

, and `L`

consists of strings, symbols or characters giving the variable names.

In the final form, the argument list consists of a sequence of one or more of the following:

- A vector
`L`

of variable names. - A pair of the form
`A => B`

, where`A`

is a`VarName`

(so a string, symbol or character) and`B`

is a range or more generally an`AbstractVector`

. Then`length(B)`

generators are defined whose names derive from a combination of`A`

and the respective element of`B`

. For example`:x => 1:3`

defines three generators`x[1], x[2], x[3]`

. - A pair of the form
`A => C`

, where`A`

is again a`VarName`

, and`C`

is a tuple of ranges or v. For example`"a" => (1:2, 1:2)`

defines four generators`a[1, 1], a[2, 1], a[1, 2], a[2, 2]`

.

For the second and third type, optionally the `A`

part can contain the placeholder `#`

to modify where the indices are inserted. For example `"a#" => (1:2, 1:2)`

defines four generators `a11, a21, a12, a22`

.

Also, instead of a range, any vector can be used. For example `"#" => ([:x,:y], [:A, :B])`

defines four generators `xA, yA, xB, yB`

.

In all variants, if the optional keyword argument `eltype`

is given and has the value `:syllable`

then each element in the free group is internally represented by a vector of syllables, whereas a representation by a vector of integers is chosen in the default case of `eltype == :letter`

.

Julia variables named like the group generators are *not* created by this function. However, the macro `@free_group`

does just that.

**Examples**

```
julia> F = free_group(:a, :b)
Free group of rank 2
julia> w = F[1]^3 * F[2]^F[1] * F[-2]^2
a^2*b*a*b^-2
```

Here we show some of the different ways to create a free group.

```
julia> gens(free_group(2))
2-element Vector{FPGroupElem}:
f1
f2
julia> gens(free_group(2, :a))
2-element Vector{FPGroupElem}:
a1
a2
julia> gens(free_group(:u, :v))
2-element Vector{FPGroupElem}:
u
v
julia> gens(free_group([:a, :b], "x" => 1:2, 'y' => (1:2, 1:2)))
8-element Vector{FPGroupElem}:
a
b
x[1]
x[2]
y[1, 1]
y[2, 1]
y[1, 2]
y[2, 2]
```

`@free_group`

— Macro`@free_group(args...)`

Return the free group obtained from `free_group(args...)`

and introduce its generators as Julia variables into the current scope.

**Examples**

```
julia> F = @free_group(:a, :b)
Free group of rank 2
julia> a^2*b*a*b^-2
a^2*b*a*b^-2
```

Note that the `varname => vector`

syntax for specifying a vector or matrix or general array of variables behaves slightly differently compared to `free_group`

, as the following example demonstrates.

```
julia> U1 = free_group("x" => 1:3); gens(U1)
3-element Vector{FPGroupElem}:
x[1]
x[2]
x[3]
julia> U2 = @free_group("x" => 1:3); gens(U2)
3-element Vector{FPGroupElem}:
x1
x2
x3
julia> (x2^x1)^-1
x1^-1*x2^-1*x1
```

`full_group`

— Method```
full_group(G::T) where T <: Union{SubFPGroup, SubPcGroup}
full_group(G::T) where T <: Union{FPGroup, PcGroup}
```

Return `F, emb`

where `F`

is the full pc group of f.p. group of which `G`

is a subgroup, and `emb`

is an embedding of `G`

into `F`

.

**Examples**

```
julia> G = perfect_group(FPGroup, 60, 1);
julia> H = sylow_subgroup(G, 2)[1];
julia> full_group(H)[1] == G
true
julia> full_group(G)[1] == G
true
```

`relators`

— Method`relators(G::FPGroup)`

Return a vector of relators for the full finitely presented group `G`

, i.e., elements $[w_1, w_2, \ldots, w_n]$ in $F =$ `free_group(ngens(G))`

such that `G`

is isomorphic with $F/[w_1, w_2, \ldots, w_n]$.

**Examples**

```
julia> f = @free_group(:x, :y);
julia> q = quo(f, [x^2, y^2, comm(x, y)])[1]; relators(q)
3-element Vector{FPGroupElem}:
x^2
y^2
x^-1*y^-1*x*y
```

`length`

— Method`length(g::Union{FPGroupElem, SubFPGroupElem})`

Return the length of `g`

as a word in terms of the generators of its parent or of the full group of its parent if `g`

is an element of a free group, otherwise an exception is thrown.

**Examples**

```
julia> F = @free_group(:F1, :F2);
julia> length(F1*F2^-2)
3
julia> length(one(F))
0
julia> length(one(quo(F, [F1])[1]))
ERROR: ArgumentError: the element does not lie in a free group
```

`map_word`

— Method```
map_word(g::Union{FPGroupElem, SubFPGroupElem}, genimgs::Vector; genimgs_inv::Vector = Vector(undef, length(genimgs)), init = nothing)
map_word(v::Vector{Union{Int, Pair{Int, Int}}}, genimgs::Vector; genimgs_inv::Vector = Vector(undef, length(genimgs)), init = nothing)
```

Return the product $R_1 R_2 \cdots R_n$ that is described by `g`

or `v`

, respectively.

If `g`

is an element of a free group $G$, say, then the rank of $G$ must be equal to the length of `genimgs`

, `g`

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 generator of $G$ and the $e_i$ are nonzero integers, and $R_j =$ `imgs[`

$i_j$`]`

$^{e_j}$.

If `g`

is an element of (a subgroup of) a finitely presented group then the result is defined as `map_word`

applied to a representing element of the underlying free group of `full_group(parent(g))`

. In particular, `genimgs`

are interpreted as the images of the generators of this free group, not of `gens(parent(g))`

.

If the first argument is a vector `v`

of integers $k_i$ or pairs `k_i => e_i`

, respectively, then the absolute values of the $k_i$ must be at most the length of `genimgs`

, and $R_j =$ `imgs[`

$|k_i|$`]`

$^{\epsilon_i}$ where $\epsilon_i$ is the `sign`

of $k_i$ (times $e_i$).

If a vector `genimgs_inv`

is given then its assigned entries are expected to be the inverses of the corresponding entries in `genimgs`

, and the function will use (and set) these entries in order to avoid calling `inv`

(more than once) for entries of `genimgs`

.

If `init`

is different from `nothing`

then the product gets initialized with `init`

.

If `v`

has length zero then `init`

is returned if also `genimgs`

has length zero, otherwise `one(genimgs[1])`

is returned. Thus the intended value for the empty word must be specified as `init`

whenever it is possible that the elements in `genimgs`

do not support `one`

.

**Examples**

```
julia> F = @free_group(:F1, :F2);
julia> imgs = gens(symmetric_group(4))
2-element Vector{PermGroupElem}:
(1,2,3,4)
(1,2)
julia> map_word(F1^2, imgs)
(1,3)(2,4)
julia> map_word(F2, imgs)
(1,2)
julia> map_word(one(F), imgs)
()
julia> map_word(one(F), imgs, init = imgs[1])
(1,2,3,4)
julia> invs = Vector(undef, 2);
julia> map_word(F1^-2*F2, imgs, genimgs_inv = invs)
(1,3,2,4)
julia> invs
2-element Vector{Any}:
(1,4,3,2)
#undef
```