Skip to content

Commit

Permalink
sagemathgh-38197: Column and row stabilizers for skew tableaux
Browse files Browse the repository at this point in the history
    
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: sagemath#38197
Reported by: Darij Grinberg
Reviewer(s): Travis Scrimshaw
  • Loading branch information
Release Manager committed Jun 16, 2024
2 parents 314ae6c + a9c13b1 commit 7da2ae3
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 17 deletions.
76 changes: 76 additions & 0 deletions src/sage/combinat/skew_tableau.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from sage.misc.persist import register_unpickle_override

lazy_import('sage.matrix.special', 'zero_matrix')
lazy_import('sage.groups.perm_gps.permgroup', 'PermutationGroup')


class SkewTableau(ClonableList,
Expand Down Expand Up @@ -1139,6 +1140,81 @@ def to_list(self):
"""
return [list(row) for row in self]

def row_stabilizer(self):
"""
Return the :func:`PermutationGroup` corresponding to the row stabilizer of
``self``.
This assumes that every integer from `1` to the size of ``self``
appears exactly once in ``self``.
EXAMPLES::
sage: # needs sage.groups
sage: rs = SkewTableau([[None,1,2,3],[4,5]]).row_stabilizer()
sage: rs.order() == factorial(3) * factorial(2)
True
sage: PermutationGroupElement([(1,3,2),(4,5)]) in rs
True
sage: PermutationGroupElement([(1,4)]) in rs
False
sage: rs = SkewTableau([[None,1,2],[3]]).row_stabilizer()
sage: PermutationGroupElement([(1,2),(3,)]) in rs
True
sage: rs.one().domain()
[1, 2, 3]
sage: rs = SkewTableau([[None,None,1],[None,2],[3]]).row_stabilizer()
sage: rs.order()
1
sage: rs = SkewTableau([[None,None,2,4,5],[1,3]]).row_stabilizer()
sage: rs.order()
12
sage: rs = SkewTableau([]).row_stabilizer()
sage: rs.order()
1
"""
# Ensure that the permutations involve all elements of the
# tableau, by including the identity permutation on the set [1..k].
k = self.size()
gens = [list(range(1, k + 1))]
for row in self:
for j in range(len(row) - 1):
if row[j] is not None:
gens.append((row[j], row[j + 1]))
return PermutationGroup(gens)

def column_stabilizer(self):
"""
Return the :func:`PermutationGroup` corresponding to the column stabilizer
of ``self``.
This assumes that every integer from `1` to the size of ``self``
appears exactly once in ``self``.
EXAMPLES::
sage: # needs sage.groups
sage: cs = SkewTableau([[None,2,3],[1,5],[4]]).column_stabilizer()
sage: cs.order() == factorial(2) * factorial(2)
True
sage: PermutationGroupElement([(1,3,2),(4,5)]) in cs
False
sage: PermutationGroupElement([(1,4)]) in cs
True
"""
# Ensure that the permutations involve all elements of the
# tableau, by including the identity permutation on the set [1..k].
k = self.size()
gens = [list(range(1, k + 1))]
ell = len(self)
while ell > 1:
ell -= 1
for i, val in enumerate(self[ell]):
top_neighbor = self[ell-1][i]
if top_neighbor is not None:
gens.append((val, top_neighbor))
return PermutationGroup(gens)

def shuffle(self, t2):
r"""
Shuffle the standard tableaux ``self`` and ``t2``.
Expand Down
63 changes: 46 additions & 17 deletions src/sage/combinat/symmetric_group_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from sage.combinat.permutation_cython import (left_action_same_n, right_action_same_n)
from sage.combinat.partition import _Partitions, Partitions, Partitions_n
from sage.combinat.tableau import Tableau, StandardTableaux_size, StandardTableaux_shape, StandardTableaux
from sage.combinat.skew_tableau import SkewTableau
from sage.algebras.group_algebra import GroupAlgebra_class
from sage.algebras.cellular_basis import CellularBasis
from sage.categories.weyl_groups import WeylGroups
Expand Down Expand Up @@ -139,7 +140,7 @@ def SymmetricGroupAlgebra(R, W, category=None):
This allows for mixed expressions::
sage: x4 = 3*QS4([3, 1, 4, 2])
sage: x4 = 3 * QS4([3, 1, 4, 2])
sage: x3 + x4
2*[2, 3, 1, 4] + [3, 1, 2, 4] + 3*[3, 1, 4, 2]
Expand Down Expand Up @@ -2608,23 +2609,32 @@ def pi_ik(itab, ktab):
algebra.
This assumes that ``itab`` and ``ktab`` are tableaux (possibly
given just as lists of lists) of the same shape.
given just as lists of lists) of the same shape. Both
tableaux are allowed to be skew.
EXAMPLES::
sage: from sage.combinat.symmetric_group_algebra import pi_ik
sage: pi_ik([[1,3],[2]], [[1,2],[3]])
[1, 3, 2]
The same with skew tableaux::
sage: from sage.combinat.symmetric_group_algebra import pi_ik
sage: pi_ik([[None,1,3],[2]], [[None,1,2],[3]])
[1, 3, 2]
"""
it = Tableau(itab)
kt = Tableau(ktab)
it = SkewTableau(itab)
kt = SkewTableau(ktab)
n = kt.size()

p = [None] * kt.size()
p = [None] * n
for i in range(len(kt)):
for j in range(len(kt[i])):
p[it[i][j] - 1] = kt[i][j]
if it[i][j] is not None:
p[it[i][j] - 1] = kt[i][j]

QSn = SymmetricGroupAlgebra(QQ, it.size())
QSn = SymmetricGroupAlgebra(QQ, n)
p = Permutation(p)
return QSn(p)

Expand Down Expand Up @@ -2703,8 +2713,13 @@ def a(tableau, star=0, base_ring=QQ):
[1, 2, 3, 4, 5] + [1, 3, 2, 4, 5] + [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
sage: a([[1,4], [2,3]], base_ring=ZZ)
[1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
The same with a skew tableau::
sage: a([[None,1,4], [2,3]], base_ring=ZZ)
[1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
"""
t = Tableau(tableau)
t = SkewTableau(tableau)
if star:
t = t.restrict(t.size() - star)

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

