Cartan matrices

AUTHORS:

  • Travis Scrimshaw (2012-04-22): Nicolas M. Thiery moved matrix creation to CartanType to prepare cartan_matrix() for deprecation.
  • Christian Stump, Travis Scrimshaw (2013-04-13): Created CartanMatrix.
  • Ben Salisbury (2018-08-07): Added Borcherds-Cartan matrices.
class sage.combinat.root_system.cartan_matrix.CartanMatrix

Bases: sage.matrix.matrix_integer_sparse.Matrix_integer_sparse, sage.combinat.root_system.cartan_type.CartanType_abstract

A (generalized) Cartan matrix.

A matrix \(A = (a_{ij})_{i,j \in I}\) for some index set \(I\) is a generalized Cartan matrix if it satisfies the following properties:

  • \(a_{ii} = 2\) for all \(i\),
  • \(a_{ij} \leq 0\) for all \(i \neq j\),
  • \(a_{ij} = 0\) if and only if \(a_{ji} = 0\) for all \(i \neq j\).

Additionally some reference assume that a Cartan matrix is symmetrizable (see is_symmetrizable()). However following Kac, we do not make that assumption here.

An even, integral Borcherds–Cartan matrix is an integral matrix \(A = (a_{ij})_{i,j \in I}\) for some countable index set \(I\) which satisfies the following properties:

  • \(a_{ii} \in \{2\} \cup 2\ZZ_{<0}\) for all \(i\),
  • \(a_{ij} \leq 0\) for all \(i \neq j\),
  • \(a_{ij} = 0\) if and only if \(a_{ji} = 0\) for all \(i \neq j\).

INPUT:

Can be anything which is accepted by CartanType or a matrix.

If given a matrix, one can also use the keyword cartan_type when giving a matrix to explicitly state the type. Otherwise this will try to check the input matrix against possible standard types of Cartan matrices. To disable this check, use the keyword cartan_type_check = False.

If one wants to initialize a Borcherds-Cartan matrix using matrix data, use the keyword borcherds=True. To specify the diagonal entries of corresponding to a Cartan type (a Cartan matrix is treated as matrix data), use borcherds with a list of the diagonal entries.

EXAMPLES:

sage: CartanMatrix(['A', 4])
[ 2 -1  0  0]
[-1  2 -1  0]
[ 0 -1  2 -1]
[ 0  0 -1  2]
sage: CartanMatrix(['B', 6])
[ 2 -1  0  0  0  0]
[-1  2 -1  0  0  0]
[ 0 -1  2 -1  0  0]
[ 0  0 -1  2 -1  0]
[ 0  0  0 -1  2 -1]
[ 0  0  0  0 -2  2]
sage: CartanMatrix(['C', 4])
[ 2 -1  0  0]
[-1  2 -1  0]
[ 0 -1  2 -2]
[ 0  0 -1  2]
sage: CartanMatrix(['D', 6])
[ 2 -1  0  0  0  0]
[-1  2 -1  0  0  0]
[ 0 -1  2 -1  0  0]
[ 0  0 -1  2 -1 -1]
[ 0  0  0 -1  2  0]
[ 0  0  0 -1  0  2]
sage: CartanMatrix(['E',6])
[ 2  0 -1  0  0  0]
[ 0  2  0 -1  0  0]
[-1  0  2 -1  0  0]
[ 0 -1 -1  2 -1  0]
[ 0  0  0 -1  2 -1]
[ 0  0  0  0 -1  2]
sage: CartanMatrix(['E',7])
[ 2  0 -1  0  0  0  0]
[ 0  2  0 -1  0  0  0]
[-1  0  2 -1  0  0  0]
[ 0 -1 -1  2 -1  0  0]
[ 0  0  0 -1  2 -1  0]
[ 0  0  0  0 -1  2 -1]
[ 0  0  0  0  0 -1  2]
sage: CartanMatrix(['E', 8])
[ 2  0 -1  0  0  0  0  0]
[ 0  2  0 -1  0  0  0  0]
[-1  0  2 -1  0  0  0  0]
[ 0 -1 -1  2 -1  0  0  0]
[ 0  0  0 -1  2 -1  0  0]
[ 0  0  0  0 -1  2 -1  0]
[ 0  0  0  0  0 -1  2 -1]
[ 0  0  0  0  0  0 -1  2]
sage: CartanMatrix(['F', 4])
[ 2 -1  0  0]
[-1  2 -1  0]
[ 0 -2  2 -1]
[ 0  0 -1  2]

