Ticket #7978: trac_7978_crystal_cleanup-as.2.patch

File trac_7978_crystal_cleanup-as.2.patch, 81.6 KB (added by Nicolas M. Thiéry, 13 years ago)

Updated patch updates one doctest.

  • sage/combinat/crystals/affine.py

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1264557112 -3600
    # Node ID 917d4e3b5b2e0b940143b4747905329c97261f08
    # Parent  ab72fe570babf4b344c4a78577c98ca01e23b0be
    Fixed some issues in crystals, such as
     - Comparison of elements
     - Latex output
     - Fixes whitespaces in /combinat/crystals/affine.py
     - All crystals have unique representation
     - Preparation of categorification of crystals:
        - C.element_class -> C.Element
        - All crystals are at least in the EnumeratedSets category
        - Use rename, or define _repr_, instead of setting _name
          Eventually, crystals should only use _repr_
        => Removed dependency upon deprecated CombinatorialClass
     - Systematic use of TestSuite instead of loads/dumps test
     - Fixed bug in fast_crystal: delpat is not immutable (which should be
       eventually be fixed), and was accidentally changed by the weight
       method). This was caught by turning on unique representation which
       made the crystals to be reused longer in the tests.
    
    Depends on trac ticket 8028 (element wrapper improvement)
    
    diff --git a/sage/combinat/crystals/affine.py b/sage/combinat/crystals/affine.py
    a b Affine crystals 
    2222#****************************************************************************
    2323
    2424from sage.misc.abstract_method import abstract_method
    25 from sage.combinat.crystals.crystals import Crystal, ClassicalCrystal, CrystalElement
     25from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    2626from sage.structure.unique_representation import UniqueRepresentation
    2727from sage.structure.element_wrapper import ElementWrapper
     28from sage.combinat.crystals.crystals import Crystal, CrystalElement
    2829from sage.combinat.root_system.cartan_type import CartanType
    29 from sage.combinat.crystals.tensor_product import CrystalOfTableaux
    30 from sage.combinat.tableau import Tableau_class
    3130
    3231class AffineCrystal(Crystal):
    3332    r"""
    class AffineCrystalFromClassical(Crystal 
    5251
    5352        sage: n=2
    5453        sage: C=CrystalOfTableaux(['A',n],shape=[1])
    55         sage: pr=lambda x : C(x.to_tableau().promotion(n))
    56         sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    57         sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    58         sage: A.list()
    59         [[[1]], [[2]], [[3]]]
    60         sage: A.cartan_type()
    61         ['A', 2, 1]
    62         sage: A.index_set()
    63         [0, 1, 2]
    64         sage: b=A(rows=[[1]])
    65         sage: b.weight()
    66         -Lambda[0] + Lambda[1]
    67         sage: b.classical_weight()
    68         (1, 0, 0)
    69         sage: [x.s(0) for x in A.list()]
    70         [[[3]], [[2]], [[1]]]
    71         sage: [x.s(1) for x in A.list()]
    72         [[[2]], [[1]], [[3]]]
     54        sage: pr=lambda x : C(x.to_tableau().promotion(n))
     55        sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     56        sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     57        sage: A.list()
     58        [[[1]], [[2]], [[3]]]
     59        sage: A.cartan_type()
     60        ['A', 2, 1]
     61        sage: A.index_set()
     62        [0, 1, 2]
     63        sage: b=A(rows=[[1]])
     64        sage: b.weight()
     65        -Lambda[0] + Lambda[1]
     66        sage: b.classical_weight()
     67        (1, 0, 0)
     68        sage: [x.s(0) for x in A.list()]
     69        [[[3]], [[2]], [[1]]]
     70        sage: [x.s(1) for x in A.list()]
     71        [[[2]], [[1]], [[3]]]
    7372    """
    7473
    7574    @staticmethod
    76     def __classcall__(cls, cartan_type, *args):
    77         ct = CartanType(cartan_type)
    78         return super(AffineCrystalFromClassical, cls).__classcall__(cls, ct, *args)
     75    def __classcall__(cls, cartan_type, *args, **options):
     76        ct = CartanType(cartan_type)
     77        return super(AffineCrystalFromClassical, cls).__classcall__(cls, ct, *args, **options)
    7978
    80     def __init__(self, cartan_type, classical_crystal):
    81         """
    82         Input is an affine Cartan type 'cartan_type', a classical crystal 'classical_crystal', and automorphism and its
    83         inverse 'automorphism' and 'inverse_automorphism', and the Dynkin node 'dynkin_node'
     79    def __init__(self, cartan_type, classical_crystal, category = None):
     80        """
     81        Input is an affine Cartan type 'cartan_type', a classical crystal 'classical_crystal', and automorphism and its
     82        inverse 'automorphism' and 'inverse_automorphism', and the Dynkin node 'dynkin_node'
    8483
    85         EXAMPLES::
     84        EXAMPLES::
     85
     86            sage: n=1
     87            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     88            sage: def pr(x): return C(x.to_tableau().promotion(n))
     89            sage: def pr_inverse(x): return C(x.to_tableau().promotion_inverse(n))
     90            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest
     91            sage: A.list()
     92            [[[1]], [[2]]]
     93            sage: A.cartan_type()
     94            ['A', 1, 1]
     95            sage: A.index_set()
     96            [0, 1]
     97
     98        TESTS::
     99
     100            sage: import __main__; __main__.pr = pr; __main__.pr_inverse = pr_inverse # standard pickling hack
     101            sage: TestSuite(A).run()
     102        """
     103        if category is None:
     104            category = FiniteEnumeratedSets()
     105        self._cartan_type = cartan_type
     106        super(AffineCrystalFromClassical, self).__init__(category = category)
     107        self.classical_crystal = classical_crystal;
     108        self.module_generators = map( self.retract, self.classical_crystal.module_generators )
     109        self.element_class._latex_ = lambda x: x.lift()._latex_()
     110
     111    def _repr_(self):
     112        """
     113        EXAMPLES::
     114
     115            sage: n=1
     116            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     117            sage: def pr(x): return C(x.to_tableau().promotion(n))
     118            sage: def pr_inverse(x): return C(x.to_tableau().promotion_inverse(n))
     119            sage: AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest
     120            An affine crystal for type ['A', 1, 1]
     121        """
     122        return "An affine crystal for type %s"%self.cartan_type()
     123
     124
     125    def __iter__(self):
     126        r"""
     127        Construct the iterator from the underlying classical crystal.
     128
     129        TESTS::
    86130
    87131            sage: n=1
    88             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    89             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    90             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    91             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest
    92             sage: A.list()
    93             [[[1]], [[2]]]
    94             sage: A.cartan_type()
    95             ['A', 1, 1]
    96             sage: A.index_set()
    97             [0, 1]
    98         """
    99         self._cartan_type = cartan_type
    100         if not hasattr(self, "_name"):
    101             self._name = "An affine crystal for type %s"%self.cartan_type()
    102         self.classical_crystal = classical_crystal;
    103         self.module_generators = map( self.retract, self.classical_crystal.module_generators )
    104 
    105     def __iter__(self):
    106         r"""
    107         Construct the iterator from the underlying classical crystal.
    108 
    109         TESTS::
    110 
    111             sage: n=1
    112             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    113             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    114             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    115             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest
    116             sage: A.list() # indirect doctest
    117             [[[1]], [[2]]]
    118         """
    119         for x in self.classical_crystal:
    120             yield self.retract(x)
     132            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     133            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     134            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     135            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1) # indirect doctest
     136            sage: A.list() # indirect doctest
     137            [[[1]], [[2]]]
     138        """
     139        for x in self.classical_crystal:
     140            yield self.retract(x)
    121141
    122142    # should be removed once crystal defines __iter__ instead of list
    123143    def list(self):
    124         """
    125         Returns the list of all crystal elements using the underlying classical crystal
     144        """
     145        Returns the list of all crystal elements using the underlying classical crystal
    126146
    127         EXAMPLES::
    128 
    129             sage: n=2
    130             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    131             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    132             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    133             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    134             sage: A.list()
    135             [[[1]], [[2]], [[3]]]
    136         """
    137         return map( self.retract, self.classical_crystal.list() )
    138        
    139     def lift(self, affine_elt):
    140         """
    141         Lifts an affine crystal element to the corresponding classical crystal element
    142 
    143         EXAMPLES::
     147        EXAMPLES::
    144148
    145149            sage: n=2
    146             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    147             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    148             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    149             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    150             sage: b=A.list()[0]
    151             sage: type(A.lift(b))
    152             <class 'sage.combinat.crystals.tensor_product.CrystalOfTableauxElement'>
     150            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     151            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     152            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     153            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     154            sage: A.list()
     155            [[[1]], [[2]], [[3]]]
     156        """
     157        return map( self.retract, self.classical_crystal.list() )
     158       
     159    def lift(self, affine_elt):
     160        """
     161        Lifts an affine crystal element to the corresponding classical crystal element
     162
     163        EXAMPLES::
     164
     165            sage: n=2
     166            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     167            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     168            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     169            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     170            sage: b=A.list()[0]
     171            sage: A.lift(b)
     172            [[1]]
     173            sage: A.lift(b).parent()
     174            The crystal of tableaux of type ['A', 2] and shape(s) [[1]]
    153175        """
    154176        return affine_elt.lift()
    155177
    156178    def retract(self, classical_elt):
    157         """
    158         Transforms a classical crystal element to the corresponding affine crystal element
     179        """
     180        Transforms a classical crystal element to the corresponding affine crystal element
    159181
    160         EXAMPLES::
     182        EXAMPLES::
    161183
    162             sage: n=2 
    163             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    164             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    165             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    166             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    167             sage: t=C(rows=[[1]])
    168             sage: type(t)
    169             <class 'sage.combinat.crystals.tensor_product.CrystalOfTableauxElement'>
    170             sage: A.retract(t)
    171             [[1]]
    172             sage: type(A.retract(t))
    173             <class 'sage.combinat.crystals.affine.AffineCrystalFromClassicalAndPromotionElement'>
     184            sage: n=2
     185            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     186            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     187            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     188            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     189            sage: t=C(rows=[[1]])
     190            sage: t.parent()
     191            The crystal of tableaux of type ['A', 2] and shape(s) [[1]]
     192            sage: A.retract(t)
     193            [[1]]
     194            sage: A.retract(t).parent() is A
     195            True
    174196        """
    175197        return self.element_class(classical_elt, parent = self)
    176198   
    class AffineCrystalFromClassical(Crystal 
    181203        EXAMPLES:
    182204
    183205            sage: n=2
    184             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    185             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    186             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    187             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    188             sage: b=A(rows=[[1]])
    189             sage: b
    190             [[1]]
    191             sage: type(b)
    192             <class 'sage.combinat.crystals.affine.AffineCrystalFromClassicalAndPromotionElement'>
    193             sage: A(b)
    194             [[1]]
    195             sage: type(A(b))
    196             <class 'sage.combinat.crystals.affine.AffineCrystalFromClassicalAndPromotionElement'>
     206            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     207            sage: def pr(x): return C(x.to_tableau().promotion(n))
     208            sage: def pr_inverse(x): return C(x.to_tableau().promotion_inverse(n))
     209            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     210            sage: b=A(rows=[[1]])
     211            sage: b
     212            [[1]]
     213            sage: b.parent()
     214            An affine crystal for type ['A', 2, 1]
     215            sage: A(b) is b
     216            True
    197217        """
    198218        if len(value) == 1 and isinstance(value[0], self.element_class) and value[0].parent() == self:
    199219            return value[0]
    class AffineCrystalFromClassical(Crystal 
    202222
    203223    def __contains__(self, x):
    204224        r"""
    205         Checks whether x is an element of self.
     225        Checks whether x is an element of self.
    206226
    207227        EXAMPLES:
    208228
    209229            sage: n=2
    210             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    211             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    212             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    213             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    214             sage: b=A(rows=[[1]])
    215             sage: A.__contains__(b)
    216             True
     230            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     231            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     232            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     233            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     234            sage: b=A(rows=[[1]])
     235            sage: A.__contains__(b)
     236            True
    217237        """
    218238        return x.parent() is self
    219239
    class AffineCrystalFromClassicalElement( 
    231251    EXAMPLES::
    232252
    233253        sage: n=2
    234         sage: C=CrystalOfTableaux(['A',n],shape=[1])
    235         sage: pr=lambda x : C(x.to_tableau().promotion(n))
    236         sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    237         sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    238         sage: b=A(rows=[[1]])
    239         sage: b.__repr__()
    240         '[[1]]'
     254        sage: C=CrystalOfTableaux(['A',n],shape=[1])
     255        sage: pr=lambda x : C(x.to_tableau().promotion(n))
     256        sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     257        sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     258        sage: b=A(rows=[[1]])
     259        sage: b.__repr__()
     260        '[[1]]'
    241261    """
    242262
    243263    def classical_weight(self):
    244         """
    245         Returns the classical weight corresponding to self.
     264        """
     265        Returns the classical weight corresponding to self.
    246266
    247         EXAMPLES::
     267        EXAMPLES::
    248268
    249             sage: n=2
    250             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    251             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    252             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    253             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    254             sage: b=A(rows=[[1]])
    255             sage: b.classical_weight()
    256             (1, 0, 0)
     269            sage: n=2
     270            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     271            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     272            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     273            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     274            sage: b=A(rows=[[1]])
     275            sage: b.classical_weight()
     276            (1, 0, 0)
    257277        """
    258         return self.lift().weight()
     278        return self.lift().weight()
    259279
    260280    def lift(self):
    261         """
    262         Lifts an affine crystal element to the corresponding classical crystal element
     281        """
     282        Lifts an affine crystal element to the corresponding classical crystal element
    263283
    264         EXAMPLES::
     284        EXAMPLES::
    265285
    266286            sage: n=2
    267             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    268             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    269             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    270             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    271             sage: b=A.list()[0]
    272             sage: type(b.lift())
    273             <class 'sage.combinat.crystals.tensor_product.CrystalOfTableauxElement'>
     287            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     288            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     289            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     290            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     291            sage: b=A.list()[0]
     292            sage: b.lift()
     293            [[1]]
     294            sage: b.lift().parent()
     295            The crystal of tableaux of type ['A', 2] and shape(s) [[1]]
    274296        """
    275297        return self.value
    276298
     299    def pp(self):
     300        """
     301        Method for pretty printing
     302
     303        EXAMPLES::
     304
     305            sage: K = KirillovReshetikhinCrystal(['D',3,2],1,1)
     306            sage: t=K(rows=[[1]])
     307            sage: t.pp()
     308            1
     309        """
     310        return self.lift().pp()
     311
    277312    @abstract_method
    278313    def e0(self):
    279         r"""
    280         Assumes that `e_0` is implemented separately.
    281         """
     314        r"""
     315        Assumes that `e_0` is implemented separately.
     316        """
    282317
    283318    @abstract_method
    284319    def f0(self):
    285         r"""
    286         Assumes that `f_0` is implemented separately.
    287         """
     320        r"""
     321        Assumes that `f_0` is implemented separately.
     322        """
    288323
    289324    def e(self, i):
    290325        r"""
    291326        Returns the action of `e_i` on self.
    292327
    293         EXAMPLES::
     328        EXAMPLES::
    294329
    295330            sage: n=2
    296             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    297             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    298             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    299             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    300             sage: b=A(rows=[[1]])
    301             sage: b.e(0)
    302             [[3]]
    303             sage: b.e(1)
     331            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     332            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     333            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     334            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     335            sage: b=A(rows=[[1]])
     336            sage: b.e(0)
     337            [[3]]
     338            sage: b.e(1)
    304339        """
    305340        if i == 0:
    306             return self.e0()
    307         else:
     341            return self.e0()
     342        else:
    308343            x = self.lift().e(i)
    309344            if (x == None):
    310345                return None
    class AffineCrystalFromClassicalElement( 
    315350        r"""
    316351        Returns the action of `f_i` on self.
    317352
    318         EXAMPLES::
     353        EXAMPLES::
    319354
    320355            sage: n=2
    321             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    322             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    323             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    324             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    325             sage: b=A(rows=[[3]])
    326             sage: b.f(0)
    327             [[1]]
    328             sage: b.f(2)
     356            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     357            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     358            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     359            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     360            sage: b=A(rows=[[3]])
     361            sage: b.f(0)
     362            [[1]]
     363            sage: b.f(2)
    329364        """
    330365        if i == 0:
    331             return self.f0()
    332         else:
     366            return self.f0()
     367        else:
    333368            x = self.lift().f(i)
    334369            if (x == None):
    335370                return None
    class AffineCrystalFromClassicalElement( 
    337372                return self.parent().retract(x)
    338373
    339374    def epsilon0(self):
    340         r"""
    341         Uses `epsilon_0` from the super class, but should be implemented if a faster implementation exists.
    342         """
    343         return super(AffineCrystalFromClassicalElement, self).epsilon(0)
     375        r"""
     376        Uses `epsilon_0` from the super class, but should be implemented if a faster implementation exists.
     377        """
     378        return super(AffineCrystalFromClassicalElement, self).epsilon(0)
    344379
    345380    def epsilon(self, i):
    346         """
    347         Returns the maximal time the crystal operator `e_i` can be applied to self.
     381        """
     382        Returns the maximal time the crystal operator `e_i` can be applied to self.
    348383
    349         EXAMPLES::
     384        EXAMPLES::
    350385
    351             sage: n=2
    352             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    353             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    354             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    355             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    356             sage: [x.epsilon(0) for x in A.list()]
    357             [1, 0, 0]
    358             sage: [x.epsilon(1) for x in A.list()]
    359             [0, 1, 0]
    360         """
     386            sage: n=2
     387            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     388            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     389            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     390            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     391            sage: [x.epsilon(0) for x in A.list()]
     392            [1, 0, 0]
     393            sage: [x.epsilon(1) for x in A.list()]
     394            [0, 1, 0]
     395        """
    361396        if i == 0:
    362397            return self.epsilon0()
    363398        else:
    364399            return self.lift().epsilon(i)
    365400
    366401    def phi0(self):
    367         r"""
    368         Uses `phi_0` from the super class, but should be implemented if a faster implementation exists.
    369         """
    370         return super(AffineCrystalFromClassicalElement, self).phi(0)
     402        r"""
     403        Uses `phi_0` from the super class, but should be implemented if a faster implementation exists.
     404        """
     405        return super(AffineCrystalFromClassicalElement, self).phi(0)
    371406
    372407    def phi(self, i):
    373         r"""
    374         Returns the maximal time the crystal operator `f_i` can be applied to self.
     408        r"""
     409        Returns the maximal time the crystal operator `f_i` can be applied to self.
    375410
    376         EXAMPLES::
     411        EXAMPLES::
    377412
    378             sage: n=2
    379             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    380             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    381             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    382             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    383             sage: [x.phi(0) for x in A.list()]
    384             [0, 0, 1]
    385             sage: [x.phi(1) for x in A.list()]
    386             [1, 0, 0]
     413            sage: n=2
     414            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     415            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     416            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     417            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     418            sage: [x.phi(0) for x in A.list()]
     419            [0, 0, 1]
     420            sage: [x.phi(1) for x in A.list()]
     421            [1, 0, 0]
    387422        """
    388423        if i == 0:
    389             return self.phi0()
     424            return self.phi0()
    390425        else:
    391426            return self.lift().phi(i)
    392427
    393 AffineCrystalFromClassical.element_class = AffineCrystalFromClassicalElement
     428AffineCrystalFromClassical.Element = AffineCrystalFromClassicalElement
    394429
    395430
    396431class AffineCrystalFromClassicalAndPromotion(AffineCrystalFromClassical):
    class AffineCrystalFromClassicalAndPromo 
    418453
    419454        sage: n=2
    420455        sage: C=CrystalOfTableaux(['A',n],shape=[1])
    421         sage: pr=lambda x : C(x.to_tableau().promotion(n))
    422         sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    423         sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    424         sage: A.list()
    425         [[[1]], [[2]], [[3]]]
    426         sage: A.cartan_type()
    427         ['A', 2, 1]
    428         sage: A.index_set()
    429         [0, 1, 2]
    430         sage: b=A(rows=[[1]])
    431         sage: b.weight()
    432         -Lambda[0] + Lambda[1]
    433         sage: b.classical_weight()
    434         (1, 0, 0)
    435         sage: [x.s(0) for x in A.list()]
    436         [[[3]], [[2]], [[1]]]
    437         sage: [x.s(1) for x in A.list()]
    438         [[[2]], [[1]], [[3]]]
     456        sage: pr=lambda x : C(x.to_tableau().promotion(n))
     457        sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     458        sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     459        sage: A.list()
     460        [[[1]], [[2]], [[3]]]
     461        sage: A.cartan_type()
     462        ['A', 2, 1]
     463        sage: A.index_set()
     464        [0, 1, 2]
     465        sage: b=A(rows=[[1]])
     466        sage: b.weight()
     467        -Lambda[0] + Lambda[1]
     468        sage: b.classical_weight()
     469        (1, 0, 0)
     470        sage: [x.s(0) for x in A.list()]
     471        [[[3]], [[2]], [[1]]]
     472        sage: [x.s(1) for x in A.list()]
     473        [[[2]], [[1]], [[3]]]
    439474    """
    440475
    441476    def __init__(self, cartan_type, classical_crystal, p_automorphism, p_inverse_automorphism, dynkin_node):
    442         """
    443         Input is an affine Cartan type 'cartan_type', a classical crystal 'classical_crystal', and automorphism and its
    444         inverse 'automorphism' and 'inverse_automorphism', and the Dynkin node 'dynkin_node'
     477        """
     478        Input is an affine Cartan type 'cartan_type', a classical crystal 'classical_crystal', and automorphism and its
     479        inverse 'automorphism' and 'inverse_automorphism', and the Dynkin node 'dynkin_node'
    445480
    446         EXAMPLES::
     481        EXAMPLES::
    447482
    448             sage: n=1
    449             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    450             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    451             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    452             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    453             sage: A.list()
    454             [[[1]], [[2]]]
    455             sage: A.cartan_type()
    456             ['A', 1, 1]
    457             sage: A.index_set()
    458             [0, 1]
    459         """
    460         AffineCrystalFromClassical.__init__(self, cartan_type, classical_crystal)
     483            sage: n=1
     484            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     485            sage: def pr(x): return C(x.to_tableau().promotion(n))
     486            sage: def pr_inverse(x): return C(x.to_tableau().promotion_inverse(n))
     487            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     488            sage: A.list()
     489            [[[1]], [[2]]]
     490            sage: A.cartan_type()
     491            ['A', 1, 1]
     492            sage: A.index_set()
     493            [0, 1]
     494
     495        TESTS::
     496
     497            sage: import __main__; __main__.pr = pr; __main__.pr_inverse = pr_inverse # standard pickling hack
     498            sage: TestSuite(A).run()
     499        """
     500        AffineCrystalFromClassical.__init__(self, cartan_type, classical_crystal)
    461501        self.p_automorphism = p_automorphism
    462502        self.p_inverse_automorphism = p_inverse_automorphism
    463         self.dynkin_node = dynkin_node
     503        self.dynkin_node = dynkin_node
    464504
    465505    def automorphism(self, x):
    466         """
    467         Gives the analogue of the affine Dynkin diagram automorphism on the level of crystals
     506        """
     507        Gives the analogue of the affine Dynkin diagram automorphism on the level of crystals
    468508
    469         EXAMPLES::
     509        EXAMPLES::
    470510
    471511            sage: n=2
    472             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    473             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    474             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    475             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    476             sage: b=A.list()[0]
    477             sage: A.automorphism(b)
    478             [[2]]
    479         """
     512            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     513            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     514            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     515            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     516            sage: b=A.list()[0]
     517            sage: A.automorphism(b)
     518            [[2]]
     519        """
    480520        return self.retract( self.p_automorphism( x.lift() ) )
    481521
    482522    def inverse_automorphism(self, x):
    483         """
    484         Gives the analogue of the inverse of the affine Dynkin diagram automorphism on the level of crystals
     523        """
     524        Gives the analogue of the inverse of the affine Dynkin diagram automorphism on the level of crystals
    485525
    486         EXAMPLES::
     526        EXAMPLES::
    487527
    488528            sage: n=2
    489             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    490             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    491             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    492             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    493             sage: b=A.list()[0]
    494             sage: A.inverse_automorphism(b)
    495             [[3]]
    496         """
     529            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     530            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     531            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     532            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     533            sage: b=A.list()[0]
     534            sage: A.inverse_automorphism(b)
     535            [[3]]
     536        """
    497537        return self.retract( self.p_inverse_automorphism( x.lift() ) )
    498538
    499539class AffineCrystalFromClassicalAndPromotionElement(AffineCrystalFromClassicalElement):
    class AffineCrystalFromClassicalAndPromo 
    513553    EXAMPLES::
    514554
    515555        sage: n=2
    516         sage: C=CrystalOfTableaux(['A',n],shape=[1])
    517         sage: pr=lambda x : C(x.to_tableau().promotion(n))
    518         sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    519         sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    520         sage: b=A(rows=[[1]])
    521         sage: b.__repr__()
    522         '[[1]]'
     556        sage: C=CrystalOfTableaux(['A',n],shape=[1])
     557        sage: pr=lambda x : C(x.to_tableau().promotion(n))
     558        sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     559        sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     560        sage: b=A(rows=[[1]])
     561        sage: b.__repr__()
     562        '[[1]]'
    523563    """
    524564
    525565    def e0(self):
    526         r"""
    527         Implements `e_0` using the automorphism as
    528         `e_0 = \pr^{-1} e_{dynkin_node} \pr`
     566        r"""
     567        Implements `e_0` using the automorphism as
     568        `e_0 = \pr^{-1} e_{dynkin_node} \pr`
    529569
    530         EXAMPLES::
     570        EXAMPLES::
    531571
    532             sage: n=2
    533             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    534             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    535             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    536             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    537             sage: b=A(rows=[[1]])
    538             sage: b.e0()
    539             [[3]]
    540         """
    541         x = self.parent().automorphism(self).e(self.parent().dynkin_node)
    542         if (x == None):
    543             return None
    544         else:
    545             return self.parent().inverse_automorphism(x)
     572            sage: n=2
     573            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     574            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     575            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     576            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     577            sage: b=A(rows=[[1]])
     578            sage: b.e0()
     579            [[3]]
     580        """
     581        x = self.parent().automorphism(self).e(self.parent().dynkin_node)
     582        if (x == None):
     583            return None
     584        else:
     585            return self.parent().inverse_automorphism(x)
    546586
    547587    def f0(self):
    548         r"""
    549         Implements `f_0` using the automorphism as
    550         `f_0 = \pr^{-1} f_{dynkin_node} \pr`
     588        r"""
     589        Implements `f_0` using the automorphism as
     590        `f_0 = \pr^{-1} f_{dynkin_node} \pr`
    551591
    552         EXAMPLES::
     592        EXAMPLES::
    553593
    554             sage: n=2
    555             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    556             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    557             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    558             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    559             sage: b=A(rows=[[3]])
    560             sage: b.f0()
    561             [[1]]
     594            sage: n=2
     595            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     596            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     597            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     598            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     599            sage: b=A(rows=[[3]])
     600            sage: b.f0()
     601            [[1]]
    562602        """
    563         x = self.parent().automorphism(self).f(self.parent().dynkin_node)
    564         if (x == None):
    565             return None
    566         else:
    567             return self.parent().inverse_automorphism(x)
     603        x = self.parent().automorphism(self).f(self.parent().dynkin_node)
     604        if (x == None):
     605            return None
     606        else:
     607            return self.parent().inverse_automorphism(x)
    568608
    569609    def epsilon0(self):
    570         r"""
    571         Implements `epsilon_0` using the automorphism.
     610        r"""
     611        Implements `epsilon_0` using the automorphism.
    572612
    573         EXAMPLES::
     613        EXAMPLES::
    574614
    575             sage: n=2
    576             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    577             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    578             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    579             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    580             sage: [x.epsilon0() for x in A.list()]
    581             [1, 0, 0]
    582         """
    583         x = self.parent().automorphism(self)
    584         return x.lift().epsilon(self.parent().dynkin_node)
     615            sage: n=2
     616            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     617            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     618            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     619            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     620            sage: [x.epsilon0() for x in A.list()]
     621            [1, 0, 0]
     622        """
     623        x = self.parent().automorphism(self)
     624        return x.lift().epsilon(self.parent().dynkin_node)
    585625
    586626    def phi0(self):
    587         r"""
    588         Implements `phi_0` using the automorphism.
     627        r"""
     628        Implements `phi_0` using the automorphism.
    589629
    590         EXAMPLES::
     630        EXAMPLES::
    591631
    592             sage: n=2
    593             sage: C=CrystalOfTableaux(['A',n],shape=[1])
    594             sage: pr=lambda x : C(x.to_tableau().promotion(n))
    595             sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
    596             sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
    597             sage: [x.phi0() for x in A.list()]
    598             [0, 0, 1]
    599         """
    600         x = self.parent().automorphism(self)
    601         return x.lift().phi(self.parent().dynkin_node)
     632            sage: n=2
     633            sage: C=CrystalOfTableaux(['A',n],shape=[1])
     634            sage: pr=lambda x : C(x.to_tableau().promotion(n))
     635            sage: pr_inverse = lambda x : C(x.to_tableau().promotion_inverse(n))
     636            sage: A=AffineCrystalFromClassicalAndPromotion(['A',n,1],C,pr,pr_inverse,1)
     637            sage: [x.phi0() for x in A.list()]
     638            [0, 0, 1]
     639        """
     640        x = self.parent().automorphism(self)
     641        return x.lift().phi(self.parent().dynkin_node)
    602642
    603 AffineCrystalFromClassicalAndPromotion.element_class = AffineCrystalFromClassicalAndPromotionElement
     643AffineCrystalFromClassicalAndPromotion.Element = AffineCrystalFromClassicalAndPromotionElement
  • sage/combinat/crystals/crystals.py

    diff --git a/sage/combinat/crystals/crystals.py b/sage/combinat/crystals/crystals.py
    a b It has a single highest weight element:: 
    5151    sage: C.highest_weight_vectors()
    5252    [1]
    5353
    54 A crystal is a CombinatorialClass; and we can count and list its
    55 elements in the usual way::
     54A crystal is an enumerated set (see :class:`EnumeratedSets`); and we
     55can count and list its elements in the usual way::
    5656
    5757    sage: C.cardinality()
    5858    6
    5959    sage: C.list()
    6060    [1, 2, 3, 4, 5, 6]
    6161
    62 as well as use it in for loops
    63 
    64 ::
     62as well as use it in for loops::
    6563
    6664    sage: [x for x in C]
    6765    [1, 2, 3, 4, 5, 6]
    inspiration. 
    138136
    139137from sage.misc.latex import latex
    140138from sage.misc.cachefunc import CachedFunction
     139from sage.structure.unique_representation import UniqueRepresentation
    141140from sage.structure.parent import Parent
    142141from sage.structure.element import Element
    143 from sage.combinat.combinat import CombinatorialClass
     142from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    144143from sage.graphs.all import DiGraph
    145144from sage.combinat import ranker
    146 from sage.combinat.tools import transitive_ideal
    147 from sage.combinat.root_system.weyl_characters import WeylCharacterRing, WeylCharacter
     145from sage.combinat.root_system.weyl_characters import WeylCharacter
    148146from sage.combinat.backtrack import GenericBacktracker
    149147
    150148## MuPAD-Combinat's Cat::Crystal
    151149# FIXME: crystals, like most parent should have unique data representation
    152 class Crystal(CombinatorialClass, Parent):
     150# TODO: make into a category
     151class Crystal(UniqueRepresentation, Parent):
    153152    r"""
    154153    The abstract class of crystals
    155154   
    class Crystal(CombinatorialClass, Parent 
    162161
    163162    """
    164163
     164    def _an_element_(self):
     165        """
     166        Returns an element of self
     167
     168            sage: C = CrystalOfLetters(['A', 5])
     169            sage: C.an_element()
     170            1
     171        """
     172        return self.first()
     173
    165174    def weight_lattice_realization(self):
    166175        """
    167176        Returns the weight lattice realization for the root system
    class Crystal(CombinatorialClass, Parent 
    445454        f = open(filename, 'w')
    446455        f.write(header + self.latex() + footer)
    447456        f.close()
    448        
    449 
     457 
    450458    def latex(self):
    451459        r"""
    452460        Returns the crystal graph as a bit of latex. This can be exported
    453461        to a file with self.latex_file('filename').
    454        
    455         This requires dot2tex to be installed in sage-python.
    456        
    457         Here some tips for installation:
    458        
    459        
     462
     463        This requires the dot2tex spkg. Here some tips for installation:
     464
    460465        -  Install graphviz = 2.14
    461        
    462         -  Download pyparsing-1.4.11.tar.gz pydot-0.9.10.tar.gz
    463            dot2tex-2.7.0.tar.gz (see the dot2tex web page for download links)
    464            (note that the most recent version of pydot may not work. Be sure
    465            to install the 0.9.10 version.) Install each of them using the
    466            standard python install, but using sage-python:
    467        
    468            ::
    469        
    470                            # FIX ACCORDING TO YOUR Sage INSTALL
    471                            export sagedir=/opt/sage/
    472                            export sagepython=$sagedir/local/bin/sage-python
    473                
    474                            # Use downloaded version nums
    475                            for package in pyparsing-1.4.11 pydot-0.9.10 dot2tex-2.7.0; do\ 
    476                                    tar zxvf $package.tar.gz;\
    477                                    cd $package;\
    478                                    sudo $sagepython setup.py install;\
    479                                    cd ..;\
    480                                done
    481                          
    482        
    483         -  Install pgf-2.00 inside your latex tree In short:
    484        
    485            
     466
     467        -  Download dot2tex-0.?.spkg from http://wiki.sagemath.org/combinat/FPSAC09/projects
     468
     469        -  Install pgf-2.00 inside your latex tree. In short:
     470
    486471           -  untaring in /usr/share/texmf/tex/generic
    487        
     472
    488473           -  clean out remaining pgf files from older version
    489        
     474
    490475           -  run texhash
    491        
    492        
    493        
    494         You should be done! To test, go to the dot2tex-2.7.0/examples
    495         directory, and type::
    496        
    497                     $sagedir//local/bin/dot2tex balls.dot > balls.tex
    498                     pdflatex balls.tex
    499                     open balls.pdf \#your favorite viewer here
    500                    
    501        
     476
     477
     478        In case LaTeX complains about tikzpicture not being defined,
     479        you may need to further run::
     480
     481           sage: sage.misc.latex.LATEX_HEADER+=r"\\usepackage{tikz}"
     482
     483
    502484        EXAMPLES::
    503        
     485
    504486            sage: C = CrystalOfLetters(['A', 5])
    505             sage: C.latex() #optional requires dot2tex
     487            sage: C.latex()         #optional requires dot2tex
    506488            ...
     489            sage: view(C, pdflatex = True, tightpage = True) # optional
    507490        """
    508491
    509492        try:
    class Crystal(CombinatorialClass, Parent 
    519502
    520503        return content
    521504
     505    _latex_ = latex
     506
    522507    def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, tallness=1.0):
    523508        """Use C.metapost("filename.mp",[options])
    524509        where options can be:
    class Crystal(CombinatorialClass, Parent 
    687672                child = x.f(i)
    688673                if child is None:
    689674                    continue
    690                 result += "  " + vertex_key(x) + " -> "+vertex_key(child)+ " [ label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n"
     675#                result += "  " + vertex_key(x) + " -> "+vertex_key(child)+ " [ label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n"
     676                if i == 0:
     677                    option = "dir = back, "
     678                    (source, target) = (child, x)
     679                else:
     680                    option = ""
     681                    (source, target) = (x, child)
     682                result += "  " + vertex_key(source) + " -> "+vertex_key(target)+ " [ "+option+"label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n"
    691683        result+="}"
    692684        return result
    693685   
    class ClassicalCrystal(Crystal): 
    10741066    r"""
    10751067    The abstract class of classical crystals
    10761068    """
    1077     list  = CombinatorialClass.list#__list_from_iterator
     1069
     1070    def list(self):
     1071        r"""
     1072        Returns the list of the elements of ``self``, as per
     1073        :meth:`FiniteEnumeratedSets.ParentMethods.list`
     1074
     1075        EXAMPLES::
     1076
     1077            sage: C = CrystalOfLetters(['D',4])
     1078            sage: C.list()
     1079            [1, 2, 3, 4, -4, -3, -2, -1]
     1080
     1081        FIXME: this is just there to reinstate the default
     1082        implementation of list which is overriden in
     1083        :class:`Crystals`.
     1084        """
     1085        return self._list_from_iterator()
     1086
    10781087    def __iter__(self):
    10791088        r"""
    10801089        Returns an iterator over the elements of the crystal.
  • sage/combinat/crystals/fast_crystals.py

    diff --git a/sage/combinat/crystals/fast_crystals.py b/sage/combinat/crystals/fast_crystals.py
    a b Fast Rank Two Crystals 
    1919#
    2020#                  http://www.gnu.org/licenses/
    2121#****************************************************************************
    22 from sage.rings.all import Integer
     22from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     23from sage.structure.element import Element, parent
    2324from sage.combinat.root_system.cartan_type import CartanType
    2425from sage.combinat.crystals.crystals import ClassicalCrystal, CrystalElement
    2526
    class FastCrystal(ClassicalCrystal): 
    8384        sage: C.check()
    8485        True
    8586    """
    86     def __init__(self, ct, shape, format="string"):
     87
     88    @staticmethod
     89    def __classcall__(cls, cartan_type, shape, format = "string"):
     90        """
     91        Normalizes the input arguments to ensure unique representation
     92
     93        EXAMPLES::
     94
     95            sage: C1 = FastCrystal(['A',2],            shape=(4,1))
     96            sage: C2 = FastCrystal(CartanType(['A',2]),shape=[4,1])
     97            sage: C1 is C2
     98            True
     99        """
     100        cartan_type = CartanType(cartan_type)
     101        shape = tuple(shape)
     102        if len(shape) > 2:
     103            raise ValueError, "The shape must have length <=2"
     104        shape = shape + (0,)*(2-len(shape))
     105        return super(FastCrystal, cls).__classcall__(cls, cartan_type, shape, format)
     106
     107    def __init__(self, ct, shape, format):
    87108        """
    88109        EXAMPLES::
    89        
     110
    90111            sage: C = FastCrystal(['A',2],shape=[4,1]); C
    91112            The fast crystal for A2 with shape [4,1]
     113            sage: TestSuite(C).run()
    92114        """
    93         self._cartan_type = CartanType(ct)
     115        super(FastCrystal, self).__init__(category = FiniteEnumeratedSets())
     116        self._cartan_type = ct
    94117        if ct[1] != 2:
    95118            raise NotImplementedError
    96119
    97         if len(shape) > 2:
    98             raise ValueError, "The shape must have length <=2"
    99 
    100         while len(shape)<2:
    101             shape.append(0)
    102 
    103120        l1 = shape[0]
    104121        l2 = shape[1]
    105122
     123        # For safety, delpat and gampat should be immutable
     124
    106125        self.delpat = []
    107126        self.gampat = []
    108127
    class FastCrystal(ClassicalCrystal): 
    141160            assert self._cartan_type[0] == 'B' and int(2*l2)%2 == 1
    142161            l1_str = "%d/2"%int(2*l1)
    143162            l2_str = "%d/2"%int(2*l2)
    144         self._name = "The fast crystal for %s2 with shape [%s,%s]"%(ct[0],l1_str,l2_str)
     163        self.rename("The fast crystal for %s2 with shape [%s,%s]"%(ct[0],l1_str,l2_str))
    145164        self.module_generators = [self(0)]
    146165        self._list = ClassicalCrystal.list(self)
    147166        self._digraph = ClassicalCrystal.digraph(self)
    class FastCrystal(ClassicalCrystal): 
    216235            [0, 0, 0]
    217236            sage: C(1)
    218237            [1, 0, 0]
     238            sage: x = C(0)
     239            sage: C(x) is x
     240            True
    219241        """
    220         return FastCrystalElement(self, value, self.format)
     242        if parent(value) is self: return value
     243        return self.element_class(self, value, self.format)
    221244
    222245    def list(self):
    223246        """
    class FastCrystalElement(CrystalElement) 
    287310            sage: C = FastCrystal(['A',2],shape=[2,1])
    288311            sage: c = C(0); c
    289312            [0, 0, 0]
     313            sage: C[0].parent()
     314            The fast crystal for A2 with shape [2,1]
     315            sage: TestSuite(c).run()
    290316        """
    291         self._parent = parent
     317        Element.__init__(self, parent)
    292318        self.value = value
    293319        self.format = format
    294320
    295     def parent(self): # Should be inherited from Element
    296         """
    297         Returns the parent of self.
    298        
    299         EXAMPLES::
    300        
    301             sage: C = FastCrystal(['A',2],shape=[2,1])
    302             sage: C[0].parent()
    303             The fast crystal for A2 with shape [2,1]
    304         """
    305         return self._parent
    306 
    307321    def weight(self):
    308322        """
    309323        Returns the weight of self.
    class FastCrystalElement(CrystalElement) 
    323337        """
    324338        delpat = self.parent().delpat[self.value]
    325339        if self.parent()._cartan_type[0] == 'A':
    326             delpat.append(0)
     340            delpat = delpat + [0,]
    327341        [alpha1, alpha2] = self.parent().weight_lattice_realization().simple_roots()
    328342        hwv = sum(self.parent().shape[i]*self.parent().weight_lattice_realization().monomial(i) for i in range(2))
    329343        return hwv - (delpat[0]+delpat[2])*alpha1 - (delpat[1]+delpat[3])*alpha2
    class FastCrystalElement(CrystalElement) 
    423437        return self.parent()(r) if r is not None else None           
    424438
    425439
     440FastCrystal.Element = FastCrystalElement
  • sage/combinat/crystals/kirillov_reshetikhin.py

    diff --git a/sage/combinat/crystals/kirillov_reshetikhin.py b/sage/combinat/crystals/kirillov_reshetikhin.py
    a b Affine crystals 
    2323from sage.combinat.combinat import CombinatorialObject
    2424from sage.rings.integer import Integer
    2525from sage.misc.functional import is_even, is_odd
    26 from sage.combinat.crystals.crystals import Crystal, ClassicalCrystal, CrystalElement
     26from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    2727from sage.combinat.crystals.affine import AffineCrystal, AffineCrystalFromClassical, AffineCrystalFromClassicalElement
    28 from sage.combinat.crystals.affine import AffineCrystalFromClassicalAndPromotion, AffineCrystalFromClassicalAndPromotionElement
     28from sage.combinat.crystals.affine import AffineCrystalFromClassicalAndPromotion
    2929from sage.combinat.root_system.cartan_type import CartanType
    3030from sage.combinat.crystals.tensor_product import CrystalOfTableaux
    31 from sage.combinat.tableau import Tableau_class, Tableau
     31from sage.combinat.tableau import Tableau
    3232from sage.combinat.partition import Partition, Partitions
    3333from sage.combinat.integer_vector import IntegerVectors
    3434
    def KirillovReshetikhinCrystal(cartan_ty 
    115115        sage: K.cartan_type()
    116116        ['D', 4, 1]
    117117        sage: type(K.module_generators[0])
    118         <class 'sage.combinat.crystals.affine.AffineCrystalFromClassicalAndPromotionElement'>
     118        <class 'sage.combinat.crystals.affine.KR_type_vertical_with_category.element_class'>
    119119    """
    120120    ct = CartanType(cartan_type)
    121121    assert ct.is_affine()
    class KirillovReshetikhinGenericCrystal( 
    153153
    154154        TESTS::
    155155
    156             sage: K = sage.combinat.crystals.kirillov_reshetikhin.KirillovReshetikhinGenericCrystal(['A',2,1], 1, 1)
     156            sage: K = sage.combinat.crystals.kirillov_reshetikhin.KirillovReshetikhinGenericCrystal(CartanType(['A',2,1]), 1, 1)
    157157            sage: K
    158158            Kirillov-Reshetikhin crystal of type ['A', 2, 1] with (r,s)=(1,1)
    159159            sage: K.r()
    class KirillovReshetikhinGenericCrystal( 
    161161            sage: K.s()
    162162            1
    163163        """
    164         self._cartan_type = CartanType(cartan_type)
     164        self._cartan_type = cartan_type
    165165        self._r = r
    166166        self._s = s
    167         self._name = "Kirillov-Reshetikhin crystal of type %s with (r,s)=(%d,%d)" % (cartan_type, r, s)
     167
     168    def _repr_(self):
     169        """
     170        EXAMPLES::
     171
     172            sage: sage.combinat.crystals.kirillov_reshetikhin.KirillovReshetikhinGenericCrystal(CartanType(['A',2,1]), 1, 1) # indirect doctest
     173            Kirillov-Reshetikhin crystal of type ['A', 2, 1] with (r,s)=(1,1)
     174        """
     175        return "Kirillov-Reshetikhin crystal of type %s with (r,s)=(%d,%d)" % (self.cartan_type(), self.r(), self.s())
    168176
    169177    def r(self):
    170178        """
    class KirillovReshetikhinCrystalFromProm 
    210218            sage: K = KirillovReshetikhinCrystal(['B',2,1], 1, 1)
    211219            sage: K
    212220            Kirillov-Reshetikhin crystal of type ['B', 2, 1] with (r,s)=(1,1)
     221            sage: TestSuite(K).run()
    213222        """
    214223        KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r ,s)
    215         AffineCrystalFromClassicalAndPromotion.__init__(self, cartan_type, self.classical_decomposition(), 
    216                                                         self.promotion(), self.promotion_inverse(), 
     224        AffineCrystalFromClassicalAndPromotion.__init__(self, cartan_type, self.classical_decomposition(),
     225                                                        self.promotion(), self.promotion_inverse(),
    217226                                                        self.dynkin_diagram_automorphism(0))
    218227
    219228
    class KR_type_A(KirillovReshetikhinCryst 
    237246
    238247            sage: K = KirillovReshetikhinCrystal(['A',3,1], 2,2)
    239248            sage: K.classical_decomposition()
    240             The crystal of tableaux of type ['A', 3] and shape(s) ([2, 2],)
     249            The crystal of tableaux of type ['A', 3] and shape(s) [[2, 2]]
    241250        """
    242251        return CrystalOfTableaux(self.cartan_type().classical(), shape = [self.s() for i in range(1,self.r()+1)])
    243252   
    class KR_type_C(KirillovReshetikhinGener 
    488497            sage: K = sage.combinat.crystals.kirillov_reshetikhin.KR_type_C(['C',2,1], 1, 1)
    489498            sage: K
    490499            Kirillov-Reshetikhin crystal of type ['C', 2, 1] with (r,s)=(1,1)
     500            sage: TestSuite(K).run()
    491501        """
    492502        KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r ,s)
    493503        AffineCrystalFromClassical.__init__(self, cartan_type, self.classical_decomposition())
    class KR_type_C(KirillovReshetikhinGener 
    590600            sage: b=K(rows=[])
    591601            sage: K.to_ambient_crystal()(b)
    592602            [[2], [-2]]
    593             sage: type(K.to_ambient_crystal()(b))
    594             <class 'sage.combinat.crystals.affine.AffineCrystalFromClassicalAndPromotionElement'>
     603            sage: K.to_ambient_crystal()(b).parent() # Anne: please check this!!!!
     604            Kirillov-Reshetikhin crystal of type ['B', 4, 1]^* with (r,s)=(2,2)
    595605        """
    596606        keys = self.highest_weight_dict().keys()
    597607        pdict = dict( (self.highest_weight_dict()[key], self.ambient_highest_weight_dict()[key]) for key in keys )
    class KR_type_CElement(AffineCrystalFrom 
    624634
    625635        sage: K=KirillovReshetikhinCrystal(['C',3,1],1,2)
    626636        sage: type(K.module_generators[0])
    627         <class 'sage.combinat.crystals.kirillov_reshetikhin.KR_type_CElement'>
     637        <class 'sage.combinat.crystals.kirillov_reshetikhin.KR_type_C_with_category.element_class'>
    628638    """
    629639
    630640    def e0(self):
    class KR_type_CElement(AffineCrystalFrom 
    693703        b = self.parent().to_ambient_crystal()(self)
    694704        return b.phi(1)
    695705
    696 KR_type_C.element_class = KR_type_CElement
     706KR_type_C.Element = KR_type_CElement
    697707
    698708
    699709class KR_type_box(KirillovReshetikhinGenericCrystal, AffineCrystalFromClassical):
    class KR_type_box(KirillovReshetikhinGen 
    724734            sage: K = sage.combinat.crystals.kirillov_reshetikhin.KR_type_box(['D',4,2], 1, 1)
    725735            sage: K
    726736            Kirillov-Reshetikhin crystal of type ['C', 3, 1]^* with (r,s)=(1,1)
     737            sage: TestSuite(K).run()
    727738        """
    728739        KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r ,s)
    729740        AffineCrystalFromClassical.__init__(self, cartan_type, self.classical_decomposition())
    class KR_type_boxElement(AffineCrystalFr 
    858869
    859870        sage: K=KirillovReshetikhinCrystal(['A',4,2],1,2)
    860871        sage: type(K.module_generators[0])
    861         <class 'sage.combinat.crystals.kirillov_reshetikhin.KR_type_boxElement'>
     872        <class 'sage.combinat.crystals.kirillov_reshetikhin.KR_type_box_with_category.element_class'>
    862873    """
    863874
    864875    def e0(self):
    class KR_type_boxElement(AffineCrystalFr 
    925936        b = self.parent().to_ambient_crystal()(self)
    926937        return b.phi(0)
    927938
    928 KR_type_box.element_class = KR_type_boxElement
     939KR_type_box.Element = KR_type_boxElement
    929940
    930941
    931942class PMDiagram(CombinatorialObject):
  • sage/combinat/crystals/letters.py

    diff --git a/sage/combinat/crystals/letters.py b/sage/combinat/crystals/letters.py
    a b Crystals of letters 
    44
    55#*****************************************************************************
    66#       Copyright (C) 2007 Anne Schilling <anne at math.ucdavis.edu>
    7 #                          Nicolas Thiery <nthiery at users.sf.net>
     7#                          Nicolas M. Thiery <nthiery at users.sf.net>
    88#                          Daniel Bump    <bump at match.stanford.edu>
    99#                          Brant Jones    <brant at math.ucdavis.edu>
    1010#
    Crystals of letters 
    2121#****************************************************************************
    2222
    2323from sage.structure.unique_representation import UniqueRepresentation
    24 from sage.structure.element import Element
     24from sage.structure.element import parent
     25from sage.structure.parent import Parent
     26from sage.structure.element_wrapper import ElementWrapper
     27from sage.categories.all import FiniteEnumeratedSets
    2528from sage.combinat.root_system.cartan_type import CartanType
    2629from crystals import ClassicalCrystal, CrystalElement
    2730
    def CrystalOfLetters(cartan_type, elemen 
    6770    EXAMPLES::
    6871
    6972        sage: C = CrystalOfLetters(['E',6], element_print_style = 'compact')
     73        sage: C
     74        The crystal of letters for type ['E', 6]
    7075        sage: C.list()
    7176        [+, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]
    7277        sage: C = CrystalOfLetters(['E',6], element_print_style = 'compact', dual = True)
     78        sage: C
     79        The crystal of letters for type ['E', 6] (dual)
    7380        sage: C.list()
    7481        [-, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
    7582    """
    def CrystalOfLetters(cartan_type, elemen 
    103110        raise NotImplementedError
    104111
    105112
    106 class ClassicalCrystalOfLetters(UniqueRepresentation, ClassicalCrystal):
     113class ClassicalCrystalOfLetters(ClassicalCrystal):
    107114    r"""
    108115    A generic class for classical crystals of letters.
    109116   
    class ClassicalCrystalOfLetters(UniqueRe 
    123130    def __init__(self, cartan_type, element_class, element_print_style = None, dual = None):
    124131        """
    125132        EXAMPLES::
    126        
     133
    127134            sage: C = CrystalOfLetters(['A',5])
    128             sage: C == loads(dumps(C))
    129             True
     135            sage: C.category()
     136            Category of finite enumerated sets
     137            sage: TestSuite(C).run()
    130138        """
    131139        self._cartan_type = CartanType(cartan_type)
    132         self._name = "The crystal of letters for type %s"%cartan_type
    133         self.element_class = element_class
     140        self.rename("The crystal of letters for type %s"%cartan_type)
     141        self.Element = element_class
     142        Parent.__init__(self, category = FiniteEnumeratedSets()) #, category = ClassicalCrystals()
    134143        if cartan_type == CartanType(['E',6]):
    135144            if dual:
    136145                self.module_generators = [self([6])]
    137146                self._ambient = CrystalOfLetters(CartanType(['E',6]))
     147                self.rename("%s (dual)"%self)
    138148            else:
    139149                self.module_generators = [self([1])]
    140150        elif cartan_type == CartanType(['E',7]):
    class ClassicalCrystalOfLetters(UniqueRe 
    233243        return False
    234244
    235245# Utility. Note: much of this class should be factored out at some point!
    236 class Letter(Element):
     246class Letter(ElementWrapper):
    237247    r"""
    238248    A class for letters
     249
     250    Like :class:`ElementWrapper`, plus delegates __lt__ (comparison)
     251    to the parent.
     252
     253    EXAMPLES::
     254
     255        sage: from sage.combinat.crystals.letters import Letter
     256        sage: a = Letter(ZZ, 1)
     257        sage: Letter(ZZ, 1).parent()
     258        Integer Ring
     259
     260        sage: Letter(ZZ, 1).__repr__()
     261        '1'
     262
     263        sage: parent1 = ZZ  # Any fake value ...
     264        sage: parent2 = QQ  # Any fake value ...
     265        sage: l11 = Letter(parent1, 1)
     266        sage: l12 = Letter(parent1, 2)
     267        sage: l21 = Letter(parent2, 1)
     268        sage: l22 = Letter(parent2, 2)
     269        sage: l11 == l11
     270        True
     271        sage: l11 == l12
     272        False
     273        sage: l11 == l21
     274        False
     275
     276        sage: C = CrystalOfLetters(['B', 3])
     277        sage: C(0) <> C(0)
     278        False
     279        sage: C(1) <> C(-1)
     280        True
    239281    """
    240    
    241282    def __init__(self, parent, value):
    242283        """
    243284        EXAMPLES::
    244        
     285
    245286            sage: from sage.combinat.crystals.letters import Letter
    246287            sage: a = Letter(ZZ, 1)
    247             sage: a == loads(dumps(a))
    248             True
     288            sage: TestSuite(a).run(skip = "_test_category")
     289
    249290        """
    250         self._parent = parent
    251         self.value = value
     291        # Will soon be unneeded once the order of the arguments in
     292        # ElementWrapper will have been fixed.
     293        ElementWrapper.__init__(self, value, parent)
    252294
    253     def parent(self):
    254         """
    255         Returns the parent of self.
    256        
    257         EXAMPLES::
    258        
    259             sage: from sage.combinat.crystals.letters import Letter
    260             sage: Letter(ZZ, 1).parent()
    261             Integer Ring
    262         """
    263         return self._parent  # Should be inherited from Element!
    264 
    265     def __repr__(self):
    266         """
    267         EXAMPLES::
    268        
    269             sage: from sage.combinat.crystals.letters import Letter
    270             sage: Letter(ZZ, 1).__repr__()
    271             '1'
    272         """
    273         return "%s"%self.value
    274 
    275     def __eq__(self, other):
    276         """
    277         EXAMPLES::
    278        
    279             sage: from sage.combinat.crystals.letters import Letter
    280             sage: parent1 = 1  # Any fake value ...
    281             sage: parent2 = 2  # Any fake value ...
    282             sage: l11 = Letter(parent1, 1)
    283             sage: l12 = Letter(parent1, 2)
    284             sage: l21 = Letter(parent2, 1)
    285             sage: l22 = Letter(parent2, 2)
    286             sage: l11 == l11
    287             True
    288             sage: l11 == l12
    289             False
    290             sage: l11 == l21
    291             False
    292         """
    293         return self.__class__ is other.__class__ and \
    294                self.parent() == other.parent() and \
    295                self.value == other.value
    296 
    297     def __ne__(self, other):
    298         """
    299         EXAMPLES::
    300 
    301             sage: C = CrystalOfLetters(['B', 3])
    302             sage: C(0) <> C(0)
    303             False
    304             sage: C(1) <> C(-1)
    305             True
    306         """
    307         return not self == other
    308    
    309295    def __lt__(self, other):
    310296        """
    311297        EXAMPLES::
    class Letter(Element): 
    317303            True
    318304            sage: C(4) < C(4)
    319305            False
     306            sage: C(4) < 5
     307            False
    320308        """
     309        if parent(self) is not parent(other):
     310            return False
    321311        return self.parent().lt_elements(self, other)
    322312
    323313    def __gt__(self, other):
    class Crystal_of_letters_type_E6_element 
    892882        sage: G.show(edge_labels=true, figsize=12, vertex_size=1)
    893883    """
    894884
     885    def __hash__(self):
     886        return hash(tuple(self.value))
     887
    895888    def __repr__(self):
    896889        """
    897890        In their full representation, the vertices of this crystal are labeled
    class Crystal_of_letters_type_E6_element 
    11751168            return l[self.parent().list().index(self)]
    11761169        return "%s"%self.value
    11771170
     1171    def __hash__(self):
     1172        return hash(tuple(self.value))
     1173
    11781174    def lift(self):
    11791175        """
    11801176        Lifts an element of self to the crystal of letters CrystalOfLetters(['E',6])
    class Crystal_of_letters_type_E7_element 
    13091305        sage: G = C.digraph()
    13101306        sage: G.show(edge_labels=true, figsize=12, vertex_size=1)
    13111307    """
     1308
     1309    def __hash__(self):
     1310        return hash(tuple(self.value))
    13121311   
    13131312    def weight(self):
    13141313        """
  • sage/combinat/crystals/spins.py

    diff --git a/sage/combinat/crystals/spins.py b/sage/combinat/crystals/spins.py
    a b internal_repn and signature of the cryst 
    3939## TODO: proper latex'ing of spins
    4040
    4141from sage.structure.element import Element
     42from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    4243from sage.combinat.root_system.cartan_type import CartanType
    4344from crystals import ClassicalCrystal, CrystalElement
    4445
    class GenericCrystalOfSpins(ClassicalCry 
    187188        EXAMPLES::
    188189       
    189190            sage: E = CrystalOfSpinsMinus(['D',4])
    190             sage: E == loads(dumps(E))
    191             True
     191            sage: TestSuite(E).run()
    192192        """
    193193        self._cartan_type = CartanType(ct)
    194194        if case == "spins":
    195             self._name = "The crystal of spins for type %s"%ct
     195            self.rename("The crystal of spins for type %s"%ct)
    196196        elif case == "plus":
    197             self._name = "The plus crystal of spins for type %s"%ct
     197            self.rename("The plus crystal of spins for type %s"%ct)
    198198        else:
    199             self._name = "The minus crystal of spins for type %s"%ct
    200            
    201         self.element_class = element_class
     199            self.rename("The minus crystal of spins for type %s"%ct)
     200
     201        self.Element = element_class
     202        super(GenericCrystalOfSpins, self).__init__(category = FiniteEnumeratedSets())
     203
    202204        if case == "minus":
    203205            generator = [1]*(ct[1]-1)
    204206            generator.append(-1)
    205207        else:
    206208            generator = [1]*ct[1]
    207209        self.module_generators = [self(generator)]
    208         self._list = ClassicalCrystal.list(self)
     210        self._list = list(self)
    209211        self._digraph = ClassicalCrystal.digraph(self)
    210212        self._digraph_closure = self.digraph().transitive_closure()
    211213
    class GenericCrystalOfSpins(ClassicalCry 
    217219            sage: C([1,1,1])
    218220            [1, 1, 1]
    219221        """
    220         if value.__class__ == self.element_class and value.parent == self:
    221             return self
     222        if value.__class__ == self.element_class and value.parent() == self:
     223            return value
    222224        else:
    223225            return self.element_class(self, value)
    224226
    class Spin(Element): 
    284286    def __init__(self, parent, value):
    285287        """
    286288        EXAMPLES::
    287        
     289
    288290            sage: C = CrystalOfSpins(['B',3])
    289291            sage: c = C([1,1,1])
    290             sage: c == loads(dumps(c))
    291             True
     292            sage: TestSuite(c).run()
    292293        """
    293294        self._parent = parent
    294295        self.value = value
  • sage/combinat/crystals/tensor_product.py

    diff --git a/sage/combinat/crystals/tensor_product.py b/sage/combinat/crystals/tensor_product.py
    a b Tensor Products of Crystals 
    1717#                  http://www.gnu.org/licenses/
    1818#****************************************************************************
    1919
     20import operator
    2021from sage.misc.latex import latex
    2122from sage.misc.cachefunc import cached_method
    22 from sage.structure.element import Element
     23from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets, EnumeratedSets
     24from sage.structure.element import Element, parent
    2325from sage.combinat.root_system.cartan_type import CartanType
    2426from sage.combinat.cartesian_product import CartesianProduct
    2527from sage.combinat.combinat import CombinatorialObject
    26 from sage.combinat.partition import Partition, Partitions
     28from sage.combinat.partition import Partition
    2729from sage.combinat.tableau import Tableau
    2830from sage.combinat.tableau import Tableau_class
    2931from crystals import CrystalElement, ClassicalCrystal, Crystal
    3032from letters import CrystalOfLetters
    3133from sage.misc.flatten import flatten
    3234from sage.rings.integer import Integer
    33 from sage.misc.mrange import xmrange_iter
    34 from sage.misc.mrange import cartesian_product_iterator
    35 from sage.combinat.combinat import CombinatorialClass
    3635
    3736##############################################################################
    3837# Support classes
    3938##############################################################################
    4039
     40from sage.structure.parent import Parent
     41from sage.structure.unique_representation import UniqueRepresentation
     42
     43class TestParent(UniqueRepresentation, Parent):
     44    def _repr_(self):
     45        return "A parent for tests"
     46
    4147class ImmutableListWithParent(CombinatorialObject, Element):
    4248    r"""
    4349    A class for lists having a parent
    class ImmutableListWithParent(Combinator 
    4854    EXAMPLES: We create an immutable list whose parent is the class
    4955    list::
    5056   
    51         sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    52         sage: l = ImmutableListWithParent(list, [1,2,3])
     57        sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent
     58        sage: l = ImmutableListWithParent(TestParent(), [1,2,3])
    5359        sage: l._list
    5460        [1, 2, 3]
    5561        sage: l.parent()
    56         <type 'list'>
    57         sage: l.sibling([2,1]) == ImmutableListWithParent(list, [2,1])
     62        A parent for tests
     63        sage: l.sibling([2,1]) == ImmutableListWithParent(TestParent(), [2,1])
    5864        True
    5965        sage: l.reversed()
    6066        [3, 2, 1]
    class ImmutableListWithParent(Combinator 
    6672        """
    6773        EXAMPLES::
    6874       
    69             sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    70             sage: l = ImmutableListWithParent(list, [1,2,3])
    71             sage: l == loads(dumps(l))
    72             True
     75            sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent
     76            sage: l = ImmutableListWithParent(TestParent(), [1,2,3])
     77            sage: l.parent()
     78            A parent for tests
     79            sage: parent(l)
     80            A parent for tests
     81            sage: TestSuite(l).run(skip = "_test_category")
    7382        """
    74         self._parent = parent
     83        Element.__init__(self, parent)
    7584        CombinatorialObject.__init__(self, list)
    76    
    7785
    78     def parent(self):
     86    def _repr_(self):
    7987        """
    8088        EXAMPLES::
    8189       
    82             sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    83             sage: l = ImmutableListWithParent(list, [1,2,3])
    84             sage: l.parent()
    85             <type 'list'>
    86         """
    87         return self._parent  # Should be inherited from Element!
    88 
    89     def __repr__(self):
    90         """
    91         EXAMPLES::
    92        
    93             sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    94             sage: l = ImmutableListWithParent(list, [1,2,3])
     90            sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent
     91            sage: l = ImmutableListWithParent(TestParent(), [1,2,3])
    9592            sage: l.__repr__()
    9693            '[1, 2, 3]'
    9794        """
    class ImmutableListWithParent(Combinator 
    10198        """
    10299        EXAMPLES::
    103100       
    104             sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    105             sage: l = ImmutableListWithParent(list, [1,2,3])
     101            sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent
     102            sage: l = ImmutableListWithParent(TestParent(), [1,2,3])
    106103            sage: m = ImmutableListWithParent(ZZ, [1,2,3])
    107104            sage: n = ImmutableListWithParent(ZZ, [2,3,4])
    108105            sage: l == l
    class ImmutableListWithParent(Combinator 
    116113               self.parent() == other.parent() and \
    117114               self._list == other._list
    118115
     116    def __ne__(self, other):
     117        return not self.__eq__(other)
     118
     119    # Should go in Element? Sets.ElementMethods?
     120    # How to define them conditionally, only of __lt__ is defined?
     121    def __le__(self, other):
     122        if self == other:
     123            return True
     124        else:
     125            return self.__le__(other)
     126
     127    def __gt__(self, other):
     128        if parent(self) is not parent(other):
     129            return NotImplemented
     130        return other.__lt__(self)
     131
     132    def __ge__(self, other):
     133        if self == other:
     134            return True
     135        else:
     136            return self.__le__(other)
     137
    119138    def sibling(self, l):
    120139        """
    121140        Returns an ImmutableListWithParent object whose list is l and whose
    class ImmutableListWithParent(Combinator 
    126145       
    127146        EXAMPLES::
    128147       
    129             sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    130             sage: l = ImmutableListWithParent(list, [1,2,3])
     148            sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent
     149            sage: l = ImmutableListWithParent(TestParent(), [1,2,3])
    131150            sage: m = l.sibling([2,3,4]); m
    132151            [2, 3, 4]
    133152            sage: m.parent()
    134             <type 'list'>
     153            A parent for tests
    135154        """
    136155        return self.__class__(self.parent(), list=l)
    137156
    class ImmutableListWithParent(Combinator 
    142161       
    143162        EXAMPLES::
    144163       
    145             sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    146             sage: l = ImmutableListWithParent(list, [1,2,3])
     164            sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent
     165            sage: l = ImmutableListWithParent(TestParent(), [1,2,3])
    147166            sage: l.reversed()
    148167            [3, 2, 1]
    149168        """
    class ImmutableListWithParent(Combinator 
    156175       
    157176        EXAMPLES::
    158177       
    159             sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent
    160             sage: l = ImmutableListWithParent(list, [1,2,3])
     178            sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent
     179            sage: l = ImmutableListWithParent(TestParent(), [1,2,3])
    161180            sage: l.set_index(0,2)
    162181            [2, 2, 3]
    163182            sage: l.set_index(1,4)
    164183            [1, 4, 3]
    165184            sage: _.parent()
    166             <type 'list'>
     185            A parent for tests
    167186        """
    168187        l = [i for i in self._list]
    169188        l[k] = value
    def TensorProductOfCrystals(*crystals, * 
    258277        sage: T.highest_weight_vectors()
    259278        [[2, 1, 1], [1, 2, 1]]
    260279    """
    261     if options.has_key('generators'):
     280    crystals = tuple(crystals)
     281    if "cartan_type" in options:
     282        cartan_type = CartanType(options["cartan_type"])
     283    else:
     284        if len(crystals) == 0:
     285            raise ValueError, "you need to specify the Cartan type if the tensor product list is empty"
     286        else:
     287            cartan_type = crystals[0].cartan_type()
     288
     289    if "generators" in options:
     290        generators = tuple(tuple(x) if isinstance(x, list) else x for x in options["generators"])
    262291        if all(isinstance(crystal,ClassicalCrystal) for crystal in crystals):
    263             return TensorProductOfClassicalCrystalsWithGenerators(generators=options['generators'], *crystals)
     292            return TensorProductOfClassicalCrystalsWithGenerators(crystals, generators=generators, cartan_type = cartan_type)
    264293        else:
    265             return TensorProductOfCrystalsWithGenerators(generators=options['generators'], *crystals)
     294            return TensorProductOfCrystalsWithGenerators(crystals, generators=generators, cartan_type = cartan_type)
    266295    else:
    267296        if all(isinstance(crystal,ClassicalCrystal) for crystal in crystals):
    268             return FullTensorProductOfClassicalCrystals(*crystals)
    269         else: 
    270             return FullTensorProductOfCrystals(*crystals)
     297            return FullTensorProductOfClassicalCrystals(crystals, cartan_type = cartan_type)
     298        else:
     299            return FullTensorProductOfCrystals(crystals, cartan_type = cartan_type)
    271300
    272301
    273302class CrystalOfWords(Crystal):
    class CrystalOfWords(Crystal): 
    291320            sage: T(C(2), C(1), C(1))
    292321            [2, 1, 1]
    293322        """
    294         return TensorProductOfCrystalsElement(self, list(crystalElements))
     323        return self.element_class(self, list(crystalElements))
    295324
    296325
    297326class TensorProductOfCrystalsWithGenerators(CrystalOfWords):
    298     def __init__(self, *crystals, **options):
     327
     328    def __init__(self, crystals, generators, cartan_type):
    299329        """
    300330        EXAMPLES::
    301        
     331
    302332            sage: C = CrystalOfLetters(['A',2])
    303333            sage: T = TensorProductOfCrystals(C,C,C,generators=[[C(2),C(1),C(1)]])
    304             sage: T == loads(dumps(T))
    305             True
     334            sage: TestSuite(T).run()
    306335        """
    307         crystals = [ crystal for crystal in crystals]
    308         self._name = "The tensor product of the crystals %s"%crystals
     336        assert isinstance(crystals, tuple)
     337        assert isinstance(generators, tuple)
     338        if all(crystal in FiniteEnumeratedSets() for crystal in crystals):
     339            category = FiniteEnumeratedSets()
     340        else:
     341            category = EnumeratedSets()
     342        super(TensorProductOfCrystalsWithGenerators, self).__init__(category = category)
     343        self.rename("The tensor product of the crystals %s"%(crystals,))
    309344        self.crystals = crystals
    310         if options.has_key('cartan_type'):
    311             self._cartan_type = CartanType(options['cartan_type'])
    312         else:
    313             if len(crystals) == 0:
    314                 raise ValueError, "you need to specify the Cartan type if the tensor product list is empty"
    315             else:
    316                 self._cartan_type = crystals[0].cartan_type()
    317         self.module_generators = [ self(*x) for x in options['generators']]
    318 
     345        self._cartan_type = cartan_type
     346        self.module_generators = [ self(*x) for x in generators ]
    319347
    320348class TensorProductOfClassicalCrystalsWithGenerators(TensorProductOfCrystalsWithGenerators, ClassicalCrystal):
    321349    pass
    322350
    323351class FullTensorProductOfCrystals(CrystalOfWords):
    324     def __init__(self, *crystals, **options):
     352    def __init__(self, crystals, **options):
    325353        """
    326354        TESTS::
    327355       
    class FullTensorProductOfCrystals(Crysta 
    330358            sage: T = TensorProductOfCrystals(C,C)
    331359            sage: isinstance(T, FullTensorProductOfCrystals)
    332360            True
    333             sage: T == loads(dumps(T))
    334             True
     361            sage: TestSuite(T).run()
    335362        """
    336363        crystals = list(crystals)
    337         self._name = "Full tensor product of the crystals %s"%crystals
     364        if all(crystal in FiniteEnumeratedSets() for crystal in crystals):
     365            category = FiniteEnumeratedSets()
     366        else:
     367            category = EnumeratedSets()
     368        super(FullTensorProductOfCrystals, self).__init__(category = category)
     369        self.rename("Full tensor product of the crystals %s"%(crystals,))
    338370        self.crystals = crystals
    339371        if options.has_key('cartan_type'):
    340372            self._cartan_type = CartanType(options['cartan_type'])
    class FullTensorProductOfCrystals(Crysta 
    360392        for x in self.cartesian_product:
    361393            yield self(*x)
    362394
    363     list = CombinatorialClass._CombinatorialClass__list_from_iterator
     395#    list = CombinatorialClass._CombinatorialClass__list_from_iterator
    364396   
    365397    def cardinality(self):
    366398        """
    class TensorProductOfCrystalsElement(Imm 
    381413    r"""
    382414    A class for elements of tensor products of crystals
    383415    """
     416
     417    def __lt__(self, other):
     418        """
     419        Non elements of the crystal are incomparable with elements of the crystal
     420        (or should it return NotImplemented?)
     421
     422        Comparison of two elements of this crystal:
     423         - different length: incomparable
     424         - otherwise lexicographicaly, considering self[i] and other[i]
     425           as incomparable if self[i] < other[i] returns NotImplemented
     426        """
     427        if parent(self) is not parent(other):
     428            return False
     429        if len(self) != len(other):
     430            return False
     431        for i in range(len(self)):
     432            if (self[i] < other[i]) == True:
     433                return True
     434            if (self[i] > other[i]) == True:
     435                return False
     436        return False
     437
    384438    def e(self, i):
    385439        """
    386440        Returns the action of `e_i` on self.
    class TensorProductOfCrystalsElement(Imm 
    538592        l.reverse()
    539593        return [len(self)-1-l[j] for j in range(len(l))]
    540594
     595    def _latex_(self):
     596        """
     597        Returns latex code for self.
     598
     599        EXAMPLES::
     600
     601            sage: C = CrystalOfLetters(["A",2])
     602            sage: D = CrystalOfTableaux(["A",2], shape=[2])
     603            sage: E = TensorProductOfCrystals(C,D)
     604            sage: E.module_generators[0]._latex_()
     605            '1\\otimes{\\def\\lr#1{\\multicolumn{1}{|@{\\hspace{.6ex}}c@{\\hspace{.6ex}}|}{\\raisebox{-.3ex}{$#1$}}}\n\\raisebox{-.6ex}{$\\begin{array}[b]{cc}\n\\cline{1-1}\\cline{2-2}\n\\lr{1}&\\lr{1}\\\\\n\\cline{1-1}\\cline{2-2}\n\\end{array}$}\n}'
     606        """
     607        return '\otimes'.join(latex(c) for c in self)
     608
     609CrystalOfWords.Element = TensorProductOfCrystalsElement
     610
    541611class CrystalOfTableaux(CrystalOfWords, ClassicalCrystal):
    542612    r"""
    543613    Crystals of tableaux. Input: a Cartan Type type and "shape", a
    class CrystalOfTableaux(CrystalOfWords,  
    673743        sage: t in T.list()
    674744        False
    675745    """
    676     def __init__(self, type, shape = None, shapes = None):
     746
     747    @staticmethod
     748    def __classcall__(cls, cartan_type, shapes = None, shape = None):
    677749        """
     750        Normalizes the input arguments to ensure unique representation
     751
    678752        EXAMPLES::
    679        
     753
     754            sage: T1 = CrystalOfTableaux(CartanType(['A',3]), shape  = [2,2])
     755            sage: T2 = CrystalOfTableaux(['A',3],             shape  = (2,2))
     756            sage: T3 = CrystalOfTableaux(['A',3],             shapes = ([2,2],))
     757            sage: T2 is T1, T3 is T1
     758            (True, True)
     759        """
     760        cartan_type = CartanType(cartan_type)
     761        # standardize shape/shapes input into a tuple of tuples
     762        assert operator.xor(shape is not None, shapes is not None)
     763        if shape is not None:
     764            shapes = (shape,)
     765        shapes = tuple( tuple(shape) for shape in shapes )
     766        return super(CrystalOfTableaux, cls).__classcall__(cls, cartan_type, shapes)
     767
     768
     769    def __init__(self, cartan_type, shapes):
     770        """
     771        Construct the crystal of all tableaux of the given shapes
     772
     773        INPUT:
     774         - ``cartan_type`` - (data coercible into) a cartan type
     775         - ``shapes``      - a list (or iterable) of shapes
     776         - ``shape` `      - a shape
     777
     778        shapes themselves are lists (or iterable) of integers
     779
     780        EXAMPLES::
     781
    680782            sage: T = CrystalOfTableaux(['A',3], shape = [2,2])
    681             sage: T == loads(dumps(T))
    682             True
     783            sage: TestSuite(T).run()
    683784        """
    684         self.letters = CrystalOfLetters(type)
    685         if shape is not None:
    686             assert shapes is None
    687             shapes = (shape,)
    688         assert shapes is not None
    689         CrystalOfWords.__init__(self)
    690         module_generators = tuple(self.module_generator(la) for la in shapes)
    691         self.module_generators = module_generators
    692         self._name = "The crystal of tableaux of type %s and shape(s) %s"%(type, str(shapes))
     785        super(CrystalOfTableaux, self).__init__(category = FiniteEnumeratedSets())
     786        self.letters = CrystalOfLetters(cartan_type)
     787        self.module_generators = tuple(self.module_generator(la) for la in shapes)
     788        self.rename("The crystal of tableaux of type %s and shape(s) %s"%(cartan_type, list(list(shape) for shape in shapes)))
    693789
    694790    def cartan_type(self):
    695791        """
    class CrystalOfTableaux(CrystalOfWords,  
    716812        type = self.cartan_type()
    717813        if type[0] == 'D' and len(shape) == type[1] and shape[type[1]-1] < 0:
    718814            invert = True
    719             shape[type[1]-1]=-shape[type[1]-1]
     815            shape = shape[:-1]+(-shape[type[1]-1],)
    720816        else:
    721817            invert = False
    722818        p = Partition(shape).conjugate()
    class CrystalOfTableaux(CrystalOfWords,  
    740836            sage: T(columns=[[3,1],[4,2]])
    741837            [[1, 2], [3, 4]]
    742838        """
    743         return CrystalOfTableauxElement(self, *args, **options)
     839        return self.element_class(self, *args, **options)
    744840
    745841class CrystalOfTableauxElement(TensorProductOfCrystalsElement):
    746842    def __init__(self, parent, *args, **options):
    class CrystalOfTableauxElement(TensorPro 
    749845       
    750846            sage: T = CrystalOfTableaux(['A',3], shape = [2,2])
    751847            sage: t = T(rows=[[1,2],[3,4]])
    752             sage: t == loads(dumps(t))
    753             True
     848            sage: TestSuite(t).run()
    754849        """
    755850        if len(args) == 1:
    756851            if isinstance(args[0], CrystalOfTableauxElement):
    class CrystalOfTableauxElement(TensorPro 
    792887        """
    793888        return repr(self.to_tableau())
    794889
     890    def pp(self):
     891        """
     892        EXAMPLES::
     893
     894            sage: T = CrystalOfTableaux(['A',3], shape = [2,2])
     895            sage: t = T(rows=[[1,2],[3,4]])
     896            sage: t.pp()
     897            1  2
     898            3  4
     899        """
     900        return self.to_tableau().pp()
     901
    795902    def _latex_(self):
    796903        r"""
    797904        EXAMPLES::
    class CrystalOfTableauxElement(TensorPro 
    843950        for x in tab:
    844951            x.reverse()
    845952        return Tableau(tab).conjugate()
     953
     954CrystalOfTableaux.Element = CrystalOfTableauxElement
  • sage/combinat/root_system/cartan_type.py

    diff --git a/sage/combinat/root_system/cartan_type.py b/sage/combinat/root_system/cartan_type.py
    a b One may also construct crystals associat 
    6767
    6868    sage: C = CrystalOfTableaux(T, shape=[2])
    6969    sage: C
    70     The crystal of tableaux of type ['A', 4] and shape(s) ([2],)
     70    The crystal of tableaux of type ['A', 4] and shape(s) [[2]]
    7171    sage: C.cardinality()
    7272    15
    7373
  • sage/combinat/tableau.py

    diff --git a/sage/combinat/tableau.py b/sage/combinat/tableau.py
    a b class Tableau_class(CombinatorialObject) 
    8181            \end{array}$}
    8282            }
    8383        """
     84        if len(self) == 0:
     85            return "{\emptyset}"
    8486        return self._tex_from_array()
    8587   
    8688    def _tex_from_array(self):