Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macro for entering permutations in cycle notation #1307

Merged
merged 26 commits into from
May 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions src/Groups/perm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,120 @@ function cycle_structure(g::PermGroupElem)
# TODO: use SortedDict from DataStructures.jl ?
return Pair{Int,Int}[ i+1 => c[i] for i in 1:length(c) if GAP.Globals.ISB_LIST(c, i) ]
end


# The following code implements a new way to input permutations in Julia. For example
# it is possible to create a permutation as follow
# pi = Oscar.Permutations.@perm (1,2,3)(4,5)(6,7,8)
# > (1,2,3)(4,5)(6,7,8)
# For this we use macros to modify the syntax tree of (1,2,3)(4,5)(6,7,8) such that
# Julia can deal with the expression.


################################################################################
#
# _perm_helper
#

function _perm_helper(ex::Expr)

res = []

while ex isa Expr && ex.head == :call
pushfirst!(res, Expr(:vect, ex.args[2:end]...))
ex = ex.args[1]
end

if !(ex isa Expr) || ex.head != :tuple
error("Input is not a permutation.")
end

pushfirst!(res, Expr(:vect,ex.args...))

return res
end


################################################################################
#
# perm
#
@doc Markdown.doc"""
@perm(ex)

Macro to input a permutation as
danielrademacher marked this conversation as resolved.
Show resolved Hide resolved
`pi = @perm (1,2,3)(4,5)(6,7,8)` to obtain
the permutation `(1,2,3)(4,5)(6,7,8)`, that is, the output of
`cperm([1,2,3],[4,5],[6,7,8])`.
# Examples
```jldoctest
julia> @perm (1,2,3)(4,5)(6,7,8)
(1,2,3)(4,5)(6,7,8)
```
"""
macro perm(ex)
ex != :( () ) || return cperm()
ex isa Expr || error("Input is not a permutation expression")
res = _perm_helper(ex)
return esc(:(Oscar.cperm($(res...))))
end


################################################################################
#
# perm(n,gens)
#
@doc Markdown.doc"""
@perm(n,gens)
danielrademacher marked this conversation as resolved.
Show resolved Hide resolved

Macro to input a list of permutations which are generated as elements of
the `symmetric_group(n)` with the function `cperm`.
# Examples
```jldoctest
julia> gens = @perm 14 [
(1,10)
(2,11)
(3,12)
(4,13)
(5,14)
(6,8)
(7,9)
(1,2,3,4,5,6,7)(8,9,10,11,12,13,14)
(1,2)(10,11)
]
9-element Vector{PermGroupElem}:
(1,10)
(2,11)
(3,12)
(4,13)
(5,14)
(6,8)
(7,9)
(1,2,3,4,5,6,7)(8,9,10,11,12,13,14)
(1,2)(10,11)
danielrademacher marked this conversation as resolved.
Show resolved Hide resolved

julia> parent(gens[1])
Sym( [ 1 .. 14 ] )
```
"""
macro perm(n,gens)

ores = Vector{Expr}(undef,length(gens.args))
i = 1
for ex in gens.args
if ex == :( () )
ores[i] = esc(:(Oscar.cperm(symmetric_group($n))))
i = i + 1
else
ex isa Expr || error("Input is not a permutation expression")
res = _perm_helper(ex)

ores[i] = esc(:(Oscar.cperm(symmetric_group($n),$(res...))))
i = i + 1
end
end

return Expr(:vect,ores...)
end

export @perm
46 changes: 46 additions & 0 deletions test/Groups/Permutations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@testset "Examples.Permutations" begin
p = @perm (1,2)(3,4)(5,6)
@test p == cperm([1,2],[3,4],[5,6])
p = @perm (1,2)(3,4,5)(7,8,9)
@test p == cperm([1,2],[3,4,5],[7,8,9])

a=1;b=2;f=x->3*x + 2;
p = @perm (a,f(a),b)(a+1,b*2)
@test p == cperm([1,5,4,2])
p = @perm ()
@test p == cperm()

@test_throws ErrorException @perm (-1, 1)
@test_throws LoadError @eval @perm "bla"
@test_throws LoadError @eval @perm 1 + 1

gens = @perm 14 [
(1,10)
(2,11)
(3,12)
(4,13)
(5,14)
(6,8)
(7,9)
(1,2,3,4,5,6,7)(8,9,10,11,12,13,14)
(1,2)(10,11)
]
p = Vector{PermGroupElem}(undef,9)
p[1] = cperm(symmetric_group(14),[1,10])
p[2] = cperm(symmetric_group(14),[2,11])
p[3] = cperm(symmetric_group(14),[3,12])
p[4] = cperm(symmetric_group(14),[4,13])
p[5] = cperm(symmetric_group(14),[5,14])
p[6] = cperm(symmetric_group(14),[6,8])
p[7] = cperm(symmetric_group(14),[7,9])
p[8] = cperm(symmetric_group(14),[1,2,3,4,5,6,7],[8,9,10,11,12,13,14])
p[9] = cperm(symmetric_group(14),[1,2],[10,11])
@test gens == p

@test_throws ArgumentError @perm 10 [(1,11)]

G = sub(symmetric_group(14),gens)[1]
@test order(G) == 645120
end


1 change: 1 addition & 0 deletions test/Groups/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ include("MatrixDisplay.jl")
include("group_characters.jl")
include("FiniteFormOrthogonalGroup.jl")
include("GrpAb.jl")
include("Permutations.jl")