This is different from MuPAD-Combinat, due to different node convention?

sage: CartanMatrix(['G', 2])
[ 2 -3]
[-1  2]
sage: CartanMatrix(['A',1,1])
[ 2 -2]
[-2  2]
sage: CartanMatrix(['A', 3, 1])
[ 2 -1  0 -1]
[-1  2 -1  0]
[ 0 -1  2 -1]
[-1  0 -1  2]
sage: CartanMatrix(['B', 3, 1])
[ 2  0 -1  0]
[ 0  2 -1  0]
[-1 -1  2 -1]
[ 0  0 -2  2]
sage: CartanMatrix(['C', 3, 1])
[ 2 -1  0  0]
[-2  2 -1  0]
[ 0 -1  2 -2]
[ 0  0 -1  2]
sage: CartanMatrix(['D', 4, 1])
[ 2  0 -1  0  0]
[ 0  2 -1  0  0]
[-1 -1  2 -1 -1]
[ 0  0 -1  2  0]
[ 0  0 -1  0  2]
sage: CartanMatrix(['E', 6, 1])
[ 2  0 -1  0  0  0  0]
[ 0  2  0 -1  0  0  0]
[-1  0  2  0 -1  0  0]
[ 0 -1  0  2 -1  0  0]
[ 0  0 -1 -1  2 -1  0]
[ 0  0  0  0 -1  2 -1]
[ 0  0  0  0  0 -1  2]
sage: CartanMatrix(['E', 7, 1])
[ 2 -1  0  0  0  0  0  0]
[-1  2  0 -1  0  0  0  0]
[ 0  0  2  0 -1  0  0  0]
[ 0 -1  0  2 -1  0  0  0]
[ 0  0 -1 -1  2 -1  0  0]
[ 0  0  0  0 -1  2 -1  0]
[ 0  0  0  0  0 -1  2 -1]
[ 0  0  0  0  0  0 -1  2]
sage: CartanMatrix(['E', 8, 1])
[ 2  0  0  0  0  0  0  0 -1]
[ 0  2  0 -1  0  0  0  0  0]
[ 0  0  2  0 -1  0  0  0  0]
[ 0 -1  0  2 -1  0  0  0  0]
[ 0  0 -1 -1  2 -1  0  0  0]
[ 0  0  0  0 -1  2 -1  0  0]
[ 0  0  0  0  0 -1  2 -1  0]
[ 0  0  0  0  0  0 -1  2 -1]
[-1  0  0  0  0  0  0 -1  2]
sage: CartanMatrix(['F', 4, 1])
[ 2 -1  0  0  0]
[-1  2 -1  0  0]
[ 0 -1  2 -1  0]
[ 0  0 -2  2 -1]
[ 0  0  0 -1  2]
sage: CartanMatrix(['G', 2, 1])
[ 2  0 -1]
[ 0  2 -3]
[-1 -1  2]

Examples of Borcherds-Cartan matrices:

sage: CartanMatrix([[2,-1],[-1,-2]], borcherds=True)
[ 2 -1]
[-1 -2]
sage: CartanMatrix('B3', borcherds=[-4,-6,2])
[-4 -1  0]
[-1 -6 -1]
[ 0 -2  2]

Note

Since this is a matrix, row() and column() will return the standard row and column respectively. To get the row with the indices as in Dynkin diagrams/Cartan types, use row_with_indices() and column_with_indices() respectively.

cartan_matrix()

Return the Cartan matrix of self.

EXAMPLES:

sage: CartanMatrix(['C',3]).cartan_matrix()
[ 2 -1  0]
[-1  2 -2]
[ 0 -1  2]
cartan_type()

Return the Cartan type of self or self if unknown.

EXAMPLES:

sage: C = CartanMatrix(['A',4,1])
sage: C.cartan_type()
['A', 4, 1]

