Skip to content

Commit

Permalink
next attempt to introduce group action functions
Browse files Browse the repository at this point in the history
- added a description what this is about
- define `^` as default action of permutations on (pos.) integers
- added natural action of permutations on multivariate polynomials
  by permuting indeterminates
- do not introduce `on_points`, `on_right`
  • Loading branch information
ThomasBreuer authored and fingolfin committed Oct 5, 2020
1 parent b95824a commit 476dd82
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 101 deletions.
4 changes: 4 additions & 0 deletions src/Groups/GAPGroups.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# further possible functions: similar, literal_pow, parent_type

import Base.:^

export GroupConjClass

export
Expand Down Expand Up @@ -392,6 +394,8 @@ function (x::PermGroupElem)(n::Int)
return GAP.Globals.OnPoints(n,x.X)
end

^(n::Int, x::PermGroupElem) = GAP.Globals.OnPoints(n,x.X)

################################################################################
#
# Conjugacy Classes
Expand Down
223 changes: 123 additions & 100 deletions src/Groups/action.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
"""
A *group action* of a group G on a set Ω (from the right) is defined by
a map μ: Ω × G → Ω that satisfies the compatibility conditions
μ(μ(x, g), h) = μ(x, g*h) and μ(x, one(G)) == x for all x ∈ Ω.
The maps μ are implemented as functions that take two arguments, an element
x of Ω and a group element g, and return the image of x under g.
In many cases, a natural action is given by the types of the elements in Ω
and in G.
For example permutation groups act on positive integers by just applying
the permutations.
In such situations, the function `^` can be used as action function,
and `^` is taken as the default whenever no other function is prescribed.
However, the action is not always determined by the types of the involved
objects.
For example, permutations can act on arrays of positive integers by
applying the permutations pointwise, or by permuting the entries;
matrices can act on vectors by multiplying the vector with the matrix,
or by multiplying the inverse of the matrix with the vector;
and of course one can construct new custom actions in situations where
default actions are already available.
Thus it is in general necessary to specify the action function explicitly.
The following ones are commonly used.
"""

#############################################################################
##
## common actions of group elements
Expand All @@ -6,90 +34,41 @@
## on `GAP.GapObj` objects to the corresponding GAP action,
## and to implement the action on native Julia objects case by case.

export on_points, on_right, on_tuples, on_sets, permuted
import Base.:^
import Base.:*

export on_tuples, on_sets, on_indeterminates, permuted

"""
on_points(pnt::GAP.GapObj, x::GAPGroupElem)
on_points(pnt::GAPGroupElem, x::GAPGroupElem)
on_points(pnt::Int, x::PermGroupElem)
Return the image of `pnt` under `x`.
If `pnt` is a `GAP.GapObj` then the action is given by `GAP.Globals.OnPoints`.
If `pnt` is a `GAPGroupElem` then the action is given by conjugation,
that is, the result is `x`^-1 * `pnt` * `x`.
If `pnt` is a positive integer and `x` is a permutation then the action
is given by the natural action that maps `pnt` to `x(pnt)`.
# Examples
```jldoctest
julia> g = symmetric_group(3); g[1]
(1,2,3)
julia> g[2]
(1,2)
julia> on_points(g[2], g[1])
(2,3)
julia> on_points(g[2].X, g[1])
GAP: (2,3)
julia> on_points(1, g[1])
2
We try to avoid introducing `on_points` and `on_right`.
Note that the GAP functions `OnPoints` and `OnRight` just delegate
to powering `^` and right multiplication `*`, respectively.
Thus we have to make sure that `^` and `*` are installed in all
relevant situations.
One such case is the action of `GAPGroupElem` objects on `GapObj`
objects, for example wrapped GAP matrices on GAP vectors:
```
"""
on_points(pnt::GAP.GapObj, x::GAPGroupElem) = GAP.Globals.OnPoints(pnt, x.X)

on_points(pnt::GAPGroupElem, x::GAPGroupElem) = inv(x) * pnt * x
julia> g = GL(2,3);
on_points(pnt::Int, x::PermGroupElem) = GAP.Globals.OnPoints(pnt, x.X)


