Virtual crystals - Combinatorics

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

# Virtual crystals

These are the crystals that are subsets of a larger ambient crystal with virtual crystal operators.

AUTHORS:

- Travis Scrimshaw (2013-10-16): initial implementation

class sage.combinat.crystals.virtual_crystal.VirtualCrystal(ambient, virtualization, scaling_factors, contained, generators, cartan_type, index_set, category)

  Bases: `Subcrystal`

  A virtual crystal \(V\) of an ambient crystal \(\widehat{B}\) is a crystal formed by taking a subset of \(\widehat{B}\) and whose crystal structure is given by

  \[e_i = \prod_{j \in \sigma_i} \widehat{e}_j^{\gamma_i}, \quad f_i = \prod_{j \in \sigma_i} \widehat{f}_j^{\gamma_i},\]
  \[\varepsilon_i = \frac{\widehat{\varepsilon}_j}{\gamma_j}, \quad \varphi_i = \frac{\widehat{\varphi}_j}{\gamma_j}, \quad \operatorname{wt} = \Psi^{-1} \circ \widehat{\operatorname{wt}}\]

  where \(\sigma_i\) is a subset of the index set of \(B\), \(\gamma_i \in \ZZ\) are the scaling factors, and \(\Psi : P \to \widehat{P}\) is an embedding of the weight lattices. We note that for the crystal to be well-defined, we must have

  \[\widehat{\varepsilon}_j = \widehat{\varepsilon|j^{\prime}}, \quad \widehat{\varphi}_j = \widehat{\varphi}_{j^{\prime}}\]

  for all \(j, j^{\prime} \in \sigma_i\) and that the order that the Kashiwara operators in the ambient space are applied does not affect the result.

  INPUT:

  - `ambient` – the ambient crystal

  - `virtualization` – dictionary whose key \(i\) corresponds to the set \(\sigma_i\)

  - `scaling_factors` – dictionary whose key \(i\) corresponds to the scaling factor \(\gamma_i\)

  - `contained` – (optional) a set (or function) which specifies when an element is contained in the subcrystal; the default is everything possible is included

  - `generators` – (optional) the generators for the virtual crystal; the default is the generators for the ambient crystal

  - `cartan_type` – (optional) the Cartan type for the virtual crystal; the default is the Cartan type for the ambient crystal

  - `index_set` – (optional) the index set for the virtual crystal; the default is the index set for the Cartan type

  - `category` – (optional) the category for the virtual crystal; the default is the `Crystals` category

  EXAMPLES:

  We construct an example from a natural virtualization map of type \(C_n\) in type \(A_{2n-1}\):

  Sage

      sage: C = crystals.Tableaux(['C',2], shape=[1])
      sage: A = crystals.Tableaux(['A',3], shape=[2,1,1])
      sage: psi = C.crystal_morphism(A.module_generators)
      sage: V = psi.image()
      sage: list(V)
      [[[1, 1], [2], [3]],
       [[1, 2], [2], [4]],
       [[1, 3], [3], [4]],
       [[2, 4], [3], [4]]]
      sage: V.digraph().is_isomorphic(C.digraph(), edge_labels=True)
      True

  Python

      >>> from sage.all import *
      >>> C = crystals.Tableaux(['C',Integer(2)], shape=[Integer(1)])
      >>> A = crystals.Tableaux(['A',Integer(3)], shape=[Integer(2),Integer(1),Integer(1)])
      >>> psi = C.crystal_morphism(A.module_generators)
      >>> V = psi.image()
      >>> list(V)
      [[[1, 1], [2], [3]],
       [[1, 2], [2], [4]],
       [[1, 3], [3], [4]],
       [[2, 4], [3], [4]]]
      >>> V.digraph().is_isomorphic(C.digraph(), edge_labels=True)
      True

  We construct the virtualization of a \(U_q'(\mathfrak{g})\)-crystal \(B^{r,s}\) of type \(C_n^{(1)}\) in type \(A_{2n+1}^{(2)}\). Here it is not a default folding known to Sage, so we have to explicitly state the folding (since the scaling factors are not specified, they are all assumed to be 1):

  Sage

      sage: K = crystals.KirillovReshetikhin(['C',2,1], 1,1)
      sage: VK = crystals.KirillovReshetikhin(['A',5,2], 1,1)
      sage: target = VK.module_generator().f(1); target
      [[2]]
      sage: psi = K.crystal_morphism({K.module_generator(): target},
      ....:                          virtualization={0:[0,1], 1:[2], 2:[3]})
      sage: V = psi.image()
      sage: list(V)
      [[[2]], [[3]], [[-2]], [[-3]]]
      sage: V.digraph().is_isomorphic(K.digraph(), edge_labels=True)
      True

  [Python]

      >>> from sage.all import *
      >>> K = crystals.KirillovReshetikhin(['C',Integer(2),Integer(1)], Integer(1),Integer(1))
      >>> VK = crystals.KirillovReshetikhin(['A',Integer(5),Integer(2)], Integer(1),Integer(1))
      >>> target = VK.module_generator().f(Integer(1)); target
      [[2]]
      >>> psi = K.crystal_morphism({K.module_generator(): target},
      ...                          virtualization={Integer(0):[Integer(0),Integer(1)], Integer(1):[Integer(2)], Integer(2):[Integer(3)]})
      >>> V = psi.image()
      >>> list(V)
      [[[2]], [[3]], [[-2]], [[-3]]]
      >>> V.digraph().is_isomorphic(K.digraph(), edge_labels=True)
      True

  We create an example of \(B(\Lambda_n)\) of type \(B_n\) inside of \(B(2\Lambda_n)\) using the doubling map through the (virtual) subcrystal method:

  Sage

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

  Python

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

  We can also directly construct a virtual crystal using `VirtualCrystal` (however it is recommended to use either `crystal_morphism()` or `subcrystal()`):

  Sage

      sage: from sage.combinat.crystals.virtual_crystal import VirtualCrystal
      sage: A = crystals.Tableaux(['A',3], shape=[2,1,1])
      sage: V = VirtualCrystal(A, {1:(1,3), 2:(2,)}, {1:1, 2:2}, cartan_type=['C',2])
      sage: G = crystals.Tableaux(['C',2], shape=[1]).digraph()
      sage: V.digraph().is_isomorphic(G, edge_labels=True)
      True

      sage: C1 = crystals.Tableaux(['A',3], shape=[1])
      sage: C2 = crystals.Tableaux(['A',3], shape=[1,1,1])
      sage: T = C1.tensor(C2)
      sage: mg = T(C1.module_generators[0], C2.module_generators[0])
      sage: V = VirtualCrystal(A, {1:(1,3), 2:(2,)}, {1:1, 2:2},
      ....:                    cartan_type=['C',2], generators=[mg])
      sage: V.digraph().is_isomorphic(G, edge_labels=True)
      True

  [Python]

      >>> from sage.all import *
      >>> from sage.combinat.crystals.virtual_crystal import VirtualCrystal
      >>> A = crystals.Tableaux(['A',Integer(3)], shape=[Integer(2),Integer(1),Integer(1)])
      >>> V = VirtualCrystal(A, {Integer(1):(Integer(1),Integer(3)), Integer(2):(Integer(2),)}, {Integer(1):Integer(1), Integer(2):Integer(2)}, cartan_type=['C',Integer(2)])
      >>> G = crystals.Tableaux(['C',Integer(2)], shape=[Integer(1)]).digraph()
      >>> V.digraph().is_isomorphic(G, edge_labels=True)
      True

      >>> C1 = crystals.Tableaux(['A',Integer(3)], shape=[Integer(1)])
      >>> C2 = crystals.Tableaux(['A',Integer(3)], shape=[Integer(1),Integer(1),Integer(1)])
      >>> T = C1.tensor(C2)
      >>> mg = T(C1.module_generators[Integer(0)], C2.module_generators[Integer(0)])
      >>> V = VirtualCrystal(A, {Integer(1):(Integer(1),Integer(3)), Integer(2):(Integer(2),)}, {Integer(1):Integer(1), Integer(2):Integer(2)},
      ...                    cartan_type=['C',Integer(2)], generators=[mg])
      >>> V.digraph().is_isomorphic(G, edge_labels=True)
      True

  REFERENCES:

  - [FOS2009]

  - [OSS03]

  - [OSS2003]

  class Element

    Bases: `Element`

    An element of a virtual (sub)crystal. Wraps an element in the ambient crystal.

    e(i)

      Return \(e_i\) of `self`.

      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: V = psi.image()
          sage: mg = V.module_generators[0]
          sage: mg.e(1)
          sage: b = psi(B.module_generators[0].f(1))
          sage: V(b).e(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)])
          >>> psi = B.crystal_morphism(C.module_generators)
          >>> V = psi.image()
          >>> mg = V.module_generators[Integer(0)]
          >>> mg.e(Integer(1))
          >>> b = psi(B.module_generators[Integer(0)].f(Integer(1)))
          >>> V(b).e(Integer(1))
          [[1, 1]]

    epsilon(i)

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

      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: V = psi.image()
          sage: mg = V.module_generators[0]
          sage: mg.epsilon(2)
          0
          sage: mg.f(1).epsilon(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)])
          >>> psi = B.crystal_morphism(C.module_generators)
          >>> V = psi.image()
          >>> mg = V.module_generators[Integer(0)]
          >>> mg.epsilon(Integer(2))
          0
          >>> mg.f(Integer(1)).epsilon(Integer(1))
          1

    f(i)

      Return \(f_i\) of `self`.

      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: V = psi.image()
          sage: mg = V.module_generators[0]
          sage: mg.f(1)
          [[2, 2]]
          sage: mg.f(2)

      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)
          >>> V = psi.image()
          >>> mg = V.module_generators[Integer(0)]
          >>> mg.f(Integer(1))
          [[2, 2]]
          >>> mg.f(Integer(2))

    phi(i)

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

      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: V = psi.image()
          sage: mg = V.module_generators[0]
          sage: mg.phi(1)
          1
          sage: mg.phi(2)
          0

      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)
          >>> V = psi.image()
          >>> mg = V.module_generators[Integer(0)]
          >>> mg.phi(Integer(1))
          1
          >>> mg.phi(Integer(2))
          0

    weight()

      Return the weight of `self`.

      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: V = psi.image()
          sage: mg = V.module_generators[0]
          sage: mg.weight()
          (1, 0, 0)
          sage: mg.f(1).weight()
          (0, 1, 0)
          sage: all(V(psi(x)).weight() == x.weight() for x in B)
          True

      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)
          >>> V = psi.image()
          >>> mg = V.module_generators[Integer(0)]
          >>> mg.weight()
          (1, 0, 0)
          >>> mg.f(Integer(1)).weight()
          (0, 1, 0)
          >>> all(V(psi(x)).weight() == x.weight() for x in B)
          True

  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: V = psi.image()
        sage: V.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)
        >>> V = psi.image()
        >>> V.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: V = psi.image()
        sage: V.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)
        >>> V = psi.image()
        >>> V.virtualization()
        Finite family {1: (1,), 2: (2,), 3: (3, 4)}