Skip to content

Commit

Permalink
Lie algebras: more progress (#4053)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens committed Sep 16, 2024
1 parent dfe5d5d commit 0b52e65
Show file tree
Hide file tree
Showing 11 changed files with 843 additions and 122 deletions.
12 changes: 12 additions & 0 deletions docs/oscar_references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,18 @@ @Misc{MNP24
url = {https://gap-packages.github.io/tomlib/}
}

@Article{MP82,
author = {Moody, R. V. and Patera, J.},
title = {Fast recursion formula for weight multiplicities},
journal = {Bull. Amer. Math. Soc. (N.S.)},
fjournal = {American Mathematical Society. Bulletin. New Series},
volume = {7},
number = {1},
pages = {237--242},
year = {1982},
doi = {10.1090/S0273-0979-1982-15021-2}
}

@Article{MR20,
author = {Markwig, Thomas and Ren, Yue},
title = {Computing tropical varieties over fields with valuation},
Expand Down
38 changes: 22 additions & 16 deletions experimental/LieAlgebras/src/CoxeterGroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,32 @@ Return the Coxeter matrix $m$ associated to the Cartan matrix `gcm`. If there is
then this will be expressed by $m_{ij} = 0$ (instead of the usual convention $m_{ij} = \infty$).
The keyword argument `check` can be set to `false` to skip verification whether `gcm` is indeed a generalized Cartan matrix.
"""
function coxeter_from_cartan_matrix(gcm; check::Bool=true)
function coxeter_from_cartan_matrix(gcm::ZZMatrix; check::Bool=true)
@req !check || is_cartan_matrix(gcm) "requires a generalized Cartan matrix"

cm = identity_matrix(gcm)
rk, _ = size(gcm)
for i in 1:rk, j in 1:rk
if i == j
continue
end
cm = matrix(
ZZ, [coxeter_matrix_entry_from_cartan_matrix(gcm, i, j) for i in 1:rk, j in 1:rk]
)

if gcm[i, j] == 0
cm[i, j] = 2
elseif gcm[i, j] == -1
cm[i, j] = 3
elseif gcm[i, j] == -2
cm[i, j] = 4
elseif gcm[i, j] == -3
cm[i, j] = 6
end
return cm
end

function coxeter_matrix_entry_from_cartan_matrix(gcm::ZZMatrix, i::Int, j::Int)
if i == j
return 1
end

return cm
d = gcm[i, j] * gcm[j, i]
if d == 0
return 2
elseif d == 1
return 3
elseif d == 2
return 4
elseif d == 3
return 6
else
return 0
end
end
143 changes: 113 additions & 30 deletions experimental/LieAlgebras/src/LieAlgebraModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,7 @@ end
dim_of_simple_module([T = Int], L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> T
Compute the dimension of the simple module of the Lie algebra `L` with highest weight `hw`
using Weyl's dimension formula.
using Weyl's dimension formula.
The return value is of type `T`.
# Example
Expand Down Expand Up @@ -1431,11 +1431,65 @@ function dim_of_simple_module(L::LieAlgebra, hw::Vector{<:IntegerUnion})
end

@doc raw"""
dominant_character(L::LieAlgebra{C}, hw::Vector{Int}) -> Dict{Vector{Int}, Int}
dominant_weights([T,] L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Vector{T}
Computes the dominant weights occurring in the simple module of the Lie algebra `L` with highest weight `hw`,
sorted ascendingly by the total height of roots needed to reach them from `hw`.
When supplying `T = Vector{Int}`, the weights are returned as vectors of integers.
See [MP82](@cite) for details and the implemented algorithm.
# Example
```jldoctest
julia> L = lie_algebra(QQ, :B, 3);
julia> dominant_weights(L, [1, 0, 3])
7-element Vector{Vector{Int64}}:
[1, 0, 3]
[1, 1, 1]
[2, 0, 1]
[0, 0, 3]
[0, 1, 1]
[1, 0, 1]
[0, 0, 1]
```
"""
function dominant_weights(T::Type, L::LieAlgebra, hw::Vector{<:IntegerUnion})
if has_root_system(L)
R = root_system(L)
return dominant_weights(T, R, hw)
else # TODO: remove branch once root system detection is implemented
@req is_dominant_weight(hw) "Not a dominant weight."
return first.(
sort!(
collect(
T(w) => d for (w, d) in
zip(
GAP.Globals.DominantWeights(
GAP.Globals.RootSystem(codomain(Oscar.iso_oscar_gap(L))),
GAP.Obj(hw; recursive=true),
)...,
)
); by=last)
)
end
end

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

@doc raw"""
dominant_character(L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Dict{Vector{Int}, Int}
Computes the dominant weights occurring in the simple module of the Lie algebra `L` with highest weight `hw`,
together with their multiplicities.
The return type may change in the future.
This function uses an optimized version of the Freudenthal formula, see [MP82](@cite) for details.
# Example
```jldoctest
julia> L = lie_algebra(QQ, :A, 3);
Expand All @@ -1448,19 +1502,31 @@ Dict{Vector{Int64}, Int64} with 4 entries:
[0, 2, 0] => 1
```
"""
function dominant_character(L::LieAlgebra, hw::Vector{Int})
@req is_dominant_weight(hw) "Not a dominant weight."
return Dict{Vector{Int},Int}(
Vector{Int}(w) => d for (w, d) in
zip(GAPWrap.DominantCharacter(codomain(Oscar.iso_oscar_gap(L)), GAP.Obj(hw))...)
)
function dominant_character(L::LieAlgebra, hw::Vector{<:IntegerUnion})
if has_root_system(L)
R = root_system(L)
return dominant_character(R, hw)
else # TODO: remove branch once root system detection is implemented
@req is_dominant_weight(hw) "Not a dominant weight."
return Dict{Vector{Int},Int}(
Vector{Int}(w) => d for (w, d) in
zip(
GAPWrap.DominantCharacter(
codomain(Oscar.iso_oscar_gap(L)), GAP.Obj(hw; recursive=true)
)...,
)
)
end
end

@doc raw"""
character(L::LieAlgebra{C}, hw::Vector{Int}) -> Dict{Vector{Int}, Int}
character(L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Dict{Vector{Int}, Int}
Computes all weights occurring in the simple module of the Lie algebra `L` with highest weight `hw`,
together with their multiplicities.
This is achieved by acting with the Weyl group on the [`dominant_character`](@ref dominant_character(::LieAlgebra, ::Vector{<:IntegerUnion})).
The return type may change in the future.
# Example
```jldoctest
Expand All @@ -1476,29 +1542,37 @@ Dict{Vector{Int64}, Int64} with 10 entries:
[1, -1, 1] => 1
[-1, 0, 1] => 1
[1, 0, -1] => 1
[0, -1, 0] => 1
[2, 0, 0] => 1
[0, -1, 0] => 1
```
"""
function character(L::LieAlgebra, hw::Vector{Int})
@req is_dominant_weight(hw) "Not a dominant weight."
dc = dominant_character(L, hw)
c = Dict{Vector{Int},Int}()
W = GAPWrap.WeylGroup(GAPWrap.RootSystem(codomain(Oscar.iso_oscar_gap(L))))
for (w, d) in dc
it = GAPWrap.WeylOrbitIterator(W, GAP.Obj(w))
while !GAPWrap.IsDoneIterator(it)
push!(c, Vector{Int}(GAPWrap.NextIterator(it)) => d)
function character(L::LieAlgebra, hw::Vector{<:IntegerUnion})
if has_root_system(L)
R = root_system(L)
return character(R, hw)
else # TODO: remove branch once root system detection is implemented
@req is_dominant_weight(hw) "Not a dominant weight."
dc = dominant_character(L, hw)
c = Dict{Vector{Int},Int}()
W = GAPWrap.WeylGroup(GAPWrap.RootSystem(codomain(Oscar.iso_oscar_gap(L))))
for (w, d) in dc
it = GAPWrap.WeylOrbitIterator(W, GAP.Obj(w))
while !GAPWrap.IsDoneIterator(it)
push!(c, Vector{Int}(GAPWrap.NextIterator(it)) => d)
end
end
return c
end
return c
end

@doc raw"""
tensor_product_decomposition(L::LieAlgebra, hw1::Vector{Int}, hw2::Vector{Int}) -> MSet{Vector{Int}}
tensor_product_decomposition(L::LieAlgebra, hw1::Vector{<:IntegerUnion}, hw2::Vector{<:IntegerUnion}) -> MSet{Vector{Int}}
Computes the decomposition of the tensor product of the simple modules of the Lie algebra `L` with highest weights `hw1` and `hw2`
into simple modules with their multiplicities.
This function uses Klimyk's formula (see [Hum72; Exercise 24.9](@cite)).
The return type may change in the future.
# Example
```jldoctest
Expand All @@ -1518,13 +1592,22 @@ MSet{Vector{Int64}} with 6 elements:
[0, 3]
```
"""
function tensor_product_decomposition(L::LieAlgebra, hw1::Vector{Int}, hw2::Vector{Int})
@req is_dominant_weight(hw1) && is_dominant_weight(hw2) "Both weights must be dominant."
return multiset(
Tuple{Vector{Vector{Int}},Vector{Int}}(
GAPWrap.DecomposeTensorProduct(
codomain(Oscar.iso_oscar_gap(L)), GAP.Obj(hw1), GAP.Obj(hw2)
),
)...,
)
function tensor_product_decomposition(
L::LieAlgebra, hw1::Vector{<:IntegerUnion}, hw2::Vector{<:IntegerUnion}
)
if has_root_system(L)
R = root_system(L)
return tensor_product_decomposition(R, hw1, hw2)
else # TODO: remove branch once root system detection is implemented
@req is_dominant_weight(hw1) && is_dominant_weight(hw2) "Both weights must be dominant."
return multiset(
Tuple{Vector{Vector{Int}},Vector{Int}}(
GAPWrap.DecomposeTensorProduct(
codomain(Oscar.iso_oscar_gap(L)),
GAP.Obj(hw1; recursive=true),
GAP.Obj(hw2; recursive=true),
),
)...,
)
end
end
5 changes: 5 additions & 0 deletions experimental/LieAlgebras/src/LieAlgebras.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import ..Oscar:
_iso_oscar_gap,
_vec,
action,
add!,
basis_matrix,
basis,
canonical_injection,
Expand All @@ -43,6 +44,7 @@ import ..Oscar:
elem_type,
expressify,
exterior_power,
fp_group,
gen,
gens,
height,
Expand All @@ -62,9 +64,11 @@ import ..Oscar:
is_simple,
is_solvable,
is_welldefined,
isomorphism,
kernel,
lower_central_series,
matrix,
neg!,
normalizer,
number_of_generators,
ngens,
Expand All @@ -74,6 +78,7 @@ import ..Oscar:
root,
roots,
sub,
sub!,
symbols,
symmetric_power,
tensor_product,
Expand Down
Loading

0 comments on commit 0b52e65

Please sign in to comment.