Permutations (Perms)

PermGroups.PermsModule

This module implements permutations and associated functions. It depends only on the package Combinat.

We follow the design of permutations in the GAP language. Perms are permutations of the set 1:n, represented internally as a vector of n integers holding the images of 1:n. The integer n is called the degree of the permutation. In this module, as in GAP (and contrary to the philosophy of Magma or the package Permutations.jl), two permutations of different degrees can be multiplied (the result has the larger degree). Two permutations are equal if and only if they move the same points in the same way, so two permutations of different degree can be equal; the degree is thus an implementation detail so usually it should not be used. One should rather use the function last_moved.

This design makes it easy to multiply permutations coming from different groups, like a group and one of its subgroups. It has a negligible overhead compared to the design where the degree is fixed.

The default constructor for a permutation uses the list of images of 1:n, like Perm([2,3,1,5,4,6]). Often it is more convenient to use cycle decompositions: the above permutation has cycle decomposition (1,2,3)(4,5) thus can be written Perm(1,2,3)*Perm(4,5) or perm"(1,2,3)(4,5)"; this last form can parse a permutation coming from GAP or the default printing at the REPL. The list of images of 1:n can be recovered from the permutation by the function perm; note that equal permutations with different degrees will have different perm. The default constructor tests the validity of the input by calling the julia function isperm. To have a faster constructor which does not test the input, use the keyword argument check=false.

The complete type of a permutation is Perm{T} where T<:Integer, so that Vector{T} is the type of the vector which holds the image of 1:n. This can be used to save space or time. For instance Perm{UInt8}(1,2,3) can be used for Weyl groups of rank≤8 since they permute at most 240 roots. If T is not specified we take it to be Int16 since this is a good compromise between speed, compactness and possible size of n. One can mix permutations of different integer types; they are promoted to the wider one when multiplying.

Examples of operations with permutations

julia> a=Perm(1,2,3)
(1,2,3)

julia> perm(a)
3-element Vector{Int16}:
 2
 3
 1

julia> a==Perm(perm(a))
true

julia> b=Perm(1,2,3,4)
(1,2,3,4)

julia> a*b     # product
(1,3,2,4)

julia> inv(a)  # inverse
(1,3,2)

julia> a/b     # quotient  a*inv(b)
(3,4)

julia> a\b     # left quotient inv(a)*b
(1,4)

julia> a^b     # conjugation inv(b)*a*b
(2,3,4)

julia> b^2     # square
(1,3)(2,4)

julia> 1^a     # image by a of point 1
2

julia> one(a)  # trivial permutation
()

julia> sign(a) # signature of permutation
1

julia> order(a) # order (least trivial power) of permutation
3

julia> last_moved(a)
3

julia> first_moved(a)
1

julia> Perm{Int8}(a) # convert a to Perm{Int8}
Perm{Int8}: (1,2,3)

julia> Matrix(b)  # permutation matrix of b
4×4 Matrix{Bool}:
 0  1  0  0
 0  0  1  0
 0  0  0  1
 1  0  0  0
julia> randPerm(10) # random permutation of 1:10
(1,8,4,2,9,7,5,10,3,6)

Perms have methods copy, hash, ==, so they can be keys in hashes or elements of sets; two permutations are equal if they move the same points to the same images. They have methods cmp, isless (lexicographic order on moved points) so they can be sorted. Perms are scalars for broadcasting.

Other methods on permutations are cycles, cycletype, reflection_length, mappingPerm, restricted, support, sortPerm, Perm_rowcol, preimage, randPerm.

No method is given in this module to enumerate Perms; you can use the method permutations from Combinat, iterate Combinat.Permutations or iterate the elements of symmetric_group from PermGroups.

source
PermGroups.Perms.PermType

struct Perm{T<:Integer}

A Perm represents a permutation of the set 1:n and is implemented by a struct with one field, a Vector{T} holding the images of 1:n. When showing a Perm at the REPL, the cycle decomposition is displayed as well as the type if it is not Int16. The default constructor checks the input, unless the keyword argument check=false is given.

julia> Perms.Perm_(UInt8[1,3,2,4])
Perm{UInt8}: (2,3)
source
PermGroups.Perms.PermMethod

Perm{T}(x::Integer...)where T<:Integer

returns a cycle. For example Perm{Int8}(1,2,3) constructs the cycle (1,2,3) as a Perm{Int8}. If omitted {T} is taken to be {Int16}.

source
PermGroups.Perms.PermMethod

