Path: blob/master/src/sage/combinat/crystals/affine.py
8817 views
r"""1Affine Crystals2"""3#*****************************************************************************4# Copyright (C) 2008 Brant Jones <brant at math.ucdavis.edu>5# Anne Schilling <anne at math.ucdavis.edu>6#7# Distributed under the terms of the GNU General Public License (GPL)8# http://www.gnu.org/licenses/9#****************************************************************************10# Acknowledgment: most of the design and implementation of this11# library is heavily inspired from MuPAD-Combinat.12#****************************************************************************1314from sage.misc.abstract_method import abstract_method15from sage.categories.regular_crystals import RegularCrystals16from sage.categories.finite_crystals import FiniteCrystals17from sage.structure.parent import Parent18from sage.structure.unique_representation import UniqueRepresentation19from sage.structure.element_wrapper import ElementWrapper20from sage.combinat.root_system.cartan_type import CartanType2122class AffineCrystalFromClassical(UniqueRepresentation, Parent):23r"""24This abstract class can be used for affine crystals that are constructed from a classical crystal.25The zero arrows can be implemented using different methods (for example using a Dynkin diagram26automorphisms or virtual crystals).2728This is a helper class, mostly used to implement Kirillov-Reshetikhin crystals29(see: :func:`sage.combinat.crystals.kirillov_reshetikhin.KirillovReshetikhin`).3031For general information about crystals see :mod:`sage.combinat.crystals`.3233INPUT:3435- ``cartan_type`` - The Cartan type of the resulting affine crystal3637- ``classical_crystal`` - instance of a classical crystal.3839EXAMPLES::4041sage: n=242sage: C=CrystalOfTableaux(['A',n],shape=[1])43sage: pr = attrcall("promotion")44sage: pr_inverse = attrcall("promotion_inverse")45sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)46sage: A.list()47[[[1]], [[2]], [[3]]]48sage: A.cartan_type()49['A', 2, 1]50sage: A.index_set()51(0, 1, 2)52sage: b=A(rows=[[1]])53sage: b.weight()54-Lambda[0] + Lambda[1]55sage: b.classical_weight()56(1, 0, 0)57sage: [x.s(0) for x in A.list()]58[[[3]], [[2]], [[1]]]59sage: [x.s(1) for x in A.list()]60[[[2]], [[1]], [[3]]]61"""6263@staticmethod64def __classcall__(cls, cartan_type, *args, **options):65"""66TESTS::6768sage: n = 169sage: C = CrystalOfTableaux(['A',n],shape=[1])70sage: pr = attrcall("promotion")71sage: pr_inverse = attrcall("promotion_inverse")72sage: A = AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest73sage: B = AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest74sage: A is B75True76"""77ct = CartanType(cartan_type)78return super(AffineCrystalFromClassical, cls).__classcall__(cls, ct, *args, **options)7980def __init__(self, cartan_type, classical_crystal, category = None):81"""82Input is an affine Cartan type 'cartan_type', a classical crystal 'classical_crystal', and automorphism and its83inverse 'automorphism' and 'inverse_automorphism', and the Dynkin node 'dynkin_node'8485EXAMPLES::8687sage: n = 188sage: C = CrystalOfTableaux(['A',n],shape=[1])89sage: pr = attrcall("promotion")90sage: pr_inverse = attrcall("promotion_inverse")91sage: A = AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest92sage: A.list()93[[[1]], [[2]]]94sage: A.cartan_type()95['A', 1, 1]96sage: A.index_set()97(0, 1)9899Note: AffineCrystalFromClassical is an abstract class, so we100can't test it directly.101102TESTS::103104sage: TestSuite(A).run()105"""106if category is None:107category = (RegularCrystals(), FiniteCrystals())108self._cartan_type = cartan_type109Parent.__init__(self, category = category)110self.classical_crystal = classical_crystal;111self.module_generators = map( self.retract, self.classical_crystal.module_generators )112self.element_class._latex_ = lambda x: x.lift()._latex_()113114def _repr_(self):115"""116EXAMPLES::117118sage: n=1119sage: C=CrystalOfTableaux(['A',n],shape=[1])120sage: pr = attrcall("promotion")121sage: pr_inverse = attrcall("promotion_inverse")122sage: AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest123An affine crystal for type ['A', 1, 1]124"""125return "An affine crystal for type %s"%self.cartan_type()126127128def __iter__(self):129r"""130Construct the iterator from the underlying classical crystal.131132TESTS::133134sage: n=1135sage: C=CrystalOfTableaux(['A',n],shape=[1])136sage: pr = attrcall("promotion")137sage: pr_inverse = attrcall("promotion_inverse")138sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest139sage: A.list() # indirect doctest140[[[1]], [[2]]]141"""142for x in self.classical_crystal:143yield self.retract(x)144145# should be removed once crystal defines __iter__ instead of list146def list(self):147"""148Returns the list of all crystal elements using the underlying classical crystal149150EXAMPLES::151152sage: n=2153sage: C=CrystalOfTableaux(['A',n],shape=[1])154sage: pr = attrcall("promotion")155sage: pr_inverse = attrcall("promotion_inverse")156sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)157sage: A.list()158[[[1]], [[2]], [[3]]]159"""160return map( self.retract, self.classical_crystal.list() )161162def lift(self, affine_elt):163"""164Lifts an affine crystal element to the corresponding classical crystal element165166EXAMPLES::167168sage: n=2169sage: C=CrystalOfTableaux(['A',n],shape=[1])170sage: pr = attrcall("promotion")171sage: pr_inverse = attrcall("promotion_inverse")172sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)173sage: b=A.list()[0]174sage: A.lift(b)175[[1]]176sage: A.lift(b).parent()177The crystal of tableaux of type ['A', 2] and shape(s) [[1]]178"""179return affine_elt.lift()180181def retract(self, classical_elt):182"""183Transforms a classical crystal element to the corresponding affine crystal element184185EXAMPLES::186187sage: n=2188sage: C=CrystalOfTableaux(['A',n],shape=[1])189sage: pr = attrcall("promotion")190sage: pr_inverse = attrcall("promotion_inverse")191sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)192sage: t=C(rows=[[1]])193sage: t.parent()194The crystal of tableaux of type ['A', 2] and shape(s) [[1]]195sage: A.retract(t)196[[1]]197sage: A.retract(t).parent() is A198True199"""200return self.element_class(self, classical_elt)201202def _element_constructor_(self, *value, **options):203r"""204Coerces ``value`` into ``self``.205206EXAMPLES:207208sage: n=2209sage: C=CrystalOfTableaux(['A',n],shape=[1])210sage: pr = attrcall("promotion")211sage: pr_inverse = attrcall("promotion_inverse")212sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)213sage: b=A(rows=[[1]]) # indirect doctest214sage: b215[[1]]216sage: b.parent()217An affine crystal for type ['A', 2, 1]218sage: A(b) is b219True220"""221if len(value) == 1 and isinstance(value[0], self.element_class) and value[0].parent() == self:222return value[0]223else: # Should do sanity checks! (Including check for inconsistent parent.)224return self.retract(self.classical_crystal(*value, **options))225226def __contains__(self, x):227r"""228Checks whether x is an element of self.229230EXAMPLES:231232sage: n=2233sage: C=CrystalOfTableaux(['A',n],shape=[1])234sage: pr = attrcall("promotion")235sage: pr_inverse = attrcall("promotion_inverse")236sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)237sage: b=A(rows=[[1]])238sage: A.__contains__(b)239True240"""241return x.parent() is self242243244class AffineCrystalFromClassicalElement(ElementWrapper):245r"""246Elements of crystals that are constructed from a classical crystal.247The elements inherit many of their methods from the classical crystal248using lift and retract.249250This class is not instantiated directly but rather __call__ed from251AffineCrystalFromClassical. The syntax of this is governed by the252(classical) CrystalOfTableaux.253254EXAMPLES::255256sage: n=2257sage: C=CrystalOfTableaux(['A',n],shape=[1])258sage: pr = attrcall("promotion")259sage: pr_inverse = attrcall("promotion_inverse")260sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)261sage: b=A(rows=[[1]])262sage: b._repr_()263'[[1]]'264"""265266def classical_weight(self):267"""268Returns the classical weight corresponding to self.269270EXAMPLES::271272sage: n=2273sage: C=CrystalOfTableaux(['A',n],shape=[1])274sage: pr = attrcall("promotion")275sage: pr_inverse = attrcall("promotion_inverse")276sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)277sage: b=A(rows=[[1]])278sage: b.classical_weight()279(1, 0, 0)280"""281return self.lift().weight()282283def lift(self):284"""285Lifts an affine crystal element to the corresponding classical crystal element286287EXAMPLES::288289sage: n=2290sage: C=CrystalOfTableaux(['A',n],shape=[1])291sage: pr = attrcall("promotion")292sage: pr_inverse = attrcall("promotion_inverse")293sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)294sage: b=A.list()[0]295sage: b.lift()296[[1]]297sage: b.lift().parent()298The crystal of tableaux of type ['A', 2] and shape(s) [[1]]299"""300return self.value301302def pp(self):303"""304Method for pretty printing305306EXAMPLES::307308sage: K = KirillovReshetikhinCrystal(['D',3,2],1,1)309sage: t=K(rows=[[1]])310sage: t.pp()3111312"""313return self.lift().pp()314315@abstract_method316def e0(self):317r"""318Assumes that `e_0` is implemented separately.319"""320321@abstract_method322def f0(self):323r"""324Assumes that `f_0` is implemented separately.325"""326327def e(self, i):328r"""329Returns the action of `e_i` on self.330331EXAMPLES::332333sage: n=2334sage: C=CrystalOfTableaux(['A',n],shape=[1])335sage: pr = attrcall("promotion")336sage: pr_inverse = attrcall("promotion_inverse")337sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)338sage: b=A(rows=[[1]])339sage: b.e(0)340[[3]]341sage: b.e(1)342"""343if i == 0:344return self.e0()345else:346x = self.lift().e(i)347if (x == None):348return None349else:350return self.parent().retract(x)351352def f(self, i):353r"""354Returns the action of `f_i` on self.355356EXAMPLES::357358sage: n=2359sage: C=CrystalOfTableaux(['A',n],shape=[1])360sage: pr = attrcall("promotion")361sage: pr_inverse = attrcall("promotion_inverse")362sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)363sage: b=A(rows=[[3]])364sage: b.f(0)365[[1]]366sage: b.f(2)367"""368if i == 0:369return self.f0()370else:371x = self.lift().f(i)372if (x == None):373return None374else:375return self.parent().retract(x)376377def epsilon0(self):378r"""379Uses `epsilon_0` from the super class, but should be implemented if a faster implementation exists.380"""381return super(AffineCrystalFromClassicalElement, self).epsilon(0)382383def epsilon(self, i):384"""385Returns the maximal time the crystal operator `e_i` can be applied to self.386387EXAMPLES::388389sage: n=2390sage: C=CrystalOfTableaux(['A',n],shape=[1])391sage: pr = attrcall("promotion")392sage: pr_inverse = attrcall("promotion_inverse")393sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)394sage: [x.epsilon(0) for x in A.list()]395[1, 0, 0]396sage: [x.epsilon(1) for x in A.list()]397[0, 1, 0]398"""399if i == 0:400return self.epsilon0()401else:402return self.lift().epsilon(i)403404def phi0(self):405r"""406Uses `phi_0` from the super class, but should be implemented if a faster implementation exists.407"""408return super(AffineCrystalFromClassicalElement, self).phi(0)409410def phi(self, i):411r"""412Returns the maximal time the crystal operator `f_i` can be applied to self.413414EXAMPLES::415416sage: n=2417sage: C=CrystalOfTableaux(['A',n],shape=[1])418sage: pr = attrcall("promotion")419sage: pr_inverse = attrcall("promotion_inverse")420sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)421sage: [x.phi(0) for x in A.list()]422[0, 0, 1]423sage: [x.phi(1) for x in A.list()]424[1, 0, 0]425"""426if i == 0:427return self.phi0()428else:429return self.lift().phi(i)430431def __lt__(self, other):432"""433Non elements of the crystal are incomparable with elements of the crystal434(or should it return NotImplemented?). Elements of this crystal are compared435using the comparison in the underlying classical crystal.436437EXAMPLES::438439sage: K = KirillovReshetikhinCrystal(['A',2,1],1,1)440sage: b = K(rows=[[1]])441sage: c = K(rows=[[2]])442sage: c<b443False444sage: b<b445False446sage: b<c447True448"""449if self.parent() is not other.parent():450return False451return self.lift() < other.lift()452453AffineCrystalFromClassical.Element = AffineCrystalFromClassicalElement454455456class AffineCrystalFromClassicalAndPromotion(AffineCrystalFromClassical):457r"""458Crystals that are constructed from a classical crystal and a459Dynkin diagram automorphism `\sigma`. In type `A_n`, the Dynkin460diagram automorphism is `i \to i+1 \pmod n+1` and the461corresponding map on the crystal is the promotion operation462`\mathrm{pr}` on tableaux. The affine crystal operators are given463by `f_0= \mathrm{pr}^{-1} f_{\sigma(0)} \mathrm{pr}`.464465INPUT:466467- ``cartan_type`` - The Cartan type of the resulting affine crystal468469- ``classical_crystal`` - instance of a classical crystal.470471- ``automorphism, inverse_automorphism`` - A function on the472elements of the classical_crystal473474- ``dynkin_node`` - Integer specifying the classical node in the475image of the zero node under the automorphism sigma.476477EXAMPLES::478479sage: n=2480sage: C=CrystalOfTableaux(['A',n],shape=[1])481sage: pr = attrcall("promotion")482sage: pr_inverse = attrcall("promotion_inverse")483sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)484sage: A.list()485[[[1]], [[2]], [[3]]]486sage: A.cartan_type()487['A', 2, 1]488sage: A.index_set()489(0, 1, 2)490sage: b=A(rows=[[1]])491sage: b.weight()492-Lambda[0] + Lambda[1]493sage: b.classical_weight()494(1, 0, 0)495sage: [x.s(0) for x in A.list()]496[[[3]], [[2]], [[1]]]497sage: [x.s(1) for x in A.list()]498[[[2]], [[1]], [[3]]]499"""500501def __init__(self, cartan_type, classical_crystal, p_automorphism, p_inverse_automorphism, dynkin_node):502"""503Input is an affine Cartan type 'cartan_type', a classical crystal 'classical_crystal', and automorphism and its504inverse 'automorphism' and 'inverse_automorphism', and the Dynkin node 'dynkin_node'505506EXAMPLES::507508sage: n=1509sage: C=CrystalOfTableaux(['A',n],shape=[1])510sage: pr = attrcall("promotion")511sage: pr_inverse = attrcall("promotion_inverse")512sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)513sage: A.list()514[[[1]], [[2]]]515sage: A.cartan_type()516['A', 1, 1]517sage: A.index_set()518(0, 1)519520TESTS::521522sage: TestSuite(A).run()523"""524AffineCrystalFromClassical.__init__(self, cartan_type, classical_crystal)525self.p_automorphism = p_automorphism526self.p_inverse_automorphism = p_inverse_automorphism527self.dynkin_node = dynkin_node528529def automorphism(self, x):530"""531Gives the analogue of the affine Dynkin diagram automorphism on the level of crystals532533EXAMPLES::534535sage: n=2536sage: C=CrystalOfTableaux(['A',n],shape=[1])537sage: pr = attrcall("promotion")538sage: pr_inverse = attrcall("promotion_inverse")539sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)540sage: b=A.list()[0]541sage: A.automorphism(b)542[[2]]543"""544return self.retract( self.p_automorphism( x.lift() ) )545546def inverse_automorphism(self, x):547"""548Gives the analogue of the inverse of the affine Dynkin diagram automorphism on the level of crystals549550EXAMPLES::551552sage: n=2553sage: C=CrystalOfTableaux(['A',n],shape=[1])554sage: pr = attrcall("promotion")555sage: pr_inverse = attrcall("promotion_inverse")556sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)557sage: b=A.list()[0]558sage: A.inverse_automorphism(b)559[[3]]560"""561return self.retract( self.p_inverse_automorphism( x.lift() ) )562563class AffineCrystalFromClassicalAndPromotionElement(AffineCrystalFromClassicalElement):564r"""565Elements of crystals that are constructed from a classical crystal566and a Dynkin diagram automorphism. In type A, the automorphism is567the promotion operation on tableaux.568569This class is not instantiated directly but rather __call__ed from570AffineCrystalFromClassicalAndPromotion. The syntax of this is governed by the571(classical) CrystalOfTableaux.572573Since this class inherits from AffineClassicalFromClassicalElement, the methods574that need to be implemented are e0, f0 and possibly epsilon0 and phi0 if more efficient575algorithms exist.576577EXAMPLES::578579sage: n=2580sage: C=CrystalOfTableaux(['A',n],shape=[1])581sage: pr = attrcall("promotion")582sage: pr_inverse = attrcall("promotion_inverse")583sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)584sage: b=A(rows=[[1]])585sage: b._repr_()586'[[1]]'587"""588589def e0(self):590r"""591Implements `e_0` using the automorphism as592`e_0 = \operatorname{pr}^{-1} e_{dynkin_node} \operatorname{pr}`593594EXAMPLES::595596sage: n=2597sage: C=CrystalOfTableaux(['A',n],shape=[1])598sage: pr = attrcall("promotion")599sage: pr_inverse = attrcall("promotion_inverse")600sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)601sage: b=A(rows=[[1]])602sage: b.e0()603[[3]]604"""605x = self.parent().automorphism(self).e(self.parent().dynkin_node)606if (x == None):607return None608else:609return self.parent().inverse_automorphism(x)610611def f0(self):612r"""613Implements `f_0` using the automorphism as614`f_0 = \operatorname{pr}^{-1} f_{dynkin_node} \operatorname{pr}`615616EXAMPLES::617618sage: n=2619sage: C=CrystalOfTableaux(['A',n],shape=[1])620sage: pr = attrcall("promotion")621sage: pr_inverse = attrcall("promotion_inverse")622sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)623sage: b=A(rows=[[3]])624sage: b.f0()625[[1]]626"""627x = self.parent().automorphism(self).f(self.parent().dynkin_node)628if (x == None):629return None630else:631return self.parent().inverse_automorphism(x)632633def epsilon0(self):634r"""635Implements `epsilon_0` using the automorphism.636637EXAMPLES::638639sage: n=2640sage: C=CrystalOfTableaux(['A',n],shape=[1])641sage: pr = attrcall("promotion")642sage: pr_inverse = attrcall("promotion_inverse")643sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)644sage: [x.epsilon0() for x in A.list()]645[1, 0, 0]646"""647x = self.parent().automorphism(self)648return x.lift().epsilon(self.parent().dynkin_node)649650def phi0(self):651r"""652Implements `phi_0` using the automorphism.653654EXAMPLES::655656sage: n=2657sage: C=CrystalOfTableaux(['A',n],shape=[1])658sage: pr = attrcall("promotion")659sage: pr_inverse = attrcall("promotion_inverse")660sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)661sage: [x.phi0() for x in A.list()]662[0, 0, 1]663"""664x = self.parent().automorphism(self)665return x.lift().phi(self.parent().dynkin_node)666667AffineCrystalFromClassicalAndPromotion.Element = AffineCrystalFromClassicalAndPromotionElement668669670