add Roots.jl, SpNs.jl, actions and their tests

This commit is contained in:
kalmarek 2019-04-03 00:47:40 +02:00
parent a09ad8dd7e
commit 84945d3b5c
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
4 changed files with 325 additions and 0 deletions

59
src/Roots.jl Normal file
View File

@ -0,0 +1,59 @@
module Roots
using StaticArrays
using LinearAlgebra
export Root, isproportional, isorthogonal, ~,
abstract type AbstractRoot end
struct Root{N} <: AbstractRoot
coord::SVector{N, Float64}
Root(a::SVector{N}) where N = new{N}(a)
end
Root(a) = Root(SVector(a...))
function Base.:(==)(r::Root{N}, s::Root{M}) where {M, N}
M == N || return false
r.coord == s.coord || return false
return true
end
Base.hash(r::Root, h::UInt) = hash(Root, hash(r.coord, h))
Base.:+(r::Root{N}, s::Root{N}) where N = Root(r.coord+s.coord)
Base.:-(r::Root{N}, s::Root{N}) where N = Root(r.coord-s.coord)
Base.:-(r::Root{N}) where N = Root(-r.coord)
Base.:*(a::Number, r::Root) = Root(a*r.coord)
Base.:*(r::Root, a::Number) = a*r
Base.length(r::Root) = norm(r, 2)
LinearAlgebra.norm(r::Root, p::Real=2) = norm(r.coord, p)
LinearAlgebra.dot(r::Root{N}, s::Root{N}) where N = dot(r.coord, s.coord)
cos_angle(a,b) = dot(a, b) / (norm(a) * norm(b))
function isproportional(α::Root{N}, β::Root{N}) where N
return isapprox(abs(cos_angle(α, β)), 1.0, atol=eps(1.0))
end
Base.:~(α::Root{N}, β::Root{N}) where N = isproportional(α, β)
function isorthogonal(α::Root{N}, β::Root{N}) where N
return isapprox(cos_angle(α, β), 0.0, atol=eps(1.0))
end
(α::Root{N}, β::Root{N}) where N = isorthogonal(α, β)
function Base.show(io::IO, r::Root{N}) where N
print(io, "$(r.coord): root of length $(norm(r))")
end
E(N, i::Integer) = Root(ntuple(k -> k == i ? 1 : 0, N))
end # of module RootSystems

39
src/SpN_actions.jl Normal file
View File

@ -0,0 +1,39 @@
function blkdiag(A, B)
new_size = (size(A,1) + size(B,1), size(A,2) + size(B,2))
res = zeros(eltype(A), new_size)
res[1:size(A,1), 1:size(A,2)] .= A
res[size(A,1)+1:end, size(A,2)+1:end] .= B
return res
end
function matrix_emb(n::DirectPowerGroupElem, p::perm)
Id = parent(n.elts[1])()
elt = Diagonal([(-1)^(el == Id ? 0 : 1) for el in n.elts])
elt = elt[:, p.d]
return blkdiag(elt, elt)
end
function (g::WreathProductElem)(A::MatElem)
g_inv = inv(g)
G = matrix_emb(g.n, g_inv.p)
G_inv = matrix_emb(g_inv.n, g.p)
M = parent(A)
return M(G)*A*M(G_inv)
end
function Base.:*(x::AbstractAlgebra.MatElem, P::Generic.perm)
z = similar(x)
m = nrows(x)
n = ncols(x)
for i = 1:m
for j = 1:n
z[i, j] = x[i,P[j]]
end
end
return z
end
function (p::perm)(A::MatElem)
length(p.d) == A.r == A.c || throw("Can't act via $p on matrix of size ($(A.r), $(A.c))")
return p*A*inv(p)
end

119
src/SpNs.jl Normal file
View File