Perm{T}(x::Integer...)where T<:Integer

returns a cycle. For example Perm{Int8}(1,2,3) constructs the cycle (1,2,3) as a Perm{Int8}. If omitted {T} is taken to be {Int16}.

source

Perm{T}(m::AbstractMatrix) If m is a permutation matrix, returns the corresponding permutation of type T. If omitted, T is taken to be Int16.

julia> Perm([0 1 0;0 0 1;1 0 0])
(1,2,3)
source
PermGroups.Perms.PermMethod

Perm{T}(l::AbstractVector,l1::AbstractVector)

returns p, a Perm{T}, such that invpermute(l1,p)==l if such a p exists; returns nothing otherwise. If not given {T} is taken to be {Int16}. Needs the eltype of l and l1 to be sortable.

julia> Perm([0,2,4],[4,0,2])
(1,3,2)
source
PermGroups.Perms.PermMethod

Perm{T}(m::AbstractMatrix,m1::AbstractMatrix;dims=1)

returns p, a Perm{T}, which invpermutes the rows of m1 (the columns of m1 if dims=2, simultaneously the rows and columns if dims=(1,2)) to bring them to those of m, if such a p exists; returns nothing otherwise. If not given {T} is taken to be {Int16}. Needs the elements of m and m1 to be sortable.

julia> Perm([0 1 0;0 0 1;1 0 0],[1 0 0;0 1 0;0 0 1];dims=1)
(1,3,2)

julia> Perm([0 1 0;0 0 1;1 0 0],[1 0 0;0 1 0;0 0 1];dims=2)
(1,2,3)

julia> n=(1:30)'.*(1:30).%15;

julia> m=onmats(n,Perm(1,5,2,8,12,4,7)*Perm(3,9,11,6));

julia> Perm(m,n,dims=(1,2))
(1,5,2,8,12,4,7)(3,9,11,6)
source
PermGroups.Perms.@perm_strMacro

@perm"..."

makes a Perm{Int16} from a string; allows GAP-style perm"(1,2)(5,6,7)(4,9)". If the cycle decomposition is preceded by "Perm{T}:" the constructed permutation is of type T.

perm"Perm{UInt8}:(1,2)(3,4)"
Perm{UInt8}: (1,2)(3,4)
source
PermGroups.Perms.permFunction

perm(p::Perm) returns the data field of a Perm.

julia> perm(Perm(2,3;degree=4))
4-element Vector{Int16}:
 1
 3
 2
 4
source
PermGroups.Perms.preimageFunction

preimage(i::Integer,p::Perm) or i/p

the preimage of i by p (same as image of i by inv(p) but does not need computing the inverse)."

source
PermGroups.Perms.invpermuteFunction

invpermute(l::AbstractVector,p::Perm)

returns l invpermuted by p, a vector r of same length as l such that r[i^p]==l[i] for i in eachindex(l). This function corresponds to the GAP function Permuted, but we changed the name to fit the Julia conventions since invpermute(l,p)==invpermute!(copy(l),perm(p)).

julia> invpermute([5,4,6],Perm(1,2,3))
3-element Vector{Int64}:
 6
 5
 4
source

invpermute(m::AbstractMatrix, p1::Perm,p2::Perm)

invpermutes the rows of m by p1 and the columns of m by p2.

julia> m=reshape(1:9,3,3)
3×3 reshape(::UnitRange{Int64}, 3, 3) with eltype Int64:
 1  4  7
 2  5  8
 3  6  9

julia> invpermute(m,Perm(1,2),Perm(2,3))
3×3 Matrix{Int64}:
 2  8  5
 1  7  4
 3  9  6
source

invpermute(m::AbstractMatrix,p::Perm;dims=1)

invpermutes by p the rows, columns or both of the matrix m depending on the value of dims.

julia> m=reshape(1:9,3,3)
3×3 reshape(::UnitRange{Int64}, 3, 3) with eltype Int64:
 1  4  7
 2  5  8
 3  6  9

julia> p=Perm(1,2,3)
(1,2,3)

julia> invpermute(m,p)
3×3 Matrix{Int64}:
 3  6  9
 1  4  7
 2  5  8

julia> invpermute(m,p;dims=2)
3×3 Matrix{Int64}:
 7  1  4
 8  2  5
 9  3  6

julia> invpermute(m,p;dims=(1,2))
3×3 Matrix{Int64}:
 9  3  6
 7  1  4
 8  2  5
source
PermGroups.Perms.orbitsMethod

