diff --git a/src/Groups/perm.jl b/src/Groups/perm.jl index d926711ab483..19a18207dd5e 100644 --- a/src/Groups/perm.jl +++ b/src/Groups/perm.jl @@ -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 +`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) + +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) + +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 diff --git a/test/Groups/Permutations.jl b/test/Groups/Permutations.jl new file mode 100644 index 000000000000..7e77d04ade13 --- /dev/null +++ b/test/Groups/Permutations.jl @@ -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 + + diff --git a/test/Groups/runtests.jl b/test/Groups/runtests.jl index 2ffb378a7e92..0bebf7e264ac 100644 --- a/test/Groups/runtests.jl +++ b/test/Groups/runtests.jl @@ -21,3 +21,4 @@ include("MatrixDisplay.jl") include("group_characters.jl") include("FiniteFormOrthogonalGroup.jl") include("GrpAb.jl") +include("Permutations.jl")