2021-06-07 20:26:18 +02:00
|
|
|
|
struct ΡΛ
|
|
|
|
|
id::Symbol
|
|
|
|
|
A::Alphabet
|
|
|
|
|
N::Int
|
2021-05-28 18:54:21 +02:00
|
|
|
|
end
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
function Base.getindex(rl::ΡΛ, i::Integer, j::Integer)
|
2021-08-13 13:51:45 +02:00
|
|
|
|
@assert 1 ≤ i ≤ rl.N "Got $i > $(rl.N)"
|
|
|
|
|
@assert 1 ≤ j ≤ rl.N "Got $j > $(rl.N)"
|
2021-06-07 20:26:18 +02:00
|
|
|
|
@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)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
@assert λ.N == ϱ.N
|
|
|
|
|
@assert λ.id == :λ && ϱ.id == :ϱ
|
2021-05-28 18:54:21 +02:00
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
N = λ.N
|
2021-05-28 18:54:21 +02:00
|
|
|
|
@assert iseven(N)
|
2021-08-13 13:51:45 +02:00
|
|
|
|
A = λ.A
|
2021-05-28 18:54:21 +02:00
|
|
|
|
n = N ÷ 2
|
|
|
|
|
j = i + 1
|
|
|
|
|
|
2021-08-13 13:51:45 +02:00
|
|
|
|
if i == n
|
|
|
|
|
τ = rotation_element(λ, ϱ)
|
2022-10-13 23:27:50 +02:00
|
|
|
|
return inv(τ, A) * Te_diagonal(λ, ϱ, 1) * τ
|
2021-08-13 13:51:45 +02:00
|
|
|
|
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
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
g = one(Word(Int[]))
|
2021-07-21 16:26:22 +02:00
|
|
|
|
g *= λ[NJ, NI] # β ↦ α*β
|
2022-10-13 23:27:50 +02:00
|
|
|
|
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
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
return g
|
2021-05-28 18:54:21 +02:00
|
|
|
|
end
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
function Te_lantern(A::Alphabet, b₀::T, a₁::T, a₂::T, a₃::T, a₄::T, a₅::T) where {T}
|
2022-10-13 23:27:50 +02:00
|
|
|
|
a₀ = (a₁ * a₂ * a₃)^4 * inv(b₀, A)
|
2021-08-13 13:51:45 +02:00
|
|
|
|
X = a₄ * a₅ * a₃ * a₄ # from Primer
|
2022-10-13 23:27:50 +02:00
|
|
|
|
b₁ = inv(X, A) * a₀ * X # from Primer
|
2021-05-28 18:54:21 +02:00
|
|
|
|
Y = a₂ * a₃ * a₁ * a₂
|
2022-10-13 23:27:50 +02:00
|
|
|
|
return inv(Y, A) * b₁ * Y # b₂ from Primer
|
2021-05-28 18:54:21 +02:00
|
|
|
|
end
|
|
|
|
|
|
2021-08-13 13:51:45 +02:00
|
|
|
|
function Ta(λ::Groups.ΡΛ, i::Integer)
|
2022-10-13 23:27:50 +02:00
|
|
|
|
@assert λ.id == :λ
|
|
|
|
|
return λ[mod1(λ.N - 2i + 1, λ.N), mod1(λ.N - 2i + 2, λ.N)]
|
2021-08-13 13:51:45 +02:00
|
|
|
|
end
|
2021-07-21 16:26:22 +02:00
|
|
|
|
|
2021-08-13 13:51:45 +02:00
|
|
|
|
function Tα(λ::Groups.ΡΛ, i::Integer)
|
2022-10-13 23:27:50 +02:00
|
|
|
|
@assert λ.id == :λ
|
|
|
|
|
return inv(λ[mod1(λ.N - 2i + 2, λ.N), mod1(λ.N - 2i + 1, λ.N)], λ.A)
|
2021-08-13 13:51:45 +02:00
|
|
|
|
end
|
2021-05-28 18:54:21 +02:00
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
function Te(λ::ΡΛ, ϱ::ΡΛ, i, j)
|
2021-05-28 18:54:21 +02:00
|
|
|
|
@assert i ≠ j
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
@assert λ.N == ϱ.N
|
|
|
|
|
@assert λ.A == ϱ.A
|
|
|
|
|
@assert λ.id == :λ && ϱ.id == :ϱ
|
2021-05-28 18:54:21 +02:00
|
|
|
|
|
2021-08-13 13:51:45 +02:00
|
|
|
|
@assert iseven(λ.N)
|
2022-10-14 01:14:38 +02:00
|
|
|
|
genus = λ.N ÷ 2
|
2021-08-13 13:51:45 +02:00
|
|
|
|
i = mod1(i, genus)
|
|
|
|
|
j = mod1(j, genus)
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
@assert 1 ≤ i ≤ λ.N
|
|
|
|
|
@assert 1 ≤ j ≤ λ.N
|
2021-05-28 18:54:21 +02:00
|
|
|
|
|
2021-08-13 13:51:45 +02:00
|
|
|
|
A = λ.A
|
|
|
|
|
|
|
|
|
|
if mod(j - (i + 1), genus) == 0
|
2021-06-07 20:26:18 +02:00
|
|
|
|
return Te_diagonal(λ, ϱ, i)
|
2021-05-28 18:54:21 +02:00
|
|
|
|
else
|
2022-10-13 23:27:50 +02:00
|
|
|
|
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
|
|
|
|
|
|
2021-08-13 13:51:45 +02:00
|
|
|
|
"""
|
|
|
|
|
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
|
2021-08-13 13:51:45 +02:00
|
|
|
|
A = λ.A
|
|
|
|
|
|
|
|
|
|
halftwists = map(1:genus-1) do i
|
|
|
|
|
j = i + 1
|
2022-10-13 23:27:50 +02:00
|
|
|
|
x = Ta(λ, j) * inv(Ta(λ, i), A) * Tα(λ, j) * Te_diagonal(λ, ϱ, i)
|
|
|
|
|
δ = x * Tα(λ, i) * inv(x, A)
|
2021-08-13 13:51:45 +02:00
|
|
|
|
c =
|
2022-10-13 23:27:50 +02:00
|
|
|
|
inv(Ta(λ, j), A) *
|
2021-08-13 13:51:45 +02:00
|
|
|
|
Te(λ, ϱ, i, j) *
|
|
|
|
|
Tα(λ, i)^2 *
|
2022-10-13 23:27:50 +02:00
|
|
|
|
inv(δ, A) *
|
|
|
|
|
inv(Ta(λ, j), A) *
|
2021-08-13 13:51:45 +02:00
|
|
|
|
Ta(λ, i) *
|
|
|
|
|
δ
|
|
|
|
|
z =
|
|
|
|
|
Te_diagonal(λ, ϱ, i) *
|
2022-10-13 23:27:50 +02:00
|
|
|
|
inv(Ta(λ, i), A) *
|
2021-08-13 13:51:45 +02:00
|
|
|
|
Tα(λ, i) *
|
|
|
|
|
Ta(λ, i) *
|
2022-10-13 23:27:50 +02:00
|
|
|
|
inv(Te_diagonal(λ, ϱ, i), A)
|
2021-08-13 13:51:45 +02:00
|
|
|
|
|
2022-10-13 23:27:50 +02:00
|
|
|
|
Ta(λ, i) * inv(Ta(λ, j) * Tα(λ, j), A)^6 * (Ta(λ, j) * Tα(λ, j) * z)^4 * c
|
2021-08-13 13:51:45 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
τ = (Ta(λ, 1) * Tα(λ, 1))^6 * prod(halftwists)
|
|
|
|
|
return τ
|
|
|
|
|
end
|
|
|
|
|
|
2021-07-07 10:32:13 +02:00
|
|
|
|
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)
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
λ = ΡΛ(:λ, A, 2genus)
|
|
|
|
|
ϱ = ΡΛ(:ϱ, A, 2genus)
|
2021-05-28 18:54:21 +02:00
|
|
|
|
|
2021-06-07 20:26:18 +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
|
|
|
|
|
2021-06-07 20:26:18 +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
|
2021-06-07 20:26:18 +02:00
|
|
|
|
|
2022-10-14 01:14:38 +02:00
|
|
|
|
struct SymplecticMappingClass{T,F} <: GSymbol
|
2021-06-07 20:26:18 +02:00
|
|
|
|
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
|
2021-06-07 20:26:18 +02:00
|
|
|
|
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)
|
|
|
|
|
|
2021-06-07 20:26:18 +02:00
|
|
|
|
function SymplecticMappingClass(
|
2021-08-13 13:55:35 +02:00
|
|
|
|
sautFn::AutomorphismGroup{<:FreeGroup},
|
2021-06-07 20:26:18 +02:00
|
|
|
|
id::Symbol,
|
|
|
|
|
i::Integer,
|
|
|
|
|
j::Integer;
|
2022-10-14 01:14:38 +02:00
|
|
|
|
minus=false,
|
|
|
|
|
inverse=false
|
2021-06-07 20:26:18 +02:00
|
|
|
|
)
|
|
|
|
|
@assert i > 0 && j > 0
|
|
|
|
|
id === :A && @assert i ≠ j
|
2021-08-13 13:55:35 +02:00
|
|
|
|
@assert iseven(ngens(object(sautFn)))
|
2022-10-14 01:14:38 +02:00
|
|
|
|
genus = ngens(object(sautFn)) ÷ 2
|
2021-06-07 20:26:18 +02:00
|
|
|
|
|
2021-08-13 13:55:35 +02:00
|
|
|
|
A = alphabet(sautFn)
|
|
|
|
|
λ = ΡΛ(:λ, A, 2genus)
|
|
|
|
|
ϱ = ΡΛ(:ϱ, A, 2genus)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
|
|
|
|
|
w = if id === :A
|
|
|
|
|
Te(λ, ϱ, i, j) *
|
2022-10-13 23:27:50 +02:00
|
|
|
|
inv(Ta(λ, i), A) *
|
2021-06-07 20:26:18 +02:00
|
|
|
|
Tα(λ, i) *
|
|
|
|
|
Ta(λ, i) *
|
2022-10-13 23:27:50 +02:00
|
|
|
|
inv(Te(λ, ϱ, i, j), A) *
|
|
|
|
|
inv(Tα(λ, i), A) *
|
|
|
|
|
inv(Ta(λ, j), A)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
elseif id === :B
|
|
|
|
|
if !minus
|
|
|
|
|
if i ≠ j
|
2022-10-13 23:27:50 +02:00
|
|
|
|
x = Ta(λ, j) * inv(Ta(λ, i), A) * Tα(λ, j) * Te(λ, ϱ, i, j)
|
|
|
|
|
δ = x * Tα(λ, i) * inv(x, A)
|
|
|
|
|
Tα(λ, i) * Tα(λ, j) * inv(δ, A)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
else
|
2022-10-13 23:27:50 +02:00
|
|
|
|
inv(Tα(λ, i), A)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
if i ≠ j
|
2022-10-13 23:27:50 +02:00
|
|
|
|
Ta(λ, i) * Ta(λ, j) * inv(Te(λ, ϱ, i, j), A)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
else
|
|
|
|
|
Ta(λ, i)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
throw("Type not recognized: $id")
|
|
|
|
|
end
|
|
|
|
|
|
2021-08-13 13:55:35 +02:00
|
|
|
|
# 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-06-07 20:26:18 +02:00
|
|
|
|
|
2021-07-17 20:11:32 +02:00
|
|
|
|
f = compiled(a)
|
|
|
|
|
# f = t -> evaluate!(t, a)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
|
2021-08-13 13:55:35 +02:00
|
|
|
|
res = SymplecticMappingClass(id, UInt(i), UInt(j), minus, inverse, a, f)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
|
|
|
|
|
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
|
2021-06-07 20:26:18 +02:00
|
|
|
|
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)
|
2021-08-13 13:55:35 +02:00
|
|
|
|
return SymplecticMappingClass(m.id, m.i, m.j, m.minus, !m.inv, inv_w, f)
|
2021-06-07 20:26:18 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function evaluate!(
|
|
|
|
|
t::NTuple{N,T},
|
|
|
|
|
smc::SymplecticMappingClass,
|
2021-08-13 13:48:25 +02:00
|
|
|
|
tmp=nothing,
|
2021-06-07 20:26:18 +02:00
|
|
|
|
) where {N,T}
|
2021-08-13 13:55:35 +02:00
|
|
|
|
t = smc.f(t)
|
|
|
|
|
for i in 1:N
|
|
|
|
|
normalform!(t[i])
|
2021-07-07 10:36:40 +02:00
|
|
|
|
end
|
2021-08-13 13:55:35 +02:00
|
|
|
|
return t
|
2021-07-07 10:36:40 +02:00
|
|
|
|
end
|