Skip to content

Commit

Permalink
LieAlgebras: Adapt Demazure operator (#4384)
Browse files Browse the repository at this point in the history
Co-authored-by: Lars Göttgens <lars.goettgens@gmail.com>
Co-authored-by: Max Horn <max@quendi.de>
  • Loading branch information
3 people authored Jan 9, 2025
1 parent 02d2e8d commit 8ab4265
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 20 deletions.
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
35 changes: 29 additions & 6 deletions experimental/LieAlgebras/src/RootSystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -335,13 +335,12 @@ 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"
@req is_positive_root(r) "r is not a positive root"

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 +363,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 group ring $\mathbb{Z}[P]$.
If a single Weight lattice element `w` is supplied, this is interpreted as `Dict(w => 1)`.
# 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 +405,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
16 changes: 8 additions & 8 deletions src/Groups/spinor_norms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ function _sigma_sharp(rkL, detL, q, p)
end

@doc raw"""
reflection(gram::QQMatrix, v::QQMatrix) -> QQMatrix
Oscar._reflection(gram::QQMatrix, v::QQMatrix) -> QQMatrix
Return the matrix representation of the orthogonal reflection in the row vector `v`.
"""
function reflection(gram::MatElem, v::MatElem)
function _reflection(gram::MatElem, v::MatElem)
n = ncols(gram)
E = identity_matrix(base_ring(gram), n)
c = base_ring(gram)(2) * ((v * gram * transpose(v)))[1,1]^(-1)
Expand Down Expand Up @@ -154,7 +154,7 @@ function spin(gram_diag::MatElem, isometry::MatElem, check::Bool=true)
r = v - w
s = r * G * transpose(r)
if !iszero(s)
tau = reflection(G, r)
tau = _reflection(G, r)
f = f * tau
@assert w * f == w
spinor_norm *= s
Expand All @@ -164,8 +164,8 @@ function spin(gram_diag::MatElem, isometry::MatElem, check::Bool=true)
r2 = v
s2 = r2 * G * transpose(r2)/2
@assert !iszero(s1) && !iszero(s2)
tau1 = reflection(G, r1)
tau2 = reflection(G, r2)
tau1 = _reflection(G, r1)
tau2 = _reflection(G, r2)
f = f * tau2 * tau1
@assert w * f == w
spinor_norm *= s1 * s2
Expand Down Expand Up @@ -219,15 +219,15 @@ function det_spin(G::QQMatrix, T::QQMatrix, p, nu)
bm = g - E[k:k,:]
qm = bm * G * transpose(bm)
if valuation(qm, p) <= gammaL[k] + 2*delta
tau1 = reflection(G, bm)
tau1 = _reflection(G, bm)
push!(reflection_vectors, bm)
tau2 = E
else
bp = g + E[k:k,:]
qp = bp * G * transpose(bp)
@assert valuation(qp, p) <= gammaL[k] + 2*delta
tau1 = reflection(G, bp)
tau2 = reflection(G, E[k:k,:])
tau1 = _reflection(G, bp)
tau2 = _reflection(G, E[k:k,:])
push!(reflection_vectors,bp)
push!(reflection_vectors,E[k:k,:])
end
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)
@req root_system(w) === root_system(beta) "Incompatible root systems"
for s in word(reflection(beta))
reflect!(w, Int(s))
end
return w
end
37 changes: 37 additions & 0 deletions src/LieTheory/WeylGroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,43 @@ 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 the root `beta`.
"""
function reflection(beta::RootSpaceElem)
R = root_system(beta)
W = weyl_group(R)
rk = number_of_simple_roots(R)

b, index_of_beta = is_root_with_index(beta)
@req b "Not a root"
# for a negative root we want the index of the corresponding positive root
if index_of_beta > number_of_positive_roots(R)
index_of_beta -= number_of_positive_roots(R)
end

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 @@ -1408,6 +1408,7 @@ export reduced_groebner_basis
export reduced_scheme
export reducible_fibers
export reflect, reflect!
export reflection
export register_morphism!
export regular_120_cell
export regular_24_cell
Expand Down
Loading

0 comments on commit 8ab4265

Please sign in to comment.