From e7cfeeac74b7d66d470b17283b16032aca857591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 20 Nov 2024 17:34:38 +0100 Subject: [PATCH] Draft: Use group algebra for characters --- .../src/MainAlgorithm.jl | 2 +- .../LieAlgebras/src/LieAlgebraModule.jl | 40 +++----- experimental/LieAlgebras/src/RootSystem.jl | 91 +++++++++++-------- experimental/LieAlgebras/src/Types.jl | 1 + experimental/LieAlgebras/src/WeightLattice.jl | 2 - .../LieAlgebras/test/WeightLattice-test.jl | 2 +- 6 files changed, 72 insertions(+), 66 deletions(-) diff --git a/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl b/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl index 832357e7226c..c212095c24b8 100644 --- a/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl +++ b/experimental/BasisLieHighestWeight/src/MainAlgorithm.jl @@ -367,7 +367,7 @@ function add_by_hand( push!(basis, ZZx(1)) # required monomials of each weightspace - weightspaces = _character(R, highest_weight) + weightspaces = Dict{WeightLatticeElem,Int}(_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/LieAlgebras/src/LieAlgebraModule.jl b/experimental/LieAlgebras/src/LieAlgebraModule.jl index a66743167284..4139643ff14f 100644 --- a/experimental/LieAlgebras/src/LieAlgebraModule.jl +++ b/experimental/LieAlgebras/src/LieAlgebraModule.jl @@ -1454,14 +1454,14 @@ 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 + 3*w_3 + 2*w_1 + w_3 + w_2 + w_3 + w_1 + w_3 + w_3 ``` """ function dominant_weights(T::Type, L::LieAlgebra, hw::Vector{<:IntegerUnion}) @@ -1470,7 +1470,8 @@ function dominant_weights(T::Type, L::LieAlgebra, hw::Vector{<:IntegerUnion}) end function dominant_weights(L::LieAlgebra, hw::Vector{<:IntegerUnion}) - return dominant_weights(Vector{Int}, L, hw) + R = root_system(L) + return dominant_weights(R, hw) end function dominant_weights(T::Type, L::LieAlgebra, hw::WeightLatticeElem) @@ -1479,7 +1480,8 @@ function dominant_weights(T::Type, L::LieAlgebra, hw::WeightLatticeElem) end function dominant_weights(L::LieAlgebra, hw::WeightLatticeElem) - return dominant_weights(Vector{Int}, L, hw) + R = root_system(L) + return dominant_weights(R, hw) end @doc raw""" @@ -1498,11 +1500,7 @@ 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 +3*e(0) + e(2*w_1 + w_2) + e(2*w_2) + 2*e(w_1 + w_3) ``` """ function dominant_character(L::LieAlgebra, hw::Vector{<:IntegerUnion}) @@ -1530,17 +1528,7 @@ The return type may change in the future. 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 +e(2*w_1) + e(w_2) + e(-2*w_1 + 2*w_2) + e(-2*w_2 + 2*w_3) + e(-2*w_3) + e(w_1 - w_2 + w_3) + e(-w_1 + w_3) + e(w_1 - w_3) + e(-w_1 + w_2 - w_3) + e(-w_2) ``` """ function character(L::LieAlgebra, hw::Vector{<:IntegerUnion}) diff --git a/experimental/LieAlgebras/src/RootSystem.jl b/experimental/LieAlgebras/src/RootSystem.jl index 18d8b99306ba..9771beb10cf7 100644 --- a/experimental/LieAlgebras/src/RootSystem.jl +++ b/experimental/LieAlgebras/src/RootSystem.jl @@ -307,6 +307,15 @@ function set_root_system_type!( return nothing end +function character_parent_ring(R::RootSystem) + if !isdefined(R, :character_parent_ring) + R.character_parent_ring = Hecke._group_algebra( + ZZ, weight_lattice(R); sparse=true, cached=false + ) + end + return R.character_parent_ring::GroupAlgebra{ZZRingElem,WeightLattice,WeightLatticeElem} +end + @doc raw""" weight_lattice(R::RootSystem) -> WeightLattice @@ -1516,15 +1525,15 @@ See [MP82](@cite) for details and the implemented algorithm. ```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) @@ -1597,16 +1606,11 @@ 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 +e(2*w_1 + w_3) + e(w_2 + w_3) + 3*e(w_1 + w_3) + 6*e(w_3) ``` """ function dominant_character(R::RootSystem, hw::WeightLatticeElem) - char = _dominant_character(R, hw) - return Dict(Int.(_vec(coefficients(w))) => m for (w, m) in char) + return _dominant_character(R, hw) end function dominant_character(R::RootSystem, hw::Vector{<:IntegerUnion}) @@ -1626,13 +1630,14 @@ function _dominant_character(R::RootSystem, hw::WeightLatticeElem) pos_roots_w = WeightLatticeElem.(positive_roots(R)) pos_roots_w_coeffs = coefficients.(pos_roots_w) - char = Dict(hw => T(1)) + ZP = character_parent_ring(R) + char = ZP(hw) todo = dominant_weights(R, hw) 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 1 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] @@ -1657,7 +1662,7 @@ function _dominant_character(R::RootSystem, hw::WeightLatticeElem) w_plus_i_rep = w + rep while true w_plus_i_rep_conj = conjugate_dominant_weight(w_plus_i_rep) - haskey(char, w_plus_i_rep_conj) || break + iszero(char[w_plus_i_rep_conj]) && break accum2 += char[w_plus_i_rep_conj] * dot(w_plus_i_rep, rep) add!(w_plus_i_rep, rep) end @@ -1667,11 +1672,11 @@ function _dominant_character(R::RootSystem, hw::WeightLatticeElem) w_plus_rho = w + rho denom = dot_how_plus_rho - dot(w_plus_rho, w_plus_rho) if !iszero(denom) - char[w] = T(ZZ(div(accum, denom))) + char += ZZ(div(accum, denom)) * ZP(w) end end end - return char + return char::elem_type(ZP) end @doc raw""" @@ -1689,20 +1694,11 @@ The return type may change in the future. 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 +e(w_3) + e(w_2 - w_3) + e(w_1 - w_2 + w_3) + e(-w_1 + w_3) + e(w_1 - w_3) + e(-w_1 + w_2 - w_3) + e(-w_2 + w_3) + e(-w_3) ``` """ function character(R::RootSystem, hw::WeightLatticeElem) - char = _character(R, hw) - return Dict(Int.(_vec(coefficients(w))) => m for (w, m) in char) + return _character(R, hw) end function character(R::RootSystem, hw::Vector{<:IntegerUnion}) @@ -1714,11 +1710,12 @@ function _character(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) - char = Dict{WeightLatticeElem,T}() + ZP = character_parent_ring(R) + char = zero(ZP) for (w, m) in dom_char for w_conj in weyl_orbit(w) - push!(char, w_conj => m) + char += m * ZP(w_conj) end end @@ -1769,13 +1766,13 @@ 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) if all(!iszero, coefficients(w_dom)) sub!(w_dom, rho) coeff = m * (-1)^length(x) - push!(mults, w_dom, coeff) + push!(mults, w_dom, Int(coeff)) end end end @@ -1855,3 +1852,25 @@ function positive_roots_and_reflections(cartan_matrix::ZZMatrix) roots[perm], coroots[perm], table end + +# TODO: move to Hecke +function Base.length(x::GroupAlgebraElem) + @assert Hecke._is_sparse(x) + return length(x.coeffs_sparse) +end + +function Base.iterate(x::GroupAlgebraElem) + @assert Hecke._is_sparse(x) + next = iterate(x.coeffs_sparse) + isnothing(next) && return nothing + (i, c), st = next + return (parent(x).base_to_group[i], c), st +end + +function Base.iterate(x::GroupAlgebraElem, st) + @assert Hecke._is_sparse(x) + next = iterate(x.coeffs_sparse, st) + isnothing(next) && return nothing + (i, c), st = next + return (parent(x).base_to_group[i], c), st +end diff --git a/experimental/LieAlgebras/src/Types.jl b/experimental/LieAlgebras/src/Types.jl index 57b469d6ce15..b78f8ed37bfd 100644 --- a/experimental/LieAlgebras/src/Types.jl +++ b/experimental/LieAlgebras/src/Types.jl @@ -23,6 +23,7 @@ See [`root_system(::ZZMatrix)`](@ref) for the constructor. # optional: type::Vector{Tuple{Symbol,Int}} type_ordering::Vector{Int} + character_parent_ring::Any #::GroupAlgebra{ZZRingElem, WeightLattice, WeightLatticeElem} function RootSystem(mat::ZZMatrix; check::Bool=true, detect_type::Bool=true) check && @req is_cartan_matrix(mat) "Requires a generalized Cartan matrix" diff --git a/experimental/LieAlgebras/src/WeightLattice.jl b/experimental/LieAlgebras/src/WeightLattice.jl index 8dc3bee98f05..c047a8b4e863 100644 --- a/experimental/LieAlgebras/src/WeightLattice.jl +++ b/experimental/LieAlgebras/src/WeightLattice.jl @@ -62,7 +62,6 @@ function is_finite(P::WeightLattice) return iszero(rank(P)) end - ############################################################################### # # Weight lattice elements @@ -122,7 +121,6 @@ function root_system(w::WeightLatticeElem) return root_system(parent(w)) end - function zero(w::WeightLatticeElem) return zero(parent(w)) end diff --git a/experimental/LieAlgebras/test/WeightLattice-test.jl b/experimental/LieAlgebras/test/WeightLattice-test.jl index 16943dae1a65..985eac2cd0ba 100644 --- a/experimental/LieAlgebras/test/WeightLattice-test.jl +++ b/experimental/LieAlgebras/test/WeightLattice-test.jl @@ -5,7 +5,7 @@ @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]),