Weyl groups
The Weyl group is generated by simple reflections $s_1, \ldots, s_r$. Elements are stored as reduced words (sequences of generator indices).
Semisimple.jl writes Weyl group actions on the right: λ * x denotes the usual geometric action of x on the weight or root λ. Products are applied in the same order as written in λ * (s1 * s2), matching OSCAR's right-action convention for roots and weights.
Creating the Weyl group
julia> using Semisimple
julia> W = weyl_group(TypeA{3})
Weyl group of type A3
julia> weyl_order(TypeA{3})
24Semisimple.WeylGroup — Type
WeylGroup{DT,R}The Weyl group of a root system of Dynkin type DT with rank R.
Semisimple.jl writes Weyl group actions on the right: λ * x denotes the usual action of the Weyl group element x on the weight or root λ.
Examples
julia> using Semisimple
julia> weyl_order(TypeA{2})
6Semisimple.WeylGroupElem — Type
WeylGroupElem{DT,R}An element of the Weyl group, stored as a reduced word (vector of simple reflection indices).
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2});
julia> W([1, 2])
s1 * s2Semisimple.weyl_group — Function
weyl_group(::Type{DT}) -> WeylGroup{DT}Construct the Weyl group for the given Dynkin type.
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2})
Weyl group of type A2Semisimple.weyl_order — Function
weyl_order(::Type{DT}) -> BigIntReturn the order of the Weyl group of type DT.
Examples
julia> using Semisimple
julia> weyl_order(TypeA{3})
24
julia> weyl_order(TypeE{8})
696729600Semisimple.root_system — Function
root_system(W::WeylGroup) -> RootSystemReturn the root system underlying the Weyl group W.
Examples
julia> using Semisimple
julia> root_system(weyl_group(TypeA{2}))
Root system of type A2, rank 2 with 3 positive rootsGenerators and multiplication
julia> s1 = gen(W, 1)
s1
julia> s2 = gen(W, 2)
s2
julia> s1 * s2
s1 * s2
julia> word(s1)
1-element Vector{UInt8}:
0x01
julia> word(s1 * s2)
2-element Vector{UInt8}:
0x01
0x02Longest element
The longest element $w_0$ has maximal length in the Weyl group:
julia> w0 = longest_element(W)
s1 * s2 * s1 * s3 * s2 * s1
julia> length(word(w0))
6Semisimple.gens — Function
gens(W::WeylGroup) -> Vector{WeylGroupElem}Return all simple reflections.
Examples
julia> using Semisimple
julia> gens(weyl_group(TypeA{2}))
2-element Vector{WeylGroupElem{TypeA{2}, 2}}:
s1
s2Semisimple.gen — Function
gen(W::WeylGroup, i) -> WeylGroupElemReturn the i-th simple reflection.
Examples
julia> using Semisimple
julia> gen(weyl_group(TypeA{2}), 1)
s1Semisimple.longest_element — Function
longest_element(W::WeylGroup{DT,R}) -> WeylGroupElem{DT,R}Compute the longest element w0 of the Weyl group. Uses the iterative algorithm: repeatedly find a simple reflection that increases length. The result is cached per Dynkin type.
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2});
julia> w0 = longest_element(W);
julia> length(w0)
3Semisimple.word — Function
word(x::WeylGroupElem) -> Vector{UInt8}Return the reduced word of x.
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2});
julia> word(W([1, 2]))
2-element Vector{UInt8}:
0x01
0x02Base.length — Method
Base.length(x::WeylGroupElem) -> IntReturn the length (number of simple reflections) of x.
Semisimple.rmul! — Function
rmul!(x::WeylGroupElem, s::UInt8) -> WeylGroupElemMultiply x from the right by the simple reflection s, maintaining the reduced word in short-lex normal form.
Uses the reflection table from the root system.
Action on weights
The Weyl group acts on the weight lattice. Right multiplication corresponds to the geometric reflection:
julia> ω1 = fundamental_weight(TypeA{3}, 1);
julia> ω1 * s1 # s1(ω1) = -ω1 + ω2
-ω1 + ω2
julia> ω1 * s2 # s2(ω1) = ω1 (orthogonal)
ω1Action on roots
julia> RS = RootSystem(TypeA{3});
julia> α1 = simple_root(RS, 1);
julia> α1 * s1 # s1(α1) = -α1
-α1
julia> α1 * s2 # s2(α1) = α1 + α2
α1 + α2Weyl orbits
The orbit of a weight under the full Weyl group:
julia> orbit = weyl_orbit(TypeA{3}, ω1);
julia> length(orbit) # |W/Stab(ω1)| = 4 for std rep of A3
4For the adjoint representation of $\mathrm{A}_2$:
julia> ω = fundamental_weight(TypeA{2}, 1) + fundamental_weight(TypeA{2}, 2);
julia> length(weyl_orbit(TypeA{2}, ω))
6Semisimple.weyl_orbit — Function
weyl_orbit(::Type{DT}, w::WeightLatticeElem{DT,R}) -> Vector{WeightLatticeElem{DT,R}}Compute the full Weyl orbit of the weight w.
Examples
julia> using Semisimple
julia> length(weyl_orbit(TypeA{2}, fundamental_weight(TypeA{2}, 1)))
3Dominant weights
All dominant weights $\mu \leq \lambda$ (in the dominance order):
julia> ω2 = fundamental_weight(TypeA{3}, 2);
julia> dw = dominant_weights(TypeA{3}, ω1 + ω2);
julia> length(dw)
2Semisimple.dominant_weights — Function
dominant_weights(::Type{DT}, hw::WeightLatticeElem{DT,R}) -> Vector{WeightLatticeElem{DT,R}}Compute the dominant weights occurring in the irreducible representation with highest weight hw, sorted by decreasing level below hw.
The level of μ below hw is the root-lattice height of hw - μ, i.e. the sum of coefficients when hw - μ is written in the simple root basis.
Examples
julia> using Semisimple
julia> λ = fundamental_weight(TypeA{2}, 1) + fundamental_weight(TypeA{2}, 2);
julia> length(dominant_weights(λ))
2Weyl dimension formula
The dimension of the irreducible representation $\mathrm{V}(\lambda)$:
julia> degree(ω1) # standard rep of A3 (SL4)
4
julia> degree(ω2) # ⋀² of standard = 6-dim
6
julia> degree(ω1 + ω2) # 20-dim rep
20
julia> degree(weyl_vector(TypeA{3})) # ρ = ω1+ω2+ω3
64A₂ examples:
julia> ω1_a2 = fundamental_weight(TypeA{2}, 1);
julia> degree(ω1_a2)
3
julia> degree(ω1_a2 + fundamental_weight(TypeA{2}, 2)) # adjoint
8The zero weight gives the trivial representation:
julia> degree(WeightLatticeElem(TypeA{3}, [0, 0, 0]))
1Semisimple.degree — Function
degree(::Type{DT}, hw::WeightLatticeElem{DT,R}) -> BigInt
degree(hw::WeightLatticeElem{DT,R}) -> BigIntDimension of the irreducible representation with highest weight hw, computed via the Weyl dimension formula:
$\dim \mathrm{V}(λ) = \prod_{α > 0} \frac{⟨λ + ρ, α^\vee⟩}{⟨ρ, α^\vee⟩}$
Equivalently, using the invariant bilinear form, $\prod_{α>0} (λ+ρ,α)/(ρ,α)$.
The denominator and the symmetrizer-scaled root vectors are precomputed once per Dynkin type. The numerator is computed as a BigInt product of Int-valued inner products via in-place GMP arithmetic.
Examples
julia> using Semisimple
julia> degree(fundamental_weight(TypeA{3}, 1))
4
julia> degree(fundamental_weight(TypeB{3}, 3))
8
julia> degree(fundamental_weight(TypeE{8}, 8))
248
julia> [degree(fundamental_weight(TypeB{3}, i)) for i in 1:3]
3-element Vector{BigInt}:
7
21
8degree(::Type{DT}, v::AbstractVector{<:Integer}) -> BigIntDimension of the irreducible representation with highest weight given by the integer vector v (in the fundamental weight basis).
This is a convenience wrapper: degree(DT, v) == degree(WeightLatticeElem(DT, v)).
Examples
julia> using Semisimple
julia> degree(TypeA{2}, [1, 0]) # standard representation of A2
3
julia> degree(TypeE{8}, [0, 0, 0, 0, 0, 0, 0, 1]) # adjoint of E8
248degree(V::WeylCharacter) -> BigIntReturn the (signed) dimension of a character in the representation ring.
For a virtual character V = ∑ mᵢ V(λᵢ) (with mᵢ possibly negative), returns:
deg(V) = ∑ mᵢ dim(V(λᵢ))For effective characters (all mᵢ ≥ 0) this equals the total dimension of the corresponding representation. For virtual characters (some mᵢ < 0) the result can be negative or zero; this is the Euler characteristic in the representation ring.
Returns a BigInt.
Examples
julia> using Semisimple
julia> ω1 = fundamental_weight(TypeA{2}, 1);
julia> V = WeylCharacter(ω1);
julia> degree(V) # dim of standard representation
3
julia> degree(V^2) # dim of V ⊗ V = Sym²V ⊕ ⋀²V
9
julia> degree(Sym(2, V)) # dim of Sym²V
6
julia> # Virtual character: V(ω1) - V(ω2) has degree 0 (both dim 3)
degree(V - WeylCharacter(fundamental_weight(TypeA{2}, 2)))
0
julia> ω8 = fundamental_weight(TypeE{8}, 8);
julia> degree(WeylCharacter(ω8))
248Semisimple.weyl_dimension — Function
weyl_dimension(λ::WeightLatticeElem) -> BigInt
weyl_dimension(::Type{DT}, λ::WeightLatticeElem) -> BigInt
weyl_dimension(::Type{DT}, v::AbstractVector{<:Integer}) -> BigInt
weyl_dimension(dt::DynkinType, v) -> BigIntSynonym for degree. Computes the dimension of the irreducible representation via the Weyl dimension formula.
Borel–Weil–Bott theorem
Compute the cohomological degree and resulting representation for a weight on a flag variety:
julia> import Semisimple: borel_weil_bott
julia> borel_weil_bott(ω1) # dominant weight → degree 0
(0, ω1)
julia> borel_weil_bott(WeightLatticeElem(TypeA{3}, [-3, 2, 1]))
(1, ω1 + ω3)Singular weights give zero cohomology, and borel_weil_bott returns nothing:
julia> borel_weil_bott(-weyl_vector(TypeA{3})) === nothing
trueborel_weil_bott is not exported. It is rather a feature for PartialFlagVarieties.jl. Use import Semisimple: borel_weil_bott to access it.
Semisimple.borel_weil_bott — Function
borel_weil_bott(λ::WeightLatticeElem{DT,R}) -> Union{Nothing, Tuple{Int, WeightLatticeElem{DT,R}}}Apply the Borel–Weil–Bott theorem to the weight λ.
This function is a preview implementation that properly belongs to PartialFlagVarieties.jl, an upcoming companion package. It is included here for convenience but is not part of the public API of Semisimple.jl and is not exported. Access it via import Semisimple: borel_weil_bott.
Compute μ = λ + ρ and find the unique Weyl group element w such that w(μ) is dominant. If μ is singular (lies on a Weyl chamber wall), all cohomology vanishes and we return nothing. Otherwise, return (d, w(μ) - ρ) where d = ℓ(w) is the cohomological degree, meaning
$\mathrm{H}^d(G/B, \mathcal{L}_λ) \cong \mathrm{V}_{w(μ)-ρ}^*$
and all other cohomology groups vanish.
Examples
julia> using Semisimple; import Semisimple: borel_weil_bott
julia> borel_weil_bott(fundamental_weight(TypeA{2}, 1))
(0, ω1)
julia> borel_weil_bott(WeightLatticeElem(TypeA{2}, [-2, 1]))
(1, 0)
julia> borel_weil_bott(-weyl_vector(TypeA{2})) === nothing
trueSingular weights
A weight $\lambda$ is singular when $\langle \lambda + \rho, \alpha^\vee \rangle = 0$ for some positive root $\alpha$. Singular weights give zero cohomology:
julia> λ = WeightLatticeElem(TypeA{2}, [-1, 0]);
julia> is_singular(λ)
trueSemisimple.is_singular — Function
is_singular(w::WeightLatticeElem{DT,R}) -> BoolCheck whether the weight w is singular, i.e. lies on some wall of a Weyl chamber. Equivalently, w is singular iff ⟨α∨, w⟩ = 0 for some positive root α.
For a dominant weight this simplifies to checking whether any fundamental weight coordinate is zero. For a general weight, we first conjugate to the dominant chamber.
Examples
julia> using Semisimple
julia> is_singular(fundamental_weight(TypeA{2}, 1))
true
julia> is_singular(weyl_vector(TypeA{2}))
falseBruhat order and descent sets
The Bruhat order on the Weyl group is a partial order defined by subword inclusion in reduced expressions. Descent sets record which simple reflections reduce the word length.
julia> s3 = gen(W, 3)
s3
julia> x = s1 * s2;
julia> right_descent_set(x)
1-element Vector{Int64}:
2
julia> bruhat_leq(s1, x)
true
julia> bruhat_leq(x, s1)
falseSemisimple.right_descent_set — Function
right_descent_set(w::WeylGroupElem) -> Vector{Int}Return the right descent set of w, i.e. the indices i such that \ell(ws_i) < \ell(w).
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2});
julia> right_descent_set(W([1, 2]))
1-element Vector{Int64}:
2Semisimple.left_descent_set — Function
left_descent_set(w::WeylGroupElem) -> Vector{Int}Return the left descent set of w, i.e. the indices i such that \ell(s_iw) < \ell(w).
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2});
julia> left_descent_set(W([1, 2]))
1-element Vector{Int64}:
1Semisimple.bruhat_leq — Function
bruhat_leq(x::WeylGroupElem, y::WeylGroupElem) -> BoolReturn whether x \le y in the (strong) Bruhat order.
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2});
julia> bruhat_leq(gen(W, 1), W([1, 2]))
trueSemisimple.bruhat_descendants — Function
bruhat_descendants(w::WeylGroupElem) -> Vector{WeylGroupElem}Return the immediate Bruhat descendants obtained by right-multiplying by simple reflections in the right descent set.
Examples
julia> using Semisimple
julia> W = weyl_group(TypeA{2});
julia> bruhat_descendants(W([1, 2]))
1-element Vector{WeylGroupElem{TypeA{2}, 2}}:
s1Parabolic subgroups and coset representatives
For a subset $I \subseteq \{1,\ldots,r\}$ of simple root indices, the parabolic subgroup $W_I$ is generated by $\{s_i : i \in I\}$. The minimal-length coset representatives for $W/W_I$ are the elements whose right descent sets are disjoint from $I$.
julia> reps = right_coset_reps(W, [1]); # W/⟨s1⟩ for A3
julia> length(reps) # |A3|/|A1×A1 ... actually just |W|/|W_{1}| = 24/2 = 12
12
julia> all(w -> !(1 in right_descent_set(w)), reps)
trueSemisimple.right_coset_reps — Function
right_coset_reps(W::WeylGroup, I::AbstractVector{<:Integer}) -> Vector{WeylGroupElem}Enumerate minimal right coset representatives for W/W_I, where W_I is the parabolic subgroup generated by simple reflections in I.
Uses a weight-orbit BFS: the weight $λ_I = \sum_{j \notin I} ω_j$ has stabilizer exactly $W_I$, so its $W$-orbit has size $|W/W_I|$. Enumerates that orbit using $O(|W/W_I| \cdot R)$ weight reflections, independent of $|W|$.
Examples
julia> using Semisimple
julia> length(right_coset_reps(weyl_group(TypeA{2}), [1]))
3Semisimple.left_coset_reps — Function
left_coset_reps(W::WeylGroup, I::AbstractVector{<:Integer}) -> Vector{WeylGroupElem}Enumerate minimal left coset representatives for W_I\W.
Examples
julia> using Semisimple
julia> length(left_coset_reps(weyl_group(TypeA{2}), [1]))
3Weyl group orders
julia> weyl_order(TypeA{3})
24
julia> weyl_order(TypeB{3})
48
julia> weyl_order(TypeG2)
12
julia> weyl_order(TypeE{8})
696729600