Cartan types

Loosely speaking, Dynkin diagrams (or equivalently Cartan matrices) are graphs which are used to classify root systems, Coxeter and Weyl groups, Lie algebras, Lie groups, crystals, etc. up to an isomorphism. Cartan types are a standard set of names for those Dynkin diagrams (see Wikipedia article Dynkin_diagram).

Let us consider, for example, the Cartan type \(A_4\):

sage: T = CartanType(['A', 4])
sage: T
['A', 4]

It is the name of the following Dynkin diagram:

sage: DynkinDiagram(T)
O---O---O---O
1   2   3   4
A4

Note

For convenience, the following shortcuts are available:

sage: DynkinDiagram(['A',4])
O---O---O---O
1   2   3   4
A4
sage: DynkinDiagram('A4')
O---O---O---O
1   2   3   4
A4
sage: T.dynkin_diagram()
O---O---O---O
1   2   3   4
A4

See DynkinDiagram for how to further manipulate Dynkin diagrams.

From this data (the Cartan datum), one can construct the associated root system:

sage: RootSystem(T)
Root system of type ['A', 4]

The associated Weyl group of \(A_n\) is the symmetric group \(S_{n+1}\):

sage: W = WeylGroup(T)
sage: W
Weyl Group of type ['A', 4] (as a matrix group acting on the ambient space)
sage: W.cardinality()
120

while the Lie algebra is \(sl_{n+1}\), and the Lie group \(SL_{n+1}\) (TODO: illustrate this once this is implemented).

One may also construct crystals associated to various Dynkin diagrams. For example:

sage: C = crystals.Letters(T)
sage: C
The crystal of letters for type ['A', 4]
sage: C.list()
[1, 2, 3, 4, 5]

sage: C = crystals.Tableaux(T, shape=[2])
sage: C
The crystal of tableaux of type ['A', 4] and shape(s) [[2]]
sage: C.cardinality()
15

Here is a sample of all the finite irreducible crystallographic Cartan types:

sage: CartanType.samples(finite = True, crystallographic = True)
[['A', 1], ['A', 5], ['B', 1], ['B', 5], ['C', 1], ['C', 5], ['D', 2], ['D', 3], ['D', 5],
 ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2]]

One can also get latex representations of the crystallographic Cartan types and their corresponding Dynkin diagrams:

sage: [latex(ct) for ct in CartanType.samples(crystallographic=True)]
[A_{1}, A_{5}, B_{1}, B_{5}, C_{1}, C_{5}, D_{2}, D_{3}, D_{5},
 E_6, E_7, E_8, F_4, G_2,
 A_{1}^{(1)}, A_{5}^{(1)}, B_{1}^{(1)}, B_{5}^{(1)}, C_{1}^{(1)}, C_{5}^{(1)}, D_{3}^{(1)}, D_{5}^{(1)},
 E_6^{(1)}, E_7^{(1)}, E_8^{(1)}, F_4^{(1)}, G_2^{(1)},
 BC_{1}^{(2)}, BC_{5}^{(2)},
 B_{5}^{(1)\vee}, C_{4}^{(1)\vee}, F_4^{(1)\vee}, G_2^{(1)\vee}, BC_{1}^{(2)\vee}, BC_{5}^{(2)\vee}]
sage: view([DynkinDiagram(ct) for ct in CartanType.samples(crystallographic=True)]) # not tested

Non-crystallographic Cartan types are also partially supported:

sage: CartanType.samples(finite = True, crystallographic = False)
[['I', 5], ['H', 3], ['H', 4]]

In Sage, a Cartan type is used as a database of type-specific information and algorithms (see e.g. sage.combinat.root_system.type_A). This database includes how to construct the Dynkin diagram, the ambient space for the root system (see Wikipedia article Root_system), and further mathematical properties:

sage: T.is_finite(), T.is_simply_laced(), T.is_affine(), T.is_crystallographic()
(True, True, False, True)

In particular, a Sage Cartan type is endowed with a fixed choice of labels for the nodes of the Dynkin diagram. This choice follows the conventions of Nicolas Bourbaki, Lie Groups and Lie Algebras: Chapter 4-6, Elements of Mathematics, Springer (2002). ISBN 978-3540426509. For example:

sage: T = CartanType(['D', 4])
sage: DynkinDiagram(T)
    O 4
    |
    |
O---O---O
1   2   3
D4

sage: E6 = CartanType(['E',6])
sage: DynkinDiagram(E6)
        O 2
        |
        |
O---O---O---O---O
1   3   4   5   6
E6

Note

The direction of the arrows is the opposite (i.e. the transpose) of Bourbaki’s convention, but agrees with Kac’s.

For example, in type \(C_2\), we have:

sage: C2 = DynkinDiagram(['C',2]); C2
O=<=O
1   2
C2
sage: C2.cartan_matrix()
[ 2 -2]
[-1  2]

However Bourbaki would have the Cartan matrix as:

\[\begin{split}\begin{bmatrix} 2 & -1 \\ -2 & 2 \end{bmatrix}.\end{split}\]

If desired, other node labelling conventions can be achieved. For example the Kac labelling for type \(E_6\) can be obtained via:

sage: E6.relabel({1:1,2:6,3:2,4:3,5:4,6:5}).dynkin_diagram()
        O 6
        |
        |
O---O---O---O---O
1   2   3   4   5
E6 relabelled by {1: 1, 2: 6, 3: 2, 4: 3, 5: 4, 6: 5}

Contributions implementing other conventions are very welcome.

Another option is to build from scratch a new Dynkin diagram. The architecture has been designed to make it fairly easy to add other labelling conventions. In particular, we strived at choosing type free algorithms whenever possible, so in principle most features should remain available even with custom Cartan types. This has not been used much yet, so some rough corners certainly remain.

Here, we construct the hyperbolic example of Exercise 4.9 p. 57 of Kac, Infinite Dimensional Lie Algebras. We start with an empty Dynkin diagram, and add a couple nodes:

sage: g = DynkinDiagram()
sage: g.add_vertices([1,2,3])

Note that the diagonal of the Cartan matrix is already initialized:

sage: g.cartan_matrix()
[2 0 0]
[0 2 0]
[0 0 2]

Then we add a couple edges:

sage: g.add_edge(1,2,2)
sage: g.add_edge(1,3)
sage: g.add_edge(2,3)

and we get the desired Cartan matrix:

sage: g.cartan_matrix()
[2 0 0]
[0 2 0]
[0 0 2]

Oops, the Cartan matrix did not change! This is because it is cached for efficiency (see cached_method). In general, a Dynkin diagram should not be modified after having been used.

Warning

this is not checked currently

Todo

add a method set_mutable() as, say, for matrices

Here, we can work around this by clearing the cache:

sage: delattr(g, 'cartan_matrix')

Now we get the desired Cartan matrix:

sage: g.cartan_matrix()
[ 2 -1 -1]
[-2  2 -1]
[-1 -1  2]

Note that backward edges have been automatically added:

sage: g.edges()
[(1, 2, 2), (1, 3, 1), (2, 1, 1), (2, 3, 1), (3, 1, 1), (3, 2, 1)]

Reducible Cartan types

Reducible Cartan types can be specified by passing a sequence or list of irreducible Cartan types:

sage: CartanType(['A',2],['B',2])
A2xB2
sage: CartanType([['A',2],['B',2]])
A2xB2
sage: CartanType(['A',2],['B',2]).is_reducible()
True

or using the following short hand notation:

sage: CartanType("A2xB2")
A2xB2
sage: CartanType("A2","B2") == CartanType("A2xB2")
True

Degenerate cases

When possible, type \(I_n\) is automatically converted to the isomorphic crystallographic Cartan types (any reason not to do so?):

sage: CartanType(["I",1])
A1xA1
sage: CartanType(["I",3])
['A', 2]
sage: CartanType(["I",4])
['C', 2]
sage: CartanType(["I",6])
['G', 2]

The Dynkin diagrams for types \(B_1\), \(C_1\), \(D_2\), and \(D_3\) are isomorphic to that for \(A_1\), \(A_1\), \(A_1 \times A_1\), and \(A_3\), respectively. However their natural ambient space realizations (stemming from the corresponding infinite families of Lie groups) are different. Therefore, the Cartan types are considered as distinct:

sage: CartanType(['B',1])
['B', 1]
sage: CartanType(['C',1])
['C', 1]
sage: CartanType(['D',2])
['D', 2]
sage: CartanType(['D',3])
['D', 3]

Affine Cartan types

For affine types, we use the usual conventions for affine Coxeter groups: each affine type is either untwisted (that is arise from the natural affinisation of a finite Cartan type):

sage: CartanType(["A", 4, 1]).dynkin_diagram()
0
O-----------+
|           |
|           |
O---O---O---O
1   2   3   4
A4~
sage: CartanType(["B", 4, 1]).dynkin_diagram()
    O 0
    |
    |
O---O---O=>=O
1   2   3   4
B4~

or dual thereof:

sage: CartanType(["B", 4, 1]).dual().dynkin_diagram()
    O 0
    |
    |
O---O---O=<=O
1   2   3   4
B4~*

or is of type \(\widetilde{BC}_n\) (which yields an irreducible, but nonreduced root system):

