Crystals - Category Framework

Skip to content
Back to top
View this page
Edit this page

# Crystals

class sage.categories.crystals.CrystalHomset(X, Y, category=None)

  Bases: `Homset`

  The set of crystal morphisms from one crystal to another.

  An \(U_q(\mathfrak{g})\) \(I\)-crystal morphism \(\Psi : B \to C\) is a map \(\Psi : B \cup \{ 0 \} \to C \cup \{ 0 \}\) such that:

  - \(\Psi(0) = 0\).

  - If \(b \in B\) and \(\Psi(b) \in C\), then \(\mathrm{wt}(\Psi(b)) = \mathrm{wt}(b)\), \(\varepsilon_i(\Psi(b)) = \varepsilon_i(b)\), and \(\varphi_i(\Psi(b)) = \varphi_i(b)\) for all \(i \in I\).

  - If \(b, b^{\prime} \in B\), \(\Psi(b), \Psi(b^{\prime}) \in C\) and \(f_i b = b^{\prime}\), then \(f_i \Psi(b) = \Psi(b^{\prime})\) and \(\Psi(b) = e_i \Psi(b^{\prime})\) for all \(i \in I\).

  If the Cartan type is unambiguous, it is suppressed from the notation.

  We can also generalize the definition of a crystal morphism by considering a map of \(\sigma\) of the (now possibly different) Dynkin diagrams corresponding to \(B\) and \(C\) along with scaling factors \(\gamma_i \in \ZZ\) for \(i \in I\). Let \(\sigma_i\) denote the orbit of \(i\) under \(\sigma\). We write objects for \(B\) as \(X\) with corresponding objects of \(C\) as \(\widehat{X}\). Then a virtual crystal morphism \(\Psi\) is a map such that the following holds:

  - \(\Psi(0) = 0\).

  - If \(b \in B\) and \(\Psi(b) \in C\), then for all \(j \in \sigma_i\):

  \[\varepsilon_i(b) = \frac{1}{\gamma_j} \widehat{\varepsilon}_j(\Psi(b)), \quad \varphi_i(b) = \frac{1}{\gamma_j} \widehat{\varphi}_j(\Psi(b)), \quad \mathrm{wt}(\Psi(b)) = \sum_i c_i \sum_{j \in \sigma_i} \gamma_j \widehat{\Lambda}_j,\]

  where \(\mathrm{wt}(b) = \sum_i c_i \Lambda_i\).

  - If \(b, b^{\prime} \in B\), \(\Psi(b), \Psi(b^{\prime}) \in C\) and \(f_i b = b^{\prime}\), then independent of the ordering of \(\sigma_i\) we have:

    \[\Psi(b^{\prime}) = e_i \Psi(b) = \prod_{j \in \sigma_i} \widehat{e}_j^{\gamma_i} \Psi(b), \quad \Psi(b^{\prime}) = f_i \Psi(b) = \prod_{j \in \sigma_i} \widehat{f}_j^{\gamma_i} \Psi(b).\]

  If \(\gamma_i = 1\) for all \(i \in I\) and the Dynkin diagrams are the same, then we call \(\Psi\) a twisted crystal morphism.

  INPUT:

  - `X` – the domain

  - `Y` – the codomain

  - `category` – (optional) the category of the crystal morphisms

  See also

  For the construction of an element of the homset, see `CrystalMorphismByGenerators` and `crystal_morphism()`.

  EXAMPLES:

  We begin with the natural embedding of \(B(2\Lambda_1)\) into \(B(\Lambda_1) \otimes B(\Lambda_1)\) in type \(A_1\):

  Sage

      sage: B = crystals.Tableaux(['A',1], shape=[2])
      sage: F = crystals.Tableaux(['A',1], shape=[1])
      sage: T = crystals.TensorProduct(F, F)
      sage: v = T.highest_weight_vectors()[0]; v
      [[[1]], [[1]]]
      sage: H = Hom(B, T)
      sage: psi = H([v])
      sage: b = B.highest_weight_vector(); b
      [[1, 1]]
      sage: psi(b)
      [[[1]], [[1]]]
      sage: b.f(1)
      [[1, 2]]
      sage: psi(b.f(1))
      [[[1]], [[2]]]

  Python

      >>> from sage.all import *
      >>> B = crystals.Tableaux(['A',Integer(1)], shape=[Integer(2)])
      >>> F = crystals.Tableaux(['A',Integer(1)], shape=[Integer(1)])
      >>> T = crystals.TensorProduct(F, F)
      >>> v = T.highest_weight_vectors()[Integer(0)]; v
      [[[1]], [[1]]]
      >>> H = Hom(B, T)
      >>> psi = H([v])
      >>> b = B.highest_weight_vector(); b
      [[1, 1]]
      >>> psi(b)
      [[[1]], [[1]]]
      >>> b.f(Integer(1))
      [[1, 2]]
      >>> psi(b.f(Integer(1)))
      [[[1]], [[2]]]

  We now look at the decomposition of \(B(\Lambda_1) \otimes B(\Lambda_1)\) into \(B(2\Lambda_1) \oplus B(0)\):

  Sage

      sage: B0 = crystals.Tableaux(['A',1], shape=[])
      sage: D = crystals.DirectSum([B, B0])
      sage: H = Hom(T, D)
      sage: psi = H(D.module_generators)
      sage: psi
      ['A', 1] Crystal morphism:
        From: Full tensor product of the crystals
         [The crystal of tableaux of type ['A', 1] and shape(s) [[1]],
          The crystal of tableaux of type ['A', 1] and shape(s) [[1]]]
        To:   Direct sum of the crystals Family
         (The crystal of tableaux of type ['A', 1] and shape(s) [[2]],
          The crystal of tableaux of type ['A', 1] and shape(s) [[]])
        Defn: [[[1]], [[1]]] |--> [[1, 1]]
              [[[2]], [[1]]] |--> []
      sage: psi.is_isomorphism()
      True

  [Python]

      >>> from sage.all import *
      >>> B0 = crystals.Tableaux(['A',Integer(1)], shape=[])
      >>> D = crystals.DirectSum([B, B0])
      >>> H = Hom(T, D)
      >>> psi = H(D.module_generators)
      >>> psi
      ['A', 1] Crystal morphism:
        From: Full tensor product of the crystals
         [The crystal of tableaux of type ['A', 1] and shape(s) [[1]],
          The crystal of tableaux of type ['A', 1] and shape(s) [[1]]]
        To:   Direct sum of the crystals Family
         (The crystal of tableaux of type ['A', 1] and shape(s) [[2]],
          The crystal of tableaux of type ['A', 1] and shape(s) [[]])
        Defn: [[[1]], [[1]]] |--> [[1, 1]]
              [[[2]], [[1]]] |--> []
      >>> psi.is_isomorphism()
      True

  We can always construct the trivial morphism which sends everything to \(0\):

  Sage

      sage: Binf = crystals.infinity.Tableaux(['B', 2])
      sage: B = crystals.Tableaux(['B',2], shape=[1])
      sage: H = Hom(Binf, B)
      sage: psi = H(lambda x: None)
      sage: psi(Binf.highest_weight_vector())

  Python

      >>> from sage.all import *
      >>> Binf = crystals.infinity.Tableaux(['B', Integer(2)])
      >>> B = crystals.Tableaux(['B',Integer(2)], shape=[Integer(1)])
      >>> H = Hom(Binf, B)
      >>> psi = H(lambda x: None)
      >>> psi(Binf.highest_weight_vector())

  For Kirillov-Reshetikhin crystals, we consider the map to the corresponding classical crystal:

  Sage

      sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,1)
      sage: B = K.classical_decomposition()
      sage: H = Hom(K, B)
      sage: psi = H(lambda x: x.lift(), cartan_type=['D',4])
      sage: L = [psi(mg) for mg in K.module_generators]; L
      [[], [[1], [2]]]
      sage: all(x.parent() == B for x in L)
      True

  [Python]

      >>> from sage.all import *
      >>> K = crystals.KirillovReshetikhin(['D',Integer(4),Integer(1)], Integer(2),Integer(1))
      >>> B = K.classical_decomposition()
      >>> H = Hom(K, B)
      >>> psi = H(lambda x: x.lift(), cartan_type=['D',Integer(4)])
      >>> L = [psi(mg) for mg in K.module_generators]; L
      [[], [[1], [2]]]
      >>> all(x.parent() == B for x in L)
      True

  Next we consider a type \(D_4\) crystal morphism where we twist by \(3 \leftrightarrow 4\):

  Sage

      sage: B = crystals.Tableaux(['D',4], shape=[1])
      sage: H = Hom(B, B)
      sage: d = {1:1, 2:2, 3:4, 4:3}
      sage: psi = H(B.module_generators, automorphism=d)
      sage: b = B.highest_weight_vector()
      sage: b.f_string([1,2,3])
      [[4]]
      sage: b.f_string([1,2,4])
      [[-4]]
      sage: psi(b.f_string([1,2,3]))
      [[-4]]
      sage: psi(b.f_string([1,2,4]))
      [[4]]

  Python

      >>> from sage.all import *
      >>> B = crystals.Tableaux(['D',Integer(4)], shape=[Integer(1)])
      >>> H = Hom(B, B)
      >>> d = {Integer(1):Integer(1), Integer(2):Integer(2), Integer(3):Integer(4), Integer(4):Integer(3)}
      >>> psi = H(B.module_generators, automorphism=d)
      >>> b = B.highest_weight_vector()
      >>> b.f_string([Integer(1),Integer(2),Integer(3)])
      [[4]]
      >>> b.f_string([Integer(1),Integer(2),Integer(4)])
      [[-4]]
      >>> psi(b.f_string([Integer(1),Integer(2),Integer(3)]))
      [[-4]]
      >>> psi(b.f_string([Integer(1),Integer(2),Integer(4)]))
      [[4]]

  We construct the natural virtual embedding of a type \(B_3\) into a type \(D_4\) crystal:

  Sage

      sage: B = crystals.Tableaux(['B',3], shape=[1])
      sage: C = crystals.Tableaux(['D',4], shape=[2])
      sage: H = Hom(B, C)
      sage: psi = H(C.module_generators)
      sage: psi
      ['B', 3] -> ['D', 4] Virtual Crystal morphism:
        From: The crystal of tableaux of type ['B', 3] and shape(s) [[1]]
        To:   The crystal of tableaux of type ['D', 4] and shape(s) [[2]]
        Defn: [[1]] |--> [[1, 1]]
      sage: for b in B: print("{} |--> {}".format(b, psi(b)))
      [[1]] |--> [[1, 1]]
      [[2]] |--> [[2, 2]]
      [[3]] |--> [[3, 3]]
      [[0]] |--> [[3, -3]]
      [[-3]] |--> [[-3, -3]]
      [[-2]] |--> [[-2, -2]]
      [[-1]] |--> [[-1, -1]]

  [Python]

      >>> from sage.all import *
      >>> B = crystals.Tableaux(['B',Integer(3)], shape=[Integer(1)])
      >>> C = crystals.Tableaux(['D',Integer(4)], shape=[Integer(2)])
      >>> H = Hom(B, C)
      >>> psi = H(C.module_generators)
      >>> psi
      ['B', 3] -> ['D', 4] Virtual Crystal morphism:
        From: The crystal of tableaux of type ['B', 3] and shape(s) [[1]]
        To:   The crystal of tableaux of type ['D', 4] and shape(s) [[2]]
        Defn: [[1]] |--> [[1, 1]]
      >>> for b in B: print("{} |--> {}".format(b, psi(b)))
      [[1]] |--> [[1, 1]]
      [[2]] |--> [[2, 2]]
      [[3]] |--> [[3, 3]]
      [[0]] |--> [[3, -3]]
      [[-3]] |--> [[-3, -3]]
      [[-2]] |--> [[-2, -2]]
      [[-1]] |--> [[-1, -1]]

  Element

    alias of `CrystalMorphismByGenerators`

