Groups.jl/src/Groups.jl

163 lines
4.1 KiB
Julia

module Groups
using AbstractAlgebra
import AbstractAlgebra: Group, GroupElem, Ring
import AbstractAlgebra: parent, parent_type, elem_type
import AbstractAlgebra: order, gens, matrix_repr
import Base: length, ==, hash, show, convert, eltype, iterate
import Base: inv, reduce, *, ^, power_by_squaring
import Base: findfirst, findnext, findlast, findprev, replace
import Base: deepcopy_internal
using LinearAlgebra
using ThreadsX
export gens, FreeGroup, Aut, SAut
include("types.jl")
include("FreeGroup.jl")
include("FPGroups.jl")
include("AutGroup.jl")
include("symbols.jl")
include("fallbacks.jl")
include("words.jl")
include("hashing.jl")
include("freereduce.jl")
include("arithmetic.jl")
include("findreplace.jl")
include("DirectPower.jl")
include("WreathProducts.jl")
###############################################################################
#
# String I/O
#
function Base.show(io::IO, W::GWord)
if length(W) == 0
print(io, "(id)")
else
join(io, (string(s) for s in syllables(W)), "*")
end
end
function Base.show(io::IO, s::T) where {T<:GSymbol}
if s.pow == 1
print(io, string(s.id))
else
print(io, "$(s.id)^$(s.pow)")
end
end
###############################################################################
#
# Misc
#
"""
gens(G::AbstractFPGroups)
Return vector of generators of `G`, as its elements.
"""
AbstractAlgebra.gens(G::AbstractFPGroup) = G.(G.gens)
"""
wlmetric_ball(S::AbstractVector{<:GroupElem}
[, center=one(first(S)); radius=2, op=*])
Compute metric ball as a list of elements of non-decreasing length, given the
word-length metric on the group generated by `S`. The ball is centered at `center`
(by default: the identity element). `radius` and `op` keywords specify the
radius and multiplication operation to be used.
"""
function wlmetric_ball_serial(
S::AbstractVector{T};
radius = 2,
op = *,
) where {T<:Union{GroupElem,NCRingElem}}
old = unique!([one(first(S)), S...])
sizes = [1, length(old)]
for i = 2:radius
new = collect(op(o, s) for o in @view(old[sizes[end-1]:end]) for s in S)
append!(old, new)
resize!(new, 0)
old = unique!(old)
push!(sizes, length(old))
end
return old, sizes[2:end]
end
function wlmetric_ball_thr(
S::AbstractVector{T};
radius = 2,
op = *,
) where {T<:Union{GroupElem,NCRingElem}}
old = unique!([one(first(S)), S...])
sizes = [1, length(old)]
for r = 2:radius
begin
new = ThreadsX.collect(
op(o, s) for o in @view(old[sizes[end-1]:end]) for s in S
)
ThreadsX.foreach(hash, new)
end
append!(old, new)
resize!(new, 0)
old = ThreadsX.unique(old)
push!(sizes, length(old))
end
return old, sizes[2:end]
end
function wlmetric_ball_serial(
S::AbstractVector{T},
center::T;
radius = 2,
op = *,
) where {T<:Union{GroupElem,NCRingElem}}
E, sizes = wlmetric_ball_serial(S, radius = radius, op = op)
isone(center) && return E, sizes
return c .* E, sizes
end
function wlmetric_ball_thr(
S::AbstractVector{T},
center::T;
radius = 2,
op = *,
) where {T<:Union{GroupElem,NCRingElem}}
E, sizes = wlmetric_ball_thr(S, radius = radius, op = op)
isone(center) && return E, sizes
return c .* E, sizes
end
function wlmetric_ball(
S::AbstractVector{T},
center::T = one(first(S));
radius = 2,
op = *,
threading = true,
) where {T<:Union{GroupElem,NCRingElem}}
threading && return wlmetric_ball_thr(S, center, radius = radius, op = op)
return return wlmetric_ball_serial(S, center, radius = radius, op = op)
end
"""
image(w::GWord, homomorphism; kwargs...)
Evaluate homomorphism `homomorphism` on a group word (element) `w`.
`homomorphism` needs to implement
> `hom(w; kwargs...)`,
where `hom(;kwargs...)` returns the value at the identity element.
"""
function image(w::GWord, hom; kwargs...)
return reduce(
*,
(hom(s; kwargs...) for s in syllables(w)),
init = hom(; kwargs...),
)
end
end # of module Groups