Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Alcove paths
AUTHORS:
- Brant Jones (2008): initial version - Arthur Lubovsky (2013-03-07): rewritten to implement affine type - Travis Scrimshaw (2016-06-23): implemented `\mathcal{B}(\infty)`
Special thanks to: Nicolas Borie, Anne Schilling, Travis Scrimshaw, and Nicolas Thiery. """
#***************************************************************************** # Copyright (C) 2008 Brant Jones <brant at math.ucdavis.edu> # Copyright (C) 2013 Arthur Lubovsky <alubovsky at albany.edu> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function
from sage.structure.parent import Parent from sage.structure.element import Element from sage.structure.element_wrapper import ElementWrapper from sage.structure.unique_representation import UniqueRepresentation from sage.structure.richcmp import richcmp from sage.categories.finite_crystals import FiniteCrystals from sage.categories.classical_crystals import ClassicalCrystals from sage.categories.loop_crystals import LoopCrystals from sage.graphs.all import DiGraph from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.root_system import RootSystem from sage.all import vector from sage.rings.integer import Integer from sage.combinat.root_system.weyl_group import WeylGroup from sage.misc.misc_c import prod from sage.categories.sets_cat import Sets from sage.misc.cachefunc import cached_method, cached_in_parent_method from sage.categories.highest_weight_crystals import HighestWeightCrystals from copy import copy from sage.misc.latex import latex
class CrystalOfAlcovePaths(UniqueRepresentation, Parent): r""" Crystal of alcove paths generated from a "straight-line" path to the negative of a given dominant weight.
INPUT:
- ``cartan_type`` -- Cartan type of a finite or affine untwisted root system.
- ``weight`` -- Dominant weight as a list of (integral) coefficients of the fundamental weights.
- ``highest_weight_crystal`` -- (Default: ``True``) If ``True`` returns the highest weight crystal. If ``False`` returns an object which is close to being isomorphic to the tensor product of Kirillov-Reshetikhin crystals of column shape in the following sense: We get all the vertices, but only some of the edges. We'll call the included edges pseudo-Demazure. They are all non-zero edges and the 0-edges not at the end of a 0-string of edges, i.e. not those with `f_{0}(b) = b'` with `\varphi_0(b) =1`. (Whereas Demazure 0-edges are those that are not at the beginning of a zero string.) In this case the weight `[c_1, c_2, \ldots, c_k]` represents `\sum_{i=1}^k c_i \omega_i`.
.. NOTE::
If ``highest_weight_crystal`` = ``False``, since we do not get the full crystal, ``TestSuite`` will fail on the Stembridge axioms.
.. SEEALSO::
- :class:`Crystals`
EXAMPLES:
The following example appears in Figure 2 of [LP2008]_::
sage: C = crystals.AlcovePaths(['G',2],[0,1]) sage: G = C.digraph() sage: GG = DiGraph({ ....: () : {(0) : 2 }, ....: (0) : {(0,8) : 1 }, ....: (0,1) : {(0,1,7) : 2 }, ....: (0,1,2) : {(0,1,2,9) : 1 }, ....: (0,1,2,3) : {(0,1,2,3,4) : 2 }, ....: (0,1,2,6) : {(0,1,2,3) : 1 }, ....: (0,1,2,9) : {(0,1,2,6) : 1 }, ....: (0,1,7) : {(0,1,2) : 2 }, ....: (0,1,7,9) : {(0,1,2,9) : 2 }, ....: (0,5) : {(0,1) : 1, (0,5,7) : 2 }, ....: (0,5,7) : {(0,5,7,9) : 1 }, ....: (0,5,7,9) : {(0,1,7,9) : 1 }, ....: (0,8) : {(0,5) : 1 }, ....: }) sage: G.is_isomorphic(GG) True sage: for (u,v,i) in G.edges(): ....: print((u.integer_sequence() , v.integer_sequence(), i)) ([], [0], 2) ([0], [0, 8], 1) ([0, 1], [0, 1, 7], 2) ([0, 1, 2], [0, 1, 2, 9], 1) ([0, 1, 2, 3], [0, 1, 2, 3, 4], 2) ([0, 1, 2, 6], [0, 1, 2, 3], 1) ([0, 1, 2, 9], [0, 1, 2, 6], 1) ([0, 1, 7], [0, 1, 2], 2) ([0, 1, 7, 9], [0, 1, 2, 9], 2) ([0, 5], [0, 1], 1) ([0, 5], [0, 5, 7], 2) ([0, 5, 7], [0, 5, 7, 9], 1) ([0, 5, 7, 9], [0, 1, 7, 9], 1) ([0, 8], [0, 5], 1)
Alcove path crystals are a discrete version of Littelmann paths. We verify that the alcove path crystal is isomorphic to the LS path crystal::
sage: C1 = crystals.AlcovePaths(['C',3],[2,1,0]) sage: g1 = C1.digraph() #long time sage: C2 = crystals.LSPaths(['C',3],[2,1,0]) sage: g2 = C2.digraph() #long time sage: g1.is_isomorphic(g2, edge_labels=True) #long time True
The preferred initialization method is via explicit weights rather than a Cartan type and the coefficients of the fundamental weights::
sage: R = RootSystem(['C',3]) sage: P = R.weight_lattice() sage: La = P.fundamental_weights() sage: C = crystals.AlcovePaths(2*La[1]+La[2]); C Highest weight crystal of alcove paths of type ['C', 3] and weight 2*Lambda[1] + Lambda[2] sage: C1==C True
We now explain the data structure::
sage: C = crystals.AlcovePaths(['A',2],[2,0]) ; C Highest weight crystal of alcove paths of type ['A', 2] and weight 2*Lambda[1] sage: C._R.lambda_chain() [(alpha[1], 0), (alpha[1] + alpha[2], 0), (alpha[1], 1), (alpha[1] + alpha[2], 1)]
The previous list gives the initial "straight line" path from the fundamental alcove `A_o` to its translation `A_o - \lambda` where `\lambda = 2\omega_1` in this example. The initial path for weight `\lambda` is called the `\lambda`-chain. This path is constructed from the ordered pairs `(\beta, k)`, by crossing the hyperplane orthogonal to `\beta` at height `-k`. We can view a plot of this path as follows::
sage: x=C( () ) sage: x.plot() # not tested - outputs a pdf
An element of the crystal is given by a subset of the `\lambda`-chain. This subset indicates the hyperplanes where the initial path should be folded. The highest weight element is given by the empty subset. ::
sage: x () sage: x.f(1).f(2) ((alpha[1], 1), (alpha[1] + alpha[2], 1)) sage: x.f(1).f(2).integer_sequence() [2, 3] sage: C([2,3]) ((alpha[1], 1), (alpha[1] + alpha[2], 1)) sage: C([2,3]).is_admissible() #check if a valid vertex True sage: C([1,3]).is_admissible() #check if a valid vertex False
Alcove path crystals now works in affine type (:trac:`14143`)::
sage: C = crystals.AlcovePaths(['A',2,1],[1,0,0]) ; C Highest weight crystal of alcove paths of type ['A', 2, 1] and weight Lambda[0] sage: x=C( () ) sage: x.f(0) ((alpha[0], 0),) sage: C.R Root system of type ['A', 2, 1] sage: C.weight Lambda[0]
Test that the tensor products of Kirillov-Reshetikhin crystals minus non-pseudo-Demazure arrows is in bijection with alcove path construction::
sage: K = crystals.KirillovReshetikhin(['B',3,1],2,1) sage: T = crystals.TensorProduct(K,K) sage: g = T.digraph() #long time sage: for e in g.edges(): #long time ....: if e[0].phi(0) == 1 and e[2] == 0: #long time ....: g.delete_edge(e) #long time
sage: C = crystals.AlcovePaths(['B',3,1],[0,2,0], highest_weight_crystal=False) sage: g2 = C.digraph() #long time sage: g.is_isomorphic(g2, edge_labels = True) #long time True
.. NOTE::
In type `C_n^{(1)}`, the Kirillov-Reshetikhin crystal is not connected when restricted to pseudo-Demazure arrows, hence the previous example will fail for type `C_n^{(1)}` crystals.
::
sage: R = RootSystem(['B',3]) sage: P = R.weight_lattice() sage: La = P.fundamental_weights() sage: D = crystals.AlcovePaths(2*La[2], highest_weight_crystal=False) sage: C == D True
.. WARNING:: Weights from finite root systems index non-highest weight crystals.
REFERENCES:
.. [LP2008] \C. Lenart and A. Postnikov. *A combinatorial model for crystals of Kac-Moody algebras*. Trans. Amer. Math. Soc. 360 (2008), 4349-4381. """
@staticmethod def __classcall_private__(cls, starting_weight, cartan_type=None, highest_weight_crystal=None): """ Classcall to mend the input.
Internally, the :class:`~sage.combinat.crystals.alcove_path.CrystalOfAlcovePaths` code works with a ``starting_weight`` that is in the weight space associated to the crystal. The user can, however, also input a ``cartan_type`` and the coefficients of the fundamental weights as ``starting_weight``. This code transforms the input into the right format (also necessary for :class:`UniqueRepresentation`).
TESTS::
sage: C = crystals.AlcovePaths(['A',2,1], [1,0,0]) sage: C2 = crystals.AlcovePaths(CartanType(['A',2,1]), (1,0,0)) sage: C is C2 True sage: R = RootSystem(['B',2,1]) sage: La = R.weight_space().basis() sage: B1 = crystals.AlcovePaths(['B',2,1],[0,0,1]) sage: B2 = crystals.AlcovePaths(La[2]) sage: B1 is B2 True """
#switch positional arguments
raise ValueError("non-highest weight crystals only valid for affine types")
else:
#set defaults
raise ValueError("{0} is not a dominant weight".format(starting_weight))
starting_weight, highest_weight_crystal)
def __init__(self, starting_weight, highest_weight_crystal): r""" Initialize ``self``.
TESTS::
sage: C = crystals.AlcovePaths(['G',2],[0,1]) sage: TestSuite(C).run()
sage: C = crystals.AlcovePaths(['A',2,1],[1,0,0]) sage: TestSuite(C).run() #long time
sage: C = crystals.AlcovePaths(['A',2,1],[1,0],False) sage: TestSuite(C).run(skip="_test_stembridge_local_axioms") #long time
Check that :trac:`20292` is fixed::
sage: A = crystals.AlcovePaths(['A',2], [1,0]) sage: A.category() Category of classical crystals """ ########################################################################## # NOTE: # If cartan_type.is_affine() == True and highest weight crystal == False, # since we only use the positive roots of the *finite* root system # to get the crystal we set self._finite_cartan_type is true # # We want the indexing set to include 0 so use the affine type notation # for the Cartan type. ##########################################################################
else:
def _repr_(self): """ Return a string representation of ``self``.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2,1], [1,0,0]) sage: C Highest weight crystal of alcove paths of type ['A', 2, 1] and weight Lambda[0] sage: C = crystals.AlcovePaths(['A',2,1], [1,0], False) sage: C Crystal of alcove paths of type ['A', 2, 1] and weight Lambda[1] """
def _element_constructor_(self, data): """ Construct an element of ``self`` from ``data``.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[3,2]) sage: C([8,9]) ((alpha[1], 2), (alpha[1] + alpha[2], 4)) """ #data starts indexing at 0
def vertices(self): """ Return a list of all the vertices of the crystal.
The vertices are represented as lists of integers recording the folding positions.
One can compute all vertices of the crystal by finding all the admissible subsets of the `\lambda`-chain (see method is_admissible, for definition). We use the breath first search algorithm.
.. WARNING::
This method is (currently) only useful for the case when ``highest_weight_crystal = False``, where you cannot always reach all vertices of the crystal using crystal operators, starting from the highest weight vertex. This method is typically slower than generating the crystal graph using crystal operators.
EXAMPLES::
sage: C = crystals.AlcovePaths(['C',2],[1,0]) sage: C.vertices() [[], [0], [0, 1], [0, 1, 2]] sage: C = crystals.AlcovePaths(['C',2,1],[2,1],False) sage: len(C.vertices()) 80
The number of elements reachable using the crystal operators from the module generator::
sage: len(list(C)) 55 """
else:
# lst contains ordered pairs (w,l) l= list of positions that get # you to the word, it needs to be refreshed
#initialization
[ s[k] for k in lambda_chain[j].root.associated_reflection() ]) else :
def digraph_fast(self, depth=None): r""" Return the crystal :class:`graph <DiGraph>` with maximum depth ``depth`` deep starting at the module generator.
Deprecated in :trac:`19625`.
EXAMPLES::
sage: crystals.AlcovePaths(['A',2], [1,1]).digraph_fast(depth=3) doctest:...: DeprecationWarning: digraph_fast is deprecated. Use digraph instead. See http://trac.sagemath.org/19625 for details. Digraph on 7 vertices """ return super(CrystalOfAlcovePaths, self).digraph()
class CrystalOfAlcovePathsElement(ElementWrapper): """ Crystal of alcove paths element.
INPUT:
- ``data`` -- a list of folding positions in the lambda chain (indexing starts at 0) or a tuple of :class:`RootsWithHeight` giving folding positions in the lambda chain.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[3,2]) sage: x = C ( () ) sage: x.f(1).f(2) ((alpha[1], 2), (alpha[1] + alpha[2], 4)) sage: x.f(1).f(2).integer_sequence() [8, 9] sage: C([8,9]) ((alpha[1], 2), (alpha[1] + alpha[2], 4)) """ def __iter__(self): r""" Initialize ``self``.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[1,0]) sage: lst = list(C) sage: for i in lst[2]: i (alpha[1], 0) (alpha[1] + alpha[2], 0) """
def is_admissible(self): r""" Diagnostic test to check if ``self`` is a valid element of the crystal.
If ``self.value`` is given by
.. MATH::
(\beta_1, i_1), (\beta_2, i_2), \ldots, (\beta_k, i_k),
for highest weight crystals this checks if the sequence
.. MATH::
1 \rightarrow s_{\beta_1} \rightarrow s_{\beta_1}s_{\beta_2} \rightarrow \cdots \rightarrow s_{\beta_1}s_{\beta_2} \ldots s_{\beta_k}
is a path in the Bruhat graph. If ``highest_weight_crystal=False``, then the method checks if the above sequence is a path in the quantum Bruhat graph.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[1,1]); C Highest weight crystal of alcove paths of type ['A', 2] and weight Lambda[1] + Lambda[2] sage: roots = sorted(list(C._R._root_lattice.positive_roots())); roots [alpha[1], alpha[1] + alpha[2], alpha[2]] sage: r1 = C._R(roots[0],0); r1 (alpha[1], 0) sage: r2 = C._R(roots[2],0); r2 (alpha[2], 0) sage: r3 = C._R(roots[1],1); r3 (alpha[1] + alpha[2], 1) sage: x = C( ( r1,r2) ) sage: x.is_admissible() True sage: x = C( (r3,) ); x ((alpha[1] + alpha[2], 1),) sage: x.is_admissible() False sage: C = crystals.AlcovePaths(['C',2,1],[2,1],False) sage: C([7,8]).is_admissible() True sage: C = crystals.AlcovePaths(['A',2],[3,2]) sage: C([2,3]).is_admissible() True
.. TODO:: Better doctest """
else:
#start at the identity
def _latex_(self): r""" Return a `\LaTeX` representation of ``self``.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[1,1]) sage: C([1,2])._latex_() [(\alpha_{1} + \alpha_{2}, 0), (\alpha_{1}, 0)] """
@cached_in_parent_method def integer_sequence(self): r""" Return a list of integers corresponding to positions in the `\lambda`-chain where it is folded.
.. TODO::
Incorporate this method into the ``_repr_`` for finite Cartan type.
.. NOTE::
Only works for finite Cartan types and indexing starts at 0.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[3,2]) sage: x = C( () ) sage: x.f(1).f(2).integer_sequence() [8, 9] """
def phi(self, i): r""" Return the distance to the end of the `i`-string.
This method overrides the generic implementation in the category of crystals since this computation is more efficient.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[1,1]) sage: [c.phi(1) for c in C] [1, 0, 0, 1, 0, 2, 1, 0] sage: [c.phi(2) for c in C] [1, 2, 1, 0, 0, 0, 0, 1] """
raise NotImplementedError # I think the M below should still work in this case
def epsilon(self, i): r""" Return the distance to the start of the `i`-string.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[1,1]) sage: [c.epsilon(1) for c in C] [0, 1, 0, 0, 1, 0, 1, 2] sage: [c.epsilon(2) for c in C] [0, 0, 1, 2, 1, 1, 0, 0] """ #crude but functional
def weight(self): """ Return the weight of ``self``.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[2,0]) sage: for i in C: i.weight() (2, 0, 0) (1, 1, 0) (0, 2, 0) (0, -1, 0) (-1, 0, 0) (-2, -2, 0) sage: B = crystals.AlcovePaths(['A',2,1],[1,0,0]) sage: p = B.module_generators[0].f_string([0,1,2]) sage: p.weight() Lambda[0] - delta
TESTS:
Check that crystal morphisms work (:trac:`19481`)::
sage: C1 = crystals.AlcovePaths(['A',2],[1,0]) sage: C2 = crystals.AlcovePaths(['A',2],[2,0]) sage: phi = C1.crystal_morphism(C2.module_generators, scaling_factors={1:2, 2:2}) sage: [phi(x) for x in C1] [(), ((alpha[1], 0),), ((alpha[1], 0), (alpha[1] + alpha[2], 0))]
Check that all weights are of level 0 in the KR crystal setting (:trac:`20292`)::
sage: A = crystals.AlcovePaths(['A',2,1], [1,0], highest_weight_crystal=False) sage: all(x.weight().level() == 0 for x in A) True """
# We assume that WLR is the (extended) weight lattice remove_zeros=False)
#def __repr__(self): #return str(self.integer_sequence())
def plot(self): r""" Return a plot ``self``.
.. NOTE::
Currently only implemented for types `A_2`, `B_2`, and `C_2`.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[2,0]) sage: x = C( () ).f(1).f(2) sage: x.plot() # Not tested - creates a pdf """ ct = self.parent()._R._cartan_type.dual() word = self.parent()._R.word() integer_sequence = self.integer_sequence() foldings = [False for i in word] for i in integer_sequence: foldings[i] = True affine_ambient_space = RootSystem(ct.affine()).ambient_space() return affine_ambient_space.plot() + affine_ambient_space.plot_alcove_walk( word, foldings=foldings, labels=False)
def __eq__(self, other): r""" Test equality of ``self.value`` and ``other.value``.
EXAMPLES::
sage: C=crystals.AlcovePaths(['B',2],[1,0]) sage: lst=list(C) sage: lst[2] == lst[2] True sage: lst[2] == lst[1] False """ #note: may want to use _eq_ for coercion
def __lt__(self, other): r""" Test if ``self.value`` is less than ``other.value`` in dictionary order.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[2,0]) sage: x = C( () ) sage: x.__lt__(x.f(1)) True sage: a=x.f(1) ; b = x.f(1).f(1).f(2) sage: a.__lt__(b) False """
def __gt__(self, other): r""" Test if ``self.value`` is greater than ``other.value`` in dictionary order.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[2,0]) sage: x = C( () ) sage: x.__gt__(x.f(1)) False sage: a=x.f(1) ; b = x.f(1).f(1).f(2) sage: a.__gt__(b) True """
def _folding_data(self, i): r""" Compute information needed to build the graph `g_{\alpha_i}`. Results of this method are sent to _gi for further processing.
INPUT:
- ``i`` -- element of the index_set of the underlying root_system.
OUTPUT:
A dictionary where the keys are of type RootsWithHeight which record positions where `\pm \alpha_i` shows up in the folded `\lambda` chain. The values are `1` if `\alpha_i` is in the corresponding position in the folded `\lambda`-chain, `-1` if `-\alpha_i` is in the corresponding position in the folded `\lambda`-chain.
.. NOTE::
*infinity* is a special key that records the "sign at infinity".
::
sage: C = crystals.AlcovePaths(['A',2],[1,1]) sage: x = C( () ).f(1) sage: fd = x._folding_data(2); fd # # random output {(alpha[2], 0): 1, (alpha[1] + alpha[2], 1): 1, 'infinity': 1} sage: fd['infinity'] 1 sage: fd.values() [1, 1, 1] """
#self.value contains the admissible sequence as a tuple of Element
#NOTE: R is a RootsWithHeight object and NOT a RootSystem object
# 0 arrows in the case of finite Cartan type # always allow 0 arrows
#NOTE: we assume J is sorted by order on Element of RootsWithHeight
(sign_Beta * Beta).associated_coroot())
# some optimization so we don't initialize too many objects # range(c1,c2) can be replaced by range(max_height_Beta) but it # checks unnecessary extra things
else:
( j < len(J) - 1 and J[j] < x <= J[j+1] ) or ( j == len(J) - 1 and J[j] < x) ):
# in g_alpha
def e(self, i): r""" Return the `i`-th crystal raising operator on ``self``.
INPUT:
- ``i`` -- element of the index set of the underlying root system.
EXAMPLES::
sage: C = crystals.AlcovePaths(['A',2],[2,0]); C Highest weight crystal of alcove paths of type ['A', 2] and weight 2*Lambda[1] sage: x = C( () ) sage: x.e(1) sage: x.f(1) == x.f(1).f(2).e(2) True """
else:
###################################################################### # NOTE: # In the KR_case we want to insure that positions[m_index] is in J # If m_index > 0 then it's always true # If m_index == 0 then M >=1 guarantees this ######################################################################
) or KR_test:
# i.e. positions[m_index+1] makes sense
# we attach to each admissible sequence a list # which encodes a path (via root operators) from the () generator # to the admissible sequence # this is useful for investing the crystal
else:
@cached_method def _gi(self, i): r""" Compute information needed to build the graph `g_{\alpha_i}`. This graph is used to apply the `i`-th crystal operator.
INPUT:
- ``i`` - element of the index_set of the underlying root_system.
OUTPUT:
A tuple ``(positions, gi)``:
- ``positions`` -- is a list of RootsWithHeight. These appear sorted in their natural order, and record where `\pm \alpha_i` shows up in the folded `\lambda`-chain.
- ``gi`` -- is a list of integers recording the height (up to affine transformation) of `\pm \alpha_i` in the folded `\lambda`-chain whose location is recorded by ``positions``.
.. NOTE::
- ``positions`` has length one less than ``gi`` since it does not contain the position 'infinity'.
- To get the real `g_{\alpha_i}` one has to divide by 2 and add 1/2 or divide by 2 and subtract 1/2 depending on if ``self._finite_cartan_type==True and i == 0`` or not. This is done in crystal operator methods.
EXAMPLES::
sage: C=crystals.AlcovePaths(['A',2],[1,1]) sage: x=C( () ).f(1) sage: x._gi(2) ([(alpha[2], 0), (alpha[1] + alpha[2], 1)], [1, 3, 5]) """
gi[j-1] + signs[positions[j-1]]*self._eps(positions[j-1]) + signs[positions[j]] ) signs[positions[-1]]*self._eps(positions[-1]) + signs['infinity'] )
def f(self, i): r""" Returns the `i`-th crystal lowering operator on ``self``.
INPUT:
- ``i`` -- element of the index_set of the underlying root_system.
EXAMPLES::
sage: C=crystals.AlcovePaths(['B',2],[1,1]) sage: x=C( () ) sage: x.f(1) ((alpha[1], 0),) sage: x.f(1).f(2) ((alpha[1], 0), (alpha[1] + alpha[2], 2))
"""
# get a copy in a form of a list of self.value
# python doesn't handle fractions natively else:
# boolean determining when to move a folding in KR case
# In the KR case, we return a value other than None when # `\alpha_i` is in position m_index - 1 # (The following relies on a technical condition (C2) ) # note insert reference # # if m_index - 1 == 0 then M > 1 and (C2) forces # `\alhpa_i` in positions[m_index - 1] # # otherwise if m_index - 1 > 0 then (C2) is enough
) or KR_test :# KR case
# thus positions[m_index] makes sense
# we attach to each admissible sequence a list # which encodes a path (via root operators) from the generator ()
else:
@staticmethod def _sign(root): r""" Return `1` if root is a positive root, and `-1` if root is a negative root.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import CrystalOfAlcovePathsElement sage: rl = RootSystem(['A',2]).root_lattice() sage: x = rl.from_vector(vector([0,1])) sage: CrystalOfAlcovePathsElement._sign(x) 1 """ else:
def _eps(self, root): r""" Return `-1` if root is in ``self.value``, otherwise return `1`.
EXAMPLES::
sage: C = crystals.AlcovePaths(['C',2],[3,2]) sage: x = C( () ).f(1).f(2); x ((alpha[1], 2), (2*alpha[1] + alpha[2], 4)) sage: x._eps(x.value[0]) -1 sage: R = C._R sage: y = R ( x.value[0].root, 1 ); y (alpha[1], 1) sage: x._eps(y) 1
""" else:
def path(self): """ Return the path in the (quantum) Bruhat graph corresponding to ``self``.
EXAMPLES::
sage: C = crystals.AlcovePaths(['B', 3], [3,1,2]) sage: b = C.highest_weight_vector().f_string([1,3,2,1,3,1]) sage: b.path() [1, s1, s3*s1, s2*s3*s1, s3*s2*s3*s1] sage: b = C.highest_weight_vector().f_string([2,3,3,2]) sage: b.path() [1, s2, s3*s2, s2*s3*s2] sage: b = C.highest_weight_vector().f_string([2,3,3,2,1]) sage: b.path() [1, s2, s3*s2, s2*s3*s2, s1*s2*s3*s2] """
#start at the identity
CrystalOfAlcovePaths.Element = CrystalOfAlcovePathsElement
class InfinityCrystalOfAlcovePaths(UniqueRepresentation, Parent): r""" `\mathcal{B}(\infty)` crystal of alcove paths. """ @staticmethod def __classcall_private__(cls, cartan_type): """ Normalize input to ensure a unique representation.
TESTS::
sage: A1 = crystals.infinity.AlcovePaths(['A',2]) sage: A2 = crystals.infinity.AlcovePaths(CartanType(['A',2])) sage: A3 = crystals.infinity.AlcovePaths('A2') sage: A1 is A2 and A2 is A3 True """
def __init__(self, cartan_type): """ Initialize ``self``.
TESTS::
sage: A = crystals.infinity.AlcovePaths(['C',3]) sage: TestSuite(A).run(max_runs=20)
sage: A = crystals.infinity.AlcovePaths(['A',2,1]) sage: TestSuite(A).run() # long time """
def _repr_(self): """ Return a string representation of ``self``.
EXAMPLES::
sage: crystals.infinity.AlcovePaths(['E',6]) Infinity crystal of alcove paths of type ['E', 6] """
class Element(ElementWrapper): def __init__(self, parent, elt, shift): """ Initialize ``self``.
EXAMPLES::
sage: A = crystals.infinity.AlcovePaths(['F',4]) sage: mg = A.highest_weight_vector() sage: x = mg.f_string([2,3,1,4,4,2,3,1]) sage: TestSuite(x).run() """
def e(self, i): """ Return the action of `e_i` on ``self``.
INPUT:
- ``i`` -- an element of the index set
EXAMPLES::
sage: A = crystals.infinity.AlcovePaths(['D',5,1]) sage: mg = A.highest_weight_vector() sage: x = mg.f_string([1,3,4,2,5,4,5,5]) sage: x.f(4).e(5) == x.e(5).f(4) True """ return self.parent().module_generators[0]
# The only element with a shift of 0 is the highest weight element. # So we do not need to check for the shift being 0. tuple([(rt.root, rt.height - shift*s(rt.root)) for rt in prev.value]), shift)
def f(self, i): """ Return the action of `f_i` on ``self``.
INPUT:
- ``i`` -- an element of the index set
EXAMPLES::
sage: A = crystals.infinity.AlcovePaths(['E',7,1]) sage: mg = A.highest_weight_vector() sage: mg.f_string([1,3,5,6,4,2,0,2,1,0,2,4,7,4,2]) ((alpha[2], -3), (alpha[5], -1), (alpha[1], -1), (alpha[0] + alpha[1], -2), (alpha[2] + alpha[4] + alpha[5], -2), (alpha[5] + alpha[6], -1), (alpha[1] + alpha[3], -1), (alpha[5] + alpha[6] + alpha[7], -1), (alpha[0] + alpha[1] + alpha[3], -1), (alpha[1] + alpha[3] + alpha[4] + alpha[5], -1)) """ tuple([(rt.root, rt.height - self._shift*s(rt.root)) for rt in y.value]), self._shift)
tuple([(rt.root, rt.height - shift*s(rt.root)) for rt in y.value]), shift)
def epsilon(self, i): r""" Return `\varepsilon_i` of ``self``.
INPUT:
- ``i`` -- an element of the index set
EXAMPLES::
sage: A = crystals.infinity.AlcovePaths(['A',7,2]) sage: mg = A.highest_weight_vector() sage: x = mg.f_string([1,0,2,3,4,4,4,2,3,3,3]) sage: [x.epsilon(i) for i in A.index_set()] [0, 0, 0, 3, 0] sage: x = mg.f_string([2,2,1,1,0,1,0,2,3,3,3,4]) sage: [x.epsilon(i) for i in A.index_set()] [1, 2, 0, 1, 1] """
def phi(self, i): r""" Return `\varphi_i` of ``self``.
Let `A \in \mathcal{B}(\infty)` Define `\varphi_i(A) := \varepsilon_i(A) + \langle h_i, \mathrm{wt}(A) \rangle`, where `h_i` is the `i`-th simple coroot and `\mathrm{wt}(A)` is the :meth:`weight` of `A`.
INPUT:
- ``i`` -- an element of the index set
EXAMPLES::
sage: A = crystals.infinity.AlcovePaths(['A',8,2]) sage: mg = A.highest_weight_vector() sage: x = mg.f_string([1,0,2,3,4,4,4,2,3,3,3]) sage: [x.phi(i) for i in A.index_set()] [1, 1, 1, 3, -2] sage: x = mg.f_string([2,2,1,1,0,1,0,2,3,3,3,4]) sage: [x.phi(i) for i in A.index_set()] [4, -1, 0, 0, 2] """
def weight(self): """ Return the weight of ``self``.
EXAMPLES::
sage: A = crystals.infinity.AlcovePaths(['E',6]) sage: mg = A.highest_weight_vector() sage: fstr = [1,3,4,2,1,2,3,6,5,3,2,6,2] sage: x = mg.f_string(fstr) sage: al = A.weight_lattice_realization().simple_roots() sage: x.weight() == -sum(al[i]*fstr.count(i) for i in A.index_set()) True """
def projection(self, k=None): r""" Return the projection ``self`` onto `B(k \rho)`.
INPUT:
- ``k`` -- (optional) if not given, defaults to the smallest value such that ``self`` is not ``None`` under the projection
EXAMPLES::
sage: A = crystals.infinity.AlcovePaths(['G',2]) sage: mg = A.highest_weight_vector() sage: x = mg.f_string([2,1,1,2,2,2,1,1]); x ((alpha[2], -3), (alpha[1] + alpha[2], -3), (3*alpha[1] + 2*alpha[2], -1), (2*alpha[1] + alpha[2], -1)) sage: x.projection() ((alpha[2], 0), (alpha[1] + alpha[2], 9), (3*alpha[1] + 2*alpha[2], 8), (2*alpha[1] + alpha[2], 14)) sage: x.projection().parent() Highest weight crystal of alcove paths of type ['G', 2] and weight 3*Lambda[1] + 3*Lambda[2]
sage: mg.projection().parent() Highest weight crystal of alcove paths of type ['G', 2] and weight 0 sage: mg.f(1).projection().parent() Highest weight crystal of alcove paths of type ['G', 2] and weight Lambda[1] + Lambda[2] sage: mg.f(1).f(2).projection().parent() Highest weight crystal of alcove paths of type ['G', 2] and weight Lambda[1] + Lambda[2] sage: b = mg.f_string([1,2,2,1,2]) sage: b.projection().parent() Highest weight crystal of alcove paths of type ['G', 2] and weight 2*Lambda[1] + 2*Lambda[2] sage: b.projection(3).parent() Highest weight crystal of alcove paths of type ['G', 2] and weight 3*Lambda[1] + 3*Lambda[2] sage: b.projection(1) """
class RootsWithHeight(UniqueRepresentation, Parent): r""" Data structure of the ordered pairs `(\beta,k)`, where `\beta` is a positive root and `k` is a non-negative integer. A total order is implemented on this set, and depends on the weight.
INPUT:
- ``cartan_type`` -- Cartan type of a finite or affine untwisted root system
- ``weight`` -- dominant weight as a list of (integral) coefficients of the fundamental weights
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[1,1]); R Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2]
sage: r1 = R._root_lattice.from_vector(vector([1,0])); r1 alpha[1] sage: r2 = R._root_lattice.from_vector(vector([1,1])); r2 alpha[1] + alpha[2]
sage: x = R(r1,0); x (alpha[1], 0) sage: y = R(r2,1); y (alpha[1] + alpha[2], 1) sage: x < y True """
@staticmethod def __classcall_private__(cls, starting_weight, cartan_type = None): """ Classcall to mend the input.
Internally, the RootsWithHeight code works with a ``starting_weight`` that is in the ``weight_space`` associated to the crystal. The user can, however, also input a ``cartan_type`` and the coefficients of the fundamental weights as ``starting_weight``. This code transforms the input into the right format (also necessary for UniqueRepresentation).
TESTS::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: S = RootsWithHeight(CartanType(['A',2]), (3,2)) sage: R is S True
sage: R = RootSystem(['B',2,1]) sage: La = R.weight_space().basis() sage: C = RootsWithHeight(['B',2,1],[0,0,1]) sage: B = RootsWithHeight(La[2]) sage: B is C True """
def __init__(self, weight): r""" Initialize ``self``.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: TestSuite(R).run() """
def _repr_(self): """ Return a string representation of ``self``.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: RootsWithHeight(['A',2],[3,2]) Roots with height of Cartan type ['A', 2] and dominant weight 3*Lambda[1] + 2*Lambda[2] """ self._root_system.cartan_type(), self.weight)
def _max_height(self, root): r""" If root is `\beta`, return `k = \langle \lambda, \beta^{\vee} \rangle`.
Only ordered pairs of the form `(\beta, l)` for `0 \leq l < k` are allowed.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: C = RootsWithHeight(['A',3],[3,2,0]) sage: x = C._root_lattice.from_vector(vector([1,1])); x alpha[1] + alpha[2] sage: C._max_height(x) 5 """
@cached_method def word(self): r""" Gives the initial alcove path (`\lambda`-chain) in terms of simple roots. Used for plotting the path.
.. NOTE::
Currently only implemented for finite Cartan types.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: R.word() [2, 1, 2, 0, 1, 2, 1, 0, 1, 2] """ raise NotImplementedError
#beta is now a simple root or the highest root
else: assert False, 'should never get here'
@cached_method def lambda_chain(self): r""" Return the unfolded `\lambda`-chain.
.. NOTE:: Only works in root systems of finite type.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[1,1]); R Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2] sage: R.lambda_chain() [(alpha[2], 0), (alpha[1] + alpha[2], 0), (alpha[1], 0), (alpha[1] + alpha[2], 1)] """ raise ValueError("Cartan type {0} is not finite".format(self._root_lattice.cartan_type()))
def _element_constructor_(self, root, height): r""" Construct a :class:`RootsWithHeightElement` with ``self`` as the parent.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: rl = RootSystem(['A',2]).root_lattice() sage: x = rl.from_vector(vector([1,1])); x alpha[1] + alpha[2] sage: R = RootsWithHeight(['A',2],[1,1]); R Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2] sage: y = R(x,1); y (alpha[1] + alpha[2], 1) """
def _an_element_(self): r"""
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: R._an_element_() (alpha[1], 0) """
class RootsWithHeightElement(Element): r""" Element of :class:`RootsWithHeight`.
INPUT:
- ``root`` -- A positive root `\beta` in our root system - ``height`` -- Is an integer, such that `0 \leq l \leq \langle \lambda, \beta^{\vee} \rangle`
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: rl = RootSystem(['A',2]).root_lattice() sage: x = rl.from_vector(vector([1,1])); x alpha[1] + alpha[2] sage: R = RootsWithHeight(['A',2],[1,1]); R Roots with height of Cartan type ['A', 2] and dominant weight Lambda[1] + Lambda[2] sage: y = R(x, 1); y (alpha[1] + alpha[2], 1) """ def __init__(self, parent, root, height): r""" Initialize ``self``.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: rl = RootSystem(['A',2]).root_lattice() sage: x = rl.from_vector(vector([1,1])) sage: R = RootsWithHeight(['A',2],[3,2]) sage: y = R(x, 1); y (alpha[1] + alpha[2], 1) sage: TestSuite(x).run() """
# make sure the height is in the right range, this also catches negative # roots
#v.insert(0, height/max_height)
# the map from (root, height) --> _cmp_v is injective
def _repr_(self): r""" Return a string representation of ``self``.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: rl = RootSystem(['A',2]).root_lattice() sage: vec = rl.from_vector(vector([1,1])); vec alpha[1] + alpha[2] sage: R(vec,1) (alpha[1] + alpha[2], 1) """
def __hash__(self): r"""
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: rl = RootSystem(['A',2]).root_lattice() sage: root = rl.from_vector(vector([1,1])) sage: vec = R(root,0) sage: hash(vec) == hash(vec) True """
def __eq__(self, other): r"""
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: rl = RootSystem(['A',2]).root_lattice() sage: v1 = rl.from_vector(vector([1,1])) sage: v2 = rl.from_vector(vector([1])) sage: x1 = R(v1,1) ; x2 = R(v1,0) ; x3 = R(v2,1) sage: x1.__eq__(x1) True sage: x1.__eq__(x2) False sage: x1.__eq__(x3) False """
def _richcmp_(self, other, op): r""" Define a total order on :class:`RootsWithHeightElement`. This defines the initial `\lambda`-chain.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import RootsWithHeight sage: R = RootsWithHeight(['A',2],[3,2]) sage: rl = RootSystem(['A',2]).root_lattice() sage: v1 = rl.from_vector(vector([1,1])) sage: v2 = rl.from_vector(vector([1])) sage: x1 = R(v1,1) ; x2 = R(v1,0) ; x3 = R(v2,1) sage: x1 < x2 False sage: x1 < x3 True """ # I suspect that if you redefine this method to produce a # different (valid) `\lambda`-chain the rest of the # code should still work. #todo: check if self and other have the same parent ? #assert self.parent() is other.parent(), "elements have different parents"
RootsWithHeight.Element = RootsWithHeightElement
##################################################################### # Test code, by comparing with existing crystal implementations. #####################################################################
def _test_some_specific_examples(clss=CrystalOfAlcovePaths): r""" Test against some specific (finite type) examples.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import _test_some_specific_examples sage: _test_some_specific_examples(crystals.AlcovePaths) G2 example passed. C3 example passed. B3 example 1 passed. B3 example 2 passed. True """ # This appears in Lenart.
() : {(0) : 2 }, (0) : {(0,8) : 1 }, (0,1) : {(0,1,7) : 2 }, (0,1,2) : {(0,1,2,9) : 1 }, (0,1,2,3) : {(0,1,2,3,4) : 2 }, (0,1,2,6) : {(0,1,2,3) : 1 }, (0,1,2,9) : {(0,1,2,6) : 1 }, (0,1,7) : {(0,1,2) : 2 }, (0,1,7,9) : {(0,1,2,9) : 2 }, (0,5) : {(0,1) : 1, (0,5,7) : 2 }, (0,5,7) : {(0,5,7,9) : 1 }, (0,5,7,9) : {(0,1,7,9) : 1 }, (0,8) : {(0,5) : 1 } })
return False else:
# Some examples from Hong--Kang:
# type C, ex. 8.3.5, pg. 189 ():{ (0): 3}, (0):{ (0, 6): 2}, (0, 1):{ (0, 1, 3): 3, (0, 1, 7): 1}, (0, 1, 2):{ (0, 1, 2, 3): 3}, (0, 1, 2, 3):{ (0, 1, 2, 3, 8): 2}, (0, 1, 2, 3, 4):{ (0, 1, 2, 3, 4, 5): 3}, (0, 1, 2, 3, 8):{ (0, 1, 2, 3, 4): 2}, (0, 1, 3):{ (0, 1, 3, 7): 1}, (0, 1, 3, 7):{ (0, 1, 2, 3): 1, (0, 1, 3, 7, 8): 2}, (0, 1, 3, 7, 8):{ (0, 1, 2, 3, 8): 1}, (0, 1, 7):{ (0, 1, 2): 1, (0, 1, 3, 7): 3}, (0, 6):{ (0, 1): 2, (0, 6, 7): 1}, (0, 6, 7):{ (0, 1, 7): 2} })
return False else:
# type B, fig. 8.1 pg. 172
():{ (6): 1}, (0):{ (0, 7): 2}, (0, 1):{ (0, 1, 11): 3}, (0, 1, 2):{ (0, 1, 2, 9): 2}, (0, 1, 2, 3):{ (0, 1, 2, 3, 10): 1}, (0, 1, 2, 3, 10):{ (0, 1, 2, 3, 4): 1}, (0, 1, 2, 9):{ (0, 1, 2, 3): 2, (0, 1, 2, 9, 10): 1}, (0, 1, 2, 9, 10):{ (0, 1, 2, 3, 10): 2}, (0, 1, 5):{ (0, 1, 2): 3, (0, 1, 5, 9): 2}, (0, 1, 5, 9):{ (0, 1, 2, 9): 3, (0, 1, 5, 9, 10): 1}, (0, 1, 5, 9, 10):{ (0, 1, 2, 9, 10): 3}, (0, 1, 8):{ (0, 1, 5): 3}, (0, 1, 8, 9):{ (0, 1, 5, 9): 3, (0, 1, 8, 9, 10): 1}, (0, 1, 8, 9, 10):{ (0, 1, 5, 9, 10): 3}, (0, 1, 11):{ (0, 1, 8): 3}, (0, 7):{ (0, 1): 2, (0, 7, 11): 3}, (0, 7, 8):{ (0, 7, 8, 9): 2}, (0, 7, 8, 9):{ (0, 1, 8, 9): 2}, (0, 7, 8, 9, 10):{ (0, 1, 8, 9, 10): 2}, (0, 7, 11):{ (0, 1, 11): 2, (0, 7, 8): 3}, (6):{ (0): 1, (6, 7): 2}, (6, 7):{ (0, 7): 1, (6, 7, 11): 3}, (6, 7, 8):{ (0, 7, 8): 1, (6, 7, 8, 9): 2}, (6, 7, 8, 9):{ (6, 7, 8, 9, 10): 1}, (6, 7, 8, 9, 10):{ (0, 7, 8, 9, 10): 1}, (6, 7, 11):{ (0, 7, 11): 1, (6, 7, 8): 3} })
return False else:
():{ (0): 2}, (0):{ (0, 1): 1, (0, 7): 3}, (0, 1):{ (0, 1, 7): 3}, (0, 1, 2):{ (0, 1, 2, 8): 2}, (0, 1, 2, 3):{ (0, 1, 2, 3, 5): 1, (0, 1, 2, 3, 9): 3}, (0, 1, 2, 3, 4):{ (0, 1, 2, 3, 4, 5): 1}, (0, 1, 2, 3, 4, 5):{ (0, 1, 2, 3, 4, 5, 6): 2}, (0, 1, 2, 3, 5):{ (0, 1, 2, 3, 5, 9): 3}, (0, 1, 2, 3, 5, 9):{ (0, 1, 2, 3, 4, 5): 3}, (0, 1, 2, 3, 9):{ (0, 1, 2, 3, 4): 3, (0, 1, 2, 3, 5, 9): 1}, (0, 1, 2, 5):{ (0, 1, 2, 3, 5): 2}, (0, 1, 2, 8):{ (0, 1, 2, 3): 2}, (0, 1, 2, 8, 9):{ (0, 1, 2, 3, 9): 2}, (0, 1, 7):{ (0, 1, 2): 3, (0, 1, 7, 8): 2}, (0, 1, 7, 8):{ (0, 1, 7, 8, 9): 3}, (0, 1, 7, 8, 9):{ (0, 1, 2, 8, 9): 3}, (0, 2):{ (0, 1, 2): 1, (0, 2, 5): 2}, (0, 2, 5):{ (0, 2, 5, 8): 1}, (0, 2, 5, 8):{ (0, 1, 2, 5): 1}, (0, 7):{ (0, 1, 7): 1, (0, 2): 3} })
return False else:
# type B, fig. 8.3 pg. 174
def compare_graphs(g1, g2, node1, node2): r""" Compare two edge-labeled :class:`graphs <DiGraph>` obtained from ``Crystal.digraph()``, starting from the root nodes of each graph.
- ``g1`` -- :class:`graphs <DiGraph>`, first digraph - ``g2`` -- :class:`graphs <DiGraph>`, second digraph - ``node1`` -- element of ``g1`` - ``node2`` -- element of ``g2``
Traverse ``g1`` starting at ``node1`` and compare this graph with the one obtained by traversing ``g2`` starting with ``node2``. If the graphs match (including labels) then return ``True``. Return ``False`` otherwise.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import compare_graphs sage: G1 = crystals.Tableaux(['A',3], shape=[1,1]).digraph() sage: C = crystals.AlcovePaths(['A',3],[0,1,0]) sage: G2 = C.digraph() sage: compare_graphs(G1, G2, C( () ), G2.vertices()[0]) True """ print("ERROR: Two edges with the same label for ", out_edge, " exist.") return False return False print("ERROR: No matching edge for ", out_edge, ".") return False
def _test_against_tableaux(R, N, k, clss=CrystalOfAlcovePaths): r""" Test :class:`~sage.combinat.crystals.alcove_path.CrystalOfAlcovePaths` against all of the tableaux crystals of type `R` in rank `N` with highest weight given by a partition of `k`.
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import _test_against_tableaux sage: _test_against_tableaux(['A',3], 3, 2) ** Shape [2] T has 10 nodes. C weight [2, 0, 0] C has 10 nodes. Compare graphs: True ** Shape [1, 1] T has 6 nodes. C weight [0, 1, 0] C has 6 nodes. Compare graphs: True """ #T.digraph().show(edge_labels=True)
#C.digraph().show(edge_labels=True) print("FAIL: number of nodes differ.", cc, ct) return
def _test_with_lspaths_crystal(cartan_type, weight, depth=10): r""" Test if the digraphs generated are isomorphic to the ones generated by LS-path model.
INPUT:
- ``cartan_type`` -- Cartan type of a finite or affine untwisted root system - ``weight`` -- dominant weight as a list of (integral) coefficients of the fundamental weights - ``depth`` -- starting at the module generator how deep do you want to generate the crystal, useful for affine types
EXAMPLES::
sage: from sage.combinat.crystals.alcove_path import _test_with_lspaths_crystal sage: _test_with_lspaths_crystal(['A',3,1],[1,0,0,0],10) #long time True sage: _test_with_lspaths_crystal(['G',2,1],[1,0,0,0,0],10) #long time True """ from sage.combinat.crystals.littelmann_path import CrystalOfLSPaths G1 = CrystalOfAlcovePaths(cartan_type, weight).digraph(depth=depth) C = CrystalOfLSPaths(cartan_type, weight) G2 = C.digraph(subset=C.subcrystal(max_depth=depth, direction='lower'))
return G1.is_isomorphic(G2, edge_labels=True)
|