Root system data for affine Cartan types#
- class sage.combinat.root_system.type_affine.AmbientSpace(root_system, base_ring)[source]#
Bases:
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 dually 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()
andfundamental_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() # needs sage.graphs 2*e['delta']
>>> from sage.all import * >>> R = RootSystem(["BC",Integer(3),Integer(2)]).ambient_space() >>> R.null_root() # needs sage.graphs 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() # needs sage.graphs sage: Lambda[0] # needs sage.graphs e['deltacheck'] sage: L.null_coroot() # needs sage.graphs e['deltacheck']
>>> from sage.all import * >>> L = RootSystem(["A",Integer(3),Integer(1)]).ambient_space() >>> Lambda = L.fundamental_weights() # needs sage.graphs >>> Lambda[Integer(0)] # needs sage.graphs e['deltacheck'] >>> L.null_coroot() # needs sage.graphs 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()) # needs sage.graphs 1
>>> from sage.all import * >>> L.null_coroot().scalar(L.null_coroot()) # needs sage.graphs 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()
>>> from sage.all import * >>> R = RootSystem(["A",Integer(3),Integer(1)]) >>> e = R.ambient_space(); e Ambient space of the Root system of type ['A', 3, 1] >>> 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]^*
>>> from sage.all import * >>> 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[source]#
Bases:
IndexedFreeModuleElement
- associated_coroot()[source]#
Return the coroot associated to
self
.INPUT:
self
– a root
EXAMPLES:
sage: # needs sage.graphs 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]
>>> from sage.all import * >>> # needs sage.graphs >>> alpha = RootSystem(['C',Integer(2),Integer(1)]).ambient_space().simple_roots() >>> alpha Finite family {0: -2*e[0] + e['delta'], 1: e[0] - e[1], 2: 2*e[1]} >>> alpha[Integer(0)].associated_coroot() -e[0] + e['deltacheck'] >>> alpha[Integer(1)].associated_coroot() e[0] - e[1] >>> alpha[Integer(2)].associated_coroot() e[1]
- inner_product(other)[source]#
Implement the canonical inner product of
self
withother
.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
>>> from sage.all import * >>> e = RootSystem(['B',Integer(3),Integer(1)]).ambient_space() >>> B = e.basis() >>> 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] >>> x = e.an_element(); x 2*e[0] + 2*e[1] + 3*e[2] >>> x.inner_product(x) 17
scalar()
is an alias for this method:sage: x.scalar(x) 17
>>> from sage.all import * >>> x.scalar(x) 17
Todo
Lift to CombinatorialFreeModule.Element as canonical_inner_product
- scalar(other)[source]#
Implement the canonical inner product of
self
withother
.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
>>> from sage.all import * >>> e = RootSystem(['B',Integer(3),Integer(1)]).ambient_space() >>> B = e.basis() >>> 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] >>> x = e.an_element(); x 2*e[0] + 2*e[1] + 3*e[2] >>> x.inner_product(x) 17
scalar()
is an alias for this method:sage: x.scalar(x) 17
>>> from sage.all import * >>> x.scalar(x) 17
Todo
Lift to CombinatorialFreeModule.Element as canonical_inner_product
- coroot_lattice()[source]#
EXAMPLES:
sage: RootSystem(["A",3,1]).ambient_lattice().coroot_lattice() Ambient lattice of the Root system of type ['A', 3, 1]
>>> from sage.all import * >>> RootSystem(["A",Integer(3),Integer(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.
- fundamental_weight(i)[source]#
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) # needs sage.graphs e[0] + e[1] + e['deltacheck'] sage: RootSystem(['A',3,1]).ambient_space().fundamental_weights() # needs sage.graphs 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: A31wl = RootSystem(['A',3,1]).weight_lattice() sage: A31wl.fundamental_weights().map(attrcall("level")) # needs sage.graphs Finite family {0: 1, 1: 1, 2: 1, 3: 1} sage: RootSystem(['B',3,1]).ambient_space().fundamental_weights() # needs sage.graphs 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: B31wl = RootSystem(['B',3,1]).weight_lattice() sage: B31wl.fundamental_weights().map(attrcall("level")) # needs sage.graphs Finite family {0: 1, 1: 1, 2: 2, 3: 1}
>>> from sage.all import * >>> RootSystem(['A',Integer(3),Integer(1)]).ambient_space().fundamental_weight(Integer(2)) # needs sage.graphs e[0] + e[1] + e['deltacheck'] >>> RootSystem(['A',Integer(3),Integer(1)]).ambient_space().fundamental_weights() # needs sage.graphs 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']} >>> RootSystem(['A',Integer(3)]).ambient_space().fundamental_weights() Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0)} >>> A31wl = RootSystem(['A',Integer(3),Integer(1)]).weight_lattice() >>> A31wl.fundamental_weights().map(attrcall("level")) # needs sage.graphs Finite family {0: 1, 1: 1, 2: 1, 3: 1} >>> RootSystem(['B',Integer(3),Integer(1)]).ambient_space().fundamental_weights() # needs sage.graphs 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']} >>> RootSystem(['B',Integer(3)]).ambient_space().fundamental_weights() Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)} >>> B31wl = RootSystem(['B',Integer(3),Integer(1)]).weight_lattice() >>> B31wl.fundamental_weights().map(attrcall("level")) # needs sage.graphs 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() # needs sage.graphs 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")) # needs sage.graphs Finite family {0: 2, 1: 2, 2: 2, 3: 1} sage: R.ambient_space().null_coroot() # needs sage.graphs 2*e['deltacheck']
>>> from sage.all import * >>> R = CartanType(['BC',Integer(3),Integer(2)]).dual().root_system() >>> R.ambient_space().fundamental_weights() # needs sage.graphs 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']} >>> R.weight_lattice().fundamental_weights().map(attrcall("level")) # needs sage.graphs Finite family {0: 2, 1: 2, 2: 2, 3: 1} >>> R.ambient_space().null_coroot() # needs sage.graphs 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']
>>> from sage.all import * >>> RootSystem(['A',Integer(3),Integer(1)]).ambient_space().fundamental_weight("delta") e['delta']
- is_extended()[source]#
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
>>> from sage.all import * >>> RootSystem(['A',Integer(3),Integer(1)]).ambient_space().is_extended() True
- simple_coroot(i)[source]#
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]
>>> from sage.all import * >>> RootSystem(["A",Integer(3),Integer(1)]).ambient_space().simple_coroot(Integer(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() # needs sage.graphs 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() # needs sage.graphs Finite family {0: -e[0] - e[1] + e['deltacheck'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]}
>>> from sage.all import * >>> RootSystem(["B",Integer(3),Integer(1)]).ambient_space().simple_roots() # needs sage.graphs Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: e[2]} >>> RootSystem(["B",Integer(3),Integer(1)]).ambient_space().simple_coroots() # needs sage.graphs 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.
- simple_root(i)[source]#
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]
>>> from sage.all import * >>> RootSystem(["A",Integer(3),Integer(1)]).ambient_space().simple_root(Integer(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() # needs sage.graphs Finite family {0: -e[0] + e[3] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: e[2] - e[3]}
>>> from sage.all import * >>> RootSystem(["A",Integer(3)]).ambient_space().simple_roots() Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1)} >>> RootSystem(["A",Integer(3),Integer(1)]).ambient_space().simple_roots() # needs sage.graphs 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: B31v = RootSystem(CartanType(["B",3,1]).dual()) sage: B31v.ambient_space().simple_roots() # needs sage.graphs Finite family {0: -e[0] - e[1] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]}
>>> from sage.all import * >>> B31v = RootSystem(CartanType(["B",Integer(3),Integer(1)]).dual()) >>> B31v.ambient_space().simple_roots() # needs sage.graphs 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() # needs sage.graphs 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() # needs sage.graphs 2*e['delta']
>>> from sage.all import * >>> L = RootSystem(CartanType(["BC",Integer(3),Integer(2)])).ambient_space() >>> L.simple_roots() # needs sage.graphs Finite family {0: -e[0] + e['delta'], 1: e[0] - e[1], 2: e[1] - e[2], 3: 2*e[2]} >>> L.null_root() # needs sage.graphs 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
CartanType.col_annihilator()
null_root()
- classmethod smallest_base_ring(cartan_type)[source]#
Return the smallest base ring the ambient space can be defined on.
This is the smallest base ring for the associated classical ambient space.
See also
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
>>> from sage.all import * >>> cartan_type = CartanType(["A",Integer(3),Integer(1)]) >>> cartan_type.AmbientSpace.smallest_base_ring(cartan_type) Integer Ring >>> cartan_type = CartanType(["B",Integer(3),Integer(1)]) >>> cartan_type.AmbientSpace.smallest_base_ring(cartan_type) Rational Field