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
63 changes: 28 additions & 35 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,10 +128,37 @@ end
#
###############################################################################

function is_abelian(L::AbstractLieAlgebra)
@attr function is_abelian(L::AbstractLieAlgebra)
return all(e -> iszero(length(e)), _struct_consts(L))
lgoettgens marked this conversation as resolved.
Show resolved Hide resolved
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

###############################################################################
#
# Constructor
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
39 changes: 39 additions & 0 deletions experimental/LieAlgebras/src/LieAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,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.

This function should be implemented by subtypes that support root systems.
Copy link
Member

Choose a reason for hiding this comment

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

Another off-topic comment, but: perhaps we should agree to whom docstrings of exported (documented) functions are addressed. I'd say it should be users. Of course sometimes there is also a point in adding some remarks for implementors. But I think those then should be marked explicitly as such, e.g. via a callout (so the !!! syntax). That said, in this case I think one could just rephrase it slightly:

Suggested change
This function should be implemented by subtypes that support root systems.
This is only implemented for Lie algebras that support root systems.

or so?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the remark. I collected the information about which functions need to be implemented by subtypes that support root systems to the general list about subtype-implemented functions to the top. Furthermore, the docstrings are adapted to reflect what users need to know. (Note that I don't have to mention subtypes with no root system support there, as in these cases has_root_system should always return false, i.e. the NotImplemented() should never trigger.). Changes in 7ea927d

"""
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 should be implemented by subtypes that support root systems.
"""
function root_system(L::LieAlgebra)
@req has_root_system(L) "root system of `L` not known."
throw(Hecke.NotImplemented())

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

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/LieAlgebra.jl#L462-L464

Added lines #L462 - L464 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).
"""
function chevalley_basis(L::LieAlgebra)
@req has_root_system(L) "root system of `L` not known."
throw(Hecke.NotImplemented())

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

View check run for this annotation

Codecov / codecov/patch

experimental/LieAlgebras/src/LieAlgebra.jl#L474-L476

Added lines #L474 - L476 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