Ticket #7729: iwahori.patch

File iwahori.patch, 20.4 KB (added by bump, 13 years ago)

Iwahori Hecke algebra patch, including revisions from

  • sage/algebras/all.py

    diff -r 8ccaf3deb11c sage/algebras/all.py
    a b  
    3535
    3636from group_algebra import GroupAlgebra, GroupAlgebraElement
    3737
    38    
     38from iwahori import IwahoriHeckeAlgebraT
     39   
    3940def is_R_algebra(Q, R):
    4041    # TODO: do something nontrivial when morphisms are defined.
    4142    return True
  • new file sage/algebras/iwahori.py

    diff -r 8ccaf3deb11c sage/algebras/iwahori.py
    - +  
     1"""
     2Iwahori Hecke Algebras
     3"""
     4#*****************************************************************************
     5#  Copyright (C) 2008 Daniel Bump <bump at match.stanford.edu>
     6#
     7#  Distributed under the terms of the GNU General Public License (GPL)
     8#                  http://www.gnu.org/licenses/
     9#*****************************************************************************
     10from sage.categories.all import AlgebrasWithBasis, FiniteDimensionalAlgebrasWithBasis
     11import sage.combinat.root_system.cartan_type
     12from sage.combinat.root_system.cartan_type import CartanType
     13from sage.combinat.root_system.weyl_group import WeylGroup
     14from sage.structure.element import is_Element
     15from sage.rings.all import ZZ
     16from sage.misc.misc import repr_lincomb
     17from sage.algebras.algebra_element import AlgebraElement
     18from sage.combinat.family import Family
     19import sage.rings.polynomial.laurent_polynomial
     20from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement
     21from sage.misc.cachefunc import cached_method
     22
     23class IwahoriHeckeAlgebraT(CombinatorialFreeModule):
     24    r"""
     25    INPUT:
     26
     27     - ``ct`` -- A Cartan Type (possibly affine)
     28     - ``q1`` -- a parameter.
     29
     30    OPTIONAL ARGUMENTS:
     31
     32     - ``q2`` -- another parameter (default -1)
     33     - ``base_ring`` -- A ring containing q1 and q2 (default q1.parent())
     34     - ``prefix`` -- a label for the generators (default "T")
     35
     36    Given a Cartan type T, the Iwahori Hecke algebra is defined in:
     37
     38    Nagayoshi Iwahori, On the structure of a Hecke ring of a Chevalley group
     39    over a finite field.  J. Fac. Sci. Univ. Tokyo Sect. I 10 1964 215--236
     40    (1964).
     41
     42    The Iwahori Hecke algebra is a deformation of the group algebra of
     43    the Weyl group. Taking the deformation parameter `q=1` as in the
     44    following example gives a ring isomorphic to that group
     45    algebra. The parameter `q` is a deformation parameter.
     46
     47    EXAMPLES::
     48
     49        sage: H = IwahoriHeckeAlgebraT("A3",1,prefix = "s")
     50        sage: [s1,s2,s3] = H.algebra_generators()
     51        sage: s1*s2*s3*s1*s2*s1 == s3*s2*s1*s3*s2*s3
     52        True
     53        sage: w0 = H(H.weyl_group().long_element())
     54        sage: w0
     55        s1*s2*s3*s1*s2*s1
     56        sage: H.an_element()
     57        3*s1*s2 + 3*s1 + 1
     58
     59    Iwahori Hecke algebras have proved to be fundamental. See for example:
     60
     61    Kazhdan and Lusztig, Representations of Coxeter groups and Hecke algebras.
     62    Invent. Math. 53 (1979), no. 2, 165--184.
     63
     64    Iwahori-Hecke Algebras: Thomas J. Haines, Robert E. Kottwitz,
     65    Amritanshu Prasad, http://front.math.ucdavis.edu/0309.5168
     66
     67    V. Jones, Hecke algebra representations of braid groups and link
     68    polynomials.  Ann. of Math. (2) 126 (1987), no. 2, 335--388.
     69
     70    For every simple reflection `s_i` of the Weyl group, there is a
     71    corresponding generator `T_i` of the Iwahori Hecke algebra. These
     72    are subject to the relations
     73
     74        `(T_i-q_1)*(T_i-q_2) == 0`
     75
     76    together with the braid relations `T_i T_j T_i ... == T_j T_i T_j ...`,
     77    where the number of terms on both sides is `k/2` with `k` the order of
     78    `s_i s_j` in the Weyl group.
     79
     80    Weyl group elements form a basis of the Iwahori Hecke algebra `H`
     81    with the property that if `w1` and `w2` are Weyl group elements
     82    such that ``(w1*w2).length() == w1.length() + w2.length()`` then
     83    ``H(w1*w2) == H(w1)*H(w2)``.
     84
     85    With the default value `q_2 = -1` and with `q_1 = q` the
     86    generating relation may be written `T_i^2 = (q-1)*T_i + q*1` as in
     87    Iwahori's paper.
     88
     89    EXAMPLES::
     90
     91        sage: R.<q>=PolynomialRing(ZZ)
     92        sage: H=IwahoriHeckeAlgebraT("B3",q); H
     93        The Iwahori Hecke Algebra of Type B3 in q,-1 over Univariate Polynomial Ring in q over Integer Ring and prefix T
     94        sage: T1,T2,T3 = H.algebra_generators()
     95        sage: T1*T1
     96        (q-1)*T1 + q
     97
     98    It is useful to define ``T1,T2,T3 = H.algebra_generators()`` as above
     99    so that H can parse its own output::
     100
     101        sage: H(T1)
     102        T1
     103
     104    The Iwahori Hecke algebra associated with an affine Weyl group is
     105    called an affine Hecke algebra. These may be implemented as follows::
     106
     107        sage: R.<q>=QQ[]
     108        sage: H=IwahoriHeckeAlgebraT(['A',2,1],q)
     109        sage: [T0,T1,T2]=H.algebra_generators()
     110        sage: T1*T2*T1*T0*T1*T0
     111        (q-1)*T1*T2*T0*T1*T0 + q*T1*T2*T0*T1
     112        sage: T1*T2*T1*T0*T1*T1
     113        q*T1*T2*T1*T0 + (q-1)*T1*T2*T0*T1*T0
     114        sage: T1*T2*T1*T0*T1*T2
     115        T1*T2*T0*T1*T0*T2
     116
     117        sage: R = IwahoriHeckeAlgebraT("A3",0,0,prefix = "s")
     118        sage: [s1,s2,s3] = R.algebra_generators()
     119        sage: s1*s1
     120        0
     121
     122    TESTS::
     123
     124        sage: H1 = IwahoriHeckeAlgebraT("A2",1)
     125        sage: H2 = IwahoriHeckeAlgebraT("A2",1)
     126        sage: H3 = IwahoriHeckeAlgebraT("A2",-1)
     127        sage: H1 == H1, H1 == H2, H1 is H2
     128        (True, True, True)
     129        sage: H1 == H3
     130        False
     131
     132        sage: R.<q>=PolynomialRing(QQ)
     133        sage: IwahoriHeckeAlgebraT("A3",q).base_ring() == R
     134        True
     135
     136        sage: R.<q>=QQ[]; H=IwahoriHeckeAlgebraT("A2",q)
     137        sage: 1+H(q)
     138        (q+1)
     139
     140        sage: R.<q>=QQ[]
     141        sage: H = IwahoriHeckeAlgebraT("A2",q)
     142        sage: T1,T2 = H.algebra_generators()
     143        sage: H(T1+2*T2)
     144        T1 + 2*T2
     145
     146    .. rubric:: Design discussion
     147
     148    This is a preliminary implementation. For work in progress, see:
     149    http://wiki.sagemath.org/HeckeAlgebras.
     150
     151     - Should the input be a cartan type or a Coxeter group?
     152     - Should we use q in QQ['q'] as default parameter for q_1?
     153
     154    """
     155
     156    @staticmethod
     157    def __classcall__(cls, ct, q1, q2=-1, base_ring=None, prefix="T"):
     158        """
     159        TESTS::
     160
     161            sage: H = IwahoriHeckeAlgebraT("A2", 1)
     162            sage: H.cartan_type() == CartanType("A2")
     163            True
     164            sage: H.base_ring() == ZZ
     165            True
     166            sage: H._q2 == -1
     167            True
     168        """
     169        ct = CartanType(ct)
     170        if base_ring is None:
     171            base_ring = q1.parent()
     172        return super(IwahoriHeckeAlgebraT, cls).__classcall__(cls, ct, q1=q1, q2=q2, base_ring=base_ring, prefix=prefix)
     173
     174    def __init__(self, ct, q1, q2, base_ring, prefix):
     175         """
     176        EXAMPLES ::
     177
     178            sage: R.<q1,q2>=QQ[]
     179            sage: H = IwahoriHeckeAlgebraT("A2",q1,q2,base_ring=Frac(R),prefix="t"); H
     180            The Iwahori Hecke Algebra of Type A2 in q1,q2 over Fraction Field of Multivariate Polynomial Ring in q1, q2 over Rational Field and prefix t
     181            sage: TestSuite(H).run()
     182
     183         """
     184         self._cartan_type = ct
     185         self._q1 = base_ring(q1)
     186         self._q2 = base_ring(q2)
     187         self._weyl_group = WeylGroup(ct)
     188         if ct.is_finite():
     189             category = FiniteDimensionalAlgebrasWithBasis(base_ring)
     190         else:
     191             category = AlgebrasWithBasis(base_ring)
     192         CombinatorialFreeModule.__init__(self, base_ring, self._weyl_group, category = category)
     193
     194         self._weyl_group_one = self._weyl_group.one()
     195         self._prefix = prefix
     196         self._index_set = self._weyl_group.index_set()
     197         self._one = self.__call__(1)
     198
     199
     200    def _element_constructor_(self, w):
     201        """
     202        Construct a basis element from an element of the Weyl group
     203
     204        EXAMPLES ::
     205
     206            sage: R.<q>=QQ[]
     207            sage: H = IwahoriHeckeAlgebraT("A2",q)
     208            sage: [H(x) for x in H.weyl_group()]   # indirect doctest
     209            [1, T1, T1*T2, T1*T2*T1, T2, T2*T1]
     210
     211        """
     212        assert w in self.weyl_group()
     213        return self.term(w)
     214
     215    @cached_method
     216    def one_basis(self):
     217        """
     218        Returns the unit of the underlying coxeter group, which index
     219        the one of this algebra, as per
     220        :meth:`AlgebrasWithBasis.ParentMethods.one_basis`.
     221
     222        EXAMPLES::
     223
     224            sage: H = IwahoriHeckeAlgebraT("B3", 1)
     225            sage: H.one_basis()
     226            [1 0 0]
     227            [0 1 0]
     228            [0 0 1]
     229            sage: H.one_basis() == H.weyl_group().one()
     230            True
     231            sage: H.one()
     232            1
     233        """
     234        return self.weyl_group().one()
     235
     236    def _repr_(self):
     237        """
     238        EXAMPLES ::
     239
     240            sage: R.<q1,q2>=QQ[]
     241            sage: IwahoriHeckeAlgebraT("A2",q1,-q2,base_ring=Frac(R),prefix="Z") # indirect doctest
     242            The Iwahori Hecke Algebra of Type A2 in q1,-q2 over Fraction Field of Multivariate Polynomial Ring in q1, q2 over Rational Field and prefix Z
     243
     244        """
     245        return "The Iwahori Hecke Algebra of Type %s in %s,%s over %s and prefix %s"%(self._cartan_type._repr_(compact=True), self._q1, self._q2, self.base_ring(), self._prefix)
     246
     247    def cartan_type(self):
     248        """
     249        EXAMPLES ::
     250
     251            sage: IwahoriHeckeAlgebraT("D4",0).cartan_type()
     252            ['D', 4]
     253
     254        """
     255        return self._cartan_type
     256
     257    def weyl_group(self):
     258        """
     259        EXAMPLES::
     260
     261            sage: IwahoriHeckeAlgebraT("B2",1).weyl_group()
     262            Weyl Group of type ['B', 2] (as a matrix group acting on the ambient space)
     263
     264        """
     265        return self._weyl_group
     266
     267    def index_set(self):
     268        """
     269        EXAMPLES::
     270
     271            sage: IwahoriHeckeAlgebraT("B2",1).index_set()
     272            [1, 2]
     273        """
     274        return self._index_set
     275
     276    @cached_method
     277    def algebra_generators(self):
     278        """
     279        Returns the generators. They do not have order two but satisfy
     280        a quadratic relation. They coincide with the simple
     281        reflections in the Coxeter group when `q_1=1` and `q_2=-1`. In
     282        this special case, the Iwahori Hecke algebra is identified
     283        with the group algebra of the Coxeter group.
     284
     285        EXAMPLES ::
     286
     287            sage: R.<q>=QQ[]
     288            sage: H = IwahoriHeckeAlgebraT("A3",q)
     289            sage: T=H.algebra_generators(); T
     290            Finite family {1: T1, 2: T2, 3: T3}
     291            sage: T.list()
     292            [T1, T2, T3]
     293            sage: [T[i] for i in [1,2,3]]
     294            [T1, T2, T3]
     295            sage: [T1, T2, T3] = H.algebra_generators()
     296            sage: T1
     297            T1
     298            sage: H = IwahoriHeckeAlgebraT(['A',2,1],q)
     299            sage: T=H.algebra_generators(); T
     300            Finite family {0: T0, 1: T1, 2: T2}
     301            sage: T.list()
     302            [T0, T1, T2]
     303            sage: [T[i] for i in [0,1,2]]
     304            [T0, T1, T2]
     305            sage: [T0, T1, T2] = H.algebra_generators()
     306            sage: T0
     307            T0
     308        """
     309        return self.weyl_group().simple_reflections().map(self.term)
     310
     311    def algebra_generator(self, i):
     312        """
     313        EXAMPLES ::
     314
     315            sage: R.<q>=QQ[]
     316            sage: H = IwahoriHeckeAlgebraT("A3",q)
     317            sage: [H.algebra_generator(i) for i in H.index_set()]
     318            [T1, T2, T3]
     319
     320        """
     321        return self.algebra_generators()[i]
     322
     323    def inverse_generator(self, i):
     324        """
     325        This method is only available if q1 and q2 are invertible. In
     326        that case, the algebra generators are also invertible and this
     327        method returns the inverse of self.algebra_generator(i). The
     328        base ring should be either a field or a Laurent polynomial ring.
     329
     330        EXAMPLES::
     331
     332            sage: P.<q1,q2>=QQ[]
     333            sage: F=Frac(P)
     334            sage: H = IwahoriHeckeAlgebraT("A2",q1,q2,base_ring=F)
     335            sage: H.base_ring()
     336            Fraction Field of Multivariate Polynomial Ring in q1, q2 over Rational Field
     337            sage: H.inverse_generator(1)
     338            ((-1)/(q1*q2))*T1 + ((q1+q2)/(q1*q2))
     339            sage: H = IwahoriHeckeAlgebraT("A2",q1,-1,base_ring=F)
     340            sage: H.inverse_generator(2)
     341            ((-1)/(-q1))*T2 + ((q1-1)/(-q1))
     342            sage: P1.<r1,r2>=LaurentPolynomialRing(QQ)
     343            sage: H1 = IwahoriHeckeAlgebraT("B2",r1,r2,base_ring=P1)
     344            sage: H1.base_ring()
     345            Multivariate Laurent Polynomial Ring in r1, r2 over Rational Field
     346            sage: H1.inverse_generator(2)
     347            (-r1^-1*r2^-1)*T2 + (r2^-1+r1^-1)
     348            sage: H2 = IwahoriHeckeAlgebraT("C2",r1,-1,base_ring=P1)
     349            sage: H2.inverse_generator(2)
     350            (r1^-1)*T2 + (-1+r1^-1)
     351
     352        """
     353        try:
     354            # This currently works better than ~(self._q1) if
     355            # self.base_ring() is a Laurent polynomial ring since it
     356            # avoids accidental coercion into a field of fractions.
     357            i1 = self._q1.__pow__(-1)
     358            i2 = self._q2.__pow__(-1)
     359        except:
     360            raise ValueError, "%s and %s must be invertible."%(self._q1, self._q2)
     361        return (-i1*i2)*self.algebra_generator(i)+(i1+i2)
     362
     363    @cached_method
     364    def inverse_generators(self):
     365        """
     366        This method is only available if q1 and q2 are invertible. In
     367        that case, the algebra generators are also invertible and this
     368        method returns their inverses.
     369
     370        EXAMPLES ::
     371            sage: P.<q> = PolynomialRing(QQ)
     372            sage: F = Frac(P)
     373            sage: H = IwahoriHeckeAlgebraT("A2",q,base_ring=F)
     374            sage: [T1,T2]=H.algebra_generators()
     375            sage: [U1,U2]=H.inverse_generators()
     376            sage: U1*T1,T1*U1
     377            (1, 1)
     378            sage: P1.<q> = LaurentPolynomialRing(QQ)
     379            sage: H1 = IwahoriHeckeAlgebraT("A2",q,base_ring=P1,prefix="V")
     380            sage: [V1,V2]=H1.algebra_generators()
     381            sage: [W1,W2]=H1.inverse_generators()
     382            sage: [W1,W2]
     383            [(q^-1)*V1 + (-1+q^-1), (q^-1)*V2 + (-1+q^-1)]
     384            sage: V1*W1, W2*V2
     385            (1, 1)
     386
     387        """
     388        return Family(self.index_set(), self.inverse_generator)
     389
     390    def product_on_basis(self, w1, w2):
     391        """
     392
     393        Returns `T_w1 T_w2`, where `w_1` and `w_2` are in the Coxeter group
     394
     395        EXAMPLES::
     396
     397            sage: R.<q>=QQ[]; H = IwahoriHeckeAlgebraT("A2",q)
     398            sage: s1,s2 = H.weyl_group().simple_reflections()
     399            sage: [H.product_on_basis(s1,x) for x in [s1,s2]]
     400            [(q-1)*T1 + q, T1*T2]
     401
     402        """
     403        result = self.term(w1)
     404        for i in w2.reduced_word():
     405            result = self.product_by_generator(result, i)
     406        return result
     407
     408    def product_by_generator_on_basis(self, w, i, side = "right"):
     409        """
     410        INPUT:
     411         - ``w`` - an element of the Coxeter group
     412         - ``i`` - an element of the index set
     413         - ``side`` - "left" or "right" (default: "right")
     414
     415        Returns the product `T_w T_i` (resp. `T_i T_w`) if ``side`` is "right" (resp. "left")
     416
     417        EXAMPLES::
     418
     419            sage: R.<q>=QQ[]; H = IwahoriHeckeAlgebraT("A2",q)
     420            sage: s1,s2 = H.weyl_group().simple_reflections()
     421            sage: [H.product_by_generator_on_basis(w, 1) for w in [s1,s2,s1*s2]]
     422            [(q-1)*T1 + q, T2*T1, T1*T2*T1]
     423            sage: [H.product_by_generator_on_basis(w, 1, side = "left") for w in [s1,s2,s1*s2]]
     424            [(q-1)*T1 + q, T1*T2, (q-1)*T1*T2 + q*T2]
     425        """
     426        wi = w.apply_simple_reflection(i, side = side)
     427        if w.has_descent(i, side = side):
     428            return self.monomial(w ,  self._q1+self._q2) + \
     429                   self.monomial(wi, -self._q1*self._q2)
     430        else:
     431            return self.term(wi)
     432
     433    def product_by_generator(self, x, i, side = "right"):
     434        """
     435        Returns T_i*x, where T_i is the i-th generator. This is coded
     436        individually for use in x._mul_().
     437
     438        EXAMPLES ::
     439            sage: R.<q>=QQ[]; H = IwahoriHeckeAlgebraT("A2",q)
     440            sage: [T1,T2] = H.algebra_generators()
     441            sage: [H.product_by_generator(x, 1, side = "left") for x in [T1,T2]]
     442            [(q-1)*T1 + q, T2*T1]
     443
     444        """
     445        return self.sum(self.product_by_generator_on_basis(w, i)._acted_upon_(c) for (w,c) in x)
     446
     447    def _repr_term(self, t):
     448        """
     449        EXAMPLES ::
     450
     451            sage: R.<q>=QQ[]
     452            sage: H = IwahoriHeckeAlgebraT("A3",q)
     453            sage: W=H.weyl_group()
     454            sage: H._repr_term(W.from_reduced_word([1,2,3]))
     455            'T1*T2*T3'
     456
     457        """
     458        redword = t.reduced_word()
     459        if len(redword) == 0:
     460            return "1"
     461        else:
     462            return "*".join("%s%d"%(self._prefix, i) for i in redword)
     463
     464    class Element(CombinatorialFreeModuleElement):
     465        """
     466        A class for elements of an IwahoriHeckeAlgebra
     467
     468        TESTS::
     469
     470            sage: R.<q>=QQ[]
     471            sage: H=IwahoriHeckeAlgebraT("B3",q)
     472            sage: [T1, T2, T3] = H.algebra_generators()
     473            sage: T1+2*T2*T3
     474            T1 + 2*T2*T3
     475
     476            sage: R.<q1,q2>=QQ[]
     477            sage: H=IwahoriHeckeAlgebraT("A2",q1,q2,prefix="x")
     478            sage: sum(H.algebra_generators())^2
     479            x1*x2 + x2*x1 + (q1+q2)*x1 + (q1+q2)*x2 + (-2*q1*q2)
     480
     481            sage: H=IwahoriHeckeAlgebraT("A2",q1,q2,prefix="t")
     482            sage: [t1,t2] = H.algebra_generators()
     483            sage: (t1-t2)^3
     484            (q1^2-q1*q2+q2^2)*t1 + (-q1^2+q1*q2-q2^2)*t2
     485
     486            sage: R.<q>=QQ[]
     487            sage: H=IwahoriHeckeAlgebraT("G2",q)
     488            sage: [T1, T2] = H.algebra_generators()
     489            sage: T1*T2*T1*T2*T1*T2 == T2*T1*T2*T1*T2*T1
     490            True
     491            sage: T1*T2*T1 == T2*T1*T2
     492            False
     493
     494            sage: H = IwahoriHeckeAlgebraT("A2",1)
     495            sage: [T1,T2]=H.algebra_generators()
     496            sage: T1+T2
     497            T1 + T2
     498
     499            sage: -(T1+T2)
     500            -T1 - T2
     501
     502            sage: 1-T1
     503            -T1 + 1
     504
     505            sage: T1.parent()
     506            The Iwahori Hecke Algebra of Type A2 in 1,-1 over Integer Ring and prefix T
     507        """
     508
     509        # TODO: lift this to CombinatorialFreeModule
     510        def basis_element_to_weyl_group(self):
     511            """
     512            This function recovers w from H(w) if w is a Weyl group element.
     513
     514                sage: R.<q>=PolynomialRing(QQ)
     515                sage: H = IwahoriHeckeAlgebraT("A3",q)
     516                sage: T1,T2,T3 = H.algebra_generators()
     517                sage: (T1*T2*T3).basis_element_to_weyl_group().reduced_word()
     518                [1, 2, 3]
     519
     520            """
     521            if len(self) == 1:
     522                return self.support()[0]
     523            else:
     524                raise ValueError, "%s is not in the distinguished basis"%(self)
     525
     526        def inverse(self):
     527            """
     528            If the element is a basis element, that is, an element of the
     529            form self(w) with w in the Weyl group, this method computes
     530            its inverse. The base ring must be a field or Laurent
     531            polynomial ring. Other elements of the ring have inverses but
     532            the inverse method is only implemented for the basis elements.
     533
     534            EXAMPLES::
     535
     536                sage: R.<q>=LaurentPolynomialRing(QQ)
     537                sage: H = IwahoriHeckeAlgebraT("A2",q)
     538                sage: [T1,T2]=H.algebra_generators()
     539                sage: x = (T1*T2).inverse(); x
     540                (q^-2)*T2*T1 + (-q^-1+q^-2)*T1 + (-q^-1+q^-2)*T2 + (1-2*q^-1+q^-2)
     541                sage: x*T1*T2
     542                1
     543
     544            """
     545            if len(self) != 1:
     546                raise NotImplementedError, "inverse only implemented for basis elements (monomials in the generators)"%self
     547            H = self.parent()
     548            w = self.basis_element_to_weyl_group()
     549
     550            return H.prod(H.inverse_generator(i) for i in reversed(w.reduced_word()))
  • sage/categories/pushout.py

    diff -r 8ccaf3deb11c sage/categories/pushout.py
    a b  
    310310        if self.multi_variate and is_LaurentPolynomialRing(R):
    311311            return LaurentPolynomialRing(R.base_ring(), (list(R.variable_names()) + [self.var]))
    312312        else:
     313            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    313314            return PolynomialRing(R, self.var)
    314315    def __cmp__(self, other):
    315316        c = cmp(type(self), type(other))