remove DirectPower, WreathProduct

these are included in GroupsCore
This commit is contained in:
Marek Kaluba 2021-04-11 01:27:01 +02:00
parent 41eb7224dd
commit 990c8dd1c3
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
7 changed files with 4 additions and 595 deletions

View File

@ -5,11 +5,13 @@ version = "0.5.2"
[deps]
AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d"
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
ThreadsX = "ac1d9e8a-700a-412c-b207-f0111f4b6c0d"
[compat]
AbstractAlgebra = "^0.10.0"
AbstractAlgebra = "^0.13.0, ^0.14.0, ^0.15.0"
GroupsCore = "^0.3"
ThreadsX = "^0.1.0"
julia = "1.3, 1.4, 1.5"

View File

@ -1,192 +0,0 @@
export DirectPowerGroup, DirectPowerGroupElem
###############################################################################
#
# DirectPowerGroup / DirectPowerGroupElem Constructors
#
###############################################################################
"""
DirectPowerGroup(G::Group, n::Int) <: Group
Return `n`-fold direct product of `G`. The group operation is
`*` distributed component-wise, with component-wise identity as neutral element.
"""
struct DirectPowerGroup{N, T<:Group} <: Group
group::T
end
DirectPowerGroup(G::Gr, N::Int) where Gr<:Group = DirectPowerGroup{N,Gr}(G)
function DirectPower(G::Group, H::Group)
G == H || throw(DomainError(
"Direct Powers are defined only for the same groups"))
return DirectPowerGroup(G,2)
end
DirectPower(H::Group, G::DirectPowerGroup) = DirectPower(G,H)
function DirectPower(G::DirectPowerGroup{N}, H::Group) where N
G.group == H || throw(DomainError(
"Direct Powers are defined only for the same groups"))
return DirectPowerGroup(G.group, N+1)
end
struct DirectPowerGroupElem{N, T<:GroupElem} <: GroupElem
elts::NTuple{N,T}
end
function DirectPowerGroupElem(v::Vector{GrEl}) where GrEl<:GroupElem
return DirectPowerGroupElem(tuple(v...))
end
###############################################################################
#
# Type and parent object methods
#
###############################################################################
elem_type(::Type{DirectPowerGroup{N,T}}) where {N,T} =
DirectPowerGroupElem{N, elem_type(T)}
parent_type(::Type{DirectPowerGroupElem{N,T}}) where {N,T} =
DirectPowerGroup{N, parent_type(T)}
parent(g::DirectPowerGroupElem{N, T}) where {N,T} =
DirectPowerGroup(parent(first(g.elts)), N)
###############################################################################
#
# AbstractVector interface
#
###############################################################################
Base.size(g::DirectPowerGroupElem{N}) where N = (N,)
Base.IndexStyle(::Type{DirectPowerGroupElem}) = Base.LinearFast()
Base.getindex(g::DirectPowerGroupElem, i::Int) = g.elts[i]
###############################################################################
#
# Parent object call overloads
#
###############################################################################
"""
(G::DirectPowerGroup)(a::Vector, check::Bool=true)
Constructs element of the `n`-fold direct product group `G` by coercing each
element of vector `a` to `G.group`. If `check` flag is set to `false` neither
check on the correctness nor coercion is performed.
"""
function (G::DirectPowerGroup{N})(a::Vector, check::Bool=true) where N
if check
N == length(a) || throw(DomainError(
"Can not coerce to DirectPowerGroup: lengths differ"))
a = (G.group).(a)
end
return DirectPowerGroupElem(a)
end
function (G::DirectPowerGroup{N})(a::NTuple{N, GrEl}) where {N, GrEl}
return DirectPowerGroupElem(G.group.(a))
end
(G::DirectPowerGroup{N})(a::Vararg{GrEl, N}) where {N, GrEl} = DirectPowerGroupElem(G.group.(a))
function Base.one(G::DirectPowerGroup{N}) where N
return DirectPowerGroupElem(ntuple(i->one(G.group),N))
end
(G::DirectPowerGroup)(g::DirectPowerGroupElem) = G(g.elts)
###############################################################################
#
# Basic manipulation
#
###############################################################################
function hash(G::DirectPowerGroup{N}, h::UInt) where N
return hash(G.group, hash(N, hash(DirectPowerGroup,h)))
end
function hash(g::DirectPowerGroupElem, h::UInt)
return hash(g.elts, hash(DirectPowerGroupElem, h))
end
###############################################################################
#
# String I/O
#
###############################################################################
function show(io::IO, G::DirectPowerGroup{N}) where N
print(io, "$(N)-fold direct product of $(G.group)")
end
function show(io::IO, g::DirectPowerGroupElem)
print(io, "[$(join(g.elts,","))]")
end
###############################################################################
#
# Comparison
#
###############################################################################
function (==)(G::DirectPowerGroup{N}, H::DirectPowerGroup{M}) where {N,M}
N == M || return false
G.group == H.group || return false
return true
end
(==)(g::DirectPowerGroupElem, h::DirectPowerGroupElem) = g.elts == h.elts
###############################################################################
#
# Group operations
#
###############################################################################
function *(g::DirectPowerGroupElem{N}, h::DirectPowerGroupElem{N}, check::Bool=true) where N
if check
parent(g) == parent(h) || throw(DomainError(
"Can not multiply elements of different groups!"))
end
return DirectPowerGroupElem(ntuple(i-> g.elts[i]*h.elts[i], N))
end
^(g::DirectPowerGroupElem, n::Integer) = Base.power_by_squaring(g, n)
function inv(g::DirectPowerGroupElem{N}) where {N}
return DirectPowerGroupElem(ntuple(i-> inv(g.elts[i]), N))
end
###############################################################################
#
# Misc
#
###############################################################################
order(G::DirectPowerGroup{N}) where N = order(G.group)^N
function iterate(G::DirectPowerGroup{N}) where N
elts = collect(G.group)
indices = CartesianIndices(ntuple(i -> order(G.group), N))
idx, s = iterate(indices)
g = DirectPowerGroupElem(ntuple(i -> elts[idx[i]], N))
return g, (elts, indices, s)
end
function iterate(G::DirectPowerGroup{N}, state) where N
elts, indices, s = state
res = iterate(indices, s)
if res == nothing
return nothing
else
idx, s = res
end
g = DirectPowerGroupElem(ntuple(i -> elts[idx[i]], N))
return g, (elts, indices, s)
end
eltype(::Type{DirectPowerGroup{N, G}}) where {N, G} = DirectPowerGroupElem{N, elem_type(G)}
Base.length(G::DirectPowerGroup) = order(G)

