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