Groups.jl/src/aut_groups/symplectic_twists.jl

270 lines
6.9 KiB
Julia
Raw Normal View History

struct ΡΛ
id::Symbol
A::Alphabet
N::Int
2021-05-28 18:54:21 +02:00
end
function Base.getindex(rl::ΡΛ, i::Integer, j::Integer)
@assert 1 i rl.N "Got $i > $(rl.N)"
@assert 1 j rl.N "Got $j > $(rl.N)"
@assert i j
@assert rl.id (, :ϱ)
rl.id == && return Word([rl.A[λ(i, j)]])
rl.id == :ϱ && return Word([rl.A[ϱ(i, j)]])
end
2021-05-28 18:54:21 +02:00
2021-07-21 16:26:22 +02:00
function Te_diagonal(λ::Groups.ΡΛ, ϱ::Groups.ΡΛ, i::Integer)
@assert λ.N == ϱ.N
@assert λ.id == && ϱ.id == :ϱ
2021-05-28 18:54:21 +02:00
N = λ.N
2021-05-28 18:54:21 +02:00
@assert iseven(N)
A = λ.A
2021-05-28 18:54:21 +02:00
n = N ÷ 2
j = i + 1
if i == n
τ = rotation_element(λ, ϱ)
return inv(τ, A) * Te_diagonal(λ, ϱ, 1) * τ
end
@assert 1 <= i < n
2021-05-28 18:54:21 +02:00
2021-07-21 16:26:22 +02:00
NI = (2n - 2i) + 1
NJ = (2n - 2j) + 1
I = (2n - 2i) + 2
J = (2n - 2j) + 2
g = one(Word(Int[]))
2021-07-21 16:26:22 +02:00
g *= λ[NJ, NI] # β ↦ α
g *= λ[NI, I] * inv(ϱ[NI, J], A) # α ↦ a*α*b^-1
g *= inv(λ[NJ, NI], A) # β ↦ b*α^-1*a^-1*α
g *= λ[J, NI] * inv(λ[J, I], A) # b ↦ α
g *= inv(λ[J, NI], A) # b ↦ b*α^-1*a^-1*α
g *= inv(ϱ[J, NI], A) * ϱ[J, I] # b ↦ b*α^-1*a^-1*α*b*α^-1
2021-07-21 16:26:22 +02:00
g *= ϱ[J, NI] # b ↦ b*α^-1*a^-1*α*b*α^-1*a*α*b^-1
return g
2021-05-28 18:54:21 +02:00
end
function Te_lantern(A::Alphabet, b₀::T, a₁::T, a₂::T, a₃::T, a₄::T, a₅::T) where {T}
a₀ = (a₁ * a₂ * a₃)^4 * inv(b₀, A)
X = a₄ * a₅ * a₃ * a₄ # from Primer
b₁ = inv(X, A) * a₀ * X # from Primer
2021-05-28 18:54:21 +02:00
Y = a₂ * a₃ * a₁ * a₂
return inv(Y, A) * b₁ * Y # b₂ from Primer
2021-05-28 18:54:21 +02:00
end
function Ta(λ::Groups.ΡΛ, i::Integer)
@assert λ.id ==
return λ[mod1(λ.N - 2i + 1, λ.N), mod1(λ.N - 2i + 2, λ.N)]
end
2021-07-21 16:26:22 +02:00
function Tα(λ::Groups.ΡΛ, i::Integer)
@assert λ.id ==
return inv(λ[mod1(λ.N - 2i + 2, λ.N), mod1(λ.N - 2i + 1, λ.N)], λ.A)
end
2021-05-28 18:54:21 +02:00
function Te(λ::ΡΛ, ϱ::ΡΛ, i, j)
2021-05-28 18:54:21 +02:00
@assert i j
@assert λ.N == ϱ.N
@assert λ.A == ϱ.A
@assert λ.id == && ϱ.id == :ϱ
2021-05-28 18:54:21 +02:00
@assert iseven(λ.N)
2022-10-14 01:14:38 +02:00
genus = λ.N ÷ 2
i = mod1(i, genus)
j = mod1(j, genus)
@assert 1 i λ.N
@assert 1 j λ.N
2021-05-28 18:54:21 +02:00
A = λ.A
if mod(j - (i + 1), genus) == 0
return Te_diagonal(λ, ϱ, i)
2021-05-28 18:54:21 +02:00
else
return inv(Te_lantern(
A,
# Our notation: # Primer notation:
inv(Ta(λ, i + 1), A), # b₀
inv(Ta(λ, i), A), # a₁
inv(Tα(λ, i), A), # a₂
inv(Te_diagonal(λ, ϱ, i), A), # a₃
inv(Tα(λ, i + 1), A), # a₄
inv(Te(λ, ϱ, i + 1, j), A), # a₅
), A)
2021-05-28 18:54:21 +02:00
end
end
"""
rotation_element(G::AutomorphismGroup{<:FreeGroup})
Return the element of `G` which corresponds to shifting generators of the free group.
In the corresponding mapping class group this element acts by rotation of the surface anti-clockwise.
"""
function rotation_element(G::AutomorphismGroup{<:FreeGroup})
A = alphabet(G)
@assert iseven(ngens(object(G)))
genus = ngens(object(G)) ÷ 2
λ = ΡΛ(, A, 2genus)
ϱ = ΡΛ(:ϱ, A, 2genus)
return G(rotation_element(λ, ϱ))
end
function rotation_element(λ::ΡΛ, ϱ::ΡΛ)
@assert iseven(λ.N)
2022-10-14 01:14:38 +02:00
genus = λ.N ÷ 2
A = λ.A
halftwists = map(1:genus-1) do i
j = i + 1
x = Ta(λ, j) * inv(Ta(λ, i), A) * Tα(λ, j) * Te_diagonal(λ, ϱ, i)
δ = x * Tα(λ, i) * inv(x, A)
c =
inv(Ta(λ, j), A) *
Te(λ, ϱ, i, j) *
Tα(λ, i)^2 *
inv(δ, A) *
inv(Ta(λ, j), A) *
Ta(λ, i) *
δ
z =
Te_diagonal(λ, ϱ, i) *
inv(Ta(λ, i), A) *
Tα(λ, i) *
Ta(λ, i) *
inv(Te_diagonal(λ, ϱ, i), A)
Ta(λ, i) * inv(Ta(λ, j) * Tα(λ, j), A)^6 * (Ta(λ, j) * Tα(λ, j) * z)^4 * c
end
τ = (Ta(λ, 1) * Tα(λ, 1))^6 * prod(halftwists)
return τ
end
function mcg_twists(G::AutomorphismGroup{<:FreeGroup})
@assert iseven(ngens(object(G)))
genus = ngens(object(G)) ÷ 2
2021-05-28 18:54:21 +02:00
genus < 3 && throw("Not Implemented: genus = $genus < 3")
A = KnuthBendix.alphabet(G)
λ = ΡΛ(, A, 2genus)
ϱ = ΡΛ(:ϱ, A, 2genus)
2021-05-28 18:54:21 +02:00
Tas = [Ta(λ, i) for i in 1:genus]
Tαs = [Tα(λ, i) for i in 1:genus]
2021-05-28 18:54:21 +02:00
idcs = ((i, j) for i in 1:genus for j in i+1:genus)
Tes = [Te(λ, ϱ, i, j) for (i, j) in idcs]
2021-05-28 18:54:21 +02:00
return Tas, Tαs, Tes
end
2022-10-14 01:14:38 +02:00
struct SymplecticMappingClass{T,F} <: GSymbol
id::Symbol # :A, :B
i::UInt
j::UInt
minus::Bool
inv::Bool
2021-07-12 11:11:39 +02:00
autFn_word::T
f::F
end
2021-07-12 11:11:39 +02:00
Base.:(==)(a::SymplecticMappingClass, b::SymplecticMappingClass) = a.autFn_word == b.autFn_word
Base.hash(a::SymplecticMappingClass, h::UInt) = hash(a.autFn_word, h)
function SymplecticMappingClass(
sautFn::AutomorphismGroup{<:FreeGroup},
id::Symbol,
i::Integer,
j::Integer;
2022-10-14 01:14:38 +02:00
minus=false,
inverse=false
)
@assert i > 0 && j > 0
id === :A && @assert i j
@assert iseven(ngens(object(sautFn)))
2022-10-14 01:14:38 +02:00
genus = ngens(object(sautFn)) ÷ 2
A = alphabet(sautFn)
λ = ΡΛ(, A, 2genus)
ϱ = ΡΛ(:ϱ, A, 2genus)
w = if id === :A
Te(λ, ϱ, i, j) *
inv(Ta(λ, i), A) *
Tα(λ, i) *
Ta(λ, i) *
inv(Te(λ, ϱ, i, j), A) *
inv(Tα(λ, i), A) *
inv(Ta(λ, j), A)
elseif id === :B
if !minus
if i j
x = Ta(λ, j) * inv(Ta(λ, i), A) * Tα(λ, j) * Te(λ, ϱ, i, j)
δ = x * Tα(λ, i) * inv(x, A)
Tα(λ, i) * Tα(λ, j) * inv(δ, A)
else
inv(Tα(λ, i), A)
end
else
if i j
Ta(λ, i) * Ta(λ, j) * inv(Te(λ, ϱ, i, j), A)
else
Ta(λ, i)
end
end
else
throw("Type not recognized: $id")
end
# w is a word defined in the context of A (= alphabet(sautFn))
# so this "coercion" is correct
2021-07-12 11:11:39 +02:00
a = sautFn(w)
2021-07-17 20:11:32 +02:00
f = compiled(a)
# f = t -> evaluate!(t, a)
res = SymplecticMappingClass(id, UInt(i), UInt(j), minus, inverse, a, f)
return res
end
function Base.show(io::IO, smc::SymplecticMappingClass)
smc.minus && print(io, 'm')
2022-10-14 01:14:38 +02:00
if smc.i < 10 && smc.j < 10
print(io, smc.id, subscriptify(smc.i), subscriptify(smc.j))
else
print(io, smc.id, subscriptify(smc.i), ".", subscriptify(smc.j))
end
smc.inv && print(io, "^-1")
end
function Base.inv(m::SymplecticMappingClass)
2021-07-12 11:11:39 +02:00
inv_w = inv(m.autFn_word)
2021-07-17 20:11:32 +02:00
# f(t) = evaluate!(t, inv_w)
f = compiled(inv_w)
return SymplecticMappingClass(m.id, m.i, m.j, m.minus, !m.inv, inv_w, f)
end
function evaluate!(
t::NTuple{N,T},
smc::SymplecticMappingClass,
2021-08-13 13:48:25 +02:00
tmp=nothing,
) where {N,T}
t = smc.f(t)
for i in 1:N
normalform!(t[i])
end
return t
end