If the Cartan type is unknown:

sage: C = CartanMatrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]])
sage: C.cartan_type()
[ 2 -1 -2]
[-1  2 -1]
[-2 -1  2]
column_with_indices(j)

Return the \(j^{th}\) column \((a_{i,j})_i\) of self as a container (or iterator) of tuples \((i, a_{i,j})\)

EXAMPLES:

sage: M = CartanMatrix(['B',4])
sage: [ (i,a) for (i,a) in M.column_with_indices(3) ]
[(3, 2), (2, -1), (4, -2)]
dual()

Return the dual Cartan matrix of self, which is obtained by taking the transpose.

EXAMPLES:

sage: ct = CartanType(['C',3])
sage: M = CartanMatrix(ct); M
[ 2 -1  0]
[-1  2 -2]
[ 0 -1  2]
sage: M.dual()
[ 2 -1  0]
[-1  2 -1]
[ 0 -2  2]
sage: M.dual() == CartanMatrix(ct.dual())
True
sage: M.dual().cartan_type() == ct.dual()
True

An example with arbitrary Cartan matrices:

sage: cm = CartanMatrix([[2,-5], [-2, 2]]); cm
[ 2 -5]
[-2  2]
sage: cm.dual()
[ 2 -2]
[-5  2]
sage: cm.dual() == CartanMatrix(cm.transpose())
True
sage: cm.dual().dual() == cm
True
dynkin_diagram()

Return the Dynkin diagram corresponding to self.

EXAMPLES:

sage: C = CartanMatrix(['A',2])
sage: C.dynkin_diagram()
O---O
1   2
A2
sage: C = CartanMatrix(['F',4,1])
sage: C.dynkin_diagram()
O---O---O=>=O---O
0   1   2   3   4
F4~
sage: C = CartanMatrix([[2,-4],[-4,2]])
sage: C.dynkin_diagram()
Dynkin diagram of rank 2
indecomposable_blocks()

Return a tuple of all indecomposable blocks of self.

EXAMPLES:

sage: M = CartanMatrix(['A',2])
sage: M.indecomposable_blocks()
(
[ 2 -1]
[-1  2]
)
sage: M = CartanMatrix([['A',2,1],['A',3,1]])
sage: M.indecomposable_blocks()
(
[ 2 -1  0 -1]
[-1  2 -1  0]  [ 2 -1 -1]
[ 0 -1  2 -1]  [-1  2 -1]
[-1  0 -1  2], [-1 -1  2]
)
index_set()

Return the index set of self.

EXAMPLES:

sage: C = CartanMatrix(['A',1,1])
sage: C.index_set()
(0, 1)
sage: C = CartanMatrix(['E',6])
sage: C.index_set()
(1, 2, 3, 4, 5, 6)
is_affine()

Return True if self is an affine type or False otherwise.

A generalized Cartan matrix is affine if all of its indecomposable blocks are either finite (see is_finite()) or have zero determinant with all proper principal minors positive.

EXAMPLES:

sage: M = CartanMatrix(['C',4])
sage: M.is_affine()
False
sage: M = CartanMatrix(['D',4,1])
sage: M.is_affine()
True
sage: M = CartanMatrix([[2, -4], [-3, 2]])
sage: M.is_affine()
False
is_crystallographic()

Implements CartanType_abstract.is_crystallographic().

A Cartan matrix is crystallographic if it is symmetrizable.

EXAMPLES:

sage: CartanMatrix(['F',4]).is_crystallographic()
True
is_finite()

Return True if self is a finite type or False otherwise.

A generalized Cartan matrix is finite if the determinant of all its principal submatrices (see principal_submatrices()) is positive. Such matrices have a positive definite symmetrized matrix. Note that a finite matrix may consist of multiple blocks of Cartan matrices each having finite Cartan type.

EXAMPLES:

sage: M = CartanMatrix(['C',4])
sage: M.is_finite()
True
sage: M = CartanMatrix(['D',4,1])
sage: M.is_finite()
False
sage: M = CartanMatrix([[2, -4], [-3, 2]])
sage: M.is_finite()
False
is_hyperbolic(compact=False)

Return if True if self is a (compact) hyperbolic type or False otherwise.