sage: CartanType(["BC", 4, 2]).dynkin_diagram()
O=<=O---O---O=<=O
0   1   2   3   4
BC4~

This includes the two degenerate cases:

sage: CartanType(["A", 1, 1]).dynkin_diagram()
O<=>O
0   1
A1~
sage: CartanType(["BC", 1, 2]).dynkin_diagram()
  4
O=<=O
0   1
BC1~

For the user convenience, Kac’s notations for twisted affine types are automatically translated into the previous ones:

sage: CartanType(["A", 9, 2])
['B', 5, 1]^*
sage: CartanType(["A", 9, 2]).dynkin_diagram()
    O 0
    |
    |
O---O---O---O=<=O
1   2   3   4   5
B5~*
sage: CartanType(["A", 10, 2]).dynkin_diagram()
O=<=O---O---O---O=<=O
0   1   2   3   4   5
BC5~
sage: CartanType(["D", 5, 2]).dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
C4~*
sage: CartanType(["D", 4, 3]).dynkin_diagram()
  3
O=>=O---O
2   1   0
G2~* relabelled by {0: 0, 1: 2, 2: 1}
sage: CartanType(["E", 6, 2]).dynkin_diagram()
O---O---O=<=O---O
0   1   2   3   4
F4~*

Additionally one can set the notation global option to use Kac’s notation:

sage: CartanType.global_options['notation'] = 'Kac'
sage: CartanType(["A", 9, 2])
['A', 9, 2]
sage: CartanType(["A", 9, 2]).dynkin_diagram()
    O 0
    |
    |
O---O---O---O=<=O
1   2   3   4   5
A9^2
sage: CartanType(["A", 10, 2]).dynkin_diagram()
O=<=O---O---O---O=<=O
0   1   2   3   4   5
A10^2
sage: CartanType(["D", 5, 2]).dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
D5^2
sage: CartanType(["D", 4, 3]).dynkin_diagram()
  3
O=>=O---O
2   1   0
D4^3
sage: CartanType(["E", 6, 2]).dynkin_diagram()
O---O---O=<=O---O
0   1   2   3   4
E6^2
sage: CartanType.global_options['notation'] = 'BC'
sage.combinat.root_system.cartan_type.CartanType(*args)

Cartan types

Loosely speaking, Dynkin diagrams (or equivalently Cartan matrices) are graphs which are used to classify root systems, Coxeter and Weyl groups, Lie algebras, Lie groups, crystals, etc. up to an isomorphism. Cartan types are a standard set of names for those Dynkin diagrams (see Wikipedia article Dynkin_diagram).

Let us consider, for example, the Cartan type \(A_4\):

sage: T = CartanType(['A', 4])
sage: T
['A', 4]

It is the name of the following Dynkin diagram:

sage: DynkinDiagram(T)
O---O---O---O
1   2   3   4
A4

Note

For convenience, the following shortcuts are available:

sage: DynkinDiagram(['A',4])
O---O---O---O
1   2   3   4
A4
sage: DynkinDiagram('A4')
O---O---O---O
1   2   3   4
A4
sage: T.dynkin_diagram()
O---O---O---O
1   2   3   4
A4

See DynkinDiagram for how to further manipulate Dynkin diagrams.

From this data (the Cartan datum), one can construct the associated root system:

sage: RootSystem(T)
Root system of type ['A', 4]

The associated Weyl group of \(A_n\) is the symmetric group \(S_{n+1}\):

sage: W = WeylGroup(T)
sage: W
Weyl Group of type ['A', 4] (as a matrix group acting on the ambient space)
sage: W.cardinality()
120

while the Lie algebra is \(sl_{n+1}\), and the Lie group \(SL_{n+1}\) (TODO: illustrate this once this is implemented).

One may also construct crystals associated to various Dynkin diagrams. For example:

sage: C = crystals.Letters(T)
sage: C
The crystal of letters for type ['A', 4]
sage: C.list()
[1, 2, 3, 4, 5]

sage: C = crystals.Tableaux(T, shape=[2])
sage: C
The crystal of tableaux of type ['A', 4] and shape(s) [[2]]
sage: C.cardinality()
15

Here is a sample of all the finite irreducible crystallographic Cartan types:

sage: CartanType.samples(finite = True, crystallographic = True)
[['A', 1], ['A', 5], ['B', 1], ['B', 5], ['C', 1], ['C', 5], ['D', 2], ['D', 3], ['D', 5],
 ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2]]

One can also get latex representations of the crystallographic Cartan types and their corresponding Dynkin diagrams:

sage: [latex(ct) for ct in CartanType.samples(crystallographic=True)]
[A_{1}, A_{5}, B_{1}, B_{5}, C_{1}, C_{5}, D_{2}, D_{3}, D_{5},
 E_6, E_7, E_8, F_4, G_2,
 A_{1}^{(1)}, A_{5}^{(1)}, B_{1}^{(1)}, B_{5}^{(1)}, C_{1}^{(1)}, C_{5}^{(1)}, D_{3}^{(1)}, D_{5}^{(1)},
 E_6^{(1)}, E_7^{(1)}, E_8^{(1)}, F_4^{(1)}, G_2^{(1)},
 BC_{1}^{(2)}, BC_{5}^{(2)},
 B_{5}^{(1)\vee}, C_{4}^{(1)\vee}, F_4^{(1)\vee}, G_2^{(1)\vee}, BC_{1}^{(2)\vee}, BC_{5}^{(2)\vee}]
sage: view([DynkinDiagram(ct) for ct in CartanType.samples(crystallographic=True)]) # not tested

Non-crystallographic Cartan types are also partially supported:

sage: CartanType.samples(finite = True, crystallographic = False)
[['I', 5], ['H', 3], ['H', 4]]

In Sage, a Cartan type is used as a database of type-specific information and algorithms (see e.g. sage.combinat.root_system.type_A). This database includes how to construct the Dynkin diagram, the ambient space for the root system (see Wikipedia article Root_system), and further mathematical properties:

sage: T.is_finite(), T.is_simply_laced(), T.is_affine(), T.is_crystallographic()
(True, True, False, True)

In particular, a Sage Cartan type is endowed with a fixed choice of labels for the nodes of the Dynkin diagram. This choice follows the conventions of Nicolas Bourbaki, Lie Groups and Lie Algebras: Chapter 4-6, Elements of Mathematics, Springer (2002). ISBN 978-3540426509. For example:

sage: T = CartanType(['D', 4])
sage: DynkinDiagram(T)
    O 4
    |
    |
O---O---O
1   2   3
D4

sage: E6 = CartanType(['E',6])
sage: DynkinDiagram(E6)
        O 2
        |
        |
O---O---O---O---O
1   3   4   5   6
E6

Note

The direction of the arrows is the opposite (i.e. the transpose) of Bourbaki’s convention, but agrees with Kac’s.

For example, in type \(C_2\), we have:

sage: C2 = DynkinDiagram(['C',2]); C2
O=<=O
1   2
C2
sage: C2.cartan_matrix()
[ 2 -2]
[-1  2]

However Bourbaki would have the Cartan matrix as:

\[\begin{split}\begin{bmatrix} 2 & -1 \\ -2 & 2 \end{bmatrix}.\end{split}\]

If desired, other node labelling conventions can be achieved. For example the Kac labelling for type \(E_6\) can be obtained via:

sage: E6.relabel({1:1,2:6,3:2,4:3,5:4,6:5}).dynkin_diagram()
        O 6
        |
        |
O---O---O---O---O
1   2   3   4   5
E6 relabelled by {1: 1, 2: 6, 3: 2, 4: 3, 5: 4, 6: 5}

Contributions implementing other conventions are very welcome.

Another option is to build from scratch a new Dynkin diagram. The architecture has been designed to make it fairly easy to add other labelling conventions. In particular, we strived at choosing type free algorithms whenever possible, so in principle most features should remain available even with custom Cartan types. This has not been used much yet, so some rough corners certainly remain.

Here, we construct the hyperbolic example of Exercise 4.9 p. 57 of Kac, Infinite Dimensional Lie Algebras. We start with an empty Dynkin diagram, and add a couple nodes:

sage: g = DynkinDiagram()
sage: g.add_vertices([1,2,3])

Note that the diagonal of the Cartan matrix is already initialized:

sage: g.cartan_matrix()
[2 0 0]
[0 2 0]
[0 0 2]

Then we add a couple edges:

sage: g.add_edge(1,2,2)
sage: g.add_edge(1,3)
sage: g.add_edge(2,3)

and we get the desired Cartan matrix:

sage: g.cartan_matrix()
[2 0 0]
[0 2 0]
[0 0 2]

Oops, the Cartan matrix did not change! This is because it is cached for efficiency (see cached_method). In general, a Dynkin diagram should not be modified after having been used.

Warning

this is not checked currently

Todo

add a method set_mutable() as, say, for matrices

Here, we can work around this by clearing the cache:

sage: delattr(g, 'cartan_matrix')

Now we get the desired Cartan matrix:

sage: g.cartan_matrix()
[ 2 -1 -1]
[-2  2 -1]
[-1 -1  2]

Note that backward edges have been automatically added:

sage: g.edges()
[(1, 2, 2), (1, 3, 1), (2, 1, 1), (2, 3, 1), (3, 1, 1), (3, 2, 1)]

