Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/categories/classical_crystals.py
4057 views
1
r"""
2
Classical Crystals
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2010 Anne Schilling <anne at math.ucdavis.edu>
6
#
7
# Distributed under the terms of the GNU General Public License (GPL)
8
# http://www.gnu.org/licenses/
9
#******************************************************************************
10
11
from sage.misc.cachefunc import cached_method
12
from sage.categories.category import Category
13
from sage.categories.category_singleton import Category_singleton
14
from sage.categories.finite_crystals import FiniteCrystals
15
from sage.categories.highest_weight_crystals import HighestWeightCrystals
16
17
class ClassicalCrystals(Category_singleton):
18
"""
19
The category of classical crystals, that is crystals of finite Cartan type.
20
21
EXAMPLES::
22
23
sage: C = ClassicalCrystals()
24
sage: C
25
Category of classical crystals
26
sage: C.super_categories()
27
[Category of finite crystals, Category of highest weight crystals]
28
sage: C.example()
29
Highest weight crystal of type A_3 of highest weight omega_1
30
31
TESTS::
32
33
sage: TestSuite(C).run()
34
sage: B = FiniteCrystals().example()
35
sage: TestSuite(B).run(verbose = True)
36
running ._test_an_element() . . . pass
37
running ._test_category() . . . pass
38
running ._test_elements() . . .
39
Running the test suite of self.an_element()
40
running ._test_category() . . . pass
41
running ._test_eq() . . . pass
42
running ._test_not_implemented_methods() . . . pass
43
running ._test_pickling() . . . pass
44
running ._test_stembridge_local_axioms() . . . pass
45
pass
46
running ._test_elements_eq() . . . pass
47
running ._test_enumerated_set_contains() . . . pass
48
running ._test_enumerated_set_iter_cardinality() . . . pass
49
running ._test_enumerated_set_iter_list() . . . pass
50
running ._test_eq() . . . pass
51
running ._test_fast_iter() . . . pass
52
running ._test_not_implemented_methods() . . . pass
53
running ._test_pickling() . . . pass
54
running ._test_some_elements() . . . pass
55
running ._test_stembridge_local_axioms() . . . pass
56
"""
57
58
def super_categories(self):
59
r"""
60
EXAMPLES::
61
62
sage: ClassicalCrystals().super_categories()
63
[Category of finite crystals, Category of highest weight crystals]
64
"""
65
return [FiniteCrystals(), HighestWeightCrystals()]
66
67
def example(self, n = 3):
68
"""
69
Returns an example of highest weight crystals, as per
70
:meth:`Category.example`.
71
72
EXAMPLES::
73
74
sage: B = ClassicalCrystals().example(); B
75
Highest weight crystal of type A_3 of highest weight omega_1
76
"""
77
from sage.categories.crystals import Crystals
78
return Crystals().example(n)
79
80
81
class ParentMethods:
82
83
@cached_method
84
def opposition_automorphism(self):
85
r"""
86
Returns the opposition automorphism
87
88
The *opposition automorphism* is the automorphism
89
`i \mapsto i^*` of the vertices Dynkin diagram such that,
90
for `w_0` the longest element of the Weyl group, and any
91
simple root `\alpha_i`, one has `\alpha_{i^*} = -w_0(\alpha_i)`.
92
93
The automorphism is returned as a dictionary.
94
95
EXAMPLES::
96
97
sage: T = CrystalOfTableaux(['A',5],shape=[1])
98
sage: T.opposition_automorphism()
99
{1: 5, 2: 4, 3: 3, 4: 2, 5: 1}
100
101
sage: T = CrystalOfTableaux(['D',4],shape=[1])
102
sage: T.opposition_automorphism()
103
{1: 1, 2: 2, 3: 3, 4: 4}
104
105
sage: T = CrystalOfTableaux(['D',5],shape=[1])
106
sage: T.opposition_automorphism()
107
{1: 1, 2: 2, 3: 3, 4: 5, 5: 4}
108
109
sage: T = CrystalOfTableaux(['C',4],shape=[1])
110
sage: T.opposition_automorphism()
111
{1: 1, 2: 2, 3: 3, 4: 4}
112
"""
113
L = self.cartan_type().root_system().root_lattice()
114
W = L.weyl_group()
115
w0 = W.long_element()
116
alpha = L.simple_roots()
117
return dict( (i, (w0.action(alpha[i])).leading_support()) for i in self.index_set() )
118
119
def demazure_character(self, weight, reduced_word = False):
120
r"""
121
Returns the Demazure character associated to the specified
122
weight in the ambient weight lattice.
123
124
INPUT:
125
126
- ``weight`` -- an element of the weight lattice
127
realization of the crystal, or a reduced word
128
- ``reduced_word`` -- a boolean (default: ``False``)
129
whether ``weight`` is given as a reduced word
130
131
This is currently only supported for crystals whose
132
underlying weight space is the ambient space.
133
134
EXAMPLES::
135
136
sage: T = CrystalOfTableaux(['A',2], shape = [2,1])
137
sage: e = T.weight_lattice_realization().basis()
138
sage: weight = e[0] + 2*e[2]
139
sage: weight.reduced_word()
140
[2, 1]
141
sage: T.demazure_character(weight)
142
x1^2*x2 + x1^2*x3 + x1*x2^2 + x1*x2*x3 + x1*x3^2
143
144
sage: T = CrystalOfTableaux(['A',3],shape=[2,1])
145
sage: T.demazure_character([1,2,3], reduced_word = True)
146
x1^2*x2 + x1^2*x3 + x1*x2^2 + x1*x2*x3 + x2^2*x3
147
148
sage: T = CrystalOfTableaux(['B',2], shape = [2])
149
sage: e = T.weight_lattice_realization().basis()
150
sage: weight = -2*e[1]
151
sage: T.demazure_character(weight)
152
x1^2 + x1*x2 + x2^2 + x1 + x2 + x1/x2 + 1/x2 + 1/x2^2 + 1
153
154
TODO: detect automatically if weight is a reduced word,
155
and remove the (untested!) ``reduced_word`` option.
156
157
REFERENCES::
158
159
.. [D1974] M. Demazure, Desingularisation des varietes de Schubert,
160
Ann. E. N. S., Vol. 6, (1974), p. 163-172
161
162
.. [M2009] Sarah Mason, An Explicit Construction of Type A Demazure Atoms,
163
Journal of Algebraic Combinatorics, Vol. 29, (2009), No. 3, p.295-313
164
(arXiv:0707.4267)
165
166
"""
167
from sage.misc.misc_c import prod
168
from sage.rings.rational_field import QQ
169
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
170
if reduced_word:
171
word = weight
172
else:
173
word = weight.reduced_word()
174
n = self.weight_lattice_realization().n
175
u = list( self.module_generators )
176
for i in reversed(word):
177
u = u + sum((x.demazure_operator(i, truncated = True) for x in u), [])
178
x = ['x%s'%i for i in range(1,n+1)]
179
P = PolynomialRing(QQ, x)
180
u = [b.weight() for b in u]
181
return sum((prod((x[i]**(la[i]) for i in range(n)), P.one()) for la in u), P.zero())
182
183
def character(self, R=None):
184
"""
185
Returns the character of this crystal.
186
187
INPUT:
188
189
- ``R`` -- a :class:`WeylCharacterRing`
190
(default: the default :class:`WeylCharacterRing` for this Cartan type)
191
192
Returns the character of ``self`` as an element of ``R``.
193
194
EXAMPLES::
195
196
sage: C = CrystalOfTableaux("A2", shape=[2,1])
197
sage: chi = C.character(); chi
198
A2(2,1,0)
199
200
sage: T = TensorProductOfCrystals(C,C)
201
sage: chiT = T.character(); chiT
202
A2(2,2,2) + 2*A2(3,2,1) + A2(3,3,0) + A2(4,1,1) + A2(4,2,0)
203
sage: chiT == chi^2
204
True
205
206
One may specify an alternate :class:`WeylCharacterRing`::
207
208
sage: R = WeylCharacterRing("A2", style="coroots")
209
sage: chiT = T.character(R); chiT
210
A2(0,0) + 2*A2(1,1) + A2(0,3) + A2(3,0) + A2(2,2)
211
sage: chiT in R
212
True
213
214
It should have the same cartan type and use the same
215
realization of the weight lattice as ``self``::
216
217
sage: R = WeylCharacterRing("A3", style="coroots")
218
sage: T.character(R)
219
Traceback (most recent call last):
220
...
221
ValueError: Weyl character ring does not have the right Cartan type
222
223
"""
224
from sage.combinat.root_system.weyl_characters import WeylCharacterRing
225
if R == None:
226
R = WeylCharacterRing(self.cartan_type())
227
if not R.cartan_type() == self.cartan_type():
228
raise ValueError, "Weyl character ring does not have the right Cartan type"
229
assert R.basis().keys() == self.weight_lattice_realization()
230
231
return R.sum_of_monomials( x.weight() for x in self.highest_weight_vectors() )
232
233
def list(self):
234
r"""
235
Returns the list of the elements of ``self``, as per
236
:meth:`FiniteEnumeratedSets.ParentMethods.list`
237
238
EXAMPLES::
239
240
sage: C = CrystalOfLetters(['D',4])
241
sage: C.list()
242
[1, 2, 3, 4, -4, -3, -2, -1]
243
244
FIXME: this is just there to reinstate the default
245
implementation of :meth:`.list` from :meth:`.__iter__`
246
which is overriden in :class:`Crystals`.
247
"""
248
return self._list_from_iterator()
249
250
def __iter__(self):
251
r"""
252
Returns an iterator over the elements of this crystal.
253
254
This iterator uses little memory, storing only one element
255
of the crystal at a time. For details on the complexity, see
256
:class:`sage.combinat.crystals.crystals.CrystalBacktracker`.
257
258
EXAMPLES::
259
260
sage: C = CrystalOfLetters(['A',5])
261
sage: [x for x in C]
262
[1, 2, 3, 4, 5, 6]
263
264
TESTS::
265
266
sage: C = CrystalOfLetters(['D',4])
267
sage: D = CrystalOfSpinsPlus(['D',4])
268
sage: E = CrystalOfSpinsMinus(['D',4])
269
sage: T=TensorProductOfCrystals(D,E,generators=[[D.list()[0],E.list()[0]]])
270
sage: U=TensorProductOfCrystals(C,E,generators=[[C(1),E.list()[0]]])
271
sage: T.cardinality()
272
56
273
274
sage: TestSuite(T).run(verbose = True)
275
running ._test_an_element() . . . pass
276
running ._test_category() . . . pass
277
running ._test_elements() . . .
278
Running the test suite of self.an_element()
279
running ._test_category() . . . pass
280
running ._test_eq() . . . pass
281
running ._test_not_implemented_methods() . . . pass
282
running ._test_pickling() . . . pass
283
running ._test_stembridge_local_axioms() . . . pass
284
pass
285
running ._test_elements_eq() . . . pass
286
running ._test_enumerated_set_contains() . . . pass
287
running ._test_enumerated_set_iter_cardinality() . . . pass
288
running ._test_enumerated_set_iter_list() . . . pass
289
running ._test_eq() . . . pass
290
running ._test_fast_iter() . . . pass
291
running ._test_not_implemented_methods() . . . pass
292
running ._test_pickling() . . . pass
293
running ._test_some_elements() . . . pass
294
running ._test_stembridge_local_axioms() . . . pass
295
296
sage: TestSuite(U).run(verbose = True)
297
running ._test_an_element() . . . pass
298
running ._test_category() . . . pass
299
running ._test_elements() . . .
300
Running the test suite of self.an_element()
301
running ._test_category() . . . pass
302
running ._test_eq() . . . pass
303
running ._test_not_implemented_methods() . . . pass
304
running ._test_pickling() . . . pass
305
running ._test_stembridge_local_axioms() . . . pass
306
pass
307
running ._test_elements_eq() . . . pass
308
running ._test_enumerated_set_contains() . . . pass
309
running ._test_enumerated_set_iter_cardinality() . . . pass
310
running ._test_enumerated_set_iter_list() . . . pass
311
running ._test_eq() . . . pass
312
running ._test_fast_iter() . . . pass
313
running ._test_not_implemented_methods() . . . pass
314
running ._test_pickling() . . . pass
315
running ._test_some_elements() . . . pass
316
running ._test_stembridge_local_axioms() . . . pass
317
318
Bump's systematic tests::
319
320
sage: fa3 = lambda a,b,c: CrystalOfTableaux(['A',3],shape=[a+b+c,b+c,c])
321
sage: fb3 = lambda a,b,c: CrystalOfTableaux(['B',3],shape=[a+b+c,b+c,c])
322
sage: fc3 = lambda a,b,c: CrystalOfTableaux(['C',3],shape=[a+b+c,b+c,c])
323
sage: fb4 = lambda a,b,c,d: CrystalOfTableaux(['B',4],shape=[a+b+c+d,b+c+d,c+d,d])
324
sage: fd4 = lambda a,b,c,d: CrystalOfTableaux(['D',4],shape=[a+b+c+d,b+c+d,c+d,d])
325
sage: fd5 = lambda a,b,c,d,e: CrystalOfTableaux(['D',5],shape=[a+b+c+d+e,b+c+d+e,c+d+e,d+e,e])
326
sage: def fd4spinplus(a,b,c,d):
327
... C = CrystalOfTableaux(['D',4],shape=[a+b+c+d,b+c+d,c+d,d])
328
... D = CrystalOfSpinsPlus(['D',4])
329
... return TensorProductOfCrystals(C,D,generators=[[C[0],D[0]]])
330
sage: def fb3spin(a,b,c):
331
... C = CrystalOfTableaux(['B',3],shape=[a+b+c,b+c,c])
332
... D = CrystalOfSpins(['B',3])
333
... return TensorProductOfCrystals(C,D,generators=[[C[0],D[0]]])
334
335
TODO: choose a good panel of values for a,b,c ... both for
336
basic systematic tests and for conditionally run,
337
computationally involved tests.
338
339
::
340
341
sage: TestSuite(fb4(1,0,1,0)).run(verbose = True) # long time (8s on sage.math, 2011)
342
running ._test_an_element() . . . pass
343
running ._test_category() . . . pass
344
running ._test_elements() . . .
345
Running the test suite of self.an_element()
346
running ._test_category() . . . pass
347
running ._test_eq() . . . pass
348
running ._test_not_implemented_methods() . . . pass
349
running ._test_pickling() . . . pass
350
running ._test_stembridge_local_axioms() . . . pass
351
pass
352
running ._test_elements_eq() . . . pass
353
running ._test_enumerated_set_contains() . . . pass
354
running ._test_enumerated_set_iter_cardinality() . . . pass
355
running ._test_enumerated_set_iter_list() . . .Enumerated set too big; skipping test; see ``self.max_test_enumerated_set_loop``
356
pass
357
running ._test_eq() . . . pass
358
running ._test_fast_iter() . . . pass
359
running ._test_not_implemented_methods() . . . pass
360
running ._test_pickling() . . . pass
361
running ._test_some_elements() . . . pass
362
running ._test_stembridge_local_axioms() . . . pass
363
364
::
365
366
#sage: fb4(1,1,1,1).check() # expensive: the crystal is of size 297297
367
#True
368
"""
369
from sage.combinat.crystals.crystals import CrystalBacktracker
370
return iter(CrystalBacktracker(self))
371
372
def _test_fast_iter(self, **options):
373
r"""
374
Tests whether the elements returned by :meth:`.__iter__`
375
and ``Crystal.list(self)`` are the same (the two
376
algorithms are different).
377
378
EXAMPLES::
379
380
sage: C = CrystalOfLetters(['A', 5])
381
sage: C._test_fast_iter()
382
"""
383
tester = self._tester(**options)
384
S = self._list_brute_force()
385
SS = set(S)
386
tester.assert_( len(S) == len(SS) )
387
tester.assert_( set(self) == set(SS) )
388
389
def cardinality(self):
390
r"""
391
Returns the number of elements of the crystal, using Weyl's
392
dimension formula on each connected component.
393
394
EXAMPLES::
395
396
sage: C = ClassicalCrystals().example(5)
397
sage: C.cardinality()
398
6
399
"""
400
return sum(self.weight_lattice_realization().weyl_dimension(x.weight())
401
for x in self.highest_weight_vectors())
402
403
class ElementMethods:
404
405
def lusztig_involution(self):
406
r"""
407
Returns the Lusztig involution on the classical highest weight crystal self.
408
409
The Lusztig involution on a finite-dimensional highest weight crystal `B(\lambda)` of highest weight `\lambda`
410
maps the highest weight vector to the lowest weight vector and the Kashiwara operator `f_i` to
411
`e_{i^*}`, where `i^*` is defined as `\alpha_{i^*} = -w_0(\alpha_i)`. Here `w_0` is the longest element
412
of the Weyl group acting on the `i`-th simple root `\alpha_i`.
413
414
EXAMPLES::
415
416
sage: B = CrystalOfTableaux(['A',3],shape=[2,1])
417
sage: b = B(rows=[[1,2],[4]])
418
sage: b.lusztig_involution()
419
[[1, 4], [3]]
420
sage: b.to_tableau().schuetzenberger_involution(n=4)
421
[[1, 4], [3]]
422
423
sage: all(b.lusztig_involution().to_tableau() == b.to_tableau().schuetzenberger_involution(n=4) for b in B)
424
True
425
426
sage: B = CrystalOfTableaux(['D',4],shape=[1])
427
sage: [[b,b.lusztig_involution()] for b in B]
428
[[[[1]], [[-1]]], [[[2]], [[-2]]], [[[3]], [[-3]]], [[[4]], [[-4]]], [[[-4]],
429
[[4]]], [[[-3]], [[3]]], [[[-2]], [[2]]], [[[-1]], [[1]]]]
430
431
sage: B = CrystalOfTableaux(['D',3],shape=[1])
432
sage: [[b,b.lusztig_involution()] for b in B]
433
[[[[1]], [[-1]]], [[[2]], [[-2]]], [[[3]], [[3]]], [[[-3]], [[-3]]],
434
[[[-2]], [[2]]], [[[-1]], [[1]]]]
435
436
sage: C=CartanType(['E',6])
437
sage: La=C.root_system().weight_lattice().fundamental_weights()
438
sage: T = HighestWeightCrystal(La[1])
439
sage: t = T[3]; t
440
[[-4, 2, 5]]
441
sage: t.lusztig_involution()
442
[[-2, -3, 4]]
443
"""
444
hw = self.to_highest_weight()[1]
445
hw.reverse()
446
hw = [self.parent().opposition_automorphism()[i] for i in hw]
447
return self.to_lowest_weight()[0].e_string(hw)
448
449