Dynkin types and Cartan matrices
Dynkin types
Over $\mathbb{C}$, every finite-dimensional semisimple Lie algebra is classified up to isomorphism by its Dynkin type, a combinatorial datum that encodes the root system. Semisimple.jl represents types at the Julia type level — TypeA{3}, TypeB{4}, etc. — so that rank and root counts are compile-time constants, enabling zero-cost dispatch and @generated specialisation.
Simple types
The classical families TypeA{N}, TypeB{N}, TypeC{N}, TypeD{N}, and the exceptional types TypeE{6}, TypeE{7}, TypeE{8}, TypeF4, TypeG2:
julia> using Semisimple
julia> rank(TypeA{3})
3
julia> rank(TypeG2)
2
julia> n_positive_roots(TypeA{3})
6
julia> n_positive_roots(TypeE{8})
120Semisimple.DynkinType — Type
DynkinTypeAbstract supertype for finite Dynkin types (simple and semisimple).
Examples
julia> using Semisimple
julia> TypeA{2} <: DynkinType
trueSemisimple.SimpleDynkinType — Type
SimpleDynkinType <: DynkinTypeAbstract supertype for simple (irreducible) finite Dynkin types.
Examples
julia> using Semisimple
julia> TypeG2 <: SimpleDynkinType
trueSemisimple.TypeA — Type
TypeA{N} <: SimpleDynkinTypeDynkin type $\mathrm{A}_N$: the root-system type of $\mathfrak{sl}_{N+1}(\mathbb{C})$ and groups isogenous to $\mathrm{SL}_{N+1}$. Valid for $N \ge 1$.
Examples
julia> using Semisimple
julia> rank(TypeA{3})
3Semisimple.TypeB — Type
TypeB{N} <: SimpleDynkinTypeDynkin type $\mathrm{B}_N$: the root-system type of $\mathfrak{so}_{2N+1}(\mathbb{C})$ and groups isogenous to $\mathrm{Spin}_{2N+1}$ or $\mathrm{SO}_{2N+1}$. Valid for $N \ge 2$.
Examples
julia> using Semisimple
julia> rank(TypeB{3})
3Semisimple.TypeC — Type
TypeC{N} <: SimpleDynkinTypeDynkin type $\mathrm{C}_N$: the root-system type of $\mathfrak{sp}_{2N}(\mathbb{C})$ and groups isogenous to $\mathrm{Sp}_{2N}$. Valid for $N \ge 2$.
Examples
julia> using Semisimple
julia> rank(TypeC{3})
3Semisimple.TypeD — Type
TypeD{N} <: SimpleDynkinTypeDynkin type $\mathrm{D}_N$: the root-system type of $\mathfrak{so}_{2N}(\mathbb{C})$ and groups isogenous to $\mathrm{Spin}_{2N}$ or $\mathrm{SO}_{2N}$. Valid for $N \ge 3$.
Examples
julia> using Semisimple
julia> rank(TypeD{4})
4Semisimple.TypeE — Type
TypeE{N} <: SimpleDynkinTypeExceptional Dynkin type $\mathrm{E}_N$ for $N \in \{6,7,8\}$.
Examples
julia> using Semisimple
julia> n_positive_roots(TypeE{6})
36Semisimple.TypeF4 — Type
TypeF4 <: SimpleDynkinTypeExceptional Dynkin type $\mathrm{F}_4$.
Examples
julia> using Semisimple
julia> rank(TypeF4)
4Semisimple.TypeG2 — Type
TypeG2 <: SimpleDynkinTypeExceptional Dynkin type $\mathrm{G}_2$.
Examples
julia> using Semisimple
julia> rank(TypeG2)
2Semisimple.rank — Function
rank(::Type{DT}) where DT<:DynkinType -> IntReturn the rank (dimension of the Cartan subalgebra) of the Dynkin type DT. This is a compile-time constant.
Examples
julia> using Semisimple
julia> rank(TypeA{3})
3
julia> rank(TypeE{8})
8Semisimple.n_positive_roots — Function
n_positive_roots(::Type{DT}) -> IntNumber of positive roots for a simple Dynkin type.
Examples
julia> using Semisimple
julia> n_positive_roots(TypeA{3})
6
julia> n_positive_roots(TypeE{8})
120n_positive_roots(RS::RootSystem) -> IntReturn the number of positive roots.
Examples
julia> using Semisimple
julia> n_positive_roots(RootSystem(TypeA{2}))
3Dynkin diagrams
The function dynkin_diagram produces a text rendering of the Dynkin diagram following Bourbaki labelling conventions. This includes the correct arrow directions for non-simply-laced types and the branching for types D and E.
The return value is a DynkinDiagram object that pretty-prints automatically in the REPL without requiring println:
julia> dynkin_diagram(TypeA{4})
○───○───○───○
1 2 3 4
julia> dynkin_diagram(TypeG2)
○≡<≡○
1 2For types with branching (D and E), the diagram shows the fork:
dynkin_diagram(TypeD{5}) ○ 5
/
○───○───○───○
1 2 3 4dynkin_diagram(TypeE{6}) ○ 2
|
○───○───○───○───○
1 3 4 5 6Semisimple.DynkinDiagram — Type
DynkinDiagramA pretty-printable wrapper around the text rendering of a Dynkin diagram.
Displaying a DynkinDiagram in the REPL renders the diagram automatically without requiring println. Call string to recover the raw string.
See also: dynkin_diagram.
Examples
julia> using Semisimple
julia> occursin(Char(10), string(dynkin_diagram(TypeA{2})))
trueSemisimple.dynkin_diagram — Function
dynkin_diagram(::Type{DT}) -> DynkinDiagram
dynkin_diagram(dt::DynkinType) -> DynkinDiagramReturn the Dynkin diagram for the given type as a DynkinDiagram, following Bourbaki conventions. The result pretty-prints automatically in the REPL; call string to recover the raw multi-line string.
Examples
julia> using Semisimple
julia> dynkin_diagram(TypeA{4})
○───○───○───○
1 2 3 4
julia> dynkin_diagram(TypeB{3})
○───○═>═○
1 2 3
julia> dynkin_diagram(TypeG2)
○≡<≡○
1 2Product types
Direct products of simple types are represented by ProductDynkinType. The Dynkin diagram shows each component separately:
julia> PT = ProductDynkinType{Tuple{TypeA{2}, TypeB{2}}};
julia> rank(PT)
4
julia> n_components(PT)
2
julia> component_ranks(PT)
(2, 2)
julia> component_offsets(PT)
(0, 2)PT = ProductDynkinType{Tuple{TypeA{2}, TypeB{2}}}
dynkin_diagram(PT)A2:
○───○
1 2
B2:
○═>═○
1 2Semisimple.ProductDynkinType — Type
ProductDynkinType{Ts} <: DynkinTypeProduct of simple Dynkin types, representing a semisimple Lie algebra. Ts is a Tuple type of SimpleDynkinType subtypes.
Examples
julia> using Semisimple
julia> ProductDynkinType{Tuple{TypeA{3}, TypeD{5}, TypeE{6}}}() # A3 × D5 × E6
A3 × D5 × E6Semisimple.n_components — Function
n_components(::Type{ProductDynkinType{Ts}}) -> IntNumber of simple factors in a product type.
Examples
julia> using Semisimple
julia> n_components(ProductDynkinType{Tuple{TypeA{2}, TypeB{2}}})
2Semisimple.component_type — Function
component_type(::Type{ProductDynkinType{Ts}}, i::Integer) -> TypeReturn the i-th simple Dynkin type in a product.
Examples
julia> using Semisimple
julia> PT = ProductDynkinType{Tuple{TypeA{2}, TypeB{2}}};
julia> component_type(PT, 1)
TypeA{2}
julia> component_type(PT, 2)
TypeB{2}Semisimple.component_ranks — Function
component_ranks(::Type{ProductDynkinType{Ts}}) -> TupleReturn a tuple of ranks of the components.
Examples
julia> using Semisimple
julia> component_ranks(ProductDynkinType{Tuple{TypeA{2}, TypeB{3}}})
(2, 3)Semisimple.component_offsets — Function
component_offsets(::Type{ProductDynkinType{Ts}}) -> TupleReturn a tuple of starting index offsets for each component in the product type. The i-th component occupies indices offset[i]+1 : offset[i]+rank(component_i).
Examples
julia> using Semisimple
julia> component_offsets(ProductDynkinType{Tuple{TypeA{2}, TypeB{3}}})
(0, 2)Validation
Invalid ranks are caught at construction time:
julia> TypeA{0}()
ERROR: ArgumentError: TypeA{N} requires N ≥ 1, got N=0
[...]
julia> TypeD{2}()
ERROR: ArgumentError: TypeD{N} requires N ≥ 3, got N=2
[...]Cartan matrices
The Cartan matrix $C_{ij} = \langle \alpha_i^\vee, \alpha_j \rangle$ is computed at compile time via @generated functions, returning a StaticArrays.SMatrix. The conventions follow Bourbaki. With this convention, column $i$ of $C$ gives the simple root $\alpha_i$ in the fundamental weight basis: $\alpha_i = \sum_j C_{ji}\omega_j$.
julia> cartan_matrix(TypeA{3})
3×3 StaticArraysCore.SMatrix{3, 3, Int64, 9} with indices SOneTo(3)×SOneTo(3):
2 -1 0
-1 2 -1
0 -1 2
julia> cartan_matrix(TypeG2)
2×2 StaticArraysCore.SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
2 -3
-1 2
julia> cartan_matrix(TypeB{2})
2×2 StaticArraysCore.SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
2 -1
-2 2Symmetriser
The vector $d$ such that $\operatorname{diag}(d) \cdot C$ is symmetric. For simply-laced types (A, D, E) all entries are 1:
julia> cartan_symmetrizer(TypeA{3})
3-element StaticArraysCore.SVector{3, Int64} with indices SOneTo(3):
1
1
1
julia> cartan_symmetrizer(TypeG2)
2-element StaticArraysCore.SVector{2, Int64} with indices SOneTo(2):
1
3
julia> cartan_symmetrizer(TypeB{2})
2-element StaticArraysCore.SVector{2, Int64} with indices SOneTo(2):
2
1Bilinear form and inverse
The symmetric bilinear form $B = \operatorname{diag}(d) \cdot C$ and the rational inverse $C^{-1}$:
julia> cartan_bilinear_form(TypeA{3})
3×3 StaticArraysCore.SMatrix{3, 3, Int64, 9} with indices SOneTo(3)×SOneTo(3):
2 -1 0
-1 2 -1
0 -1 2
julia> cartan_matrix_inverse(TypeA{3})
3×3 StaticArraysCore.SMatrix{3, 3, Rational{Int64}, 9} with indices SOneTo(3)×SOneTo(3):
3//4 1//2 1//4
1//2 1 1//2
1//4 1//2 3//4Semisimple.cartan_matrix — Function
cartan_matrix(::Type{ProductDynkinType{Ts}})Block-diagonal Cartan matrix for a product of simple types.
Examples
julia> using Semisimple, StaticArrays
julia> cartan_matrix(TypeA{2}) == SMatrix{2,2}(2, -1, -1, 2)
true
julia> cartan_matrix(TypeG2) == SMatrix{2,2}(2, -1, -3, 2)
trueSemisimple.cartan_symmetrizer — Function
cartan_symmetrizer(::Type{DT}) -> SVectorReturn the symmetrizer d such that diag(d) * C is symmetric, where C is the Cartan matrix of DT. Entries are positive integers with gcd 1.
Examples
julia> using Semisimple, StaticArrays
julia> cartan_symmetrizer(TypeB{3}) == SVector(2, 2, 1)
true
julia> cartan_symmetrizer(TypeG2) == SVector(1, 3)
trueSemisimple.cartan_bilinear_form — Function
cartan_bilinear_form(::Type{DT}) -> SMatrixReturn the symmetrized Cartan matrix diag(d) * C, which is a symmetric positive-definite matrix defining the inner product on the root space.
Examples
julia> using Semisimple
julia> cartan_bilinear_form(TypeB{2})
2×2 StaticArraysCore.SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
4 -2
-2 2Semisimple.cartan_matrix_inverse — Function
cartan_matrix_inverse(::Type{DT}) -> SMatrix{R,R,Rational{Int}}Return the inverse of the Cartan matrix over the rationals.
Examples
julia> using Semisimple
julia> cartan_matrix_inverse(TypeA{2})
2×2 StaticArraysCore.SMatrix{2, 2, Rational{Int64}, 4} with indices SOneTo(2)×SOneTo(2):
2//3 1//3
1//3 2//3Semisimple.cartan_determinant — Function
cartan_determinant(::Type{DT}) -> Int
cartan_determinant(dt::DT) -> IntCompute the determinant of the Cartan matrix of the Dynkin type DT.
For semisimple Lie algebras, this determinant equals the connection index, which measures the index of the root lattice in the weight lattice.
This is a compile-time constant based on hardcoded values for simple types.
Examples
julia> using Semisimple
julia> cartan_determinant(TypeA{3})
4
julia> cartan_determinant(TypeB{3})
2
julia> cartan_determinant(TypeG2)
1Dimension
The dimension of the semisimple Lie algebra equals $r + 2n$ where $r$ is the rank and $n$ is the number of positive roots:
julia> dimension(TypeA{3}) # dim sl_4(C) = 15
15
julia> dimension(TypeE{8}) # dim(E_8) = 248
248
julia> dimension(ProductDynkinType{Tuple{TypeA{1}, TypeA{1}}}()) # dim(sl_2(C) + sl_2(C)) = 6
6Semisimple.dimension — Function
dimension(::Type{DT}) -> Int
dimension(dt::DynkinType) -> IntReturn the dimension of the semisimple Lie algebra of type DT.
For a semisimple Lie algebra of rank $r$ with $n$ positive roots, the dimension is $r + 2n$ (Cartan subalgebra plus positive and negative root spaces).
Note: for the adjoint representation dimension (same number), use degree on adjoint_representation.
Examples
julia> using Semisimple
julia> dimension(TypeA{3}) # sl_4(C) has dimension 15
15
julia> dimension(TypeE{8}) # e_8(C) has dimension 248
248
julia> dimension(ProductDynkinType{Tuple{TypeA{1}, TypeA{1}}}()) # sl_2(C) ⊕ sl_2(C)
6Scaled bilinear form
The scaled bilinear form on the fundamental weight basis, used internally by Freudenthal's formula:
Semisimple.omega_bilinear_form_scaled — Function
omega_bilinear_form_scaled(::Type{DT}) -> Tuple{Int, SMatrix{R,R,Int}}Return $(S, B_{\omega,S})$ where $B_{\omega,S} = S (C^{-1})^{\mathsf T} B C^{-1}$ is the bilinear form in the fundamental weight basis, scaled by the smallest positive integer S that makes all entries integral. This is a compile-time constant.
Examples
julia> using Semisimple
julia> first(omega_bilinear_form_scaled(TypeA{2}))
3Connection index
The determinant of the Cartan matrix is the connection index, which gives the index of the root lattice $Q$ in the weight lattice $P$:
\[\det(C) = [P : Q]\]
For simply-laced types (A, D, E), the index varies by type. For multiply-laced types, the determinant encodes how the roots and weights are related:
julia> using Semisimple
julia> cartan_determinant(TypeA{3}) # A3: det = 4 = n+1
4
julia> cartan_determinant(TypeB{2}) # B2 multiply-laced
2
julia> cartan_determinant(TypeG2)
1