Groups.jl/src/new_autgroups.jl

102 lines
2.7 KiB
Julia
Raw Normal View History

function KnuthBendix.Alphabet(S::AbstractVector{<:GSymbol})
S = unique!([S; inv.(S)])
inversions = [findfirst(==(inv(s)), S) for s in S]
return Alphabet(S, inversions)
end
struct AutomorphismGroup{G<:Group, T, R, S} <: AbstractFPGroup
group::G
gens::Vector{T}
rws::R
domain::S
end
object(G::AutomorphismGroup) = G.group
function SpecialAutomorphismGroup(F::FreeGroup;
ordering=KnuthBendix.LenLex, kwargs...)
n = length(KnuthBendix.alphabet(F))÷2
A, rels = gersten_relations(n, commutative=false)
S = KnuthBendix.letters(A)[1:2(n^2 - n)]
rws = KnuthBendix.RewritingSystem(rels, ordering(A))
KnuthBendix.knuthbendix!(rws; kwargs...)
return AutomorphismGroup(F, S, rws, ntuple(i->gens(F, i), n))
end
KnuthBendix.alphabet(G::AutomorphismGroup{<:FreeGroup}) = alphabet(rewriting(G))
rewriting(G::AutomorphismGroup) = G.rws
function relations(G::AutomorphismGroup)
n = length(KnuthBendix.alphabet(object(G)))÷2
return last(gersten_relations(n, commutative=false))
end
2021-05-16 22:27:54 +02:00
equality_data(f::FPGroupElement{<:AutomorphismGroup}) = normalform!.(evaluate(f))
function Base.:(==)(g::A, h::A) where A<:FPGroupElement{<:AutomorphismGroup}
@assert parent(g) === parent(h)
if _isvalidhash(g) && _isvalidhash(h)
hash(g) != hash(h) && return false
end
length(word(g)) > 8 && normalform!(g)
length(word(h)) > 8 && normalform!(h)
word(g) == word(h) && return true
img_computed, imh_computed = false, false
if !_isvalidhash(g)
2021-05-16 22:27:54 +02:00
img = equality_data(g)
_update_savedhash!(g, img)
img_computed = true
end
if !_isvalidhash(h)
2021-05-16 22:27:54 +02:00
imh = equality_data(h)
_update_savedhash!(h, imh)
imh_computed = true
end
@assert _isvalidhash(g)
@assert _isvalidhash(h)
hash(g) != hash(h) && return false
# words are different, but hashes agree
2021-05-16 22:27:54 +02:00
@sync begin
!img_computed && Threads.@spawn img = equality_data(g)
!imh_computed && Threads.@spawn imh = equality_data(h)
end
2021-05-16 22:27:54 +02:00
equal = img == imh
equal || @warn "hash collision in == :" g h
2021-05-16 22:27:54 +02:00
return equal
end
# eye-candy
Base.show(io::IO, ::Type{<:FPGroupElement{<:AutomorphismGroup{T}}}) where T <: FreeGroup = print(io, "Automorphism{$T}")
## Automorphism Evaluation
domain(f::FPGroupElement{<:AutomorphismGroup}) = deepcopy(parent(f).domain)
# tuple(gens(object(parent(f)))...)
evaluate(f::FPGroupElement{<:AutomorphismGroup{<:FreeGroup}}) =
evaluate!(domain(f), f)
2021-05-16 22:47:20 +02:00
function evaluate!(
t::NTuple{N,T},
f::FPGroupElement{<:AutomorphismGroup{<:FreeGroup}},
) where {T<:FPGroupElement,N}
A = alphabet(f)
for idx in word(f)
2021-05-16 22:47:20 +02:00
t = evaluate!(t, A[idx], alphabet(object(parent(f))))::NTuple{N,T}
end
return t
end