Reducible Cartan types

Reducible Cartan types can be specified by passing a sequence or list of irreducible Cartan types:

sage: CartanType(['A',2],['B',2])
A2xB2
sage: CartanType([['A',2],['B',2]])
A2xB2
sage: CartanType(['A',2],['B',2]).is_reducible()
True

or using the following short hand notation:

sage: CartanType("A2xB2")
A2xB2
sage: CartanType("A2","B2") == CartanType("A2xB2")
True

Degenerate cases

When possible, type \(I_n\) is automatically converted to the isomorphic crystallographic Cartan types (any reason not to do so?):

sage: CartanType(["I",1])
A1xA1
sage: CartanType(["I",3])
['A', 2]
sage: CartanType(["I",4])
['C', 2]
sage: CartanType(["I",6])
['G', 2]

The Dynkin diagrams for types \(B_1\), \(C_1\), \(D_2\), and \(D_3\) are isomorphic to that for \(A_1\), \(A_1\), \(A_1 \times A_1\), and \(A_3\), respectively. However their natural ambient space realizations (stemming from the corresponding infinite families of Lie groups) are different. Therefore, the Cartan types are considered as distinct:

sage: CartanType(['B',1])
['B', 1]
sage: CartanType(['C',1])
['C', 1]
sage: CartanType(['D',2])
['D', 2]
sage: CartanType(['D',3])
['D', 3]

Affine Cartan types

For affine types, we use the usual conventions for affine Coxeter groups: each affine type is either untwisted (that is arise from the natural affinisation of a finite Cartan type):

sage: CartanType(["A", 4, 1]).dynkin_diagram()
0
O-----------+
|           |
|           |
O---O---O---O
1   2   3   4
A4~
sage: CartanType(["B", 4, 1]).dynkin_diagram()
    O 0
    |
    |
O---O---O=>=O
1   2   3   4
B4~

or dual thereof:

sage: CartanType(["B", 4, 1]).dual().dynkin_diagram()
    O 0
    |
    |
O---O---O=<=O
1   2   3   4
B4~*

or is of type \(\widetilde{BC}_n\) (which yields an irreducible, but nonreduced root system):

sage: CartanType(["BC", 4, 2]).dynkin_diagram()
O=<=O---O---O=<=O
0   1   2   3   4
BC4~

This includes the two degenerate cases:

sage: CartanType(["A", 1, 1]).dynkin_diagram()
O<=>O
0   1
A1~
sage: CartanType(["BC", 1, 2]).dynkin_diagram()
  4
O=<=O
0   1
BC1~

For the user convenience, Kac’s notations for twisted affine types are automatically translated into the previous ones:

sage: CartanType(["A", 9, 2])
['B', 5, 1]^*
sage: CartanType(["A", 9, 2]).dynkin_diagram()
    O 0
    |
    |
O---O---O---O=<=O
1   2   3   4   5
B5~*
sage: CartanType(["A", 10, 2]).dynkin_diagram()
O=<=O---O---O---O=<=O
0   1   2   3   4   5
BC5~
sage: CartanType(["D", 5, 2]).dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
C4~*
sage: CartanType(["D", 4, 3]).dynkin_diagram()
  3
O=>=O---O
2   1   0
G2~* relabelled by {0: 0, 1: 2, 2: 1}
sage: CartanType(["E", 6, 2]).dynkin_diagram()
O---O---O=<=O---O
0   1   2   3   4
F4~*

Additionally one can set the notation global option to use Kac’s notation:

sage: CartanType.global_options['notation'] = 'Kac'
sage: CartanType(["A", 9, 2])
['A', 9, 2]
sage: CartanType(["A", 9, 2]).dynkin_diagram()
    O 0
    |
    |
O---O---O---O=<=O
1   2   3   4   5
A9^2
sage: CartanType(["A", 10, 2]).dynkin_diagram()
O=<=O---O---O---O=<=O
0   1   2   3   4   5
A10^2
sage: CartanType(["D", 5, 2]).dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
D5^2
sage: CartanType(["D", 4, 3]).dynkin_diagram()
  3
O=>=O---O
2   1   0
D4^3
sage: CartanType(["E", 6, 2]).dynkin_diagram()
O---O---O=<=O---O
0   1   2   3   4
E6^2
sage: CartanType.global_options['notation'] = 'BC'
class sage.combinat.root_system.cartan_type.CartanTypeFactory

Bases: sage.structure.sage_object.SageObject

x.__init__(...) initializes x; see help(type(x)) for signature

classmethod color(i)

Default color scheme for the vertices of a Dynkin diagram (and associated objects)

EXAMPLES:

sage: CartanType.color(1)
'blue'
sage: CartanType.color(2)
'red'
sage: CartanType.color(3)
'green'

The default color is black:

sage: CartanType.color(0)
'black'

Negative indices get the same color as their positive counterparts:

sage: CartanType.color(-1)
'blue'
sage: CartanType.color(-2)
'red'
sage: CartanType.color(-3)
'green'
global_options(*get_value, **set_value)

Sets and displays the global options for Cartan types. If no parameters are set, then the function returns a copy of the options dictionary.

The options to partitions can be accessed as the method CartanType.global_options of CartanType.

OPTIONS:

  • dual_latex – (default: \vee) The latex used for dual CartanTypes when latexing
  • dual_str – (default: *) The string used for dual Cartan types when printing
  • latex_relabel – (default: True) Indicate in the latex output if a Cartan type has been relabelled
  • mark_special_node – (default: none) Make the special nodes
    • both – both in latex and printing
    • latex – only in latex
    • none – no markup
    • printing – only in printing
  • notation – (default: Stembridge) Specifies which notation Cartan types should use when printed
    • BC – alias for Stembridge
    • Kac – use Kac’s notation
    • Stembridge – use Stembridge’s notation
    • tilde – alias for Stembridge
    • twisted – alias for Kac
  • special_node_str – (default: X) The string used to indicate which node is special when printing

EXAMPLES:

sage: ct = CartanType(['D',5,2]); ct
['C', 4, 1]^*
sage: ct.dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
C4~*
sage: latex(ct)
C_{4}^{(1)\vee}
sage: CartanType.global_options(dual_str='#', dual_latex='\\ast',)
sage: ct
['C', 4, 1]^#
sage: ct.dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
C4~#
sage: latex(ct)
C_{4}^{(1)\ast}
sage: CartanType.global_options(notation='kac', mark_special_node='both')
sage: ct
['D', 5, 2]
sage: ct.dynkin_diagram()
X=<=O---O---O=>=O
0   1   2   3   4
D5^2
sage: latex(ct)
D_{5}^{(2)}

For type \(A_{2n}^{(2)\dagger}\), the dual string/latex options are automatically overriden:

sage: dct = CartanType(['A',8,2]).dual(); dct
['A', 8, 2]^+
sage: latex(dct)
A_{8}^{(2)\dagger}
sage: dct.dynkin_diagram()
X=>=O---O---O=>=O
0   1   2   3   4
A8^2+
sage: CartanType.global_options.reset()

See GlobalOptions for more features of these options.

samples(finite=None, affine=None, crystallographic=None)

Return a sample of the available Cartan types.

INPUT:

  • finite – a boolean or None (default: None)
  • affine – a boolean or None (default: None)
  • crystallographic – a boolean or None (default: None)

The sample contains all the exceptional finite and affine Cartan types, as well as typical representatives of the infinite families.

EXAMPLES:

sage: CartanType.samples()
[['A', 1], ['A', 5], ['B', 1], ['B', 5], ['C', 1], ['C', 5], ['D', 2], ['D', 3], ['D', 5],
 ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2], ['I', 5], ['H', 3], ['H', 4],
 ['A', 1, 1], ['A', 5, 1], ['B', 1, 1], ['B', 5, 1],
 ['C', 1, 1], ['C', 5, 1], ['D', 3, 1], ['D', 5, 1],
 ['E', 6, 1], ['E', 7, 1], ['E', 8, 1], ['F', 4, 1], ['G', 2, 1], ['BC', 1, 2], ['BC', 5, 2],
 ['B', 5, 1]^*, ['C', 4, 1]^*, ['F', 4, 1]^*, ['G', 2, 1]^*, ['BC', 1, 2]^*, ['BC', 5, 2]^*]

The finite, affine and crystallographic options allow respectively for restricting to (non) finite, (non) affine, and (non) crystallographic Cartan types:

sage: CartanType.samples(finite=True)
[['A', 1], ['A', 5], ['B', 1], ['B', 5], ['C', 1], ['C', 5], ['D', 2], ['D', 3], ['D', 5],
 ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2], ['I', 5], ['H', 3], ['H', 4]]

sage: CartanType.samples(affine=True)
[['A', 1, 1], ['A', 5, 1], ['B', 1, 1], ['B', 5, 1],
 ['C', 1, 1], ['C', 5, 1], ['D', 3, 1], ['D', 5, 1],
 ['E', 6, 1], ['E', 7, 1], ['E', 8, 1], ['F', 4, 1], ['G', 2, 1], ['BC', 1, 2], ['BC', 5, 2],
 ['B', 5, 1]^*, ['C', 4, 1]^*, ['F', 4, 1]^*, ['G', 2, 1]^*, ['BC', 1, 2]^*, ['BC', 5, 2]^*]