rd = dict((P(h), one) for h in rs)
Expand Down Expand Up @@ -2774,6 +2789,11 @@ def b(tableau, star=0, base_ring=QQ):
sage: b([[1, 4], [2, 3]], base_ring=Integers(5))
[1, 2, 3, 4] + 4*[1, 2, 4, 3] + 4*[2, 1, 3, 4] + [2, 1, 4, 3]
The same with a skew tableau::
sage: b([[None, 2, 4], [1, 3], [5]])
[1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
With the ``l2r`` setting for multiplication, the unnormalized
Young symmetrizer ``e(tableau)`` should be the product
``b(tableau) * a(tableau)`` for every ``tableau``. Let us check
Expand All @@ -2783,7 +2803,7 @@ def b(tableau, star=0, base_ring=QQ):
sage: all( e(t) == b(t) * a(t) for t in StandardTableaux(5) )
True
"""
t = Tableau(tableau)
t = SkewTableau(tableau)
if star:
t = t.restrict(t.size() - star)

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

cd = dict((P(v), v.sign() * one) for v in cs)
Expand Down Expand Up @@ -2859,6 +2879,12 @@ def e(tableau, star=0):
sage: QS3.antipode(e([[1,2],[3]]))
[1, 2, 3] + [2, 1, 3] - [2, 3, 1] - [3, 2, 1]
And here is an example for a skew tableau::
sage: e([[None, 2, 1], [4, 3]])
[1, 2, 3, 4] + [1, 2, 4, 3] - [1, 3, 2, 4] - [1, 4, 2, 3]
+ [2, 1, 3, 4] + [2, 1, 4, 3] - [2, 3, 1, 4] - [2, 4, 1, 3]
.. SEEALSO::
:func:`e_hat`
Expand All @@ -2868,7 +2894,7 @@ def e(tableau, star=0):
# a way to compute them over other base rings as well. Be careful
# with the cache.

t = Tableau(tableau)
t = SkewTableau(tableau)
if star:
t = t.restrict(t.size() - star)

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

e_cache[t] = res

Expand Down Expand Up @@ -2955,7 +2981,10 @@ def e_hat(tab, star=0):
:func:`e`
"""
t = Tableau(tab)
t = SkewTableau(tab)
# This is for consistency's sake. This method is NOT meant
# to be applied to skew tableaux, since the meaning of
# \kappa is unclear in that case.
if star:
t = t.restrict(t.size() - star)
if t in ehat_cache:
Expand All @@ -2978,8 +3007,8 @@ def e_ik(itab, ktab, star=0):
sage: e_ik([[1,2,3]], [[1,2,3]], star=1)
[1, 2] + [2, 1]
"""
it = Tableau(itab)
kt = Tableau(ktab)
it = SkewTableau(itab)
kt = SkewTableau(ktab)
if star:
it = it.restrict(it.size() - star)
kt = kt.restrict(kt.size() - star)
Expand Down

0 comments on commit 7da2ae3

Please sign in to comment.