Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/combinat/core.py
4045 views
1
"""
2
Cores
3
4
A `k`-core is a partition from which no rim hook of size `k` can be removed.
5
Alternatively, a `k`-core is an integer partition such that the Ferrers
6
diagram for the partition contains no cells with a hook of size (a
7
multiple of) `k`.
8
9
Authors:
10
11
- Anne Schilling and Mike Zabrocki (2011): initial version
12
- Travis Scrimshaw (2012): Added latex output for Core class
13
"""
14
#*****************************************************************************
15
# Copyright (C) 2011 Anne Schilling <anne at math.ucdavis.edu>
16
# Mike Zabrocki <zabrocki at mathstat.yorku.ca>
17
#
18
# Distributed under the terms of the GNU General Public License (GPL)
19
#
20
# This code is distributed in the hope that it will be useful,
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
# General Public License for more details.
24
#
25
# The full text of the GPL is available at:
26
#
27
# http://www.gnu.org/licenses/
28
#****************************************************************************
29
30
from sage.misc.classcall_metaclass import ClasscallMetaclass
31
from sage.structure.unique_representation import UniqueRepresentation
32
from sage.structure.parent import Parent
33
from sage.structure.element import Element
34
from sage.combinat.partition import Partitions, Partition
35
from sage.combinat.combinat import CombinatorialObject
36
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
37
from sage.functions.other import floor
38
39
class Core(CombinatorialObject, Element):
40
r"""
41
A `k`-core is an integer partition from which no rim hook of size `k`
42
can be removed.
43
44
EXAMPLES::
45
46
sage: c = Core([2,1],4); c
47
[2, 1]
48
sage: c = Core([3,1],4); c
49
Traceback (most recent call last):
50
...
51
ValueError: [3, 1] is not a 4-core
52
"""
53
54
__metaclass__ = ClasscallMetaclass
55
56
@staticmethod
57
def __classcall_private__(cls, part, k):
58
r"""
59
Implements the shortcut ``Core(part, k)`` to ``Cores(k,l)(part)``
60
where `l` is the length of the core.
61
62
TESTS::
63
64
sage: c = Core([2,1],4); c
65
[2, 1]
66
sage: c.parent()
67
4-Cores of length 3
68
sage: type(c)
69
<class 'sage.combinat.core.Cores_length_with_category.element_class'>
70
71
sage: Core([2,1],3)
72
Traceback (most recent call last):
73
...
74
ValueError: [2, 1] is not a 3-core
75
"""
76
if isinstance(part, cls):
77
return part
78
part = Partition(part)
79
if not part.is_core(k):
80
raise ValueError, "%s is not a %s-core"%(part, k)
81
l = sum(part.k_boundary(k).row_lengths())
82
return Cores(k, l)(part)
83
84
def __init__(self, core, parent):
85
"""
86
TESTS::
87
88
sage: C = Cores(4,3)
89
sage: c = C([2,1]); c
90
[2, 1]
91
sage: type(c)
92
<class 'sage.combinat.core.Cores_length_with_category.element_class'>
93
sage: c.parent()
94
4-Cores of length 3
95
sage: TestSuite(c).run()
96
97
sage: C = Cores(3,3)
98
sage: C([2,1])
99
Traceback (most recent call last):
100
...
101
ValueError: [2, 1] is not a 3-core
102
"""
103
k = parent.k
104
part = Partition(core)
105
if not part.is_core(k):
106
raise ValueError, "%s is not a %s-core"%(part, k)
107
CombinatorialObject.__init__(self, core)
108
Element.__init__(self, parent)
109
110
def _latex_(self):
111
"""
112
Outputs the LaTeX representation of this core using its Ferrers diagram.
113
114
EXAMPLES::
115
116
sage: c = Core([2,1],4)
117
sage: latex(c)
118
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
119
\raisebox{-.6ex}{$\begin{array}[b]{cc}
120
\cline{1-1}\cline{2-2}
121
\lr{\phantom{x}}&\lr{\phantom{x}}\\
122
\cline{1-1}\cline{2-2}
123
\lr{\phantom{x}}\\
124
\cline{1-1}
125
\end{array}$}
126
}
127
"""
128
return self.to_partition()._latex_()
129
130
def k(self):
131
r"""
132
Returns `k` of the `k`-core ``self``.
133
134
EXAMPLES::
135
136
sage: c = Core([2,1],4)
137
sage: c.k()
138
4
139
"""
140
return self.parent().k
141
142
def to_partition(self):
143
r"""
144
Turns the core ``self`` into the partition identical to ``self``.
145
146
EXAMPLES::
147
148
sage: mu = Core([2,1,1],3)
149
sage: mu.to_partition()
150
[2, 1, 1]
151
"""
152
return Partition(self)
153
154
def to_bounded_partition(self):
155
r"""
156
Bijection between `k`-cores and `(k-1)`-bounded partitions.
157
158
Maps the `k`-core ``self`` to the corresponding `(k-1)`-bounded partition.
159
This bijection is achieved by deleting all cells in ``self`` of hook length
160
greater than `k`.
161
162
EXAMPLES::
163
164
sage: gamma = Core([9,5,3,2,1,1], 5)
165
sage: gamma.to_bounded_partition()
166
[4, 3, 2, 2, 1, 1]
167
"""
168
k_boundary = self.to_partition().k_boundary(self.k())
169
return Partition(k_boundary.row_lengths())
170
171
def size(self):
172
r"""
173
Returns the size of ``self`` as a partition.
174
175
EXAMPLES::
176
177
sage: Core([2,1],4).size()
178
3
179
sage: Core([4,2],3).size()
180
6
181
"""
182
return self.to_partition().size()
183
184
def length(self):
185
r"""
186
Returns the length of ``self``.
187
188
The length of a `k`-core is the size of the corresponding `(k-1)`-bounded partition
189
which agrees with the length of the corresponding Grassmannian element,
190
see :meth:`to_grassmannian`.
191
192
EXAMPLES::
193
194
sage: c = Core([4,2],3); c.length()
195
4
196
sage: c.to_grassmannian().length()
197
4
198
199
sage: Core([9,5,3,2,1,1], 5).length()
200
13
201
"""
202
return self.to_bounded_partition().size()
203
204
def to_grassmannian(self):
205
r"""
206
Bijection between `k`-cores and Grassmannian elements in the affine Weyl group of type `A_{k-1}^{(1)}`.
207
208
For further details, see the documentation of the method
209
:meth:`~sage.combinat.partition.Partition_class.from_kbounded_to_reduced_word` and
210
:meth:`~sage.combinat.partition.Partition_class.from_kbounded_to_grassmannian`.
211
212
EXAMPLES::
213
214
sage: c = Core([3,1,1],3)
215
sage: w = c.to_grassmannian(); w
216
[-1 1 1]
217
[-2 2 1]
218
[-2 1 2]
219
sage: c.parent()
220
3-Cores of length 4
221
sage: w.parent()
222
Weyl Group of type ['A', 2, 1] (as a matrix group acting on the root space)
223
224
sage: c = Core([],3)
225
sage: c.to_grassmannian()
226
[1 0 0]
227
[0 1 0]
228
[0 0 1]
229
"""
230
return self.to_bounded_partition().from_kbounded_to_grassmannian(self.k()-1)
231
232
def affine_symmetric_group_simple_action(self, i):
233
r"""
234
Returns the action of the simple transposition `s_i` of the affine symmetric group on ``self``.
235
236
This gives the action of the affine symmetric group of type `A_k^{(1)}` on the `k`-core
237
``self``. If ``self`` has outside (resp. inside) corners of content `i` modulo `k`, then
238
these corners are added (resp. removed). Otherwise the action is trivial.
239
240
EXAMPLES::
241
242
sage: c = Core([4,2],3)
243
sage: c.affine_symmetric_group_simple_action(0)
244
[3, 1]
245
sage: c.affine_symmetric_group_simple_action(1)
246
[5, 3, 1]
247
sage: c.affine_symmetric_group_simple_action(2)
248
[4, 2]
249
250
This action corresponds to the left action by the `i`-th simple reflection in the affine
251
symmetric group::
252
253
sage: c = Core([4,2],3)
254
sage: W = c.to_grassmannian().parent()
255
sage: i=0
256
sage: c.affine_symmetric_group_simple_action(i).to_grassmannian() == W.simple_reflection(i)*c.to_grassmannian()
257
True
258
sage: i=1
259
sage: c.affine_symmetric_group_simple_action(i).to_grassmannian() == W.simple_reflection(i)*c.to_grassmannian()
260
True
261
"""
262
mu = self.to_partition()
263
corners = mu.outside_corners()
264
corners = [ p for p in corners if mu.content(p[0],p[1])%self.k()==i ]
265
if corners == []:
266
corners = mu.corners()
267
corners = [ p for p in corners if mu.content(p[0],p[1])%self.k()==i ]
268
if corners == []:
269
return self
270
for p in corners:
271
mu = mu.remove_cell(p[0])
272
else:
273
for p in corners:
274
mu = mu.add_cell(p[0])
275
return Core(mu, self.k())
276
277
def affine_symmetric_group_action(self, w, transposition = False):
278
r"""
279
Returns the (left) action of the affine symmetric group on ``self``.
280
281
INPUT:
282
283
- `w` is a tupe of integers `[w_1,\ldots,w_m]` with `0\le w_j<k`.
284
If transposition is set to be True, then `w = [w_0,w_1]` is interpreted as a transposition `t_{w_0, w_1}`
285
(see :meth:`_transposition_to_reduced_word`).
286
287
The output is the (left) action of the product of the corresponding simple transpositions
288
on ``self``, that is `s_{w_1} \cdots s_{w_m}(self)`. See :meth:`affine_symmetric_group_simple_action`.
289
290
EXAMPLES::
291
292
sage: c = Core([4,2],3)
293
sage: c.affine_symmetric_group_action([0,1,0,2,1])
294
[8, 6, 4, 2]
295
sage: c.affine_symmetric_group_action([0,2], transposition=True)
296
[4, 2, 1, 1]
297
298
sage: c = Core([11,8,5,5,3,3,1,1,1],4)
299
sage: c.affine_symmetric_group_action([2,5],transposition=True)
300
[11, 8, 7, 6, 5, 4, 3, 2, 1]
301
"""
302
c = self
303
if transposition:
304
w = self._transposition_to_reduced_word(w)
305
w.reverse()
306
for i in w:
307
c = c.affine_symmetric_group_simple_action(i)
308
return c
309
310
def _transposition_to_reduced_word(self, t):
311
r"""
312
Converts the transposition `t = [r,s]` to a reduced word.
313
314
INPUT:
315
316
- a tuple `[r,s]` such that `r` and `s` are not equivalent mod `k`
317
318
OUTPUT:
319
320
- a list of integers in `\{0,1,\ldots,k-1\}` representing a reduced word for the transposition `t`
321
322
EXAMPLE::
323
324
sage: c = Core([],4)
325
sage: c._transposition_to_reduced_word([2, 5])
326
[2, 3, 0, 3, 2]
327
sage: c._transposition_to_reduced_word([2, 5]) == c._transposition_to_reduced_word([5,2])
328
True
329
sage: c._transposition_to_reduced_word([2, 2])
330
Traceback (most recent call last):
331
...
332
AssertionError: t_0 and t_1 cannot be equal mod k
333
334
sage: c = Core([],30)
335
sage: c._transposition_to_reduced_word([4, 12])
336
[4, 5, 6, 7, 8, 9, 10, 11, 10, 9, 8, 7, 6, 5, 4]
337
338
sage: c = Core([],3)
339
sage: c._transposition_to_reduced_word([4, 12])
340
[1, 2, 0, 1, 2, 0, 2, 1, 0, 2, 1]
341
"""
342
k = self.k()
343
assert (t[0]-t[1])%k != 0, "t_0 and t_1 cannot be equal mod k"
344
if t[0] > t[1]:
345
return self._transposition_to_reduced_word([t[1],t[0]])
346
else:
347
return [i%k for i in range(t[0],t[1]-floor((t[1]-t[0])/k))] + [(t[1]-floor((t[1]-t[0])/k)-2-i)%(k) for i in
348
range(t[1]-floor((t[1]-t[0])/k)-t[0]-1)]
349
350
def weak_le(self, other):
351
r"""
352
Weak order comparison on cores.
353
354
INPUT:
355
356
- other - another `k`-core
357
358
OUTPUT: a boolean
359
360
Returns whether ``self`` <= ``other`` in weak order.
361
362
EXAMPLES::
363
364
sage: c = Core([4,2],3)
365
sage: x = Core([5,3,1],3)
366
sage: c.weak_le(x)
367
True
368
sage: c.weak_le([5,3,1])
369
True
370
371
sage: x = Core([4,2,2,1,1],3)
372
sage: c.weak_le(x)
373
False
374
375
sage: x = Core([5,3,1],6)
376
sage: c.weak_le(x)
377
Traceback (most recent call last):
378
...
379
AssertionError: The two cores do not have the same k
380
"""
381
if type(self) == type(other):
382
assert self.k() == other.k(), "The two cores do not have the same k"
383
else:
384
other = Core(other, self.k())
385
w = self.to_grassmannian()
386
v = other.to_grassmannian()
387
return w.weak_le(v, side='left')
388
389
def weak_covers(self):
390
r"""
391
Returns a list of all elements that cover ``self`` in weak order.
392
393
EXAMPLES::
394
395
sage: c = Core([1],3)
396
sage: c.weak_covers()
397
[[2], [1, 1]]
398
399
sage: c = Core([4,2],3)
400
sage: c.weak_covers()
401
[[5, 3, 1]]
402
"""
403
w = self.to_grassmannian()
404
S = w.upper_covers(side='left')
405
S = [x for x in S if x.is_affine_grassmannian()]
406
return [ x.affine_grassmannian_to_core() for x in set(S) ]
407
408
def strong_le(self, other):
409
r"""
410
Strong order (Bruhat) comparison on cores.
411
412
INPUT:
413
414
- other - another `k`-core
415
416
OUTPUT: a boolean
417
418
Returns whether ``self`` <= ``other`` in Bruhat (or strong) order.
419
420
EXAMPLES::
421
422
sage: c = Core([4,2],3)
423
sage: x = Core([4,2,2,1,1],3)
424
sage: c.strong_le(x)
425
True
426
sage: c.strong_le([4,2,2,1,1])
427
True
428
429
sage: x = Core([4,1],4)
430
sage: c.strong_le(x)
431
Traceback (most recent call last):
432
...
433
AssertionError: The two cores do not have the same k
434
"""
435
if type(self) == type(other):
436
assert self.k() == other.k(), "The two cores do not have the same k"
437
else:
438
other = Core(other, self.k())
439
w = self.to_grassmannian()
440
v = other.to_grassmannian()
441
return w.bruhat_le(v)
442
443
def contains(self, other):
444
r"""
445
Checks whether ``self`` contains other.
446
447
INPUT:
448
449
- other - another `k`-core
450
451
OUTPUT: a boolean
452
453
Returns True if the Ferrers diagram of ``self`` contains the Ferrers diagram of other.
454
455
EXAMPLES::
456
457
sage: c = Core([4,2],3)
458
sage: x = Core([4,2,2,1,1],3)
459
sage: x.contains(c)
460
True
461
sage: c.contains(x)
462
False
463
"""
464
la = self.to_partition()
465
mu = other.to_partition()
466
return la.contains(mu)
467
468
def strong_covers(self):
469
r"""
470
Returns a list of all elements that cover ``self`` in strong order.
471
472
EXAMPLES::
473
474
sage: c = Core([1],3)
475
sage: c.strong_covers()
476
[[2], [1, 1]]
477
sage: c = Core([4,2],3)
478
sage: c.strong_covers()
479
[[5, 3, 1], [4, 2, 1, 1]]
480
"""
481
w = self.to_grassmannian()
482
S = w.bruhat_upper_covers()
483
S = [x for x in S if x.is_affine_grassmannian()]
484
return [ x.affine_grassmannian_to_core() for x in set(S) ]
485
486
487
def Cores(k, length = None, **kwargs):
488
r"""
489
A `k`-core is a partition from which no rim hook of size `k` can be removed.
490
Alternatively, a `k`-core is an integer partition such that the Ferrers
491
diagram for the partition contains no cells with a hook of size (a multiple of) `k`.
492
493
The `k`-cores generally have two notions of size which are
494
useful for different applications. One is the number of cells in the
495
Ferrers diagram with hook less than `k`, the other is the total
496
number of cells of the Ferrers diagram. In the implementation in
497
Sage, the first of notion is referred to as the ``length`` of the `k`-core
498
and the second is the ``size`` of the `k`-core. The class
499
of Cores requires that either the size or the length of the elements in
500
the class is specified.
501
502
EXAMPLES:
503
504
We create the set of the `4`-cores of length `6`. Here the length of a `k`-core is the size
505
of the corresponding `(k-1)`-bounded partition, see also :meth:`~sage.combinat.core.Core.length`::
506
507
sage: C = Cores(4, 6); C
508
4-Cores of length 6
509
sage: C.list()
510
[[6, 3], [5, 2, 1], [4, 1, 1, 1], [4, 2, 2], [3, 3, 1, 1], [3, 2, 1, 1, 1], [2, 2, 2, 1, 1, 1]]
511
sage: C.cardinality()
512
7
513
sage: C.an_element()
514
[6, 3]
515
516
We may also list the set of `4`-cores of size `6`, where the size is the number of boxes in the
517
core, see also :meth:`~sage.combinat.core.Core.size`::
518
519
sage: C = Cores(4, size=6); C
520
4-Cores of size 6
521
sage: C.list()
522
[[4, 1, 1], [3, 2, 1], [3, 1, 1, 1]]
523
sage: C.cardinality()
524
3
525
sage: C.an_element()
526
[4, 1, 1]
527
"""
528
if length is None and 'size' in kwargs:
529
return Cores_size(k,kwargs['size'])
530
elif length is not None:
531
return Cores_length(k,length)
532
else:
533
raise ValueError("You need to either specify the length or size of the cores considered!")
534
535
class Cores_length(UniqueRepresentation, Parent):
536
r"""
537
The class of `k`-cores of length `n`.
538
"""
539
540
def __init__(self, k, n):
541
"""
542
TESTS::
543
544
sage: C = Cores(3, 4)
545
sage: TestSuite(C).run()
546
547
"""
548
self.k = k
549
self.n = n
550
Parent.__init__(self, category = FiniteEnumeratedSets())
551
552
def _repr_(self):
553
"""
554
TESTS::
555
556
sage: repr(Cores(4, 3)) #indirect doctest
557
'4-Cores of length 3'
558
"""
559
return "%s-Cores of length %s"%(self.k,self.n)
560
561
def list(self):
562
r"""
563
Returns the list of all `k`-cores of length `n`.
564
565
EXAMPLES::
566
567
sage: C = Cores(3,4)
568
sage: C.list()
569
[[4, 2], [3, 1, 1], [2, 2, 1, 1]]
570
"""
571
return [la.to_core(self.k-1) for la in Partitions(self.n, max_part=self.k-1)]
572
573
def from_partition(self, part):
574
r"""
575
Converts the partition `part` into a core (as the identity map).
576
577
This is the inverse method to :meth:`~sage.combinat.core.Core.to_partition`.
578
579
EXAMPLES::
580
581
sage: C = Cores(3,4)
582
sage: c = C.from_partition([4,2]); c
583
[4, 2]
584
585
sage: mu = Partition([2,1,1])
586
sage: C = Cores(3,3)
587
sage: C.from_partition(mu).to_partition() == mu
588
True
589
590
sage: mu = Partition([])
591
sage: C = Cores(3,0)
592
sage: C.from_partition(mu).to_partition() == mu
593
True
594
"""
595
return Core(part, self.k)
596
597
Element = Core
598
599
600
class Cores_size(UniqueRepresentation, Parent):
601
r"""
602
The class of `k`-cores of size `n`.
603
"""
604
605
def __init__(self, k, n):
606
"""
607
TESTS::
608
609
sage: C = Cores(3, size = 4)
610
sage: TestSuite(C).run()
611
"""
612
self.k = k
613
self.n = n
614
Parent.__init__(self, category = FiniteEnumeratedSets())
615
616
def _repr_(self):
617
"""
618
TESTS::
619
620
sage: repr(Cores(4, size = 3)) #indirect doctest
621
'4-Cores of size 3'
622
"""
623
return "%s-Cores of size %s"%(self.k,self.n)
624
625
def list(self):
626
r"""
627
Returns the list of all `k`-cores of size `n`.
628
629
EXAMPLES::
630
631
sage: C = Cores(3, size = 4)
632
sage: C.list()
633
[[3, 1], [2, 1, 1]]
634
"""
635
k_cores = Partitions(self.n).filter(lambda x: x.is_core(self.k))
636
return [ Core(x, self.k) for x in k_cores ]
637
638
def from_partition(self, part):
639
r"""
640
Converts the partition `part` into a core (as the identity map).
641
642
This is the inverse method to :meth:`to_partition`.
643
644
EXAMPLES::
645
646
sage: C = Cores(3,size=4)
647
sage: c = C.from_partition([2,1,1]); c
648
[2, 1, 1]
649
650
sage: mu = Partition([2,1,1])
651
sage: C = Cores(3,size=4)
652
sage: C.from_partition(mu).to_partition() == mu
653
True
654
655
sage: mu = Partition([])
656
sage: C = Cores(3,size=0)
657
sage: C.from_partition(mu).to_partition() == mu
658
True
659
"""
660
return Core(part, self.k)
661
662
Element = Core
663
664