Skip to content

Commit a43e74a

Browse files
author
Release Manager
committed
gh-38197: Column and row stabilizers for skew tableaux Row and column stabilizers and the usual a, b, e elements of the symmetric group algebra are now computable for skew standard tableaux, not just for straight ones. The a, b, e functions are still not exposed at class level, but this can be done another day. The performance cost (at least on the e function) is trivial: ``` sage: %timeit eold([[2,3],[1,4]]) 1.29 ms ± 12.7 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each) sage: %timeit enew([[2,3],[1,4]]) 1.29 ms ± 15.5 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each) sage: %timeit eold([[2,3],[1,4],[5,7]]) 3.43 ms ± 141 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) sage: %timeit enew([[2,3],[1,4],[5,7]]) 3.44 ms ± 158 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) ``` (Tested using factored-out code, since the actual functions are cached.) URL: #38197 Reported by: Darij Grinberg Reviewer(s): Travis Scrimshaw
2 parents 693e45a + a9c13b1 commit a43e74a

File tree

2 files changed

+122
-17
lines changed

2 files changed

+122
-17
lines changed

src/sage/combinat/skew_tableau.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
from sage.misc.persist import register_unpickle_override
5151

5252
lazy_import('sage.matrix.special', 'zero_matrix')
53+
lazy_import('sage.groups.perm_gps.permgroup', 'PermutationGroup')
5354

5455

