Permutations (Perms)
PermGroups.Perms — Module
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 0julia> 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.
PermGroups.Perms.Perm — Type
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)PermGroups.Perms.Perm — Method
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}.
PermGroups.Perms.Perm — Method
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}.
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)PermGroups.Perms.Perm — Method
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)PermGroups.Perms.Perm — Method
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)PermGroups.Perms.@perm_str — Macro
@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)PermGroups.Perms.last_moved — Method
last_moved(a::Perm) is the largest integer moved by a
last_moved(G::PermGroup) the largest moved point by any g∈ G
PermGroups.Perms.first_moved — Method
first_moved(a::Perm) is the smallest integer moved by a
first_moved(G::PermGroup) the smallest moved point by any g∈ G
PermGroups.Perms.perm — Function
perm(p::Perm) returns the data field of a Perm.
julia> perm(Perm(2,3;degree=4))
4-element Vector{Int16}:
1
3
2
4PermGroups.Perms.preimage — Function
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)."
PermGroups.Perms.invpermute — Function
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
4invpermute(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 6invpermute(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 5PermGroups.Perms.sortPerm — Function
for convenience: sortPerm(a)=Perm(sortperm(a))
PermGroups.Perms.randPerm — Function
randPerm([T,]n::Integer) a random permutation of 1:n of type T. If omitted T is taken to be Int16
PermGroups.Perms.orbit — Method
orbit(p::Perm,i::Integer) returns the orbit of p on i.
PermGroups.Perms.orbits — Method
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]PermGroups.Perms.order — Method
order(a::Perm) the order of a
PermGroups.Perms.cycles — Method
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]PermGroups.Perms.cycletype — Method
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
1PermGroups.Perms.support — Function
support(a::Perm) is the sorted list of all points moved by a
Base.Matrix — Method
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 1PermGroups.Perms.restricted — Method
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)PermGroups.Perms.reflection_length — Method
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.
PermGroups.Perms.mappingPerm — Function
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
5mappingPerm([::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)PermGroups.Perms.Perm_rowcol — Function
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