mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-09-13 08:25:39 +02:00
170 lines
4.4 KiB
Julia
170 lines
4.4 KiB
Julia
using Permutations
|
||
|
||
import Base: convert
|
||
export AutSymbol, AutWord, rmul_AutSymbol, lmul_AutSymbol, flip_AutSymbol, symmetric_AutSymbol
|
||
|
||
immutable AutSymbol <: GSymbol
|
||
gen::String
|
||
pow::Int
|
||
ex::Expr
|
||
func::Function
|
||
end
|
||
|
||
function (f::AutSymbol){T}(v::Vector{GWord{T}})
|
||
if f.pow == 0
|
||
return v
|
||
end
|
||
return f.func(v)
|
||
end
|
||
|
||
(==)(s::AutSymbol, t::AutSymbol) = s.gen == t.gen && s.pow == t.pow
|
||
hash(s::AutSymbol, h::UInt) = hash(s.gen, hash(s.pow, hash(:AutSymbol, h)))
|
||
|
||
IdSymbol(::Type{AutSymbol}) = AutSymbol("(id)", 0, :(id()), id)
|
||
|
||
function change_pow(s::AutSymbol, n::Int)
|
||
if n == 0
|
||
return one(s)
|
||
end
|
||
symbol = s.ex.args[1]
|
||
if symbol == :ɛ
|
||
return flip_AutSymbol(s.ex.args[2], pow=n)
|
||
elseif symbol == :σ
|
||
return symmetric_AutSymbol(s.ex.args[2], pow=n)
|
||
elseif symbol == :ϱ
|
||
s.ex.args[2:end-1]
|
||
return rmul_AutSymbol(s.ex.args[2:end-1]..., pow=n)
|
||
elseif symbol == :λ
|
||
return lmul_AutSymbol(s.ex.args[2:end-1]..., pow=n)
|
||
elseif symbol == :id
|
||
return s
|
||
else
|
||
warn("Changing an unknown type of symbol! $s")
|
||
return AutSymbol(s.gen, n, s.ex, s.func)
|
||
end
|
||
end
|
||
|
||
inv(f::AutSymbol) = change_pow(f, -f.pow)
|
||
|
||
function id()
|
||
return v -> v
|
||
end
|
||
|
||
function ϱ(i,j, pow=1)
|
||
# @assert i ≠ j
|
||
return v -> [(k==i ? v[i]*v[j]^pow : v[k]) for k in eachindex(v)]
|
||
end
|
||
|
||
function λ(i,j, pow=1)
|
||
# @assert i ≠ j
|
||
return v -> [(k==i ? v[j]^pow*v[i] : v[k]) for k in eachindex(v)]
|
||
end
|
||
|
||
function σ(perm, pow=1)
|
||
# @assert sort(perm) == collect(1:length(perm))
|
||
if pow == 1
|
||
return v -> [v[perm[k]] for k in eachindex(v)]
|
||
else
|
||
p = Permutations.Permutation(perm)
|
||
perm = array(p^pow)
|
||
return v -> [v[perm[k]] for k in eachindex(v)]
|
||
end
|
||
end
|
||
|
||
ɛ(i, pow=1) = v -> [(k==i ? v[k]^(-1*(2+pow%2)%2) : v[k]) for k in eachindex(v)]
|
||
|
||
# taken from ValidatedNumerics
|
||
function subscriptify(n::Int)
|
||
dig = reverse(digits(n))
|
||
subscript_0 = Int('₀') # 0x2080
|
||
join([Char(subscript_0 + i) for i in dig])
|
||
end
|
||
|
||
function rmul_AutSymbol(i,j; pow::Int=1)
|
||
gen = "ϱ"*subscriptify(i)*subscriptify(j)
|
||
return AutSymbol(gen, pow, :(ϱ($i,$j, $pow)), ϱ(i,j, pow))
|
||
end
|
||
|
||
function lmul_AutSymbol(i,j; pow::Int=1)
|
||
gen = "λ"*subscriptify(i)*subscriptify(j)
|
||
return AutSymbol(gen, pow, :(λ($i,$j, $pow)), λ(i,j, pow))
|
||
end
|
||
|
||
function flip_AutSymbol(j; pow::Int=1)
|
||
gen = "ɛ"*subscriptify(j)
|
||
return AutSymbol(gen, (2+pow%2)%2, :(ɛ($j, $pow)), ɛ(j,pow))
|
||
end
|
||
|
||
function symmetric_AutSymbol(perm::Vector{Int}; pow::Int=1)
|
||
perm = Permutations.Permutation(perm)
|
||
perm = perm^pow
|
||
p = array(perm)
|
||
if p == collect(1:length(p))
|
||
return one(AutSymbol)
|
||
else
|
||
gen = "σ"*join([subscriptify(i) for i in p])
|
||
return AutSymbol(gen, 1, :(σ($p, 1)), σ(p, 1))
|
||
end
|
||
end
|
||
|
||
function getperm(s::AutSymbol)
|
||
if s.ex.args[1] == :σ
|
||
return s.ex.args[2]
|
||
else
|
||
throw(ArgumentError("$s is not a permutation automorphism!"))
|
||
end
|
||
end
|
||
|
||
typealias AutWord GWord{AutSymbol}
|
||
|
||
function (F::AutWord)(v)
|
||
for f in F.symbols
|
||
v = f(v)
|
||
end
|
||
return v
|
||
end
|
||
|
||
convert(::Type{AutWord}, s::AutSymbol) = GWord(s)
|
||
|
||
function simplify_perms!(W::AutWord)
|
||
reduced = true
|
||
for i in 1:length(W.symbols) - 1
|
||
current = W.symbols[i]
|
||
if current.ex.args[1] == :σ
|
||
if current.pow != 1
|
||
current = symmetric_AutSymbol(perm(current), pow=current.pow)
|
||
end
|
||
next_s = W.symbols[i+1]
|
||
if next_s.ex.args[1] == :σ
|
||
reduced = false
|
||
if next_s.pow != 1
|
||
next_s = symmetric_AutSymbol(perm(next_s), pow=next_s.pow)
|
||
end
|
||
p1 = Permutation(getperm(current))
|
||
p2 = Permutation(getperm(next_s))
|
||
W.symbols[i] = one(AutSymbol)
|
||
W.symbols[i+1] = symmetric_AutSymbol(array(p1*p2))
|
||
end
|
||
end
|
||
end
|
||
deleteat!(W.symbols, find(x -> x.pow == 0, W.symbols))
|
||
return reduced
|
||
end
|
||
|
||
function reduce!(W::AutWord)
|
||
if length(W) < 2
|
||
deleteat!(W.symbols, find(x -> x.pow == 0, W.symbols))
|
||
else
|
||
reduced = false
|
||
while !reduced
|
||
reduced = simplify_perms!(W)
|
||
reduced = join_free_symbols!(W)
|
||
deleteat!(W.symbols, find(x -> x.pow == 0, W.symbols))
|
||
end
|
||
end
|
||
|
||
W.modified = false
|
||
W.savedhash = hash(W.symbols,hash(typeof(W)))
|
||
return W
|
||
end
|