sage: CartanType.samples(crystallographic=True)
[['A', 1], ['A', 5], ['B', 1], ['B', 5], ['C', 1], ['C', 5], ['D', 2], ['D', 3], ['D', 5],
 ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2],
 ['A', 1, 1], ['A', 5, 1], ['B', 1, 1], ['B', 5, 1],
 ['C', 1, 1], ['C', 5, 1], ['D', 3, 1], ['D', 5, 1],
 ['E', 6, 1], ['E', 7, 1], ['E', 8, 1], ['F', 4, 1], ['G', 2, 1], ['BC', 1, 2], ['BC', 5, 2],
 ['B', 5, 1]^*, ['C', 4, 1]^*, ['F', 4, 1]^*, ['G', 2, 1]^*, ['BC', 1, 2]^*, ['BC', 5, 2]^*]

sage: CartanType.samples(crystallographic=False)
[['I', 5], ['H', 3], ['H', 4]]

Todo

add some reducible Cartan types (suggestions?)

TESTS:

sage: for ct in CartanType.samples(): TestSuite(ct).run()
sage: CartanType.samples(crystalographic=False)
doctest:...: DeprecationWarning: use the option 'crystallographic' instead of 'crystalographic'
See http://trac.sagemath.org/14673 for details.
[['I', 5], ['H', 3], ['H', 4]]
class sage.combinat.root_system.cartan_type.CartanType_abstract

Bases: object

Abstract class for Cartan types

Subclasses should implement:

as_folding(folding_of=None, sigma=None)

Return self realized as a folded Cartan type.

For finite and affine types, this is realized by the Dynkin diagram foldings:

\[\begin{split}\begin{array}{ccl} C_n^{(1)}, A_{2n}^{(2)}, A_{2n}^{(2)\dagger}, D_{n+1}^{(2)} & \hookrightarrow & A_{2n-1}^{(1)}, \\ A_{2n-1}^{(2)}, B_n^{(1)} & \hookrightarrow & D_{n+1}^{(1)}, \\ E_6^{(2)}, F_4^{(1)} & \hookrightarrow & E_6^{(1)}, \\ D_4^{(3)}, G_2^{(1)} & \hookrightarrow & D_4^{(1)}, \\ C_n & \hookrightarrow & A_{2n-1}, \\ B_n & \hookrightarrow & D_{n+1}, \\ F_4 & \hookrightarrow & E_6, \\ G_2 & \hookrightarrow & D_4. \end{array}\end{split}\]

For general types, this returns self as a folded type of self with \(\sigma\) as the identity map.

For more information on these foldings and folded Cartan types, see sage.combinat.root_system.type_folded.CartanTypeFolded.

If the optional inputs folding_of and sigma are specified, then this returns the folded Cartan type of self in folding_of given by the automorphism sigma.

EXAMPLES:

sage: CartanType(['B', 3, 1]).as_folding()
['B', 3, 1] as a folding of  ['D', 4, 1]
sage: CartanType(['F', 4]).as_folding()
['F', 4] as a folding of  ['E', 6]
sage: CartanType(['BC', 3, 2]).as_folding()
['BC', 3, 2] as a folding of  ['A', 5, 1]
sage: CartanType(['D', 4, 3]).as_folding()
['G', 2, 1]^* relabelled by {0: 0, 1: 2, 2: 1} as a folding of ['D', 4, 1]
coxeter_diagram()

Return the Coxeter diagram for self.

EXAMPLES:

sage: CartanType(['B',3]).coxeter_diagram()
Graph on 3 vertices
sage: CartanType(['A',3]).coxeter_diagram().edges()
[(1, 2, 3), (2, 3, 3)]
sage: CartanType(['B',3]).coxeter_diagram().edges()
[(1, 2, 3), (2, 3, 4)]
sage: CartanType(['G',2]).coxeter_diagram().edges()
[(1, 2, 6)]
sage: CartanType(['F',4]).coxeter_diagram().edges()
[(1, 2, 3), (2, 3, 4), (3, 4, 3)]
coxeter_matrix()

Return the Coxeter matrix for self.

EXAMPLES:

sage: CartanType(['A', 4]).coxeter_matrix()
[1 3 2 2]
[3 1 3 2]
[2 3 1 3]
[2 2 3 1]
dual()

Return the dual Cartan type, possibly just as a formal dual.

EXAMPLES:

sage: CartanType(['A',3]).dual()
['A', 3]
sage: CartanType(["B", 3]).dual()
['C', 3]
sage: CartanType(['C',2]).dual()
['B', 2]
sage: CartanType(['D',4]).dual()
['D', 4]
sage: CartanType(['E',8]).dual()
['E', 8]
sage: CartanType(['F',4]).dual()
['F', 4] relabelled by {1: 4, 2: 3, 3: 2, 4: 1}
global_options(*get_value, **set_value)

Sets and displays the global options for Cartan types. If no parameters are set, then the function returns a copy of the options dictionary.

The options to partitions can be accessed as the method CartanType.global_options of CartanType.

OPTIONS:

  • dual_latex – (default: \vee) The latex used for dual CartanTypes when latexing
  • dual_str – (default: *) The string used for dual Cartan types when printing
  • latex_relabel – (default: True) Indicate in the latex output if a Cartan type has been relabelled
  • mark_special_node – (default: none) Make the special nodes
    • both – both in latex and printing
    • latex – only in latex
    • none – no markup
    • printing – only in printing
  • notation – (default: Stembridge) Specifies which notation Cartan types should use when printed
    • BC – alias for Stembridge
    • Kac – use Kac’s notation
    • Stembridge – use Stembridge’s notation
    • tilde – alias for Stembridge
    • twisted – alias for Kac
  • special_node_str – (default: X) The string used to indicate which node is special when printing

EXAMPLES:

sage: ct = CartanType(['D',5,2]); ct
['C', 4, 1]^*
sage: ct.dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
C4~*
sage: latex(ct)
C_{4}^{(1)\vee}
sage: CartanType.global_options(dual_str='#', dual_latex='\\ast',)
sage: ct
['C', 4, 1]^#
sage: ct.dynkin_diagram()
O=<=O---O---O=>=O
0   1   2   3   4
C4~#
sage: latex(ct)
C_{4}^{(1)\ast}
sage: CartanType.global_options(notation='kac', mark_special_node='both')
sage: ct
['D', 5, 2]
sage: ct.dynkin_diagram()
X=<=O---O---O=>=O
0   1   2   3   4
D5^2
sage: latex(ct)
D_{5}^{(2)}

For type \(A_{2n}^{(2)\dagger}\), the dual string/latex options are automatically overriden:

sage: dct = CartanType(['A',8,2]).dual(); dct
['A', 8, 2]^+
sage: latex(dct)
A_{8}^{(2)\dagger}
sage: dct.dynkin_diagram()
X=>=O---O---O=>=O
0   1   2   3   4
A8^2+
sage: CartanType.global_options.reset()

See GlobalOptions for more features of these options.

index_set()

Return the index set for self.

This is the list of the nodes of the associated Coxeter or Dynkin diagram.

EXAMPLES:

sage: CartanType(['A', 3, 1]).index_set()
(0, 1, 2, 3)
sage: CartanType(['D', 4]).index_set()
(1, 2, 3, 4)
sage: CartanType(['A', 7, 2]).index_set()
(0, 1, 2, 3, 4)
sage: CartanType(['A', 7, 2]).index_set()
(0, 1, 2, 3, 4)
sage: CartanType(['A', 6, 2]).index_set()
(0, 1, 2, 3)
sage: CartanType(['D', 6, 2]).index_set()
(0, 1, 2, 3, 4, 5)
sage: CartanType(['E', 6, 1]).index_set()
(0, 1, 2, 3, 4, 5, 6)
sage: CartanType(['E', 6, 2]).index_set()
(0, 1, 2, 3, 4)
sage: CartanType(['A', 2, 2]).index_set()
(0, 1)
sage: CartanType(['G', 2, 1]).index_set()
(0, 1, 2)
sage: CartanType(['F', 4, 1]).index_set()
(0, 1, 2, 3, 4)
is_affine()

Return whether self is affine.

EXAMPLES:

sage: CartanType(['A', 3]).is_affine()
False
sage: CartanType(['A', 3, 1]).is_affine()
True
is_atomic()

This method is usually equivalent to is_reducible(), except for the Cartan type \(D_2\).

\(D_2\) is not a standard Cartan type. It is equivalent to type \(A_1 \times A_1\) which is reducible; however the isomorphism from its ambient space (for the orthogonal group of degree 4) to that of \(A_1 \times A_1\) is non trivial, and it is useful to have it.

From a programming point of view its implementation is more similar to the irreducible types, and so the method is_atomic() is supplied.

EXAMPLES:

sage: CartanType("D2").is_atomic()
True
sage: CartanType("D2").is_irreducible()
False

TESTS:

sage: all( T.is_irreducible() == T.is_atomic() for T in CartanType.samples() if T != CartanType("D2"))
True
is_compound()

A short hand for not is_atomic().

TESTS:

sage: all( T.is_compound() == (not T.is_atomic()) for T in CartanType.samples())
True
is_crystallographic()

Return whether this Cartan type is crystallographic.

This returns False by default. Derived class should override this appropriately.