5556
class SkewTableau(ClonableList,
@@ -1139,6 +1140,81 @@ def to_list(self):
11391140
"""
11401141
return [list(row) for row in self]
11411142

1143+
def row_stabilizer(self):
1144+
"""
1145+
Return the :func:`PermutationGroup` corresponding to the row stabilizer of
1146+
``self``.
1147+
1148+
This assumes that every integer from `1` to the size of ``self``
1149+
appears exactly once in ``self``.
1150+
1151+
EXAMPLES::
1152+
1153+
sage: # needs sage.groups
1154+
sage: rs = SkewTableau([[None,1,2,3],[4,5]]).row_stabilizer()
1155+
sage: rs.order() == factorial(3) * factorial(2)
1156+
True
1157+
sage: PermutationGroupElement([(1,3,2),(4,5)]) in rs
1158+
True
1159+
sage: PermutationGroupElement([(1,4)]) in rs
1160+
False
1161+
sage: rs = SkewTableau([[None,1,2],[3]]).row_stabilizer()
1162+
sage: PermutationGroupElement([(1,2),(3,)]) in rs
1163+
True
1164+
sage: rs.one().domain()
1165+
[1, 2, 3]
1166+
sage: rs = SkewTableau([[None,None,1],[None,2],[3]]).row_stabilizer()
1167+
sage: rs.order()
1168+
1
1169+
sage: rs = SkewTableau([[None,None,2,4,5],[1,3]]).row_stabilizer()
1170+
sage: rs.order()
1171+
12
1172+
sage: rs = SkewTableau([]).row_stabilizer()
1173+
sage: rs.order()
1174+
1
1175+
"""
1176+
# Ensure that the permutations involve all elements of the
1177+
# tableau, by including the identity permutation on the set [1..k].
1178+
k = self.size()
1179+
gens = [list(range(1, k + 1))]
1180+
for row in self:
1181+
for j in range(len(row) - 1):
1182+
if row[j] is not None:
1183+
gens.append((row[j], row[j + 1]))
1184+
return PermutationGroup(gens)
1185+
1186+
def column_stabilizer(self):
1187+
"""
1188+
Return the :func:`PermutationGroup` corresponding to the column stabilizer
1189+
of ``self``.
1190+
1191+
This assumes that every integer from `1` to the size of ``self``
1192+
appears exactly once in ``self``.
1193+
1194+
EXAMPLES::
1195+
1196+
sage: # needs sage.groups
1197+
sage: cs = SkewTableau([[None,2,3],[1,5],[4]]).column_stabilizer()
1198+
sage: cs.order() == factorial(2) * factorial(2)
1199+
True
1200+
sage: PermutationGroupElement([(1,3,2),(4,5)]) in cs
1201+
False
1202+
sage: PermutationGroupElement([(1,4)]) in cs
1203+
True
1204+
"""
1205+
# Ensure that the permutations involve all elements of the
1206+
# tableau, by including the identity permutation on the set [1..k].
1207+
k = self.size()
1208+
gens = [list(range(1, k + 1))]
1209+
ell = len(self)
1210+
while ell > 1:
1211+
ell -= 1
1212+
for i, val in enumerate(self[ell]):
1213+
top_neighbor = self[ell-1][i]
1214+
if top_neighbor is not None:
1215+
gens.append((val, top_neighbor))
1216+
return PermutationGroup(gens)
1217+
11421218
def shuffle(self, t2):
11431219
r"""
11441220
Shuffle the standard tableaux ``self`` and ``t2``.

src/sage/combinat/symmetric_group_algebra.py

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from sage.combinat.permutation_cython import (left_action_same_n, right_action_same_n)
1919
from sage.combinat.partition import _Partitions, Partitions, Partitions_n
2020
from sage.combinat.tableau import Tableau, StandardTableaux_size, StandardTableaux_shape, StandardTableaux
21+
from sage.combinat.skew_tableau import SkewTableau
2122
from sage.algebras.group_algebra import GroupAlgebra_class
2223
from sage.algebras.cellular_basis import CellularBasis
2324
from sage.categories.weyl_groups import WeylGroups
@@ -139,7 +140,7 @@ def SymmetricGroupAlgebra(R, W, category=None):
139140
140141
This allows for mixed expressions::
141142
142-
sage: x4 = 3*QS4([3, 1, 4, 2])
143+
sage: x4 = 3 * QS4([3, 1, 4, 2])
143144
sage: x3 + x4
144145
2*[2, 3, 1, 4] + [3, 1, 2, 4] + 3*[3, 1, 4, 2]
145146
@@ -2608,23 +2609,32 @@ def pi_ik(itab, ktab):
26082609
algebra.
26092610
26102611
This assumes that ``itab`` and ``ktab`` are tableaux (possibly
2611-
given just as lists of lists) of the same shape.
2612+
given just as lists of lists) of the same shape. Both
2613+
tableaux are allowed to be skew.
26122614
26132615
EXAMPLES::
26142616
26152617
sage: from sage.combinat.symmetric_group_algebra import pi_ik
26162618
sage: pi_ik([[1,3],[2]], [[1,2],[3]])
26172619
[1, 3, 2]
2620+
2621+
The same with skew tableaux::
2622+
2623+
sage: from sage.combinat.symmetric_group_algebra import pi_ik
2624+
sage: pi_ik([[None,1,3],[2]], [[None,1,2],[3]])
2625+
[1, 3, 2]
26182626
"""
2619-
it = Tableau(itab)
2620-
kt = Tableau(ktab)
2627+
it = SkewTableau(itab)
2628+
kt = SkewTableau(ktab)
2629+
n = kt.size()
26212630

2622-
p = [None] * kt.size()
2631+
p = [None] * n
26232632
for i in range(len(kt)):
26242633
for j in range(len(kt[i])):
2625-
p[it[i][j] - 1] = kt[i][j]
2634+
if it[i][j] is not None:
2635+
p[it[i][j] - 1] = kt[i][j]
26262636

2627-
QSn = SymmetricGroupAlgebra(QQ, it.size())
2637+
QSn = SymmetricGroupAlgebra(QQ, n)
26282638
p = Permutation(p)
26292639
return QSn(p)
26302640

@@ -2703,8 +2713,13 @@ def a(tableau, star=0, base_ring=QQ):
27032713
[1, 2, 3, 4, 5] + [1, 3, 2, 4, 5] + [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
27042714
sage: a([[1,4], [2,3]], base_ring=ZZ)
27052715
[1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
2716+
2717+
The same with a skew tableau::
2718+
2719+
sage: a([[None,1,4], [2,3]], base_ring=ZZ)
2720+
[1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
27062721
"""
2707-
t = Tableau(tableau)
2722+
t = SkewTableau(tableau)
27082723
if star:
27092724
t = t.restrict(t.size() - star)
27102725

@@ -2720,7 +2735,7 @@ def a(tableau, star=0, base_ring=QQ):
27202735
# being [1] rather than [] (which seems to have its origins in
27212736
# permutation group code).
27222737
# TODO: Fix this.
2723-
if len(tableau) == 0:
2738+
if n <= 1:
27242739
return sgalg.one()
27252740

