Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LieAlgebras: Adapt Demazure operator #4384

Merged
merged 21 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/src/LieTheory/root_systems.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ is_negative_root_with_index(::RootSpaceElem)
```@docs
reflect(::RootSpaceElem, ::Int)
reflect!(::RootSpaceElem, ::Int)
reflect(::RootSpaceElem, ::RootSpaceElem)
reflect!(::RootSpaceElem, ::RootSpaceElem)
```


Expand Down
2 changes: 2 additions & 0 deletions docs/src/LieTheory/weight_lattices.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ is_fundamental_weight_with_index(::WeightLatticeElem)
```@docs
reflect(::WeightLatticeElem, ::Int)
reflect!(::WeightLatticeElem, ::Int)
reflect(::WeightLatticeElem, ::RootSpaceElem)
reflect!(::WeightLatticeElem, ::RootSpaceElem)
```

### Conjugate dominant weight
Expand Down
14 changes: 13 additions & 1 deletion docs/src/LieTheory/weyl_groups.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ weyl_group(::Vector{Tuple{Symbol,Int}})
## Basic properties
Basic group arithmetic like `*`, and `inv` are defined for `WeylGroupElem` objects.

Using `(W::WeylGroup)(word::Vector{<:Integer})`, one can construct group elements from a word in the generators.
Finite Weyl groups support iteration over all group elements (in an arbitrary order).

```@docs
Expand All @@ -50,6 +49,19 @@ order(::Type{T}, ::WeylGroup) where {T}
root_system(::WeylGroup)
```

### Element constructors

Using `(W::WeylGroup)(word::Vector{<:Integer})`, one can construct group elements from a word in the generators.

```@docs; canonical=false
gen(::WeylGroup, ::Int)
gens(::WeylGroup)
```

```@docs
reflection(::RootSpaceElem)
```

### Words and length
```@docs
word(::WeylGroupElem)
Expand Down
36 changes: 30 additions & 6 deletions experimental/LieAlgebras/src/RootSystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -335,13 +335,13 @@ end
###############################################################################
# demazures character formula
function _demazure_operator(r::RootSpaceElem, w::WeightLatticeElem)
fl, index_of_r = is_simple_root_with_index(r)
@req fl "not a simple root"
fl, index_of_r = is_positive_root_with_index(r)
@req fl "r is not a positive root"
janikapeters marked this conversation as resolved.
Show resolved Hide resolved

d = 2 * dot(w, r)//dot(r, r)
list_of_occuring_weights = WeightLatticeElem[]

refl = reflect(w, index_of_r)
refl = reflect(w, r)

wlelem_r = WeightLatticeElem(r)
if d > -1
Expand All @@ -364,10 +364,30 @@ function _demazure_operator(r::RootSpaceElem, w::WeightLatticeElem)
end
end

function demazure_operator(r::RootSpaceElem, w::WeightLatticeElem)
return demazure_operator(r, Dict(w => 1))
end
@doc raw"""
demazure_operator(r::RootSpaceElem, w::WeightLatticeElem) -> Dict{WeightLatticeElem,<:IntegerUnion}
demazure_operator(r::RootSpaceElem, groupringelem::Dict{WeightLatticeElem,<:IntegerUnion}) -> Dict{WeightLatticeElem,<:IntegerUnion}

Computes the action of the Demazure operator associated to the positive root `r` on the given element of the groupring $\mathbb{Z}[P]$.

If a single Weight lattice element `w` is supplied, this is interpreted as `Dict(w => 1)`.
lgoettgens marked this conversation as resolved.
Show resolved Hide resolved

# Examples
```jldoctest
julia> R = root_system(:A, 3);

julia> pos_r = positive_root(R, 4)
a_1 + a_2

julia> w = fundamental_weight(R, 1)
w_1

