Weight lattice
Weights are elements of the weight lattice, expressed in the fundamental weight basis $(\omega_1, \ldots, \omega_r)$ where $\langle \alpha_i^\vee, \omega_j \rangle = \delta_{ij}$.
Creating weights
Weights are constructed with fundamental_weight or directly from a coefficient vector using WeightLatticeElem:
julia> using Semisimple
julia> ω1 = fundamental_weight(TypeA{3}, 1)
ω1
julia> ω2 = fundamental_weight(TypeA{3}, 2)
ω2
julia> ω3 = fundamental_weight(TypeA{3}, 3)
ω3
julia> ω1 + ω2
ω1 + ω2
julia> 2 * ω1
2ω1
julia> WeightLatticeElem(TypeA{3}, [3, 1, 0])
3ω1 + ω2All fundamental weights
julia> fundamental_weights(TypeA{3})
3-element Vector{WeightLatticeElem{TypeA{3}, 3}}:
ω1
ω2
ω3Weyl vector
The Weyl vector $\rho = \omega_1 + \cdots + \omega_r$:
julia> weyl_vector(TypeA{3})
ω1 + ω2 + ω3Semisimple.WeightLatticeElem — Type
WeightLatticeElem{DT,R}An element of the weight lattice for Dynkin type DT of rank R, stored as an SVector{R,Int} of coordinates in the fundamental weight basis $(\omega_1, \ldots, \omega_r)$.
The pairing with the i-th simple coroot is simply w[i]: $\langle \alpha_i^\vee, \lambda \rangle = \lambda_i$
Constructors
WeightLatticeElem(::Type{DT}, v::AbstractVector{<:Integer})When v has fewer entries than rank(DT), the remaining coordinates are silently filled with zeros. When v has more entries than rank(DT), a warning is emitted and only the first rank(DT) entries are used.
Length handling
The AbstractVector constructor is meant as a convenience for interactive work. For library code, tests, and reproducible computations, prefer the exact-length SVector or NTuple constructors so dimension mismatches are caught immediately. Padding can change the intended weight by implicitly adding zero coordinates, while truncation discards trailing coordinates after emitting a warning.
Examples
julia> using Semisimple
julia> WeightLatticeElem(TypeA{3}, [1, 2]) # padded with one zero
ω1 + 2ω2
julia> WeightLatticeElem(TypeA{3}, [1, 2, 3]) # exact length
ω1 + 2ω2 + 3ω3
julia> using Test
julia> @test_logs (:warn, r"truncating to first 3 entries") WeightLatticeElem(TypeA{3}, [1, 2, 3, 4])
ω1 + 2ω2 + 3ω3Semisimple.fundamental_weight — Function
fundamental_weight(::Type{DT}, i) -> WeightLatticeElem{DT}Return the i-th fundamental weight $\omega_i$.
Examples
julia> using Semisimple
julia> fundamental_weight(TypeA{3}, 1)
ω1
julia> fundamental_weight(TypeB{2}, 2)
ω2Semisimple.fundamental_weights — Function
fundamental_weights(::Type{DT}) -> Vector{WeightLatticeElem{DT}}Return all fundamental weights.
Examples
julia> using Semisimple
julia> fundamental_weights(TypeA{2})
2-element Vector{WeightLatticeElem{TypeA{2}, 2}}:
ω1
ω2Semisimple.weyl_vector — Function
weyl_vector(::Type{DT}) -> WeightLatticeElem{DT}Return the Weyl vector $\rho = \omega_1 + \omega_2 + \cdots + \omega_r = \frac{1}{2}\sum_{\alpha > 0} \alpha$.
Examples
julia> using Semisimple
julia> weyl_vector(TypeA{3})
ω1 + ω2 + ω3Display
Weights are printed in the fundamental weight basis by default: ω1, 2ω1 + ω2, 0, etc.
Per-call compact format
Pass :compact => true via IOContext to switch a single show call to the concise coordinate form DT[c₁,c₂,…]:
julia> show(IOContext(stdout, :compact => true), ω1)
A3[1,0,0]
julia> show(IOContext(stdout, :compact => true), 2*ω1 - ω3)
A3[2,0,-1]The same compact form is used by RootSpaceElem.
Global compact toggle
Call compact_display! to make the compact form the session-wide default for all WeightLatticeElem and RootSpaceElem output:
julia> compact_display!(true)
true
julia> fundamental_weights(TypeA{3})
3-element Vector{WeightLatticeElem{TypeA{3}, 3}}:
A3[1,0,0]
A3[0,1,0]
A3[0,0,1]
julia> compact_display!(false) # restore default
falseSemisimple.compact_display! — Function
compact_display!(val::Bool = true)Set the global compact-display mode for WeightLatticeElem and RootSpaceElem.
When true, every call to show on these types prints the coordinate form DT[c₁,c₂,…] (e.g. A3[1,0,0] for ω₁ in type A₃) regardless of the IOContext. When false (the default), the standard symbolic form is used (ω1, α1 + α2, etc.).
The per-call IOContext(:compact => true) override always takes precedence.
Examples
julia> using Semisimple
julia> ω1 = fundamental_weight(TypeA{3}, 1);
julia> compact_display!(true)
true
julia> ω1
A3[1,0,0]
julia> fundamental_weights(TypeA{3})
3-element Vector{WeightLatticeElem{TypeA{3}, 3}}:
A3[1,0,0]
A3[0,1,0]
A3[0,0,1]
julia> compact_display!(false)
false
julia> ω1
ω1Dominance
A weight is dominant when all its fundamental weight coordinates are non-negative:
julia> is_dominant(ω1)
true
julia> is_dominant(ω1 - 2 * ω2)
falseConjugation to the dominant chamber
Every weight is Weyl-conjugate to a unique dominant weight:
julia> w = WeightLatticeElem(TypeA{3}, [-1, 2, 0]);
julia> is_dominant(w)
false
julia> conjugate_dominant_weight(w)
ω1 + ω2Semisimple.is_dominant — Function
is_dominant(w::WeightLatticeElem) -> BoolA weight is dominant iff all its coordinates (pairings with simple coroots) are >= 0.
Examples
julia> using Semisimple
julia> is_dominant(fundamental_weight(TypeA{2}, 1))
true
julia> is_dominant(WeightLatticeElem(TypeA{2}, [-1, 1]))
falseSemisimple.conjugate_dominant_weight — Function
conjugate_dominant_weight(w::WeightLatticeElem{DT,R}) -> WeightLatticeElem{DT,R}Return the unique dominant weight in the Weyl orbit of w.
Examples
julia> using Semisimple
julia> conjugate_dominant_weight(WeightLatticeElem(TypeA{2}, [-1, 1]))
ω1
julia> conjugate_dominant_weight(fundamental_weight(TypeA{3}, 1))
ω1Semisimple.conjugate_dominant_weight_with_elem — Function
conjugate_dominant_weight_with_elem(w::WeightLatticeElem{DT,R}) -> (WeightLatticeElem, Vector{Int})Return the dominant weight and the sequence of simple reflections applied.
Examples
julia> using Semisimple
julia> conjugate_dominant_weight_with_elem(WeightLatticeElem(TypeA{2}, [-1, 1]))
(ω1, [1])Semisimple.conjugate_dominant_weight_with_length — Function
conjugate_dominant_weight_with_length(w::WeightLatticeElem{DT,R}) -> (WeightLatticeElem, Int)Return the dominant weight in the Weyl orbit of w together with the number of simple reflections applied (i.e. the length of the Weyl group element mapping w into the dominant chamber).
This is faster than conjugate_dominant_weight_with_elem because it only tracks a counter instead of building the full word.
Examples
julia> using Semisimple
julia> conjugate_dominant_weight_with_length(WeightLatticeElem(TypeA{2}, [-1, 1]))
(ω1, 1)
julia> conjugate_dominant_weight_with_length(fundamental_weight(TypeA{3}, 1))
(ω1, 0)Reflections
Simple reflections act on weights by the formula $s_i(\lambda) = \lambda - \langle \alpha_i^\vee, \lambda \rangle \alpha_i$, which in the fundamental weight basis simplifies to $(s_i(\lambda))_j = \lambda_j - \lambda_i C_{ji}$, because $\alpha_i = \sum_j C_{ji}\omega_j$:
julia> reflect(ω1, 1) # reflection in the first simple root
-ω1 + ω2
julia> reflect(ω1, 2) # unchanged because the pairing is zero
ω1Semisimple.reflect — Function
reflect(w::WeightLatticeElem{DT,R}, s::Integer) -> WeightLatticeElem{DT,R}Reflect w by the s-th simple reflection: $s_s(\lambda) = \lambda - \langle \alpha_s^\vee, \lambda \rangle \alpha_s$
In the fundamental weight basis, $\langle \alpha_s^\vee, \lambda \rangle = \lambda_s$ and $\alpha_s = \sum_j C_{js} \omega_j$, so the new weight has coordinates: $(s_s(\lambda))_j = \lambda_j - \lambda_s C_{js}$
Examples
julia> using Semisimple
julia> reflect(WeightLatticeElem(TypeA{2}, [2, 1]), 1)
-2ω1 + 3ω2reflect(w::WeightLatticeElem{DT,R}, β::RootSpaceElem{DT,R}) -> WeightLatticeElem{DT,R}Reflect w by the root β: $s_\beta(\lambda) = \lambda - \langle \beta^\vee, \lambda \rangle \beta$ where $\langle \beta^\vee, \lambda \rangle = 2(\beta, \lambda) / (\beta, \beta)$.
The argument $\beta$ must be an actual root of the root system.
Examples
julia> using Semisimple
julia> reflect(fundamental_weight(TypeA{2}, 1), simple_root(RootSystem(TypeA{2}), 1))
-ω1 + ω2Inner products
Pairing of roots and weights, $\langle \alpha^\vee, \lambda \rangle$, and the weight-space inner product:
julia> RS = RootSystem(TypeA{2});
julia> α1 = simple_root(RS, 1);
julia> ω1 = fundamental_weight(TypeA{2}, 1);
julia> ω2 = fundamental_weight(TypeA{2}, 2);
julia> dot(α1, ω1) # simple-coroot pairing equals 1
1//1
julia> dot(α1, ω2) # simple-coroot pairing equals 0
0//1
julia> dot(ω1, ω1) # invariant bilinear form
2//3
julia> dot(ω1, ω2)
1//3LinearAlgebra.dot — Function
dot(a::RootSpaceElem{DT,R}, b::RootSpaceElem{DT,R}) -> Rational{Int}Inner product of two root space elements using the symmetrized Cartan form.
$(α, β) = αᵀ \operatorname{diag}(d) C β$
dot(r::RootSpaceElem{DT,R}, w::WeightLatticeElem{DT,R}) -> Rational{Int}Compute the inner product $(\alpha, \lambda)$ between a root $\alpha$ (in simple-root coordinates) and a weight $\lambda$ (in fundamental-weight coordinates).
Following OSCAR's convention: $(\alpha, \lambda) = \sum_i \alpha_i d_i \lambda_i$ where d is the Cartan symmetrizer.
This works because $(\alpha_i, \omega_j) = d_i \delta_{ij}$, which follows from $\langle \alpha_i^\vee, \omega_j \rangle = \delta_{ij}$ and $\alpha_i^\vee = \alpha_i / d_i$ in the bilinear-form sense.
Examples
julia> using Semisimple
julia> dot(simple_root(RootSystem(TypeA{2}), 1), fundamental_weight(TypeA{2}, 1))
1//1dot(w1::WeightLatticeElem{DT,R}, w2::WeightLatticeElem{DT,R}) -> Rational{Int}Compute the inner product $(\lambda, \mu)$ between two weights. Both are given in fundamental-weight coordinates; the implementation converts to root coordinates and applies the bilinear form there.
Examples
julia> using Semisimple
julia> dot(fundamental_weight(TypeA{2}, 1), fundamental_weight(TypeA{2}, 1))
2//3Conversions
Weights and roots live in different coordinate systems. Convert between them:
julia> α1_as_weight = WeightLatticeElem(simple_root(RS, 1))
2ω1 - ω2
julia> ρ_as_root = RootSpaceElem(weyl_vector(TypeA{2}))
α1 + α2Every weight lies in the rational span of the simple roots via $C^{-1}$. It lies in the root lattice only when those rational simple-root coordinates are integral; otherwise RootSpaceElem(w) throws an ArgumentError.