Let be a CartanType with index set
, and
be a realization of the type
weight
lattice.
A type crystal
is a colored oriented graph
equipped with a weight function from the nodes to some realization
of the type
weight lattice such that:
Each edge is colored with a label in .
For each , each node
has:
Furthermore, when they exist,
This crystal actually models a representation of a Lie algebra if it satisfies some further local conditions due to Stembridge, see J. Stembridge, A local characterization of simply-laced crystals, Trans. Amer. Math. Soc. 355 (2003), no. 12, 4807-4823.
EXAMPLES:
We construct the type crystal on letters (or in
representation theoretic terms, the highest weight crystal of type
corresponding to the highest weight
)
sage: C = CrystalOfLetters(['A',5]); C
The crystal of letters for type ['A', 5]
It has a single highest weight element:
sage: C.highest_weight_vectors()
[1]
A crystal is an enumerated set (see EnumeratedSets); and we can count and list its elements in the usual way:
sage: C.cardinality()
6
sage: C.list()
[1, 2, 3, 4, 5, 6]
as well as use it in for loops:
sage: [x for x in C]
[1, 2, 3, 4, 5, 6]
Here are some more elaborate crystals (see their respective documentations):
sage: Tens = TensorProductOfCrystals(C, C)
sage: Spin = CrystalOfSpins(['B', 3])
sage: Tab = CrystalOfTableaux(['A', 3], shape = [2,1,1])
sage: Fast = FastCrystal(['B', 2], shape = [3/2, 1/2])
sage: KR = KirillovReshetikhinCrystal(['A',2,1],1,1)
One can get (currently) crude plotting via:
sage: Tab.plot()
For rank two crystals, there is an alternative method of getting metapost pictures. For more information see C.metapost?
Caveat: this crystal library, although relatively featureful for classical crystals, is still in an early development stage, and the syntax details may be subject to changes.
TODO:
Most of the above features (except Littelmann/alcove paths) are in MuPAD-Combinat (see lib/COMBINAT/crystals.mu), which could provide inspiration.
Bases: sage.combinat.crystals.crystals.Crystal
The abstract class of classical crystals
Returns the number of elements of the crystal, using Weyl’s dimension formula on each connected component
EXAMPLES:
sage: from sage.combinat.crystals.crystals import ClassicalCrystal
sage: C = CrystalOfLetters(['A', 5])
sage: ClassicalCrystal.cardinality(C)
6
Returns the highest weight vector if there is a single one; otherwise, raises an error.
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C.highest_weight_vector()
1
Returns a list of the highest weight vectors of self.
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C.highest_weight_vectors()
[1]
sage: C = CrystalOfLetters(['A',2])
sage: T = TensorProductOfCrystals(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]]
Returns the list of the elements of self, as per FiniteEnumeratedSets.ParentMethods.list()
EXAMPLES:
sage: C = CrystalOfLetters(['D',4])
sage: C.list()
[1, 2, 3, 4, -4, -3, -2, -1]
FIXME: this is just there to reinstate the default implementation of list which is overriden in Crystals.
Bases: sage.structure.unique_representation.UniqueRepresentation, sage.structure.parent.Parent
The abstract class of crystals
Derived subclasses should implement the following:
Returns the fundamentals weights in the weight lattice realization for the root system associated to self.
EXAMPLES:
sage: C = CrystalOfLetters(['A', 5])
sage: C.Lambda()
Finite family {1: (1, 0, 0, 0, 0, 0), 2: (1, 1, 0, 0, 0, 0), 3: (1, 1, 1, 0, 0, 0), 4: (1, 1, 1, 1, 0, 0), 5: (1, 1, 1, 1, 1, 0)}
Returns the Cartan type of the associated crystal
INPUT: R, a WeylCharacterRing. Produces the character of the crystal.
EXAMPLES:
sage: C = CrystalOfLetters(['A',2])
sage: T = TensorProductOfCrystals(C, C)
sage: A2 = WeylCharacterRing(C.cartan_type()); A2
The Weyl Character Ring of Type ['A', 2] with Integer Ring coefficients
sage: chi = T.character(A2); chi
A2(1,1,0) + A2(2,0,0)
sage: chi.check(verbose = true)
[9, 9]
Runs sanity checks on the crystal:
EXAMPLES:
sage: C = CrystalOfLetters(['A', 5])
sage: C.check()
True
Constructs a morphism from the crystal self to another crystal.
The input can either be a function of a (sub)set of elements of self to
element in another crystal or a dictionary between certain elements.
Usually one would map highest weight elements or crystal generators to each
other using g.
Specifying index_set gives the opportunity to define the morphism as
-crystals
where
index_set. If index_set is not specified, the index set of self is used.
It is also possible to define twisted-morphisms by specifying an automorphism on the
nodes in te Dynkin diagram (or the index_set).
The option direction and direction_image indicate whether to use
or
in
self or the image crystal to construct the morphism, depending on whether the direction
is set to ‘down’ or ‘up’.
It is also possible to set a similarity_factor. This should be a dictionary between
the elements in the index set and positive integers. The crystal operator
then gets
mapped to
where
similarity_factor[i].
Setting similarity_factor_domain to a dictionary between the index set and positive integers
has the effect that
gets mapped to
where
similarity_factor_domain[i].
Finally, it is possible to set the option
. This calculates an isomorphism
for cyclic crystals (for example finite affine crystals). In this case the input function
is supposed to be given as a dictionary.
EXAMPLES:
sage: C2 = CrystalOfLetters(['A',2])
sage: C3 = CrystalOfLetters(['A',3])
sage: g = {C2.module_generators[0] : C3.module_generators[0]}
sage: g_full = C2.crystal_morphism(g)
sage: g_full(C2(1))
1
sage: g_full(C2(2))
2
sage: g = {C2(1) : C2(3)}
sage: g_full = C2.crystal_morphism(g, automorphism = lambda i : 3-i, direction_image = 'up')
sage: [g_full(b) for b in C2]
[3, 2, 1]
sage: T = CrystalOfTableaux(['A',2], shape = [2])
sage: g = {C2(1) : T(rows=[[1,1]])}
sage: g_full = C2.crystal_morphism(g, similarity_factor = {1:2, 2:2})
sage: [g_full(b) for b in C2]
[[[1, 1]], [[2, 2]], [[3, 3]]]
sage: g = {T(rows=[[1,1]]) : C2(1)}
sage: g_full = T.crystal_morphism(g, similarity_factor_domain = {1:2, 2:2})
sage: g_full(T(rows=[[2,2]]))
2
sage: B1=KirillovReshetikhinCrystal(['A',2,1],1,1)
sage: B2=KirillovReshetikhinCrystal(['A',2,1],1,2)
sage: T=TensorProductOfCrystals(B1,B2)
sage: T1=TensorProductOfCrystals(B2,B1)
sage: La = T.weight_lattice_realization().fundamental_weights()
sage: t = [b for b in T if b.weight() == -3*La[0] + 3*La[1]][0]
sage: t1 = [b for b in T1 if b.weight() == -3*La[0] + 3*La[1]][0]
sage: g={t:t1}
sage: f=T.crystal_morphism(g,acyclic = False)
sage: [[b,f(b)] for b in T]
[[[[[1]], [[1, 1]]], [[[1, 1]], [[1]]]],
[[[[1]], [[1, 2]]], [[[1, 1]], [[2]]]],
[[[[1]], [[2, 2]]], [[[1, 2]], [[2]]]],
[[[[1]], [[1, 3]]], [[[1, 1]], [[3]]]],
[[[[1]], [[2, 3]]], [[[1, 2]], [[3]]]],
[[[[1]], [[3, 3]]], [[[1, 3]], [[3]]]],
[[[[2]], [[1, 1]]], [[[1, 2]], [[1]]]],
[[[[2]], [[1, 2]]], [[[2, 2]], [[1]]]],
[[[[2]], [[2, 2]]], [[[2, 2]], [[2]]]],
[[[[2]], [[1, 3]]], [[[2, 3]], [[1]]]],
[[[[2]], [[2, 3]]], [[[2, 2]], [[3]]]],
[[[[2]], [[3, 3]]], [[[2, 3]], [[3]]]],
[[[[3]], [[1, 1]]], [[[1, 3]], [[1]]]],
[[[[3]], [[1, 2]]], [[[1, 3]], [[2]]]],
[[[[3]], [[2, 2]]], [[[2, 3]], [[2]]]],
[[[[3]], [[1, 3]]], [[[3, 3]], [[1]]]],
[[[[3]], [[2, 3]]], [[[3, 3]], [[2]]]],
[[[[3]], [[3, 3]]], [[[3, 3]], [[3]]]]]
Calculates the Demazure character associated to the specified weight in the ambient weight lattice.
This is currently only supported for crystals whose underlying weight space is the ambient space.
References:
M. Demazure, “Desingularisation des varietes de Schubert”, Ann. E. N. S., Vol. 6, (1974), p. 163-172
Sarah Mason, “An Explicit Construction of Type A Demazure Atoms”, Journal of Algebraic Combinatorics, Vol. 29, (2009), No. 3, p.295-313 (arXiv:0707.4267)
EXAMPLES:
sage: T = CrystalOfTableaux(['A',2], shape = [2,1])
sage: e = T.weight_lattice_realization().basis()
sage: weight = e[0] + 2*e[2]
sage: weight.reduced_word()
[2, 1]
sage: T.demazure_character(weight)
x1^2*x2 + x1^2*x3 + x1*x2^2 + x1*x2*x3 + x1*x3^2
sage: T = CrystalOfTableaux(['A',3],shape=[2,1])
sage: T.demazure_character([1,2,3], reduced_word = True)
x1^2*x2 + x1^2*x3 + x1*x2^2 + x1*x2*x3 + x2^2*x3
sage: T = CrystalOfTableaux(['B',2], shape = [2])
sage: e = T.weight_lattice_realization().basis()
sage: weight = -2*e[1]
sage: T.demazure_character(weight)
x1^2 + x1*x2 + x2^2 + x1 + x2 + x1/x2 + 1/x2 + 1/x2^2 + 1
Returns the DiGraph associated to self.
EXAMPLES:
sage: from sage.combinat.crystals.crystals import Crystal
sage: C = CrystalOfLetters(['A', 5])
sage: Crystal.digraph(C)
Digraph on 6 vertices
Returns a dot_tex version of self.
EXAMPLES:
sage: C = CrystalOfLetters(['A',2])
sage: C.dot_tex()
'digraph G { \n node [ shape=plaintext ];\n N_0 [ label = " ", texlbl = "$1$" ];\n N_1 [ label = " ", texlbl = "$2$" ];\n N_2 [ label = " ", texlbl = "$3$" ];\n N_0 -> N_1 [ label = " ", texlbl = "1" ];\n N_1 -> N_2 [ label = " ", texlbl = "2" ];\n}'
Returns the index set of the Dynkin diagram underlying the given crystal
Returns the crystal graph as a bit of latex. This can be exported to a file with self.latex_file(‘filename’).
This requires the dot2tex spkg. Here some tips for installation:
In case LaTeX complains about tikzpicture not being defined, you may need to further run:
sage: sage.misc.latex.LATEX_HEADER+=r"\\usepackage{tikz}"
EXAMPLES:
sage: C = CrystalOfLetters(['A', 5])
sage: C.latex() #optional requires dot2tex
...
sage: view(C, pdflatex = True, tightpage = True) # optional
Exports a file, suitable for pdflatex, to ‘filename’. This requires a proper installation of dot2tex in sage-python. For more information see the documentation for self.latex().
EXAMPLES:
sage: C = CrystalOfLetters(['A', 5])
sage: C.latex_file('/tmp/test.tex') #optional requires dot2tex
Returns a list of the elements of self obtained by continually
apply the operators to the module generators of
self.
EXAMPLES:
sage: from sage.combinat.crystals.crystals import Crystal
sage: C = CrystalOfLetters(['A', 5])
sage: l = Crystal.list(C)
sage: l.sort(); l
[1, 2, 3, 4, 5, 6]
Use C.metapost(“filename.mp”,[options]) where options can be:
thicklines = True (for thicker edges) labels = False (to suppress labeling of the vertices) scaling_factor=value, where value is a floating point number, 1.0 by default. Increasing or decreasing the scaling factor changes the size of the image. tallness=1.0. Increasing makes the image taller without increasing the width.
Root operators e(1) or f(1) move along red lines, e(2) or f(2) along green. The highest weight is in the lower left. Vertices with the same weight are kept close together. The concise labels on the nodes are strings introduced by Berenstein and Zelevinsky and Littelmann; see Littelmann’s paper Cones, Crystals, Patterns, sections 5 and 6.
For Cartan types B2 or C2, the pattern has the form
a2 a3 a4 a1
where c*a2 = a3 = 2*a4 =0 and a1=0, with c=2 for B2, c=1 for C2. Applying e(2) a1 times, e(1) a2 times, e(2) a3 times, e(1) a4 times returns to the highest weight. (Observe that Littelmann writes the roots in opposite of the usual order, so our e(1) is his e(2) for these Cartan types.) For type A2, the pattern has the form
a3 a2 a1
where applying e(1) a1 times, e(2) a2 times then e(3) a1 times returns to the highest weight. These data determine the vertex and may be translated into a Gelfand-Tsetlin pattern or tableau.
EXAMPLES:
sage: C = CrystalOfLetters(['A', 2])
sage: C.metapost('/tmp/test.mp') #optional
sage: C = CrystalOfLetters(['A', 5])
sage: C.metapost('/tmp/test.mp')
Traceback (most recent call last):
...
NotImplementedError
Returns the plot of self as a directed graph.
EXAMPLES:
sage: C = CrystalOfLetters(['A', 5])
sage: show_default(False) #do not show the plot by default
sage: C.plot()
Graphics object consisting of 17 graphics primitives
Returns the weight lattice realization for the root system associated to self. This default implementation uses the ambient space of the root system.
EXAMPLES:
sage: C = CrystalOfLetters(['A', 5])
sage: C.weight_lattice_realization()
Ambient space of the Root system of type ['A', 5]
sage: K = KirillovReshetikhinCrystal(['A',2,1], 1, 1)
sage: K.weight_lattice_realization()
Weight lattice of the Root system of type ['A', 2, 1]
Bases: sage.structure.element.Element
The abstract class of crystal elements
Sub classes should implement at least:
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(0).Epsilon()
(0, 0, 0, 0, 0, 0)
sage: C(1).Epsilon()
(0, 0, 0, 0, 0, 0)
sage: C(2).Epsilon()
(1, 0, 0, 0, 0, 0)
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(0).Phi()
(0, 0, 0, 0, 0, 0)
sage: C(1).Phi()
(1, 0, 0, 0, 0, 0)
sage: C(2).Phi()
(1, 1, 0, 0, 0, 0)
Returns the cartan type associated to self
Yields all elements one can obtain from self by application of .
If the option “truncated” is set to True, then
is not included in the list.
References:
Peter Littelmann, “Crystal graphs and Young tableaux”, J. Algebra 175 (1995), no. 1, 65–87.
Masaki Kashiwara, “The crystal base and Littelmann’s refined Demazure character formula”, Duke Math. J. 71 (1993), no. 3, 839–858.
EXAMPLES:
sage: T = CrystalOfTableaux(['A',2], shape=[2,1])
sage: t=T(rows=[[1,2],[2]])
sage: t.demazure_operator(2)
[[[1, 2], [2]], [[1, 3], [2]], [[1, 3], [3]]]
sage: t.demazure_operator(2, truncated = True)
[[[1, 3], [2]], [[1, 3], [3]]]
sage: t.demazure_operator(1, truncated = True)
[]
sage: t.demazure_operator(1)
[[[1, 2], [2]]]
sage: K = KirillovReshetikhinCrystal(['A',2,1],2,1)
sage: t = K(rows=[[3],[2]])
sage: t.demazure_operator(0)
[[[2, 3]], [[1, 2]]]
Returns if it exists or None otherwise. This is
to be implemented by subclasses of CrystalElement.
TESTS:
sage: from sage.combinat.crystals.crystals import CrystalElement
sage: C = CrystalOfLetters(['A',5])
sage: CrystalElement.e(C(1), 1)
Traceback (most recent call last):
...
NotImplementedError
Applies to self for
EXAMPLES:
sage: C = CrystalOfLetters(['A',3])
sage: b = C(3)
sage: b.e_string([2,1])
1
sage: b.e_string([1,2])
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(1).epsilon(1)
0
sage: C(2).epsilon(1)
1
Returns if it exists or None otherwise. This is
to be implemented by subclasses of CrystalElement.
TESTS:
sage: from sage.combinat.crystals.crystals import CrystalElement
sage: C = CrystalOfLetters(['A',5])
sage: CrystalElement.f(C(1), 1)
Traceback (most recent call last):
...
NotImplementedError
Applies to self for
EXAMPLES:
sage: C = CrystalOfLetters(['A',3])
sage: b = C(1)
sage: b.f_string([1,2])
3
sage: b.f_string([2,1])
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(1).index_set()
[1, 2, 3, 4, 5]
Returns True if self is a highest weight.
Specifying the option index_set to be a subset of the index set
of the underlying crystal, finds all highest weight vectors for arrows in
.
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(1).is_highest_weight()
True
sage: C(2).is_highest_weight()
False
sage: C(2).is_highest_weight(index_set = [2,3,4,5])
True
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(1).phi(1)
1
sage: C(2).phi(1)
0
Returns of self. There are sometimes
better implementations using the weight for this. It is used
for reflections along a string.
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(1).phi_minus_epsilon(1)
1
Returns the reflection of self along its -string
EXAMPLES:
sage: C = CrystalOfTableaux(['A',2], shape=[2,1])
sage: b=C(rows=[[1,1],[3]])
sage: b.s(1)
[[2, 2], [3]]
sage: b=C(rows=[[1,2],[3]])
sage: b.s(2)
[[1, 2], [3]]
sage: T=CrystalOfTableaux(['A',2],shape=[4])
sage: t=T(rows=[[1,2,2,2]])
sage: t.s(1)
[[1, 1, 1, 2]]
Yields the highest weight element and list
such that
, where
are
elements in
. By default the index set is assumed to be
the full index set of self.
EXAMPLES:
sage: T = CrystalOfTableaux(['A',3], shape = [1])
sage: t = T(rows = [[3]])
sage: t.to_highest_weight()
[[[1]], [2, 1]]
sage: t.to_highest_weight()
[[[1]], [2, 1]]
sage: T = CrystalOfTableaux(['A',3], shape = [2,1])
sage: t = T(rows = [[1,2],[4]])
sage: t.to_highest_weight()
[[[1, 1], [2]], [1, 3, 2]]
sage: t.to_highest_weight(index_set = [3])
[[[1, 2], [3]], [3]]
EXAMPLES:
sage: C = CrystalOfLetters(['A',5])
sage: C(1).weight()
(1, 0, 0, 0, 0, 0)