Skip to content

Commit

Permalink
Draft: Use group algebra for characters
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens committed Nov 20, 2024
1 parent 67ef67a commit e7cfeea
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 66 deletions.
2 changes: 1 addition & 1 deletion experimental/BasisLieHighestWeight/src/MainAlgorithm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 14 additions & 26 deletions experimental/LieAlgebras/src/LieAlgebraModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand All @@ -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)
Expand All @@ -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"""
Expand All @@ -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})
Expand Down Expand Up @@ -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})
Expand Down
91 changes: 55 additions & 36 deletions experimental/LieAlgebras/src/RootSystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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})
Expand All @@ -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]
Expand All @@ -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
Expand All @@ -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"""
Expand All @@ -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})
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions experimental/LieAlgebras/src/Types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 0 additions & 2 deletions experimental/LieAlgebras/src/WeightLattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ function is_finite(P::WeightLattice)
return iszero(rank(P))
end


###############################################################################
#
# Weight lattice elements
Expand Down Expand Up @@ -122,7 +121,6 @@ function root_system(w::WeightLatticeElem)
return root_system(parent(w))
end


function zero(w::WeightLatticeElem)
return zero(parent(w))
end
Expand Down
2 changes: 1 addition & 1 deletion experimental/LieAlgebras/test/WeightLattice-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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]),
Expand Down

0 comments on commit e7cfeea

Please sign in to comment.