mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-11-19 06:30:29 +01:00
add Constructions module with Direct/Wreath product
This commit is contained in:
parent
dd6588f018
commit
e78520f90b
@ -8,6 +8,7 @@ Folds = "41a02a25-b8f0-4f67-bc48-60067656b558"
|
|||||||
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
|
GroupsCore = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120"
|
||||||
KnuthBendix = "c2604015-7b3d-4a30-8a26-9074551ec60a"
|
KnuthBendix = "c2604015-7b3d-4a30-8a26-9074551ec60a"
|
||||||
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
||||||
|
PermutationGroups = "8bc5a954-2dfc-11e9-10e6-cd969bffa420"
|
||||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||||
|
|
||||||
[compat]
|
[compat]
|
||||||
|
@ -15,6 +15,10 @@ export Alphabet, AutomorphismGroup, FreeGroup, FreeGroup, FPGroup, FPGroupElemen
|
|||||||
|
|
||||||
export alphabet, evaluate, word, gens
|
export alphabet, evaluate, word, gens
|
||||||
|
|
||||||
|
# general constructions
|
||||||
|
include(joinpath("constructions", "constructions.jl"))
|
||||||
|
using .Constructions
|
||||||
|
|
||||||
include("types.jl")
|
include("types.jl")
|
||||||
include("hashing.jl")
|
include("hashing.jl")
|
||||||
include("normalform.jl")
|
include("normalform.jl")
|
||||||
|
10
src/constructions/constructions.jl
Normal file
10
src/constructions/constructions.jl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module Constructions
|
||||||
|
|
||||||
|
using GroupsCore
|
||||||
|
using Random
|
||||||
|
|
||||||
|
include("direct_product.jl")
|
||||||
|
include("direct_power.jl")
|
||||||
|
include("wreath_product.jl")
|
||||||
|
|
||||||
|
end # of module Constructions
|
112
src/constructions/direct_power.jl
Normal file
112
src/constructions/direct_power.jl
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
struct DirectPower{Gr,N,GEl<:GroupsCore.GroupElement} <: GroupsCore.Group
|
||||||
|
group::Gr
|
||||||
|
|
||||||
|
function DirectPower{N}(G::GroupsCore.Group) where {N}
|
||||||
|
@assert N > 1
|
||||||
|
return new{typeof(G),N,eltype(G)}(G)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
struct DirectPowerElement{GEl,N,Gr<:GroupsCore.Group} <: GroupsCore.GroupElement
|
||||||
|
elts::NTuple{N,GEl}
|
||||||
|
parent::DirectPower{Gr,N,GEl}
|
||||||
|
end
|
||||||
|
|
||||||
|
DirectPowerElement(
|
||||||
|
elts::AbstractVector{<:GroupsCore.GroupElement},
|
||||||
|
G::DirectPower,
|
||||||
|
) = DirectPowerElement(ntuple(i -> elts[i], _nfold(G)), G)
|
||||||
|
|
||||||
|
_nfold(::DirectPower{Gr,N}) where {Gr,N} = N
|
||||||
|
|
||||||
|
Base.one(G::DirectPower) =
|
||||||
|
DirectPowerElement(ntuple(_ -> one(G.group), _nfold(G)), G)
|
||||||
|
|
||||||
|
Base.eltype(::Type{<:DirectPower{Gr,N,GEl}}) where {Gr,N,GEl} =
|
||||||
|
DirectPowerElement{GEl,N,Gr}
|
||||||
|
|
||||||
|
function Base.iterate(G::DirectPower)
|
||||||
|
itr = Iterators.ProductIterator(ntuple(i -> G.group, _nfold(G)))
|
||||||
|
res = iterate(itr)
|
||||||
|
@assert res !== nothing
|
||||||
|
elt = DirectPowerElement(first(res), G)
|
||||||
|
return elt, (iterator = itr, state = last(res))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Base.iterate(G::DirectPower, state)
|
||||||
|
itr, st = state.iterator, state.state
|
||||||
|
res = iterate(itr, st)
|
||||||
|
res === nothing && return nothing
|
||||||
|
elt = DirectPowerElement(first(res), G)
|
||||||
|
return elt, (iterator = itr, state = last(res))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Base.IteratorSize(::Type{<:DirectPower{Gr,N}}) where {Gr,N}
|
||||||
|
Base.IteratorSize(Gr) isa Base.HasLength && return Base.HasShape{N}()
|
||||||
|
Base.IteratorSize(Gr) isa Base.HasShape && return Base.HasShape{N}()
|
||||||
|
return Base.IteratorSize(Gr)
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.size(G::DirectPower) = ntuple(_ -> length(G.group), _nfold(G))
|
||||||
|
|
||||||
|
GroupsCore.order(::Type{I}, G::DirectPower) where {I<:Integer} =
|
||||||
|
convert(I, order(I, G.group)^_nfold(G))
|
||||||
|
|
||||||
|
GroupsCore.ngens(G::DirectPower) = _nfold(G)*ngens(G.group)
|
||||||
|
|
||||||
|
function GroupsCore.gens(G::DirectPower, i::Integer)
|
||||||
|
k = ngens(G.group)
|
||||||
|
ci = CartesianIndices((k, _nfold(G)))
|
||||||
|
@boundscheck checkbounds(ci, i)
|
||||||
|
r, c = Tuple(ci[i])
|
||||||
|
tup = ntuple(j -> j == c ? gens(G.group, r) : one(G.group), _nfold(G))
|
||||||
|
return DirectPowerElement(tup, G)
|
||||||
|
end
|
||||||
|
|
||||||
|
function GroupsCore.gens(G::DirectPower)
|
||||||
|
N = _nfold(G)
|
||||||
|
S = gens(G.group)
|
||||||
|
tups = [ntuple(j->(i == j ? s : one(s)), N) for i in 1:N for s in S]
|
||||||
|
|
||||||
|
return [DirectPowerElement(elts, G) for elts in tups]
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.isfinite(G::DirectPower) = isfinite(G.group)
|
||||||
|
|
||||||
|
function Base.rand(
|
||||||
|
rng::Random.AbstractRNG,
|
||||||
|
rs::Random.SamplerTrivial{<:DirectPower},
|
||||||
|
)
|
||||||
|
G = rs[]
|
||||||
|
return DirectPowerElement(rand(rng, G.group, _nfold(G)), G)
|
||||||
|
end
|
||||||
|
|
||||||
|
GroupsCore.parent(g::DirectPowerElement) = g.parent
|
||||||
|
|
||||||
|
Base.:(==)(g::DirectPowerElement, h::DirectPowerElement) =
|
||||||
|
(parent(g) === parent(h) && g.elts == h.elts)
|
||||||
|
|
||||||
|
Base.hash(g::DirectPowerElement, h::UInt) = hash(g.elts, hash(parent(g), h))
|
||||||
|
|
||||||
|
Base.deepcopy_internal(g::DirectPowerElement, stackdict::IdDict) =
|
||||||
|
DirectPowerElement(Base.deepcopy_internal(g.elts, stackdict), parent(g))
|
||||||
|
|
||||||
|
Base.inv(g::DirectPowerElement) = DirectPowerElement(inv.(g.elts), parent(g))
|
||||||
|
|
||||||
|
function Base.:(*)(g::DirectPowerElement, h::DirectPowerElement)
|
||||||
|
@assert parent(g) === parent(h)
|
||||||
|
return DirectPowerElement(g.elts .* h.elts, parent(g))
|
||||||
|
end
|
||||||
|
|
||||||
|
GroupsCore.order(::Type{I}, g::DirectPowerElement) where {I<:Integer} =
|
||||||
|
convert(I, reduce(lcm, (order(I, h) for h in g.elts), init = one(I)))
|
||||||
|
|
||||||
|
Base.isone(g::DirectPowerElement) = all(isone, g.elts)
|
||||||
|
|
||||||
|
function Base.show(io::IO, G::DirectPower)
|
||||||
|
n = _nfold(G)
|
||||||
|
nn = n == 1 ? "1-st" : n == 2 ? "2-nd" : n == 3 ? "3-rd" : "$n-th"
|
||||||
|
print(io, "Direct $(nn) power of $(G.group)")
|
||||||
|
end
|
||||||
|
Base.show(io::IO, g::DirectPowerElement) =
|
||||||
|
print(io, "( ", join(g.elts, ", "), " )")
|
105
src/constructions/direct_product.jl
Normal file
105
src/constructions/direct_product.jl
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using Random
|
||||||
|
using GroupsCore
|
||||||
|
|
||||||
|
struct DirectProduct{Gt,Ht,GEl,HEl} <: GroupsCore.Group
|
||||||
|
first::Gt
|
||||||
|
last::Ht
|
||||||
|
|
||||||
|
function DirectProduct(G::GroupsCore.Group, H::GroupsCore.Group)
|
||||||
|
return new{typeof(G),typeof(H),eltype(G),eltype(H)}(G, H)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
struct DirectProductElement{GEl,HEl,Gt,Ht} <: GroupsCore.GroupElement
|
||||||
|
elts::Tuple{GEl,HEl}
|
||||||
|
parent::DirectProduct{Gt,Ht,GEl,HEl}
|
||||||
|
end
|
||||||
|
|
||||||
|
DirectProductElement(g, h, G::DirectProduct) = DirectProduct((g, h), G)
|
||||||
|
|
||||||
|
Base.one(G::DirectProduct) =
|
||||||
|
DirectProductElement((one(G.first), one(G.last)), G)
|
||||||
|
|
||||||
|
Base.eltype(::Type{<:DirectProduct{Gt,Ht,GEl,HEl}}) where {Gt,Ht,GEl,HEl} =
|
||||||
|
DirectProductElement{GEl,HEl,Gt,Ht}
|
||||||
|
|
||||||
|
function Base.iterate(G::DirectProduct)
|
||||||
|
itr = Iterators.product(G.first, G.last)
|
||||||
|
res = iterate(itr)
|
||||||
|
@assert res !== nothing
|
||||||
|
elt = DirectProductElement(first(res), G)
|
||||||
|
return elt, (iterator = itr, state = last(res))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Base.iterate(G::DirectProduct, state)
|
||||||
|
itr, st = state.iterator, state.state
|
||||||
|
res = iterate(itr, st)
|
||||||
|
res === nothing && return nothing
|
||||||
|
elt = DirectProductElement(first(res), G)
|
||||||
|
return elt, (iterator = itr, state = last(res))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Base.IteratorSize(::Type{<:DirectProduct{Gt,Ht}}) where {Gt,Ht}
|
||||||
|
Gi = Base.IteratorSize(Gt)
|
||||||
|
Hi = Base.IteratorSize(Ht)
|
||||||
|
if Gi isa Base.IsInfinite || Hi isa Base.IsInfinite
|
||||||
|
return Base.IsInfinite()
|
||||||
|
elseif Gi isa Base.SizeUnknown || Hi isa Base.SizeUnknown
|
||||||
|
return Base.SizeUnknown()
|
||||||
|
else
|
||||||
|
return Base.HasShape{2}()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.size(G::DirectProduct) = (length(G.first), length(G.last))
|
||||||
|
|
||||||
|
GroupsCore.order(::Type{I}, G::DirectProduct) where {I<:Integer} =
|
||||||
|
convert(I, order(I, G.first) * order(I, G.last))
|
||||||
|
|
||||||
|
GroupsCore.ngens(G::DirectProduct) = ngens(G.first) + ngens(G.last)
|
||||||
|
|
||||||
|
function GroupsCore.gens(G::DirectProduct)
|
||||||
|
gens_first = [DirectProductElement((g, one(G.last)), G) for g in gens(G.first)]
|
||||||
|
|
||||||
|
gens_last = [DirectProductElement((one(G.first), g), G) for g in gens(G.last)]
|
||||||
|
|
||||||
|
return [gens_first; gens_last]
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.isfinite(G::DirectProduct) = isfinite(G.first) && isfinite(G.last)
|
||||||
|
|
||||||
|
function Base.rand(
|
||||||
|
rng::Random.AbstractRNG,
|
||||||
|
rs::Random.SamplerTrivial{<:DirectProduct},
|
||||||
|
)
|
||||||
|
G = rs[]
|
||||||
|
return DirectProductElement((rand(rng, G.first), rand(rng, G.last)), G)
|
||||||
|
end
|
||||||
|
|
||||||
|
GroupsCore.parent(g::DirectProductElement) = g.parent
|
||||||
|
|
||||||
|
Base.:(==)(g::DirectProductElement, h::DirectProductElement) =
|
||||||
|
(parent(g) === parent(h) && g.elts == h.elts)
|
||||||
|
|
||||||
|
Base.hash(g::DirectProductElement, h::UInt) = hash(g.elts, hash(parent(g), h))
|
||||||
|
|
||||||
|
Base.deepcopy_internal(g::DirectProductElement, stackdict::IdDict) =
|
||||||
|
DirectProductElement(Base.deepcopy_internal(g.elts, stackdict), parent(g))
|
||||||
|
|
||||||
|
Base.inv(g::DirectProductElement) =
|
||||||
|
DirectProductElement(inv.(g.elts), parent(g))
|
||||||
|
|
||||||
|
function Base.:(*)(g::DirectProductElement, h::DirectProductElement)
|
||||||
|
@assert parent(g) === parent(h)
|
||||||
|
return DirectProductElement(g.elts .* h.elts, parent(g))
|
||||||
|
end
|
||||||
|
|
||||||
|
GroupsCore.order(::Type{I}, g::DirectProductElement) where {I<:Integer} =
|
||||||
|
convert(I, lcm(order(I, first(g.elts)), order(I, last(g.elts))))
|
||||||
|
|
||||||
|
Base.isone(g::DirectProductElement) = all(isone, g.elts)
|
||||||
|
|
||||||
|
Base.show(io::IO, G::DirectProduct) =
|
||||||
|
print(io, "Direct product of $(G.first) and $(G.last)")
|
||||||
|
Base.show(io::IO, g::DirectProductElement) =
|
||||||
|
print(io, "( $(join(g.elts, ",")) )")
|
136
src/constructions/wreath_product.jl
Normal file
136
src/constructions/wreath_product.jl
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import PermutationGroups: AbstractPermutationGroup, AbstractPerm, degree, SymmetricGroup
|
||||||
|
|
||||||
|
"""
|
||||||
|
WreathProduct(G::Group, P::AbstractPermutationGroup) <: Group
|
||||||
|
Return the wreath product of a group `G` by permutation group `P`, usually
|
||||||
|
written as `G ≀ P`.
|
||||||
|
|
||||||
|
As set `G ≀ P` is the same as `Gᵈ × P` and the group can be understood as a
|
||||||
|
semi-direct product of `P` acting on `d`-fold cartesian product of `G` by
|
||||||
|
permuting coordinates. To be more precise, the multiplication inside wreath
|
||||||
|
product is defined as
|
||||||
|
> `(n, σ) * (m, τ) = (n*(m^σ), σ*τ)`
|
||||||
|
where `m^σ` denotes the action (from the right) of the permutation `σ` on
|
||||||
|
`d`-tuples of elements from `G`.
|
||||||
|
"""
|
||||||
|
struct WreathProduct{DP<:DirectPower,PGr<:AbstractPermutationGroup} <:
|
||||||
|
GroupsCore.Group
|
||||||
|
N::DP
|
||||||
|
P::PGr
|
||||||
|
|
||||||
|
function WreathProduct(G::Group, P::AbstractPermutationGroup)
|
||||||
|
N = DirectPower{degree(P)}(G)
|
||||||
|
return new{typeof(N),typeof(P)}(N, P)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
struct WreathProductElement{
|
||||||
|
DPEl<:DirectPowerElement,
|
||||||
|
PEl<:AbstractPerm,
|
||||||
|
Wr<:WreathProduct,
|
||||||
|
} <: GroupsCore.GroupElement
|
||||||
|
n::DPEl
|
||||||
|
p::PEl
|
||||||
|
parent::Wr
|
||||||
|
|
||||||
|
function WreathProductElement(
|
||||||
|
n::DirectPowerElement,
|
||||||
|
p::AbstractPerm,
|
||||||
|
W::WreathProduct,
|
||||||
|
)
|
||||||
|
new{typeof(n),typeof(p),typeof(W)}(n, p, W)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.one(W::WreathProduct) = WreathProductElement(one(W.N), one(W.P), W)
|
||||||
|
|
||||||
|
Base.eltype(::Type{<:WreathProduct{DP,PGr}}) where {DP,PGr} =
|
||||||
|
WreathProductElement{eltype(DP),eltype(PGr),WreathProduct{DP,PGr}}
|
||||||
|
|
||||||
|
function Base.iterate(G::WreathProduct)
|
||||||
|
itr = Iterators.product(G.N, G.P)
|
||||||
|
res = iterate(itr)
|
||||||
|
@assert res !== nothing
|
||||||
|
elt = WreathProductElement(first(res)..., G)
|
||||||
|
return elt, (iterator = itr, state = last(res))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Base.iterate(G::WreathProduct, state)
|
||||||
|
itr, st = state.iterator, state.state
|
||||||
|
res = iterate(itr, st)
|
||||||
|
res === nothing && return nothing
|
||||||
|
elt = WreathProductElement(first(res)..., G)
|
||||||
|
return elt, (iterator = itr, state = last(res))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Base.IteratorSize(::Type{<:WreathProduct{DP,PGr}}) where {DP,PGr}
|
||||||
|
dpI = Base.IteratorSize(DP)
|
||||||
|
pgI = Base.IteratorSize(PGr)
|
||||||
|
|
||||||
|
if dpI isa Base.IsInfinite || pgI isa Base.IsInfinite
|
||||||
|
return Base.IsInfinite()
|
||||||
|
elseif dpI isa Base.SizeUnknown || pgI isa Base.SizeUnknown
|
||||||
|
return Base.SizeUnknown()
|
||||||
|
else
|
||||||
|
return Base.HasShape{2}()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.size(G::WreathProduct) = (length(G.N), length(G.P))
|
||||||
|
|
||||||
|
GroupsCore.order(::Type{I}, G::WreathProduct) where {I<:Integer} =
|
||||||
|
convert(I, order(I, G.N) * order(I, G.P))
|
||||||
|
|
||||||
|
function GroupsCore.gens(G::WreathProduct)
|
||||||
|
N_gens = [WreathProductElement(n, one(G.P), G) for n in gens(G.N)]
|
||||||
|
P_gens = [WreathProductElement(one(G.N), p, G) for p in gens(G.P)]
|
||||||
|
return [N_gens; P_gens]
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.isfinite(G::WreathProduct) = isfinite(G.N) && isfinite(G.P)
|
||||||
|
|
||||||
|
function Base.rand(
|
||||||
|
rng::Random.AbstractRNG,
|
||||||
|
rs::Random.SamplerTrivial{<:WreathProduct},
|
||||||
|
)
|
||||||
|
|
||||||
|
G = rs[]
|
||||||
|
return WreathProductElement(rand(rng, G.N), rand(rng, G.P), G)
|
||||||
|
end
|
||||||
|
|
||||||
|
GroupsCore.parent(g::WreathProductElement) = g.parent
|
||||||
|
|
||||||
|
Base.:(==)(g::WreathProductElement, h::WreathProductElement) =
|
||||||
|
parent(g) === parent(h) && g.n == h.n && g.p == h.p
|
||||||
|
|
||||||
|
Base.hash(g::WreathProductElement, h::UInt) =
|
||||||
|
hash(g.n, hash(g.p, hash(g.parent, h)))
|
||||||
|
|
||||||
|
function Base.deepcopy_internal(g::WreathProductElement, stackdict::IdDict)
|
||||||
|
return WreathProductElement(
|
||||||
|
Base.deepcopy_internal(g.n, stackdict),
|
||||||
|
Base.deepcopy_internal(g.p, stackdict),
|
||||||
|
parent(g),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
_act(p::AbstractPerm, n::DirectPowerElement) =
|
||||||
|
DirectPowerElement(n.elts^p, parent(n))
|
||||||
|
|
||||||
|
function Base.inv(g::WreathProductElement)
|
||||||
|
pinv = inv(g.p)
|
||||||
|
return WreathProductElement(_act(pinv, inv(g.n)), pinv, parent(g))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Base.:(*)(g::WreathProductElement, h::WreathProductElement)
|
||||||
|
@assert parent(g) === parent(h)
|
||||||
|
return WreathProductElement(g.n * _act(g.p, h.n), g.p * h.p, parent(g))
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.isone(g::WreathProductElement) = isone(g.n) && isone(g.p)
|
||||||
|
|
||||||
|
Base.show(io::IO, G::WreathProduct) =
|
||||||
|
print(io, "Wreath product of $(G.N.group) by $(G.P)")
|
||||||
|
Base.show(io::IO, g::WreathProductElement) = print(io, "( $(g.n)≀$(g.p) )")
|
||||||
|
|
||||||
|
Base.copy(g::WreathProductElement) = WreathProductElement(g.n, g.p, parent(g))
|
@ -1,11 +1,13 @@
|
|||||||
module MatrixGroups
|
module MatrixGroups
|
||||||
|
|
||||||
|
using StaticArrays
|
||||||
|
|
||||||
using GroupsCore
|
using GroupsCore
|
||||||
using Groups
|
using Groups
|
||||||
using KnuthBendix
|
using KnuthBendix
|
||||||
|
|
||||||
using LinearAlgebra # Identity matrix
|
import LinearAlgebra # Identity matrix
|
||||||
using Random # GroupsCore rand
|
import Random # GroupsCore rand
|
||||||
|
|
||||||
export SpecialLinearGroup, SymplecticGroup
|
export SpecialLinearGroup, SymplecticGroup
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
abstract type MatrixGroup{N, T} <: Groups.AbstractFPGroup end
|
abstract type MatrixGroup{N, T} <: Groups.AbstractFPGroup end
|
||||||
const MatrixGroupElement{N, T} = Groups.AbstractFPGroupElement{<:MatrixGroup{N, T}}
|
const MatrixGroupElement{N, T} = Groups.AbstractFPGroupElement{<:MatrixGroup{N, T}}
|
||||||
|
|
||||||
Base.isone(g::MatrixGroupElement{N, T}) where {N, T} = matrix_repr(g) == I
|
Base.isone(g::MatrixGroupElement{N, T}) where {N, T} =
|
||||||
|
isone(word(g)) || matrix_repr(g) == LinearAlgebra.I
|
||||||
|
|
||||||
function Base.:(==)(m1::M1, m2::M2) where {M1<:MatrixGroupElement, M2<:MatrixGroupElement}
|
function Base.:(==)(m1::M1, m2::M2) where {M1<:MatrixGroupElement, M2<:MatrixGroupElement}
|
||||||
parent(m1) === parent(m2) || return false
|
parent(m1) === parent(m2) || return false
|
||||||
@ -26,7 +27,9 @@ Base.getindex(sl::MatrixGroupElement, i, j) = matrix_repr(sl)[i,j]
|
|||||||
# Base.iterate(sl::MatrixGroupElement, state) = iterate(sl.elts, state)
|
# Base.iterate(sl::MatrixGroupElement, state) = iterate(sl.elts, state)
|
||||||
|
|
||||||
function matrix_repr(m::MatrixGroupElement{N, T}) where {N, T}
|
function matrix_repr(m::MatrixGroupElement{N, T}) where {N, T}
|
||||||
isempty(word(m)) && return StaticArrays.SMatrix{N, N, T}(I)
|
if isone(word(m))
|
||||||
|
return StaticArrays.SMatrix{N, N, T}(LinearAlgebra.I)
|
||||||
|
end
|
||||||
A = alphabet(parent(m))
|
A = alphabet(parent(m))
|
||||||
return prod(matrix_repr(A[l]) for l in word(m))
|
return prod(matrix_repr(A[l]) for l in word(m))
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
using Groups
|
|
||||||
using StaticArrays
|
|
||||||
|
|
||||||
struct ElementaryMatrix{N, T} <: Groups.GSymbol
|
struct ElementaryMatrix{N, T} <: Groups.GSymbol
|
||||||
i::Int
|
i::Int
|
||||||
j::Int
|
j::Int
|
||||||
@ -24,7 +21,7 @@ Base.inv(e::ElementaryMatrix{N}) where N =
|
|||||||
ElementaryMatrix{N}(e.i, e.j, -e.val)
|
ElementaryMatrix{N}(e.i, e.j, -e.val)
|
||||||
|
|
||||||
function matrix_repr(e::ElementaryMatrix{N, T}) where {N, T}
|
function matrix_repr(e::ElementaryMatrix{N, T}) where {N, T}
|
||||||
m = StaticArrays.MMatrix{N, N, T}(I)
|
m = StaticArrays.MMatrix{N, N, T}(LinearAlgebra.I)
|
||||||
m[e.i, e.j] = e.val
|
m[e.i, e.j] = e.val
|
||||||
x = StaticArrays.SMatrix{N, N}(m)
|
x = StaticArrays.SMatrix{N, N}(m)
|
||||||
return x
|
return x
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
using Groups
|
|
||||||
using StaticArrays
|
|
||||||
|
|
||||||
struct ElementarySymplectic{N, T} <: Groups.GSymbol
|
struct ElementarySymplectic{N, T} <: Groups.GSymbol
|
||||||
symbol::Symbol
|
symbol::Symbol
|
||||||
i::Int
|
i::Int
|
||||||
@ -69,7 +66,7 @@ Base.inv(s::ElementarySymplectic{N}) where N =
|
|||||||
function matrix_repr(s::ElementarySymplectic{N, T}) where {N, T}
|
function matrix_repr(s::ElementarySymplectic{N, T}) where {N, T}
|
||||||
@assert iseven(N)
|
@assert iseven(N)
|
||||||
n = div(N, 2)
|
n = div(N, 2)
|
||||||
m = StaticArrays.MMatrix{N, N, T}(I)
|
m = StaticArrays.MMatrix{N, N, T}(LinearAlgebra.I)
|
||||||
i,j = _ind(s)
|
i,j = _ind(s)
|
||||||
m[i,j] = s.val
|
m[i,j] = s.val
|
||||||
if s.symbol === :A
|
if s.symbol === :A
|
||||||
|
43
test/group_constructions.jl
Normal file
43
test/group_constructions.jl
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
@testset "GroupConstructions" begin
|
||||||
|
|
||||||
|
@testset "DirectProduct" begin
|
||||||
|
GH =
|
||||||
|
let G = PermutationGroups.SymmetricGroup(3),
|
||||||
|
H = PermutationGroups.SymmetricGroup(4)
|
||||||
|
|
||||||
|
Groups.Constructions.DirectProduct(G, H)
|
||||||
|
end
|
||||||
|
test_Group_interface(GH)
|
||||||
|
test_GroupElement_interface(rand(GH, 2)...)
|
||||||
|
|
||||||
|
@test collect(GH) isa Array{eltype(GH), 2}
|
||||||
|
@test contains(sprint(print, GH), "Direct product")
|
||||||
|
@test sprint(print, rand(GH)) isa String
|
||||||
|
end
|
||||||
|
|
||||||
|
@testset "DirectPower" begin
|
||||||
|
GGG = Groups.Constructions.DirectPower{3}(
|
||||||
|
PermutationGroups.SymmetricGroup(3),
|
||||||
|
)
|
||||||
|
test_Group_interface(GGG)
|
||||||
|
test_GroupElement_interface(rand(GGG, 2)...)
|
||||||
|
|
||||||
|
@test collect(GGG) isa Array{eltype(GGG), 3}
|
||||||
|
@test contains(sprint(print, GGG), "Direct 3-rd power")
|
||||||
|
@test sprint(print, rand(GGG)) isa String
|
||||||
|
end
|
||||||
|
@testset "WreathProduct" begin
|
||||||
|
W =
|
||||||
|
let G = PermutationGroups.SymmetricGroup(2),
|
||||||
|
P = PermutationGroups.SymmetricGroup(4)
|
||||||
|
|
||||||
|
Groups.Constructions.WreathProduct(G, P)
|
||||||
|
end
|
||||||
|
test_Group_interface(W)
|
||||||
|
test_GroupElement_interface(rand(W, 2)...)
|
||||||
|
|
||||||
|
@test collect(W) isa Array{eltype(W), 2}
|
||||||
|
@test contains(sprint(print, W), "Wreath product")
|
||||||
|
@test sprint(print, rand(W)) isa String
|
||||||
|
end
|
||||||
|
end
|
@ -33,6 +33,8 @@ include(joinpath(pathof(GroupsCore), "..", "..", "test", "conformance_test.jl"))
|
|||||||
include("AutSigma_41.jl")
|
include("AutSigma_41.jl")
|
||||||
include("AutSigma3.jl")
|
include("AutSigma3.jl")
|
||||||
|
|
||||||
|
include("group_constructions.jl")
|
||||||
|
|
||||||
# if !haskey(ENV, "CI")
|
# if !haskey(ENV, "CI")
|
||||||
# include("benchmarks.jl")
|
# include("benchmarks.jl")
|
||||||
# end
|
# end
|
||||||
|
Loading…
Reference in New Issue
Block a user