View File

@ -10,6 +10,7 @@ import Base: inv, reduce, *, ^, power_by_squaring
import Base: findfirst, findnext, findlast, findprev, replace
import Base: deepcopy_internal
using GroupsCore
using LinearAlgebra
using ThreadsX
@ -29,9 +30,6 @@ include("freereduce.jl")
include("arithmetic.jl")
include("findreplace.jl")
include("DirectPower.jl")
include("WreathProducts.jl")
###############################################################################
#
# String I/O

View File

@ -1,210 +0,0 @@
export WreathProduct, WreathProductElem
import AbstractAlgebra: AbstractPermutationGroup, AbstractPerm
###############################################################################
#
# WreathProduct / WreathProductElem
#
###############################################################################
"""
WreathProduct(N, P) <: Group
Return the wreath product of a group `N` by permutation group `P`, usually
written as `N ≀ P`. The multiplication inside wreath product is defined as
> `(n, σ) * (m, τ) = (n*σ(m), στ)`
where `σ(m)` denotes the action (from the right) of the permutation group on
`n-tuples` of elements from `N`
# Arguments:
* `N::Group` : the single factor of the `DirectPower` group `N`
* `P::AbstractPermutationGroup` acting on `DirectPower` of `N`
"""
struct WreathProduct{N, T<:Group, PG<:AbstractPermutationGroup} <: Group
N::DirectPowerGroup{N, T}
P::PG
function WreathProduct(G::Gr, P::PG) where
{Gr <: Group, PG <: AbstractPermutationGroup}
N = DirectPowerGroup(G, Int(P.n))
return new{Int(P.n), Gr, PG}(N, P)
end
end
struct WreathProductElem{N, T<:GroupElem, P<:AbstractPerm} <: GroupElem
n::DirectPowerGroupElem{N, T}
p::P
function WreathProductElem(n::DirectPowerGroupElem{N,T}, p::P,
check::Bool=true) where {N, T, P<:AbstractPerm}
if check
N == length(p.d) || throw(DomainError(
"Can't form WreathProductElem: lengths differ"))
end
return new{N, T, P}(n, p)
end
end
###############################################################################
#
# Type and parent object methods
#
###############################################################################
elem_type(::Type{WreathProduct{N, T, PG}}) where {N, T, PG} = WreathProductElem{N, elem_type(T), elem_type(PG)}
parent_type(::Type{WreathProductElem{N, T, P}}) where {N, T, P} =
WreathProduct{N, parent_type(T), parent_type(P)}
parent(g::WreathProductElem) = WreathProduct(parent(g.n[1]), parent(g.p))
###############################################################################
#
# Parent object call overloads
#
###############################################################################
function (G::WreathProduct{N})(g::WreathProductElem{N}) where {N}
n = G.N(g.n)
p = G.P(g.p)
return WreathProductElem(n, p)
end
"""
(G::WreathProduct)(n::DirectPowerGroupElem, p::Generic.Perm)
Create an element of wreath product `G` by coercing `n` and `p` to `G.N` and
`G.P`, respectively.
"""
(G::WreathProduct)(n::DirectPowerGroupElem, p::Generic.Perm) = WreathProductElem(n,p)
Base.one(G::WreathProduct) = WreathProductElem(one(G.N), one(G.P), false)
"""
(G::WreathProduct)(p::Generic.Perm)
Return the image of permutation `p` in `G` via embedding `p → (id,p)`.
"""
(G::WreathProduct)(p::Generic.Perm) = G(one(G.N), p)
"""
(G::WreathProduct)(n::DirectPowerGroupElem)
Return the image of `n` in `G` via embedding `n → (n, ())`. This is the
embedding that makes the sequence `1 → N → G → P → 1` exact.
"""
(G::WreathProduct)(n::DirectPowerGroupElem) = G(n, one(G.P))
(G::WreathProduct)(n,p) = G(G.N(n), G.P(p))
###############################################################################
#
# Basic manipulation
#
###############################################################################
function hash(G::WreathProduct, h::UInt)
return hash(G.N, hash(G.P, hash(WreathProduct, h)))
end
function hash(g::WreathProductElem, h::UInt)
return hash(g.n, hash(g.p, hash(WreathProductElem, h)))
end
###############################################################################
#
# String I/O
#
###############################################################################
function show(io::IO, G::WreathProduct)
print(io, "Wreath Product of $(G.N.group) by $(G.P)")
end
function show(io::IO, g::WreathProductElem)
print(io, "($(g.n)$(g.p))")
end
###############################################################################
#
# Comparison
#
###############################################################################
function (==)(G::WreathProduct, H::WreathProduct)
G.N == H.N || return false
G.P == H.P || return false
return true
end
function (==)(g::WreathProductElem, h::WreathProductElem)
g.n == h.n || return false
g.p == h.p || return false
return true
end
###############################################################################
#
# Group operations
#
###############################################################################
(p::Generic.Perm)(n::DirectPowerGroupElem) = DirectPowerGroupElem(n.elts[p.d])
"""
*(g::WreathProductElem, h::WreathProductElem)
Return the group operation of wreath product elements, i.e.
> `g*h = (g.n*g.p(h.n), g.p*h.p)`,
where `g.p(h.n)` denotes the action of `g.p::Generic.Perm` on
`h.n::DirectPowerGroupElem` via standard permutation of coordinates.
"""
function *(g::WreathProductElem, h::WreathProductElem)
return WreathProductElem(g.n*g.p(h.n), g.p*h.p, false)
end
^(g::WreathProductElem, n::Integer) = Base.power_by_squaring(g, n)
"""
inv(g::WreathProductElem)
Return 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)`.
"""
function inv(g::WreathProductElem)
pinv = inv(g.p)
return WreathProductElem(pinv(inv(g.n)), pinv, false)
end
###############################################################################
#
# Misc
#
###############################################################################
matrix_repr(g::WreathProductElem) = Any[matrix_repr(g.p) g.n]
function iterate(G::WreathProduct)
n, state_N = iterate(G.N)
p, state_P = iterate(G.P)
return G(n,p), (state_N, p, state_P)
end
function iterate(G::WreathProduct, state)
state_N, p, state_P = state
res = iterate(G.N, state_N)
if res == nothing
resP = iterate(G.P, state_P)
if resP == nothing
return nothing
else
n, state_N = iterate(G.N)
p, state_P = resP
end
else
n, state_N = res
end
return G(n,p), (state_N, p, state_P)
end
eltype(::Type{WreathProduct{N,G,PG}}) where {N,G,PG} = WreathProductElem{N, elem_type(G), elem_type(PG)}
order(G::WreathProduct) = order(G.P)*order(G.N)
length(G::WreathProduct) = order(G)