"""
on_right(pnt::GAP.GapObj, x::GAPGroupElem)
on_right(pnt::GAPGroupElem, x::GAPGroupElem)
on_right(v::Vector{T}, x::MatrixGroupElem) where T
Return the image of the point `pnt` under `x`,
where the action is given by right multiplication with `x`.
# Examples
```jldoctest
julia> g = general_linear_group(2,3); mat = g[1]
julia> m = g[1]
[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]
julia> on_right(mat, mat)
[ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]
julia> r = mat.X[1]
julia> v = m.X[1]
GAP: [ Z(3), 0*Z(3) ]
julia> on_right( r, mat )
julia> v^m
GAP: [ Z(3)^0, 0*Z(3) ]
julia> v = Vector{GAP.FFE}(r)
2-element Array{FFE,1}:
GAP: Z(3)
GAP: 0*Z(3)
julia> on_right(v, mat)
2-element Array{GAP.FFE,1}:
GAP: Z(3)^0
GAP: 0*Z(3)
julia> v*m
GAP: [ Z(3)^0, 0*Z(3) ]
```
"""
on_right(pnt::GAP.GapObj, x::GAPGroupElem) = GAP.Globals.OnRight(pnt, x.X)

on_right(pnt::GAPGroupElem, x::GAPGroupElem) = pnt * x
^(pnt::GAP.GapObj, x::GAPGroupElem) = GAP.Globals.:^(pnt, x.X)

function on_right(v::Vector{T}, x::MatrixGroupElem) where T
gapv = GAP.julia_to_gap(v)
img = GAP.Globals.OnRight(gapv, x.X)
return Vector{T}(img)
end
*(pnt::GAP.GapObj, x::GAPGroupElem) = GAP.Globals.:*(pnt, x.X)


"""
Expand All @@ -98,38 +77,40 @@ end
on_tuples(tuple::T, x::GAPGroupElem) where T <: Tuple
Return the image of `tuple` under `x`,
where the action is given by applying [`on_points`](@ref) to the entries
of `tuple`.
where the action is given by applying `^` to the entries of `tuple`.
For `Vector` and `Tuple` objects,
one can also call `^` instead of `on_tuples`.
# Examples
```jldoctest
julia> g = symmetric_group(3); g[1]
(1,2,3)
julia> l = GAP.julia_to_gap([1, 2, 3, 4, 5])
GAP: [ 1, 2, 3, 4, 5 ]
julia> l = GAP.julia_to_gap([1, 2, 4])
GAP: [ 1, 2, 4 ]
julia> on_tuples(l, g[1])
GAP: [ 2, 3, 1, 4, 5 ]
GAP: [ 2, 3, 4 ]
julia> on_tuples([1, 2, 3, 4, 5], g[1])
5-element Array{Int64,1}:
julia> on_tuples([1, 2, 4], g[1])
3-element Array{Int64,1}:
2
3
1
4
5
julia> on_tuples((1, 2, 3, 4, 5), g[1])
(2, 3, 1, 4, 5)
julia> on_tuples((1, 2, 4), g[1])
(2, 3, 4)
```
"""
on_tuples(tuple::GAP.GapObj, x::GAPGroupElem) = GAP.Globals.OnTuples(tuple, x.X)

on_tuples(tuple::Vector{T}, x::GAPGroupElem) where T = T[on_points(pnt, x) for pnt in tuple]
on_tuples(tuple::Vector{T}, x::GAPGroupElem) where T = T[pnt^x for pnt in tuple]
^(tuple::Vector{T}, x::GAPGroupElem) where T = on_tuples(tuple, x)

on_tuples(tuple::T, x::GAPGroupElem) where T <: Tuple = T([on_points(pnt, x) for pnt in tuple])
on_tuples(tuple::T, x::GAPGroupElem) where T <: Tuple = T([pnt^x for pnt in tuple])
^(tuple::T, x::GAPGroupElem) where T <: Tuple = on_tuples(tuple, x)


