Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/combinat/crystals/spins.py
4079 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
+/-. Two other representations are available as attributes
12
internal_repn and 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.structure.unique_representation import UniqueRepresentation
40
from sage.structure.parent import Parent
41
from sage.categories.classical_crystals import ClassicalCrystals
42
from sage.combinat.crystals.letters import Letter
43
from sage.combinat.root_system.cartan_type import CartanType
44
from sage.combinat.tableau import Tableau
45
46
47
#########################
48
# Type B spin
49
#########################
50
51
def CrystalOfSpins(ct):
52
r"""
53
Return the spin crystal of the given type B.
54
55
This is a combinatorial model for the crystal with highest weight
56
`Lambda_n` (the n-th fundamental weight). It has
57
`2^n` elements, here called Spins. See also
58
CrystalOfLetters, CrystalOfSpinsPlus and CrystalOfSpinsMinus.
59
60
INPUT:
61
62
63
- ``['B',n]`` - A CartanType of type B.
64
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
104
- ``['D',n]`` - A CartanType of type D.
105
106
107
EXAMPLES::
108
109
sage: D = CrystalOfSpinsPlus(['D',4])
110
sage: D.list()
111
[++++, ++--, +-+-, -++-, +--+, -+-+, --++, ----]
112
113
::
114
115
sage: [x.signature() for x in D]
116
['++++', '++--', '+-+-', '-++-', '+--+', '-+-+', '--++', '----']
117
118
TESTS::
119
120
sage: TestSuite(D).run()
121
"""
122
ct = CartanType(ct)
123
if ct[0] == 'D':
124
return GenericCrystalOfSpins(ct, Spin_crystal_type_D_element, "plus")
125
else:
126
raise NotImplementedError
127
128
def CrystalOfSpinsMinus(ct):
129
r"""
130
Return the minus spin crystal of the given type D.
131
132
This is the crystal with highest weight `Lambda_{n-1}`
133
(the (n-1)-st fundamental weight).
134
135
INPUT:
136
137
138
- ``['D',n]`` - A CartanType of type D.
139
140
141
EXAMPLES::
142
143
sage: E = CrystalOfSpinsMinus(['D',4])
144
sage: E.list()
145
[+++-, ++-+, +-++, -+++, +---, -+--, --+-, ---+]
146
sage: [x.signature() for x in E]
147
['+++-', '++-+', '+-++', '-+++', '+---', '-+--', '--+-', '---+']
148
149
TESTS::
150
151
sage: len(TensorProductOfCrystals(E,E,generators=[[E[0],E[0]]]).list())
152
35
153
sage: D = CrystalOfSpinsPlus(['D',4])
154
sage: len(TensorProductOfCrystals(D,E,generators=[[D.list()[0],E.list()[0]]]).list())
155
56
156
"""
157
ct = CartanType(ct)
158
if ct[0] == 'D':
159
return GenericCrystalOfSpins(ct, Spin_crystal_type_D_element, "minus")
160
else:
161
raise NotImplementedError
162
163
class GenericCrystalOfSpins(UniqueRepresentation, Parent):
164
def __init__(self, ct, element_class, case):
165
"""
166
EXAMPLES::
167
168
sage: E = CrystalOfSpinsMinus(['D',4])
169
sage: TestSuite(E).run()
170
"""
171
self._cartan_type = CartanType(ct)
172
if case == "spins":
173
self.rename("The crystal of spins for type %s"%ct)
174
elif case == "plus":
175
self.rename("The plus crystal of spins for type %s"%ct)
176
else:
177
self.rename("The minus crystal of spins for type %s"%ct)
178
179
self.Element = element_class
180
# super(GenericCrystalOfSpins, self).__init__(category = FiniteEnumeratedSets())
181
Parent.__init__(self, category = ClassicalCrystals())
182
183
if case == "minus":
184
generator = [1]*(ct[1]-1)
185
generator.append(-1)
186
else:
187
generator = [1]*ct[1]
188
self.module_generators = [self(generator)]
189
self._list = list(self)
190
# self._digraph = ClassicalCrystal.digraph(self)
191
self._digraph = super(GenericCrystalOfSpins, self).digraph()
192
self._digraph_closure = self.digraph().transitive_closure()
193
194
def __call__(self, value):
195
"""
196
EXAMPLES::
197
198
sage: C = CrystalOfSpins(['B',3])
199
sage: C([1,1,1])
200
+++
201
"""
202
if value.__class__ == self.element_class and value.parent() == self:
203
return value
204
else:
205
return self.element_class(self, value)
206
207
def list(self):
208
"""
209
Returns a list of the elements of self.
210
211
EXAMPLES::
212
213
sage: CrystalOfSpins(['B',3]).list()
214
[+++, ++-, +-+, -++, +--, -+-, --+, ---]
215
"""
216
return self._list
217
218
def digraph(self):
219
"""
220
Returns the directed graph associated to self.
221
222
EXAMPLES::
223
224
sage: CrystalOfSpins(['B',3]).digraph()
225
Digraph on 8 vertices
226
"""
227
return self._digraph
228
229
def lt_elements(self, x,y):
230
r"""
231
Returns True if and only if there is a path from x to y in the
232
crystal graph.
233
234
Because the crystal graph is classical, it is a directed acyclic
235
graph which can be interpreted as a poset. This function implements
236
the comparison function of this poset.
237
238
EXAMPLES::
239
240
sage: C = CrystalOfSpins(['B',3])
241
sage: x = C([1,1,1])
242
sage: y = C([-1,-1,-1])
243
sage: C.lt_elements(x,y)
244
True
245
sage: C.lt_elements(y,x)
246
False
247
sage: C.lt_elements(x,x)
248
False
249
"""
250
assert x.parent() == self and y.parent() == self
251
if self._digraph_closure.has_edge(x,y):
252
return True
253
return False
254
255
class Spin(Letter):
256
"""
257
EXAMPLES::
258
259
sage: C = CrystalOfSpins(['B',3])
260
sage: c = C([1,1,1])
261
sage: TestSuite(c).run()
262
263
sage: C([1,1,1]).parent()
264
The crystal of spins for type ['B', 3]
265
266
sage: c = C([1,1,1])
267
sage: c._repr_()
268
'+++'
269
270
sage: D = CrystalOfSpins(['B',4])
271
sage: a = C([1,1,1])
272
sage: b = C([-1,-1,-1])
273
sage: c = D([1,1,1,1])
274
sage: a == a
275
True
276
sage: a == b
277
False
278
sage: b == c
279
False
280
"""
281
282
def __hash__(self):
283
"""
284
EXAMPLES::
285
286
sage: C = CrystalOfSpins(['B',3])
287
sage: c = C([1,1,1])
288
sage: type(hash(c))
289
<type 'int'>
290
"""
291
292
return hash(tuple(self.value))
293
294
def signature(self):
295
"""
296
Returns the signature of self.
297
298
EXAMPLES::
299
300
sage: C = CrystalOfSpins(['B',3])
301
sage: C([1,1,1]).signature()
302
'+++'
303
sage: C([1,1,-1]).signature()
304
'++-'
305
"""
306
sword = ""
307
for x in range(self.parent().cartan_type().n):
308
sword += "+" if self.value[x] == 1 else "-"
309
return sword
310
311
def _repr_(self):
312
"""
313
Represents the spin elements in terms of its signature.
314
315
EXAMPLES::
316
317
sage: C = CrystalOfSpins(['B',3])
318
sage: b = C([1,1,-1])
319
sage: b
320
++-
321
sage: b._repr_()
322
'++-'
323
"""
324
return self.signature()
325
326
def _latex_(self):
327
"""
328
Gives the latex output of a spin column.
329
330
EXAMPLES::
331
332
sage: C = CrystalOfSpins(['B',3])
333
sage: b = C([1,1,-1])
334
sage: b._latex_()
335
'{\\def\\lr#1{\\multicolumn{1}{|@{\\hspace{.6ex}}c@{\\hspace{.6ex}}|}{\\raisebox{-.3ex}{$#1$}}}\n\\raisebox{-.6ex}{$\\begin{array}[b]{c}\n\\cline{1-1}\n\\lr{-}\\\\\n\\cline{1-1}\n\\lr{+}\\\\\n\\cline{1-1}\n\\lr{+}\\\\\n\\cline{1-1}\n\\end{array}$}\n}'
336
"""
337
return Tableau([[i] for i in reversed(self.signature())])._latex_()
338
339
340
class Spin_crystal_type_B_element(Spin):
341
r"""
342
Type B spin representation crystal element
343
"""
344
def e(self, i):
345
r"""
346
Returns the action of `e_i` on self.
347
348
EXAMPLES::
349
350
sage: C = CrystalOfSpins(['B',3])
351
sage: [[C[m].e(i) for i in range(1,4)] for m in range(8)]
352
[[None, None, None], [None, None, +++], [None, ++-, None], [+-+, None, None],
353
[None, None, +-+], [+--, None, -++], [None, -+-, None], [None, None, --+]]
354
"""
355
assert i in self.index_set()
356
rank = self.parent().cartan_type().n
357
if i < rank:
358
if self.value[i-1] == -1 and self.value[i] == 1:
359
ret = [self.value[x] for x in range(rank)]
360
ret[i-1] = 1
361
ret[i] = -1
362
return self.parent()(ret)
363
elif i == rank:
364
if self.value[i-1] == -1:
365
ret = [self.value[x] for x in range(rank)]
366
ret[i-1] = 1
367
return self.parent()(ret)
368
else:
369
return None
370
371
def f(self, i):
372
r"""
373
Returns the action of `f_i` on self.
374
375
EXAMPLES::
376
377
sage: C = CrystalOfSpins(['B',3])
378
sage: [[C[m].f(i) for i in range(1,4)] for m in range(8)]
379
[[None, None, ++-], [None, +-+, None], [-++, None, +--], [None, None, -+-],
380
[-+-, None, None], [None, --+, None], [None, None, ---], [None, None, None]]
381
"""
382
assert i in self.index_set()
383
rank = self.parent().cartan_type().n
384
if i < rank:
385
if self.value[i-1] == 1 and self.value[i] == -1:
386
ret = [self.value[x] for x in range(rank)]
387
ret[i-1] = -1
388
ret[i] = 1
389
return self.parent()(ret)
390
elif i == rank:
391
if self.value[i-1] == 1:
392
ret = [self.value[x] for x in range(rank)]
393
ret[i-1] = -1
394
return self.parent()(ret)
395
else:
396
return None
397
398
class Spin_crystal_type_D_element(Spin):
399
r"""
400
Type D spin representation crystal element
401
"""
402
def e(self, i):
403
r"""
404
Returns the action of `e_i` on self.
405
406
EXAMPLES::
407
408
sage: D = CrystalOfSpinsPlus(['D',4])
409
sage: [[D.list()[m].e(i) for i in range(1,4)] for m in range(8)]
410
[[None, None, None], [None, None, None], [None, ++--, None], [+-+-, None, None],
411
[None, None, +-+-], [+--+, None, -++-], [None, -+-+, None], [None, None, None]]
412
413
::
414
415
sage: E = CrystalOfSpinsMinus(['D',4])
416
sage: [[E[m].e(i) for i in range(1,4)] for m in range(8)]
417
[[None, None, 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-2] == -1 and self.value[i-1] == -1:
430
ret = [self.value[x] for x in range(rank)]
431
ret[i-2] = 1
432
ret[i-1] = 1
433
return self.parent()(ret)
434
else:
435
return None
436
437
def f(self, i):
438
r"""
439
Returns the action of `f_i` on self.
440
441
EXAMPLES::
442
443
sage: D = CrystalOfSpinsPlus(['D',4])
444
sage: [[D.list()[m].f(i) for i in range(1,4)] for m in range(8)]
445
[[None, None, None], [None, +-+-, None], [-++-, None, +--+], [None, None, -+-+],
446
[-+-+, None, None], [None, --++, None], [None, None, None], [None, None, None]]
447
448
::
449
450
sage: E = CrystalOfSpinsMinus(['D',4])
451
sage: [[E[m].f(i) for i in range(1,4)] for m in range(8)]
452
[[None, None, ++-+], [None, +-++, None], [-+++, None, None], [None, None, None],
453
[-+--, None, None], [None, --+-, None], [None, None, ---+], [None, None, None]]
454
"""
455
assert i in self.index_set()
456
rank = self.parent().cartan_type().n
457
if i < rank:
458
if self.value[i-1] == 1 and self.value[i] == -1:
459
ret = [self.value[x] for x in range(rank)]
460
ret[i-1] = -1
461
ret[i] = 1
462
return self.parent()(ret)
463
elif i == rank:
464
if self.value[i-2] == 1 and self.value[i-1] == 1:
465
ret = [self.value[x] for x in range(rank)]
466
ret[i-2] = -1
467
ret[i-1] = -1
468
return self.parent()(ret)
469
else:
470
return None
471
472