View File

@ -1,89 +0,0 @@
@testset "DirectPowers" begin
×(a,b) = Groups.DirectPower(a,b)
@testset "Constructors" begin
G = SymmetricGroup(3)
@test Groups.DirectPowerGroup(G,2) isa AbstractAlgebra.Group
@test G×G isa AbstractAlgebra.Group
@test Groups.DirectPowerGroup(G,2) isa Groups.DirectPowerGroup{2, Generic.SymmetricGroup{Int64}}
@test (G×G)×G == DirectPowerGroup(G, 3)
@test (G×G)×G == (G×G)×G
GG = DirectPowerGroup(G,2)
@test one(G×G) isa GroupElem
@test (G×G)((one(G), one(G))) isa GroupElem
@test (G×G)([one(G), one(G)]) isa GroupElem
@test Groups.DirectPowerGroupElem((one(G), one(G))) == one(G×G)
@test GG(one(G), one(G)) == one(G×G)
g = perm"(1,2,3)"
@test GG(g, g^2) isa GroupElem
@test GG(g, g^2) isa Groups.DirectPowerGroupElem{2, Generic.Perm{Int64}}
h = GG(g,g^2)
@test h == GG(h)
@test GG(g, g^2) isa GroupElem
@test GG(g, g^2) isa Groups.DirectPowerGroupElem
@test_throws MethodError GG(g,g,g)
@test GG(g,g^2) == h
@test h[1] == g
@test h[2] == g^2
h = GG(g, one(G))
@test h == GG(g, one(G))
end
@testset "Basic arithmetic" begin
G = SymmetricGroup(3)
GG = G×G
i = perm"(1,3)"
g = perm"(1,2,3)"
h = GG(g,g^2)
k = GG(g^3, g^2)
@test h^2 == GG(g^2,g)
@test h^6 == one(GG)
@test h*h == h^2
@test h*k == GG(g,g)
@test h*inv(h) == one(G×G)
w = GG(g,i)*GG(i,g)
@test w == GG(perm"(1,2)(3)", perm"(2,3)")
@test w == inv(w)
@test w^2 == w*w == one(GG)
end
@testset "elem/parent_types" begin
G = SymmetricGroup(3)
g = perm"(1,2,3)"
@test elem_type(G×G) == DirectPowerGroupElem{2, elem_type(G)}
@test elem_type(G×G×G) == DirectPowerGroupElem{3, elem_type(G)}
@test parent_type(typeof((G×G)(g,g^2))) == Groups.DirectPowerGroup{2, typeof(G)}
@test parent(DirectPowerGroupElem((g,g^2,g^3))) == DirectPowerGroup(G,3)
end
@testset "Misc" begin
G = SymmetricGroup(3)
GG = Groups.DirectPowerGroup(G,3)
@test order(GG) == 216
@test isa(collect(GG), Vector{Groups.DirectPowerGroupElem{3, elem_type(G)}})
elts = vec(collect(GG))
@test length(elts) == 216
@test all([g*inv(g) == one(GG) for g in elts])
@test all(inv(g*h) == inv(h)*inv(g) for g in elts for h in elts)
end
end

