63 lines
2.0 KiB
Julia
63 lines
2.0 KiB
Julia
|
"""
|
||
|
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}
|
||
|
@assert radius > 0
|
||
|
old = unique!([one(first(S)), S...])
|
||
|
sizes = [1, length(old)]
|
||
|
for i in 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}
|
||
|
@assert radius > 0
|
||
|
old = unique!([one(first(S)), S...])
|
||
|
sizes = [1, length(old)]
|
||
|
for r in 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}
|
||
|
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}
|
||
|
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}
|
||
|
threading && return wlmetric_ball_thr(S, center, radius = radius, op = op)
|
||
|
return wlmetric_ball_serial(S, center, radius = radius, op = op)
|
||
|
end
|