diff --git a/src/Groups.jl b/src/Groups.jl index 03fa1ec..a93c3f3 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -23,13 +23,13 @@ include("arithmetic.jl") include("findreplace.jl") module New -import Groups: AutSymbol, GSymbol, λ, ϱ, RTransvect, LTransvect using DataStructures include("new_types.jl") include("new_hashing.jl") include("normalform.jl") +include("new_transvections.jl") include("gersten_relations.jl") include("new_autgroups.jl") diff --git a/src/gersten_relations.jl b/src/gersten_relations.jl index ea86e6d..79014b8 100644 --- a/src/gersten_relations.jl +++ b/src/gersten_relations.jl @@ -1,12 +1,9 @@ function gersten_alphabet(n::Integer; commutative::Bool = true) - indexing = [[i, j] for i in 1:n for j in 1:n if i ≠ j] - rmuls = [ϱ(i, j) for (i, j) in indexing] + indexing = [(i, j) for i in 1:n for j in 1:n if i ≠ j] + S = [ϱ(i, j) for (i, j) in indexing] - S = if commutative - Vector{AutSymbol}(rmuls) - else - lmuls = [λ(i, j) for (i, j) in indexing] - AutSymbol[rmuls; lmuls] + if !commutative + append!(S, [λ(i, j) for (i, j) in indexing]) end return Alphabet(S) diff --git a/src/new_autgroups.jl b/src/new_autgroups.jl index a8da29a..aea1766 100644 --- a/src/new_autgroups.jl +++ b/src/new_autgroups.jl @@ -89,37 +89,13 @@ domain(f::FPGroupElement{<:AutomorphismGroup}) = deepcopy(parent(f).domain) evaluate(f::FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}) = evaluate!(domain(f), f) -function evaluate!(t::NTuple{N, T}, f::FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}) where {T<:FPGroupElement, N} +function evaluate!( + t::NTuple{N,T}, + f::FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}, +) where {T<:FPGroupElement,N} A = alphabet(f) for idx in word(f) - t = evaluate!(t, A[idx])::NTuple{N, T} + t = evaluate!(t, A[idx], alphabet(object(parent(f))))::NTuple{N,T} end return t end - -function evaluate!(v::NTuple{N, T}, s::AutSymbol) where {N, T} - @assert s.pow in (-1, 1) - return evaluate!(v, s.fn, isone(s.pow))::NTuple{N, T} -end - -function evaluate!(v, ϱ::RTransvect, flag) - if flag - append!(New.word(v[ϱ.i]), New.word(v[ϱ.j] )) - else - append!(New.word(v[ϱ.i]), New.word(v[ϱ.j]^-1)) - end - _setnormalform!(v[ϱ.i], false) - _setvalidhash!(v[ϱ.i], false) - return v -end - -function evaluate!(v, λ::LTransvect, flag) - if flag - prepend!(New.word(v[λ.i]), New.word(v[λ.j] )) - else - prepend!(New.word(v[λ.i]), New.word(v[λ.j]^-1)) - end - _setnormalform!(v[λ.i], false) - _setvalidhash!(v[λ.i], false) - return v -end diff --git a/src/new_transvections.jl b/src/new_transvections.jl new file mode 100644 index 0000000..3dd3832 --- /dev/null +++ b/src/new_transvections.jl @@ -0,0 +1,85 @@ +abstract type GSymbol end +Base.literal_pow(::typeof(^), t::GSymbol, ::Val{-1}) = inv(t) + +struct Transvection <: GSymbol + id::Symbol + ij::UInt8 + inv::Bool + + function Transvection(id::Symbol, i::Integer, j::Integer, inv=false) + @assert id in (:ϱ, :λ) + return new(id, _indices(UInt8(i),UInt8(j)), inv) + end +end + +ϱ(i, j) = Transvection(:ϱ, i, j) +λ(i, j) = Transvection(:λ, i, j) + +_indices(ij::UInt8) = (ij & 0xf0)>>4, (ij & 0x0f) + +function _indices(i::UInt8, j::UInt8) + @boundscheck @assert i < typemax(i) ÷ 2 + @boundscheck @assert j < typemax(j) ÷ 2 + sizeof + return (i << 4) + j +end + +indices(t::Transvection) = Int.(_indices(t.ij)) + +function Base.getproperty(t::Transvection, s::Symbol) + s === :i && return first(indices(t)) + s === :j && return last(indices(t)) + return Core.getfield(t, s) +end + +function Base.show(io::IO, t::Transvection) + id = if t.id === :ϱ + "ϱ" + else # if t.id === :λ + "λ" + end + # print(io, id, Groups.subscriptify(t.i), ".", Groups.subscriptify(t.j)) + print(io, id, "_", t.i, ",", t.j) + t.inv && print(io, "^-1") +end + +Base.inv(t::Transvection) = Transvection(t.id, _indices(t.ij)..., !t.inv) + +Base.:(==)(t::Transvection, s::Transvection) = + t.id === s.id && t.ij == s.ij && t.inv == s.inv +Base.hash(t::Transvection, h::UInt) = hash(t.id, hash(t.ij, hash(t.inv, h))) + +function evaluate!(v::Tuple, t::Transvection, A::Alphabet) + i, j = indices(t) + @assert i ≤ length(v) && j ≤ length(v) + + @inbounds begin + if t.id === :ϱ + if !t.inv + append!(word(v[i]), word(v[j])) + else + # append!(word(v[i]), inv(A, word(v[j]))) + for l in Iterators.reverse(word(v[j])) + push!(word(v[i]), inv(A, l)) + end + end + else # if t.id === :λ + if !t.inv + # prepend!(word(v[i]), word(v[j])) + for l in Iterators.reverse(word(v[j])) + pushfirst!(word(v[i]), l) + end + else + # prepend!(word(v[i]), inv(A, word(v[j]))) + for l in word(v[j]) + pushfirst!(word(v[i]), inv(A, l)) + end + end + end + + _setnormalform!(v[i], false) + _setvalidhash!(v[i], false) + end + + return v +end