class sage.categories.crystals.CrystalMorphism(parent, cartan_type=None, virtualization=None, scaling_factors=None)

  Bases: `Morphism`

  A crystal morphism.

  INPUT:

  - `parent` – a homset

  - `cartan_type` – (optional) a Cartan type; the default is the Cartan type of the domain

  - `virtualization` – (optional) a dictionary whose keys are in the index set of the domain and whose values are lists of entries in the index set of the codomain

  - `scaling_factors` – (optional) a dictionary whose keys are in the index set of the domain and whose values are scaling factors for the weight, \(\varepsilon\) and \(\varphi\)

  cartan_type()

    Return the Cartan type of `self`.

    EXAMPLES:

    Sage

        sage: B = crystals.Tableaux(['A',2], shape=[2,1])
        sage: psi = Hom(B, B).an_element()
        sage: psi.cartan_type()
        ['A', 2]

    Python

        >>> from sage.all import *
        >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
        >>> psi = Hom(B, B).an_element()
        >>> psi.cartan_type()
        ['A', 2]

  is_injective()

    Return if `self` is an injective crystal morphism.

    EXAMPLES:

    Sage

        sage: B = crystals.Tableaux(['A',2], shape=[2,1])
        sage: psi = Hom(B, B).an_element()
        sage: psi.is_injective()
        False

    Python

        >>> from sage.all import *
        >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
        >>> psi = Hom(B, B).an_element()
        >>> psi.is_injective()
        False

  is_surjective()

    Check if `self` is a surjective crystal morphism.

    EXAMPLES:

    Sage

        sage: B = crystals.Tableaux(['C',2], shape=[1,1])
        sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
        sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
        sage: psi.is_surjective()
        False
        sage: im_gens = [None, B.module_generators[0]]
        sage: psi = C.crystal_morphism(im_gens, codomain=B)
        sage: psi.is_surjective()
        True

        sage: C = crystals.Tableaux(['A',2], shape=[2,1])
        sage: B = crystals.infinity.Tableaux(['A',2])
        sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
        sage: W = crystals.elementary.T(['A',2], La[1]+La[2])
        sage: T = W.tensor(B)
        sage: mg = T(W.module_generators[0], B.module_generators[0])
        sage: psi = Hom(C,T)([mg])
        sage: psi.is_surjective()
        False

    Python

        >>> from sage.all import *
        >>> B = crystals.Tableaux(['C',Integer(2)], shape=[Integer(1),Integer(1)])
        >>> C = crystals.Tableaux(['C',Integer(2)], ([Integer(2),Integer(1)], [Integer(1),Integer(1)]))
        >>> psi = B.crystal_morphism(C.module_generators[Integer(1):], codomain=C)
        >>> psi.is_surjective()
        False
        >>> im_gens = [None, B.module_generators[Integer(0)]]
        >>> psi = C.crystal_morphism(im_gens, codomain=B)
        >>> psi.is_surjective()
        True

        >>> C = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
        >>> B = crystals.infinity.Tableaux(['A',Integer(2)])
        >>> La = RootSystem(['A',Integer(2)]).weight_lattice().fundamental_weights()
        >>> W = crystals.elementary.T(['A',Integer(2)], La[Integer(1)]+La[Integer(2)])
        >>> T = W.tensor(B)
        >>> mg = T(W.module_generators[Integer(0)], B.module_generators[Integer(0)])
        >>> psi = Hom(C,T)([mg])
        >>> psi.is_surjective()
        False

  scaling_factors()

    Return the scaling factors \(\gamma_i\).

    EXAMPLES:

    Sage

        sage: B = crystals.Tableaux(['B',3], shape=[1])
        sage: C = crystals.Tableaux(['D',4], shape=[2])
        sage: psi = B.crystal_morphism(C.module_generators)
        sage: psi.scaling_factors()
        Finite family {1: 2, 2: 2, 3: 1}

    Python

        >>> from sage.all import *
        >>> B = crystals.Tableaux(['B',Integer(3)], shape=[Integer(1)])
        >>> C = crystals.Tableaux(['D',Integer(4)], shape=[Integer(2)])
        >>> psi = B.crystal_morphism(C.module_generators)
        >>> psi.scaling_factors()
        Finite family {1: 2, 2: 2, 3: 1}

  virtualization()

    Return the virtualization sets \(\sigma_i\).

    EXAMPLES:

    Sage

        sage: B = crystals.Tableaux(['B',3], shape=[1])
        sage: C = crystals.Tableaux(['D',4], shape=[2])
        sage: psi = B.crystal_morphism(C.module_generators)
        sage: psi.virtualization()
        Finite family {1: (1,), 2: (2,), 3: (3, 4)}

    Python

        >>> from sage.all import *
        >>> B = crystals.Tableaux(['B',Integer(3)], shape=[Integer(1)])
        >>> C = crystals.Tableaux(['D',Integer(4)], shape=[Integer(2)])
        >>> psi = B.crystal_morphism(C.module_generators)
        >>> psi.virtualization()
        Finite family {1: (1,), 2: (2,), 3: (3, 4)}

class sage.categories.crystals.CrystalMorphismByGenerators(parent, on_gens, cartan_type=None, virtualization=None, scaling_factors=None, gens=None, check=True)

  Bases: `CrystalMorphism`

  A crystal morphism defined by a set of generators which create a virtual crystal inside the codomain.

  INPUT:

  - `parent` – a homset

  - `on_gens` – a function or list that determines the image of the generators (if given a list, then this uses the order of the generators of the domain) of the domain under `self`

  - `cartan_type` – (optional) a Cartan type; the default is the Cartan type of the domain

  - `virtualization` – (optional) a dictionary whose keys are in the index set of the domain and whose values are lists of entries in the index set of the codomain

  - `scaling_factors` – (optional) a dictionary whose keys are in the index set of the domain and whose values are scaling factors for the weight, \(\varepsilon\) and \(\varphi\)

  - `gens` – (optional) a finite list of generators to define the morphism; the default is to use the highest weight vectors of the crystal

  - `check` – boolean (default: `True`); check if the crystal morphism is valid

  See also

  `sage.categories.crystals.Crystals.ParentMethods.crystal_morphism()`

  im_gens()

    Return the image of the generators of `self` as a tuple.

    EXAMPLES:

    Sage

        sage: B = crystals.Tableaux(['A',2], shape=[2,1])
        sage: F = crystals.Tableaux(['A',2], shape=[1])
        sage: T = crystals.TensorProduct(F, F, F)
        sage: H = Hom(T, B)
        sage: b = B.highest_weight_vector()
        sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors())
        sage: psi.im_gens()
        (None, [[1, 1], [2]], [[1, 1], [2]], None)

    Python

        >>> from sage.all import *
        >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
        >>> F = crystals.Tableaux(['A',Integer(2)], shape=[Integer(1)])
        >>> T = crystals.TensorProduct(F, F, F)
        >>> H = Hom(T, B)
        >>> b = B.highest_weight_vector()
        >>> psi = H((None, b, b, None), generators=T.highest_weight_vectors())
        >>> psi.im_gens()
        (None, [[1, 1], [2]], [[1, 1], [2]], None)

  image()

    Return the image of `self` in the codomain as a `Subcrystal`.

    Warning

    This assumes that `self` is a strict crystal morphism.

    EXAMPLES:

    Sage

        sage: B = crystals.Tableaux(['B',3], shape=[1])
        sage: C = crystals.Tableaux(['D',4], shape=[2])
        sage: H = Hom(B, C)
        sage: psi = H(C.module_generators)
        sage: psi.image()
        Virtual crystal of The crystal of tableaux of type ['D', 4] and shape(s) [[2]] of type ['B', 3]

    Python

        >>> from sage.all import *
        >>> B = crystals.Tableaux(['B',Integer(3)], shape=[Integer(1)])
        >>> C = crystals.Tableaux(['D',Integer(4)], shape=[Integer(2)])
        >>> H = Hom(B, C)
        >>> psi = H(C.module_generators)
        >>> psi.image()
        Virtual crystal of The crystal of tableaux of type ['D', 4] and shape(s) [[2]] of type ['B', 3]

  to_module_generator(x)

    Return a generator `mg` and a path of \(e_i\) and \(f_i\) operations to `mg`.

    OUTPUT: a tuple consisting of:

    - a module generator,

    - a list of `'e'` and `'f'` to denote which operation, and

    - a list of matching indices.

    EXAMPLES:

    Sage

        sage: B = crystals.elementary.Elementary(['A',2], 2)
        sage: psi = B.crystal_morphism(B.module_generators)
        sage: psi.to_module_generator(B(4))
        (0, ['f', 'f', 'f', 'f'], [2, 2, 2, 2])
        sage: psi.to_module_generator(B(-2))
        (0, ['e', 'e'], [2, 2])

    Python

        >>> from sage.all import *
        >>> B = crystals.elementary.Elementary(['A',Integer(2)], Integer(2))
        >>> psi = B.crystal_morphism(B.module_generators)
        >>> psi.to_module_generator(B(Integer(4)))
        (0, ['f', 'f', 'f', 'f'], [2, 2, 2, 2])
        >>> psi.to_module_generator(B(-Integer(2)))
        (0, ['e', 'e'], [2, 2])

