Classical Crystals#
A classical crystal is one coming from the finite (classical) types
Tableaux and representations of #
Let

A semi-standard Young tableau of shape

is a semistandard Young tableau. Sage has a Tableau
class,
and you may create this tableau as follows:
sage: T = Tableau([[1,2,2], [2,3]]); T
[[1, 2, 2], [2, 3]]
A partition of length
It is true that not every dominant weight
Theorem [Littlewood] If
For example, if

This is consistent with the theorem since the dimension of the
irreducible representation of
sage: A2 = WeylCharacterRing("A2")
sage: A2(3,2,0).degree()
15
In fact we may obtain the character of the representation from the set
of tableaux. Indeed, one of the definitions of the Schur polynomial
(due to Littlewood) is the following combinatorial one. If
where the sum is over all semi-standard Young tableaux of shape
Frobenius-Schur Duality#
Frobenius-Schur duality is a relationship between the representation theories of the symmetric group and general linear group. We will relate this to tableaux in the next section.
Representations of the symmetric group
as bimodules for the two groups. This is Frobenius-Schur duality and
it serves to characterize the parametrization of the irreducible
representations of
Counting pairs of tableaux#
In both the representation theory of
Let us say that a semistandard Young tableau
Theorem [Young, 1927] The degree of
Now let us consider the implications of Frobenius-Schur duality.
The dimension of
The Robinson-Schensted-Knuth correspondence#
The last purely combinatorial statement has a combinatorial proof, based on the Robinson-Schensted-Knuth (RSK) correspondence.
References:
[Knuth1998], section “Tableaux and Involutions”.
The RSK correspondence gives bijections between
pairs of tableaux of various types and combinatorial objects of
different types. We will not review the correspondence in detail here,
but see the references. We note that Schensted insertion is
implemented as the method schensted_insertion
of Tableau class in
Sage.
Thus we have the following bijections:
Pairs of tableaux
and of shape where runs through the partitions of such that is a standard tableau and is a semistandard tableau in are in bijection with the words of length in .Pairs of standard tableaux of the same shape
as runs through the partitions of are in bijection with the elements of .Pairs of tableaux
and of the same shape but arbitrary size in are in bijection with positive integer matrices.Pairs of tableaux
and of conjugate shapes and are in bijection with matrices with entries or .
The second of these four bijection gives a combinatorial proof of
the fact explained above, that the number of pairs
Analogies between representation theory and combinatorics#
The four combinatorial bijections (variants of RSK) cited above have the following analogs in representation theory.
The first combinatorial fact corresponds to Frobenius-Schur duality, as we have already explained.
The second combinatorial fact also has an analog in representation theory. The group algebra
is an bimodule with of dimension . It decomposes as a direct sum of .
Both the combinatorial fact and the decomposition of
The third combinatorial fact is analogous to the decomposition of the ring of polynomial functions on
on which acts by . The polynomial ring decomposes into the direct sum of .
Taking traces gives the Cauchy identity:
where
The last combinatorial fact is analogous to the decomposition of the exterior algebra over
.
Taking traces gives the dual Cauchy identity:
Again the sum is over partitions
Interpolating between representation theory and combinatorics#
The theory of quantum groups interpolates between the representation
theoretic picture and the combinatorial picture, and thereby explains
these analogies. The representation
Kashiwara crystals#
References:
Kashiwara considered the highest weight modules of quantized
enveloping algebras
Kashiwara’s crystal bases have a combinatorial structure that sheds light even on purely combinatorial constructions on tableaux that predated quantum groups. It gives a good generalization to other Cartan types (or more generally to Kac-Moody algebras).
Let
Moreover, we assume that
for all
We call a crystal regular if it satisfies the additional assumption that
Note
Most of the crystals that we are concerned with here are regular.
Given the crystal
Given any highest weight
The crystal
Installing dot2tex#
Before giving examples of crystals, we digress to help you install
dot2tex
, which you will need in order to make latex images of
crystals.
dot2tex
is an optional package of sage and the latest version
can be installed via:
$ sage -i dot2tex
This also requires various LaTeX packages. The following command checks whether those are available:
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random
Crystals of tableaux in Sage#
All crystals that are currently in Sage can be accessed by crystals.<tab>
.
For type
Once you have dot2tex
installed, you may make images pictures of crystals
with a command such as this:
sage: fn = tmp_filename(ext=".tex")
sage: crystals.Tableaux("A2", shape=[2,1]).latex_file(fn)
Here C
is
a2rho.tex
.
This can also be achieved without the detour of saving the latex file via:
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
sage: view(B, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
This produces the crystal graph:

You may also wish to color the edges in different colors by specifying further latex options:
sage: B = crystals.Tableaux(['A',2], shape=[2,1])
sage: G = B.digraph()
sage: G.set_latex_options(color_by_label = {1:"red", 2:"yellow"})
sage: view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
As you can see, the elements of this crystal are exactly the eight
tableaux of shape

We recall that the weight of the tableau is
Once the crystal is created, you have access to the ambient space and
its methods through the method weight_lattice_realization()
:
sage: C = crystals.Tableaux("A2", shape=[2,1])
sage: L = C.weight_lattice_realization(); L
Ambient space of the Root system of type ['A', 2]
sage: L.fundamental_weights()
Finite family {1: (1, 0, 0), 2: (1, 1, 0)}
The highest weight vector is available as follows:
sage: C = crystals.Tableaux("A2", shape=[2,1])
sage: v = C.highest_weight_vector(); v
[[1, 1], [2]]
or more simply:
sage: C = crystals.Tableaux("A2", shape=[2,1])
sage: C[0]
[[1, 1], [2]]
Now we may apply the operators
sage: C = crystals.Tableaux("A2", shape=[2,1])
sage: v = C.highest_weight_vector()
sage: v.f(1)
[[1, 2], [2]]
sage: v.f(1).f(1)
sage: v.f(1).f(1) is None
True
sage: v.f(1).f(2)
[[1, 3], [2]]
sage: v.f(1).f(2).f(2)
[[1, 3], [3]]
sage: v.f(1).f(2).f(2).f(1)
[[2, 3], [3]]
sage: v.f(1).f(2).f(2).f(1) == v.f(2).f(1).f(1).f(2)
True
You can construct the character if you first make a Weyl character ring:
sage: A2 = WeylCharacterRing("A2")
sage: C = crystals.Tableaux("A2", shape=[2,1])
sage: C.character(A2)
A2(2,1,0)
Crystals of letters#
For each of the classical Cartan types there is a standard crystal
Here is the standard crystal of type

You may create the crystal and work with it as follows:
sage: C = crystals.Letters("A6")
sage: v0 = C.highest_weight_vector(); v0
1
sage: v0.f(1)
2
sage: v0.f(1).f(2)
3
sage: [v0.f(1).f(2).f(x) for x in [1..6]]
[None, None, 4, None, None, None]
sage: [v0.f(1).f(2).e(x) for x in [1..6]]
[None, 2, None, None, None, None]
Here is the standard crystal of type

There is, additionally, a spin crystal for spin
If
Create the spin crystal as follows. The crystal elements are represented
in the signature representation listing the
sage: C = crystals.Spins("B3")
sage: C.list()
[+++, ++-, +-+, -++, +--, -+-, --+, ---]
Here is the standard crystal of type

Here is the standard crystal of type

There are two spin crystals for type
sage: Cplus = crystals.SpinsPlus("D4")
sage: Cminus = crystals.SpinsMinus("D4")
It is also possible to construct the standard crystal for type

The crystal of letters is a special case of the crystal of tableaux
in the sense that
sage: crystals.Letters("A3")
The crystal of letters for type ['A', 3]
sage: crystals.Tableaux("A3", shape=[1])
The crystal of tableaux of type ['A', 3] and shape(s) [[1]]
These two crystals are different in implementation, but they are isomorphic. In fact the second crystal is constructed from the first. We can test isomorphisms between crystals as follows:
sage: Cletter = crystals.Letters(['A',3])
sage: Ctableaux = crystals.Tableaux(['A',3], shape = [1])
sage: Cletter.digraph().is_isomorphic(Ctableaux.digraph())
True
sage: Cletter.digraph().is_isomorphic(Ctableaux.digraph(), certificate = True)
(True, {1: [[1]], 2: [[2]], 3: [[3]], 4: [[4]]})
where in the last step the explicit map between the vertices of the crystals is given.
Crystals of letters have a special role in the theory since they are particularly simple, yet as Kashiwara and Nakashima showed, the crystals of tableaux can be created from them. We will review how this works.
Tensor products of crystals#
Kashiwara defined the tensor product of crystals in a purely
combinatorial way. The beauty of this construction is that it exactly
parallels the tensor product of crystals of representations. That is,
if
We will describe two conventions for the tensor product of crystals.
Kashiwara’s definition#
As a set, the tensor product
and
It is understood that
Alternative definition#
As a set, the tensor product
and
It is understood that
The tensor product is associative:
The relationship between the two definitions#
The relationship between the two definitions is simply that the
Kashiwara tensor product
Note
Using abstract crystals (i.e. they satisfy the axioms but do not arise
from a representation of
Tensor products of crystals in Sage#
You may construct the tensor product of several crystals in Sage using
crystals.TensorProduct
:
sage: C = crystals.Letters("A2")
sage: T = crystals.TensorProduct(C,C,C); T
Full tensor product of the crystals [The crystal of letters for type ['A', 2],
The crystal of letters for type ['A', 2], The crystal of letters for type ['A', 2]]
sage: T.cardinality()
27
sage: T.highest_weight_vectors()
([1, 1, 1], [2, 1, 1], [1, 2, 1], [3, 2, 1])
This crystal has four highest weight vectors. We may understand this as follows:
sage: A2 = WeylCharacterRing("A2")
sage: C = crystals.Letters("A2")
sage: T = crystals.TensorProduct(C,C,C)
sage: chi_C = C.character(A2)
sage: chi_T = T.character(A2)
sage: chi_C
A2(1,0,0)
sage: chi_T
A2(1,1,1) + 2*A2(2,1,0) + A2(3,0,0)
sage: chi_T == chi_C^3
True
As expected, the character of T
is the cube of the character of
C
, and representations with highest weight
It is useful to be able to select one irreducible constitutent of
T
. If we only want one of the irreducible constituents of T
,
we can specify a list of highest weight vectors by the option
generators
. If the list has only one element, then we get an
irreducible crystal. We can make four such crystals:
sage: A2 = WeylCharacterRing("A2")
sage: C = crystals.Letters("A2")
sage: T = crystals.TensorProduct(C,C,C)
sage: [T1,T2,T3,T4] = \
[crystals.TensorProduct(C,C,C,generators=[v]) for v in T.highest_weight_vectors()]
sage: [B.cardinality() for B in [T1,T2,T3,T4]]
[10, 8, 8, 1]
sage: [B.character(A2) for B in [T1,T2,T3,T4]]
[A2(3,0,0), A2(2,1,0), A2(2,1,0), A2(1,1,1)]
We see that two of these crystals are isomorphic, with character
A2(2,1,0)
. Try:
sage: A2 = WeylCharacterRing("A2")
sage: C = crystals.Letters("A2")
sage: T = crystals.TensorProduct(C,C,C)
sage: [T1,T2,T3,T4] = \
[crystals.TensorProduct(C,C,C,generators=[v]) for v in T.highest_weight_vectors()]
sage: T1.plot()
Graphics object consisting of 35 graphics primitives
sage: T2.plot()
Graphics object consisting of 25 graphics primitives
sage: T3.plot()
Graphics object consisting of 25 graphics primitives
sage: T4.plot()
Graphics object consisting of 2 graphics primitives
Elements of crystals.TensorProduct(A,B,C, ...)
are represented by
sequences [a,b,c, ...]
with a
in A
, b
in B
, etc.
This of course represents
Crystals of tableaux as tensor products of crystals#
Sage implements the
CrystalOfTableaux
as
a subcrystal of a tensor product of the
ClassicalCrystalOfLetters
.
You can see how its done as follows:
sage: T = crystals.Tableaux("A4",shape=[3,2])
sage: v = T.highest_weight_vector().f(1).f(2).f(3).f(2).f(1).f(4).f(2).f(3); v
[[1, 2, 5], [3, 4]]
sage: list(v)
[3, 1, 4, 2, 5]
We’ve looked at the internal representation of ClassicalCrystalOfLetters
.
We see that the tableau:

is interpreted as the tensor:

The elements of the tableau are read from bottom to top and from left to right. This is the inverse middle-Eastern reading of the tableau. See Hong and Kang, loc. cit. for discussion of the readings of a tableau.
Spin crystals#
For the Cartan types CrystalOfTableaux
are
capable of making any finite crystal. (For type
For Cartan types CrystalOfTableaux
also allows
the input shape
sage: C = crystals.Tableaux(['B',2], shape = [3/2, 1/2])
sage: C.list()
[[++, [[1]]], [++, [[2]]], [++, [[0]]], [++, [[-2]]], [++, [[-1]]], [+-, [[-2]]],
[+-, [[-1]]], [-+, [[-1]]], [+-, [[1]]], [+-, [[2]]], [-+, [[2]]], [+-, [[0]]],
[-+, [[0]]], [-+, [[-2]]], [--, [[-2]]], [--, [[-1]]]]
Here the first list of CrystalOfTableaux
the
sage: C = crystals.Tableaux(['D',3], shape = [1/2, 1/2,-1/2])
sage: C.list()
[[++-, []], [+-+, []], [-++, []], [---, []]]
For rank two Cartan types, we also have crystals.FastRankTwo
which gives
a different fast implementation of these crystals:
sage: B = crystals.FastRankTwo(['B',2], shape=[3/2,1/2]); B
The fast crystal for B2 with shape [3/2,1/2]
sage: v = B.highest_weight_vector(); v.weight()
(3/2, 1/2)
Type B spin crystal#
The spin crystal has highest weight
sage: Cspin = crystals.Spins("B3"); Cspin
The crystal of spins for type ['B', 3]
sage: Cspin.cardinality()
8
The crystals with highest weight
sage: B3 = WeylCharacterRing("B3")
sage: B3(3/2,3/2,1/2).degree()
112
So Cspin
sage: B3 = WeylCharacterRing("B3")
sage: B3(1,1,0)*B3(1/2,1/2,1/2)
B3(1/2,1/2,1/2) + B3(3/2,1/2,1/2) + B3(3/2,3/2,1/2)
We see that just taking the tensor product of these two crystals will produce a reducible crystal with three constitutents, and we want to extract the one we want. We do that as follows:
sage: B3 = WeylCharacterRing("B3")
sage: C1 = crystals.Tableaux("B3", shape=[1,1])
sage: Cspin = crystals.Spins("B3")
sage: C = crystals.TensorProduct(C1, Cspin, generators=[[C1[0],Cspin[0]]])
sage: C.cardinality()
112
Alternatively, we can get this directly from
CrystalOfTableaux
:
sage: C = crystals.Tableaux(['B',3], shape = [3/2,3/2,1/2])
sage: C.cardinality()
112
This is the desired crystal.
Type D spin crystals#
A similar situation pertains for type
sage: SpinPlus = crystals.SpinsPlus("D4")
sage: SpinMinus = crystals.SpinsMinus("D4")
sage: SpinPlus[0].weight()
(1/2, 1/2, 1/2, 1/2)
sage: SpinMinus[0].weight()
(1/2, 1/2, 1/2, -1/2)
sage: [C.cardinality() for C in [SpinPlus,SpinMinus]]
[8, 8]
Similarly to type B crystal, we obtain crystal with spin weight by allowing for partitions with half-integer values, and the last entry can be negative depending on the type of the spin.
Lusztig involution#
The Lusztig involution on a finite-dimensional highest weight crystal
sage: B = crystals.Tableaux(['A',3],shape=[2,1])
sage: b = B(rows=[[1,2],[3]])
sage: b.lusztig_involution()
[[2, 4], [3]]
For type
sage: t = Tableau([[1,2],[3]])
sage: t.schuetzenberger_involution(n=4)
[[2, 4], [3]]
For all tableaux in a given crystal, this can be tested via:
sage: B = crystals.Tableaux(['A',3],shape=[2])
sage: all(b.lusztig_involution().to_tableau() == b.to_tableau().schuetzenberger_involution(n=4) for b in B)
True
The Lusztig involution is also defined for finite-dimensional highest weight crystals of exceptional type:
sage: C = CartanType(['E',6])
sage: La = C.root_system().weight_lattice().fundamental_weights()
sage: T = crystals.HighestWeight(La[1])
sage: t = T[4]; t
[(-2, 5)]
sage: t.lusztig_involution()
[(-3, 2)]
Levi branching rules for crystals#
Let
If
In Sage this is achieved by specifying the index set used in the digraph method:
sage: T = crystals.Tableaux(['D',4],shape=[1])
sage: G = T.digraph(index_set=[1,2,3])
We see that the type

For more on branching rules, see Maximal Subgroups and Branching Rules or Levi subgroups for specifics on the Levi subgroups.
Subcrystals#
Sometimes it might be desirable to work with a subcrystal of a crystal. For example,
one might want to look at all
sage: T = crystals.Tableaux(['D',4],shape=[2,1])
sage: hw = [ t for t in T if t.is_highest_weight(index_set = [2,3,4]) ]; hw
[[[1, 1], [2]],
[[1, 2], [2]],
[[2, -1], [-2]],
[[2, -1], [-1]],
[[1, -1], [2]],
[[2, -1], [3]],
[[1, 2], [3]],
[[2, 2], [3]],
[[1, 2], [-2]],
[[2, 2], [-2]],
[[2, 2], [-1]]]
sage: C = T.subcrystal(generators = [T(rows=[[2,-1],[3]])], index_set = [2,3,4])
sage: G = T.digraph(subset = C, index_set=[2,3,4])