orbits(a::Perm,d::AbstractVector{<:Integer};trivial=true)

returns the orbits of a on domain d, which should be a union of orbits of a. If trivial=false, does not return the orbits of length 1.

Example

julia> orbits(Perm(1,2)*Perm(4,5),1:5)
3-element Vector{Vector{Int64}}:
 [1, 2]
 [3]
 [4, 5]
source
PermGroups.Perms.cyclesMethod

cycles(a::Perm) returns the cycles of a

Example

julia> cycles(Perm(1,2)*Perm(4,5))
2-element Vector{Vector{Int16}}:
 [1, 2]
 [4, 5]
source
PermGroups.Perms.cycletypeMethod

cycletype(a::Perm,domain::AbstractVector{<:Integer};trivial=true)

domain should be a union of orbits of a. Returns the partition of length(domain) associated to the conjugacy class of a in the symmetric group of domain, with ones removed if trivial=false (in which case the partition does not depend on domain but just on support(a))

cycletype(a::Perm)

returns cycletype(a,1:last_moved(a);trivial=false)

Example

julia> cycletype(Perm(1,2)*Perm(4,5))
2-element Vector{Int64}:
 2
 2

julia> cycletype(Perm(1,2)*Perm(4,5),1:5)
3-element Vector{Int64}:
 2
 2
 1

julia> cycletype(Perm(1,2)*Perm(4,5),1:6)
4-element Vector{Int64}:
 2
 2
 1
 1
source
Base.signFunction

sign(p::Perm) is the signature of the permutation p

source
Base.MatrixMethod

Matrix(p::Perm,n=last_moved(p)) the permutation matrix for p operating on n points.

julia> Matrix(Perm(2,3,4),5)
5×5 Matrix{Bool}:
 1  0  0  0  0
 0  0  1  0  0
 0  0  0  1  0
 0  1  0  0  0
 0  0  0  0  1
source
PermGroups.Perms.restrictedMethod

restricted(p::Perm,domain::AbstractVector{<:Integer})

domain should be a union of orbits of p; returns p restricted to domain

julia> restricted(Perm(1,2)*Perm(3,4),3:4)
(3,4)
source
PermGroups.Perms.reflection_lengthMethod

reflection_length(p::Perm) or reflength

gives the "reflection length" of p (when the symmetric group on n points to which p belongs is interpreted as a reflection group on a space of dimension n), that is, the minimum number of transpositions of which p is the product.

source
PermGroups.Perms.mappingPermFunction

mappingPerm([::Type{T},]a::AbstractVector{<:Integer})

given a list of positive integers without repetition a, this function finds a Perm{T} p such that sort(a).^p==a. This can be used to translate between arrangements and Perms. If omitted T is taken to be Int16.

julia> p=mappingPerm([6,7,5])
(5,6,7)

julia> (5:7).^p
3-element Vector{Int64}:
 6
 7
 5
source

mappingPerm([::Type{T},]a,b)

given two lists of positive integers without repetition a and b, this function finds a Perm{T} p such that a.^p==b. If omitted T is taken to be Int16.

julia> mappingPerm([1,2,5,3],[2,3,4,6])
(1,2,3,6,5,4)
source
PermGroups.Perms.Perm_rowcolFunction

Perm_rowcol(m1::AbstractMatrix, m2::AbstractMatrix)

whether m1 can be obtained from m2 by row/col permutations.

m1 and m2 should be rectangular matrices of the same size. The function returns a Tuple of permutations (p1,p2) such that invpermute(m2,p1,p2)==m1 if such permutations exist, nothing otherwise. The eltype of m1 and m2 must be sortable.

julia> a=[1 1 1 -1 -1; 2 0 -2 0 0; 1 -1 1 -1 1; 1 1 1 1 1; 1 -1 1 1 -1]
5×5 Matrix{Int64}:
 1   1   1  -1  -1
 2   0  -2   0   0
 1  -1   1  -1   1
 1   1   1   1   1
 1  -1   1   1  -1

julia> b=[1 -1 -1 1 1; 1 1 -1 -1 1; 1 -1 1 -1 1; 2 0 0 0 -2; 1 1 1 1 1]
5×5 Matrix{Int64}:
 1  -1  -1   1   1
 1   1  -1  -1   1
 1  -1   1  -1   1
 2   0   0   0  -2
 1   1   1   1   1

julia> p1,p2=Perm_rowcol(a,b)
((1,3,5,4,2), (3,4,5))

julia> invpermute(b,p1,p2)==a
true
source