An indecomposable generalized Cartan matrix is hyperbolic if it has negative determinant and if any proper connected subdiagram of its Dynkin diagram is of finite or affine type. It is compact hyperbolic if any proper connected subdiagram has finite type.

INPUT:

  • compact – if True, check if matrix is compact hyperbolic

EXAMPLES:

sage: M = CartanMatrix([[2,-2,0],[-2,2,-1],[0,-1,2]])
sage: M.is_hyperbolic()
True
sage: M.is_hyperbolic(compact=True)
False
sage: M = CartanMatrix([[2,-3],[-3,2]])
sage: M.is_hyperbolic()
True
sage: M = CartanMatrix(['C',4])
sage: M.is_hyperbolic()
False
is_indecomposable()

Return if self is an indecomposable matrix or False otherwise.

EXAMPLES:

sage: M = CartanMatrix(['A',5])
sage: M.is_indecomposable()
True
sage: M = CartanMatrix([[2,-1,0],[-1,2,0],[0,0,2]])
sage: M.is_indecomposable()
False
is_indefinite()

Return if self is an indefinite type or False otherwise.

EXAMPLES:

sage: M = CartanMatrix([[2,-3],[-3,2]])
sage: M.is_indefinite()
True
sage: M = CartanMatrix("A2")
sage: M.is_indefinite()
False
is_lorentzian()

Return True if self is a Lorentzian type or False otherwise.

A generalized Cartan matrix is Lorentzian if it has negative determinant and exactly one negative eigenvalue.

EXAMPLES:

sage: M = CartanMatrix([[2,-3],[-3,2]])
sage: M.is_lorentzian()
True
sage: M = CartanMatrix([[2,-1],[-1,2]])
sage: M.is_lorentzian()
False
is_simply_laced()

Implements CartanType_abstract.is_simply_laced().

A Cartan matrix is simply-laced if all non diagonal entries are \(0\) or \(-1\).

EXAMPLES:

sage: cm = CartanMatrix([[2, -1, -1, -1], [-1, 2, -1, -1], [-1, -1, 2, -1], [-1, -1, -1, 2]])
sage: cm.is_simply_laced()
True
matrix_space(nrows=None, ncols=None, sparse=None)

Return a matrix space over the integers.

INPUT:

  • nrows - number of rows
  • ncols - number of columns
  • sparse - (boolean) sparseness

EXAMPLES:

sage: cm = CartanMatrix(['A', 3])
sage: cm.matrix_space()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring
sage: cm.matrix_space(2, 2)
Full MatrixSpace of 2 by 2 sparse matrices over Integer Ring
sage: cm[:2,1:]   # indirect doctest
[-1  0]
[ 2 -1]
principal_submatrices(proper=False)

Return a list of all principal submatrices of self.

INPUT:

  • proper – if True, return only proper submatrices

EXAMPLES:

sage: M = CartanMatrix(['A',2])
sage: M.principal_submatrices()
[
              [ 2 -1]
[], [2], [2], [-1  2]
]
sage: M.principal_submatrices(proper=True)
[[], [2], [2]]
rank()

Return the rank of self.

EXAMPLES:

sage: CartanMatrix(['C',3]).rank()
3
sage: CartanMatrix(["A2","B2","F4"]).rank()
8
reflection_group(type='matrix')

Return the reflection group corresponding to self.

EXAMPLES:

sage: C = CartanMatrix(['A',3])
sage: C.reflection_group()
Weyl Group of type ['A', 3] (as a matrix group acting on the root space)
relabel(relabelling)

Return the relabelled Cartan matrix.

EXAMPLES:

sage: CM = CartanMatrix(['C',3])
sage: R = CM.relabel({1:0, 2:4, 3:1}); R
[ 2  0 -1]
[ 0  2 -1]
[-1 -2  2]
sage: R.index_set()
(0, 1, 4)
sage: CM
[ 2 -1  0]
[-1  2 -2]
[ 0 -1  2]
root_space()

Return the root space corresponding to self.

EXAMPLES:

sage: C = CartanMatrix(['A',3])
sage: C.root_space()
Root space over the Rational Field of the Root system of type ['A', 3]
root_system()