EXAMPLES:

sage: [ [t, t.is_crystallographic() ] for t in CartanType.samples(finite=True) ]
[[['A', 1], True], [['A', 5], True],
 [['B', 1], True], [['B', 5], True],
 [['C', 1], True], [['C', 5], True],
 [['D', 2], True], [['D', 3], True], [['D', 5], True],
 [['E', 6], True], [['E', 7], True], [['E', 8], True],
 [['F', 4], True], [['G', 2], True],
 [['I', 5], False], [['H', 3], False], [['H', 4], False]]

TESTS:

sage: all(t.is_crystallographic() for t in CartanType.samples(affine=True))
True
sage: t = CartanType(['A',3]); t.is_crystalographic()
doctest:...: DeprecationWarning: is_crystalographic is deprecated. Please use is_crystallographic instead.
See http://trac.sagemath.org/14673 for details.
True
is_crystalographic(*args, **kwds)

Deprecated: Use is_crystallographic() instead. See trac ticket #14673 for details.

is_finite()

Return whether this Cartan type is finite.

EXAMPLES:

sage: from sage.combinat.root_system.cartan_type import CartanType_abstract
sage: C = CartanType_abstract()
sage: C.is_finite()
Traceback (most recent call last):
...
NotImplementedError: <abstract method is_finite at ...>
sage: CartanType(['A',4]).is_finite()
True
sage: CartanType(['A',4, 1]).is_finite()
False
is_implemented()

Check whether the Cartan datum for self is actually implemented.

EXAMPLES:

sage: CartanType(["A",4,1]).is_implemented()
True
sage: CartanType(['H',3]).is_implemented()
True
is_irreducible()

Report whether this Cartan type is irreducible (i.e. simple). This should be overridden in any subclass.

This returns False by default. Derived class should override this appropriately.

EXAMPLES:

sage: from sage.combinat.root_system.cartan_type import CartanType_abstract
sage: C = CartanType_abstract()
sage: C.is_irreducible()
False
is_reducible()

Report whether the root system is reducible (i.e. not simple), that is whether it can be factored as a product of root systems.

EXAMPLES:

sage: CartanType("A2xB3").is_reducible()
True
sage: CartanType(['A',2]).is_reducible()
False
is_simply_laced()

Return whether this Cartan type is simply laced.

This returns False by default. Derived class should override this appropriately.

EXAMPLES:

sage: [ [t, t.is_simply_laced() ] for t in CartanType.samples() ]
[[['A', 1], True], [['A', 5], True],
 [['B', 1], True], [['B', 5], False],
 [['C', 1], True], [['C', 5], False],
 [['D', 2], True], [['D', 3], True], [['D', 5], True],
 [['E', 6], True], [['E', 7], True], [['E', 8], True],
 [['F', 4], False], [['G', 2], False], [['I', 5], False], [['H', 3], False], [['H', 4], False],
 [['A', 1, 1], False], [['A', 5, 1], True],
 [['B', 1, 1], False], [['B', 5, 1], False],
 [['C', 1, 1], False], [['C', 5, 1], False],
 [['D', 3, 1], True], [['D', 5, 1], True],
 [['E', 6, 1], True], [['E', 7, 1], True], [['E', 8, 1], True],
 [['F', 4, 1], False], [['G', 2, 1], False],
 [['BC', 1, 2], False], [['BC', 5, 2], False],
 [['B', 5, 1]^*, False], [['C', 4, 1]^*, False], [['F', 4, 1]^*, False], [['G', 2, 1]^*, False],
 [['BC', 1, 2]^*, False], [['BC', 5, 2]^*, False]]
rank()

Return the rank of self.

This is the number of nodes of the associated Coxeter or Dynkin diagram.

EXAMPLES:

sage: CartanType(['A', 4]).rank()
4
sage: CartanType(['A', 7, 2]).rank()
5
sage: CartanType(['I', 8]).rank()
2
relabel(relabelling)

Return a relabelled copy of this Cartan type.

INPUT:

  • type – a Cartan type
  • relabelling – a function (or a list or dictionary)

OUTPUT:

an isomorphic Cartan type obtained by relabelling the nodes of the Dynkin diagram. Namely, the node with label i is relabelled f(i) (or, by f[i] if f is a list or dictionary).

EXAMPLES:

sage: CartanType(['F',4]).relabel({ 1:4, 2:3, 3:2, 4:1 }).dynkin_diagram()
O---O=>=O---O
4   3   2   1
F4 relabelled by {1: 4, 2: 3, 3: 2, 4: 1}
root_system()

Return the root system associated to self.

EXAMPLES:

sage: CartanType(['A',4]).root_system()
Root system of type ['A', 4]
type()

Return the type of self, or None if unknown.

This method should be overridden in any subclass.

EXAMPLES:

sage: from sage.combinat.root_system.cartan_type import CartanType_abstract
sage: C = CartanType_abstract()
sage: C.type() is None
True
class sage.combinat.root_system.cartan_type.CartanType_affine

Bases: sage.combinat.root_system.cartan_type.CartanType_simple, sage.combinat.root_system.cartan_type.CartanType_crystallographic

An abstract class for simple affine Cartan types

AmbientSpace

alias of AmbientSpace

a()

Return the unique minimal non trivial annihilating linear combination of \(\alpha^\vee_0, \alpha^\vee, \ldots, \alpha^\vee\) with nonnegative coefficients (or alternatively, the unique minimal non trivial annihilating linear combination of the columns of the Cartan matrix with non-negative coefficients).

Throw an error if the existence or uniqueness does not hold

FIXME: the current implementation assumes that the Cartan matrix is indexed by \([0,1,...]\), in the same order as the index set.

EXAMPLES:

sage: RootSystem(['C',2,1]).cartan_type().a()
Finite family {0: 1, 1: 2, 2: 1}
sage: RootSystem(['D',4,1]).cartan_type().a()
Finite family {0: 1, 1: 1, 2: 2, 3: 1, 4: 1}
sage: RootSystem(['F',4,1]).cartan_type().a()
Finite family {0: 1, 1: 2, 2: 3, 3: 4, 4: 2}
sage: RootSystem(['BC',4,2]).cartan_type().a()
Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1}

a is a shortcut for col_annihilator:

sage: RootSystem(['BC',4,2]).cartan_type().col_annihilator()
Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1}
acheck(m=None)

Return the unique minimal non trivial annihilating linear combination of \(\alpha_0, \alpha_1, \ldots, \alpha_n\) with nonnegative coefficients (or alternatively, the unique minimal non trivial annihilating linear combination of the rows of the Cartan matrix with non-negative coefficients).

Throw an error if the existence of uniqueness does not hold

The optional argument m is for internal use only.

EXAMPLES:

sage: RootSystem(['C',2,1]).cartan_type().acheck()
Finite family {0: 1, 1: 1, 2: 1}
sage: RootSystem(['D',4,1]).cartan_type().acheck()
Finite family {0: 1, 1: 1, 2: 2, 3: 1, 4: 1}
sage: RootSystem(['F',4,1]).cartan_type().acheck()
Finite family {0: 1, 1: 2, 2: 3, 3: 2, 4: 1}
sage: RootSystem(['BC',4,2]).cartan_type().acheck()
Finite family {0: 1, 1: 2, 2: 2, 3: 2, 4: 2}

acheck is a shortcut for row_annihilator:

sage: RootSystem(['BC',4,2]).cartan_type().row_annihilator()
Finite family {0: 1, 1: 2, 2: 2, 3: 2, 4: 2}

FIXME:

  • The current implementation assumes that the Cartan matrix is indexed by \([0,1,...]\), in the same order as the index set.
  • This really should be a method of CartanMatrix.
basic_untwisted()

Return the basic untwisted Cartan type associated with this affine Cartan type.

Given an affine type \(X_n^{(r)}\), the basic untwisted type is \(X_n\). In other words, it is the classical Cartan type that is twisted to obtain self.

EXAMPLES:

sage: CartanType(['A', 1, 1]).basic_untwisted()
['A', 1]
sage: CartanType(['A', 3, 1]).basic_untwisted()
['A', 3]
sage: CartanType(['B', 3, 1]).basic_untwisted()
['B', 3]
sage: CartanType(['E', 6, 1]).basic_untwisted()
['E', 6]
sage: CartanType(['G', 2, 1]).basic_untwisted()
['G', 2]

sage: CartanType(['A', 2, 2]).basic_untwisted()
['A', 2]
sage: CartanType(['A', 4, 2]).basic_untwisted()
['A', 4]
sage: CartanType(['A', 11, 2]).basic_untwisted()
['A', 11]
sage: CartanType(['D', 5, 2]).basic_untwisted()
['D', 5]
sage: CartanType(['E', 6, 2]).basic_untwisted()
['E', 6]
sage: CartanType(['D', 4, 3]).basic_untwisted()
['D', 4]
c()

Returns the family (c_i)_i of integer coefficients defined by \(c_i=max(1, a_i/a^vee_i)\) (see e.g. [FSS07] p. 3)

FIXME: the current implementation assumes that the Cartan matrix is indexed by \([0,1,...]\), in the same order as the index set.

EXAMPLES:

