Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/combinat/crystals/fast_crystals.py
4096 views
1
r"""
2
Fast Rank Two Crystals
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2007 Anne Schilling <anne at math.ucdavis.edu>
6
# Nicolas Thiery <nthiery at users.sf.net>
7
# Ben Brubaker <brubaker at math.mit.edu>
8
# Daniel Bump <bump at match.stanford.edu>
9
# Justin Walker <justin at mac.com>
10
#
11
# Distributed under the terms of the GNU General Public License (GPL)
12
#
13
# This code is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
# General Public License for more details.
17
#
18
# The full text of the GPL is available at:
19
#
20
# http://www.gnu.org/licenses/
21
#****************************************************************************
22
23
from sage.structure.unique_representation import UniqueRepresentation
24
from sage.structure.parent import Parent
25
from sage.categories.classical_crystals import ClassicalCrystals
26
from sage.structure.element import Element, parent
27
from sage.combinat.root_system.cartan_type import CartanType
28
29
30
class FastCrystal(UniqueRepresentation, Parent):
31
"""
32
An alternative implementation of rank 2 crystals. The root
33
operators are implemented in memory by table lookup. This means
34
that in comparison with the CrystalsOfTableaux, these crystals
35
are slow to instantiate but faster for computation. Implemented for
36
types A2, B2 and C2.
37
38
Input: CartanType and a shape. The CartanType is ['A',2], ['B',2]
39
or ['C',2]. The shape is of the form [l1,l2] where l1 and l2 are
40
either integers or (in type B) half integers such that l1-l2 is
41
integral. It is assumed that l1 >= l2 >= 0. If l1 and l2 are
42
integers, this will produce the a crystal isomorphic to the one
43
obtained by CrystalOfTableaux(type, shape=[l1,l2]). Furthermore
44
FastCrystal(['B', 2], l1+1/2, l2+1/2) produces a crystal isomorphic
45
to the following crystal T::
46
47
C = CrystalOfTableaux(['B',2], shape=[l1,l2])
48
D = CrystalOfSpins(['B',2])
49
T = TensorProductOfCrystals(C,D,C.list()[0],D.list()[0])
50
51
The representation of elements is in term of the
52
Berenstein-Zelevinsky-Littelmann strings [a1, a2, ...] described
53
under metapost in crystals.py. Alternative representations may be
54
obtained by the options format="dual_string" or format="simple".
55
In the simple format, the element is represented by and integer,
56
and in the dual_string format, it is represented by the
57
Berenstein-Zelevinsky-Littelmann string, but the underlying
58
decomposition of the long Weyl group element into simple
59
reflections is changed.
60
61
TESTS::
62
63
sage: C = FastCrystal(['A',2],shape=[4,1])
64
sage: C.cardinality()
65
24
66
sage: C.cartan_type()
67
['A', 2]
68
sage: TestSuite(C).run()
69
sage: C = FastCrystal(['B',2],shape=[4,1])
70
sage: C.cardinality()
71
154
72
sage: TestSuite(C).run()
73
sage: C = FastCrystal(['B',2],shape=[3/2,1/2])
74
sage: C.cardinality()
75
16
76
sage: TestSuite(C).run()
77
sage: C = FastCrystal(['C',2],shape=[2,1])
78
sage: C.cardinality()
79
16
80
sage: C = FastCrystal(['C',2],shape=[3,1])
81
sage: C.cardinality()
82
35
83
sage: TestSuite(C).run()
84
"""
85
86
@staticmethod
87
def __classcall__(cls, cartan_type, shape, format = "string"):
88
"""
89
Normalizes the input arguments to ensure unique representation
90
91
EXAMPLES::
92
93
sage: C1 = FastCrystal(['A',2], shape=(4,1))
94
sage: C2 = FastCrystal(CartanType(['A',2]),shape=[4,1])
95
sage: C1 is C2
96
True
97
"""
98
cartan_type = CartanType(cartan_type)
99
shape = tuple(shape)
100
if len(shape) > 2:
101
raise ValueError, "The shape must have length <=2"
102
shape = shape + (0,)*(2-len(shape))
103
return super(FastCrystal, cls).__classcall__(cls, cartan_type, shape, format)
104
105
def __init__(self, ct, shape, format):
106
"""
107
EXAMPLES::
108
109
sage: C = FastCrystal(['A',2],shape=[4,1]); C
110
The fast crystal for A2 with shape [4,1]
111
sage: TestSuite(C).run()
112
"""
113
Parent.__init__(self, category = ClassicalCrystals())
114
# super(FastCrystal, self).__init__(category = FiniteEnumeratedSets())
115
self._cartan_type = ct
116
if ct[1] != 2:
117
raise NotImplementedError
118
119
l1 = shape[0]
120
l2 = shape[1]
121
122
# For safety, delpat and gampat should be immutable
123
124
self.delpat = []
125
self.gampat = []
126
127
if ct[0] == 'A':
128
self._type_a_init(l1, l2)
129
elif ct[0] == 'B' or ct[0] == 'C':
130
self._type_bc_init(l1, l2)
131
else:
132
raise NotImplementedError
133
134
self.format = format
135
self.size = len(self.delpat)
136
self._rootoperators = []
137
self.shape = shape
138
139
for i in range(self.size):
140
target = [x for x in self.delpat[i]]
141
142
target[0] = target[0]-1
143
e1 = None if target not in self.delpat else self.delpat.index(target)
144
target[0] = target[0]+1+1
145
f1 = None if target not in self.delpat else self.delpat.index(target)
146
147
target = [x for x in self.gampat[i]]
148
target[0] = target[0]-1
149
e2 = None if target not in self.gampat else self.gampat.index(target)
150
target[0] = target[0]+1+1
151
f2 = None if target not in self.gampat else self.gampat.index(target)
152
153
self._rootoperators.append([e1,f1,e2,f2])
154
155
if int(2*l1)%2 == 0:
156
l1_str = "%d"%l1
157
l2_str = "%d"%l2
158
else:
159
assert self._cartan_type[0] == 'B' and int(2*l2)%2 == 1
160
l1_str = "%d/2"%int(2*l1)
161
l2_str = "%d/2"%int(2*l2)
162
self.rename("The fast crystal for %s2 with shape [%s,%s]"%(ct[0],l1_str,l2_str))
163
self.module_generators = [self(0)]
164
# self._list = ClassicalCrystal.list(self)
165
self._list = super(FastCrystal, self).list()
166
# self._digraph = ClassicalCrystal.digraph(self)
167
self._digraph = super(FastCrystal, self).digraph()
168
self._digraph_closure = self.digraph().transitive_closure()
169
170
def _type_a_init(self, l1, l2):
171
"""
172
EXAMPLES::
173
174
sage: C = FastCrystal(['A',2],shape=[1,1])
175
sage: C.delpat # indirect doctest
176
[[0, 0, 0], [0, 1, 0], [1, 1, 0]]
177
sage: C.gampat
178
[[0, 0, 0], [1, 0, 0], [0, 1, 1]]
179
"""
180
for b in range(l2,-1,-1):
181
for a in range(l1,l2-1,-1):
182
for c in range(a,b-1,-1):
183
a3 = l1-a
184
a2 = l1+l2-a-b
185
a1 = a-c
186
b1 = max(a3,a2-a1)
187
b2 = a1+a3
188
b3 = min(a2-a3,a1)
189
self.delpat.append([a1,a2,a3])
190
self.gampat.append([b1,b2,b3])
191
192
def _type_bc_init(self, l1, l2):
193
"""
194
EXAMPLES::
195
196
sage: C = FastCrystal(['B',2],shape=[1])
197
sage: len(C.delpat) # indirect doctest
198
5
199
sage: len(C.gampat)
200
5
201
sage: C = FastCrystal(['C',2],shape=[1])
202
sage: len(C.delpat)
203
4
204
sage: len(C.gampat)
205
4
206
"""
207
if self._cartan_type[0] == 'B':
208
[m1, m2] = [l1+l2, l1-l2]
209
else:
210
[m1, m2] = [l1, l2]
211
for b in range(m2,-1,-1):
212
for a in range(m1,m2-1,-1):
213
for c in range(b,a+1):
214
for d in range(c,-1,-1):
215
a1 = c-d
216
a2 = m1+m2+c-a-2*b
217
a3 = m1+m2-a-b
218
a4 = m1-a
219
b1 = max(a4,2*a3-a2,a2-2*a1)
220
b2 = max(a3, a1+a4, a1+2*a3-a2)
221
b3 = min(a2, 2*a2-2*a3+a4, 2*a1+a4)
222
b4 = min(a1, a2-a3, a3-a4)
223
if self._cartan_type[0] == 'B':
224
self.delpat.append([a1,a2,a3,a4])
225
self.gampat.append([b1,b2,b3,b4])
226
else:
227
self.gampat.append([a1,a2,a3,a4])
228
self.delpat.append([b1,b2,b3,b4])
229
230
def __call__(self, value):
231
"""
232
EXAMPLES::
233
234
sage: C = FastCrystal(['A',2],shape=[2,1])
235
sage: C(0)
236
[0, 0, 0]
237
sage: C(1)
238
[1, 0, 0]
239
sage: x = C(0)
240
sage: C(x) is x
241
True
242
"""
243
if parent(value) is self: return value
244
return self.element_class(self, value, self.format)
245
246
def list(self):
247
"""
248
Returns a list of the elements of self.
249
250
EXAMPLES::
251
252
sage: C = FastCrystal(['A',2],shape=[2,1])
253
sage: C.list()
254
[[0, 0, 0],
255
[1, 0, 0],
256
[0, 1, 1],
257
[0, 2, 1],
258
[1, 2, 1],
259
[0, 1, 0],
260
[1, 1, 0],
261
[2, 1, 0]]
262
"""
263
return self._list
264
265
def digraph(self):
266
"""
267
Returns the digraph associated to self.
268
269
EXAMPLES::
270
271
sage: C = FastCrystal(['A',2],shape=[2,1])
272
sage: C.digraph()
273
Digraph on 8 vertices
274
"""
275
return self._digraph
276
277
def cmp_elements(self, x,y):
278
r"""
279
Returns True if and only if there is a path from x to y in the
280
crystal graph.
281
282
Because the crystal graph is classical, it is a directed acyclic
283
graph which can be interpreted as a poset. This function implements
284
the comparison function of this poset.
285
286
EXAMPLES::
287
288
sage: C = FastCrystal(['A',2],shape=[2,1])
289
sage: x = C(0)
290
sage: y = C(1)
291
sage: C.cmp_elements(x,y)
292
-1
293
sage: C.cmp_elements(y,x)
294
1
295
sage: C.cmp_elements(x,x)
296
0
297
"""
298
assert x.parent() == self and y.parent() == self
299
if self._digraph_closure.has_edge(x,y):
300
return -1
301
elif self._digraph_closure.has_edge(y,x):
302
return 1
303
else:
304
return 0
305
306
class Element(Element):
307
def __init__(self, parent, value, format):
308
"""
309
EXAMPLES::
310
311
sage: C = FastCrystal(['A',2],shape=[2,1])
312
sage: c = C(0); c
313
[0, 0, 0]
314
sage: C[0].parent()
315
The fast crystal for A2 with shape [2,1]
316
sage: TestSuite(c).run()
317
"""
318
Element.__init__(self, parent)
319
self.value = value
320
self.format = format
321
322
def weight(self):
323
"""
324
Returns the weight of self.
325
326
EXAMPLES::
327
328
sage: [v.weight() for v in FastCrystal(['A',2], shape=[2,1])]
329
[(2, 1, 0), (1, 2, 0), (1, 1, 1), (1, 0, 2), (0, 1, 2), (2, 0, 1), (1, 1, 1), (0, 2, 1)]
330
sage: [v.weight() for v in FastCrystal(['B',2], shape=[1,0])]
331
[(1, 0), (0, 1), (0, 0), (0, -1), (-1, 0)]
332
sage: [v.weight() for v in FastCrystal(['B',2], shape=[1/2,1/2])]
333
[(1/2, 1/2), (1/2, -1/2), (-1/2, 1/2), (-1/2, -1/2)]
334
sage: [v.weight() for v in FastCrystal(['C',2], shape=[1,0])]
335
[(1, 0), (0, 1), (0, -1), (-1, 0)]
336
sage: [v.weight() for v in FastCrystal(['C',2], shape=[1,1])]
337
[(1, 1), (1, -1), (0, 0), (-1, 1), (-1, -1)]
338
"""
339
delpat = self.parent().delpat[self.value]
340
if self.parent()._cartan_type[0] == 'A':
341
delpat = delpat + [0,]
342
[alpha1, alpha2] = self.parent().weight_lattice_realization().simple_roots()
343
hwv = sum(self.parent().shape[i]*self.parent().weight_lattice_realization().monomial(i) for i in range(2))
344
return hwv - (delpat[0]+delpat[2])*alpha1 - (delpat[1]+delpat[3])*alpha2
345
346
def _repr_(self):
347
"""
348
EXAMPLES::
349
350
sage: C = FastCrystal(['A',2],shape=[2,1])
351
sage: C[0]._repr_()
352
'[0, 0, 0]'
353
"""
354
if self.format == "string":
355
return repr(self.parent().delpat[self.value])
356
elif self.format == "dual_string":
357
return repr(self.parent().gampat[self.value])
358
elif self.format == "simple":
359
return repr(self.value)
360
else:
361
raise NotImplementedError
362
363
def __eq__(self, other):
364
"""
365
EXAMPLES::
366
367
sage: C = FastCrystal(['A',2],shape=[2,1])
368
sage: D = FastCrystal(['B',2],shape=[2,1])
369
sage: C(0) == C(0)
370
True
371
sage: C(1) == C(0)
372
False
373
sage: C(0) == D(0)
374
False
375
"""
376
return self.__class__ is other.__class__ and \
377
self.parent() == other.parent() and \
378
self.value == other.value
379
380
def __ne__(self, other):
381
"""
382
EXAMPLES::
383
384
sage: C = FastCrystal(['A',2],shape=[2,1])
385
sage: D = FastCrystal(['B',2],shape=[2,1])
386
sage: C(0) != C(0)
387
False
388
sage: C(1) != C(0)
389
True
390
sage: C(0) != D(0)
391
True
392
"""
393
return not self == other
394
395
396
def __cmp__(self, other):
397
"""
398
EXAMPLES::
399
400
sage: C = FastCrystal(['A',2],shape=[2,1])
401
sage: C(1) < C(2)
402
True
403
sage: C(2) < C(1)
404
False
405
sage: C(2) > C(1)
406
True
407
sage: C(1) <= C(1)
408
True
409
"""
410
if type(self) is not type(other):
411
return cmp(type(self), type(other))
412
if self.parent() != other.parent():
413
return cmp(self.parent(), other.parent())
414
return self.parent().cmp_elements(self, other)
415
416
def e(self, i):
417
"""
418
Returns the action of `e_i` on self.
419
420
EXAMPLES::
421
422
sage: C = FastCrystal(['A',2],shape=[2,1])
423
sage: C(1).e(1)
424
[0, 0, 0]
425
sage: C(0).e(1) is None
426
True
427
"""
428
assert i in self.index_set()
429
if i == 1:
430
r = self.parent()._rootoperators[self.value][0]
431
else:
432
r = self.parent()._rootoperators[self.value][2]
433
return self.parent()(r) if r is not None else None
434
435
436
def f(self, i):
437
"""
438
Returns the action of `f_i` on self.
439
440
EXAMPLES::
441
442
sage: C = FastCrystal(['A',2],shape=[2,1])
443
sage: C(6).f(1)
444
[1, 2, 1]
445
sage: C(7).f(1) is None
446
True
447
"""
448
assert i in self.index_set()
449
if i == 1:
450
r = self.parent()._rootoperators[self.value][1]
451
else:
452
r = self.parent()._rootoperators[self.value][3]
453
return self.parent()(r) if r is not None else None
454
455
456
#FastCrystal.Element = FastCrystalElement
457
458