Path: blob/master/src/sage/combinat/kazhdan_lusztig.py
8815 views
"""1Kazhdan-Lusztig Polynomials2"""3#*****************************************************************************4# Copyright (C) 2008 Daniel Bump <bump at match.stanford.edu>,5#6# Distributed under the terms of the GNU General Public License (GPL)7#8# http://www.gnu.org/licenses/9#*****************************************************************************1011from sage.rings.polynomial.polynomial_element import is_Polynomial12from sage.functions.other import floor13from sage.misc.cachefunc import cached_method14from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_mpair15from sage.structure.sage_object import SageObject16from sage.structure.unique_representation import UniqueRepresentation17from sage.combinat.root_system.coxeter_group import CoxeterGroup1819class KazhdanLusztigPolynomial(UniqueRepresentation, SageObject):20"""21A Kazhdan-Lusztig polynomial.2223INPUT:2425- ``W`` -- a Weyl Group26- ``q`` -- an indeterminate2728OPTIONAL:2930- ``trace`` -- if ``True``, then this displays the trace: the intermediate31results. This is instructive and fun.3233The parent of ``q`` may be a :class:`PolynomialRing` or a34:class:`LaurentPolynomialRing`.3536REFERENCES:3738.. [KL79] D. Kazhdan and G. Lusztig. *Representations of Coxeter39groups and Hecke algebras*. Invent. Math. **53** (1979).40no. 2, 165--184. :doi:`10.1007/BF01390031` :mathscinet:`MR0560412`4142EXAMPLES::4344sage: W = WeylGroup("B3",prefix="s")45sage: [s1,s2,s3] = W.simple_reflections()46sage: R.<q> = LaurentPolynomialRing(QQ)47sage: KL = KazhdanLusztigPolynomial(W,q)48sage: KL.P(s2,s3*s2*s3*s1*s2)49q + 15051A faster implementation (using the optional package Coxeter 3) is given by::5253sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter354sage: W.kazhdan_lusztig_polynomial([2], [3,2,3,1,2]) # optional - coxeter355q + 156"""57def __init__(self, W, q, trace=False):58"""59Initialize ``self``.6061EXAMPLES::6263sage: W = WeylGroup("B3",prefix="s")64sage: R.<q> = LaurentPolynomialRing(QQ)65sage: KL = KazhdanLusztigPolynomial(W,q)66sage: TestSuite(KL).run()67"""68self._coxeter_group = W69self._q = q70self._trace = trace71self._one = W.one()72self._base_ring = q.parent()73if is_Polynomial(q):74self._base_ring_type = "polynomial"75elif isinstance(q, LaurentPolynomial_mpair):76self._base_ring_type = "laurent"77else:78self._base_ring_type = "unknown"7980@cached_method81def R(self, x, y):82"""83Return the Kazhdan-Lusztig `R` polynomial.8485INPUT:8687- ``x``, ``y`` -- elements of the underlying Coxeter group8889EXAMPLES::9091sage: R.<q>=QQ[]92sage: W = WeylGroup("A2", prefix="s")93sage: [s1,s2]=W.simple_reflections()94sage: KL = KazhdanLusztigPolynomial(W, q)95sage: [KL.R(x,s2*s1) for x in [1,s1,s2,s1*s2]]96[q^2 - 2*q + 1, q - 1, q - 1, 0]97"""98if x == 1:99x = self._one100if y == 1:101y = self._one102if x == y:103return self._base_ring.one()104if not x.bruhat_le(y):105return self._base_ring.zero()106if y.length() == 0:107if x.length() == 0:108return self._base_ring.one()109else:110return self._base_ring.zero()111s = self._coxeter_group.simple_reflection(y.first_descent(side="left"))112if (s*x).length() < x.length():113ret = self.R(s*x,s*y)114if self._trace:115print " R(%s,%s)=%s"%(x, y, ret)116return ret117else:118ret = (self._q-1)*self.R(s*x,y)+self._q*self.R(s*x,s*y)119if self._trace:120print " R(%s,%s)=%s"%(x, y, ret)121return ret122123@cached_method124def P(self, x, y):125"""126Return the Kazhdan-Lusztig `P` polynomial.127128If the rank is large, this runs slowly at first but speeds up129as you do repeated calculations due to the caching.130131INPUT:132133- ``x``, ``y`` -- elements of the underlying Coxeter group134135.. SEEALSO::136137:mod:`~sage.libs.coxeter3.coxeter_group.CoxeterGroup.kazhdan_lusztig_polynomial`138for a faster implementation using Fokko Ducloux's Coxeter3 C++ library.139140EXAMPLES::141142sage: R.<q> = QQ[]143sage: W = WeylGroup("A3", prefix="s")144sage: [s1,s2,s3] = W.simple_reflections()145sage: KL = KazhdanLusztigPolynomial(W, q)146sage: KL.P(s2,s2*s1*s3*s2)147q + 1148"""149if x == 1:150x = self._one151if y == 1:152y = self._one153if x == y:154return self._base_ring.one()155if not x.bruhat_le(y):156return self._base_ring.zero()157if y.length() == 0:158if x.length() == 0:159return self._base_ring.one()160else:161return self._base_ring.zero()162p = sum(-self.R(x,t)*self.P(t,y) for t in self._coxeter_group.bruhat_interval(x,y) if t != x)163tr = floor((y.length()-x.length()+1)/2)164try:165ret = p.truncate(tr)166except Exception:167ret = laurent_polynomial_truncate(p, tr)168if self._trace:169print " P(%s,%s)=%s"%(x, y, ret)170return ret171172def laurent_polynomial_truncate(p, n):173"""174Truncate the Laurent polynomial ``p``, returning only terms of degree175less than ``n``, similar to the truncate method for polynomials.176177EXAMPLES::178179sage: from sage.combinat.kazhdan_lusztig import laurent_polynomial_truncate180sage: P.<q> = LaurentPolynomialRing(QQ)181sage: laurent_polynomial_truncate((q+q^-1)^3+q^2*(q+q^-1)^4,3)1826*q^2 + 3*q + 4 + 3*q^-1 + q^-2 + q^-3183"""184pdict = p._dict()185dict = {}186for k in pdict:187if k[0] < n:188dict[k] = pdict[k]189return p.parent()(dict)190191192193