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