Skip to content

Commit

Permalink
[Lie algebras] misc bugfixes, root system in Lie alg interface, `dim_…
Browse files Browse the repository at this point in the history
…of_simple_module` implementation in julia (#4030)

* Add `!` to `set_root_system_type`

* Add `has_root_system` to Lie algebra interface

* Enhance some root system tests

* Add `root_system` to Lie algebra interface

* Add missing `@attr`

* Implement `dim_of_simple_module` in julia (in some cases)

* Revert "Skip one excessive test"

This reverts commit 0932db8 from
#3913.

* Test some more code paths in `dim_of_simple_module`

* Move `dim_of_simple_module` to the root system

* Remove `is_integral`

* Copy fix for `id \in W`

* Cache `cartan_symmetrizer`

* Make root system interface a bit clearer

* Update experimental/LieAlgebras/src/AbstractLieAlgebra.jl
  • Loading branch information
lgoettgens authored Aug 21, 2024
1 parent 38cc0a9 commit a7e4188
Show file tree
Hide file tree
Showing 10 changed files with 327 additions and 160 deletions.
65 changes: 29 additions & 36 deletions experimental/LieAlgebras/src/AbstractLieAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,40 +63,6 @@ dim(L::AbstractLieAlgebra) = L.dim
_struct_consts(L::AbstractLieAlgebra{C}) where {C<:FieldElem} =
L.struct_consts::Matrix{sparse_row_type(C)}

###############################################################################
#
# Root system getters
#
###############################################################################

has_root_system(L::LieAlgebra) = isdefined(L, :root_system)

function root_system(L::LieAlgebra)
@req has_root_system(L) "No root system known."
return L.root_system
end

@doc raw"""
chevalley_basis(L::AbstractLieAlgebra{C}) -> NTuple{3,Vector{AbstractLieAlgebraElem{C}}}
Return the Chevalley basis of the Lie algebra `L` in three vectors, stating first the positive root vectors,
then the negative root vectors, and finally the basis of the Cartan subalgebra. The order of root vectors corresponds
to the order of the roots in the root system.
"""
function chevalley_basis(L::AbstractLieAlgebra)
@req has_root_system(L) "No root system known."
# TODO: once there is root system detection, this function needs to be updated to indeed return the Chevalley basis

npos = n_positive_roots(root_system(L))
b = basis(L)
# root vectors
r_plus = b[1:npos]
r_minus = b[(npos + 1):(2 * npos)]
# basis for cartan algebra
h = b[(2 * npos + 1):dim(L)]
return (r_plus, r_minus, h)
end

###############################################################################
#
# String I/O
Expand Down Expand Up @@ -162,8 +128,35 @@ end
#
###############################################################################

function is_abelian(L::AbstractLieAlgebra)
return all(e -> iszero(length(e)), _struct_consts(L))
@attr function is_abelian(L::AbstractLieAlgebra)
return all(iszero, _struct_consts(L))
end

###############################################################################
#
# Root system getters
#
###############################################################################

has_root_system(L::AbstractLieAlgebra) = isdefined(L, :root_system)

function root_system(L::AbstractLieAlgebra)
@req has_root_system(L) "no root system known."
return L.root_system
end

function chevalley_basis(L::AbstractLieAlgebra)
@req has_root_system(L) "no root system known."
# TODO: once there is root system detection, this function needs to be updated to indeed return the Chevalley basis

npos = n_positive_roots(root_system(L))
b = basis(L)
# root vectors
r_plus = b[1:npos]
r_minus = b[(npos + 1):(2 * npos)]
# basis for cartan algebra
h = b[(2 * npos + 1):dim(L)]
return (r_plus, r_minus, h)
end

###############################################################################
Expand Down
12 changes: 11 additions & 1 deletion experimental/LieAlgebras/src/DirectSumLieAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ end
#
###############################################################################

function is_abelian(L::DirectSumLieAlgebra)
@attr function is_abelian(L::DirectSumLieAlgebra)
return all(is_abelian, L.summands)
end

Expand Down Expand Up @@ -152,6 +152,16 @@ function canonical_projection(D::DirectSumLieAlgebra, i::Int)
return hom(D, S, mat; check=false)
end

###############################################################################
#
# Root system getters
#
###############################################################################

# The following implementation needs direct sums of root systems, which
# is not yet implemented.
# has_root_system(D::DirectSumLieAlgebra) = all(has_root_system, D.summands)

###############################################################################
#
# Constructor
Expand Down
60 changes: 52 additions & 8 deletions experimental/LieAlgebras/src/LieAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ abstract type LieAlgebra{C<:FieldElem} end
abstract type LieAlgebraElem{C<:FieldElem} end

# To be implemented by subtypes:
# parent_type(::Type{MyLieAlgebraElem{C}})
# elem_type(::Type{MyLieAlgebra{C}})
# parent(x::MyLieAlgebraElem{C})
# coefficient_ring(L::MyLieAlgebra{C})
# dim(L::MyLieAlgebra{C})
# Base.show(io::IO, x::MyLieAlgebra{C})
# symbols(L::MyLieAlgebra{C})
# bracket(x::MyLieAlgebraElem{C}, y::MyLieAlgebraElem{C})
# Mandatory:
# parent_type(::Type{MyLieAlgebraElem{C}}) = MyLieAlgebra{C}
# elem_type(::Type{MyLieAlgebra{C}}) = MyLieAlgebraElem{C}
# parent(x::MyLieAlgebraElem{C}) -> MyLieAlgebra{C}
# coefficient_ring(L::MyLieAlgebra{C}) -> parent_type(C)
# dim(L::MyLieAlgebra) -> Int
# symbols(L::MyLieAlgebra) -> Vector{Symbol}
# bracket(x::MyLieAlgebraElem{C}, y::MyLieAlgebraElem{C}) -> MyLieAlgebraElem{C}
# Base.show(io::IO, x::MyLieAlgebra)
# If the subtype supports root systems:
# has_root_system(::MyLieAlgebra) -> Bool
# root_system(::MyLieAlgebra) -> RootSystem
# chevalley_basis(L::MyLieAlgebra) -> NTuple{3,Vector{elem_type(L)}}

###############################################################################
#
Expand Down Expand Up @@ -437,6 +442,45 @@ Return `true` if `L` is solvable, i.e. the derived series of `L` terminates in $
return dim(derived_series(L)[end]) == 0
end

###############################################################################
#
# Root system getters
#
###############################################################################

@doc raw"""
has_root_system(L::LieAlgebra) -> Bool
Return whether a root system for `L` is known.
"""
has_root_system(L::LieAlgebra) = false # to be implemented by subtypes

@doc raw"""
root_system(L::LieAlgebra) -> RootSystem
Return the root system of `L`.
This function will error if no root system is known (see [`has_root_system(::LieAlgebra)`](@ref)).
"""
function root_system(L::LieAlgebra) # to be implemented by subtypes
@req has_root_system(L) "root system of `L` not known."
throw(Hecke.NotImplemented())
end

@doc raw"""
chevalley_basis(L::LieAlgebra) -> NTuple{3,Vector{elem_type(L)}}
Return the Chevalley basis of the Lie algebra `L` in three vectors, stating first the positive root vectors,
then the negative root vectors, and finally the basis of the Cartan subalgebra. The order of root vectors corresponds
to the order of the roots in [`root_system(::LieAlgebra)`](@ref).
This function will error if no root system is known (see [`has_root_system(::LieAlgebra)`](@ref)).
"""
function chevalley_basis(L::LieAlgebra) # to be implemented by subtypes
@req has_root_system(L) "root system of `L` not known."
throw(Hecke.NotImplemented())
end

###############################################################################
#
# Universal enveloping algebra
Expand Down
28 changes: 18 additions & 10 deletions experimental/LieAlgebras/src/LieAlgebraModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1406,9 +1406,9 @@ end
#
###############################################################################

# TODO: check semisimplicity check once that is available
# TODO: add semisimplicity check once that is available

function is_dominant_weight(hw::Vector{Int})
function is_dominant_weight(hw::Vector{<:IntegerUnion})
return all(>=(0), hw)
end

Expand All @@ -1427,9 +1427,10 @@ function simple_module(L::LieAlgebra, hw::Vector{Int})
end

@doc raw"""
dim_of_simple_module([T = Int], L::LieAlgebra{C}, hw::Vector{Int}) -> T
dim_of_simple_module([T = Int], L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> T
Computes the dimension of the simple module of the Lie algebra `L` with highest weight `hw`.
Compute the dimension of the simple module of the Lie algebra `L` with highest weight `hw`
using Weyl's dimension formula.
The return value is of type `T`.
# Example
Expand All @@ -1440,14 +1441,21 @@ julia> dim_of_simple_module(L, [1, 1, 1])
64
```
"""
function dim_of_simple_module(T::Type, L::LieAlgebra, hw::Vector{Int})
@req is_dominant_weight(hw) "Not a dominant weight."
return T(
GAPWrap.DimensionOfHighestWeightModule(codomain(Oscar.iso_oscar_gap(L)), GAP.Obj(hw))
)
function dim_of_simple_module(T::Type, L::LieAlgebra, hw::Vector{<:IntegerUnion})
if has_root_system(L)
R = root_system(L)
return dim_of_simple_module(T, R, hw)
else # TODO: remove branch once root system detection is implemented
@req is_dominant_weight(hw) "Not a dominant weight."
return T(
GAPWrap.DimensionOfHighestWeightModule(
codomain(Oscar.iso_oscar_gap(L)), GAP.Obj(hw; recursive=true)
),
)
end
end

function dim_of_simple_module(L::LieAlgebra, hw::Vector{Int})
function dim_of_simple_module(L::LieAlgebra, hw::Vector{<:IntegerUnion})
return dim_of_simple_module(Int, L, hw)
end

Expand Down
78 changes: 71 additions & 7 deletions experimental/LieAlgebras/src/RootSystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function root_system(cartan_matrix::ZZMatrix; check::Bool=true, detect_type::Boo
R = RootSystem(cartan_matrix)
detect_type &&
is_finite(weyl_group(R)) &&
set_root_system_type(R, cartan_type_with_ordering(cartan_matrix)...)
set_root_system_type!(R, cartan_type_with_ordering(cartan_matrix)...)
return R
end

Expand All @@ -75,14 +75,14 @@ Root system defined by Cartan matrix
function root_system(fam::Symbol, rk::Int)
cartan = cartan_matrix(fam, rk)
R = root_system(cartan; check=false, detect_type=false)
set_root_system_type(R, [(fam, rk)])
set_root_system_type!(R, [(fam, rk)])
return R
end

function root_system(type::Vector{Tuple{Symbol,Int}})
cartan = cartan_matrix(type)
R = root_system(cartan; check=false, detect_type=false)
set_root_system_type(R, type)
set_root_system_type!(R, type)
return R
end

Expand Down Expand Up @@ -127,6 +127,10 @@ function cartan_matrix(R::RootSystem)
return R.cartan_matrix
end

@attr Vector{ZZRingElem} function cartan_symmetrizer(R::RootSystem)
return cartan_symmetrizer(cartan_matrix(R); check=false)
end

@doc raw"""
coroot(R::RootSystem, i::Int) -> RootSpaceElem
Expand Down Expand Up @@ -324,11 +328,11 @@ function has_root_system_type(R::RootSystem)
return isdefined(R, :type) && isdefined(R, :type_ordering)
end

function set_root_system_type(R::RootSystem, type::Vector{Tuple{Symbol,Int}})
return set_root_system_type(R, type, 1:sum(t[2] for t in type; init=0))
function set_root_system_type!(R::RootSystem, type::Vector{Tuple{Symbol,Int}})
return set_root_system_type!(R, type, 1:sum(t[2] for t in type; init=0))
end

function set_root_system_type(
function set_root_system_type!(
R::RootSystem, type::Vector{Tuple{Symbol,Int}}, ordering::AbstractVector{Int}
)
R.type = type
Expand Down Expand Up @@ -758,7 +762,7 @@ end
function Base.:(+)(w::WeightLatticeElem, w2::WeightLatticeElem)
@req root_system(w) === root_system(w2) "parent weight lattics mismatch"

return RootSpaceElem(root_system(w), w.vec + w2.vec)
return WeightLatticeElem(root_system(w), w.vec + w2.vec)
end

function Base.:(-)(w::WeightLatticeElem, w2::WeightLatticeElem)
Expand Down Expand Up @@ -906,6 +910,66 @@ function root_system(w::WeightLatticeElem)
return w.root_system
end

###############################################################################
# more functions

function dot(r::RootSpaceElem, w::WeightLatticeElem)
@req root_system(r) === root_system(w) "parent root system mismatch"

symmetrizer = cartan_symmetrizer(root_system(r))
return sum(
r[i] * symmetrizer[i] * w[i] for
i in 1:rank(root_system(r));
init=zero(QQ),
)
end

function dot(w::WeightLatticeElem, r::RootSpaceElem)
return dot(r, w)
end

@doc raw"""
dim_of_simple_module([T = Int], R::RootSystem, hw::WeightLatticeElem -> T
dim_of_simple_module([T = Int], R::RootSystem, hw::Vector{<:IntegerUnion}) -> T
Compute the dimension of the simple module of the Lie algebra defined by the root system `R`
with highest weight `hw` using Weyl's dimension formula.
The return value is of type `T`.
# Example
```jldoctest
julia> R = root_system(:B, 2);
julia> dim_of_simple_module(R, [1, 0])
5
```
"""
function dim_of_simple_module(T::Type, R::RootSystem, hw::WeightLatticeElem)
@req root_system(hw) === R "parent root system mismatch"
@req is_dominant(hw) "not a dominant weight"
rho = weyl_vector(R)
hw_rho = hw + rho
num = one(ZZ)
den = one(ZZ)
for alpha in positive_roots(R)
num *= ZZ(dot(hw_rho, alpha))
den *= ZZ(dot(rho, alpha))
end
return T(div(num, den))
end

function dim_of_simple_module(T::Type, R::RootSystem, hw::Vector{<:IntegerUnion})
return dim_of_simple_module(T, R, WeightLatticeElem(R, hw))
end

function dim_of_simple_module(R::RootSystem, hw::Vector{<:IntegerUnion})
return dim_of_simple_module(Int, R, hw)
end

function dim_of_simple_module(R::RootSystem, hw::WeightLatticeElem)
return dim_of_simple_module(Int, R, hw)
end

###############################################################################
# internal helpers

Expand Down
2 changes: 2 additions & 0 deletions experimental/LieAlgebras/src/WeylGroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,8 @@ function Base.iterate(iter::ReducedExpressionIterator)
end

function Base.iterate(iter::ReducedExpressionIterator, word::Vector{UInt8})
isempty(word) && return nothing

rk = rank(root_system(parent(iter.el)))

# we need to copy word; iterate behaves differently when length is (not) known
Expand Down
2 changes: 1 addition & 1 deletion experimental/LieAlgebras/test/AbstractLieAlgebra-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@
0 2 -2 0 0;
0 -1 2 0 0;
0 0 0 2 -1;
-1 0 0 -1 2]), ["A3 B2", "B2 A3"], :all), # 32
-1 0 0 -1 2]), ["A3 B2", "B2 A3", "A3 C2", "C2 A3"], :all), # 32
("B3 + G2, shuffled",
root_system([
2 -2 0 0 0;
Expand Down
Loading

0 comments on commit a7e4188

Please sign in to comment.