Return the root system corresponding to self.

EXAMPLES:

sage: C = CartanMatrix(['A',3])
sage: C.root_system()
Root system of type ['A', 3]
row_with_indices(i)

Return the \(i^{th}\) row \((a_{i,j})_j\) of self as a container (or iterator) of tuples \((j, a_{i,j})\)

EXAMPLES:

sage: M = CartanMatrix(['C',4])
sage: [ (i,a) for (i,a) in M.row_with_indices(3) ]
[(3, 2), (2, -1), (4, -2)]
subtype(index_set)

Return a subtype of self given by index_set.

A subtype can be considered the Dynkin diagram induced from the Dynkin diagram of self by index_set.

EXAMPLES:

sage: C = CartanMatrix(['F',4])
sage: S = C.subtype([1,2,3])
sage: S
[ 2 -1  0]
[-1  2 -1]
[ 0 -2  2]
sage: S.index_set()
(1, 2, 3)
symmetrized_matrix()

Return the symmetrized matrix of self if symmetrizable.

EXAMPLES:

sage: cm = CartanMatrix(['B',4,1])
sage: cm.symmetrized_matrix()
[ 4  0 -2  0  0]
[ 0  4 -2  0  0]
[-2 -2  4 -2  0]
[ 0  0 -2  4 -2]
[ 0  0  0 -2  2]
symmetrizer()

Return the symmetrizer of self.

EXAMPLES:

sage: cm = CartanMatrix([[2,-5],[-2,2]])
sage: cm.symmetrizer()
Finite family {0: 2, 1: 5}
sage.combinat.root_system.cartan_matrix.find_cartan_type_from_matrix(CM)

Find a Cartan type by direct comparison of Dynkin diagrams given from the generalized Cartan matrix CM and return None if not found.

INPUT:

  • CM – a generalized Cartan matrix

EXAMPLES:

sage: from sage.combinat.root_system.cartan_matrix import find_cartan_type_from_matrix
sage: CM = CartanMatrix([[2,-1,-1], [-1,2,-1], [-1,-1,2]])
sage: find_cartan_type_from_matrix(CM)
['A', 2, 1]
sage: CM = CartanMatrix([[2,-1,0], [-1,2,-2], [0,-1,2]])
sage: find_cartan_type_from_matrix(CM)
['C', 3] relabelled by {1: 0, 2: 1, 3: 2}
sage: CM = CartanMatrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]])
sage: find_cartan_type_from_matrix(CM)
sage.combinat.root_system.cartan_matrix.is_borcherds_cartan_matrix(M)

Return True if M is an even, integral Borcherds-Cartan matrix. For a definition of such a matrix, see CartanMatrix.

EXAMPLES:

sage: from sage.combinat.root_system.cartan_matrix import is_borcherds_cartan_matrix
sage: M = Matrix([[2,-1],[-1,2]])
sage: is_borcherds_cartan_matrix(M)
True
sage: N = Matrix([[2,-1],[-1,0]])
sage: is_borcherds_cartan_matrix(N)
False
sage: O = Matrix([[2,-1],[-1,-2]])
sage: is_borcherds_cartan_matrix(O)
True
sage: O = Matrix([[2,-1],[-1,-3]])
sage: is_borcherds_cartan_matrix(O)
False
sage.combinat.root_system.cartan_matrix.is_generalized_cartan_matrix(M)

Return True if M is a generalized Cartan matrix. For a definition of a generalized Cartan matrix, see CartanMatrix.

EXAMPLES:

sage: from sage.combinat.root_system.cartan_matrix import is_generalized_cartan_matrix
sage: M = matrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]])
sage: is_generalized_cartan_matrix(M)
True
sage: M = matrix([[2,-1,-2], [-1,2,-1], [0,-1,2]])
sage: is_generalized_cartan_matrix(M)
False
sage: M = matrix([[1,-1,-2], [-1,2,-1], [-2,-1,2]])
sage: is_generalized_cartan_matrix(M)
False

A non-symmetrizable example:

sage: M = matrix([[2,-1,-2], [-1,2,-1], [-1,-1,2]])
sage: is_generalized_cartan_matrix(M)
True