julia> demazure_operator(pos_r, w)
Dict{WeightLatticeElem, Int64} with 2 entries:
-w_2 + w_3 => 1
w_1 => 1
```
"""
function demazure_operator(
r::RootSpaceElem, groupringelem::Dict{WeightLatticeElem,<:IntegerUnion}
)
Expand All @@ -386,6 +406,10 @@ function demazure_operator(
return dict
end

function demazure_operator(r::RootSpaceElem, w::WeightLatticeElem)
return demazure_operator(r, Dict(w => 1))
end

@doc raw"""
demazure_character([T = Int], R::RootSystem, w::WeightLatticeElem, x::WeylGroupElem) -> Dict{WeightLatticeElem, T}
demazure_character([T = Int], R::RootSystem, w::Vector{<:IntegerUnion}, x::WeylGroupElem) -> Dict{WeightLatticeElem, T}
Expand Down
31 changes: 31 additions & 0 deletions experimental/LieAlgebras/test/LieAlgebraModule-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,37 @@
end
end

@testset "demazure_operator" begin
R = root_system(:B, 2)
rho = weyl_vector(R)

@test demazure_operator(simple_root(R, 1), rho) == Dict(
WeightLatticeElem(R, [1, 1]) => 1,
WeightLatticeElem(R, [-1, 3]) => 1,
)

@test demazure_operator(simple_root(R, 2), rho) == Dict(
WeightLatticeElem(R, [1, 1]) => 1,
WeightLatticeElem(R, [2, -1]) => 1,
)

@test demazure_operator(root(R, 3), rho) == Dict(
WeightLatticeElem(R, [1, 1]) => 1,
WeightLatticeElem(R, [-2, 1]) => 1,
WeightLatticeElem(R, [0, 1]) => 1,
WeightLatticeElem(R, [-1, 1]) => 1,
)

@test demazure_operator(simple_root(R, 1), -rho) == Dict()

@test demazure_operator(simple_root(R, 2), -rho) == Dict()

@test demazure_operator(root(R, 3), -rho) == Dict(
WeightLatticeElem(R, [0, -1]) => -1,
WeightLatticeElem(R, [1, -1]) => -1,
)
end

@testset "demazure_character" begin
function demazure_character_trivial_tests(R::RootSystem, w::WeightLatticeElem)
W = weyl_group(R)
Expand Down
44 changes: 41 additions & 3 deletions src/LieTheory/RootSystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,32 @@ function reflect!(r::RootSpaceElem, s::Int)
return r
end

@doc raw"""
reflect(r::RootSpaceElem, beta::RootSpaceElem) -> RootSpaceElem

Return the reflection of `r` in the hyperplane orthogonal to root `beta`.

See also: [`reflect!(::RootSpaceElem, ::RootSpaceElem)`](@ref).
"""
function reflect(r::RootSpaceElem, beta::RootSpaceElem)
return reflect!(deepcopy(r), beta)
end

@doc raw"""
reflect!(r::RootSpaceElem, beta::RootSpaceElem) -> RootSpaceElem

Reflect `r` in the hyperplane orthogonal to the root `beta`, and return it.

This is a mutating version of [`reflect(::RootSpaceElem, ::RootSpaceElem)`](@ref).
"""
function reflect!(r::RootSpaceElem, beta::RootSpaceElem)
@req root_system(r) === root_system(beta) "Incompatible root systems"
for s in word(reflection(beta))
reflect!(r, Int(s))
end
return r
end

@doc raw"""
root_system(r::RootSpaceElem) -> RootSystem

Expand Down Expand Up @@ -1452,8 +1478,20 @@ end
###############################################################################
# internal helpers

# cartan matrix in the format <a^v, b>
function positive_roots_and_reflections(cartan_matrix::ZZMatrix)
@doc raw"""
_positive_roots_and_reflections(cartan_matrix::ZZMatrix) -> Vector{Vector{ZZRingElem}}, Vector{Vector{ZZRingElem}}, Matrix{UInt64}

Compute the positive roots, the positive coroots, and a matrix `refl` of size $m \times n$,
where $m$ is the rank of the root system and $n$ is the number of minimal roots.

The minimal roots and coroots are given as coefficient vectors w.r.t. the simple roots and simple coroots, respectively.
The minimal roots are indexed by `1:n`, with the first `m` of them corresponding
to the simple roots, and the other roots sorted by height.

If `beta = alpha_j * s_i` is a minimal root, then `refl_table[i, j]` stores the index of beta, and otherwise `0`.
Note that `refl_table[i, i] = 0` for every simple root `alpha_i`.
"""
function _positive_roots_and_reflections(cartan_matrix::ZZMatrix)
rank, _ = size(cartan_matrix)

roots = [[l == s ? one(ZZ) : zero(ZZ) for l in 1:rank] for s in 1:rank]
Expand Down Expand Up @@ -1508,5 +1546,5 @@ function positive_roots_and_reflections(cartan_matrix::ZZMatrix)
table[s, i] = iszero(refl[s, perm[i]]) ? 0 : invp[refl[s, perm[i]]]
end

roots[perm], coroots[perm], table
return roots[perm], coroots[perm], table
end
4 changes: 2 additions & 2 deletions src/LieTheory/Types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ See [`root_system(::ZZMatrix)`](@ref) for the constructor.
function RootSystem(mat::ZZMatrix; check::Bool=true, detect_type::Bool=true)
check && @req is_cartan_matrix(mat) "Requires a generalized Cartan matrix"

pos_roots, pos_coroots, refl = positive_roots_and_reflections(mat)
pos_roots, pos_coroots, refl = _positive_roots_and_reflections(mat)
finite = count(refl .== 0) == nrows(mat)

R = new(mat)
Expand Down Expand Up @@ -149,7 +149,7 @@ See [`weyl_group(::RootSystem)`](@ref) for the constructor.
"""
@attributes mutable struct WeylGroup <: AbstractAlgebra.Group
finite::Bool # finite indicates whether the Weyl group is finite
refl::Matrix{UInt} # see positive_roots_and_reflections
refl::Matrix{UInt} # see _positive_roots_and_reflections
root_system::RootSystem # root_system is the RootSystem from which the Weyl group was constructed

function WeylGroup(finite::Bool, refl::Matrix{UInt}, root_system::RootSystem)
Expand Down
26 changes: 26 additions & 0 deletions src/LieTheory/WeightLattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,29 @@ 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"""
reflect(w::WeightLatticeElem, beta::RootSpaceElem) -> RootSpaceElem

Return the reflection of `w` in the hyperplane orthogonal to root `beta`.

See also: [`reflect!(::WeightLatticeElem, ::RootSpaceElem)`](@ref).
"""
function reflect(w::WeightLatticeElem, beta::RootSpaceElem)
return reflect!(deepcopy(w), beta)
end

@doc raw"""
reflect!(w::WeightLatticeElem, beta::RootSpaceElem) -> RootSpaceElem

Reflect `w` in the hyperplane orthogonal to the root `beta`, and return it.

This is a mutating version of [`reflect(::WeightLatticeElem, ::RootSpaceElem)`](@ref).
"""
function reflect!(w::WeightLatticeElem, beta::RootSpaceElem)
janikapeters marked this conversation as resolved.
Show resolved Hide resolved
@req root_system(w) === root_system(beta) "Incompatible root systems"
for s in word(reflection(beta))
reflect!(w, Int(s))
end
return w
end
36 changes: 36 additions & 0 deletions src/LieTheory/WeylGroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,42 @@ function word(x::WeylGroupElem)
return x.word
end

@doc raw"""
reflection(beta::RootSpaceElem) -> WeylGroupElem

Return the Weyl group element corresponding to the reflection at the hyperplane orthogonal to root `beta`.
lgoettgens marked this conversation as resolved.
Show resolved Hide resolved
"""
function reflection(beta::RootSpaceElem)
R = root_system(beta)
W = weyl_group(R)
rk = number_of_simple_roots(R)

b, index_of_beta = is_positive_root_with_index(beta)
if !b
b, index_of_beta = is_negative_root_with_index(beta)
end
@req b "Not a root"
janikapeters marked this conversation as resolved.
Show resolved Hide resolved

found_simple_root = index_of_beta <= rk
current_index = index_of_beta
list_of_indices = Int[]
while !found_simple_root
for j in 1:rk
next_index = W.refl[j, current_index]
if !iszero(next_index) &&
next_index < current_index
current_index = next_index
if current_index <= rk
found_simple_root = true
end
push!(list_of_indices, j)
break
end
end
end
return W([list_of_indices; current_index; reverse(list_of_indices)])
end

###############################################################################
# ReducedExpressionIterator

Expand Down
1 change: 1 addition & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,7 @@ export reduced_groebner_basis
export reduced_scheme
export reducible_fibers
export reflect, reflect!
export reflection
janikapeters marked this conversation as resolved.
Show resolved Hide resolved
export register_morphism!
export regular_120_cell
export regular_24_cell
Expand Down
63 changes: 63 additions & 0 deletions test/LieTheory/WeylGroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,70 @@ include(
@test parent(x) === x.parent
@test parent(x) isa WeylGroup
end

@testset "reflection" begin
for i in 2:4
R = root_system(:A, i)
for r in roots(R)
@test r * reflection(r) == -r
end
end

for i in 2:4
R = root_system(:B, i)
for r in roots(R)
@test r * reflection(r) == -r
end
end

for i in 2:4
R = root_system(:C, i)
for r in roots(R)
@test r * reflection(r) == -r
end
end

R = root_system(:D, 4)
for r in roots(R)
@test r * reflection(r) == -r
end

R = root_system(:E, 6)
for r in roots(R)
@test r * reflection(r) == -r
end

R = root_system(:E, 7)
for r in roots(R)
@test r * reflection(r) == -r
end

R = root_system(:E, 8)
for r in roots(R)
@test r * reflection(r) == -r
end

R = root_system(:F, 4)
for r in roots(R)
@test r * reflection(r) == -r
end

R = root_system(:G, 2)
for r in roots(R)
@test r * reflection(r) == -r
end

R = root_system([(:B, 2), (:A, 2)])
for r in roots(R)
@test r * reflection(r) == -r
for r2 in roots(R)
if is_zero(dot(r, r2)) #roots are orthogonal
@test r2 * reflection(r) == r2
end
end
end
end

@testset "ReducedExpressionIterator" begin
W = weyl_group(:A, 3)
s = gens(W)
Expand Down
Loading