sage: RootSystem(['C',2,1]).cartan_type().c()
Finite family {0: 1, 1: 2, 2: 1}
sage: RootSystem(['D',4,1]).cartan_type().c()
Finite family {0: 1, 1: 1, 2: 1, 3: 1, 4: 1}
sage: RootSystem(['F',4,1]).cartan_type().c()
Finite family {0: 1, 1: 1, 2: 1, 3: 2, 4: 2}
sage: RootSystem(['BC',4,2]).cartan_type().c()
Finite family {0: 2, 1: 1, 2: 1, 3: 1, 4: 1}

TESTS:

sage: CartanType(["B", 3, 1]).c().map(parent)
Finite family {0: Integer Ring, 1: Integer Ring, 2: Integer Ring, 3: Integer Ring}

REFERENCES:

[FSS07]G. Fourier, A. Schilling, and M. Shimozono, Demazure structure inside Kirillov-Reshetikhin crystals, J. Algebra, Vol. 309, (2007), p. 386-404 http://arxiv.org/abs/math/0605451
classical()

Return the classical Cartan type associated with this affine Cartan type.

EXAMPLES:

sage: CartanType(['A', 1, 1]).classical()
['A', 1]
sage: CartanType(['A', 3, 1]).classical()
['A', 3]
sage: CartanType(['B', 3, 1]).classical()
['B', 3]

sage: CartanType(['A', 2, 2]).classical()
['C', 1]
sage: CartanType(['BC', 1, 2]).classical()
['C', 1]
sage: CartanType(['A', 4, 2]).classical()
['C', 2]
sage: CartanType(['BC', 2, 2]).classical()
['C', 2]
sage: CartanType(['A', 10, 2]).classical()
['C', 5]
sage: CartanType(['BC', 5, 2]).classical()
['C', 5]

sage: CartanType(['D', 5, 2]).classical()
['B', 4]
sage: CartanType(['E', 6, 1]).classical()
['E', 6]
sage: CartanType(['G', 2, 1]).classical()
['G', 2]
sage: CartanType(['E', 6, 2]).classical()
['F', 4] relabelled by {1: 4, 2: 3, 3: 2, 4: 1}
sage: CartanType(['D', 4, 3]).classical()
['G', 2]

We check that classical(), sage.combinat.root_system.cartan_type.CartanType_crystallographic.dynkin_diagram(), and special_node() are consistent:

sage: for ct in CartanType.samples(affine = True):
...       g1 = ct.classical().dynkin_diagram()
...       g2 = ct.dynkin_diagram()
...       g2.delete_vertex(ct.special_node())
...       assert sorted(g1.vertices()) == sorted(g2.vertices())
...       assert sorted(g1.edges()) == sorted(g2.edges())
col_annihilator()

Return the unique minimal non trivial annihilating linear combination of \(\alpha^\vee_0, \alpha^\vee, \ldots, \alpha^\vee\) with nonnegative coefficients (or alternatively, the unique minimal non trivial annihilating linear combination of the columns of the Cartan matrix with non-negative coefficients).

Throw an error if the existence or uniqueness does not hold

FIXME: the current implementation assumes that the Cartan matrix is indexed by \([0,1,...]\), in the same order as the index set.

EXAMPLES:

sage: RootSystem(['C',2,1]).cartan_type().a()
Finite family {0: 1, 1: 2, 2: 1}
sage: RootSystem(['D',4,1]).cartan_type().a()
Finite family {0: 1, 1: 1, 2: 2, 3: 1, 4: 1}
sage: RootSystem(['F',4,1]).cartan_type().a()
Finite family {0: 1, 1: 2, 2: 3, 3: 4, 4: 2}
sage: RootSystem(['BC',4,2]).cartan_type().a()
Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1}

a is a shortcut for col_annihilator:

sage: RootSystem(['BC',4,2]).cartan_type().col_annihilator()
Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1}
is_affine()

EXAMPLES:

sage: CartanType(['A', 3, 1]).is_affine()
True
is_finite()

EXAMPLES:

sage: CartanType(['A', 3, 1]).is_finite()
False
is_untwisted_affine()

Return whether self is untwisted affine

A Cartan type is untwisted affine if it is the canonical affine extension of some finite type. Every affine type is either untwisted affine, dual thereof, or of type BC.

EXAMPLES:

sage: CartanType(['A', 3, 1]).is_untwisted_affine()
True
sage: CartanType(['A', 3, 1]).dual().is_untwisted_affine() # this one is self dual!
True
sage: CartanType(['B', 3, 1]).dual().is_untwisted_affine()
False
sage: CartanType(['BC', 3, 2]).is_untwisted_affine()
False
other_affinization()

Return the other affinization of the same classical type.

EXAMPLES:

sage: CartanType(["A", 3, 1]).other_affinization()
['A', 3, 1]
sage: CartanType(["B", 3, 1]).other_affinization()
['C', 3, 1]^*
sage: CartanType(["C", 3, 1]).dual().other_affinization()
['B', 3, 1]

Is this what we want?:

sage: CartanType(["BC", 3, 2]).dual().other_affinization()
['B', 3, 1]
row_annihilator(m=None)

Return the unique minimal non trivial annihilating linear combination of \(\alpha_0, \alpha_1, \ldots, \alpha_n\) with nonnegative coefficients (or alternatively, the unique minimal non trivial annihilating linear combination of the rows of the Cartan matrix with non-negative coefficients).

Throw an error if the existence of uniqueness does not hold

The optional argument m is for internal use only.

EXAMPLES:

sage: RootSystem(['C',2,1]).cartan_type().acheck()
Finite family {0: 1, 1: 1, 2: 1}
sage: RootSystem(['D',4,1]).cartan_type().acheck()
Finite family {0: 1, 1: 1, 2: 2, 3: 1, 4: 1}
sage: RootSystem(['F',4,1]).cartan_type().acheck()
Finite family {0: 1, 1: 2, 2: 3, 3: 2, 4: 1}
sage: RootSystem(['BC',4,2]).cartan_type().acheck()
Finite family {0: 1, 1: 2, 2: 2, 3: 2, 4: 2}

acheck is a shortcut for row_annihilator:

sage: RootSystem(['BC',4,2]).cartan_type().row_annihilator()
Finite family {0: 1, 1: 2, 2: 2, 3: 2, 4: 2}

FIXME:

  • The current implementation assumes that the Cartan matrix is indexed by \([0,1,...]\), in the same order as the index set.
  • This really should be a method of CartanMatrix.
special_node()

Return a special node of the Dynkin diagram.

A special node is a node of the Dynkin diagram such that pruning it yields a Dynkin diagram for the associated classical type (see classical()).

This method returns the label of some special node. This is usually \(0\) in the standard conventions.

EXAMPLES:

sage: CartanType(['A', 3, 1]).special_node()
0

The choice is guaranteed to be consistent with the indexing of the nodes of the classical Dynkin diagram:

sage: CartanType(['A', 3, 1]).index_set()
(0, 1, 2, 3)
sage: CartanType(['A', 3, 1]).classical().index_set()
(1, 2, 3)
translation_factors()

Returns the translation factors for self. Those are the smallest factors \(t_i\) such that the translation by \(t_i \alpha_i\) maps the fundamental polygon to another polygon in the alcove picture.

OUTPUT: a dictionary from self.index_set() to \(\ZZ\) (or \(\QQ\) for affine type \(BC\))

Those coefficients are all \(1\) for dual untwisted, and in particular for simply laced. They coincide with the usual \(c_i\) coefficients (see c()) for untwisted and dual thereof. See the discussion below for affine type \(BC\).

Note: one usually realizes the alcove picture in the coweight lattice, with translations by coroots; in that case, one will use the translation factors for the dual Cartan type.

FIXME: the current implementation assumes that the Cartan matrix is indexed by \([0,1,...]\), in the same order as the index set.

EXAMPLES:

sage: CartanType(['C',2,1]).translation_factors()
Finite family {0: 1, 1: 2, 2: 1}
sage: CartanType(['C',2,1]).dual().translation_factors()
Finite family {0: 1, 1: 1, 2: 1}
sage: CartanType(['D',4,1]).translation_factors()
Finite family {0: 1, 1: 1, 2: 1, 3: 1, 4: 1}
sage: CartanType(['F',4,1]).translation_factors()
Finite family {0: 1, 1: 1, 2: 1, 3: 2, 4: 2}
sage: CartanType(['BC',4,2]).translation_factors()
Finite family {0: 1, 1: 1, 2: 1, 3: 1, 4: 1/2}

We proceed with systematic tests taken from MuPAD-Combinat’s testsuite:

