49 lines
1.6 KiB
Julia
49 lines
1.6 KiB
Julia
"""
|
|
wlmetric_ball(S::AbstractVector{<:GroupElem}
|
|
[, center=one(first(S)); radius=2, op=*, threading=true])
|
|
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(
|
|
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
|
|
|
|
function wlmetric_ball_serial(S::AbstractVector{T}, center::T=one(first(S)); radius=2, op=*) where {T}
|
|
@assert radius >= 1
|
|
old = union!([center], [center * s for s in S])
|
|
return _wlmetric_ball(S, old, radius, op, collect, unique!)
|
|
end
|
|
|
|
function wlmetric_ball_thr(S::AbstractVector{T}, center::T=one(first(S)); radius=2, op=*) where {T}
|
|
@assert radius >= 1
|
|
old = union!([center], [center * s for s in S])
|
|
return _wlmetric_ball(S, old, radius, op, Folds.collect, Folds.unique)
|
|
end
|
|
|
|
function _wlmetric_ball(S, old, radius, op, collect, unique)
|
|
sizes = [1, length(old)]
|
|
for r in 2:radius
|
|
old = let old = old, S = S,
|
|
new = collect(
|
|
(g = op(o, s); hash(g); g)
|
|
for o in @view(old[sizes[end-1]:end]) for s in S
|
|
)
|
|
|
|
append!(old, new)
|
|
unique(old)
|
|
end
|
|
push!(sizes, length(old))
|
|
end
|
|
return old, sizes[2:end]
|
|
end
|
|
|