Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/combinat/crystals/spins.py
8817 views
1
r"""
2
Spin Crystals
3
4
These are the crystals associated with the three spin
5
representations: the spin representations of odd orthogonal groups
6
(or rather their double covers); and the `+` and `-` spin
7
representations of the even orthogonal groups.
8
9
We follow Kashiwara and Nakashima (Journal of Algebra 165, 1994) in
10
representing the elements of the spin Crystal by sequences of signs
11
`\pm`. Two other representations are available as attributes
12
:meth:`Spin.internal_repn` and :meth:`Spin.signature` of the crystal element.
13
14
- A numerical internal representation, an integer `n` such that if `n-1`
15
is written in binary and the `1`'s are replaced by ``-``, the `0`'s by
16
``+``
17
18
- The signature, which is a list in which ``+`` is replaced by `+1` and
19
``-`` by `-1`.
20
"""
21
22
#*****************************************************************************
23
# Copyright (C) 2007 Anne Schilling <anne at math.ucdavis.edu>
24
# Nicolas Thiery <nthiery at users.sf.net>
25
# Daniel Bump <bump at match.stanford.edu>
26
#
27
# Distributed under the terms of the GNU General Public License (GPL)
28
#
29
# This code is distributed in the hope that it will be useful,
30
# but WITHOUT ANY WARRANTY; without even the implied warranty of
31
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32
# General Public License for more details.
33
#
34
# The full text of the GPL is available at:
35
#
36
# http://www.gnu.org/licenses/
37
#****************************************************************************
38
39
from sage.misc.cachefunc import cached_method
40
from sage.structure.unique_representation import UniqueRepresentation
41
from sage.structure.parent import Parent
42
from sage.categories.classical_crystals import ClassicalCrystals
43
from sage.combinat.crystals.letters import LetterTuple
44
from sage.combinat.root_system.cartan_type import CartanType
45
from sage.combinat.tableau import Tableau
46
47
48
#########################
49
# Type B spin
50
#########################
51
52
def CrystalOfSpins(ct):
53
r"""
54
Return the spin crystal of the given type `B`.
55
56
This is a combinatorial model for the crystal with highest weight
57
`Lambda_n` (the `n`-th fundamental weight). It has
58
`2^n` elements, here called Spins. See also
59
:func:`CrystalOfLetters`, :func:`CrystalOfSpinsPlus`,
60
and :func:`CrystalOfSpinsMinus`.
61
62
INPUT:
63
64
- ``['B', n]`` - A Cartan type `B_n`.
65
66
EXAMPLES::
67
68
sage: C = CrystalOfSpins(['B',3])
69
sage: C.list()
70
[+++, ++-, +-+, -++, +--, -+-, --+, ---]
71
sage: C.cartan_type()
72
['B', 3]
73
74
::
75
76
sage: [x.signature() for x in C]
77
['+++', '++-', '+-+', '-++', '+--', '-+-', '--+', '---']
78
79
TESTS::
80
81
sage: TensorProductOfCrystals(C,C,generators=[[C.list()[0],C.list()[0]]]).cardinality()
82
35
83
"""
84
ct = CartanType(ct)
85
if ct[0] == 'B':
86
return GenericCrystalOfSpins(ct, Spin_crystal_type_B_element, "spins")
87
else:
88
raise NotImplementedError
89
90
#########################
91
# Type D spins
92
#########################
93
94
def CrystalOfSpinsPlus(ct):
95
r"""
96
Return the plus spin crystal of the given type D.
97
98
This is the crystal with highest weight `Lambda_n` (the
99
`n`-th fundamental weight).
100
101
INPUT:
102
103
- ``['D', n]`` - A Cartan type `D_n`.
104
105
EXAMPLES::
106
107
sage: D = CrystalOfSpinsPlus(['D',4])
108
sage: D.list()
109
[++++, ++--, +-+-, -++-, +--+, -+-+, --++, ----]
110
111
::
112
113
sage: [x.signature() for x in D]
114
['++++', '++--', '+-+-', '-++-', '+--+', '-+-+', '--++', '----']
115
116
TESTS::
117
118
sage: TestSuite(D).run()
119
"""
120
ct = CartanType(ct)
121
if ct[0] == 'D':
122
return GenericCrystalOfSpins(ct, Spin_crystal_type_D_element, "plus")
123
else:
124
raise NotImplementedError
125
126
def CrystalOfSpinsMinus(ct):
127
r"""
128
Return the minus spin crystal of the given type D.
129
130
This is the crystal with highest weight `Lambda_{n-1}`
131
(the `(n-1)`-st fundamental weight).
132
133
INPUT:
134
135
- ``['D', n]`` - A Cartan type `D_n`.
136
137
EXAMPLES::
138
139
sage: E = CrystalOfSpinsMinus(['D',4])
140
sage: E.list()
141
[+++-, ++-+, +-++, -+++, +---, -+--, --+-, ---+]
142
sage: [x.signature() for x in E]
143
['+++-', '++-+', '+-++', '-+++', '+---', '-+--', '--+-', '---+']
144
145
TESTS::
146
147
sage: len(TensorProductOfCrystals(E,E,generators=[[E[0],E[0]]]).list())
148
35
149
sage: D = CrystalOfSpinsPlus(['D',4])
150
sage: len(TensorProductOfCrystals(D,E,generators=[[D.list()[0],E.list()[0]]]).list())
151
56
152
"""
153
ct = CartanType(ct)
154
if ct[0] == 'D':
155
return GenericCrystalOfSpins(ct, Spin_crystal_type_D_element, "minus")
156
else:
157
raise NotImplementedError
158
159
class GenericCrystalOfSpins(UniqueRepresentation, Parent):
160
"""
161
A generic crystal of spins.
162
"""
163
def __init__(self, ct, element_class, case):
164
"""
165
EXAMPLES::
166
167
sage: E = CrystalOfSpinsMinus(['D',4])
168
sage: TestSuite(E).run()
169
"""
170
self._cartan_type = CartanType(ct)
171
if case == "spins":
172
self.rename("The crystal of spins for type %s"%ct)
173
elif case == "plus":
174
self.rename("The plus crystal of spins for type %s"%ct)
175
else:
176
self.rename("The minus crystal of spins for type %s"%ct)
177
178
self.Element = element_class
179
# super(GenericCrystalOfSpins, self).__init__(category = FiniteEnumeratedSets())
180
Parent.__init__(self, category = ClassicalCrystals())
181
182
if case == "minus":
183
generator = [1]*(ct[1]-1)
184
generator.append(-1)
185
else:
186
generator = [1]*ct[1]
187
self.module_generators = (self._element_constructor_(tuple(generator)),)
188
self._list = list(self)
189
# self._digraph = ClassicalCrystal.digraph(self)
190
self._digraph = super(GenericCrystalOfSpins, self).digraph()
191
self._digraph_closure = self.digraph().transitive_closure()
192
193
def __call__(self, value):
194
"""
195
Parse input for ``cached_method``.
196
197
EXAMPLES::
198
199
sage: C = CrystalOfSpins(['B',3])
200
sage: C([1,1,1])
201
+++
202
"""
203
if value.__class__ == self.element_class and value.parent() == self:
204
return value
205
return self._element_constructor_(tuple(value))
206
207
@cached_method
208
def _element_constructor_(self, value):
209
"""
210
Construct an element of ``self`` from ``value``.
211
212
EXAMPLES::
213
214
sage: C = CrystalOfSpins(['B',3])
215
sage: C((1,1,1))
216
+++
217
"""
218
return self.element_class(self, value)
219
220
def list(self):
221
"""
222
Return a list of the elements of ``self``.
223
224
EXAMPLES::
225
226
sage: CrystalOfSpins(['B',3]).list()
227
[+++, ++-, +-+, -++, +--, -+-, --+, ---]
228
"""
229
return self._list
230
231
def digraph(self):
232
"""
233
Return the directed graph associated to ``self``.
234
235
EXAMPLES::
236
237
sage: CrystalOfSpins(['B',3]).digraph()
238
Digraph on 8 vertices
239
"""
240
return self._digraph
241
242
def lt_elements(self, x,y):
243
r"""
244
Return ``True`` if and only if there is a path from ``x`` to ``y``
245
in the crystal graph.
246
247
Because the crystal graph is classical, it is a directed acyclic
248
graph which can be interpreted as a poset. This function implements
249
the comparison function of this poset.
250
251
EXAMPLES::
252
253
sage: C = CrystalOfSpins(['B',3])
254
sage: x = C([1,1,1])
255
sage: y = C([-1,-1,-1])
256
sage: C.lt_elements(x,y)
257
True
258
sage: C.lt_elements(y,x)
259
False
260
sage: C.lt_elements(x,x)
261
False
262
"""
263
if x.parent() is not self or y.parent() is not self:
264
raise ValueError("Both elements must be in this crystal")
265
if self._digraph_closure.has_edge(x,y):
266
return True
267
return False
268
269
class Spin(LetterTuple):
270
"""
271
A spin letter in the crystal of spins.
272
273
EXAMPLES::
274
275
sage: C = CrystalOfSpins(['B',3])
276
sage: c = C([1,1,1])
277
sage: TestSuite(c).run()
278
279
sage: C([1,1,1]).parent()
280
The crystal of spins for type ['B', 3]
281
282
sage: c = C([1,1,1])
283
sage: c._repr_()
284
'+++'
285
286
sage: D = CrystalOfSpins(['B',4])
287
sage: a = C([1,1,1])
288
sage: b = C([-1,-1,-1])
289
sage: c = D([1,1,1,1])
290
sage: a == a
291
True
292
sage: a == b
293
False
294
sage: b == c
295
False
296
"""
297
def signature(self):
298
"""
299
Return the signature of ``self``.
300
301
EXAMPLES::
302
303
sage: C = CrystalOfSpins(['B',3])
304
sage: C([1,1,1]).signature()
305
'+++'
306
sage: C([1,1,-1]).signature()
307
'++-'
308
"""
309
sword = ""
310
for x in range(self.parent().cartan_type().n):
311
sword += "+" if self.value[x] == 1 else "-"
312
return sword
313
314
def _repr_(self):
315
"""
316
Represents the spin elements in terms of its signature.
317
318
EXAMPLES::
319
320
sage: C = CrystalOfSpins(['B',3])
321
sage: b = C([1,1,-1])
322
sage: b
323
++-
324
sage: b._repr_()
325
'++-'
326
"""
327
return self.signature()
328
329
def _latex_(self):
330
r"""
331
Gives the latex output of a spin column.
332
333
EXAMPLES::
334
335
sage: C = CrystalOfSpins(['B',3])
336
sage: b = C([1,1,-1])
337
sage: print b._latex_()
338
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
339
\raisebox{-.6ex}{$\begin{array}[b]{*{1}c}\cline{1-1}
340
\lr{-}\\\cline{1-1}
341
\lr{+}\\\cline{1-1}
342
\lr{+}\\\cline{1-1}
343
\end{array}$}
344
}
345
"""
346
return Tableau([[i] for i in reversed(self.signature())])._latex_()
347
348
def epsilon(self, i):
349
r"""
350
Return `\varepsilon_i` of ``self``.
351
352
EXAMPLES::
353
354
sage: C = CrystalOfSpins(['B',3])
355
sage: [[C[m].epsilon(i) for i in range(1,4)] for m in range(8)]
356
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0],
357
[0, 0, 1], [1, 0, 1], [0, 1, 0], [0, 0, 1]]
358
"""
359
if self.e(i) is None:
360
return 0
361
return 1
362
363
def phi(self, i):
364
r"""
365
Return `\varphi_i` of ``self``.
366
367
EXAMPLES::
368
369
sage: C = CrystalOfSpins(['B',3])
370
sage: [[C[m].phi(i) for i in range(1,4)] for m in range(8)]
371
[[0, 0, 1], [0, 1, 0], [1, 0, 1], [0, 0, 1],
372
[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]]
373
"""
374
if self.f(i) is None:
375
return 0
376
return 1
377
378
class Spin_crystal_type_B_element(Spin):
379
r"""
380
Type B spin representation crystal element
381
"""
382
def e(self, i):
383
r"""
384
Returns the action of `e_i` on self.
385
386
EXAMPLES::
387
388
sage: C = CrystalOfSpins(['B',3])
389
sage: [[C[m].e(i) for i in range(1,4)] for m in range(8)]
390
[[None, None, None], [None, None, +++], [None, ++-, None], [+-+, None, None],
391
[None, None, +-+], [+--, None, -++], [None, -+-, None], [None, None, --+]]
392
"""
393
assert i in self.index_set()
394
rank = self.parent().cartan_type().n
395
if i < rank:
396
if self.value[i-1] == -1 and self.value[i] == 1:
397
ret = [self.value[x] for x in range(rank)]
398
ret[i-1] = 1
399
ret[i] = -1
400
return self.parent()(ret)
401
elif i == rank:
402
if self.value[i-1] == -1:
403
ret = [self.value[x] for x in range(rank)]
404
ret[i-1] = 1
405
return self.parent()(ret)
406
else:
407
return None
408
409
def f(self, i):
410
r"""
411
Returns the action of `f_i` on self.
412
413
EXAMPLES::
414
415
sage: C = CrystalOfSpins(['B',3])
416
sage: [[C[m].f(i) for i in range(1,4)] for m in range(8)]
417
[[None, None, ++-], [None, +-+, None], [-++, None, +--], [None, None, -+-],
418
[-+-, None, None], [None, --+, None], [None, None, ---], [None, None, None]]
419
"""
420
assert i in self.index_set()
421
rank = self.parent().cartan_type().n
422
if i < rank:
423
if self.value[i-1] == 1 and self.value[i] == -1:
424
ret = [self.value[x] for x in range(rank)]
425
ret[i-1] = -1
426
ret[i] = 1
427
return self.parent()(ret)
428
elif i == rank:
429
if self.value[i-1] == 1:
430
ret = [self.value[x] for x in range(rank)]
431
ret[i-1] = -1
432
return self.parent()(ret)
433
else:
434
return None
435
436
class Spin_crystal_type_D_element(Spin):
437
r"""
438
Type D spin representation crystal element
439
"""
440
def e(self, i):
441
r"""
442
Returns the action of `e_i` on self.
443
444
EXAMPLES::
445
446
sage: D = CrystalOfSpinsPlus(['D',4])
447
sage: [[D.list()[m].e(i) for i in range(1,4)] for m in range(8)]
448
[[None, None, None], [None, None, None], [None, ++--, None], [+-+-, None, None],
449
[None, None, +-+-], [+--+, None, -++-], [None, -+-+, None], [None, None, None]]
450
451
::
452
453
sage: E = CrystalOfSpinsMinus(['D',4])
454
sage: [[E[m].e(i) for i in range(1,4)] for m in range(8)]
455
[[None, None, None], [None, None, +++-], [None, ++-+, None], [+-++, None, None],
456
[None, None, None], [+---, None, None], [None, -+--, None], [None, None, --+-]]
457
"""
458
assert i in self.index_set()
459
rank = self.parent().cartan_type().n
460
if i < rank:
461
if self.value[i-1] == -1 and self.value[i] == 1:
462
ret = [self.value[x] for x in range(rank)]
463
ret[i-1] = 1
464
ret[i] = -1
465
return self.parent()(ret)
466
elif i == rank:
467
if self.value[i-2] == -1 and self.value[i-1] == -1:
468
ret = [self.value[x] for x in range(rank)]
469
ret[i-2] = 1
470
ret[i-1] = 1
471
return self.parent()(ret)
472
else:
473
return None
474
475
def f(self, i):
476
r"""
477
Returns the action of `f_i` on self.
478
479
EXAMPLES::
480
481
sage: D = CrystalOfSpinsPlus(['D',4])
482
sage: [[D.list()[m].f(i) for i in range(1,4)] for m in range(8)]
483
[[None, None, None], [None, +-+-, None], [-++-, None, +--+], [None, None, -+-+],
484
[-+-+, None, None], [None, --++, None], [None, None, None], [None, None, None]]
485
486
::
487
488
sage: E = CrystalOfSpinsMinus(['D',4])
489
sage: [[E[m].f(i) for i in range(1,4)] for m in range(8)]
490
[[None, None, ++-+], [None, +-++, None], [-+++, None, None], [None, None, None],
491
[-+--, None, None], [None, --+-, None], [None, None, ---+], [None, None, None]]
492
"""
493
assert i in self.index_set()
494
rank = self.parent().cartan_type().n
495
if i < rank:
496
if self.value[i-1] == 1 and self.value[i] == -1:
497
ret = [self.value[x] for x in range(rank)]
498
ret[i-1] = -1
499
ret[i] = 1
500
return self.parent()(ret)
501
elif i == rank:
502
if self.value[i-2] == 1 and self.value[i-1] == 1:
503
ret = [self.value[x] for x in range(rank)]
504
ret[i-2] = -1
505
ret[i-1] = -1
506
return self.parent()(ret)
507
else:
508
return None
509
510