Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/combinat/kazhdan_lusztig.py
8815 views
1
"""
2
Kazhdan-Lusztig Polynomials
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
#
9
# http://www.gnu.org/licenses/
10
#*****************************************************************************
11
12
from sage.rings.polynomial.polynomial_element import is_Polynomial
13
from sage.functions.other import floor
14
from sage.misc.cachefunc import cached_method
15
from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_mpair
16
from sage.structure.sage_object import SageObject
17
from sage.structure.unique_representation import UniqueRepresentation
18
from sage.combinat.root_system.coxeter_group import CoxeterGroup
19
20
class KazhdanLusztigPolynomial(UniqueRepresentation, SageObject):
21
"""
22
A Kazhdan-Lusztig polynomial.
23
24
INPUT:
25
26
- ``W`` -- a Weyl Group
27
- ``q`` -- an indeterminate
28
29
OPTIONAL:
30
31
- ``trace`` -- if ``True``, then this displays the trace: the intermediate
32
results. This is instructive and fun.
33
34
The parent of ``q`` may be a :class:`PolynomialRing` or a
35
:class:`LaurentPolynomialRing`.
36
37
REFERENCES:
38
39
.. [KL79] D. Kazhdan and G. Lusztig. *Representations of Coxeter
40
groups and Hecke algebras*. Invent. Math. **53** (1979).
41
no. 2, 165--184. :doi:`10.1007/BF01390031` :mathscinet:`MR0560412`
42
43
EXAMPLES::
44
45
sage: W = WeylGroup("B3",prefix="s")
46
sage: [s1,s2,s3] = W.simple_reflections()
47
sage: R.<q> = LaurentPolynomialRing(QQ)
48
sage: KL = KazhdanLusztigPolynomial(W,q)
49
sage: KL.P(s2,s3*s2*s3*s1*s2)
50
q + 1
51
52
A faster implementation (using the optional package Coxeter 3) is given by::
53
54
sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
55
sage: W.kazhdan_lusztig_polynomial([2], [3,2,3,1,2]) # optional - coxeter3
56
q + 1
57
"""
58
def __init__(self, W, q, trace=False):
59
"""
60
Initialize ``self``.
61
62
EXAMPLES::
63
64
sage: W = WeylGroup("B3",prefix="s")
65
sage: R.<q> = LaurentPolynomialRing(QQ)
66
sage: KL = KazhdanLusztigPolynomial(W,q)
67
sage: TestSuite(KL).run()
68
"""
69
self._coxeter_group = W
70
self._q = q
71
self._trace = trace
72
self._one = W.one()
73
self._base_ring = q.parent()
74
if is_Polynomial(q):
75
self._base_ring_type = "polynomial"
76
elif isinstance(q, LaurentPolynomial_mpair):
77
self._base_ring_type = "laurent"
78
else:
79
self._base_ring_type = "unknown"
80
81
@cached_method
82
def R(self, x, y):
83
"""
84
Return the Kazhdan-Lusztig `R` polynomial.
85
86
INPUT:
87
88
- ``x``, ``y`` -- elements of the underlying Coxeter group
89
90
EXAMPLES::
91
92
sage: R.<q>=QQ[]
93
sage: W = WeylGroup("A2", prefix="s")
94
sage: [s1,s2]=W.simple_reflections()
95
sage: KL = KazhdanLusztigPolynomial(W, q)
96
sage: [KL.R(x,s2*s1) for x in [1,s1,s2,s1*s2]]
97
[q^2 - 2*q + 1, q - 1, q - 1, 0]
98
"""
99
if x == 1:
100
x = self._one
101
if y == 1:
102
y = self._one
103
if x == y:
104
return self._base_ring.one()
105
if not x.bruhat_le(y):
106
return self._base_ring.zero()
107
if y.length() == 0:
108
if x.length() == 0:
109
return self._base_ring.one()
110
else:
111
return self._base_ring.zero()
112
s = self._coxeter_group.simple_reflection(y.first_descent(side="left"))
113
if (s*x).length() < x.length():
114
ret = self.R(s*x,s*y)
115
if self._trace:
116
print " R(%s,%s)=%s"%(x, y, ret)
117
return ret
118
else:
119
ret = (self._q-1)*self.R(s*x,y)+self._q*self.R(s*x,s*y)
120
if self._trace:
121
print " R(%s,%s)=%s"%(x, y, ret)
122
return ret
123
124
@cached_method
125
def P(self, x, y):
126
"""
127
Return the Kazhdan-Lusztig `P` polynomial.
128
129
If the rank is large, this runs slowly at first but speeds up
130
as you do repeated calculations due to the caching.
131
132
INPUT:
133
134
- ``x``, ``y`` -- elements of the underlying Coxeter group
135
136
.. SEEALSO::
137
138
:mod:`~sage.libs.coxeter3.coxeter_group.CoxeterGroup.kazhdan_lusztig_polynomial`
139
for a faster implementation using Fokko Ducloux's Coxeter3 C++ library.
140
141
EXAMPLES::
142
143
sage: R.<q> = QQ[]
144
sage: W = WeylGroup("A3", prefix="s")
145
sage: [s1,s2,s3] = W.simple_reflections()
146
sage: KL = KazhdanLusztigPolynomial(W, q)
147
sage: KL.P(s2,s2*s1*s3*s2)
148
q + 1
149
"""
150
if x == 1:
151
x = self._one
152
if y == 1:
153
y = self._one
154
if x == y:
155
return self._base_ring.one()
156
if not x.bruhat_le(y):
157
return self._base_ring.zero()
158
if y.length() == 0:
159
if x.length() == 0:
160
return self._base_ring.one()
161
else:
162
return self._base_ring.zero()
163
p = sum(-self.R(x,t)*self.P(t,y) for t in self._coxeter_group.bruhat_interval(x,y) if t != x)
164
tr = floor((y.length()-x.length()+1)/2)
165
try:
166
ret = p.truncate(tr)
167
except Exception:
168
ret = laurent_polynomial_truncate(p, tr)
169
if self._trace:
170
print " P(%s,%s)=%s"%(x, y, ret)
171
return ret
172
173
def laurent_polynomial_truncate(p, n):
174
"""
175
Truncate the Laurent polynomial ``p``, returning only terms of degree
176
less than ``n``, similar to the truncate method for polynomials.
177
178
EXAMPLES::
179
180
sage: from sage.combinat.kazhdan_lusztig import laurent_polynomial_truncate
181
sage: P.<q> = LaurentPolynomialRing(QQ)
182
sage: laurent_polynomial_truncate((q+q^-1)^3+q^2*(q+q^-1)^4,3)
183
6*q^2 + 3*q + 4 + 3*q^-1 + q^-2 + q^-3
184
"""
185
pdict = p._dict()
186
dict = {}
187
for k in pdict:
188
if k[0] < n:
189
dict[k] = pdict[k]
190
return p.parent()(dict)
191
192
193