sage: list(CartanType(["A", 1, 1]).translation_factors())
[1, 1]
sage: list(CartanType(["A", 5, 1]).translation_factors())
[1, 1, 1, 1, 1, 1]
sage: list(CartanType(["B", 5, 1]).translation_factors())
[1, 1, 1, 1, 1, 2]
sage: list(CartanType(["C", 5, 1]).translation_factors())
[1, 2, 2, 2, 2, 1]
sage: list(CartanType(["D", 5, 1]).translation_factors())
[1, 1, 1, 1, 1, 1]
sage: list(CartanType(["E", 6, 1]).translation_factors())
[1, 1, 1, 1, 1, 1, 1]
sage: list(CartanType(["E", 7, 1]).translation_factors())
[1, 1, 1, 1, 1, 1, 1, 1]
sage: list(CartanType(["E", 8, 1]).translation_factors())
[1, 1, 1, 1, 1, 1, 1, 1, 1]
sage: list(CartanType(["F", 4, 1]).translation_factors())
[1, 1, 1, 2, 2]
sage: list(CartanType(["G", 2, 1]).translation_factors())
[1, 3, 1]
sage: list(CartanType(["A", 2, 2]).translation_factors())
[1, 1/2]
sage: list(CartanType(["A", 2, 2]).dual().translation_factors())
[1/2, 1]
sage: list(CartanType(["A", 10, 2]).translation_factors())
[1, 1, 1, 1, 1, 1/2]
sage: list(CartanType(["A", 10, 2]).dual().translation_factors())
[1/2, 1, 1, 1, 1, 1]
sage: list(CartanType(["A", 9, 2]).translation_factors())
[1, 1, 1, 1, 1, 1]
sage: list(CartanType(["D", 5, 2]).translation_factors())
[1, 1, 1, 1, 1]
sage: list(CartanType(["D", 4, 3]).translation_factors())
[1, 1, 1]
sage: list(CartanType(["E", 6, 2]).translation_factors())
[1, 1, 1, 1, 1]

We conclude with a discussion of the appropriate value for affine type \(BC\). Let us consider the alcove picture realized in the weight lattice. It is obtained by taking the level-\(1\) affine hyperplane in the weight lattice, and projecting it along \(\Lambda_0\):

sage: R = RootSystem(["BC",2,2])
sage: alpha = R.weight_space().simple_roots()
sage: alphacheck = R.coroot_space().simple_roots()
sage: Lambda = R.weight_space().fundamental_weights()

Here are the levels of the fundamental weights:

sage: Lambda[0].level(), Lambda[1].level(), Lambda[2].level()
(1, 2, 2)

So the “center” of the fundamental polygon at level \(1\) is:

sage: O = Lambda[0]
sage: O.level()
1

We take the projection \(\omega_1\) at level \(0\) of \(\Lambda_1\) as unit vector on the \(x\)-axis, and the projection \(\omega_2\) at level 0 of \(\Lambda_2\) as unit vector of the \(y\)-axis:

sage: omega1 = Lambda[1]-2*Lambda[0]
sage: omega2 = Lambda[2]-2*Lambda[0]
sage: omega1.level(), omega2.level()
(0, 0)

The projections of the simple roots can be read off:

sage: alpha[0]
2*Lambda[0] - Lambda[1]
sage: alpha[1]
-2*Lambda[0] + 2*Lambda[1] - Lambda[2]
sage: alpha[2]
-2*Lambda[1] + 2*Lambda[2]

Namely \(\alpha_0 = -\omega_1\), \(\alpha_1 = 2\omega_1 - \omega_2\) and \(\alpha_2 = -2 \omega_1 + 2 \omega_2\).

The reflection hyperplane defined by \(\alpha_0^\vee\) goes through the points \(O+1/2 \omega_1\) and \(O+1/2 \omega_2\):

sage: (O+(1/2)*omega1).scalar(alphacheck[0])
0
sage: (O+(1/2)*omega2).scalar(alphacheck[0])
0

Hence, the fundamental alcove is the triangle \((O, O+1/2 \omega_1, O+1/2 \omega_2)\). By successive reflections, one can tile the full plane. This induces a tiling of the full plane by translates of the fundamental polygon.

Todo

Add the picture here, once root system plots in the weight lattice will be implemented. In the mean time, the reader may look up the dual picture on Figure 2 of [HST09] which was produced by MuPAD-Combinat.

From this picture, one can read that translations by \(\alpha_0\), \(\alpha_1\), and \(1/2\alpha_2\) map the fundamental polygon to translates of it in the alcove picture, and are smallest with this property. Hence, the translation factors for affine type \(BC\) are \(t_0=1, t_1=1, t_2=1/2\):

sage: CartanType(['BC',2,2]).translation_factors()
Finite family {0: 1, 1: 1, 2: 1/2}

TESTS:

sage: CartanType(["B", 3, 1]).translation_factors().map(parent)
Finite family {0: Integer Ring, 1: Integer Ring, 2: Integer Ring, 3: Integer Ring}
sage: CartanType(["BC", 3, 2]).translation_factors().map(parent)
Finite family {0: Integer Ring, 1: Integer Ring, 2: Integer Ring, 3: Rational Field}

REFERENCES:

[HST09]F. Hivert, A. Schilling, and N. M. Thiery, Hecke group algebras as quotients of affine Hecke algebras at level 0, JCT A, Vol. 116, (2009) p. 844-863 http://arxiv.org/abs/0804.3781
class sage.combinat.root_system.cartan_type.CartanType_crystallographic

Bases: sage.combinat.root_system.cartan_type.CartanType_abstract

An abstract class for crystallographic Cartan types.

ascii_art(label='lambda x: x')

Return an ascii art representation of the Dynkin diagram.

INPUT:

  • label – a relabeling function for the nodes (default: the identity)

EXAMPLES:

sage: cartan_type = CartanType(['B',5,1])
sage: print cartan_type.ascii_art()
    O 0
    |
    |
O---O---O---O=>=O
1   2   3   4   5

The label option is useful to visualize various statistics on the nodes of the Dynkin diagram:

sage: a = cartan_type.col_annihilator(); a
Finite family {0: 1, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2}
sage: print CartanType(['B',5,1]).ascii_art(label=a.__getitem__)
    O 1
    |
    |
O---O---O---O=>=O
1   2   2   2   2
cartan_matrix()

Return the Cartan matrix associated with self.

EXAMPLES:

sage: CartanType(['A',4]).cartan_matrix()
[ 2 -1  0  0]
[-1  2 -1  0]
[ 0 -1  2 -1]
[ 0  0 -1  2]
coxeter_diagram()

Return the Coxeter diagram for self.

This implementation constructs it from the Dynkin diagram.

EXAMPLES:

sage: CartanType(['A',3]).coxeter_diagram()
Graph on 3 vertices
sage: CartanType(['A',3]).coxeter_diagram().edges()
[(1, 2, 3), (2, 3, 3)]
sage: CartanType(['B',3]).coxeter_diagram().edges()
[(1, 2, 3), (2, 3, 4)]
sage: CartanType(['G',2]).coxeter_diagram().edges()
[(1, 2, 6)]
sage: CartanType(['F',4]).coxeter_diagram().edges()
[(1, 2, 3), (2, 3, 4), (3, 4, 3)]
sage: CartanType(['A',2,2]).coxeter_diagram().edges()
[(0, 1, +Infinity)]
dynkin_diagram()

Return the Dynkin diagram associated with self.

EXAMPLES:

sage: CartanType(['A',4]).dynkin_diagram()
O---O---O---O
1   2   3   4
A4

Note

Derived subclasses should typically implement this as a cached method.

index_set_bipartition()

Return a bipartition \(\{L,R\}\) of the vertices of the Dynkin diagram.

For \(i\) and \(j\) both in \(L\) (or both in \(R\)), the simple reflections \(s_i\) and \(s_j\) commute.

Of course, the Dynkin diagram should be bipartite. This is always the case for all finite types.

EXAMPLES:

sage: CartanType(['A',5]).index_set_bipartition()
(set([1, 3, 5]), set([2, 4]))

sage: CartanType(['A',2,1]).index_set_bipartition()
Traceback (most recent call last):
...
AssertionError: The Dynkin diagram should be bipartite
is_crystallographic()

Implements CartanType_abstract.is_crystallographic() by returning True.

EXAMPLES:

sage: CartanType(['A', 3, 1]).is_crystallographic()
True

TESTS:

sage: t = CartanType(['A',3]); t.is_crystalographic()
doctest:...: DeprecationWarning: is_crystalographic is deprecated. Please use is_crystallographic instead.
See http://trac.sagemath.org/14673 for details.
True
is_crystalographic(*args, **kwds)

Deprecated: Use is_crystallographic() instead. See trac ticket #14673 for details.

symmetrizer()

Return the symmetrizer of the Cartan matrix of self.

A Cartan matrix \(M\) is symmetrizable if there exists a non trivial diagonal matrix \(D\) such that \(DM\) is a symmetric matrix, that is \(DM = M^tD\). In that case, \(D\) is unique, up to a scalar factor for each connected component of the Dynkin diagram.

This method computes the unique minimal such \(D\) with positive integral coefficients. If \(D\) exists, it is returned as a family. Otherwise None is returned.

The coefficients are coerced to base_ring.

EXAMPLES:

sage: CartanType(["B",5]).symmetrizer()
Finite family {1: 2, 2: 2, 3: 2, 4: 2, 5: 1}

Here is a neat trick to visualize it better:

sage: T = CartanType(["B",5])
sage: print T.ascii_art(T.symmetrizer().__getitem__)
O---O---O---O=>=O
2   2   2   2   1

sage: T = CartanType(["BC",5, 2])
sage: print T.ascii_art(T.symmetrizer().__getitem__)
O=<=O---O---O---O=<=O
1   2   2   2   2   4

