1
0
mirror of https://github.com/kalmarek/Groups.jl.git synced 2024-11-19 06:30:29 +01:00

Merge branch 'master' into enh/julia-v0.6

# Conflicts:
#	src/FPGroups.jl
This commit is contained in:
kalmarek 2017-09-13 11:17:42 +02:00
commit 36b87c12fa
10 changed files with 346 additions and 211 deletions

View File

@ -4,20 +4,31 @@ os:
- linux - linux
- osx - osx
julia: julia:
- release - 0.5
- 0.6
- nightly - nightly
notifications:
email: true
git:
depth: 99999999
matrix: matrix:
fast_finish: true fast_finish: true
allow_failures: allow_failures:
- julia: nightly - julia: nightly
notifications: ## uncomment and modify the following lines to manually install system packages
email: false #addons:
# uncomment the following lines to override the default test script # apt: # apt-get for linux
# packages:
# - gfortran
#before_script: # homebrew for mac
# - if [ $TRAVIS_OS_NAME = osx ]; then brew install gcc; fi
## uncomment the following lines to override the default test script
script: script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - julia -e 'Pkg.clone("https://github.com/Nemocas/Nemo.jl"); Pkg.build("Nemo")'
- julia -e 'Pkg.clone("https://github.com/scheinerman/Permutations.jl.git")'
- julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)' - julia -e 'Pkg.clone(pwd()); Pkg.build("Groups"); Pkg.test("Groups"; coverage=true)'
after_success: after_success:
# push coverage results to Coveralls # push coverage results to Coveralls
- julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' - julia -e 'cd(Pkg.dir("Groups")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'

View File

@ -1,2 +1,2 @@
# Groups # Groups
[![Build Status](https://travis-ci.org/abulak/Groups.jl.svg?branch=master)](https://travis-ci.org/abulak/Groups.jl) [![Build Status](https://travis-ci.org/kalmarek/Groups.jl.svg?branch=master)](https://travis-ci.org/kalmarek/Groups.jl)

View File

@ -9,21 +9,18 @@ export DirectProductGroup, DirectProductGroupElem
############################################################################### ###############################################################################
doc""" doc"""
DirectProductGroup(factors::Vector{Group}) <: Group DirectProductGroup(G::Group, n::Int) <: Group
Implements direct product of groups as vector factors. The group operation is Implements `n`-fold direct product of `G`. The group operation is
`*` distributed component-wise, with component-wise identity as neutral element. `*` distributed component-wise, with component-wise identity as neutral element.
""" """
type DirectProductGroup <: Group immutable DirectProductGroup{T<:Group} <: Group
factors::Vector{Group} group::T
operations::Vector{Function} n::Int
end end
type DirectProductGroupElem <: GroupElem immutable DirectProductGroupElem{T<:GroupElem} <: GroupElem
elts::Vector{GroupElem} elts::Vector{T}
parent::DirectProductGroup
DirectProductGroupElem{T<:GroupElem}(a::Vector{T}) = new(a)
end end
############################################################################### ###############################################################################
@ -32,11 +29,29 @@ end
# #
############################################################################### ###############################################################################
elem_type(G::DirectProductGroup) = DirectProductGroupElem elem_type{T<:Group}(G::DirectProductGroup{T}) =
DirectProductGroupElem{elem_type(G.group)}
parent_type(::Type{DirectProductGroupElem}) = DirectProductGroup parent_type{T<:GroupElem}(::Type{DirectProductGroupElem{T}}) =
DirectProductGroup{parent_type(T)}
parent(g::DirectProductGroupElem) = g.parent parent(g::DirectProductGroupElem) =
DirectProductGroup(parent(first(g.elts)), length(g.elts))
###############################################################################
#
# AbstractVector interface
#
###############################################################################
Base.size(g::DirectProductGroupElem) = size(g.elts)
Base.linearindexing(::Type{DirectProductGroupElem}) = Base.LinearFast()
Base.getindex(g::DirectProductGroupElem, i::Int) = g.elts[i]
function Base.setindex!{T<:GroupElem}(g::DirectProductGroupElem{T}, v::T, i::Int)
parent(v) == parent(first(g.elts)) || throw("$g is not an element of $i-th factor of $(parent(G))")
g.elts[i] = v
return g
end
############################################################################### ###############################################################################
# #
@ -44,29 +59,9 @@ parent(g::DirectProductGroupElem) = g.parent
# #
############################################################################### ###############################################################################
DirectProductGroup(G::Group, H::Group) = DirectProductGroup([G, H], Function[(*),(*)]) function ×(G::Group, H::Group)
G == H || throw("Direct products are defined only for the same groups")
DirectProductGroup(G::Group, H::Ring) = DirectProductGroup([G, H], Function[(*),(+)]) return DirectProductGroup(G,2)
DirectProductGroup(G::Ring, H::Group) = DirectProductGroup([G, H], Function[(+),(*)])
DirectProductGroup(G::Ring, H::Ring) = DirectProductGroup([G, H], Function[(+),(+)])
DirectProductGroup{T<:Ring}(X::Vector{T}) = DirectProductGroup(Group[X...], Function[(+) for _ in X])
×(G::Group, H::Group) = DirectProductGroup(G,H)
function DirectProductGroup{T<:Group, S<:Group}(G::Tuple{T, Function}, H::Tuple{S, Function})
return DirectProductGroup([G[1], H[1]], Function[G[2],H[2]])
end
function DirectProductGroup(groups::Vector)
for G in groups
typeof(G) <: Group || throw("$G is not a group!")
end
ops = Function[typeof(G) <: Ring ? (+) : (*) for G in groups]
return DirectProductGroup(groups, ops)
end end
############################################################################### ###############################################################################
@ -75,41 +70,26 @@ end
# #
############################################################################### ###############################################################################
(G::DirectProductGroup)() = G([H() for H in G.factors]; checked=false)
function (G::DirectProductGroup)(g::DirectProductGroupElem; checked=true)
if checked
return G(g.elts)
else
g.parent = G
return g
end
end
doc""" doc"""
(G::DirectProductGroup)(a::Vector; checked=true) (G::DirectProductGroup)(a::Vector, check::Bool=true)
> Constructs element of the direct product group `G` by coercing each element > Constructs element of the $n$-fold direct product group `G` by coercing each
> of vector `a` to the corresponding factor of `G`. If `checked` flag is set to > element of vector `a` to `G.group`. If `check` flag is set to `false` neither
> `false` no checks on the correctness are performed. > check on the correctness nor coercion is performed.
""" """
function (G::DirectProductGroup)(a::Vector; checked=true) function (G::DirectProductGroup)(a::Vector, check::Bool=true)
length(a) == length(G.factors) || throw("Cannot coerce $a to $G: they have if check
different number of factors") G.n == length(a) || throw("Can not coerce to DirectProductGroup: lengths differ")
if checked a = G.group.(a)
for (F,g) in zip(G.factors, a)
try
F(g)
catch
throw("Cannot coerce to $G: $g cannot be coerced to $F.")
end
end
end end
elt = DirectProductGroupElem([F(g) for (F,g) in zip(G.factors, a)]) return DirectProductGroupElem(a)
elt.parent = G
return elt
end end
(G::DirectProductGroup)() = DirectProductGroupElem([G.group() for _ in 1:G.n])
(G::DirectProductGroup)(g::DirectProductGroupElem) = G(g.elts)
(G::DirectProductGroup){T<:GroupElem, N}(a::Vararg{T, N}) = G([a...])
############################################################################### ###############################################################################
# #
# Basic manipulation # Basic manipulation
@ -122,20 +102,13 @@ function deepcopy_internal(g::DirectProductGroupElem, dict::ObjectIdDict)
end end
function hash(G::DirectProductGroup, h::UInt) function hash(G::DirectProductGroup, h::UInt)
return hash(G.factors, hash(G.operations, hash(DirectProductGroup,h))) return hash(G.group, hash(G.n, hash(DirectProductGroup,h)))
end end
function hash(g::DirectProductGroupElem, h::UInt) function hash(g::DirectProductGroupElem, h::UInt)
return hash(g.elts, hash(g.parent, hash(DirectProductGroupElem, h))) return hash(g.elts, hash(parent(g), hash(DirectProductGroupElem, h)))
end end
doc"""
eye(G::DirectProductGroup)
> Return the identity element for the given direct product of groups.
"""
eye(G::DirectProductGroup) = G()
############################################################################### ###############################################################################
# #
# String I/O # String I/O
@ -143,12 +116,11 @@ eye(G::DirectProductGroup) = G()
############################################################################### ###############################################################################
function show(io::IO, G::DirectProductGroup) function show(io::IO, G::DirectProductGroup)
println(io, "Direct product of groups") println(io, "$(G.n)-fold direct product of $(G.group)")
join(io, G.factors, ", ", " and ")
end end
function show(io::IO, g::DirectProductGroupElem) function show(io::IO, g::DirectProductGroupElem)
print(io, "("*join(g.elts,",")*")") print(io, "($(join(g.elts,",")))")
end end
############################################################################### ###############################################################################
@ -157,58 +129,62 @@ end
# #
############################################################################### ###############################################################################
doc"""
==(g::DirectProductGroup, h::DirectProductGroup)
> Checks if two direct product groups are the same.
"""
function (==)(G::DirectProductGroup, H::DirectProductGroup) function (==)(G::DirectProductGroup, H::DirectProductGroup)
G.factors == H.factors || return false G.group == H.group || return false
G.operations == H.operations || return false G.n == G.n || return false
return true return true
end end
doc""" doc"""
==(g::DirectProductGroupElem, h::DirectProductGroupElem) ==(g::DirectProductGroupElem, h::DirectProductGroupElem)
> Return `true` if the given elements of direct products are equal, otherwise return `false`. > Checks if two direct product group elements are the same.
""" """
function (==)(g::DirectProductGroupElem, h::DirectProductGroupElem) function (==)(g::DirectProductGroupElem, h::DirectProductGroupElem)
parent(g) == parent(h) || return false
g.elts == h.elts || return false g.elts == h.elts || return false
return true return true
end end
############################################################################### ###############################################################################
# #
# Binary operators # Group operations
# #
############################################################################### ###############################################################################
function direct_mult(g::DirectProductGroupElem, h::DirectProductGroupElem)
parent(g) == parent(h) || throw("Can't multiply elements from different groups: $g, $h")
G = parent(g)
return G([op(a,b) for (op,a,b) in zip(G.operations, g.elts, h.elts)])
end
doc""" doc"""
*(g::DirectProductGroupElem, h::DirectProductGroupElem) *(g::DirectProductGroupElem, h::DirectProductGroupElem)
> Return the direct-product group operation of elements, i.e. component-wise > Return the direct-product group operation of elements, i.e. component-wise
> operation as defined by `operations` field of the parent object. > operation as defined by `operations` field of the parent object.
""" """
(*)(g::DirectProductGroupElem, h::DirectProductGroupElem) = direct_mult(g,h) # TODO: dirty hack around `+/*` operations
function *{T<:GroupElem}(g::DirectProductGroupElem{T}, h::DirectProductGroupElem{T}, check::Bool=true)
if check
parent(g) == parent(h) || throw("Can not multiply elements of different groups!")
end
return DirectProductGroupElem([a*b for (a,b) in zip(g.elts,h.elts)])
end
############################################################################### function *{T<:RingElem}(g::DirectProductGroupElem{T}, h::DirectProductGroupElem{T}, check::Bool=true)
# if check
# Inversion parent(g) == parent(h) || throw("Can not multiply elements of different groups!")
# end
############################################################################### return DirectProductGroupElem(g.elts + h.elts)
end
doc""" doc"""
inv(g::DirectProductGroupElem) inv(g::DirectProductGroupElem)
> Return the inverse of the given element in the direct product group. > Return the inverse of the given element in the direct product group.
""" """
# TODO: dirty hack around `+` operation # TODO: dirty hack around `+/*` operation
function inv(g::DirectProductGroupElem) function inv{T<:GroupElem}(g::DirectProductGroupElem{T})
G = parent(g) return DirectProductGroupElem([inv(a) for a in g.elts])
return G([(op == (*) ? inv(elt): -elt) for (op,elt) in zip(G.operations, g.elts)]) end
function inv{T<:RingElem}(g::DirectProductGroupElem{T})
return DirectProductGroupElem(-g.elts)
end end
############################################################################### ###############################################################################
@ -219,15 +195,15 @@ end
doc""" doc"""
elements(G::DirectProductGroup) elements(G::DirectProductGroup)
> Returns `Task` that produces all elements of group `G` (provided that factors > Returns `generator` that produces all elements of group `G` (provided that
> implement the elements function). > `G.group` implements the `elements` method).
""" """
# TODO: can Base.product handle generators? # TODO: can Base.product handle generators?
# now it returns nothing's so we have to collect ellements... # now it returns nothing's so we have to collect ellements...
function elements(G::DirectProductGroup) function elements(G::DirectProductGroup)
cartesian_prod = Base.product([collect(elements(H)) for H in G.factors]...) elts = collect(elements(G.group))
return (G(collect(elt)) for elt in cartesian_prod) cartesian_prod = Base.product([elts for _ in 1:G.n]...)
return (DirectProductGroupElem([elt...]) for elt in cartesian_prod)
end end
doc""" doc"""
@ -235,4 +211,4 @@ doc"""
> Returns the order (number of elements) in the group. > Returns the order (number of elements) in the group.
""" """
order(G::DirectProductGroup) = prod([order(H) for H in G.factors]) order(G::DirectProductGroup) = order(G.group)^G.n

View File

@ -4,14 +4,14 @@
# #
############################################################################### ###############################################################################
@compat struct FPSymbol <: GSymbol struct FPSymbol <: GSymbol
str::String str::String
pow::Int pow::Int
end end
@compat FPGroupElem = GWord{FPSymbol} FPGroupElem = GWord{FPSymbol}
@compat mutable struct FPGroup <: AbstractFPGroup mutable struct FPGroup <: AbstractFPGroup
gens::Vector{FPSymbol} gens::Vector{FPSymbol}
rels::Dict{FPGroupElem, FPGroupElem} rels::Dict{FPGroupElem, FPGroupElem}

View File

@ -378,12 +378,12 @@ end
# #
############################################################################### ###############################################################################
function products{T<:GroupElem}(X::AbstractVector{T}, Y::AbstractVector{T}) function products{T<:GroupElem}(X::AbstractVector{T}, Y::AbstractVector{T}, op=*)
result = Vector{T}() result = Vector{T}()
seen = Set{T}() seen = Set{T}()
for x in X for x in X
for y in Y for y in Y
z = x*y z = op(x,y)
if !in(z, seen) if !in(z, seen)
push!(seen, z) push!(seen, z)
push!(result, z) push!(result, z)
@ -393,12 +393,13 @@ function products{T<:GroupElem}(X::AbstractVector{T}, Y::AbstractVector{T})
return result return result
end end
function generate_balls{T<:GroupElem}(S::Vector{T}, Id::T; radius=2) function generate_balls{T<:GroupElem}(S::Vector{T}, Id::T; radius=2, op=*)
sizes = Vector{Int}() sizes = Vector{Int}()
S = deepcopy(S)
S = unshift!(S, Id) S = unshift!(S, Id)
B = [Id] B = [Id]
for i in 1:radius for i in 1:radius
B = products(B, S); B = products(B, S, op);
push!(sizes, length(B)) push!(sizes, length(B))
end end
return B, sizes return B, sizes

View File

@ -7,35 +7,38 @@ export WreathProduct, WreathProductElem
############################################################################### ###############################################################################
doc""" doc"""
WreathProduct <: Group WreathProduct{T<:Group} <: Group
> Implements Wreath product of a group N by permutation (sub)group P < Sₖ, > Implements Wreath product of a group $N$ by permutation (sub)group $P < S_k$,
> usually written as $N \wr P$. > usually written as $N \wr P$.
> The multiplication inside wreath product is defined as > The multiplication inside wreath product is defined as
> (n, σ) * (m, τ) = (n*ψ(σ)(m), σ*τ), > $$(n, \sigma) * (m, \tau) = (n\psi(\sigma)(m), \sigma\tau),$$
> where ψ:P Aut(Nᵏ) is the permutation representation of Sₖ restricted to P. > where $\psi:P Aut(N^k)$ is the permutation representation of $S_k$
> restricted to $P$.
# Arguments: # Arguments:
* `::Group` : the single factor of group N * `::Group` : the single factor of group $N$
* `::PermutationGroup` : full PermutationGroup * `::PermGroup` : full `PermutationGroup`
""" """
immutable WreathProduct{T<:Group} <: Group
N::DirectProductGroup{T}
P::PermGroup
type WreathProduct <: Group function WreathProduct(G::Group, P::PermGroup)
N::DirectProductGroup N = DirectProductGroup(G, P.n)
P::PermutationGroup
function WreathProduct(G::Group, P::PermutationGroup)
N = DirectProductGroup(typeof(G)[G for _ in 1:P.n])
return new(N, P) return new(N, P)
end end
end end
type WreathProductElem <: GroupElem immutable WreathProductElem{T<:GroupElem} <: GroupElem
n::DirectProductGroupElem n::DirectProductGroupElem{T}
p::perm p::perm
parent::WreathProduct # parent::WreathProduct
function WreathProductElem(n::DirectProductGroupElem, p::perm) function WreathProductElem(n::DirectProductGroupElem, p::perm,
length(n.elts) == parent(p).n check::Bool=true)
if check
length(n.elts) == parent(p).n || throw("Can't form WreathProductElem: lengths differ")
end
return new(n, p) return new(n, p)
end end
end end
@ -46,11 +49,12 @@ end
# #
############################################################################### ###############################################################################
elem_type(::WreathProduct) = WreathProductElem elem_type{T<:Group}(::WreathProduct{T}) = WreathProductElem{elem_type(T)}
parent_type(::WreathProductElem) = WreathProduct parent_type{T<:GroupElem}(::Type{WreathProductElem{T}}) =
WreathProduct{parent_type(T)}
parent(g::WreathProductElem) = g.parent parent(g::WreathProductElem) = WreathProduct(parent(g.n[1]), parent(g.p))
############################################################################### ###############################################################################
# #
@ -58,7 +62,10 @@ parent(g::WreathProductElem) = g.parent
# #
############################################################################### ###############################################################################
# converts??? WreathProduct{T<:Group}(G::T, P::PermGroup) = WreathProduct{T}(G, P)
WreathProductElem{T<:GroupElem}(n::DirectProductGroupElem{T},
p::perm, check::Bool=true) = WreathProductElem{T}(n, p, check)
############################################################################### ###############################################################################
# #
@ -67,39 +74,31 @@ parent(g::WreathProductElem) = g.parent
############################################################################### ###############################################################################
function (G::WreathProduct)(g::WreathProductElem) function (G::WreathProduct)(g::WreathProductElem)
try n = try
G.N(g.n) G.N(g.n)
catch catch
throw("Can't coerce $(g.n) to $(G.N) factor of $G") throw("Can't coerce $(g.n) to $(G.N) factor of $G")
end end
try p = try
G.P(g.p) G.P(g.p)
catch catch
throw("Can't coerce $(g.p) to $(G.P) factor of $G") throw("Can't coerce $(g.p) to $(G.P) factor of $G")
end end
elt = WreathProductElem(G.N(g.n), G.P(g.p)) return WreathProductElem(n, p)
elt.parent = G
return elt
end end
doc""" doc"""
(G::WreathProduct)(n::DirectProductGroupElem, p::perm) (G::WreathProduct)(n::DirectProductGroupElem, p::perm)
> Creates an element of wreath product `G` by coercing `n` and `p` to `G.N` and > Creates an element of wreath product `G` by coercing `n` and `p` to `G.N` and
> `G.P`, respectively. > `G.P`, respectively.
""" """
function (G::WreathProduct)(n::DirectProductGroupElem, p::perm) (G::WreathProduct)(n::DirectProductGroupElem, p::perm) = WreathProductElem(n,p)
result = WreathProductElem(n,p)
result.parent = G
return result
end
(G::WreathProduct)() = G(G.N(), G.P()) (G::WreathProduct)() = WreathProductElem(G.N(), G.P(), false)
doc""" doc"""
(G::WreathProduct)(p::perm) (G::WreathProduct)(p::perm)
> Returns the image of permutation `p` in `G` via embedding `p -> (id,p)`. > Returns the image of permutation `p` in `G` via embedding `p -> (id,p)`.
""" """
(G::WreathProduct)(p::perm) = G(G.N(), p) (G::WreathProduct)(p::perm) = G(G.N(), p)
@ -107,7 +106,6 @@ doc"""
(G::WreathProduct)(n::DirectProductGroupElem) (G::WreathProduct)(n::DirectProductGroupElem)
> Returns the image of `n` in `G` via embedding `n -> (n,())`. This is the > Returns the image of `n` in `G` via embedding `n -> (n,())`. This is the
> embedding that makes sequence `1 -> N -> G -> P -> 1` exact. > embedding that makes sequence `1 -> N -> G -> P -> 1` exact.
""" """
(G::WreathProduct)(n::DirectProductGroupElem) = G(n, G.P()) (G::WreathProduct)(n::DirectProductGroupElem) = G(n, G.P())
@ -118,8 +116,7 @@ doc"""
############################################################################### ###############################################################################
function deepcopy_internal(g::WreathProductElem, dict::ObjectIdDict) function deepcopy_internal(g::WreathProductElem, dict::ObjectIdDict)
G = parent(g) return WreathProductElem(deepcopy(g.n), deepcopy(g.p), false)
return G(deepcopy(g.n), deepcopy(g.p))
end end
function hash(G::WreathProduct, h::UInt) function hash(G::WreathProduct, h::UInt)
@ -127,7 +124,7 @@ function hash(G::WreathProduct, h::UInt)
end end
function hash(g::WreathProductElem, h::UInt) function hash(g::WreathProductElem, h::UInt)
return hash(g.n, hash(g.p, hash(parent(g), h))) return hash(g.n, hash(g.p, hash(WreathProductElem, h)))
end end
############################################################################### ###############################################################################
@ -137,12 +134,10 @@ end
############################################################################### ###############################################################################
function show(io::IO, G::WreathProduct) function show(io::IO, G::WreathProduct)
print(io, "Wreath Product of $(G.N.factors[1]) and $(G.P)") print(io, "Wreath Product of $(G.N.group) by $(G.P)")
end end
function show(io::IO, g::WreathProductElem) function show(io::IO, g::WreathProductElem)
# println(io, "Element of WreathProduct over $T of size $(size(X)):")
# show(io, "text/plain", matrix_repr(X))
print(io, "($(g.n)$(g.p))") print(io, "($(g.n)$(g.p))")
end end
@ -159,7 +154,6 @@ function (==)(G::WreathProduct, H::WreathProduct)
end end
function (==)(g::WreathProductElem, h::WreathProductElem) function (==)(g::WreathProductElem, h::WreathProductElem)
parent(g) == parent(h) || return false
g.n == h.n || return false g.n == h.n || return false
g.p == h.p || return false g.p == h.p || return false
return true return true
@ -167,45 +161,32 @@ end
############################################################################### ###############################################################################
# #
# Binary operators # Group operations
# #
############################################################################### ###############################################################################
function wreath_multiplication(g::WreathProductElem, h::WreathProductElem)
parent(g) == parent(h) || throw("Can not multiply elements from different
groups!")
G = parent(g)
w=G.N((h.n).elts[inv(g.p).d])
return G(g.n*w, g.p*h.p)
end
doc""" doc"""
*(g::WreathProductElem, h::WreathProductElem) *(g::WreathProductElem, h::WreathProductElem)
> Return the wreath product group operation of elements, i.e. > Return the wreath product group operation of elements, i.e.
> >
> g*h = (g.n*g.p(h.n), g.p*h.p), > `g*h = (g.n*g.p(h.n), g.p*h.p)`,
> >
> where g.p(h.n) denotes the action of `g.p::perm` on > where `g.p(h.n)` denotes the action of `g.p::perm` on
> `h.n::DirectProductGroupElem` via standard permutation of coordinates. > `h.n::DirectProductGroupElem` via standard permutation of coordinates.
""" """
(*)(g::WreathProductElem, h::WreathProductElem) = wreath_multiplication(g,h) function *(g::WreathProductElem, h::WreathProductElem)
w = DirectProductGroupElem((h.n).elts[inv(g.p).d])
return WreathProductElem(g.n*w, g.p*h.p, false)
############################################################################### end
#
# Inversion
#
###############################################################################
doc""" doc"""
inv(g::WreathProductElem) inv(g::WreathProductElem)
> Returns the inverse of element of a wreath product, according to the formula > Returns the inverse of element of a wreath product, according to the formula
> g^-1 = (g.n, g.p)^-1 = (g.p^-1(g.n^-1), g.p^-1). > `g^-1 = (g.n, g.p)^-1 = (g.p^-1(g.n^-1), g.p^-1)`.
""" """
function inv(g::WreathProductElem) function inv(g::WreathProductElem)
G = parent(g) w = DirectProductGroupElem(inv(g.n).elts[g.p.d])
w = G.N(inv(g.n).elts[g.p.d]) return WreathProductElem(w, inv(g.p), false)
return G(w, inv(g.p))
end end
############################################################################### ###############################################################################
@ -218,7 +199,7 @@ matrix_repr(g::WreathProductElem) = Any[matrix_repr(g.p) g.n]
function elements(G::WreathProduct) function elements(G::WreathProduct)
iter = Base.product(collect(elements(G.N)), collect(elements(G.P))) iter = Base.product(collect(elements(G.N)), collect(elements(G.P)))
return (G(n)*G(p) for (n,p) in iter) return (WreathProductElem(n, p, false) for (n,p) in iter)
end end
order(G::WreathProduct) = order(G.P)*order(G.N) order(G::WreathProduct) = order(G.P)*order(G.N)

83
test/DirectProd-tests.jl Normal file
View File

@ -0,0 +1,83 @@
@testset "DirectProducts" begin
using Nemo
G = PermutationGroup(3)
g = G([2,3,1])
F, a = FiniteField(2,3,"a")
@testset "Constructors" begin
@test isa(Groups.DirectProductGroup(G,2), Nemo.Group)
@test isa(G×G, Nemo.Group)
@test isa(Groups.DirectProductGroup(G,2), Groups.DirectProductGroup{Nemo.PermGroup})
GG = Groups.DirectProductGroup(G,2)
@test GG == Groups.DirectProductGroup(G,2)
@test Groups.DirectProductGroupElem([G(), G()]) == GG()
@test GG(G(), G()) == GG()
@test isa(GG([g, g^2]), GroupElem)
@test isa(GG([g, g^2]), Groups.DirectProductGroupElem{Nemo.perm})
h = GG([g,g^2])
@test h == GG(h)
@test isa(GG(g, g^2), GroupElem)
@test isa(GG(g, g^2), Groups.DirectProductGroupElem)
@test_throws String GG(g,g,g)
@test GG(g,g^2) == h
@test size(h) == (2,)
@test h[1] == g
@test h[2] == g^2
h[2] = G()
@test h == GG(g, G())
end
GG = Groups.DirectProductGroup(G,2)
FF = Groups.DirectProductGroup(F,2)
@testset "Types" begin
@test elem_type(GG) == Groups.DirectProductGroupElem{elem_type(G)}
@test elem_type(FF) == Groups.DirectProductGroupElem{elem_type(F)}
@test parent_type(typeof(GG(g,g^2))) == Groups.DirectProductGroup{typeof(G)}
@test parent_type(typeof(FF(a,a^2))) == Groups.DirectProductGroup{typeof(F)}
@test isa(FF([0,1]), GroupElem)
@test isa(FF([0,1]), Groups.DirectProductGroupElem)
@test isa(FF([0,1]), Groups.DirectProductGroupElem{elem_type(F)})
@test_throws MethodError FF(1,0)
end
@testset "Group arithmetic" begin
g = G([2,3,1])
h = GG([g,g^2])
@test h^2 == GG(g^2,g)
@test h^6 == GG()
@test h*h == h^2
@test h*inv(h) == GG()
@test FF([0,a])*FF([a,1]) == FF(a,1+a)
x, y = FF([1,a]), FF([a^2,1])
@test x*y == FF([a^2+1, a+1])
@test inv(x) == FF([1,a])
end
@testset "Misc" begin
@test order(GG) == 36
@test order(FF) == 64
@test isa([elements(GG)...], Vector{Groups.DirectProductGroupElem{elem_type(G)}})
elts = [elements(GG)...]
@test length(elts) == 36
@test all([g*inv(g) for g in elts] .== GG())
@test all(inv(g*h) == inv(h)*inv(g) for g in elts for h in elts)
end
end

View File

@ -1,7 +1,9 @@
@testset "Groups.FreeSymbols" begin @testset "Groups.FreeSymbols" begin
s = Groups.FreeSymbol("s") s = Groups.FreeSymbol("s")
t = Groups.FreeSymbol("t") t = Groups.FreeSymbol("t")
@testset "defines" begin
@testset "constructors" begin
@test isa(Groups.FreeSymbol("aaaaaaaaaaaaaaaa"), Groups.GSymbol) @test isa(Groups.FreeSymbol("aaaaaaaaaaaaaaaa"), Groups.GSymbol)
@test Groups.FreeSymbol("abc").pow == 1 @test Groups.FreeSymbol("abc").pow == 1
@test isa(s, Groups.FreeSymbol) @test isa(s, Groups.FreeSymbol)
@ -23,28 +25,19 @@
end end
end end
@testset "FreeGroupElems" begin @testset "FreeGroupSymbols manipulation" begin
s = Groups.FreeSymbol("s") s = Groups.FreeSymbol("s")
t = Groups.FreeSymbol("t", -2) t = Groups.FreeSymbol("t", -2)
@testset "defines" begin
@test isa(Groups.GWord(s), Groups.GWord)
@test isa(Groups.GWord(s), FreeGroupElem)
@test isa(FreeGroupElem(s), Groups.GWord)
@test isa(convert(FreeGroupElem, s), Groups.GWord)
@test isa(convert(FreeGroupElem, s), FreeGroupElem)
@test isa(Vector{FreeGroupElem}([s,t]), Vector{FreeGroupElem})
@test length(FreeGroupElem(s)) == 1
@test length(FreeGroupElem(t)) == 2
end
@testset "eltary functions" begin @test isa(Groups.GWord(s), Groups.GWord)
@test_skip (s*s).symbols == (s^2).symbols @test isa(Groups.GWord(s), FreeGroupElem)
@test_skip Vector{Groups.GWord{Groups.FreeSymbol}}([s,t]) == @test isa(FreeGroupElem(s), Groups.GWord)
Vector{FreeGroupElem}([s,t]) @test isa(convert(FreeGroupElem, s), Groups.GWord)
@test_skip Vector{Groups.GWord}([s,t]) == @test isa(convert(FreeGroupElem, s), FreeGroupElem)
[Groups.GWord(s), Groups.GWord(t)] @test isa(Vector{FreeGroupElem}([s,t]), Vector{FreeGroupElem})
@test_skip hash([t^1,s^1]) == hash([t^2*inv(t),s*inv(s)*s]) @test length(FreeGroupElem(s)) == 1
end @test length(FreeGroupElem(t)) == 2
end end
@testset "FreeGroup" begin @testset "FreeGroup" begin
@ -55,8 +48,6 @@ end
@test isa(G(), FreeGroupElem) @test isa(G(), FreeGroupElem)
@test eltype(G.gens) == Groups.FreeSymbol @test eltype(G.gens) == Groups.FreeSymbol
@test length(G.gens) == 2 @test length(G.gens) == 2
@test_skip eltype(G.rels) == FreeGroupElem
@test_skip length(G.rels) == 0
@test eltype(Nemo.gens(G)) == FreeGroupElem @test eltype(Nemo.gens(G)) == FreeGroupElem
@test length(Nemo.gens(G)) == 2 @test length(Nemo.gens(G)) == 2
end end
@ -64,6 +55,11 @@ end
s, t = Nemo.gens(G) s, t = Nemo.gens(G)
@testset "internal arithmetic" begin @testset "internal arithmetic" begin
@test Vector{Groups.GWord}([s,t]) == [Groups.GWord(s), Groups.GWord(t)]
@test (s*s).symbols == (s^2).symbols
@test hash([t^1,s^1]) == hash([t^2*inv(t),s*inv(s)*s])
t_symb = Groups.FreeSymbol("t") t_symb = Groups.FreeSymbol("t")
tt = deepcopy(t) tt = deepcopy(t)
@test string(Groups.r_multiply!(tt,[inv(t_symb)]; reduced=true)) == @test string(Groups.r_multiply!(tt,[inv(t_symb)]; reduced=true)) ==
@ -96,7 +92,7 @@ end
@test Groups.reduce!(w).symbols ==Vector{Groups.FreeSymbol}([]) @test Groups.reduce!(w).symbols ==Vector{Groups.FreeSymbol}([])
end end
@testset "binary/inv operations" begin @testset "Group operations" begin
@test parent(s) == G @test parent(s) == G
@test parent(s) === parent(deepcopy(s)) @test parent(s) === parent(deepcopy(s))
@test isa(s*t, FreeGroupElem) @test isa(s*t, FreeGroupElem)

85
test/WreathProd-tests.jl Normal file
View File

@ -0,0 +1,85 @@
@testset "WreathProducts" begin
S_3 = PermutationGroup(3)
F, a = FiniteField(2,3,"a")
b = S_3([2,3,1])
@testset "Constructors" begin
@test isa(Groups.WreathProduct(F, S_3), Nemo.Group)
@test isa(Groups.WreathProduct(F, S_3), Groups.WreathProduct)
@test isa(Groups.WreathProduct(F, S_3), Groups.WreathProduct{Nemo.FqNmodFiniteField})
aa = Groups.DirectProductGroupElem([a^0 ,a, a^2])
@test isa(Groups.WreathProductElem(aa, b), Nemo.GroupElem)
@test isa(Groups.WreathProductElem(aa, b), Groups.WreathProductElem)
@test isa(Groups.WreathProductElem(aa, b), Groups.WreathProductElem{typeof(a)})
B3 = Groups.WreathProduct(F, S_3)
@test B3.N == Groups.DirectProductGroup(F, 3)
@test B3.P == S_3
@test B3(aa, b) == Groups.WreathProductElem(aa, b)
@test B3(b) == Groups.WreathProductElem(B3.N(), b)
@test B3(aa) == Groups.WreathProductElem(aa, S_3())
g = B3(aa, b)
@test g.p == b
@test g.n == aa
h = deepcopy(g)
@test hash(g) == hash(h)
g.n[1] = a
@test g.n[1] == a
@test g != h
@test hash(g) != hash(h)
end
@testset "Types" begin
B3 = Groups.WreathProduct(F, S_3)
@test elem_type(B3) == Groups.WreathProductElem{elem_type(F)}
@test parent_type(typeof(B3())) == Groups.WreathProduct{parent_type(typeof(B3.N.group()))}
@test parent(B3()) == Groups.WreathProduct(F,S_3)
@test parent(B3()) == B3
end
@testset "Group arithmetic" begin
B3 = Groups.WreathProduct(F, S_3)
x = B3(B3.N([1,0,0]), B3.P([2,3,1]))
y = B3(B3.N([0,1,1]), B3.P([2,1,3]))
@test x*y == B3(B3.N([0,0,1]), B3.P([3,2,1]))
@test y*x == B3(B3.N([0,0,1]), B3.P([1,3,2]))
@test inv(x) == B3(B3.N([0,0,1]), B3.P([3,1,2]))
@test inv(y) == B3(B3.N([1,0,1]), B3.P([2,1,3]))
@test inv(x)*y == B3(B3.N([1,1,1]), B3.P([1,3,2]))
@test y*inv(x) == B3(B3.N([0,1,0]), B3.P([3,2,1]))
end
@testset "Misc" begin
B3 = Groups.WreathProduct(FiniteField(2,1,"a")[1], S_3)
@test order(B3) == 48
Wr = WreathProduct(PermutationGroup(2),S_3)
@test isa([elements(Wr)...], Vector{Groups.WreathProductElem{Nemo.perm}})
elts = [elements(Wr)...]
@test length(elts) == order(Wr)
@test all([g*inv(g) for g in elts] .== Wr())
@test all(inv(g*h) == inv(h)*inv(g) for g in elts for h in elts)
end
end

View File

@ -6,4 +6,6 @@ using Base.Test
@testset "Groups" begin @testset "Groups" begin
include("FreeGroup-tests.jl") include("FreeGroup-tests.jl")
include("AutGroup-tests.jl") include("AutGroup-tests.jl")
include("DirectProd-tests.jl")
include("WreathProd-tests.jl")
end end