Root system data for affine Cartan types

class sage.combinat.root_system.type_affine.AmbientSpace(root_system, base_ring)

Bases: sage.combinat.free_module.CombinatorialFreeModule

Ambient space for affine types.

This is constructed from the data in the corresponding classical ambient space. Namely, this space is obtained by adding two elements \(\delta\) and \(\delta^\vee\) to the basis of the classical ambient space, and by endowing it with the canonical scalar product.

The coefficient of an element in \(\delta^\vee\), thus its scalar product with \(\delta^\vee\) gives its level, and dualy for the colevel. The canonical projection onto the classical ambient space (by killing \(\delta\) and \(\delta^\vee\)) maps the simple roots (except \(\alpha_0\)) onto the corresponding classical simple roots, and similarly for the coroots, fundamental weights, ... Altogether, this uniquely determines the embedding of the root, coroot, weight, and coweight lattices. See simple_root() and fundamental_weight() for the details.

Warning

In type \(BC\), the null root is in fact:

sage: R = RootSystem(["BC",3,2]).ambient_space()
sage: R.null_root()
2*e['delta']

Warning

In the literature one often considers a larger affine ambient space obtained from the classical ambient space by adding four dimensions, namely for the fundamental weight \(\Lambda_0\) the fundamental coweight \(\Lambda^\vee_0\), the null root \(\delta\), and the null coroot \(c\) (aka central element). In this larger ambient space, the scalar product is degenerate: \(\langle \delta,\delta\rangle=0\) and similarly for the null coroot.

In the current implementation, \(\Lambda_0\) and the null coroot are identified:

sage: L = RootSystem([“A”,3,1]).ambient_space() sage: Lambda = L.fundamental_weights() sage: Lambda[0] e[‘deltacheck’] sage: L.null_coroot() e[‘deltacheck’]

Therefore the scalar product of the null coroot with itself differs from the larger ambient space:

sage: L.null_coroot().scalar(L.null_coroot())
1

In general, scalar products between two elements that do not live on “opposite sides” won’t necessarily match.

EXAMPLES:

sage: R = RootSystem(["A",3,1])
sage: e = R.ambient_space(); e
Ambient space of the Root system of type ['A', 3, 1]
sage: TestSuite(e).run()

Systematic checks on all affine types:

sage: for ct in CartanType.samples(affine=True, crystallographic=True):
...       if ct.classical().root_system().ambient_space() is not None:
...           print ct
...           L = ct.root_system().ambient_space()
...           assert L
...           TestSuite(L).run()
['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]^*
class Element(M, x)

Bases: sage.combinat.free_module.CombinatorialFreeModuleElement

Create a combinatorial module element. This should never be called directly, but only through the parent combinatorial free module’s __call__() method.

TESTS:

sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
sage: B = F.basis()
sage: f = B['a'] + 3*B['c']; f
B['a'] + 3*B['c']
sage: f == loads(dumps(f))
True
associated_coroot()

Return the coroot associated to self.

INPUT:

  • self – a root

EXAMPLES:

sage: alpha = RootSystem(['C',2,1]).ambient_space().simple_roots()
sage: alpha
Finite family {0: -2*e[0] + e['delta'], 1: e[0] - e[1], 2: 2*e[1]}
sage: alpha[0].associated_coroot()
-e[0] + e['deltacheck']
sage: alpha[1].associated_coroot()
e[0] - e[1]
sage: alpha[2].associated_coroot()
e[1]
inner_product(other)

Implement the canonical inner product of self with other.

EXAMPLES:

sage: e = RootSystem(['B',3,1]).ambient_space()
sage: B = e.basis()
sage: matrix([[x.inner_product(y) for x in B] for y in B])
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
sage: x = e.an_element(); x
2*e[0] + 2*e[1] + 3*e[2]
sage: x.inner_product(x)
17

scalar() is an alias for this method:

sage: x.scalar(x)
17

Todo

Lift to CombinatorialFreeModule.Element as canonical_inner_product

scalar(other)

Implement the canonical inner product of self with other.

EXAMPLES:

sage: e = RootSystem(['B',3,1]).ambient_space()
sage: B = e.basis()
sage: matrix([[x.inner_product(y) for x in B] for y in B])
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
sage: x = e.an_element(); x
2*e[0] + 2*e[1] + 3*e[2]
sage: x.inner_product(x)
17

scalar() is an alias for this method:

sage: x.scalar(x)
17

Todo

Lift to CombinatorialFreeModule.Element as canonical_inner_product

AmbientSpace.coroot_lattice()

EXAMPLES:

sage: RootSystem(["A",3,1]).ambient_lattice().coroot_lattice()
Ambient lattice of the Root system of type ['A', 3, 1]

Todo

Factor out this code with the classical ambient space.

AmbientSpace.fundamental_weight(i)

Return the fundamental weight \(\Lambda_i\) in this ambient space.

It is constructed by taking the corresponding fundamental weight of the classical ambient space (or \(0\) for \(\Lambda_0\)) and raising it to the appropriate level by adding a suitable multiple of \(\delta^\vee\).

EXAMPLES:

sage: RootSystem(['A',3,1]).ambient_space().fundamental_weight(2)
e[0] + e[1] + e['deltacheck']
sage: RootSystem(['A',3,1]).ambient_space().fundamental_weights()
Finite family {0: e['deltacheck'], 1: e[0] + e['deltacheck'],
               2: e[0] + e[1] + e['deltacheck'], 3: e[0] + e[1] + e[2] + e['deltacheck']}
sage: RootSystem(['A',3]).ambient_space().fundamental_weights()
Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0)}
sage: RootSystem(['A',3,1]).weight_lattice().fundamental_weights().map(attrcall("level"))
Finite family {0: 1, 1: 1, 2: 1, 3: 1}