Here is the symmetrizer of some reducible Cartan types:

    sage: T = CartanType(["D", 2])
    sage: print T.ascii_art(T.symmetrizer().__getitem__)
    O   O
    1   1

    sage: T = CartanType(["B",5],["BC",5, 2])
    sage: print T.ascii_art(T.symmetrizer().__getitem__)
    O---O---O---O=>=O
    2   2   2   2   1
    O=<=O---O---O---O=<=O
    1   2   2   2   2   4

Property: up to an overall scalar factor, this gives the norm
of the simple roots in the ambient space::

    sage: T = CartanType(["C",5])
    sage: print T.ascii_art(T.symmetrizer().__getitem__)
    O---O---O---O=<=O
    1   1   1   1   2

    sage: alpha = RootSystem(T).ambient_space().simple_roots()
    sage: print T.ascii_art(lambda i: alpha[i].scalar(alpha[i]))
    O---O---O---O=<=O
    2   2   2   2   4
class sage.combinat.root_system.cartan_type.CartanType_finite

Bases: sage.combinat.root_system.cartan_type.CartanType_abstract

An abstract class for simple affine Cartan types.

is_affine()

EXAMPLES:

sage: CartanType(["A", 3]).is_affine()
False
is_finite()

EXAMPLES:

sage: CartanType(["A", 3]).is_finite()
True
class sage.combinat.root_system.cartan_type.CartanType_simple

Bases: sage.combinat.root_system.cartan_type.CartanType_abstract

An abstract class for simple Cartan types.

is_irreducible()

Return whether self is irreducible, which is True.

EXAMPLES:

sage: CartanType(['A', 3]).is_irreducible()
True
class sage.combinat.root_system.cartan_type.CartanType_simple_finite

Bases: object

x.__init__(...) initializes x; see help(type(x)) for signature

class sage.combinat.root_system.cartan_type.CartanType_simply_laced

Bases: sage.combinat.root_system.cartan_type.CartanType_crystallographic

An abstract class for simply laced Cartan types.

dual()

Simply laced Cartan types are self-dual, so return self.

EXAMPLES:

sage: CartanType(["A", 3]).dual()
['A', 3]
sage: CartanType(["A", 3, 1]).dual()
['A', 3, 1]
sage: CartanType(["D", 3]).dual()
['D', 3]
sage: CartanType(["D", 4, 1]).dual()
['D', 4, 1]
sage: CartanType(["E", 6]).dual()
['E', 6]
sage: CartanType(["E", 6, 1]).dual()
['E', 6, 1]
is_simply_laced()

Return whether self is simply laced, which is True.

EXAMPLES:

sage: CartanType(['A',3,1]).is_simply_laced()
True
sage: CartanType(['A',2]).is_simply_laced()
True
class sage.combinat.root_system.cartan_type.CartanType_standard_affine(letter, n, affine=1)

Bases: sage.structure.unique_representation.UniqueRepresentation, sage.structure.sage_object.SageObject, sage.combinat.root_system.cartan_type.CartanType_affine

A concrete class for affine simple Cartan types.

index_set()

Implements CartanType_abstract.index_set().

The index set for all standard affine Cartan types is of the form \(\{0, \ldots, n\}\).

EXAMPLES:

sage: CartanType(['A', 5, 1]).index_set()
(0, 1, 2, 3, 4, 5)
rank()

Return the rank of self which for type \(X_n^{(1)}\) is \(n + 1\).

EXAMPLES:

sage: CartanType(['A', 4, 1]).rank()
5
sage: CartanType(['B', 4, 1]).rank()
5
sage: CartanType(['C', 3, 1]).rank()
4
sage: CartanType(['D', 4, 1]).rank()
5
sage: CartanType(['E', 6, 1]).rank()
7
sage: CartanType(['E', 7, 1]).rank()
8
sage: CartanType(['F', 4, 1]).rank()
5
sage: CartanType(['G', 2, 1]).rank()
3
sage: CartanType(['A', 2, 2]).rank()
2
sage: CartanType(['A', 6, 2]).rank()
4
sage: CartanType(['A', 7, 2]).rank()
5
sage: CartanType(['D', 5, 2]).rank()
5
sage: CartanType(['E', 6, 2]).rank()
5
sage: CartanType(['D', 4, 3]).rank()
3
special_node()

Implement CartanType_abstract.special_node().

With the standard labelling conventions, \(0\) is always a special node.

EXAMPLES:

sage: CartanType(['A', 3, 1]).special_node()
0
type()

Return the type of self.

EXAMPLES:

sage: CartanType(['A', 4, 1]).type()
'A'
class sage.combinat.root_system.cartan_type.CartanType_standard_finite(letter, n)

Bases: sage.structure.unique_representation.UniqueRepresentation, sage.structure.sage_object.SageObject, sage.combinat.root_system.cartan_type.CartanType_finite

A concrete base class for the finite standard Cartan types.

This includes for example \(A_3\), \(D_4\), or \(E_8\).

affine()

Return the corresponding untwisted affine Cartan type.

EXAMPLES:

sage: CartanType(['A',3]).affine()
['A', 3, 1]
coxeter_number()

Return the Coxeter number associated with self.

The Coxeter number is the order of a Coxeter element of the corresponding Weyl group.

See Bourbaki, Lie Groups and Lie Algebras V.6.1 or Wikipedia article Coxeter_element for more information.

EXAMPLES:

sage: CartanType(['A',4]).coxeter_number()
5
sage: CartanType(['B',4]).coxeter_number()
8
sage: CartanType(['C',4]).coxeter_number()
8
dual_coxeter_number()

Return the Coxeter number associated with self.

EXAMPLES:

sage: CartanType(['A',4]).dual_coxeter_number()
5
sage: CartanType(['B',4]).dual_coxeter_number()
7
sage: CartanType(['C',4]).dual_coxeter_number()
5
index_set()

Implements CartanType_abstract.index_set().

The index set for all standard finite Cartan types is of the form \(\{1, \ldots, n\}\). (See type_I for a slight abuse of this).

EXAMPLES:

sage: CartanType(['A', 5]).index_set()
(1, 2, 3, 4, 5)
opposition_automorphism()

Returns the opposition automorphism

The opposition automorphism is the automorphism \(i \mapsto i^*\) of the vertices Dynkin diagram such that, for \(w_0\) the longest element of the Weyl group, and any simple root \(\alpha_i\), one has \(\alpha_{i^*} = -w_0(\alpha_i)\).

The automorphism is returned as a Family.

EXAMPLES:

sage: ct = CartanType(['A', 5])
sage: ct.opposition_automorphism()
Finite family {1: 5, 2: 4, 3: 3, 4: 2, 5: 1}

sage: ct = CartanType(['D', 4])
sage: ct.opposition_automorphism()
Finite family {1: 1, 2: 2, 3: 3, 4: 4}

sage: ct = CartanType(['D', 5])
sage: ct.opposition_automorphism()
Finite family {1: 1, 2: 2, 3: 3, 4: 5, 5: 4}

sage: ct = CartanType(['C', 4])
sage: ct.opposition_automorphism()
Finite family {1: 1, 2: 2, 3: 3, 4: 4}
rank()

Return the rank of self which for type \(X_n\) is \(n\).

EXAMPLES:

sage: CartanType(['A', 3]).rank()
3
sage: CartanType(['B', 3]).rank()
3
sage: CartanType(['C', 3]).rank()
3
sage: CartanType(['D', 4]).rank()
4
sage: CartanType(['E', 6]).rank()
6
type()

Returns the type of self.

EXAMPLES:

sage: CartanType(['A', 4]).type()
'A'
sage: CartanType(['A', 4, 1]).type()
'A'
class sage.combinat.root_system.cartan_type.CartanType_standard_untwisted_affine(letter, n, affine=1)

Bases: sage.combinat.root_system.cartan_type.CartanType_standard_affine

A concrete class for the standard untwisted affine Cartan types.

basic_untwisted()

Return the basic_untwisted Cartan type associated with this affine Cartan type.

Given an affine type \(X_n^{(r)}\), the basic_untwisted type is \(X_n\). In other words, it is the classical Cartan type that is twisted to obtain self.

EXAMPLES:

sage: CartanType(['A', 1, 1]).basic_untwisted()
['A', 1]
sage: CartanType(['A', 3, 1]).basic_untwisted()
['A', 3]
sage: CartanType(['B', 3, 1]).basic_untwisted()
['B', 3]
sage: CartanType(['E', 6, 1]).basic_untwisted()
['E', 6]
sage: CartanType(['G', 2, 1]).basic_untwisted()
['G', 2]
classical()

Return the classical Cartan type associated with self.

EXAMPLES:

sage: CartanType(['A', 3, 1]).classical()
['A', 3]
sage: CartanType(['B', 3, 1]).classical()
['B', 3]
sage: CartanType(['C', 3, 1]).classical()
['C', 3]
sage: CartanType(['D', 4, 1]).classical()
['D', 4]
sage: CartanType(['E', 6, 1]).classical()
['E', 6]
sage: CartanType(['F', 4, 1]).classical()
['F', 4]
sage: CartanType(['G', 2, 1]).classical()
['G', 2]
is_untwisted_affine()

Implement CartanType_affine.is_untwisted_affine() by returning True.

EXAMPLES:

sage: CartanType(['B', 3, 1]).is_untwisted_affine()
True

Previous topic

Root Systems

Next topic

Dynkin diagrams

This Page