"""
Expand All @@ -138,10 +119,12 @@ on_tuples(tuple::T, x::GAPGroupElem) where T <: Tuple = T([on_points(pnt, x) for
on_sets(set::T, x::GAPGroupElem) where T <: Union{Tuple, Set}
Return the image of `set` under `x`,
where the action is given by applying [`on_points`](@ref) to the entries
where the action is given by applying `^` to the entries
of `set`, and then turning the result into a sorted array/tuple or a set,
respectively.
For `Set` objects, one can also call `^` instead of `on_sets`.
# Examples
```jldoctest
julia> g = symmetric_group(3); g[1]
Expand Down Expand Up @@ -171,17 +154,19 @@ Set{Int64} with 2 elements:
on_sets(set::GAP.GapObj, x::GAPGroupElem) = GAP.Globals.OnSets(set, x.X)

function on_sets(set::Vector{T}, x::GAPGroupElem) where T
res = T[on_points(pnt, x) for pnt in set]
res = T[pnt^x for pnt in set]
sort!(res)
return res
end

function on_sets(set::T, x::GAPGroupElem) where T <: Union{Tuple, Set}
res = [on_points(pnt, x) for pnt in set]
res = [pnt^x for pnt in set]
sort!(res)
return T(res)
end

^(set::T, x::GAPGroupElem) where T <: Set = on_sets(set, x)


"""
permuted(pnt::GAP.GapObj, x::PermGroupElem)
Expand All @@ -196,42 +181,80 @@ where the action is given by permuting the entries of `pnt` with `x`.
julia> g = symmetric_group(3); g[1]
(1,2,3)
julia> a = ["a", "b", "c", "d", "e"]
5-element Array{String,1}:
julia> a = ["a", "b", "c"]
3-element Array{String,1}:
"a"
"b"
"c"
"d"
"e"
julia> l = GAP.julia_to_gap(a, recursive = true)
GAP: [ "a", "b", "c", "d", "e" ]
julia> permuted(l, g[1])
GAP: [ "c", "a", "b", "d", "e" ]
julia> permuted(a, g[1])
5-element Array{String,1}:
3-element Array{String,1}:
"c"
"a"
"b"
"d"
"e"
julia> permuted(("a", "b", "c", "d", "e"), g[1])
("c", "a", "b", "d", "e")
julia> permuted(("a", "b", "c"), g[1])
("c", "a", "b")
julia> l = GAP.julia_to_gap(a, recursive = true)
GAP: [ "a", "b", "c" ]
julia> permuted(l, g[1])
GAP: [ "c", "a", "b" ]
```
"""
permuted(pnt::GAP.GapObj, x::PermGroupElem) = GAP.Globals.Permuted(pnt, x.X)

function permuted(pnt::Vector{T}, x::PermGroupElem) where T
invx = inv(x)
return Vector{T}(pnt[[invx(i) for i in 1:length(pnt)]])
return pnt[[i^invx for i in 1:length(pnt)]]
end

function permuted(pnt::T, x::PermGroupElem) where T <: Tuple
invx = inv(x)
return T(pnt[[invx(i) for i in 1:length(pnt)]])
return T(pnt[[i^invx for i in 1:length(pnt)]])
end


"""
on_indeterminates(f::GAP.GapObj, p::PermGroupElem)
on_indeterminates(f::Nemo.MPolyElem{T}, p::PermGroupElem) where T
Returns the image of `f` under `p`, w.r.t. permuting the indeterminates
with `p`.
For `Nemo.MPolyElem{T}` objects, one can also call `^` instead of
`on_indeterminates`.
# Examples
```
julia> g = symmetric_group(3); p = g[1]
(1,2,3)
julia> R, x = PolynomialRing(QQ, ["x1", "x2", "x3"]);
julia> f = x[1]*x[2] + x[2]*x[3]
x1*x2 + x2*x3
julia> f^p
x1*x3 + x2*x3
julia> x = [GAP.Globals.X( GAP.Globals.Rationals, i ) for i in 1:3];
julia> f = x[1]*x[2] + x[2]*x[3]
GAP: x_1*x_2+x_2*x_3
julia> on_indeterminates(f, p)
GAP: x_1*x_3+x_2*x_3
```
"""
on_indeterminates(f::GAP.GapObj, p::PermGroupElem) = GAP.Globals.OnIndeterminates(f, p.X)

function on_indeterminates(f::Nemo.MPolyElem{T}, p::PermGroupElem) where T
pnt = gens(parent(f))
return evaluate(f, pnt[[i^p for i in 1:length(pnt)]])
end

^(f::Nemo.MPolyElem{T}, p::PermGroupElem) where T = on_indeterminates(f, p)
2 changes: 1 addition & 1 deletion src/Groups/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ end
Element of a group of permutation. It is displayed as product of disjoint cycles.
# Assumptions:
- for `x`,`y` in Sym(n), the product `xy` is read from left to right;
- for `x` in Sym(n) and `i` in {1,...,n}, `x(i)` return the image of `i` under the action of `x`.
- for `x` in Sym(n) and `i` in {1,...,n}, `i^x` and `x(i)` return the image of `i` under the action of `x`.
"""
const PermGroupElem = GAPGroupElem{PermGroup}

Expand Down

0 comments on commit 476dd82

Please sign in to comment.