make LettersMap a bit safer to use

This commit is contained in:
Marek Kaluba 2024-02-12 11:34:51 +01:00
parent 22cf6297a9
commit 8137e40998
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
1 changed files with 26 additions and 21 deletions

View File

@ -138,43 +138,47 @@ end
# forward evaluate by substitution # forward evaluate by substitution
struct LettersMap{T,A} struct LettersMap{W<:AbstractWord,A}
indices_map::Dict{Int,T} indices_map::Dict{Int,W}
A::A A::A
end end
function LettersMap(a::FPGroupElement{<:AutomorphismGroup}) function LettersMap(a::FPGroupElement{<:AutomorphismGroup})
dom = domain(a) dom = domain(a)
@assert all(isone length word, dom) if all(isone length word, dom)
A = alphabet(first(dom)) A = alphabet(first(dom))
first_letters = first.(word.(dom)) first_letters = first.(word.(dom))
img = evaluate!(dom, a) img = evaluate!(dom, a)
# (dom[i] → img[i] is a map from domain to images) # (dom[i] → img[i] is a map from domain to images)
# we need a map from alphabet indices → (gens, gens⁻¹) → images # we need a map from alphabet indices → (gens, gens⁻¹) → images
# here we do it for elements of the domain # here we do it for elements of the domain
# (trusting it's a set of generators that define a) # (trusting it's a set of generators that define a)
@assert length(dom) == length(img) @assert length(dom) == length(img)
indices_map = indices_map =
Dict(A[A[fl]] => word(im) for (fl, im) in zip(first_letters, img)) Dict(Int(fl) => word(im) for (fl, im) in zip(first_letters, img))
# inverses of generators are dealt lazily in getindex # inverses of generators are dealt lazily in getindex
else
throw("LettersMap is not implemented for non-generators in domain")
end
return LettersMap(indices_map, A) return LettersMap(indices_map, A)
end end
function Base.getindex(lm::LettersMap, i::Integer) function Base.getindex(lm::LettersMap{W}, i::Integer) where {W}
# here i is an index of an alphabet # here i is an index of an alphabet
@boundscheck 1 i length(lm.A) @boundscheck 1 i length(lm.A)
if !haskey(lm.indices_map, i) if !haskey(lm.indices_map, i)
img = if haskey(lm.indices_map, inv(i, lm.A)) I = inv(i, lm.A)
inv(lm.indices_map[inv(i, lm.A)], lm.A) if haskey(lm.indices_map, I)
img = inv(lm.indices_map[I], lm.A)
lm.indices_map[i] = img
else else
@warn "LetterMap: neither $i nor its inverse has assigned value" lm.indices_map[i] = W([i])
one(valtype(lm.indices_map)) lm.indices_map[I] = W([I])
end end
lm.indices_map[i] = img
end end
return lm.indices_map[i] return lm.indices_map[i]
end end
@ -185,9 +189,10 @@ function (a::FPGroupElement{<:AutomorphismGroup})(g::FPGroupElement)
return parent(g)(img_w) return parent(g)(img_w)
end end
evaluate(w::AbstractWord, lm::LettersMap) = evaluate!(one(w), w, lm) evaluate(w::AbstractWord, lm::LettersMap) = evaluate!(similar(w), w, lm)
function evaluate!(res::AbstractWord, w::AbstractWord, lm::LettersMap) function evaluate!(res::AbstractWord, w::AbstractWord, lm::LettersMap)
resize!(res, 0)
for i in w for i in w
append!(res, lm[i]) append!(res, lm[i])
end end