Tensor Products of Crystals¶
Main entry points:
AUTHORS:
- Anne Schilling, Nicolas Thiery (2007): Initial version
- Ben Salisbury, Travis Scrimshaw (2013): Refactored tensor products to handle non-regular crystals and created new subclass to take advantage of the regularity
-
class
sage.combinat.crystals.tensor_product.
CrystalOfTableaux
(cartan_type, shapes)¶ Bases:
sage.combinat.crystals.tensor_product.CrystalOfWords
A class for crystals of tableaux with integer valued shapes
INPUT:
cartan_type
– a Cartan typeshape
– a partition of length at mostcartan_type.rank()
shapes
– a list of such partitions
This constructs a classical crystal with the given Cartan type and highest weight(s) corresponding to the given shape(s).
If the type is \(D_r\), the shape is permitted to have a negative value in the \(r\)-th position. Thus if the shape equals \([s_1,\ldots,s_r]\), then \(s_r\) may be negative but in any case \(s_1 \geq \cdots \geq s_{r-1} \geq |s_r|\). This crystal is related to that of shape \([s_1,\ldots,|s_r|]\) by the outer automorphism of \(SO(2r)\).
If the type is \(D_r\) or \(B_r\), the shape is permitted to be of length \(r\) with all parts of half integer value. This corresponds to having one spin column at the beginning of the tableau. If several shapes are provided, they currently should all or none have this property.
Crystals of tableaux are constructed using an embedding into tensor products following Kashiwara and Nakashima [KN94]. Sage’s tensor product rule for crystals differs from that of Kashiwara and Nakashima by reversing the order of the tensor factors. Sage produces the same crystals of tableaux as Kashiwara and Nakashima. With Sage’s convention, the tensor product of crystals is the same as the monoid operation on tableaux and hence the plactic monoid.
See also
sage.combinat.crystals.crystals
for general help on crystals, and in particular plotting and \(\LaTeX\) output.EXAMPLES:
We create the crystal of tableaux for type \(A_2\), with highest weight given by the partition \([2,1,1]\):
sage: T = crystals.Tableaux(['A',3], shape = [2,1,1])
Here is the list of its elements:
sage: T.list() [[[1, 1], [2], [3]], [[1, 2], [2], [3]], [[1, 3], [2], [3]], [[1, 4], [2], [3]], [[1, 4], [2], [4]], [[1, 4], [3], [4]], [[2, 4], [3], [4]], [[1, 1], [2], [4]], [[1, 2], [2], [4]], [[1, 3], [2], [4]], [[1, 3], [3], [4]], [[2, 3], [3], [4]], [[1, 1], [3], [4]], [[1, 2], [3], [4]], [[2, 2], [3], [4]]]
Internally, a tableau of a given Cartan type is represented as a tensor product of letters of the same type. The order in which the tensor factors appear is by reading the columns of the tableaux left to right, top to bottom (in French notation). As an example:
sage: T = crystals.Tableaux(['A',2], shape = [3,2]) sage: T.module_generators[0] [[1, 1, 1], [2, 2]] sage: T.module_generators[0]._list [2, 1, 2, 1, 1]
To create a tableau, one can use:
sage: Tab = crystals.Tableaux(['A',3], shape = [2,2]) sage: Tab(rows=[[1,2],[3,4]]) [[1, 2], [3, 4]] sage: Tab(columns=[[3,1],[4,2]]) [[1, 2], [3, 4]]
Todo
FIXME:
- Do we want to specify the columns increasingly or
decreasingly? That is, should this be
Tab(columns = [[1,3],[2,4]])
? - Make this fully consistent with
Tableau()
!
We illustrate the use of a shape with a negative last entry in type \(D\):
sage: T = crystals.Tableaux(['D',4],shape=[1,1,1,-1]) sage: T.cardinality() 35 sage: TestSuite(T).run()
We illustrate the construction of crystals of spin tableaux when the partitions have half integer values in type \(B\) and \(D\):
sage: T = crystals.Tableaux(['B',3],shape=[3/2,1/2,1/2]); T The crystal of tableaux of type ['B', 3] and shape(s) [[3/2, 1/2, 1/2]] sage: T.cardinality() 48 sage: T.module_generators [[+++, [[1]]]] sage: TestSuite(T).run() sage: T = crystals.Tableaux(['D',3],shape=[3/2,1/2,-1/2]); T The crystal of tableaux of type ['D', 3] and shape(s) [[3/2, 1/2, -1/2]] sage: T.cardinality() 20 sage: T.module_generators [[++-, [[1]]]] sage: TestSuite(T).run()
TESTS:
Base cases:
sage: T = crystals.Tableaux(['A',2], shape = []) sage: T.list() [[]] sage: TestSuite(T).run() sage: T = crystals.Tableaux(['C',2], shape = [1]) sage: T.list() [[[1]], [[2]], [[-2]], [[-1]]] sage: TestSuite(T).run() sage: T = crystals.Tableaux(['A',2], shapes = [[],[1],[2]]) sage: T.list() [[], [[1]], [[2]], [[3]], [[1, 1]], [[1, 2]], [[2, 2]], [[1, 3]], [[2, 3]], [[3, 3]]] sage: T.module_generators ([], [[1]], [[1, 1]]) sage: T = crystals.Tableaux(['B',2], shape=[3]) sage: T(rows=[[1,1,0]]) [[1, 1, 0]]
Input tests:
sage: T = crystals.Tableaux(['A',3], shape = [2,2]) sage: C = T.letters sage: Tab(rows = [[1,2],[3,4]])._list == [C(3),C(1),C(4),C(2)] True sage: Tab(columns = [[3,1],[4,2]])._list == [C(3),C(1),C(4),C(2)] True
For compatibility with
TensorProductOfCrystals()
we need to accept as input the internal list or sequence of elements:sage: Tab(list = [3,1,4,2])._list == [C(3),C(1),C(4),C(2)] True sage: Tab(3,1,4,2)._list == [C(3),C(1),C(4),C(2)] True
The next example checks whether a given tableau is in fact a valid type \(C\) tableau or not:
sage: T = crystals.Tableaux(['C',3], shape = [2,2,2]) sage: Tab = T(rows=[[1,3],[2,-3],[3,-1]]) sage: Tab in T.list() True sage: Tab = T(rows=[[2,3],[3,-3],[-3,-2]]) sage: Tab in T.list() False
-
Element
¶ alias of
CrystalOfTableauxElement
-
cartan_type
()¶ Returns the Cartan type of the associated crystal
EXAMPLES:
sage: T = crystals.Tableaux(['A',3], shape = [2,2]) sage: T.cartan_type() ['A', 3]
-
module_generator
(shape)¶ This yields the module generator (or highest weight element) of a classical crystal of given shape. The module generator is the unique tableau with equal shape and content.
EXAMPLE:
sage: T = crystals.Tableaux(['D',3], shape = [1,1]) sage: T.module_generator([1,1]) [[1], [2]] sage: T = crystals.Tableaux(['D',4],shape=[2,2,2,-2]) sage: T.module_generator(tuple([2,2,2,-2])) [[1, 1], [2, 2], [3, 3], [-4, -4]] sage: T.cardinality() 294 sage: T = crystals.Tableaux(['D',4],shape=[2,2,2,2]) sage: T.module_generator(tuple([2,2,2,2])) [[1, 1], [2, 2], [3, 3], [4, 4]] sage: T.cardinality() 294
-
class
sage.combinat.crystals.tensor_product.
CrystalOfTableauxElement
(parent, *args, **options)¶ Bases:
sage.combinat.crystals.tensor_product.TensorProductOfRegularCrystalsElement
Element in a crystal of tableaux.
-
pp
()¶ EXAMPLES:
sage: T = crystals.Tableaux(['A',3], shape = [2,2]) sage: t = T(rows=[[1,2],[3,4]]) sage: t.pp() 1 2 3 4
-
promotion
()¶ Promotion for type A crystals of tableaux of rectangular shape
Returns the result of applying promotion on this tableau.
This method only makes sense in type A with rectangular shapes.
EXAMPLES:
sage: C = crystals.Tableaux(["A",3], shape = [3,3,3]) sage: t = C(Tableau([[1,1,1],[2,2,3],[3,4,4]])) sage: t [[1, 1, 1], [2, 2, 3], [3, 4, 4]] sage: t.promotion() [[1, 1, 2], [2, 2, 3], [3, 4, 4]] sage: t.promotion().parent() The crystal of tableaux of type ['A', 3] and shape(s) [[3, 3, 3]]
-
promotion_inverse
()¶ Inverse promotion for type A crystals of tableaux of rectangular shape
Returns the result of applying inverse promotion on this tableau.
This method only makes sense in type A with rectangular shapes.
EXAMPLES:
sage: C = crystals.Tableaux(["A",3], shape = [3,3,3]) sage: t = C(Tableau([[1,1,1],[2,2,3],[3,4,4]])) sage: t [[1, 1, 1], [2, 2, 3], [3, 4, 4]] sage: t.promotion_inverse() [[1, 1, 2], [2, 3, 3], [4, 4, 4]] sage: t.promotion_inverse().parent() The crystal of tableaux of type ['A', 3] and shape(s) [[3, 3, 3]]
-
to_tableau
()¶ Returns the Tableau object corresponding to self.
EXAMPLES:
sage: T = crystals.Tableaux(['A',3], shape = [2,2]) sage: t = T(rows=[[1,2],[3,4]]).to_tableau(); t [[1, 2], [3, 4]] sage: type(t) <class 'sage.combinat.tableau.Tableaux_all_with_category.element_class'> sage: type(t[0][0]) <type 'int'> sage: T = crystals.Tableaux(['D',3], shape = [1,1]) sage: t=T(rows=[[-3],[3]]).to_tableau(); t [[-3], [3]] sage: t=T(rows=[[3],[-3]]).to_tableau(); t [[3], [-3]] sage: T = crystals.Tableaux(['B',2], shape = [1,1]) sage: t = T(rows=[[0],[0]]).to_tableau(); t [[0], [0]]
-
-
class
sage.combinat.crystals.tensor_product.
CrystalOfWords
¶ Bases:
sage.structure.unique_representation.UniqueRepresentation
,sage.structure.parent.Parent
Auxiliary class to provide a call method to create tensor product elements. This class is shared with several tensor product classes and is also used in
CrystalOfTableaux
to allow tableaux of different tensor product structures in column-reading (and hence different shapes) to be considered elements in the same crystal.-
Element
¶ alias of
TensorProductOfCrystalsElement
-
one_dimensional_configuration_sum
(q=None, group_components=True)¶ Computes the one-dimensional configuration sum.
INPUT:
q
– (default:None
) a variable orNone
; ifNone
, a variable \(q\) is set in the codegroup_components
– (default:True
) boolean; ifTrue
, then the terms are grouped by classical component
The one-dimensional configuration sum is the sum of the weights of all elements in the crystal weighted by the energy function.
EXAMPLES:
sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: T = crystals.TensorProduct(K,K) sage: T.one_dimensional_configuration_sum() B[-2*Lambda[1] + 2*Lambda[2]] + (q+1)*B[-Lambda[1]] + (q+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + B[-2*Lambda[2]] + (q+1)*B[Lambda[2]] sage: R.<t> = ZZ[] sage: T.one_dimensional_configuration_sum(t, False) B[-2*Lambda[1] + 2*Lambda[2]] + (t+1)*B[-Lambda[1]] + (t+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + B[-2*Lambda[2]] + (t+1)*B[Lambda[2]] sage: R = RootSystem(['A',2,1]) sage: La = R.weight_space().basis() sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) sage: LS.one_dimensional_configuration_sum() == T.one_dimensional_configuration_sum() # long time True
TESTS:
sage: K1 = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: K2 = crystals.KirillovReshetikhin(['A',2,1],2,1) sage: T = crystals.TensorProduct(K1,K2) sage: T.one_dimensional_configuration_sum() == T.one_dimensional_configuration_sum(group_components=False) True sage: RC = RiggedConfigurations(['A',3,1],[[1,1],[1,2]]) sage: B = crystals.KirillovReshetikhin(['A',3,1],1,1) sage: B1 = crystals.KirillovReshetikhin(['A',3,1],1,2) sage: T = crystals.TensorProduct(B,B1) sage: RC.fermionic_formula() == T.one_dimensional_configuration_sum() True
-
-
class
sage.combinat.crystals.tensor_product.
FullTensorProductOfCrystals
(crystals, **options)¶ Bases:
sage.combinat.crystals.tensor_product.TensorProductOfCrystals
Full tensor product of crystals.
Todo
Merge this into
TensorProductOfCrystals
.-
cardinality
()¶ Return the cardinality of
self
.EXAMPLES:
sage: C = crystals.Letters(['A',2]) sage: T = crystals.TensorProduct(C,C) sage: T.cardinality() 9
-
weight_lattice_realization
()¶ Return the weight lattice realization used to express weights.
The weight lattice realization is the common parent which all weight lattice realizations of the crystals of
self
coerce into.EXAMPLES:
sage: B = crystals.elementary.B(['A',4], 2) sage: B.weight_lattice_realization() Root lattice of the Root system of type ['A', 4] sage: T = crystals.infinity.Tableaux(['A',4]) sage: T.weight_lattice_realization() Ambient space of the Root system of type ['A', 4] sage: TP = crystals.TensorProduct(B, T) sage: TP.weight_lattice_realization() Ambient space of the Root system of type ['A', 4]
-
-
class
sage.combinat.crystals.tensor_product.
FullTensorProductOfRegularCrystals
(crystals, **options)¶ Bases:
sage.combinat.crystals.tensor_product.FullTensorProductOfCrystals
Full tensor product of regular crystals.
-
Element
¶
-
-
class
sage.combinat.crystals.tensor_product.
ImmutableListWithParent
(parent, *args, **kwds)¶ Bases:
sage.combinat.combinat.CombinatorialElement
A class for lists having a parent
Specification: any subclass
C
should implement__init__
which accepts the following formC(parent, list = list)
EXAMPLES:
We create an immutable list whose parent is the class list:
sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) sage: l._list [1, 2, 3] sage: l.parent() A parent for tests sage: l.sibling([2,1]) == ImmutableListWithParent(TestParent(), [2,1]) True sage: l.reversed() [3, 2, 1] sage: l.set_index(1,4) [1, 4, 3]
TESTS:
sage: TestSuite(l).run(skip = "_test_category")
-
reversed
()¶ Returns the sibling of
self
which is obtained by reversing the elements of`` self``.EXAMPLES:
sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) sage: l.reversed() [3, 2, 1]
-
set_index
(k, value)¶ Returns the sibling of
self
obtained by setting the \(k^{th}\) entry of self to value.EXAMPLES:
sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) sage: l.set_index(0,2) [2, 2, 3] sage: l.set_index(1,4) [1, 4, 3] sage: _.parent() A parent for tests
-
sibling
(l)¶ Returns an
ImmutableListWithParent
object whose list isl
and whose parent is the same as the parent ofself
.Note that the implementation of this function makes an assumption about the constructor for subclasses.
EXAMPLES:
sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) sage: m = l.sibling([2,3,4]); m [2, 3, 4] sage: m.parent() A parent for tests
-
-
class
sage.combinat.crystals.tensor_product.
LocalEnergyFunction
(B, Bp, normalization=0)¶ Bases:
sage.categories.map.Map
The local energy function.
Let \(B\) and \(B'\) be Kirillov-Reshetikhin crystals with maximal vectors \(u_B\) and \(u_{B'}\) respectively. The local energy function \(H : B \otimes B' \to \ZZ\) is the function which satisfies
\[\begin{split}H(e_0(b \otimes b')) = H(b \otimes b') + \begin{cases} 1 & \text{if } i = 0 \text{ and LL}, \\ -1 & \text{if } i = 0 \text{ and RR}, \\ 0 & \text{otherwise,} \end{cases}\end{split}\]where LL (resp. RR) denote \(e_0\) acts on the left (resp. right) on both \(b \otimes b'\) and \(R(b \otimes b')\), and normalized by \(H(u_B \otimes u_{B'}) = 0\).
INPUT:
B
– a Kirillov-Reshetikhin crystalBp
– a Kirillov-Reshetikhin crystalnormalization
– (default: 0) the normalization value
EXAMPLES:
sage: K = crystals.KirillovReshetikhin(['C',2,1], 1,2) sage: K2 = crystals.KirillovReshetikhin(['C',2,1], 2,1) sage: H = K.local_energy_function(K2) sage: T = tensor([K, K2]) sage: hw = [x for x in T if x.is_highest_weight([1,2])] sage: for b in hw: ....: b, H(b) ([[], [[1], [2]]], 1) ([[[1, 1]], [[1], [2]]], 0) ([[[2, -2]], [[1], [2]]], 1) ([[[1, -2]], [[1], [2]]], 1)
REFERENCES:
[KKMMNN92] S-J. Kang, M. Kashiwara, K. C. Misra, T. Miwa, T. Nakashima, and A. Nakayashiki. Affine crystals and vertex models. Int. J. Mod. Phys. A, 7 (suppl. 1A), (1992) pp. 449-484.
-
class
sage.combinat.crystals.tensor_product.
TensorProductOfCrystals
¶ Bases:
sage.combinat.crystals.tensor_product.CrystalOfWords
Tensor product of crystals.
Given two crystals \(B\) and \(B'\) of the same Cartan type, one can form the tensor product \(B \otimes B^{\prime}\). As a set \(B \otimes B^{\prime}\) is the Cartesian product \(B \times B^{\prime}\). The crystal operators \(f_i\) and \(e_i\) act on \(b \otimes b^{\prime} \in B \otimes B^{\prime}\) as follows:
\[\begin{split}f_i(b \otimes b^{\prime}) = \begin{cases} f_i(b) \otimes b^{\prime} & \text{if } \varepsilon_i(b) \geq \varphi_i(b^{\prime}) \\ b \otimes f_i(b^{\prime}) & \text{otherwise} \end{cases}\end{split}\]and
\[\begin{split}e_i(b \otimes b') = \begin{cases} e_i(b) \otimes b' & \text{if } \varepsilon_i(b) > \varphi_i(b') \\ b \otimes e_i(b') & \text{otherwise.} \end{cases}\end{split}\]We also define:
\[\begin{split}\begin{aligned} \varphi_i(b \otimes b') & = \max\left( \varphi_i(b), \varphi_i(b') + \langle \alpha_i^{\vee}, \mathrm{wt}(b) \rangle \right), \\ \varepsilon_i(b \otimes b') & = \max\left( \varepsilon_i(b'), \varepsilon_i(b) - \langle \alpha_i^{\vee}, \mathrm{wt}(b') \rangle \right). \end{aligned}\end{split}\]Note
This is the opposite of Kashiwara’s convention for tensor products of crystals.
Since tensor products are associative \((\mathcal{B} \otimes \mathcal{C}) \otimes \mathcal{D} \cong \mathcal{B} \otimes (\mathcal{C} \otimes \mathcal{D})\) via the natural isomorphism \((b \otimes c) \otimes d \mapsto b \otimes (c \otimes d)\), we can generalizing this to arbitrary tensor products. Thus consider \(B_N \otimes \cdots \otimes B_1\), where each \(B_k\) is an abstract crystal. The underlying set of the tensor product is \(B_N \times \cdots \times B_1\), while the crystal structure is given as follows. Let \(I\) be the index set, and fix some \(i \in I\) and \(b_N \otimes \cdots \otimes b_1 \in B_N \otimes \cdots \otimes B_1\). Define
\[a_i(k) := \varepsilon_i(b_k) - \sum_{j=1}^{k-1} \langle \alpha_i^{\vee}, \mathrm{wt}(b_j) \rangle.\]Then
\[\begin{split}\begin{aligned} \mathrm{wt}(b_N \otimes \cdots \otimes b_1) &= \mathrm{wt}(b_N) + \cdots + \mathrm{wt}(b_1), \\ \varepsilon_i(b_N \otimes \cdots \otimes b_1) &= \max_{1 \leq k \leq n}\left( \sum_{j=1}^k \varepsilon_i(b_j) - \sum_{j=1}^{k-1} \varphi_i(b_j) \right) \\ & = \max_{1 \leq k \leq N}\bigl( a_i(k) \bigr), \\ \varphi_i(b_N \otimes \cdots \otimes b_1) &= \max_{1 \leq k \leq N} \left( \varphi_i(b_N) + \sum_{j=k}^{N-1} \big( \varphi_i(b_j) - \varepsilon_i(b_{j+1}) \big) \right) \\ & = \max_{1 \leq k \leq N}\bigl( \lambda_i + a_i(k) \bigr) \end{aligned}\end{split}\]where \(\lambda_i = \langle \alpha_i^{\vee}, \mathrm{wt}(b_N \otimes \cdots \otimes b_1) \rangle\). Then for \(k = 1, \ldots, N\) the action of the Kashiwara operators is determined as follows.
If \(a_i(k) > a_i(j)\) for \(1 \leq j < k\) and \(a_i(k) \geq a_i(j)\) for \(k < j \leq N\):
\[e_i(b_N \otimes \cdots \otimes b_1) = b_N \otimes \cdots \otimes e_i b_k \otimes \cdots \otimes b_1.\]If \(a_i(k) \geq a_i(j)\) for \(1 \leq j < k\) and \(a_i(k) > a_i(j)\) for \(k < j \leq N\):
\[f_i(b_N \otimes \cdots \otimes b_1) = b_N \otimes \cdots \otimes f_i b_k \otimes \cdots \otimes b_1.\]
Note that this is just recursively applying the definition of the tensor product on two crystals. Recall that \(\langle \alpha_i^{\vee}, \mathrm{wt}(b_j) \rangle = \varphi_i(b_j) - \varepsilon_i(b_j)\) by the definition of a crystal.
Regular crystals
Now if all crystals \(B_k\) are regular crystals, all \(\varepsilon_i\) and \(\varphi_i\) are non-negative and we can define tensor product by the signature rule. We start by writing a word in \(+\) and \(-\) as follows:
\[\underbrace{- \cdots -}_{\varphi_i(b_N) \text{ times}} \quad \underbrace{+ \cdots +}_{\varepsilon_i(b_N) \text{ times}} \quad \cdots \quad \underbrace{- \cdots -}_{\varphi_i(b_1) \text{ times}} \quad \underbrace{+ \cdots +}_{\varepsilon_i(b_1) \text{ times}},\]and then canceling ordered pairs of \(+-\) until the word is in the reduced form:
\[\underbrace{- \cdots -}_{\varphi_i \text{ times}} \quad \underbrace{+ \cdots +}_{\varepsilon_i \text{ times}}.\]Here \(e_i\) acts on the factor corresponding to the leftmost \(+\) and \(f_i\) on the factor corresponding to the rightmost \(-\). If there is no \(+\) or \(-\) respectively, then the result is \(0\) (
None
).EXAMPLES:
We construct the type \(A_2\)-crystal generated by \(2 \otimes 1 \otimes 1\):
sage: C = crystals.Letters(['A',2]) sage: T = crystals.TensorProduct(C,C,C,generators=[[C(2),C(1),C(1)]])
It has \(8\) elements:
sage: T.list() [[2, 1, 1], [2, 1, 2], [2, 1, 3], [3, 1, 3], [3, 2, 3], [3, 1, 1], [3, 1, 2], [3, 2, 2]]
One can also check the Cartan type of the crystal:
sage: T.cartan_type() ['A', 2]
Other examples include crystals of tableaux (which internally are represented as tensor products obtained by reading the tableaux columnwise):
sage: C = crystals.Tableaux(['A',3], shape=[1,1,0]) sage: D = crystals.Tableaux(['A',3], shape=[1,0,0]) sage: T = crystals.TensorProduct(C,D, generators=[[C(rows=[[1], [2]]), D(rows=[[1]])], [C(rows=[[2], [3]]), D(rows=[[1]])]]) sage: T.cardinality() 24 sage: TestSuite(T).run() sage: T.module_generators [[[[1], [2]], [[1]]], [[[2], [3]], [[1]]]] sage: [x.weight() for x in T.module_generators] [(2, 1, 0, 0), (1, 1, 1, 0)]
If no module generators are specified, we obtain the full tensor product:
sage: C = crystals.Letters(['A',2]) sage: T = crystals.TensorProduct(C,C) sage: T.list() [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]] sage: T.cardinality() 9
For a tensor product of crystals without module generators, the default implementation of
module_generators
contains all elements in the tensor product of the crystals. If there is a subset of elements in the tensor product that still generates the crystal, this needs to be implemented for the specific crystal separately:sage: T.module_generators.list() [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]]
For classical highest weight crystals, it is also possible to list all highest weight elements:
sage: C = crystals.Letters(['A',2]) sage: T = crystals.TensorProduct(C,C,C,generators=[[C(2),C(1),C(1)],[C(1),C(2),C(1)]]) sage: T.highest_weight_vectors() ([2, 1, 1], [1, 2, 1])
Examples with non-regular and infinite crystals (these did not work before trac ticket #14402):
sage: B = crystals.infinity.Tableaux(['D',10]) sage: T = crystals.TensorProduct(B,B) sage: T Full tensor product of the crystals [The infinity crystal of tableaux of type ['D', 10], The infinity crystal of tableaux of type ['D', 10]] sage: B = crystals.infinity.GeneralizedYoungWalls(15) sage: T = crystals.TensorProduct(B,B,B) sage: T Full tensor product of the crystals [Crystal of generalized Young walls of type ['A', 15, 1], Crystal of generalized Young walls of type ['A', 15, 1], Crystal of generalized Young walls of type ['A', 15, 1]] sage: La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() sage: B = crystals.GeneralizedYoungWalls(2,La[0]+La[1]) sage: C = crystals.GeneralizedYoungWalls(2,2*La[2]) sage: D = crystals.GeneralizedYoungWalls(2,3*La[0]+La[2]) sage: T = crystals.TensorProduct(B,C,D) sage: T Full tensor product of the crystals [Highest weight crystal of generalized Young walls of Cartan type ['A', 2, 1] and highest weight Lambda[0] + Lambda[1], Highest weight crystal of generalized Young walls of Cartan type ['A', 2, 1] and highest weight 2*Lambda[2], Highest weight crystal of generalized Young walls of Cartan type ['A', 2, 1] and highest weight 3*Lambda[0] + Lambda[2]]
There is also a global option for setting the convention (by default Sage uses anti-Kashiwara):
sage: C = crystals.Letters(['A',2]) sage: T = crystals.TensorProduct(C,C) sage: elt = T(C(1), C(2)); elt [1, 2] sage: crystals.TensorProduct.options.convention = "Kashiwara" sage: elt [2, 1] sage: crystals.TensorProduct.options._reset()
-
global_options
(*args, **kwds)¶ Deprecated: Use
options()
instead. See trac ticket #18555 for details.
-
options
(*get_value, **set_value)¶ Sets the global options for tensor products of crystals. The default is to use the anti-Kashiwara convention.
There are two conventions for how \(e_i\) and \(f_i\) act on tensor products, and the difference between the two is the order of the tensor factors are reversed. This affects both the input and output. See the example below.
OPTIONS:
convention
– (default:antiKashiwara
) Sets the convention used for displaying/inputting tensor product of crystalsKashiwara
– use the Kashiwara conventionanti
– alias forantiKashiwara
antiKashiwara
– use the anti-Kashiwara conventionopposite
– alias forantiKashiwara
Note
Changing the
convention
also changes how the input is handled.Warning
Internally, the crystals are always stored using the anti-Kashiwara convention.
If no parameters are set, then the function returns a copy of the options dictionary.
EXAMPLES:
sage: C = crystals.Letters(['A',2]) sage: T = crystals.TensorProduct(C,C) sage: elt = T(C(1), C(2)); elt [1, 2] sage: crystals.TensorProduct.options.convention = "Kashiwara" sage: elt [2, 1] sage: T(C(1), C(2)) == elt False sage: T(C(2), C(1)) == elt True sage: crystals.TensorProduct.options._reset()
See
GlobalOptions
for more features of these options.
-
class
sage.combinat.crystals.tensor_product.
TensorProductOfCrystalsElement
(parent, *args, **kwds)¶ Bases:
sage.combinat.crystals.tensor_product.ImmutableListWithParent
A class for elements of tensor products of crystals.
-
e
(i)¶ Return the action of \(e_i\) on
self
.INPUT:
i
– An element of the index set
EXAMPLES:
sage: B = crystals.infinity.Tableaux("D4") sage: T = crystals.TensorProduct(B,B) sage: b1 = B.highest_weight_vector().f_string([1,4,3]) sage: b2 = B.highest_weight_vector().f_string([2,2,3,1,4]) sage: t = T(b2, b1) sage: t.e(1) [[[1, 1, 1, 1, 1], [2, 2, 3, -3], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] sage: t.e(2) sage: t.e(3) [[[1, 1, 1, 1, 1, 2], [2, 2, 3, -4], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] sage: t.e(4) [[[1, 1, 1, 1, 1, 2], [2, 2, 3, 4], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]]
-
epsilon
(i)¶ Return \(\varepsilon_i\) of
self
.INPUT:
i
– An element of the index set
EXAMPLES:
sage: B = crystals.infinity.Tableaux("G2") sage: T = crystals.TensorProduct(B,B) sage: b1 = B.highest_weight_vector().f(2) sage: b2 = B.highest_weight_vector().f_string([2,2,1]) sage: t = T(b2, b1) sage: [t.epsilon(i) for i in B.index_set()] [0, 3]
-
f
(i)¶ Return the action of \(f_i\) on
self
.INPUT:
i
– An element of the index set
EXAMPLES:
sage: La = RootSystem(['A',3,1]).weight_lattice(extended=True).fundamental_weights() sage: B = crystals.GeneralizedYoungWalls(3,La[0]) sage: T = crystals.TensorProduct(B,B,B) sage: b1 = B.highest_weight_vector().f_string([0,3]) sage: b2 = B.highest_weight_vector().f_string([0]) sage: b3 = B.highest_weight_vector() sage: t = T(b3, b2, b1) sage: t.f(0) [[[0]], [[0]], [[0, 3]]] sage: t.f(1) [[], [[0]], [[0, 3], [1]]] sage: t.f(2) [[], [[0]], [[0, 3, 2]]] sage: t.f(3) [[], [[0, 3]], [[0, 3]]]
-
phi
(i)¶ Return \(\varphi_i\) of
self
.INPUT:
i
– An element of the index set
EXAMPLES:
sage: La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() sage: B = crystals.GeneralizedYoungWalls(2,La[0]+La[1]) sage: T = crystals.TensorProduct(B,B) sage: b1 = B.highest_weight_vector().f_string([1,0]) sage: b2 = B.highest_weight_vector().f_string([0,1]) sage: t = T(b2, b1) sage: [t.phi(i) for i in B.index_set()] [1, 1, 4]
TESTS:
Check that trac ticket #15462 is fixed:
sage: B = crystals.Tableaux(['A',2], shape=[2,1]) sage: La = RootSystem(['A',2]).ambient_space().fundamental_weights() sage: T = crystals.TensorProduct(crystals.elementary.T(['A',2], La[1]+La[2]), B) sage: t = T.an_element() sage: t.phi(1) 2 sage: t.phi(2) 2
-
pp
()¶ Pretty print
self
.EXAMPLES:
sage: C = crystals.Tableaux(['A',3], shape=[3,1]) sage: D = crystals.Tableaux(['A',3], shape=[1]) sage: E = crystals.Tableaux(['A',3], shape=[2,2,2]) sage: T = crystals.TensorProduct(C,D,E) sage: T.module_generators[0].pp() 1 1 1 (X) 1 (X) 1 1 2 2 2 3 3
-
weight
()¶ Return the weight of
self
.EXAMPLES:
sage: B = crystals.infinity.Tableaux("A3") sage: T = crystals.TensorProduct(B,B) sage: b1 = B.highest_weight_vector().f_string([2,1,3]) sage: b2 = B.highest_weight_vector().f(1) sage: t = T(b2, b1) sage: t [[[1, 1, 1, 2], [2, 2], [3]], [[1, 1, 1, 1, 2], [2, 2, 4], [3]]] sage: t.weight() (-2, 1, 0, 1)
-
-
class
sage.combinat.crystals.tensor_product.
TensorProductOfCrystalsWithGenerators
(crystals, generators, cartan_type)¶ Bases:
sage.combinat.crystals.tensor_product.TensorProductOfCrystals
Tensor product of crystals with a generating set.
Todo
Deprecate this class in favor of using
subcrystal()
.
-
class
sage.combinat.crystals.tensor_product.
TensorProductOfRegularCrystalsElement
(parent, *args, **kwds)¶ Bases:
sage.combinat.crystals.tensor_product.TensorProductOfCrystalsElement
Element class for a tensor product of regular crystals.
TESTS:
sage: C = crystals.Letters(['A',2]) sage: T = crystals.TensorProduct(C, C) sage: elt = T(C(1), C(2)) sage: from sage.combinat.crystals.tensor_product import TensorProductOfRegularCrystalsElement sage: isinstance(elt, TensorProductOfRegularCrystalsElement) True
-
affine_grading
()¶ Returns the affine grading of \(self\).
The affine grading is only defined when
self
is an element of a tensor product of affine Kirillov-Reshetikhin crystals. It is calculated by finding a path fromself
to a ground state path using the helper methode_string_to_ground_state()
and counting the number of affine Kashiwara operators \(e_0\) applied on the way.INPUT:
self
– an element of a tensor product of Kirillov-Reshetikhin crystals
OUTPUT: an integer
EXAMPLES:
sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: T = crystals.TensorProduct(K,K) sage: t = T.module_generators[0] sage: t.affine_grading() 1 sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: T = crystals.TensorProduct(K,K,K) sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] sage: for b in hw: ....: print("{} {}".format(b, b.affine_grading())) [[[1]], [[1]], [[1]]] 3 [[[1]], [[2]], [[1]]] 1 [[[2]], [[1]], [[1]]] 2 [[[3]], [[2]], [[1]]] 0 sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) sage: T = crystals.TensorProduct(K,K,K) sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] sage: for b in hw: ....: print("{} {}".format(b, b.affine_grading())) [[[1]], [[1]], [[1]]] 2 [[[1]], [[2]], [[1]]] 1 [[[1]], [[-1]], [[1]]] 0 [[[2]], [[1]], [[1]]] 1 [[[-2]], [[2]], [[1]]] 0 [[[-1]], [[1]], [[1]]] 1
-
e
(i)¶ Return the action of \(e_i\) on
self
.EXAMPLES:
sage: C = crystals.Letters(['A',5]) sage: T = crystals.TensorProduct(C,C) sage: T(C(1),C(2)).e(1) == T(C(1),C(1)) True sage: T(C(2),C(1)).e(1) is None True sage: T(C(2),C(2)).e(1) == T(C(1),C(2)) True
-
e_string_to_ground_state
()¶ Returns a string of integers in the index set \((i_1,\ldots,i_k)\) such that \(e_{i_k} \cdots e_{i_1}\) of
self
is the ground state.This method is only defined when
self
is an element of a tensor product of affine Kirillov-Reshetikhin crystals. It calculates a path fromself
to a ground state path using Demazure arrows as defined in Lemma 7.3 in [SchillingTingley2011].INPUT:
self
– an element of a tensor product of Kirillov-Reshetikhin crystals
OUTPUT: a tuple of integers \((i_1,\ldots,i_k)\)
EXAMPLES:
sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: T = crystals.TensorProduct(K,K) sage: t = T.module_generators[0] sage: t.e_string_to_ground_state() (0, 2) sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) sage: T = crystals.TensorProduct(K,K) sage: t = T.module_generators[0]; t [[[1]], [[1]]] sage: t.e_string_to_ground_state() (0,) sage: x=t.e(0) sage: x.e_string_to_ground_state() () sage: y=t.f_string([1,2,1,1,0]); y [[[2]], [[1]]] sage: y.e_string_to_ground_state() ()
-
energy_function
(algorithm=None)¶ Return the energy function of
self
.ALGORITHM:
definition
Let \(T\) be a tensor product of Kirillov-Reshetikhin crystals. Let \(R_i\) and \(H_i\) be the combinatorial \(R\)-matrix and local energy functions, respectively, acting on the \(i\) and \(i+1\) factors. Let \(D_B\) be the energy function of a single Kirillov-Reshetikhin crystal. The energy function is given by
\[D = \sum_{j > i} H_i R_{i+1} R_{i+2} \cdots R_{j-1} + \sum_j D_B R_1 R_2 \cdots R_{j-1},\]where \(D_B\) acts on the rightmost factor.
grading
If
self
is an element of \(T\), a tensor product of perfect crystals of the same level, then use the affine grading to determine the energy. Specifically, let \(g\) denote the affine grading ofself
and \(d\) the affine grading of the maximal vector in \(T\). Then the energy ofself
is given by \(d - g\).For more details, see Theorem 7.5 in [SchillingTingley2011].
INPUT:
algorithm
– (default:None
) use one of the following algorithms to determine the energy function:'definition'
- use the definition of the energy function;'grading'
- use the affine grading;
if not specified, then this uses
'grading'
if all factors are perfect of the same level and otherwise this uses'definition'
OUTPUT: an integer
REFERENCES:
[SchillingTingley2011] (1, 2) A. Schilling, P. Tingley. Demazure crystals, Kirillov-Reshetikhin crystals, and the energy function. Electronic Journal of Combinatorics. 19(2). 2012. Arxiv 1104.2359 EXAMPLES:
sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) sage: T = crystals.TensorProduct(K,K,K) sage: hw = sorted([x for x in T if x.is_highest_weight([1,2])]) sage: for b in hw: ....: print("{} {}".format(b, b.energy_function())) [[[1]], [[1]], [[1]]] 0 [[[1]], [[2]], [[1]]] 2 [[[2]], [[1]], [[1]]] 1 [[[3]], [[2]], [[1]]] 3 sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) sage: T = crystals.TensorProduct(K,K) sage: hw = [x for x in T if x.is_highest_weight([1,2])] sage: for b in hw: ....: print("{} {}".format(b, b.energy_function())) [[], []] 4 [[], [[1, 1]]] 1 [[[1, 1]], []] 3 [[[1, 1]], [[1, 1]]] 0 [[[1, 2]], [[1, 1]]] 1 [[[2, 2]], [[1, 1]]] 2 [[[-1, -1]], [[1, 1]]] 2 [[[1, -1]], [[1, 1]]] 2 [[[2, -1]], [[1, 1]]] 2 sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) sage: T = crystals.TensorProduct(K) sage: t = T.module_generators[0] sage: t.energy_function('grading') Traceback (most recent call last): ... NotImplementedError: all crystals in the tensor product need to be perfect of the same level
TESTS:
sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) sage: K2 = crystals.KirillovReshetikhin(['C',2,1], 2, 2) sage: T = tensor([K, K2]) sage: hw = [x for x in T if x.is_highest_weight([1,2])] sage: all(b.energy_function() == b.energy_function(algorithm='definition') ....: for b in hw) True
-
epsilon
(i)¶ Return \(\varepsilon_i\) of
self
.EXAMPLES:
sage: C = crystals.Letters(['A',5]) sage: T = crystals.TensorProduct(C,C) sage: T(C(1),C(1)).epsilon(1) 0 sage: T(C(1),C(2)).epsilon(1) 1 sage: T(C(2),C(1)).epsilon(1) 0
-
f
(i)¶ Return the action of \(f_i\) on
self
.EXAMPLES:
sage: C = crystals.Letters(['A',5]) sage: T = crystals.TensorProduct(C,C) sage: T(C(1),C(1)).f(1) [1, 2] sage: T(C(1),C(2)).f(1) [2, 2] sage: T(C(2),C(1)).f(1) is None True
-
phi
(i)¶ Return \(\varphi_i\) of
self
.EXAMPLES:
sage: C = crystals.Letters(['A',5]) sage: T = crystals.TensorProduct(C,C) sage: T(C(1),C(1)).phi(1) 2 sage: T(C(1),C(2)).phi(1) 1 sage: T(C(2),C(1)).phi(1) 0
-
positions_of_unmatched_minus
(i, dual=False, reverse=False)¶ EXAMPLES:
sage: C = crystals.Letters(['A',5]) sage: T = crystals.TensorProduct(C,C) sage: T(C(2),C(1)).positions_of_unmatched_minus(1) [] sage: T(C(1),C(2)).positions_of_unmatched_minus(1) [0]
-
positions_of_unmatched_plus
(i)¶ EXAMPLES:
sage: C = crystals.Letters(['A',5]) sage: T = crystals.TensorProduct(C,C) sage: T(C(2),C(1)).positions_of_unmatched_plus(1) [] sage: T(C(1),C(2)).positions_of_unmatched_plus(1) [1]
-
weight
()¶ Return the weight of
self
.EXAMPLES:
sage: C = crystals.Letters(['A',3]) sage: T = crystals.TensorProduct(C,C) sage: T(C(1),C(2)).weight() (1, 1, 0, 0) sage: T = crystals.Tableaux(['D',4],shape=[]) sage: T.list()[0].weight() (0, 0, 0, 0)
-
-
class
sage.combinat.crystals.tensor_product.
TensorProductOfRegularCrystalsWithGenerators
(crystals, generators, cartan_type)¶ Bases:
sage.combinat.crystals.tensor_product.TensorProductOfCrystalsWithGenerators
Tensor product of regular crystals with a generating set.
-
Element
¶
-
-
class
sage.combinat.crystals.tensor_product.
TestParent
¶ Bases:
sage.structure.unique_representation.UniqueRepresentation
,sage.structure.parent.Parent
A parent for tests.
-
sage.combinat.crystals.tensor_product.
trunc
(i)¶ Truncates to the integer closer to zero
EXAMPLES:
sage: from sage.combinat.crystals.tensor_product import trunc sage: trunc(-3/2), trunc(-1), trunc(-1/2), trunc(0), trunc(1/2), trunc(1), trunc(3/2) (-1, -1, 0, 0, 0, 1, 1) sage: isinstance(trunc(3/2), Integer) True