27262741
rd = dict((P(h), one) for h in rs)
@@ -2774,6 +2789,11 @@ def b(tableau, star=0, base_ring=QQ):
27742789
sage: b([[1, 4], [2, 3]], base_ring=Integers(5))
27752790
[1, 2, 3, 4] + 4*[1, 2, 4, 3] + 4*[2, 1, 3, 4] + [2, 1, 4, 3]
27762791
2792+
The same with a skew tableau::
2793+
2794+
sage: b([[None, 2, 4], [1, 3], [5]])
2795+
[1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
2796+
27772797
With the ``l2r`` setting for multiplication, the unnormalized
27782798
Young symmetrizer ``e(tableau)`` should be the product
27792799
``b(tableau) * a(tableau)`` for every ``tableau``. Let us check
@@ -2783,7 +2803,7 @@ def b(tableau, star=0, base_ring=QQ):
27832803
sage: all( e(t) == b(t) * a(t) for t in StandardTableaux(5) )
27842804
True
27852805
"""
2786-
t = Tableau(tableau)
2806+
t = SkewTableau(tableau)
27872807
if star:
27882808
t = t.restrict(t.size() - star)
27892809

@@ -2799,7 +2819,7 @@ def b(tableau, star=0, base_ring=QQ):
27992819
# being [1] rather than [] (which seems to have its origins in
28002820
# permutation group code).
28012821
# TODO: Fix this.
2802-
if len(tableau) == 0:
2822+
if n <= 1:
28032823
return sgalg.one()
28042824

28052825
cd = dict((P(v), v.sign() * one) for v in cs)
@@ -2859,6 +2879,12 @@ def e(tableau, star=0):
28592879
sage: QS3.antipode(e([[1,2],[3]]))
28602880
[1, 2, 3] + [2, 1, 3] - [2, 3, 1] - [3, 2, 1]
28612881
2882+
And here is an example for a skew tableau::
2883+
2884+
sage: e([[None, 2, 1], [4, 3]])
2885+
[1, 2, 3, 4] + [1, 2, 4, 3] - [1, 3, 2, 4] - [1, 4, 2, 3]
2886+
+ [2, 1, 3, 4] + [2, 1, 4, 3] - [2, 3, 1, 4] - [2, 4, 1, 3]
2887+
28622888
.. SEEALSO::
28632889
28642890
:func:`e_hat`
@@ -2868,7 +2894,7 @@ def e(tableau, star=0):
28682894
# a way to compute them over other base rings as well. Be careful
28692895
# with the cache.
28702896

2871-
t = Tableau(tableau)
2897+
t = SkewTableau(tableau)
28722898
if star:
28732899
t = t.restrict(t.size() - star)
28742900

@@ -2896,8 +2922,8 @@ def e(tableau, star=0):
28962922
# being [1] rather than [] (which seems to have its origins in
28972923
# permutation group code).
28982924
# TODO: Fix this.
2899-
if not tableau:
2900-
res = QSn.one()
2925+
if n <= 1:
2926+
return QSn.one()
29012927

29022928
e_cache[t] = res
29032929

@@ -2955,7 +2981,10 @@ def e_hat(tab, star=0):
29552981
29562982
:func:`e`
29572983
"""
2958-
t = Tableau(tab)
2984+
t = SkewTableau(tab)
2985+
# This is for consistency's sake. This method is NOT meant
2986+
# to be applied to skew tableaux, since the meaning of
2987+
# \kappa is unclear in that case.
29592988
if star:
29602989
t = t.restrict(t.size() - star)
29612990
if t in ehat_cache:
@@ -2978,8 +3007,8 @@ def e_ik(itab, ktab, star=0):
29783007
sage: e_ik([[1,2,3]], [[1,2,3]], star=1)
29793008
[1, 2] + [2, 1]
29803009
"""
2981-
it = Tableau(itab)
2982-
kt = Tableau(ktab)
3010+
it = SkewTableau(itab)
3011+
kt = SkewTableau(ktab)
29833012
if star:
29843013
it = it.restrict(it.size() - star)
29853014
kt = kt.restrict(kt.size() - star)

0 commit comments

Comments
 (0)