sage: RootSystem(['B',3,1]).ambient_space().fundamental_weights()
Finite family {0: e['deltacheck'], 1: e[0] + e['deltacheck'],
               2: e[0] + e[1] + 2*e['deltacheck'], 3: 1/2*e[0] + 1/2*e[1] + 1/2*e[2] + e['deltacheck']}
sage: RootSystem(['B',3]).ambient_space().fundamental_weights()
Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)}
sage: RootSystem(['B',3,1]).weight_lattice().fundamental_weights().map(attrcall("level"))
Finite family {0: 1, 1: 1, 2: 2, 3: 1}

In type \(BC\) dual, the coefficient of ‘delta^vee’ is the level divided by \(2\) to take into account that the null coroot is \(2\delta^\vee\):

    sage: R = CartanType(['BC',3,2]).dual().root_system()
    sage: R.ambient_space().fundamental_weights()
    Finite family {0: e['deltacheck'], 1: e[0] + e['deltacheck'],
                   2: e[0] + e[1] + e['deltacheck'],
                   3: 1/2*e[0] + 1/2*e[1] + 1/2*e[2] + 1/2*e['deltacheck']}
    sage: R.weight_lattice().fundamental_weights().map(attrcall("level"))
    Finite family {0: 2, 1: 2, 2: 2, 3: 1}
    sage: R.ambient_space().null_coroot()
    2*e['deltacheck']

By a slight naming abuse this function also accepts "delta" as
input so that it can be used to implement the embedding from
the extended weight lattice::

    sage: RootSystem(['A',3,1]).ambient_space().fundamental_weight("delta")
    e['delta']
AmbientSpace.is_extended()

Return whether this is a realization of the extended weight lattice: yes!

See also

EXAMPLES:

sage: RootSystem(['A',3,1]).ambient_space().is_extended()
True
AmbientSpace.simple_coroot(i)

Return the \(i\)-th simple coroot \(\alpha_i^\vee\) of this affine ambient space.

EXAMPLES:

sage: RootSystem(["A",3,1]).ambient_space().simple_coroot(1)
e[0] - e[1]

It is built as the coroot associated to the simple root \(\alpha_i\):

sage: RootSystem(["B",3,1]).ambient_space().simple_roots()
Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: e[2]}
sage: RootSystem(["B",3,1]).ambient_space().simple_coroots()
Finite family {0: -e[0] - e[1] + e['deltacheck'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]}

Todo

Factor out this code with the classical ambient space.

AmbientSpace.simple_root(i)

Return the \(i\)-th simple root of this affine ambient space.

EXAMPLES:

It is built straightforwardly from the corresponding simple root \(\alpha_i\) in the classical ambient space:

sage: RootSystem(["A",3,1]).ambient_space().simple_root(1)
e[0] - e[1]

For the special node (typically \(i=0\)), \(\alpha_0\) is built from the other simple roots using the column annihilator of the Cartan matrix and adding \(\delta\), where \(\delta\) is the null root:

sage: RootSystem(["A",3]).ambient_space().simple_roots()
Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1)}
sage: RootSystem(["A",3,1]).ambient_space().simple_roots()
Finite family {0: -e[0] + e[3] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: e[2] - e[3]}

Here is a twisted affine example:

sage: RootSystem(CartanType(["B",3,1]).dual()).ambient_space().simple_roots()
Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]}

In fact \(\delta\) is really \(1/a_0\) times the null root (see the discussion in WeightSpace) but this only makes a difference in type \(BC\):

sage: L = RootSystem(CartanType(["BC",3,2])).ambient_space()
sage: L.simple_roots()
Finite family {0: -e[0] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]}
sage: L.null_root()
2*e['delta']

Note

An alternative would have been to use the default implementation of the simple roots as linear combinations of the fundamental weights. However, as in type \(A_n\) it is preferable to take a slight variant to avoid rational coefficient (the usual \(GL_n\) vs \(SL_n\) issue).

See also

classmethod AmbientSpace.smallest_base_ring(cartan_type)

Return the smallest base ring the ambient space can be defined on.

This is the smallest base ring for the associated classical ambient space.

EXAMPLES:

sage: cartan_type = CartanType(["A",3,1])
sage: cartan_type.AmbientSpace.smallest_base_ring(cartan_type)
Integer Ring
sage: cartan_type = CartanType(["B",3,1])
sage: cartan_type.AmbientSpace.smallest_base_ring(cartan_type)
Rational Field

Previous topic

Root System Types

Next topic

Root system data for dual Cartan types

This Page