diff --git a/experimental/BasisLieHighestWeight/src/BasisLieHighestWeight.jl b/experimental/BasisLieHighestWeight/src/BasisLieHighestWeight.jl index 85105ae1e52d..99ed55fa3eaf 100644 --- a/experimental/BasisLieHighestWeight/src/BasisLieHighestWeight.jl +++ b/experimental/BasisLieHighestWeight/src/BasisLieHighestWeight.jl @@ -5,7 +5,6 @@ using ..Oscar: IntegerUnion using ..Oscar: _is_weighted using Oscar.LieAlgebras: - _character, _root_system_type_string, lie_algebra_simple_module_struct_consts_gap diff --git a/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl b/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl index 889fc3ae0161..7c4e2b7bf4be 100644 --- a/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl +++ b/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl @@ -43,7 +43,7 @@ function basis_lie_highest_weight_compute( # save computations from recursions calc_highest_weight = Dict{WeightLatticeElem,Set{ZZMPolyRingElem}}( - zero(WeightLatticeElem, R) => Set([ZZx(1)]) + zero(weight_lattice(R)) => Set([ZZx(1)]) ) # save all highest weights, for which the Minkowski-sum did not suffice to gain all monomials no_minkowski = Set{WeightLatticeElem}() @@ -98,7 +98,7 @@ function basis_coordinate_ring_kodaira_compute( # save computations from recursions calc_highest_weight = Dict{WeightLatticeElem,Set{ZZMPolyRingElem}}( - zero(WeightLatticeElem, R) => Set([ZZx(1)]) + zero(weight_lattice(R)) => Set([ZZx(1)]) ) # save all highest weights, for which the Minkowski-sum did not suffice to gain all monomials @@ -362,12 +362,12 @@ function add_by_hand( matrices_of_operators = tensor_matrices_of_operators( L, highest_weight, operators_as_roots(birational_seq) ) - space = Dict(zero(WeightLatticeElem, R) => sparse_matrix(QQ)) # span of basis vectors to keep track of the basis + space = Dict(zero(weight_lattice(R)) => sparse_matrix(QQ)) # span of basis vectors to keep track of the basis v0 = sparse_row(ZZ, [(1, 1)]) # starting vector v push!(basis, ZZx(1)) # required monomials of each weightspace - weightspaces = _character(R, highest_weight) + weightspaces = character(R, highest_weight) # sort the monomials from the minkowski-sum by their weightspaces monomials_in_weightspace = Dict{WeightLatticeElem,Set{ZZMPolyRingElem}}() for (weight_w, _) in weightspaces diff --git a/experimental/BasisLieHighestWeight/test/MainAlgorithm-test.jl b/experimental/BasisLieHighestWeight/test/MainAlgorithm-test.jl index b5c9a0d8a9b2..0ce680f95bcb 100644 --- a/experimental/BasisLieHighestWeight/test/MainAlgorithm-test.jl +++ b/experimental/BasisLieHighestWeight/test/MainAlgorithm-test.jl @@ -36,7 +36,7 @@ end sub_weights_proper = BasisLieHighestWeight.sub_weights_proper R = root_system(:B, 3) - w_zero = zero(WeightLatticeElem, R) + w_zero = zero(weight_lattice(R)) @test issetequal(sub_weights(w_zero), [w_zero]) @test isempty(sub_weights_proper(w_zero)) diff --git a/experimental/LieAlgebras/docs/doc.main b/experimental/LieAlgebras/docs/doc.main index 50f30650ee38..403ab988c8fc 100644 --- a/experimental/LieAlgebras/docs/doc.main +++ b/experimental/LieAlgebras/docs/doc.main @@ -8,6 +8,7 @@ "module_homs.md", "cartan_matrix.md", "root_systems.md", + "weight_lattices.md", "weyl_groups.md", ], ] diff --git a/experimental/LieAlgebras/docs/src/root_systems.md b/experimental/LieAlgebras/docs/src/root_systems.md index e61c7f80cef5..1449e39eac3a 100644 --- a/experimental/LieAlgebras/docs/src/root_systems.md +++ b/experimental/LieAlgebras/docs/src/root_systems.md @@ -10,8 +10,7 @@ Root systems in this module are meant to be abstract root systems, i.e. they are The relevant types around root systems are: - `RootSystem` for the root system itself, - `RootSpaceElem` for elements in the root space, i.e. roots and linear combinations thereof, -- `DualRootSpaceElem` for elements in the dual root space, i.e. coroots and linear combinations thereof, -- `WeightLatticeElem` for elements in the weight lattice, i.e. weights and linear combinations thereof. +- `DualRootSpaceElem` for elements in the dual root space, i.e. coroots and linear combinations thereof. !!! warning Most functionality around root systems is currently only intended to be used with root systems of finite type. @@ -46,6 +45,7 @@ rank(::RootSystem) cartan_matrix(::RootSystem) ``` ```@docs; canonical=false +weight_lattice(::RootSystem) weyl_group(::RootSystem) ``` @@ -180,44 +180,3 @@ is_positive_coroot_with_index(::DualRootSpaceElem) is_negative_coroot(::DualRootSpaceElem) is_negative_coroot_with_index(::DualRootSpaceElem) ``` - - -## Weight lattice elements - -```@docs -WeightLatticeElem(::RootSystem, ::Vector{<:IntegerUnion}) -WeightLatticeElem(::RootSystem, ::ZZMatrix) -WeightLatticeElem(::RootSpaceElem) -zero(::Type{WeightLatticeElem}, ::RootSystem) -``` - -```@docs -root_system(::WeightLatticeElem) -``` - -Basic arithmetic operations like `zero`, `+`, `-`, `*` (with integer scalars), and `==` are supported. - -```@docs -coeff(::WeightLatticeElem, ::Int) -coefficients(::WeightLatticeElem) -``` - -```@docs -iszero(::WeightLatticeElem) -is_dominant(::WeightLatticeElem) -is_fundamental_weight(::WeightLatticeElem) -is_fundamental_weight_with_index(::WeightLatticeElem) -``` - -### Reflections -```@docs -reflect(::WeightLatticeElem, ::Int) -reflect!(::WeightLatticeElem, ::Int) -``` - -### Conjugate dominant weight -```@docs -conjugate_dominant_weight(::WeightLatticeElem) -conjugate_dominant_weight_with_left_elem(::WeightLatticeElem) -conjugate_dominant_weight_with_right_elem(::WeightLatticeElem) -``` diff --git a/experimental/LieAlgebras/docs/src/weight_lattices.md b/experimental/LieAlgebras/docs/src/weight_lattices.md new file mode 100644 index 000000000000..543b3b22d0f4 --- /dev/null +++ b/experimental/LieAlgebras/docs/src/weight_lattices.md @@ -0,0 +1,75 @@ +```@meta +CurrentModule = Oscar +DocTestSetup = Oscar.doctestsetup() +``` + +# Weight lattices + +Weight lattices are represented by objects of type `WeightLattice <: AdditiveGroup`, and their elements by `WeightLatticeElem <: AdditiveGroupElement`. + +They are introduced to have a formal parent object of all weights that correspond to a common given root system. + + +## Table of contents + +```@contents +Pages = ["weight_lattices.md"] +Depth = 2:5 +``` + +## Constructing weight lattices +```@docs +weight_lattice(::RootSystem) +``` + + +## Properties of weight lattices + +```@docs +rank(::WeightLattice) +is_finite(::WeightLattice) +zero(::WeightLattice) +gen(::WeightLattice, ::Int) +gens(::WeightLattice) +``` + +```@docs +root_system(::WeightLattice) +``` + + +## Weight lattice elements + +```@docs +WeightLatticeElem(::WeightLattice, ::Vector{<:IntegerUnion}) +WeightLatticeElem(::RootSystem, ::Vector{<:IntegerUnion}) +WeightLatticeElem(::WeightLattice, ::ZZMatrix) +WeightLatticeElem(::RootSystem, ::ZZMatrix) +WeightLatticeElem(::RootSpaceElem) +``` + +Basic arithmetic operations like `zero`, `+`, `-`, `*` (with integer scalars), and `==` are supported. + +```@docs +coeff(::WeightLatticeElem, ::Int) +coefficients(::WeightLatticeElem) +``` + +```@docs +iszero(::WeightLatticeElem) +is_dominant(::WeightLatticeElem) +is_fundamental_weight(::WeightLatticeElem) +is_fundamental_weight_with_index(::WeightLatticeElem) +``` + +### Reflections +```@docs +reflect(::WeightLatticeElem, ::Int) +reflect!(::WeightLatticeElem, ::Int) +``` + +### Conjugate dominant weight +```@docs +conjugate_dominant_weight(::WeightLatticeElem) +conjugate_dominant_weight_with_elem(::WeightLatticeElem) +``` diff --git a/experimental/LieAlgebras/docs/src/weyl_groups.md b/experimental/LieAlgebras/docs/src/weyl_groups.md index 78a31ad11b38..471f762aaadb 100644 --- a/experimental/LieAlgebras/docs/src/weyl_groups.md +++ b/experimental/LieAlgebras/docs/src/weyl_groups.md @@ -7,6 +7,12 @@ DocTestSetup = Oscar.doctestsetup() Weyl groups are represented by objects of type `WeylGroup <: Group`, and their elements by `WeylGroupElem <: GroupElement`. +!!! warning + Weyl groups in OSCAR afford both left and right actions on roots and weights. + Note however, that **the left action** is the default (to align with the literature), + and all more complex functionality is defined with respect to the left action, e.g. + [`conjugate_dominant_weight_with_elem(::WeightLatticeElem)`](@ref). + ## Table of contents ```@contents diff --git a/experimental/LieAlgebras/src/LieAlgebraModule.jl b/experimental/LieAlgebras/src/LieAlgebraModule.jl index cdeea1d92357..76ece8a7b749 100644 --- a/experimental/LieAlgebras/src/LieAlgebraModule.jl +++ b/experimental/LieAlgebras/src/LieAlgebraModule.jl @@ -1405,8 +1405,8 @@ function simple_module(L::LieAlgebra, hw::Vector{Int}) end @doc raw""" - dim_of_simple_module([T = Int], L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> T dim_of_simple_module([T = Int], L::LieAlgebra{C}, hw::WeightLatticeElem) -> T + 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. @@ -1420,33 +1420,29 @@ julia> dim_of_simple_module(L, [1, 1, 1]) 64 ``` """ -function dim_of_simple_module(T::Type, L::LieAlgebra, hw::Vector{<:IntegerUnion}) - R = root_system(L) - return dim_of_simple_module(T, R, hw) +function dim_of_simple_module(L::LieAlgebra, hw::WeightLatticeElem) + return dim_of_simple_module(root_system(L), hw) end -function dim_of_simple_module(L::LieAlgebra, hw::Vector{<:IntegerUnion}) - return dim_of_simple_module(Int, L, hw) +function dim_of_simple_module(T::Type, L::LieAlgebra, hw::WeightLatticeElem) + return dim_of_simple_module(T, root_system(L), hw) end -function dim_of_simple_module(T::Type, L::LieAlgebra, hw::WeightLatticeElem) - R = root_system(L) - return dim_of_simple_module(T, R, hw) +function dim_of_simple_module(L::LieAlgebra, hw::Vector{<:IntegerUnion}) + return dim_of_simple_module(root_system(L), hw) end -function dim_of_simple_module(L::LieAlgebra, hw::WeightLatticeElem) - return dim_of_simple_module(Int, L, hw) +function dim_of_simple_module(T::Type, L::LieAlgebra, hw::Vector{<:IntegerUnion}) + return dim_of_simple_module(T, root_system(L), hw) end @doc raw""" - dominant_weights([T,] L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Vector{T} - dominant_weights([T,] L::LieAlgebra{C}, hw::WeightLatticeElem) -> Vector{T} + dominant_weights(L::LieAlgebra{C}, hw::WeightLatticeElem) -> Vector{WeightLatticeElem} + dominant_weights(L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Vector{WeightLatticeElem} 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 @@ -1454,43 +1450,31 @@ See [MP82](@cite) for details and the implemented algorithm. 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] - [0, 0, 3] - [2, 0, 1] - [0, 1, 1] - [1, 0, 1] - [0, 0, 1] +7-element Vector{WeightLatticeElem}: + w_1 + 3*w_3 + w_1 + w_2 + w_3 + 2*w_1 + w_3 + 3*w_3 + w_2 + w_3 + w_1 + w_3 + w_3 ``` """ -function dominant_weights(T::Type, L::LieAlgebra, hw::Vector{<:IntegerUnion}) - R = root_system(L) - return dominant_weights(T, R, hw) +function dominant_weights(L::LieAlgebra, hw::WeightLatticeElem) + return dominant_weights(root_system(L), hw) end function dominant_weights(L::LieAlgebra, hw::Vector{<:IntegerUnion}) - return dominant_weights(Vector{Int}, L, hw) -end - -function dominant_weights(T::Type, L::LieAlgebra, hw::WeightLatticeElem) - R = root_system(L) - return dominant_weights(T, R, hw) -end - -function dominant_weights(L::LieAlgebra, hw::WeightLatticeElem) - return dominant_weights(Vector{Int}, L, hw) + return dominant_weights(root_system(L), hw) end @doc raw""" - dominant_character(L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Dict{Vector{Int}, Int} - dominant_character(L::LieAlgebra{C}, hw::WeightLatticeElem) -> Dict{Vector{Int}, Int} + dominant_character([T = Int], L::LieAlgebra{C}, hw::WeightLatticeElem) -> Dict{WeightLatticeElem, T} + dominant_character([T = Int], L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Dict{WeightLatticeElem, T} 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 @@ -1498,59 +1482,109 @@ This function uses an optimized version of the Freudenthal formula, see [MP82](@ julia> L = lie_algebra(QQ, :A, 3); julia> dominant_character(L, [2, 1, 0]) -Dict{Vector{Int64}, Int64} with 4 entries: - [2, 1, 0] => 1 - [1, 0, 1] => 2 - [0, 0, 0] => 3 - [0, 2, 0] => 1 +Dict{WeightLatticeElem, Int64} with 4 entries: + 0 => 3 + 2*w_2 => 1 + w_1 + w_3 => 2 + 2*w_1 + w_2 => 1 ``` """ +function dominant_character(L::LieAlgebra, hw::WeightLatticeElem) + return dominant_character(root_system(L), hw) +end + +function dominant_character(T::DataType, L::LieAlgebra, hw::WeightLatticeElem) + return dominant_character(T, root_system(L), hw) +end + function dominant_character(L::LieAlgebra, hw::Vector{<:IntegerUnion}) - R = root_system(L) - return dominant_character(R, hw) + return dominant_character(root_system(L), hw) end -function dominant_character(L::LieAlgebra, hw::WeightLatticeElem) - R = root_system(L) - return dominant_character(R, hw) +function dominant_character(T::DataType, L::LieAlgebra, hw::Vector{<:IntegerUnion}) + return dominant_character(T, root_system(L), hw) end @doc raw""" - character(L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Dict{Vector{Int}, Int} - character(L::LieAlgebra{C}, hw::WeightLatticeElem) -> Dict{Vector{Int}, Int} + character([T = Int], L::LieAlgebra{C}, hw::WeightLatticeElem) -> Dict{WeightLatticeElem, T} + character([T = Int], L::LieAlgebra{C}, hw::Vector{<:IntegerUnion}) -> Dict{WeightLatticeElem, T} 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 julia> L = lie_algebra(QQ, :A, 3); julia> character(L, [2, 0, 0]) -Dict{Vector{Int64}, Int64} with 10 entries: - [0, 1, 0] => 1 - [0, -2, 2] => 1 - [0, 0, -2] => 1 - [-1, 1, -1] => 1 - [-2, 2, 0] => 1 - [1, -1, 1] => 1 - [1, 0, -1] => 1 - [-1, 0, 1] => 1 - [0, -1, 0] => 1 - [2, 0, 0] => 1 +Dict{WeightLatticeElem, Int64} with 10 entries: + -2*w_3 => 1 + -2*w_2 + 2*w_3 => 1 + 2*w_1 => 1 + -2*w_1 + 2*w_2 => 1 + -w_1 + w_3 => 1 + w_2 => 1 + w_1 - w_2 + w_3 => 1 + w_1 - w_3 => 1 + -w_1 + w_2 - w_3 => 1 + -w_2 => 1 ``` """ +function character(L::LieAlgebra, hw::WeightLatticeElem) + return character(root_system(L), hw) +end + +function character(T::DataType, L::LieAlgebra, hw::WeightLatticeElem) + return character(T, root_system(L), hw) +end + function character(L::LieAlgebra, hw::Vector{<:IntegerUnion}) - R = root_system(L) - return character(R, hw) + return character(root_system(L), hw) end -function character(L::LieAlgebra, hw::WeightLatticeElem) - R = root_system(L) - return character(R, hw) +function character(T::DataType, L::LieAlgebra, hw::Vector{<:IntegerUnion}) + return character(T, root_system(L), hw) +end + +@doc raw""" + tensor_product_decomposition(L::LieAlgebra, hw1::WeightLatticeElem, hw2::WeightLatticeElem) -> 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 +julia> L = lie_algebra(QQ, :A, 2); + +julia> tensor_product_decomposition(L, [1, 0], [0, 1]) +MSet{Vector{Int64}} with 2 elements: + [0, 0] + [1, 1] + +julia> tensor_product_decomposition(L, [1, 1], [1, 1]) +MSet{Vector{Int64}} with 6 elements: + [0, 0] + [1, 1] : 2 + [2, 2] + [3, 0] + [0, 3] +``` +""" +function tensor_product_decomposition( + L::LieAlgebra, hw1::Vector{<:IntegerUnion}, hw2::Vector{<:IntegerUnion} +) + return tensor_product_decomposition(root_system(L), hw1, hw2) +end + +function tensor_product_decomposition( + L::LieAlgebra, hw1::WeightLatticeElem, hw2::WeightLatticeElem +) + return tensor_product_decomposition(root_system(L), hw1, hw2) end @doc raw""" @@ -1571,11 +1605,11 @@ julia> L = lie_algebra(QQ, :A, 2); julia> demazure_character(L, [1, 1], [1, 2]) Dict{WeightLatticeElem, Int64} with 5 entries: - -w_1 + 2*w_2 => 1 + 2*w_1 - w_2 => 1 + w_1 + w_2 => 1 0 => 1 + -w_1 + 2*w_2 => 1 -2*w_1 + w_2 => 1 - w_1 + w_2 => 1 - 2*w_1 - w_2 => 1 ``` """ function demazure_character(L::LieAlgebra, w::WeightLatticeElem, x::WeylGroupElem) @@ -1627,45 +1661,3 @@ function demazure_character( ) return demazure_character(T, root_system(L), w, reduced_expression) end - -@doc raw""" - tensor_product_decomposition(L::LieAlgebra, hw1::Vector{<:IntegerUnion}, hw2::Vector{<:IntegerUnion}) -> MSet{Vector{Int}} - tensor_product_decomposition(L::LieAlgebra, hw1::WeightLatticeElem, hw2::WeightLatticeElem) -> 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 -julia> L = lie_algebra(QQ, :A, 2); - -julia> tensor_product_decomposition(L, [1, 0], [0, 1]) -MSet{Vector{Int64}} with 2 elements: - [0, 0] - [1, 1] - -julia> tensor_product_decomposition(L, [1, 1], [1, 1]) -MSet{Vector{Int64}} with 6 elements: - [0, 0] - [1, 1] : 2 - [2, 2] - [3, 0] - [0, 3] -``` -""" -function tensor_product_decomposition( - L::LieAlgebra, hw1::Vector{<:IntegerUnion}, hw2::Vector{<:IntegerUnion} -) - R = root_system(L) - return tensor_product_decomposition(R, hw1, hw2) -end - -function tensor_product_decomposition( - L::LieAlgebra, hw1::WeightLatticeElem, hw2::WeightLatticeElem -) - R = root_system(L) - return tensor_product_decomposition(R, hw1, hw2) -end diff --git a/experimental/LieAlgebras/src/LieAlgebras.jl b/experimental/LieAlgebras/src/LieAlgebras.jl index 1ea1997fa4b5..020861f40d75 100644 --- a/experimental/LieAlgebras/src/LieAlgebras.jl +++ b/experimental/LieAlgebras/src/LieAlgebras.jl @@ -60,6 +60,7 @@ import ..Oscar: inv, is_abelian, is_finite, + is_gen, is_isomorphism, is_nilpotent, is_perfect, @@ -125,6 +126,7 @@ include("Util.jl") include("CartanMatrix.jl") include("CoxeterGroup.jl") include("RootSystem.jl") +include("WeightLattice.jl") include("DynkinDiagram.jl") include("WeylGroup.jl") diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index 6b825ba54a7b..ceb2e2501e16 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -172,7 +172,7 @@ end function Base.hash(R::RootSystem, h::UInt) # even though we don't have a == method for RootSystem, we add a hash method - # to make hashing of RootSpaceElem and WeightLatticeElem more deterministic + # to make hashing of RootSpaceElem and WeightLattice more deterministic b = 0xeb5362118dea2a0e % UInt h = hash(cartan_matrix(R), h) return xor(b, h) @@ -307,6 +307,35 @@ function set_root_system_type!( return nothing end +@doc raw""" + weight_lattice(R::RootSystem) -> WeightLattice + +Return the weight lattice of `R`, i.e. the lattice spanned by the fundamental weights. + +This is the parent of all weights of `R`. + +# Examples +```jldoctest +julia> weight_lattice(root_system([2 -1; -1 2])) +Weight lattice + of root system of rank 2 + of type A2 + +julia> weight_lattice(root_system(matrix(ZZ, 2, 2, [2, -1, -1, 2]); detect_type=false)) +Weight lattice + of root system of rank 2 + of unknown type + +julia> weight_lattice(root_system(matrix(ZZ, [2 -1 -2; -1 2 0; -1 0 2]))) +Weight lattice + of root system of rank 3 + of type C3 (with non-canonical ordering of simple roots) +``` +""" +function weight_lattice(R::RootSystem) + return R.weight_lattice::WeightLattice +end + @doc raw""" weyl_group(R::RootSystem) -> WeylGroup @@ -680,8 +709,7 @@ This is a more efficient version for `fundamental_weights(R)[i]`. See also: [`fundamental_weight(::RootSystem)`](@ref). """ function fundamental_weight(R::RootSystem, i::Int) - @req 1 <= i <= rank(R) "invalid index" - return WeightLatticeElem(R, matrix(ZZ, 1, rank(R), i .== 1:rank(R))) + return gen(weight_lattice(R), i) end @doc raw""" @@ -701,7 +729,7 @@ julia> fundamental_weights(root_system(:A, 2)) ``` """ function fundamental_weights(R::RootSystem) - return [fundamental_weight(R, i) for i in 1:rank(R)] + return gens(weight_lattice(R)) end @doc raw""" @@ -845,7 +873,7 @@ end function Base.hash(r::RootSpaceElem, h::UInt) b = 0xbe7603eb38c985ad % UInt - h = hash(r.root_system, h) + h = hash(root_system(r), h) h = hash(r.vec, h) return xor(b, h) end @@ -1203,7 +1231,7 @@ end function Base.hash(r::DualRootSpaceElem, h::UInt) b = 0x721bec0418bdbe0f % UInt - h = hash(r.root_system, h) + h = hash(root_system(r), h) h = hash(r.vec, h) return xor(b, h) end @@ -1406,364 +1434,6 @@ function root_system(r::DualRootSpaceElem) return r.root_system end -############################################################################### -# -# Weight lattice elements -# -############################################################################### - -@doc raw""" - WeightLatticeElem(R::RootSystem, vec::Vector{<:IntegerUnion}) -> WeightLatticeElem - -Construct a weight lattice element in the root system `R` with the given coefficients w.r.t. the fundamental weights of `R`. -""" -function WeightLatticeElem(R::RootSystem, v::Vector{<:IntegerUnion}) - return WeightLatticeElem(R, matrix(ZZ, 1, rank(R), v)) -end - -@doc raw""" - WeightLatticeElem(r::RootSpaceElem) -> WeightLatticeElem - -Construct a weight lattice element from the root space element `r`. -""" -function WeightLatticeElem(r::RootSpaceElem) - R = root_system(r) - coeffs = coefficients(r) * cartan_matrix_tr(R) - @req all(is_integer, coeffs) "RootSpaceElem does not correspond to a weight" - return WeightLatticeElem(R, matrix(ZZ, coeffs)) -end - -@doc raw""" - zero(::Type{WeightLatticeElem}, R::RootSystem) -> WeightLatticeElem - -Return the neutral additive element in the weight lattice of `R`. -""" -function zero(::Type{WeightLatticeElem}, R::RootSystem) - return WeightLatticeElem(R, zero_matrix(ZZ, 1, rank(R))) -end - -function zero(r::WeightLatticeElem) - return zero(WeightLatticeElem, root_system(r)) -end - -function Base.:*(n::IntegerUnion, w::WeightLatticeElem) - return WeightLatticeElem(root_system(w), n * w.vec) -end - -function Base.:*(w::WeightLatticeElem, n::IntegerUnion) - return WeightLatticeElem(root_system(w), w.vec * n) -end - -function Base.:+(w::WeightLatticeElem, w2::WeightLatticeElem) - @req root_system(w) === root_system(w2) "parent root system mismatch" - - return WeightLatticeElem(root_system(w), w.vec + w2.vec) -end - -function Base.:-(w::WeightLatticeElem, w2::WeightLatticeElem) - @req root_system(w) === root_system(w2) "parent root system mismatch" - - return WeightLatticeElem(root_system(w), w.vec - w2.vec) -end - -function Base.:-(w::WeightLatticeElem) - return WeightLatticeElem(root_system(w), -w.vec) -end - -function zero!(w::WeightLatticeElem) - w.vec = zero!(w.vec) - return w -end - -function add!(wr::WeightLatticeElem, w1::WeightLatticeElem, w2::WeightLatticeElem) - @req root_system(wr) === root_system(w1) === root_system(w2) "parent root system mismatch" - wr.vec = add!(wr.vec, w1.vec, w2.vec) - return wr -end - -function neg!(wr::WeightLatticeElem, w::WeightLatticeElem) - @req root_system(wr) === root_system(w) "parent root system mismatch" - wr.vec = neg!(wr.vec, w.vec) - return wr -end - -function sub!(wr::WeightLatticeElem, w1::WeightLatticeElem, w2::WeightLatticeElem) - @req root_system(wr) === root_system(w1) === root_system(w2) "parent root system mismatch" - wr.vec = sub!(wr.vec, w1.vec, w2.vec) - return wr -end - -function mul!(wr::WeightLatticeElem, w::WeightLatticeElem, n::IntegerUnion) - @req root_system(wr) === root_system(w) "parent root system mismatch" - wr.vec = mul!(wr.vec, w.vec, n) - return wr -end - -function mul!(wr::WeightLatticeElem, n::IntegerUnion, w::WeightLatticeElem) - @req root_system(wr) === root_system(w) "parent root system mismatch" - wr.vec = mul!(wr.vec, n, w.vec) - return wr -end - -function addmul!(wr::WeightLatticeElem, w::WeightLatticeElem, n::IntegerUnion) - @req root_system(wr) === root_system(w) "parent root system mismatch" - wr.vec = addmul!(wr.vec, w.vec, n) - return wr -end - -function addmul!(wr::WeightLatticeElem, n::IntegerUnion, w::WeightLatticeElem) - @req root_system(wr) === root_system(w) "parent root system mismatch" - wr.vec = addmul!(wr.vec, n, w.vec) - return wr -end - -# ignore temp storage -addmul!(wr::WeightLatticeElem, w::WeightLatticeElem, n::IntegerUnion, t) = addmul!(wr, w, n) -addmul!(wr::WeightLatticeElem, n::IntegerUnion, w::WeightLatticeElem, t) = addmul!(wr, n, w) - -function Base.:(==)(w::WeightLatticeElem, w2::WeightLatticeElem) - return w.root_system === w2.root_system && w.vec == w2.vec -end - -function Base.deepcopy_internal(w::WeightLatticeElem, dict::IdDict) - if haskey(dict, w) - return dict[w] - end - - w2 = WeightLatticeElem(root_system(w), deepcopy_internal(w.vec, dict)) - dict[w] = w2 - return w2 -end - -function Base.hash(w::WeightLatticeElem, h::UInt) - b = 0x7b2fefadacf46f4e % UInt - h = hash(w.root_system, h) - h = hash(w.vec, h) - return xor(b, h) -end - -@doc raw""" - iszero(w::WeightLatticeElem) -> Bool - -Return whether `w` is zero. -""" -function Base.iszero(w::WeightLatticeElem) - return iszero(w.vec) -end - -@doc raw""" - coefficients(w::WeightLatticeElem) -> ZZMatrix - -Return the coefficients of the weight lattice element `w` -w.r.t. the fundamental weights as a row vector. - -!!! note - The return type may not be relied on; - we only guarantee that it is a one-dimensional iterable with `eltype` `ZZRingElem` - that can be indexed with integers. -""" -function coefficients(w::WeightLatticeElem) - return w.vec -end - -@doc raw""" - coeff(w::WeightLatticeElem, i::Int) -> ZZRingElem - -Return the coefficient of the `i`-th fundamental weight in `w`. - -This can be also accessed via `w[i]`. -""" -function coeff(w::WeightLatticeElem, i::Int) - return w.vec[i] -end - -function Base.getindex(w::WeightLatticeElem, i::Int) - return coeff(w, i) -end - -@doc raw""" - conjugate_dominant_weight(w::WeightLatticeElem) -> WeightLatticeElem - -Return the unique dominant weight conjugate to `w`. - -See also: [`conjugate_dominant_weight_with_left_elem(::WeightLatticeElem)`](@ref), [`conjugate_dominant_weight_with_right_elem(::WeightLatticeElem)`](@ref). -""" -function conjugate_dominant_weight(w::WeightLatticeElem) - return conjugate_dominant_weight!(deepcopy(w)) -end - -function conjugate_dominant_weight!(w::WeightLatticeElem) - # w will be dominant once all fundamental weights have a positive coefficient, - # so search for negative coefficients and make them positive by applying the corresponding reflection. - s = 1 - while s <= rank(root_system(w)) - if w[s] < 0 - reflect!(w, s) - s = 1 - else - s += 1 - end - end - - return w -end - -@doc raw""" - conjugate_dominant_weight_with_left_elem(w::WeightLatticeElem) -> Tuple{WeightLatticeElem, WeylGroupElem} - -Returns the unique dominant weight `dom` conjugate to `w` and a Weyl group element `x` -such that `x * w == dom`. - -See also: [`conjugate_dominant_weight_with_right_elem(::WeightLatticeElem)`](@ref). -""" -function conjugate_dominant_weight_with_left_elem(w::WeightLatticeElem) - return conjugate_dominant_weight_with_left_elem!(deepcopy(w)) -end - -function conjugate_dominant_weight_with_left_elem!(w::WeightLatticeElem) - R = root_system(w) - - # determine the Weyl group element taking w to the fundamental chamber - word = UInt8[] - #sizehint!(word, count(<(0), coefficients(w))^2) - s = 1 - while s <= rank(R) - if w[s] < 0 - push!(word, UInt8(s)) - reflect!(w, s) - s = 1 - else - s += 1 - end - end - - # reversing word means it is in short revlex normal form - # and it is the element taking original w to new w - return w, weyl_group(R)(reverse!(word); normalize=false) -end - -@doc raw""" - conjugate_dominant_weight_with_right_elem(w::WeightLatticeElem) -> Tuple{WeightLatticeElem, WeylGroupElem} - -Returns the unique dominant weight `dom` conjugate to `w` and a Weyl group element `x` -such that `w * x == dom`. - -See also: [`conjugate_dominant_weight_with_left_elem(::WeightLatticeElem)`](@ref). -""" -function conjugate_dominant_weight_with_right_elem(w::WeightLatticeElem) - return conjugate_dominant_weight_with_right_elem!(deepcopy(w)) -end - -function conjugate_dominant_weight_with_right_elem!(w::WeightLatticeElem) - w, x = conjugate_dominant_weight_with_left_elem!(w) - return w, inv(x) -end - -function dot(w1::WeightLatticeElem, w2::WeightLatticeElem) - @req root_system(w1) === root_system(w2) "parent root system mismatch" - R = root_system(w1) - - return dot( - coefficients(w1), - (coefficients(w2) * _cartan_symmetrizer_mat(R)) * cartan_matrix_inv(R), - ) -end - -function expressify(w::WeightLatticeElem; context=nothing) - if is_unicode_allowed() - return expressify(w, :ω; context) - else - return expressify(w, :w; context) - end -end - -function expressify(w::WeightLatticeElem, s; context=nothing) - sum = Expr(:call, :+) - for i in 1:length(w.vec) - push!(sum.args, Expr(:call, :*, expressify(w.vec[i]; context), "$(s)_$(i)")) - end - return sum -end -@enable_all_show_via_expressify WeightLatticeElem - -@doc raw""" - is_dominant(w::WeightLatticeElem) -> Bool - -Check if `w` is a dominant weight, i.e. if all coefficients are non-negative. -""" -function is_dominant(w::WeightLatticeElem) - return all(>=(0), coefficients(w)) -end - -@doc raw""" - is_fundamental_weight(w::WeightLatticeElem) -> Bool - -Check if `w` is a fundamental weight, i.e. exactly one coefficient is equal to 1 and all others are zero. - -See also: [`is_fundamental_weight_with_index(::WeightLatticeElem)`](@ref). -""" -function is_fundamental_weight(w::WeightLatticeElem) - fl, _ = is_fundamental_weight_with_index(w) - return fl -end - -@doc raw""" - is_fundamental_weight_with_index(w::WeightLatticeElem) -> Bool, Int - -Check if `w` is a fundamental weight and return this together with the index of the fundamental weight in [`fundamental_weights(::RootSystem)`](@ref fundamental_weights(root_system(w))). - -If `w` is not a fundamental weight, the second return value is arbitrary. - -See also: [`is_fundamental_weight(::WeightLatticeElem)`](@ref). -""" -function is_fundamental_weight_with_index(w::WeightLatticeElem) - ind = 0 - coeffs = coefficients(w) - for i in 1:size(coeffs, 2) - if is_zero_entry(coeffs, 1, i) - continue - elseif is_one(coeffs[1, i]) - ind != 0 && return false, 0 - ind = i - else - return false, 0 - end - end - return ind != 0, ind -end - -@doc raw""" - reflect(w::WeightLatticeElem, s::Int) -> WeightLatticeElem - -Return the reflection of `w` in the hyperplane orthogonal to the `s`-th simple root. - -See also: [`reflect!(::WeightLatticeElem, ::Int)`](@ref). -""" -function reflect(w::WeightLatticeElem, s::Int) - return reflect!(deepcopy(w), s) -end - -@doc raw""" - reflect!(w::WeightLatticeElem, s::Int) -> WeightLatticeElem - -Reflect `w` in the hyperplane orthogonal to the `s`-th simple root, and return it. - -This is a mutating version of [`reflect(::WeightLatticeElem, ::Int)`](@ref). -""" -function reflect!(w::WeightLatticeElem, s::Int) - w.vec = addmul!(w.vec, view(cartan_matrix_tr(root_system(w)), s:s, :), -w.vec[s]) # change to submul! once available - return w -end - -@doc raw""" - root_system(w::WeightLatticeElem) -> RootSystem - -Return the root system `w` belongs to. -""" -function root_system(w::WeightLatticeElem) - return w.root_system -end - ############################################################################### # more functions @@ -1806,6 +1476,10 @@ julia> dim_of_simple_module(R, [1, 0]) 5 ``` """ +function dim_of_simple_module(R::RootSystem, hw::WeightLatticeElem) + return dim_of_simple_module(Int, R, hw) +end + 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" @@ -1825,49 +1499,35 @@ function dim_of_simple_module(T::Type, R::RootSystem, hw::Vector{<:IntegerUnion} 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) + return dim_of_simple_module(R, WeightLatticeElem(R, hw)) end @doc raw""" - dominant_weights([T = WeightLatticeElem,] R::RootSystem, hw::WeightLatticeElem) -> Vector{T} - dominant_weights([T = WeightLatticeElem,] R::RootSystem, hw::Vector{<:IntegerUnion}) -> Vector{T} + dominant_weights(R::RootSystem, hw::WeightLatticeElem) -> Vector{WeightLatticeElem} + dominant_weights(R::RootSystem, hw::Vector{<:IntegerUnion}) -> Vector{WeightLatticeElem} Computes the dominant weights occurring in the simple module of the Lie algebra defined by the root system `R` 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> R = root_system(:B, 3); -julia> dominant_weights(Vector{Int}, R, [3, 0, 1]) -7-element Vector{Vector{Int64}}: - [3, 0, 1] - [1, 1, 1] - [0, 0, 3] - [2, 0, 1] - [0, 1, 1] - [1, 0, 1] - [0, 0, 1] +julia> dominant_weights(R, [3, 0, 1]) +7-element Vector{WeightLatticeElem}: + 3*w_1 + w_3 + w_1 + w_2 + w_3 + 2*w_1 + w_3 + 3*w_3 + w_2 + w_3 + w_1 + w_3 + w_3 ``` """ function dominant_weights(R::RootSystem, hw::WeightLatticeElem) - return dominant_weights(WeightLatticeElem, R, hw) -end - -function dominant_weights(R::RootSystem, hw::Vector{<:IntegerUnion}) - return dominant_weights(R, WeightLatticeElem(R, hw)) -end - -function dominant_weights(::Type{WeightLatticeElem}, R::RootSystem, hw::WeightLatticeElem) @req root_system(hw) === R "parent root system mismatch" @req is_dominant(hw) "not a dominant weight" @@ -1892,15 +1552,8 @@ function dominant_weights(::Type{WeightLatticeElem}, R::RootSystem, hw::WeightLa return first.(sort!(collect(ws_with_level); by=last)) # order by level needed for dominant_character end -function dominant_weights(T::Type, R::RootSystem, hw::Vector{<:IntegerUnion}) - return dominant_weights(T, R, WeightLatticeElem(R, hw)) -end - -function dominant_weights( - ::Type{T}, R::RootSystem, hw::WeightLatticeElem -) where {T<:Vector{<:IntegerUnion}} - weights = dominant_weights(WeightLatticeElem, R, hw) - return [T(_vec(coefficients(w))) for w in weights] +function dominant_weights(R::RootSystem, hw::Vector{<:IntegerUnion}) + return dominant_weights(R, WeightLatticeElem(R, hw)) end function _action_matrices_on_weights(W::WeylGroup) @@ -1914,14 +1567,12 @@ function _action_matrices_on_weights(W::WeylGroup) end @doc raw""" - dominant_character(R::RootSystem, hw::WeightLatticeElem) -> Dict{Vector{Int}, Int} - dominant_character(R::RootSystem, hw::Vector{<:IntegerUnion}) -> Dict{Vector{Int}, Int}} + dominant_character([T = Int], R::RootSystem, hw::WeightLatticeElem) -> Dict{WeightLatticeElem, T} + dominant_character([T = Int], R::RootSystem, hw::Vector{<:IntegerUnion}) -> Dict{WeightLatticeElem, T} Computes the dominant weights occurring in the simple module of the Lie algebra defined by the root system `R` 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 @@ -1929,24 +1580,18 @@ This function uses an optimized version of the Freudenthal formula, see [MP82](@ julia> R = root_system(:B, 3); julia> dominant_character(R, [2, 0, 1]) -Dict{Vector{Int64}, Int64} with 4 entries: - [1, 0, 1] => 3 - [0, 0, 1] => 6 - [2, 0, 1] => 1 - [0, 1, 1] => 1 +Dict{WeightLatticeElem, Int64} with 4 entries: + w_2 + w_3 => 1 + 2*w_1 + w_3 => 1 + w_1 + w_3 => 3 + w_3 => 6 ``` """ function dominant_character(R::RootSystem, hw::WeightLatticeElem) - char = _dominant_character(R, hw) - return Dict(Int.(_vec(coefficients(w))) => m for (w, m) in char) -end - -function dominant_character(R::RootSystem, hw::Vector{<:IntegerUnion}) - return dominant_character(R, WeightLatticeElem(R, hw)) + return dominant_character(Int, R, hw) end -function _dominant_character(R::RootSystem, hw::WeightLatticeElem) - T = Int +function dominant_character(T::DataType, R::RootSystem, hw::WeightLatticeElem) @req root_system(hw) === R "parent root system mismatch" @req is_dominant(hw) "not a dominant weight" W = weyl_group(R) @@ -1964,7 +1609,7 @@ function _dominant_character(R::RootSystem, hw::WeightLatticeElem) all_orbs = Dict{Vector{Int},Vector{Tuple{WeightLatticeElem,Int}}}() action_matrices_on_weights = _action_matrices_on_weights(W) - for w in Iterators.drop(todo, 1) + for w in Iterators.drop(todo, 1) # drop hw as its multiplicity is already known stab_inds = [i for (i, ci) in enumerate(coefficients(w)) if iszero(ci)] orbs = get!(all_orbs, stab_inds) do gens = action_matrices_on_weights[stab_inds] @@ -2006,46 +1651,46 @@ function _dominant_character(R::RootSystem, hw::WeightLatticeElem) return char end +function dominant_character(R::RootSystem, hw::Vector{<:IntegerUnion}) + return dominant_character(R, WeightLatticeElem(R, hw)) +end + +function dominant_character(T::DataType, R::RootSystem, hw::Vector{<:IntegerUnion}) + return dominant_character(T, R, WeightLatticeElem(R, hw)) +end + @doc raw""" - character(R::RootSystem, hw::WeightLatticeElem) -> Vector{T} - character(R::RootSystem, hw::Vector{<:IntegerUnion}) -> Vector{T} + character([T = Int], R::RootSystem, hw::WeightLatticeElem) -> Dict{WeightLatticeElem, T} + character([T = Int], R::RootSystem, hw::Vector{<:IntegerUnion}) -> Dict{WeightLatticeElem, T} Computes all weights occurring in the simple module of the Lie algebra defined by the root system `R` with highest weight `hw`, together with their multiplicities. This is achieved by acting with the Weyl group on the [`dominant_character`](@ref dominant_character(::RootSystem, ::WeightLatticeElem)). -The return type may change in the future. - # Example ```jldoctest julia> R = root_system(:B, 3); julia> character(R, [0, 0, 1]) -Dict{Vector{Int64}, Int64} with 8 entries: - [0, 1, -1] => 1 - [-1, 1, -1] => 1 - [0, 0, 1] => 1 - [1, -1, 1] => 1 - [-1, 0, 1] => 1 - [1, 0, -1] => 1 - [0, 0, -1] => 1 - [0, -1, 1] => 1 +Dict{WeightLatticeElem, Int64} with 8 entries: + -w_1 + w_2 - w_3 => 1 + w_1 - w_3 => 1 + -w_2 + w_3 => 1 + w_3 => 1 + w_2 - w_3 => 1 + -w_3 => 1 + w_1 - w_2 + w_3 => 1 + -w_1 + w_3 => 1 ``` """ function character(R::RootSystem, hw::WeightLatticeElem) - char = _character(R, hw) - return Dict(Int.(_vec(coefficients(w))) => m for (w, m) in char) + return character(Int, R, hw) end -function character(R::RootSystem, hw::Vector{<:IntegerUnion}) - return character(R, WeightLatticeElem(R, hw)) -end - -function _character(R::RootSystem, hw::WeightLatticeElem) - T = Int +function character(T::DataType, R::RootSystem, hw::WeightLatticeElem) @req root_system(hw) === R "parent root system mismatch" @req is_dominant(hw) "not a dominant weight" - dom_char = _dominant_character(R, hw) + dom_char = dominant_character(T, R, hw) char = Dict{WeightLatticeElem,T}() for (w, m) in dom_char @@ -2057,6 +1702,14 @@ function _character(R::RootSystem, hw::WeightLatticeElem) return char end +function character(R::RootSystem, hw::Vector{<:IntegerUnion}) + return character(R, WeightLatticeElem(R, hw)) +end + +function character(T::DataType, R::RootSystem, hw::Vector{<:IntegerUnion}) + return character(T, R, WeightLatticeElem(R, hw)) +end + @doc raw""" tensor_product_decomposition(R::RootSystem, hw1::WeightLatticeElem, hw2::WeightLatticeElem) -> MSet{Vector{Int}} tensor_product_decomposition(R::RootSystem, hw1::Vector{<:IntegerUnion}, hw2::Vector{<:IntegerUnion}) -> MSet{Vector{Int}} @@ -2101,9 +1754,9 @@ function tensor_product_decomposition( mults = multiset(WeightLatticeElem) for (w_, m) in dominant_character(R, hw1) - for w in weyl_orbit(WeightLatticeElem(R, w_)) + for w in weyl_orbit(w_) add!(w, hw2_plus_rho) - w_dom, x = conjugate_dominant_weight_with_left_elem!(w) + w_dom, x = conjugate_dominant_weight_with_elem!(w) if all(!iszero, coefficients(w_dom)) sub!(w_dom, rho) coeff = m * (-1)^length(x) @@ -2127,7 +1780,7 @@ function tensor_product_decomposition( end ############################################################################### -#demazures charcter formula +# demazures charcter formula function _demazure_operator(r::RootSpaceElem, w::WeightLatticeElem) fl, index_of_r = is_simple_root_with_index(r) @req fl "not a simple root" @@ -2198,10 +1851,10 @@ julia> R = root_system(:B, 3); julia> demazure_character(R, [0, 1, 0], [3, 2, 1]) Dict{WeightLatticeElem, Int64} with 4 entries: - w_1 => 1 - w_2 => 1 w_1 + w_2 - 2*w_3 => 1 + w_1 => 1 w_1 - w_2 + 2*w_3 => 1 + w_2 => 1 ``` """ function demazure_character(R::RootSystem, w::WeightLatticeElem, x::WeylGroupElem) diff --git a/experimental/LieAlgebras/src/Types.jl b/experimental/LieAlgebras/src/Types.jl index 155637542896..57b469d6ce15 100644 --- a/experimental/LieAlgebras/src/Types.jl +++ b/experimental/LieAlgebras/src/Types.jl @@ -18,6 +18,7 @@ See [`root_system(::ZZMatrix)`](@ref) for the constructor. positive_coroots::Vector #::Vector{DualRootSpaceElem} (cyclic reference) positive_coroots_map::Dict{QQMatrix,Int} weyl_group::Any #::WeylGroup (cyclic reference) + weight_lattice::Any #::WeightLattice (cyclic reference) # optional: type::Vector{Tuple{Symbol,Int}} @@ -41,6 +42,7 @@ See [`root_system(::ZZMatrix)`](@ref) for the constructor. (ind, root) in enumerate(R.positive_coroots::Vector{DualRootSpaceElem}) ) R.weyl_group = WeylGroup(finite, refl, R) + R.weight_lattice = WeightLattice(R) detect_type && is_finite(weyl_group(R)) && assure_root_system_type(R) return R @@ -91,25 +93,44 @@ mutable struct DualRootSpaceElem end end +############################################################################### +# +# Weight lattices +# +############################################################################### + @doc raw""" - WeightLatticeElem + WeightLattice <: AbstractAlgebra.AdditiveGroup -Type for weights and linear combinations thereof. +Type for weight lattices, parent type of `WeightLatticeElem`. """ -mutable struct WeightLatticeElem +@attributes mutable struct WeightLattice <: AbstractAlgebra.AdditiveGroup root_system::RootSystem + + function WeightLattice(root_system::RootSystem) + return new(root_system) + end +end + +@doc raw""" + WeightLatticeElem <: AbstractAlgebra.AdditiveGroupElem + +Type for weights and linear combinations thereof, elem type of `WeightLattice`. +""" +mutable struct WeightLatticeElem <: AbstractAlgebra.AdditiveGroupElem + parent_lat::WeightLattice vec::ZZMatrix # the coordinate (row) vector with respect to the fundamental weights @doc raw""" - WeightLatticeElem(R::RootSystem, vec::ZZMatrix) -> WeightLatticeElem + WeightLatticeElem(P::WeightLattice, vec::ZZMatrix) -> WeightLatticeElem - Construct a weight lattice element in the root system `R` with the given coefficient vector w.r.t. the fundamental weights of `R`. + Construct a weight lattice element in `P` with the given coefficients w.r.t. the fundamental weights of corresponding root system. - `vec` must be a row vector of the same length as the rank of `R`. + `vec` must be a row vector of the same length as the rank of `P`. """ - function WeightLatticeElem(root_system::RootSystem, vec::ZZMatrix) - @req size(vec) == (1, rank(root_system)) "Invalid dimension" - return new(root_system, vec) + function WeightLatticeElem(P::WeightLattice, vec::ZZMatrix) + @req size(vec) == (1, rank(P)) "Invalid dimension" + return new(P, vec) end end diff --git a/experimental/LieAlgebras/src/WeightLattice.jl b/experimental/LieAlgebras/src/WeightLattice.jl new file mode 100644 index 000000000000..7f534d0a4b5d --- /dev/null +++ b/experimental/LieAlgebras/src/WeightLattice.jl @@ -0,0 +1,466 @@ +############################################################################### +# +# Weight lattices +# +############################################################################### + +function elem_type(::Type{WeightLattice}) + return WeightLatticeElem +end + +@doc raw""" + rank(P::WeightLattice) -> Int + +Return the rank of the weight lattice `P`. +""" +function rank(P::WeightLattice) + return rank(root_system(P)) +end + +@doc raw""" + root_system(P::WeightLattice) -> RootSystem + +Return the underlying root system of `P`. +""" +function root_system(P::WeightLattice) + return P.root_system +end + +@doc raw""" + zero(P::WeightLattice) -> WeightLatticeElem + +Return the neutral additive element in the weight lattice `P`. +""" +function zero(P::WeightLattice) + return WeightLatticeElem(P, zero_matrix(ZZ, 1, rank(P))) +end + +function Base.show(io::IO, mime::MIME"text/plain", P::WeightLattice) + @show_name(io, P) + @show_special(io, mime, P) + io = pretty(io) + println(io, "Weight lattice") + print(io, Indent(), "of ", Lowercase()) + show(io, mime, root_system(P)) + print(io, Dedent()) +end + +function Base.show(io::IO, P::WeightLattice) + @show_name(io, P) + @show_special(io, P) + io = pretty(io) + if is_terse(io) + print(io, "Weight lattice") + else + print(io, "Weight lattice of ", Lowercase(), root_system(P)) + end +end + +function number_of_generators(P::WeightLattice) + return rank(P) +end + +@doc raw""" + gen(P::WeightLattice, i::Int) -> WeightLatticeElem + +Return the `i`-th generator of the weight lattice `P`, +i.e. the `i`-th fundamental weight of the root system of `P`. + +This is a more efficient version for `gens(P)[i]`. + +See also: [`fundamental_weight(::RootSystem, ::Int)`](@ref). +""" +function gen(P::WeightLattice, i::Int) + @req 1 <= i <= rank(P) "invalid index" + return WeightLatticeElem(P, matrix(ZZ, 1, rank(P), i .== 1:rank(P))) +end + +@doc raw""" + gens(P::WeightLattice) -> Vector{WeightLatticeElem} + +Return the generators of the weight lattice `P`, +i.e. the fundamental weights of the root system of `P`. + +See also: [`gen(::WeightLattice, ::Int)`](@ref), [`fundamental_weights(::RootSystem)`](@ref). +""" +function gens(P::WeightLattice) + return [gen(P, i) for i in 1:rank(P)] +end + +function is_abelian(P::WeightLattice) + return true +end + +@doc raw""" + is_finite(P::WeightLattice) -> Bool + +Check if the weight lattice `P` is finite, i.e. if it has rank 0. +""" +function is_finite(P::WeightLattice) + return iszero(rank(P)) +end + +function Base.hash(P::WeightLattice, h::UInt) + # even though we don't have a == method for WeightLattice, we add a hash method + # to make hashing of WeightLattice and WeightLatticeElem more deterministic + b = 0x770fdd486cbdeea2 % UInt + h = hash(root_system(P), h) + return xor(b, h) +end + +############################################################################### +# +# Weight lattice elements +# +############################################################################### + +@doc raw""" + WeightLatticeElem(R::RootSystem, vec::ZZMatrix) -> WeightLatticeElem + +Construct a weight lattice element in the root system `R` with the given coefficient vector w.r.t. the fundamental weights of `R`. + +`vec` must be a row vector of the same length as the rank of `R`. +""" +function WeightLatticeElem(R::RootSystem, vec::ZZMatrix) + return WeightLatticeElem(weight_lattice(R), vec) +end + +@doc raw""" + WeightLatticeElem(R::RootSystem, vec::Vector{<:IntegerUnion}) -> WeightLatticeElem + +Construct a weight lattice element in the root system `R` with the given coefficients w.r.t. the fundamental weights of `R`. +""" +function WeightLatticeElem(R::RootSystem, v::Vector{<:IntegerUnion}) + return WeightLatticeElem(R, matrix(ZZ, 1, rank(R), v)) +end + +@doc raw""" + WeightLatticeElem(P::WeightLattice, vec::Vector{<:IntegerUnion}) -> WeightLatticeElem + +Construct a weight lattice element in `P` with the given coefficients w.r.t. the fundamental weights of corresponding root system. +""" +function WeightLatticeElem(P::WeightLattice, v::Vector{<:IntegerUnion}) + return WeightLatticeElem(P, matrix(ZZ, 1, rank(P), v)) +end + +@doc raw""" + WeightLatticeElem(r::RootSpaceElem) -> WeightLatticeElem + +Construct a weight lattice element from the root space element `r`. +""" +function WeightLatticeElem(r::RootSpaceElem) + R = root_system(r) + coeffs = coefficients(r) * cartan_matrix_tr(R) + @req all(is_integer, coeffs) "RootSpaceElem does not correspond to a weight" + return WeightLatticeElem(R, matrix(ZZ, coeffs)) +end + +function parent_type(::Type{WeightLatticeElem}) + return WeightLattice +end + +function parent(w::WeightLatticeElem) + return w.parent_lat +end + +function root_system(w::WeightLatticeElem) + return root_system(parent(w)) +end + +function zero(w::WeightLatticeElem) + return zero(parent(w)) +end + +function Base.:*(n::IntegerUnion, w::WeightLatticeElem) + return WeightLatticeElem(parent(w), n * w.vec) +end + +function Base.:*(w::WeightLatticeElem, n::IntegerUnion) + return WeightLatticeElem(parent(w), w.vec * n) +end + +function Base.:+(w::WeightLatticeElem, w2::WeightLatticeElem) + @req parent(w) === parent(w2) "parent mismatch" + + return WeightLatticeElem(parent(w), w.vec + w2.vec) +end + +function Base.:-(w::WeightLatticeElem, w2::WeightLatticeElem) + @req parent(w) === parent(w2) "parent mismatch" + + return WeightLatticeElem(parent(w), w.vec - w2.vec) +end + +function Base.:-(w::WeightLatticeElem) + return WeightLatticeElem(parent(w), -w.vec) +end + +function zero!(w::WeightLatticeElem) + w.vec = zero!(w.vec) + return w +end + +function add!(wr::WeightLatticeElem, w1::WeightLatticeElem, w2::WeightLatticeElem) + @req parent(wr) === parent(w1) === parent(w2) "parent mismatch" + wr.vec = add!(wr.vec, w1.vec, w2.vec) + return wr +end + +function neg!(wr::WeightLatticeElem, w::WeightLatticeElem) + @req parent(wr) === parent(w) "parent mismatch" + wr.vec = neg!(wr.vec, w.vec) + return wr +end + +function sub!(wr::WeightLatticeElem, w1::WeightLatticeElem, w2::WeightLatticeElem) + @req parent(wr) === parent(w1) === parent(w2) "parent mismatch" + wr.vec = sub!(wr.vec, w1.vec, w2.vec) + return wr +end + +function mul!(wr::WeightLatticeElem, w::WeightLatticeElem, n::IntegerUnion) + @req parent(wr) === parent(w) "parent mismatch" + wr.vec = mul!(wr.vec, w.vec, n) + return wr +end + +function mul!(wr::WeightLatticeElem, n::IntegerUnion, w::WeightLatticeElem) + @req parent(wr) === parent(w) "parent mismatch" + wr.vec = mul!(wr.vec, n, w.vec) + return wr +end + +function addmul!(wr::WeightLatticeElem, w::WeightLatticeElem, n::IntegerUnion) + @req parent(wr) === parent(w) "parent mismatch" + wr.vec = addmul!(wr.vec, w.vec, n) + return wr +end + +function addmul!(wr::WeightLatticeElem, n::IntegerUnion, w::WeightLatticeElem) + @req parent(wr) === parent(w) "parent mismatch" + wr.vec = addmul!(wr.vec, n, w.vec) + return wr +end + +# ignore temp storage +addmul!(wr::WeightLatticeElem, w::WeightLatticeElem, n::IntegerUnion, t) = addmul!(wr, w, n) +addmul!(wr::WeightLatticeElem, n::IntegerUnion, w::WeightLatticeElem, t) = addmul!(wr, n, w) + +function Base.:(==)(w1::WeightLatticeElem, w2::WeightLatticeElem) + return parent(w1) === parent(w2) && w1.vec == w2.vec +end + +function Base.deepcopy_internal(w::WeightLatticeElem, dict::IdDict) + if haskey(dict, w) + return dict[w] + end + + w2 = WeightLatticeElem(parent(w), deepcopy_internal(w.vec, dict)) + dict[w] = w2 + return w2 +end + +function Base.hash(w::WeightLatticeElem, h::UInt) + b = 0x7b2fefadacf46f4e % UInt + h = hash(parent(w), h) + h = hash(w.vec, h) + return xor(b, h) +end + +@doc raw""" + iszero(w::WeightLatticeElem) -> Bool + +Return whether `w` is zero. +""" +function Base.iszero(w::WeightLatticeElem) + return iszero(w.vec) +end + +@doc raw""" + coefficients(w::WeightLatticeElem) -> ZZMatrix + +Return the coefficients of the weight lattice element `w` +w.r.t. the fundamental weights as a row vector. + +!!! note + The return type may not be relied on; + we only guarantee that it is a one-dimensional iterable with `eltype` `ZZRingElem` + that can be indexed with integers. +""" +function coefficients(w::WeightLatticeElem) + return w.vec +end + +@doc raw""" + coeff(w::WeightLatticeElem, i::Int) -> ZZRingElem + +Return the coefficient of the `i`-th fundamental weight in `w`. + +This can be also accessed via `w[i]`. +""" +function coeff(w::WeightLatticeElem, i::Int) + return w.vec[i] +end + +function Base.getindex(w::WeightLatticeElem, i::Int) + return coeff(w, i) +end + +@doc raw""" + conjugate_dominant_weight(w::WeightLatticeElem) -> WeightLatticeElem + +Return the unique dominant weight conjugate to `w`. + +See also: [`conjugate_dominant_weight_with_elem(::WeightLatticeElem)`](@ref). +""" +function conjugate_dominant_weight(w::WeightLatticeElem) + return conjugate_dominant_weight!(deepcopy(w)) +end + +function conjugate_dominant_weight!(w::WeightLatticeElem) + # w will be dominant once all fundamental weights have a positive coefficient, + # so search for negative coefficients and make them positive by applying the corresponding reflection. + s = 1 + while s <= rank(parent(w)) + if w[s] < 0 + reflect!(w, s) + s = 1 + else + s += 1 + end + end + + return w +end + +@doc raw""" + conjugate_dominant_weight_with_elem(w::WeightLatticeElem) -> Tuple{WeightLatticeElem, WeylGroupElem} + +Returns the unique dominant weight `dom` conjugate to `w` and a Weyl group element `x` +such that `x * w == dom`. + +If one wants a group element that takes `w` to`dom` using a right action, one can use `inv(x)`. +""" +function conjugate_dominant_weight_with_elem(w::WeightLatticeElem) + return conjugate_dominant_weight_with_elem!(deepcopy(w)) +end + +function conjugate_dominant_weight_with_elem!(w::WeightLatticeElem) + # determine the Weyl group element taking w to the fundamental chamber + word = UInt8[] + #sizehint!(word, count(<(0), coefficients(w))^2) + s = 1 + while s <= rank(parent(w)) + if w[s] < 0 + push!(word, UInt8(s)) + reflect!(w, s) + s = 1 + else + s += 1 + end + end + + # reversing word means it is in short revlex normal form + # and it is the element taking original w to new w + return w, weyl_group(root_system(w))(reverse!(word); normalize=false) +end + +function dot(w1::WeightLatticeElem, w2::WeightLatticeElem) + @req parent(w1) === parent(w2) "parent mismatch" + R = root_system(w1) + + return dot( + coefficients(w1), + (coefficients(w2) * _cartan_symmetrizer_mat(R)) * cartan_matrix_inv(R), + ) +end + +function expressify(w::WeightLatticeElem; context=nothing) + if is_unicode_allowed() + return expressify(w, :ω; context) + else + return expressify(w, :w; context) + end +end + +function expressify(w::WeightLatticeElem, s; context=nothing) + sum = Expr(:call, :+) + for i in 1:length(w.vec) + push!(sum.args, Expr(:call, :*, expressify(w.vec[i]; context), "$(s)_$(i)")) + end + return sum +end +@enable_all_show_via_expressify WeightLatticeElem + +@doc raw""" + is_dominant(w::WeightLatticeElem) -> Bool + +Check if `w` is a dominant weight, i.e. if all coefficients are non-negative. +""" +function is_dominant(w::WeightLatticeElem) + return all(>=(0), coefficients(w)) +end + +@doc raw""" + is_fundamental_weight(w::WeightLatticeElem) -> Bool + +Check if `w` is a fundamental weight, i.e. exactly one coefficient is equal to 1 and all others are zero. + +See also: [`is_fundamental_weight_with_index(::WeightLatticeElem)`](@ref). +""" +function is_fundamental_weight(w::WeightLatticeElem) + fl, _ = is_fundamental_weight_with_index(w) + return fl +end + +function is_gen(w::WeightLatticeElem) + return is_fundamental_weight(w) +end + +@doc raw""" + is_fundamental_weight_with_index(w::WeightLatticeElem) -> Bool, Int + +Check if `w` is a fundamental weight and return this together with the index of the fundamental weight in [`fundamental_weights(::RootSystem)`](@ref fundamental_weights(root_system(w))). + +If `w` is not a fundamental weight, the second return value is arbitrary. + +See also: [`is_fundamental_weight(::WeightLatticeElem)`](@ref). +""" +function is_fundamental_weight_with_index(w::WeightLatticeElem) + ind = 0 + coeffs = coefficients(w) + for i in 1:size(coeffs, 2) + if is_zero_entry(coeffs, 1, i) + continue + elseif is_one(coeffs[1, i]) + ind != 0 && return false, 0 + ind = i + else + return false, 0 + end + end + return ind != 0, ind +end + +@doc raw""" + reflect(w::WeightLatticeElem, s::Int) -> WeightLatticeElem + +Return the reflection of `w` in the hyperplane orthogonal to the `s`-th simple root. + +See also: [`reflect!(::WeightLatticeElem, ::Int)`](@ref). +""" +function reflect(w::WeightLatticeElem, s::Int) + return reflect!(deepcopy(w), s) +end + +@doc raw""" + reflect!(w::WeightLatticeElem, s::Int) -> WeightLatticeElem + +Reflect `w` in the hyperplane orthogonal to the `s`-th simple root, and return it. + +This is a mutating version of [`reflect(::WeightLatticeElem, ::Int)`](@ref). +""" +function reflect!(w::WeightLatticeElem, s::Int) + w.vec = addmul!(w.vec, view(cartan_matrix_tr(root_system(w)), s:s, :), -w.vec[s]) # change to submul! once available + return w +end diff --git a/experimental/LieAlgebras/src/WeylGroup.jl b/experimental/LieAlgebras/src/WeylGroup.jl index 6683f177baf9..40772bf4ad9f 100644 --- a/experimental/LieAlgebras/src/WeylGroup.jl +++ b/experimental/LieAlgebras/src/WeylGroup.jl @@ -146,6 +146,8 @@ end gen(W::WeylGroup, i::Int) -> WeylGroupElem Return the `i`-th simple reflection (with respect to the underlying root system) of `W`. + +This is a more efficient version for `gens(W)[i]`. """ function gen(W::WeylGroup, i::Integer) @req 1 <= i <= ngens(W) "invalid index" @@ -156,6 +158,8 @@ end gens(W::WeylGroup) -> WeylGroupElem Return the simple reflections (with respect to the underlying root system) of `W`. + +See also: [`gen(::WeylGroup, ::Int)`](@ref). """ function gens(W::WeylGroup) return [gen(W, i) for i in 1:ngens(W)] @@ -170,7 +174,7 @@ This only exists if `W` is finite. function longest_element(W::WeylGroup) @req is_finite(W) "Weyl group is not finite" - _, w0 = conjugate_dominant_weight_with_left_elem(-weyl_vector(root_system(W))) + _, w0 = conjugate_dominant_weight_with_elem(-weyl_vector(root_system(W))) return w0 end @@ -694,9 +698,7 @@ end # Iterates over all weights in the Weyl group orbit of the dominant weight `weight`, # or analogously over all elements in the quotient W/W_P # The iterator returns a tuple (wt, x), such that x*wt == iter.weight; -# this choice is made to align with conjugate_dominant_weight_with_left_elem - -# TODO: add a way to iterate aligned with conjugate_dominant_weight_with_right_elem +# this choice is made to align with conjugate_dominant_weight_with_elem function Base.IteratorSize(::Type{WeylIteratorNoCopy}) return Base.SizeUnknown() @@ -722,7 +724,6 @@ end function _iterate_nocopy(state::WeylIteratorNoCopyState) wt, path = state[1], word(state[2]) - R = root_system(wt) ai = isempty(path) ? UInt8(0) : path[end] # compute next descendant index @@ -748,7 +749,7 @@ end # based on [Ste01], 4.D function next_descendant_index(ai::Int, di::Int, wt::WeightLatticeElem) if iszero(ai) - for j in (di + 1):rank(root_system(wt)) + for j in (di + 1):rank(parent(wt)) if !iszero(wt[j]) return j end @@ -762,7 +763,7 @@ function next_descendant_index(ai::Int, di::Int, wt::WeightLatticeElem) end end - for j in (max(ai, di) + 1):rank(root_system(wt)) + for j in (max(ai, di) + 1):rank(parent(wt)) if is_zero_entry(cartan_matrix(root_system(wt)), ai, j) continue end diff --git a/experimental/LieAlgebras/src/exports.jl b/experimental/LieAlgebras/src/exports.jl index 8ed684c2753e..9c15f6333d47 100644 --- a/experimental/LieAlgebras/src/exports.jl +++ b/experimental/LieAlgebras/src/exports.jl @@ -14,7 +14,7 @@ export LieSubalgebra export LinearLieAlgebra, LinearLieAlgebraElem export RootSpaceElem export RootSystem -export WeightLatticeElem +export WeightLattice, WeightLatticeElem export WeylGroup, WeylGroupElem export WeylOrbitIterator @@ -34,8 +34,7 @@ export cartan_type_with_ordering export chevalley_basis export coerce_to_lie_algebra_elem export conjugate_dominant_weight -export conjugate_dominant_weight_with_left_elem -export conjugate_dominant_weight_with_right_elem +export conjugate_dominant_weight_with_elem export coroot export coroots export coxeter_matrix @@ -112,6 +111,7 @@ export tensor_power export tensor_product_decomposition export trivial_module export universal_enveloping_algebra +export weight_lattice export weyl_group export weyl_orbit export word diff --git a/experimental/LieAlgebras/test/LieAlgebraModule-test.jl b/experimental/LieAlgebras/test/LieAlgebraModule-test.jl index 42cdc6da815e..6e392826f6dd 100644 --- a/experimental/LieAlgebras/test/LieAlgebraModule-test.jl +++ b/experimental/LieAlgebras/test/LieAlgebraModule-test.jl @@ -780,138 +780,155 @@ end @testset "dominant_character" begin - is_dominant_weight = Oscar.LieAlgebras.is_dominant_weight - function check_dominant_character( LR::Union{LieAlgebra,RootSystem}, hw::Vector{<:Oscar.IntegerUnion} ) domchar = @inferred dominant_character(LR, hw) - @test domchar[Int.(hw)] == 1 - @test issetequal(keys(domchar), dominant_weights(Vector{Int}, LR, hw)) - @test all(is_dominant_weight, keys(domchar)) + R = LR isa RootSystem ? LR : root_system(LR) + @test domchar isa Dict{WeightLatticeElem,Int} + @test domchar[WeightLatticeElem(R, hw)] == 1 + @test issetequal(keys(domchar), dominant_weights(LR, hw)) + @test all(is_dominant, keys(domchar)) @test all(>=(1), values(domchar)) + + domchar_ZZ = @inferred dominant_character(ZZRingElem, LR, hw) + @test domchar_ZZ isa Dict{WeightLatticeElem,ZZRingElem} + @test domchar_ZZ == Dict{WeightLatticeElem,ZZRingElem}(domchar) + return domchar end # All concrete test results have been computed using the LiE CAS (http://wwwmathlabo.univ-poitiers.fr/~maavl/LiE/) v2.2.2 let R = root_system(Tuple{Symbol,Int}[]), hw = Int[] domchar = check_dominant_character(R, hw) - @test domchar == Dict(Int[] => 1) + @test domchar == Dict(WeightLatticeElem(R, Int[]) => 1) end let L = lie_algebra(QQ, :A, 2), hw = [0, 0] domchar = check_dominant_character(L, hw) - @test domchar == Dict([0, 0] => 1) + R = root_system(L) + @test domchar == Dict(WeightLatticeElem(R, [0, 0]) => 1) end let L = lie_algebra(QQ, :A, 3), hw = ZZ.([1, 1, 1]) domchar = check_dominant_character(L, hw) - @test domchar == Dict([1, 1, 1] => 1, [2, 0, 0] => 2, [0, 0, 2] => 2, [0, 1, 0] => 4) + R = root_system(L) + @test domchar == Dict( + WeightLatticeElem(R, [1, 1, 1]) => 1, + WeightLatticeElem(R, [2, 0, 0]) => 2, + WeightLatticeElem(R, [0, 0, 2]) => 2, + WeightLatticeElem(R, [0, 1, 0]) => 4, + ) end let L = lie_algebra(QQ, :C, 3), hw = [2, 0, 1] domchar = check_dominant_character(L, hw) + R = root_system(L) @test domchar == Dict( - [2, 0, 1] => 1, - [0, 1, 1] => 1, - [3, 0, 0] => 1, - [1, 1, 0] => 3, - [0, 0, 1] => 6, - [1, 0, 0] => 7, + WeightLatticeElem(R, [2, 0, 1]) => 1, + WeightLatticeElem(R, [0, 1, 1]) => 1, + WeightLatticeElem(R, [3, 0, 0]) => 1, + WeightLatticeElem(R, [1, 1, 0]) => 3, + WeightLatticeElem(R, [0, 0, 1]) => 6, + WeightLatticeElem(R, [1, 0, 0]) => 7, ) end let L = lie_algebra(QQ, :D, 4), hw = [0, 3, 1, 0] domchar = check_dominant_character(L, hw) + R = root_system(L) @test domchar == Dict( - [0, 3, 1, 0] => 1, - [1, 1, 2, 1] => 1, - [1, 2, 0, 1] => 2, - [2, 0, 3, 0] => 1, - [2, 0, 1, 2] => 2, - [0, 0, 3, 2] => 1, - [2, 1, 1, 0] => 3, - [0, 1, 3, 0] => 2, - [0, 1, 1, 2] => 3, - [0, 2, 1, 0] => 7, - [3, 0, 0, 1] => 4, - [1, 0, 2, 1] => 8, - [1, 0, 0, 3] => 4, - [1, 1, 0, 1] => 12, - [2, 0, 1, 0] => 16, - [0, 0, 3, 0] => 12, - [0, 0, 1, 2] => 16, - [0, 1, 1, 0] => 26, - [1, 0, 0, 1] => 36, - [0, 0, 1, 0] => 56, + WeightLatticeElem(R, [0, 3, 1, 0]) => 1, + WeightLatticeElem(R, [1, 1, 2, 1]) => 1, + WeightLatticeElem(R, [1, 2, 0, 1]) => 2, + WeightLatticeElem(R, [2, 0, 3, 0]) => 1, + WeightLatticeElem(R, [2, 0, 1, 2]) => 2, + WeightLatticeElem(R, [0, 0, 3, 2]) => 1, + WeightLatticeElem(R, [2, 1, 1, 0]) => 3, + WeightLatticeElem(R, [0, 1, 3, 0]) => 2, + WeightLatticeElem(R, [0, 1, 1, 2]) => 3, + WeightLatticeElem(R, [0, 2, 1, 0]) => 7, + WeightLatticeElem(R, [3, 0, 0, 1]) => 4, + WeightLatticeElem(R, [1, 0, 2, 1]) => 8, + WeightLatticeElem(R, [1, 0, 0, 3]) => 4, + WeightLatticeElem(R, [1, 1, 0, 1]) => 12, + WeightLatticeElem(R, [2, 0, 1, 0]) => 16, + WeightLatticeElem(R, [0, 0, 3, 0]) => 12, + WeightLatticeElem(R, [0, 0, 1, 2]) => 16, + WeightLatticeElem(R, [0, 1, 1, 0]) => 26, + WeightLatticeElem(R, [1, 0, 0, 1]) => 36, + WeightLatticeElem(R, [0, 0, 1, 0]) => 56, ) end let R = root_system(:E, 6), hw = [1, 0, 1, 0, 1, 0] domchar = check_dominant_character(R, hw) @test domchar == Dict( - [1, 0, 1, 0, 1, 0] => 1, - [0, 0, 0, 1, 1, 0] => 2, - [2, 1, 0, 0, 0, 1] => 3, - [0, 1, 1, 0, 0, 1] => 6, - [2, 0, 1, 0, 0, 0] => 10, - [1, 0, 0, 0, 1, 1] => 16, - [1, 2, 0, 0, 0, 0] => 15, - [0, 0, 2, 0, 0, 0] => 20, - [1, 0, 0, 1, 0, 0] => 44, - [0, 1, 0, 0, 0, 2] => 36, - [0, 1, 0, 0, 1, 0] => 92, - [2, 0, 0, 0, 0, 1] => 104, - [0, 0, 1, 0, 0, 1] => 204, - [1, 1, 0, 0, 0, 0] => 425, - [0, 0, 0, 0, 0, 2] => 416, - [0, 0, 0, 0, 1, 0] => 836, - [1, 0, 0, 0, 0, 0] => 1600, + WeightLatticeElem(R, [1, 0, 1, 0, 1, 0]) => 1, + WeightLatticeElem(R, [0, 0, 0, 1, 1, 0]) => 2, + WeightLatticeElem(R, [2, 1, 0, 0, 0, 1]) => 3, + WeightLatticeElem(R, [0, 1, 1, 0, 0, 1]) => 6, + WeightLatticeElem(R, [2, 0, 1, 0, 0, 0]) => 10, + WeightLatticeElem(R, [1, 0, 0, 0, 1, 1]) => 16, + WeightLatticeElem(R, [1, 2, 0, 0, 0, 0]) => 15, + WeightLatticeElem(R, [0, 0, 2, 0, 0, 0]) => 20, + WeightLatticeElem(R, [1, 0, 0, 1, 0, 0]) => 44, + WeightLatticeElem(R, [0, 1, 0, 0, 0, 2]) => 36, + WeightLatticeElem(R, [0, 1, 0, 0, 1, 0]) => 92, + WeightLatticeElem(R, [2, 0, 0, 0, 0, 1]) => 104, + WeightLatticeElem(R, [0, 0, 1, 0, 0, 1]) => 204, + WeightLatticeElem(R, [1, 1, 0, 0, 0, 0]) => 425, + WeightLatticeElem(R, [0, 0, 0, 0, 0, 2]) => 416, + WeightLatticeElem(R, [0, 0, 0, 0, 1, 0]) => 836, + WeightLatticeElem(R, [1, 0, 0, 0, 0, 0]) => 1600, ) end let L = lie_algebra(QQ, :G, 2), hw = [1, 2] domchar = check_dominant_character(L, hw) + R = root_system(L) @test domchar == Dict( - [1, 2] => 1, - [4, 0] => 1, - [2, 1] => 2, - [0, 2] => 2, - [3, 0] => 3, - [1, 1] => 5, - [2, 0] => 7, - [0, 1] => 7, - [1, 0] => 10, - [0, 0] => 10, + WeightLatticeElem(R, [1, 2]) => 1, + WeightLatticeElem(R, [4, 0]) => 1, + WeightLatticeElem(R, [2, 1]) => 2, + WeightLatticeElem(R, [0, 2]) => 2, + WeightLatticeElem(R, [3, 0]) => 3, + WeightLatticeElem(R, [1, 1]) => 5, + WeightLatticeElem(R, [2, 0]) => 7, + WeightLatticeElem(R, [0, 1]) => 7, + WeightLatticeElem(R, [1, 0]) => 10, + WeightLatticeElem(R, [0, 0]) => 10, ) end let L = special_linear_lie_algebra(QQ, 2), hw = [7] # type A_1 but without known root system domchar = check_dominant_character(L, hw) + R = root_system(L) @test domchar == Dict( - [7] => 1, - [5] => 1, - [3] => 1, - [1] => 1, + WeightLatticeElem(R, [7]) => 1, + WeightLatticeElem(R, [5]) => 1, + WeightLatticeElem(R, [3]) => 1, + WeightLatticeElem(R, [1]) => 1, ) end let L = special_orthogonal_lie_algebra(QQ, 7), hw = ZZ.([1, 2, 0]) # type B_3 but without known root system domchar = check_dominant_character(L, hw) + R = root_system(L) @test domchar == Dict( - [1, 2, 0] => 1, - [2, 0, 2] => 1, - [2, 1, 0] => 1, - [0, 1, 2] => 2, - [0, 2, 0] => 2, - [3, 0, 0] => 2, - [1, 0, 2] => 3, - [1, 1, 0] => 6, - [2, 0, 0] => 6, - [0, 0, 2] => 9, - [0, 1, 0] => 9, - [1, 0, 0] => 15, - [0, 0, 0] => 15, + WeightLatticeElem(R, [1, 2, 0]) => 1, + WeightLatticeElem(R, [2, 0, 2]) => 1, + WeightLatticeElem(R, [2, 1, 0]) => 1, + WeightLatticeElem(R, [0, 1, 2]) => 2, + WeightLatticeElem(R, [0, 2, 0]) => 2, + WeightLatticeElem(R, [3, 0, 0]) => 2, + WeightLatticeElem(R, [1, 0, 2]) => 3, + WeightLatticeElem(R, [1, 1, 0]) => 6, + WeightLatticeElem(R, [2, 0, 0]) => 6, + WeightLatticeElem(R, [0, 0, 2]) => 9, + WeightLatticeElem(R, [0, 1, 0]) => 9, + WeightLatticeElem(R, [1, 0, 0]) => 15, + WeightLatticeElem(R, [0, 0, 0]) => 15, ) end end @@ -921,44 +938,53 @@ LR::Union{LieAlgebra,RootSystem}, hw::Vector{<:Oscar.IntegerUnion} ) char = @inferred character(LR, hw) - @test char[Int.(hw)] == 1 + R = LR isa RootSystem ? LR : root_system(LR) + @test char isa Dict{WeightLatticeElem,Int} + @test char[WeightLatticeElem(R, hw)] == 1 @test all(>=(1), values(char)) @test sum(values(char)) == dim_of_simple_module(LR, hw) domchar = @inferred dominant_character(LR, hw) @test all(w -> domchar[w] == char[w], keys(domchar)) + + char_ZZ = @inferred character(ZZRingElem, LR, hw) + @test char_ZZ isa Dict{WeightLatticeElem,ZZRingElem} + @test char_ZZ == Dict{WeightLatticeElem,ZZRingElem}(char) + return char end # All concrete test results have been computed using the LiE CAS (http://wwwmathlabo.univ-poitiers.fr/~maavl/LiE/) v2.2.2 let R = root_system(Tuple{Symbol,Int}[]), hw = Int[] domchar = check_character(R, hw) - @test domchar == Dict(Int[] => 1) + @test domchar == Dict(WeightLatticeElem(R, Int[]) => 1) end let L = lie_algebra(QQ, :A, 2), hw = [0, 0] domchar = check_character(L, hw) - @test domchar == Dict([0, 0] => 1) + R = root_system(L) + @test domchar == Dict(WeightLatticeElem(R, [0, 0]) => 1) end let L = lie_algebra(QQ, :A, 3), hw = ZZ.([1, 1, 0]) char = check_character(L, hw) + R = root_system(L) @test char == Dict( - [1, 1, 0] => 1, - [2, -1, 1] => 1, - [-1, 2, 0] => 1, - [2, 0, -1] => 1, - [0, 0, 1] => 2, - [1, -2, 2] => 1, - [0, 1, -1] => 2, - [-2, 1, 1] => 1, - [1, -1, 0] => 2, - [-1, -1, 2] => 1, - [-2, 2, -1] => 1, - [1, 0, -2] => 1, - [-1, 0, 0] => 2, - [0, -2, 1] => 1, - [-1, 1, -2] => 1, - [0, -1, -1] => 1, + WeightLatticeElem(R, [1, 1, 0]) => 1, + WeightLatticeElem(R, [2, -1, 1]) => 1, + WeightLatticeElem(R, [-1, 2, 0]) => 1, + WeightLatticeElem(R, [2, 0, -1]) => 1, + WeightLatticeElem(R, [0, 0, 1]) => 2, + WeightLatticeElem(R, [1, -2, 2]) => 1, + WeightLatticeElem(R, [0, 1, -1]) => 2, + WeightLatticeElem(R, [-2, 1, 1]) => 1, + WeightLatticeElem(R, [1, -1, 0]) => 2, + WeightLatticeElem(R, [-1, -1, 2]) => 1, + WeightLatticeElem(R, [-2, 2, -1]) => 1, + WeightLatticeElem(R, [1, 0, -2]) => 1, + WeightLatticeElem(R, [-1, 0, 0]) => 2, + WeightLatticeElem(R, [0, -2, 1]) => 1, + WeightLatticeElem(R, [-1, 1, -2]) => 1, + WeightLatticeElem(R, [0, -1, -1]) => 1, ) end @@ -980,15 +1006,16 @@ let L = special_linear_lie_algebra(QQ, 2), hw = [7] # type A_1 but without known root system char = check_character(L, hw) + R = root_system(L) @test char == Dict( - [7] => 1, - [5] => 1, - [3] => 1, - [1] => 1, - [-1] => 1, - [-3] => 1, - [-5] => 1, - [-7] => 1, + WeightLatticeElem(R, [7]) => 1, + WeightLatticeElem(R, [5]) => 1, + WeightLatticeElem(R, [3]) => 1, + WeightLatticeElem(R, [1]) => 1, + WeightLatticeElem(R, [-1]) => 1, + WeightLatticeElem(R, [-3]) => 1, + WeightLatticeElem(R, [-5]) => 1, + WeightLatticeElem(R, [-7]) => 1, ) end @@ -1128,7 +1155,7 @@ W = weyl_group(R) char = demazure_character(R, w, longest_element(W)) - @test char == Oscar.LieAlgebras._character(R, w) # TODO: update me once #4344 is merged + @test char == character(R, w) @test char isa Dict{WeightLatticeElem,Int} char = demazure_character(R, w, one(W)) diff --git a/experimental/LieAlgebras/test/RootSystem-test.jl b/experimental/LieAlgebras/test/RootSystem-test.jl index 4a4bca04ab5b..51b72df8b162 100644 --- a/experimental/LieAlgebras/test/RootSystem-test.jl +++ b/experimental/LieAlgebras/test/RootSystem-test.jl @@ -1,25 +1,4 @@ @testset "LieAlgebras.RootSystem" begin - @testset "conjugate_dominant_weight_with_*_elem(w::WeightLatticeElem)" begin - for (R, vec) in [ - (root_system(:A, 5), [1, -1, 2, 0, 2]), - (root_system(:B, 3), [1, 1, 1]), - (root_system(:C, 4), [2, 1, 0, 1]), - (root_system(:D, 5), [-1, 2, 2, -1, -1]), - (root_system(:E, 6), [1, 2, 0, 0, 2, 1]), - (root_system(:F, 4), [1, 2, 3, 4]), - (root_system(:G, 2), [-1, -1]), - ] - wt = WeightLatticeElem(R, vec) - d, x = conjugate_dominant_weight_with_left_elem(wt) - @test is_dominant(d) - @test x * wt == d - - d, x = conjugate_dominant_weight_with_right_elem(wt) - @test is_dominant(d) - @test wt * x == d - end - end - @testset "root_system(cartan_matrix::ZZMatrix)" begin R = root_system(:F, 4) @test n_positive_roots(R) == 24 @@ -139,9 +118,9 @@ is_fundamental_weight_with_index(w) == (true, i) for (i, w) in enumerate(fundamental_weights(R)) ) - @test !is_fundamental_weight(zero(WeightLatticeElem, R)) + @test !is_fundamental_weight(zero(weight_lattice(R))) rk != 1 && @test !is_fundamental_weight( - sum(fundamental_weights(R); init=zero(WeightLatticeElem, R)) + sum(fundamental_weights(R); init=zero(weight_lattice(R))) ) @test all( dot(simple_root(R, i), fundamental_weight(R, j)) == @@ -279,13 +258,6 @@ end end - @testset "WeightLatticeElem" begin - R = root_system(:A, 2) - w = WeightLatticeElem(R, [2, 2]) - - @test root_system(w) === R - end - @testset "Root/weight conversion" begin let R = root_system(:A, 2) # from Hum72, Ch. 13.1 @test WeightLatticeElem(simple_root(R, 1)) == WeightLatticeElem(R, [2, -1]) diff --git a/experimental/LieAlgebras/test/WeightLattice-test.jl b/experimental/LieAlgebras/test/WeightLattice-test.jl new file mode 100644 index 000000000000..5d1d13f98e1e --- /dev/null +++ b/experimental/LieAlgebras/test/WeightLattice-test.jl @@ -0,0 +1,26 @@ +@testset "LieAlgebras.WeightLattice" begin + @testset "WeightLatticeElem" begin + R = root_system(:A, 2) + w = WeightLatticeElem(R, [2, 2]) + + @test root_system(w) === R + end + + @testset "conjugate_dominant_weight_with_*_elem(w::WeightLatticeElem)" begin + for (R, vec) in [ + (root_system(:A, 5), [1, -1, 2, 0, 2]), + (root_system(:B, 3), [1, 1, 1]), + (root_system(:C, 4), [2, 1, 0, 1]), + (root_system(:D, 5), [-1, 2, 2, -1, -1]), + (root_system(:E, 6), [1, 2, 0, 0, 2, 1]), + (root_system(:F, 4), [1, 2, 3, 4]), + (root_system(:G, 2), [-1, -1]), + ] + wt = WeightLatticeElem(R, vec) + d, x = conjugate_dominant_weight_with_elem(wt) + @test is_dominant(d) + @test x * wt == d + @test wt * inv(x) == d + end + end +end diff --git a/experimental/LieAlgebras/test/WeylGroup-test.jl b/experimental/LieAlgebras/test/WeylGroup-test.jl index 3dc027355d99..a38215dcf461 100644 --- a/experimental/LieAlgebras/test/WeylGroup-test.jl +++ b/experimental/LieAlgebras/test/WeylGroup-test.jl @@ -482,7 +482,7 @@ include( ] R = root_system(fam, rk) wt = WeightLatticeElem(R, vec) - dom_wt, conj = conjugate_dominant_weight_with_left_elem(wt) + dom_wt, conj = conjugate_dominant_weight_with_elem(wt) orb = Tuple{WeightLatticeElem,WeylGroupElem}[] for tup in WeylIteratorNoCopy(wt) push!(orb, deepcopy(tup)) @@ -518,7 +518,7 @@ include( ] R = root_system(type...) wt = WeightLatticeElem(R, vec) - dom_wt, conj = conjugate_dominant_weight_with_left_elem(wt) + dom_wt, conj = conjugate_dominant_weight_with_elem(wt) orb = Tuple{WeightLatticeElem,WeylGroupElem}[] for tup in WeylIteratorNoCopy(wt) push!(orb, deepcopy(tup))