class sage.categories.crystals.Crystals

  Bases: `Category_singleton`

  The category of crystals.

  See `sage.combinat.crystals.crystals` for an introduction to crystals.

  EXAMPLES:

  Sage

      sage: C = Crystals()
      sage: C
      Category of crystals
      sage: C.super_categories()
      [Category of... enumerated sets]
      sage: C.example()
      Highest weight crystal of type A_3 of highest weight omega_1

  Python

      >>> from sage.all import *
      >>> C = Crystals()
      >>> C
      Category of crystals
      >>> C.super_categories()
      [Category of... enumerated sets]
      >>> C.example()
      Highest weight crystal of type A_3 of highest weight omega_1

  Parents in this category should implement the following methods:

  - either an attribute `_cartan_type` or a method `cartan_type`

  - `module_generators`: a list (or container) of distinct elements which generate the crystal using \(f_i\)

  Furthermore, their elements `x` should implement the following methods:

  - `x.e(i)` (returning \(e_i(x)\))

  - `x.f(i)` (returning \(f_i(x)\))

  - `x.epsilon(i)` (returning \(\varepsilon_i(x)\))

  - `x.phi(i)` (returning \(\varphi_i(x)\))

  EXAMPLES:

  Sage

      sage: from sage.misc.abstract_method import abstract_methods_of_class
      sage: abstract_methods_of_class(Crystals().element_class)
      {'optional': [], 'required': ['e', 'epsilon', 'f', 'phi', 'weight']}

  [Python]

      >>> from sage.all import *
      >>> from sage.misc.abstract_method import abstract_methods_of_class
      >>> abstract_methods_of_class(Crystals().element_class)
      {'optional': [], 'required': ['e', 'epsilon', 'f', 'phi', 'weight']}

  class ElementMethods

    Bases: `object`

    Epsilon()

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['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)

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(0)).Epsilon()
          (0, 0, 0, 0, 0, 0)
          >>> C(Integer(1)).Epsilon()
          (0, 0, 0, 0, 0, 0)
          >>> C(Integer(2)).Epsilon()
          (1, 0, 0, 0, 0, 0)

    Phi()

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['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)

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(0)).Phi()
          (0, 0, 0, 0, 0, 0)
          >>> C(Integer(1)).Phi()
          (1, 0, 0, 0, 0, 0)
          >>> C(Integer(2)).Phi()
          (1, 1, 0, 0, 0, 0)

    all_paths_to_highest_weight(index_set=None)

      Iterate over all paths to the highest weight from `self` with respect to `index_set`.

      INPUT:

      - `index_set` – (optional) a subset of the index set of `self`

      EXAMPLES:

      Sage

          sage: B = crystals.infinity.Tableaux("A2")
          sage: b0 = B.highest_weight_vector()
          sage: b = b0.f_string([1, 2, 1, 2])
          sage: L = b.all_paths_to_highest_weight()
          sage: list(L)
          [[2, 1, 2, 1], [2, 2, 1, 1]]

          sage: Y = crystals.infinity.GeneralizedYoungWalls(3)
          sage: y0 = Y.highest_weight_vector()
          sage: y = y0.f_string([0, 1, 2, 3, 2, 1, 0])
          sage: list(y.all_paths_to_highest_weight())
          [[0, 1, 2, 3, 2, 1, 0],
           [0, 1, 3, 2, 2, 1, 0],
           [0, 3, 1, 2, 2, 1, 0],
           [0, 3, 2, 1, 1, 0, 2],
           [0, 3, 2, 1, 1, 2, 0]]

          sage: B = crystals.Tableaux("A3", shape=[4,2,1])
          sage: b0 = B.highest_weight_vector()
          sage: b = b0.f_string([1, 1, 2, 3])
          sage: list(b.all_paths_to_highest_weight())
          [[1, 3, 2, 1], [3, 1, 2, 1], [3, 2, 1, 1]]

      Python

          >>> from sage.all import *
          >>> B = crystals.infinity.Tableaux("A2")
          >>> b0 = B.highest_weight_vector()
          >>> b = b0.f_string([Integer(1), Integer(2), Integer(1), Integer(2)])
          >>> L = b.all_paths_to_highest_weight()
          >>> list(L)
          [[2, 1, 2, 1], [2, 2, 1, 1]]

          >>> Y = crystals.infinity.GeneralizedYoungWalls(Integer(3))
          >>> y0 = Y.highest_weight_vector()
          >>> y = y0.f_string([Integer(0), Integer(1), Integer(2), Integer(3), Integer(2), Integer(1), Integer(0)])
          >>> list(y.all_paths_to_highest_weight())
          [[0, 1, 2, 3, 2, 1, 0],
           [0, 1, 3, 2, 2, 1, 0],
           [0, 3, 1, 2, 2, 1, 0],
           [0, 3, 2, 1, 1, 0, 2],
           [0, 3, 2, 1, 1, 2, 0]]

          >>> B = crystals.Tableaux("A3", shape=[Integer(4),Integer(2),Integer(1)])
          >>> b0 = B.highest_weight_vector()
          >>> b = b0.f_string([Integer(1), Integer(1), Integer(2), Integer(3)])
          >>> list(b.all_paths_to_highest_weight())
          [[1, 3, 2, 1], [3, 1, 2, 1], [3, 2, 1, 1]]

    cartan_type()

      Return the Cartan type associated to `self`.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 5])
          sage: C(1).cartan_type()
          ['A', 5]

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(5)])
          >>> C(Integer(1)).cartan_type()
          ['A', 5]

    e(i)

      Return \(e_i\) of `self` if it exists or `None` otherwise.

      This method should be implemented by the element class of the crystal.

      EXAMPLES:

      Sage

          sage: C = Crystals().example(5)
          sage: x = C[2]; x
          3
          sage: x.e(1), x.e(2), x.e(3)
          (None, 2, None)

      Python

          >>> from sage.all import *
          >>> C = Crystals().example(Integer(5))
          >>> x = C[Integer(2)]; x
          3
          >>> x.e(Integer(1)), x.e(Integer(2)), x.e(Integer(3))
          (None, 2, None)

    e_string(list)

      Applies \(e_{i_r} \cdots e_{i_1}\) to `self` for `list` as \([i_1, ..., i_r]\)

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',3])
          sage: b = C(3)
          sage: b.e_string([2,1])
          1
          sage: b.e_string([1,2])

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(3)])
          >>> b = C(Integer(3))
          >>> b.e_string([Integer(2),Integer(1)])
          1
          >>> b.e_string([Integer(1),Integer(2)])

    epsilon(i)

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',5])
          sage: C(1).epsilon(1)
          0
          sage: C(2).epsilon(1)
          1

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(1)).epsilon(Integer(1))
          0
          >>> C(Integer(2)).epsilon(Integer(1))
          1

    f(i)

      Return \(f_i\) of `self` if it exists or `None` otherwise.

      This method should be implemented by the element class of the crystal.

      EXAMPLES:

      Sage

          sage: C = Crystals().example(5)
          sage: x = C[1]; x
          2
          sage: x.f(1), x.f(2), x.f(3)
          (None, 3, None)

      Python

          >>> from sage.all import *
          >>> C = Crystals().example(Integer(5))
          >>> x = C[Integer(1)]; x
          2
          >>> x.f(Integer(1)), x.f(Integer(2)), x.f(Integer(3))
          (None, 3, None)

    f_string(list)

      Applies \(f_{i_r} \cdots f_{i_1}\) to `self` for `list` as \([i_1, ..., i_r]\)

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',3])
          sage: b = C(1)
          sage: b.f_string([1,2])
          3
          sage: b.f_string([2,1])

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(3)])
          >>> b = C(Integer(1))
          >>> b.f_string([Integer(1),Integer(2)])
          3
          >>> b.f_string([Integer(2),Integer(1)])

    index_set()

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',5])
          sage: C(1).index_set()
          (1, 2, 3, 4, 5)

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(1)).index_set()
          (1, 2, 3, 4, 5)

    is_highest_weight(index_set=None)

      Return `True` if `self` is a highest weight.

      Specifying the option `index_set` to be a subset \(I\) of the index set of the underlying crystal, finds all highest weight vectors for arrows in \(I\).

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['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

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(1)).is_highest_weight()
          True
          >>> C(Integer(2)).is_highest_weight()
          False
          >>> C(Integer(2)).is_highest_weight(index_set = [Integer(2),Integer(3),Integer(4),Integer(5)])
          True

    is_lowest_weight(index_set=None)

      Return `True` if `self` is a lowest weight.

      Specifying the option `index_set` to be a subset \(I\) of the index set of the underlying crystal, finds all lowest weight vectors for arrows in \(I\).

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',5])
          sage: C(1).is_lowest_weight()
          False
          sage: C(6).is_lowest_weight()
          True
          sage: C(4).is_lowest_weight(index_set = [1,3])
          True

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(1)).is_lowest_weight()
          False
          >>> C(Integer(6)).is_lowest_weight()
          True
          >>> C(Integer(4)).is_lowest_weight(index_set = [Integer(1),Integer(3)])
          True

    phi(i)

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',5])
          sage: C(1).phi(1)
          1
          sage: C(2).phi(1)
          0

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(1)).phi(Integer(1))
          1
          >>> C(Integer(2)).phi(Integer(1))
          0

    phi_minus_epsilon(i)

      Return \(\varphi_i - \varepsilon_i\) of `self`.

      There are sometimes better implementations using the weight for this. It is used for reflections along a string.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',5])
          sage: C(1).phi_minus_epsilon(1)
          1

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(1)).phi_minus_epsilon(Integer(1))
          1

    s(i)

      Return the reflection of `self` along its \(i\)-string.

      EXAMPLES:

      Sage

          sage: C = crystals.Tableaux(['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 = crystals.Tableaux(['A',2],shape=[4])
          sage: t = T(rows=[[1,2,2,2]])
          sage: t.s(1)
          [[1, 1, 1, 2]]

      Python

          >>> from sage.all import *
          >>> C = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> b = C(rows=[[Integer(1),Integer(1)],[Integer(3)]])
          >>> b.s(Integer(1))
          [[2, 2], [3]]
          >>> b = C(rows=[[Integer(1),Integer(2)],[Integer(3)]])
          >>> b.s(Integer(2))
          [[1, 2], [3]]
          >>> T = crystals.Tableaux(['A',Integer(2)],shape=[Integer(4)])
          >>> t = T(rows=[[Integer(1),Integer(2),Integer(2),Integer(2)]])
          >>> t.s(Integer(1))
          [[1, 1, 1, 2]]

    subcrystal(index_set=None, max_depth=inf, direction='both', contained=None, cartan_type=None, category=None)

      Construct the subcrystal generated by `self` using \(e_i\) and/or \(f_i\) for all \(i\) in `index_set`.

      INPUT:

      - `index_set` – (default: `None`) the index set; if `None` then use the index set of the crystal

      - `max_depth` – (default: infinity) the maximum depth to build

      - `direction` – (default: `'both'`) the direction to build the subcrystal; it can be one of the following:

        - `'both'` – using both \(e_i\) and \(f_i\)

        - `'upper'` – using \(e_i\)

        - `'lower'` – using \(f_i\)

      - `contained` – (optional) a set (or function) defining the containment in the subcrystal

      - `cartan_type` – (optional) specify the Cartan type of the subcrystal

      - `category` – (optional) specify the category of the subcrystal

      See also

      - `Crystals.ParentMethods.subcrystal()`

      EXAMPLES:

      Sage

          sage: C = crystals.KirillovReshetikhin(['A',3,1], 1, 2)
          sage: elt = C(1,4)
          sage: list(elt.subcrystal(index_set=[1,3]))
          [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
          sage: list(elt.subcrystal(index_set=[1,3], max_depth=1))
          [[[1, 4]], [[2, 4]], [[1, 3]]]
          sage: list(elt.subcrystal(index_set=[1,3], direction='upper'))
          [[[1, 4]], [[1, 3]]]
          sage: list(elt.subcrystal(index_set=[1,3], direction='lower'))
          [[[1, 4]], [[2, 4]]]

      Python

          >>> from sage.all import *
          >>> C = crystals.KirillovReshetikhin(['A',Integer(3),Integer(1)], Integer(1), Integer(2))
          >>> elt = C(Integer(1),Integer(4))
          >>> list(elt.subcrystal(index_set=[Integer(1),Integer(3)]))
          [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
          >>> list(elt.subcrystal(index_set=[Integer(1),Integer(3)], max_depth=Integer(1)))
          [[[1, 4]], [[2, 4]], [[1, 3]]]
          >>> list(elt.subcrystal(index_set=[Integer(1),Integer(3)], direction='upper'))
          [[[1, 4]], [[1, 3]]]
          >>> list(elt.subcrystal(index_set=[Integer(1),Integer(3)], direction='lower'))
          [[[1, 4]], [[2, 4]]]

    tensor(*elts)

      Return the tensor product of `self` with the crystal elements `elts`.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 3])
          sage: B = crystals.infinity.Tableaux(['A', 3])
          sage: c = C[0]
          sage: b = B.highest_weight_vector()
          sage: t = c.tensor(c, b)
          sage: ascii_art(t)
                    1  1  1
          1 # 1 #   2  2
                    3
          sage: tensor([c, c, b]) == t
          True
          sage: ascii_art(tensor([b, b, c]))
            1  1  1     1  1  1
            2  2    #   2  2    # 1
            3           3

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(3)])
          >>> B = crystals.infinity.Tableaux(['A', Integer(3)])
          >>> c = C[Integer(0)]
          >>> b = B.highest_weight_vector()
          >>> t = c.tensor(c, b)
          >>> ascii_art(t)
                    1  1  1
          1 # 1 #   2  2
                    3
          >>> tensor([c, c, b]) == t
          True
          >>> ascii_art(tensor([b, b, c]))
            1  1  1     1  1  1
            2  2    #   2  2    # 1
            3           3

    to_highest_weight(index_set=None)

      Return the highest weight element \(u\) and a list \([i_1,...,i_k]\) such that `self` \(= f_{i_1} ... f_{i_k} u\), where \(i_1,...,i_k\) are elements in `index_set`.

      By default the `index_set` is assumed to be the full index set of `self`.

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',3], shape = [1])
          sage: t = T(rows = [[3]])
          sage: t.to_highest_weight()
          [[[1]], [2, 1]]
          sage: T = crystals.Tableaux(['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]]
          sage: K = crystals.KirillovReshetikhin(['A',3,1],2,1)
          sage: t = K(rows=[[2],[3]]); t.to_highest_weight(index_set=[1])
          [[[1], [3]], [1]]
          sage: t.to_highest_weight()
          Traceback (most recent call last):
          ...
          ValueError: this is not a highest weight crystal

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(3)], shape = [Integer(1)])
          >>> t = T(rows = [[Integer(3)]])
          >>> t.to_highest_weight()
          [[[1]], [2, 1]]
          >>> T = crystals.Tableaux(['A',Integer(3)], shape = [Integer(2),Integer(1)])
          >>> t = T(rows = [[Integer(1),Integer(2)],[Integer(4)]])
          >>> t.to_highest_weight()
          [[[1, 1], [2]], [1, 3, 2]]
          >>> t.to_highest_weight(index_set = [Integer(3)])
          [[[1, 2], [3]], [3]]
          >>> K = crystals.KirillovReshetikhin(['A',Integer(3),Integer(1)],Integer(2),Integer(1))
          >>> t = K(rows=[[Integer(2)],[Integer(3)]]); t.to_highest_weight(index_set=[Integer(1)])
          [[[1], [3]], [1]]
          >>> t.to_highest_weight()
          Traceback (most recent call last):
          ...
          ValueError: this is not a highest weight crystal

    to_lowest_weight(index_set=None)

      Return the lowest weight element \(u\) and a list \([i_1,...,i_k]\) such that `self` \(= e_{i_1} ... e_{i_k} u\), where \(i_1,...,i_k\) are elements in `index_set`.

      By default the `index_set` is assumed to be the full index set of `self`.

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',3], shape = [1])
          sage: t = T(rows = [[3]])
          sage: t.to_lowest_weight()
          [[[4]], [3]]
          sage: T = crystals.Tableaux(['A',3], shape = [2,1])
          sage: t = T(rows = [[1,2],[4]])
          sage: t.to_lowest_weight()
          [[[3, 4], [4]], [1, 2, 2, 3]]
          sage: t.to_lowest_weight(index_set = [3])
          [[[1, 2], [4]], []]
          sage: K = crystals.KirillovReshetikhin(['A',3,1],2,1)
          sage: t = K.module_generator(); t
          [[1], [2]]
          sage: t.to_lowest_weight(index_set=[1,2,3])
          [[[3], [4]], [2, 1, 3, 2]]
          sage: t.to_lowest_weight()
          Traceback (most recent call last):
          ...
          ValueError: this is not a highest weight crystal

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(3)], shape = [Integer(1)])
          >>> t = T(rows = [[Integer(3)]])
          >>> t.to_lowest_weight()
          [[[4]], [3]]
          >>> T = crystals.Tableaux(['A',Integer(3)], shape = [Integer(2),Integer(1)])
          >>> t = T(rows = [[Integer(1),Integer(2)],[Integer(4)]])
          >>> t.to_lowest_weight()
          [[[3, 4], [4]], [1, 2, 2, 3]]
          >>> t.to_lowest_weight(index_set = [Integer(3)])
          [[[1, 2], [4]], []]
          >>> K = crystals.KirillovReshetikhin(['A',Integer(3),Integer(1)],Integer(2),Integer(1))
          >>> t = K.module_generator(); t
          [[1], [2]]
          >>> t.to_lowest_weight(index_set=[Integer(1),Integer(2),Integer(3)])
          [[[3], [4]], [2, 1, 3, 2]]
          >>> t.to_lowest_weight()
          Traceback (most recent call last):
          ...
          ValueError: this is not a highest weight crystal

    weight()

      Return the weight of this crystal element.

      This method should be implemented by the element class of the crystal.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',5])
          sage: C(1).weight()
          (1, 0, 0, 0, 0, 0)

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(5)])
          >>> C(Integer(1)).weight()
          (1, 0, 0, 0, 0, 0)

  Finite

    alias of `FiniteCrystals`

  class MorphismMethods

    Bases: `object`

    is_embedding()

      Check if `self` is an injective crystal morphism.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['C',2], shape=[1,1])
          sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
          sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
          sage: psi.is_embedding()
          True

          sage: C = crystals.Tableaux(['A',2], shape=[2,1])
          sage: B = crystals.infinity.Tableaux(['A',2])
          sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
          sage: W = crystals.elementary.T(['A',2], La[1]+La[2])
          sage: T = W.tensor(B)
          sage: mg = T(W.module_generators[0], B.module_generators[0])
          sage: psi = Hom(C,T)([mg])
          sage: psi.is_embedding()
          True

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['C',Integer(2)], shape=[Integer(1),Integer(1)])
          >>> C = crystals.Tableaux(['C',Integer(2)], ([Integer(2),Integer(1)], [Integer(1),Integer(1)]))
          >>> psi = B.crystal_morphism(C.module_generators[Integer(1):], codomain=C)
          >>> psi.is_embedding()
          True

          >>> C = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> B = crystals.infinity.Tableaux(['A',Integer(2)])
          >>> La = RootSystem(['A',Integer(2)]).weight_lattice().fundamental_weights()
          >>> W = crystals.elementary.T(['A',Integer(2)], La[Integer(1)]+La[Integer(2)])
          >>> T = W.tensor(B)
          >>> mg = T(W.module_generators[Integer(0)], B.module_generators[Integer(0)])
          >>> psi = Hom(C,T)([mg])
          >>> psi.is_embedding()
          True

    is_isomorphism()

      Check if `self` is a crystal isomorphism.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['C',2], shape=[1,1])
          sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
          sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
          sage: psi.is_isomorphism()
          False

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['C',Integer(2)], shape=[Integer(1),Integer(1)])
          >>> C = crystals.Tableaux(['C',Integer(2)], ([Integer(2),Integer(1)], [Integer(1),Integer(1)]))
          >>> psi = B.crystal_morphism(C.module_generators[Integer(1):], codomain=C)
          >>> psi.is_isomorphism()
          False

    is_strict()

      Check if `self` is a strict crystal morphism.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['C',2], shape=[1,1])
          sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
          sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
          sage: psi.is_strict()
          True

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['C',Integer(2)], shape=[Integer(1),Integer(1)])
          >>> C = crystals.Tableaux(['C',Integer(2)], ([Integer(2),Integer(1)], [Integer(1),Integer(1)]))
          >>> psi = B.crystal_morphism(C.module_generators[Integer(1):], codomain=C)
          >>> psi.is_strict()
          True

  class ParentMethods

    Bases: `object`

    Lambda()

      Return the fundamental weights in the weight lattice realization for the root system associated with the crystal

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['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)}

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(5)])
          >>> 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)}

    an_element()

      Return an element of `self`.

      > sage: C = crystals.Letters([‘A’, 5]) sage: C.an_element() 1

    cartan_type()

      Return the Cartan type of the crystal.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A',2])
          sage: C.cartan_type()
          ['A', 2]

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(2)])
          >>> C.cartan_type()
          ['A', 2]

    connected_components()

      Return the connected components of `self` as subcrystals.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[2,1])
          sage: C = crystals.Letters(['A',2])
          sage: T = crystals.TensorProduct(B,C)
          sage: T.connected_components()
          [Subcrystal of Full tensor product of the crystals
           [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
            The crystal of letters for type ['A', 2]],
           Subcrystal of Full tensor product of the crystals
           [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
            The crystal of letters for type ['A', 2]],
           Subcrystal of Full tensor product of the crystals
           [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
            The crystal of letters for type ['A', 2]]]

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> C = crystals.Letters(['A',Integer(2)])
          >>> T = crystals.TensorProduct(B,C)
          >>> T.connected_components()
          [Subcrystal of Full tensor product of the crystals
           [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
            The crystal of letters for type ['A', 2]],
           Subcrystal of Full tensor product of the crystals
           [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
            The crystal of letters for type ['A', 2]],
           Subcrystal of Full tensor product of the crystals
           [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
            The crystal of letters for type ['A', 2]]]

    connected_components_generators()

      Return a tuple of generators for each of the connected components of `self`.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[2,1])
          sage: C = crystals.Letters(['A',2])
          sage: T = crystals.TensorProduct(B,C)
          sage: T.connected_components_generators()
          ([[[1, 1], [2]], 1], [[[1, 2], [2]], 1], [[[1, 2], [3]], 1])

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> C = crystals.Letters(['A',Integer(2)])
          >>> T = crystals.TensorProduct(B,C)
          >>> T.connected_components_generators()
          ([[[1, 1], [2]], 1], [[[1, 2], [2]], 1], [[[1, 2], [3]], 1])

    crystal_morphism(on_gens, codomain=None, cartan_type=None, index_set=None, generators=None, automorphism=None, virtualization=None, scaling_factors=None, category=None, check=True)

      Construct a crystal morphism from `self` to another crystal `codomain`.

      INPUT:

      - `on_gens` – a function or list that determines the image of the generators (if given a list, then this uses the order of the generators of the domain) of `self` under the crystal morphism

      - `codomain` – (default: `self`) the codomain of the morphism

      - `cartan_type` – (optional) the Cartan type of the morphism; the default is the Cartan type of `self`

      - `index_set` – (optional) the index set of the morphism; the default is the index set of the Cartan type

      - `generators` – (optional) the generators to define the morphism; the default is the generators of `self`

      - `automorphism` – (optional) the automorphism to perform the twisting

      - `virtualization` – (optional) a dictionary whose keys are in the index set of the domain and whose values are lists of entries in the index set of the codomain; the default is the identity dictionary

      - `scaling_factors` – (optional) a dictionary whose keys are in the index set of the domain and whose values are scaling factors for the weight, \(\varepsilon\) and \(\varphi\); the default are all scaling factors to be one

      - `category` – (optional) the category for the crystal morphism; the default is the category of `Crystals`.

      - `check` – boolean (default: `True`); check if the crystal morphism is valid

      See also

      For more examples, see `sage.categories.crystals.CrystalHomset`.

      EXAMPLES:

      We construct the natural embedding of a crystal using tableaux into the tensor product of single boxes via the reading word:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[2,1])
          sage: F = crystals.Tableaux(['A',2], shape=[1])
          sage: T = crystals.TensorProduct(F, F, F)
          sage: mg = T.highest_weight_vectors()[2]; mg
          [[[1]], [[2]], [[1]]]
          sage: psi = B.crystal_morphism([mg], codomain=T); psi
          ['A', 2] Crystal morphism:
            From: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
            To:   Full tensor product of the crystals
                   [The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
                    The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
                    The crystal of tableaux of type ['A', 2] and shape(s) [[1]]]
            Defn: [[1, 1], [2]] |--> [[[1]], [[2]], [[1]]]
          sage: b = B.module_generators[0]
          sage: b.pp()
            1  1
            2
          sage: psi(b)
          [[[1]], [[2]], [[1]]]
          sage: psi(b.f(2))
          [[[1]], [[3]], [[1]]]
          sage: psi(b.f_string([2,1,1]))
          [[[2]], [[3]], [[2]]]
          sage: lw = b.to_lowest_weight()[0]
          sage: lw.pp()
            2  3
            3
          sage: psi(lw)
          [[[3]], [[3]], [[2]]]
          sage: psi(lw) == mg.to_lowest_weight()[0]
          True

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> F = crystals.Tableaux(['A',Integer(2)], shape=[Integer(1)])
          >>> T = crystals.TensorProduct(F, F, F)
          >>> mg = T.highest_weight_vectors()[Integer(2)]; mg
          [[[1]], [[2]], [[1]]]
          >>> psi = B.crystal_morphism([mg], codomain=T); psi
          ['A', 2] Crystal morphism:
            From: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
            To:   Full tensor product of the crystals
                   [The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
                    The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
                    The crystal of tableaux of type ['A', 2] and shape(s) [[1]]]
            Defn: [[1, 1], [2]] |--> [[[1]], [[2]], [[1]]]
          >>> b = B.module_generators[Integer(0)]
          >>> b.pp()
            1  1
            2
          >>> psi(b)
          [[[1]], [[2]], [[1]]]
          >>> psi(b.f(Integer(2)))
          [[[1]], [[3]], [[1]]]
          >>> psi(b.f_string([Integer(2),Integer(1),Integer(1)]))
          [[[2]], [[3]], [[2]]]
          >>> lw = b.to_lowest_weight()[Integer(0)]
          >>> lw.pp()
            2  3
            3
          >>> psi(lw)
          [[[3]], [[3]], [[2]]]
          >>> psi(lw) == mg.to_lowest_weight()[Integer(0)]
          True

      We now take the other isomorphic highest weight component in the tensor product:

      Sage

          sage: mg = T.highest_weight_vectors()[1]; mg
          [[[2]], [[1]], [[1]]]
          sage: psi = B.crystal_morphism([mg], codomain=T)
          sage: psi(lw)
          [[[3]], [[2]], [[3]]]

      [Python]

          >>> from sage.all import *
          >>> mg = T.highest_weight_vectors()[Integer(1)]; mg
          [[[2]], [[1]], [[1]]]
          >>> psi = B.crystal_morphism([mg], codomain=T)
          >>> psi(lw)
          [[[3]], [[2]], [[3]]]

      We construct a crystal morphism of classical crystals using a Kirillov-Reshetikhin crystal:

      Sage

          sage: B = crystals.Tableaux(['D', 4], shape=[1,1])
          sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,2)
          sage: K.module_generators
          [[], [[1], [2]], [[1, 1], [2, 2]]]
          sage: v = K.module_generators[1]
          sage: psi = B.crystal_morphism([v], codomain=K, category=FiniteCrystals())
          sage: psi
          ['D', 4] -> ['D', 4, 1] Virtual Crystal morphism:
            From: The crystal of tableaux of type ['D', 4] and shape(s) [[1, 1]]
            To:   Kirillov-Reshetikhin crystal of type ['D', 4, 1] with (r,s)=(2,2)
            Defn: [[1], [2]] |--> [[1], [2]]
          sage: b = B.module_generators[0]
          sage: psi(b)
          [[1], [2]]
          sage: psi(b.to_lowest_weight()[0])
          [[-2], [-1]]

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['D', Integer(4)], shape=[Integer(1),Integer(1)])
          >>> K = crystals.KirillovReshetikhin(['D',Integer(4),Integer(1)], Integer(2),Integer(2))
          >>> K.module_generators
          [[], [[1], [2]], [[1, 1], [2, 2]]]
          >>> v = K.module_generators[Integer(1)]
          >>> psi = B.crystal_morphism([v], codomain=K, category=FiniteCrystals())
          >>> psi
          ['D', 4] -> ['D', 4, 1] Virtual Crystal morphism:
            From: The crystal of tableaux of type ['D', 4] and shape(s) [[1, 1]]
            To:   Kirillov-Reshetikhin crystal of type ['D', 4, 1] with (r,s)=(2,2)
            Defn: [[1], [2]] |--> [[1], [2]]
          >>> b = B.module_generators[Integer(0)]
          >>> psi(b)
          [[1], [2]]
          >>> psi(b.to_lowest_weight()[Integer(0)])
          [[-2], [-1]]

      We can define crystal morphisms using a different set of generators. For example, we construct an example using the lowest weight vector:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[1])
          sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
          sage: T = crystals.elementary.T(['A',2], La[2])
          sage: Bp = T.tensor(B)
          sage: C = crystals.Tableaux(['A',2], shape=[2,1])
          sage: x = C.module_generators[0].f_string([1,2])
          sage: psi = Bp.crystal_morphism([x], generators=Bp.lowest_weight_vectors())
          sage: psi(Bp.highest_weight_vector())
          [[1, 1], [2]]

      [Python]

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(1)])
          >>> La = RootSystem(['A',Integer(2)]).weight_lattice().fundamental_weights()
          >>> T = crystals.elementary.T(['A',Integer(2)], La[Integer(2)])
          >>> Bp = T.tensor(B)
          >>> C = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> x = C.module_generators[Integer(0)].f_string([Integer(1),Integer(2)])
          >>> psi = Bp.crystal_morphism([x], generators=Bp.lowest_weight_vectors())
          >>> psi(Bp.highest_weight_vector())
          [[1, 1], [2]]

      We can also use a dictionary to specify the generators and their images:

      Sage

          sage: psi = Bp.crystal_morphism({Bp.lowest_weight_vectors()[0]: x})
          sage: psi(Bp.highest_weight_vector())
          [[1, 1], [2]]

      Python

          >>> from sage.all import *
          >>> psi = Bp.crystal_morphism({Bp.lowest_weight_vectors()[Integer(0)]: x})
          >>> psi(Bp.highest_weight_vector())
          [[1, 1], [2]]

      We construct a twisted crystal morphism induced from the diagram automorphism of type \(A_3^{(1)}\):

      Sage

          sage: La = RootSystem(['A',3,1]).weight_lattice(extended=True).fundamental_weights()
          sage: B0 = crystals.GeneralizedYoungWalls(3, La[0])
          sage: B1 = crystals.GeneralizedYoungWalls(3, La[1])
          sage: phi = B0.crystal_morphism(B1.module_generators, automorphism={0:1, 1:2, 2:3, 3:0})
          sage: phi
          ['A', 3, 1] Twisted Crystal morphism:
            From: Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[0]
            To:   Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[1]
            Defn: [] |--> []
          sage: x = B0.module_generators[0].f_string([0,1,2,3]); x
          [[0, 3], [1], [2]]
          sage: phi(x)
          [[], [1, 0], [2], [3]]

      [Python]

          >>> from sage.all import *
          >>> La = RootSystem(['A',Integer(3),Integer(1)]).weight_lattice(extended=True).fundamental_weights()
          >>> B0 = crystals.GeneralizedYoungWalls(Integer(3), La[Integer(0)])
          >>> B1 = crystals.GeneralizedYoungWalls(Integer(3), La[Integer(1)])
          >>> phi = B0.crystal_morphism(B1.module_generators, automorphism={Integer(0):Integer(1), Integer(1):Integer(2), Integer(2):Integer(3), Integer(3):Integer(0)})
          >>> phi
          ['A', 3, 1] Twisted Crystal morphism:
            From: Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[0]
            To:   Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[1]
            Defn: [] |--> []
          >>> x = B0.module_generators[Integer(0)].f_string([Integer(0),Integer(1),Integer(2),Integer(3)]); x
          [[0, 3], [1], [2]]
          >>> phi(x)
          [[], [1, 0], [2], [3]]

      We construct a virtual crystal morphism from type \(G_2\) into type \(D_4\):

      Sage

          sage: D = crystals.Tableaux(['D',4], shape=[1,1])
          sage: G = crystals.Tableaux(['G',2], shape=[1])
          sage: psi = G.crystal_morphism(D.module_generators,
          ....:                          virtualization={1:[2],2:[1,3,4]},
          ....:                          scaling_factors={1:1, 2:1})
          sage: for x in G:
          ....:     ascii_art(x, psi(x), sep='  |-->  ')
          ....:     print("")
                       1
            1  |-->    2

                       1
            2  |-->    3

                       2
            3  |-->   -3

                       3
            0  |-->   -3

                       3
           -3  |-->   -2

                      -3
           -2  |-->   -1

                      -2
           -1  |-->   -1

      Python

          >>> from sage.all import *
          >>> D = crystals.Tableaux(['D',Integer(4)], shape=[Integer(1),Integer(1)])
          >>> G = crystals.Tableaux(['G',Integer(2)], shape=[Integer(1)])
          >>> psi = G.crystal_morphism(D.module_generators,
          ...                          virtualization={Integer(1):[Integer(2)],Integer(2):[Integer(1),Integer(3),Integer(4)]},
          ...                          scaling_factors={Integer(1):Integer(1), Integer(2):Integer(1)})
          >>> for x in G:
          ...     ascii_art(x, psi(x), sep='  |-->  ')
          ...     print("")
                       1
            1  |-->    2
          <BLANKLINE>
                       1
            2  |-->    3
          <BLANKLINE>
                       2
            3  |-->   -3
          <BLANKLINE>
                       3
            0  |-->   -3
          <BLANKLINE>
                       3
           -3  |-->   -2
          <BLANKLINE>
                      -3
           -2  |-->   -1
          <BLANKLINE>
                      -2
           -1  |-->   -1

    digraph(subset=None, index_set=None)

      Return the `DiGraph` associated to `self`.

      INPUT:

      - `subset` – (optional) a subset of vertices for which the digraph should be constructed

      - `index_set` – (optional) the index set to draw arrows

      EXAMPLES:

      Sage

          sage: C = Crystals().example(5)
          sage: C.digraph()
          Digraph on 6 vertices

      Python

          >>> from sage.all import *
          >>> C = Crystals().example(Integer(5))
          >>> C.digraph()
          Digraph on 6 vertices

      The edges of the crystal graph are by default colored using blue for edge 1, red for edge 2, and green for edge 3:

      Sage

          sage: C = Crystals().example(3)
          sage: G = C.digraph()
          sage: view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      [Python]

          >>> from sage.all import *
          >>> C = Crystals().example(Integer(3))
          >>> G = C.digraph()
          >>> view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      One may also overwrite the colors:

      Sage

          sage: C = Crystals().example(3)
          sage: G = C.digraph()
          sage: G.set_latex_options(color_by_label = {1:"red", 2:"purple", 3:"blue"})
          sage: view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      Python

          >>> from sage.all import *
          >>> C = Crystals().example(Integer(3))
          >>> G = C.digraph()
          >>> G.set_latex_options(color_by_label = {Integer(1):"red", Integer(2):"purple", Integer(3):"blue"})
          >>> view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      Or one may add colors to yet unspecified edges:

      Sage

          sage: C = Crystals().example(4)
          sage: G = C.digraph()
          sage: C.cartan_type()._index_set_coloring[4]="purple"
          sage: view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      [Python]

          >>> from sage.all import *
          >>> C = Crystals().example(Integer(4))
          >>> G = C.digraph()
          >>> C.cartan_type()._index_set_coloring[Integer(4)]="purple"
          >>> view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      Here is an example of how to take the top part up to a given depth of an infinite dimensional crystal:

      Sage

          sage: C = CartanType(['C',2,1])
          sage: La = C.root_system().weight_lattice().fundamental_weights()
          sage: T = crystals.HighestWeight(La[0])
          sage: S = T.subcrystal(max_depth=3)
          sage: G = T.digraph(subset=S); G
          Digraph on 5 vertices
          sage: G.vertices(sort=True, key=str)
          [(-Lambda[0] + 2*Lambda[1] - delta,),
           (1/2*Lambda[0] + Lambda[1] - Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
           (1/2*Lambda[0] - Lambda[1] + Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
           (Lambda[0] - 2*Lambda[1] + 2*Lambda[2] - delta,),
           (Lambda[0],)]

      Python

          >>> from sage.all import *
          >>> C = CartanType(['C',Integer(2),Integer(1)])
          >>> La = C.root_system().weight_lattice().fundamental_weights()
          >>> T = crystals.HighestWeight(La[Integer(0)])
          >>> S = T.subcrystal(max_depth=Integer(3))
          >>> G = T.digraph(subset=S); G
          Digraph on 5 vertices
          >>> G.vertices(sort=True, key=str)
          [(-Lambda[0] + 2*Lambda[1] - delta,),
           (1/2*Lambda[0] + Lambda[1] - Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
           (1/2*Lambda[0] - Lambda[1] + Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
           (Lambda[0] - 2*Lambda[1] + 2*Lambda[2] - delta,),
           (Lambda[0],)]

      Here is a way to construct a picture of a Demazure crystal using the `subset` option:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = B.highest_weight_vector()
          sage: D = B.demazure_subcrystal(t, [2,1])
          sage: list(D)
          [[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
           [[1, 3], [2]], [[1, 3], [3]]]
          sage: view(D)  # optional - dot2tex graphviz, not tested (opens external window)

      [Python]

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> t = B.highest_weight_vector()
          >>> D = B.demazure_subcrystal(t, [Integer(2),Integer(1)])
          >>> list(D)
          [[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
           [[1, 3], [2]], [[1, 3], [3]]]
          >>> view(D)  # optional - dot2tex graphviz, not tested (opens external window)

      We can also choose to display particular arrows using the `index_set` option:

      Sage

          sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1)
          sage: G = C.digraph(index_set=[1,3])
          sage: len(G.edges(sort=False))
          20
          sage: view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      Python

          >>> from sage.all import *
          >>> C = crystals.KirillovReshetikhin(['D',Integer(4),Integer(1)], Integer(2), Integer(1))
          >>> G = C.digraph(index_set=[Integer(1),Integer(3)])
          >>> len(G.edges(sort=False))
          20
          >>> view(G)  # optional - dot2tex graphviz, not tested (opens external window)

      Todo

      Add more tests.

    direct_sum(X)

      Return the direct sum of `self` with `X`.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[2,1])
          sage: C = crystals.Letters(['A',2])
          sage: B.direct_sum(C)
          Direct sum of the crystals Family
          (The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
           The crystal of letters for type ['A', 2])

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> C = crystals.Letters(['A',Integer(2)])
          >>> B.direct_sum(C)
          Direct sum of the crystals Family
          (The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
           The crystal of letters for type ['A', 2])

      As a shorthand, we can use `+`:

      Sage

          sage: B + C
          Direct sum of the crystals Family
          (The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
           The crystal of letters for type ['A', 2])

      [Python]

          >>> from sage.all import *
          >>> B + C
          Direct sum of the crystals Family
          (The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
           The crystal of letters for type ['A', 2])

    dot_tex()

      Return a dot_tex string representation of `self`.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['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}'

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A',Integer(2)])
          >>> 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}'

    index_set()

      Return the index set of the Dynkin diagram underlying the crystal.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 5])
          sage: C.index_set()
          (1, 2, 3, 4, 5)

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(5)])
          >>> C.index_set()
          (1, 2, 3, 4, 5)

    is_connected()

      Return `True` if `self` is a connected crystal.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[2,1])
          sage: C = crystals.Letters(['A',2])
          sage: T = crystals.TensorProduct(B,C)
          sage: B.is_connected()
          True
          sage: T.is_connected()
          False

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> C = crystals.Letters(['A',Integer(2)])
          >>> T = crystals.TensorProduct(B,C)
          >>> B.is_connected()
          True
          >>> T.is_connected()
          False

    latex(**options)

      Return the crystal graph as a latex string. This can be exported to a file with `self.latex_file('filename')`.

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2],shape=[1])
          sage: T._latex_()
          '...tikzpicture...'
          sage: view(T) # optional - dot2tex graphviz, not tested (opens external window)

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(2)],shape=[Integer(1)])
          >>> T._latex_()
          '...tikzpicture...'
          >>> view(T) # optional - dot2tex graphviz, not tested (opens external window)

      One can for example also color the edges using the following options:

      Sage

          sage: T = crystals.Tableaux(['A',2],shape=[1])
          sage: T._latex_(color_by_label={0:"black", 1:"red", 2:"blue"})
          '...tikzpicture...'

      [Python]

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(2)],shape=[Integer(1)])
          >>> T._latex_(color_by_label={Integer(0):"black", Integer(1):"red", Integer(2):"blue"})
          '...tikzpicture...'

    latex_file(filename)

      Export a file, suitable for pdflatex, to `filename`.

      This requires a proper installation of `dot2tex`. For more information see the documentation for `self.latex()`.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 5])
          sage: fn = tmp_filename(ext='.tex')
          sage: C.latex_file(fn)

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(5)])
          >>> fn = tmp_filename(ext='.tex')
          >>> C.latex_file(fn)

    metapost(filename, thicklines=False, labels=True, scaling_factor=1.0, tallness=1.0)

      Export a file, suitable for MetaPost, to `filename`.

      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

      \(a_2 a_3 a_4 a_1\)

      where \(c*a_2 = a_3 = 2*a_4 = 0\) and \(a_1=0\), with \(c=2\) for B2, \(c=1\) for C2. Applying \(e(2)\) \(a_1\) times, \(e(1)\) \(a_2\) times, \(e(2)\) \(a_3\) times, \(e(1)\) \(a_4\) 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

      \(a_3 a_2 a_1\)

      where applying \(e(1)\) \(a_3\) times, \(e(2)\) \(a_2\) times then \(e(1)\) \(a_1\) times returns to the highest weight. These data determine the vertex and may be translated into a Gelfand-Tsetlin pattern or tableau.

      INPUT:

      - `filename` – name of the output file, e.g., `'filename.mp'`

      - `thicklines` – boolean (default: `True`); for thicker edges

      - `labels` – boolean (default: `False`); whether to suppress labeling of the vertices

      - `scaling_factor` – (default: `1.0`) increasing or decreasing the scaling factor changes the size of the image

      - `tallness` – (default: `1.0`) increasing makes the image taller without increasing the width

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 2])
          sage: C.metapost(tmp_filename())

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(2)])
          >>> C.metapost(tmp_filename())

      Sage

          sage: C = crystals.Letters(['A', 5])
          sage: C.metapost(tmp_filename())
          Traceback (most recent call last):
          ...
          NotImplementedError

      [Python]

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(5)])
          >>> C.metapost(tmp_filename())
          Traceback (most recent call last):
          ...
          NotImplementedError

    number_of_connected_components()

      Return the number of connected components of `self`.

      EXAMPLES:

      Sage

          sage: B = crystals.Tableaux(['A',2], shape=[2,1])
          sage: C = crystals.Letters(['A',2])
          sage: T = crystals.TensorProduct(B,C)
          sage: T.number_of_connected_components()
          3

      Python

          >>> from sage.all import *
          >>> B = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> C = crystals.Letters(['A',Integer(2)])
          >>> T = crystals.TensorProduct(B,C)
          >>> T.number_of_connected_components()
          3

    plot(**options)

      Return the plot of `self` as a directed graph.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 5])
          sage: print(C.plot())
          Graphics object consisting of 17 graphics primitives

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(5)])
          >>> print(C.plot())
          Graphics object consisting of 17 graphics primitives

    plot3d(**options)

      Return the 3-dimensional plot of `self` as a directed graph.

      EXAMPLES:

      Sage

          sage: C = crystals.KirillovReshetikhin(['A',3,1],2,1)
          sage: print(C.plot3d())
          Graphics3d Object

      Python

          >>> from sage.all import *
          >>> C = crystals.KirillovReshetikhin(['A',Integer(3),Integer(1)],Integer(2),Integer(1))
          >>> print(C.plot3d())
          Graphics3d Object

    subcrystal(index_set=None, generators=None, max_depth=inf, direction='both', contained=None, virtualization=None, scaling_factors=None, cartan_type=None, category=None)

      Construct the subcrystal from `generators` using \(e_i\) and/or \(f_i\) for all \(i\) in `index_set`.

      INPUT:

      - `index_set` – (default: `None`) the index set; if `None` then use the index set of the crystal

      - `generators` – (default: `None`) the list of generators; if `None` then use the module generators of the crystal

      - `max_depth` – (default: infinity) the maximum depth to build

      - `direction` – (default: `'both'`) the direction to build the subcrystal; it can be one of the following:

        - `'both'` – using both \(e_i\) and \(f_i\)

        - `'upper'` – using \(e_i\)

        - `'lower'` – using \(f_i\)

      - `contained` – (optional) a set or function defining the containment in the subcrystal

      - `virtualization`, `scaling_factors` – (optional) dictionaries whose key \(i\) corresponds to the sets \(\sigma_i\) and \(\gamma_i\) respectively used to define virtual crystals; see `VirtualCrystal`

      - `cartan_type` – (optional) specify the Cartan type of the subcrystal

      - `category` – (optional) specify the category of the subcrystal

      EXAMPLES:

      Sage

          sage: C = crystals.KirillovReshetikhin(['A',3,1], 1, 2)
          sage: S = list(C.subcrystal(index_set=[1,2])); S
          [[[1, 1]], [[1, 2]], [[2, 2]], [[1, 3]], [[2, 3]], [[3, 3]]]
          sage: C.cardinality()
          10
          sage: len(S)
          6
          sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)]))
          [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
          sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], max_depth=1))
          [[[1, 4]], [[2, 4]], [[1, 3]]]
          sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='upper'))
          [[[1, 4]], [[1, 3]]]
          sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='lower'))
          [[[1, 4]], [[2, 4]]]

          sage: G = C.subcrystal(index_set=[1,2,3]).digraph()
          sage: GA = crystals.Tableaux('A3', shape=[2]).digraph()
          sage: G.is_isomorphic(GA, edge_labels=True)
          True

      Python

          >>> from sage.all import *
          >>> C = crystals.KirillovReshetikhin(['A',Integer(3),Integer(1)], Integer(1), Integer(2))
          >>> S = list(C.subcrystal(index_set=[Integer(1),Integer(2)])); S
          [[[1, 1]], [[1, 2]], [[2, 2]], [[1, 3]], [[2, 3]], [[3, 3]]]
          >>> C.cardinality()
          10
          >>> len(S)
          6
          >>> list(C.subcrystal(index_set=[Integer(1),Integer(3)], generators=[C(Integer(1),Integer(4))]))
          [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
          >>> list(C.subcrystal(index_set=[Integer(1),Integer(3)], generators=[C(Integer(1),Integer(4))], max_depth=Integer(1)))
          [[[1, 4]], [[2, 4]], [[1, 3]]]
          >>> list(C.subcrystal(index_set=[Integer(1),Integer(3)], generators=[C(Integer(1),Integer(4))], direction='upper'))
          [[[1, 4]], [[1, 3]]]
          >>> list(C.subcrystal(index_set=[Integer(1),Integer(3)], generators=[C(Integer(1),Integer(4))], direction='lower'))
          [[[1, 4]], [[2, 4]]]

          >>> G = C.subcrystal(index_set=[Integer(1),Integer(2),Integer(3)]).digraph()
          >>> GA = crystals.Tableaux('A3', shape=[Integer(2)]).digraph()
          >>> G.is_isomorphic(GA, edge_labels=True)
          True

      We construct the subcrystal which contains the necessary data to construct the corresponding dual equivalence graph:

      Sage

          sage: C = crystals.Tableaux(['A',5], shape=[3,3])
          sage: is_wt0 = lambda x: all(x.epsilon(i) == x.phi(i) for i in x.parent().index_set())
          sage: def check(x):
          ....:     if is_wt0(x):
          ....:         return True
          ....:     for i in x.parent().index_set()[:-1]:
          ....:         L = [x.e(i), x.e_string([i,i+1]), x.f(i), x.f_string([i,i+1])]
          ....:         if any(y is not None and is_wt0(y) for y in L):
          ....:             return True
          ....:     return False
          sage: wt0 = [x for x in C if is_wt0(x)]
          sage: S = C.subcrystal(contained=check, generators=wt0)
          sage: S.module_generators[0]
          [[1, 3, 5], [2, 4, 6]]
          sage: S.module_generators[0].e(2).e(3).f(2).f(3)
          [[1, 2, 5], [3, 4, 6]]

      [Python]

          >>> from sage.all import *
          >>> C = crystals.Tableaux(['A',Integer(5)], shape=[Integer(3),Integer(3)])
          >>> is_wt0 = lambda x: all(x.epsilon(i) == x.phi(i) for i in x.parent().index_set())
          >>> def check(x):
          ...     if is_wt0(x):
          ...         return True
          ...     for i in x.parent().index_set()[:-Integer(1)]:
          ...         L = [x.e(i), x.e_string([i,i+Integer(1)]), x.f(i), x.f_string([i,i+Integer(1)])]
          ...         if any(y is not None and is_wt0(y) for y in L):
          ...             return True
          ...     return False
          >>> wt0 = [x for x in C if is_wt0(x)]
          >>> S = C.subcrystal(contained=check, generators=wt0)
          >>> S.module_generators[Integer(0)]
          [[1, 3, 5], [2, 4, 6]]
          >>> S.module_generators[Integer(0)].e(Integer(2)).e(Integer(3)).f(Integer(2)).f(Integer(3))
          [[1, 2, 5], [3, 4, 6]]

      An example of a type \(B_2\) virtual crystal inside of a type \(A_3\) ambient crystal:

      Sage

          sage: A = crystals.Tableaux(['A',3], shape=[2,1,1])
          sage: S = A.subcrystal(virtualization={1:[1,3], 2:[2]},
          ....:                  scaling_factors={1:1,2:1}, cartan_type=['B',2])
          sage: B = crystals.Tableaux(['B',2], shape=[1])
          sage: S.digraph().is_isomorphic(B.digraph(), edge_labels=True)
          True

      Python

          >>> from sage.all import *
          >>> A = crystals.Tableaux(['A',Integer(3)], shape=[Integer(2),Integer(1),Integer(1)])
          >>> S = A.subcrystal(virtualization={Integer(1):[Integer(1),Integer(3)], Integer(2):[Integer(2)]},
          ...                  scaling_factors={Integer(1):Integer(1),Integer(2):Integer(1)}, cartan_type=['B',Integer(2)])
          >>> B = crystals.Tableaux(['B',Integer(2)], shape=[Integer(1)])
          >>> S.digraph().is_isomorphic(B.digraph(), edge_labels=True)
          True

    tensor(*crystals, **options)

      Return the tensor product of `self` with the crystals `B`.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 3])
          sage: B = crystals.infinity.Tableaux(['A', 3])
          sage: T = C.tensor(C, B); T
          Full tensor product of the crystals
           [The crystal of letters for type ['A', 3],
            The crystal of letters for type ['A', 3],
            The infinity crystal of tableaux of type ['A', 3]]
          sage: tensor([C, C, B]) is T
          True

          sage: C = crystals.Letters(['A',2])
          sage: T = C.tensor(C, C, generators=[[C(2),C(1),C(1)],[C(1),C(2),C(1)]]); T
          The 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.module_generators
          ([2, 1, 1], [1, 2, 1])

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(3)])
          >>> B = crystals.infinity.Tableaux(['A', Integer(3)])
          >>> T = C.tensor(C, B); T
          Full tensor product of the crystals
           [The crystal of letters for type ['A', 3],
            The crystal of letters for type ['A', 3],
            The infinity crystal of tableaux of type ['A', 3]]
          >>> tensor([C, C, B]) is T
          True

          >>> C = crystals.Letters(['A',Integer(2)])
          >>> T = C.tensor(C, C, generators=[[C(Integer(2)),C(Integer(1)),C(Integer(1))],[C(Integer(1)),C(Integer(2)),C(Integer(1))]]); T
          The 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]]
          >>> T.module_generators
          ([2, 1, 1], [1, 2, 1])

    weight_lattice_realization()

      Return the weight lattice realization used to express weights in `self`.

      This default implementation uses the ambient space of the root system for (non relabelled) finite types and the weight lattice otherwise. This is a legacy from when ambient spaces were partially implemented, and may be changed in the future.

      For affine types, this returns the extended weight lattice by default.

      EXAMPLES:

      Sage

          sage: C = crystals.Letters(['A', 5])
          sage: C.weight_lattice_realization()
          Ambient space of the Root system of type ['A', 5]
          sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1)
          sage: K.weight_lattice_realization()
          Weight lattice of the Root system of type ['A', 2, 1]

      Python

          >>> from sage.all import *
          >>> C = crystals.Letters(['A', Integer(5)])
          >>> C.weight_lattice_realization()
          Ambient space of the Root system of type ['A', 5]
          >>> K = crystals.KirillovReshetikhin(['A',Integer(2),Integer(1)], Integer(1), Integer(1))
          >>> K.weight_lattice_realization()
          Weight lattice of the Root system of type ['A', 2, 1]

  class SubcategoryMethods

    Bases: `object`

    Methods for all subcategories.

    TensorProducts()

      Return the full subcategory of objects of `self` constructed as tensor products.

      See also

      - `tensor.TensorProductsCategory`

      - `RegressiveCovariantFunctorialConstruction`.

      EXAMPLES:

      Sage

          sage: HighestWeightCrystals().TensorProducts()
          Category of tensor products of highest weight crystals

      Python

          >>> from sage.all import *
          >>> HighestWeightCrystals().TensorProducts()
          Category of tensor products of highest weight crystals

  class TensorProducts(category, *args)

    Bases: `TensorProductsCategory`

    The category of crystals constructed by tensor product of crystals.

    extra_super_categories()

      EXAMPLES:

      Sage

          sage: Crystals().TensorProducts().extra_super_categories()
          [Category of crystals]

      Python

          >>> from sage.all import *
          >>> Crystals().TensorProducts().extra_super_categories()
          [Category of crystals]

  example(choice='highwt', **kwds)

    Return an example of a crystal, as per `Category.example()`.

    INPUT:

    - `choice` – string (default: `'highwt'`); can be either `'highwt'` for the highest weight crystal of type A, or `'naive'` for an example of a broken crystal

    - `**kwds` – keyword arguments passed onto the constructor for the chosen crystal

    EXAMPLES:

    Sage

        sage: Crystals().example(choice='highwt', n=5)
        Highest weight crystal of type A_5 of highest weight omega_1
        sage: Crystals().example(choice='naive')
        A broken crystal, defined by digraph, of dimension five.

    Python

        >>> from sage.all import *
        >>> Crystals().example(choice='highwt', n=Integer(5))
        Highest weight crystal of type A_5 of highest weight omega_1
        >>> Crystals().example(choice='naive')
        A broken crystal, defined by digraph, of dimension five.

  super_categories()

    EXAMPLES:

    Sage

        sage: Crystals().super_categories()
        [Category of enumerated sets]

    Python

        >>> from sage.all import *
        >>> Crystals().super_categories()
        [Category of enumerated sets]