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})
24
Semisimple.WeylGroupType
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})
6
source
Semisimple.WeylGroupElemType
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 * s2
source
Semisimple.weyl_groupFunction
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 A2
source
Semisimple.weyl_orderFunction
weyl_order(::Type{DT}) -> BigInt

Return the order of the Weyl group of type DT.

Examples

julia> using Semisimple

julia> weyl_order(TypeA{3})
24

julia> weyl_order(TypeE{8})
696729600
source
Semisimple.root_systemFunction
root_system(W::WeylGroup) -> RootSystem

Return 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 roots
source

Generators 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
 0x02

Longest 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))
6
Semisimple.gensFunction
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
 s2
source
Semisimple.genFunction
gen(W::WeylGroup, i) -> WeylGroupElem

Return the i-th simple reflection.

Examples

julia> using Semisimple

julia> gen(weyl_group(TypeA{2}), 1)
s1
source
Semisimple.longest_elementFunction
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)
3
source
Semisimple.wordFunction
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
 0x02
source
Base.oneMethod
one(W::WeylGroup) -> WeylGroupElem

Return the identity element.

Examples

julia> using Semisimple

julia> one(weyl_group(TypeA{2}))
id
source
Base.lengthMethod
Base.length(x::WeylGroupElem) -> Int

Return the length (number of simple reflections) of x.

source
Semisimple.rmul!Function
rmul!(x::WeylGroupElem, s::UInt8) -> WeylGroupElem

Multiply 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.

source

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)
ω1
Base.:*Method
*(w::WeightLatticeElem{DT,R}, x::WeylGroupElem{DT,R}) -> WeightLatticeElem{DT,R}

Right action of a Weyl group element on a weight.

source

Action 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 + α2
Base.:*Method
*(r::RootSpaceElem{DT,R}, x::WeylGroupElem{DT,R}) -> RootSpaceElem{DT,R}

Right action of a Weyl group element on a root space element.

source

Weyl 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
4

For the adjoint representation of $\mathrm{A}_2$:

julia> ω = fundamental_weight(TypeA{2}, 1) + fundamental_weight(TypeA{2}, 2);

julia> length(weyl_orbit(TypeA{2}, ω))
6
Semisimple.weyl_orbitFunction
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)))
3
source

Dominant 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)
2
Semisimple.dominant_weightsFunction
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(λ))
2
source

Weyl 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
64

A₂ examples:

julia> ω1_a2 = fundamental_weight(TypeA{2}, 1);

julia> degree(ω1_a2)
3

julia> degree(ω1_a2 + fundamental_weight(TypeA{2}, 2))   # adjoint
8

The zero weight gives the trivial representation:

julia> degree(WeightLatticeElem(TypeA{3}, [0, 0, 0]))
1
Semisimple.degreeFunction
degree(::Type{DT}, hw::WeightLatticeElem{DT,R}) -> BigInt
degree(hw::WeightLatticeElem{DT,R}) -> BigInt

Dimension 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
  8
source
degree(::Type{DT}, v::AbstractVector{<:Integer}) -> BigInt

Dimension 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
248
source
degree(V::WeylCharacter) -> BigInt

Return 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))
248
source
Semisimple.weyl_dimensionFunction
weyl_dimension(λ::WeightLatticeElem) -> BigInt
weyl_dimension(::Type{DT}, λ::WeightLatticeElem) -> BigInt
weyl_dimension(::Type{DT}, v::AbstractVector{<:Integer}) -> BigInt
weyl_dimension(dt::DynkinType, v) -> BigInt

Synonym for degree. Computes the dimension of the irreducible representation via the Weyl dimension formula.

source

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
true
Note

borel_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_bottFunction
borel_weil_bott(λ::WeightLatticeElem{DT,R}) -> Union{Nothing, Tuple{Int, WeightLatticeElem{DT,R}}}

Apply the Borel–Weil–Bott theorem to the weight λ.

Package placement

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
true
source

Singular 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(λ)
true
Semisimple.is_singularFunction
is_singular(w::WeightLatticeElem{DT,R}) -> Bool

Check 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}))
false
source

Bruhat 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)
false
Semisimple.right_descent_setFunction
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}:
 2
source
Semisimple.left_descent_setFunction
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}:
 1
source
Semisimple.bruhat_leqFunction
bruhat_leq(x::WeylGroupElem, y::WeylGroupElem) -> Bool

Return 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]))
true
source
Semisimple.bruhat_descendantsFunction
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}}:
 s1
source

Parabolic 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)
true
Semisimple.right_coset_repsFunction
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]))
3
source
Semisimple.left_coset_repsFunction
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]))
3
source

Weyl 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