@ -0,0 +1,119 @@
module SpNs
using LinearAlgebra
using AbstractAlgebra
using Nemo
using Groups
using GroupRings
include("Roots.jl")
using .Roots
export Sp, isproportional, ~, isorthogonal, , positive
# two families of generators
function a(i::Int, j::Int, M::MatSpace, val=one(M.base_ring)) # short roots
@assert i j
m = one(M)
N = size(m,2)÷2
m[i,j] = val
m[N+j, N+i] = -val
@assert issymplectic(m)
return m
end
function b(i::Int, j::Int, M::MatSpace, val=one(M.base_ring)) # long roots
m = one(M)
N = size(m,2)÷2
m[i, N+j] = val
m[j, N+i] = val
@assert issymplectic(m)
return m
end
# symplectic generator with associated root datum:
struct Sp{N}
root::Root{N}
matrix::Nemo.fmpz_mat
end
function Sp{N}(typ::Val{:a}, i::Int, j::Int) where N
@assert i≠j
r = Roots.E(N, i) - Roots.E(N, j)
M = Nemo.MatrixSpace(Nemo.ZZ, 2N, 2N)
m = a(i,j, M)
return Sp{N}(r, m)
end
function Sp{N}(typ::Val{:b}, i::Int, j::Int=i) where N
r = Roots.E(N, i) + Roots.E(N, j)
M = Nemo.MatrixSpace(Nemo.ZZ, 2N, 2N)
m = b(i,j, M)
return Sp{N}(r, m)
end
Sp{N}(s::Symbol, i::Int, j::Int=i) where N = Sp{N}(Val(s), i, j)
Base.inv(s::Sp) = Sp(s.root, inv(s.matrix))
Base.:-(s::Sp) = Sp(-s.root, transpose(s.matrix))
Roots.isproportional(x::Sp, y::Sp) = isproportional(x.root, y.root)
Roots.:~(x::Sp,y::Sp) = x.root ~ y.root
Roots.isorthogonal(x::Sp, y::Sp) = isorthogonal(x.root, y.root)
Roots.:(x::Sp,y::Sp) = x.root y.root
function issymplectic(M)
r = nrows(M)
c = ncols(M)
@assert r == c
@assert iseven(r)
n = r÷2
I = Diagonal(ones(Int, n))
O = zeros(Int,n,n);
Ω = parent(M)([O I; -I O])
return Ω == transpose(M)*Ω*M
end
indexing(n) = [(i,j) for i in 1:n for j in i+1:n]
function gens_roots(N)
a_ijs = [Sp{N}(:a, i,j) for (i,j) in indexing(N)]
b_is = [Sp{N}(:b, i) for i in 1:N]
c_ijs = [Sp{N}(:b, i,j) for (i,j) in indexing(N)]
root_system = [a_ijs; b_is; c_ijs]
root_system = [root_system; [-r for r in root_system]];
root_system = [root_system; inv.(root_system)]
return root_system
end
function positive(root_system::Vector{SP}) where SP
roots = [r.root for r in root_system]
pos_roots = eltype(roots)[]
for (idx,γ) in enumerate(roots)
if any(isproportional(s, γ) for s in roots[1:idx-1])
continue
end
push!(pos_roots, γ)
@info "" positive_root = γ
end
# TODO: what about their sums??
return pos_roots
end
function laplacians(RG::GroupRing, root_system::Vector{SpNs.Sp{N}}) where N
positive_roots = positive(root_system)
Sαs = Dict(α => [w.matrix for w in root_system if isproportional(w.root, α)] for α in positive_roots)
Δs = Dict(α => RG(length(S)) - RG(S) for (α, S) in Sαs)
return Δs
end
include("SpN_actions.jl")
end # of module SPNs

108
test/runtests.jl Normal file
View File

@ -0,0 +1,108 @@
using Test
using PropertyT
include("../src/SpNs.jl")
using .SpNs
using .SpNs.Roots
@testset "Roots" begin
@test Root((2,1)) isa Root
r = Root((2,1))
@test -r isa Root
@test 2r isa Root
@test length(2r) == 2length(r)
@test r+r isa Root
@test length(r+r) == 2length(r)
@test r-r isa Root;
@test length(r-r) == 0.0
r = Root((1,1));
s = Root((-1,1));
@test string(Root((1,1))) == "[1.0, 1.0]: root of length 1.4142135623730951"
@test isproportional(r, r)
@test isproportional(r, -r)
@test isproportional(r, 2r)
@test isproportional(-r, 2r)
@test isproportional(r+s, -s-r)
@test isorthogonal(r, s)
@test isorthogonal(r, -s)
@test isorthogonal(r, 2s)
@test isorthogonal(-r, 2s)
@test !isorthogonal(r, r+s)
@test !isorthogonal(r, -r)
@test !isorthogonal(r+s, 2s)
@test !isorthogonal(-r, 2s+r)
@test isorthogonal(r+s, -s+r)
N = 3
@test length(Roots.E(N, 1) - Roots.E(N,2)) == sqrt(2)
end
@testset "Symplectic Generators" begin
s = Sp{2}(:a, 1, 2)
@test -s isa Sp
@test inv(s) isa Sp
t = Sp{2}(:b, 1, 2)
@test -t isa Sp
@test inv(t) isa Sp
@test isproportional(s, -s)
@test isproportional(s, -s)
@test isproportional(s, inv(s))
@test isproportional(t, -t)
@test isproportional(t, inv(t))
@test !isproportional(s, t)
@test !isproportional(inv(s), -t)
end
@testset "Symplectic Group" begin
@testset "Symplectic Root System" begin
rs = SpNs.gens_roots(2)
S = [r.matrix for r in rs];
@test all(SpNs.issymplectic.(S))
@test length(S) == 16
rs = SpNs.gens_roots(3)
S = [r.matrix for r in rs];
@test all(SpNs.issymplectic.(S))
@test length(S) == 36
end
@testset "Sp(4,Z)" begin
N = 2
root_system = SpNs.gens_roots(N)
S = [g.matrix for g in root_system]
Δ = PropertyT.Laplacian(S, 2)
RG = parent(Δ)
Δs = SpNs.laplacians(RG, root_system)
@test sum(Δα for (α, Δα) in Δs) == Δ
@testset "Orthogonality & commutation" begin
r = Root([2, 0])
s = Root([0, 2])
a = Δs[r]
b = Δs[s]
@test a*b == b*a
end
Sq = sum( Δα^2 for (α, Δα) in Δs );
Adj = sum( Δα * sum(Δβ for (β, Δβ) in Δs if !isproportional(α, β)) for (α, Δα) in Δs );
@test Sq + Adj == Δ^2
end
end