Regular Crystals - Category Framework

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

# Regular Crystals

class sage.categories.regular_crystals.RegularCrystals

  Bases: `Category_singleton`

  The category of regular crystals.

  A crystal is called regular if every vertex \(b\) satisfies

  \[\varepsilon_i(b) = \max\{ k \mid e_i^k(b) \neq 0 \} \quad \text{and} \quad \varphi_i(b) = \max\{ k \mid f_i^k(b) \neq 0 \}.\]

  Note

  Regular crystals are sometimes referred to as normal. When only one of the conditions (on either \(\varphi_i\) or \(\varepsilon_i\)) holds, these crystals are sometimes called seminormal or semiregular.

  EXAMPLES:

  Sage

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

  Python

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

  class ElementMethods

    Bases: `object`

    demazure_operator_simple(i, ring=None)

      Return the Demazure operator \(D_i\) applied to `self`.

      INPUT:

      - `i` – an element of the index set of the underlying crystal

      - `ring` – (default: `QQ`) a ring

      OUTPUT:

      An element of the `ring`-free module indexed by the underlying crystal.

      Let \(r = \langle \mathrm{wt}(b), \alpha^{\vee}_i \rangle\), then \(D_i(b)\) is defined as follows:

      - If \(r \geq 0\), this returns the sum of the elements obtained from `self` by application of \(f_i^k\) for \(0 \leq k \leq r\).

      - If \(r < 0\), this returns the opposite of the sum of the elements obtained by application of \(e_i^k\) for \(0 < k < -r\).

      REFERENCES:

      - [Li1995]

      - [Ka1993]

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = T(rows=[[1,2],[2]])
          sage: t.demazure_operator_simple(2)
          B[[[1, 2], [2]]] + B[[[1, 3], [2]]] + B[[[1, 3], [3]]]
          sage: t.demazure_operator_simple(2).parent()
          Algebra of The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
                  over Integer Ring

          sage: t.demazure_operator_simple(1)
          0

          sage: K = crystals.KirillovReshetikhin(['A',2,1],2,1)
          sage: t = K(rows=[[3],[2]])
          sage: t.demazure_operator_simple(0)
          B[[[1, 2]]] + B[[[2, 3]]]

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> t = T(rows=[[Integer(1),Integer(2)],[Integer(2)]])
          >>> t.demazure_operator_simple(Integer(2))
          B[[[1, 2], [2]]] + B[[[1, 3], [2]]] + B[[[1, 3], [3]]]
          >>> t.demazure_operator_simple(Integer(2)).parent()
          Algebra of The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
                  over Integer Ring

          >>> t.demazure_operator_simple(Integer(1))
          0

          >>> K = crystals.KirillovReshetikhin(['A',Integer(2),Integer(1)],Integer(2),Integer(1))
          >>> t = K(rows=[[Integer(3)],[Integer(2)]])
          >>> t.demazure_operator_simple(Integer(0))
          B[[[1, 2]]] + B[[[2, 3]]]

    dual_equivalence_class(index_set=None)

      Return the dual equivalence class indexed by `index_set` of `self`.

      The dual equivalence class of an element \(b \in B\) is the set of all elements of \(B\) reachable from \(b\) via sequences of \(i\)-elementary dual equivalence relations (i.e., \(i\)-elementary dual equivalence transformations and their inverses) for \(i\) in the index set of \(B\).

      For this to be well-defined, the element \(b\) has to be of weight \(0\) with respect to \(I\); that is, we need to have \(\varepsilon_j(b) = \varphi_j(b)\) for all \(j \in I\).

      See [As2008]. See also `dual_equivalence_graph()` for a definition of \(i\)-elementary dual equivalence transformations.

      INPUT:

      - `index_set` – (optional) the index set \(I\) (default: the whole index set of the crystal); this has to be a subset of the index set of the crystal (as a list or tuple)

      OUTPUT:

      The dual equivalence class of `self` indexed by the subset `index_set`. This class is returned as an undirected edge-colored multigraph. The color of an edge is the index \(i\) of the dual equivalence relation it encodes.

      See also

      - `dual_equivalence_graph()`

      - `sage.combinat.partition.Partition.dual_equivalence_graph()`

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',3], shape=[2,2])
          sage: G = T(2,1,4,3).dual_equivalence_class()
          sage: G.edges(sort=True)
          [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
           ([[1, 3], [2, 4]], [[1, 2], [3, 4]], 3)]
          sage: T = crystals.Tableaux(['A',4], shape=[3,2])
          sage: G = T(2,1,4,3,5).dual_equivalence_class()
          sage: G.edges(sort=True)
          [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
           ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
           ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 3),
           ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
           ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
           ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 4)]

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(3)], shape=[Integer(2),Integer(2)])
          >>> G = T(Integer(2),Integer(1),Integer(4),Integer(3)).dual_equivalence_class()
          >>> G.edges(sort=True)
          [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
           ([[1, 3], [2, 4]], [[1, 2], [3, 4]], 3)]
          >>> T = crystals.Tableaux(['A',Integer(4)], shape=[Integer(3),Integer(2)])
          >>> G = T(Integer(2),Integer(1),Integer(4),Integer(3),Integer(5)).dual_equivalence_class()
          >>> G.edges(sort=True)
          [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
           ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
           ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 3),
           ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
           ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
           ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 4)]

    epsilon(i)

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

      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

    phi(i)

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

      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

    stembridgeDel_depth(i, j)

      Return the difference in the \(j\)-depth of `self` and \(f_i\) of `self`, where \(i\) and \(j\) are in the index set of the underlying crystal. This function is useful for checking the Stembridge local axioms for crystal bases.

      The \(i\)-depth of a crystal node \(x\) is \(\varepsilon_i(x)\).

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = T(rows=[[1,1],[2]])
          sage: t.stembridgeDel_depth(1,2)
          0
          sage: s = T(rows=[[1,3],[3]])
          sage: s.stembridgeDel_depth(1,2)
          -1

      Python

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

    stembridgeDel_rise(i, j)

      Return the difference in the \(j\)-rise of `self` and \(f_i\) of `self`, where \(i\) and \(j\) are in the index set of the underlying crystal. This function is useful for checking the Stembridge local axioms for crystal bases.

      The \(i\)-rise of a crystal node \(x\) is \(\varphi_i(x)\).

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = T(rows=[[1,1],[2]])
          sage: t.stembridgeDel_rise(1,2)
          -1
          sage: s = T(rows=[[1,3],[3]])
          sage: s.stembridgeDel_rise(1,2)
          0

      Python

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

    stembridgeDelta_depth(i, j)

      Return the difference in the \(j\)-depth of `self` and \(e_i\) of `self`, where \(i\) and \(j\) are in the index set of the underlying crystal. This function is useful for checking the Stembridge local axioms for crystal bases.

      The \(i\)-depth of a crystal node \(x\) is \(-\varepsilon_i(x)\).

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = T(rows=[[1,2],[2]])
          sage: t.stembridgeDelta_depth(1,2)
          0
          sage: s = T(rows=[[2,3],[3]])
          sage: s.stembridgeDelta_depth(1,2)
          -1

      Python

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

    stembridgeDelta_rise(i, j)

      Return the difference in the \(j\)-rise of `self` and \(e_i\) of `self`, where \(i\) and \(j\) are in the index set of the underlying crystal. This function is useful for checking the Stembridge local axioms for crystal bases.

      The \(i\)-rise of a crystal node \(x\) is \(\varphi_i(x)\).

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = T(rows=[[1,2],[2]])
          sage: t.stembridgeDelta_rise(1,2)
          -1
          sage: s = T(rows=[[2,3],[3]])
          sage: s.stembridgeDelta_rise(1,2)
          0

      Python

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

    stembridgeTriple(i, j)

      Let \(A\) be the Cartan matrix of the crystal, \(x\) a crystal element, and let \(i\) and \(j\) be in the index set of the crystal. Further, set `b=stembridgeDelta_depth(x,i,j)`, and `c=stembridgeDelta_rise(x,i,j))`. If `x.e(i)` is non-empty, this function returns the triple \(( A_{ij}, b, c )\); otherwise it returns `None`. By the Stembridge local characterization of crystal bases, one should have \(A_{ij}=b+c\).

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = T(rows=[[1,1],[2]])
          sage: t.stembridgeTriple(1,2)
          sage: s = T(rows=[[1,2],[2]])
          sage: s.stembridgeTriple(1,2)
          (-1, 0, -1)

          sage: T = crystals.Tableaux(['B',2], shape=[2,1])
          sage: t = T(rows=[[1,2],[2]])
          sage: t.stembridgeTriple(1,2)
          (-2, 0, -2)
          sage: s = T(rows=[[-1,-1],[0]])
          sage: s.stembridgeTriple(1,2)
          (-2, -2, 0)
          sage: u = T(rows=[[0,2],[1]])
          sage: u.stembridgeTriple(1,2)
          (-2, -1, -1)

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> t = T(rows=[[Integer(1),Integer(1)],[Integer(2)]])
          >>> t.stembridgeTriple(Integer(1),Integer(2))
          >>> s = T(rows=[[Integer(1),Integer(2)],[Integer(2)]])
          >>> s.stembridgeTriple(Integer(1),Integer(2))
          (-1, 0, -1)

          >>> T = crystals.Tableaux(['B',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> t = T(rows=[[Integer(1),Integer(2)],[Integer(2)]])
          >>> t.stembridgeTriple(Integer(1),Integer(2))
          (-2, 0, -2)
          >>> s = T(rows=[[-Integer(1),-Integer(1)],[Integer(0)]])
          >>> s.stembridgeTriple(Integer(1),Integer(2))
          (-2, -2, 0)
          >>> u = T(rows=[[Integer(0),Integer(2)],[Integer(1)]])
          >>> u.stembridgeTriple(Integer(1),Integer(2))
          (-2, -1, -1)

    weight()

      Return the weight of this crystal element.

      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)

  class MorphismMethods

    Bases: `object`

    is_isomorphism()

      Check if `self` is a crystal isomorphism, which is true if and only if this is a strict embedding with the same number of connected components.

      EXAMPLES:

      Sage

          sage: A21 = RootSystem(['A',2,1])
          sage: La = A21.weight_space(extended=True).fundamental_weights()
          sage: B = crystals.LSPaths(La[0])
          sage: La = A21.weight_lattice(extended=True).fundamental_weights()
          sage: C = crystals.GeneralizedYoungWalls(2, La[0])
          sage: H = Hom(B, C)
          sage: from sage.categories.highest_weight_crystals import HighestWeightCrystalMorphism
          sage: class Psi(HighestWeightCrystalMorphism):
          ....:     def is_strict(self):
          ....:         return True
          sage: psi = Psi(H, C.module_generators); psi
          ['A', 2, 1] Crystal morphism:
            From: The crystal of LS paths of type ['A', 2, 1] and weight Lambda[0]
            To:   Highest weight crystal of generalized Young walls
                  of Cartan type ['A', 2, 1] and highest weight Lambda[0]
            Defn: (Lambda[0],) |--> []
          sage: psi.is_isomorphism()
          True

      Python

          >>> from sage.all import *
          >>> A21 = RootSystem(['A',Integer(2),Integer(1)])
          >>> La = A21.weight_space(extended=True).fundamental_weights()
          >>> B = crystals.LSPaths(La[Integer(0)])
          >>> La = A21.weight_lattice(extended=True).fundamental_weights()
          >>> C = crystals.GeneralizedYoungWalls(Integer(2), La[Integer(0)])
          >>> H = Hom(B, C)
          >>> from sage.categories.highest_weight_crystals import HighestWeightCrystalMorphism
          >>> class Psi(HighestWeightCrystalMorphism):
          ...     def is_strict(self):
          ...         return True
          >>> psi = Psi(H, C.module_generators); psi
          ['A', 2, 1] Crystal morphism:
            From: The crystal of LS paths of type ['A', 2, 1] and weight Lambda[0]
            To:   Highest weight crystal of generalized Young walls
                  of Cartan type ['A', 2, 1] and highest weight Lambda[0]
            Defn: (Lambda[0],) |--> []
          >>> psi.is_isomorphism()
          True

  class ParentMethods

    Bases: `object`

    demazure_operator(element, reduced_word)

      Return the application of Demazure operators \(D_i\) for \(i\) from `reduced_word` on `element`.

      INPUT:

      - `element` – an element of a free module indexed by the underlying crystal

      - `reduced_word` – a reduced word of the Weyl group of the same type as the underlying crystal

      OUTPUT: an element of the free module indexed by the underlying crystal

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: C = CombinatorialFreeModule(QQ, T)                                # needs sage.modules
          sage: t = T.highest_weight_vector()
          sage: b = 2*C(t)                                                        # needs sage.modules
          sage: T.demazure_operator(b,[1,2,1])                                    # needs sage.modules
          2*B[[[1, 1], [2]]] + 2*B[[[1, 2], [2]]] + 2*B[[[1, 3], [2]]]
          + 2*B[[[1, 1], [3]]] + 2*B[[[1, 2], [3]]] + 2*B[[[1, 3], [3]]]
          + 2*B[[[2, 2], [3]]] + 2*B[[[2, 3], [3]]]

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> C = CombinatorialFreeModule(QQ, T)                                # needs sage.modules
          >>> t = T.highest_weight_vector()
          >>> b = Integer(2)*C(t)                                                        # needs sage.modules
          >>> T.demazure_operator(b,[Integer(1),Integer(2),Integer(1)])                                    # needs sage.modules
          2*B[[[1, 1], [2]]] + 2*B[[[1, 2], [2]]] + 2*B[[[1, 3], [2]]]
          + 2*B[[[1, 1], [3]]] + 2*B[[[1, 2], [3]]] + 2*B[[[1, 3], [3]]]
          + 2*B[[[2, 2], [3]]] + 2*B[[[2, 3], [3]]]

      The Demazure operator is idempotent:

      Sage

          sage: # needs sage.modules
          sage: T = crystals.Tableaux("A1", shape=[4])
          sage: C = CombinatorialFreeModule(QQ, T)
          sage: b = C(T.module_generators[0]); b
          B[[[1, 1, 1, 1]]]
          sage: e = T.demazure_operator(b,[1]); e
          B[[[1, 1, 1, 1]]] + B[[[1, 1, 1, 2]]] + B[[[1, 1, 2, 2]]]
          + B[[[1, 2, 2, 2]]] + B[[[2, 2, 2, 2]]]
          sage: e == T.demazure_operator(e,[1])
          True
          sage: all(T.demazure_operator(T.demazure_operator(C(t),[1]),[1])
          ....:      == T.demazure_operator(C(t),[1]) for t in T)
          True

      [Python]

          >>> from sage.all import *
          >>> # needs sage.modules
          >>> T = crystals.Tableaux("A1", shape=[Integer(4)])
          >>> C = CombinatorialFreeModule(QQ, T)
          >>> b = C(T.module_generators[Integer(0)]); b
          B[[[1, 1, 1, 1]]]
          >>> e = T.demazure_operator(b,[Integer(1)]); e
          B[[[1, 1, 1, 1]]] + B[[[1, 1, 1, 2]]] + B[[[1, 1, 2, 2]]]
          + B[[[1, 2, 2, 2]]] + B[[[2, 2, 2, 2]]]
          >>> e == T.demazure_operator(e,[Integer(1)])
          True
          >>> all(T.demazure_operator(T.demazure_operator(C(t),[Integer(1)]),[Integer(1)])
          ...      == T.demazure_operator(C(t),[Integer(1)]) for t in T)
          True

    demazure_subcrystal(element, reduced_word, only_support=True)

      Return the subcrystal corresponding to the application of Demazure operators \(D_i\) for \(i\) from `reduced_word` on `element`.

      INPUT:

      - `element` – an element of a free module indexed by the underlying crystal

      - `reduced_word` – a reduced word of the Weyl group of the same type as the underlying crystal

      - `only_support` – boolean (default: `True`); only include arrows corresponding to the support of `reduced_word`

      OUTPUT: the Demazure subcrystal

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',2], shape=[2,1])
          sage: t = T.highest_weight_vector()
          sage: S = T.demazure_subcrystal(t, [1,2])
          sage: list(S)
          [[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
           [[1, 2], [3]], [[2, 2], [3]]]
          sage: S = T.demazure_subcrystal(t, [2,1])
          sage: list(S)
          [[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
           [[1, 3], [2]], [[1, 3], [3]]]

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(2)], shape=[Integer(2),Integer(1)])
          >>> t = T.highest_weight_vector()
          >>> S = T.demazure_subcrystal(t, [Integer(1),Integer(2)])
          >>> list(S)
          [[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
           [[1, 2], [3]], [[2, 2], [3]]]
          >>> S = T.demazure_subcrystal(t, [Integer(2),Integer(1)])
          >>> list(S)
          [[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
           [[1, 3], [2]], [[1, 3], [3]]]

      We construct an example where we don’t only want the arrows indicated by the support of the reduced word:

      Sage

          sage: K = crystals.KirillovReshetikhin(['A',1,1], 1, 2)
          sage: mg = K.module_generator()
          sage: S = K.demazure_subcrystal(mg, [1])
          sage: S.digraph().edges(sort=True)
          [([[1, 1]], [[1, 2]], 1), ([[1, 2]], [[2, 2]], 1)]
          sage: S = K.demazure_subcrystal(mg, [1], only_support=False)
          sage: S.digraph().edges(sort=True)
          [([[1, 1]], [[1, 2]], 1),
           ([[1, 2]], [[1, 1]], 0),
           ([[1, 2]], [[2, 2]], 1),
           ([[2, 2]], [[1, 2]], 0)]

      [Python]

          >>> from sage.all import *
          >>> K = crystals.KirillovReshetikhin(['A',Integer(1),Integer(1)], Integer(1), Integer(2))
          >>> mg = K.module_generator()
          >>> S = K.demazure_subcrystal(mg, [Integer(1)])
          >>> S.digraph().edges(sort=True)
          [([[1, 1]], [[1, 2]], 1), ([[1, 2]], [[2, 2]], 1)]
          >>> S = K.demazure_subcrystal(mg, [Integer(1)], only_support=False)
          >>> S.digraph().edges(sort=True)
          [([[1, 1]], [[1, 2]], 1),
           ([[1, 2]], [[1, 1]], 0),
           ([[1, 2]], [[2, 2]], 1),
           ([[2, 2]], [[1, 2]], 0)]

    dual_equivalence_graph(X=None, index_set=None, directed=True)

      Return the dual equivalence graph indexed by `index_set` on the subset `X` of `self`.

      Let \(b \in B\) be an element of weight \(0\), so \(\varepsilon_j(b) = \varphi_j(b)\) for all \(j \in I\), where \(I\) is the indexing set. We say \(b'\) is an \(i\)-elementary dual equivalence transformation of \(b\) (where \(i \in I\)) if

      - \(\varepsilon_i(b) = 1\) and \(\varepsilon_{i-1}(b) = 0\), and

      - \(b' = f_{i-1} f_i e_{i-1} e_i b\).

      We can do the inverse procedure by interchanging \(i\) and \(i-1\) above.

      Note

      If the index set is not an ordered interval, we let \(i - 1\) mean the index appearing before \(i\) in \(I\).

      This definition comes from [As2008] Section 4 (where our \(\varphi_j(b)\) and \(\varepsilon_j(b)\) are denoted by \(\epsilon(b, j)\) and \(-\delta(b, j)\), respectively).

      The dual equivalence graph of \(B\) is defined to be the colored graph whose vertices are the elements of \(B\) of weight \(0\), and whose edges of color \(i\) (for \(i \in I\)) connect pairs \(\{ b, b' \}\) such that \(b'\) is an \(i\)-elementary dual equivalence transformation of \(b\).

      Note

      This dual equivalence graph is a generalization of \(\mathcal{G}\left(\mathcal{X}\right)\) in [As2008] Section 4 except we do not require \(\varepsilon_i(b) = 0, 1\) for all \(i\).

      This definition can be generalized by choosing a subset \(X\) of the set of all vertices of \(B\) of weight \(0\), and restricting the dual equivalence graph to the vertex set \(X\).

      INPUT:

      - `X` – (optional) the vertex set \(X\) (default: the whole set of vertices of `self` of weight \(0\))

      - `index_set` – (optional) the index set \(I\) (default: the whole index set of `self`); this has to be a subset of the index set of `self` (as a list or tuple)

      - `directed` – boolean (default: `True`); whether to have the dual equivalence graph be directed, where the head of an edge \(b - b'\) is \(b\) and the tail is \(b' = f_{i-1} f_i e_{i-1} e_i b\))

      See also

      `sage.combinat.partition.Partition.dual_equivalence_graph()`

      EXAMPLES:

      Sage

          sage: T = crystals.Tableaux(['A',3], shape=[2,2])
          sage: G = T.dual_equivalence_graph()
          sage: G.edges(sort=True)
          [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
           ([[1, 2], [3, 4]], [[1, 3], [2, 4]], 3)]
          sage: T = crystals.Tableaux(['A',4], shape=[3,2])
          sage: G = T.dual_equivalence_graph()
          sage: G.edges(sort=True)
          [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
           ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
           ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
           ([[1, 2, 5], [3, 4]], [[1, 3, 5], [2, 4]], 3),
           ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
           ([[1, 2, 3], [4, 5]], [[1, 2, 4], [3, 5]], 4)]

          sage: T = crystals.Tableaux(['A',4], shape=[3,1])
          sage: G = T.dual_equivalence_graph(index_set=[1,2,3])
          sage: G.vertices(sort=True)
          [[[1, 3, 4], [2]], [[1, 2, 4], [3]], [[1, 2, 3], [4]]]
          sage: G.edges(sort=True)
          [([[1, 3, 4], [2]], [[1, 2, 4], [3]], 2),
           ([[1, 2, 4], [3]], [[1, 2, 3], [4]], 3)]

      Python

          >>> from sage.all import *
          >>> T = crystals.Tableaux(['A',Integer(3)], shape=[Integer(2),Integer(2)])
          >>> G = T.dual_equivalence_graph()
          >>> G.edges(sort=True)
          [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
           ([[1, 2], [3, 4]], [[1, 3], [2, 4]], 3)]
          >>> T = crystals.Tableaux(['A',Integer(4)], shape=[Integer(3),Integer(2)])
          >>> G = T.dual_equivalence_graph()
          >>> G.edges(sort=True)
          [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
           ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
           ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
           ([[1, 2, 5], [3, 4]], [[1, 3, 5], [2, 4]], 3),
           ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
           ([[1, 2, 3], [4, 5]], [[1, 2, 4], [3, 5]], 4)]

          >>> T = crystals.Tableaux(['A',Integer(4)], shape=[Integer(3),Integer(1)])
          >>> G = T.dual_equivalence_graph(index_set=[Integer(1),Integer(2),Integer(3)])
          >>> G.vertices(sort=True)
          [[[1, 3, 4], [2]], [[1, 2, 4], [3]], [[1, 2, 3], [4]]]
          >>> G.edges(sort=True)
          [([[1, 3, 4], [2]], [[1, 2, 4], [3]], 2),
           ([[1, 2, 4], [3]], [[1, 2, 3], [4]], 3)]

  class TensorProducts(category, *args)

    Bases: `TensorProductsCategory`

    The category of regular crystals constructed by tensor product of regular crystals.

    extra_super_categories()

      EXAMPLES:

      Sage

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

      Python

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

  additional_structure()

    Return `None`.

    Indeed, the category of regular crystals defines no new structure: it only relates \(\varepsilon_a\) and \(\varphi_a\) to \(e_a\) and \(f_a\) respectively.

    See also

    `Category.additional_structure()`

    Todo

    Should this category be a `CategoryWithAxiom`?

    EXAMPLES:

    Sage

        sage: RegularCrystals().additional_structure()

    Python

        >>> from sage.all import *
        >>> RegularCrystals().additional_structure()

  example(n=3)

    Return an example of highest weight crystals, as per `Category.example()`.

    EXAMPLES:

    Sage

        sage: B = RegularCrystals().example(); B
        Highest weight crystal of type A_3 of highest weight omega_1

    Python

        >>> from sage.all import *
        >>> B = RegularCrystals().example(); B
        Highest weight crystal of type A_3 of highest weight omega_1

  super_categories()

    EXAMPLES:

    Sage

        sage: RegularCrystals().super_categories()
        [Category of crystals]

    Python

        >>> from sage.all import *
        >>> RegularCrystals().super_categories()
        [Category of crystals]