From a7e41881932a031ac778b6a7abc7d5999954bcd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 21 Aug 2024 13:07:00 +0200 Subject: [PATCH] [Lie algebras] misc bugfixes, root system in Lie alg interface, `dim_of_simple_module` implementation in julia (#4030) * Add `!` to `set_root_system_type` * Add `has_root_system` to Lie algebra interface * Enhance some root system tests * Add `root_system` to Lie algebra interface * Add missing `@attr` * Implement `dim_of_simple_module` in julia (in some cases) * Revert "Skip one excessive test" This reverts commit 0932db81ba8ba98ff0234e95ba55094ca0aafbb5 from oscar-system#3913. * Test some more code paths in `dim_of_simple_module` * Move `dim_of_simple_module` to the root system * Remove `is_integral` * Copy fix for `id \in W` * Cache `cartan_symmetrizer` * Make root system interface a bit clearer * Update experimental/LieAlgebras/src/AbstractLieAlgebra.jl --- .../LieAlgebras/src/AbstractLieAlgebra.jl | 65 +++---- .../LieAlgebras/src/DirectSumLieAlgebra.jl | 12 +- experimental/LieAlgebras/src/LieAlgebra.jl | 60 ++++++- .../LieAlgebras/src/LieAlgebraModule.jl | 28 +-- experimental/LieAlgebras/src/RootSystem.jl | 78 +++++++- experimental/LieAlgebras/src/WeylGroup.jl | 2 + .../test/AbstractLieAlgebra-test.jl | 2 +- .../LieAlgebras/test/LieAlgebraModule-test.jl | 58 ++++-- .../LieAlgebras/test/RootSystem-test.jl | 170 +++++++++--------- experimental/LieAlgebras/test/setup_tests.jl | 12 ++ 10 files changed, 327 insertions(+), 160 deletions(-) diff --git a/experimental/LieAlgebras/src/AbstractLieAlgebra.jl b/experimental/LieAlgebras/src/AbstractLieAlgebra.jl index d74afddca933..d1adb4e4f4c8 100644 --- a/experimental/LieAlgebras/src/AbstractLieAlgebra.jl +++ b/experimental/LieAlgebras/src/AbstractLieAlgebra.jl @@ -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 @@ -162,8 +128,35 @@ end # ############################################################################### -function is_abelian(L::AbstractLieAlgebra) - return all(e -> iszero(length(e)), _struct_consts(L)) +@attr function is_abelian(L::AbstractLieAlgebra) + return all(iszero, _struct_consts(L)) +end + +############################################################################### +# +# Root system getters +# +############################################################################### + +has_root_system(L::AbstractLieAlgebra) = isdefined(L, :root_system) + +function root_system(L::AbstractLieAlgebra) + @req has_root_system(L) "no root system known." + return L.root_system +end + +function chevalley_basis(L::AbstractLieAlgebra) + @req has_root_system(L) "no root system known." + # TODO: once there is root system detection, this function needs to be updated to indeed return the Chevalley basis + + npos = n_positive_roots(root_system(L)) + b = basis(L) + # root vectors + r_plus = b[1:npos] + r_minus = b[(npos + 1):(2 * npos)] + # basis for cartan algebra + h = b[(2 * npos + 1):dim(L)] + return (r_plus, r_minus, h) end ############################################################################### diff --git a/experimental/LieAlgebras/src/DirectSumLieAlgebra.jl b/experimental/LieAlgebras/src/DirectSumLieAlgebra.jl index b23446843f0c..3375a040ee35 100644 --- a/experimental/LieAlgebras/src/DirectSumLieAlgebra.jl +++ b/experimental/LieAlgebras/src/DirectSumLieAlgebra.jl @@ -121,7 +121,7 @@ end # ############################################################################### -function is_abelian(L::DirectSumLieAlgebra) +@attr function is_abelian(L::DirectSumLieAlgebra) return all(is_abelian, L.summands) end @@ -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 diff --git a/experimental/LieAlgebras/src/LieAlgebra.jl b/experimental/LieAlgebras/src/LieAlgebra.jl index c1b208fe5a12..b741d2049c33 100644 --- a/experimental/LieAlgebras/src/LieAlgebra.jl +++ b/experimental/LieAlgebras/src/LieAlgebra.jl @@ -9,14 +9,19 @@ abstract type LieAlgebra{C<:FieldElem} end abstract type LieAlgebraElem{C<:FieldElem} end # To be implemented by subtypes: -# parent_type(::Type{MyLieAlgebraElem{C}}) -# elem_type(::Type{MyLieAlgebra{C}}) -# parent(x::MyLieAlgebraElem{C}) -# coefficient_ring(L::MyLieAlgebra{C}) -# dim(L::MyLieAlgebra{C}) -# Base.show(io::IO, x::MyLieAlgebra{C}) -# symbols(L::MyLieAlgebra{C}) -# bracket(x::MyLieAlgebraElem{C}, y::MyLieAlgebraElem{C}) +# Mandatory: +# parent_type(::Type{MyLieAlgebraElem{C}}) = MyLieAlgebra{C} +# elem_type(::Type{MyLieAlgebra{C}}) = MyLieAlgebraElem{C} +# parent(x::MyLieAlgebraElem{C}) -> MyLieAlgebra{C} +# coefficient_ring(L::MyLieAlgebra{C}) -> parent_type(C) +# dim(L::MyLieAlgebra) -> Int +# symbols(L::MyLieAlgebra) -> Vector{Symbol} +# bracket(x::MyLieAlgebraElem{C}, y::MyLieAlgebraElem{C}) -> MyLieAlgebraElem{C} +# Base.show(io::IO, x::MyLieAlgebra) +# If the subtype supports root systems: +# has_root_system(::MyLieAlgebra) -> Bool +# root_system(::MyLieAlgebra) -> RootSystem +# chevalley_basis(L::MyLieAlgebra) -> NTuple{3,Vector{elem_type(L)}} ############################################################################### # @@ -437,6 +442,45 @@ Return `true` if `L` is solvable, i.e. the derived series of `L` terminates in $ return dim(derived_series(L)[end]) == 0 end +############################################################################### +# +# Root system getters +# +############################################################################### + +@doc raw""" + has_root_system(L::LieAlgebra) -> Bool + +Return whether a root system for `L` is known. +""" +has_root_system(L::LieAlgebra) = false # to be implemented by subtypes + +@doc raw""" + root_system(L::LieAlgebra) -> RootSystem + +Return the root system of `L`. + +This function will error if no root system is known (see [`has_root_system(::LieAlgebra)`](@ref)). +""" +function root_system(L::LieAlgebra) # to be implemented by subtypes + @req has_root_system(L) "root system of `L` not known." + throw(Hecke.NotImplemented()) +end + +@doc raw""" + chevalley_basis(L::LieAlgebra) -> NTuple{3,Vector{elem_type(L)}} + +Return the Chevalley basis of the Lie algebra `L` in three vectors, stating first the positive root vectors, +then the negative root vectors, and finally the basis of the Cartan subalgebra. The order of root vectors corresponds +to the order of the roots in [`root_system(::LieAlgebra)`](@ref). + +This function will error if no root system is known (see [`has_root_system(::LieAlgebra)`](@ref)). +""" +function chevalley_basis(L::LieAlgebra) # to be implemented by subtypes + @req has_root_system(L) "root system of `L` not known." + throw(Hecke.NotImplemented()) +end + ############################################################################### # # Universal enveloping algebra diff --git a/experimental/LieAlgebras/src/LieAlgebraModule.jl b/experimental/LieAlgebras/src/LieAlgebraModule.jl index dad31f9c952b..6aa80ec27a2b 100644 --- a/experimental/LieAlgebras/src/LieAlgebraModule.jl +++ b/experimental/LieAlgebras/src/LieAlgebraModule.jl @@ -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 @@ -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 @@ -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 diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index 228ace73cb8c..8f1d55f9dba9 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -51,7 +51,7 @@ function root_system(cartan_matrix::ZZMatrix; check::Bool=true, detect_type::Boo R = RootSystem(cartan_matrix) detect_type && is_finite(weyl_group(R)) && - set_root_system_type(R, cartan_type_with_ordering(cartan_matrix)...) + set_root_system_type!(R, cartan_type_with_ordering(cartan_matrix)...) return R end @@ -75,14 +75,14 @@ Root system defined by Cartan matrix function root_system(fam::Symbol, rk::Int) cartan = cartan_matrix(fam, rk) R = root_system(cartan; check=false, detect_type=false) - set_root_system_type(R, [(fam, rk)]) + set_root_system_type!(R, [(fam, rk)]) return R end function root_system(type::Vector{Tuple{Symbol,Int}}) cartan = cartan_matrix(type) R = root_system(cartan; check=false, detect_type=false) - set_root_system_type(R, type) + set_root_system_type!(R, type) return R end @@ -127,6 +127,10 @@ function cartan_matrix(R::RootSystem) return R.cartan_matrix end +@attr Vector{ZZRingElem} function cartan_symmetrizer(R::RootSystem) + return cartan_symmetrizer(cartan_matrix(R); check=false) +end + @doc raw""" coroot(R::RootSystem, i::Int) -> RootSpaceElem @@ -324,11 +328,11 @@ function has_root_system_type(R::RootSystem) return isdefined(R, :type) && isdefined(R, :type_ordering) end -function set_root_system_type(R::RootSystem, type::Vector{Tuple{Symbol,Int}}) - return set_root_system_type(R, type, 1:sum(t[2] for t in type; init=0)) +function set_root_system_type!(R::RootSystem, type::Vector{Tuple{Symbol,Int}}) + return set_root_system_type!(R, type, 1:sum(t[2] for t in type; init=0)) end -function set_root_system_type( +function set_root_system_type!( R::RootSystem, type::Vector{Tuple{Symbol,Int}}, ordering::AbstractVector{Int} ) R.type = type @@ -758,7 +762,7 @@ end function Base.:(+)(w::WeightLatticeElem, w2::WeightLatticeElem) @req root_system(w) === root_system(w2) "parent weight lattics mismatch" - return RootSpaceElem(root_system(w), w.vec + w2.vec) + return WeightLatticeElem(root_system(w), w.vec + w2.vec) end function Base.:(-)(w::WeightLatticeElem, w2::WeightLatticeElem) @@ -906,6 +910,66 @@ function root_system(w::WeightLatticeElem) return w.root_system end +############################################################################### +# more functions + +function dot(r::RootSpaceElem, w::WeightLatticeElem) + @req root_system(r) === root_system(w) "parent root system mismatch" + + symmetrizer = cartan_symmetrizer(root_system(r)) + return sum( + r[i] * symmetrizer[i] * w[i] for + i in 1:rank(root_system(r)); + init=zero(QQ), + ) +end + +function dot(w::WeightLatticeElem, r::RootSpaceElem) + return dot(r, w) +end + +@doc raw""" + dim_of_simple_module([T = Int], R::RootSystem, hw::WeightLatticeElem -> T + dim_of_simple_module([T = Int], R::RootSystem, hw::Vector{<:IntegerUnion}) -> T + +Compute the dimension of the simple module of the Lie algebra defined by the root system `R` +with highest weight `hw` using Weyl's dimension formula. +The return value is of type `T`. + +# Example +```jldoctest +julia> R = root_system(:B, 2); + +julia> dim_of_simple_module(R, [1, 0]) +5 +``` +""" +function dim_of_simple_module(T::Type, R::RootSystem, hw::WeightLatticeElem) + @req root_system(hw) === R "parent root system mismatch" + @req is_dominant(hw) "not a dominant weight" + rho = weyl_vector(R) + hw_rho = hw + rho + num = one(ZZ) + den = one(ZZ) + for alpha in positive_roots(R) + num *= ZZ(dot(hw_rho, alpha)) + den *= ZZ(dot(rho, alpha)) + end + return T(div(num, den)) +end + +function dim_of_simple_module(T::Type, R::RootSystem, hw::Vector{<:IntegerUnion}) + return dim_of_simple_module(T, R, WeightLatticeElem(R, hw)) +end + +function dim_of_simple_module(R::RootSystem, hw::Vector{<:IntegerUnion}) + return dim_of_simple_module(Int, R, hw) +end + +function dim_of_simple_module(R::RootSystem, hw::WeightLatticeElem) + return dim_of_simple_module(Int, R, hw) +end + ############################################################################### # internal helpers diff --git a/experimental/LieAlgebras/src/WeylGroup.jl b/experimental/LieAlgebras/src/WeylGroup.jl index 138dd5cb046f..e20bfddc45f3 100644 --- a/experimental/LieAlgebras/src/WeylGroup.jl +++ b/experimental/LieAlgebras/src/WeylGroup.jl @@ -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 diff --git a/experimental/LieAlgebras/test/AbstractLieAlgebra-test.jl b/experimental/LieAlgebras/test/AbstractLieAlgebra-test.jl index a8b0cf3b9448..8542f4349600 100644 --- a/experimental/LieAlgebras/test/AbstractLieAlgebra-test.jl +++ b/experimental/LieAlgebras/test/AbstractLieAlgebra-test.jl @@ -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; diff --git a/experimental/LieAlgebras/test/LieAlgebraModule-test.jl b/experimental/LieAlgebras/test/LieAlgebraModule-test.jl index 49f6263f85d8..f96aa25a4510 100644 --- a/experimental/LieAlgebras/test/LieAlgebraModule-test.jl +++ b/experimental/LieAlgebras/test/LieAlgebraModule-test.jl @@ -712,43 +712,69 @@ @testset "dim_of_simple_module" begin # All concrete test results have been computed using the LiE CAS (http://wwwmathlabo.univ-poitiers.fr/~maavl/LiE/) v2.2.2 let L = lie_algebra(QQ, :A, 6) - @test (@inferred dim_of_simple_module( + dim = @inferred dim_of_simple_module( Int, L, [1, 3, 5, 0, 1, 0] - )) == ZZ(393513120) + ) + @test dim isa Int + @test dim == 393513120 end - let L = lie_algebra(QQ, :B, 7) - @test_skip (@inferred dim_of_simple_module( - ZZRingElem, L, [7, 2, 5, 1, 0, 2, 6] - )) == ZZ(307689492858882008424585750) # re-enable this once this is computed without GAP + let R = root_system(:B, 7) + dim = @inferred dim_of_simple_module( + ZZRingElem, R, [7, 2, 5, 1, 0, 2, 6] + ) + @test dim isa ZZRingElem + @test dim == 307689492858882008424585750 end let L = lie_algebra(QQ, :C, 3) - @test (@inferred dim_of_simple_module( + dim = @inferred dim_of_simple_module( L, [3, 3, 3] - )) == 262144 + ) + @test dim isa Int + @test dim == 262144 end let L = lie_algebra(QQ, :D, 5) - @test (@inferred dim_of_simple_module( + dim = @inferred dim_of_simple_module( Int128, L, [1, 2, 3, 4, 5] - )) == Int128(591080490000) + ) + @test dim isa Int128 + @test dim == 591080490000 end let L = lie_algebra(QQ, :E, 6) - @test (@inferred dim_of_simple_module( + dim = @inferred dim_of_simple_module( ZZRingElem, L, [6, 5, 4, 3, 2, 1] - )) == ZZ(53947263633682628459250) + ) + @test dim isa ZZRingElem + @test dim == 53947263633682628459250 end let L = lie_algebra(QQ, :F, 4) - @test (@inferred dim_of_simple_module( - ZZRingElem, L, [2, 4, 1, 2] - )) == ZZ(5989283015625) + dim = @inferred dim_of_simple_module( + BigInt, L, [2, 4, 1, 2] + ) + @test dim isa BigInt + @test dim == 5989283015625 end let L = lie_algebra(QQ, :G, 2) - @test (@inferred dim_of_simple_module(L, [2, 2])) == 729 + dim = @inferred dim_of_simple_module(L, ZZ.([2, 2])) + @test dim isa Int + @test dim == 729 + end + + let L = special_linear_lie_algebra(QQ, 2) # type A_1 but without known root system + dim = @inferred dim_of_simple_module(Int8, L, [15]) + @test dim isa Int8 + @test dim == 16 + end + + let L = special_orthogonal_lie_algebra(QQ, 5) # type B_2 but without known root system + dim = @inferred dim_of_simple_module(L, ZZ.([1, 2])) + @test dim isa Int + @test dim == 35 end end diff --git a/experimental/LieAlgebras/test/RootSystem-test.jl b/experimental/LieAlgebras/test/RootSystem-test.jl index a1f80c8f2dd3..1f0732d05145 100644 --- a/experimental/LieAlgebras/test/RootSystem-test.jl +++ b/experimental/LieAlgebras/test/RootSystem-test.jl @@ -31,87 +31,95 @@ @testset "property tests" begin function root_system_property_tests(R::RootSystem, rk::Int, npositive_roots::Int) - @test rank(R) == rk - @test n_simple_roots(R) == rk - @test n_positive_roots(R) == npositive_roots - @test n_roots(R) == 2 * npositive_roots - - @test length(simple_roots(R)) == n_simple_roots(R) - @test length(positive_roots(R)) == n_positive_roots(R) - @test length(negative_roots(R)) == n_positive_roots(R) - @test length(roots(R)) == n_roots(R) - @test all(i -> simple_root(R, i) == simple_roots(R)[i], 1:rk) - @test all(i -> positive_root(R, i) == positive_roots(R)[i], 1:npositive_roots) - @test all(i -> negative_root(R, i) == negative_roots(R)[i], 1:npositive_roots) - @test simple_roots(R) == positive_roots(R)[1:rk] - @test all(is_root, roots(R)) - @test !is_root(root(R, 1) - root(R, 1)) - @test all(r -> !is_root(2 * r), roots(R)) - @test all(is_root_with_index(r) == (true, i) for (i, r) in enumerate(roots(R))) - @test all(r -> is_positive_root(r) == is_positive_root_with_index(r)[1], roots(R)) - @test all(r -> is_negative_root(r) == is_negative_root_with_index(r)[1], roots(R)) - @test all(r -> is_simple_root(r) == is_simple_root_with_index(r)[1], roots(R)) - @test all( - is_positive_root_with_index(r) == (true, i) for - (i, r) in enumerate(positive_roots(R)) - ) - @test all(!is_negative_root, positive_roots(R)) - @test all( - is_negative_root_with_index(r) == (true, i) for - (i, r) in enumerate(negative_roots(R)) - ) - @test all(!is_positive_root, negative_roots(R)) - @test all( - is_simple_root_with_index(r) == (true, i) for (i, r) in enumerate(simple_roots(R)) - ) - @test all(is_positive_root, simple_roots(R)) - @test all(!is_negative_root, simple_roots(R)) - @test all(iszero, positive_roots(R) + negative_roots(R)) - - @test length(simple_coroots(R)) == n_simple_roots(R) - @test length(positive_coroots(R)) == n_positive_roots(R) - @test length(negative_coroots(R)) == n_positive_roots(R) - @test length(coroots(R)) == n_roots(R) - @test all(i -> simple_coroot(R, i) == simple_coroots(R)[i], 1:rk) - @test all(i -> positive_coroot(R, i) == positive_coroots(R)[i], 1:npositive_roots) - @test all(i -> negative_coroot(R, i) == negative_coroots(R)[i], 1:npositive_roots) - @test simple_coroots(R) == positive_coroots(R)[1:rk] - @test all(is_coroot, coroots(R)) - @test !is_coroot(coroot(R, 1) - coroot(R, 1)) - @test all(r -> !is_coroot(2 * r), coroots(R)) - @test all(is_coroot_with_index(r) == (true, i) for (i, r) in enumerate(coroots(R))) - @test all( - r -> is_positive_coroot(r) == is_positive_coroot_with_index(r)[1], coroots(R) - ) - @test all( - r -> is_negative_coroot(r) == is_negative_coroot_with_index(r)[1], coroots(R) - ) - @test all(r -> is_simple_coroot(r) == is_simple_coroot_with_index(r)[1], coroots(R)) - @test all( - is_positive_coroot_with_index(r) == (true, i) for - (i, r) in enumerate(positive_coroots(R)) - ) - @test all(!is_negative_coroot, positive_coroots(R)) - @test all( - is_negative_coroot_with_index(r) == (true, i) for - (i, r) in enumerate(negative_coroots(R)) - ) - @test all(!is_positive_coroot, negative_coroots(R)) - @test all( - is_simple_coroot_with_index(r) == (true, i) for - (i, r) in enumerate(simple_coroots(R)) - ) - @test all(is_positive_coroot, simple_coroots(R)) - @test all(!is_negative_coroot, simple_coroots(R)) - @test all(iszero, positive_coroots(R) + negative_coroots(R)) - - @test issorted(height.(positive_roots(R))) # sorted by height - - @test all( - i -> - dot(coefficients(coroot(R, i)) * cartan_matrix(R), coefficients(root(R, i))) == 2, - 1:n_roots(R), - ) + @testset "Property tests" begin + @test rank(R) == rk + @test n_simple_roots(R) == rk + @test n_positive_roots(R) == npositive_roots + @test n_roots(R) == 2 * npositive_roots + + @test length(simple_roots(R)) == n_simple_roots(R) + @test length(positive_roots(R)) == n_positive_roots(R) + @test length(negative_roots(R)) == n_positive_roots(R) + @test length(roots(R)) == n_roots(R) + @test all(i -> simple_root(R, i) == simple_roots(R)[i], 1:rk) + @test all(i -> positive_root(R, i) == positive_roots(R)[i], 1:npositive_roots) + @test all(i -> negative_root(R, i) == negative_roots(R)[i], 1:npositive_roots) + @test simple_roots(R) == positive_roots(R)[1:rk] + @test all(is_root, roots(R)) + n_roots(R) >= 1 && @test !is_root(root(R, 1) - root(R, 1)) + @test all(r -> !is_root(2 * r), roots(R)) + @test all(is_root_with_index(r) == (true, i) for (i, r) in enumerate(roots(R))) + @test all(r -> is_positive_root(r) == is_positive_root_with_index(r)[1], roots(R)) + @test all(r -> is_negative_root(r) == is_negative_root_with_index(r)[1], roots(R)) + @test all(r -> is_simple_root(r) == is_simple_root_with_index(r)[1], roots(R)) + @test all( + is_positive_root_with_index(r) == (true, i) for + (i, r) in enumerate(positive_roots(R)) + ) + @test all(!is_negative_root, positive_roots(R)) + @test all( + is_negative_root_with_index(r) == (true, i) for + (i, r) in enumerate(negative_roots(R)) + ) + @test all(!is_positive_root, negative_roots(R)) + @test all( + is_simple_root_with_index(r) == (true, i) for (i, r) in enumerate(simple_roots(R)) + ) + @test all(is_positive_root, simple_roots(R)) + @test all(!is_negative_root, simple_roots(R)) + @test all(iszero, positive_roots(R) + negative_roots(R)) + + @test length(simple_coroots(R)) == n_simple_roots(R) + @test length(positive_coroots(R)) == n_positive_roots(R) + @test length(negative_coroots(R)) == n_positive_roots(R) + @test length(coroots(R)) == n_roots(R) + @test all(i -> simple_coroot(R, i) == simple_coroots(R)[i], 1:rk) + @test all(i -> positive_coroot(R, i) == positive_coroots(R)[i], 1:npositive_roots) + @test all(i -> negative_coroot(R, i) == negative_coroots(R)[i], 1:npositive_roots) + @test simple_coroots(R) == positive_coroots(R)[1:rk] + @test all(is_coroot, coroots(R)) + n_roots(R) >= 1 && @test !is_coroot(coroot(R, 1) - coroot(R, 1)) + @test all(r -> !is_coroot(2 * r), coroots(R)) + @test all(is_coroot_with_index(r) == (true, i) for (i, r) in enumerate(coroots(R))) + @test all( + r -> is_positive_coroot(r) == is_positive_coroot_with_index(r)[1], coroots(R) + ) + @test all( + r -> is_negative_coroot(r) == is_negative_coroot_with_index(r)[1], coroots(R) + ) + @test all(r -> is_simple_coroot(r) == is_simple_coroot_with_index(r)[1], coroots(R)) + @test all( + is_positive_coroot_with_index(r) == (true, i) for + (i, r) in enumerate(positive_coroots(R)) + ) + @test all(!is_negative_coroot, positive_coroots(R)) + @test all( + is_negative_coroot_with_index(r) == (true, i) for + (i, r) in enumerate(negative_coroots(R)) + ) + @test all(!is_positive_coroot, negative_coroots(R)) + @test all( + is_simple_coroot_with_index(r) == (true, i) for + (i, r) in enumerate(simple_coroots(R)) + ) + @test all(is_positive_coroot, simple_coroots(R)) + @test all(!is_negative_coroot, simple_coroots(R)) + @test all(iszero, positive_coroots(R) + negative_coroots(R)) + + @test issorted(height.(positive_roots(R))) # sorted by height + + @test all( + i -> + dot(coefficients(coroot(R, i)) * cartan_matrix(R), coefficients(root(R, i))) == + 2, + 1:n_roots(R), + ) + end + end + + @testset "rk 0" begin + R = root_system(zero_matrix(ZZ, 0, 0)) + root_system_property_tests(R, 0, 0) end @testset "A_$n" for n in [1, 2, 6] diff --git a/experimental/LieAlgebras/test/setup_tests.jl b/experimental/LieAlgebras/test/setup_tests.jl index 234c424de6f4..c01437f9a029 100644 --- a/experimental/LieAlgebras/test/setup_tests.jl +++ b/experimental/LieAlgebras/test/setup_tests.jl @@ -106,6 +106,18 @@ if !isdefined(Main, :lie_algebra_conformance_test) @test (x * (y * z)) + (y * (z * x)) + (z * (x * y)) == zero(L) end end + + @testset "Root systems" begin + if has_root_system(L) + rs = root_system(L) + @test rs isa RootSystem + @test dim(L) == n_roots(rs) + n_simple_roots(rs) + chev = @inferred chevalley_basis(L) + @test length(chev) == 3 + @test length(chev[1]) == length(chev[2]) + @test dim(L) == sum(length, chev; init=0) + end + end end end