View File

@ -1,98 +0,0 @@
@testset "WreathProducts" begin
S_3 = SymmetricGroup(3)
S_2 = SymmetricGroup(2)
b = perm"(1,2,3)"
a = perm"(1,2)"
@testset "Constructors" begin
@test Groups.WreathProduct(S_2, S_3) isa AbstractAlgebra.Group
B3 = Groups.WreathProduct(S_2, S_3)
@test B3 isa Groups.WreathProduct
@test B3 isa WreathProduct{3, Generic.SymmetricGroup{Int}, Generic.SymmetricGroup{Int}}
aa = Groups.DirectPowerGroupElem((a^0 ,a, a^2))
@test Groups.WreathProductElem(aa, b) isa AbstractAlgebra.GroupElem
x = Groups.WreathProductElem(aa, b)
@test x isa Groups.WreathProductElem
@test x isa
Groups.WreathProductElem{3, Generic.Perm{Int}, Generic.Perm{Int}}
@test B3.N == Groups.DirectPowerGroup(S_2, 3)
@test B3.P == S_3
@test B3(aa, b) == Groups.WreathProductElem(aa, b)
w = B3(aa, b)
@test B3(w) == w
@test B3(b) == Groups.WreathProductElem(one(B3.N), b)
@test B3(aa) == Groups.WreathProductElem(aa, one(S_3))
@test B3((a^0 ,a, a^2), b) isa WreathProductElem
@test B3((a^0 ,a, a^2), b) == B3(aa, b)
end
@testset "Types" begin
B3 = Groups.WreathProduct(S_2, S_3)
@test elem_type(B3) == Groups.WreathProductElem{3, Generic.Perm{Int}, Generic.Perm{Int}}
@test parent_type(typeof(one(B3))) == Groups.WreathProduct{3, parent_type(typeof(one(B3.N.group))), Generic.SymmetricGroup{Int}}
@test parent(one(B3)) == Groups.WreathProduct(S_2,S_3)
@test parent(one(B3)) == B3
end
@testset "Basic operations on WreathProductElem" begin
aa = Groups.DirectPowerGroupElem((a^0 ,a, a^2))
B3 = Groups.WreathProduct(S_2, S_3)
g = B3(aa, b)
@test g.p == b
@test g.n == DirectPowerGroupElem(aa.elts)
h = deepcopy(g)
@test h == g
@test !(g === h)
g = B3(Groups.DirectPowerGroupElem((a ,a, a^2)), g.p)
@test g.n[1] == parent(g.n[1])(a)
@test g != h
@test hash(g) != hash(h)
end
@testset "Group arithmetic" begin
B4 = Groups.WreathProduct(SymmetricGroup(3), SymmetricGroup(4))
id, a, b = perm"(3)", perm"(1,2)(3)", perm"(1,2,3)"
x = B4((id,a,b,id), perm"(1,2,3)(4)")
@test inv(x) == B4((inv(b),id, a,id), perm"(1,3,2)(4)")
y = B4((a,id,a,b), perm"(1,4)(2,3)")
@test inv(y) == B4((inv(b), a,id, a), perm"(1,4)(2,3)")
@test x*y == B4((id,id,b*a,b), perm"(1,3,4)(2)")
@test y*x == B4(( a, b, id,b), perm"(1,4,2)(3)")
@test inv(x)*y == B4((inv(b)*a,a,a,b), perm"(1,2,4)(3)")
@test y*inv(x) == B4((a,a,a,id), perm"(1,4,3)(2)")
@test (x*y)^6 == ((x*y)^2)^3
end
@testset "Iteration" begin
Wr = WreathProduct(SymmetricGroup(2),SymmetricGroup(4))
elts = collect(Wr)
@test elts isa Vector{Groups.WreathProductElem{4, Generic.Perm{Int}, Generic.Perm{Int}}}
@test order(Wr) == 2^4*factorial(4)
@test length(elts) == order(Wr)
@test all((g*inv(g) == one(Wr) for g in elts))
@test all(inv(g*h) == inv(h)*inv(g) for g in elts for h in elts)
end
end

View File

@ -21,7 +21,5 @@ using LinearAlgebra
include("FreeGroup-tests.jl")
include("AutGroup-tests.jl")
include("DirectPower-tests.jl")
include("WreathProd-tests.jl")
include("FPGroup-tests.jl")
end