Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lie algebras] misc bugfixes, root system in Lie alg interface, dim_of_simple_module implementation in julia #4030

Merged
merged 14 commits into from
Aug 21, 2024
Merged
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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems this function was only moved, why was the doc string deleted?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring is now attached to chevalley_basis(::LieAlgebra), as it contained nothing specific for the Lie algebra subtype

@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 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 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())

Check warning on line 467 in experimental/LieAlgebras/src/LieAlgebra.jl

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/LieAlgebra.jl#L465-L467

Added lines #L465 - L467 were not covered by tests
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())

Check warning on line 481 in experimental/LieAlgebras/src/LieAlgebra.jl

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/LieAlgebra.jl#L479-L481

Added lines #L479 - L481 were not covered by tests
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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)

Check warning on line 970 in experimental/LieAlgebras/src/RootSystem.jl

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/RootSystem.jl#L969-L970

Added lines #L969 - L970 were not covered by tests
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
Loading