Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/libs/coxeter3/coxeter_group.py
8817 views
1
"""
2
Coxeter Groups implemented with Coxeter3
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2009-2013 Mike Hansen <[email protected]>
6
#
7
# Distributed under the terms of the GNU General Public License (GPL)
8
# http://www.gnu.org/licenses/
9
#*****************************************************************************
10
from sage.groups.group import Group
11
from sage.libs.coxeter3.coxeter import get_CoxGroup, CoxGroupElement
12
from sage.structure.element import MultiplicativeGroupElement
13
from sage.misc.cachefunc import cached_method
14
15
from sage.structure.unique_representation import UniqueRepresentation
16
from sage.structure.element_wrapper import ElementWrapper
17
from sage.categories.all import CoxeterGroups, FiniteCoxeterGroups
18
from sage.structure.parent import Parent
19
20
class CoxeterGroup(UniqueRepresentation, Parent):
21
@staticmethod
22
def __classcall__(cls, cartan_type, *args, **options):
23
"""
24
TESTS::
25
26
sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup # optional - coxeter3
27
sage: CoxeterGroup(['B',2]) # optional - coxeter3
28
Coxeter group of type ['B', 2] implemented by Coxeter3
29
30
"""
31
from sage.combinat.all import CartanType
32
ct = CartanType(cartan_type)
33
return super(CoxeterGroup, cls).__classcall__(cls, ct, *args, **options)
34
35
def __init__(self, cartan_type):
36
"""
37
TESTS::
38
39
sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup # optional - coxeter3
40
sage: CoxeterGroup(['A',2]) # optional - coxeter3
41
Coxeter group of type ['A', 2] implemented by Coxeter3
42
sage: TestSuite(CoxeterGroup(['A',2])).run() # optional - coxeter3
43
"""
44
Parent.__init__(self, category=(FiniteCoxeterGroups() if cartan_type.is_finite() else CoxeterGroups()))
45
self._coxgroup = get_CoxGroup(cartan_type)
46
self._cartan_type = cartan_type
47
48
def _repr_(self):
49
"""
50
EXAMPLES::
51
52
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3'); W # optional - coxeter3 # indirect doctest
53
Coxeter group of type ['A', 3] implemented by Coxeter3
54
sage: W = CoxeterGroup(['A', 3, 1], implementation='coxeter3'); W # optional - coxeter3
55
Coxeter group of type ['A', 3, 1] implemented by Coxeter3
56
"""
57
return "Coxeter group of type %s implemented by Coxeter3"%(self.cartan_type())
58
59
def __iter__(self):
60
"""
61
EXAMPLES::
62
63
sage: W = CoxeterGroup(['A', 2], implementation='coxeter3') # optional - coxeter3
64
sage: list(W) # optional - coxeter3
65
[[], [1], [2], [1, 2], [2, 1], [1, 2, 1]]
66
"""
67
for x in self._coxgroup:
68
yield CoxeterGroup.Element(self, x)
69
70
def cartan_type(self):
71
"""
72
Return the Cartan type for this Coxeter group.
73
74
EXAMPLES::
75
76
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
77
sage: W.cartan_type() # optional - coxeter3
78
['A', 3]
79
"""
80
return self._cartan_type
81
82
def index_set(self):
83
"""
84
Return the index set for the generators of this Coxeter group.
85
86
EXAMPLES::
87
88
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
89
sage: W.index_set() # optional - coxeter3
90
[1, 2, 3]
91
sage: C = CoxeterGroup(['A', 3,1], implementation='coxeter3') # optional - coxeter3
92
sage: C.index_set() # optional - coxeter3
93
[0, 1, 2, 3]
94
"""
95
return self.cartan_type().index_set()
96
#return range(1, self.rank()+1)
97
98
def bruhat_interval(self, u, v):
99
"""
100
Return the Bruhat interval between ``u`` and ``v``.
101
102
EXAMPLES::
103
104
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
105
sage: W.bruhat_interval([1],[3,1,2,3]) # optional - coxeter3
106
[[1], [1, 2], [1, 3], [1, 2, 3], [1, 3, 2], [1, 2, 3, 2]]
107
"""
108
u, v = self(u), self(v)
109
return self._coxgroup.bruhat_interval(u.value, v.value)
110
111
def cardinality(self):
112
"""
113
Return the cardinality of this Coxeter group.
114
115
EXAMPLES::
116
117
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
118
sage: W.cardinality() # optional - coxeter3
119
24
120
"""
121
return self._coxgroup.order()
122
123
def one(self):
124
"""
125
Return the identity element of this Coxeter group.
126
127
EXAMPLES::
128
129
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
130
sage: W.one() # optional - coxeter3
131
[]
132
133
"""
134
return self([])
135
136
def simple_reflections(self):
137
"""
138
Return the family of generators for this Coxeter group.
139
140
EXAMPLES::
141
142
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
143
sage: s = W.simple_reflections() # optional - coxeter3
144
sage: s[2]*s[1]*s[2] # optional - coxeter3
145
[2, 1, 2]
146
"""
147
from sage.combinat.family import Family
148
return Family(self.index_set(), lambda i: self([i]))
149
150
gens = simple_reflections
151
152
def rank(self):
153
"""
154
Return the rank of this coxeter group, that is, the number of generators.
155
156
EXAMPLES::
157
158
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
159
sage: W.rank() # optional - coxeter3
160
3
161
"""
162
return self._coxgroup.rank()
163
164
def is_finite(self):
165
"""
166
Return True if this is a finite Coxeter group.
167
168
EXAMPLES::
169
170
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
171
sage: W.is_finite() # optional - coxeter3
172
True
173
"""
174
return self._coxgroup.is_finite()
175
176
def length(self, x):
177
"""
178
Return the length of an element ``x`` in this Coxeter group.
179
This is just the length of a reduced word for ``x``.
180
181
EXAMPLES::
182
183
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
184
sage: W.length(W([1,2])) # optional - coxeter3
185
2
186
sage: W.length(W([1,1])) # optional - coxeter3
187
0
188
189
"""
190
return len(x.value)
191
192
@cached_method
193
def coxeter_matrix(self):
194
"""
195
Return the Coxeter matrix for this Coxeter group.
196
197
The columns and rows are ordered according to the result of
198
:meth:`index_set`.
199
200
EXAMPLES::
201
202
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
203
sage: W.coxeter_matrix() # optional - coxeter3
204
[1 3 2]
205
[3 1 3]
206
[2 3 1]
207
208
"""
209
return self._coxgroup.coxeter_matrix()
210
211
def root_system(self):
212
"""
213
Return the root system associated with this Coxeter group.
214
215
EXAMPLES::
216
217
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
218
sage: R = W.root_system(); R # optional - coxeter3
219
Root system of type ['A', 3]
220
sage: alpha = R.root_space().basis() # optional - coxeter3
221
sage: alpha[2] + alpha[3] # optional - coxeter3
222
alpha[2] + alpha[3]
223
"""
224
return self.cartan_type().root_system()
225
226
def _an_element_(self):
227
"""
228
Return an element of this Coxeter group.
229
230
EXAMPLES::
231
232
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
233
sage: W._an_element_() # optional - coxeter3
234
[]
235
236
"""
237
return self([])
238
239
def m(self, i, j):
240
"""
241
Return the entry in the Coxeter matrix between the generator
242
with label ``i`` and the generator with label ``j``.
243
244
EXAMPLES::
245
246
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
247
sage: W.m(1,1) # optional - coxeter3
248
1
249
sage: W.m(1,0) # optional - coxeter3
250
2
251
"""
252
return self.coxeter_matrix()[i-1,j-1]
253
254
def kazhdan_lusztig_polynomial(self, u, v, constant_term_one=True):
255
r"""
256
Return the Kazhdan-Lusztig polynomial `P_{u,v}`.
257
258
INPUT:
259
260
- ``u``, ``v`` -- elements of the underlying Coxeter group
261
- ``constant_term_one`` -- (default: True) True uses the constant equals one convention,
262
False uses the Leclerc-Thibon convention
263
264
.. SEEALSO::
265
266
- :class:`~sage.combinat.kazhdan_lusztig.KazhdanLusztigPolynomial`
267
- :meth:`parabolic_kazhdan_lusztig_polynomial`
268
269
EXAMPLES::
270
271
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
272
sage: W.kazhdan_lusztig_polynomial([], [1,2, 1]) # optional - coxeter3
273
1
274
sage: W.kazhdan_lusztig_polynomial([1],[3,2]) # optional - coxeter3
275
0
276
sage: W = CoxeterGroup(['A',3],implementation='coxeter3') # optional - coxeter3
277
sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2]) # optional - coxeter3
278
q + 1
279
280
.. NOTE::
281
282
Coxeter3, as well as Sage's native implementation in
283
:class:`~sage.combinat.kazhdan_lusztig.KazhdanLusztigPolynomial`
284
use the convention under which Kazhdan-Lusztig
285
polynomials give the change of basis from the `(C_w)_{w\in W}`
286
basis to the `(T_w)_{w\in W}` of the Hecke algebra of `W` with
287
parameters `q` and `q^{-1}`:
288
289
.. MATH:: C_w = \sum_u P_{u,w} T_w
290
291
In particular, `P_{u,u}=1`::
292
293
sage: all(W.kazhdan_lusztig_polynomial(u,u) == 1 for u in W) # optional - coxeter3
294
True
295
296
This convention differs from Theorem 2.7 in [LeclercThibon1998]_ by:
297
298
.. MATH::
299
300
{}^{LT} P_{y,w}(q) = q^{\ell(w)-\ell(y)} P_{y,w}(q^{-2})
301
302
To access the Leclerc-Thibon convention use::
303
304
sage: W = CoxeterGroup(['A',3],implementation='coxeter3') # optional - coxeter3
305
sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2],constant_term_one=False) # optional - coxeter3
306
q^3 + q
307
308
TESTS:
309
310
We check that Coxeter3 and Sage's implementation give the same results::
311
312
sage: C = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
313
sage: W = WeylGroup("B3",prefix="s")
314
sage: [s1,s2,s3]=W.simple_reflections()
315
sage: R.<q>=LaurentPolynomialRing(QQ)
316
sage: KL=KazhdanLusztigPolynomial(W,q)
317
sage: all(KL.P(1,w) == C.kazhdan_lusztig_polynomial([],w.reduced_word()) for w in W) # optional - coxeter3 # long (15s)
318
True
319
"""
320
u, v = self(u), self(v)
321
p = u.value.kazhdan_lusztig_polynomial(v.value)
322
if constant_term_one:
323
return u.value.kazhdan_lusztig_polynomial(v.value)
324
q = p.parent().gen()
325
return q**(v.length()-u.length())*p.substitute(q=q**(-2))
326
327
def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True):
328
"""
329
Return the parabolic Kazhdan-Lusztig polynomial `P_{u,v}^{-,J}`.
330
331
INPUT:
332
333
- ``u``, ``v`` -- minimal length coset representatives of `W/W_J` for this Coxeter group `W`
334
- ``J`` -- a subset of the index set of ``self`` specifying the parabolic subgroup
335
336
This method implements the parabolic Kazhdan-Lusztig polynomials
337
`P^{-,J}_{u,v}` of [Deodhar1987]_, which are defined as
338
`P^{-,J}_{u,v} = \sum_{z\in W_J} (-1)^{\ell(z)} P_{yz,w}(q)`
339
with the conventions in Sage.
340
As for :meth:`kazhdan_lusztig_polynomial` the convention
341
differs from Theorem 2.7 in [LeclercThibon1998]_ by:
342
343
.. MATH::
344
345
{}^{LT} P_{y,w}^{-,J}(q) = q^{\ell(w)-\ell(y)} P_{y,w}^{-,J}(q^{-2})
346
347
REFERENCES:
348
349
.. [Deodhar1987] V.V. Deodhar, On some geometric aspects of Bruhat orderings II. The parabolic analogue of Kazhdan-Lusztig polynomials, J. Alg. 111 (1987) 483-506.
350
351
.. [LeclercThibon1998] B. Leclerc, J.-Y. Thibon, Littlewood-Richardson coefficients and Kazhdan-Lusztig polynomials, http://front.math.ucdavis.edu/9809.5122
352
353
EXAMPLES::
354
355
sage: W = CoxeterGroup(['A',3], implementation='coxeter3') # optional - coxeter3
356
sage: W.parabolic_kazhdan_lusztig_polynomial([],[3,2],[1,3]) # optional - coxeter3
357
0
358
sage: W.parabolic_kazhdan_lusztig_polynomial([2],[2,1,3,2],[1,3]) # optional - coxeter3
359
q
360
361
sage: C = CoxeterGroup(['A',3,1], implementation='coxeter3') # optional - coxeter3
362
sage: C.parabolic_kazhdan_lusztig_polynomial([],[1],[0]) # optional - coxeter3
363
1
364
sage: C.parabolic_kazhdan_lusztig_polynomial([],[1,2,1],[0]) # optional - coxeter3
365
1
366
sage: C.parabolic_kazhdan_lusztig_polynomial([],[0,1,0,1,2,1],[0]) # optional - coxeter3
367
q
368
sage: w=[1, 2, 1, 3, 0, 2, 1, 0, 3, 0, 2]
369
sage: v=[1, 2, 1, 3, 0, 1, 2, 1, 0, 3, 0, 2, 1, 0, 3, 0, 2]
370
sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3]) # optional - coxeter3
371
q^2 + q
372
sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3],constant_term_one=False) # optional - coxeter3
373
q^4 + q^2
374
375
TESTS::
376
377
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
378
sage: type(W.parabolic_kazhdan_lusztig_polynomial([2],[],[1])) # optional - coxeter3
379
<type 'sage.rings.polynomial.polynomial_integer_dense_flint.Polynomial_integer_dense_flint'>
380
"""
381
from sage.rings.all import ZZ
382
u = self(u)
383
v = self(v)
384
if any(d in J for d in u.descents()) or any(d in J for d in v.descents()):
385
raise ValueError, "u and v have to be minimal coset representatives"
386
P = ZZ['q']
387
q = P.gen()
388
subgroup = [ z for z in self.weak_order_ideal(lambda x: set(x.descents()).issubset(set(J))) if (u*z).bruhat_le(v) ]
389
if constant_term_one:
390
return P.sum((-1)**(z.length())*self.kazhdan_lusztig_polynomial(u*z,v) for z in subgroup)
391
return P.sum((-q)**(z.length())*self.kazhdan_lusztig_polynomial(u*z,v, constant_term_one=False) for z in subgroup)
392
393
394
class Element(ElementWrapper):
395
wrapped_class = CoxGroupElement
396
397
def __init__(self, parent, x):
398
"""
399
TESTS::
400
401
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
402
sage: W([2,1,2]) # optional - coxeter3
403
[1, 2, 1]
404
"""
405
if not isinstance(x, CoxGroupElement):
406
x = CoxGroupElement(parent._coxgroup, x).reduced()
407
ElementWrapper.__init__(self, parent, x)
408
409
def _repr_(self):
410
"""
411
TESTS::
412
413
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
414
sage: W([1,2,1]) # indirect doctest # optional - coxeter3
415
[1, 2, 1]
416
"""
417
return repr(self.value)
418
419
def __iter__(self):
420
"""
421
Return an iterator for the elements in the reduced word.
422
423
EXAMPLES::
424
425
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
426
sage: w = W([1,2,1]) # optional - coxeter3
427
sage: list(iter(w)) # optional - coxeter3
428
[1, 2, 1]
429
"""
430
return iter(self.value)
431
432
def coatoms(self):
433
"""
434
Return the coatoms (or co-covers) of this element in the Bruhat order.
435
436
EXAMPLES::
437
438
sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
439
sage: w = W([1,2,3]) # optional - coxeter3
440
sage: w.coatoms() # optional - coxeter3
441
[[2, 3], [1, 3], [1, 2]]
442
"""
443
W = self.parent()
444
return [W(w) for w in self.value.coatoms()]
445
446
def __cmp__(self, other):
447
"""
448
Return lexicographic comparison of ``self`` and ``other``.
449
450
EXAMPLES::
451
452
sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
453
sage: w = W([1,2,3]) # optional - coxeter3
454
sage: v = W([3,1,2]) # optional - coxeter3
455
sage: w.__cmp__(v) # optional - coxeter3
456
-1
457
sage: v.__cmp__(w) # optional - coxeter3
458
1
459
"""
460
if type(self) is not type(other):
461
return cmp(type(self), type(other))
462
return cmp(list(self), list(other))
463
464
def reduced_word(self):
465
"""
466
Return the reduced word of ``self``.
467
468
EXAMPLES::
469
470
sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
471
sage: w = W([1,2,3]) # optional - coxeter3
472
sage: w.reduced_word() # optional - coxeter3
473
[1, 2, 3]
474
"""
475
return list(self)
476
477
def __invert__(self):
478
"""
479
Return the inverse of this Coxeter group element.
480
481
EXAMPLES::
482
483
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
484
sage: w = W([1,2,3]) # optional - coxeter3
485
sage: ~w # optional - coxeter3
486
[3, 2, 1]
487
"""
488
return self.parent()(~self.value)
489
490
inverse = __invert__
491
492
def __getitem__(self, i):
493
"""
494
EXAMPLES::
495
496
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
497
sage: w0 = W([1,2,1]) # optional - coxeter3
498
sage: w0[0] # optional - coxeter3
499
1
500
sage: w0[1] # optional - coxeter3
501
2
502
503
"""
504
if i >= len(self):
505
raise IndexError
506
return self.value[i]
507
508
def _mul_(self, y):
509
"""
510
EXAMPLES::
511
512
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
513
sage: s = W.gens() # optional - coxeter3
514
sage: s[1]._mul_(s[1]) # optional - coxeter3
515
[]
516
sage: s[1]*s[2]*s[1] # optional - coxeter3
517
[1, 2, 1]
518
"""
519
result = self.value * y.value
520
return self.parent()(result)
521
522
def __eq__(self, y):
523
"""
524
Return whether this Coxeter group element is equal to ``y``.
525
526
This is computed by computing the normal form of both elements.
527
528
EXAMPLES::
529
530
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
531
sage: W([1,2,1]) == W([2,1,2]) # optional - coxeter3
532
True
533
sage: W([1,2,1]) == W([2,1]) # optional - coxeter3
534
False
535
536
"""
537
if not isinstance(y, self.parent().element_class):
538
return False
539
540
return list(self) == list(y)
541
542
def __len__(self):
543
"""
544
EXAMPLES::
545
546
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
547
sage: len(W([1,2,1])) # optional - coxeter3
548
3
549
"""
550
return self.parent().length(self)
551
552
553
def bruhat_le(self, v):
554
"""
555
Return whether ``self`` `\le` ``v`` in Bruhat order.
556
557
EXAMPLES::
558
559
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
560
sage: W([]).bruhat_le([1,2,1]) # optional - coxeter3
561
True
562
"""
563
v = self.parent()(v)
564
return self.value.bruhat_le(v.value)
565
566
def poincare_polynomial(self):
567
"""
568
Return the Poincare polynomial associated with this element.
569
570
EXAMPLES::
571
572
sage: W = CoxeterGroup(['A', 2], implementation='coxeter3') # optional - coxeter3
573
sage: W.long_element().poincare_polynomial() # optional - coxeter3
574
t^3 + 2*t^2 + 2*t + 1
575
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
576
sage: W([2,1,3,2]).poincare_polynomial() # optional - coxeter3
577
t^4 + 4*t^3 + 5*t^2 + 3*t + 1
578
sage: W([1,2,3,2,1]).poincare_polynomial() # optional - coxeter3
579
t^5 + 4*t^4 + 6*t^3 + 5*t^2 + 3*t + 1
580
581
sage: rw = sage.combinat.permutation.from_reduced_word # optional - coxeter3
582
sage: p = map(attrcall('poincare_polynomial'), W) # optional - coxeter3
583
sage: [rw(w.reduced_word()) for i,w in enumerate(W) if p[i] != p[i].reverse()] # optional - coxeter3
584
[[3, 4, 1, 2], [4, 2, 3, 1]]
585
"""
586
return self.value.poincare_polynomial()
587
588
def has_right_descent(self, i):
589
"""
590
Return whether ``i`` is a right descent of this element.
591
592
EXAMPLES::
593
594
sage: W = CoxeterGroup(['A', 4], implementation='coxeter3') # optional - coxeter3
595
sage: W([1,2]).has_right_descent(1) # optional - coxeter3
596
False
597
sage: W([1,2]).has_right_descent(2) # optional - coxeter3
598
True
599
"""
600
return i in self.value.right_descents()
601
602
def has_left_descent(self, i):
603
"""
604
Return True if ``i`` is a left descent of this element.
605
606
EXAMPLES::
607
608
sage: W = CoxeterGroup(['A', 4], implementation='coxeter3') # optional - coxeter3
609
sage: W([1,2]).has_left_descent(1) # optional - coxeter3
610
True
611
sage: W([1,2]).has_left_descent(2) # optional - coxeter3
612
False
613
"""
614
return i in self.value.left_descents()
615
616
def action(self, v):
617
"""
618
Return the action of of this Coxeter group element on the root space.
619
620
INPUT:
621
622
- ``v`` -- an element of the root space associated with the Coxeter group for ``self``
623
624
EXAMPLES::
625
626
sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
627
sage: R = W.root_system().root_space() # optional - coxeter3
628
sage: v = R.an_element(); v # optional - coxeter3
629
2*alpha[1] + 2*alpha[2] + 3*alpha[3]
630
sage: w = W([1,2,3]) # optional - coxeter3
631
sage: w.action(v) # optional - coxeter3
632
-alpha[1] + alpha[2] + alpha[3]
633
"""
634
#TODO: Find a better way to do this
635
W = self.parent().root_system().root_space().weyl_group()
636
w = W.from_reduced_word(list(self))
637
return w.action(v)
638
639
def action_on_rational_function(self, f):
640
r"""
641
Return the natural action of this Coxeter group element on a
642
polynomial considered as an element of `S(\mathfrak{h}^*)`.
643
644
.. NOTE::
645
646
Note that the number of variables in the polynomial
647
ring must correspond to the rank of this Coxeter
648
group. The ordering of the variables is assumed to
649
coincide with the result of :meth:`index_set`.
650
651
EXAMPLES::
652
653
sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3
654
sage: S = PolynomialRing(QQ, 'x,y,z').fraction_field() # optional - coxeter3
655
sage: x,y,z = S.gens() # optional - coxeter3
656
sage: W([1]).action_on_rational_function(x+y+z) # optional - coxeter3
657
(x^2*y + x*z + 1)/x
658
sage: W([2]).action_on_rational_function(x+y+z) # optional - coxeter3
659
(x*y^2 + y^2*z + 1)/y
660
sage: W([3]).action_on_rational_function(x+y+z) # optional - coxeter3
661
(y*z^2 + x*z + 1)/z
662
"""
663
Q = f.parent()
664
Q_gens = Q.gens()
665
W = self.parent()
666
R = W.root_system().root_space()
667
alpha = R.basis()
668
n = W.rank()
669
670
if Q.ngens() != n:
671
raise ValueError, "the number of generators for the polynomial ring must be the same as the rank of the root system"
672
673
basis_elements = [alpha[i] for i in W.index_set()]
674
basis_to_order = dict([(s, i) for i, s in enumerate(W.index_set())])
675
676
results = []
677
for poly in [f.numerator(), f.denominator()]:
678
result = 0
679
exponents = poly.exponents()
680
681
for exponent in exponents:
682
#Construct something in the root lattice from the exponent vector
683
exponent = sum([e*b for e, b in zip(exponent, basis_elements)])
684
exponent = self.action(exponent)
685
686
monomial = 1
687
for s, c in exponent.monomial_coefficients().iteritems():
688
monomial *= Q_gens[basis_to_order[s]]**int(c)
689
690
result += monomial
691
692
results.append(result)
693
694
numerator, denominator = results
695
return numerator / denominator
696
697